browserclaw 0.2.9 → 0.3.0

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/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as playwright_core from 'playwright-core';
2
+ import { lookup } from 'node:dns/promises';
2
3
 
3
4
  interface FrameEvalResult {
4
5
  frameUrl: string;
@@ -196,7 +197,7 @@ interface ClickOptions {
196
197
  /** Mouse button to use */
197
198
  button?: 'left' | 'right' | 'middle';
198
199
  /** Modifier keys to hold during click */
199
- modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[];
200
+ modifiers?: ('Alt' | 'Control' | 'ControlOrMeta' | 'Meta' | 'Shift')[];
200
201
  /** Timeout in milliseconds. Default: `8000` */
201
202
  timeoutMs?: number;
202
203
  }
@@ -683,6 +684,8 @@ declare class CrawlPage {
683
684
  */
684
685
  evaluate(fn: string, opts?: {
685
686
  ref?: string;
687
+ timeoutMs?: number;
688
+ signal?: AbortSignal;
686
689
  }): Promise<unknown>;
687
690
  /**
688
691
  * Run JavaScript in ALL frames on the page (including cross-origin iframes).
@@ -1107,6 +1110,7 @@ declare class BrowserClaw {
1107
1110
  stop(): Promise<void>;
1108
1111
  }
1109
1112
 
1113
+ type LookupFn = typeof lookup;
1110
1114
  /**
1111
1115
  * Thrown when a navigation URL is blocked by SSRF policy.
1112
1116
  * Callers can catch this specifically to distinguish navigation blocks
@@ -1121,5 +1125,13 @@ type BrowserNavigationPolicyOptions = {
1121
1125
  };
1122
1126
  /** Build a BrowserNavigationPolicyOptions from an SsrfPolicy. */
1123
1127
  declare function withBrowserNavigationPolicy(ssrfPolicy?: SsrfPolicy): BrowserNavigationPolicyOptions;
1128
+ /**
1129
+ * Assert that a URL is allowed for browser navigation under the given SSRF policy.
1130
+ * Throws `InvalidBrowserNavigationUrlError` if the URL is blocked.
1131
+ */
1132
+ declare function assertBrowserNavigationAllowed(opts: {
1133
+ url: string;
1134
+ lookupFn?: LookupFn;
1135
+ } & BrowserNavigationPolicyOptions): Promise<void>;
1124
1136
 
1125
- export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, withBrowserNavigationPolicy };
1137
+ export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type LookupFn, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, assertBrowserNavigationAllowed, withBrowserNavigationPolicy };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as playwright_core from 'playwright-core';
2
+ import { lookup } from 'node:dns/promises';
2
3
 
3
4
  interface FrameEvalResult {
4
5
  frameUrl: string;
@@ -196,7 +197,7 @@ interface ClickOptions {
196
197
  /** Mouse button to use */
197
198
  button?: 'left' | 'right' | 'middle';
198
199
  /** Modifier keys to hold during click */
199
- modifiers?: ('Alt' | 'Control' | 'Meta' | 'Shift')[];
200
+ modifiers?: ('Alt' | 'Control' | 'ControlOrMeta' | 'Meta' | 'Shift')[];
200
201
  /** Timeout in milliseconds. Default: `8000` */
201
202
  timeoutMs?: number;
202
203
  }
@@ -683,6 +684,8 @@ declare class CrawlPage {
683
684
  */
684
685
  evaluate(fn: string, opts?: {
685
686
  ref?: string;
687
+ timeoutMs?: number;
688
+ signal?: AbortSignal;
686
689
  }): Promise<unknown>;
687
690
  /**
688
691
  * Run JavaScript in ALL frames on the page (including cross-origin iframes).
@@ -1107,6 +1110,7 @@ declare class BrowserClaw {
1107
1110
  stop(): Promise<void>;
1108
1111
  }
1109
1112
 
1113
+ type LookupFn = typeof lookup;
1110
1114
  /**
1111
1115
  * Thrown when a navigation URL is blocked by SSRF policy.
1112
1116
  * Callers can catch this specifically to distinguish navigation blocks
@@ -1121,5 +1125,13 @@ type BrowserNavigationPolicyOptions = {
1121
1125
  };
1122
1126
  /** Build a BrowserNavigationPolicyOptions from an SsrfPolicy. */
1123
1127
  declare function withBrowserNavigationPolicy(ssrfPolicy?: SsrfPolicy): BrowserNavigationPolicyOptions;
1128
+ /**
1129
+ * Assert that a URL is allowed for browser navigation under the given SSRF policy.
1130
+ * Throws `InvalidBrowserNavigationUrlError` if the URL is blocked.
1131
+ */
1132
+ declare function assertBrowserNavigationAllowed(opts: {
1133
+ url: string;
1134
+ lookupFn?: LookupFn;
1135
+ } & BrowserNavigationPolicyOptions): Promise<void>;
1124
1136
 
1125
- export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, withBrowserNavigationPolicy };
1137
+ export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type LookupFn, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, assertBrowserNavigationAllowed, withBrowserNavigationPolicy };
package/dist/index.js CHANGED
@@ -1404,7 +1404,7 @@ async function assertBrowserNavigationAllowed(opts) {
1404
1404
  const hostname = parsed.hostname.toLowerCase();
1405
1405
  if (allowedHostnames.some((h) => h.toLowerCase() === hostname)) return;
1406
1406
  }
1407
- if (await isInternalUrlResolved(opts.url)) {
1407
+ if (await isInternalUrlResolved(opts.url, opts.lookupFn)) {
1408
1408
  throw new InvalidBrowserNavigationUrlError(
1409
1409
  `Navigation to internal/loopback address blocked: "${opts.url}". Use ssrfPolicy: { allowPrivateNetwork: true } if this is intentional.`
1410
1410
  );
@@ -1532,7 +1532,7 @@ function isInternalUrl(url) {
1532
1532
  }
1533
1533
  return false;
1534
1534
  }
1535
- async function isInternalUrlResolved(url) {
1535
+ async function isInternalUrlResolved(url, lookupFn = lookup) {
1536
1536
  if (isInternalUrl(url)) return true;
1537
1537
  let parsed;
1538
1538
  try {
@@ -1541,7 +1541,7 @@ async function isInternalUrlResolved(url) {
1541
1541
  return true;
1542
1542
  }
1543
1543
  try {
1544
- const { address } = await lookup(parsed.hostname);
1544
+ const { address } = await lookupFn(parsed.hostname);
1545
1545
  if (isInternalIP(address)) return true;
1546
1546
  } catch {
1547
1547
  return true;
@@ -1699,6 +1699,7 @@ async function evaluateViaPlaywright(opts) {
1699
1699
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
1700
1700
  ensurePageState(page);
1701
1701
  restoreRoleRefsForTarget({ cdpUrl: opts.cdpUrl, targetId: opts.targetId, page });
1702
+ const timeout = opts.timeoutMs != null ? opts.timeoutMs : void 0;
1702
1703
  if (opts.ref) {
1703
1704
  const locator = refLocator(page, opts.ref);
1704
1705
  return await locator.evaluate(
@@ -1711,10 +1712,11 @@ async function evaluateViaPlaywright(opts) {
1711
1712
  throw new Error("Invalid evaluate function: " + (err instanceof Error ? err.message : String(err)));
1712
1713
  }
1713
1714
  },
1714
- fnText
1715
+ fnText,
1716
+ { timeout }
1715
1717
  );
1716
1718
  }
1717
- return await page.evaluate(
1719
+ const evalPromise = page.evaluate(
1718
1720
  // eslint-disable-next-line no-eval
1719
1721
  (fnBody) => {
1720
1722
  try {
@@ -1726,6 +1728,13 @@ async function evaluateViaPlaywright(opts) {
1726
1728
  },
1727
1729
  fnText
1728
1730
  );
1731
+ if (!opts.signal) return evalPromise;
1732
+ return Promise.race([
1733
+ evalPromise,
1734
+ new Promise((_, reject) => {
1735
+ opts.signal.addEventListener("abort", () => reject(new Error("Evaluate aborted")), { once: true });
1736
+ })
1737
+ ]);
1729
1738
  }
1730
1739
 
1731
1740
  // src/actions/download.ts
@@ -2504,7 +2513,9 @@ var CrawlPage = class {
2504
2513
  cdpUrl: this.cdpUrl,
2505
2514
  targetId: this.targetId,
2506
2515
  fn,
2507
- ref: opts?.ref
2516
+ ref: opts?.ref,
2517
+ timeoutMs: opts?.timeoutMs,
2518
+ signal: opts?.signal
2508
2519
  });
2509
2520
  }
2510
2521
  /**
@@ -3097,6 +3108,6 @@ var BrowserClaw = class _BrowserClaw {
3097
3108
  }
3098
3109
  };
3099
3110
 
3100
- export { BrowserClaw, CrawlPage, InvalidBrowserNavigationUrlError, withBrowserNavigationPolicy };
3111
+ export { BrowserClaw, CrawlPage, InvalidBrowserNavigationUrlError, assertBrowserNavigationAllowed, withBrowserNavigationPolicy };
3101
3112
  //# sourceMappingURL=index.js.map
3102
3113
  //# sourceMappingURL=index.js.map