fix(tooling): resolve Bun executable on Windows

This commit is contained in:
hehuaiyu
2026-09-04 14:34:34 +08:00
parent 0d8709a72e
commit 0dafc512a6
11 changed files with 337 additions and 18 deletions
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env node
import { spawn } from 'node:child_process';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { resolveBunExecutable } from '../../../scripts/lib/bun-executable.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const webRoot = path.resolve(__dirname, '..');
export function createDevServerWatchCommand(options = {}) {
const platform = options.platform ?? process.platform;
const env = options.env ?? process.env;
const bunExecutable = options.bunExecutable ?? resolveBunExecutable({ env, platform });
const configuredPort = env.OPENCHAMBER_PORT?.trim();
const port = configuredPort || '3001';
if (!/^\d+$/.test(port) || Number(port) < 1 || Number(port) > 65535) {
throw new Error(`Invalid OPENCHAMBER_PORT: ${port}`);
}
return {
command: bunExecutable,
args: platform === 'win32'
? ['--watch', 'server/index.js', '--port', port]
: [
'x',
'nodemon',
'--watch',
'server',
'--ext',
'js',
'--exec',
`bun server/index.js --port ${port}`,
],
spawnOptions: {
cwd: webRoot,
stdio: 'inherit',
env: {
...env,
OPENCHAMBER_RELAY_HOST: env.OPENCHAMBER_RELAY_HOST || 'off',
},
windowsHide: true,
},
};
}
export function runDevServerWatch(options = {}) {
const runner = options.runner ?? spawn;
const { command, args, spawnOptions } = createDevServerWatchCommand(options);
const child = runner(command, args, spawnOptions);
child.on('error', (error) => {
console.error('[dev:web:server] Failed to start server watcher:', error);
process.exitCode = 1;
});
child.on('exit', (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
return;
}
process.exitCode = code ?? 1;
});
return child;
}
const isMain = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
if (isMain) {
try {
runDevServerWatch();
} catch (error) {
console.error('[dev:web:server] Unable to configure server watcher:', error);
process.exitCode = 1;
}
}
@@ -0,0 +1,60 @@
import { describe, expect, it } from 'vitest';
import { createDevServerWatchCommand } from './dev-server-watch.mjs';
describe('createDevServerWatchCommand', () => {
it('uses the package default port and disables relay hosting by default', () => {
const command = createDevServerWatchCommand({
platform: 'win32',
env: {},
bunExecutable: '/opt/bun/bin/bun',
});
expect(command.command).toBe('/opt/bun/bin/bun');
expect(command.args).toEqual(['--watch', 'server/index.js', '--port', '3001']);
expect(command.spawnOptions.env.OPENCHAMBER_RELAY_HOST).toBe('off');
expect(command.spawnOptions.windowsHide).toBe(true);
});
it('passes the configured port and relay host to the Bun watcher', () => {
const command = createDevServerWatchCommand({
platform: 'win32',
env: {
OPENCHAMBER_PORT: '58992',
OPENCHAMBER_RELAY_HOST: 'relay.example.test',
},
bunExecutable: 'C:\\Tools\\Bun\\bun.exe',
});
expect(command.args).toEqual(['--watch', 'server/index.js', '--port', '58992']);
expect(command.spawnOptions.env.OPENCHAMBER_RELAY_HOST).toBe('relay.example.test');
});
it('rejects an invalid configured port before spawning', () => {
expect(() => createDevServerWatchCommand({
platform: 'win32',
env: { OPENCHAMBER_PORT: 'not-a-port' },
bunExecutable: 'bun',
})).toThrow(/Invalid OPENCHAMBER_PORT/);
});
it('preserves the nodemon watcher command outside Windows', () => {
const command = createDevServerWatchCommand({
platform: 'linux',
env: { OPENCHAMBER_PORT: '4200' },
bunExecutable: '/opt/bun/bin/bun',
});
expect(command.command).toBe('/opt/bun/bin/bun');
expect(command.args).toEqual([
'x',
'nodemon',
'--watch',
'server',
'--ext',
'js',
'--exec',
'bun server/index.js --port 4200',
]);
});
});