@camunda8/sdk
Version:
[](https://www.npmjs.com/package/@camunda8/sdk)
183 lines • 7.17 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.gotBeforeErrorHook = exports.HTTPError = void 0;
const Got = __importStar(require("got"));
const got_1 = require("got");
const GotHooks_1 = require("./GotHooks");
const Defaults = {
status: 0,
title: '',
detail: '',
instance: '',
type: 'about:blank',
};
class HTTPError extends Got.HTTPError {
constructor({ response, method, url, message, }) {
super(response);
this.type = 'about:blank';
this.method = method;
this.url = url;
this.originalMessage = message;
let details = Defaults;
try {
details = JSON.parse(response?.body || '{}');
}
catch {
// ignore JSON parse errors
}
this.statusCode = details.status;
this.title = details.title;
this.detail = details.detail;
this.instance = details.instance;
this.status = details.status;
// Sometimes APIs return errors data in plain text (not JSON)
// and sometimes we get back an HTML error page (for example: 502 Bad Gateway)
// We want to extract and surface plain text errors
// and ignore the HTML strings
if (!(response.body ?? '<').startsWith('<')) {
this.message += ` - ${response.body}`;
}
}
/**
* Provides a rich string representation including method, URL, and response
* detail for debugging (e.g. console.log, uncaught exception traces) while
* keeping error.message static for error-monitoring grouping (Sentry, etc.).
* See: https://github.com/camunda/camunda-8-js-sdk/issues/658
*/
toString() {
const parts = [this.message];
if (this.method || this.url) {
parts.push(`(${this.method ?? ''} ${this.url ?? ''})`);
}
if (this.detail) {
parts.push(this.detail);
}
return parts.join(' ');
}
}
exports.HTTPError = HTTPError;
const gotBeforeErrorHook = (config) => (error) => {
const { request } = error;
const method = request?.options.method;
const url = request?.options.url.href;
let detail = '';
if (error instanceof got_1.HTTPError) {
error = new HTTPError({
response: error.response,
method,
url,
message: error.message,
});
try {
const details = JSON.parse(error.response?.body || '{detail:""}');
error.statusCode = details.status;
detail = details ?? '';
}
catch {
error.statusCode = 0;
}
}
const enhancedStack = error.options.context.stack?.split('\n');
error.source = enhancedStack ?? ['No enhanced stack trace available'];
// Attach request context as structured properties so error-monitoring
// tools (Sentry, Datadog, etc.) can group by the static error.message.
// See: https://github.com/camunda/camunda-8-js-sdk/issues/658
if (!(error instanceof HTTPError)) {
// HTTPError already has these from its constructor; for plain
// RequestErrors we attach them here.
;
error.method = method;
error.url = url;
error.detail =
typeof detail === 'string' ? detail : JSON.stringify(detail);
}
if (enhancedStack) {
error.message += `. Enhanced stack trace available as error.source.`;
}
const structured = error.options.context.__stackTrace;
if (structured?.stacks?.length) {
;
error.originalStack =
error.stack;
const synthesized = [
`${error.name}: ${error.message}`,
...structured.stacks.map((s) => s.location),
`RequestId: ${structured.requestId}`,
structured.apiMethod ? `ApiMethod: ${structured.apiMethod}` : undefined,
]
.filter(Boolean)
.join('\n');
error.stack = synthesized;
}
/** Hinting for error messages. See https://github.com/camunda/camunda-8-js-sdk/issues/456 */
/** Here we reason over the error and the configuration to enrich the message with hints */
if (error.message.includes('Invalid header token')) {
// This is a parse error, which means the response header was not valid JSON.
// Debugging for https://github.com/camunda/camunda-8-js-sdk/issues/491
error.message += ` (response headers: ${JSON.stringify(error.response?.headers)})`;
}
if (error.code === '401') {
// the call was unauthorized
if (config.CAMUNDA_AUTH_STRATEGY === 'OAUTH') {
if (request?.options.headers?.authorization) {
/** This is a 401 error, but the token is set in the header */
error.message +=
' (this may be due to the client credentials not being authorized to access the resource)';
if (config.CAMUNDA_TENANT_ID) {
/** We're *probably* making a multi-tenant call. It might have been overridden in the call, but we don't have access to the body */
error.message += `. Is the client credential authorized in the tenant?`;
}
}
}
}
/** Log details of errors to the Camunda Support log */
GotHooks_1.supportLogger.log('**ERROR**: Got error during Rest call:');
GotHooks_1.supportLogger.log({
code: error.code,
message: error.message,
method,
url,
detail,
stack: error.stack, // replaced stack
originalStack: error
.originalStack,
requestOptions: error.request?.options,
source: error.source,
});
return error;
};
exports.gotBeforeErrorHook = gotBeforeErrorHook;
//# sourceMappingURL=GotErrors.js.map