modern-errors
plugin to serialize/parse
errors.
This adds BaseError.toJSON()
,
BaseError.fromJSON()
,
BaseError.serialize()
and
BaseError.parse()
to serialize/parse errors to/from
plain objects.
- Ensures errors are safe to serialize with JSON
- Deep serialization/parsing
- Custom serialization/parsing (e.g. YAML or
process.send()
) - Keeps error classes
- Preserves errors' additional properties
- Works recursively with
AggregateError
- Safe: this never throws
Adding the plugin to
modern-errors
.
import ModernError from 'modern-errors'
import modernErrorsSerialize from 'modern-errors-serialize'
export const BaseError = ModernError.subclass('BaseError', {
plugins: [modernErrorsSerialize],
})
// ...
Serializing errors to plain objects.
const error = new InputError('Wrong file.', { props: { filePath } })
const errorObject = BaseError.toJSON(error)
// { name: 'InputError', message: 'Wrong file', stack: '...', filePath: '...' }
const errorString = JSON.stringify(errorObject)
// '{"name":"InputError",...}'
Parsing errors from plain objects.
const newErrorObject = JSON.parse(errorString)
const newError = BaseError.fromJSON(newErrorObject)
// InputError: Wrong file.
// at ...
// filePath: '...'
npm install modern-errors-serialize
This package works in both Node.js >=14.18.0 and
browsers.
It is an ES module and must be loaded using
an import
or import()
statement,
not require()
.
Type: Plugin
Plugin object to pass to the
plugins
option of
ErrorClass.subclass()
.
error
: ErrorInstance
Return value: ErrorObject
Converts error
to an error plain object that is
serializable to JSON
(or YAML,
etc.). All
error properties
are kept.
Plugin options are
also preserved.
Nested error instances are serialized deeply. If
error
is not an error instance, it is first
normalized to one.
This is also set as
error.toJSON()
.
Therefore
JSON.stringify()
automatically calls it.
errorObject
: ErrorObject
Return value: ErrorInstance
Converts errorObject
to an error instance. The original error classes are
preserved.
Nested error plain objects are parsed deeply. If
errorObject
is not an error plain object, it is first normalized to one.
This is like BaseError.toJSON(value)
except, if
value
is not an error instance, it is kept as is. However, any nested error
instances is still serialized.
This is like BaseError.fromJSON(value)
except, if value
is not an error plain object, it is kept as is. However, any
nested error plain object is still parsed.
Error plain objects are always safe to serialize with JSON.
const error = new InputError('Wrong file.')
error.cycle = error
// Cycles make `JSON.stringify()` throw, so they are removed
console.log(BaseError.toJSON(error).cycle) // undefined
Objects and arrays are deeply serialized and parsed.
const error = new InputError('Wrong file.')
const deepArray = [{}, { error }]
const jsonString = JSON.stringify(deepArray)
const newDeepArray = JSON.parse(jsonString)
const newError = BaseError.parse(newDeepArray)[1].error
// InputError: Wrong file.
// at ...
Errors are converted to/from plain objects, not strings. This allows any serialization/parsing logic to be performed.
import { dump, load } from 'js-yaml'
const error = new InputError('Wrong file.')
const errorObject = BaseError.toJSON(error)
const errorYamlString = dump(errorObject)
// name: InputError
// message: Wrong file.
// stack: InputError: Wrong file. ...
const newErrorObject = load(errorYamlString)
const newError = BaseError.fromJSON(newErrorObject) // InputError: Wrong file.
const error = new InputError('Wrong file.', { props: { prop: true } })
const errorObject = BaseError.toJSON(error)
console.log(errorObject.prop) // true
const newError = BaseError.fromJSON(errorObject)
console.log(newError.prop) // true
const error = new InputError('Wrong file.', {
errors: [new ExampleError('one'), new ExampleError('two')],
})
const errorObject = BaseError.toJSON(error)
// {
// name: 'InputError',
// message: 'Wrong file.',
// stack: '...',
// errors: [{ name: 'ExampleError', message: 'one', stack: '...' }, ...],
// }
const newError = BaseError.fromJSON(errorObject)
// InputError: Wrong file.
// [errors]: [ExampleError: one, ExampleError: two]
If an error with a
custom
class is
parsed, its custom constructor is not called. However, any property previously
set by that constructor is still preserved, providing it is serializable and
enumerable.
const InputError = BaseError.subclass('InputError', {
custom: class extends BaseError {
constructor(message, options, prop) {
super(message, options, prop)
this.prop = prop
}
},
})
const error = new InputError('Wrong file.', {}, true)
const errorObject = BaseError.toJSON(error)
// `constructor(message, options, prop)` is not called
const newError = BaseError.fromJSON(errorObject)
// But properties set by that `constructor(...)` are kept
console.log(newError.prop) // true
error-serializer
: Convert errors to/from plain objectsmodern-errors
: Handle errors like it's 2022 🔮modern-errors-cli
: Handle errors in CLI modulesmodern-errors-process
: Handle process errorsmodern-errors-bugs
: Print where to report bugsmodern-errors-clean
: Clean stack tracesmodern-errors-http
: Create HTTP error responsesmodern-errors-winston
: Log errors with Winston
For any question, don't hesitate to submit an issue on GitHub.
Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.
This project was made with ❤️. The simplest way to give back is by starring and sharing it online.
If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!