New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

error-ninja

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

error-ninja - npm Package Compare versions

Comparing version 0.2.0 to 1.0.0

examples/example.js

4

.eslintrc.js
module.exports = {
"extends": "eslint-config-recombix",
"rules": {
"id-length": 0,
"no-console": 0,
"no-process-exit": 0,
"max-params": 0,
}
};

@@ -10,3 +10,3 @@ {

"name": "error-ninja",
"version": "0.2.0",
"version": "1.0.0",
"description": "Allows us to pre-define error types and error messages in each module.",

@@ -27,2 +27,5 @@ "keywords": [

"main": "errorNinja.js",
"scripts": {
"example": "node ./examples/example.js"
},
"author": "Josh Cole <saikojosh@gmail.com> (http://www.JoshuaCole.me)",

@@ -33,11 +36,15 @@ "dependencies": {},

"eslint-config-recombix": "latest",
"eslint-config-vue": "latest",
"eslint-plugin-disable": "latest",
"eslint-plugin-filenames": "latest",
"eslint-plugin-html": "latest",
"eslint-plugin-json": "latest",
"eslint-plugin-node": "latest",
"eslint-plugin-promise": "latest"
"eslint-plugin-promise": "latest",
"eslint-plugin-vue": "latest"
},
"license": "MIT",
"engines": {
"node": ">6"
"node": ">8.3"
}
}
# Error-Ninja
Error handling in Node can be a pain, it's tempting to just pass strings around so it's easier to handle, but using a proper Error object is a better way and Error Ninja can help with this.
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 the Point?
1. Outputs a human-friendly error message in the terminal.
2. Makes it easy to locate the source of errors in your code by assigning human-readable IDs to every error.
3. Makes it easy for your frontend code to respond to errors without needing to understand the backend implementation.
4. Allows you to decorate errors with extra properties which get printed to the terminal when the error gets thrown.
5. Enables intelligent handling of errors using the extra properties added to the error e.g. `if (err.id === 'XXX') {}`.
6. Errors from other modules or the Node.js core can be converted to ErrorNinja errors using `ErrorNinja.convert()`.
7. Can be used with Promises to quit the process in a .catch() block without causing any warnings.
8. Behaves just like a traditional JavaScript Error - can be thrown and caught.
9. Makes it easy to debug in development AND production.
10. Allows you to detect if a variable is a JavaScript error or an ErrorNinja error.
## What's this for?
This library is for you if you want to:
## Define Your Error Messages
First, at the top of a module define the dictionary of error IDs and error messages that will be available to that module.
1) Maintain error stack traces across async boundaries.
2) Throw and catch errors to indicate problems instead of relying on function return values.
3) Implement custom error constructors e.g. `new DataStreamError()`.
4) Attach data/properties to errors to give them additional context.
5) Understand how bugs are triggered and how they bubble up your call stack.
6) Work with native JavaScript errors as well as your own.
7) Make your debugging life easier.
8) Add an ID property to errors to make them easy to log and trace in production.
9) Add more power to your errors without altering their native JavaScript and Node.js functionality.
## Caveats
* If you throw an error and fail to catch it you will only get the final stack trace in the terminal. This is designed behaviour so we don't impact the performance of your application by directly reading the stack traces from the full chain of errors. Bottom line: always catch errors!
* Using `fullInsight: true` is recommended for development but not for production as it maintains a reference to every error that added to the chain.
## Quick Start
See the `./examples/example.js` file for a working example or execute: `npm run example`.
```javascript
const ErrorNinja = require('error-ninja').define({
INVALID_BLOG_ID: 'The given blog ID does not exist!',
ATTACHMENT_TOO_BIG: 'You cannot upload an attachment that big!',
SOME_ERROR: 'Woah, this code is buggy!',
const setupErrorNinja = require(`error-ninja`);
const createErrorClass = setupErrorNinja({
stackTraceLimit: 20, // Expand the maximum number of stack trace frames for all errors.
fullInsight: true, // Capture full errors and stack traces instead of just the error name, ID and message.
});
```
## Create and Throw Errors
Now you can create an error. You can throw this error just like you would do normally.
```javascript
const err = new ErrorNinja('INVALID_BLOG_ID');
throw err;
const DataStreamError = createErrorClass(`DataStreamError`);
const FatalError = createErrorClass(`FatalError`);
/*
Outputs...
Error [INVALID_BLOG_ID]: The given blog ID does not exist!
at new ErrorNinja (/path/to/Error-Ninja/errorNinja.js:36:19)
at Object.<anonymous> (/path/to/myScript.js:59:13)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
*/
```
try {
## Include Data in the Error
If you need to include some extra properties in the error you can pass a second parameter to the error constructor. By default this data will be output to the terminal if the error is thrown, and you'll also be able to access it when handling your error.
```javascript
const err = new ErrorNinja('ATTACHMENT_TOO_BIG', { fileSize: 17483, maxSize: 1024, name: 'crash.log' });
console.log(err.data.fileSize);
throw err;
// ...something bad happens...
/*
Outputs...
Error [ATTACHMENT_TOO_BIG]: You cannot upload an attachment that big!
----------
{"fileSize":17483,"maxSize":1024,"name":"crash.log"}
----------
at new ErrorNinja (/path/to/Error-Ninja/errorNinja.js:36:19)
at Object.<anonymous> (/path/to/myScript.js:59:13)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
*/
throw new DataStreamError(`NETWORK_DISC`, `The network disconnected.`, { status: 500, uri: `...` });
}
catch (err) {
const newErr = FatalError.chain(err, `DATA_INTERRUPTED`, `Unable to load the resource.`);
console.error(newErr.pretty(true));
}
```
## Turn Off Data Console Output
To prevent the extra error data being output in the terminal you can do one of two things:
## Example Code
1) Pass _false_ as the 3rd argument when creating an error:
#### 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.
```javascript
const err = new ErrorNinja('SOME_ERROR', { abc: 'do-not-output-this' }, false);
const someError = new Error(`Something bad happened`);
const anotherError = DataStreamError.chain(someError, `DATA_INTERRUPTED`, `Failed to load the resource.`);
const newError = FatalError.chain(someError, `FATAL`, `Unable to continue.`);
```
2) Or you can turn off data output for all errors created by this instance of Error Ninja by passing in a config option when defining your error dictionary.
#### 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.
```javascript
const ErrorNinja = require('error-ninja').define({ ... }, { outputData: false });
const newErr = FatalError.chain(someError, `DATA_INTERRUPTED`, `Unable to load the resource.`);
const causes = newErr.cause();
causes.forEach(cause => console.error(`Cause:`, cause));
```
## Access Useful Properties in the Error
Apart from the usual error properties you can also access the following additional properties that should help with handling your errors.
#### 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.
```javascript
const err = new ErrorNinja('ATTACHMENT_TOO_BIG', { fileSize: 17483, maxSize: 1024, name: 'crash.log' });
err.id; // "ATTACHMENT_TOO_BIG"
err.isError; // True
err.isNinja; // True
err.human; // "You cannot upload an attachment that big!"
err.data; // (mixed) e.g. { fileSize: 17483, maxSize: 1024, name: 'crash.log' }
// data defaults to {}
const newErr = FatalError.chain(someError, `DATA_INTERRUPTED`, `Unable to load the resource.`);
const prettyOutput = newErr.pretty(true);
console.error(prettyOutput);
```
## Convert an existing error to an ErrorNinja
You can convert ordinary errors created by the Node.js core or other modules to ErrorNinja errors without throwing them:
## Example Output
Some sample output from the `examples.js` file.
#### Output when calling `newErr.cause()`:
```javascript
doSomethingAsync((err, result) => {
err = ErrorNinja.convert(err, 'MY_ERROR_ID'/* , data, outputData */);
ErrorNinja.isNinja(err); // true.
throw err;
});
[ { 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: 'UriError',
id: 'INVALID_URI',
message: 'The specified URI is not a string.',
data: { uri: null, typeOf: 'object' },
__isLite: true } ]
```
You can also convert and throw them immediately:
#### Output when calling `newErr.cause(true)`:
```javascript
doSomethingAsync((err, result) => {
if (err) { ErrorNinja.throw(err, 'MY_ERROR_ID'/* , data, outputData */); }
});
[ { FatalError: [CRASHED] A fatal error occured.
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)
__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 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)
__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 },
{ UriError: [INVALID_URI] The specified URI is not a string.
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)
__options: { fullInsight: true },
name: 'UriError',
id: 'INVALID_URI',
__originalMsg: 'The specified URI is not a string.',
__chain: [],
__isErrorNinja: true,
__isWrapped: false,
__isLite: false,
data: { uri: null, typeOf: 'object' } } ]
```
Alternatively, you can convert the error and quit the Node.js process with a non-zero error code (which will be the ID of your error) without throwing it. The error and its stack trace will be printed to the terminal in the same way they would if you had thrown the error. This prevents Node.js from complaining when you need to output an error in a Promise .catch() block whilst terminating the process.
#### Output when calling `err.pretty()`:
```javascript
doSomethingAsync()
.then(result => {
// Do something else here...
})
.catch(ErrorNinja.quit('MY_ERROR_ID')); // Takes the "err" param passed to the .catch() block and converts it.
```
===========================================================================
<1> FatalError: [CRASHED] A fatal error occured.
---------------------------------------------------------------------------
@property {number} someProperty: <123>
===========================================================================
<2> VideoStreamError: [CONNECT_FAILED] Unable to connect to the video server.
===========================================================================
<3> UriError: [INVALID_URI] The specified URI is not a string.
---------------------------------------------------------------------------
@property {object} uri: <null>
@property {string} typeOf: <object>
===========================================================================
```
## How to Tell if a Variable is an Error?
ErrorNinja provides two methods to detect if a variable is an error, or more specifically an ErrorNinja error.
#### Output when calling `err.pretty(true)`:
```javascript
// Ordinary JavaScript errors.
const err1 = new Error();
ErrorNinja.isError(err1)) // true
ErrorNinja.isNinja(err1)) // false
// ErrorNinja errors.
const err2 = new ErrorNinja('...');
ErrorNinja.isError(err2)) // true
ErrorNinja.isNinja(err2)) // true
```
===========================================================================
<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> UriError: [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)
===========================================================================
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc