Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't wrap existing errors #37

Merged
merged 8 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions errors.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
'use strict'

const createError = require('errno').create
const LevelUPError = createError('LevelUPError')
const NotFoundError = createError('NotFoundError', LevelUPError)
function createError (type, Proto) {
const Err = function (message, cause) {
if (typeof message === 'object' && message !== null) {
// Can be passed just a cause
cause = cause || message
message = message.message || message.name
}
juliangruber marked this conversation as resolved.
Show resolved Hide resolved

NotFoundError.prototype.notFound = true
NotFoundError.prototype.status = 404
message = message || ''
cause = cause || undefined
juliangruber marked this conversation as resolved.
Show resolved Hide resolved

// If input is already of type, return as-is to keep its stack trace.
// Avoid instanceof, for when node_modules has multiple copies of level-errors.
if (typeof cause === 'object' && cause.type === type && cause.message === message) {
return cause
}

Object.defineProperty(this, 'type', { value: type, enumerable: false, writable: true, configurable: true })
Object.defineProperty(this, 'name', { value: type, enumerable: false, writable: true, configurable: true })
Object.defineProperty(this, 'cause', { value: cause, enumerable: false, writable: true, configurable: true })
Object.defineProperty(this, 'message', { value: message, enumerable: false, writable: true, configurable: true })

Error.call(this)

if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, Err)
}
}

Err.prototype = new Proto()
return Err
}

const LevelUPError = createError('LevelUPError', Error)

module.exports = {
LevelUPError: LevelUPError,
InitializationError: createError('InitializationError', LevelUPError),
OpenError: createError('OpenError', LevelUPError),
ReadError: createError('ReadError', LevelUPError),
WriteError: createError('WriteError', LevelUPError),
NotFoundError: NotFoundError,
NotFoundError: createError('NotFoundError', LevelUPError),
EncodingError: createError('EncodingError', LevelUPError)
}

module.exports.NotFoundError.prototype.notFound = true
module.exports.NotFoundError.prototype.status = 404
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
"LICENSE.md",
"UPGRADING.md"
],
"dependencies": {
"errno": "^1.0.0"
},
"dependencies": {},
"devDependencies": {
"airtap": "^4.0.3",
"airtap-playwright": "^1.0.1",
Expand Down
86 changes: 83 additions & 3 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,100 @@
const test = require('tape')
const errors = require('.')

test('all errors are instances of LevelUPError', function (t) {
test('all errors are instances of Error and LevelUPError', function (t) {
const LevelUPError = errors.LevelUPError
const keys = Object.keys(errors)

keys.forEach(function (key) {
t.ok(new errors[key]() instanceof Error)
t.ok(new errors[key]() instanceof LevelUPError)
})

t.end()
})

test('error with message has expected properties', function (t) {
const error = new errors.ReadError('foo')

t.is(error.type, 'ReadError')
t.is(error.name, 'ReadError')
t.is(error.cause, undefined)
t.is(error.message, 'foo')
t.end()
})

test('error without message has expected properties', function (t) {
const error = new errors.ReadError()

t.is(error.type, 'ReadError')
t.is(error.name, 'ReadError')
t.is(error.cause, undefined)
t.is(error.message, '')
t.end()
})

test('error with cause has expected properties', function (t) {
const cause = new Error('foo')
const error = new errors.ReadError(cause)

t.is(error.type, 'ReadError')
t.is(error.name, 'ReadError')
t.is(error.cause, cause)
t.is(error.message, 'foo')
t.end()
})

test('error with message and cause has expected properties', function (t) {
const cause = new Error('foo')
const error = new errors.ReadError('bar', cause)

t.is(error.type, 'ReadError')
t.is(error.name, 'ReadError')
t.is(error.cause, cause)
t.is(error.message, 'bar')
t.end()
})

test('NotFoundError has special properties', function (t) {
const error = new errors.NotFoundError()
t.equal(error.notFound, true)
t.equal(error.status, 404)
t.is(error.notFound, true)
t.is(error.status, 404)
t.end()
})

test('error message is writable to mirror node core conventions', function (t) {
const error = new errors.WriteError('foo')
error.message = 'Got error: ' + error.message
vweevers marked this conversation as resolved.
Show resolved Hide resolved
t.is(error.message, 'Got error: foo')
t.end()
})

test('returns original instance if cause is the same type', function (t) {
const cause = new errors.NotFoundError('Key not found in database [foo]')
const error = new errors.NotFoundError(cause)
t.is(cause, error, 'same instance')
t.is(error.message, 'Key not found in database [foo]')
t.end()
})

test('returns new instance if cause prototype is different', function (t) {
const cause = new errors.NotFoundError('Key not found in database [foo]')
const error = new errors.WriteError(cause)
t.isNot(cause, error, 'new instance')
t.is(error.message, 'Key not found in database [foo]')
t.end()
})

test('returns original instance if message and cause are the same', function (t) {
const cause = new errors.NotFoundError('Key not found in database [foo]')
const error = new errors.NotFoundError('Key not found in database [foo]', cause)
t.is(cause, error, 'same instance')
t.end()
})

test('returns new instance if message is different', function (t) {
const cause = new errors.NotFoundError('Key not found in database [foo]')
const error = new errors.NotFoundError('Key not found in database [bar]', cause)
t.isNot(cause, error, 'new instance')
t.end()
})