diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 76e78b8..ef86c1a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 diff --git a/index.d.ts b/index.d.ts index dc47c85..5fa6689 100644 --- a/index.d.ts +++ b/index.d.ts @@ -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'; @@ -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. @@ -47,7 +47,7 @@ export interface Options { @default true */ readonly useToJSON?: boolean; -} +}; /** Serialize an `Error` object into a plain object. diff --git a/index.js b/index.js index 22f4499..525ec3b 100644 --- a/index.js +++ b/index.js @@ -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, diff --git a/index.test-d.ts b/index.test-d.ts index ea7412e..f3a8767 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -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'); diff --git a/package.json b/package.json index d5886c5..ae76c4f 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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" } } diff --git a/test.js b/test.js index 45ced34..330718f 100644 --- a/test.js +++ b/test.js @@ -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); @@ -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 => { @@ -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'); @@ -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 => {