language: TypeScript
1.01 KB / 37 lines / 32 loc
export type PageSource = {
type: "page";
url: string;
};
export type ZulipSource = {
type: "zulip";
messageIds: number[];
};
export type Source = PageSource | ZulipSource;
type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
function deterministicSerialize(val: JSONValue): string {
if (val === null) {
return "null";
} else if (Array.isArray(val)) {
return `[${val.map(deterministicSerialize).join(",")}]`;
} else if (typeof val === "object") {
let s = "{";
for (const key of Object.keys(val).sort()) {
if (s !== "{") s += ",";
s += `${key}:${deterministicSerialize(val[key]!)}`;
}
return s + "}";
} else {
return JSON.stringify(val);
}
}
export async function deriveUid(source: Source) {
const serialized: string = deterministicSerialize(source);
const encoded = new TextEncoder().encode(serialized);
const uid: ArrayBuffer = await globalThis.crypto.subtle.digest("SHA-256", encoded);
return { uid, serialized };
}