mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
@@ -1,21 +1,19 @@
|
||||
# overleaf-error-type
|
||||
# @overleaf/o-error
|
||||
|
||||
Make custom error types that:
|
||||
Make custom error classes that:
|
||||
- pass `instanceof` checks,
|
||||
- have stack traces,
|
||||
- support custom messages and properties (`info`), and
|
||||
- can wrap internal errors (causes) like [VError](https://github.com/joyent/node-verror).
|
||||
|
||||
## For ES6
|
||||
|
||||
ES6 classes make it easy to define custom errors by subclassing `Error`. Subclassing `OError` adds a few extra helpers.
|
||||
|
||||
### Usage
|
||||
## Usage
|
||||
|
||||
#### Throw an error directly
|
||||
### Throw an error directly
|
||||
|
||||
```js
|
||||
const OError = require('overleaf-error-type')
|
||||
const OError = require('@overleaf/o-error')
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new OError({
|
||||
@@ -25,13 +23,13 @@ function doSomethingBad () {
|
||||
}
|
||||
doSomethingBad()
|
||||
// =>
|
||||
// { ErrorTypeError: did something bad
|
||||
// { OError: did something bad
|
||||
// at doSomethingBad (repl:2:9) <-- stack trace
|
||||
// name: 'ErrorTypeError', <-- default name
|
||||
// name: 'OError', <-- default name
|
||||
// info: { thing: 'foo' } } <-- attached info
|
||||
```
|
||||
|
||||
#### Custom error class
|
||||
### Custom error class
|
||||
|
||||
```js
|
||||
class FooError extends OError {
|
||||
@@ -51,7 +49,7 @@ doFoo()
|
||||
// info: { foo: 'bar' } } <-- attached info
|
||||
```
|
||||
|
||||
#### Wrapping an inner error (cause)
|
||||
### Wrapping an inner error (cause)
|
||||
|
||||
```js
|
||||
function doFoo2 () {
|
||||
@@ -90,91 +88,11 @@ try {
|
||||
// ...
|
||||
```
|
||||
|
||||
## For ES5
|
||||
|
||||
For backward compatibility, the following ES5-only interface is still supported.
|
||||
|
||||
The approach is based mainly on https://gist.github.com/justmoon/15511f92e5216fa2624b; it just tries to DRY it up a bit.
|
||||
|
||||
### Usage
|
||||
|
||||
#### Define a standalone error class
|
||||
|
||||
```js
|
||||
const OError = require('overleaf-error-type')
|
||||
|
||||
const CustomError = OError.define('CustomError')
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new CustomError()
|
||||
}
|
||||
doSomethingBad()
|
||||
// =>
|
||||
// CustomError <-- correct name
|
||||
// at doSomethingBad (repl:2:9) <-- stack trace
|
||||
```
|
||||
|
||||
#### Define an error subclass
|
||||
|
||||
```js
|
||||
const SubCustomError = OError.extend(CustomError, 'SubCustomError')
|
||||
|
||||
try {
|
||||
throw new SubCustomError()
|
||||
} catch (err) {
|
||||
console.log(err.name) // => SubCustomError
|
||||
console.log(err instanceof SubCustomError) // => true
|
||||
console.log(err instanceof CustomError) // => true
|
||||
console.log(err instanceof Error) // => true
|
||||
}
|
||||
```
|
||||
|
||||
#### Add custom message and/or properties
|
||||
|
||||
```js
|
||||
const UserNotFoundError = OError.define('UserNotFoundError',
|
||||
function (userId) {
|
||||
this.message = `User not found: ${userId}`
|
||||
this.userId = userId
|
||||
})
|
||||
|
||||
throw new UserNotFoundError(123)
|
||||
// => UserNotFoundError: User not found: 123
|
||||
```
|
||||
|
||||
#### Add custom Error types under an existing class
|
||||
|
||||
```js
|
||||
class User {
|
||||
static lookup (userId) {
|
||||
throw new User.UserNotFoundError(userId)
|
||||
}
|
||||
}
|
||||
|
||||
OError.defineIn(User, 'UserNotFoundError', function (userId) {
|
||||
this.message = `User not found: ${userId}`
|
||||
this.userId = userId
|
||||
})
|
||||
|
||||
User.lookup(123)
|
||||
// =>
|
||||
// UserNotFoundError: User not found: 123
|
||||
// at Function.lookup (repl:3:11)
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
General:
|
||||
|
||||
- [MDN: Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
||||
- [Error Handling in Node.js](https://www.joyent.com/node-js/production/design/errors)
|
||||
- [verror](https://github.com/joyent/node-verror)
|
||||
|
||||
For ES6:
|
||||
|
||||
- [Custom JavaScript Errors in ES6](https://medium.com/@xjamundx/custom-javascript-errors-in-es6-aa891b173f87)
|
||||
- [Custom errors, extending Error](https://javascript.info/custom-errors)
|
||||
|
||||
For ES5:
|
||||
|
||||
- https://gist.github.com/justmoon/15511f92e5216fa2624b
|
||||
- https://gist.github.com/justmoon/15511f92e5216fa2624b (some tests are based largely on this gist)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
'use strict'
|
||||
|
||||
var util = require('util')
|
||||
|
||||
/**
|
||||
* Make custom error types that pass `instanceof` checks, have stack traces,
|
||||
* support custom messages and properties, and support wrapping errors (causes).
|
||||
@@ -9,10 +7,6 @@ var util = require('util')
|
||||
* @module
|
||||
*/
|
||||
|
||||
//
|
||||
// For ES6+ Classes
|
||||
//
|
||||
|
||||
/**
|
||||
* A base class for custom errors that handles:
|
||||
*
|
||||
@@ -96,45 +90,4 @@ OError.getFullInfo = getFullInfo
|
||||
OError.getFullStack = getFullStack
|
||||
OError.hasCauseInstanceOf = hasCauseInstanceOf
|
||||
|
||||
//
|
||||
// For ES5
|
||||
//
|
||||
|
||||
function extendErrorType (base, name, builder) {
|
||||
var errorConstructor = function () {
|
||||
Error.captureStackTrace && Error.captureStackTrace(this, this.constructor)
|
||||
if (builder) builder.apply(this, arguments)
|
||||
this.name = name
|
||||
}
|
||||
|
||||
util.inherits(errorConstructor, base)
|
||||
|
||||
errorConstructor.prototype.withCause = function (cause) {
|
||||
this.cause = cause
|
||||
if (this.message && cause.message) {
|
||||
this.message += ': ' + cause.message
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
return errorConstructor
|
||||
}
|
||||
|
||||
function defineErrorType (name, builder) {
|
||||
return extendErrorType(Error, name, builder)
|
||||
}
|
||||
|
||||
function extendErrorTypeIn (container, base, name, builder) {
|
||||
container[name] = extendErrorType(base, name, builder)
|
||||
}
|
||||
|
||||
function defineErrorTypeIn (container, name, builder) {
|
||||
extendErrorTypeIn(container, Error, name, builder)
|
||||
}
|
||||
|
||||
OError.extend = extendErrorType
|
||||
OError.define = defineErrorType
|
||||
OError.extendIn = extendErrorTypeIn
|
||||
OError.defineIn = defineErrorTypeIn
|
||||
|
||||
module.exports = OError
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "overleaf-error-type",
|
||||
"version": "1.0.0",
|
||||
"name": "@overleaf/o-error",
|
||||
"version": "2.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -523,13 +523,13 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -1,14 +1,13 @@
|
||||
{
|
||||
"name": "overleaf-error-type",
|
||||
"version": "1.0.0",
|
||||
"description": "Make custom error types that pass `instanceof` checks, have stack traces and support custom messages and properties.",
|
||||
"name": "@overleaf/o-error",
|
||||
"version": "2.0.0",
|
||||
"description": "Make custom error types that pass `instanceof` checks, have stack traces, support custom messages and properties, and can wrap causes (like VError).",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha --require test/support"
|
||||
},
|
||||
"author": "Overleaf (https://www.overleaf.com)",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"chai": "^3.3.0",
|
||||
"mocha": "^6.1.4"
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var OError = require('..')
|
||||
const { expectError } = require('./support')
|
||||
|
||||
describe('OError', function () {
|
||||
it('defines a custom error type', function () {
|
||||
var CustomError = OError.define('CustomError')
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new CustomError()
|
||||
}
|
||||
|
||||
try {
|
||||
doSomethingBad()
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expectError(e, {
|
||||
name: 'CustomError',
|
||||
klass: CustomError,
|
||||
message: 'CustomError',
|
||||
firstFrameRx: /doSomethingBad/
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
it('defines a custom error type with a message', function () {
|
||||
var CustomError = OError.define('CustomError', function (x) {
|
||||
this.message = 'x=' + x
|
||||
this.x = x
|
||||
})
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new CustomError('foo')
|
||||
}
|
||||
|
||||
try {
|
||||
doSomethingBad()
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expect(e.toString()).to.equal('CustomError: x=foo')
|
||||
expect(e.message).to.equal('x=foo')
|
||||
expect(e.x).to.equal('foo')
|
||||
}
|
||||
})
|
||||
|
||||
it('defines extended error type', function () {
|
||||
var BaseError = OError.define('BaseError')
|
||||
var DerivedError = OError.extend(BaseError, 'DerivedError')
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new DerivedError()
|
||||
}
|
||||
|
||||
try {
|
||||
doSomethingBad()
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expect(e.toString()).to.equal('DerivedError')
|
||||
}
|
||||
})
|
||||
|
||||
it('defines error types in a container object', function () {
|
||||
var SomeClass = {}
|
||||
OError.defineIn(SomeClass, 'CustomError')
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new SomeClass.CustomError()
|
||||
}
|
||||
|
||||
try {
|
||||
doSomethingBad()
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expect(e.toString()).to.equal('CustomError')
|
||||
}
|
||||
})
|
||||
|
||||
it('extends error types in a container object', function () {
|
||||
var SomeClass = {}
|
||||
OError.defineIn(SomeClass, 'CustomError', function (payload) {
|
||||
this.message = 'custom error'
|
||||
this.payload = payload
|
||||
})
|
||||
OError.extendIn(SomeClass, SomeClass.CustomError, 'DerivedCustomError',
|
||||
function (payload) {
|
||||
SomeClass.CustomError.call(this, payload)
|
||||
this.message = 'derived custom error'
|
||||
})
|
||||
|
||||
function doSomethingBad () {
|
||||
throw new SomeClass.CustomError(123)
|
||||
}
|
||||
|
||||
try {
|
||||
doSomethingBad()
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expect(e.toString()).to.equal('CustomError: custom error')
|
||||
expect(e.payload).to.equal(123)
|
||||
}
|
||||
|
||||
function doSomethingBadWithDerived () {
|
||||
throw new SomeClass.DerivedCustomError(456)
|
||||
}
|
||||
|
||||
try {
|
||||
doSomethingBadWithDerived()
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expect(e.toString()).to.equal('DerivedCustomError: derived custom error')
|
||||
expect(e.payload).to.equal(456)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -99,7 +99,6 @@ describe('OError', () => {
|
||||
it('handles a custom error without info', () => {
|
||||
try {
|
||||
throw new CustomError1({})
|
||||
expect.fail('should have thrown')
|
||||
} catch (e) {
|
||||
expect(OError.getFullInfo(e)).to.deep.equal({})
|
||||
let infoKey = Object.keys(e).find(k => k === 'info')
|
||||
@@ -4,7 +4,7 @@ var chai = require('chai')
|
||||
|
||||
global.expect = chai.expect
|
||||
|
||||
exports.expectError = function errorTypeExpectError (e, expected) {
|
||||
exports.expectError = function OErrorExpectError (e, expected) {
|
||||
// should set the name to the error's name
|
||||
expect(e.name).to.equal(expected.name)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user