| 312 | /** The first drivable page target's WebSocket URL, fetched through the forward |
| 313 | * (so the returned ws URL already points at the local port). */ |
| 314 | export const pageWsUrl = async (localPort: number): Promise<string> => { |
| 315 | const deadline = Date.now() + 60_000; |
| 316 | for (;;) { |
| 317 | const targets = (await fetch(`http://127.0.0.1:${localPort}/json/list`) |
| 318 | .then((r) => (r.ok ? r.json() : [])) |
| 319 | .catch(() => [])) as ReadonlyArray<CdpTarget>; |
| 320 | const page = targets.find((t) => t.type === "page" && t.webSocketDebuggerUrl); |
| 321 | if (page?.webSocketDebuggerUrl) return page.webSocketDebuggerUrl; |
| 322 | // oxlint-disable-next-line executor/no-error-constructor -- boundary: setup failure surfaced to the caller |
| 323 | if (Date.now() >= deadline) |
| 324 | throw new Error("no CDP page target (app not running with --remote-debugging-port?)"); |
| 325 | await sleep(500); |
| 326 | } |
| 327 | }; |