// esbuild build for @hive/swarm-ui (project-bootstrap scope). Output // layout (`dist/`): // // dist/index.html served at GET / // dist/static/main.js served at /static/main.js (ESM bundle, // Preact + wouter-preact) // dist/static/main.js.map source map sibling // dist/static/main.css every component's own `import // './Foo.css'` (Shell.css, Panel.css, …), // folded by esbuild into one companion // output alongside main.js — no separate // build step, this falls out of bundling // main.tsx with `bundle: true` // dist/static/colors.css served at /static/colors.css // dist/static/theme.css served at /static/theme.css // dist/static/swarm-ui.css served at /static/swarm-ui.css — just the // shared base reset now (@import resolved // from @hive/shared), NOT component styles // dist/manifest.webmanifest served at /manifest.webmanifest (PWA) // dist/sw.js served at /sw.js (PWA) — plain JS, no // esbuild pass needed (see its own // top comment for why); copied as-is. // // PWA icons (icon-192.png/icon-512.png/icon-512-maskable.png) are NOT // produced here — like favicon.svg, they're rasterized from // branding/*.svg and copied in by nix/packages/swarm-ui.nix's // installPhase, outside the npm tree this script builds. A plain `npm // run build` here has no `/icon-*.png`, same as it's always had no // `/favicon.svg`. // // Not yet wired into any Rust binary's `ServeDir` — swarm-controller // only serves `/health` today (see swarm-controller/README.md); this // just makes `dist/` buildable so nix/packages/swarm-ui.nix has // something to package. `.tsx` → JS: esbuild transpiles TypeScript // natively (types stripped, not checked) — run `npm run typecheck` // (plain `tsc --noEmit`) separately for real type errors; not yet // wired into CI. import { build } from "esbuild"; import { mkdirSync, copyFileSync, rmSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const here = dirname(fileURLToPath(import.meta.url)); const src = (p) => resolve(here, "src", p); const dist = (p) => resolve(here, "dist", p); const staticDir = (p) => resolve(here, "dist", "static", p); rmSync(dist(""), { recursive: true, force: true }); mkdirSync(staticDir(""), { recursive: true }); await build({ entryPoints: [src("main.tsx")], outfile: staticDir("main.js"), bundle: true, format: "esm", platform: "browser", target: ["es2022"], sourcemap: true, logLevel: "info", jsx: "automatic", jsxImportSource: "preact", }); for (const entry of ["colors.css", "theme.css", "swarm-ui.css"]) { await build({ entryPoints: [src(entry)], outfile: staticDir(entry), bundle: true, loader: { ".css": "css" }, logLevel: "info", }); } copyFileSync(src("index.html"), dist("index.html")); copyFileSync(src("manifest.webmanifest"), dist("manifest.webmanifest")); copyFileSync(src("sw.js"), dist("sw.js")); console.log("swarm-ui build ok →", dist(""));