@leyyo/exception
v1.0.5
Published
Abstract Exception/Error for JavaScript/TypeScript
Downloads
36
Readme
exception
Abstract Exception/Error for JavaScript/TypeScript
Leyyo > Exception
- Dynamic/extendable extention for JavaScript/TypeScript
- Supports supports params
- Supports cause or previous error, expecially re-triggered errors in try/catch
- Support parsed stach-trace as array of {file: string, method: string, line: number, arguments: Array};
Aim
- Standardized Exception structure
- Easy Monitoring
- Decrease to figure out errors
- Modern exception logging
TODO
- [ ] I18N dictionary
- [x] Logger binding
- [ ] API response supports
- [ ] Severity usage
- [ ] Environment based usage
- [ ] Triggers (email, sms, slack etc)
Install
npm i @leyyo/exception
Standards
- [x] Language:
TS
- [x] Eslint:
Yes
- [x] Static Code Analysis:
Yes
IntelliJ Code Inspections - [x] DDD - Document Driven:
No
- [x] EDD - Exception Driven:
Yes
- [ ] TDD - Test Driven:
Yes
go to test folder
Commands
npm run clear
// clears "dist" foldernpm run lint
// runs eslint for static code analysisnpm run build
// builds JS files at "dist" foldernpm run test
// runs test files in "test" foldernpm run test:watch
*// runs test with watch optionnpm run test:coverage
*// runs test with coverage
Assumption
- Your company name is 'Lemonade'
Basic Sample
Define Your Named Exception
// file: DbConnectionException.ts
import {Exception} from "@leyyo/exception";
@Fqn('lemonade')
export class DbConnectionException extends Exception {
constructor(type: string, host: string) {
super(`Database[${type}] could not connect to host: "${host}"`, {type, path});
}
}
Base Exception
// file: MongoConnect.ts --sample
import {DbConnectionException} from "./DbConnectionException";
// ....
throw new DbConnectionException('mongodb', 'mongo.44444.aws.com');
It generates ...
{
"name": "lemonade.DbConnectionException",
"message": "Database[mongodb] could not connect to host: \"mongo.44444.aws.com\"",
"params": {
"type": "mongodb",
"host": "mongo.44444.aws.com"
}
}
With Chained Exception
import {DbConnectionException} from "./DbConnectionException";
const host = 'mongo.44444.aws.com';
try {
await mongodb.connect(host, 27017, 'user', 'pa55w0rd'); // fake code :)
} catch (e) { // assume that e is instance of MongoNetworkError
throw new DbConnectionException('mongodb', host).withCause(e); // append previous error to raised error
}
It generates ...
{
"name": "lemonade.DbConnectionException",
"message": "Database[mongodb] could not connect to host: \"mongo.44444.aws.com\"",
"params": {
"type": "mongodb",
"host": "mongo.44444.aws.com"
},
"cause": {
"name": "MongoNetworkError",
"message": "failed to connect to server [mongo.44444.aws.com:27017] on first connect"
}
}
With Error Trace
import {DbConnectionException} from "./DbConnectionException";
const host = 'mongo.44444.aws.com';
try {
await mongodb.connect(host, 27017, 'user', 'pa55w0rd'); // fake code :)
} catch (e) { // assume that e is instance of MongoNetworkError
throw new DbConnectionException('mongodb', host).withCause(e).withStack(); // parses native e.stack
}
It generates ...
{
"name": "lemonade.DbConnectionException",
"message": "Database[mongodb] could not connect to host: \"mongo.44444.aws.com\"",
"params": {
"type": "mongodb",
"host": "mongo.44444.aws.com"
},
"cause": {
"name": "MongoNetworkError",
"message": "failed to connect to server [mongo.44444.aws.com:27017] on first connect"
},
"parsedStack": [
{
"file": "... file path, @look errorUtils.folder",
"method": "function or method name[if in class]",
"line": "line number",
"arguments": ["foo", 5]
}
]
}
Http Sample
Define Your Named Exception
// file: DbConnectionException.ts
import {HttpException} from "@leyyo/exception";
// HttpException is inherited from Exception
// It supports also with withCause and withStack builder methods
// there is only a difference, you set status property, so you can use it for API responses
@Fqn('lemonade')
export class NotFoundRecordException extends HttpException {
constructor(entity: string, id: string | number) {
super(`Record of ${entity} could not be found with id: "${id}"`, 404, {entity, id});
}
}
Usage
// file: NotFoundRecordException.ts --sample
import {NotFoundRecordException} from "./NotFoundRecordException";
// ....
throw new NotFoundRecordException('Customer', 6666);
It generates ...
{
"name": "lemonade.NotFoundRecordException",
"message": "Record of Customer could not be found with id: \"6666\"",
"params": {
"entity": "Customer",
"id": 6666
},
"status": 404
}
Your Custom Abstract Exception
Define Your Named Exception
import {Exception} from "@leyyo/exception";
// you may need your custom abstract error class and you need to inherit all named exception from it
// We assume that you need two properties for all exceptions, and they are environment and micro-service
// there is only a difference, you set status property, so you can use it for API responses
@Fqn('<your.company.package>')
export abstract class LemonadeException extends Exception {
readonly environment: string = process.env.NODE_ENV;
readonly microservice: string = 'notification-api';
protected constructor(message: string, params?: Record<string, unknown>) {
super(message, params);
}
}
A named exception as a sample
// file: DbConnectionException.ts
import {LemonadeException} from "./LemonadeException";
@Fqn('lemonade')
export class DbConnectionException extends LemonadeException {
constructor(type: string, host: string) {
super(`Database[${type}] could not connect to host: "${host}"`, {type, path});
}
}
It generates ...
{
"name": "lemonade.DbConnectionException",
"message": "Database[mongodb] could not connect to host: \"mongo.44444.aws.com\"",
"params": {
"type": "mongodb",
"host": "mongo.44444.aws.com"
},
"environment": "prod",
"microservice": "notification-api"
}
A named Http exception as a sample
import {HttpException} from "@leyyo/exception";
// And also you may need your custom http exception
@Fqn('lemonade')
export abstract class LemonadeHttpException extends HttpException {
readonly environment: string = process.env.NODE_ENV;
readonly microservice: string = 'notification-api';
protected constructor(message: string, status?: number, params?: Record<string, unknown>) {
super(message, number, params);
}
}
It generates ...
{
"name": "lemonade.NotFoundRecordException",
"message": "Record of Customer could not be found with id: \"6666\"",
"params": {
"entity": "Customer",
"id": 6666
},
"status": 404,
"environment": "prod",
"microservice": "notification-api"
}
Settings
import {exceptionOptions} from "@leyyo/exception";
exceptionOptions
.setLambda((err) => {}) // Function for error log
.setI18nLambda((err, req) => {}) // Function for building I18N
.setStatus((err) => {}) // it should be integer between 400 - 999, else default is 400
;
Author
Date
2021-11-15Name
Mustafa YelmerRepo
github.com/mustafayelmer/exception