import console from "node:console"; import { createHash } from "node:crypto"; import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs"; import { dirname, join, relative, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import process from "node:process"; const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const uiRoot = join(root, "packages", "ui"); const baseline = join(root, "docs", "ui-visual-contract-0.8.json"); const files = [ join(uiRoot, "ui.css"), ...readdirSync(join(uiRoot, "components")) .filter((file) => file.endsWith(".wrn")) .map((file) => join(uiRoot, "components", file)), ...readdirSync(join(uiRoot, "styles")) .filter((file) => file.endsWith(".wrn")) .map((file) => join(uiRoot, "styles", file)), ].sort(); const artifacts = Object.fromEntries( files.map((file) => [ relative(root, file).replace(/\\/g, "/"), createHash("sha256").update(readFileSync(file)).digest("hex"), ]), ); const output = `${JSON.stringify({ schemaVersion: 1, releaseLine: "0.8", artifacts }, null, 2)}\n`; if (process.argv.includes("--write")) { writeFileSync(baseline, output, "utf8"); console.log(`Wrote ${relative(root, baseline)}`); } else { if (!existsSync(baseline) || readFileSync(baseline, "utf8") !== output) { throw new Error( "UI visual contract changed. Review rendered components, then run `bun run generate:ui-visual`.", ); } console.log(`UI visual contract matches ${files.length} CSS/component artifacts.`); }