/** * The built page, off disk. Vite compiles src/tools/control-room/ui into * ui/dist; this serves it, and says so plainly when the build has not been run * rather than answering a blank page. */ import { spawnSync } from "node:child_process"; import { existsSync } from "node:fs"; import { isAbsolute, relative, resolve } from "node:path"; const UI_DIST = resolve(import.meta.dir, "ui", "dist"); export const BUILD_COMMAND = "bun run build:ui"; export function isBuilt(): boolean { return existsSync(resolve(UI_DIST, "index.html")); } /** * A clone has vite; a published install has the prepacked dist and never needs * it. Either way the page is there by the time the server answers. */ export function buildPage(): boolean { const repoRoot = resolve(import.meta.dir, "..", "..", ".."); // node_modules/.bin/vite is a shell shim that Windows cannot spawn directly; // the package's own JS entry runs the same build under any runtime. const vite = resolve(repoRoot, "node_modules", "vite", "bin", "vite.js"); if (!existsSync(vite)) return false; const built = spawnSync(process.execPath, [vite, "build"], { cwd: resolve(import.meta.dir, "ui"), encoding: "utf-8", }); return built.status === 0 && isBuilt(); } function unbuiltPage(): Response { return new Response( `
The control room's assets are a build artifact rather than source. Run:
` + `${BUILD_COMMAND}`,
{ status: 503, headers: { "content-type": "text/html; charset=utf-8" } }
);
}
export function indexHtml(): Response {
if (!isBuilt()) return unbuiltPage();
return new Response(Bun.file(resolve(UI_DIST, "index.html")), {
headers: { "content-type": "text/html; charset=utf-8" },
});
}
/**
* Only what the build emitted, resolved inside dist — a request that climbs out
* of it with `..` is a miss, not a file read.
*/
export function staticAsset(pathname: string): Response | null {
const target = resolve(UI_DIST, `.${pathname}`);
if (!isInsideDist(target)) return null;
return existsSync(target) ? new Response(Bun.file(target)) : null;
}
/** Compared as paths, not strings — a separator differs by platform. */
function isInsideDist(target: string): boolean {
const rel = relative(UI_DIST, target);
return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
}