From ab999c1c4327cbaff21e69bd9e7158e018a7b88c Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Mon, 28 Sep 2026 12:37:56 -0400 Subject: [PATCH] npm run dev:all starts the server and the site together Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG --- README.md | 2 +- package.json | 1 + scripts/dev-all.mjs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 scripts/dev-all.mjs diff --git a/README.md b/README.md index f2dda1d..701e307 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The full rules, as transcribed from the *Duel Purpose* fanzine, are in ```sh npm install -npm run dev +npm run dev:all # the duel server and the site together; Ctrl-C stops both ``` The hall at `/` offers two ways in: play the bot at `/play`, or duel a person. A duel between diff --git a/package.json b/package.json index 9020b69..f8ce445 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "type": "module", "scripts": { "dev": "vite dev", + "dev:all": "node scripts/dev-all.mjs", "build": "vite build", "preview": "vite preview", "prepare": "svelte-kit sync || echo ''", diff --git a/scripts/dev-all.mjs b/scripts/dev-all.mjs new file mode 100644 index 0000000..ac793ec --- /dev/null +++ b/scripts/dev-all.mjs @@ -0,0 +1,31 @@ +// The game server and the site together, for playing locally: one terminal, +// each line marked with its side, and Ctrl-C (or either one stopping) stops both. +import { spawn } from 'node:child_process'; + +const sides = [ + ['server', ['run', 'server']], + ['site', ['run', 'dev', '--', ...process.argv.slice(2)]] +]; +const children = sides.map(([name, args]) => { + const child = spawn('npm', args, { stdio: ['inherit', 'pipe', 'pipe'] }); + for (const stream of [child.stdout, child.stderr]) { + let rest = ''; + stream.on('data', (chunk) => { + const lines = (rest + chunk).split('\n'); + rest = lines.pop(); + for (const line of lines) console.log(`[${name}] ${line}`); + }); + } + child.on('exit', (code) => stop(code ?? 0)); + return child; +}); + +let stopping = false; +function stop(code) { + if (stopping) return; + stopping = true; + for (const c of children) if (c.exitCode === null) c.kill('SIGTERM'); + process.exitCode = code; +} +process.on('SIGINT', () => stop(0)); +process.on('SIGTERM', () => stop(0));