barebrowse 0.17.0 → 0.19.1

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.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * dialog.js — Shared JS-dialog decision core for both engines.
3
+ *
4
+ * A JS dialog (alert/confirm/prompt/beforeunload) surfaces differently per
5
+ * protocol — CDP's `Page.javascriptDialogOpening` vs BiDi's
6
+ * `browsingContext.userPromptOpened` — but the *decision* (accept? what prompt
7
+ * text?) and the log entry are identical. This module single-sources both so
8
+ * the CDP path (index.js) and the BiDi path (firefox-page.js) can't drift
9
+ * (code-review Phase-3 finding #5).
10
+ */
11
+ /**
12
+ * Build a dialogLog entry from a normalized dialog descriptor.
13
+ * @param {string} type - 'alert' | 'confirm' | 'prompt' | 'beforeunload'
14
+ * @param {string} [message]
15
+ * @returns {{type: string, message: string, timestamp: string}}
16
+ */
17
+ export function dialogLogEntry(type: string, message?: string): {
18
+ type: string;
19
+ message: string;
20
+ timestamp: string;
21
+ };
22
+ /**
23
+ * Decide how to answer a JS dialog. Default policy (both engines): accept
24
+ * everything except `beforeunload` (dismiss = stay on page); a `prompt`
25
+ * returns its default text. A caller-installed handler may override via
26
+ * `{ accept, promptText }`; if the handler throws we keep the defaults so the
27
+ * page never hangs waiting for a reply that never arrives.
28
+ *
29
+ * @param {{type: string, message?: string, defaultPrompt?: string}} dialog
30
+ * @param {?(function({type,message,defaultPrompt}): (object|Promise<object>))} handler
31
+ * @returns {Promise<{accept: boolean, promptText: string}>}
32
+ */
33
+ export function decideDialog({ type, message, defaultPrompt }: {
34
+ type: string;
35
+ message?: string;
36
+ defaultPrompt?: string;
37
+ }, handler: ((arg0: {
38
+ type: any;
39
+ message: any;
40
+ defaultPrompt: any;
41
+ }) => (object | Promise<object>)) | null): Promise<{
42
+ accept: boolean;
43
+ promptText: string;
44
+ }>;
@@ -7,6 +7,9 @@
7
7
  * @param {string} [opts.uploadDir] - When set, upload() rejects files outside this dir.
8
8
  * @param {boolean} [opts.incognito=false] - Clean session: injectCookies() is a no-op.
9
9
  * @param {boolean} [opts.consent=true] - Auto-dismiss cookie consent dialogs after goto().
10
+ * @param {boolean} [opts.hybrid=false] - Relaunch headed on a bot-challenge page and retry.
11
+ * @param {boolean} [opts.headed=false] - Whether the browser was launched headed (skips hybrid fallback).
12
+ * @param {?function(): Promise<{bidi: object, topContext: string}>} [opts.relaunchHeaded] - Hybrid relaunch hook (from connectFirefox).
10
13
  * @returns {Promise<object>} page object
11
14
  */
12
15
  export function createFirefoxPage(bidi: object, opts?: {
@@ -18,4 +21,10 @@ export function createFirefoxPage(bidi: object, opts?: {
18
21
  uploadDir?: string | undefined;
19
22
  incognito?: boolean | undefined;
20
23
  consent?: boolean | undefined;
24
+ hybrid?: boolean | undefined;
25
+ headed?: boolean | undefined;
26
+ relaunchHeaded?: (() => Promise<{
27
+ bidi: object;
28
+ topContext: string;
29
+ }>) | null | undefined;
21
30
  }): Promise<object>;
@@ -14,6 +14,7 @@ export function findFirefox(): string;
14
14
  * @param {string} [opts.proxy] - Proxy 'host:port' or 'scheme://host:port'
15
15
  * (http/https → HTTP+SSL proxy; socks/socks5/socks4 → SOCKS), via prefs
16
16
  * @param {{width:number,height:number}} [opts.viewport] - Initial window size
17
+ * @param {string} [opts.downloadDir] - Route downloads here (throwaway dir), no prompt
17
18
  * @returns {Promise<{wsUrl: string, process: import('node:child_process').ChildProcess, port: number, ownedProfileDir: string}>}
18
19
  */
19
20
  export function launchFirefox(opts?: {
@@ -25,6 +26,7 @@ export function launchFirefox(opts?: {
25
26
  width: number;
26
27
  height: number;
27
28
  } | undefined;
29
+ downloadDir?: string | undefined;
28
30
  }): Promise<{
29
31
  wsUrl: string;
30
32
  process: import("node:child_process").ChildProcess;
package/types/index.d.ts CHANGED
@@ -129,21 +129,5 @@ export function connect(opts?: {
129
129
  export function applyBlocklist(session: any, pageOpts: any): Promise<void>;
130
130
  /** Test-only: reset the warn-once flag. Not part of the public API. */
131
131
  export function _resetBlocklistWarning(): void;
132
- /**
133
- * Detect if a page is a bot-challenge page (Cloudflare, hCaptcha, etc.).
134
- *
135
- * Pre-H9 this was over-aggressive: `nodeCount < 50` alone fired on any
136
- * legitimate small page (404s, simple landings, error pages), and generic
137
- * phrases like "access denied" / "unknown error" / "permission denied"
138
- * triggered on real HTTP 4xx/5xx pages, kicking hybrid mode into a costly
139
- * headed fallback for nothing.
140
- *
141
- * H9 split: STRONG_PHRASES are essentially-unambiguous challenge UI and
142
- * fire regardless of page size; WEAK_PHRASES only fire when the page is
143
- * ALSO tiny (so a legitimate-looking error page with "access denied" in
144
- * its body doesn't trip the fallback).
145
- *
146
- * @param {object} tree - Nested ARIA tree (from buildTree)
147
- * @param {number} [nodeCount] - Raw CDP node count (from Accessibility.getFullAXTree)
148
- */
149
- export function isChallengePage(tree: object, nodeCount?: number): boolean;
132
+ export { isChallengePage };
133
+ import { isChallengePage } from './challenge.js';