Code Monkey home page Code Monkey logo

super-error's Introduction

Super Error

Easily subclass errors.

npm install super-error

Simple Subclassing

SuperError can easily be subclassed using the subclass method. Class hierarchies can be created by using the subclass method on other subclasses.

Error instances can be tested with the instanceof operator how you'd expect. They also have stack, name and message properties, as you'd expect.

var SuperError = require('super-error');

var MyError = SuperError.subclass('MyError');
var MySpecificError = MyError.subclass('MySpecificError');

var err = new MySpecificError('my message');

err instanceof MySpecificError; //=> true
err instanceof MyError;         //=> true
err instanceof SuperError;      //=> true
err instanceof Error;           //=> true

throw err;

The default SuperError constructor also accepts a plain object of properties to assign on the error.

var err = new MySpecificError('my message', {code: 404});
// Or, equivalently:
var err = new MySpecificError({message: 'my message', code: 404});

err.message; //=> 'my message'
err.code;    //=> 404

Custom Constructors

A custom constructor can be passed to subclass, which will hide all super constructors. If you want to propagate arguments to the parent constructor, call it explicitly.

var SuperError = require('super-error');

var ERROR_CODES = {
  1: 'Invalid foo',
  2: 'Invalid bar',
  3: 'Invalid baz'
};

var MyCodeError = SuperError.subclass('MyCodeError', function(code) {
  this.code = code;
  this.message = ERROR_CODES[code];
});

var err = new MyCodeError(2);

err.code;    //=> 2
err.message; //=> 'Invalid bar'

throw err;

var MyCustomError = SuperError.subclass('MyCustomError', function(message, properties) {
  SuperError.call(this, 'Decorated ' + message, properties);
});

Custom ES6 Classes

The custom constructor passed to subclass can be an ES6 class, which must extend (directly or indirectly) SuperError.

var SuperError = require('super-error');

var ERROR_CODES = {
  1: 'Invalid foo',
  2: 'Invalid bar',
  3: 'Invalid baz'
};

var MyES6CodeError = SuperError.subclass('MyES6CodeError', class extends SuperError {
  constructor(code) {
    super();
    this.code = code;
  }
  get message() {
    return ERROR_CODES[this.code];
  }
});

var err = new MyES6CodeError(2);

err.code;    //=> 2
err.message; //=> 'Invalid bar'

throw err;

Exporting Error Classes

An exports object can be passed to subclass in order to automatically export the error class. This prevents repeating the class name more than twice and simplifies a common pattern.

var SuperError = require('super-error');

var MyError = SuperError.subclass(exports, 'MyError');
var MySpecificError = MyError.subclass(exports, 'MySpecificError');

exports.MyError === MyError;                 //=> true
exports.MySpecificError === MySpecificError; //=> true

Error Causes

SuperError instances can wrap other Error or SuperError instances as their cause. This allows for higher-level error matching and handling at the top of a call stack without losing any information about the original specific cause.

Causes are set using causedBy on a SuperError instance. The instance is returned from the method for ease of use with throw or callbacks.

var SuperError = require('super-error');

var MyParseError = SuperError.subclass('MyParseError');

try {
  var obj = JSON.parse('"foo');
} catch (e) {
  throw new MyParseError('failed to parse').causedBy(e);
}

The cause is saved on the cause property of the SuperError instance, and the stack traces are concatenated. The original stack trace can be accessed through the ownStack property.

MyParseError: failed to parse
    at Object.<anonymous> (example.js:8:9)
    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
Cause: SyntaxError: Unexpected end of input
    at Object.parse (native)
    at Object.<anonymous> (example.js:6:18)
    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

In a chain of nested wrapped errors, the original unwrapped cause can be accessed through the rootCause property of each SuperError instance in the chain.

var SuperError = require('super-error');

var WrappedError = SuperError.subclass('WrappedError');
var TopError = SuperError.subclass('TopError');

var cause = new Error('cause');
var wrapped = new WrappedError('wrapped').causedBy(cause);
var top = new TopError('top').causedBy(wrapped);

top.cause.message;     //=> 'wrapped'
top.rootCause.message; //=> 'cause'

super-error's People

Contributors

briganti avatar causal-agent avatar cdnbacon avatar dependabot[bot] avatar dustinblackman avatar insightfuls avatar nicoespeon avatar peakwinter avatar valeriangalliat avatar vcianciarelli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

insightfuls

super-error's Issues

Allow wrapping errors of other types

Allow wrapping original (low-level) errors in (high-level) errors, saving them as the cause. This is something that Bluebird's OperationalError does, and is a feature of error types in Rust.

e.g.

try {
  JSON.parse('"foo');
} catch(e) {
  return done(SuperError.fromError(e, 'something bad happened');
}

Override default constructor

I'd like to create an error with a custom constructor taking an object as parameter.

Currently the default constructor is always called, whether I define my custom constructor or no, resulting in the parameter object being merged in the error instance.

Example:

var CustomError = SuperError.subclass('CustomError', function (obj) {
  this.bar = obj.foo
})

new CustomError({ foo: 42, ignoreMe: 1337 })

// Expected: { bar: 42 }
// Documented (and actual result): { foo: 42, ignoreMe: 1337, bar: 42 }

Is there a way to prevent the default constructor to be called (or call it with different arguments)?

BTW I believe it's really counter-intuitive to have the default constructor always called even if we define a custom constructor (even if documented), especially because one use case I'd expect for a custom constructor is to allow the end user to pass different kind of arguments than the super constructor (even if internally we can still apply the original constructor with adapted arguments).

A solution not involving any change in super-error could be to define some kind of static constructor like CustomError.create(myObject) calling the default constructor with the transformed arguments.

But I'd like other opinions on this behavior, and maybe discuss if we expect/want the default constructor to be always called or no.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.