Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ehmicky/error-serializer
Convert errors to/from plain objects.
https://github.com/ehmicky/error-serializer
convert error error-handling error-monitoring error-reporting errors exception-handling javascript json library message monitoring nodejs normalization object parsing serialization serializer stacktrace typescript
Last synced: 19 days ago
JSON representation
Convert errors to/from plain objects.
- Host: GitHub
- URL: https://github.com/ehmicky/error-serializer
- Owner: ehmicky
- License: mit
- Created: 2022-08-14T19:29:13.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-09-14T16:52:57.000Z (2 months ago)
- Last Synced: 2024-10-11T10:17:02.423Z (about 1 month ago)
- Topics: convert, error, error-handling, error-monitoring, error-reporting, errors, exception-handling, javascript, json, library, message, monitoring, nodejs, normalization, object, parsing, serialization, serializer, stacktrace, typescript
- Language: JavaScript
- Homepage:
- Size: 4.25 MB
- Stars: 15
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
[![Node](https://img.shields.io/badge/-Node.js-808080?logo=node.js&colorA=404040&logoColor=66cc33)](https://www.npmjs.com/package/error-serializer)
[![Browsers](https://img.shields.io/badge/-Browsers-808080?logo=firefox&colorA=404040)](https://unpkg.com/error-serializer?module)
[![TypeScript](https://img.shields.io/badge/-Typed-808080?logo=typescript&colorA=404040&logoColor=0096ff)](/src/main.d.ts)
[![Codecov](https://img.shields.io/badge/-Tested%20100%25-808080?logo=codecov&colorA=404040)](https://codecov.io/gh/ehmicky/error-serializer)
[![Minified size](https://img.shields.io/bundlephobia/minzip/error-serializer?label&colorA=404040&colorB=808080&logo=webpack)](https://bundlephobia.com/package/error-serializer)
[![Mastodon](https://img.shields.io/badge/-Mastodon-808080.svg?logo=mastodon&colorA=404040&logoColor=9590F9)](https://fosstodon.org/@ehmicky)
[![Medium](https://img.shields.io/badge/-Medium-808080.svg?logo=medium&colorA=404040)](https://medium.com/@ehmicky)Convert errors to/from plain objects.
# Hire me
Please
[reach out](https://www.linkedin.com/feed/update/urn:li:activity:7117265228068716545/)
if you're looking for a Node.js API or CLI engineer (11 years of experience).
Most recently I have been [Netlify Build](https://github.com/netlify/build)'s
and [Netlify Plugins](https://www.netlify.com/products/build/plugins/)'
technical lead for 2.5 years. I am available for full-time remote positions.# Features
- Ensures errors are [safe to serialize with JSON](#json-safety)
- Can be used as [`error.toJSON()`](#errortojson)
- [Deep serialization/parsing](#deep-serializationparsing), including
[transforming](#transforming)
- [Custom serialization/parsing](#custom-serializationparsing) (e.g. YAML or
`process.send()`)
- Keeps both native (`TypeError`, etc.) and [custom](#classes) error classes
- Preserves errors' [additional properties](#additional-error-properties)
- Can keep [constructor's arguments](#constructors)
- Works [recursively](#errorcause-and-aggregateerror) with
[`error.cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)
and
[`AggregateError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError)
- [Normalizes](#loose) invalid errors
- Safe: this never throws# Example
```js
import { serialize, parse } from 'error-serializer'const error = new TypeError('example')
const errorObject = serialize(error)
// Plain object: { name: 'TypeError', message: 'example', stack: '...' }const errorString = JSON.stringify(errorObject)
const newErrorObject = JSON.parse(errorString)const newError = parse(newErrorObject)
// Error instance: 'TypeError: example ...'
```# Install
```bash
npm install error-serializer
```This package works in both Node.js >=18.18.0 and
[browsers](https://raw.githubusercontent.com/ehmicky/dev-tasks/main/src/browserslist).This is an ES module. It must be loaded using
[an `import` or `import()` statement](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c),
not `require()`. If TypeScript is used, it must be configured to
[output ES modules](https://www.typescriptlang.org/docs/handbook/esm-node.html),
not CommonJS.# API
## serialize(errorInstance, options?)
`errorInstance` `any`\
`options` [`Options?`](#options)\
_Return value_: `ErrorObject`Convert an `Error` instance into a plain object.
### Options
Object with the following optional properties.
#### shallow
_Type_: `boolean`\
_Default_: `false`Unless this option is `true`, nested errors are also serialized. They can be
inside other errors, plain objects or arrays.```js
const error = new Error('example')
error.inner = new Error('inner')
serialize(error).inner // { name: 'Error', message: 'inner', ... }
serialize(error, { shallow: true }).inner // Error: inner ...
```#### loose
_Type_: `boolean`\
_Default_: `false`By default, when the argument is not an `Error` instance, it is converted to
one. If this option is `true`, it is kept as is instead.```js
serialize('example') // { name: 'Error', message: 'example', ... }
serialize('example', { loose: true }) // 'example'
```#### include
_Type_: `string[]`
Only pick [specific properties](#omit-additional-error-properties).
```js
serialize(error, { include: ['message'] }) // { message: 'example' }
```#### exclude
_Type_: `string[]`
Omit [specific properties](#omit-stack-traces).
```js
serialize(error, { exclude: ['stack'] }) // { name: 'Error', message: 'example' }
```#### transformObject(errorObject, errorInstance)
_Type_: `(errorObject, errorInstance) => void`
[Transform](#transforming) each error plain object.
`errorObject` is the error after serialization. It must be directly mutated.
`errorInstance` is the error before serialization.
## parse(errorObject, options?)
`errorObject` `any`\
`options` [`Options?`](#options)\
_Return value_: `Error`Convert an error plain object into an `Error` instance.
### Options
Object with the following optional properties.
#### classes
_Type_: `object`
Custom error classes to keep when parsing.
- Each key is an `errorObject.name`
- Each value is the error class to use```js
const errorObject = serialize(new CustomError('example'))
// `CustomError` class is kept
const error = parse(errorObject, { classes: { CustomError } })
// Map `CustomError` to another class
const otherError = parse(errorObject, { classes: { CustomError: TypeError } })
```#### shallow
_Type_: `boolean`\
_Default_: `false`Unless this option is `true`, nested error plain objects are also parsed. They
can be inside other errors, plain objects or arrays.```js
const error = new Error('example')
error.inner = new Error('inner')
const errorObject = serialize(error)parse(errorObject).inner // Error: inner ...
parse(errorObject, { shallow: true }).inner // { name: 'Error', message: ... }
```#### loose
_Type_: `boolean`\
_Default_: `false`By default, when the argument is not an error plain object, it is converted to
one. If this option is `true`, it is kept as is instead.```js
parse('example') // Error: example
parse('example', { loose: true }) // 'example'
```#### transformArgs(constructorArgs, errorObject, ErrorClass)
_Type_: `(constructorArgs, errorObject, ErrorClass) => void`
[Transform](#transforming) the arguments passed to each `new Error()`.
`constructorArgs` is the array of arguments. Usually, `constructorArgs[0]` is
the
[error message](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/message)
and `constructorArgs[1]` is the
[constructor options object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error#parameters).
`constructorArgs` must be directly mutated.`errorObject` is the error before parsing. `ErrorClass` is its
[class](#classes).#### transformInstance(errorInstance, errorObject)
_Type_: `(errorInstance, errorObject) => void`
[Transform](#transforming) each `Error` instance.
`errorInstance` is the error after parsing. It must be directly mutated.
`errorObject` is the error before parsing.
# Usage
## JSON safety
Error plain objects are always
[safe to serialize with JSON](https://github.com/ehmicky/safe-json-value).```js
const error = new Error('example')
error.cycle = error// Cycles make `JSON.stringify()` throw, so they are removed
serialize(error).cycle // undefined
```## `error.toJSON()`
[`serialize()`](#serializeerrorinstance-options) can be used as
[`error.toJSON()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior).```js
class CustomError extends Error {
/* constructor(...) { ... } */toJSON() {
return serialize(this)
}
}
const error = new CustomError('example')error.toJSON()
// { name: 'CustomError', message: 'example', stack: '...' }
JSON.stringify(error)
// '{"name":"CustomError","message":"example","stack":"..."}'
```## Custom serialization/parsing
Errors are converted to/from plain objects, not strings. This allows any
serialization/parsing logic to be performed.```js
import { dump, load } from 'js-yaml'const error = new Error('example')
const errorObject = serialize(error)
const errorYamlString = dump(errorObject)
// name: Error
// message: example
// stack: Error: example ...
const newErrorObject = load(errorYamlString)
const newError = parse(newErrorObject) // Error: example
```## Additional error properties
```js
const error = new TypeError('example')
error.prop = trueconst errorObject = serialize(error)
console.log(errorObject.prop) // true
const newError = parse(errorObject)
console.log(newError.prop) // true
```## Omit additional error properties
```js
const error = new Error('example')
error.prop = trueconst errorObject = serialize(error, { include: ['name', 'message', 'stack'] })
console.log(errorObject.prop) // undefined
console.log(errorObject) // { name: 'Error', message: 'example', stack: '...' }
```## Omit stack traces
```js
const error = new Error('example')const errorObject = serialize(error, { exclude: ['stack'] })
console.log(errorObject.stack) // undefined
console.log(errorObject) // { name: 'Error', message: 'example' }
```## Deep serialization/parsing
The [`loose` option](#loose) can be used to deeply serialize/parse objects and
arrays.```js
const error = new Error('example')
const deepArray = serialize([{}, { error }], { loose: true })const jsonString = JSON.stringify(deepArray)
const newDeepArray = JSON.parse(jsonString)const newError = parse(newDeepArray, { loose: true })[1].error // Error: example
```## Transforming
```js
const errors = [new Error('test secret')]
errors[0].date = new Date()const errorObjects = serialize(errors, {
loose: true,
// Serialize `Date` instances as strings
transformObject: (errorObject) => {
errorObject.date = errorObject.date.toString()
},
})
console.log(errorObjects[0].date) // Date stringconst newErrors = parse(errorObjects, {
loose: true,
// Transform error message
transformArgs: (constructorArgs) => {
constructorArgs[0] = constructorArgs[0].replace('secret', '***')
},
// Parse date strings as `Date` instances
transformInstance: (error) => {
error.date = new Date(error.date)
},
})
console.log(newErrors[0].message) // 'test ***'
console.log(newErrors[0].date) // `Date` instance
```## `error.cause` and `AggregateError`
```js
const innerErrors = [new Error('one'), new Error('two')]
const cause = new Error('three')
const error = new AggregateError(innerErrors, 'four', { cause })const errorObject = serialize(error)
// {
// name: 'AggregateError',
// message: 'four',
// stack: '...',
// cause: { name: 'Error', message: 'three', stack: '...' },
// errors: [{ name: 'Error', message: 'one', stack: '...' }, ...],
// }
const newError = parse(errorObject)
// AggregateError: four
// [cause]: Error: three
// [errors]: [Error: one, Error: two]
```## Constructors
By default, when an error with custom [`classes`](#classes) is parsed, its
constructor is not called. In most cases, this is not a problem since any
property previously set by that constructor is still preserved, providing it is
serializable and enumerable.However, the `error.constructorArgs` property can be set to call the constructor
with those arguments. It it throws, `Error` will be used as a fallback error
class.```js
class CustomError extends Error {
constructor(prefix, message) {
super(`${prefix} - ${message}`)
this.constructorArgs = [prefix, message]
}
}
CustomError.prototype.name = 'CustomError'const error = new CustomError('Prefix', 'example')
const errorObject = serialize(error)
// This calls `new CustomError('Prefix', 'example')`
const newError = parse(errorObject, { classes: { CustomError } })
```# Related projects
- [`modern-errors`](https://github.com/ehmicky/modern-errors): Handle errors in
a simple, stable, consistent way
- [`modern-errors-serialize`](https://github.com/ehmicky/modern-errors-serialize):
Serialize/parse errors
- [`error-custom-class`](https://github.com/ehmicky/error-custom-class): Create
one error class
- [`error-class-utils`](https://github.com/ehmicky/error-class-utils): Utilities
to properly create error classes
- [`normalize-exception`](https://github.com/ehmicky/normalize-exception):
Normalize exceptions/errors
- [`is-error-instance`](https://github.com/ehmicky/is-error-instance): Check if
a value is an `Error` instance
- [`merge-error-cause`](https://github.com/ehmicky/merge-error-cause): Merge an
error with its `cause`
- [`set-error-class`](https://github.com/ehmicky/set-error-class): Properly
update an error's class
- [`set-error-message`](https://github.com/ehmicky/set-error-message): Properly
update an error's message
- [`wrap-error-message`](https://github.com/ehmicky/wrap-error-message):
Properly wrap an error's message
- [`set-error-props`](https://github.com/ehmicky/set-error-props): Properly
update an error's properties
- [`set-error-stack`](https://github.com/ehmicky/set-error-stack): Properly
update an error's stack
- [`error-cause-polyfill`](https://github.com/ehmicky/error-cause-polyfill):
Polyfill `error.cause`
- [`handle-cli-error`](https://github.com/ehmicky/handle-cli-error): 💣 Error
handler for CLI applications 💥
- [`safe-json-value`](https://github.com/ehmicky/safe-json-value): ⛑️ JSON
serialization should never fail
- [`log-process-errors`](https://github.com/ehmicky/log-process-errors): Show
some ❤ to Node.js process errors
- [`error-http-response`](https://github.com/ehmicky/error-http-response):
Create HTTP error responses
- [`winston-error-format`](https://github.com/ehmicky/winston-error-format): Log
errors with Winston# Support
For any question, _don't hesitate_ to [submit an issue on GitHub](../../issues).
Everyone is welcome regardless of personal background. We enforce a
[Code of conduct](CODE_OF_CONDUCT.md) 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](CONTRIBUTING.md). Pull requests are welcome!
ehmicky
💻 🎨 🤔 📖
Pedro Augusto de Paula Barbosa
🐛 📖