/**
* SUETA_TS=1 node test/vectors/generate.mjs
*
* Golden-vector extractor for everything chat owns above the vendored p2p lib.
*
* Run against the TypeScript implementation while it was still canon, per
* dev/docs/CLJS.md: "splice the real modules into a harness rather than
* transcribing their logic into a generator". harness/ts.mjs esbuild-bundles
* `src/**.ts` once and hands the REAL classes over; hard-private members come in
* through a mechanically injected `__t` bag, so not one line of logic is retyped.
*
* node test/vectors/generate.mjs # writes test/vectors/*.json
*
* The lib layer below `app/` is NOT re-extracted here: chat's
* lib/{access,crypto,descriptor,encryption,protocol,turn}.ts are byte-identical
* to rooms-kit's pre-CLJS ancestors and lib/{log,net,orbit-identity}.ts differ
* only by the three sanctioned browser deltas, so those fixtures are reused
* verbatim as `vectors/rk-*.json` and re-verified against THIS TypeScript by
* `test/vectors.test.mjs` / `test/machines.test.mjs` in `SUETA_TS=1` mode.
*
* Not re-runnable after the TypeScript is retired (it needs esbuild, which the
* CLJS install drops). Kept in the tree as the provenance record.
*/
import { writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { installDom, localStorageStub } from "../harness/dom.mjs";
installDom();
// the SAME normalised module map the tests use, so the generator and the
// checker drive identical call shapes
const { mods, priv, TS_MODE } = await import("../helpers/load.mjs");
if (!TS_MODE) throw new Error("run with SUETA_TS=1: fixtures come from the TypeScript, never from the port");
const M = await mods();
const { chatOpsScript, projectorScript, trustScript, roomsScript, migrateScript,
storageScript, historyScript, mailboxScript, callScript } = await import("../helpers/app-fakes.mjs");
const OUT = dirname(fileURLToPath(import.meta.url));
const write = (name, data) => {
writeFileSync(join(OUT, `${name}.json`), `${JSON.stringify(data, null, 2)}\n`);
console.log(`wrote ${name}.json`);
};
/* ------------------------------------------------------------------ config -- */
write("config", {
appSalt: M.APP_SALT,
ns: M.NS,
// Every persistent name the app ever writes. A change here orphans existing
// users' identity seed, TOFU bindings, room list and block store.
keys: ["id", "id-prev", "name", "notify", "trust", "rooms", "rooms-gone", "lang", "storage-migrated", "room"].map(
(k) => [k, M.nsKey(k)],
),
perRoomKeys: ["mbx-cursor", "mbx-queue", "mbx-sent", "mbx-retry", "mbx-ident", "migrated"].map((k) => [
k,
M.nsKey(`${k}:ROOMID`),
]),
dbs: ["blocks", "data"].map((d) => [d, M.nsDb(d)]),
});
/* --------------------------------------------------------------- wire bytes -- */
write("logops", await chatOpsScript({ ...M, priv }));
write("call", await callScript({ ...M, priv }));
/* ---------------------------------------------------------------- projector -- */
write("projector", await projectorScript({ ...M, priv }));
/* ----------------------------------------------------------------- app state -- */
write("trust", await trustScript({ ...M, localStorageStub }));
write("rooms", await roomsScript({ ...M, localStorageStub }));
write("migrate", await migrateScript({ ...M, localStorageStub }));
write("storage", await storageScript({ ...M, localStorageStub }));
write("history", await historyScript({ ...M }));
write("mailbox", await mailboxScript({ ...M, priv, localStorageStub }));
/* ---------------------------------------------------------------------- i18n -- */
{
const langs = ["en", "ro", "hu"];
const out = { keys: {}, snapshot: {} };
for (const lang of langs) {
out.keys[lang] = M.catalogKeys(lang);
// byte snapshot: the whole catalog, so a single changed character in a
// Romanian or Hungarian string fails the suite (the transliteration gate)
out.snapshot[lang] = Object.fromEntries(out.keys[lang].map((k) => [k, M.catalogRaw(lang, k)]));
}
// the plural sites, spelled out — Romanian's few/other split and Hungarian's
// uninflected numerals must survive the port
out.plurals = {};
for (const k of out.keys.en) {
const shapes = Object.fromEntries(langs.map((l) => [l, M.catalogMsg(l, k)]));
if (langs.some((l) => Array.isArray(shapes[l]))) out.plurals[k] = shapes;
}
write("i18n", out);
}
console.log("done");
process.exit(0);