Skip to content

Commit

Permalink
Require Node.js 12.20 and move to ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Nov 17, 2021
1 parent d853349 commit f698ea0
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 83 deletions.
3 changes: 0 additions & 3 deletions .github/funding.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Expand Up @@ -10,12 +10,12 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 14
- 12
- 10
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
24 changes: 12 additions & 12 deletions index.d.ts
Expand Up @@ -33,12 +33,12 @@ export interface Options {
/**
Serialize an `Error` object into a plain object.
Non-error values are passed through.
Custom properties are preserved.
Buffer properties are replaced with `[object Buffer]`.
Circular references are handled.
If the input object has a `.toJSON()` method, then it's called instead of serializing the object's properties.
It's up to `.toJSON()` implementation to handle circular references and enumerability of the properties.
- Non-error values are passed through.
- Custom properties are preserved.
- Buffer properties are replaced with `[object Buffer]`.
- Circular references are handled.
- If the input object has a `.toJSON()` method, then it's called instead of serializing the object's properties.
- It's up to `.toJSON()` implementation to handle circular references and enumerability of the properties.
@example
```
Expand Down Expand Up @@ -98,12 +98,12 @@ export function serializeError<ErrorType>(error: ErrorType, options?: Options):
/**
Deserialize a plain object or any value into an `Error` object.
`Error` objects are passed through.
Non-error values are wrapped in a `NonError` error.
Custom properties are preserved.
Non-enumerable properties are kept non-enumerable (name, message, stack).
Enumerable properties are kept enumerable (all properties besides the non-enumerable ones).
Circular references are handled.
- `Error` objects are passed through.
- Non-error values are wrapped in a `NonError` error.
- Custom properties are preserved.
- Non-enumerable properties are kept non-enumerable (name, message, stack).
- Enumerable properties are kept enumerable (all properties besides the non-enumerable ones).
- Circular references are handled.
@example
```
Expand Down
61 changes: 34 additions & 27 deletions index.js
@@ -1,12 +1,11 @@
'use strict';

class NonError extends Error {
export class NonError extends Error {
constructor(message) {
super(NonError._prepareSuperMessage(message));

Object.defineProperty(this, 'name', {
value: 'NonError',
configurable: true,
writable: true
writable: true,
});

if (Error.captureStackTrace) {
Expand All @@ -24,18 +23,30 @@ class NonError extends Error {
}

const commonProperties = [
{property: 'name', enumerable: false},
{property: 'message', enumerable: false},
{property: 'stack', enumerable: false},
{property: 'code', enumerable: true}
{
property: 'name',
enumerable: false,
},
{
property: 'message',
enumerable: false,
},
{
property: 'stack',
enumerable: false,
},
{
property: 'code',
enumerable: true,
},
];

const isCalled = Symbol('.toJSON called');
const toJsonWasCalled = Symbol('.toJSON was called');

const toJSON = from => {
from[isCalled] = true;
from[toJsonWasCalled] = true;
const json = from.toJSON();
delete from[isCalled];
delete from[toJsonWasCalled];
return json;
};

Expand All @@ -45,7 +56,7 @@ const destroyCircular = ({
to_,
forceEnumerable,
maxDepth,
depth
depth,
}) => {
const to = to_ || (Array.isArray(from) ? [] : {});

Expand All @@ -55,11 +66,12 @@ const destroyCircular = ({
return to;
}

if (typeof from.toJSON === 'function' && from[isCalled] !== true) {
if (typeof from.toJSON === 'function' && from[toJsonWasCalled] !== true) {
return toJSON(from);
}

for (const [key, value] of Object.entries(from)) {
// eslint-disable-next-line node/prefer-global/buffer
if (typeof Buffer === 'function' && Buffer.isBuffer(value)) {
to[key] = '[object Buffer]';
continue;
Expand All @@ -79,10 +91,10 @@ const destroyCircular = ({

to[key] = destroyCircular({
from: from[key],
seen: seen.slice(),
seen: [...seen],
forceEnumerable,
maxDepth,
depth
depth,
});
continue;
}
Expand All @@ -96,15 +108,15 @@ const destroyCircular = ({
value: from[property],
enumerable: forceEnumerable ? true : enumerable,
configurable: true,
writable: true
writable: true,
});
}
}

return to;
};

const serializeError = (value, options = {}) => {
export function serializeError(value, options = {}) {
const {maxDepth = Number.POSITIVE_INFINITY} = options;

if (typeof value === 'object' && value !== null) {
Expand All @@ -113,7 +125,7 @@ const serializeError = (value, options = {}) => {
seen: [],
forceEnumerable: true,
maxDepth,
depth: 0
depth: 0,
});
}

Expand All @@ -124,9 +136,9 @@ const serializeError = (value, options = {}) => {
}

return value;
};
}

const deserializeError = (value, options = {}) => {
export function deserializeError(value, options = {}) {
const {maxDepth = Number.POSITIVE_INFINITY} = options;

if (value instanceof Error) {
Expand All @@ -140,15 +152,10 @@ const deserializeError = (value, options = {}) => {
seen: [],
to_: newError,
maxDepth,
depth: 0
depth: 0,
});
return newError;
}

return new NonError(value);
};

module.exports = {
serializeError,
deserializeError
};
}
2 changes: 1 addition & 1 deletion index.test-d.ts
Expand Up @@ -11,5 +11,5 @@ expectType<Error>(deserializeError({
message: 'error message',
stack: 'at <anonymous>:1:13',
name: 'name',
code: 'code'
code: 'code',
}));
12 changes: 7 additions & 5 deletions package.json
Expand Up @@ -10,8 +10,10 @@
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=10"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -31,11 +33,11 @@
"deserialize"
],
"dependencies": {
"type-fest": "^0.20.2"
"type-fest": "^2.5.3"
},
"devDependencies": {
"ava": "^2.4.0",
"tsd": "^0.14.0",
"xo": "^0.37.1"
"ava": "^3.15.0",
"tsd": "^0.18.0",
"xo": "^0.46.4"
}
}
38 changes: 20 additions & 18 deletions readme.md
Expand Up @@ -6,14 +6,14 @@ Useful if you for example need to `JSON.stringify()` or `process.send()` the err

## Install

```
$ npm install serialize-error
```sh
npm install serialize-error
```

## Usage

```js
const {serializeError, deserializeError} = require('serialize-error');
import {serializeError, deserializeError} from 'serialize-error';

const error = new Error('🦄');

Expand All @@ -39,19 +39,19 @@ Type: `Error | unknown`

Serialize an `Error` object into a plain object.

Non-error values are passed through.
Custom properties are preserved.
Non-enumerable properties are kept non-enumerable (name, message, stack).
Enumerable properties are kept enumerable (all properties besides the non-enumerable ones).
Buffer properties are replaced with `[object Buffer]`.
Circular references are handled.
If the input object has a `.toJSON()` method, then it's called instead of serializing the object's properties.
It's up to `.toJSON()` implementation to handle circular references and enumerability of the properties.
- Non-error values are passed through.
- Custom properties are preserved.
- Non-enumerable properties are kept non-enumerable (name, message, stack).
- Enumerable properties are kept enumerable (all properties besides the non-enumerable ones).
- Buffer properties are replaced with `[object Buffer]`.
- Circular references are handled.
- If the input object has a `.toJSON()` method, then it's called instead of serializing the object's properties.
- It's up to `.toJSON()` implementation to handle circular references and enumerability of the properties.

`.toJSON` examples:

```js
const {serializeError} = require('serialize-error');
import {serializeError} from 'serialize-error';

class ErrorWithDate extends Error {
constructor() {
Expand All @@ -67,7 +67,7 @@ serializeError(error);
```

```js
const {serializeError} = require('serialize-error');
import {serializeError} from 'serialize-error';

class ErrorWithToJSON extends Error {
constructor() {
Expand All @@ -92,10 +92,12 @@ Type: `{[key: string]: unknown} | unknown`

Deserialize a plain object or any value into an `Error` object.

`Error` objects are passed through.
Non-error values are wrapped in a `NonError` error.
Custom properties are preserved.
Circular references are handled.
- `Error` objects are passed through.
- Non-error values are wrapped in a `NonError` error.
- Custom properties are preserved.
- Non-enumerable properties are kept non-enumerable (name, message, stack).
- Enumerable properties are kept enumerable (all properties besides the non-enumerable ones).
- Circular references are handled.

### options

Expand All @@ -109,7 +111,7 @@ Default: `Number.POSITIVE_INFINITY`
The maximum depth of properties to preserve when serializing/deserializing.

```js
const {serializeError} = require('serialize-error');
import {serializeError} from 'serialize-error';

const error = new Error('🦄');
error.one = {two: {three: {}}};
Expand Down

0 comments on commit f698ea0

Please sign in to comment.