()
| 61 | } |
| 62 | |
| 63 | async function startDevWebBridge() { |
| 64 | await buildDevWebBridge() |
| 65 | |
| 66 | const child = spawn(electronPath, [bridgeBuildPath], { |
| 67 | cwd: projectRoot, |
| 68 | env: { |
| 69 | ...process.env, |
| 70 | HOWCODE_REPO_ROOT: devRepoRoot, |
| 71 | HOWCODE_DEV_WEB_BRIDGE_HOST: DEV_SERVER_HOST, |
| 72 | HOWCODE_DEV_WEB_BRIDGE_PORT: '0', |
| 73 | HOWCODE_DEV_WEB_BRIDGE_TOKEN: bridgeToken, |
| 74 | ELECTRON_RUN_AS_NODE: '1', |
| 75 | }, |
| 76 | stdio: ['ignore', 'pipe', 'pipe'], |
| 77 | }) |
| 78 | |
| 79 | child.stderr?.on('data', (chunk) => { |
| 80 | process.stderr.write(chunk) |
| 81 | }) |
| 82 | |
| 83 | return new Promise<{ child: ChildProcess; port: number }>((resolve, reject) => { |
| 84 | let stdoutBuffer = '' |
| 85 | let settled = false |
| 86 | |
| 87 | const fail = (error: Error) => { |
| 88 | if (settled) { |
| 89 | return |
| 90 | } |
| 91 | settled = true |
| 92 | reject(error) |
| 93 | } |
| 94 | |
| 95 | child.once('error', fail) |
| 96 | child.once('exit', (code, signal) => { |
| 97 | if (!settled) { |
| 98 | fail(new Error(`dev:web bridge exited before startup (code=${code}, signal=${signal}).`)) |
| 99 | return |
| 100 | } |
| 101 | |
| 102 | console.error(`dev:web bridge exited unexpectedly (code=${code}, signal=${signal}).`) |
| 103 | void shutdown(1) |
| 104 | }) |
| 105 | |
| 106 | child.stdout?.on('data', (chunk) => { |
| 107 | const text = chunk.toString() |
| 108 | stdoutBuffer += text |
| 109 | process.stdout.write(text) |
| 110 | |
| 111 | const lines = stdoutBuffer.split('\n') |
| 112 | stdoutBuffer = lines.pop() ?? '' |
| 113 | |
| 114 | for (const line of lines) { |
| 115 | if (!line.startsWith('HOWCODE_DEV_WEB_BRIDGE_READY ')) { |
| 116 | continue |
| 117 | } |
| 118 | |
| 119 | const payload = JSON.parse(line.slice('HOWCODE_DEV_WEB_BRIDGE_READY '.length)) as { |
| 120 | port?: number |
no test coverage detected