Files
zernie__vigiles/scripts/build-report.mjs
Claude 878111f794 refactor(report): extract shared @vigiles/report-view via npm workspaces
Stage 1 of the hosted-demo work: the audit report view must be a genuinely
shared package so report/, site/, and the future in-browser demo all render the
SAME AuditReport JSON through the SAME components — never a screenshot, never a
duplicated/relative-cross-imported component (the landing-site skill's shared-UI
invariant, and the prerequisite Fable's demo brief names).

- New packages/report-view (@vigiles/report-view, source-only/private): the
  presentational components, the AuditReport schema (mirrors src/audit-report.ts,
  pinned by src/audit-report.test.ts), band tokens, and theme.css. report/src/*
  moved here (git renames); internal @/ imports rewritten relative.
- report/ consumes it; report/src is just the app shell (main.tsx + index.css,
  which @sources the package + @imports its theme — Tailwind v4 ignores node_modules).

Wired as npm WORKSPACES (root workspaces:[packages/*,report,site]) so deps hoist
to root and resolve with zero config (no preserveSymlinks). Four aligned changes
kept the published vigiles package's CI green: root lockfile regen, pages.yml
builds site via the workspace (cd site && npm ci would fail with no per-package
lock), build-report.mjs checks root node_modules for its install-guard, and the
per-package lockfiles are removed. Verified with a clean-room
rm -rf node_modules && npm ci && npm run build (+ tsc, fmt, site build, report
renders styled). Design + Stage-2 demo brief in
research/report-view-and-hosted-demo.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 03:49:54 +00:00

48 lines
2.0 KiB
JavaScript

/**
* Build the React/shadcn audit report (report/, Vite + vite-plugin-singlefile) to
* ONE self-contained file and copy it to dist/audit-report.template.html — the
* template the CLI fills with an AuditReport. Run after `tsc` by `npm run build`.
*
* Fails LOUD (exit 1) if it can't build — the React report is part of the product,
* so a build/release must not silently ship without the template. It auto-installs
* report/ deps if missing (first run / CI), so a normal `npm run build` Just Works
* where the npm registry is reachable.
*/
import { existsSync, copyFileSync, mkdirSync } from "node:fs";
import { execSync } from "node:child_process";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const reportDir = resolve(root, "report");
const built = resolve(reportDir, "dist", "index.html");
const out = resolve(root, "dist", "audit-report.template.html");
try {
// npm workspaces hoist deps to the ROOT node_modules, so ensure the workspace
// deps are installed (a fresh clone / first local run) at the root before
// building the report workspace. In CI, `npm ci` already ran, so this is
// skipped. `vite` is a report+site devDep, hoisted — a reliable presence probe.
if (!existsSync(resolve(root, "node_modules", "vite"))) {
console.log("[build-report] installing workspace deps…");
execSync("npm install --no-audit --no-fund", {
cwd: root,
stdio: "inherit",
});
}
execSync("npm run build", { cwd: reportDir, stdio: "inherit" });
mkdirSync(dirname(out), { recursive: true });
copyFileSync(built, out);
console.log("[build-report] → dist/audit-report.template.html");
} catch (e) {
console.error(
"[build-report] FAILED to build the audit report template: " +
(e instanceof Error ? e.message : String(e)),
);
console.error(
"[build-report] the React report is part of the product — fix the report/ build " +
"(needs the npm registry for first install).",
);
process.exit(1);
}