UNPKG

@mdf.js/crash

Version:

MMS - API Crash - Enhanced error management library

227 lines 8.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Boom = void 0; const BaseError_1 = require("../BaseError"); const const_1 = require("../const"); const Crash_1 = require("../Crash"); const Multi_1 = require("../Multi"); /** * Improved error handling in REST-API interfaces * * * Boom helps us with error responses (HTTP Codes 3XX-5XX) within our REST-API interface by * providing us with some tools: * - Helpers for the rapid generation of standard responses. * - Association of errors and their causes in a hierarchical way. * - Adaptation of validation errors of the Joi library. * * In addition, in combination with the Multi error types, errors in validation processes, and * Crash, standard application errors, it allows a complete management of the different types of * errors in our backend. * @category Boom * @public */ class Boom extends BaseError_1.Base { /** * Create a new Boom error * @param message - human friendly error message * @param uuid - unique identifier for this particular occurrence of the problem * @param code - HTTP Standard error code * @param options - enhanced error options */ constructor(message, uuid, code = 500, options) { var _a, _b; super(message, uuid, { name: (_b = (_a = options === null || options === void 0 ? void 0 : options.cause) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'HTTP', info: options === null || options === void 0 ? void 0 : options.info, }); /** Boom error */ this._isBoom = true; // ***************************************************************************************** // #region code type safe if (typeof code !== 'number') { throw new Crash_1.Crash('Code must be a number', uuid); } this._code = code; // #endregion // ***************************************************************************************** // #region options type safe this._cause = this.typeSafeCause(uuid, options === null || options === void 0 ? void 0 : options.cause); // #endregion if (!this.typeSafeLinks(options === null || options === void 0 ? void 0 : options.links) || !this.typeSafeSource(options === null || options === void 0 ? void 0 : options.source)) { throw new Crash_1.Crash('Links and source must be strings', uuid); } this._links = options === null || options === void 0 ? void 0 : options.links; this._source = options === null || options === void 0 ? void 0 : options.source; if (this.name === 'BaseError') { this.name = 'HTTPError'; } } /** Return APIError in JSON format */ toJSON() { var _a, _b; return { uuid: this._uuid, links: this._links, status: this._code, code: this.name, title: (_a = const_1.HTTP_CODES.get(this._code)) !== null && _a !== void 0 ? _a : 'Undefined error', detail: this.message, source: this._source, meta: (_b = this._options) === null || _b === void 0 ? void 0 : _b.info, }; } /** Boom error code */ get status() { return this._code; } /** * Links that leads to further details about this particular occurrence of the problem. * A link MUST be represented as either: * - self: a string containing the link’s URL * - related: an object (“link object”) which can contain the following members: * - href: a string containing the link’s URL. * - meta: a meta object containing non-standard meta-information about the link. */ get links() { return this._links; } /** * Object with the key information of the requested resource in the REST API context * @deprecated - `source` has been deprecated, use resource instead */ get source() { return this._source; } /** Object with the key information of the requested resource in the REST API context */ get resource() { return this._source; } /** Boom error */ get isBoom() { return this._isBoom; } /** Cause source of error */ get cause() { return this._cause; } /** Get the trace of this hierarchy of errors */ trace() { const trace = []; let cause = this._cause; while (cause) { if (cause instanceof Multi_1.Multi) { trace.push(`caused by ${cause.toString()}`); if (cause.causes) { trace.push(...cause.causes.map(entry => `failed with ${entry.toString()}`)); } cause = undefined; } else if (cause instanceof Crash_1.Crash) { trace.push(`caused by ${cause.toString()}`); cause = cause.cause; } else { trace.push(`caused by ${cause.name}: ${cause.message}`); cause = undefined; } } trace.unshift(this.toString()); return trace; } /** * Transform joi Validation error in a Boom error * @param error - `ValidationError` from a Joi validation process */ Boomify(error) { if (error.name === 'ValidationError') { if (error.details.length > 1) { this._cause = new Multi_1.Multi(error.message, this._uuid, { name: 'ValidationError' }); this._cause.Multify(error); } else { this._cause = new Crash_1.Crash(error.message, this._uuid, { name: 'ValidationError', info: error.details[0], }); } } } /** * Check if the cause are type safe and valid * @param uuid - unique identifier for this particular occurrence of the problem * @param cause - Crash error cause */ typeSafeCause(uuid, cause) { if (cause) { if (cause instanceof Crash_1.Crash || cause instanceof Error) { return cause; } else { throw new Crash_1.Crash('Parameter cause must be an Error/Crash', uuid); } } else { return undefined; } } /** * Check if links are type safe and valid * @param links - Information links for error */ typeSafeLinks(links) { if (typeof links === 'object') { let check = true; for (const key of Object.keys(links)) { if (typeof links[key] === 'object') { check = this.typeSafeContextLinks(links[key]); } else if (typeof links[key] !== 'string') { check = false; } } return check; } else if (links === undefined) { return true; } else { return false; } } /** * Check if links are type safe and valid * @param links - Information links for error */ typeSafeContextLinks(links) { if (typeof links === 'object') { let check = true; for (const key of Object.keys(links)) { if (typeof links[key] !== 'string') { check = false; } } return check; } else if (links === undefined) { return true; } else { return false; } } /** * Check if source are type safe and valid * @param source - Source of error */ typeSafeSource(source) { if (source !== undefined) { return typeof source.pointer === 'string'; } else { return true; } } } exports.Boom = Boom; //# sourceMappingURL=BoomError.js.map