Files

65 lines
1.8 KiB
JavaScript

/**
* Run the server and the web dev server together, with one Ctrl+C to stop both.
*
* A tiny spawner instead of a dependency like concurrently: two fewer packages to
* install, and it behaves predictably on Windows, which is where this demo runs.
*/
import { spawn } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
const targets = [
{ name: 'server', args: ['run', 'dev', '-w', 'server'], color: '\x1b[36m' },
{ name: 'web', args: ['run', 'dev', '-w', 'web'], color: '\x1b[35m' },
];
const children = [];
let shuttingDown = false;
for (const t of targets) {
const child = spawn(npm, t.args, { cwd: root, shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
children.push(child);
const prefix = `${t.color}[${t.name}]\x1b[0m `;
const pipe = (stream) => {
let buf = '';
stream.on('data', (chunk) => {
buf += chunk.toString();
let i;
while ((i = buf.indexOf('\n')) >= 0) {
const line = buf.slice(0, i);
buf = buf.slice(i + 1);
if (line.trim()) process.stdout.write(prefix + line + '\n');
}
});
};
pipe(child.stdout);
pipe(child.stderr);
child.on('exit', (code) => {
if (shuttingDown) return;
console.log(`${prefix}exited with code ${code}. Shutting down.`);
shutdown();
});
}
function shutdown() {
if (shuttingDown) return;
shuttingDown = true;
for (const c of children) {
if (!c.killed) c.kill();
}
setTimeout(() => process.exit(0), 300);
}
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
console.log('\n Digital twin demo starting…');
console.log(' Dashboard: \x1b[1mhttp://localhost:5173\x1b[0m');
console.log(' API: http://localhost:8787\n');