Skip to content

Commit

Permalink
feat(utils): safe json stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
glebcha committed Nov 21, 2024
1 parent 1634e28 commit 7f5efa6
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 4 deletions.
3 changes: 1 addition & 2 deletions src/utils/getBody/getBody.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
import { suite } from 'uvu';
import * as assert from 'uvu/assert';

Expand All @@ -8,7 +7,7 @@ import { getBody } from './getBody';

const clientSuite = suite('Safe JSON Stringify');

clientSuite('should output object with formatted sql string', async () => {
clientSuite('should output object with formatted sql string', () => {
const result = getBody(query);

assert.equal(result.length, 22);
Expand Down
4 changes: 3 additions & 1 deletion src/utils/getBody/getBody.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { safeJsonStringify } from './safeJsonStringify';

const { warn } = console;

const LIB_ID = process.env.LIB_ID ?? 'ExtendedFetch';
Expand All @@ -10,7 +12,7 @@ export function getBody(query?: unknown) {
let body = '{}';

try {
body = JSON.stringify(query);
body = safeJsonStringify(query);
} catch (error) {
warn(`${LIB_ID}: Failed to parse query ${String(error)}`);
}
Expand Down
1 change: 1 addition & 0 deletions src/utils/getBody/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { getBody } from './getBody';
export { safeJsonStringify } from './safeJsonStringify';
35 changes: 35 additions & 0 deletions src/utils/getBody/safeJsonStringify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { is } from '../getType';

function safeJsonStringifyReplacer(seen: WeakSet<object>) {
return function (_key: string | number, value: unknown) {
if (is.Object(value) && typeof value?.toJSON === 'function') {
value = value.toJSON();
}

if (!(value !== null && typeof value === 'object')) {
return value;
}

if (seen.has(value)) {
return '[Circular]';
}

seen.add(value);

const newValue = (Array.isArray(value) ? [] : {}) as unknown[] & Record<string, unknown>;

for (const [innerKey, innerValue] of Object.entries(value)) {
newValue[innerKey] = safeJsonStringifyReplacer(seen)(innerKey, innerValue);
}

seen.delete(value);

return newValue;
};
}

export function safeJsonStringify(data: unknown, space?: string | number) {
const seen = new WeakSet();

return JSON.stringify(data, safeJsonStringifyReplacer(seen), space);
}
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { getBody } from './getBody';
export { getBody, safeJsonStringify } from './getBody';
export { is } from './getType';
export { deepMerge } from './deepMerge';
export { applyHeaders } from './applyHeaders';

0 comments on commit 7f5efa6

Please sign in to comment.