ohbee-safe-json 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -47,6 +47,7 @@ var DEFAULTS = {
47
47
  handleSymbol: "omit",
48
48
  onCircular: "placeholder"
49
49
  };
50
+ var TRUNCATED_KEYS_KEY = "[Truncated]";
50
51
  function resolveOptions(options) {
51
52
  if (!options) return DEFAULTS;
52
53
  const userKeys = options.redactKeys?.map((k) => k.toLowerCase()) ?? [];
@@ -72,10 +73,34 @@ function isRedactedKey(key, opts) {
72
73
  const lower = key.toLowerCase();
73
74
  if (opts.redactKeys.includes(lower)) return true;
74
75
  for (const pattern of opts.redactByPattern) {
76
+ pattern.lastIndex = 0;
75
77
  if (pattern.test(key)) return true;
76
78
  }
77
79
  return false;
78
80
  }
81
+ function setResultValue(result, key, value) {
82
+ Object.defineProperty(result, key, {
83
+ value,
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true
87
+ });
88
+ }
89
+ function createResult() {
90
+ return {};
91
+ }
92
+ function serializeDate(value) {
93
+ return Number.isNaN(value.getTime()) ? "[Invalid Date]" : value.toISOString();
94
+ }
95
+ function addObjectTruncation(result, totalKeys, includedKeys) {
96
+ if (totalKeys > includedKeys) {
97
+ setResultValue(
98
+ result,
99
+ TRUNCATED_KEYS_KEY,
100
+ `[Truncated ${totalKeys - includedKeys} more keys]`
101
+ );
102
+ }
103
+ }
79
104
  function circularRef(opts, seen, obj) {
80
105
  if (opts.onCircular === "path") {
81
106
  return `[Circular: ${seen.get(obj) ?? "?"}]`;
@@ -83,27 +108,38 @@ function circularRef(opts, seen, obj) {
83
108
  return "[Circular]";
84
109
  }
85
110
  function serializeError(err, opts, seen, depth, path) {
86
- const result = {
87
- name: err.name,
88
- message: err.message
89
- };
111
+ const result = createResult();
112
+ setResultValue(result, "name", err.name);
113
+ setResultValue(result, "message", err.message);
90
114
  if (opts.includeErrorStack && err.stack) {
91
- result["stack"] = err.stack.length > opts.maxStringLength ? err.stack.slice(0, opts.maxStringLength) + "...[Truncated]" : err.stack;
115
+ setResultValue(
116
+ result,
117
+ "stack",
118
+ err.stack.length > opts.maxStringLength ? err.stack.slice(0, opts.maxStringLength) + "...[Truncated]" : err.stack
119
+ );
92
120
  }
93
121
  if (err.cause !== void 0) {
94
- result["cause"] = walk(err.cause, opts, seen, depth + 1, `${path}.cause`);
122
+ setResultValue(
123
+ result,
124
+ "cause",
125
+ walk(err.cause, opts, seen, depth + 1, `${path}.cause`)
126
+ );
95
127
  }
96
128
  for (const key of Object.keys(err)) {
97
- if (key in result) continue;
129
+ if (Object.prototype.hasOwnProperty.call(result, key)) continue;
98
130
  if (isRedactedKey(key, opts)) {
99
- result[key] = opts.replacement;
131
+ setResultValue(result, key, opts.replacement);
100
132
  } else {
101
- result[key] = walk(
102
- err[key],
103
- opts,
104
- seen,
105
- depth + 1,
106
- `${path}.${key}`
133
+ setResultValue(
134
+ result,
135
+ key,
136
+ walk(
137
+ err[key],
138
+ opts,
139
+ seen,
140
+ depth + 1,
141
+ `${path}.${key}`
142
+ )
107
143
  );
108
144
  }
109
145
  }
@@ -137,7 +173,7 @@ function walk(value, opts, seen, depth, path) {
137
173
  return "[Symbol]";
138
174
  }
139
175
  if (depth > opts.maxDepth) return "[MaxDepth]";
140
- if (value instanceof Date) return value.toISOString();
176
+ if (value instanceof Date) return serializeDate(value);
141
177
  if (value instanceof Error) {
142
178
  if (seen.has(value)) return circularRef(opts, seen, value);
143
179
  seen.set(value, path);
@@ -148,14 +184,19 @@ function walk(value, opts, seen, depth, path) {
148
184
  if (value instanceof Map) {
149
185
  if (seen.has(value)) return circularRef(opts, seen, value);
150
186
  seen.set(value, path);
151
- const obj = {};
187
+ const obj = createResult();
152
188
  let keyCount = 0;
153
189
  for (const [k, v] of value) {
154
190
  if (keyCount >= opts.maxObjectKeys) break;
155
191
  const keyStr = String(k);
156
- obj[keyStr] = isRedactedKey(keyStr, opts) ? opts.replacement : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`);
192
+ setResultValue(
193
+ obj,
194
+ keyStr,
195
+ isRedactedKey(keyStr, opts) ? opts.replacement : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`)
196
+ );
157
197
  keyCount++;
158
198
  }
199
+ addObjectTruncation(obj, value.size, keyCount);
159
200
  seen.delete(value);
160
201
  return obj;
161
202
  }
@@ -185,20 +226,21 @@ function walk(value, opts, seen, depth, path) {
185
226
  if (seen.has(value)) return circularRef(opts, seen, value);
186
227
  seen.set(value, path);
187
228
  const keys = opts.stable ? sortedKeys(value) : Object.keys(value);
188
- const result = {};
229
+ const result = createResult();
189
230
  let keyCount = 0;
190
231
  for (const key of keys) {
191
232
  if (keyCount >= opts.maxObjectKeys) break;
192
233
  if (isRedactedKey(key, opts)) {
193
- result[key] = opts.replacement;
234
+ setResultValue(result, key, opts.replacement);
194
235
  } else {
195
236
  const walked = walk(value[key], opts, seen, depth + 1, `${path}.${key}`);
196
237
  if (walked !== void 0) {
197
- result[key] = walked;
238
+ setResultValue(result, key, walked);
198
239
  }
199
240
  }
200
241
  keyCount++;
201
242
  }
243
+ addObjectTruncation(result, keys.length, keyCount);
202
244
  seen.delete(value);
203
245
  return result;
204
246
  }
@@ -206,12 +248,12 @@ function walk(value, opts, seen, depth, path) {
206
248
  if (seen.has(value)) return circularRef(opts, seen, value);
207
249
  seen.set(value, path);
208
250
  const keys = opts.stable ? Object.keys(value).sort() : Object.keys(value);
209
- const result = {};
251
+ const result = createResult();
210
252
  let keyCount = 0;
211
253
  for (const key of keys) {
212
254
  if (keyCount >= opts.maxObjectKeys) break;
213
255
  if (isRedactedKey(key, opts)) {
214
- result[key] = opts.replacement;
256
+ setResultValue(result, key, opts.replacement);
215
257
  } else {
216
258
  const walked = walk(
217
259
  value[key],
@@ -221,11 +263,12 @@ function walk(value, opts, seen, depth, path) {
221
263
  `${path}.${key}`
222
264
  );
223
265
  if (walked !== void 0) {
224
- result[key] = walked;
266
+ setResultValue(result, key, walked);
225
267
  }
226
268
  }
227
269
  keyCount++;
228
270
  }
271
+ addObjectTruncation(result, keys.length, keyCount);
229
272
  seen.delete(value);
230
273
  return result;
231
274
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/is-plain-object.ts","../src/utils/stable-sort.ts","../src/safe-clone.ts","../src/safe-stringify.ts","../src/redact.ts","../src/presets.ts","../src/create-safe-json.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n","export function sortedKeys(obj: Record<string, unknown>): string[] {\n return Object.keys(obj).sort();\n}\n","import type { ResolvedOptions, SafeJsonOptions } from \"./types.js\";\nimport { isPlainObject } from \"./utils/is-plain-object.js\";\nimport { sortedKeys } from \"./utils/stable-sort.js\";\n\nconst DEFAULT_REDACT_KEYS = [\n \"password\",\n \"pass\",\n \"pwd\",\n \"secret\",\n \"token\",\n \"accesstoken\",\n \"refreshtoken\",\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"apikey\",\n \"privatekey\",\n \"otp\",\n \"pin\",\n \"cardnumber\",\n \"cvv\",\n];\n\nconst DEFAULTS: ResolvedOptions = {\n redactKeys: DEFAULT_REDACT_KEYS,\n redactByPattern: [],\n replacement: \"[REDACTED]\",\n maxDepth: 6,\n maxArrayLength: 100,\n maxObjectKeys: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: false,\n pretty: false,\n handleBigInt: \"string\",\n handleFunction: \"omit\",\n handleSymbol: \"omit\",\n onCircular: \"placeholder\",\n};\n\nexport function resolveOptions(options?: SafeJsonOptions): ResolvedOptions {\n if (!options) return DEFAULTS;\n\n const userKeys = options.redactKeys?.map((k) => k.toLowerCase()) ?? [];\n const mergedKeys = [...DEFAULT_REDACT_KEYS, ...userKeys];\n\n return {\n redactKeys: mergedKeys,\n redactByPattern: options.redactByPattern ?? DEFAULTS.redactByPattern,\n replacement: options.replacement ?? DEFAULTS.replacement,\n maxDepth: options.maxDepth ?? DEFAULTS.maxDepth,\n maxArrayLength: options.maxArrayLength ?? DEFAULTS.maxArrayLength,\n maxObjectKeys: options.maxObjectKeys ?? DEFAULTS.maxObjectKeys,\n maxStringLength: options.maxStringLength ?? DEFAULTS.maxStringLength,\n includeErrorStack: options.includeErrorStack ?? DEFAULTS.includeErrorStack,\n stable: options.stable ?? DEFAULTS.stable,\n pretty: options.pretty ?? DEFAULTS.pretty,\n handleBigInt: options.handleBigInt ?? DEFAULTS.handleBigInt,\n handleFunction: options.handleFunction ?? DEFAULTS.handleFunction,\n handleSymbol: options.handleSymbol ?? DEFAULTS.handleSymbol,\n onCircular: options.onCircular ?? DEFAULTS.onCircular,\n };\n}\n\nfunction isRedactedKey(key: string, opts: ResolvedOptions): boolean {\n const lower = key.toLowerCase();\n if (opts.redactKeys.includes(lower)) return true;\n for (const pattern of opts.redactByPattern) {\n if (pattern.test(key)) return true;\n }\n return false;\n}\n\nfunction circularRef(\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n obj: object\n): string {\n if (opts.onCircular === \"path\") {\n return `[Circular: ${seen.get(obj) ?? \"?\"}]`;\n }\n return \"[Circular]\";\n}\n\nfunction serializeError(\n err: Error,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): Record<string, unknown> {\n const result: Record<string, unknown> = {\n name: err.name,\n message: err.message,\n };\n\n if (opts.includeErrorStack && err.stack) {\n result[\"stack\"] =\n err.stack.length > opts.maxStringLength\n ? err.stack.slice(0, opts.maxStringLength) + \"...[Truncated]\"\n : err.stack;\n }\n\n if (err.cause !== undefined) {\n result[\"cause\"] = walk(err.cause, opts, seen, depth + 1, `${path}.cause`);\n }\n\n for (const key of Object.keys(err)) {\n if (key in result) continue;\n if (isRedactedKey(key, opts)) {\n result[key] = opts.replacement;\n } else {\n result[key] = walk(\n (err as unknown as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n );\n }\n }\n\n return result;\n}\n\nfunction walk(\n value: unknown,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): unknown {\n // primitives\n if (value === null) return null;\n if (value === undefined) return undefined;\n\n if (typeof value === \"boolean\" || typeof value === \"number\") return value;\n\n if (typeof value === \"string\") {\n if (value.length > opts.maxStringLength) {\n return value.slice(0, opts.maxStringLength) + \"...[Truncated]\";\n }\n return value;\n }\n\n if (typeof value === \"bigint\") {\n if (opts.handleBigInt === \"redact\") return opts.replacement;\n if (opts.handleBigInt === \"number\") return Number(value);\n return value.toString();\n }\n\n if (typeof value === \"function\") {\n if (opts.handleFunction === \"omit\") return undefined;\n if (opts.handleFunction === \"name\")\n return value.name ? `[Function: ${value.name}]` : \"[Function]\";\n return \"[Function]\";\n }\n\n if (typeof value === \"symbol\") {\n if (opts.handleSymbol === \"omit\") return undefined;\n if (opts.handleSymbol === \"description\")\n return value.description ?? \"[Symbol]\";\n return \"[Symbol]\";\n }\n\n // objects\n if (depth > opts.maxDepth) return \"[MaxDepth]\";\n\n if (value instanceof Date) return value.toISOString();\n\n if (value instanceof Error) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const result = serializeError(value, opts, seen, depth, path);\n seen.delete(value);\n return result;\n }\n\n if (value instanceof Map) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const obj: Record<string, unknown> = {};\n let keyCount = 0;\n for (const [k, v] of value) {\n if (keyCount >= opts.maxObjectKeys) break;\n const keyStr = String(k);\n obj[keyStr] = isRedactedKey(keyStr, opts)\n ? opts.replacement\n : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`);\n keyCount++;\n }\n seen.delete(value);\n return obj;\n }\n\n if (value instanceof Set) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const arr = [...value].slice(0, opts.maxArrayLength);\n const result = arr.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.size > opts.maxArrayLength) {\n result.push(`[Truncated ${value.size - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const slice = value.slice(0, opts.maxArrayLength);\n const result = slice.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.length > opts.maxArrayLength) {\n result.push(`[Truncated ${value.length - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n\n const keys = opts.stable ? sortedKeys(value) : Object.keys(value);\n const result: Record<string, unknown> = {};\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n result[key] = opts.replacement;\n } else {\n const walked = walk(value[key], opts, seen, depth + 1, `${path}.${key}`);\n if (walked !== undefined) {\n result[key] = walked;\n }\n }\n keyCount++;\n }\n\n seen.delete(value);\n return result;\n }\n\n // non-plain objects (class instances) — treat as plain, extract own enumerable keys\n if (typeof value === \"object\") {\n if (seen.has(value as object)) return circularRef(opts, seen, value as object);\n seen.set(value as object, path);\n\n const keys = opts.stable\n ? Object.keys(value as object).sort()\n : Object.keys(value as object);\n const result: Record<string, unknown> = {};\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n result[key] = opts.replacement;\n } else {\n const walked = walk(\n (value as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n );\n if (walked !== undefined) {\n result[key] = walked;\n }\n }\n keyCount++;\n }\n\n seen.delete(value as object);\n return result;\n }\n\n return value;\n}\n\nexport function safeCloneResolved(value: unknown, opts: ResolvedOptions): unknown {\n const seen = new WeakMap<object, string>();\n return walk(value, opts, seen, 0, \"$\");\n}\n\nexport function safeClone(value: unknown, options?: SafeJsonOptions): unknown {\n return safeCloneResolved(value, resolveOptions(options));\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { resolveOptions, safeCloneResolved } from \"./safe-clone.js\";\n\nexport function safeStringify(value: unknown, options?: SafeJsonOptions): string {\n const opts = resolveOptions(options);\n const cloned = safeCloneResolved(value, opts);\n const indent = opts.pretty === true ? 2 : opts.pretty === false ? undefined : opts.pretty;\n return JSON.stringify(cloned, null, indent) ?? \"undefined\";\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\n\nexport type RedactOptions = {\n keys?: string[];\n pattern?: RegExp[];\n replacement?: string;\n};\n\nexport function redact(value: unknown, options?: RedactOptions): unknown {\n const opts: SafeJsonOptions = {};\n if (options?.keys !== undefined) opts.redactKeys = options.keys;\n if (options?.pattern !== undefined) opts.redactByPattern = options.pattern;\n if (options?.replacement !== undefined) opts.replacement = options.replacement;\n return safeClone(value, opts);\n}\n","import type { SafeJsonOptions } from \"./types.js\";\n\nexport const presets = {\n log: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n } satisfies SafeJsonOptions,\n\n debug: {\n maxDepth: 8,\n maxArrayLength: 200,\n maxStringLength: 8000,\n includeErrorStack: true,\n stable: false,\n } satisfies SafeJsonOptions,\n\n http: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n redactKeys: [\"headers\", \"cookie\", \"set-cookie\", \"authorization\"],\n } satisfies SafeJsonOptions,\n\n audit: {\n maxDepth: 5,\n maxArrayLength: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: true,\n } satisfies SafeJsonOptions,\n} as const;\n","import type { SafeJsonOptions, SafeJsonInstance } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\nimport { safeStringify } from \"./safe-stringify.js\";\nimport { presets } from \"./presets.js\";\n\nexport function createSafeJson(base: SafeJsonOptions = {}): SafeJsonInstance {\n function merge(overrides?: SafeJsonOptions): SafeJsonOptions {\n if (!overrides) return base;\n const mergedKeys = [\n ...(base.redactKeys ?? []),\n ...(overrides.redactKeys ?? []),\n ];\n const mergedPatterns = [\n ...(base.redactByPattern ?? []),\n ...(overrides.redactByPattern ?? []),\n ];\n const merged: SafeJsonOptions = { ...base, ...overrides };\n if (mergedKeys.length > 0) merged.redactKeys = mergedKeys;\n if (mergedPatterns.length > 0) merged.redactByPattern = mergedPatterns;\n return merged;\n }\n\n return {\n stringify(value, overrides) {\n return safeStringify(value, merge(overrides));\n },\n clone(value, overrides) {\n return safeClone(value, merge(overrides));\n },\n forLog(value) {\n return safeClone(value, merge(presets.log));\n },\n forDebug(value) {\n return safeClone(value, merge(presets.debug));\n },\n forHttp(value) {\n return safeClone(value, merge(presets.http));\n },\n forAudit(value) {\n return safeClone(value, merge(presets.audit));\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/is-plain-object.ts","../src/utils/stable-sort.ts","../src/safe-clone.ts","../src/safe-stringify.ts","../src/redact.ts","../src/presets.ts","../src/create-safe-json.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n","export function sortedKeys(obj: Record<string, unknown>): string[] {\n return Object.keys(obj).sort();\n}\n","import type { ResolvedOptions, SafeJsonOptions } from \"./types.js\";\nimport { isPlainObject } from \"./utils/is-plain-object.js\";\nimport { sortedKeys } from \"./utils/stable-sort.js\";\n\nconst DEFAULT_REDACT_KEYS = [\n \"password\",\n \"pass\",\n \"pwd\",\n \"secret\",\n \"token\",\n \"accesstoken\",\n \"refreshtoken\",\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"apikey\",\n \"privatekey\",\n \"otp\",\n \"pin\",\n \"cardnumber\",\n \"cvv\",\n];\n\nconst DEFAULTS: ResolvedOptions = {\n redactKeys: DEFAULT_REDACT_KEYS,\n redactByPattern: [],\n replacement: \"[REDACTED]\",\n maxDepth: 6,\n maxArrayLength: 100,\n maxObjectKeys: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: false,\n pretty: false,\n handleBigInt: \"string\",\n handleFunction: \"omit\",\n handleSymbol: \"omit\",\n onCircular: \"placeholder\",\n};\n\nconst TRUNCATED_KEYS_KEY = \"[Truncated]\";\n\nexport function resolveOptions(options?: SafeJsonOptions): ResolvedOptions {\n if (!options) return DEFAULTS;\n\n const userKeys = options.redactKeys?.map((k) => k.toLowerCase()) ?? [];\n const mergedKeys = [...DEFAULT_REDACT_KEYS, ...userKeys];\n\n return {\n redactKeys: mergedKeys,\n redactByPattern: options.redactByPattern ?? DEFAULTS.redactByPattern,\n replacement: options.replacement ?? DEFAULTS.replacement,\n maxDepth: options.maxDepth ?? DEFAULTS.maxDepth,\n maxArrayLength: options.maxArrayLength ?? DEFAULTS.maxArrayLength,\n maxObjectKeys: options.maxObjectKeys ?? DEFAULTS.maxObjectKeys,\n maxStringLength: options.maxStringLength ?? DEFAULTS.maxStringLength,\n includeErrorStack: options.includeErrorStack ?? DEFAULTS.includeErrorStack,\n stable: options.stable ?? DEFAULTS.stable,\n pretty: options.pretty ?? DEFAULTS.pretty,\n handleBigInt: options.handleBigInt ?? DEFAULTS.handleBigInt,\n handleFunction: options.handleFunction ?? DEFAULTS.handleFunction,\n handleSymbol: options.handleSymbol ?? DEFAULTS.handleSymbol,\n onCircular: options.onCircular ?? DEFAULTS.onCircular,\n };\n}\n\nfunction isRedactedKey(key: string, opts: ResolvedOptions): boolean {\n const lower = key.toLowerCase();\n if (opts.redactKeys.includes(lower)) return true;\n for (const pattern of opts.redactByPattern) {\n pattern.lastIndex = 0;\n if (pattern.test(key)) return true;\n }\n return false;\n}\n\nfunction setResultValue(\n result: Record<string, unknown>,\n key: string,\n value: unknown\n): void {\n Object.defineProperty(result, key, {\n value,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n}\n\nfunction createResult(): Record<string, unknown> {\n return {};\n}\n\nfunction serializeDate(value: Date): string {\n return Number.isNaN(value.getTime()) ? \"[Invalid Date]\" : value.toISOString();\n}\n\nfunction addObjectTruncation(\n result: Record<string, unknown>,\n totalKeys: number,\n includedKeys: number\n): void {\n if (totalKeys > includedKeys) {\n setResultValue(\n result,\n TRUNCATED_KEYS_KEY,\n `[Truncated ${totalKeys - includedKeys} more keys]`\n );\n }\n}\n\nfunction circularRef(\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n obj: object\n): string {\n if (opts.onCircular === \"path\") {\n return `[Circular: ${seen.get(obj) ?? \"?\"}]`;\n }\n return \"[Circular]\";\n}\n\nfunction serializeError(\n err: Error,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): Record<string, unknown> {\n const result = createResult();\n\n setResultValue(result, \"name\", err.name);\n setResultValue(result, \"message\", err.message);\n\n if (opts.includeErrorStack && err.stack) {\n setResultValue(\n result,\n \"stack\",\n err.stack.length > opts.maxStringLength\n ? err.stack.slice(0, opts.maxStringLength) + \"...[Truncated]\"\n : err.stack\n );\n }\n\n if (err.cause !== undefined) {\n setResultValue(\n result,\n \"cause\",\n walk(err.cause, opts, seen, depth + 1, `${path}.cause`)\n );\n }\n\n for (const key of Object.keys(err)) {\n if (Object.prototype.hasOwnProperty.call(result, key)) continue;\n if (isRedactedKey(key, opts)) {\n setResultValue(result, key, opts.replacement);\n } else {\n setResultValue(\n result,\n key,\n walk(\n (err as unknown as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n )\n );\n }\n }\n\n return result;\n}\n\nfunction walk(\n value: unknown,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): unknown {\n // primitives\n if (value === null) return null;\n if (value === undefined) return undefined;\n\n if (typeof value === \"boolean\" || typeof value === \"number\") return value;\n\n if (typeof value === \"string\") {\n if (value.length > opts.maxStringLength) {\n return value.slice(0, opts.maxStringLength) + \"...[Truncated]\";\n }\n return value;\n }\n\n if (typeof value === \"bigint\") {\n if (opts.handleBigInt === \"redact\") return opts.replacement;\n if (opts.handleBigInt === \"number\") return Number(value);\n return value.toString();\n }\n\n if (typeof value === \"function\") {\n if (opts.handleFunction === \"omit\") return undefined;\n if (opts.handleFunction === \"name\")\n return value.name ? `[Function: ${value.name}]` : \"[Function]\";\n return \"[Function]\";\n }\n\n if (typeof value === \"symbol\") {\n if (opts.handleSymbol === \"omit\") return undefined;\n if (opts.handleSymbol === \"description\")\n return value.description ?? \"[Symbol]\";\n return \"[Symbol]\";\n }\n\n // objects\n if (depth > opts.maxDepth) return \"[MaxDepth]\";\n\n if (value instanceof Date) return serializeDate(value);\n\n if (value instanceof Error) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const result = serializeError(value, opts, seen, depth, path);\n seen.delete(value);\n return result;\n }\n\n if (value instanceof Map) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const obj = createResult();\n let keyCount = 0;\n for (const [k, v] of value) {\n if (keyCount >= opts.maxObjectKeys) break;\n const keyStr = String(k);\n setResultValue(\n obj,\n keyStr,\n isRedactedKey(keyStr, opts)\n ? opts.replacement\n : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`)\n );\n keyCount++;\n }\n addObjectTruncation(obj, value.size, keyCount);\n seen.delete(value);\n return obj;\n }\n\n if (value instanceof Set) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const arr = [...value].slice(0, opts.maxArrayLength);\n const result = arr.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.size > opts.maxArrayLength) {\n result.push(`[Truncated ${value.size - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const slice = value.slice(0, opts.maxArrayLength);\n const result = slice.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.length > opts.maxArrayLength) {\n result.push(`[Truncated ${value.length - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n\n const keys = opts.stable ? sortedKeys(value) : Object.keys(value);\n const result = createResult();\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n setResultValue(result, key, opts.replacement);\n } else {\n const walked = walk(value[key], opts, seen, depth + 1, `${path}.${key}`);\n if (walked !== undefined) {\n setResultValue(result, key, walked);\n }\n }\n keyCount++;\n }\n\n addObjectTruncation(result, keys.length, keyCount);\n seen.delete(value);\n return result;\n }\n\n // non-plain objects (class instances) — treat as plain, extract own enumerable keys\n if (typeof value === \"object\") {\n if (seen.has(value as object)) return circularRef(opts, seen, value as object);\n seen.set(value as object, path);\n\n const keys = opts.stable\n ? Object.keys(value as object).sort()\n : Object.keys(value as object);\n const result = createResult();\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n setResultValue(result, key, opts.replacement);\n } else {\n const walked = walk(\n (value as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n );\n if (walked !== undefined) {\n setResultValue(result, key, walked);\n }\n }\n keyCount++;\n }\n\n addObjectTruncation(result, keys.length, keyCount);\n seen.delete(value as object);\n return result;\n }\n\n return value;\n}\n\nexport function safeCloneResolved(value: unknown, opts: ResolvedOptions): unknown {\n const seen = new WeakMap<object, string>();\n return walk(value, opts, seen, 0, \"$\");\n}\n\nexport function safeClone(value: unknown, options?: SafeJsonOptions): unknown {\n return safeCloneResolved(value, resolveOptions(options));\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { resolveOptions, safeCloneResolved } from \"./safe-clone.js\";\n\nexport function safeStringify(value: unknown, options?: SafeJsonOptions): string {\n const opts = resolveOptions(options);\n const cloned = safeCloneResolved(value, opts);\n const indent = opts.pretty === true ? 2 : opts.pretty === false ? undefined : opts.pretty;\n return JSON.stringify(cloned, null, indent) ?? \"undefined\";\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\n\nexport type RedactOptions = {\n keys?: string[];\n pattern?: RegExp[];\n replacement?: string;\n};\n\nexport function redact(value: unknown, options?: RedactOptions): unknown {\n const opts: SafeJsonOptions = {};\n if (options?.keys !== undefined) opts.redactKeys = options.keys;\n if (options?.pattern !== undefined) opts.redactByPattern = options.pattern;\n if (options?.replacement !== undefined) opts.replacement = options.replacement;\n return safeClone(value, opts);\n}\n","import type { SafeJsonOptions } from \"./types.js\";\n\nexport const presets = {\n log: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n } satisfies SafeJsonOptions,\n\n debug: {\n maxDepth: 8,\n maxArrayLength: 200,\n maxStringLength: 8000,\n includeErrorStack: true,\n stable: false,\n } satisfies SafeJsonOptions,\n\n http: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n redactKeys: [\"headers\", \"cookie\", \"set-cookie\", \"authorization\"],\n } satisfies SafeJsonOptions,\n\n audit: {\n maxDepth: 5,\n maxArrayLength: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: true,\n } satisfies SafeJsonOptions,\n} as const;\n","import type { SafeJsonOptions, SafeJsonInstance } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\nimport { safeStringify } from \"./safe-stringify.js\";\nimport { presets } from \"./presets.js\";\n\nexport function createSafeJson(base: SafeJsonOptions = {}): SafeJsonInstance {\n function merge(overrides?: SafeJsonOptions): SafeJsonOptions {\n if (!overrides) return base;\n const mergedKeys = [\n ...(base.redactKeys ?? []),\n ...(overrides.redactKeys ?? []),\n ];\n const mergedPatterns = [\n ...(base.redactByPattern ?? []),\n ...(overrides.redactByPattern ?? []),\n ];\n const merged: SafeJsonOptions = { ...base, ...overrides };\n if (mergedKeys.length > 0) merged.redactKeys = mergedKeys;\n if (mergedPatterns.length > 0) merged.redactByPattern = mergedPatterns;\n return merged;\n }\n\n return {\n stringify(value, overrides) {\n return safeStringify(value, merge(overrides));\n },\n clone(value, overrides) {\n return safeClone(value, merge(overrides));\n },\n forLog(value) {\n return safeClone(value, merge(presets.log));\n },\n forDebug(value) {\n return safeClone(value, merge(presets.debug));\n },\n forHttp(value) {\n return safeClone(value, merge(presets.http));\n },\n forAudit(value) {\n return safeClone(value, merge(presets.audit));\n },\n };\n}\n"]}
package/dist/index.js CHANGED
@@ -45,6 +45,7 @@ var DEFAULTS = {
45
45
  handleSymbol: "omit",
46
46
  onCircular: "placeholder"
47
47
  };
48
+ var TRUNCATED_KEYS_KEY = "[Truncated]";
48
49
  function resolveOptions(options) {
49
50
  if (!options) return DEFAULTS;
50
51
  const userKeys = options.redactKeys?.map((k) => k.toLowerCase()) ?? [];
@@ -70,10 +71,34 @@ function isRedactedKey(key, opts) {
70
71
  const lower = key.toLowerCase();
71
72
  if (opts.redactKeys.includes(lower)) return true;
72
73
  for (const pattern of opts.redactByPattern) {
74
+ pattern.lastIndex = 0;
73
75
  if (pattern.test(key)) return true;
74
76
  }
75
77
  return false;
76
78
  }
79
+ function setResultValue(result, key, value) {
80
+ Object.defineProperty(result, key, {
81
+ value,
82
+ enumerable: true,
83
+ configurable: true,
84
+ writable: true
85
+ });
86
+ }
87
+ function createResult() {
88
+ return {};
89
+ }
90
+ function serializeDate(value) {
91
+ return Number.isNaN(value.getTime()) ? "[Invalid Date]" : value.toISOString();
92
+ }
93
+ function addObjectTruncation(result, totalKeys, includedKeys) {
94
+ if (totalKeys > includedKeys) {
95
+ setResultValue(
96
+ result,
97
+ TRUNCATED_KEYS_KEY,
98
+ `[Truncated ${totalKeys - includedKeys} more keys]`
99
+ );
100
+ }
101
+ }
77
102
  function circularRef(opts, seen, obj) {
78
103
  if (opts.onCircular === "path") {
79
104
  return `[Circular: ${seen.get(obj) ?? "?"}]`;
@@ -81,27 +106,38 @@ function circularRef(opts, seen, obj) {
81
106
  return "[Circular]";
82
107
  }
83
108
  function serializeError(err, opts, seen, depth, path) {
84
- const result = {
85
- name: err.name,
86
- message: err.message
87
- };
109
+ const result = createResult();
110
+ setResultValue(result, "name", err.name);
111
+ setResultValue(result, "message", err.message);
88
112
  if (opts.includeErrorStack && err.stack) {
89
- result["stack"] = err.stack.length > opts.maxStringLength ? err.stack.slice(0, opts.maxStringLength) + "...[Truncated]" : err.stack;
113
+ setResultValue(
114
+ result,
115
+ "stack",
116
+ err.stack.length > opts.maxStringLength ? err.stack.slice(0, opts.maxStringLength) + "...[Truncated]" : err.stack
117
+ );
90
118
  }
91
119
  if (err.cause !== void 0) {
92
- result["cause"] = walk(err.cause, opts, seen, depth + 1, `${path}.cause`);
120
+ setResultValue(
121
+ result,
122
+ "cause",
123
+ walk(err.cause, opts, seen, depth + 1, `${path}.cause`)
124
+ );
93
125
  }
94
126
  for (const key of Object.keys(err)) {
95
- if (key in result) continue;
127
+ if (Object.prototype.hasOwnProperty.call(result, key)) continue;
96
128
  if (isRedactedKey(key, opts)) {
97
- result[key] = opts.replacement;
129
+ setResultValue(result, key, opts.replacement);
98
130
  } else {
99
- result[key] = walk(
100
- err[key],
101
- opts,
102
- seen,
103
- depth + 1,
104
- `${path}.${key}`
131
+ setResultValue(
132
+ result,
133
+ key,
134
+ walk(
135
+ err[key],
136
+ opts,
137
+ seen,
138
+ depth + 1,
139
+ `${path}.${key}`
140
+ )
105
141
  );
106
142
  }
107
143
  }
@@ -135,7 +171,7 @@ function walk(value, opts, seen, depth, path) {
135
171
  return "[Symbol]";
136
172
  }
137
173
  if (depth > opts.maxDepth) return "[MaxDepth]";
138
- if (value instanceof Date) return value.toISOString();
174
+ if (value instanceof Date) return serializeDate(value);
139
175
  if (value instanceof Error) {
140
176
  if (seen.has(value)) return circularRef(opts, seen, value);
141
177
  seen.set(value, path);
@@ -146,14 +182,19 @@ function walk(value, opts, seen, depth, path) {
146
182
  if (value instanceof Map) {
147
183
  if (seen.has(value)) return circularRef(opts, seen, value);
148
184
  seen.set(value, path);
149
- const obj = {};
185
+ const obj = createResult();
150
186
  let keyCount = 0;
151
187
  for (const [k, v] of value) {
152
188
  if (keyCount >= opts.maxObjectKeys) break;
153
189
  const keyStr = String(k);
154
- obj[keyStr] = isRedactedKey(keyStr, opts) ? opts.replacement : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`);
190
+ setResultValue(
191
+ obj,
192
+ keyStr,
193
+ isRedactedKey(keyStr, opts) ? opts.replacement : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`)
194
+ );
155
195
  keyCount++;
156
196
  }
197
+ addObjectTruncation(obj, value.size, keyCount);
157
198
  seen.delete(value);
158
199
  return obj;
159
200
  }
@@ -183,20 +224,21 @@ function walk(value, opts, seen, depth, path) {
183
224
  if (seen.has(value)) return circularRef(opts, seen, value);
184
225
  seen.set(value, path);
185
226
  const keys = opts.stable ? sortedKeys(value) : Object.keys(value);
186
- const result = {};
227
+ const result = createResult();
187
228
  let keyCount = 0;
188
229
  for (const key of keys) {
189
230
  if (keyCount >= opts.maxObjectKeys) break;
190
231
  if (isRedactedKey(key, opts)) {
191
- result[key] = opts.replacement;
232
+ setResultValue(result, key, opts.replacement);
192
233
  } else {
193
234
  const walked = walk(value[key], opts, seen, depth + 1, `${path}.${key}`);
194
235
  if (walked !== void 0) {
195
- result[key] = walked;
236
+ setResultValue(result, key, walked);
196
237
  }
197
238
  }
198
239
  keyCount++;
199
240
  }
241
+ addObjectTruncation(result, keys.length, keyCount);
200
242
  seen.delete(value);
201
243
  return result;
202
244
  }
@@ -204,12 +246,12 @@ function walk(value, opts, seen, depth, path) {
204
246
  if (seen.has(value)) return circularRef(opts, seen, value);
205
247
  seen.set(value, path);
206
248
  const keys = opts.stable ? Object.keys(value).sort() : Object.keys(value);
207
- const result = {};
249
+ const result = createResult();
208
250
  let keyCount = 0;
209
251
  for (const key of keys) {
210
252
  if (keyCount >= opts.maxObjectKeys) break;
211
253
  if (isRedactedKey(key, opts)) {
212
- result[key] = opts.replacement;
254
+ setResultValue(result, key, opts.replacement);
213
255
  } else {
214
256
  const walked = walk(
215
257
  value[key],
@@ -219,11 +261,12 @@ function walk(value, opts, seen, depth, path) {
219
261
  `${path}.${key}`
220
262
  );
221
263
  if (walked !== void 0) {
222
- result[key] = walked;
264
+ setResultValue(result, key, walked);
223
265
  }
224
266
  }
225
267
  keyCount++;
226
268
  }
269
+ addObjectTruncation(result, keys.length, keyCount);
227
270
  seen.delete(value);
228
271
  return result;
229
272
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/is-plain-object.ts","../src/utils/stable-sort.ts","../src/safe-clone.ts","../src/safe-stringify.ts","../src/redact.ts","../src/presets.ts","../src/create-safe-json.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n","export function sortedKeys(obj: Record<string, unknown>): string[] {\n return Object.keys(obj).sort();\n}\n","import type { ResolvedOptions, SafeJsonOptions } from \"./types.js\";\nimport { isPlainObject } from \"./utils/is-plain-object.js\";\nimport { sortedKeys } from \"./utils/stable-sort.js\";\n\nconst DEFAULT_REDACT_KEYS = [\n \"password\",\n \"pass\",\n \"pwd\",\n \"secret\",\n \"token\",\n \"accesstoken\",\n \"refreshtoken\",\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"apikey\",\n \"privatekey\",\n \"otp\",\n \"pin\",\n \"cardnumber\",\n \"cvv\",\n];\n\nconst DEFAULTS: ResolvedOptions = {\n redactKeys: DEFAULT_REDACT_KEYS,\n redactByPattern: [],\n replacement: \"[REDACTED]\",\n maxDepth: 6,\n maxArrayLength: 100,\n maxObjectKeys: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: false,\n pretty: false,\n handleBigInt: \"string\",\n handleFunction: \"omit\",\n handleSymbol: \"omit\",\n onCircular: \"placeholder\",\n};\n\nexport function resolveOptions(options?: SafeJsonOptions): ResolvedOptions {\n if (!options) return DEFAULTS;\n\n const userKeys = options.redactKeys?.map((k) => k.toLowerCase()) ?? [];\n const mergedKeys = [...DEFAULT_REDACT_KEYS, ...userKeys];\n\n return {\n redactKeys: mergedKeys,\n redactByPattern: options.redactByPattern ?? DEFAULTS.redactByPattern,\n replacement: options.replacement ?? DEFAULTS.replacement,\n maxDepth: options.maxDepth ?? DEFAULTS.maxDepth,\n maxArrayLength: options.maxArrayLength ?? DEFAULTS.maxArrayLength,\n maxObjectKeys: options.maxObjectKeys ?? DEFAULTS.maxObjectKeys,\n maxStringLength: options.maxStringLength ?? DEFAULTS.maxStringLength,\n includeErrorStack: options.includeErrorStack ?? DEFAULTS.includeErrorStack,\n stable: options.stable ?? DEFAULTS.stable,\n pretty: options.pretty ?? DEFAULTS.pretty,\n handleBigInt: options.handleBigInt ?? DEFAULTS.handleBigInt,\n handleFunction: options.handleFunction ?? DEFAULTS.handleFunction,\n handleSymbol: options.handleSymbol ?? DEFAULTS.handleSymbol,\n onCircular: options.onCircular ?? DEFAULTS.onCircular,\n };\n}\n\nfunction isRedactedKey(key: string, opts: ResolvedOptions): boolean {\n const lower = key.toLowerCase();\n if (opts.redactKeys.includes(lower)) return true;\n for (const pattern of opts.redactByPattern) {\n if (pattern.test(key)) return true;\n }\n return false;\n}\n\nfunction circularRef(\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n obj: object\n): string {\n if (opts.onCircular === \"path\") {\n return `[Circular: ${seen.get(obj) ?? \"?\"}]`;\n }\n return \"[Circular]\";\n}\n\nfunction serializeError(\n err: Error,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): Record<string, unknown> {\n const result: Record<string, unknown> = {\n name: err.name,\n message: err.message,\n };\n\n if (opts.includeErrorStack && err.stack) {\n result[\"stack\"] =\n err.stack.length > opts.maxStringLength\n ? err.stack.slice(0, opts.maxStringLength) + \"...[Truncated]\"\n : err.stack;\n }\n\n if (err.cause !== undefined) {\n result[\"cause\"] = walk(err.cause, opts, seen, depth + 1, `${path}.cause`);\n }\n\n for (const key of Object.keys(err)) {\n if (key in result) continue;\n if (isRedactedKey(key, opts)) {\n result[key] = opts.replacement;\n } else {\n result[key] = walk(\n (err as unknown as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n );\n }\n }\n\n return result;\n}\n\nfunction walk(\n value: unknown,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): unknown {\n // primitives\n if (value === null) return null;\n if (value === undefined) return undefined;\n\n if (typeof value === \"boolean\" || typeof value === \"number\") return value;\n\n if (typeof value === \"string\") {\n if (value.length > opts.maxStringLength) {\n return value.slice(0, opts.maxStringLength) + \"...[Truncated]\";\n }\n return value;\n }\n\n if (typeof value === \"bigint\") {\n if (opts.handleBigInt === \"redact\") return opts.replacement;\n if (opts.handleBigInt === \"number\") return Number(value);\n return value.toString();\n }\n\n if (typeof value === \"function\") {\n if (opts.handleFunction === \"omit\") return undefined;\n if (opts.handleFunction === \"name\")\n return value.name ? `[Function: ${value.name}]` : \"[Function]\";\n return \"[Function]\";\n }\n\n if (typeof value === \"symbol\") {\n if (opts.handleSymbol === \"omit\") return undefined;\n if (opts.handleSymbol === \"description\")\n return value.description ?? \"[Symbol]\";\n return \"[Symbol]\";\n }\n\n // objects\n if (depth > opts.maxDepth) return \"[MaxDepth]\";\n\n if (value instanceof Date) return value.toISOString();\n\n if (value instanceof Error) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const result = serializeError(value, opts, seen, depth, path);\n seen.delete(value);\n return result;\n }\n\n if (value instanceof Map) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const obj: Record<string, unknown> = {};\n let keyCount = 0;\n for (const [k, v] of value) {\n if (keyCount >= opts.maxObjectKeys) break;\n const keyStr = String(k);\n obj[keyStr] = isRedactedKey(keyStr, opts)\n ? opts.replacement\n : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`);\n keyCount++;\n }\n seen.delete(value);\n return obj;\n }\n\n if (value instanceof Set) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const arr = [...value].slice(0, opts.maxArrayLength);\n const result = arr.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.size > opts.maxArrayLength) {\n result.push(`[Truncated ${value.size - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const slice = value.slice(0, opts.maxArrayLength);\n const result = slice.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.length > opts.maxArrayLength) {\n result.push(`[Truncated ${value.length - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n\n const keys = opts.stable ? sortedKeys(value) : Object.keys(value);\n const result: Record<string, unknown> = {};\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n result[key] = opts.replacement;\n } else {\n const walked = walk(value[key], opts, seen, depth + 1, `${path}.${key}`);\n if (walked !== undefined) {\n result[key] = walked;\n }\n }\n keyCount++;\n }\n\n seen.delete(value);\n return result;\n }\n\n // non-plain objects (class instances) — treat as plain, extract own enumerable keys\n if (typeof value === \"object\") {\n if (seen.has(value as object)) return circularRef(opts, seen, value as object);\n seen.set(value as object, path);\n\n const keys = opts.stable\n ? Object.keys(value as object).sort()\n : Object.keys(value as object);\n const result: Record<string, unknown> = {};\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n result[key] = opts.replacement;\n } else {\n const walked = walk(\n (value as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n );\n if (walked !== undefined) {\n result[key] = walked;\n }\n }\n keyCount++;\n }\n\n seen.delete(value as object);\n return result;\n }\n\n return value;\n}\n\nexport function safeCloneResolved(value: unknown, opts: ResolvedOptions): unknown {\n const seen = new WeakMap<object, string>();\n return walk(value, opts, seen, 0, \"$\");\n}\n\nexport function safeClone(value: unknown, options?: SafeJsonOptions): unknown {\n return safeCloneResolved(value, resolveOptions(options));\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { resolveOptions, safeCloneResolved } from \"./safe-clone.js\";\n\nexport function safeStringify(value: unknown, options?: SafeJsonOptions): string {\n const opts = resolveOptions(options);\n const cloned = safeCloneResolved(value, opts);\n const indent = opts.pretty === true ? 2 : opts.pretty === false ? undefined : opts.pretty;\n return JSON.stringify(cloned, null, indent) ?? \"undefined\";\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\n\nexport type RedactOptions = {\n keys?: string[];\n pattern?: RegExp[];\n replacement?: string;\n};\n\nexport function redact(value: unknown, options?: RedactOptions): unknown {\n const opts: SafeJsonOptions = {};\n if (options?.keys !== undefined) opts.redactKeys = options.keys;\n if (options?.pattern !== undefined) opts.redactByPattern = options.pattern;\n if (options?.replacement !== undefined) opts.replacement = options.replacement;\n return safeClone(value, opts);\n}\n","import type { SafeJsonOptions } from \"./types.js\";\n\nexport const presets = {\n log: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n } satisfies SafeJsonOptions,\n\n debug: {\n maxDepth: 8,\n maxArrayLength: 200,\n maxStringLength: 8000,\n includeErrorStack: true,\n stable: false,\n } satisfies SafeJsonOptions,\n\n http: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n redactKeys: [\"headers\", \"cookie\", \"set-cookie\", \"authorization\"],\n } satisfies SafeJsonOptions,\n\n audit: {\n maxDepth: 5,\n maxArrayLength: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: true,\n } satisfies SafeJsonOptions,\n} as const;\n","import type { SafeJsonOptions, SafeJsonInstance } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\nimport { safeStringify } from \"./safe-stringify.js\";\nimport { presets } from \"./presets.js\";\n\nexport function createSafeJson(base: SafeJsonOptions = {}): SafeJsonInstance {\n function merge(overrides?: SafeJsonOptions): SafeJsonOptions {\n if (!overrides) return base;\n const mergedKeys = [\n ...(base.redactKeys ?? []),\n ...(overrides.redactKeys ?? []),\n ];\n const mergedPatterns = [\n ...(base.redactByPattern ?? []),\n ...(overrides.redactByPattern ?? []),\n ];\n const merged: SafeJsonOptions = { ...base, ...overrides };\n if (mergedKeys.length > 0) merged.redactKeys = mergedKeys;\n if (mergedPatterns.length > 0) merged.redactByPattern = mergedPatterns;\n return merged;\n }\n\n return {\n stringify(value, overrides) {\n return safeStringify(value, merge(overrides));\n },\n clone(value, overrides) {\n return safeClone(value, merge(overrides));\n },\n forLog(value) {\n return safeClone(value, merge(presets.log));\n },\n forDebug(value) {\n return safeClone(value, merge(presets.debug));\n },\n forHttp(value) {\n return safeClone(value, merge(presets.http));\n },\n forAudit(value) {\n return safeClone(value, merge(presets.audit));\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/is-plain-object.ts","../src/utils/stable-sort.ts","../src/safe-clone.ts","../src/safe-stringify.ts","../src/redact.ts","../src/presets.ts","../src/create-safe-json.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n","export function sortedKeys(obj: Record<string, unknown>): string[] {\n return Object.keys(obj).sort();\n}\n","import type { ResolvedOptions, SafeJsonOptions } from \"./types.js\";\nimport { isPlainObject } from \"./utils/is-plain-object.js\";\nimport { sortedKeys } from \"./utils/stable-sort.js\";\n\nconst DEFAULT_REDACT_KEYS = [\n \"password\",\n \"pass\",\n \"pwd\",\n \"secret\",\n \"token\",\n \"accesstoken\",\n \"refreshtoken\",\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"apikey\",\n \"privatekey\",\n \"otp\",\n \"pin\",\n \"cardnumber\",\n \"cvv\",\n];\n\nconst DEFAULTS: ResolvedOptions = {\n redactKeys: DEFAULT_REDACT_KEYS,\n redactByPattern: [],\n replacement: \"[REDACTED]\",\n maxDepth: 6,\n maxArrayLength: 100,\n maxObjectKeys: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: false,\n pretty: false,\n handleBigInt: \"string\",\n handleFunction: \"omit\",\n handleSymbol: \"omit\",\n onCircular: \"placeholder\",\n};\n\nconst TRUNCATED_KEYS_KEY = \"[Truncated]\";\n\nexport function resolveOptions(options?: SafeJsonOptions): ResolvedOptions {\n if (!options) return DEFAULTS;\n\n const userKeys = options.redactKeys?.map((k) => k.toLowerCase()) ?? [];\n const mergedKeys = [...DEFAULT_REDACT_KEYS, ...userKeys];\n\n return {\n redactKeys: mergedKeys,\n redactByPattern: options.redactByPattern ?? DEFAULTS.redactByPattern,\n replacement: options.replacement ?? DEFAULTS.replacement,\n maxDepth: options.maxDepth ?? DEFAULTS.maxDepth,\n maxArrayLength: options.maxArrayLength ?? DEFAULTS.maxArrayLength,\n maxObjectKeys: options.maxObjectKeys ?? DEFAULTS.maxObjectKeys,\n maxStringLength: options.maxStringLength ?? DEFAULTS.maxStringLength,\n includeErrorStack: options.includeErrorStack ?? DEFAULTS.includeErrorStack,\n stable: options.stable ?? DEFAULTS.stable,\n pretty: options.pretty ?? DEFAULTS.pretty,\n handleBigInt: options.handleBigInt ?? DEFAULTS.handleBigInt,\n handleFunction: options.handleFunction ?? DEFAULTS.handleFunction,\n handleSymbol: options.handleSymbol ?? DEFAULTS.handleSymbol,\n onCircular: options.onCircular ?? DEFAULTS.onCircular,\n };\n}\n\nfunction isRedactedKey(key: string, opts: ResolvedOptions): boolean {\n const lower = key.toLowerCase();\n if (opts.redactKeys.includes(lower)) return true;\n for (const pattern of opts.redactByPattern) {\n pattern.lastIndex = 0;\n if (pattern.test(key)) return true;\n }\n return false;\n}\n\nfunction setResultValue(\n result: Record<string, unknown>,\n key: string,\n value: unknown\n): void {\n Object.defineProperty(result, key, {\n value,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n}\n\nfunction createResult(): Record<string, unknown> {\n return {};\n}\n\nfunction serializeDate(value: Date): string {\n return Number.isNaN(value.getTime()) ? \"[Invalid Date]\" : value.toISOString();\n}\n\nfunction addObjectTruncation(\n result: Record<string, unknown>,\n totalKeys: number,\n includedKeys: number\n): void {\n if (totalKeys > includedKeys) {\n setResultValue(\n result,\n TRUNCATED_KEYS_KEY,\n `[Truncated ${totalKeys - includedKeys} more keys]`\n );\n }\n}\n\nfunction circularRef(\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n obj: object\n): string {\n if (opts.onCircular === \"path\") {\n return `[Circular: ${seen.get(obj) ?? \"?\"}]`;\n }\n return \"[Circular]\";\n}\n\nfunction serializeError(\n err: Error,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): Record<string, unknown> {\n const result = createResult();\n\n setResultValue(result, \"name\", err.name);\n setResultValue(result, \"message\", err.message);\n\n if (opts.includeErrorStack && err.stack) {\n setResultValue(\n result,\n \"stack\",\n err.stack.length > opts.maxStringLength\n ? err.stack.slice(0, opts.maxStringLength) + \"...[Truncated]\"\n : err.stack\n );\n }\n\n if (err.cause !== undefined) {\n setResultValue(\n result,\n \"cause\",\n walk(err.cause, opts, seen, depth + 1, `${path}.cause`)\n );\n }\n\n for (const key of Object.keys(err)) {\n if (Object.prototype.hasOwnProperty.call(result, key)) continue;\n if (isRedactedKey(key, opts)) {\n setResultValue(result, key, opts.replacement);\n } else {\n setResultValue(\n result,\n key,\n walk(\n (err as unknown as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n )\n );\n }\n }\n\n return result;\n}\n\nfunction walk(\n value: unknown,\n opts: ResolvedOptions,\n seen: WeakMap<object, string>,\n depth: number,\n path: string\n): unknown {\n // primitives\n if (value === null) return null;\n if (value === undefined) return undefined;\n\n if (typeof value === \"boolean\" || typeof value === \"number\") return value;\n\n if (typeof value === \"string\") {\n if (value.length > opts.maxStringLength) {\n return value.slice(0, opts.maxStringLength) + \"...[Truncated]\";\n }\n return value;\n }\n\n if (typeof value === \"bigint\") {\n if (opts.handleBigInt === \"redact\") return opts.replacement;\n if (opts.handleBigInt === \"number\") return Number(value);\n return value.toString();\n }\n\n if (typeof value === \"function\") {\n if (opts.handleFunction === \"omit\") return undefined;\n if (opts.handleFunction === \"name\")\n return value.name ? `[Function: ${value.name}]` : \"[Function]\";\n return \"[Function]\";\n }\n\n if (typeof value === \"symbol\") {\n if (opts.handleSymbol === \"omit\") return undefined;\n if (opts.handleSymbol === \"description\")\n return value.description ?? \"[Symbol]\";\n return \"[Symbol]\";\n }\n\n // objects\n if (depth > opts.maxDepth) return \"[MaxDepth]\";\n\n if (value instanceof Date) return serializeDate(value);\n\n if (value instanceof Error) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const result = serializeError(value, opts, seen, depth, path);\n seen.delete(value);\n return result;\n }\n\n if (value instanceof Map) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const obj = createResult();\n let keyCount = 0;\n for (const [k, v] of value) {\n if (keyCount >= opts.maxObjectKeys) break;\n const keyStr = String(k);\n setResultValue(\n obj,\n keyStr,\n isRedactedKey(keyStr, opts)\n ? opts.replacement\n : walk(v, opts, seen, depth + 1, `${path}.${keyStr}`)\n );\n keyCount++;\n }\n addObjectTruncation(obj, value.size, keyCount);\n seen.delete(value);\n return obj;\n }\n\n if (value instanceof Set) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const arr = [...value].slice(0, opts.maxArrayLength);\n const result = arr.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.size > opts.maxArrayLength) {\n result.push(`[Truncated ${value.size - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n const slice = value.slice(0, opts.maxArrayLength);\n const result = slice.map((v, i) => walk(v, opts, seen, depth + 1, `${path}[${i}]`));\n if (value.length > opts.maxArrayLength) {\n result.push(`[Truncated ${value.length - opts.maxArrayLength} more items]`);\n }\n seen.delete(value);\n return result;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return circularRef(opts, seen, value);\n seen.set(value, path);\n\n const keys = opts.stable ? sortedKeys(value) : Object.keys(value);\n const result = createResult();\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n setResultValue(result, key, opts.replacement);\n } else {\n const walked = walk(value[key], opts, seen, depth + 1, `${path}.${key}`);\n if (walked !== undefined) {\n setResultValue(result, key, walked);\n }\n }\n keyCount++;\n }\n\n addObjectTruncation(result, keys.length, keyCount);\n seen.delete(value);\n return result;\n }\n\n // non-plain objects (class instances) — treat as plain, extract own enumerable keys\n if (typeof value === \"object\") {\n if (seen.has(value as object)) return circularRef(opts, seen, value as object);\n seen.set(value as object, path);\n\n const keys = opts.stable\n ? Object.keys(value as object).sort()\n : Object.keys(value as object);\n const result = createResult();\n let keyCount = 0;\n\n for (const key of keys) {\n if (keyCount >= opts.maxObjectKeys) break;\n if (isRedactedKey(key, opts)) {\n setResultValue(result, key, opts.replacement);\n } else {\n const walked = walk(\n (value as Record<string, unknown>)[key],\n opts,\n seen,\n depth + 1,\n `${path}.${key}`\n );\n if (walked !== undefined) {\n setResultValue(result, key, walked);\n }\n }\n keyCount++;\n }\n\n addObjectTruncation(result, keys.length, keyCount);\n seen.delete(value as object);\n return result;\n }\n\n return value;\n}\n\nexport function safeCloneResolved(value: unknown, opts: ResolvedOptions): unknown {\n const seen = new WeakMap<object, string>();\n return walk(value, opts, seen, 0, \"$\");\n}\n\nexport function safeClone(value: unknown, options?: SafeJsonOptions): unknown {\n return safeCloneResolved(value, resolveOptions(options));\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { resolveOptions, safeCloneResolved } from \"./safe-clone.js\";\n\nexport function safeStringify(value: unknown, options?: SafeJsonOptions): string {\n const opts = resolveOptions(options);\n const cloned = safeCloneResolved(value, opts);\n const indent = opts.pretty === true ? 2 : opts.pretty === false ? undefined : opts.pretty;\n return JSON.stringify(cloned, null, indent) ?? \"undefined\";\n}\n","import type { SafeJsonOptions } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\n\nexport type RedactOptions = {\n keys?: string[];\n pattern?: RegExp[];\n replacement?: string;\n};\n\nexport function redact(value: unknown, options?: RedactOptions): unknown {\n const opts: SafeJsonOptions = {};\n if (options?.keys !== undefined) opts.redactKeys = options.keys;\n if (options?.pattern !== undefined) opts.redactByPattern = options.pattern;\n if (options?.replacement !== undefined) opts.replacement = options.replacement;\n return safeClone(value, opts);\n}\n","import type { SafeJsonOptions } from \"./types.js\";\n\nexport const presets = {\n log: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n } satisfies SafeJsonOptions,\n\n debug: {\n maxDepth: 8,\n maxArrayLength: 200,\n maxStringLength: 8000,\n includeErrorStack: true,\n stable: false,\n } satisfies SafeJsonOptions,\n\n http: {\n maxDepth: 5,\n maxArrayLength: 50,\n maxStringLength: 2000,\n includeErrorStack: false,\n stable: false,\n redactKeys: [\"headers\", \"cookie\", \"set-cookie\", \"authorization\"],\n } satisfies SafeJsonOptions,\n\n audit: {\n maxDepth: 5,\n maxArrayLength: 100,\n maxStringLength: 4000,\n includeErrorStack: false,\n stable: true,\n } satisfies SafeJsonOptions,\n} as const;\n","import type { SafeJsonOptions, SafeJsonInstance } from \"./types.js\";\nimport { safeClone } from \"./safe-clone.js\";\nimport { safeStringify } from \"./safe-stringify.js\";\nimport { presets } from \"./presets.js\";\n\nexport function createSafeJson(base: SafeJsonOptions = {}): SafeJsonInstance {\n function merge(overrides?: SafeJsonOptions): SafeJsonOptions {\n if (!overrides) return base;\n const mergedKeys = [\n ...(base.redactKeys ?? []),\n ...(overrides.redactKeys ?? []),\n ];\n const mergedPatterns = [\n ...(base.redactByPattern ?? []),\n ...(overrides.redactByPattern ?? []),\n ];\n const merged: SafeJsonOptions = { ...base, ...overrides };\n if (mergedKeys.length > 0) merged.redactKeys = mergedKeys;\n if (mergedPatterns.length > 0) merged.redactByPattern = mergedPatterns;\n return merged;\n }\n\n return {\n stringify(value, overrides) {\n return safeStringify(value, merge(overrides));\n },\n clone(value, overrides) {\n return safeClone(value, merge(overrides));\n },\n forLog(value) {\n return safeClone(value, merge(presets.log));\n },\n forDebug(value) {\n return safeClone(value, merge(presets.debug));\n },\n forHttp(value) {\n return safeClone(value, merge(presets.http));\n },\n forAudit(value) {\n return safeClone(value, merge(presets.audit));\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohbee-safe-json",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "JSON.stringify for production logs: safe, lightweight, redacted, bounded, and predictable.",
5
5
  "keywords": [
6
6
  "json",
@@ -15,7 +15,7 @@
15
15
  "author": "Ohbee",
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "https://github.com/ohbee-labs/-ohbee-safe-json"
18
+ "url": "git+https://github.com/ohbee-labs/-ohbee-safe-json.git"
19
19
  },
20
20
  "type": "module",
21
21
  "main": "./dist/index.cjs",