@orkestrel/browser 0.0.5 → 0.0.6

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.
@@ -1,4 +1,5 @@
1
1
  import { BrowserContextInterface } from '../core/index.ts';
2
+ import { BrowserContextOptions } from '../core/index.ts';
2
3
  import { BrowserError } from '../core/index.ts';
3
4
  import { BrowserPageInterface } from '../core/index.ts';
4
5
  import { BrowserPageOptions } from '../core/index.ts';
@@ -14,6 +15,9 @@ import { EmitterHooks } from '@orkestrel/emitter';
14
15
  import { EmitterInterface } from '@orkestrel/emitter';
15
16
  import { ScreenshotWriterInterface } from '../core/index.ts';
16
17
 
18
+ /**
19
+ * Discovers, launches, connects to, and owns Chromium-family browser sessions.
20
+ */
17
21
  export declare class Browser implements BrowserInterface {
18
22
  #private;
19
23
  constructor(options?: BrowserOptions);
@@ -30,6 +34,7 @@ export declare class Browser implements BrowserInterface {
30
34
  disconnect(): Promise<void>;
31
35
  context(index?: number): BrowserContextInterface | undefined;
32
36
  contexts(): readonly BrowserContextInterface[];
37
+ isolate(options?: BrowserContextOptions): Promise<BrowserContextInterface>;
33
38
  create(options?: BrowserPageOptions): Promise<BrowserPageInterface>;
34
39
  destroy(): Promise<void>;
35
40
  close(): Promise<void>;
@@ -80,6 +85,9 @@ export declare const BROWSER_PORT_PROBE_TIMEOUT_MS = 200;
80
85
  /** Machine-readable error-context cause for an owned browser process exiting. */
81
86
  export declare const BROWSER_PROCESS_EXIT_CAUSE = "process-exit";
82
87
 
88
+ /** Prefix for isolated browser profiles created beneath the operating-system temp directory. */
89
+ export declare const BROWSER_PROFILE_PREFIX = "orkestrel-browser-";
90
+
83
91
  /** Per-OS default Playwright browser cache directory, relative to the home directory (win32 uses `LOCALAPPDATA` directly). */
84
92
  export declare const BROWSER_STORE_CACHE_DIRS: Readonly<Record<string, string>>;
85
93
 
@@ -190,6 +198,7 @@ export declare type BrowserEventMap = {
190
198
  readonly disconnect: readonly [];
191
199
  readonly launch: readonly [engine: BrowserEngine];
192
200
  readonly page: readonly [page: BrowserPageInterface];
201
+ readonly context: readonly [context: BrowserContextInterface];
193
202
  readonly error: readonly [error: unknown];
194
203
  readonly destroy: readonly [];
195
204
  };
@@ -266,6 +275,7 @@ export declare interface BrowserInterface {
266
275
  disconnect(): Promise<void>;
267
276
  context(index?: number): BrowserContextInterface | undefined;
268
277
  contexts(): readonly BrowserContextInterface[];
278
+ isolate(options?: BrowserContextOptions): Promise<BrowserContextInterface>;
269
279
  create(options?: BrowserPageOptions): Promise<BrowserPageInterface>;
270
280
  destroy(): Promise<void>;
271
281
  close(): Promise<void>;
@@ -315,6 +325,19 @@ export declare interface BrowserOptions {
315
325
  readonly browsers?: SystemBrowserOptions;
316
326
  }
317
327
 
328
+ /**
329
+ * Resolved browser profile directory used for a Chromium-family launch.
330
+ *
331
+ * @remarks
332
+ * `temporary` is true only for an isolated profile created by
333
+ * {@link createBrowserProfile}; caller-supplied persistent profiles are
334
+ * never removed by the library.
335
+ */
336
+ export declare interface BrowserProfileResult {
337
+ readonly path: string;
338
+ readonly temporary: boolean;
339
+ }
340
+
318
341
  /** Lifecycle status of a browser wrapper. */
319
342
  export declare type BrowserStatus = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';
320
343
 
@@ -337,6 +360,14 @@ export declare function browserToEngine(browser?: string): BrowserEngine;
337
360
  */
338
361
  export declare function createBrowser(options?: BrowserOptions): BrowserInterface;
339
362
 
363
+ /**
364
+ * Resolve a persistent caller profile or create an isolated temporary one.
365
+ *
366
+ * @param path - Optional caller-owned persistent user-data directory
367
+ * @returns The resolved profile and whether the library owns its lifecycle
368
+ */
369
+ export declare function createBrowserProfile(path?: string): Promise<BrowserProfileResult>;
370
+
340
371
  /**
341
372
  * Create a Node `WebSocket`-backed CDP transport.
342
373
  *
@@ -473,6 +504,18 @@ export declare function probeAllPathNames(names: readonly string[], platform: st
473
504
  /** Probe PATH (`which`/`where`) for the first resolvable command name. */
474
505
  export declare function probePathNames(names: readonly string[], platform: string): string | undefined;
475
506
 
507
+ /**
508
+ * Remove a library-owned isolated browser profile.
509
+ *
510
+ * @remarks
511
+ * The path must remain a direct child of the operating-system temp directory
512
+ * with {@link BROWSER_PROFILE_PREFIX}; this defensive check prevents a
513
+ * malformed profile value from widening recursive deletion.
514
+ *
515
+ * @param profile - Resolved profile lifecycle result
516
+ */
517
+ export declare function removeBrowserProfile(profile: BrowserProfileResult): Promise<void>;
518
+
476
519
  /**
477
520
  * One discovered browser executable on this machine.
478
521
  *
@@ -1,16 +1,17 @@
1
- import { BROWSER_DEFAULT_TIMEOUT_MS, BROWSER_WAIT_POLL_INTERVAL_MS, BrowserContext, BrowserError, CDPClient } from "../core/index.js";
1
+ import { BROWSER_DEFAULT_TIMEOUT_MS, BROWSER_WAIT_POLL_INTERVAL_MS, BrowserContext, BrowserError, CDPClient, validateBrowserContextOptions } from "../core/index.js";
2
+ import { attempt, isArray, isError, isInstance, isInteger, isRecord, isString } from "@orkestrel/contract";
2
3
  import { existsSync, globSync } from "node:fs";
3
- import { dirname, posix, win32 } from "node:path";
4
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
5
+ import { tmpdir } from "node:os";
6
+ import { basename, dirname, join, posix, resolve, win32 } from "node:path";
4
7
  import { spawn, spawnSync } from "node:child_process";
5
8
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
6
- import { isRecord, isString } from "@orkestrel/contract";
7
9
  import { randomBytes } from "node:crypto";
8
10
  import { request } from "node:http";
9
11
  import { request as request$1 } from "node:https";
10
12
  import { Emitter } from "@orkestrel/emitter";
11
13
  import { WEBSOCKET_READY_CLOSED, WEBSOCKET_READY_OPEN, WEBSOCKET_VERSION, computeWebSocketAccept, createNodeWebSocket } from "@orkestrel/websocket";
12
14
  import { addAbortListener, once } from "node:events";
13
- import { mkdir, writeFile } from "node:fs/promises";
14
15
  //#region src/server/constants.ts
15
16
  /** Default CDP port probed for an existing browser and used for launches. */
16
17
  var BROWSER_DEFAULT_CDP_PORT = 9222;
@@ -26,6 +27,8 @@ var BROWSER_CDP_LIST_PATH = "/json/list";
26
27
  var BROWSER_LAUNCH_ARGS = Object.freeze(["--no-first-run", "--no-default-browser-check"]);
27
28
  /** Flag enabling headless mode on a launched browser process. */
28
29
  var BROWSER_HEADLESS_ARG = "--headless=new";
30
+ /** Prefix for isolated browser profiles created beneath the operating-system temp directory. */
31
+ var BROWSER_PROFILE_PREFIX = "orkestrel-browser-";
29
32
  /** Grace period after SIGTERM before a launched process is escalated to SIGKILL during teardown. */
30
33
  var BROWSER_KILL_GRACE_MS = 3e3;
31
34
  /** Bound for the `discover: false` port-occupancy probe before launching — short, since it only needs to detect an already-listening CDP endpoint, not perform full discovery. */
@@ -157,7 +160,7 @@ var BrowserDestroyedError = class extends BrowserError {
157
160
  * @returns True when value is a BrowserConnectionError instance
158
161
  */
159
162
  function isBrowserConnectionError(value) {
160
- return value instanceof BrowserConnectionError;
163
+ return isInstance(value, BrowserConnectionError);
161
164
  }
162
165
  /**
163
166
  * Narrow an unknown value to BrowserNotConnectedError.
@@ -166,7 +169,7 @@ function isBrowserConnectionError(value) {
166
169
  * @returns True when value is a BrowserNotConnectedError instance
167
170
  */
168
171
  function isBrowserNotConnectedError(value) {
169
- return value instanceof BrowserNotConnectedError;
172
+ return isInstance(value, BrowserNotConnectedError);
170
173
  }
171
174
  /**
172
175
  * Narrow an unknown value to BrowserDestroyedError.
@@ -175,7 +178,7 @@ function isBrowserNotConnectedError(value) {
175
178
  * @returns True when value is a BrowserDestroyedError instance
176
179
  */
177
180
  function isBrowserDestroyedError(value) {
178
- return value instanceof BrowserDestroyedError;
181
+ return isInstance(value, BrowserDestroyedError);
179
182
  }
180
183
  //#endregion
181
184
  //#region src/server/helpers.ts
@@ -263,6 +266,44 @@ function browserToEngine(browser) {
263
266
  if (browser?.includes("Chrome/") === true) return "chrome";
264
267
  return "chromium";
265
268
  }
269
+ /**
270
+ * Resolve a persistent caller profile or create an isolated temporary one.
271
+ *
272
+ * @param path - Optional caller-owned persistent user-data directory
273
+ * @returns The resolved profile and whether the library owns its lifecycle
274
+ */
275
+ async function createBrowserProfile(path) {
276
+ if (path !== void 0) return {
277
+ path,
278
+ temporary: false
279
+ };
280
+ return {
281
+ path: await mkdtemp(join(tmpdir(), BROWSER_PROFILE_PREFIX)),
282
+ temporary: true
283
+ };
284
+ }
285
+ /**
286
+ * Remove a library-owned isolated browser profile.
287
+ *
288
+ * @remarks
289
+ * The path must remain a direct child of the operating-system temp directory
290
+ * with {@link BROWSER_PROFILE_PREFIX}; this defensive check prevents a
291
+ * malformed profile value from widening recursive deletion.
292
+ *
293
+ * @param profile - Resolved profile lifecycle result
294
+ */
295
+ async function removeBrowserProfile(profile) {
296
+ if (!profile.temporary) return;
297
+ const path = resolve(profile.path);
298
+ const temporary = resolve(tmpdir());
299
+ if (dirname(path) !== temporary || !basename(path).startsWith("orkestrel-browser-")) throw new Error("Refusing to remove an unsafe browser profile path");
300
+ await rm(path, {
301
+ recursive: true,
302
+ force: true,
303
+ maxRetries: 3,
304
+ retryDelay: 100
305
+ });
306
+ }
266
307
  /** Check the env-override keys (`PLAYWRIGHT_EXECUTABLE_PATH`, `CHROME_PATH`) in order for an existing file. */
267
308
  function findEnvOverride(env) {
268
309
  return findAllEnvOverrides(env)[0];
@@ -415,7 +456,7 @@ async function fetchCDPTargets(port, timeout, host = BROWSER_DEFAULT_HOST) {
415
456
  const response = await fetch(url, { signal: controller.signal });
416
457
  if (!response.ok) return [];
417
458
  const list = await response.json();
418
- if (!Array.isArray(list)) return [];
459
+ if (!isArray(list)) return [];
419
460
  const targets = [];
420
461
  for (const entry of list) {
421
462
  if (!isRecord(entry)) continue;
@@ -479,12 +520,12 @@ var WebSocketCDPTransport = class {
479
520
  }
480
521
  this.#socket?.destroy();
481
522
  this.#socket = void 0;
482
- const attempt = this.#open();
483
- this.#starting = attempt;
523
+ const transition = this.#open();
524
+ this.#starting = transition;
484
525
  try {
485
- await attempt;
526
+ await transition;
486
527
  } finally {
487
- if (this.#starting === attempt) this.#starting = void 0;
528
+ if (this.#starting === transition) this.#starting = void 0;
488
529
  }
489
530
  }
490
531
  async send(data) {
@@ -498,16 +539,21 @@ var WebSocketCDPTransport = class {
498
539
  await active;
499
540
  return;
500
541
  }
501
- const attempt = this.#stop();
502
- this.#closing = attempt;
542
+ const transition = this.#stop();
543
+ this.#closing = transition;
503
544
  try {
504
- await attempt;
545
+ await transition;
505
546
  } finally {
506
- if (this.#closing === attempt) this.#closing = void 0;
547
+ if (this.#closing === transition) this.#closing = void 0;
507
548
  }
508
549
  }
509
550
  async #open() {
510
- const url = new URL(this.#url);
551
+ const parsed = attempt(() => new URL(this.#url));
552
+ if (!parsed.success) throw new BrowserConnectionError(`WebSocket CDP URL is invalid: ${this.#url}`, {
553
+ url: this.#url,
554
+ error: parsed.error
555
+ });
556
+ const url = parsed.value;
511
557
  if (url.protocol !== "ws:" && url.protocol !== "wss:") throw new BrowserConnectionError(`WebSocket CDP connection requires a ws: or wss: URL: ${this.#url}`, { url: this.#url });
512
558
  const key = randomBytes(16).toString("base64");
513
559
  const deferred = Promise.withResolvers();
@@ -669,6 +715,9 @@ function createScreenshotWriter() {
669
715
  }
670
716
  //#endregion
671
717
  //#region src/server/Browser.ts
718
+ /**
719
+ * Discovers, launches, connects to, and owns Chromium-family browser sessions.
720
+ */
672
721
  var Browser = class {
673
722
  #emitter;
674
723
  #options;
@@ -682,6 +731,7 @@ var Browser = class {
682
731
  #endpoint;
683
732
  #client;
684
733
  #process;
734
+ #profile;
685
735
  #contexts = [];
686
736
  #destroyed = false;
687
737
  #connecting;
@@ -779,6 +829,35 @@ var Browser = class {
779
829
  contexts() {
780
830
  return [...this.#contexts];
781
831
  }
832
+ async isolate(options) {
833
+ if (this.#destroyed) throw new BrowserDestroyedError();
834
+ const client = this.#client;
835
+ if (this.#status !== "connected" || client === void 0) throw new BrowserNotConnectedError();
836
+ validateBrowserContextOptions(options);
837
+ const params = { disposeOnDetach: false };
838
+ if (options?.proxy !== void 0) {
839
+ params["proxyServer"] = options.proxy.server;
840
+ if (options.proxy.bypass !== void 0) params["proxyBypassList"] = options.proxy.bypass.join(",");
841
+ }
842
+ if (options?.origins !== void 0) params["originsWithUniversalNetworkAccess"] = [...options.origins];
843
+ const result = await client.send("Target.createBrowserContext", params);
844
+ if (!isRecord(result) || !isString(result["browserContextId"])) throw new BrowserConnectionError("Failed to create isolated browser context");
845
+ const id = result["browserContextId"];
846
+ const context = new BrowserContext(client, id, options?.emulation?.viewport ?? this.#options.viewport, createScreenshotWriter(), options?.emulation, options?.downloads);
847
+ try {
848
+ if (options?.downloads !== void 0) await client.send("Browser.setDownloadBehavior", {
849
+ behavior: options.downloads.named === true ? "allowAndName" : "allow",
850
+ browserContextId: id,
851
+ downloadPath: options.downloads.path,
852
+ eventsEnabled: true
853
+ });
854
+ } catch (error) {
855
+ await context.close().catch(() => void 0);
856
+ throw error;
857
+ }
858
+ this.#registerContext(context);
859
+ return context;
860
+ }
782
861
  async create(options) {
783
862
  if (this.#destroyed) throw new BrowserDestroyedError();
784
863
  const client = this.#client;
@@ -786,7 +865,7 @@ var Browser = class {
786
865
  let context = this.#contexts[0];
787
866
  if (context === void 0) {
788
867
  context = new BrowserContext(client, void 0, this.#options.viewport, createScreenshotWriter());
789
- this.#contexts.push(context);
868
+ this.#registerContext(context);
790
869
  }
791
870
  const page = await context.create(options);
792
871
  this.#emitter.emit("page", page);
@@ -839,8 +918,8 @@ var Browser = class {
839
918
  if (this.#destroyed) throw new BrowserDestroyedError();
840
919
  this.#status = "error";
841
920
  this.#emitter.emit("error", error);
842
- if (error instanceof BrowserConnectionError) throw error;
843
- throw new BrowserConnectionError(error instanceof Error ? error.message : String(error), { executable: this.#options.executable });
921
+ if (isBrowserConnectionError(error)) throw error;
922
+ throw new BrowserConnectionError(isError(error) ? error.message : String(error), { executable: this.#options.executable });
844
923
  }
845
924
  }
846
925
  async #detach() {
@@ -889,6 +968,7 @@ var Browser = class {
889
968
  this.#unbindTransport();
890
969
  this.#unbindProcess();
891
970
  this.#process = void 0;
971
+ this.#releaseProfile().catch((error) => this.#emitter.emit("error", error));
892
972
  this.#client = void 0;
893
973
  this.#contexts = [];
894
974
  this.#connection = void 0;
@@ -1063,8 +1143,16 @@ var Browser = class {
1063
1143
  }
1064
1144
  if (executable === void 0) throw new BrowserConnectionError("No Chromium browser found. Install Chrome, Edge, or Chromium.", requestedEngine === void 0 ? void 0 : { engine: requestedEngine });
1065
1145
  this.#engine = resolvedEngine ?? "chromium";
1066
- const profile = this.#options.profile;
1067
- const process = launchBrowserProcess(executable, this.#cdpPort, this.#options.headless ?? true, profile, this.#options.args);
1146
+ await this.#releaseProfile();
1147
+ const profile = await createBrowserProfile(this.#options.profile);
1148
+ this.#profile = profile;
1149
+ let process;
1150
+ try {
1151
+ process = launchBrowserProcess(executable, this.#cdpPort, this.#options.headless ?? true, profile.path, this.#options.args);
1152
+ } catch (error) {
1153
+ await this.#releaseProfile();
1154
+ throw error;
1155
+ }
1068
1156
  this.#process = process;
1069
1157
  let client;
1070
1158
  try {
@@ -1078,7 +1166,7 @@ var Browser = class {
1078
1166
  timeout: this.#timeout()
1079
1167
  });
1080
1168
  await this.#raceAbort(client.connect());
1081
- const connection = profile === void 0 ? "launch" : "persistent";
1169
+ const connection = this.#options.profile === void 0 ? "launch" : "persistent";
1082
1170
  this.#client = client;
1083
1171
  this.#endpoint = endpoint;
1084
1172
  this.#connection = connection;
@@ -1094,6 +1182,7 @@ var Browser = class {
1094
1182
  this.#unbindProcess();
1095
1183
  await this.#closeClient(client);
1096
1184
  await this.#terminate(process);
1185
+ await this.#releaseProfile();
1097
1186
  this.#process = void 0;
1098
1187
  this.#client = void 0;
1099
1188
  this.#endpoint = void 0;
@@ -1110,16 +1199,16 @@ var Browser = class {
1110
1199
  const signal = AbortSignal.any([controller.signal, this.#signal()]);
1111
1200
  const ready = waitForCDPReady(this.#cdpPort, this.#timeout(), this.#cdpHost, signal);
1112
1201
  const exited = once(process, "exit", { signal }).then((values) => {
1113
- const code = typeof values[0] === "number" ? values[0] : null;
1114
- const exitSignal = typeof values[1] === "string" ? values[1] : null;
1202
+ const code = isInteger(values[0]) ? values[0] : null;
1203
+ const exitSignal = isString(values[1]) ? values[1] : null;
1115
1204
  throw new BrowserConnectionError(this.#formatLaunchExit(code, exitSignal), context);
1116
1205
  });
1117
1206
  try {
1118
1207
  return await Promise.race([ready, exited]);
1119
1208
  } catch (error) {
1120
- if (error instanceof BrowserConnectionError) throw error;
1209
+ if (isBrowserConnectionError(error)) throw error;
1121
1210
  if (this.#signal().aborted) throw new BrowserConnectionError("Connection aborted", context);
1122
- throw new BrowserConnectionError(error instanceof Error ? error.message : String(error), context);
1211
+ throw new BrowserConnectionError(isError(error) ? error.message : String(error), context);
1123
1212
  } finally {
1124
1213
  controller.abort();
1125
1214
  ready.catch(() => void 0);
@@ -1144,7 +1233,7 @@ var Browser = class {
1144
1233
  } catch {
1145
1234
  return;
1146
1235
  }
1147
- if (!isRecord(result) || !Array.isArray(result["targetInfos"])) return;
1236
+ if (!isRecord(result) || !isArray(result["targetInfos"])) return;
1148
1237
  const pages = [];
1149
1238
  for (const target of result["targetInfos"]) {
1150
1239
  if (!isRecord(target) || !isString(target["targetId"]) || target["type"] !== "page" || !isString(target["title"]) || !isString(target["url"])) continue;
@@ -1158,7 +1247,7 @@ var Browser = class {
1158
1247
  if (pages.length === 0 || this.#contexts.length > 0) return;
1159
1248
  const context = new BrowserContext(client, void 0, this.#options.viewport, createScreenshotWriter());
1160
1249
  await context.sync(pages);
1161
- this.#contexts.push(context);
1250
+ this.#registerContext(context);
1162
1251
  }
1163
1252
  async #destroyResources() {
1164
1253
  try {
@@ -1176,7 +1265,11 @@ var Browser = class {
1176
1265
  await this.#closeClient(client);
1177
1266
  this.#client = void 0;
1178
1267
  } finally {
1179
- this.#finish();
1268
+ try {
1269
+ await this.#releaseProfile();
1270
+ } finally {
1271
+ this.#finish();
1272
+ }
1180
1273
  }
1181
1274
  }
1182
1275
  async #closeResources() {
@@ -1196,7 +1289,11 @@ var Browser = class {
1196
1289
  await this.#closeClient(client);
1197
1290
  this.#client = void 0;
1198
1291
  } finally {
1199
- this.#finish();
1292
+ try {
1293
+ await this.#releaseProfile();
1294
+ } finally {
1295
+ this.#finish();
1296
+ }
1200
1297
  }
1201
1298
  }
1202
1299
  async #settle() {
@@ -1228,12 +1325,20 @@ var Browser = class {
1228
1325
  if (temporary) await this.#closeClient(remote);
1229
1326
  }
1230
1327
  async #closeContexts() {
1231
- for (const context of this.#contexts) try {
1328
+ for (const context of [...this.#contexts]) try {
1232
1329
  await context.close();
1233
1330
  } catch {}
1234
1331
  }
1235
1332
  async #destroyContexts() {
1236
- await this.#destroyContextList(this.#contexts);
1333
+ await this.#destroyContextList([...this.#contexts]);
1334
+ }
1335
+ #registerContext(context) {
1336
+ this.#contexts.push(context);
1337
+ context.emitter.on("close", () => {
1338
+ const index = this.#contexts.indexOf(context);
1339
+ if (index >= 0) this.#contexts.splice(index, 1);
1340
+ });
1341
+ this.#emitter.emit("context", context);
1237
1342
  }
1238
1343
  async #destroyContextList(contexts) {
1239
1344
  for (const context of contexts) try {
@@ -1246,6 +1351,11 @@ var Browser = class {
1246
1351
  await client.close();
1247
1352
  } catch {}
1248
1353
  }
1354
+ async #releaseProfile() {
1355
+ const profile = this.#profile;
1356
+ this.#profile = void 0;
1357
+ if (profile !== void 0) await removeBrowserProfile(profile);
1358
+ }
1249
1359
  async #waitForProcess(process) {
1250
1360
  if (process.exitCode !== null || process.signalCode !== null) return;
1251
1361
  await once(process, "exit");
@@ -1291,6 +1401,6 @@ var Browser = class {
1291
1401
  }
1292
1402
  };
1293
1403
  //#endregion
1294
- export { BROWSER_CDP_LIST_PATH, BROWSER_CDP_PROTOCOL, BROWSER_CDP_VERSION_PATH, BROWSER_DEFAULT_CDP_PORT, BROWSER_DEFAULT_HOST, BROWSER_ENGINE_HINTS, BROWSER_ENV_PATH_KEYS, BROWSER_EXECUTABLE_NAMES, BROWSER_EXECUTABLE_PATHS, BROWSER_HEADLESS_ARG, BROWSER_KILL_GRACE_MS, BROWSER_LAUNCH_ARGS, BROWSER_PORT_PROBE_TIMEOUT_MS, BROWSER_PROCESS_EXIT_CAUSE, BROWSER_STORE_CACHE_DIRS, BROWSER_STORE_DEFAULT_DIRS, BROWSER_STORE_ENV_KEY, BROWSER_STORE_GLOBS, BROWSER_STORE_LINK_NAME, BROWSER_TRANSPORT_LOSS_CAUSE, BROWSER_TRANSPORT_LOSS_DEFER_MS, BROWSER_WINDOWS_ROOT_FALLBACKS, BROWSER_WINDOWS_SUFFIXES, Browser, BrowserConnectionError, BrowserDestroyedError, BrowserNotConnectedError, WebSocketCDPTransport, browserToEngine, createBrowser, createCDPTransport, createScreenshotWriter, defaultInstallPaths, defaultStoreBases, fetchCDPTargets, findAllEnvOverrides, findAllInStore, findAllInstallPaths, findEnvOverride, findInStore, findInstallPath, findSystemBrowser, findSystemBrowsers, isBrowserConnectionError, isBrowserDestroyedError, isBrowserNotConnectedError, launchBrowserProcess, normalizeExecutablePath, parseBrowserEngine, probeAllPathNames, probePathNames, waitForCDPReady, windowsRoots };
1404
+ export { BROWSER_CDP_LIST_PATH, BROWSER_CDP_PROTOCOL, BROWSER_CDP_VERSION_PATH, BROWSER_DEFAULT_CDP_PORT, BROWSER_DEFAULT_HOST, BROWSER_ENGINE_HINTS, BROWSER_ENV_PATH_KEYS, BROWSER_EXECUTABLE_NAMES, BROWSER_EXECUTABLE_PATHS, BROWSER_HEADLESS_ARG, BROWSER_KILL_GRACE_MS, BROWSER_LAUNCH_ARGS, BROWSER_PORT_PROBE_TIMEOUT_MS, BROWSER_PROCESS_EXIT_CAUSE, BROWSER_PROFILE_PREFIX, BROWSER_STORE_CACHE_DIRS, BROWSER_STORE_DEFAULT_DIRS, BROWSER_STORE_ENV_KEY, BROWSER_STORE_GLOBS, BROWSER_STORE_LINK_NAME, BROWSER_TRANSPORT_LOSS_CAUSE, BROWSER_TRANSPORT_LOSS_DEFER_MS, BROWSER_WINDOWS_ROOT_FALLBACKS, BROWSER_WINDOWS_SUFFIXES, Browser, BrowserConnectionError, BrowserDestroyedError, BrowserNotConnectedError, WebSocketCDPTransport, browserToEngine, createBrowser, createBrowserProfile, createCDPTransport, createScreenshotWriter, defaultInstallPaths, defaultStoreBases, fetchCDPTargets, findAllEnvOverrides, findAllInStore, findAllInstallPaths, findEnvOverride, findInStore, findInstallPath, findSystemBrowser, findSystemBrowsers, isBrowserConnectionError, isBrowserDestroyedError, isBrowserNotConnectedError, launchBrowserProcess, normalizeExecutablePath, parseBrowserEngine, probeAllPathNames, probePathNames, removeBrowserProfile, waitForCDPReady, windowsRoots };
1295
1405
 
1296
1406
  //# sourceMappingURL=index.js.map