threshold / scripts /validate-build.mjs
citispire
Publish editable A/B climate studies and discussion briefs
ac47756
Raw
History Blame Contribute Delete
1.26 kB
import { readFileSync, existsSync } from "node:fs";
import assert from "node:assert/strict";
const html = readFileSync(new URL("../build/index.html", import.meta.url), "utf8");
const app = readFileSync(new URL("../build/app.js", import.meta.url), "utf8");
for (const file of [
"index.html",
"styles.css",
"app.js",
"model.mjs",
"study.mjs",
"favicon.svg",
"og.png",
]) {
assert.ok(existsSync(new URL("../build/" + file, import.meta.url)), "Missing build/" + file);
}
const ids = [...html.matchAll(/\bid="([^"]+)"/g)].map((match) => match[1]);
assert.equal(ids.length, new Set(ids).size, "Duplicate HTML ids");
for (const [, id] of app.matchAll(/\$\('([^']+)'\)/g))
assert.ok(ids.includes(id), "Missing UI target " + id);
assert.ok(!html.includes("threshold.skai-line.com"), "Unconfigured canonical domain");
assert.ok(
!readFileSync(new URL("../build/styles.css", import.meta.url), "utf8").includes("@import"),
"CSS needs an unshipped compilation step",
);
const manifest = JSON.parse(
readFileSync(new URL("../.openai/hosting.json", import.meta.url), "utf8"),
);
assert.equal(manifest.static.directory, "build");
console.log(
"Static release validated: self-contained files, UI targets, metadata and hosting configuration.",
);