Skip to content

Commit

Permalink
Require Node.js 18+ (#100)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <[email protected]>
  • Loading branch information
fregante and sindresorhus authored Jan 3, 2025
1 parent a031f98 commit 98bbe4e
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 30 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 14
- 22
- 18
- 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down
6 changes: 3 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Primitive, JsonObject} from 'type-fest';
import {type Primitive, type JsonObject} from 'type-fest';

export {default as errorConstructors} from './error-constructors.js';

Expand All @@ -19,7 +19,7 @@ export type ErrorLike = {
code?: string;
};

export interface Options {
export type Options = {
/**
The maximum depth of properties to preserve when serializing/deserializing.
Expand Down Expand Up @@ -47,7 +47,7 @@ export interface Options {
@default true
*/
readonly useToJSON?: boolean;
}
};

/**
Serialize an `Error` object into a plain object.
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const destroyCircular = ({
}

for (const {property, enumerable} of commonProperties) {
if (typeof from[property] !== 'undefined' && from[property] !== null) {
if (from[property] !== undefined && from[property] !== null) {
Object.defineProperty(to, property, {
value: isErrorLike(from[property]) ? continueDestroyCircular(from[property]) : from[property],
enumerable: forceEnumerable ? true : enumerable,
Expand Down
7 changes: 6 additions & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import {expectType, expectAssignable} from 'tsd';
import {serializeError, deserializeError, ErrorObject, Options} from './index.js';
import {
serializeError,
deserializeError,
type ErrorObject,
type Options,
} from './index.js';

const error = new Error('unicorn');

Expand Down
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
"exports": "./index.js",
"sideEffects": false,
"engines": {
"node": ">=14.16"
"node": ">=18"
},
"scripts": {
"//test": "xo && ava && tsd",
"test": "ava && tsd"
"test": "xo && ava && tsd"
},
"files": [
"index.js",
Expand All @@ -38,11 +37,11 @@
"deserialize"
],
"dependencies": {
"type-fest": "^2.12.2"
"type-fest": "^4.31.0"
},
"devDependencies": {
"ava": "^4.2.0",
"tsd": "^0.20.0",
"xo": "^0.48.0"
"ava": "^6.2.0",
"tsd": "^0.31.2",
"xo": "^0.60.0"
}
}
31 changes: 15 additions & 16 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ function deserializeNonError(t, value) {
t.is(deserialized.message, JSON.stringify(value));
}

// TODO: Replace with plain `new Error('outer', {cause: new Error('inner')})` when targeting Node 16.9+
function setErrorCause(error, cause) {
Object.defineProperty(error, 'cause', {
value: cause,
enumerable: false,
writable: true,
});
}

test('main', t => {
const serialized = serializeError(new Error('foo'));
const properties = Object.keys(serialized);
Expand Down Expand Up @@ -119,7 +110,7 @@ test('should drop functions', t => {

const serialized = serializeError(object);
t.deepEqual(serialized, {});
t.false(Object.prototype.hasOwnProperty.call(serialized, 'a'));
t.false(Object.hasOwn(serialized, 'a'));
});

test('should not access deep non-enumerable properties', t => {
Expand Down Expand Up @@ -149,9 +140,11 @@ test('should serialize nested errors', t => {
});

test('should serialize the cause property', t => {
const error = new Error('outer error');
setErrorCause(error, new Error('inner error'));
setErrorCause(error.cause, new Error('deeper error'));
const error = new Error('outer error', {
cause: new Error('inner error', {
cause: new Error('deeper error'),
}),
});

const serialized = serializeError(error);
t.is(serialized.message, 'outer error');
Expand Down Expand Up @@ -467,13 +460,19 @@ test('should serialize properties up to `Options.maxDepth` levels deep', t => {
t.deepEqual(levelZero, {});

const levelOne = serializeError(error, {maxDepth: 1});
t.deepEqual(levelOne, {message, name, stack, one: {}});
t.deepEqual(levelOne, {
message, name, stack, one: {},
});

const levelTwo = serializeError(error, {maxDepth: 2});
t.deepEqual(levelTwo, {message, name, stack, one: {two: {}}});
t.deepEqual(levelTwo, {
message, name, stack, one: {two: {}},
});

const levelThree = serializeError(error, {maxDepth: 3});
t.deepEqual(levelThree, {message, name, stack, one: {two: {three: {}}}});
t.deepEqual(levelThree, {
message, name, stack, one: {two: {three: {}}},
});
});

test('should identify serialized errors', t => {
Expand Down

0 comments on commit 98bbe4e

Please sign in to comment.