jmou/yakatak
git clone https://github.com/jmou/yakatak.git
git clone git@github.com:jmou/yakatak.git
Loading…
(top)/shared/src/source.ts
language: TypeScript
1.01 KB / 37 lines / 32 loc
History
View raw
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 };
}