fix(client): fix dev mode hanging on Windows (#1051)

The `stdin: 'ignore'` option was not working because spawn-rx expects
an Observable for its stdin option, not a string. This caused tsx watch
and vite dev server to hang waiting for stdin on Windows.

Use Node's native `stdio: ['ignore', 'pipe', 'pipe']` option instead,
which spawn-rx passes through correctly to child_process.spawn.

Fixes #550

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ola Hungerford 2026-02-03 07:41:38 -07:00 • committed by GitHub
commit fc7897f380
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -56,9 +56,11 @@ async function startDevServer(serverOptions) {
echoOutput: true,
};
// For Windows, we need to use stdin: 'ignore' to simulate < NUL
// For Windows, we need to ignore stdin to simulate < NUL
// spawn-rx's 'stdin' option expects an Observable, not 'ignore'
// Use Node's stdio option instead
if (isWindows) {
spawnOptions.stdin = "ignore";
spawnOptions.stdio = ["ignore", "pipe", "pipe"];
}
const server = spawn(serverCommand, serverArgs, spawnOptions);
@ -140,13 +142,21 @@ async function startDevClient(clientOptions) {
const clientCommand = "npx";
const host = process.env.HOST || "localhost";
const clientArgs = ["vite", "--port", CLIENT_PORT, "--host", host];
const isWindows = process.platform === "win32";
const client = spawn(clientCommand, clientArgs, {
const spawnOptions = {
cwd: resolve(__dirname, ".."),
env: { ...process.env, CLIENT_PORT },
signal: abort.signal,
echoOutput: true,
});
};
// For Windows, we need to ignore stdin to prevent hanging
if (isWindows) {
spawnOptions.stdio = ["ignore", "pipe", "pipe"];
}
const client = spawn(clientCommand, clientArgs, spawnOptions);
const url = getClientUrl(
CLIENT_PORT,