// Client build: TypeScript (+ per-component .html/.css) -> client/dist,
// via esbuild. Kept as a small hand-written script rather than a config
// file for a heavier tool (Vite, webpack) - this app's whole client is a
// couple thousand lines across a dozen files, esbuild's own bundling
// (including its built-in "collect CSS imported from JS into a sibling
// .css file" behavior) is all it needs, consistent with this project's
// general bias against dependencies it doesn't need.
//
// Usage: node build.mjs [--watch]
// npm run build -> one-off build (what server/Dockerfile's build stage runs)
// npm run watch -> rebuilds on save, for local dev (see README's
// Running locally section)
import * as esbuild from 'esbuild';
import { copyFileSync, mkdirSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const here = path.dirname(fileURLToPath(import.meta.url));
const outdir = path.join(here, 'dist');
mkdirSync(outdir, { recursive: true });
copyFileSync(path.join(here, 'src', 'index.html'), path.join(outdir, 'index.html'));
const buildOptions = {
entryPoints: [path.join(here, 'src', 'app.ts')],
outfile: path.join(outdir, 'app.js'),
bundle: true,
format: 'esm',
target: 'es2020',
sourcemap: true,
// Each component imports its own template as a raw string (`import html
// from './Foo.html'`) - see global.d.ts. CSS imports need no loader
// entry: esbuild bundles any CSS reached from a JS/TS entry point into a
// sibling app.css automatically.
loader: { '.html': 'text' }
};
const watch = process.argv.includes('--watch');
if (watch) {
const ctx = await esbuild.context(buildOptions);
await ctx.watch();
console.log('[watchparty-client] watching for changes...');
} else {
await esbuild.build(buildOptions);
console.log('[watchparty-client] built to client/dist');
}