nothing-browser 0.1.2 → 0.1.4
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/package.json +14 -26
- package/piggy/cache/{memory.ts → memory.js} +5 -10
- package/piggy/captcha/{index.ts → index.js} +19 -28
- package/piggy/capture/index.js +40 -0
- package/piggy/client/{index.ts → index.js} +133 -154
- package/piggy/dialog/{index.ts → index.js} +15 -31
- package/piggy/export/index.js +105 -0
- package/piggy/expose/index.js +24 -0
- package/piggy/find/{index.ts → index.js} +24 -39
- package/piggy/http/{index.ts → index.js} +7 -16
- package/piggy/human/{index.ts → index.js} +18 -49
- package/piggy/iframe/index.js +56 -0
- package/piggy/interactions/{index.ts → index.js} +20 -23
- package/piggy/intercept/{scripts.ts → scripts.js} +4 -13
- package/piggy/launch/{detect.ts → detect.js} +4 -6
- package/piggy/launch/{spawn.ts → spawn.js} +17 -22
- package/piggy/media/{index.ts → index.js} +13 -11
- package/piggy/navigation/{index.ts → index.js} +16 -14
- package/piggy/pool/index.js +76 -0
- package/piggy/provide/index.js +97 -0
- package/piggy/proxy/index.js +95 -0
- package/piggy/register/index.js +543 -0
- package/piggy/router/index.js +44 -0
- package/piggy/server/{index.ts → index.js} +16 -64
- package/piggy/session/index.js +69 -0
- package/piggy/store/{index.ts → index.js} +22 -62
- package/piggy/tabs/index.js +24 -0
- package/piggy/wait/index.js +77 -0
- package/piggy.js +316 -0
- package/dist/cache/memory.js +0 -35
- package/dist/client/index.js +0 -1284
- package/dist/human/index.js +0 -82
- package/dist/launch/detect.js +0 -782
- package/dist/launch/spawn.js +0 -915
- package/dist/logger/index.js +0 -733
- package/dist/piggy/cache/memory.d.ts +0 -7
- package/dist/piggy/cache/memory.d.ts.map +0 -1
- package/dist/piggy/captcha/index.d.ts +0 -39
- package/dist/piggy/captcha/index.d.ts.map +0 -1
- package/dist/piggy/capture/index.d.ts +0 -48
- package/dist/piggy/capture/index.d.ts.map +0 -1
- package/dist/piggy/client/index.d.ts +0 -146
- package/dist/piggy/client/index.d.ts.map +0 -1
- package/dist/piggy/dialog/index.d.ts +0 -28
- package/dist/piggy/dialog/index.d.ts.map +0 -1
- package/dist/piggy/export/index.d.ts +0 -62
- package/dist/piggy/export/index.d.ts.map +0 -1
- package/dist/piggy/expose/index.d.ts +0 -6
- package/dist/piggy/expose/index.d.ts.map +0 -1
- package/dist/piggy/find/index.d.ts +0 -52
- package/dist/piggy/find/index.d.ts.map +0 -1
- package/dist/piggy/http/index.d.ts +0 -14
- package/dist/piggy/http/index.d.ts.map +0 -1
- package/dist/piggy/human/index.d.ts +0 -39
- package/dist/piggy/human/index.d.ts.map +0 -1
- package/dist/piggy/iframe/index.d.ts +0 -53
- package/dist/piggy/iframe/index.d.ts.map +0 -1
- package/dist/piggy/interactions/index.d.ts +0 -24
- package/dist/piggy/interactions/index.d.ts.map +0 -1
- package/dist/piggy/intercept/scripts.d.ts +0 -13
- package/dist/piggy/intercept/scripts.d.ts.map +0 -1
- package/dist/piggy/launch/detect.d.ts +0 -3
- package/dist/piggy/launch/detect.d.ts.map +0 -1
- package/dist/piggy/launch/spawn.d.ts +0 -6
- package/dist/piggy/launch/spawn.d.ts.map +0 -1
- package/dist/piggy/logger/index.d.ts +0 -3
- package/dist/piggy/logger/index.d.ts.map +0 -1
- package/dist/piggy/media/index.d.ts +0 -11
- package/dist/piggy/media/index.d.ts.map +0 -1
- package/dist/piggy/navigation/index.d.ts +0 -16
- package/dist/piggy/navigation/index.d.ts.map +0 -1
- package/dist/piggy/pool/index.d.ts +0 -23
- package/dist/piggy/pool/index.d.ts.map +0 -1
- package/dist/piggy/provide/index.d.ts +0 -98
- package/dist/piggy/provide/index.d.ts.map +0 -1
- package/dist/piggy/proxy/index.d.ts +0 -94
- package/dist/piggy/proxy/index.d.ts.map +0 -1
- package/dist/piggy/register/index.d.ts +0 -9
- package/dist/piggy/register/index.d.ts.map +0 -1
- package/dist/piggy/router/index.d.ts +0 -38
- package/dist/piggy/router/index.d.ts.map +0 -1
- package/dist/piggy/server/index.d.ts +0 -42
- package/dist/piggy/server/index.d.ts.map +0 -1
- package/dist/piggy/session/index.d.ts +0 -27
- package/dist/piggy/session/index.d.ts.map +0 -1
- package/dist/piggy/store/index.d.ts +0 -22
- package/dist/piggy/store/index.d.ts.map +0 -1
- package/dist/piggy/tabs/index.d.ts +0 -12
- package/dist/piggy/tabs/index.d.ts.map +0 -1
- package/dist/piggy/wait/index.d.ts +0 -28
- package/dist/piggy/wait/index.d.ts.map +0 -1
- package/dist/piggy.d.ts +0 -10
- package/dist/piggy.d.ts.map +0 -1
- package/dist/piggy.js +0 -30186
- package/dist/register/index.js +0 -23710
- package/dist/server/index.js +0 -26831
- package/piggy/capture/index.ts +0 -76
- package/piggy/export/index.d.ts +0 -117
- package/piggy/export/index.ts +0 -147
- package/piggy/expose/index.ts +0 -42
- package/piggy/iframe/index.ts +0 -79
- package/piggy/intercept/scripts.d.ts +0 -13
- package/piggy/intercept/scripts.d.ts.map +0 -1
- package/piggy/launch/detect.d.ts +0 -3
- package/piggy/launch/detect.d.ts.map +0 -1
- package/piggy/launch/spawn.d.ts +0 -6
- package/piggy/launch/spawn.d.ts.map +0 -1
- package/piggy/logger/index.d.ts +0 -3
- package/piggy/logger/index.d.ts.map +0 -1
- package/piggy/pool/index.d.ts +0 -12
- package/piggy/pool/index.ts +0 -75
- package/piggy/provide/index.ts +0 -170
- package/piggy/proxy/index.ts +0 -154
- package/piggy/register/index.ts +0 -575
- package/piggy/router/index.ts +0 -69
- package/piggy/session/index.ts +0 -76
- package/piggy/store/index.d.ts +0 -26
- package/piggy/tabs/index.ts +0 -23
- package/piggy/wait/index.ts +0 -90
- package/piggy.ts +0 -274
- /package/piggy/logger/{index.ts → index.js} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//piggy/client/index.
|
|
2
|
-
import { connect
|
|
1
|
+
// piggy/client/index.js
|
|
2
|
+
import { connect } from "net";
|
|
3
3
|
import { writeFileSync, mkdirSync } from "fs";
|
|
4
4
|
import { dirname } from "path";
|
|
5
5
|
import { platform } from "os";
|
|
@@ -9,30 +9,18 @@ const DEFAULT_SOCKET_PATH = platform() === "win32"
|
|
|
9
9
|
? "\\\\.\\pipe\\piggy"
|
|
10
10
|
: "/tmp/piggy";
|
|
11
11
|
|
|
12
|
-
// ── Transport interface ────────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
interface Transport {
|
|
15
|
-
send(data: string): void;
|
|
16
|
-
on(event: "data", handler: (chunk: string) => void): void;
|
|
17
|
-
on(event: "error", handler: (e: Error) => void): void;
|
|
18
|
-
on(event: "close", handler: () => void): void;
|
|
19
|
-
destroy(): void;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
12
|
// ── Socket transport ───────────────────────────────────────────────────────────
|
|
23
13
|
|
|
24
|
-
class SocketTransport
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
constructor(sock: Socket) {
|
|
14
|
+
class SocketTransport {
|
|
15
|
+
constructor(sock) {
|
|
28
16
|
this.sock = sock;
|
|
29
17
|
}
|
|
30
18
|
|
|
31
|
-
send(data
|
|
19
|
+
send(data) {
|
|
32
20
|
this.sock.write(data);
|
|
33
21
|
}
|
|
34
22
|
|
|
35
|
-
on(event
|
|
23
|
+
on(event, handler) {
|
|
36
24
|
this.sock.on(event, handler);
|
|
37
25
|
}
|
|
38
26
|
|
|
@@ -43,26 +31,23 @@ class SocketTransport implements Transport {
|
|
|
43
31
|
|
|
44
32
|
// ── HTTP transport ─────────────────────────────────────────────────────────────
|
|
45
33
|
|
|
46
|
-
class HttpTransport
|
|
47
|
-
|
|
48
|
-
private key: string;
|
|
49
|
-
private dataHandlers: ((chunk: string) => void)[] = [];
|
|
50
|
-
private errorHandlers: ((e: Error) => void)[] = [];
|
|
51
|
-
private closeHandlers: (() => void)[] = [];
|
|
52
|
-
private _destroyed = false;
|
|
53
|
-
|
|
54
|
-
constructor(host: string, key: string) {
|
|
34
|
+
class HttpTransport {
|
|
35
|
+
constructor(host, key) {
|
|
55
36
|
this.host = host.replace(/\/$/, "");
|
|
56
37
|
this.key = key;
|
|
38
|
+
this.dataHandlers = [];
|
|
39
|
+
this.errorHandlers = [];
|
|
40
|
+
this.closeHandlers = [];
|
|
41
|
+
this._destroyed = false;
|
|
57
42
|
}
|
|
58
43
|
|
|
59
|
-
on(event
|
|
44
|
+
on(event, handler) {
|
|
60
45
|
if (event === "data") this.dataHandlers.push(handler);
|
|
61
46
|
if (event === "error") this.errorHandlers.push(handler);
|
|
62
47
|
if (event === "close") this.closeHandlers.push(handler);
|
|
63
48
|
}
|
|
64
49
|
|
|
65
|
-
send(data
|
|
50
|
+
send(data) {
|
|
66
51
|
if (this._destroyed) return;
|
|
67
52
|
|
|
68
53
|
fetch(this.host, {
|
|
@@ -87,7 +72,7 @@ class HttpTransport implements Transport {
|
|
|
87
72
|
this.dataHandlers.forEach(h => h(line + "\n"));
|
|
88
73
|
}
|
|
89
74
|
})
|
|
90
|
-
.catch((e
|
|
75
|
+
.catch((e) => {
|
|
91
76
|
if (!this._destroyed) {
|
|
92
77
|
this.errorHandlers.forEach(h => h(e));
|
|
93
78
|
}
|
|
@@ -103,38 +88,30 @@ class HttpTransport implements Transport {
|
|
|
103
88
|
// ── PiggyClient ────────────────────────────────────────────────────────────────
|
|
104
89
|
|
|
105
90
|
export class PiggyClient {
|
|
106
|
-
|
|
107
|
-
private httpHost: string | null = null;
|
|
108
|
-
private httpKey: string | null = null;
|
|
109
|
-
private transport: Transport | null = null;
|
|
110
|
-
private reqId = 0;
|
|
111
|
-
private pending = new Map<string, { resolve: (v: any) => void; reject: (e: Error) => void }>();
|
|
112
|
-
private buf = "";
|
|
113
|
-
private eventHandlers = new Map<string, Map<string, (data: any) => Promise<any>>>();
|
|
114
|
-
private globalEventHandlers = new Map<string, Set<(data: any) => void>>();
|
|
115
|
-
|
|
116
|
-
constructor(socketPath?: string);
|
|
117
|
-
constructor(opts: { host: string; key: string });
|
|
118
|
-
|
|
119
|
-
constructor(arg?: string | { host: string; key: string }) {
|
|
91
|
+
constructor(arg) {
|
|
120
92
|
if (arg && typeof arg === "object") {
|
|
121
93
|
this.socketPath = "";
|
|
122
94
|
this.httpHost = arg.host.replace(/\/$/, "");
|
|
123
95
|
this.httpKey = arg.key;
|
|
124
96
|
} else {
|
|
125
|
-
this.socketPath =
|
|
97
|
+
this.socketPath = arg ?? DEFAULT_SOCKET_PATH;
|
|
126
98
|
}
|
|
99
|
+
this.reqId = 0;
|
|
100
|
+
this.pending = new Map();
|
|
101
|
+
this.buf = "";
|
|
102
|
+
this.eventHandlers = new Map();
|
|
103
|
+
this.globalEventHandlers = new Map();
|
|
127
104
|
this.eventHandlers.set("default", new Map());
|
|
128
105
|
}
|
|
129
106
|
|
|
130
107
|
// ── Connect ───────────────────────────────────────────────────────────────
|
|
131
108
|
|
|
132
|
-
connect()
|
|
109
|
+
connect() {
|
|
133
110
|
if (this.httpHost) return this._connectHttp();
|
|
134
111
|
return this._connectSocket();
|
|
135
112
|
}
|
|
136
113
|
|
|
137
|
-
|
|
114
|
+
_connectSocket() {
|
|
138
115
|
return new Promise((resolve, reject) => {
|
|
139
116
|
logger.info(`Connecting to socket: ${this.socketPath}`);
|
|
140
117
|
const sock = connect(this.socketPath);
|
|
@@ -155,35 +132,35 @@ export class PiggyClient {
|
|
|
155
132
|
});
|
|
156
133
|
}
|
|
157
134
|
|
|
158
|
-
|
|
135
|
+
async _connectHttp() {
|
|
159
136
|
logger.info(`Connecting to Piggy server (HTTP): ${this.httpHost}`);
|
|
160
137
|
try {
|
|
161
|
-
const res = await fetch(this.httpHost
|
|
138
|
+
const res = await fetch(this.httpHost, {
|
|
162
139
|
method: "POST",
|
|
163
140
|
headers: {
|
|
164
141
|
"Content-Type": "application/json",
|
|
165
|
-
"X-Piggy-Key": this.httpKey
|
|
142
|
+
"X-Piggy-Key": this.httpKey,
|
|
166
143
|
},
|
|
167
144
|
body: "hello",
|
|
168
145
|
});
|
|
169
146
|
if (res.status === 401) {
|
|
170
147
|
throw new Error("Unauthorized — invalid X-Piggy-Key");
|
|
171
148
|
}
|
|
172
|
-
this.transport = new HttpTransport(this.httpHost
|
|
149
|
+
this.transport = new HttpTransport(this.httpHost, this.httpKey);
|
|
173
150
|
this._wireTransport();
|
|
174
151
|
logger.success(`Connected to Piggy server (HTTP): ${this.httpHost}`);
|
|
175
|
-
} catch (e
|
|
152
|
+
} catch (e) {
|
|
176
153
|
throw new Error(`Failed to connect to Piggy HTTP server: ${e.message}`);
|
|
177
154
|
}
|
|
178
155
|
}
|
|
179
156
|
|
|
180
|
-
|
|
157
|
+
_wireTransport() {
|
|
181
158
|
if (!this.transport) return;
|
|
182
159
|
|
|
183
|
-
this.transport.on("data", (chunk
|
|
160
|
+
this.transport.on("data", (chunk) => {
|
|
184
161
|
this.buf += chunk;
|
|
185
162
|
const lines = this.buf.split("\n");
|
|
186
|
-
this.buf = lines.pop()
|
|
163
|
+
this.buf = lines.pop();
|
|
187
164
|
|
|
188
165
|
for (const line of lines) {
|
|
189
166
|
if (!line.trim()) continue;
|
|
@@ -206,7 +183,7 @@ export class PiggyClient {
|
|
|
206
183
|
}
|
|
207
184
|
});
|
|
208
185
|
|
|
209
|
-
this.transport.on("error", (e
|
|
186
|
+
this.transport.on("error", (e) => {
|
|
210
187
|
for (const p of this.pending.values()) p.reject(e);
|
|
211
188
|
this.pending.clear();
|
|
212
189
|
});
|
|
@@ -219,7 +196,7 @@ export class PiggyClient {
|
|
|
219
196
|
|
|
220
197
|
// ── Event handling ────────────────────────────────────────────────────────
|
|
221
198
|
|
|
222
|
-
|
|
199
|
+
handleEvent(event) {
|
|
223
200
|
if (event.event === "exposed_call") {
|
|
224
201
|
const { tabId, name, callId, data } = event;
|
|
225
202
|
const effectiveTabId = tabId || "default";
|
|
@@ -227,7 +204,7 @@ export class PiggyClient {
|
|
|
227
204
|
const handler = handlers?.get(name);
|
|
228
205
|
|
|
229
206
|
if (handler) {
|
|
230
|
-
let parsedData
|
|
207
|
+
let parsedData;
|
|
231
208
|
try {
|
|
232
209
|
parsedData = JSON.parse(data || "null");
|
|
233
210
|
} catch {
|
|
@@ -299,12 +276,12 @@ export class PiggyClient {
|
|
|
299
276
|
}
|
|
300
277
|
}
|
|
301
278
|
|
|
302
|
-
onEvent(eventName
|
|
279
|
+
onEvent(eventName, tabId, handler) {
|
|
303
280
|
const key = `${eventName}:${tabId}`;
|
|
304
281
|
if (!this.globalEventHandlers.has(key)) {
|
|
305
282
|
this.globalEventHandlers.set(key, new Set());
|
|
306
283
|
}
|
|
307
|
-
this.globalEventHandlers.get(key)
|
|
284
|
+
this.globalEventHandlers.get(key).add(handler);
|
|
308
285
|
return () => this.globalEventHandlers.get(key)?.delete(handler);
|
|
309
286
|
}
|
|
310
287
|
|
|
@@ -315,7 +292,7 @@ export class PiggyClient {
|
|
|
315
292
|
|
|
316
293
|
// ── Core send ─────────────────────────────────────────────────────────────
|
|
317
294
|
|
|
318
|
-
send
|
|
295
|
+
send(cmd, payload = {}) {
|
|
319
296
|
return new Promise((resolve, reject) => {
|
|
320
297
|
if (!this.transport) return reject(new Error("Not connected"));
|
|
321
298
|
const id = String(++this.reqId);
|
|
@@ -325,123 +302,123 @@ export class PiggyClient {
|
|
|
325
302
|
}
|
|
326
303
|
|
|
327
304
|
// ── Tabs ──────────────────────────────────────────────────────────────────
|
|
328
|
-
async newTab()
|
|
329
|
-
async closeTab(tabId
|
|
330
|
-
async listTabs()
|
|
305
|
+
async newTab() { return this.send("tab.new", {}); }
|
|
306
|
+
async closeTab(tabId) { await this.send("tab.close", { tabId }); }
|
|
307
|
+
async listTabs() { return this.send("tab.list", {}); }
|
|
331
308
|
|
|
332
309
|
// ── Navigation ────────────────────────────────────────────────────────────
|
|
333
|
-
async navigate(url
|
|
334
|
-
async reload(tabId = "default")
|
|
335
|
-
async goBack(tabId = "default")
|
|
336
|
-
async goForward(tabId = "default")
|
|
310
|
+
async navigate(url, tabId = "default") { await this.send("navigate", { url, tabId }); }
|
|
311
|
+
async reload(tabId = "default") { await this.send("reload", { tabId }); }
|
|
312
|
+
async goBack(tabId = "default") { await this.send("go.back", { tabId }); }
|
|
313
|
+
async goForward(tabId = "default") { await this.send("go.forward", { tabId }); }
|
|
337
314
|
|
|
338
315
|
// ── Page info ─────────────────────────────────────────────────────────────
|
|
339
|
-
async getTitle(tabId = "default")
|
|
340
|
-
async getUrl(tabId = "default")
|
|
341
|
-
async content(tabId = "default")
|
|
316
|
+
async getTitle(tabId = "default") { return this.send("page.title", { tabId }); }
|
|
317
|
+
async getUrl(tabId = "default") { return this.send("page.url", { tabId }); }
|
|
318
|
+
async content(tabId = "default") { return this.send("page.content", { tabId }); }
|
|
342
319
|
|
|
343
320
|
// ── Eval / JS ─────────────────────────────────────────────────────────────
|
|
344
|
-
async evaluate(js
|
|
345
|
-
async addInitScript(js
|
|
321
|
+
async evaluate(js, tabId = "default") { return this.send("evaluate", { js, tabId }); }
|
|
322
|
+
async addInitScript(js, tabId = "default") { await this.send("addInitScript", { js, tabId }); }
|
|
346
323
|
|
|
347
324
|
// ── Interactions ──────────────────────────────────────────────────────────
|
|
348
|
-
async click(selector
|
|
349
|
-
async doubleClick(selector
|
|
350
|
-
async hover(selector
|
|
351
|
-
async type(selector
|
|
352
|
-
async select(selector
|
|
353
|
-
async keyPress(key
|
|
354
|
-
async keyCombo(combo
|
|
355
|
-
async mouseMove(x
|
|
356
|
-
async mouseDrag(from
|
|
325
|
+
async click(selector, tabId = "default") { return this.send("click", { selector, tabId }); }
|
|
326
|
+
async doubleClick(selector, tabId = "default") { return this.send("dblclick", { selector, tabId }); }
|
|
327
|
+
async hover(selector, tabId = "default") { return this.send("hover", { selector, tabId }); }
|
|
328
|
+
async type(selector, text, tabId = "default") { return this.send("type", { selector, text, tabId }); }
|
|
329
|
+
async select(selector, value, tabId = "default") { return this.send("select", { selector, value, tabId }); }
|
|
330
|
+
async keyPress(key, tabId = "default") { return this.send("keyboard.press", { key, tabId }); }
|
|
331
|
+
async keyCombo(combo, tabId = "default") { return this.send("keyboard.combo", { combo, tabId }); }
|
|
332
|
+
async mouseMove(x, y, tabId = "default") { return this.send("mouse.move", { x, y, tabId }); }
|
|
333
|
+
async mouseDrag(from, to, tabId = "default") { return this.send("mouse.drag", { from, to, tabId }); }
|
|
357
334
|
|
|
358
335
|
// ── Scroll ────────────────────────────────────────────────────────────────
|
|
359
|
-
async scrollTo(selector
|
|
360
|
-
async scrollBy(px
|
|
336
|
+
async scrollTo(selector, tabId = "default") { return this.send("scroll.to", { selector, tabId }); }
|
|
337
|
+
async scrollBy(px, tabId = "default") { return this.send("scroll.by", { px, tabId }); }
|
|
361
338
|
|
|
362
339
|
// ── Fetch ─────────────────────────────────────────────────────────────────
|
|
363
|
-
async fetchText(query
|
|
364
|
-
async fetchLinks(query
|
|
340
|
+
async fetchText(query, tabId = "default") { return this.send("fetch.text", { query, tabId }); }
|
|
341
|
+
async fetchLinks(query, tabId = "default") {
|
|
365
342
|
if (query === "a" || query === "body") {
|
|
366
|
-
const result = await this.send
|
|
343
|
+
const result = await this.send("fetch.links.all", { tabId });
|
|
367
344
|
return Array.isArray(result) ? result : [];
|
|
368
345
|
}
|
|
369
|
-
const result = await this.send
|
|
346
|
+
const result = await this.send("fetch.links", { query, tabId });
|
|
370
347
|
return Array.isArray(result) ? result : [];
|
|
371
348
|
}
|
|
372
|
-
async fetchImages(query
|
|
373
|
-
const result = await this.send
|
|
349
|
+
async fetchImages(query, tabId = "default") {
|
|
350
|
+
const result = await this.send("fetch.image", { query, tabId });
|
|
374
351
|
return Array.isArray(result) ? result : [];
|
|
375
352
|
}
|
|
376
353
|
|
|
377
354
|
// ── Search ────────────────────────────────────────────────────────────────
|
|
378
|
-
async searchCss(query
|
|
379
|
-
async searchId(query
|
|
355
|
+
async searchCss(query, tabId = "default") { return this.send("search.css", { query, tabId }); }
|
|
356
|
+
async searchId(query, tabId = "default") { return this.send("search.id", { query, tabId }); }
|
|
380
357
|
|
|
381
358
|
// ── Wait ──────────────────────────────────────────────────────────────────
|
|
382
|
-
async waitForSelector(selector
|
|
383
|
-
async waitForNavigation(tabId = "default")
|
|
384
|
-
async waitForResponse(urlPattern
|
|
359
|
+
async waitForSelector(selector, timeout = 30000, tabId = "default") { await this.send("wait.selector", { selector, timeout, tabId }); }
|
|
360
|
+
async waitForNavigation(tabId = "default") { await this.send("wait.navigation", { tabId }); }
|
|
361
|
+
async waitForResponse(urlPattern, timeout = 30000, tabId = "default") { await this.send("wait.response", { url: urlPattern, timeout, tabId }); }
|
|
385
362
|
|
|
386
363
|
// ── Screenshot / PDF ──────────────────────────────────────────────────────
|
|
387
|
-
async screenshot(filePath
|
|
388
|
-
const b64 = await this.send
|
|
364
|
+
async screenshot(filePath, tabId = "default") {
|
|
365
|
+
const b64 = await this.send("screenshot", { tabId });
|
|
389
366
|
if (filePath) { mkdirSync(dirname(filePath), { recursive: true }); writeFileSync(filePath, Buffer.from(b64, "base64")); }
|
|
390
367
|
return filePath ?? b64;
|
|
391
368
|
}
|
|
392
|
-
async pdf(filePath
|
|
393
|
-
const b64 = await this.send
|
|
369
|
+
async pdf(filePath, tabId = "default") {
|
|
370
|
+
const b64 = await this.send("pdf", { tabId });
|
|
394
371
|
if (filePath) { mkdirSync(dirname(filePath), { recursive: true }); writeFileSync(filePath, Buffer.from(b64, "base64")); }
|
|
395
372
|
return filePath ?? b64;
|
|
396
373
|
}
|
|
397
374
|
|
|
398
375
|
// ── Image blocking ────────────────────────────────────────────────────────
|
|
399
|
-
async blockImages(tabId = "default")
|
|
400
|
-
async unblockImages(tabId = "default")
|
|
376
|
+
async blockImages(tabId = "default") { await this.send("intercept.block.images", { tabId }); }
|
|
377
|
+
async unblockImages(tabId = "default") { await this.send("intercept.unblock.images", { tabId }); }
|
|
401
378
|
|
|
402
379
|
// ── Cookies ───────────────────────────────────────────────────────────────
|
|
403
|
-
async setCookie(name
|
|
404
|
-
async getCookie(name
|
|
405
|
-
async deleteCookie(name
|
|
406
|
-
async listCookies(domain = "", tabId = "default")
|
|
380
|
+
async setCookie(name, value, domain, path = "/", tabId = "default") { await this.send("cookie.set", { name, value, domain, path, tabId }); }
|
|
381
|
+
async getCookie(name, domain = "", tabId = "default") { return this.send("cookie.get", { name, domain, tabId }); }
|
|
382
|
+
async deleteCookie(name, domain, tabId = "default") { await this.send("cookie.delete", { name, domain, tabId }); }
|
|
383
|
+
async listCookies(domain = "", tabId = "default") { return this.send("cookie.list", { domain, tabId }); }
|
|
407
384
|
|
|
408
385
|
// ── Interception ──────────────────────────────────────────────────────────
|
|
409
|
-
async addInterceptRule(action
|
|
386
|
+
async addInterceptRule(action, pattern, options = {}, tabId = "default") {
|
|
410
387
|
await this.send("intercept.rule.add", { action, pattern, ...options, tabId });
|
|
411
388
|
}
|
|
412
|
-
async clearInterceptRules(tabId = "default")
|
|
389
|
+
async clearInterceptRules(tabId = "default") { await this.send("intercept.rule.clear", { tabId }); }
|
|
413
390
|
|
|
414
391
|
// ── Network capture ───────────────────────────────────────────────────────
|
|
415
|
-
async captureStart(tabId = "default")
|
|
416
|
-
async captureStop(tabId = "default")
|
|
417
|
-
async captureRequests(tabId = "default")
|
|
418
|
-
async captureWs(tabId = "default")
|
|
419
|
-
async captureCookies(tabId = "default")
|
|
420
|
-
async captureStorage(tabId = "default")
|
|
421
|
-
async captureClear(tabId = "default")
|
|
392
|
+
async captureStart(tabId = "default") { await this.send("capture.start", { tabId }); }
|
|
393
|
+
async captureStop(tabId = "default") { await this.send("capture.stop", { tabId }); }
|
|
394
|
+
async captureRequests(tabId = "default") { return this.send("capture.requests", { tabId }); }
|
|
395
|
+
async captureWs(tabId = "default") { return this.send("capture.ws", { tabId }); }
|
|
396
|
+
async captureCookies(tabId = "default") { return this.send("capture.cookies", { tabId }); }
|
|
397
|
+
async captureStorage(tabId = "default") { return this.send("capture.storage", { tabId }); }
|
|
398
|
+
async captureClear(tabId = "default") { await this.send("capture.clear", { tabId }); }
|
|
422
399
|
|
|
423
400
|
// ── Session ───────────────────────────────────────────────────────────────
|
|
424
|
-
async sessionExport(tabId = "default")
|
|
425
|
-
async sessionImport(data
|
|
426
|
-
|
|
427
|
-
async sessionWsSave(enabled = true)
|
|
428
|
-
async sessionPingsSave(enabled = true)
|
|
429
|
-
async sessionPaths()
|
|
430
|
-
async sessionCookiesPath()
|
|
431
|
-
async sessionProfilePath()
|
|
432
|
-
async sessionWsPath()
|
|
433
|
-
async sessionPingsPath()
|
|
434
|
-
async sessionReload()
|
|
401
|
+
async sessionExport(tabId = "default") { return this.send("session.export", { tabId }); }
|
|
402
|
+
async sessionImport(data, tabId = "default") { await this.send("session.import", { data, tabId }); }
|
|
403
|
+
|
|
404
|
+
async sessionWsSave(enabled = true) { await this.send("session.ws.save", { enabled }); }
|
|
405
|
+
async sessionPingsSave(enabled = true) { await this.send("session.pings.save", { enabled }); }
|
|
406
|
+
async sessionPaths() { return this.send("session.paths", {}); }
|
|
407
|
+
async sessionCookiesPath() { return this.send("session.cookies.path", {}); }
|
|
408
|
+
async sessionProfilePath() { return this.send("session.profile.path", {}); }
|
|
409
|
+
async sessionWsPath() { return this.send("session.ws.path", {}); }
|
|
410
|
+
async sessionPingsPath() { return this.send("session.pings.path", {}); }
|
|
411
|
+
async sessionReload() { await this.send("session.reload", {}); }
|
|
435
412
|
|
|
436
413
|
// ── Expose Function ───────────────────────────────────────────────────────
|
|
437
|
-
async exposeFunction(name
|
|
414
|
+
async exposeFunction(name, handler, tabId = "default") {
|
|
438
415
|
if (!this.eventHandlers.has(tabId)) this.eventHandlers.set(tabId, new Map());
|
|
439
|
-
this.eventHandlers.get(tabId)
|
|
416
|
+
this.eventHandlers.get(tabId).set(name, async (data) => {
|
|
440
417
|
try {
|
|
441
418
|
const result = await handler(data);
|
|
442
419
|
if (result && typeof result === "object" && ("success" in result || "error" in result)) return result;
|
|
443
420
|
return { success: true, result };
|
|
444
|
-
} catch (err
|
|
421
|
+
} catch (err) {
|
|
445
422
|
return { success: false, error: err.message || String(err) };
|
|
446
423
|
}
|
|
447
424
|
});
|
|
@@ -449,42 +426,44 @@ export class PiggyClient {
|
|
|
449
426
|
logger.success(`[${tabId}] exposed function: ${name}`);
|
|
450
427
|
}
|
|
451
428
|
|
|
452
|
-
async unexposeFunction(name
|
|
429
|
+
async unexposeFunction(name, tabId = "default") {
|
|
453
430
|
const handlers = this.eventHandlers.get(tabId);
|
|
454
431
|
if (handlers) handlers.delete(name);
|
|
455
432
|
logger.info(`[${tabId}] unexposed function: ${name}`);
|
|
456
433
|
}
|
|
457
434
|
|
|
458
|
-
async clearExposedFunctions(tabId = "default")
|
|
435
|
+
async clearExposedFunctions(tabId = "default") {
|
|
459
436
|
this.eventHandlers.set(tabId, new Map());
|
|
460
437
|
logger.info(`[${tabId}] cleared all exposed functions`);
|
|
461
438
|
}
|
|
462
439
|
|
|
463
440
|
// ── Proxy ─────────────────────────────────────────────────────────────────
|
|
464
|
-
async proxyLoad(path
|
|
465
|
-
async proxyFetch(url
|
|
466
|
-
async proxyOvpn(path
|
|
467
|
-
|
|
468
|
-
async proxySet(opts
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
async
|
|
475
|
-
async
|
|
476
|
-
async
|
|
477
|
-
|
|
478
|
-
async
|
|
479
|
-
|
|
480
|
-
async
|
|
481
|
-
async
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
async proxyConfig(opts
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
441
|
+
async proxyLoad(path) { await this.send("proxy.load", { path }); }
|
|
442
|
+
async proxyFetch(url) { await this.send("proxy.fetch", { url }); }
|
|
443
|
+
async proxyOvpn(path) { await this.send("proxy.ovpn", { path }); }
|
|
444
|
+
|
|
445
|
+
async proxySet(opts) {
|
|
446
|
+
await this.send("proxy.set", opts);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
async proxyTest() { await this.send("proxy.test", {}); }
|
|
450
|
+
async proxyTestStop() { await this.send("proxy.test.stop", {}); }
|
|
451
|
+
async proxyNext() { await this.send("proxy.next", {}); }
|
|
452
|
+
async proxyDisable() { await this.send("proxy.disable", {}); }
|
|
453
|
+
async proxyEnable() { await this.send("proxy.enable", {}); }
|
|
454
|
+
|
|
455
|
+
async proxyCurrent() { return this.send("proxy.current", {}); }
|
|
456
|
+
async proxyStats() { return this.send("proxy.stats", {}); }
|
|
457
|
+
async proxyList(limit) { return this.send("proxy.list", limit !== undefined ? { limit } : {}); }
|
|
458
|
+
async proxyRotation(mode, interval) {
|
|
459
|
+
await this.send("proxy.rotation", { mode, ...(interval !== undefined ? { interval } : {}) });
|
|
460
|
+
}
|
|
461
|
+
async proxyConfig(opts) {
|
|
462
|
+
await this.send("proxy.config", opts);
|
|
463
|
+
}
|
|
464
|
+
async proxySave(path, filter = "all") { await this.send("proxy.save", { path, filter }); }
|
|
465
|
+
|
|
466
|
+
onProxyEvent(event, handler) {
|
|
488
467
|
return this.onEvent(event, "*", handler);
|
|
489
468
|
}
|
|
490
469
|
}
|
|
@@ -1,53 +1,37 @@
|
|
|
1
|
-
// piggy/dialog/index.
|
|
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
|
-
}
|
|
1
|
+
// piggy/dialog/index.js
|
|
2
|
+
import { PiggyClient } from "../client.js";
|
|
3
|
+
import logger from "../logger.js";
|
|
19
4
|
|
|
20
5
|
export class DialogClient {
|
|
21
|
-
constructor(
|
|
6
|
+
constructor(client) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
}
|
|
22
9
|
|
|
23
|
-
accept(tabId = "default", text
|
|
10
|
+
accept(tabId = "default", text) {
|
|
24
11
|
return this.client.send("dialog.accept", { tabId, ...(text !== undefined ? { text } : {}) });
|
|
25
12
|
}
|
|
26
13
|
|
|
27
|
-
dismiss(tabId = "default")
|
|
14
|
+
dismiss(tabId = "default") {
|
|
28
15
|
return this.client.send("dialog.dismiss", { tabId });
|
|
29
16
|
}
|
|
30
17
|
|
|
31
|
-
status(tabId = "default")
|
|
18
|
+
status(tabId = "default") {
|
|
32
19
|
return this.client.send("dialog.status", { tabId });
|
|
33
20
|
}
|
|
34
21
|
|
|
35
|
-
setAutoAction(tabId = "default", action
|
|
22
|
+
setAutoAction(tabId = "default", action) {
|
|
36
23
|
return this.client.send("dialog.onDialog", { tabId, action });
|
|
37
24
|
}
|
|
38
25
|
|
|
39
|
-
upload(selector
|
|
26
|
+
upload(selector, filePath, tabId = "default") {
|
|
40
27
|
return this.client.send("upload", { selector, path: filePath, tabId });
|
|
41
28
|
}
|
|
42
29
|
|
|
43
|
-
onDialog(
|
|
44
|
-
tabId: string,
|
|
45
|
-
handler: (data: DialogEventData) => void
|
|
46
|
-
): () => void {
|
|
30
|
+
onDialog(tabId, handler) {
|
|
47
31
|
return this.client.onEvent("dialog", tabId, handler);
|
|
48
32
|
}
|
|
49
33
|
|
|
50
|
-
waitAndAccept(tabId = "default", text
|
|
34
|
+
waitAndAccept(tabId = "default", text, timeoutMs = 30_000) {
|
|
51
35
|
return new Promise((resolve, reject) => {
|
|
52
36
|
const timer = setTimeout(() => {
|
|
53
37
|
unsub();
|
|
@@ -63,7 +47,7 @@ export class DialogClient {
|
|
|
63
47
|
});
|
|
64
48
|
}
|
|
65
49
|
|
|
66
|
-
waitAndDismiss(tabId = "default", timeoutMs = 30_000)
|
|
50
|
+
waitAndDismiss(tabId = "default", timeoutMs = 30_000) {
|
|
67
51
|
return new Promise((resolve, reject) => {
|
|
68
52
|
const timer = setTimeout(() => {
|
|
69
53
|
unsub();
|
|
@@ -80,6 +64,6 @@ export class DialogClient {
|
|
|
80
64
|
}
|
|
81
65
|
}
|
|
82
66
|
|
|
83
|
-
export function createDialogAPI(client
|
|
67
|
+
export function createDialogAPI(client) {
|
|
84
68
|
return new DialogClient(client);
|
|
85
69
|
}
|