UNPKG

@camunda8/sdk

Version:

[![NPM](https://nodei.co/npm/@camunda8/sdk.png)](https://www.npmjs.com/package/@camunda8/sdk)

183 lines 7.17 kB
"use strict"; 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