()
| 124 | } |
| 125 | |
| 126 | async function startViteChild(): Promise<ViteChild> { |
| 127 | const vitePort = await allocatePort(); |
| 128 | const cwd = resolve(import.meta.dirname, ".."); |
| 129 | const env = { ...process.env }; |
| 130 | delete env.PORT; |
| 131 | // `bunx --bun vite` runs vite under Bun, matching the `dev:vite` script |
| 132 | // already in apps/local. --strictPort keeps the URL we hand back stable. |
| 133 | const child: Subprocess = Bun.spawn( |
| 134 | [ |
| 135 | "bunx", |
| 136 | "--bun", |
| 137 | "vite", |
| 138 | "dev", |
| 139 | "--port", |
| 140 | String(vitePort), |
| 141 | "--strictPort", |
| 142 | "--host", |
| 143 | "127.0.0.1", |
| 144 | ], |
| 145 | { |
| 146 | cwd, |
| 147 | // EXECUTOR_DEV_VITE_PORT — vite.config reads this and points the |
| 148 | // HMR client at vite's real port. The browser loads HTML through |
| 149 | // the daemon proxy but opens the HMR WebSocket directly to vite, |
| 150 | // sidestepping the daemon's lack of WS proxying. |
| 151 | env: { |
| 152 | ...env, |
| 153 | EXECUTOR_DEV_VITE_PORT: String(vitePort), |
| 154 | }, |
| 155 | stdout: "inherit", |
| 156 | stderr: "inherit", |
| 157 | }, |
| 158 | ); |
| 159 | |
| 160 | const url = `http://127.0.0.1:${vitePort}`; |
| 161 | const deadline = Date.now() + 30_000; |
| 162 | while (Date.now() < deadline) { |
| 163 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: probing a child process that may not be listening yet |
| 164 | try { |
| 165 | const r = await fetch(`${url}/`, { redirect: "manual" }); |
| 166 | if (r.status < 500) { |
| 167 | await r.body?.cancel(); |
| 168 | return { |
| 169 | url, |
| 170 | stop: async () => { |
| 171 | child.kill(); |
| 172 | await child.exited; |
| 173 | }, |
| 174 | }; |
| 175 | } |
| 176 | await r.body?.cancel(); |
| 177 | } catch { |
| 178 | // not up yet |
| 179 | } |
| 180 | if (child.exitCode !== null) { |
| 181 | // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: child process aborted before becoming ready |
| 182 | throw new Error(`vite dev exited with code ${child.exitCode} before becoming ready`); |
| 183 | } |
no test coverage detected