The goal of @netin-js/crash is to provide improved, but simplified, error handling, while standardizing error handling across all Netin modules.
You need to register with Azure DevOps to install it, the package can be found in the Netin Systems feed.
npm install @netin-js/crash
yarn add @netin-js/crash
This library provides us with 3 different types of errors to use depending on the context in which we find ourselves:
One of the main and common parameters of the three types of error is the message associated with the error. This message indicates the type of error that occurred, always taking into account the good practices:
According to the standard RFC 4122, it allows us to associate an identifier of operation or request to the error. This is especially useful for tracing errors in requests or transactions that occur between different systems or libraries. The identifier should be created by the process or system that initiates the operation (Frontend, Service ...), being included in all processes and registers (logging with @ netin-logger) so that this can be used in troubleshooting processes. identifier as filter, allowing easy extraction.
Simple example of using the Crash
error type.
import { Crash } from '@netin-js/Crash'
import { v4 } from 'uuid';
const enhancedError = new Crash('Example', v4());
console.log(enhancedError.message); // 'Example'
or even simpler
import { Crash } from '@netin-js/Crash'
const enhancedError = new Crash('Example');
console.log(enhancedError.message); // 'Example'
Crash allows us to add extra information about the error that can be used by higher layers of our application or at the time of recording the errors.
import { Crash } from './Crash';
import fs from 'fs';
import { v4 } from 'uuid';
const operationId = v4();
try {
const myContent = fs.readFileSync('path/to/file');
} catch (error) {
const enhancedError = new Crash(`Error reading the configuration file`, operationId, {
cause: error as Error,
name: 'FileError',
info: {
path: 'path/to/file',
},
});
console.log(enhancedError.trace());
// [ 'FileError: Error reading the configuration file',
// 'caused by Error: ENOENT: no such file or directory, open \'path/to/file\'' ]
}
Crash allows us to easily determine if an error has a specific cause, being able to act differently for each cause.
ourPromiseThatRejectCrash()
.then(()=>{
// Our code in case of success
})
.catch(error => {
if (error.hasCauseWithName('FileError')) {
// Our code in case of file error
} else {
// Our code for the rest type of errors
}
})
Simple example of using Multi
type error.
import { Multi } from '@netin-js/Crash'
import { v4 } from 'uuid';
const enhancedError = new Multi('Example', v4(), {
causes: [new Error('My first check that fail'), new Error('My Second check that fail')]
});
Errors can be added later, which can be especially useful in transformation processes where various errors can appear during execution.
import { Multi, Crash } from '@netin-js/Crash'
import { v4 } from 'uuid';
const arrayOfNumbers: number[] = [];
const operationId = v4();
let enhancedError: Multi | undefined;
for (let idx = 0; idx < 10; idx++) {
arrayOfNumbers.push(Math.random() * (10 - 0) + 0);
}
for (const entry of arrayOfNumbers) {
if (entry > 5) {
const newError = new Crash(`Number of of range`, operationId, {
name: 'ValidationError',
info: {
number: entry,
},
});
if (enhancedError) {
enhancedError.push(newError);
} else {
enhancedError = new Multi(`Errors during validation process`, operationId, {
causes: [newError],
});
}
}
}
if (enhancedError) {
console.log(enhancedError.trace());
}
The most typical way to use the Boom
type of error is through helpers, thanks to them, we can create information-rich errors, within the context of our REST API, in a simple way.
import express from 'express';
import { BoomHelpers } from '@netin-js/crash';
import { v4 } from 'uuid';
const app = express();
const port = 3000;
app.get('/', (req, res) => {
const enhancedError = BoomHelpers.internalServerError('Error during request processing', v4());
res.status(enhancedError.status).json(enhancedError);
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
Any request to the previous endpoint will return the following result:
{
"uuid": "2a931651-6921-4bda-864e-123b69829cff",
"status": 500,
"code": "HTTP",
"title": "Internal Server Error",
"detail": "Error during request processing"
}
We can even provide more information to the user through the options.
import express from 'express';
import { BoomHelpers, Crash } from '@netin-js/crash';
import { v4 } from 'uuid';
const app = express();
const port = 3000;
const mock = (req: express.Request, res: express.Response, next: express.NextFunction): void => {
req.body = {};
req.body.reqId = v4();
req.body.order = 'myOrder';
next();
};
function getOrder(order: string, uuid: string): Promise<void> {
return Promise.reject(
new Crash(`The requested record is not present in the system`, uuid, {
name: 'DataNotPresent',
info: { order },
})
);
}
app.use(mock);
app.get('/order', (req, res) => {
getOrder(req.body.order, req.body.reqId)
.then(result => {
res.status(200).json(result);
})
.catch(error => {
const enhancedError = BoomHelpers.badRequest(
'Error getting the requested order',
req.body.reqId,
{
cause: error,
source: {
pointer: req.path,
parameters: { order: req.body.order },
},
name: error.name,
info: {
detail: error.message,
},
links: {
help: 'help/link/about/orders',
},
}
);
res.status(enhancedError.status).json(enhancedError);
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
Any request to the previous endpoint will return the following result:
{
"uuid": "59fe72ec-44dc-4cc3-84ec-46c98df00283",
"links": {
"help": "help/link/about/orders"
},
"status": 400,
"code": "DataNotPresent",
"title": "Bad Request",
"detail": "Error getting the requested order",
"source": {
"pointer": "/order",
"parameters": {
"order": "myOrder"
}
},
"meta": {
"detail": "The requested record is not present in the system"
}
}
As in the rest of the Netin Systems repositories, any collaboration is always welcome.
If you think there is a bug, create a [bug] (https://docs.microsoft.com/en-us/azure/devops/boards/backlogs/manage-bugs) providing as much information as possible.
If you want to make a new contribution, create a new branch, taking into account the flow established by GitFlow , make your modifications to it and request their approval through Pull Request, correctly filling in the template.
Copyright 2021 Network Intelligence S.L. All rights reserved.
Note: All information contained herein is, and remains the property of Network Intelligence S.L. and its suppliers, if any. The intellectual and technical concepts contained herein are property of Network Intelligence S.L. and its suppliers and may be covered by European and Foreign patents, patents in process, and are protected by trade secret or copyright. Dissemination of this information or the reproduction of this material is strictly forbidden unless prior written permission is obtained from Network Intelligence.
Generated using TypeDoc