@forge/kvs
1.5.1-next.01.6.0-next.1
+
Added (3 files)
~
Modified (11 files)
Index: package/out/utils/error-handling.js
===================================================================
--- package/out/utils/error-handling.js
+++ package/out/utils/error-handling.js
@@ -1,7 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-exports.checkResponseError = exports.extractTraceId = exports.safeGetParsedBody = exports.isForgeError = void 0;
+exports.checkResponseError = exports.extractTraceId = exports.getAPIErrorResponseDetails = exports.safeGetParsedBody = exports.isForgeError = void 0;
const errors_1 = require("../errors");
function isForgeError(body) {
return typeof body === 'object' && body !== null && 'code' in body && 'message' in body;
}
@@ -14,22 +14,29 @@
return undefined;
}
}
exports.safeGetParsedBody = safeGetParsedBody;
+function getAPIErrorResponseDetails(response, responseText, requestContext) {
+ return {
+ status: response.status,
+ statusText: response.statusText,
+ traceId: extractTraceId(response),
+ httpMethod: requestContext?.httpMethod,
+ httpPath: requestContext?.httpPath,
+ responseBodyLength: responseText.length
+ };
+}
+exports.getAPIErrorResponseDetails = getAPIErrorResponseDetails;
function extractTraceId(response) {
return response.headers.get('x-b3-traceid') || response.headers.get('x-trace-id');
}
exports.extractTraceId = extractTraceId;
-async function checkResponseError(response) {
+async function checkResponseError(response, requestContext) {
if (response.ok) {
return;
}
const responseText = await response.text();
- const details = {
- status: response.status,
- statusText: response.statusText,
- traceId: extractTraceId(response)
- };
+ const details = getAPIErrorResponseDetails(response, responseText, requestContext);
const parsedBody = safeGetParsedBody(responseText);
if (parsedBody && isForgeError(parsedBody)) {
throw new errors_1.ForgeKvsAPIError(details, parsedBody);
} Index: package/out/utils/__test__/error-handling.test.js
===================================================================
--- package/out/utils/__test__/error-handling.test.js
+++ package/out/utils/__test__/error-handling.test.js
@@ -1,7 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const errors_1 = require("../../errors");
+const version_1 = require("../../version");
const error_handling_1 = require("../error-handling");
describe('error-handling', () => {
it('isForgeError', () => {
expect((0, error_handling_1.isForgeError)({ code: 'code', message: 'message' })).toBe(true);
@@ -29,57 +30,65 @@
describe('Forge errors - ForgeKvsAPIError', () => {
const message = 'A test error has occurred';
const code = 'ERROR_CODE';
it('should return a ForgeKvsAPIError when response body is a Forge error', async () => {
- const mockResponse = new Response(JSON.stringify({ code, message }), {
+ const body = JSON.stringify({ code, message });
+ const mockResponse = new Response(body, {
status: 400,
statusText: 'Bad Request',
headers: { 'x-trace-id': traceId }
});
await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
status: 400,
statusText: 'Bad Request',
- traceId
+ traceId,
+ responseBodyLength: body.length
}, { code, message }));
});
it('should include context if present in the Forge error', async () => {
const context = { key: 'value' };
- const mockResponse = new Response(JSON.stringify({ code, message, context }), {
+ const body = JSON.stringify({ code, message, context });
+ const mockResponse = new Response(body, {
status: 400,
statusText: 'Bad Request',
headers: { 'x-trace-id': traceId }
});
await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
status: 400,
statusText: 'Bad Request',
- traceId
+ traceId,
+ responseBodyLength: body.length
}, { code, message, context }));
});
it('should include top level additional fields if present in the Forge error', async () => {
const extraFields = { extraValue: 'value', debug: true };
- const mockResponse = new Response(JSON.stringify({ code, message, ...extraFields }), {
+ const body = JSON.stringify({ code, message, ...extraFields });
+ const mockResponse = new Response(body, {
status: 400,
statusText: 'Bad Request',
headers: { 'x-trace-id': traceId }
});
await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
status: 400,
statusText: 'Bad Request',
- traceId
+ traceId,
+ responseBodyLength: body.length
}, { code, message, context: extraFields }));
});
it('should merge context and additional top level fields if both present in the Forge error', async () => {
const context = { key: 'value' };
const extraFields = { extraValue: 'value', debug: true };
- const mockResponse = new Response(JSON.stringify({ code, message, context, ...extraFields }), {
+ const body = JSON.stringify({ code, message, context, ...extraFields });
+ const mockResponse = new Response(body, {
status: 400,
statusText: 'Bad Request',
headers: { 'x-trace-id': traceId }
});
await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse)).rejects.toThrowError(new errors_1.ForgeKvsAPIError({
status: 400,
statusText: 'Bad Request',
- traceId
+ traceId,
+ responseBodyLength: body.length
}, { code, message, context: { ...context, ...extraFields } }));
});
describe('Handle non forge errors', () => {
it('returns an UNKNOWN_ERROR when no response body', async () => {
@@ -90,9 +99,10 @@
});
await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
status: 404,
statusText: 'Not Found',
- traceId
+ traceId,
+ responseBodyLength: 0
}, {
code: 'UNKNOWN_ERROR',
context: { responseText: '' },
message: 'Unexpected error in Forge KVS API'
@@ -107,15 +117,76 @@
});
await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
status: 500,
statusText: 'Internal Server Error',
- traceId
+ traceId,
+ responseBodyLength: body.length
}, {
code: 'UNKNOWN_ERROR',
context: { responseText: body },
message: 'Unexpected error in Forge KVS API'
}));
});
});
});
+ describe('with request context', () => {
+ const requestContext = {
+ httpMethod: 'POST',
+ httpPath: '/api/v1/get'
+ };
+ it('should include request context in ForgeKvsAPIError when provided', async () => {
+ const body = JSON.stringify({ code: 'ERROR', message: 'Test error' });
+ const mockResponse = new Response(body, {
+ status: 400,
+ statusText: 'Bad Request',
+ headers: { 'x-trace-id': traceId }
+ });
+ await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse, requestContext)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 400,
+ statusText: 'Bad Request',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/get',
+ responseBodyLength: body.length
+ }, { code: 'ERROR', message: 'Test error' }));
+ });
+ it('should include request context in UNKNOWN_ERROR when provided', async () => {
+ const body = 'not valid json';
+ const mockResponse = new Response(body, {
+ status: 500,
+ statusText: 'Internal Server Error',
+ headers: { 'x-trace-id': traceId }
+ });
+ await expect(async () => await (0, error_handling_1.checkResponseError)(mockResponse, requestContext)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 500,
+ statusText: 'Internal Server Error',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/get',
+ responseBodyLength: body.length
+ }, {
+ code: 'UNKNOWN_ERROR',
+ context: { responseText: body },
+ message: 'Unexpected error in Forge KVS API'
+ }));
+ });
+ });
});
+ describe('packageVersion', () => {
+ it('should auto-populate packageVersion on ForgeKvsError', () => {
+ const error = new errors_1.ForgeKvsError('Test error');
+ expect(error.packageVersion).toBeDefined();
+ expect(typeof error.packageVersion).toBe('string');
+ expect(error.packageVersion).toMatch(/^\d+\.\d+\.\d+/);
+ });
+ it('should auto-populate packageVersion on ForgeKvsAPIError', () => {
+ const error = new errors_1.ForgeKvsAPIError({ status: 500, statusText: 'Internal Server Error' }, { code: 'ERROR', message: 'Test error' });
+ expect(error.packageVersion).toBeDefined();
+ expect(typeof error.packageVersion).toBe('string');
+ expect(error.packageVersion).toMatch(/^\d+\.\d+\.\d+/);
+ });
+ it('should match the version in package.json', () => {
+ const error = new errors_1.ForgeKvsError('Test error');
+ expect(error.packageVersion).toBe(version_1.PACKAGE_VERSION);
+ });
+ });
}); Index: package/out/errors.js
===================================================================
--- package/out/errors.js
+++ package/out/errors.js
@@ -1,11 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ForgeKvsAPIError = exports.ForgeKvsError = void 0;
+const version_1 = require("./version");
class ForgeKvsError extends Error {
- constructor(message) {
+ packageVersion;
+ constructor(message, packageVersion = version_1.PACKAGE_VERSION) {
super(message);
this.name = 'ForgeKvsError';
+ this.packageVersion = packageVersion;
}
}
exports.ForgeKvsError = ForgeKvsError;
class ForgeKvsAPIError extends ForgeKvsError {
@@ -14,10 +17,10 @@
message;
context;
constructor(responseDetails, forgeError) {
super(forgeError.message);
- const { status, statusText, traceId } = responseDetails;
- this.responseDetails = { status, statusText, traceId };
+ const { status, statusText, traceId, httpMethod, httpPath, responseBodyLength } = responseDetails;
+ this.responseDetails = { status, statusText, traceId, httpMethod, httpPath, responseBodyLength };
const { code, message, context, ...bodyData } = forgeError;
this.code = code;
this.message = message;
this.context = { ...context, ...bodyData }; Index: package/out/__test__/index.test.js
===================================================================
--- package/out/__test__/index.test.js
+++ package/out/__test__/index.test.js
@@ -101,27 +101,43 @@
body: JSON.stringify({ key: 'foo' })
}));
});
it('should handle unexpected metadata fields', async () => {
- const response = new Response(JSON.stringify({
+ const body = JSON.stringify({
code: 'BAD_REQUEST',
message: 'Provided request body is invalid'
- }), {
+ });
+ const response = new Response(body, {
status: 400,
statusText: 'Bad Request',
headers: { 'x-trace-id': traceId }
});
const { sut } = prepare(response);
- await expect(sut.get('foo', { metadataFields: ['INVALID_METADATA_FIELD'] })).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 400, statusText: 'Bad Request', traceId }, { code: 'BAD_REQUEST', message: 'Provided request body is invalid' }));
+ await expect(sut.get('foo', { metadataFields: ['INVALID_METADATA_FIELD'] })).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 400,
+ statusText: 'Bad Request',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/get',
+ responseBodyLength: body.length
+ }, { code: 'BAD_REQUEST', message: 'Provided request body is invalid' }));
});
it('should handle unexpected response', async () => {
- const response = new Response(JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }), {
+ const body = JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' });
+ const response = new Response(body, {
status: 500,
statusText: 'Internal Server Error',
headers: { 'x-trace-id': traceId }
});
const { sut } = prepare(response);
- await expect(sut.get('foo')).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 500, statusText: 'Internal Server Error', traceId }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
+ await expect(sut.get('foo')).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 500,
+ statusText: 'Internal Server Error',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/get',
+ responseBodyLength: body.length
+ }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
});
it('should handle non-json response even though status is ok', async () => {
const responseText = 'Text that will fail to parse';
const response = new Response(responseText, {
@@ -129,9 +145,16 @@
statusText: 'OK',
headers: { 'x-trace-id': traceId, 'content-length': responseText.length.toString() }
});
const { sut } = prepare(response);
- await expect(sut.get('foo')).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 200, statusText: 'OK', traceId }, {
+ await expect(sut.get('foo')).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 200,
+ statusText: 'OK',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/get',
+ responseBodyLength: responseText.length
+ }, {
code: 'UNKNOWN_ERROR',
message: 'Unexpected error in Forge KVS API. Response was not valid JSON',
context: { contentLength: responseText.length.toString() }
}));
@@ -1177,16 +1200,24 @@
body: JSON.stringify(items)
}));
});
it('should handle batchSet API error response', async () => {
- const response = new Response(JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }), {
+ const body = JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' });
+ const response = new Response(body, {
status: 500,
statusText: 'Internal Server Error',
headers: { 'x-trace-id': traceId }
});
const { sut } = prepare(response);
const items = [{ key: 'foo', value: 'bar' }];
- await expect(sut.batchSet(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 500, statusText: 'Internal Server Error', traceId }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
+ await expect(sut.batchSet(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 500,
+ statusText: 'Internal Server Error',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/batch/set',
+ responseBodyLength: body.length
+ }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
});
it('should handle batchDelete correctly with mixed entity and non-entity items', async () => {
const response = new Response(JSON.stringify({
successfulKeys: [{ key: 'foo', entityName: 'employees' }, { key: 'bar' }],
@@ -1276,16 +1307,24 @@
body: JSON.stringify(items)
}));
});
it('should handle batchDelete API error response', async () => {
- const response = new Response(JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }), {
+ const body = JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' });
+ const response = new Response(body, {
status: 500,
statusText: 'Internal Server Error',
headers: { 'x-trace-id': traceId }
});
const { sut } = prepare(response);
const items = [{ key: 'foo' }];
- await expect(sut.batchDelete(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 500, statusText: 'Internal Server Error', traceId }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
+ await expect(sut.batchDelete(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 500,
+ statusText: 'Internal Server Error',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/batch/delete',
+ responseBodyLength: body.length
+ }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
});
it('should handle batchGet with mixed entity and non-entity items', async () => {
const response = new Response(JSON.stringify({
successfulKeys: [
@@ -1450,22 +1489,31 @@
body: JSON.stringify(items)
}));
});
it('should handle batchGet API error response', async () => {
- const response = new Response(JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }), {
+ const body = JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' });
+ const response = new Response(body, {
status: 500,
statusText: 'Internal Server Error',
headers: { 'x-trace-id': traceId }
});
const { sut } = prepare(response);
const items = [{ key: 'foo' }];
- await expect(sut.batchGet(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 500, statusText: 'Internal Server Error', traceId }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
+ await expect(sut.batchGet(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 500,
+ statusText: 'Internal Server Error',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/batch/get',
+ responseBodyLength: body.length
+ }, { code: 'INTERNAL_SERVER_ERROR', message: 'An internal server error has occurred' }));
});
it('should handle batchGet with invalid metadata fields', async () => {
- const response = new Response(JSON.stringify({
+ const body = JSON.stringify({
code: 'BAD_REQUEST',
message: 'Provided request body is invalid'
- }), {
+ });
+ const response = new Response(body, {
status: 400,
statusText: 'Bad Request',
headers: { 'x-trace-id': traceId }
});
@@ -1475,7 +1523,14 @@
key: 'foo',
options: { metadataFields: ['INVALID_METADATA_FIELD'] }
}
];
- await expect(sut.batchGet(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({ status: 400, statusText: 'Bad Request', traceId }, { code: 'BAD_REQUEST', message: 'Provided request body is invalid' }));
+ await expect(sut.batchGet(items)).rejects.toMatchError(new errors_1.ForgeKvsAPIError({
+ status: 400,
+ statusText: 'Bad Request',
+ traceId,
+ httpMethod: 'POST',
+ httpPath: '/api/v1/batch/get',
+ responseBodyLength: body.length
+ }, { code: 'BAD_REQUEST', message: 'Provided request body is invalid' }));
});
}); Index: package/out/storage-api.js
===================================================================
--- package/out/storage-api.js
+++ package/out/storage-api.js
@@ -117,9 +117,13 @@
'content-type': 'application/json'
}
};
const response = await this.apiClient(path, requestBody);
- await (0, error_handling_1.checkResponseError)(response);
+ const requestContext = {
+ httpMethod: requestBody.method,
+ httpPath: path
+ };
+ await (0, error_handling_1.checkResponseError)(response, requestContext);
if (responseType === ResponseType.NONE) {
return;
}
const responseText = await response.text();
@@ -127,13 +131,9 @@
return undefined;
}
const parsedBody = (0, error_handling_1.safeGetParsedBody)(responseText);
if (parsedBody === undefined) {
- const details = {
- status: response.status,
- statusText: response.statusText,
- traceId: (0, error_handling_1.extractTraceId)(response)
- };
+ const details = (0, error_handling_1.getAPIErrorResponseDetails)(response, responseText, requestContext);
throw new errors_1.ForgeKvsAPIError(details, {
code: 'UNKNOWN_ERROR',
message: 'Unexpected error in Forge KVS API. Response was not valid JSON',
context: { contentLength: response.headers.get('content-length') } Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
{
"name": "@forge/kvs",
- "version": "1.5.1-next.0",
+ "version": "1.6.0-next.1",
"description": "Forge Key Value Store SDK",
"author": "Atlassian",
"license": "SEE LICENSE IN LICENSE.txt",
"main": "out/index.js", Index: package/out/utils/error-handling.d.ts.map
===================================================================
--- package/out/utils/error-handling.d.ts.map
+++ package/out/utils/error-handling.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/utils/error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAA2B,UAAU,EAAoB,MAAM,WAAW,CAAC;AAElF,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,UAAU,CAE9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAMnE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAEnE;AAED,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB7E"}
\ No newline at end of file
+{"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/utils/error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAoB,MAAM,WAAW,CAAC;AAElF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,UAAU,CAE9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAMnE;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,WAAW,EACrB,YAAY,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,cAAc,GAC9B,uBAAuB,CASzB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAEnE;AAED,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9G"}
\ No newline at end of file Index: package/out/errors.d.ts.map
===================================================================
--- package/out/errors.d.ts.map
+++ package/out/errors.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,eAAe,EAAE,uBAAuB,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAErB,eAAe,EAAE,uBAAuB,EAAE,UAAU,EAAE,UAAU;CAU7E"}
\ No newline at end of file
+{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,cAAc,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,cAAc,GAAE,MAAwB;CAKtE;AAED,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,eAAe,EAAE,uBAAuB,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAErB,eAAe,EAAE,uBAAuB,EAAE,UAAU,EAAE,UAAU;CAU7E"}
\ No newline at end of file Index: package/out/storage-api.d.ts.map
===================================================================
--- package/out/storage-api.d.ts.map
+++ package/out/storage-api.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"storage-api.d.ts","sourceRoot":"","sources":["../src/storage-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EACL,SAAS,EACT,UAAU,EACV,WAAW,EAGX,SAAS,EAGT,cAAc,EACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,kBAAkB,EAElB,eAAe,EACf,eAAe,EAEf,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAEhB,kBAAkB,EAElB,gBAAgB,EAChB,UAAU,EAEV,YAAY,EAEZ,mBAAmB,EACnB,gBAAgB,EAEhB,gBAAgB,EAChB,UAAU,EAEV,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAQ9B,qBAAa,UAAU;IACT,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,WAAW;IAEpC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAO/D,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAO3E,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAO3E,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAKrE,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAKjF,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAKjF,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAQpD,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAQhE,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ3D,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ3D,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAQ9D,QAAQ,CAAC,CAAC,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAI7D,iBAAiB;YAWjB,OAAO;IA6CrB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,kBAAkB;CAgB3B"}
\ No newline at end of file
+{"version":3,"file":"storage-api.d.ts","sourceRoot":"","sources":["../src/storage-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EACL,SAAS,EACT,UAAU,EACV,WAAW,EAGX,SAAS,EAGT,cAAc,EACf,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,EACL,kBAAkB,EAElB,eAAe,EACf,eAAe,EAEf,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAEhB,kBAAkB,EAElB,gBAAgB,EAChB,UAAU,EAEV,YAAY,EAEZ,mBAAmB,EACnB,gBAAgB,EAEhB,gBAAgB,EAChB,UAAU,EAEV,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAQ9B,qBAAa,UAAU;IACT,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,WAAW;IAEpC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAO/D,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAO3E,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAO3E,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAKrE,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAKjF,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAKjF,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAQpD,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAQhE,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ3D,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ3D,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAQ9D,QAAQ,CAAC,CAAC,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAI7D,iBAAiB;YAWjB,OAAO;IA8CrB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,kBAAkB;CAgB3B"}
\ No newline at end of file Index: package/out/utils/error-handling.d.ts
===================================================================
--- package/out/utils/error-handling.d.ts
+++ package/out/utils/error-handling.d.ts
@@ -1,7 +1,12 @@
import { APIResponse } from '@forge/api';
-import { ForgeError } from '../errors';
+import { APIErrorResponseDetails, ForgeError } from '../errors';
+export interface RequestContext {
+ httpMethod: string;
+ httpPath: string;
+}
export declare function isForgeError(body: unknown): body is ForgeError;
export declare function safeGetParsedBody(text: string): unknown | undefined;
+export declare function getAPIErrorResponseDetails(response: APIResponse, responseText: string, requestContext?: RequestContext): APIErrorResponseDetails;
export declare function extractTraceId(response: APIResponse): string | null;
-export declare function checkResponseError(response: APIResponse): Promise<void>;
+export declare function checkResponseError(response: APIResponse, requestContext?: RequestContext): Promise<void>;
//# sourceMappingURL=error-handling.d.ts.map
\ No newline at end of file Index: package/out/errors.d.ts
===================================================================
--- package/out/errors.d.ts
+++ package/out/errors.d.ts
@@ -6,11 +6,15 @@
export interface APIErrorResponseDetails {
status: number;
statusText: string;
traceId?: string | null;
+ httpMethod?: string;
+ httpPath?: string;
+ responseBodyLength?: number;
}
export declare class ForgeKvsError extends Error {
- constructor(message: string);
+ packageVersion: string;
+ constructor(message: string, packageVersion?: string);
}
export declare class ForgeKvsAPIError extends ForgeKvsError {
responseDetails: APIErrorResponseDetails;
code: string;