| 1 | function isRecord(value: unknown): value is Record<string, unknown> { |
| 2 | return typeof value === "object" && value !== null && !Array.isArray(value); |
| 3 | } |
| 4 | |
| 5 | export 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 | } |