UNPKG

modern-errors-serialize

Version:
293 lines (282 loc) 9.51 kB
import type { ErrorObject, ParseOptions, SerializeOptions, } from 'error-serializer' import type { ErrorInstance, Info } from 'modern-errors' export type { ErrorObject } /** * Options of `modern-errors-serialize` */ export interface Options { /** * By default, when the argument is not an `Error` instance or an error plain * object, it is converted to one. If this option is `true`, it is kept as is * instead. * * @default false * * @example * ```js * BaseError.serialize('example') // { name: 'BaseError', message: 'example', ... } * BaseError.serialize('example', { loose: true }) // 'example' * * BaseError.parse('example') // BaseError * BaseError.parse('example', { loose: true }) // 'example' * ``` */ readonly loose?: boolean /** * Unless this option is `true`, nested errors are also serialized/parsed. * They can be inside other errors, plain objects or arrays. * * @default false * * @example * ```js * const inner = new ExampleError('inner') * const error = new ExampleError('example', { props: { inner } }) * * BaseError.serialize(error).inner // { name: 'BaseError', message: 'inner', ... } * BaseError.serialize(error, { shallow: true }).inner // BaseError * * const errorObject = BaseError.serialize(error) * BaseError.parse(errorObject).inner // BaseError * BaseError.parse(errorObject, { shallow: true }).inner // { name: '...', ... } * ``` */ readonly shallow?: boolean /** * During serialization, only pick specific properties. * * @example * ```js * BaseError.serialize(error, { include: ['message'] }) // { message: 'example' } * ``` * * @example * ```js * const ExampleError = BaseError.subclass('ExampleError', { * serialize: { include: ['name', 'message', 'stack'] }, * }) * const error = new ExampleError('example') * error.prop = true * * const errorObject = ExampleError.serialize(error) * console.log(errorObject.prop) // undefined * console.log(errorObject) // { name: 'Error', message: 'example', stack: '...' } * ``` */ readonly include?: SerializeOptions['include'] /** * During serialization, omit specific properties. * * @example * ```js * BaseError.serialize(error, { exclude: ['stack'] }) // { name: 'Error', message: 'example' } * ``` * * @example * ```js * const ExampleError = BaseError.subclass('ExampleError', { * serialize: { exclude: ['stack'] }, * }) * const error = new ExampleError('example') * * const errorObject = ExampleError.serialize(error) * console.log(errorObject.stack) // undefined * console.log(errorObject) // { name: 'Error', message: 'example' } * ``` */ readonly exclude?: SerializeOptions['exclude'] /** * During serialization, transform each error plain object. * * `errorObject` is the error after serialization. It must be directly mutated. * * `errorInstance` is the error before serialization. * * @example * ```js * const errors = [new ExampleError('message secret')] * errors[0].date = new Date() * * const errorObjects = BaseError.serialize(errors, { * loose: true, * // Serialize `Date` instances as strings * transformObject: (errorObject) => { * errorObject.date = errorObject.date.toString() * }, * }) * console.log(errorObjects[0].date) // Date string * * const newErrors = BaseError.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) // 'message ***' * console.log(newErrors[0].date) // `Date` instance * ``` */ readonly transformObject?: SerializeOptions['transformObject'] /** * During parsing, transform 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. * * @example * ```js * const errors = [new ExampleError('message secret')] * errors[0].date = new Date() * * const errorObjects = BaseError.serialize(errors, { * loose: true, * // Serialize `Date` instances as strings * transformObject: (errorObject) => { * errorObject.date = errorObject.date.toString() * }, * }) * console.log(errorObjects[0].date) // Date string * * const newErrors = BaseError.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) // 'message ***' * console.log(newErrors[0].date) // `Date` instance * ``` */ readonly transformArgs?: ParseOptions['transformArgs'] /** * During parsing, transform each `Error` instance. * * `errorInstance` is the error after parsing. It must be directly mutated. * * `errorObject` is the error before parsing. * * @example * ```js * const errors = [new ExampleError('message secret')] * errors[0].date = new Date() * * const errorObjects = BaseError.serialize(errors, { * loose: true, * // Serialize `Date` instances as strings * transformObject: (errorObject) => { * errorObject.date = errorObject.date.toString() * }, * }) * console.log(errorObjects[0].date) // Date string * * const newErrors = BaseError.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) // 'message ***' * console.log(newErrors[0].date) // `Date` instance * ``` */ readonly transformInstance?: ParseOptions['transformInstance'] } /** * `modern-errors-serialize` plugin. * * This plugin adds `BaseError.serialize()` and `BaseError.parse()` to * serialize/parse errors to/from plain objects. */ declare const plugin: { name: 'serialize' getOptions: (options: Options) => Options isOptions: (options: unknown) => boolean staticMethods: { /** * Converts `error` to an error plain object. All error properties are kept. * [Plugin options](https://github.com/ehmicky/modern-errors#plugin-options) * are also preserved. * * @example * ```js * const error = new ExampleError('message', { props: { filePath } }) * * const errorObject = BaseError.serialize(error) * // { name: 'ExampleError', message: 'message', stack: '...', filePath: '...' } * const errorString = JSON.stringify(errorObject) * // '{"name":"ExampleError",...}' * ``` */ serialize: (info: Info['staticMethods'], error: unknown) => ErrorObject /** * Converts `errorObject` to an error instance. The original error classes * are preserved providing they are * [subclasses](https://github.com/ehmicky/modern-errors#create-error-classes) * of `BaseError`. * * @example * ```js * const error = new ExampleError('message', { props: { filePath } }) * * const errorObject = BaseError.serialize(error) * // { name: 'ExampleError', message: 'message', stack: '...', filePath: '...' } * const errorString = JSON.stringify(errorObject) * // '{"name":"ExampleError",...}' * * const newErrorObject = JSON.parse(errorString) * const newError = BaseError.parse(newErrorObject) * // ExampleError: message * // at ... * // filePath: '...' * ``` */ parse: (info: Info['staticMethods'], errorObject: unknown) => ErrorInstance } instanceMethods: { /** * [`error.toJSON()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior) * is defined. It is automatically called by * [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). * * @example * ```js * const error = new ExampleError('message') * const deepArray = [{}, { error }] * * const jsonString = JSON.stringify(deepArray) * const newDeepArray = JSON.parse(jsonString) * * const newError = BaseError.parse(newDeepArray, { loose: true })[1].error * // ExampleError: message * // at ... * ``` */ toJSON: (info: Info['instanceMethods']) => ErrorObject } } export default plugin