custom-error-generator
Advanced tools
Comparing version 3.0.0 to 5.0.0
{ | ||
"name": "custom-error-generator", | ||
"version": "3.0.0", | ||
"version": "5.0.0", | ||
"description": "Custom errors and exceptions in Node.js, done right", | ||
"main": "index.js", | ||
"main": "error.js", | ||
"scripts": { | ||
@@ -7,0 +7,0 @@ "test": "make test" |
node-custom-error | ||
=================== | ||
[![Build Status](https://travis-ci.org/jproulx/node-custom-error.svg?branch=master)](https://travis-ci.org/jproulx/node-custom-error) | ||
Custom errors and exceptions in Node.js, done right. | ||
@@ -12,2 +14,3 @@ | ||
## Usage | ||
```javascript | ||
@@ -22,4 +25,7 @@ var createCustomError = require('custom-error-generator'); | ||
The generator function supports the following parameters: | ||
* `name` {String} (required) - A custom name for this error type, which is printed when logging and in stack traces | ||
* `data` {Object} (optional) - Additional properties to attach to the error, in key=value pairs or as object descriptors | ||
* `parent` {Function} (optional) - A parent Error to subclass from. If supplied, is required to be a prototype of the built-in Error function | ||
@@ -44,14 +50,14 @@ | ||
HTTPError: Something went wrong | ||
at Context.<anonymous> (/Users/jproulx/Projects/node-custom-error/test.js:19:24) | ||
at callFn (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:223:21) | ||
at Hook.Runnable.run (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:216:7) | ||
at next (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runner.js:259:10) | ||
at Object._onImmediate (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runner.js:276:5) | ||
at Context.<anonymous> (/Projects/node-custom-error/test.js:19:24) | ||
at callFn (/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:223:21) | ||
at Hook.Runnable.run (/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:216:7) | ||
at next (/Projects/node-custom-error/node_modules/mocha/lib/runner.js:259:10) | ||
at Object._onImmediate (/Projects/node-custom-error/node_modules/mocha/lib/runner.js:276:5) | ||
at processImmediate [as _immediateCallback] (timers.js:330:15) | ||
ValidationError: Missing field | ||
at Context.<anonymous> (/Users/jproulx/Projects/node-custom-error/test.js:18:24) | ||
at callFn (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:223:21) | ||
at Hook.Runnable.run (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:216:7) | ||
at next (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runner.js:259:10) | ||
at Object._onImmediate (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runner.js:276:5) | ||
at Context.<anonymous> (/Projects/node-custom-error/test.js:18:24) | ||
at callFn (/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:223:21) | ||
at Hook.Runnable.run (/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:216:7) | ||
at next (/Projects/node-custom-error/node_modules/mocha/lib/runner.js:259:10) | ||
at Object._onImmediate (/Projects/node-custom-error/node_modules/mocha/lib/runner.js:276:5) | ||
at processImmediate [as _immediateCallback] (timers.js:330:15) | ||
@@ -63,13 +69,13 @@ ``` | ||
```javascript | ||
console.log(error.toJSON()); | ||
console.log(error.toJSON()); // or console.log(JSON.stringify(error)); | ||
``` | ||
outputs | ||
```bash | ||
{ stack: | ||
{ stack: | ||
[ 'ValidationError: Missing field', | ||
' at Context.<anonymous> (/Users/jproulx/Projects/node-custom-error/test.js:17:24)', | ||
' at callFn (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:223:21)', | ||
' at Hook.Runnable.run (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:216:7)', | ||
' at next (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runner.js:259:10)', | ||
' at Object._onImmediate (/Users/jproulx/Projects/node-custom-error/node_modules/mocha/lib/runner.js:276:5)', | ||
' at Context.<anonymous> (/Projects/node-custom-error/test.js:17:24)', | ||
' at callFn (/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:223:21)', | ||
' at Hook.Runnable.run (/Projects/node-custom-error/node_modules/mocha/lib/runnable.js:216:7)', | ||
' at next (/Projects/node-custom-error/node_modules/mocha/lib/runner.js:259:10)', | ||
' at Object._onImmediate (/Projects/node-custom-error/node_modules/mocha/lib/runner.js:276:5)', | ||
' at processImmediate [as _immediateCallback] (timers.js:330:15)' ], | ||
@@ -83,4 +89,14 @@ arguments: undefined, | ||
## Notes | ||
Care is taken to preserve the built-in error handling behavior as much as possible, with support for checking `instanceof` and `typeof`, as well as making sure the error constructor behaves the same whether it is called with the `new` operator or not. | ||
Care is taken to preserve the built-in error handling behavior as much as possible, supporting: | ||
* `custom instanceOf Error` | ||
* `Error.prototype.isPrototypeOf(custom)` | ||
* `util.isError(custom)` | ||
* `custom = generator('message')` | ||
* `custom = new generator('message');` | ||
In other words, you shouldn't have to worry about these errors affecting your syntax or existing code. Simply drop in place for any existing errors you're throwing and it should work just the same. |
153
test.js
var should = require('should'); | ||
var generateCustomError = require('./index'); | ||
var generateCustomError = require('./'); | ||
var util = require('util'); | ||
describe('Custom Errors', function () { | ||
var Constructor; | ||
var Constructor2; | ||
var Constructor3; | ||
var error; | ||
var error2; | ||
var error3; | ||
var error4; | ||
beforeEach(function () { | ||
Constructor = generateCustomError('TestError'); | ||
Constructor2 = generateCustomError('TestTypeError', { 'bar' : 'baz' }, TypeError); | ||
Constructor2.prototype.foo = 'bar'; | ||
Constructor3 = generateCustomError('TestingTypeError', { 'q' : 's' }, Constructor2); | ||
error = new Constructor('message'); | ||
error2 = new Constructor2('message'); | ||
error3 = new Constructor3(error2); | ||
error4 = new Constructor3(error3); | ||
}); | ||
it('should inherit from the Error prototype', function (done) { | ||
error.should.be.an.instanceOf(Error); | ||
Error.prototype.isPrototypeOf(error).should.equal(true); | ||
var TestError = generateCustomError('TestError'); | ||
var SubTestError = generateCustomError('TestError', {}, TestError); | ||
var SubTypeError = generateCustomError('SubTypeError', {}, TypeError); | ||
var ValidationError = generateCustomError('ValidationError', { 'message' : 'Default Message', 'bar' : 'baz' }, TypeError); | ||
ValidationError.prototype.foo = 'bar'; | ||
var errors = { | ||
'with new operator' : new TestError('Message'), | ||
'without new operator' : TestError('Message'), | ||
'with inherited constructor' : new SubTestError('Message') | ||
}; | ||
describe('The custom error generator', function () { | ||
function create () { | ||
var args = Array.prototype.slice.call(arguments); | ||
return function () { | ||
return generateCustomError.apply(null, args); | ||
}; | ||
} | ||
var error = new ValidationError('Missing field'); | ||
it('should require a valid name parameter', function (done) { | ||
create().should.throw(); | ||
create(null).should.throw(); | ||
create(undefined).should.throw(); | ||
create(400).should.not.throw(); | ||
create('TestError').should.not.throw(); | ||
return done(); | ||
}); | ||
it('should inherit from the Constructor prototype', function (done) { | ||
error.should.be.an.instanceOf(Constructor); | ||
Constructor.prototype.isPrototypeOf(error).should.equal(true); | ||
it('should require inheritance from the Error prototype, if supplied', function (done) { | ||
create('Testing', {}, {}).should.throw(); | ||
create('Testing', {}, TypeError).should.not.throw(); | ||
create('Testing', {}, TestError).should.not.throw(); | ||
return done(); | ||
}); | ||
it('should return an error without the new operator', function (done) { | ||
var error = Constructor('message'); | ||
it('should inherit from a parent Error, if supplied', function (done) { | ||
error.should.be.an.instanceOf(Error); | ||
error.stack.split('\n')[1].should.containEql('/test.js:'); | ||
error.should.be.an.instanceOf(TypeError); | ||
Error.prototype.isPrototypeOf(error).should.equal(true); | ||
TypeError.prototype.isPrototypeOf(error).should.equal(true); | ||
return done(); | ||
}); | ||
it('should identify as an Error object - [object Error]', function (done) { | ||
Object.prototype.toString.call(error).should.equal('[object Error]'); | ||
it('should retain properties passed in as a parameter', function (done) { | ||
error.should.have.property('bar'); | ||
error.bar.should.equal('baz'); | ||
return done(); | ||
}); | ||
it('should identify as an error to util#isError', function (done) { | ||
util.isError(error).should.equal(true); | ||
it('should allow for prototype modification', function (done) { | ||
error.should.have.property('foo'); | ||
error.foo.should.equal('bar'); | ||
return done(); | ||
}); | ||
it('should override the default Error function name', function (done) { | ||
error.name.should.equal('TestError'); | ||
error.toString().should.equal('TestError: message'); | ||
it('should allow for JSON serialization', function (done) { | ||
var serialized = error.toJSON(); | ||
serialized.should.have.property('message'); | ||
serialized.should.have.property('stack'); | ||
return done(); | ||
}); | ||
it('should have a proper stack trace', function (done) { | ||
error.should.have.property('stack'); | ||
error.stack.split('\n')[1].should.containEql('/test.js:'); | ||
it('should modify the stack trace when another Error is passed in', function (done) { | ||
var suberror = new SubTypeError('Encountered validation error', error); | ||
suberror.should.have.property('message'); | ||
suberror.message.should.equal('Encountered validation error'); | ||
suberror.should.have.property('stack'); | ||
suberror.stack.should.containEql('SubTypeError: Encountered validation error'); | ||
suberror.stack.should.containEql('ValidationError: Missing field'); | ||
return done(); | ||
}); | ||
it('should retain properties passed to the generator', function (done) { | ||
error2.should.have.property('bar'); | ||
error2.bar.should.equal('baz'); | ||
it('should attach object keys to itself when an object is passed in', function (done) { | ||
var suberror = new SubTypeError('Testing', { | ||
'q' : 's' | ||
}); | ||
suberror.should.have.property('q'); | ||
suberror.q.should.equal('s'); | ||
return done(); | ||
}); | ||
it('should inherit from a parent Error, if specified', function (done) { | ||
error2.should.be.an.instanceOf(Error); | ||
error2.should.be.an.instanceOf(TypeError); | ||
error2.should.be.an.instanceOf(Constructor2); | ||
return done(); | ||
}); | ||
Object.keys(errors).forEach(function (name) { | ||
var error = errors[name]; | ||
describe('Custom errors created ' + name, function () { | ||
it('should inherit from the Error prototype', function (done) { | ||
error.should.be.an.instanceOf(Error); | ||
Error.prototype.isPrototypeOf(error).should.equal(true); | ||
return done(); | ||
}); | ||
it('should inherit from the TestError prototype', function (done) { | ||
error.should.be.an.instanceOf(TestError); | ||
TestError.prototype.isPrototypeOf(error).should.equal(true); | ||
return done(); | ||
}); | ||
it('should identify as an Error object - [object Error]', function (done) { | ||
Object.prototype.toString.call(error).should.equal('[object Error]'); | ||
return done(); | ||
}); | ||
it('should identify as an error to util#isError', function (done) { | ||
util.isError(error).should.equal(true); | ||
return done(); | ||
}); | ||
it('should override the default Error function name', function (done) { | ||
error.name.should.equal('TestError'); | ||
error.toString().should.equal('TestError: Message'); | ||
return done(); | ||
}); | ||
it('should have a stack trace that masks the module internals', function (done) { | ||
error.should.have.property('stack'); | ||
error.stack.split('\n')[1].should.containEql('node-custom-error/test.js:'); | ||
return done(); | ||
}); | ||
}); | ||
it('should allow for prototype modifications', function (done) { | ||
error2.should.have.property('foo'); | ||
error2.foo.should.equal('bar'); | ||
return done(); | ||
}); | ||
it('should validate arguments before creating errors', function (done) { | ||
function create () { | ||
var args = Array.prototype.slice.call(arguments); | ||
return function () { | ||
return generateCustomError.apply(null, args); | ||
}; | ||
} | ||
create().should.throw(); | ||
create('Testing', {}, {}).should.throw(); | ||
create('Testing', {}).should.not.throw(); | ||
return done(); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15064
234
98
1