@orkestrel/browser 0.0.17 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/index.cjs +1 -1
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +1 -1
- package/dist/src/core/index.d.ts +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js.map +1 -1
- package/package.json +14 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/server/constants.ts","../../../src/server/errors.ts","../../../src/server/helpers.ts","../../../src/server/transports/WebSocketCDPTransport.ts","../../../src/server/writers/FileBrowserWriter.ts","../../../src/server/factories.ts","../../../src/server/Browser.ts"],"sourcesContent":["import type { BrowserEngine } from './types.js'\n\n// === CDP discovery\n\n/**\n * Sets the default CDP port probed for an existing browser and used for launches, `9222`.\n */\nexport const BROWSER_DEFAULT_CDP_PORT = 9222\n\n/**\n * Sets the default host probed for an existing browser and used for launches, `'127.0.0.1'`,\n * which avoids `localhost` resolving to `::1` when Chromium binds `127.0.0.1`.\n */\nexport const BROWSER_DEFAULT_HOST = '127.0.0.1'\n\n/** Names the protocol prefix for CDP discovery requests, `'http'`. */\nexport const BROWSER_CDP_PROTOCOL = 'http'\n\n/**\n * Names the path appended to the CDP host to fetch version metadata, `'/json/version'`, which\n * is where endpoint discovery reads.\n */\nexport const BROWSER_CDP_VERSION_PATH = '/json/version'\n\n/**\n * Names the path appended to the CDP host to list open targets — pages, workers, and every\n * other target category Chromium reports — `'/json/list'`.\n */\nexport const BROWSER_CDP_LIST_PATH = '/json/list'\n\n// === Browser launch\n\n/** Lists the flags always passed to a launched browser process, alongside the caller's own. */\nexport const BROWSER_LAUNCH_ARGS: readonly string[] = Object.freeze([\n\t'--no-first-run',\n\t'--no-default-browser-check',\n])\n\n/**\n * Names the flag that enables headless mode on a launched browser process, `'--headless=new'`.\n */\nexport const BROWSER_HEADLESS_ARG = '--headless=new'\n\n/**\n * Names the prefix for isolated browser profiles created beneath the operating-system temp\n * directory, `'orkestrel-browser-'`.\n */\nexport const BROWSER_PROFILE_PREFIX = 'orkestrel-browser-'\n\n/**\n * Bounds each launched-process exit window during TERM-to-KILL teardown at `3_000`\n * milliseconds.\n */\nexport const BROWSER_KILL_GRACE_MS = 3_000\n\n/**\n * Bounds the `discover: false` port-occupancy probe before launching at `200` milliseconds,\n * which is short because the probe only needs to detect an already-listening CDP endpoint\n * rather than perform full discovery.\n */\nexport const BROWSER_PORT_PROBE_TIMEOUT_MS = 200\n\n/**\n * Defers once for `50` milliseconds when a transport loss is observed on an owned process,\n * giving a near-simultaneous process-exit event, which libuv may reap slightly later than the\n * socket close, first say over the diagnosis.\n */\nexport const BROWSER_TRANSPORT_LOSS_DEFER_MS = 50\n\n/**\n * Names the machine-readable error-context cause for an owned browser process exiting,\n * `'process-exit'`.\n */\nexport const BROWSER_PROCESS_EXIT_CAUSE = 'process-exit'\n\n/**\n * Names the machine-readable error-context cause for a CDP transport disconnecting while its\n * browser remains alive, `'transport-loss'`.\n */\nexport const BROWSER_TRANSPORT_LOSS_CAUSE = 'transport-loss'\n\n/**\n * Lists the environment variables checked, in order, for an explicit browser executable path\n * override: `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH`.\n */\nexport const BROWSER_ENV_PATH_KEYS: readonly string[] = Object.freeze([\n\t'PLAYWRIGHT_EXECUTABLE_PATH',\n\t'CHROME_PATH',\n])\n\n/**\n * Lists the well-known Chrome/Chromium/Edge executable paths with no platform-specific root,\n * keyed by `process.platform`, leaving `win32` empty because its roots come from\n * `BROWSER_WINDOWS_SUFFIXES`.\n */\nexport const BROWSER_EXECUTABLE_PATHS: Readonly<Record<string, readonly string[]>> = Object.freeze({\n\tlinux: Object.freeze([\n\t\t'/usr/bin/google-chrome',\n\t\t'/usr/bin/google-chrome-stable',\n\t\t'/usr/bin/microsoft-edge',\n\t\t'/usr/bin/microsoft-edge-stable',\n\t\t'/usr/bin/chromium',\n\t\t'/usr/bin/chromium-browser',\n\t\t'/snap/bin/chromium',\n\t\t'/opt/google/chrome/chrome',\n\t\t'/opt/microsoft/msedge/msedge',\n\t]),\n\tdarwin: Object.freeze([\n\t\t'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n\t\t'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n\t\t'/Applications/Chromium.app/Contents/MacOS/Chromium',\n\t]),\n\twin32: Object.freeze([]),\n})\n\n/** Lists the Windows install-root-relative suffixes for Chrome/Edge/Chromium, joined against each candidate root (`PROGRAMFILES`, `PROGRAMFILES(X86)`, `LOCALAPPDATA`). */\nexport const BROWSER_WINDOWS_SUFFIXES: readonly string[] = Object.freeze([\n\t'Google\\\\Chrome\\\\Application\\\\chrome.exe',\n\t'Microsoft\\\\Edge\\\\Application\\\\msedge.exe',\n\t'Chromium\\\\Application\\\\chrome.exe',\n])\n\n/**\n * Lists the fallback Windows install roots used when `PROGRAMFILES`, `PROGRAMFILES(X86)`, or\n * `LOCALAPPDATA` is absent.\n */\nexport const BROWSER_WINDOWS_ROOT_FALLBACKS: Readonly<Record<string, string>> = Object.freeze({\n\tPROGRAMFILES: 'C:\\\\Program Files',\n\t'PROGRAMFILES(X86)': 'C:\\\\Program Files (x86)',\n})\n\n/** Lists the command names probed on PATH when no well-known executable path exists. */\nexport const BROWSER_EXECUTABLE_NAMES: readonly string[] = Object.freeze([\n\t'google-chrome',\n\t'google-chrome-stable',\n\t'msedge',\n\t'microsoft-edge',\n\t'chromium',\n\t'chromium-browser',\n\t'chrome',\n])\n\n/**\n * Names the environment variable that carries an additional Playwright browser store base\n * directory, `'PLAYWRIGHT_BROWSERS_PATH'`.\n */\nexport const BROWSER_STORE_ENV_KEY = 'PLAYWRIGHT_BROWSERS_PATH'\n\n/**\n * Lists the well-known Playwright browser store base directories checked in addition to\n * `PLAYWRIGHT_BROWSERS_PATH`, starting with `/opt/pw-browsers`.\n */\nexport const BROWSER_STORE_DEFAULT_DIRS: readonly string[] = Object.freeze(['/opt/pw-browsers'])\n\n/** Names the per-OS default Playwright browser cache directory, relative to the home directory (win32 uses `LOCALAPPDATA` directly). */\nexport const BROWSER_STORE_CACHE_DIRS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: '.cache/ms-playwright',\n\tdarwin: 'Library/Caches/ms-playwright',\n})\n\n/**\n * Names the top-level Chromium symlink or binary Playwright maintains inside a browser store\n * base, `'chromium'`.\n */\nexport const BROWSER_STORE_LINK_NAME = 'chromium'\n\n/**\n * Lists the case-insensitive substrings identifying an executable path/name's browser\n * engine, checked by `parseBrowserEngine` in the order `edge` → `chromium` → `chrome`.\n */\nexport const BROWSER_ENGINE_HINTS: Readonly<Record<BrowserEngine, readonly string[]>> =\n\tObject.freeze({\n\t\tedge: Object.freeze(['msedge', 'microsoft-edge', 'edge']),\n\t\tchromium: Object.freeze([\n\t\t\t'chromium',\n\t\t\t'pw-browsers',\n\t\t\t'chrome-linux',\n\t\t\t'chrome-win',\n\t\t\t'chrome-mac',\n\t\t\t'chrome_headless',\n\t\t]),\n\t\tchrome: Object.freeze(['google-chrome', 'google/chrome', 'google\\\\chrome', 'chrome']),\n\t})\n\n/** Names the glob pattern (relative to a store base) matching a versioned Chromium binary, keyed by `process.platform`. */\nexport const BROWSER_STORE_GLOBS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: 'chromium-*/chrome-linux*/chrome',\n\tdarwin: 'chromium-*/chrome-mac*/Chromium.app/Contents/MacOS/Chromium',\n\twin32: 'chromium-*/chrome-win*/chrome.exe',\n})\n","import { BrowserError } from '@src/core'\nimport { isInstance } from '@orkestrel/contract'\n\n// === Server browser errors\n\n/**\n * Reports that a CDP connection, discovery, or launch attempt failed, under the code\n * `BROWSER_CONNECTION_ERROR`.\n */\nexport class BrowserConnectionError extends BrowserError {\n\tconstructor(message: string, context?: Readonly<Record<string, unknown>>) {\n\t\tsuper(message, 'BROWSER_CONNECTION_ERROR', context)\n\t\tthis.name = 'BrowserConnectionError'\n\t}\n}\n\n/**\n * Reports that an operation requiring an active connection was attempted while disconnected,\n * under the code `BROWSER_NOT_CONNECTED_ERROR`.\n */\nexport class BrowserNotConnectedError extends BrowserError {\n\tconstructor(context?: Readonly<Record<string, unknown>>) {\n\t\tsuper('Browser is not connected', 'BROWSER_NOT_CONNECTED_ERROR', context)\n\t\tthis.name = 'BrowserNotConnectedError'\n\t}\n}\n\n/**\n * Reports that an operation was attempted after the browser wrapper was destroyed, under the\n * code `BROWSER_DESTROYED_ERROR`.\n */\nexport class BrowserDestroyedError extends BrowserError {\n\tconstructor(context?: Readonly<Record<string, unknown>>) {\n\t\tsuper('Browser has been destroyed', 'BROWSER_DESTROYED_ERROR', context)\n\t\tthis.name = 'BrowserDestroyedError'\n\t}\n}\n\n// === Server browser type guards\n\n/**\n * Narrows an unknown value to a `BrowserConnectionError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserConnectionError instance; false otherwise\n */\nexport function isBrowserConnectionError(value: unknown): value is BrowserConnectionError {\n\treturn isInstance(value, BrowserConnectionError)\n}\n\n/**\n * Narrows an unknown value to a `BrowserNotConnectedError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserNotConnectedError instance; false otherwise\n */\nexport function isBrowserNotConnectedError(value: unknown): value is BrowserNotConnectedError {\n\treturn isInstance(value, BrowserNotConnectedError)\n}\n\n/**\n * Narrows an unknown value to a `BrowserDestroyedError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserDestroyedError instance; false otherwise\n */\nexport function isBrowserDestroyedError(value: unknown): value is BrowserDestroyedError {\n\treturn isInstance(value, BrowserDestroyedError)\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type { CDPTarget } from '@src/core'\nimport type { Result } from '@orkestrel/contract'\nimport type {\n\tBrowserEngine,\n\tBrowserProfileResult,\n\tSystemBrowser,\n\tSystemBrowserOptions,\n} from './types.js'\nimport { existsSync, globSync } from 'node:fs'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, resolve, win32 as pathWin32, posix as pathPosix } from 'node:path'\nimport { spawn, spawnSync } from 'node:child_process'\nimport { setTimeout as waitForTimeout } from 'node:timers/promises'\nimport { isArray, isRecord, isString } from '@orkestrel/contract'\nimport { BROWSER_WAIT_POLL_INTERVAL_MS, BrowserError } from '@src/core'\nimport { BrowserConnectionError } from './errors.js'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_VERSION_PATH,\n\tBROWSER_CDP_LIST_PATH,\n\tBROWSER_ENV_PATH_KEYS,\n\tBROWSER_EXECUTABLE_PATHS,\n\tBROWSER_EXECUTABLE_NAMES,\n\tBROWSER_WINDOWS_SUFFIXES,\n\tBROWSER_WINDOWS_ROOT_FALLBACKS,\n\tBROWSER_STORE_ENV_KEY,\n\tBROWSER_STORE_DEFAULT_DIRS,\n\tBROWSER_STORE_CACHE_DIRS,\n\tBROWSER_STORE_LINK_NAME,\n\tBROWSER_STORE_GLOBS,\n\tBROWSER_ENGINE_HINTS,\n\tBROWSER_LAUNCH_ARGS,\n\tBROWSER_HEADLESS_ARG,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_PROFILE_PREFIX,\n} from './constants.js'\n\n// === Discovery helpers\n\n/**\n * Enumerates every Chrome/Chromium/Edge executable discoverable on this\n * machine, deduplicated by normalized absolute path.\n *\n * @remarks\n * Resolution precedence (candidates appended in this order):\n * 1. `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH` — explicit environment\n * overrides that exist on disk\n * 2. Well-known platform install locations (Chrome, Edge, Chromium); Windows\n * roots are derived from `PROGRAMFILES` / `PROGRAMFILES(X86)` / `LOCALAPPDATA`\n * 3. PATH probe for known command names (`which` on POSIX, `where` on Windows)\n * 4. Playwright-managed browser stores (`PLAYWRIGHT_BROWSERS_PATH`, `/opt/pw-browsers`,\n * and the per-OS Playwright cache directory) — the top-level `chromium`\n * link/binary, then the highest-revision `chromium-*` install found\n *\n * Each candidate is classified into a {@link BrowserEngine} through\n * `parseBrowserEngine` (unclassifiable candidates default to `'chromium'`),\n * and `options.engine` (when given) narrows the result to that engine.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns Every discovered browser, in resolution-precedence order\n */\nexport function findSystemBrowsers(options?: SystemBrowserOptions): readonly SystemBrowser[] {\n\tconst platform = process.platform\n\tconst env = options?.env ?? process.env\n\n\tconst candidates: string[] = []\n\n\tcandidates.push(...findEnvOverrides(env))\n\n\tconst paths = options?.paths ?? buildInstallPaths(platform, env)\n\tcandidates.push(...findInstallPaths(paths))\n\n\tconst names = options?.names ?? BROWSER_EXECUTABLE_NAMES\n\tcandidates.push(...probePathNames(names, platform))\n\n\tconst stores = options?.stores ?? buildStoreBases(env, platform)\n\tfor (const store of stores) {\n\t\tcandidates.push(...findStorePaths(store, platform))\n\t}\n\n\tconst seen = new Set<string>()\n\tconst browsers: SystemBrowser[] = []\n\n\tfor (const executable of candidates) {\n\t\tconst key = normalizeExecutablePath(executable, platform)\n\t\tif (seen.has(key)) continue\n\t\tseen.add(key)\n\n\t\tconst engine = parseBrowserEngine(executable) ?? 'chromium'\n\t\tif (options?.engine !== undefined && engine !== options.engine) continue\n\n\t\tbrowsers.push({ executable, engine })\n\t}\n\n\treturn browsers\n}\n\n/**\n * Locates a Chrome/Chromium/Edge executable on this machine — the first entry\n * of {@link findSystemBrowsers}.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns The first discovered browser, or undefined\n */\nexport function findSystemBrowser(options?: SystemBrowserOptions): SystemBrowser | undefined {\n\treturn findSystemBrowsers(options)[0]\n}\n\n/**\n * Classifies an executable path/name into a {@link BrowserEngine} by\n * case-insensitive hint, checked in the order edge → chromium → chrome.\n *\n * @param executable - Executable path or command name to classify\n * @returns The classified engine, or undefined when no hint matches\n */\nexport function parseBrowserEngine(executable: string): BrowserEngine | undefined {\n\tconst lower = executable.toLowerCase()\n\tconst order: readonly BrowserEngine[] = ['edge', 'chromium', 'chrome']\n\tfor (const engine of order) {\n\t\tconst hints = BROWSER_ENGINE_HINTS[engine]\n\t\tif (hints.some((hint) => lower.includes(hint))) return engine\n\t}\n\treturn undefined\n}\n\n/** Normalizes an executable path for cross-source deduplication (case-insensitive on Windows). */\nexport function normalizeExecutablePath(path: string, platform: string): string {\n\tconst normalized = platform === 'win32' ? pathWin32.normalize(path) : pathPosix.normalize(path)\n\treturn platform === 'win32' ? normalized.toLowerCase() : normalized\n}\n\n/** Classifies a `/json/version` `Browser` string into a {@link BrowserEngine} (`Edg/` → edge, `Chrome/` → chrome, else chromium). */\nexport function browserToEngine(browser?: string): BrowserEngine {\n\tif (browser?.includes('Edg/') === true) return 'edge'\n\tif (browser?.includes('Chrome/') === true) return 'chrome'\n\treturn 'chromium'\n}\n\n/**\n * Resolves a persistent caller profile or creates an isolated temporary one.\n *\n * @param path - Optional caller-owned persistent user-data directory\n * @returns The resolved profile and whether the library owns its lifecycle\n */\nexport async function createBrowserProfile(path?: string): Promise<BrowserProfileResult> {\n\tif (path !== undefined) return { path, temporary: false }\n\tconst directory = await mkdtemp(join(tmpdir(), BROWSER_PROFILE_PREFIX))\n\treturn { path: directory, temporary: true }\n}\n\n/**\n * Removes a library-owned isolated browser profile.\n *\n * @remarks\n * The path must remain a direct child of the operating-system temp directory\n * with {@link BROWSER_PROFILE_PREFIX}; this defensive check prevents a\n * malformed profile value from widening recursive deletion.\n *\n * @param profile - Resolved profile lifecycle result\n */\nexport async function removeBrowserProfile(profile: BrowserProfileResult): Promise<void> {\n\tif (!profile.temporary) return\n\tconst path = resolve(profile.path)\n\tconst temporary = resolve(tmpdir())\n\tif (dirname(path) !== temporary || !basename(path).startsWith(BROWSER_PROFILE_PREFIX)) {\n\t\tthrow new BrowserError('Refusing to remove an unsafe browser profile path', undefined, {\n\t\t\tpath,\n\t\t})\n\t}\n\tawait rm(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })\n}\n\n/** Checks the env-override keys (`PLAYWRIGHT_EXECUTABLE_PATH`, `CHROME_PATH`) in order and returns every one that exists. */\nexport function findEnvOverrides(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst found: string[] = []\n\tfor (const key of BROWSER_ENV_PATH_KEYS) {\n\t\tconst value = env[key]\n\t\tif (value !== undefined && value.length > 0 && existsSync(value)) found.push(value)\n\t}\n\treturn found\n}\n\n/** Builds the default well-known install-path candidates for a platform, deriving Windows roots from env vars. */\nexport function buildInstallPaths(\n\tplatform: string,\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tif (platform !== 'win32') return BROWSER_EXECUTABLE_PATHS[platform] ?? []\n\n\tconst roots = buildWindowsRoots(env)\n\tconst paths: string[] = []\n\tfor (const root of roots) {\n\t\tfor (const suffix of BROWSER_WINDOWS_SUFFIXES) {\n\t\t\tpaths.push(pathWin32.join(root, suffix))\n\t\t}\n\t}\n\treturn paths\n}\n\n/** Derives Windows install roots from env vars, falling back to well-known literals when absent. */\nexport function buildWindowsRoots(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst programFiles = env['PROGRAMFILES'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES']\n\tconst programFilesX86 =\n\t\tenv['PROGRAMFILES(X86)'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES(X86)']\n\tconst localAppData = env['LOCALAPPDATA']\n\n\tconst roots = [programFiles, programFilesX86, localAppData]\n\treturn roots.filter((root): root is string => root !== undefined)\n}\n\n/** Returns every candidate path that exists on disk, in the given order. */\nexport function findInstallPaths(paths: readonly string[]): readonly string[] {\n\treturn paths.filter((path) => existsSync(path))\n}\n\n/** Probes PATH (`which`/`where`) for every resolvable command name, in the given order. */\nexport function probePathNames(names: readonly string[], platform: string): readonly string[] {\n\tconst finder = platform === 'win32' ? 'where' : 'which'\n\tconst found: string[] = []\n\tfor (const name of names) {\n\t\tconst result = spawnSync(finder, [name], { stdio: 'pipe' })\n\t\tif (result.status === 0) {\n\t\t\tconst executable = readFirstLine(result.stdout.toString('utf-8'))\n\t\t\tif (executable !== undefined) found.push(executable)\n\t\t}\n\t}\n\treturn found\n}\n\n/**\n * Returns the first non-empty line of a command's output, without its\n * surrounding whitespace.\n *\n * @remarks\n * `where` reports every PATH match on its own CRLF-terminated line, so a\n * carriage return left on the first line would travel into `existsSync` and\n * `spawn` as part of the executable path.\n *\n * @param output - Raw decoded standard output of a command\n * @returns The first line carrying text, or undefined when the output has none\n *\n * @example\n * ```ts\n * readFirstLine('C:\\\\bin\\\\chrome.exe\\r\\nC:\\\\other\\\\chrome.exe\\r\\n') // 'C:\\\\bin\\\\chrome.exe'\n * ```\n */\nexport function readFirstLine(output: string): string | undefined {\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tconst text = line.trim()\n\t\tif (text.length > 0) return text\n\t}\n\treturn undefined\n}\n\n/** Builds the default Playwright browser store base directories to search for a managed Chromium. */\nexport function buildStoreBases(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tplatform: string,\n): readonly string[] {\n\tconst bases: string[] = []\n\n\tconst envBase = env[BROWSER_STORE_ENV_KEY]\n\tif (envBase !== undefined && envBase.length > 0) bases.push(envBase)\n\n\tbases.push(...BROWSER_STORE_DEFAULT_DIRS)\n\n\tif (platform === 'win32') {\n\t\tconst localAppData = env['LOCALAPPDATA']\n\t\tif (localAppData !== undefined) bases.push(pathWin32.join(localAppData, 'ms-playwright'))\n\t} else {\n\t\tconst cacheDir = BROWSER_STORE_CACHE_DIRS[platform]\n\t\tconst home = env['HOME']\n\t\tif (cacheDir !== undefined && home !== undefined) bases.push(pathPosix.join(home, cacheDir))\n\t}\n\n\treturn bases\n}\n\n/** Searches one store base for the top-level `chromium` link and every `chromium-*` install, highest revision first. */\nexport function findStorePaths(base: string, platform: string): readonly string[] {\n\tconst joiner = platform === 'win32' ? pathWin32.join : pathPosix.join\n\tconst found: string[] = []\n\n\tconst linkPath = joiner(base, BROWSER_STORE_LINK_NAME)\n\tif (existsSync(linkPath)) found.push(linkPath)\n\n\tconst glob = BROWSER_STORE_GLOBS[platform]\n\tif (glob === undefined) return found\n\n\tconst pattern = `${base.replaceAll('\\\\', '/')}/${glob}`\n\tconst matches = globSync(pattern).filter((match) => existsSync(match))\n\tmatches.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))\n\tfound.push(...matches)\n\n\treturn found\n}\n\n/**\n * Launches a browser process with raw-CDP debugging flags.\n *\n * @remarks\n * POSIX launches own an isolated process group so lifecycle teardown can\n * signal and await every Chromium subprocess without affecting the caller.\n * Windows launches are not detached and own no group, so teardown there\n * signals one process by identifier: the spawned process, or the process the\n * launcher handed the endpoint to when that spawned process re-executed the\n * browser and exited. Terminating a Chromium browser process takes its own\n * subprocesses with it, so that single signal drains the tree.\n *\n * @param executable - Absolute path to the browser executable\n * @param port - Port the browser exposes its CDP endpoint on\n * @param headless - Whether to launch in headless mode\n * @param profile - Optional user-data-dir for a persistent profile\n * @param extra - Additional command-line flags\n * @returns The spawned ChildProcess\n */\nexport function launchBrowserProcess(\n\texecutable: string,\n\tport: number,\n\theadless: boolean,\n\tprofile?: string,\n\textra?: readonly string[],\n): ChildProcess {\n\t// Caller-supplied args come first so a script path (for example `node <script>`,\n\t// used to spawn a Node stand-in executable cross-platform in tests) lands\n\t// as an early positional argv entry ahead of the CDP flags that follow —\n\t// Chromium itself accepts flags in any order, so production is unaffected.\n\tconst args: string[] = []\n\tif (extra !== undefined) args.push(...extra)\n\targs.push(`--remote-debugging-port=${port}`, ...BROWSER_LAUNCH_ARGS)\n\n\tif (headless) args.push(BROWSER_HEADLESS_ARG)\n\tif (profile !== undefined) args.push(`--user-data-dir=${profile}`)\n\n\treturn spawn(executable, args, {\n\t\tstdio: 'ignore',\n\t\tdetached: process.platform !== 'win32',\n\t})\n}\n\n/**\n * Polls a browser's CDP version endpoint until it responds or the timeout elapses.\n *\n * @param port - Port the browser exposes its CDP endpoint on\n * @param timeout - Maximum time to wait in milliseconds\n * @param host - Host the browser exposes its CDP endpoint on (default `127.0.0.1`)\n * @param signal - Optional external abort; an abort while waiting rethrows rather than resolving\n * @returns The browser's WebSocket debugger URL\n *\n * @throws When the endpoint does not become ready before the timeout\n */\nexport async function waitForCDPReady(\n\tport: number,\n\ttimeout: number,\n\thost: string = BROWSER_DEFAULT_HOST,\n\tsignal?: AbortSignal,\n): Promise<string> {\n\tconst url = `${BROWSER_CDP_PROTOCOL}://${host}:${port}${BROWSER_CDP_VERSION_PATH}`\n\tconst deadline = Date.now() + timeout\n\n\twhile (Date.now() < deadline) {\n\t\tsignal?.throwIfAborted()\n\t\tconst remaining = Math.max(0, deadline - Date.now())\n\t\tconst requestSignal =\n\t\t\tsignal === undefined\n\t\t\t\t? AbortSignal.timeout(remaining)\n\t\t\t\t: AbortSignal.any([signal, AbortSignal.timeout(remaining)])\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: requestSignal })\n\t\t\tif (response.ok) {\n\t\t\t\tconst info: unknown = await response.json()\n\t\t\t\tif (isRecord(info) && isString(info['webSocketDebuggerUrl'])) {\n\t\t\t\t\treturn info['webSocketDebuggerUrl']\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted === true) throw error\n\t\t\t// Not ready yet — keep polling\n\t\t}\n\n\t\tconst delay = Math.min(BROWSER_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now()))\n\t\tif (delay > 0) await waitForTimeout(delay, undefined, { signal })\n\t}\n\n\tthrow new BrowserConnectionError(\n\t\t`CDP endpoint on port ${port} did not become ready within ${timeout}ms`,\n\t\t{ port, timeout },\n\t)\n}\n\n/**\n * Fetches the current CDP target list from a browser's `/json/list` endpoint, as a `Result`\n * carrying either the targets or a coded `BrowserConnectionError`.\n *\n * @remarks\n * The endpoint is a network boundary, so an unreachable host, a non-2xx\n * response, and a body that is not a JSON array each come back as a failed\n * `Result` carrying a coded `BrowserConnectionError`. An entry missing a\n * required string field is skipped rather than failing the whole list.\n *\n * @param port - Port the browser exposes its CDP endpoint on\n * @param timeout - Request timeout in milliseconds\n * @param host - Host the browser exposes its CDP endpoint on (default `127.0.0.1`)\n * @returns The normalized CDP targets, or the fault that stopped the request\n *\n * @example\n * ```ts\n * import { fetchCDPTargets } from '@orkestrel/browser/server'\n *\n * const result = await fetchCDPTargets(9222, 2000)\n * if (result.success) log(result.value.length)\n * else log(result.error.code)\n * ```\n */\nexport async function fetchCDPTargets(\n\tport: number,\n\ttimeout: number,\n\thost: string = BROWSER_DEFAULT_HOST,\n): Promise<Result<readonly CDPTarget[], BrowserError>> {\n\tconst url = `${BROWSER_CDP_PROTOCOL}://${host}:${port}${BROWSER_CDP_LIST_PATH}`\n\tconst controller = new AbortController()\n\tconst timer = setTimeout(() => controller.abort(), timeout)\n\n\ttry {\n\t\tconst response = await fetch(url, { signal: controller.signal })\n\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserConnectionError('CDP target list request was refused', {\n\t\t\t\t\turl,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t}),\n\t\t\t}\n\t\t}\n\n\t\tconst list: unknown = await response.json()\n\t\tif (!isArray(list)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserConnectionError('CDP target list is not a JSON array', { url }),\n\t\t\t}\n\t\t}\n\n\t\tconst targets: CDPTarget[] = []\n\t\tfor (const entry of list) {\n\t\t\tif (!isRecord(entry)) continue\n\t\t\tif (\n\t\t\t\t!isString(entry['id']) ||\n\t\t\t\t!isString(entry['type']) ||\n\t\t\t\t!isString(entry['title']) ||\n\t\t\t\t!isString(entry['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttargets.push({\n\t\t\t\tid: entry['id'],\n\t\t\t\tcategory: entry['type'],\n\t\t\t\ttitle: entry['title'],\n\t\t\t\turl: entry['url'],\n\t\t\t})\n\t\t}\n\n\t\treturn { success: true, value: targets }\n\t} catch (error) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: new BrowserConnectionError('CDP target list is unreachable', { url, error }),\n\t\t}\n\t} finally {\n\t\tclearTimeout(timer)\n\t}\n}\n","import type { CDPTransportEventMap, CDPTransportInterface } from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { NodeWebSocketInterface } from '@orkestrel/websocket'\nimport type { WebSocketCDPTransportOptions } from '../types.js'\nimport type { ClientRequest, IncomingMessage, RequestOptions } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport { randomBytes } from 'node:crypto'\nimport { request as httpRequest } from 'node:http'\nimport { request as httpsRequest } from 'node:https'\nimport { attempt, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tcomputeWebSocketAccept,\n\tcreateNodeWebSocket,\n\tWEBSOCKET_READY_CLOSED,\n\tWEBSOCKET_READY_OPEN,\n\tWEBSOCKET_VERSION,\n} from '@orkestrel/websocket'\nimport { BROWSER_DEFAULT_TIMEOUT_MS, BrowserTransition } from '@src/core'\nimport { BrowserConnectionError } from '../errors.js'\n\n// === WebSocketCDPTransport\n\n/**\n * Provides a raw CDP text transport backed by `@orkestrel/websocket`.\n *\n * @remarks\n * Performs and validates the RFC 6455 HTTP upgrade, then delegates frame\n * handling to `@orkestrel/websocket`. Concurrent and repeated `start()` /\n * `close()` calls share their active transition, and a later `start()` opens a\n * fresh socket after the prior one closes.\n *\n * @example\n * ```ts\n * import { WebSocketCDPTransport } from '@orkestrel/browser/server'\n *\n * const transport = new WebSocketCDPTransport({ url: 'ws://127.0.0.1:9222/devtools/browser/abc' })\n * await transport.start()\n * await transport.close()\n * ```\n */\nexport class WebSocketCDPTransport implements CDPTransportInterface {\n\treadonly #emitter: Emitter<CDPTransportEventMap>\n\treadonly #url: string\n\treadonly #timeout: number\n\t#socket: NodeWebSocketInterface | undefined\n\treadonly #starting: BrowserTransition = new BrowserTransition()\n\treadonly #closing: BrowserTransition = new BrowserTransition()\n\t#request: ClientRequest | undefined\n\t#resolve: ((socket: NodeWebSocketInterface) => void) | undefined\n\t#reject: ((error: unknown) => void) | undefined\n\t#timer: ReturnType<typeof setTimeout> | undefined\n\t#closeResolve: (() => void) | undefined\n\treadonly #socketCloseHandler = this.#handleSocketClose.bind(this)\n\n\tconstructor(options: WebSocketCDPTransportOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#url = options.url\n\t\tthis.#timeout = options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tget emitter(): EmitterInterface<CDPTransportEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tasync start(): Promise<void> {\n\t\tconst closing = this.#closing.pending\n\t\tif (closing !== undefined) await closing\n\t\tif (this.#socket?.readyState === WEBSOCKET_READY_OPEN) return\n\n\t\tconst active = this.#starting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\n\t\tthis.#socket?.destroy()\n\t\tthis.#socket = undefined\n\t\tawait this.#starting.execute(() => this.#start())\n\t}\n\n\tasync send(data: string): Promise<void> {\n\t\tconst socket = this.#socket\n\t\tif (socket === undefined || socket.readyState !== WEBSOCKET_READY_OPEN) {\n\t\t\tthrow new BrowserConnectionError('WebSocket CDP transport is not open', { url: this.#url })\n\t\t}\n\t\tsocket.send(data)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.#closing.execute(() => this.#close())\n\t}\n\n\t// === Private helpers\n\n\tasync #start(): Promise<void> {\n\t\tconst parsed = attempt(() => new URL(this.#url))\n\t\tif (!parsed.success) {\n\t\t\tthrow new BrowserConnectionError(`WebSocket CDP URL is invalid: ${this.#url}`, {\n\t\t\t\turl: this.#url,\n\t\t\t\terror: parsed.error,\n\t\t\t})\n\t\t}\n\t\tconst url = parsed.value\n\t\tif (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection requires a ws: or wss: URL: ${this.#url}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t)\n\t\t}\n\t\tconst key = randomBytes(16).toString('base64')\n\t\tconst deferred = Promise.withResolvers<NodeWebSocketInterface>()\n\t\tconst options: RequestOptions = {\n\t\t\thostname: url.hostname,\n\t\t\tport: url.port.length > 0 ? Number(url.port) : url.protocol === 'wss:' ? 443 : 80,\n\t\t\tpath: `${url.pathname}${url.search}`,\n\t\t\theaders: {\n\t\t\t\tConnection: 'Upgrade',\n\t\t\t\tUpgrade: 'websocket',\n\t\t\t\t'Sec-WebSocket-Key': key,\n\t\t\t\t'Sec-WebSocket-Version': WEBSOCKET_VERSION,\n\t\t\t},\n\t\t}\n\t\tconst request = url.protocol === 'wss:' ? httpsRequest(options) : httpRequest(options)\n\n\t\tthis.#request = request\n\t\tthis.#resolve = deferred.resolve\n\t\tthis.#reject = deferred.reject\n\t\tthis.#timer = setTimeout(() => this.#expire(request), this.#timeout)\n\n\t\trequest.on('upgrade', (response: IncomingMessage, socket: Duplex, head: Buffer) => {\n\t\t\tthis.#upgrade(request, key, response, socket, head)\n\t\t})\n\t\trequest.on('response', (response) => this.#decline(request, response))\n\t\trequest.on('error', (error) => this.#fail(request, error))\n\t\trequest.end()\n\n\t\tconst socket = await deferred.promise\n\t\tthis.#socket = socket\n\t\tthis.#bind(socket)\n\t}\n\n\tasync #close(): Promise<void> {\n\t\tconst request = this.#request\n\t\tif (request !== undefined) {\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} was closed before it finished connecting`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\trequest.destroy()\n\t\t}\n\t\tawait this.#starting.pending?.catch(() => undefined)\n\n\t\tconst socket = this.#socket\n\t\tthis.#socket = undefined\n\t\tif (socket === undefined || socket.readyState === WEBSOCKET_READY_CLOSED) return\n\n\t\tconst closed = Promise.withResolvers<void>()\n\t\tthis.#closeResolve = closed.resolve\n\t\tsocket.emitter.on('close', this.#socketCloseHandler)\n\t\ttry {\n\t\t\tsocket.close()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} catch {\n\t\t\tsocket.destroy()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} finally {\n\t\t\tsocket.emitter.off('close', this.#socketCloseHandler)\n\t\t\tthis.#closeResolve = undefined\n\t\t}\n\t}\n\n\t#upgrade(\n\t\trequest: ClientRequest,\n\t\tkey: string,\n\t\tresponse: IncomingMessage,\n\t\tsocket: Duplex,\n\t\thead: Buffer,\n\t): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst accept = response.headers['sec-websocket-accept']\n\t\tif (!isString(accept) || accept !== computeWebSocketAccept(key)) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: Sec-WebSocket-Accept mismatch`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tthis.#resolveRequest(request, createNodeWebSocket({ socket, head }))\n\t\t} catch (error) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(request, error)\n\t\t}\n\t}\n\n\t#decline(request: ClientRequest, response: IncomingMessage): void {\n\t\tresponse.resume()\n\t\tconst reason =\n\t\t\tresponse.statusCode === undefined\n\t\t\t\t? 'upgrade was declined without a status code'\n\t\t\t\t: `upgrade declined with status ${response.statusCode}`\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(`WebSocket CDP connection to ${this.#url} failed: ${reason}`, {\n\t\t\t\turl: this.#url,\n\t\t\t}),\n\t\t)\n\t}\n\n\t#fail(request: ClientRequest, error: Error): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: ${error.message}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t),\n\t\t)\n\t}\n\n\t#expire(request: ClientRequest): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection to ${this.#url} timed out after ${this.#timeout}ms`,\n\t\t\t\t{ url: this.#url, timeout: this.#timeout },\n\t\t\t),\n\t\t)\n\t\trequest.destroy()\n\t}\n\n\t#resolveRequest(request: ClientRequest, socket: NodeWebSocketInterface): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst resolve = this.#resolve\n\t\tthis.#clearRequest()\n\t\tresolve?.(socket)\n\t}\n\n\t#rejectRequest(request: ClientRequest, error: unknown): void {\n\t\tif (this.#request !== request) return\n\n\t\tconst reject = this.#reject\n\t\tthis.#clearRequest()\n\t\treject?.(error)\n\t}\n\n\t#clearRequest(): void {\n\t\tif (this.#timer !== undefined) clearTimeout(this.#timer)\n\t\tthis.#timer = undefined\n\t\tthis.#request = undefined\n\t\tthis.#resolve = undefined\n\t\tthis.#reject = undefined\n\t}\n\n\t#bind(socket: NodeWebSocketInterface): void {\n\t\tsocket.emitter.on('message', (data) => this.#emitter.emit('message', data))\n\t\tsocket.emitter.on('close', () => {\n\t\t\tif (this.#socket === socket) this.#socket = undefined\n\t\t\tthis.#emitter.emit('close')\n\t\t})\n\t\tsocket.emitter.on('error', (error) => this.#emitter.emit('error', error))\n\t}\n\n\t#handleSocketClose(): void {\n\t\tthis.#closeResolve?.()\n\t}\n}\n","import type { BrowserWriterInterface } from '@src/core'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\n\n// === FileBrowserWriter\n\n/**\n * Persists captured browser bytes to the filesystem through `node:fs/promises`.\n *\n * @remarks\n * Creates every missing parent directory of the target path before writing, so\n * a caller may name a nested destination that does not exist yet.\n *\n * @example\n * ```ts\n * import { FileBrowserWriter } from '@orkestrel/browser/server'\n *\n * const writer = new FileBrowserWriter()\n * await writer.write('shots/hero.png', new Uint8Array([137, 80, 78, 71]))\n * ```\n */\nexport class FileBrowserWriter implements BrowserWriterInterface {\n\t/**\n\t * Writes the captured bytes to a path, creating its parent directories.\n\t *\n\t * @param path - Destination file path\n\t * @param data - Captured bytes to persist\n\t * @returns A promise resolving once the bytes are on disk\n\t */\n\tasync write(path: string, data: Uint8Array): Promise<void> {\n\t\tawait mkdir(dirname(path), { recursive: true })\n\t\tawait writeFile(path, data)\n\t}\n}\n","import type { CDPTransportInterface, BrowserWriterInterface } from '@src/core'\nimport type { BrowserInterface, BrowserOptions, WebSocketCDPTransportOptions } from './types.js'\nimport { Browser } from './Browser.js'\nimport { WebSocketCDPTransport } from './transports/WebSocketCDPTransport.js'\nimport { FileBrowserWriter } from './writers/FileBrowserWriter.js'\n\n/**\n * Creates a raw-CDP `BrowserInterface` façade with discovery, connection, and lifecycle\n * management.\n *\n * @param options - Connection, launch, and viewport configuration\n * @returns A {@link BrowserInterface}\n *\n * @example Connect to a browser and drive a page\n * ```ts\n * import { createBrowser } from '@orkestrel/browser/server'\n *\n * const browser = createBrowser({ headless: true })\n * await browser.connect() // CDP endpoint discovery → connect, else launch\n * const page = await browser.create({ url: 'https://example.com' })\n * await page.click('#accept')\n * const shot = await page.screenshot({ path: './out.png' })\n * await browser.destroy()\n * ```\n */\nexport function createBrowser(options?: BrowserOptions): BrowserInterface {\n\treturn new Browser(options)\n}\n\n/**\n * Creates a Node `WebSocket`-backed `CDPTransportInterface` for the given CDP debugger URL.\n *\n * @param options - The CDP WebSocket debugger URL (and optional timeout)\n * @returns A {@link CDPTransportInterface}\n */\nexport function createCDPTransport(options: WebSocketCDPTransportOptions): CDPTransportInterface {\n\treturn new WebSocketCDPTransport(options)\n}\n\n/**\n * Creates a filesystem-backed `BrowserWriterInterface` that persists bytes through\n * `node:fs/promises`.\n *\n * @returns A {@link BrowserWriterInterface} that persists bytes through `node:fs/promises`\n */\nexport function createBrowserWriter(): BrowserWriterInterface {\n\treturn new FileBrowserWriter()\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type {\n\tBrowserConnection,\n\tBrowserDiscoveryResult,\n\tBrowserEngine,\n\tBrowserEventMap,\n\tBrowserInterface,\n\tBrowserOptions,\n\tBrowserProfileResult,\n\tBrowserStatus,\n} from './types.js'\nimport type {\n\tBrowserContextInterface,\n\tBrowserContextOptions,\n\tBrowserPageInterface,\n\tBrowserPageOptions,\n\tCDPTarget,\n\tCDPTransportInterface,\n} from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport { addAbortListener, once } from 'node:events'\nimport { isArray, isError, isInteger, isRecord, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tBrowserContext,\n\tBrowserTransition,\n\tBROWSER_DEFAULT_TIMEOUT_MS,\n\tBROWSER_WAIT_POLL_INTERVAL_MS,\n\tCDPClient,\n\tvalidateBrowserContextOptions,\n} from '@src/core'\nimport {\n\tBrowserConnectionError,\n\tBrowserDestroyedError,\n\tBrowserNotConnectedError,\n\tisBrowserConnectionError,\n} from './errors.js'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_VERSION_PATH,\n\tBROWSER_DEFAULT_CDP_PORT,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_KILL_GRACE_MS,\n\tBROWSER_PORT_PROBE_TIMEOUT_MS,\n\tBROWSER_PROCESS_EXIT_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_DEFER_MS,\n} from './constants.js'\nimport {\n\tbrowserToEngine,\n\tcreateBrowserProfile,\n\tfindSystemBrowser,\n\tlaunchBrowserProcess,\n\tparseBrowserEngine,\n\tremoveBrowserProfile,\n\twaitForCDPReady,\n} from './helpers.js'\nimport { createCDPTransport, createBrowserWriter } from './factories.js'\n\n// === Browser\n\n/**\n * Discovers, launches, connects to, and owns Chromium-family browser sessions.\n *\n * @example\n * ```ts\n * import { Browser } from '@orkestrel/browser/server'\n *\n * const browser = new Browser({ headless: true })\n * await browser.connect()\n * const page = await browser.create({ url: 'https://example.com' })\n * await browser.destroy()\n * ```\n */\nexport class Browser implements BrowserInterface {\n\treadonly #emitter: Emitter<BrowserEventMap>\n\treadonly #options: BrowserOptions\n\treadonly #abort = new AbortController()\n\treadonly #cdpPort: number\n\treadonly #cdpHost: string\n\t#engine: BrowserEngine\n\t#status: BrowserStatus = 'idle'\n\t#connection: BrowserConnection | undefined\n\t#owned: boolean | undefined\n\t#endpoint: string | undefined\n\t#client: CDPClient | undefined\n\t#process: ChildProcess | undefined\n\t// Identifier the launcher handed the endpoint to when it re-executed the\n\t// browser and exited before CDP became ready. Undefined whenever the\n\t// spawned child is itself the process serving the endpoint.\n\t#servingPid: number | undefined\n\t#profile: BrowserProfileResult | undefined\n\t#contexts: BrowserContext[] = []\n\t#destroyed = false\n\treadonly #connecting: BrowserTransition = new BrowserTransition()\n\treadonly #disconnecting: BrowserTransition = new BrowserTransition()\n\t#exitCleanup: Promise<void> | undefined\n\t#shutdown: Promise<void> | undefined\n\t#transport: CDPTransportInterface | undefined\n\treadonly #transportCloseHandler = this.#handleTransportLoss.bind(this)\n\treadonly #transportErrorHandler = this.#handleTransportLoss.bind(this)\n\treadonly #processExitHandler = this.#handleProcessExit.bind(this)\n\n\tconstructor(options?: BrowserOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#options = options ?? {}\n\t\tthis.#engine =\n\t\t\tthis.#options.engine ??\n\t\t\t(this.#options.executable !== undefined\n\t\t\t\t? (parseBrowserEngine(this.#options.executable) ?? 'chromium')\n\t\t\t\t: 'chromium')\n\t\tthis.#cdpPort = this.#options.cdp?.port ?? BROWSER_DEFAULT_CDP_PORT\n\t\tthis.#cdpHost = this.#options.cdp?.host ?? BROWSER_DEFAULT_HOST\n\n\t\tqueueMicrotask(() => this.#emitter.emit('idle'))\n\t}\n\n\tget emitter(): EmitterInterface<BrowserEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget engine(): BrowserEngine {\n\t\treturn this.#engine\n\t}\n\n\tget status(): BrowserStatus {\n\t\treturn this.#status\n\t}\n\n\tget connection(): BrowserConnection | undefined {\n\t\treturn this.#connection\n\t}\n\n\tget owned(): boolean | undefined {\n\t\treturn this.#owned\n\t}\n\n\tget pid(): number | undefined {\n\t\treturn this.#servingPid ?? this.#process?.pid\n\t}\n\n\tasync discover(): Promise<BrowserDiscoveryResult> {\n\t\tconst result = await this.#discoverCDP()\n\t\tthis.#emitter.emit('discover', result)\n\t\treturn result\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\n\t\tconst active = this.#connecting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\t\tif (this.#status === 'connected') return\n\n\t\tawait this.#connecting.execute(() => this.#establish())\n\t}\n\n\tadopt(): void {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tif (\n\t\t\tthis.#status !== 'connected' ||\n\t\t\tthis.#client === undefined ||\n\t\t\tthis.#endpoint === undefined\n\t\t) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tthis.#owned = true\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.#destroyed) return\n\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tconst connecting = this.#connecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tif (connecting !== undefined) await connecting.catch(() => undefined)\n\t\tif (this.#destroyed) return\n\t\tif (this.#status !== 'connected' || this.#client === undefined) return\n\n\t\tawait this.#disconnecting.execute(() => this.#detach())\n\t}\n\n\tcontext(index?: number): BrowserContextInterface | undefined {\n\t\tconst i = index ?? 0\n\t\tif (i < 0 || i >= this.#contexts.length) return undefined\n\t\treturn this.#contexts[i]\n\t}\n\n\tcontexts(): readonly BrowserContextInterface[] {\n\t\treturn [...this.#contexts]\n\t}\n\n\tasync isolate(options?: BrowserContextOptions): Promise<BrowserContextInterface> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tvalidateBrowserContextOptions(options)\n\t\tconst params: Record<string, unknown> = { disposeOnDetach: false }\n\t\tif (options?.proxy !== undefined) {\n\t\t\tparams['proxyServer'] = options.proxy.server\n\t\t\tif (options.proxy.bypass !== undefined) {\n\t\t\t\tparams['proxyBypassList'] = options.proxy.bypass.join(',')\n\t\t\t}\n\t\t}\n\t\tif (options?.origins !== undefined) {\n\t\t\tparams['originsWithUniversalNetworkAccess'] = [...options.origins]\n\t\t}\n\t\tconst result = await client.send('Target.createBrowserContext', params)\n\t\tif (!isRecord(result) || !isString(result['browserContextId'])) {\n\t\t\tthrow new BrowserConnectionError('Failed to create isolated browser context')\n\t\t}\n\t\tconst id = result['browserContextId']\n\t\tconst context = new BrowserContext(\n\t\t\tclient,\n\t\t\tid,\n\t\t\toptions?.emulation?.viewport ?? this.#options.viewport,\n\t\t\tcreateBrowserWriter(),\n\t\t\toptions?.emulation,\n\t\t\toptions?.downloads,\n\t\t\toptions,\n\t\t)\n\n\t\ttry {\n\t\t\tif (options?.downloads !== undefined) {\n\t\t\t\tawait client.send('Browser.setDownloadBehavior', {\n\t\t\t\t\tbehavior: options.downloads.named === true ? 'allowAndName' : 'allow',\n\t\t\t\t\tbrowserContextId: id,\n\t\t\t\t\tdownloadPath: options.downloads.path,\n\t\t\t\t\teventsEnabled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait context.close().catch(() => undefined)\n\t\t\tthrow error\n\t\t}\n\n\t\tthis.#registerContext(context)\n\t\treturn context\n\t}\n\n\tasync create(options?: BrowserPageOptions): Promise<BrowserPageInterface> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\n\t\tlet context = this.#contexts[0]\n\t\tif (context === undefined) {\n\t\t\tcontext = new BrowserContext(client, undefined, this.#options.viewport, createBrowserWriter())\n\t\t\tthis.#registerContext(context)\n\t\t}\n\n\t\tconst page = await context.create(options)\n\t\tthis.#emitter.emit('page', page)\n\t\treturn page\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#destroyResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\tclose(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#closeResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\t// === Private helpers\n\n\tasync #establish(): Promise<void> {\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tawait this.#settleExit()\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tif (this.#status === 'connected') return\n\n\t\tthis.#assertNotAborted()\n\t\tthis.#status = 'connecting'\n\n\t\ttry {\n\t\t\tif (this.#owned === true && this.#endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(this.#endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst endpoint = this.#options.cdp?.endpoint\n\t\t\tif (endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst discover = this.#options.cdp?.discover ?? true\n\t\t\tif (discover) {\n\t\t\t\tconst discovery = await this.#raceAbort(this.#discoverCDP(this.#signal()))\n\t\t\t\tif (discovery.endpoint !== undefined) {\n\t\t\t\t\tthis.#engine = browserToEngine(discovery.browser)\n\t\t\t\t\tawait this.#connectCDP(discovery.endpoint)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait this.#raceAbort(this.#assertPortFree())\n\t\t\t}\n\n\t\t\tthis.#assertNotAborted()\n\t\t\tawait this.#launch()\n\t\t} catch (error) {\n\t\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\n\t\t\tthis.#status = 'error'\n\t\t\tthis.#emitter.emit('error', error)\n\t\t\tif (isBrowserConnectionError(error)) throw error\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserConnectionError(message, { executable: this.#options.executable })\n\t\t}\n\t}\n\n\tasync #detach(): Promise<void> {\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#unbindTransport()\n\n\t\tconst client = this.#client\n\t\tthis.#client = undefined\n\t\tawait this.#destroyContexts()\n\t\tthis.#contexts = []\n\n\t\tif (this.#owned !== true) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tawait this.#closeClient(client)\n\t\tif (this.#destroyed) return\n\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#assertNotAborted(): void {\n\t\tif (this.#signal().aborted) throw new BrowserConnectionError('Connection aborted')\n\t}\n\n\t#signal(): AbortSignal {\n\t\tconst external = this.#options.signal\n\t\treturn external === undefined\n\t\t\t? this.#abort.signal\n\t\t\t: AbortSignal.any([this.#abort.signal, external])\n\t}\n\n\tasync #raceAbort<T>(promise: Promise<T>): Promise<T> {\n\t\tconst signal = this.#signal()\n\t\tif (signal.aborted) throw new BrowserConnectionError('Connection aborted')\n\n\t\tconst aborted = Promise.withResolvers<never>()\n\t\tconst listener = addAbortListener(signal, () => {\n\t\t\taborted.reject(new BrowserConnectionError('Connection aborted'))\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([promise, aborted.promise])\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t\tvoid promise.catch(() => undefined)\n\t\t}\n\t}\n\n\t#handleProcessExit(): void {\n\t\tif (this.#destroyed) return\n\n\t\tconst connected = this.#status === 'connected'\n\t\tconst client = this.#client\n\t\tconst contexts = this.#contexts\n\t\tconst process = this.#process\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tconst cleanup = this.#cleanupExitedProcess(process, contexts, client)\n\t\tthis.#exitCleanup = cleanup\n\t\tvoid cleanup.catch((error: unknown) => this.#emitter.emit('error', error))\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tif (connected) this.#status = 'disconnected'\n\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserConnectionError('The browser process exited unexpectedly', {\n\t\t\t\tcause: BROWSER_PROCESS_EXIT_CAUSE,\n\t\t\t}),\n\t\t)\n\n\t\tif (connected) {\n\t\t\tthis.#emitter.emit('disconnect')\n\t\t\tthis.#emitter.emit('idle')\n\t\t}\n\t}\n\n\t#handleTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process === undefined) {\n\t\t\tthis.#confirmTransportLoss()\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\t// A spawned child that is already dead is diagnosed by its own `exit`\n\t\t// event, never by a probe here: Node sets `exitCode` in the same callback\n\t\t// that emits `exit`, and reports ESRCH from `ChildProcess.kill(0)` as a\n\t\t// `false` return rather than a throw, so no reading of the handle can see\n\t\t// the death before the event does. The defer only has to outlast the loop\n\t\t// turn that delivers it.\n\t\tsetTimeout(() => this.#confirmTransportLoss(), BROWSER_TRANSPORT_LOSS_DEFER_MS)\n\t}\n\n\t#confirmTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process !== undefined && !this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\tconst client = this.#client\n\t\tconst owned = this.#owned === true\n\t\tconst contexts = this.#contexts\n\t\tthis.#unbindTransport()\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#status = 'disconnected'\n\n\t\tif (!owned) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tvoid this.#destroyContextList(contexts)\n\t\tvoid this.#closeClient(client)\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserConnectionError('The CDP transport connection was lost', {\n\t\t\t\tcause: BROWSER_TRANSPORT_LOSS_CAUSE,\n\t\t\t}),\n\t\t)\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#bindTransport(transport: CDPTransportInterface): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#transport = transport\n\t\ttransport.emitter.on('close', this.#transportCloseHandler)\n\t\ttransport.emitter.on('error', this.#transportErrorHandler)\n\t}\n\n\t#unbindTransport(): void {\n\t\tconst transport = this.#transport\n\t\tif (transport === undefined) return\n\t\ttransport.emitter.off('close', this.#transportCloseHandler)\n\t\ttransport.emitter.off('error', this.#transportErrorHandler)\n\t\tthis.#transport = undefined\n\t}\n\n\t#bindProcess(process: ChildProcess): void {\n\t\tthis.#unbindProcess()\n\t\t// A launcher that handed the endpoint on has already exited, and its exit\n\t\t// says nothing about the browser now serving CDP. That browser has no\n\t\t// child handle, so the transport reports its death.\n\t\tif (this.#servingPid !== undefined) return\n\t\tprocess.once('exit', this.#processExitHandler)\n\t\tif (process.exitCode !== null || process.signalCode !== null) {\n\t\t\tqueueMicrotask(this.#processExitHandler)\n\t\t}\n\t}\n\n\t#unbindProcess(): void {\n\t\tthis.#process?.off('exit', this.#processExitHandler)\n\t}\n\n\t#timeout(): number {\n\t\treturn this.#options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tasync #discoverCDP(signal?: AbortSignal): Promise<BrowserDiscoveryResult> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\t\tconst requestSignal =\n\t\t\tsignal === undefined\n\t\t\t\t? AbortSignal.timeout(this.#timeout())\n\t\t\t\t: AbortSignal.any([signal, AbortSignal.timeout(this.#timeout())])\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: requestSignal })\n\t\t\tif (!response.ok) return this.#notFound()\n\n\t\t\tconst info: unknown = await response.json()\n\t\t\tif (!isRecord(info)) return this.#notFound()\n\n\t\t\tconst endpoint = isString(info['webSocketDebuggerUrl'])\n\t\t\t\t? info['webSocketDebuggerUrl']\n\t\t\t\t: undefined\n\t\t\tconst browser = isString(info['Browser']) ? info['Browser'] : undefined\n\n\t\t\treturn { endpoint, browser }\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted === true) throw error\n\t\t\treturn this.#notFound()\n\t\t}\n\t}\n\n\t#notFound(): BrowserDiscoveryResult {\n\t\treturn { endpoint: undefined, browser: undefined }\n\t}\n\n\tasync #assertPortFree(): Promise<void> {\n\t\tif (await this.#probePort()) {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t`Port ${this.#cdpPort} on ${this.#cdpHost} is already occupied by another CDP endpoint`,\n\t\t\t\t{ port: this.#cdpPort, host: this.#cdpHost },\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #probePort(): Promise<boolean> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tsignal: AbortSignal.timeout(BROWSER_PORT_PROBE_TIMEOUT_MS),\n\t\t\t})\n\t\t\treturn response.ok\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync #connectCDP(endpoint: string): Promise<void> {\n\t\tconst transport = createCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\tconst client = new CDPClient({ transport, timeout: this.#timeout() })\n\t\tconst retained = this.#owned === true && this.#endpoint === endpoint\n\n\t\ttry {\n\t\t\tawait this.#raceAbort(client.connect())\n\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = retained ? this.#retainedConnection() : 'cdp'\n\t\t\tthis.#owned = retained\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('connect', this.#connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tif (this.#client === client) this.#client = undefined\n\t\t\tthis.#contexts = []\n\t\t\tthis.#connection = undefined\n\t\t\tif (!retained) {\n\t\t\t\tthis.#owned = undefined\n\t\t\t\tthis.#endpoint = undefined\n\t\t\t}\n\t\t\tawait this.#closeClient(client)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #launch(): Promise<void> {\n\t\tif (this.#process !== undefined) {\n\t\t\tthrow new BrowserConnectionError('A browser process is already active on this instance')\n\t\t}\n\n\t\tconst requestedEngine = this.#options.engine ?? this.#options.browsers?.engine\n\t\tlet executable = this.#options.executable\n\t\tlet resolvedEngine: BrowserEngine | undefined\n\n\t\tif (executable !== undefined) {\n\t\t\tresolvedEngine = parseBrowserEngine(executable) ?? 'chromium'\n\t\t} else {\n\t\t\tconst found = findSystemBrowser({\n\t\t\t\t...this.#options.browsers,\n\t\t\t\t...(requestedEngine !== undefined ? { engine: requestedEngine } : {}),\n\t\t\t})\n\t\t\texecutable = found?.executable\n\t\t\tresolvedEngine = found?.engine\n\t\t}\n\n\t\tif (executable === undefined) {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t'No Chromium browser found. Install Chrome, Edge, or Chromium.',\n\t\t\t\trequestedEngine === undefined ? undefined : { engine: requestedEngine },\n\t\t\t)\n\t\t}\n\n\t\tthis.#engine = resolvedEngine ?? 'chromium'\n\t\tawait this.#releaseProfile()\n\t\tconst profile = await createBrowserProfile(this.#options.profile)\n\t\tthis.#profile = profile\n\t\tlet process: ChildProcess\n\t\ttry {\n\t\t\tprocess = launchBrowserProcess(\n\t\t\t\texecutable,\n\t\t\t\tthis.#cdpPort,\n\t\t\t\tthis.#options.headless ?? true,\n\t\t\t\tprofile.path,\n\t\t\t\tthis.#options.args,\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tawait this.#releaseProfile()\n\t\t\tthrow error\n\t\t}\n\t\tthis.#process = process\n\n\t\tlet client: CDPClient | undefined\n\n\t\ttry {\n\t\t\tconst endpoint = await this.#waitForLaunch(process, executable, this.#options.args)\n\t\t\tconst transport = createCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\t\tclient = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\tawait this.#raceAbort(client.connect())\n\t\t\tawait this.#takeEndpointOwner(process, client)\n\n\t\t\tconst connection = this.#options.profile === undefined ? 'launch' : 'persistent'\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = connection\n\t\t\tthis.#owned = true\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\t\t\tthis.#bindProcess(process)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('launch', this.#engine)\n\t\t\tthis.#emitter.emit('connect', connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\t\t\tawait this.#closeClient(client)\n\t\t\tawait this.#terminate(process)\n\t\t\tawait this.#releaseProfile()\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tthis.#client = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t\tthis.#owned = undefined\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Takes over the process serving the CDP endpoint when the spawned child is\n\t * no longer it.\n\t *\n\t * @remarks\n\t * A Windows launcher — Microsoft Edge — re-executes the browser with the\n\t * same `--remote-debugging-port` and exits 0 before the endpoint answers, so\n\t * the child this instance spawned parents the real tree without being part\n\t * of it. Chromium names the process behind the endpoint as the `browser`\n\t * entry of `SystemInfo.getProcessInfo`, which identifies it without a\n\t * platform branch. An endpoint that names no such process cannot be owned,\n\t * so the launch closes it and fails rather than leaking it.\n\t */\n\tasync #takeEndpointOwner(process: ChildProcess, client: CDPClient): Promise<void> {\n\t\tif (process.exitCode === null && process.signalCode === null) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('SystemInfo.getProcessInfo')\n\t\t} catch {\n\t\t\tresult = undefined\n\t\t}\n\n\t\tlet pid: number | undefined\n\t\tif (isRecord(result) && isArray(result['processInfo'])) {\n\t\t\tfor (const entry of result['processInfo']) {\n\t\t\t\tif (!isRecord(entry) || entry['type'] !== 'browser' || !isInteger(entry['id'])) continue\n\t\t\t\tpid = entry['id']\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (pid === undefined) {\n\t\t\tawait this.#closeRemote(client)\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t'The browser launcher exited without naming the process serving its CDP endpoint',\n\t\t\t\t{ executable: this.#options.executable, pid: process.pid },\n\t\t\t)\n\t\t}\n\n\t\tthis.#servingPid = pid\n\t}\n\n\tasync #waitForLaunch(\n\t\tprocess: ChildProcess,\n\t\texecutable: string,\n\t\targs?: readonly string[],\n\t): Promise<string> {\n\t\tconst context = { executable, args }\n\t\tconst controller = new AbortController()\n\t\tconst signal = AbortSignal.any([controller.signal, this.#signal()])\n\t\tconst ready = waitForCDPReady(this.#cdpPort, this.#timeout(), this.#cdpHost, signal)\n\t\tconst exited = once(process, 'exit', { signal }).then((values) => {\n\t\t\tconst code = isInteger(values[0]) ? values[0] : null\n\t\t\tconst exitSignal = isString(values[1]) ? values[1] : null\n\t\t\t// A launcher that re-executes the browser exits cleanly and hands the\n\t\t\t// endpoint to the process it spawned, so a clean exit ends the child\n\t\t\t// rather than the launch. Keep waiting for the endpoint on the same\n\t\t\t// readiness budget, which still fails loudly when none appears.\n\t\t\tif (code === 0 && exitSignal === null) return ready\n\t\t\tthrow new BrowserConnectionError(this.#formatLaunchExit(code, exitSignal), context)\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([ready, exited])\n\t\t} catch (error) {\n\t\t\tif (isBrowserConnectionError(error)) throw error\n\t\t\tif (this.#signal().aborted) throw new BrowserConnectionError('Connection aborted', context)\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserConnectionError(message, context)\n\t\t} finally {\n\t\t\tcontroller.abort()\n\t\t\tvoid ready.catch(() => undefined)\n\t\t\tvoid exited.catch(() => undefined)\n\t\t}\n\t}\n\n\t#formatLaunchExit(code: number | null, signal: string | null): string {\n\t\tif (signal !== null) {\n\t\t\treturn `Browser process exited before CDP became ready (signal: ${signal})`\n\t\t}\n\t\tif (code !== null) return `Browser process exited before CDP became ready (code: ${code})`\n\t\treturn 'Browser process exited before CDP became ready'\n\t}\n\n\t#retainedConnection(): BrowserConnection {\n\t\tif (this.#process === undefined) return 'cdp'\n\t\treturn this.#options.profile === undefined ? 'launch' : 'persistent'\n\t}\n\n\tasync #syncContexts(): Promise<void> {\n\t\tconst client = this.#client\n\t\tif (client === undefined) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('Target.getTargets')\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\t\tif (!isRecord(result) || !isArray(result['targetInfos'])) return\n\n\t\tconst pages: CDPTarget[] = []\n\t\tfor (const target of result['targetInfos']) {\n\t\t\tif (\n\t\t\t\t!isRecord(target) ||\n\t\t\t\t!isString(target['targetId']) ||\n\t\t\t\ttarget['type'] !== 'page' ||\n\t\t\t\t!isString(target['title']) ||\n\t\t\t\t!isString(target['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpages.push({\n\t\t\t\tid: target['targetId'],\n\t\t\t\tcategory: target['type'],\n\t\t\t\ttitle: target['title'],\n\t\t\t\turl: target['url'],\n\t\t\t})\n\t\t}\n\t\tif (pages.length === 0 || this.#contexts.length > 0) return\n\n\t\tconst context = new BrowserContext(\n\t\t\tclient,\n\t\t\tundefined,\n\t\t\tthis.#options.viewport,\n\t\t\tcreateBrowserWriter(),\n\t\t)\n\t\tawait context.sync(pages)\n\t\tthis.#registerContext(context)\n\t}\n\n\tasync #destroyResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tif (this.#owned === true) {\n\t\t\t\tawait this.#closeContexts()\n\t\t\t\tif (this.#process === undefined) await this.#closeRemote(client)\n\t\t\t} else {\n\t\t\t\tawait this.#destroyContexts()\n\t\t\t}\n\t\t\tthis.#contexts = []\n\n\t\t\tawait this.#terminate(this.#process)\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tawait this.#closeContexts()\n\t\t\tthis.#contexts = []\n\t\t\tawait this.#closeRemote(client)\n\n\t\t\tconst process = this.#process\n\t\t\tif (process !== undefined) {\n\t\t\t\tconst exited = await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)\n\t\t\t\tif (!exited) await this.#terminate(process)\n\t\t\t}\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #settle(): Promise<void> {\n\t\tawait this.#connecting.pending?.catch(() => undefined)\n\t\tawait this.#disconnecting.pending?.catch(() => undefined)\n\t\tawait this.#settleExit()\n\t}\n\n\tasync #settleExit(): Promise<void> {\n\t\tconst cleanup = this.#exitCleanup\n\t\tif (cleanup === undefined) return\n\t\tawait cleanup\n\t\tif (this.#exitCleanup === cleanup) this.#exitCleanup = undefined\n\t}\n\n\tasync #closeRemote(client: CDPClient | undefined): Promise<void> {\n\t\tlet remote = client\n\t\tlet temporary = false\n\n\t\tif (remote === undefined && this.#owned === true && this.#endpoint !== undefined) {\n\t\t\tconst transport = createCDPTransport({\n\t\t\t\turl: this.#endpoint,\n\t\t\t\ttimeout: this.#timeout(),\n\t\t\t})\n\t\t\tremote = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\ttry {\n\t\t\t\tawait remote.connect()\n\t\t\t\ttemporary = true\n\t\t\t} catch {\n\t\t\t\tawait this.#closeClient(remote)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (remote !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait remote.send('Browser.close')\n\t\t\t} catch {\n\t\t\t\t// The remote may already be gone or close before acknowledging.\n\t\t\t}\n\t\t}\n\n\t\tif (temporary) await this.#closeClient(remote)\n\t}\n\n\tasync #closeContexts(): Promise<void> {\n\t\tfor (const context of [...this.#contexts]) {\n\t\t\ttry {\n\t\t\t\tawait context.close()\n\t\t\t} catch {\n\t\t\t\t// Teardown is best-effort after the browser begins shutting down.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #destroyContexts(): Promise<void> {\n\t\tawait this.#destroyContextList([...this.#contexts])\n\t}\n\n\t#registerContext(context: BrowserContext): void {\n\t\tthis.#contexts.push(context)\n\t\tcontext.emitter.on('close', () => {\n\t\t\tconst index = this.#contexts.indexOf(context)\n\t\t\tif (index >= 0) this.#contexts.splice(index, 1)\n\t\t})\n\t\tthis.#emitter.emit('context', context)\n\t}\n\n\tasync #destroyContextList(contexts: readonly BrowserContext[]): Promise<void> {\n\t\tfor (const context of contexts) {\n\t\t\ttry {\n\t\t\t\tawait context.destroy()\n\t\t\t} catch {\n\t\t\t\t// The transport may already be unavailable.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeClient(client: CDPClient | undefined): Promise<void> {\n\t\tif (client === undefined) return\n\t\ttry {\n\t\t\tawait client.close()\n\t\t} catch {\n\t\t\t// Teardown is best-effort after a connection fault.\n\t\t}\n\t}\n\n\tasync #releaseProfile(): Promise<void> {\n\t\tconst profile = this.#profile\n\t\tthis.#profile = undefined\n\t\tif (profile !== undefined) await removeBrowserProfile(profile)\n\t}\n\n\tasync #cleanupExitedProcess(\n\t\tprocess: ChildProcess | undefined,\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#terminate(process)\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t}\n\t\tif (terminated) await this.#releaseProfile()\n\t}\n\n\tasync #cleanupLocal(\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tawait this.#destroyContextList(contexts)\n\t\tawait this.#closeClient(client)\n\t}\n\n\tasync #waitForProcessWithin(process: ChildProcess, timeout: number): Promise<boolean> {\n\t\tif (process.exitCode !== null || process.signalCode !== null) return true\n\n\t\tconst signal = AbortSignal.timeout(timeout)\n\t\ttry {\n\t\t\tawait once(process, 'exit', { signal })\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn process.exitCode !== null || process.signalCode !== null\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#hasProcessGroup(process: ChildProcess): boolean {\n\t\tconst pid = process.pid\n\t\treturn globalThis.process.platform !== 'win32' && pid !== undefined && pid > 0\n\t}\n\n\t// Whether the process serving the CDP endpoint is still running. The spawned\n\t// child reports through its own handle; a process the launcher handed the\n\t// endpoint to has none, so it is probed by identifier.\n\t#alive(): boolean {\n\t\tconst process = this.#process\n\t\tif (process === undefined) return false\n\t\tif (this.#servingPid !== undefined) return this.#signalProcess(process, 0) !== false\n\t\treturn process.exitCode === null && process.signalCode === null\n\t}\n\n\t// Whether the launch retains a process the reaped child does not account\n\t// for: the POSIX process group, or the process the launcher handed the\n\t// endpoint to.\n\t#inspectRemainder(process: ChildProcess): boolean | undefined {\n\t\tif (!this.#hasProcessGroup(process) && this.#servingPid === undefined) return false\n\t\treturn this.#signalProcess(process, 0)\n\t}\n\n\t#signalProcess(process: ChildProcess, signal: NodeJS.Signals | 0): boolean | undefined {\n\t\tconst pid = process.pid\n\t\tconst serving = this.#servingPid\n\t\ttry {\n\t\t\tif (this.#hasProcessGroup(process) && pid !== undefined) {\n\t\t\t\treturn globalThis.process.kill(-pid, signal)\n\t\t\t}\n\t\t\t// Terminating the Chromium browser process takes its whole tree with\n\t\t\t// it, so Windows needs no separate tree walk to reach the renderers,\n\t\t\t// GPU, and utility children the serving process parents.\n\t\t\tif (serving !== undefined) return globalThis.process.kill(serving, signal)\n\t\t\treturn process.kill(signal)\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\tisError(error) && 'code' in error && isString(error.code) ? error.code : undefined\n\t\t\tif (code === 'ESRCH') return false\n\t\t\tif (signal === 0) return code === 'EPERM' ? true : undefined\n\t\t\tthrow new BrowserConnectionError('Failed to signal the browser process', {\n\t\t\t\tpid: serving ?? pid,\n\t\t\t\tsignal,\n\t\t\t\tcause: error,\n\t\t\t})\n\t\t}\n\t}\n\n\tasync #waitForRemainderWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t): Promise<boolean | undefined> {\n\t\tconst deadline = performance.now() + timeout\n\t\tlet confirmed = false\n\t\t// Node observes only the direct child, and neither the rest of a POSIX\n\t\t// process group nor a process the launcher handed the endpoint to raises\n\t\t// an exit event here, so bound the drain probe.\n\t\twhile (true) {\n\t\t\tconst alive = this.#inspectRemainder(process)\n\t\t\tif (alive === false) return true\n\t\t\tif (alive === true) confirmed = true\n\t\t\tconst remaining = deadline - performance.now()\n\t\t\tif (remaining <= 0) return confirmed ? false : undefined\n\t\t\tawait new Promise<void>((resolve) =>\n\t\t\t\tsetTimeout(resolve, Math.min(BROWSER_WAIT_POLL_INTERVAL_MS, remaining)),\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #waitForTerminationWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t\tfinal = false,\n\t): Promise<boolean> {\n\t\tconst exited = this.#waitForProcessWithin(process, timeout)\n\t\tconst drained = this.#waitForRemainderWithin(process, timeout)\n\t\tconst results = await Promise.all([exited, drained])\n\t\treturn results[0] && (results[1] === true || (final && results[1] === undefined))\n\t}\n\n\tasync #terminate(process: ChildProcess | undefined): Promise<void> {\n\t\tif (\n\t\t\tprocess === undefined ||\n\t\t\t((process.exitCode !== null || process.signalCode !== null) &&\n\t\t\t\tthis.#inspectRemainder(process) === false)\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.#signalProcess(process, 'SIGTERM') === false) return\n\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)) return\n\n\t\tif (this.#signalProcess(process, 'SIGKILL') === false) return\n\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS, true)) return\n\n\t\tthrow new BrowserConnectionError('Browser process did not exit after SIGKILL', {\n\t\t\tpid: this.#servingPid ?? process.pid,\n\t\t})\n\t}\n\n\t#finish(): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tthis.#client = undefined\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tthis.#exitCleanup = undefined\n\t\tthis.#contexts = []\n\t\tthis.#emitter.emit('destroy')\n\t\tthis.#emitter.destroy()\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["pathWin32","pathPosix","waitForTimeout","request","httpsRequest","httpRequest"],"sources":["../../../src/server/constants.ts","../../../src/server/errors.ts","../../../src/server/helpers.ts","../../../src/server/transports/WebSocketCDPTransport.ts","../../../src/server/writers/FileBrowserWriter.ts","../../../src/server/factories.ts","../../../src/server/Browser.ts"],"sourcesContent":["import type { BrowserEngine } from './types.js'\n\n// === CDP discovery\n\n/**\n * Sets the default CDP port probed for an existing browser and used for launches, `9222`.\n */\nexport const BROWSER_DEFAULT_CDP_PORT = 9222\n\n/**\n * Sets the default host probed for an existing browser and used for launches, `'127.0.0.1'`,\n * which avoids `localhost` resolving to `::1` when Chromium binds `127.0.0.1`.\n */\nexport const BROWSER_DEFAULT_HOST = '127.0.0.1'\n\n/** Names the protocol prefix for CDP discovery requests, `'http'`. */\nexport const BROWSER_CDP_PROTOCOL = 'http'\n\n/**\n * Names the path appended to the CDP host to fetch version metadata, `'/json/version'`, which\n * is where endpoint discovery reads.\n */\nexport const BROWSER_CDP_VERSION_PATH = '/json/version'\n\n/**\n * Names the path appended to the CDP host to list open targets — pages, workers, and every\n * other target category Chromium reports — `'/json/list'`.\n */\nexport const BROWSER_CDP_LIST_PATH = '/json/list'\n\n// === Browser launch\n\n/** Lists the flags always passed to a launched browser process, alongside the caller's own. */\nexport const BROWSER_LAUNCH_ARGS: readonly string[] = Object.freeze([\n\t'--no-first-run',\n\t'--no-default-browser-check',\n])\n\n/**\n * Names the flag that enables headless mode on a launched browser process, `'--headless=new'`.\n */\nexport const BROWSER_HEADLESS_ARG = '--headless=new'\n\n/**\n * Names the prefix for isolated browser profiles created beneath the operating-system temp\n * directory, `'orkestrel-browser-'`.\n */\nexport const BROWSER_PROFILE_PREFIX = 'orkestrel-browser-'\n\n/**\n * Bounds each launched-process exit window during TERM-to-KILL teardown at `3_000`\n * milliseconds.\n */\nexport const BROWSER_KILL_GRACE_MS = 3_000\n\n/**\n * Bounds the `discover: false` port-occupancy probe before launching at `200` milliseconds,\n * which is short because the probe only needs to detect an already-listening CDP endpoint\n * rather than perform full discovery.\n */\nexport const BROWSER_PORT_PROBE_TIMEOUT_MS = 200\n\n/**\n * Defers once for `50` milliseconds when a transport loss is observed on an owned process,\n * giving a near-simultaneous process-exit event, which libuv may reap slightly later than the\n * socket close, first say over the diagnosis.\n */\nexport const BROWSER_TRANSPORT_LOSS_DEFER_MS = 50\n\n/**\n * Names the machine-readable error-context cause for an owned browser process exiting,\n * `'process-exit'`.\n */\nexport const BROWSER_PROCESS_EXIT_CAUSE = 'process-exit'\n\n/**\n * Names the machine-readable error-context cause for a CDP transport disconnecting while its\n * browser remains alive, `'transport-loss'`.\n */\nexport const BROWSER_TRANSPORT_LOSS_CAUSE = 'transport-loss'\n\n/**\n * Lists the environment variables checked, in order, for an explicit browser executable path\n * override: `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH`.\n */\nexport const BROWSER_ENV_PATH_KEYS: readonly string[] = Object.freeze([\n\t'PLAYWRIGHT_EXECUTABLE_PATH',\n\t'CHROME_PATH',\n])\n\n/**\n * Lists the well-known Chrome/Chromium/Edge executable paths with no platform-specific root,\n * keyed by `process.platform`, leaving `win32` empty because its roots come from\n * `BROWSER_WINDOWS_SUFFIXES`.\n */\nexport const BROWSER_EXECUTABLE_PATHS: Readonly<Record<string, readonly string[]>> = Object.freeze({\n\tlinux: Object.freeze([\n\t\t'/usr/bin/google-chrome',\n\t\t'/usr/bin/google-chrome-stable',\n\t\t'/usr/bin/microsoft-edge',\n\t\t'/usr/bin/microsoft-edge-stable',\n\t\t'/usr/bin/chromium',\n\t\t'/usr/bin/chromium-browser',\n\t\t'/snap/bin/chromium',\n\t\t'/opt/google/chrome/chrome',\n\t\t'/opt/microsoft/msedge/msedge',\n\t]),\n\tdarwin: Object.freeze([\n\t\t'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n\t\t'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n\t\t'/Applications/Chromium.app/Contents/MacOS/Chromium',\n\t]),\n\twin32: Object.freeze([]),\n})\n\n/** Lists the Windows install-root-relative suffixes for Chrome/Edge/Chromium, joined against each candidate root (`PROGRAMFILES`, `PROGRAMFILES(X86)`, `LOCALAPPDATA`). */\nexport const BROWSER_WINDOWS_SUFFIXES: readonly string[] = Object.freeze([\n\t'Google\\\\Chrome\\\\Application\\\\chrome.exe',\n\t'Microsoft\\\\Edge\\\\Application\\\\msedge.exe',\n\t'Chromium\\\\Application\\\\chrome.exe',\n])\n\n/**\n * Lists the fallback Windows install roots used when `PROGRAMFILES`, `PROGRAMFILES(X86)`, or\n * `LOCALAPPDATA` is absent.\n */\nexport const BROWSER_WINDOWS_ROOT_FALLBACKS: Readonly<Record<string, string>> = Object.freeze({\n\tPROGRAMFILES: 'C:\\\\Program Files',\n\t'PROGRAMFILES(X86)': 'C:\\\\Program Files (x86)',\n})\n\n/** Lists the command names probed on PATH when no well-known executable path exists. */\nexport const BROWSER_EXECUTABLE_NAMES: readonly string[] = Object.freeze([\n\t'google-chrome',\n\t'google-chrome-stable',\n\t'msedge',\n\t'microsoft-edge',\n\t'chromium',\n\t'chromium-browser',\n\t'chrome',\n])\n\n/**\n * Names the environment variable that carries an additional Playwright browser store base\n * directory, `'PLAYWRIGHT_BROWSERS_PATH'`.\n */\nexport const BROWSER_STORE_ENV_KEY = 'PLAYWRIGHT_BROWSERS_PATH'\n\n/**\n * Lists the well-known Playwright browser store base directories checked in addition to\n * `PLAYWRIGHT_BROWSERS_PATH`, starting with `/opt/pw-browsers`.\n */\nexport const BROWSER_STORE_DEFAULT_DIRS: readonly string[] = Object.freeze(['/opt/pw-browsers'])\n\n/** Names the per-OS default Playwright browser cache directory, relative to the home directory (win32 uses `LOCALAPPDATA` directly). */\nexport const BROWSER_STORE_CACHE_DIRS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: '.cache/ms-playwright',\n\tdarwin: 'Library/Caches/ms-playwright',\n})\n\n/**\n * Names the top-level Chromium symlink or binary Playwright maintains inside a browser store\n * base, `'chromium'`.\n */\nexport const BROWSER_STORE_LINK_NAME = 'chromium'\n\n/**\n * Lists the case-insensitive substrings identifying an executable path/name's browser\n * engine, checked by `parseBrowserEngine` in the order `edge` → `chromium` → `chrome`.\n */\nexport const BROWSER_ENGINE_HINTS: Readonly<Record<BrowserEngine, readonly string[]>> =\n\tObject.freeze({\n\t\tedge: Object.freeze(['msedge', 'microsoft-edge', 'edge']),\n\t\tchromium: Object.freeze([\n\t\t\t'chromium',\n\t\t\t'pw-browsers',\n\t\t\t'chrome-linux',\n\t\t\t'chrome-win',\n\t\t\t'chrome-mac',\n\t\t\t'chrome_headless',\n\t\t]),\n\t\tchrome: Object.freeze(['google-chrome', 'google/chrome', 'google\\\\chrome', 'chrome']),\n\t})\n\n/** Names the glob pattern (relative to a store base) matching a versioned Chromium binary, keyed by `process.platform`. */\nexport const BROWSER_STORE_GLOBS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: 'chromium-*/chrome-linux*/chrome',\n\tdarwin: 'chromium-*/chrome-mac*/Chromium.app/Contents/MacOS/Chromium',\n\twin32: 'chromium-*/chrome-win*/chrome.exe',\n})\n","import { BrowserError } from '@src/core'\nimport { isInstance } from '@orkestrel/contract'\n\n// === Server browser errors\n\n/**\n * Reports that a CDP connection, discovery, or launch attempt failed, under the code\n * `BROWSER_CONNECTION_ERROR`.\n */\nexport class BrowserConnectionError extends BrowserError {\n\tconstructor(message: string, context?: Readonly<Record<string, unknown>>) {\n\t\tsuper(message, 'BROWSER_CONNECTION_ERROR', context)\n\t\tthis.name = 'BrowserConnectionError'\n\t}\n}\n\n/**\n * Reports that an operation requiring an active connection was attempted while disconnected,\n * under the code `BROWSER_NOT_CONNECTED_ERROR`.\n */\nexport class BrowserNotConnectedError extends BrowserError {\n\tconstructor(context?: Readonly<Record<string, unknown>>) {\n\t\tsuper('Browser is not connected', 'BROWSER_NOT_CONNECTED_ERROR', context)\n\t\tthis.name = 'BrowserNotConnectedError'\n\t}\n}\n\n/**\n * Reports that an operation was attempted after the browser wrapper was destroyed, under the\n * code `BROWSER_DESTROYED_ERROR`.\n */\nexport class BrowserDestroyedError extends BrowserError {\n\tconstructor(context?: Readonly<Record<string, unknown>>) {\n\t\tsuper('Browser has been destroyed', 'BROWSER_DESTROYED_ERROR', context)\n\t\tthis.name = 'BrowserDestroyedError'\n\t}\n}\n\n// === Server browser type guards\n\n/**\n * Narrows an unknown value to a `BrowserConnectionError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserConnectionError instance; false otherwise\n */\nexport function isBrowserConnectionError(value: unknown): value is BrowserConnectionError {\n\treturn isInstance(value, BrowserConnectionError)\n}\n\n/**\n * Narrows an unknown value to a `BrowserNotConnectedError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserNotConnectedError instance; false otherwise\n */\nexport function isBrowserNotConnectedError(value: unknown): value is BrowserNotConnectedError {\n\treturn isInstance(value, BrowserNotConnectedError)\n}\n\n/**\n * Narrows an unknown value to a `BrowserDestroyedError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserDestroyedError instance; false otherwise\n */\nexport function isBrowserDestroyedError(value: unknown): value is BrowserDestroyedError {\n\treturn isInstance(value, BrowserDestroyedError)\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type { CDPTarget } from '@src/core'\nimport type { Result } from '@orkestrel/contract'\nimport type {\n\tBrowserEngine,\n\tBrowserProfileResult,\n\tSystemBrowser,\n\tSystemBrowserOptions,\n} from './types.js'\nimport { existsSync, globSync } from 'node:fs'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, resolve, win32 as pathWin32, posix as pathPosix } from 'node:path'\nimport { spawn, spawnSync } from 'node:child_process'\nimport { setTimeout as waitForTimeout } from 'node:timers/promises'\nimport { isArray, isRecord, isString } from '@orkestrel/contract'\nimport { BROWSER_WAIT_POLL_INTERVAL_MS, BrowserError } from '@src/core'\nimport { BrowserConnectionError } from './errors.js'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_VERSION_PATH,\n\tBROWSER_CDP_LIST_PATH,\n\tBROWSER_ENV_PATH_KEYS,\n\tBROWSER_EXECUTABLE_PATHS,\n\tBROWSER_EXECUTABLE_NAMES,\n\tBROWSER_WINDOWS_SUFFIXES,\n\tBROWSER_WINDOWS_ROOT_FALLBACKS,\n\tBROWSER_STORE_ENV_KEY,\n\tBROWSER_STORE_DEFAULT_DIRS,\n\tBROWSER_STORE_CACHE_DIRS,\n\tBROWSER_STORE_LINK_NAME,\n\tBROWSER_STORE_GLOBS,\n\tBROWSER_ENGINE_HINTS,\n\tBROWSER_LAUNCH_ARGS,\n\tBROWSER_HEADLESS_ARG,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_PROFILE_PREFIX,\n} from './constants.js'\n\n// === Discovery helpers\n\n/**\n * Enumerates every Chrome/Chromium/Edge executable discoverable on this\n * machine, deduplicated by normalized absolute path.\n *\n * @remarks\n * Resolution precedence (candidates appended in this order):\n * 1. `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH` — explicit environment\n * overrides that exist on disk\n * 2. Well-known platform install locations (Chrome, Edge, Chromium); Windows\n * roots are derived from `PROGRAMFILES` / `PROGRAMFILES(X86)` / `LOCALAPPDATA`\n * 3. PATH probe for known command names (`which` on POSIX, `where` on Windows)\n * 4. Playwright-managed browser stores (`PLAYWRIGHT_BROWSERS_PATH`, `/opt/pw-browsers`,\n * and the per-OS Playwright cache directory) — the top-level `chromium`\n * link/binary, then the highest-revision `chromium-*` install found\n *\n * Each candidate is classified into a {@link BrowserEngine} through\n * `parseBrowserEngine` (unclassifiable candidates default to `'chromium'`),\n * and `options.engine` (when given) narrows the result to that engine.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns Every discovered browser, in resolution-precedence order\n */\nexport function findSystemBrowsers(options?: SystemBrowserOptions): readonly SystemBrowser[] {\n\tconst platform = process.platform\n\tconst env = options?.env ?? process.env\n\n\tconst candidates: string[] = []\n\n\tcandidates.push(...findEnvOverrides(env))\n\n\tconst paths = options?.paths ?? buildInstallPaths(platform, env)\n\tcandidates.push(...findInstallPaths(paths))\n\n\tconst names = options?.names ?? BROWSER_EXECUTABLE_NAMES\n\tcandidates.push(...probePathNames(names, platform))\n\n\tconst stores = options?.stores ?? buildStoreBases(env, platform)\n\tfor (const store of stores) {\n\t\tcandidates.push(...findStorePaths(store, platform))\n\t}\n\n\tconst seen = new Set<string>()\n\tconst browsers: SystemBrowser[] = []\n\n\tfor (const executable of candidates) {\n\t\tconst key = normalizeExecutablePath(executable, platform)\n\t\tif (seen.has(key)) continue\n\t\tseen.add(key)\n\n\t\tconst engine = parseBrowserEngine(executable) ?? 'chromium'\n\t\tif (options?.engine !== undefined && engine !== options.engine) continue\n\n\t\tbrowsers.push({ executable, engine })\n\t}\n\n\treturn browsers\n}\n\n/**\n * Locates a Chrome/Chromium/Edge executable on this machine — the first entry\n * of {@link findSystemBrowsers}.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns The first discovered browser, or undefined\n */\nexport function findSystemBrowser(options?: SystemBrowserOptions): SystemBrowser | undefined {\n\treturn findSystemBrowsers(options)[0]\n}\n\n/**\n * Classifies an executable path/name into a {@link BrowserEngine} by\n * case-insensitive hint, checked in the order edge → chromium → chrome.\n *\n * @param executable - Executable path or command name to classify\n * @returns The classified engine, or undefined when no hint matches\n */\nexport function parseBrowserEngine(executable: string): BrowserEngine | undefined {\n\tconst lower = executable.toLowerCase()\n\tconst order: readonly BrowserEngine[] = ['edge', 'chromium', 'chrome']\n\tfor (const engine of order) {\n\t\tconst hints = BROWSER_ENGINE_HINTS[engine]\n\t\tif (hints.some((hint) => lower.includes(hint))) return engine\n\t}\n\treturn undefined\n}\n\n/** Normalizes an executable path for cross-source deduplication (case-insensitive on Windows). */\nexport function normalizeExecutablePath(path: string, platform: string): string {\n\tconst normalized = platform === 'win32' ? pathWin32.normalize(path) : pathPosix.normalize(path)\n\treturn platform === 'win32' ? normalized.toLowerCase() : normalized\n}\n\n/** Classifies a `/json/version` `Browser` string into a {@link BrowserEngine} (`Edg/` → edge, `Chrome/` → chrome, else chromium). */\nexport function browserToEngine(browser?: string): BrowserEngine {\n\tif (browser?.includes('Edg/') === true) return 'edge'\n\tif (browser?.includes('Chrome/') === true) return 'chrome'\n\treturn 'chromium'\n}\n\n/**\n * Resolves a persistent caller profile or creates an isolated temporary one.\n *\n * @param path - Optional caller-owned persistent user-data directory\n * @returns The resolved profile and whether the library owns its lifecycle\n */\nexport async function createBrowserProfile(path?: string): Promise<BrowserProfileResult> {\n\tif (path !== undefined) return { path, temporary: false }\n\tconst directory = await mkdtemp(join(tmpdir(), BROWSER_PROFILE_PREFIX))\n\treturn { path: directory, temporary: true }\n}\n\n/**\n * Removes a library-owned isolated browser profile.\n *\n * @remarks\n * The path must remain a direct child of the operating-system temp directory\n * with {@link BROWSER_PROFILE_PREFIX}; this defensive check prevents a\n * malformed profile value from widening recursive deletion.\n *\n * @param profile - Resolved profile lifecycle result\n */\nexport async function removeBrowserProfile(profile: BrowserProfileResult): Promise<void> {\n\tif (!profile.temporary) return\n\tconst path = resolve(profile.path)\n\tconst temporary = resolve(tmpdir())\n\tif (dirname(path) !== temporary || !basename(path).startsWith(BROWSER_PROFILE_PREFIX)) {\n\t\tthrow new BrowserError('Refusing to remove an unsafe browser profile path', undefined, {\n\t\t\tpath,\n\t\t})\n\t}\n\tawait rm(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })\n}\n\n/** Checks the env-override keys (`PLAYWRIGHT_EXECUTABLE_PATH`, `CHROME_PATH`) in order and returns every one that exists. */\nexport function findEnvOverrides(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst found: string[] = []\n\tfor (const key of BROWSER_ENV_PATH_KEYS) {\n\t\tconst value = env[key]\n\t\tif (value !== undefined && value.length > 0 && existsSync(value)) found.push(value)\n\t}\n\treturn found\n}\n\n/** Builds the default well-known install-path candidates for a platform, deriving Windows roots from env vars. */\nexport function buildInstallPaths(\n\tplatform: string,\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tif (platform !== 'win32') return BROWSER_EXECUTABLE_PATHS[platform] ?? []\n\n\tconst roots = buildWindowsRoots(env)\n\tconst paths: string[] = []\n\tfor (const root of roots) {\n\t\tfor (const suffix of BROWSER_WINDOWS_SUFFIXES) {\n\t\t\tpaths.push(pathWin32.join(root, suffix))\n\t\t}\n\t}\n\treturn paths\n}\n\n/** Derives Windows install roots from env vars, falling back to well-known literals when absent. */\nexport function buildWindowsRoots(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst programFiles = env['PROGRAMFILES'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES']\n\tconst programFilesX86 =\n\t\tenv['PROGRAMFILES(X86)'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES(X86)']\n\tconst localAppData = env['LOCALAPPDATA']\n\n\tconst roots = [programFiles, programFilesX86, localAppData]\n\treturn roots.filter((root): root is string => root !== undefined)\n}\n\n/** Returns every candidate path that exists on disk, in the given order. */\nexport function findInstallPaths(paths: readonly string[]): readonly string[] {\n\treturn paths.filter((path) => existsSync(path))\n}\n\n/** Probes PATH (`which`/`where`) for every resolvable command name, in the given order. */\nexport function probePathNames(names: readonly string[], platform: string): readonly string[] {\n\tconst finder = platform === 'win32' ? 'where' : 'which'\n\tconst found: string[] = []\n\tfor (const name of names) {\n\t\tconst result = spawnSync(finder, [name], { stdio: 'pipe' })\n\t\tif (result.status === 0) {\n\t\t\tconst executable = readFirstLine(result.stdout.toString('utf-8'))\n\t\t\tif (executable !== undefined) found.push(executable)\n\t\t}\n\t}\n\treturn found\n}\n\n/**\n * Returns the first non-empty line of a command's output, without its\n * surrounding whitespace.\n *\n * @remarks\n * `where` reports every PATH match on its own CRLF-terminated line, so a\n * carriage return left on the first line would travel into `existsSync` and\n * `spawn` as part of the executable path.\n *\n * @param output - Raw decoded standard output of a command\n * @returns The first line carrying text, or undefined when the output has none\n *\n * @example\n * ```ts\n * readFirstLine('C:\\\\bin\\\\chrome.exe\\r\\nC:\\\\other\\\\chrome.exe\\r\\n') // 'C:\\\\bin\\\\chrome.exe'\n * ```\n */\nexport function readFirstLine(output: string): string | undefined {\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tconst text = line.trim()\n\t\tif (text.length > 0) return text\n\t}\n\treturn undefined\n}\n\n/** Builds the default Playwright browser store base directories to search for a managed Chromium. */\nexport function buildStoreBases(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tplatform: string,\n): readonly string[] {\n\tconst bases: string[] = []\n\n\tconst envBase = env[BROWSER_STORE_ENV_KEY]\n\tif (envBase !== undefined && envBase.length > 0) bases.push(envBase)\n\n\tbases.push(...BROWSER_STORE_DEFAULT_DIRS)\n\n\tif (platform === 'win32') {\n\t\tconst localAppData = env['LOCALAPPDATA']\n\t\tif (localAppData !== undefined) bases.push(pathWin32.join(localAppData, 'ms-playwright'))\n\t} else {\n\t\tconst cacheDir = BROWSER_STORE_CACHE_DIRS[platform]\n\t\tconst home = env['HOME']\n\t\tif (cacheDir !== undefined && home !== undefined) bases.push(pathPosix.join(home, cacheDir))\n\t}\n\n\treturn bases\n}\n\n/** Searches one store base for the top-level `chromium` link and every `chromium-*` install, highest revision first. */\nexport function findStorePaths(base: string, platform: string): readonly string[] {\n\tconst joiner = platform === 'win32' ? pathWin32.join : pathPosix.join\n\tconst found: string[] = []\n\n\tconst linkPath = joiner(base, BROWSER_STORE_LINK_NAME)\n\tif (existsSync(linkPath)) found.push(linkPath)\n\n\tconst glob = BROWSER_STORE_GLOBS[platform]\n\tif (glob === undefined) return found\n\n\tconst pattern = `${base.replaceAll('\\\\', '/')}/${glob}`\n\tconst matches = globSync(pattern).filter((match) => existsSync(match))\n\tmatches.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))\n\tfound.push(...matches)\n\n\treturn found\n}\n\n/**\n * Launches a browser process with raw-CDP debugging flags.\n *\n * @remarks\n * POSIX launches own an isolated process group so lifecycle teardown can\n * signal and await every Chromium subprocess without affecting the caller.\n * Windows launches are not detached and own no group, so teardown there\n * signals one process by identifier: the spawned process, or the process the\n * launcher handed the endpoint to when that spawned process re-executed the\n * browser and exited. Terminating a Chromium browser process takes its own\n * subprocesses with it, so that single signal drains the tree.\n *\n * @param executable - Absolute path to the browser executable\n * @param port - Port the browser exposes its CDP endpoint on\n * @param headless - Whether to launch in headless mode\n * @param profile - Optional user-data-dir for a persistent profile\n * @param extra - Additional command-line flags\n * @returns The spawned ChildProcess\n */\nexport function launchBrowserProcess(\n\texecutable: string,\n\tport: number,\n\theadless: boolean,\n\tprofile?: string,\n\textra?: readonly string[],\n): ChildProcess {\n\t// Caller-supplied args come first so a script path (for example `node <script>`,\n\t// used to spawn a Node stand-in executable cross-platform in tests) lands\n\t// as an early positional argv entry ahead of the CDP flags that follow —\n\t// Chromium itself accepts flags in any order, so production is unaffected.\n\tconst args: string[] = []\n\tif (extra !== undefined) args.push(...extra)\n\targs.push(`--remote-debugging-port=${port}`, ...BROWSER_LAUNCH_ARGS)\n\n\tif (headless) args.push(BROWSER_HEADLESS_ARG)\n\tif (profile !== undefined) args.push(`--user-data-dir=${profile}`)\n\n\treturn spawn(executable, args, {\n\t\tstdio: 'ignore',\n\t\tdetached: process.platform !== 'win32',\n\t})\n}\n\n/**\n * Polls a browser's CDP version endpoint until it responds or the timeout elapses.\n *\n * @param port - Port the browser exposes its CDP endpoint on\n * @param timeout - Maximum time to wait in milliseconds\n * @param host - Host the browser exposes its CDP endpoint on (default `127.0.0.1`)\n * @param signal - Optional external abort; an abort while waiting rethrows rather than resolving\n * @returns The browser's WebSocket debugger URL\n *\n * @throws When the endpoint does not become ready before the timeout\n */\nexport async function waitForCDPReady(\n\tport: number,\n\ttimeout: number,\n\thost: string = BROWSER_DEFAULT_HOST,\n\tsignal?: AbortSignal,\n): Promise<string> {\n\tconst url = `${BROWSER_CDP_PROTOCOL}://${host}:${port}${BROWSER_CDP_VERSION_PATH}`\n\tconst deadline = Date.now() + timeout\n\n\twhile (Date.now() < deadline) {\n\t\tsignal?.throwIfAborted()\n\t\tconst remaining = Math.max(0, deadline - Date.now())\n\t\tconst requestSignal =\n\t\t\tsignal === undefined\n\t\t\t\t? AbortSignal.timeout(remaining)\n\t\t\t\t: AbortSignal.any([signal, AbortSignal.timeout(remaining)])\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: requestSignal })\n\t\t\tif (response.ok) {\n\t\t\t\tconst info: unknown = await response.json()\n\t\t\t\tif (isRecord(info) && isString(info['webSocketDebuggerUrl'])) {\n\t\t\t\t\treturn info['webSocketDebuggerUrl']\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted === true) throw error\n\t\t\t// Not ready yet — keep polling\n\t\t}\n\n\t\tconst delay = Math.min(BROWSER_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now()))\n\t\tif (delay > 0) await waitForTimeout(delay, undefined, { signal })\n\t}\n\n\tthrow new BrowserConnectionError(\n\t\t`CDP endpoint on port ${port} did not become ready within ${timeout}ms`,\n\t\t{ port, timeout },\n\t)\n}\n\n/**\n * Fetches the current CDP target list from a browser's `/json/list` endpoint, as a `Result`\n * carrying either the targets or a coded `BrowserConnectionError`.\n *\n * @remarks\n * The endpoint is a network boundary, so an unreachable host, a non-2xx\n * response, and a body that is not a JSON array each come back as a failed\n * `Result` carrying a coded `BrowserConnectionError`. An entry missing a\n * required string field is skipped rather than failing the whole list.\n *\n * @param port - Port the browser exposes its CDP endpoint on\n * @param timeout - Request timeout in milliseconds\n * @param host - Host the browser exposes its CDP endpoint on (default `127.0.0.1`)\n * @returns The normalized CDP targets, or the fault that stopped the request\n *\n * @example\n * ```ts\n * import { fetchCDPTargets } from '@orkestrel/browser/server'\n *\n * const result = await fetchCDPTargets(9222, 2000)\n * if (result.success) log(result.value.length)\n * else log(result.error.code)\n * ```\n */\nexport async function fetchCDPTargets(\n\tport: number,\n\ttimeout: number,\n\thost: string = BROWSER_DEFAULT_HOST,\n): Promise<Result<readonly CDPTarget[], BrowserError>> {\n\tconst url = `${BROWSER_CDP_PROTOCOL}://${host}:${port}${BROWSER_CDP_LIST_PATH}`\n\tconst controller = new AbortController()\n\tconst timer = setTimeout(() => controller.abort(), timeout)\n\n\ttry {\n\t\tconst response = await fetch(url, { signal: controller.signal })\n\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserConnectionError('CDP target list request was refused', {\n\t\t\t\t\turl,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t}),\n\t\t\t}\n\t\t}\n\n\t\tconst list: unknown = await response.json()\n\t\tif (!isArray(list)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserConnectionError('CDP target list is not a JSON array', { url }),\n\t\t\t}\n\t\t}\n\n\t\tconst targets: CDPTarget[] = []\n\t\tfor (const entry of list) {\n\t\t\tif (!isRecord(entry)) continue\n\t\t\tif (\n\t\t\t\t!isString(entry['id']) ||\n\t\t\t\t!isString(entry['type']) ||\n\t\t\t\t!isString(entry['title']) ||\n\t\t\t\t!isString(entry['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttargets.push({\n\t\t\t\tid: entry['id'],\n\t\t\t\tcategory: entry['type'],\n\t\t\t\ttitle: entry['title'],\n\t\t\t\turl: entry['url'],\n\t\t\t})\n\t\t}\n\n\t\treturn { success: true, value: targets }\n\t} catch (error) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: new BrowserConnectionError('CDP target list is unreachable', { url, error }),\n\t\t}\n\t} finally {\n\t\tclearTimeout(timer)\n\t}\n}\n","import type { CDPTransportEventMap, CDPTransportInterface } from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { NodeWebSocketInterface } from '@orkestrel/websocket'\nimport type { WebSocketCDPTransportOptions } from '../types.js'\nimport type { ClientRequest, IncomingMessage, RequestOptions } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport { randomBytes } from 'node:crypto'\nimport { request as httpRequest } from 'node:http'\nimport { request as httpsRequest } from 'node:https'\nimport { attempt, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tcomputeWebSocketAccept,\n\tcreateNodeWebSocket,\n\tWEBSOCKET_READY_CLOSED,\n\tWEBSOCKET_READY_OPEN,\n\tWEBSOCKET_VERSION,\n} from '@orkestrel/websocket'\nimport { BROWSER_DEFAULT_TIMEOUT_MS, BrowserTransition } from '@src/core'\nimport { BrowserConnectionError } from '../errors.js'\n\n// === WebSocketCDPTransport\n\n/**\n * Provides a raw CDP text transport backed by `@orkestrel/websocket`.\n *\n * @remarks\n * Performs and validates the RFC 6455 HTTP upgrade, then delegates frame\n * handling to `@orkestrel/websocket`. Concurrent and repeated `start()` /\n * `close()` calls share their active transition, and a later `start()` opens a\n * fresh socket after the prior one closes.\n *\n * @example\n * ```ts\n * import { WebSocketCDPTransport } from '@orkestrel/browser/server'\n *\n * const transport = new WebSocketCDPTransport({ url: 'ws://127.0.0.1:9222/devtools/browser/abc' })\n * await transport.start()\n * await transport.close()\n * ```\n */\nexport class WebSocketCDPTransport implements CDPTransportInterface {\n\treadonly #emitter: Emitter<CDPTransportEventMap>\n\treadonly #url: string\n\treadonly #timeout: number\n\t#socket: NodeWebSocketInterface | undefined\n\treadonly #starting: BrowserTransition = new BrowserTransition()\n\treadonly #closing: BrowserTransition = new BrowserTransition()\n\t#request: ClientRequest | undefined\n\t#resolve: ((socket: NodeWebSocketInterface) => void) | undefined\n\t#reject: ((error: unknown) => void) | undefined\n\t#timer: ReturnType<typeof setTimeout> | undefined\n\t#closeResolve: (() => void) | undefined\n\treadonly #socketCloseHandler = this.#handleSocketClose.bind(this)\n\n\tconstructor(options: WebSocketCDPTransportOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#url = options.url\n\t\tthis.#timeout = options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tget emitter(): EmitterInterface<CDPTransportEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tasync start(): Promise<void> {\n\t\tconst closing = this.#closing.pending\n\t\tif (closing !== undefined) await closing\n\t\tif (this.#socket?.readyState === WEBSOCKET_READY_OPEN) return\n\n\t\tconst active = this.#starting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\n\t\tthis.#socket?.destroy()\n\t\tthis.#socket = undefined\n\t\tawait this.#starting.execute(() => this.#start())\n\t}\n\n\tasync send(data: string): Promise<void> {\n\t\tconst socket = this.#socket\n\t\tif (socket === undefined || socket.readyState !== WEBSOCKET_READY_OPEN) {\n\t\t\tthrow new BrowserConnectionError('WebSocket CDP transport is not open', { url: this.#url })\n\t\t}\n\t\tsocket.send(data)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.#closing.execute(() => this.#close())\n\t}\n\n\t// === Private helpers\n\n\tasync #start(): Promise<void> {\n\t\tconst parsed = attempt(() => new URL(this.#url))\n\t\tif (!parsed.success) {\n\t\t\tthrow new BrowserConnectionError(`WebSocket CDP URL is invalid: ${this.#url}`, {\n\t\t\t\turl: this.#url,\n\t\t\t\terror: parsed.error,\n\t\t\t})\n\t\t}\n\t\tconst url = parsed.value\n\t\tif (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection requires a ws: or wss: URL: ${this.#url}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t)\n\t\t}\n\t\tconst key = randomBytes(16).toString('base64')\n\t\tconst deferred = Promise.withResolvers<NodeWebSocketInterface>()\n\t\tconst options: RequestOptions = {\n\t\t\thostname: url.hostname,\n\t\t\tport: url.port.length > 0 ? Number(url.port) : url.protocol === 'wss:' ? 443 : 80,\n\t\t\tpath: `${url.pathname}${url.search}`,\n\t\t\theaders: {\n\t\t\t\tConnection: 'Upgrade',\n\t\t\t\tUpgrade: 'websocket',\n\t\t\t\t'Sec-WebSocket-Key': key,\n\t\t\t\t'Sec-WebSocket-Version': WEBSOCKET_VERSION,\n\t\t\t},\n\t\t}\n\t\tconst request = url.protocol === 'wss:' ? httpsRequest(options) : httpRequest(options)\n\n\t\tthis.#request = request\n\t\tthis.#resolve = deferred.resolve\n\t\tthis.#reject = deferred.reject\n\t\tthis.#timer = setTimeout(() => this.#expire(request), this.#timeout)\n\n\t\trequest.on('upgrade', (response: IncomingMessage, socket: Duplex, head: Buffer) => {\n\t\t\tthis.#upgrade(request, key, response, socket, head)\n\t\t})\n\t\trequest.on('response', (response) => this.#decline(request, response))\n\t\trequest.on('error', (error) => this.#fail(request, error))\n\t\trequest.end()\n\n\t\tconst socket = await deferred.promise\n\t\tthis.#socket = socket\n\t\tthis.#bind(socket)\n\t}\n\n\tasync #close(): Promise<void> {\n\t\tconst request = this.#request\n\t\tif (request !== undefined) {\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} was closed before it finished connecting`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\trequest.destroy()\n\t\t}\n\t\tawait this.#starting.pending?.catch(() => undefined)\n\n\t\tconst socket = this.#socket\n\t\tthis.#socket = undefined\n\t\tif (socket === undefined || socket.readyState === WEBSOCKET_READY_CLOSED) return\n\n\t\tconst closed = Promise.withResolvers<void>()\n\t\tthis.#closeResolve = closed.resolve\n\t\tsocket.emitter.on('close', this.#socketCloseHandler)\n\t\ttry {\n\t\t\tsocket.close()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} catch {\n\t\t\tsocket.destroy()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} finally {\n\t\t\tsocket.emitter.off('close', this.#socketCloseHandler)\n\t\t\tthis.#closeResolve = undefined\n\t\t}\n\t}\n\n\t#upgrade(\n\t\trequest: ClientRequest,\n\t\tkey: string,\n\t\tresponse: IncomingMessage,\n\t\tsocket: Duplex,\n\t\thead: Buffer,\n\t): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst accept = response.headers['sec-websocket-accept']\n\t\tif (!isString(accept) || accept !== computeWebSocketAccept(key)) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: Sec-WebSocket-Accept mismatch`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tthis.#resolveRequest(request, createNodeWebSocket({ socket, head }))\n\t\t} catch (error) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(request, error)\n\t\t}\n\t}\n\n\t#decline(request: ClientRequest, response: IncomingMessage): void {\n\t\tresponse.resume()\n\t\tconst reason =\n\t\t\tresponse.statusCode === undefined\n\t\t\t\t? 'upgrade was declined without a status code'\n\t\t\t\t: `upgrade declined with status ${response.statusCode}`\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(`WebSocket CDP connection to ${this.#url} failed: ${reason}`, {\n\t\t\t\turl: this.#url,\n\t\t\t}),\n\t\t)\n\t}\n\n\t#fail(request: ClientRequest, error: Error): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: ${error.message}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t),\n\t\t)\n\t}\n\n\t#expire(request: ClientRequest): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection to ${this.#url} timed out after ${this.#timeout}ms`,\n\t\t\t\t{ url: this.#url, timeout: this.#timeout },\n\t\t\t),\n\t\t)\n\t\trequest.destroy()\n\t}\n\n\t#resolveRequest(request: ClientRequest, socket: NodeWebSocketInterface): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst resolve = this.#resolve\n\t\tthis.#clearRequest()\n\t\tresolve?.(socket)\n\t}\n\n\t#rejectRequest(request: ClientRequest, error: unknown): void {\n\t\tif (this.#request !== request) return\n\n\t\tconst reject = this.#reject\n\t\tthis.#clearRequest()\n\t\treject?.(error)\n\t}\n\n\t#clearRequest(): void {\n\t\tif (this.#timer !== undefined) clearTimeout(this.#timer)\n\t\tthis.#timer = undefined\n\t\tthis.#request = undefined\n\t\tthis.#resolve = undefined\n\t\tthis.#reject = undefined\n\t}\n\n\t#bind(socket: NodeWebSocketInterface): void {\n\t\tsocket.emitter.on('message', (data) => this.#emitter.emit('message', data))\n\t\tsocket.emitter.on('close', () => {\n\t\t\tif (this.#socket === socket) this.#socket = undefined\n\t\t\tthis.#emitter.emit('close')\n\t\t})\n\t\tsocket.emitter.on('error', (error) => this.#emitter.emit('error', error))\n\t}\n\n\t#handleSocketClose(): void {\n\t\tthis.#closeResolve?.()\n\t}\n}\n","import type { BrowserWriterInterface } from '@src/core'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\n\n// === FileBrowserWriter\n\n/**\n * Persists captured browser bytes to the filesystem through `node:fs/promises`.\n *\n * @remarks\n * Creates every missing parent directory of the target path before writing, so\n * a caller may name a nested destination that does not exist yet.\n *\n * @example\n * ```ts\n * import { FileBrowserWriter } from '@orkestrel/browser/server'\n *\n * const writer = new FileBrowserWriter()\n * await writer.write('shots/hero.png', new Uint8Array([137, 80, 78, 71]))\n * ```\n */\nexport class FileBrowserWriter implements BrowserWriterInterface {\n\t/**\n\t * Writes the captured bytes to a path, creating its parent directories.\n\t *\n\t * @param path - Destination file path\n\t * @param data - Captured bytes to persist\n\t * @returns A promise resolving once the bytes are on disk\n\t */\n\tasync write(path: string, data: Uint8Array): Promise<void> {\n\t\tawait mkdir(dirname(path), { recursive: true })\n\t\tawait writeFile(path, data)\n\t}\n}\n","import type { CDPTransportInterface, BrowserWriterInterface } from '@src/core'\nimport type { BrowserInterface, BrowserOptions, WebSocketCDPTransportOptions } from './types.js'\nimport { Browser } from './Browser.js'\nimport { WebSocketCDPTransport } from './transports/WebSocketCDPTransport.js'\nimport { FileBrowserWriter } from './writers/FileBrowserWriter.js'\n\n/**\n * Creates a raw-CDP `BrowserInterface` façade with discovery, connection, and lifecycle\n * management.\n *\n * @param options - Connection, launch, and viewport configuration\n * @returns A {@link BrowserInterface}\n *\n * @example Connect to a browser and drive a page\n * ```ts\n * import { createBrowser } from '@orkestrel/browser/server'\n *\n * const browser = createBrowser({ headless: true })\n * await browser.connect() // CDP endpoint discovery → connect, else launch\n * const page = await browser.create({ url: 'https://example.com' })\n * await page.click('#accept')\n * const shot = await page.screenshot({ path: './out.png' })\n * await browser.destroy()\n * ```\n */\nexport function createBrowser(options?: BrowserOptions): BrowserInterface {\n\treturn new Browser(options)\n}\n\n/**\n * Creates a Node `WebSocket`-backed `CDPTransportInterface` for the given CDP debugger URL.\n *\n * @param options - The CDP WebSocket debugger URL (and optional timeout)\n * @returns A {@link CDPTransportInterface}\n */\nexport function createCDPTransport(options: WebSocketCDPTransportOptions): CDPTransportInterface {\n\treturn new WebSocketCDPTransport(options)\n}\n\n/**\n * Creates a filesystem-backed `BrowserWriterInterface` that persists bytes through\n * `node:fs/promises`.\n *\n * @returns A {@link BrowserWriterInterface} that persists bytes through `node:fs/promises`\n */\nexport function createBrowserWriter(): BrowserWriterInterface {\n\treturn new FileBrowserWriter()\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type {\n\tBrowserConnection,\n\tBrowserDiscoveryResult,\n\tBrowserEngine,\n\tBrowserEventMap,\n\tBrowserInterface,\n\tBrowserOptions,\n\tBrowserProfileResult,\n\tBrowserStatus,\n} from './types.js'\nimport type {\n\tBrowserContextInterface,\n\tBrowserContextOptions,\n\tBrowserPageInterface,\n\tBrowserPageOptions,\n\tCDPTarget,\n\tCDPTransportInterface,\n} from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport { addAbortListener, once } from 'node:events'\nimport { isArray, isError, isInteger, isRecord, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tBrowserContext,\n\tBrowserTransition,\n\tBROWSER_DEFAULT_TIMEOUT_MS,\n\tBROWSER_WAIT_POLL_INTERVAL_MS,\n\tCDPClient,\n\tvalidateBrowserContextOptions,\n} from '@src/core'\nimport {\n\tBrowserConnectionError,\n\tBrowserDestroyedError,\n\tBrowserNotConnectedError,\n\tisBrowserConnectionError,\n} from './errors.js'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_VERSION_PATH,\n\tBROWSER_DEFAULT_CDP_PORT,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_KILL_GRACE_MS,\n\tBROWSER_PORT_PROBE_TIMEOUT_MS,\n\tBROWSER_PROCESS_EXIT_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_DEFER_MS,\n} from './constants.js'\nimport {\n\tbrowserToEngine,\n\tcreateBrowserProfile,\n\tfindSystemBrowser,\n\tlaunchBrowserProcess,\n\tparseBrowserEngine,\n\tremoveBrowserProfile,\n\twaitForCDPReady,\n} from './helpers.js'\nimport { createCDPTransport, createBrowserWriter } from './factories.js'\n\n// === Browser\n\n/**\n * Discovers, launches, connects to, and owns Chromium-family browser sessions.\n *\n * @example\n * ```ts\n * import { Browser } from '@orkestrel/browser/server'\n *\n * const browser = new Browser({ headless: true })\n * await browser.connect()\n * const page = await browser.create({ url: 'https://example.com' })\n * await browser.destroy()\n * ```\n */\nexport class Browser implements BrowserInterface {\n\treadonly #emitter: Emitter<BrowserEventMap>\n\treadonly #options: BrowserOptions\n\treadonly #abort = new AbortController()\n\treadonly #cdpPort: number\n\treadonly #cdpHost: string\n\t#engine: BrowserEngine\n\t#status: BrowserStatus = 'idle'\n\t#connection: BrowserConnection | undefined\n\t#owned: boolean | undefined\n\t#endpoint: string | undefined\n\t#client: CDPClient | undefined\n\t#process: ChildProcess | undefined\n\t// Identifier the launcher handed the endpoint to when it re-executed the\n\t// browser and exited before CDP became ready. Undefined whenever the\n\t// spawned child is itself the process serving the endpoint.\n\t#servingPid: number | undefined\n\t#profile: BrowserProfileResult | undefined\n\t#contexts: BrowserContext[] = []\n\t#destroyed = false\n\treadonly #connecting: BrowserTransition = new BrowserTransition()\n\treadonly #disconnecting: BrowserTransition = new BrowserTransition()\n\t#exitCleanup: Promise<void> | undefined\n\t#shutdown: Promise<void> | undefined\n\t#transport: CDPTransportInterface | undefined\n\treadonly #transportCloseHandler = this.#handleTransportLoss.bind(this)\n\treadonly #transportErrorHandler = this.#handleTransportLoss.bind(this)\n\treadonly #processExitHandler = this.#handleProcessExit.bind(this)\n\n\tconstructor(options?: BrowserOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#options = options ?? {}\n\t\tthis.#engine =\n\t\t\tthis.#options.engine ??\n\t\t\t(this.#options.executable !== undefined\n\t\t\t\t? (parseBrowserEngine(this.#options.executable) ?? 'chromium')\n\t\t\t\t: 'chromium')\n\t\tthis.#cdpPort = this.#options.cdp?.port ?? BROWSER_DEFAULT_CDP_PORT\n\t\tthis.#cdpHost = this.#options.cdp?.host ?? BROWSER_DEFAULT_HOST\n\n\t\tqueueMicrotask(() => this.#emitter.emit('idle'))\n\t}\n\n\tget emitter(): EmitterInterface<BrowserEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget engine(): BrowserEngine {\n\t\treturn this.#engine\n\t}\n\n\tget status(): BrowserStatus {\n\t\treturn this.#status\n\t}\n\n\tget connection(): BrowserConnection | undefined {\n\t\treturn this.#connection\n\t}\n\n\tget owned(): boolean | undefined {\n\t\treturn this.#owned\n\t}\n\n\tget pid(): number | undefined {\n\t\treturn this.#servingPid ?? this.#process?.pid\n\t}\n\n\tasync discover(): Promise<BrowserDiscoveryResult> {\n\t\tconst result = await this.#discoverCDP()\n\t\tthis.#emitter.emit('discover', result)\n\t\treturn result\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\n\t\tconst active = this.#connecting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\t\tif (this.#status === 'connected') return\n\n\t\tawait this.#connecting.execute(() => this.#establish())\n\t}\n\n\tadopt(): void {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tif (\n\t\t\tthis.#status !== 'connected' ||\n\t\t\tthis.#client === undefined ||\n\t\t\tthis.#endpoint === undefined\n\t\t) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tthis.#owned = true\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.#destroyed) return\n\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tconst connecting = this.#connecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tif (connecting !== undefined) await connecting.catch(() => undefined)\n\t\tif (this.#destroyed) return\n\t\tif (this.#status !== 'connected' || this.#client === undefined) return\n\n\t\tawait this.#disconnecting.execute(() => this.#detach())\n\t}\n\n\tcontext(index?: number): BrowserContextInterface | undefined {\n\t\tconst i = index ?? 0\n\t\tif (i < 0 || i >= this.#contexts.length) return undefined\n\t\treturn this.#contexts[i]\n\t}\n\n\tcontexts(): readonly BrowserContextInterface[] {\n\t\treturn [...this.#contexts]\n\t}\n\n\tasync isolate(options?: BrowserContextOptions): Promise<BrowserContextInterface> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tvalidateBrowserContextOptions(options)\n\t\tconst params: Record<string, unknown> = { disposeOnDetach: false }\n\t\tif (options?.proxy !== undefined) {\n\t\t\tparams['proxyServer'] = options.proxy.server\n\t\t\tif (options.proxy.bypass !== undefined) {\n\t\t\t\tparams['proxyBypassList'] = options.proxy.bypass.join(',')\n\t\t\t}\n\t\t}\n\t\tif (options?.origins !== undefined) {\n\t\t\tparams['originsWithUniversalNetworkAccess'] = [...options.origins]\n\t\t}\n\t\tconst result = await client.send('Target.createBrowserContext', params)\n\t\tif (!isRecord(result) || !isString(result['browserContextId'])) {\n\t\t\tthrow new BrowserConnectionError('Failed to create isolated browser context')\n\t\t}\n\t\tconst id = result['browserContextId']\n\t\tconst context = new BrowserContext(\n\t\t\tclient,\n\t\t\tid,\n\t\t\toptions?.emulation?.viewport ?? this.#options.viewport,\n\t\t\tcreateBrowserWriter(),\n\t\t\toptions?.emulation,\n\t\t\toptions?.downloads,\n\t\t\toptions,\n\t\t)\n\n\t\ttry {\n\t\t\tif (options?.downloads !== undefined) {\n\t\t\t\tawait client.send('Browser.setDownloadBehavior', {\n\t\t\t\t\tbehavior: options.downloads.named === true ? 'allowAndName' : 'allow',\n\t\t\t\t\tbrowserContextId: id,\n\t\t\t\t\tdownloadPath: options.downloads.path,\n\t\t\t\t\teventsEnabled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait context.close().catch(() => undefined)\n\t\t\tthrow error\n\t\t}\n\n\t\tthis.#registerContext(context)\n\t\treturn context\n\t}\n\n\tasync create(options?: BrowserPageOptions): Promise<BrowserPageInterface> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\n\t\tlet context = this.#contexts[0]\n\t\tif (context === undefined) {\n\t\t\tcontext = new BrowserContext(client, undefined, this.#options.viewport, createBrowserWriter())\n\t\t\tthis.#registerContext(context)\n\t\t}\n\n\t\tconst page = await context.create(options)\n\t\tthis.#emitter.emit('page', page)\n\t\treturn page\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#destroyResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\tclose(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#closeResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\t// === Private helpers\n\n\tasync #establish(): Promise<void> {\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tawait this.#settleExit()\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tif (this.#status === 'connected') return\n\n\t\tthis.#assertNotAborted()\n\t\tthis.#status = 'connecting'\n\n\t\ttry {\n\t\t\tif (this.#owned === true && this.#endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(this.#endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst endpoint = this.#options.cdp?.endpoint\n\t\t\tif (endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst discover = this.#options.cdp?.discover ?? true\n\t\t\tif (discover) {\n\t\t\t\tconst discovery = await this.#raceAbort(this.#discoverCDP(this.#signal()))\n\t\t\t\tif (discovery.endpoint !== undefined) {\n\t\t\t\t\tthis.#engine = browserToEngine(discovery.browser)\n\t\t\t\t\tawait this.#connectCDP(discovery.endpoint)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait this.#raceAbort(this.#assertPortFree())\n\t\t\t}\n\n\t\t\tthis.#assertNotAborted()\n\t\t\tawait this.#launch()\n\t\t} catch (error) {\n\t\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\n\t\t\tthis.#status = 'error'\n\t\t\tthis.#emitter.emit('error', error)\n\t\t\tif (isBrowserConnectionError(error)) throw error\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserConnectionError(message, { executable: this.#options.executable })\n\t\t}\n\t}\n\n\tasync #detach(): Promise<void> {\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#unbindTransport()\n\n\t\tconst client = this.#client\n\t\tthis.#client = undefined\n\t\tawait this.#destroyContexts()\n\t\tthis.#contexts = []\n\n\t\tif (this.#owned !== true) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tawait this.#closeClient(client)\n\t\tif (this.#destroyed) return\n\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#assertNotAborted(): void {\n\t\tif (this.#signal().aborted) throw new BrowserConnectionError('Connection aborted')\n\t}\n\n\t#signal(): AbortSignal {\n\t\tconst external = this.#options.signal\n\t\treturn external === undefined\n\t\t\t? this.#abort.signal\n\t\t\t: AbortSignal.any([this.#abort.signal, external])\n\t}\n\n\tasync #raceAbort<T>(promise: Promise<T>): Promise<T> {\n\t\tconst signal = this.#signal()\n\t\tif (signal.aborted) throw new BrowserConnectionError('Connection aborted')\n\n\t\tconst aborted = Promise.withResolvers<never>()\n\t\tconst listener = addAbortListener(signal, () => {\n\t\t\taborted.reject(new BrowserConnectionError('Connection aborted'))\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([promise, aborted.promise])\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t\tvoid promise.catch(() => undefined)\n\t\t}\n\t}\n\n\t#handleProcessExit(): void {\n\t\tif (this.#destroyed) return\n\n\t\tconst connected = this.#status === 'connected'\n\t\tconst client = this.#client\n\t\tconst contexts = this.#contexts\n\t\tconst process = this.#process\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tconst cleanup = this.#cleanupExitedProcess(process, contexts, client)\n\t\tthis.#exitCleanup = cleanup\n\t\tvoid cleanup.catch((error: unknown) => this.#emitter.emit('error', error))\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tif (connected) this.#status = 'disconnected'\n\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserConnectionError('The browser process exited unexpectedly', {\n\t\t\t\tcause: BROWSER_PROCESS_EXIT_CAUSE,\n\t\t\t}),\n\t\t)\n\n\t\tif (connected) {\n\t\t\tthis.#emitter.emit('disconnect')\n\t\t\tthis.#emitter.emit('idle')\n\t\t}\n\t}\n\n\t#handleTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process === undefined) {\n\t\t\tthis.#confirmTransportLoss()\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\t// A spawned child that is already dead is diagnosed by its own `exit`\n\t\t// event, never by a probe here: Node sets `exitCode` in the same callback\n\t\t// that emits `exit`, and reports ESRCH from `ChildProcess.kill(0)` as a\n\t\t// `false` return rather than a throw, so no reading of the handle can see\n\t\t// the death before the event does. The defer only has to outlast the loop\n\t\t// turn that delivers it.\n\t\tsetTimeout(() => this.#confirmTransportLoss(), BROWSER_TRANSPORT_LOSS_DEFER_MS)\n\t}\n\n\t#confirmTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process !== undefined && !this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\tconst client = this.#client\n\t\tconst owned = this.#owned === true\n\t\tconst contexts = this.#contexts\n\t\tthis.#unbindTransport()\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#status = 'disconnected'\n\n\t\tif (!owned) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tvoid this.#destroyContextList(contexts)\n\t\tvoid this.#closeClient(client)\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserConnectionError('The CDP transport connection was lost', {\n\t\t\t\tcause: BROWSER_TRANSPORT_LOSS_CAUSE,\n\t\t\t}),\n\t\t)\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#bindTransport(transport: CDPTransportInterface): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#transport = transport\n\t\ttransport.emitter.on('close', this.#transportCloseHandler)\n\t\ttransport.emitter.on('error', this.#transportErrorHandler)\n\t}\n\n\t#unbindTransport(): void {\n\t\tconst transport = this.#transport\n\t\tif (transport === undefined) return\n\t\ttransport.emitter.off('close', this.#transportCloseHandler)\n\t\ttransport.emitter.off('error', this.#transportErrorHandler)\n\t\tthis.#transport = undefined\n\t}\n\n\t#bindProcess(process: ChildProcess): void {\n\t\tthis.#unbindProcess()\n\t\t// A launcher that handed the endpoint on has already exited, and its exit\n\t\t// says nothing about the browser now serving CDP. That browser has no\n\t\t// child handle, so the transport reports its death.\n\t\tif (this.#servingPid !== undefined) return\n\t\tprocess.once('exit', this.#processExitHandler)\n\t\tif (process.exitCode !== null || process.signalCode !== null) {\n\t\t\tqueueMicrotask(this.#processExitHandler)\n\t\t}\n\t}\n\n\t#unbindProcess(): void {\n\t\tthis.#process?.off('exit', this.#processExitHandler)\n\t}\n\n\t#timeout(): number {\n\t\treturn this.#options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tasync #discoverCDP(signal?: AbortSignal): Promise<BrowserDiscoveryResult> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\t\tconst requestSignal =\n\t\t\tsignal === undefined\n\t\t\t\t? AbortSignal.timeout(this.#timeout())\n\t\t\t\t: AbortSignal.any([signal, AbortSignal.timeout(this.#timeout())])\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: requestSignal })\n\t\t\tif (!response.ok) return this.#notFound()\n\n\t\t\tconst info: unknown = await response.json()\n\t\t\tif (!isRecord(info)) return this.#notFound()\n\n\t\t\tconst endpoint = isString(info['webSocketDebuggerUrl'])\n\t\t\t\t? info['webSocketDebuggerUrl']\n\t\t\t\t: undefined\n\t\t\tconst browser = isString(info['Browser']) ? info['Browser'] : undefined\n\n\t\t\treturn { endpoint, browser }\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted === true) throw error\n\t\t\treturn this.#notFound()\n\t\t}\n\t}\n\n\t#notFound(): BrowserDiscoveryResult {\n\t\treturn { endpoint: undefined, browser: undefined }\n\t}\n\n\tasync #assertPortFree(): Promise<void> {\n\t\tif (await this.#probePort()) {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t`Port ${this.#cdpPort} on ${this.#cdpHost} is already occupied by another CDP endpoint`,\n\t\t\t\t{ port: this.#cdpPort, host: this.#cdpHost },\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #probePort(): Promise<boolean> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tsignal: AbortSignal.timeout(BROWSER_PORT_PROBE_TIMEOUT_MS),\n\t\t\t})\n\t\t\treturn response.ok\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync #connectCDP(endpoint: string): Promise<void> {\n\t\tconst transport = createCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\tconst client = new CDPClient({ transport, timeout: this.#timeout() })\n\t\tconst retained = this.#owned === true && this.#endpoint === endpoint\n\n\t\ttry {\n\t\t\tawait this.#raceAbort(client.connect())\n\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = retained ? this.#retainedConnection() : 'cdp'\n\t\t\tthis.#owned = retained\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('connect', this.#connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tif (this.#client === client) this.#client = undefined\n\t\t\tthis.#contexts = []\n\t\t\tthis.#connection = undefined\n\t\t\tif (!retained) {\n\t\t\t\tthis.#owned = undefined\n\t\t\t\tthis.#endpoint = undefined\n\t\t\t}\n\t\t\tawait this.#closeClient(client)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #launch(): Promise<void> {\n\t\tif (this.#process !== undefined) {\n\t\t\tthrow new BrowserConnectionError('A browser process is already active on this instance')\n\t\t}\n\n\t\tconst requestedEngine = this.#options.engine ?? this.#options.browsers?.engine\n\t\tlet executable = this.#options.executable\n\t\tlet resolvedEngine: BrowserEngine | undefined\n\n\t\tif (executable !== undefined) {\n\t\t\tresolvedEngine = parseBrowserEngine(executable) ?? 'chromium'\n\t\t} else {\n\t\t\tconst found = findSystemBrowser({\n\t\t\t\t...this.#options.browsers,\n\t\t\t\t...(requestedEngine !== undefined ? { engine: requestedEngine } : {}),\n\t\t\t})\n\t\t\texecutable = found?.executable\n\t\t\tresolvedEngine = found?.engine\n\t\t}\n\n\t\tif (executable === undefined) {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t'No Chromium browser found. Install Chrome, Edge, or Chromium.',\n\t\t\t\trequestedEngine === undefined ? undefined : { engine: requestedEngine },\n\t\t\t)\n\t\t}\n\n\t\tthis.#engine = resolvedEngine ?? 'chromium'\n\t\tawait this.#releaseProfile()\n\t\tconst profile = await createBrowserProfile(this.#options.profile)\n\t\tthis.#profile = profile\n\t\tlet process: ChildProcess\n\t\ttry {\n\t\t\tprocess = launchBrowserProcess(\n\t\t\t\texecutable,\n\t\t\t\tthis.#cdpPort,\n\t\t\t\tthis.#options.headless ?? true,\n\t\t\t\tprofile.path,\n\t\t\t\tthis.#options.args,\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tawait this.#releaseProfile()\n\t\t\tthrow error\n\t\t}\n\t\tthis.#process = process\n\n\t\tlet client: CDPClient | undefined\n\n\t\ttry {\n\t\t\tconst endpoint = await this.#waitForLaunch(process, executable, this.#options.args)\n\t\t\tconst transport = createCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\t\tclient = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\tawait this.#raceAbort(client.connect())\n\t\t\tawait this.#takeEndpointOwner(process, client)\n\n\t\t\tconst connection = this.#options.profile === undefined ? 'launch' : 'persistent'\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = connection\n\t\t\tthis.#owned = true\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\t\t\tthis.#bindProcess(process)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('launch', this.#engine)\n\t\t\tthis.#emitter.emit('connect', connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\t\t\tawait this.#closeClient(client)\n\t\t\tawait this.#terminate(process)\n\t\t\tawait this.#releaseProfile()\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tthis.#client = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t\tthis.#owned = undefined\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Takes over the process serving the CDP endpoint when the spawned child is\n\t * no longer it.\n\t *\n\t * @remarks\n\t * A Windows launcher — Microsoft Edge — re-executes the browser with the\n\t * same `--remote-debugging-port` and exits 0 before the endpoint answers, so\n\t * the child this instance spawned parents the real tree without being part\n\t * of it. Chromium names the process behind the endpoint as the `browser`\n\t * entry of `SystemInfo.getProcessInfo`, which identifies it without a\n\t * platform branch. An endpoint that names no such process cannot be owned,\n\t * so the launch closes it and fails rather than leaking it.\n\t */\n\tasync #takeEndpointOwner(process: ChildProcess, client: CDPClient): Promise<void> {\n\t\tif (process.exitCode === null && process.signalCode === null) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('SystemInfo.getProcessInfo')\n\t\t} catch {\n\t\t\tresult = undefined\n\t\t}\n\n\t\tlet pid: number | undefined\n\t\tif (isRecord(result) && isArray(result['processInfo'])) {\n\t\t\tfor (const entry of result['processInfo']) {\n\t\t\t\tif (!isRecord(entry) || entry['type'] !== 'browser' || !isInteger(entry['id'])) continue\n\t\t\t\tpid = entry['id']\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (pid === undefined) {\n\t\t\tawait this.#closeRemote(client)\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t'The browser launcher exited without naming the process serving its CDP endpoint',\n\t\t\t\t{ executable: this.#options.executable, pid: process.pid },\n\t\t\t)\n\t\t}\n\n\t\tthis.#servingPid = pid\n\t}\n\n\tasync #waitForLaunch(\n\t\tprocess: ChildProcess,\n\t\texecutable: string,\n\t\targs?: readonly string[],\n\t): Promise<string> {\n\t\tconst context = { executable, args }\n\t\tconst controller = new AbortController()\n\t\tconst signal = AbortSignal.any([controller.signal, this.#signal()])\n\t\tconst ready = waitForCDPReady(this.#cdpPort, this.#timeout(), this.#cdpHost, signal)\n\t\tconst exited = once(process, 'exit', { signal }).then((values) => {\n\t\t\tconst code = isInteger(values[0]) ? values[0] : null\n\t\t\tconst exitSignal = isString(values[1]) ? values[1] : null\n\t\t\t// A launcher that re-executes the browser exits cleanly and hands the\n\t\t\t// endpoint to the process it spawned, so a clean exit ends the child\n\t\t\t// rather than the launch. Keep waiting for the endpoint on the same\n\t\t\t// readiness budget, which still fails loudly when none appears.\n\t\t\tif (code === 0 && exitSignal === null) return ready\n\t\t\tthrow new BrowserConnectionError(this.#formatLaunchExit(code, exitSignal), context)\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([ready, exited])\n\t\t} catch (error) {\n\t\t\tif (isBrowserConnectionError(error)) throw error\n\t\t\tif (this.#signal().aborted) throw new BrowserConnectionError('Connection aborted', context)\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserConnectionError(message, context)\n\t\t} finally {\n\t\t\tcontroller.abort()\n\t\t\tvoid ready.catch(() => undefined)\n\t\t\tvoid exited.catch(() => undefined)\n\t\t}\n\t}\n\n\t#formatLaunchExit(code: number | null, signal: string | null): string {\n\t\tif (signal !== null) {\n\t\t\treturn `Browser process exited before CDP became ready (signal: ${signal})`\n\t\t}\n\t\tif (code !== null) return `Browser process exited before CDP became ready (code: ${code})`\n\t\treturn 'Browser process exited before CDP became ready'\n\t}\n\n\t#retainedConnection(): BrowserConnection {\n\t\tif (this.#process === undefined) return 'cdp'\n\t\treturn this.#options.profile === undefined ? 'launch' : 'persistent'\n\t}\n\n\tasync #syncContexts(): Promise<void> {\n\t\tconst client = this.#client\n\t\tif (client === undefined) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('Target.getTargets')\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\t\tif (!isRecord(result) || !isArray(result['targetInfos'])) return\n\n\t\tconst pages: CDPTarget[] = []\n\t\tfor (const target of result['targetInfos']) {\n\t\t\tif (\n\t\t\t\t!isRecord(target) ||\n\t\t\t\t!isString(target['targetId']) ||\n\t\t\t\ttarget['type'] !== 'page' ||\n\t\t\t\t!isString(target['title']) ||\n\t\t\t\t!isString(target['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpages.push({\n\t\t\t\tid: target['targetId'],\n\t\t\t\tcategory: target['type'],\n\t\t\t\ttitle: target['title'],\n\t\t\t\turl: target['url'],\n\t\t\t})\n\t\t}\n\t\tif (pages.length === 0 || this.#contexts.length > 0) return\n\n\t\tconst context = new BrowserContext(\n\t\t\tclient,\n\t\t\tundefined,\n\t\t\tthis.#options.viewport,\n\t\t\tcreateBrowserWriter(),\n\t\t)\n\t\tawait context.sync(pages)\n\t\tthis.#registerContext(context)\n\t}\n\n\tasync #destroyResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tif (this.#owned === true) {\n\t\t\t\tawait this.#closeContexts()\n\t\t\t\tif (this.#process === undefined) await this.#closeRemote(client)\n\t\t\t} else {\n\t\t\t\tawait this.#destroyContexts()\n\t\t\t}\n\t\t\tthis.#contexts = []\n\n\t\t\tawait this.#terminate(this.#process)\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tawait this.#closeContexts()\n\t\t\tthis.#contexts = []\n\t\t\tawait this.#closeRemote(client)\n\n\t\t\tconst process = this.#process\n\t\t\tif (process !== undefined) {\n\t\t\t\tconst exited = await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)\n\t\t\t\tif (!exited) await this.#terminate(process)\n\t\t\t}\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #settle(): Promise<void> {\n\t\tawait this.#connecting.pending?.catch(() => undefined)\n\t\tawait this.#disconnecting.pending?.catch(() => undefined)\n\t\tawait this.#settleExit()\n\t}\n\n\tasync #settleExit(): Promise<void> {\n\t\tconst cleanup = this.#exitCleanup\n\t\tif (cleanup === undefined) return\n\t\tawait cleanup\n\t\tif (this.#exitCleanup === cleanup) this.#exitCleanup = undefined\n\t}\n\n\tasync #closeRemote(client: CDPClient | undefined): Promise<void> {\n\t\tlet remote = client\n\t\tlet temporary = false\n\n\t\tif (remote === undefined && this.#owned === true && this.#endpoint !== undefined) {\n\t\t\tconst transport = createCDPTransport({\n\t\t\t\turl: this.#endpoint,\n\t\t\t\ttimeout: this.#timeout(),\n\t\t\t})\n\t\t\tremote = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\ttry {\n\t\t\t\tawait remote.connect()\n\t\t\t\ttemporary = true\n\t\t\t} catch {\n\t\t\t\tawait this.#closeClient(remote)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (remote !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait remote.send('Browser.close')\n\t\t\t} catch {\n\t\t\t\t// The remote may already be gone or close before acknowledging.\n\t\t\t}\n\t\t}\n\n\t\tif (temporary) await this.#closeClient(remote)\n\t}\n\n\tasync #closeContexts(): Promise<void> {\n\t\tfor (const context of [...this.#contexts]) {\n\t\t\ttry {\n\t\t\t\tawait context.close()\n\t\t\t} catch {\n\t\t\t\t// Teardown is best-effort after the browser begins shutting down.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #destroyContexts(): Promise<void> {\n\t\tawait this.#destroyContextList([...this.#contexts])\n\t}\n\n\t#registerContext(context: BrowserContext): void {\n\t\tthis.#contexts.push(context)\n\t\tcontext.emitter.on('close', () => {\n\t\t\tconst index = this.#contexts.indexOf(context)\n\t\t\tif (index >= 0) this.#contexts.splice(index, 1)\n\t\t})\n\t\tthis.#emitter.emit('context', context)\n\t}\n\n\tasync #destroyContextList(contexts: readonly BrowserContext[]): Promise<void> {\n\t\tfor (const context of contexts) {\n\t\t\ttry {\n\t\t\t\tawait context.destroy()\n\t\t\t} catch {\n\t\t\t\t// The transport may already be unavailable.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeClient(client: CDPClient | undefined): Promise<void> {\n\t\tif (client === undefined) return\n\t\ttry {\n\t\t\tawait client.close()\n\t\t} catch {\n\t\t\t// Teardown is best-effort after a connection fault.\n\t\t}\n\t}\n\n\tasync #releaseProfile(): Promise<void> {\n\t\tconst profile = this.#profile\n\t\tthis.#profile = undefined\n\t\tif (profile !== undefined) await removeBrowserProfile(profile)\n\t}\n\n\tasync #cleanupExitedProcess(\n\t\tprocess: ChildProcess | undefined,\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#terminate(process)\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t}\n\t\tif (terminated) await this.#releaseProfile()\n\t}\n\n\tasync #cleanupLocal(\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tawait this.#destroyContextList(contexts)\n\t\tawait this.#closeClient(client)\n\t}\n\n\tasync #waitForProcessWithin(process: ChildProcess, timeout: number): Promise<boolean> {\n\t\tif (process.exitCode !== null || process.signalCode !== null) return true\n\n\t\tconst signal = AbortSignal.timeout(timeout)\n\t\ttry {\n\t\t\tawait once(process, 'exit', { signal })\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn process.exitCode !== null || process.signalCode !== null\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#hasProcessGroup(process: ChildProcess): boolean {\n\t\tconst pid = process.pid\n\t\treturn globalThis.process.platform !== 'win32' && pid !== undefined && pid > 0\n\t}\n\n\t// Whether the process serving the CDP endpoint is still running. The spawned\n\t// child reports through its own handle; a process the launcher handed the\n\t// endpoint to has none, so it is probed by identifier.\n\t#alive(): boolean {\n\t\tconst process = this.#process\n\t\tif (process === undefined) return false\n\t\tif (this.#servingPid !== undefined) return this.#signalProcess(process, 0) !== false\n\t\treturn process.exitCode === null && process.signalCode === null\n\t}\n\n\t// Whether the launch retains a process the reaped child does not account\n\t// for: the POSIX process group, or the process the launcher handed the\n\t// endpoint to.\n\t#inspectRemainder(process: ChildProcess): boolean | undefined {\n\t\tif (!this.#hasProcessGroup(process) && this.#servingPid === undefined) return false\n\t\treturn this.#signalProcess(process, 0)\n\t}\n\n\t#signalProcess(process: ChildProcess, signal: NodeJS.Signals | 0): boolean | undefined {\n\t\tconst pid = process.pid\n\t\tconst serving = this.#servingPid\n\t\ttry {\n\t\t\tif (this.#hasProcessGroup(process) && pid !== undefined) {\n\t\t\t\treturn globalThis.process.kill(-pid, signal)\n\t\t\t}\n\t\t\t// Terminating the Chromium browser process takes its whole tree with\n\t\t\t// it, so Windows needs no separate tree walk to reach the renderers,\n\t\t\t// GPU, and utility children the serving process parents.\n\t\t\tif (serving !== undefined) return globalThis.process.kill(serving, signal)\n\t\t\treturn process.kill(signal)\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\tisError(error) && 'code' in error && isString(error.code) ? error.code : undefined\n\t\t\tif (code === 'ESRCH') return false\n\t\t\tif (signal === 0) return code === 'EPERM' ? true : undefined\n\t\t\tthrow new BrowserConnectionError('Failed to signal the browser process', {\n\t\t\t\tpid: serving ?? pid,\n\t\t\t\tsignal,\n\t\t\t\tcause: error,\n\t\t\t})\n\t\t}\n\t}\n\n\tasync #waitForRemainderWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t): Promise<boolean | undefined> {\n\t\tconst deadline = performance.now() + timeout\n\t\tlet confirmed = false\n\t\t// Node observes only the direct child, and neither the rest of a POSIX\n\t\t// process group nor a process the launcher handed the endpoint to raises\n\t\t// an exit event here, so bound the drain probe.\n\t\twhile (true) {\n\t\t\tconst alive = this.#inspectRemainder(process)\n\t\t\tif (alive === false) return true\n\t\t\tif (alive === true) confirmed = true\n\t\t\tconst remaining = deadline - performance.now()\n\t\t\tif (remaining <= 0) return confirmed ? false : undefined\n\t\t\tawait new Promise<void>((resolve) =>\n\t\t\t\tsetTimeout(resolve, Math.min(BROWSER_WAIT_POLL_INTERVAL_MS, remaining)),\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #waitForTerminationWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t\tfinal = false,\n\t): Promise<boolean> {\n\t\tconst exited = this.#waitForProcessWithin(process, timeout)\n\t\tconst drained = this.#waitForRemainderWithin(process, timeout)\n\t\tconst results = await Promise.all([exited, drained])\n\t\treturn results[0] && (results[1] === true || (final && results[1] === undefined))\n\t}\n\n\tasync #terminate(process: ChildProcess | undefined): Promise<void> {\n\t\tif (\n\t\t\tprocess === undefined ||\n\t\t\t((process.exitCode !== null || process.signalCode !== null) &&\n\t\t\t\tthis.#inspectRemainder(process) === false)\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.#signalProcess(process, 'SIGTERM') === false) return\n\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)) return\n\n\t\tif (this.#signalProcess(process, 'SIGKILL') === false) return\n\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS, true)) return\n\n\t\tthrow new BrowserConnectionError('Browser process did not exit after SIGKILL', {\n\t\t\tpid: this.#servingPid ?? process.pid,\n\t\t})\n\t}\n\n\t#finish(): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tthis.#client = undefined\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tthis.#exitCleanup = undefined\n\t\tthis.#contexts = []\n\t\tthis.#emitter.emit('destroy')\n\t\tthis.#emitter.destroy()\n\t}\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkestrel/browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Chrome DevTools Protocol browser automation with an environment-agnostic core. Part of the @orkestrel line.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -86,22 +86,22 @@
|
|
|
86
86
|
"test:setup": "vitest run --config vite.config.ts --no-cache --reporter=dot --project setup"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@orkestrel/contract": "^0.0.
|
|
90
|
-
"@orkestrel/emitter": "^0.0.
|
|
91
|
-
"@orkestrel/html": "^0.0.
|
|
92
|
-
"@orkestrel/websocket": "^0.0.
|
|
89
|
+
"@orkestrel/contract": "^0.0.18",
|
|
90
|
+
"@orkestrel/emitter": "^0.0.11",
|
|
91
|
+
"@orkestrel/html": "^0.0.11",
|
|
92
|
+
"@orkestrel/websocket": "^0.0.14"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@microsoft/api-extractor": "^7.59.
|
|
96
|
-
"@orkestrel/guide": "^0.0.
|
|
97
|
-
"@orkestrel/probe": "^0.0.
|
|
98
|
-
"@orkestrel/scaffold": "^0.0.
|
|
99
|
-
"@orkestrel/test": "^0.0.
|
|
100
|
-
"@types/node": "^26.6.
|
|
101
|
-
"oxfmt": "^0.
|
|
102
|
-
"oxlint": "^1.
|
|
95
|
+
"@microsoft/api-extractor": "^7.59.3",
|
|
96
|
+
"@orkestrel/guide": "^0.0.20",
|
|
97
|
+
"@orkestrel/probe": "^0.0.18",
|
|
98
|
+
"@orkestrel/scaffold": "^0.0.79",
|
|
99
|
+
"@orkestrel/test": "^0.0.24",
|
|
100
|
+
"@types/node": "^26.6.3",
|
|
101
|
+
"oxfmt": "^0.71.0",
|
|
102
|
+
"oxlint": "^1.86.0",
|
|
103
103
|
"typescript": "^6.0.3",
|
|
104
|
-
"vite": "^8.3.
|
|
104
|
+
"vite": "^8.3.1",
|
|
105
105
|
"vitest": "^4.1.11"
|
|
106
106
|
},
|
|
107
107
|
"engines": {
|