// Runs every check. Exits non-zero if any assertion failed. // // nix develop -c node checks/run.mjs // // These sit beside the Go tests rather than replacing them: the server has // `go test`, and this is the frontend's half — the arithmetic behind the // charts, the structure of the markup, and the width budgets that no one here // can see. It needs no build step and no dependencies; node is already in the // devShell for `node --check`. import { execFileSync } from "node:child_process"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; import { readdirSync } from "node:fs"; const here = dirname(fileURLToPath(import.meta.url)); const root = join(here, ".."); let failed = 0; // The frontend has no build step, so a syntax error would otherwise only show // up in a browser nobody here is running. for (const file of ["app.js", "sw.js"]) { try { execFileSync(process.execPath, ["--check", join(root, "src", file)], { stdio: "pipe" }); console.log(` ok src/${file} parses`); } catch (e) { console.log(` FAIL src/${file}\n${e.stderr?.toString() ?? e.message}`); failed++; } } try { JSON.parse(readdirSync(join(root, "src")).includes("changelog.json") ? (await import("node:fs")).readFileSync(join(root, "src", "changelog.json"), "utf8") : "[]"); console.log(" ok src/changelog.json parses"); } catch (e) { console.log(` FAIL src/changelog.json: ${e.message}`); failed++; } const suites = readdirSync(here) .filter(f => f.endsWith(".mjs") && !["run.mjs", "extract.mjs", "assert.mjs"].includes(f)) .sort(); for (const file of suites) { const mod = await import(join(here, file)); failed += mod.default ?? 0; } console.log(failed === 0 ? `\nall checks passed (${suites.length} suites)` : `\n${failed} assertion(s) FAILED`); process.exit(failed === 0 ? 0 : 1);