1import { isPlainObject } from "./data.ts";
2
3export const normalizeNulls = <T>(value: T): T => {
4 if (value === null) {
5 return undefined as T;
6 }
7 if (Array.isArray(value)) {
8 return value.map((item) => normalizeNulls(item)) as T;
9 }
10 if (isPlainObject(value)) {
11 return Object.fromEntries(
12 Object.entries(value)
13 .map(([key, nested]) => [key, normalizeNulls(nested)])
14 .filter(([, nested]) => nested !== undefined),
15 ) as T;
16 }
17 return value;
18};
19
20export const stableValue = (value: unknown): unknown => {
21 if (Array.isArray(value)) {
22 return value.map(stableValue);
23 }
24 if (isPlainObject(value)) {
25 return Object.fromEntries(
26 Object.entries(value)
27 .sort(([a], [b]) => a.localeCompare(b))
28 .map(([key, nested]) => [key, stableValue(nested)]),
29 );
30 }
31 return value;
32};
33
34export const stableStringify = (value: unknown) =>
35 JSON.stringify(stableValue(normalizeNulls(value) ?? null));