2026-07-23 13:29:32 -05:00
|
|
|
/**
|
|
|
|
|
* Development supervisor.
|
|
|
|
|
*
|
2026-08-19 10:38:50 -05:00
|
|
|
* Keeps the backend and generated stylesheets up to date while
|
2026-07-23 13:29:32 -05:00
|
|
|
* preserving a single foreground process for the repository launchers.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
const cwd = import.meta.dir.replace(/[\\/]scripts$/, "");
|
|
|
|
|
const env = {
|
|
|
|
|
...process.env,
|
|
|
|
|
NODE_ENV: "development",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function runPreparation(command: string): void {
|
|
|
|
|
const result = Bun.spawnSync(["bun", "run", command], {
|
|
|
|
|
cwd,
|
|
|
|
|
env,
|
|
|
|
|
stdin: "inherit",
|
|
|
|
|
stdout: "inherit",
|
|
|
|
|
stderr: "inherit",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!result.success) {
|
|
|
|
|
process.exit(result.exitCode || 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
runPreparation("build:css");
|
2026-08-01 01:54:07 -05:00
|
|
|
runPreparation("build:web");
|
2026-07-23 13:29:32 -05:00
|
|
|
runPreparation("vendor");
|
|
|
|
|
|
|
|
|
|
const backend = Bun.spawn(["bun", "--watch", "src/index.ts"], {
|
|
|
|
|
cwd,
|
|
|
|
|
env,
|
|
|
|
|
stdin: "inherit",
|
|
|
|
|
stdout: "inherit",
|
|
|
|
|
stderr: "inherit",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const styles = Bun.spawn(["bun", "run", "watch:css"], {
|
|
|
|
|
cwd,
|
|
|
|
|
env,
|
|
|
|
|
stdin: "inherit",
|
|
|
|
|
stdout: "inherit",
|
|
|
|
|
stderr: "inherit",
|
|
|
|
|
});
|
|
|
|
|
|
2026-08-19 10:38:50 -05:00
|
|
|
const uiStyles = Bun.spawn(["bun", "run", "watch:ui"], {
|
|
|
|
|
cwd,
|
|
|
|
|
env,
|
|
|
|
|
stdin: "inherit",
|
|
|
|
|
stdout: "inherit",
|
|
|
|
|
stderr: "inherit",
|
|
|
|
|
});
|
|
|
|
|
|
2026-08-01 01:54:07 -05:00
|
|
|
const web = Bun.spawn(["bun", "run", "watch:web"], {
|
|
|
|
|
cwd,
|
|
|
|
|
env,
|
|
|
|
|
stdin: "inherit",
|
|
|
|
|
stdout: "inherit",
|
|
|
|
|
stderr: "inherit",
|
|
|
|
|
});
|
|
|
|
|
|
2026-07-23 13:29:32 -05:00
|
|
|
let stopping = false;
|
|
|
|
|
|
|
|
|
|
function stop(exitCode = 0): void {
|
|
|
|
|
if (stopping) return;
|
|
|
|
|
stopping = true;
|
|
|
|
|
backend.kill();
|
|
|
|
|
styles.kill();
|
2026-08-19 10:38:50 -05:00
|
|
|
uiStyles.kill();
|
2026-08-01 01:54:07 -05:00
|
|
|
web.kill();
|
2026-07-23 13:29:32 -05:00
|
|
|
process.exitCode = exitCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process.on("SIGINT", () => stop(130));
|
|
|
|
|
process.on("SIGTERM", () => stop(143));
|
|
|
|
|
|
|
|
|
|
const result = await Promise.race([
|
|
|
|
|
backend.exited.then((exitCode) => ({ process: "backend", exitCode })),
|
|
|
|
|
styles.exited.then((exitCode) => ({ process: "Tailwind watcher", exitCode })),
|
2026-08-19 10:38:50 -05:00
|
|
|
uiStyles.exited.then((exitCode) => ({ process: "UI stylesheet watcher", exitCode })),
|
2026-08-01 01:54:07 -05:00
|
|
|
web.exited.then((exitCode) => ({ process: "browser TypeScript watcher", exitCode })),
|
2026-07-23 13:29:32 -05:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
if (!stopping) {
|
|
|
|
|
console.error(`[dev] ${result.process} exited with code ${result.exitCode}`);
|
|
|
|
|
stop(result.exitCode || 1);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 10:38:50 -05:00
|
|
|
await Promise.allSettled([backend.exited, styles.exited, uiStyles.exited, web.exited]);
|