diff --git a/libraries/o-error/README.md b/libraries/o-error/README.md index 8c922eadc6..44afcb367d 100644 --- a/libraries/o-error/README.md +++ b/libraries/o-error/README.md @@ -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) diff --git a/libraries/o-error/index.js b/libraries/o-error/index.js index 0f00eb0600..b6cf0362b1 100644 --- a/libraries/o-error/index.js +++ b/libraries/o-error/index.js @@ -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 diff --git a/libraries/o-error/npm-shrinkwrap.json b/libraries/o-error/package-lock.json similarity index 99% rename from libraries/o-error/npm-shrinkwrap.json rename to libraries/o-error/package-lock.json index 3501376406..9324f8f8e8 100644 --- a/libraries/o-error/npm-shrinkwrap.json +++ b/libraries/o-error/package-lock.json @@ -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": { diff --git a/libraries/o-error/package.json b/libraries/o-error/package.json index 152dde4547..a3547eff77 100644 --- a/libraries/o-error/package.json +++ b/libraries/o-error/package.json @@ -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" diff --git a/libraries/o-error/test/error-type.test.js b/libraries/o-error/test/error-type.test.js deleted file mode 100644 index 9526201639..0000000000 --- a/libraries/o-error/test/error-type.test.js +++ /dev/null @@ -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) - } - }) -}) diff --git a/libraries/o-error/test/error-type-util.test.js b/libraries/o-error/test/o-error-util.test.js similarity index 100% rename from libraries/o-error/test/error-type-util.test.js rename to libraries/o-error/test/o-error-util.test.js diff --git a/libraries/o-error/test/error-type-class.test.js b/libraries/o-error/test/o-error.test.js similarity index 98% rename from libraries/o-error/test/error-type-class.test.js rename to libraries/o-error/test/o-error.test.js index fc0543f04d..0fd5020528 100644 --- a/libraries/o-error/test/error-type-class.test.js +++ b/libraries/o-error/test/o-error.test.js @@ -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') diff --git a/libraries/o-error/test/support/index.js b/libraries/o-error/test/support/index.js index 24cbc45270..502348acdf 100644 --- a/libraries/o-error/test/support/index.js +++ b/libraries/o-error/test/support/index.js @@ -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)