nothing-browser 0.0.20 → 0.1.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.
Files changed (76) hide show
  1. package/LICENSE +1 -1
  2. package/dist/human/index.js +25 -1
  3. package/dist/launch/detect.js +13 -0
  4. package/dist/launch/spawn.js +13 -0
  5. package/dist/piggy/captcha/index.d.ts +39 -0
  6. package/dist/piggy/captcha/index.d.ts.map +1 -0
  7. package/dist/piggy/capture/index.d.ts +48 -0
  8. package/dist/piggy/capture/index.d.ts.map +1 -0
  9. package/dist/piggy/dialog/index.d.ts +28 -0
  10. package/dist/piggy/dialog/index.d.ts.map +1 -0
  11. package/dist/piggy/export/index.d.ts +62 -0
  12. package/dist/piggy/export/index.d.ts.map +1 -0
  13. package/dist/piggy/find/index.d.ts +90 -0
  14. package/dist/piggy/find/index.d.ts.map +1 -0
  15. package/dist/piggy/http/index.d.ts +14 -0
  16. package/dist/piggy/http/index.d.ts.map +1 -0
  17. package/dist/piggy/human/index.d.ts +36 -4
  18. package/dist/piggy/human/index.d.ts.map +1 -1
  19. package/dist/piggy/iframe/index.d.ts +53 -0
  20. package/dist/piggy/iframe/index.d.ts.map +1 -0
  21. package/dist/piggy/interactions/index.d.ts +24 -0
  22. package/dist/piggy/interactions/index.d.ts.map +1 -0
  23. package/dist/piggy/launch/detect.d.ts +1 -1
  24. package/dist/piggy/launch/detect.d.ts.map +1 -1
  25. package/dist/piggy/launch/spawn.d.ts.map +1 -1
  26. package/dist/piggy/media/index.d.ts +11 -0
  27. package/dist/piggy/media/index.d.ts.map +1 -0
  28. package/dist/piggy/navigation/index.d.ts +16 -0
  29. package/dist/piggy/navigation/index.d.ts.map +1 -0
  30. package/dist/piggy/provide/index.d.ts +81 -0
  31. package/dist/piggy/provide/index.d.ts.map +1 -0
  32. package/dist/piggy/proxy/index.d.ts +94 -0
  33. package/dist/piggy/proxy/index.d.ts.map +1 -0
  34. package/dist/piggy/register/index.d.ts.map +1 -1
  35. package/dist/piggy/router/index.d.ts +38 -0
  36. package/dist/piggy/router/index.d.ts.map +1 -0
  37. package/dist/piggy/session/index.d.ts +27 -0
  38. package/dist/piggy/session/index.d.ts.map +1 -0
  39. package/dist/piggy/tabs/index.d.ts +10 -0
  40. package/dist/piggy/tabs/index.d.ts.map +1 -0
  41. package/dist/piggy/wait/index.d.ts +28 -0
  42. package/dist/piggy/wait/index.d.ts.map +1 -0
  43. package/dist/piggy.d.ts.map +1 -1
  44. package/dist/piggy.js +914 -181
  45. package/dist/register/index.js +39 -86
  46. package/package.json +1 -1
  47. package/piggy/captcha/index.d.ts +35 -0
  48. package/piggy/captcha/index.ts +93 -0
  49. package/piggy/capture/index.ts +76 -0
  50. package/piggy/dialog/index.d.ts +29 -0
  51. package/piggy/dialog/index.ts +85 -0
  52. package/piggy/export/index.d.ts +117 -0
  53. package/piggy/export/index.ts +147 -0
  54. package/piggy/find/index.d.ts +79 -0
  55. package/piggy/find/index.ts +165 -0
  56. package/piggy/http/index.ts +65 -0
  57. package/piggy/human/index.ts +115 -53
  58. package/piggy/iframe/index.ts +79 -0
  59. package/piggy/interactions/index.ts +79 -0
  60. package/piggy/launch/detect.ts +19 -2
  61. package/piggy/launch/spawn.ts +1 -8
  62. package/piggy/media/index.ts +46 -0
  63. package/piggy/navigation/index.ts +52 -0
  64. package/piggy/provide/index.ts +144 -0
  65. package/piggy/proxy/index.ts +154 -0
  66. package/piggy/register/index.ts +41 -59
  67. package/piggy/router/index.ts +69 -0
  68. package/piggy/session/index.ts +76 -0
  69. package/piggy/tabs/index.ts +22 -0
  70. package/piggy/wait/index.ts +90 -0
  71. package/piggy.ts +94 -39
  72. package/dist/piggy/open/index.d.ts +0 -4
  73. package/dist/piggy/open/index.d.ts.map +0 -1
  74. package/piggy/open/index.d.ts +0 -4
  75. package/piggy/open/index.d.ts.map +0 -1
  76. package/piggy/open/index.ts +0 -5
@@ -6805,6 +6805,26 @@ var require_lib = __commonJS((exports, module) => {
6805
6805
  module.exports.SqliteError = require_sqlite_error();
6806
6806
  });
6807
6807
 
6808
+ // piggy/human/index.ts
6809
+ class HumanClient {
6810
+ client;
6811
+ constructor(client) {
6812
+ this.client = client;
6813
+ }
6814
+ set(opts, tabId = "default") {
6815
+ return this.client.send("human.set", { ...opts, tabId });
6816
+ }
6817
+ get(tabId = "default") {
6818
+ return this.client.send("human.get", { tabId });
6819
+ }
6820
+ type(opts, tabId = "default") {
6821
+ return this.client.send("human.type", { ...opts, tabId });
6822
+ }
6823
+ click(opts, tabId = "default") {
6824
+ return this.client.send("human.click", { ...opts, tabId });
6825
+ }
6826
+ }
6827
+
6808
6828
  // piggy/logger/index.ts
6809
6829
  var import_ernest_logger = __toESM(require_ernest_logger(), 1);
6810
6830
  var logger = import_ernest_logger.createLogger({
@@ -22570,61 +22590,6 @@ var store = new Map;
22570
22590
  var routeRegistry = new Map;
22571
22591
  var keepAliveSites = new Set;
22572
22592
 
22573
- // piggy/human/index.ts
22574
- function randomDelay(min, max) {
22575
- return new Promise((r) => setTimeout(r, Math.floor(Math.random() * (max - min + 1)) + min));
22576
- }
22577
- function humanTypeSequence(text) {
22578
- const adjacent = {
22579
- a: ["q", "w", "s", "z"],
22580
- b: ["v", "g", "h", "n"],
22581
- c: ["x", "d", "f", "v"],
22582
- d: ["s", "e", "r", "f", "c", "x"],
22583
- e: ["w", "r", "d", "s"],
22584
- f: ["d", "r", "t", "g", "v", "c"],
22585
- g: ["f", "t", "y", "h", "b", "v"],
22586
- h: ["g", "y", "u", "j", "n", "b"],
22587
- i: ["u", "o", "k", "j"],
22588
- j: ["h", "u", "i", "k", "m", "n"],
22589
- k: ["j", "i", "o", "l", "m"],
22590
- l: ["k", "o", "p"],
22591
- m: ["n", "j", "k"],
22592
- n: ["b", "h", "j", "m"],
22593
- o: ["i", "p", "l", "k"],
22594
- p: ["o", "l"],
22595
- q: ["w", "a"],
22596
- r: ["e", "t", "f", "d"],
22597
- s: ["a", "w", "e", "d", "x", "z"],
22598
- t: ["r", "y", "g", "f"],
22599
- u: ["y", "i", "h", "j"],
22600
- v: ["c", "f", "g", "b"],
22601
- w: ["q", "e", "a", "s"],
22602
- x: ["z", "s", "d", "c"],
22603
- y: ["t", "u", "g", "h"],
22604
- z: ["a", "s", "x"]
22605
- };
22606
- const actions = [];
22607
- const typoIndices = new Set;
22608
- if (text.length > 4) {
22609
- let tries = 0;
22610
- while (typoIndices.size < 2 && tries < 20) {
22611
- typoIndices.add(Math.floor(Math.random() * text.length));
22612
- tries++;
22613
- }
22614
- }
22615
- for (let i = 0;i < text.length; i++) {
22616
- if (typoIndices.has(i)) {
22617
- const ch = text[i].toLowerCase();
22618
- const neighbors = adjacent[ch];
22619
- const typo = neighbors ? neighbors[Math.floor(Math.random() * neighbors.length)] ?? ch : ch;
22620
- actions.push(typo);
22621
- actions.push("BACKSPACE");
22622
- }
22623
- actions.push(text[i]);
22624
- }
22625
- return actions;
22626
- }
22627
-
22628
22593
  // piggy/intercept/scripts.ts
22629
22594
  function buildRespondScript(pattern, status2, contentType, body) {
22630
22595
  const safePattern = pattern.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
@@ -23035,7 +23000,7 @@ function createSiteObject(name, registeredUrl, client, tabId, pool) {
23035
23000
  },
23036
23001
  click: (selector, opts) => withErrScreen(() => withTab((t2) => retry(name, async () => {
23037
23002
  if (humanMode)
23038
- await randomDelay(80, 220);
23003
+ await new Promise((r) => setTimeout(r, 80 + Math.random() * 140));
23039
23004
  await client.waitForSelector(selector, opts?.timeout ?? 15000, t2);
23040
23005
  const ok = await client.click(selector, t2);
23041
23006
  if (!ok)
@@ -23045,48 +23010,36 @@ function createSiteObject(name, registeredUrl, client, tabId, pool) {
23045
23010
  }, opts?.retries ?? 2)), `click(${selector})`),
23046
23011
  doubleClick: (selector) => withErrScreen(() => withTab(async (t2) => {
23047
23012
  if (humanMode)
23048
- await randomDelay(80, 200);
23013
+ await new Promise((r) => setTimeout(r, 80 + Math.random() * 120));
23049
23014
  return client.doubleClick(selector, t2);
23050
23015
  }), `dblclick(${selector})`),
23051
23016
  hover: (selector) => withErrScreen(() => withTab(async (t2) => {
23052
23017
  if (humanMode)
23053
- await randomDelay(50, 150);
23018
+ await new Promise((r) => setTimeout(r, 50 + Math.random() * 100));
23054
23019
  return client.hover(selector, t2);
23055
23020
  }), `hover(${selector})`),
23056
23021
  type: (selector, text, opts) => withErrScreen(() => withTab(async (t2) => {
23057
23022
  await client.waitForSelector(selector, 30000, t2);
23058
- if (humanMode && !opts?.fact) {
23059
- const seq = humanTypeSequence(text);
23060
- let current = "";
23061
- for (const action of seq) {
23062
- if (action === "BACKSPACE")
23063
- current = current.slice(0, -1);
23064
- else
23065
- current += action;
23023
+ if (humanMode) {
23024
+ const human = new HumanClient(client);
23025
+ await human.type({
23026
+ selector,
23027
+ text,
23028
+ clear: opts?.clear ?? false,
23029
+ speed: opts?.speed
23030
+ }, t2);
23031
+ } else {
23032
+ if (opts?.clear) {
23066
23033
  await client.evaluate(`
23067
- (function() {
23068
- const el = document.querySelector('${selector}');
23069
- const nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
23070
- nativeSetter.call(el, '${current.replace(/'/g, "\\'")}');
23071
- el.dispatchEvent(new Event('input', { bubbles: true }));
23072
- el.dispatchEvent(new Event('change', { bubbles: true }));
23073
- })()
23074
- `, t2);
23075
- const wpm = opts?.wpm ?? 120;
23076
- const msPerChar = Math.round(60000 / (wpm * 5));
23077
- await randomDelay(msPerChar * 0.5, msPerChar * 1.8);
23078
- }
23079
- } else if (opts?.delay) {
23080
- for (const ch of text) {
23081
- await client.type(selector, ch, t2);
23082
- await new Promise((r) => setTimeout(r, opts.delay));
23034
+ const el = document.querySelector('${selector.replace(/'/g, "\\'")}');
23035
+ if (el) { el.value = ''; el.dispatchEvent(new Event('input', { bubbles: true })); }
23036
+ `, t2);
23083
23037
  }
23084
- } else {
23085
23038
  await client.type(selector, text, t2);
23086
23039
  }
23087
23040
  await client.evaluate(`
23088
- document.querySelector('${selector}').dispatchEvent(new Event('blur', { bubbles: true }))
23089
- `, t2);
23041
+ document.querySelector('${selector.replace(/'/g, "\\'")}')?.dispatchEvent(new Event('blur', { bubbles: true }));
23042
+ `, t2);
23090
23043
  logger_default.success(`[${name}] typed into: ${selector}`);
23091
23044
  return true;
23092
23045
  }), `type(${selector})`),
@@ -23111,7 +23064,7 @@ function createSiteObject(name, registeredUrl, client, tabId, pool) {
23111
23064
  const chunk = px / steps;
23112
23065
  for (let i = 0;i < steps; i++) {
23113
23066
  await client.scrollBy(chunk, t2);
23114
- await randomDelay(30, 80);
23067
+ await new Promise((r) => setTimeout(r, 30 + Math.random() * 50));
23115
23068
  }
23116
23069
  } else {
23117
23070
  await client.scrollBy(px, t2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothing-browser",
3
- "version": "0.0.20",
3
+ "version": "0.1.0",
4
4
  "description": "Browser automation library powered by Nothing Browser",
5
5
  "homepage": "https://github.com/ernest-tech-house-co-operation/nothing-browser#readme",
6
6
  "repository": {
@@ -0,0 +1,35 @@
1
+ // piggy/captcha/index.d.ts
2
+ import { PiggyClient } from "../client";
3
+
4
+ export interface CaptchaState {
5
+ detected: boolean;
6
+ paused: boolean;
7
+ type: string;
8
+ }
9
+
10
+ export interface BlockState {
11
+ detected: boolean;
12
+ type: string;
13
+ }
14
+
15
+ export declare class CaptchaClient {
16
+ constructor(client: PiggyClient);
17
+
18
+ status(tabId?: string): Promise<CaptchaState>;
19
+ resolve(tabId?: string): Promise<void>;
20
+ pause(tabId?: string): Promise<void>;
21
+ check(tabId?: string): Promise<void>;
22
+ setAutoRetry(enabled: boolean): Promise<void>;
23
+
24
+ blockStatus(tabId?: string): Promise<BlockState>;
25
+ blockRetry(tabId?: string): Promise<void>;
26
+
27
+ onCaptcha(tabId: string, handler: (data: { captchaType: string; tabId: string }) => void): () => void;
28
+ onCaptchaResolved(tabId: string, handler: (data: { tabId: string }) => void): () => void;
29
+ onBlocked(tabId: string, handler: (data: { blockType: string; tabId: string }) => void): () => void;
30
+ onBlockRetry(tabId: string, handler: (data: { tabId: string; proxy: string }) => void): () => void;
31
+
32
+ waitForResolution(tabId?: string, timeoutMs?: number): Promise<void>;
33
+ }
34
+
35
+ export declare function createCaptchaAPI(client: PiggyClient): CaptchaClient;
@@ -0,0 +1,93 @@
1
+ // piggy/captcha/index.ts
2
+ import { PiggyClient } from "../client";
3
+ import logger from "../logger";
4
+
5
+ export interface CaptchaState {
6
+ detected: boolean;
7
+ paused: boolean;
8
+ type: string; // "cloudflare" | "recaptcha" | "hcaptcha" | "generic"
9
+ }
10
+
11
+ export interface BlockState {
12
+ detected: boolean;
13
+ type: string; // "403" | "access-denied" | "firewall" | "rate-limit"
14
+ }
15
+
16
+ export class CaptchaClient {
17
+ constructor(private client: PiggyClient) {}
18
+
19
+ // ── Captcha ───────────────────────────────────────────────────────────────
20
+
21
+ status(tabId = "default"): Promise<CaptchaState> {
22
+ return this.client.send("captcha.status", { tabId });
23
+ }
24
+
25
+ resolve(tabId = "default"): Promise<void> {
26
+ return this.client.send("captcha.resolve", { tabId });
27
+ }
28
+
29
+ pause(tabId = "default"): Promise<void> {
30
+ return this.client.send("captcha.pause", { tabId });
31
+ }
32
+
33
+ check(tabId = "default"): Promise<void> {
34
+ return this.client.send("captcha.check", { tabId });
35
+ }
36
+
37
+ setAutoRetry(enabled: boolean): Promise<void> {
38
+ return this.client.send("captcha.autoRetry", { enabled });
39
+ }
40
+
41
+ // ── Block ─────────────────────────────────────────────────────────────────
42
+
43
+ blockStatus(tabId = "default"): Promise<BlockState> {
44
+ return this.client.send("block.status", { tabId });
45
+ }
46
+
47
+ blockRetry(tabId = "default"): Promise<void> {
48
+ return this.client.send("block.retry", { tabId });
49
+ }
50
+
51
+ // ── Event subscriptions ───────────────────────────────────────────────────
52
+
53
+ onCaptcha(tabId: string, handler: (data: { captchaType: string; tabId: string }) => void): () => void {
54
+ return this.client.onEvent("captcha", tabId, handler);
55
+ }
56
+
57
+ onCaptchaResolved(tabId: string, handler: (data: { tabId: string }) => void): () => void {
58
+ return this.client.onEvent("captcha:resolved", tabId, handler);
59
+ }
60
+
61
+ onBlocked(tabId: string, handler: (data: { blockType: string; tabId: string }) => void): () => void {
62
+ return this.client.onEvent("blocked", tabId, handler);
63
+ }
64
+
65
+ onBlockRetry(tabId: string, handler: (data: { tabId: string; proxy: string }) => void): () => void {
66
+ return this.client.onEvent("block:retry", tabId, handler);
67
+ }
68
+
69
+ // ── Convenience: wait until captcha is resolved ───────────────────────────
70
+
71
+ waitForResolution(tabId = "default", timeoutMs = 300_000): Promise<void> {
72
+ return new Promise((resolve, reject) => {
73
+ const timer = setTimeout(() => {
74
+ unsub();
75
+ reject(new Error(`captcha.waitForResolution: timed out after ${timeoutMs}ms`));
76
+ }, timeoutMs);
77
+
78
+ const unsub = this.onCaptchaResolved(tabId, () => {
79
+ clearTimeout(timer);
80
+ unsub();
81
+ resolve();
82
+ });
83
+
84
+ logger.warn(`[captcha] waiting for manual resolution on tab ${tabId}…`);
85
+ });
86
+ }
87
+ }
88
+
89
+ // ── Factory helper so site objects can expose a .captcha sub-namespace ────────
90
+
91
+ export function createCaptchaAPI(client: PiggyClient): CaptchaClient {
92
+ return new CaptchaClient(client);
93
+ }
@@ -0,0 +1,76 @@
1
+ // piggy/capture/index.ts
2
+ import { PiggyClient } from "../client";
3
+
4
+ export interface CapturedRequest {
5
+ method: string;
6
+ url: string;
7
+ status: string;
8
+ type: string;
9
+ mime: string;
10
+ reqHeaders: string;
11
+ reqBody: string;
12
+ resHeaders: string;
13
+ resBody: string;
14
+ size: number;
15
+ timestamp: string;
16
+ }
17
+
18
+ export interface WebSocketFrame {
19
+ connectionId: string;
20
+ url: string;
21
+ direction: string;
22
+ data: string;
23
+ binary: boolean;
24
+ timestamp: string;
25
+ }
26
+
27
+ export interface CapturedCookie {
28
+ name: string;
29
+ value: string;
30
+ domain: string;
31
+ path: string;
32
+ httpOnly: boolean;
33
+ secure: boolean;
34
+ expires: string;
35
+ }
36
+
37
+ export interface StorageEntry {
38
+ key: string;
39
+ value: string;
40
+ }
41
+
42
+ export class CaptureClient {
43
+ constructor(private client: PiggyClient) {}
44
+
45
+ start(tabId = "default"): Promise<void> {
46
+ return this.client.send("capture.start", { tabId });
47
+ }
48
+
49
+ stop(tabId = "default"): Promise<void> {
50
+ return this.client.send("capture.stop", { tabId });
51
+ }
52
+
53
+ requests(tabId = "default"): Promise<CapturedRequest[]> {
54
+ return this.client.send("capture.requests", { tabId });
55
+ }
56
+
57
+ ws(tabId = "default"): Promise<WebSocketFrame[]> {
58
+ return this.client.send("capture.ws", { tabId });
59
+ }
60
+
61
+ cookies(tabId = "default"): Promise<CapturedCookie[]> {
62
+ return this.client.send("capture.cookies", { tabId });
63
+ }
64
+
65
+ storage(tabId = "default"): Promise<StorageEntry[]> {
66
+ return this.client.send("capture.storage", { tabId });
67
+ }
68
+
69
+ clear(tabId = "default"): Promise<void> {
70
+ return this.client.send("capture.clear", { tabId });
71
+ }
72
+ }
73
+
74
+ export function createCaptureAPI(client: PiggyClient): CaptureClient {
75
+ return new CaptureClient(client);
76
+ }
@@ -0,0 +1,29 @@
1
+ // piggy/dialog/index.d.ts
2
+ import { PiggyClient } from "../client";
3
+
4
+ export interface DialogState {
5
+ pending: boolean;
6
+ type: string;
7
+ message: string;
8
+ defaultValue: string;
9
+ }
10
+
11
+ export declare class DialogClient {
12
+ constructor(client: PiggyClient);
13
+
14
+ accept(tabId?: string, text?: string): Promise<void>;
15
+ dismiss(tabId?: string): Promise<void>;
16
+ status(tabId?: string): Promise<DialogState>;
17
+ setAutoAction(tabId?: string, action: "accept" | "dismiss" | ""): Promise<void>;
18
+ upload(selector: string, filePath: string, tabId?: string): Promise<void>;
19
+
20
+ onDialog(
21
+ tabId: string,
22
+ handler: (data: { dialogType: string; message: string; defaultValue: string; tabId: string }) => void
23
+ ): () => void;
24
+
25
+ waitAndAccept(tabId?: string, text?: string, timeoutMs?: number): Promise<DialogState>;
26
+ waitAndDismiss(tabId?: string, timeoutMs?: number): Promise<DialogState>;
27
+ }
28
+
29
+ export declare function createDialogAPI(client: PiggyClient): DialogClient;
@@ -0,0 +1,85 @@
1
+ // piggy/dialog/index.ts
2
+ import { PiggyClient } from "../client";
3
+ import logger from "../logger";
4
+
5
+ export interface DialogState {
6
+ pending: boolean;
7
+ type: string; // "alert" | "confirm" | "prompt" | "beforeunload"
8
+ message: string;
9
+ defaultValue: string;
10
+ }
11
+
12
+ // Event data from C++ (doesn't include pending)
13
+ interface DialogEventData {
14
+ dialogType: string;
15
+ message: string;
16
+ defaultValue: string;
17
+ tabId: string;
18
+ }
19
+
20
+ export class DialogClient {
21
+ constructor(private client: PiggyClient) {}
22
+
23
+ accept(tabId = "default", text?: string): Promise<void> {
24
+ return this.client.send("dialog.accept", { tabId, ...(text !== undefined ? { text } : {}) });
25
+ }
26
+
27
+ dismiss(tabId = "default"): Promise<void> {
28
+ return this.client.send("dialog.dismiss", { tabId });
29
+ }
30
+
31
+ status(tabId = "default"): Promise<DialogState> {
32
+ return this.client.send("dialog.status", { tabId });
33
+ }
34
+
35
+ setAutoAction(tabId = "default", action: "accept" | "dismiss" | ""): Promise<void> {
36
+ return this.client.send("dialog.onDialog", { tabId, action });
37
+ }
38
+
39
+ upload(selector: string, filePath: string, tabId = "default"): Promise<void> {
40
+ return this.client.send("upload", { selector, path: filePath, tabId });
41
+ }
42
+
43
+ onDialog(
44
+ tabId: string,
45
+ handler: (data: DialogEventData) => void
46
+ ): () => void {
47
+ return this.client.onEvent("dialog", tabId, handler);
48
+ }
49
+
50
+ waitAndAccept(tabId = "default", text?: string, timeoutMs = 30_000): Promise<DialogEventData> {
51
+ return new Promise((resolve, reject) => {
52
+ const timer = setTimeout(() => {
53
+ unsub();
54
+ reject(new Error(`dialog.waitAndAccept: timed out after ${timeoutMs}ms`));
55
+ }, timeoutMs);
56
+
57
+ const unsub = this.onDialog(tabId, async (data) => {
58
+ clearTimeout(timer);
59
+ unsub();
60
+ await this.accept(tabId, text);
61
+ resolve(data);
62
+ });
63
+ });
64
+ }
65
+
66
+ waitAndDismiss(tabId = "default", timeoutMs = 30_000): Promise<DialogEventData> {
67
+ return new Promise((resolve, reject) => {
68
+ const timer = setTimeout(() => {
69
+ unsub();
70
+ reject(new Error(`dialog.waitAndDismiss: timed out after ${timeoutMs}ms`));
71
+ }, timeoutMs);
72
+
73
+ const unsub = this.onDialog(tabId, async (data) => {
74
+ clearTimeout(timer);
75
+ unsub();
76
+ await this.dismiss(tabId);
77
+ resolve(data);
78
+ });
79
+ });
80
+ }
81
+ }
82
+
83
+ export function createDialogAPI(client: PiggyClient): DialogClient {
84
+ return new DialogClient(client);
85
+ }
@@ -0,0 +1,117 @@
1
+ // piggy/export/index.d.ts
2
+ import { PiggyClient } from "../client";
3
+
4
+ export interface CookieSetOptions {
5
+ name: string;
6
+ value: string;
7
+ domain: string;
8
+ /** @default "/" */
9
+ path?: string;
10
+ /** @default false */
11
+ httpOnly?: boolean;
12
+ /** @default false */
13
+ secure?: boolean;
14
+ /** Unix epoch seconds. Omit for a session cookie. */
15
+ expiry?: number;
16
+ }
17
+
18
+ export interface CookieDeleteOptions {
19
+ name: string;
20
+ domain: string;
21
+ }
22
+
23
+ export interface CapturedRequest {
24
+ method: string;
25
+ url: string;
26
+ status: string;
27
+ type: string;
28
+ mime: string;
29
+ reqHeaders: string;
30
+ reqBody: string;
31
+ resHeaders: string;
32
+ resBody: string;
33
+ }
34
+
35
+ export interface WebSocketFrame {
36
+ url: string;
37
+ direction: string;
38
+ data: string;
39
+ binary: boolean;
40
+ }
41
+
42
+ export interface CapturedCookie {
43
+ name: string;
44
+ value: string;
45
+ domain: string;
46
+ }
47
+
48
+ export interface SessionExport {
49
+ url: string;
50
+ requests: CapturedRequest[];
51
+ ws: WebSocketFrame[];
52
+ cookies: CapturedCookie[];
53
+ }
54
+
55
+ export interface SessionPaths {
56
+ workDir: string;
57
+ cookies: string;
58
+ profile: string;
59
+ ws: string;
60
+ pings: string;
61
+ }
62
+
63
+ export interface InterceptRule {
64
+ pattern: string;
65
+ block?: boolean;
66
+ redirect?: string;
67
+ setHeaders?: Record<string, string>;
68
+ removeHeaders?: string[];
69
+ }
70
+
71
+ export interface ExposedFunctionCall {
72
+ name: string;
73
+ callId: string;
74
+ data: string;
75
+ tabId: string;
76
+ }
77
+
78
+ export declare class ExportClient {
79
+ constructor(client: PiggyClient);
80
+
81
+ // Cookies
82
+ setCookie(opts: CookieSetOptions, tabId?: string): Promise<void>;
83
+ deleteCookie(opts: CookieDeleteOptions, tabId?: string): Promise<void>;
84
+
85
+ // Session
86
+ sessionReload(tabId?: string): Promise<void>;
87
+ cookiesPath(tabId?: string): Promise<string>;
88
+ profilePath(tabId?: string): Promise<string>;
89
+ wsPath(tabId?: string): Promise<string>;
90
+ pingsPath(tabId?: string): Promise<string>;
91
+ sessionPaths(tabId?: string): Promise<SessionPaths>;
92
+ setWsSave(enabled: boolean, tabId?: string): Promise<void>;
93
+ setPingsSave(enabled: boolean, tabId?: string): Promise<void>;
94
+
95
+ // Intercept rules
96
+ addInterceptRule(rule: InterceptRule, tabId?: string): Promise<void>;
97
+ clearInterceptRules(tabId?: string): Promise<void>;
98
+
99
+ // Session export / import
100
+ exportSession(tabId?: string): Promise<SessionExport>;
101
+ importSession(data: SessionExport, tabId?: string): Promise<void>;
102
+
103
+ // Exposed functions
104
+ exposeFunction(name: string, tabId?: string): Promise<void>;
105
+ resolveExposed(callId: string, result: string, isError?: boolean, tabId?: string): Promise<void>;
106
+
107
+ // Init scripts
108
+ addInitScript(js: string, tabId?: string): Promise<void>;
109
+
110
+ // Events
111
+ onExposedFunctionCalled(
112
+ tabId: string,
113
+ handler: (call: ExposedFunctionCall) => void
114
+ ): () => void;
115
+ }
116
+
117
+ export declare function createExportAPI(client: PiggyClient): ExportClient;