1function isRecord(value: unknown): value is Record<string, unknown> {
2 return typeof value === "object" && value !== null && !Array.isArray(value);
3}
4
5export function stableStringify(value: unknown): string {
6 if (Array.isArray(value)) {
7 return `[${value.map(stableStringify).join(",")}]`;
8 }
9 if (isRecord(value)) {
10 return `{${Object.entries(value)
11 .filter(([, entryValue]) => entryValue !== undefined)
12 .sort(([left], [right]) => left.localeCompare(right))
13 .map(([key, entryValue]) => `${JSON.stringify(key)}:${stableStringify(entryValue)}`)
14 .join(",")}}`;
15 }
16 return JSON.stringify(value) ?? "null";
17}