@mdf.js/crash
Version:
MMS - API Crash - Enhanced error management library
227 lines • 8.03 kB
JavaScript
"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