From cbdf0e42577f3e9c4ac35c7c8246efd9bcb44e2a Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Sun, 3 Apr 2022 00:18:39 +0800 Subject: [PATCH 1/4] Add `useToJSON` option --- index.js | 11 +++++++++-- test.js | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 947b209..57a75a8 100644 --- a/index.js +++ b/index.js @@ -46,6 +46,7 @@ const toJSON = from => { return json; }; +// eslint-disable-next-line complexity const destroyCircular = ({ from, seen, @@ -53,6 +54,7 @@ const destroyCircular = ({ forceEnumerable, maxDepth, depth, + useToJSON, }) => { const to = to_ || (Array.isArray(from) ? [] : {}); @@ -62,7 +64,7 @@ const destroyCircular = ({ return to; } - if (typeof from.toJSON === 'function' && from[toJsonWasCalled] !== true) { + if (useToJSON && typeof from.toJSON === 'function' && from[toJsonWasCalled] !== true) { return toJSON(from); } @@ -97,6 +99,7 @@ const destroyCircular = ({ forceEnumerable, maxDepth, depth, + useToJSON, }); continue; } @@ -119,7 +122,10 @@ const destroyCircular = ({ }; export function serializeError(value, options = {}) { - const {maxDepth = Number.POSITIVE_INFINITY} = options; + const { + maxDepth = Number.POSITIVE_INFINITY, + toJSON: useToJSON = true, + } = options; if (typeof value === 'object' && value !== null) { return destroyCircular({ @@ -128,6 +134,7 @@ export function serializeError(value, options = {}) { forceEnumerable: true, maxDepth, depth: 0, + useToJSON, }); } diff --git a/test.js b/test.js index 717efac..365ce21 100644 --- a/test.js +++ b/test.js @@ -366,6 +366,31 @@ test('should serialize custom error with `.toJSON` defined with `serializeError` t.not(stack, undefined); }); +test('should ignore `.toJSON` methods if set in the options', t => { + class CustomError extends Error { + constructor() { + super('foo'); + this.name = this.constructor.name; + this.value = 10; + } + + toJSON() { + return { + message: this.message, + amount: `$${this.value}`, + }; + } + } + const error = new CustomError(); + const serialized = serializeError(error, {toJSON: false}); + t.like(serialized, { + name: 'CustomError', + message: 'foo', + value: 10, + }); + t.truthy(serialized.stack); +}); + test('should serialize properties up to `Options.maxDepth` levels deep', t => { const error = new Error('errorMessage'); error.one = {two: {three: {}}}; From 0ebfcb31035bac8af6f4aad6a7e61ed5cd022ca2 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Sun, 3 Apr 2022 00:25:03 +0800 Subject: [PATCH 2/4] docs.rtf.exe --- index.d.ts | 30 ++++++++++++++++++++++++++++++ readme.md | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index 4111da3..782ed99 100644 --- a/index.d.ts +++ b/index.d.ts @@ -28,6 +28,36 @@ export interface Options { ``` */ readonly maxDepth?: number; + + /** + Indicate whether to use a `toJSON` method if encountered in the object. + + @default true + + @example + ```js + import {serializeError} from 'serialize-error'; + + class UnserializableError extends Error { + name = 'UnserializableError'; + + toJSON() { + // Break serialization + return {}; + } + } + + const error = new UnserializableError('🦄'); + + console.log(serializeError(error)); + //=> {} + + console.log(serializeError(error, {useToJSON: false})); + //=> {name: 'UnserializableError', message: '🦄', stack: 'etc'} + ``` + + */ + readonly useToJSON?: boolean; } /** diff --git a/readme.md b/readme.md index 60634fc..0ff491d 100644 --- a/readme.md +++ b/readme.md @@ -117,8 +117,36 @@ const error = new Error('🦄'); error.one = {two: {three: {}}}; console.log(serializeError(error, {maxDepth: 1})); -//=> {name: 'Error', message: '…', one: {}} +//=> {name: 'Error', message: '🦄', one: {}} console.log(serializeError(error, {maxDepth: 2})); -//=> {name: 'Error', message: '…', one: { two: {}}} +//=> {name: 'Error', message: '🦄', one: { two: {}}} +``` + +#### useToJSON + +Type: `boolean`\ +Default: `true` + +Indicate whether to use a `toJSON` method if encountered in the object. + +```js +import {serializeError} from 'serialize-error'; + +class UnserializableError extends Error { + name = 'UnserializableError'; + + toJSON() { + // Break serialization + return {}; + } +} + +const error = new UnserializableError('🦄'); + +console.log(serializeError(error)); +//=> {} + +console.log(serializeError(error, {useToJSON: false})); +//=> {name: 'UnserializableError', message: '🦄', stack: 'etc'} ``` From d377d3662c8af23d2b05084fe6c71572afa76446 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Mon, 4 Apr 2022 12:19:49 +0800 Subject: [PATCH 3/4] `useToJSON` + replace example with extended description --- index.d.ts | 24 +----------------------- index.js | 2 +- readme.md | 23 +---------------------- test.js | 2 +- 4 files changed, 4 insertions(+), 47 deletions(-) diff --git a/index.d.ts b/index.d.ts index 782ed99..26c0974 100644 --- a/index.d.ts +++ b/index.d.ts @@ -30,32 +30,10 @@ export interface Options { readonly maxDepth?: number; /** - Indicate whether to use a `toJSON` method if encountered in the object. + Indicate whether to use a `.toJSON()` method if encountered in the object. This is useful when a custom error implements its own serialization logic via `.toJSON()` but you prefer not using it. @default true - @example - ```js - import {serializeError} from 'serialize-error'; - - class UnserializableError extends Error { - name = 'UnserializableError'; - - toJSON() { - // Break serialization - return {}; - } - } - - const error = new UnserializableError('🦄'); - - console.log(serializeError(error)); - //=> {} - - console.log(serializeError(error, {useToJSON: false})); - //=> {name: 'UnserializableError', message: '🦄', stack: 'etc'} - ``` - */ readonly useToJSON?: boolean; } diff --git a/index.js b/index.js index 57a75a8..8c6eb1a 100644 --- a/index.js +++ b/index.js @@ -124,7 +124,7 @@ const destroyCircular = ({ export function serializeError(value, options = {}) { const { maxDepth = Number.POSITIVE_INFINITY, - toJSON: useToJSON = true, + useToJSON = true, } = options; if (typeof value === 'object' && value !== null) { diff --git a/readme.md b/readme.md index 0ff491d..473011d 100644 --- a/readme.md +++ b/readme.md @@ -128,25 +128,4 @@ console.log(serializeError(error, {maxDepth: 2})); Type: `boolean`\ Default: `true` -Indicate whether to use a `toJSON` method if encountered in the object. - -```js -import {serializeError} from 'serialize-error'; - -class UnserializableError extends Error { - name = 'UnserializableError'; - - toJSON() { - // Break serialization - return {}; - } -} - -const error = new UnserializableError('🦄'); - -console.log(serializeError(error)); -//=> {} - -console.log(serializeError(error, {useToJSON: false})); -//=> {name: 'UnserializableError', message: '🦄', stack: 'etc'} -``` +Indicate whether to use a `.toJSON()` method if encountered in the object. This is useful when a custom error implements [its own serialization logic via `.toJSON()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior) but you prefer not using it. diff --git a/test.js b/test.js index 365ce21..de9ee15 100644 --- a/test.js +++ b/test.js @@ -382,7 +382,7 @@ test('should ignore `.toJSON` methods if set in the options', t => { } } const error = new CustomError(); - const serialized = serializeError(error, {toJSON: false}); + const serialized = serializeError(error, {useToJSON: false}); t.like(serialized, { name: 'CustomError', message: 'foo', From d6ecd913b328754e4aa2e28eb8ddc5857c562eef Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Mon, 4 Apr 2022 23:45:53 +0800 Subject: [PATCH 4/4] All the single reviews, all the single reviews, put your hands --- index.d.ts | 3 +-- readme.md | 2 +- test.js | 2 ++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index 5e82a7a..55ec263 100644 --- a/index.d.ts +++ b/index.d.ts @@ -40,10 +40,9 @@ export interface Options { readonly maxDepth?: number; /** - Indicate whether to use a `.toJSON()` method if encountered in the object. This is useful when a custom error implements its own serialization logic via `.toJSON()` but you prefer not using it. + Indicate whether to use a `.toJSON()` method if encountered in the object. This is useful when a custom error implements its own serialization logic via `.toJSON()` but you prefer to not use it. @default true - */ readonly useToJSON?: boolean; } diff --git a/readme.md b/readme.md index 1d806e2..0fa3944 100644 --- a/readme.md +++ b/readme.md @@ -123,7 +123,7 @@ console.log(serializeError(error, {maxDepth: 2})); Type: `boolean`\ Default: `true` -Indicate whether to use a `.toJSON()` method if encountered in the object. This is useful when a custom error implements [its own serialization logic via `.toJSON()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior) but you prefer not using it. +Indicate whether to use a `.toJSON()` method if encountered in the object. This is useful when a custom error implements [its own serialization logic via `.toJSON()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior) but you prefer to not use it. ### isErrorLike(value) diff --git a/test.js b/test.js index 29ec349..51ccad6 100644 --- a/test.js +++ b/test.js @@ -305,6 +305,7 @@ test('should serialize custom error with `.toJSON`', t => { }; } } + const error = new CustomError(); const serialized = serializeError(error); t.deepEqual(serialized, { @@ -381,6 +382,7 @@ test('should ignore `.toJSON` methods if set in the options', t => { }; } } + const error = new CustomError(); const serialized = serializeError(error, {useToJSON: false}); t.like(serialized, {