#!/usr/bin/env node // ============================================================ // build-client.mjs — Compiles client/**/*.ts to public/dist/. // // Strangler-fig pattern: TS modules live under client/, legacy // IIFE files stay under public/js/ until each is migrated. // Each top-level .ts file in client/ becomes one ES-module bundle // in public/dist/ that index.html can load via: // // // Run: // npm run build:client # one-shot // npm run build:client -- --watch # rebuild on change // ============================================================ import { build, context } from 'esbuild'; import { readdirSync, mkdirSync, existsSync } from 'node:fs'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const PROJECT_ROOT = resolve(__dirname, '..'); const SRC = resolve(PROJECT_ROOT, 'client'); const OUT = resolve(PROJECT_ROOT, 'public/dist'); const watch = process.argv.includes('--watch'); if (!existsSync(SRC)) { console.error(`[build-client] Source dir does not exist: ${SRC}`); process.exit(1); } mkdirSync(OUT, { recursive: true }); // Explicit entry list — every other .ts file in client/ is a sub-module // imported by an entry. Add new entries here when a feature truly needs // its own separate bundle (different DOM lifecycle, lazy-loaded route, // etc.). For most modernization work, just import into main.ts. const ENTRIES = [ 'main.ts', ]; const entryFiles = ENTRIES.map(name => { const p = resolve(SRC, name); if (!existsSync(p)) { console.error(`[build-client] Entry file does not exist: ${p}`); process.exit(1); } return p; }); const buildOpts = { entryPoints: entryFiles, outdir: OUT, bundle: true, format: 'esm', target: 'es2022', platform: 'browser', sourcemap: true, minify: !watch, // unminified in watch mode for easier debugging logLevel: 'info', }; if (watch) { const ctx = await context(buildOpts); await ctx.watch(); console.log('[build-client] Watching for changes…'); } else { await build(buildOpts); console.log(`[build-client] Built ${entryFiles.length} entry point(s) → ${OUT}`); }