Skip to content

Latest commit

 

History

History
291 lines (223 loc) · 10.4 KB

README.md

File metadata and controls

291 lines (223 loc) · 10.4 KB
modern-errors logo

Node Browsers TypeScript Codecov Minified size Twitter Medium

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.

Features

Example

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: '...'

Install

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().

API

modernErrorsSerialize

Type: Plugin

Plugin object to pass to the plugins option of ErrorClass.subclass().

BaseError.toJSON(error)

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.

BaseError.fromJSON(errorObject)

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.

BaseError.serialize(value)

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.

BaseError.parse(value)

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.

Usage

JSON safety

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

Deep serialization/parsing

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 ...

Custom serialization/parsing

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.

Additional error properties

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

Aggregate errors

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]

Constructors

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

Related projects

Support

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.

Contributing

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!