npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

error-ninja

v1.1.7

Published

A handy library for creating custom error constructors that work across async boundaries in Node.js.

Downloads

43

Readme

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:

  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. Print out stack traces for uncaught errors and unhandled promise rejections.
  10. 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 = 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.
});

const DataStreamError = createErrorClass(`DataStreamError`);
const FatalError = createErrorClass(`FatalError`);

try {

	// ...something bad happens...

	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));
}

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 = 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.`);

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.chain(someError, `DATA_INTERRUPTED`, `Unable to load the resource.`);
const causes = newErr.cause();
causes.forEach(cause => console.error(`Cause:`, cause));

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.chain(someError, `DATA_INTERRUPTED`, `Unable to load the resource.`);
const prettyOutput = newErr.pretty(true);
console.error(prettyOutput);

Example Output

Some sample output from the examples.js file.

Output when calling err.cause():

[ { 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 } ]

Output when calling err.cause(true):

[ { 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 },
  { CustomUriError: [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: 'CustomUriError',
    id: 'INVALID_URI',
    __originalMsg: 'The specified URI is not a string.',
    __chain: [],
    __isErrorNinja: true,
    __isWrapped: false,
    __isLite: false,
    data: { uri: null, typeOf: 'object' } } ]

Output when calling err.pretty():

===========================================================================
  <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>
===========================================================================

Output when calling err.pretty(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> 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)
===========================================================================