Error-Ninja
A handy library for creating custom error constructors that work across async boundaries in Node.js. JavaScript error handling has never been this nice!
What's this for?
This library is for you if you want to:
- Maintain error stack traces across async boundaries.
- Throw and catch errors to indicate problems instead of relying on function return values.
- Implement custom error constructors e.g.
new DataStreamError()
. - Attach data/properties to errors to give them additional context.
- Understand how bugs are triggered and how they bubble up your call stack.
- Work with native JavaScript errors as well as your own.
- Make your debugging life easier.
- Add an ID property to errors to make them easy to log and trace in production.
- Print out stack traces for uncaught errors and unhandled promise rejections.
- Add more power to your errors without altering their native JavaScript and Node.js functionality.
v1.x Breaking Changes
The new v1 of this library is a complete rewrite and is not backwards compatible with previous versions.
Quick Start
See the ./examples/example.js
file for a working example or execute: npm run example
.
const setupErrorNinja = ; const createErrorClass = ; const DataStreamError = ;const FatalError = ; try // ...something bad happens... throw `NETWORK_DISC` `The network disconnected.` status: 500 uri: `...` ; catch err const newErr = FatalError; console;
Example Code
Chaining errors together
The magic of ErrorNinja occurs when you chain errors together. This allows you to throw and catch as much as you like and obtain a full understanding of how errors propagate through your call stack.
const someError = `Something bad happened`;const anotherError = DataStreamError;const newError = FatalError;
Understanding the cause of an error
By default err.cause() returns an array of the IDs and messages for the chained errors up to this point. If true
is passed as the first parameter and the fullInsight
option is enabled it will return the original error objects.
const newErr = FatalError;const causes = newErr;causes;
Pretty printing a chain of errors to the terminal
By default err.pretty() returns a formatted string containing the IDs and messages for the chained errors up to this point. If true
is passed as the first parameter and the fullInsight
option is enabled it will add the stack traces to the output.
const newErr = FatalError;const prettyOutput = newErr;console;
Example Output
Some sample output from the examples.js
file.
err.cause()
:
Output when calling name: 'FatalError' id: 'CRASHED' message: 'A fatal error occured.' data: someProperty: 123 __isLite: true name: 'VideoStreamError' id: 'CONNECT_FAILED' message: 'Unable to connect to the video server.' data: {} __isLite: true name: 'CustomCustomUriError' id: 'INVALID_URI' message: 'The specified URI is not a string.' data: uri: null typeOf: 'object' __isLite: true
err.cause(true)
:
Output when calling FatalError: CRASHED A fatal error occured at at process at FunctionModule at at __options: fullInsight: true name: 'FatalError' id: 'CRASHED' __originalMsg: 'A fatal error occured.' __chain: NinjaError ErrorClass __isErrorNinja: true __isWrapped: false __isLite: false data: someProperty: 123 VideoStreamError: CONNECT_FAILED Unable to connect to the video server at at process at FunctionModule at at __options: fullInsight: true name: 'VideoStreamError' id: 'CONNECT_FAILED' __originalMsg: 'Unable to connect to the video server.' __chain: ErrorClass __isErrorNinja: true __isWrapped: false __isLite: false data: undefined CustomUriError: INVALID_URI The specified URI is not a string at at at Object<anonymous> /Users/josh/Repositories/Personal/Error-Ninja/examples/examplejs:97:1 at Module at ObjectModule_extensions at Module at at FunctionModule at FunctionModule at at __options: fullInsight: true name: 'CustomUriError' id: 'INVALID_URI' __originalMsg: 'The specified URI is not a string.' __chain: __isErrorNinja: true __isWrapped: false __isLite: false data: uri: null typeOf: 'object'
err.pretty()
:
Output when calling ===========================================================================
<1> FatalError: [CRASHED] A fatal error occured.
---------------------------------------------------------------------------
@property {number} someProperty: <123>
===========================================================================
<2> VideoStreamError: [CONNECT_FAILED] Unable to connect to the video server.
===========================================================================
<3> CustomUriError: [INVALID_URI] The specified URI is not a string.
---------------------------------------------------------------------------
@property {object} uri: <null>
@property {string} typeOf: <object>
===========================================================================
err.pretty(true)
:
Output when calling ===========================================================================
<1> FatalError: [CRASHED] A fatal error occured.
===========================================================================
@property {number} someProperty: <123>
---------------------------------------------------------------------------
at startVideoStream (/Users/josh/Repositories/Personal/Error-Ninja/examples/example.js:71:31)
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:744:11)
at startup (internal/bootstrap/node.js:285:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
===========================================================================
<2> VideoStreamError: [CONNECT_FAILED] Unable to connect to the video server.
---------------------------------------------------------------------------
at startVideoStream (/Users/josh/Repositories/Personal/Error-Ninja/examples/example.js:71:31)
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:744:11)
at startup (internal/bootstrap/node.js:285:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
===========================================================================
<3> CustomUriError: [INVALID_URI] The specified URI is not a string.
===========================================================================
@property {object} uri: <null>
@property {string} typeOf: <object>
---------------------------------------------------------------------------
at connectToVideoServer (/Users/josh/Repositories/Personal/Error-Ninja/examples/example.js:52:26)
at startVideoStream (/Users/josh/Repositories/Personal/Error-Ninja/examples/example.js:66:9)
at Object.<anonymous> (/Users/josh/Repositories/Personal/Error-Ninja/examples/example.js:97:1)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
at startup (internal/bootstrap/node.js:285:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
===========================================================================