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
package/piggy/session/index.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// piggy/session/index.ts
|
|
2
|
-
import { PiggyClient } from "../client";
|
|
3
|
-
import type { CookieSetOptions, CookieDeleteOptions } from "../export";
|
|
4
|
-
|
|
5
|
-
export interface SessionPaths {
|
|
6
|
-
workDir: string;
|
|
7
|
-
cookies: string;
|
|
8
|
-
profile: string;
|
|
9
|
-
ws: string;
|
|
10
|
-
pings: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class SessionClient {
|
|
14
|
-
constructor(private client: PiggyClient) {}
|
|
15
|
-
|
|
16
|
-
// Session lifecycle
|
|
17
|
-
reload(tabId = "default"): Promise<void> {
|
|
18
|
-
return this.client.send("session.reload", { tabId });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Paths
|
|
22
|
-
paths(): Promise<SessionPaths> {
|
|
23
|
-
return this.client.send("session.paths", {});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
cookiesPath(): Promise<string> {
|
|
27
|
-
return this.client.send("session.cookies.path", {});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
profilePath(): Promise<string> {
|
|
31
|
-
return this.client.send("session.profile.path", {});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
wsPath(): Promise<string> {
|
|
35
|
-
return this.client.send("session.ws.path", {});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
pingsPath(): Promise<string> {
|
|
39
|
-
return this.client.send("session.pings.path", {});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Opt-in persistence
|
|
43
|
-
setWsSave(enabled: boolean): Promise<void> {
|
|
44
|
-
return this.client.send("session.ws.save", { enabled });
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
setPingsSave(enabled: boolean): Promise<void> {
|
|
48
|
-
return this.client.send("session.pings.save", { enabled });
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Export / import
|
|
52
|
-
async export(tabId = "default"): Promise<any> {
|
|
53
|
-
const raw = await this.client.send<string>("session.export", { tabId });
|
|
54
|
-
return typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
import(data: any, tabId = "default"): Promise<void> {
|
|
58
|
-
return this.client.send("session.import", {
|
|
59
|
-
data: JSON.stringify(data),
|
|
60
|
-
tabId,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Cookies (using imported types from export)
|
|
65
|
-
setCookie(opts: CookieSetOptions, tabId = "default"): Promise<void> {
|
|
66
|
-
return this.client.send("cookie.set", { ...opts, tabId });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
deleteCookie(opts: CookieDeleteOptions, tabId = "default"): Promise<void> {
|
|
70
|
-
return this.client.send("cookie.delete", { ...opts, tabId });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function createSessionAPI(client: PiggyClient): SessionClient {
|
|
75
|
-
return new SessionClient(client);
|
|
76
|
-
}
|
package/piggy/store/index.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// piggy/store/index.d.ts
|
|
2
|
-
export type FieldType = "string" | "number" | "boolean" | "object" | "array";
|
|
3
|
-
|
|
4
|
-
export interface FieldSchema {
|
|
5
|
-
type: FieldType;
|
|
6
|
-
required?: boolean;
|
|
7
|
-
default?: any;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface StoreSchema {
|
|
11
|
-
name: string;
|
|
12
|
-
destination: string;
|
|
13
|
-
fields: Record<string, FieldSchema>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface PiggyStoreConfig {
|
|
17
|
-
stores: StoreSchema[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export declare function loadStoreConfig(configPath?: string): PiggyStoreConfig;
|
|
21
|
-
export declare function getSchema(storeName: string): StoreSchema | null;
|
|
22
|
-
export declare function shapeRecord(data: Record<string, any>, schema: StoreSchema): Record<string, any>;
|
|
23
|
-
export declare function storeRecord(
|
|
24
|
-
storeName: string,
|
|
25
|
-
data: Record<string, any> | Record<string, any>[]
|
|
26
|
-
): Promise<{ stored: number; skipped: number }>;
|
package/piggy/tabs/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// piggy/tabs/index.ts
|
|
2
|
-
import { PiggyClient } from "../client";
|
|
3
|
-
|
|
4
|
-
export class TabsClient {
|
|
5
|
-
constructor(private client: PiggyClient) {}
|
|
6
|
-
|
|
7
|
-
new(): Promise<string> {
|
|
8
|
-
return this.client.send("tab.new", {});
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
close(opts: string | { tabId: string }): Promise<void> {
|
|
12
|
-
const tabId = typeof opts === "string" ? opts : opts.tabId;
|
|
13
|
-
return this.client.send("tab.close", { tabId });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
list(): Promise<string[]> {
|
|
17
|
-
return this.client.send("tab.list", {});
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createTabsAPI(client: PiggyClient): TabsClient {
|
|
22
|
-
return new TabsClient(client);
|
|
23
|
-
}
|
package/piggy/wait/index.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
// piggy/wait/index.ts
|
|
2
|
-
import { PiggyClient } from "../client";
|
|
3
|
-
|
|
4
|
-
export type WaitSelectorState = "attached" | "detached" | "visible" | "hidden";
|
|
5
|
-
|
|
6
|
-
// ─── WaitClient ───────────────────────────────────────────────────────────────
|
|
7
|
-
// Maps to PiggyWait.cpp
|
|
8
|
-
|
|
9
|
-
export class WaitClient {
|
|
10
|
-
constructor(private client: PiggyClient) {}
|
|
11
|
-
|
|
12
|
-
// wait.function — poll every 100ms until JS expr is truthy
|
|
13
|
-
function(js: string, timeout = 10000, tabId = "default"): Promise<void> {
|
|
14
|
-
return this.client.send("wait.function", { js, timeout, tabId });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// wait.selector — with full state support (attached|detached|visible|hidden)
|
|
18
|
-
selector(
|
|
19
|
-
selector: string,
|
|
20
|
-
state: WaitSelectorState = "attached",
|
|
21
|
-
timeout = 10000,
|
|
22
|
-
tabId = "default"
|
|
23
|
-
): Promise<void> {
|
|
24
|
-
return this.client.send("wait.selector", { selector, state, timeout, tabId });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ─── EvaluateClient ───────────────────────────────────────────────────────────
|
|
29
|
-
// Maps to the evaluate command in PiggyWait.cpp (with timeout support)
|
|
30
|
-
// and PiggyInteractions.cpp (without timeout)
|
|
31
|
-
|
|
32
|
-
export class EvaluateClient {
|
|
33
|
-
constructor(private client: PiggyClient) {}
|
|
34
|
-
|
|
35
|
-
// evaluate with optional wall-clock timeout
|
|
36
|
-
run(js: string, timeout?: number, tabId = "default"): Promise<unknown> {
|
|
37
|
-
return this.client.send("evaluate", {
|
|
38
|
-
js,
|
|
39
|
-
tabId,
|
|
40
|
-
...(timeout !== undefined ? { timeout } : {}),
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// ─── FetchClient ──────────────────────────────────────────────────────────────
|
|
46
|
-
// Maps to fetch.textAll / fetch.attr / fetch.attrAll in PiggyWait.cpp
|
|
47
|
-
// and fetch.text / fetch.links / fetch.image in PiggyExport.cpp
|
|
48
|
-
|
|
49
|
-
export class FetchClient {
|
|
50
|
-
constructor(private client: PiggyClient) {}
|
|
51
|
-
|
|
52
|
-
// fetch.text — single element innerText
|
|
53
|
-
text(selector: string, tabId = "default"): Promise<string | null> {
|
|
54
|
-
return this.client.send("fetch.text", { query: selector, tabId });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// fetch.textAll — all matching elements innerText
|
|
58
|
-
textAll(selector: string, tabId = "default"): Promise<string[]> {
|
|
59
|
-
return this.client.send("fetch.textAll", { selector, tabId });
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// fetch.attr — single attribute from first match
|
|
63
|
-
attr(selector: string, attr: string, tabId = "default"): Promise<string | null> {
|
|
64
|
-
return this.client.send("fetch.attr", { selector, attr, tabId });
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// fetch.attrAll — attribute from all matches
|
|
68
|
-
attrAll(selector: string, attr: string, tabId = "default"): Promise<string[]> {
|
|
69
|
-
return this.client.send("fetch.attrAll", { selector, attr, tabId });
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// fetch.links — links inside a selector
|
|
73
|
-
links(selector: string, tabId = "default"): Promise<string[]> {
|
|
74
|
-
return this.client.send("fetch.links", { query: selector, tabId });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// fetch.links.all — all links on page
|
|
78
|
-
linksAll(tabId = "default"): Promise<string[]> {
|
|
79
|
-
return this.client.send("fetch.links.all", { tabId });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// fetch.image — images inside a selector
|
|
83
|
-
images(selector: string, tabId = "default"): Promise<string[]> {
|
|
84
|
-
return this.client.send("fetch.image", { query: selector, tabId });
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function createWaitAPI(client: PiggyClient): WaitClient { return new WaitClient(client); }
|
|
89
|
-
export function createEvaluateAPI(client: PiggyClient): EvaluateClient { return new EvaluateClient(client); }
|
|
90
|
-
export function createFetchAPI(client: PiggyClient): FetchClient { return new FetchClient(client); }
|
package/piggy.ts
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
// piggy.ts
|
|
2
|
-
//the main file
|
|
3
|
-
import { detectBinary, type BinaryMode } from "./piggy/launch/detect";
|
|
4
|
-
import { spawnBrowser, killBrowser, spawnBrowserOnSocket } from "./piggy/launch/spawn";
|
|
5
|
-
import { PiggyClient } from "./piggy/client";
|
|
6
|
-
import { setClient, setHumanMode, createSiteObject, type SiteObject } from "./piggy/register";
|
|
7
|
-
import { routeRegistry, keepAliveSites, startServer, stopServer } from "./piggy/server";
|
|
8
|
-
import { TabPool } from "./piggy/pool";
|
|
9
|
-
import { createRouter, type PiggyRouter } from "./piggy/router";
|
|
10
|
-
import { createCaptureAPI } from "./piggy/capture";
|
|
11
|
-
import { createCaptchaAPI } from "./piggy/captcha";
|
|
12
|
-
import { createDialogAPI } from "./piggy/dialog";
|
|
13
|
-
import { createExportAPI } from "./piggy/export";
|
|
14
|
-
import { createFindAPI } from "./piggy/find";
|
|
15
|
-
import { createHumanAPI } from "./piggy/human";
|
|
16
|
-
import { createIframeAPI } from "./piggy/iframe";
|
|
17
|
-
import { createInteractionsAPI } from "./piggy/interactions";
|
|
18
|
-
import { createMediaAPI } from "./piggy/media";
|
|
19
|
-
import { createNavigationAPI } from "./piggy/navigation";
|
|
20
|
-
import { createProvideAPI } from "./piggy/provide";
|
|
21
|
-
import { createProxyAPI } from "./piggy/proxy";
|
|
22
|
-
import { createSessionAPI } from "./piggy/session";
|
|
23
|
-
import { createTabsAPI } from "./piggy/tabs";
|
|
24
|
-
import { createWaitAPI, createEvaluateAPI, createFetchAPI } from "./piggy/wait";
|
|
25
|
-
import { createHttpClient, type HttpClientOptions } from "./piggy/http";
|
|
26
|
-
import logger from "./piggy/logger";
|
|
27
|
-
|
|
28
|
-
type TabMode = "tab" | "process";
|
|
29
|
-
|
|
30
|
-
let _client: PiggyClient | null = null;
|
|
31
|
-
let _router: PiggyRouter | null = null;
|
|
32
|
-
let _tabMode: TabMode = "tab";
|
|
33
|
-
const _extraProcs: { socket: string; client: PiggyClient }[] = [];
|
|
34
|
-
const _sites: Record<string, SiteObject> = {};
|
|
35
|
-
|
|
36
|
-
// ── Internal guard ────────────────────────────────────────────────────────────
|
|
37
|
-
|
|
38
|
-
function guardClient(): PiggyClient {
|
|
39
|
-
if (!_client) throw new Error("No client. Call piggy.launch() or piggy.connect() first.");
|
|
40
|
-
return _client;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ── Build sub-APIs from a client ──────────────────────────────────────────────
|
|
44
|
-
|
|
45
|
-
function buildAPIs(client: PiggyClient) {
|
|
46
|
-
_router = createRouter(client);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const piggy: any = {
|
|
50
|
-
|
|
51
|
-
// ── Local launch (unix socket) ────────────────────────────────────────────
|
|
52
|
-
launch: async (opts?: { mode?: TabMode; binary?: BinaryMode }) => {
|
|
53
|
-
_tabMode = opts?.mode ?? "tab";
|
|
54
|
-
const binaryMode: BinaryMode = opts?.binary ?? "headless";
|
|
55
|
-
await spawnBrowser(binaryMode);
|
|
56
|
-
await new Promise(r => setTimeout(r, 500));
|
|
57
|
-
_client = new PiggyClient();
|
|
58
|
-
await _client.connect();
|
|
59
|
-
setClient(_client);
|
|
60
|
-
buildAPIs(_client);
|
|
61
|
-
logger.info(`[piggy] launched — tab mode: "${_tabMode}", binary: "${binaryMode}"`);
|
|
62
|
-
return piggy;
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
// ── Remote connect (HTTP) ─────────────────────────────────────────────────
|
|
66
|
-
connect: async (opts: { host: string; key: string }) => {
|
|
67
|
-
_tabMode = "tab";
|
|
68
|
-
_client = new PiggyClient({ host: opts.host, key: opts.key });
|
|
69
|
-
await _client.connect();
|
|
70
|
-
setClient(_client);
|
|
71
|
-
buildAPIs(_client);
|
|
72
|
-
logger.info(`[piggy] connected (HTTP) → ${opts.host}`);
|
|
73
|
-
return piggy;
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
// ── HTTP client (port 2005 direct) ────────────────────────────────────────
|
|
77
|
-
// Use when you want to talk to the browser over HTTP without a socket client.
|
|
78
|
-
http: (opts: HttpClientOptions) => createHttpClient(opts),
|
|
79
|
-
|
|
80
|
-
// ── Register ──────────────────────────────────────────────────────────────
|
|
81
|
-
register: async (
|
|
82
|
-
name: string,
|
|
83
|
-
url: string,
|
|
84
|
-
opts?: { binary?: BinaryMode; pool?: number }
|
|
85
|
-
) => {
|
|
86
|
-
if (!url?.trim()) throw new Error(`No URL for site "${name}"`);
|
|
87
|
-
const binaryMode: BinaryMode = opts?.binary ?? "headless";
|
|
88
|
-
const poolSize = opts?.pool ?? 0;
|
|
89
|
-
|
|
90
|
-
if (_tabMode === "tab") {
|
|
91
|
-
const client = guardClient();
|
|
92
|
-
|
|
93
|
-
if (poolSize > 1) {
|
|
94
|
-
const pool = new TabPool(client, poolSize, url, name);
|
|
95
|
-
await pool.init();
|
|
96
|
-
const siteObj = createSiteObject(name, url, client, "default", pool);
|
|
97
|
-
_sites[name] = siteObj;
|
|
98
|
-
piggy[name] = siteObj;
|
|
99
|
-
logger.success(`[${name}] registered with pool of ${poolSize} tabs`);
|
|
100
|
-
} else {
|
|
101
|
-
const tabId = await client.newTab();
|
|
102
|
-
const siteObj = createSiteObject(name, url, client, tabId);
|
|
103
|
-
_sites[name] = siteObj;
|
|
104
|
-
piggy[name] = siteObj;
|
|
105
|
-
logger.success(`[${name}] registered as tab ${tabId}`);
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
const socketName = `piggy_${name}`;
|
|
109
|
-
await spawnBrowserOnSocket(socketName, binaryMode);
|
|
110
|
-
await new Promise(r => setTimeout(r, 500));
|
|
111
|
-
const c = new PiggyClient(socketName);
|
|
112
|
-
await c.connect();
|
|
113
|
-
_extraProcs.push({ socket: socketName, client: c });
|
|
114
|
-
const siteObj = createSiteObject(name, url, c, "default");
|
|
115
|
-
_sites[name] = siteObj;
|
|
116
|
-
piggy[name] = siteObj;
|
|
117
|
-
logger.success(`[${name}] registered as process on "${socketName}"`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return piggy;
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
// ── Sub-APIs (1:1 with C++ files, available after launch/connect) ─────────
|
|
124
|
-
|
|
125
|
-
get tabs() { return _router?.tabs ?? createTabsAPI(guardClient()); },
|
|
126
|
-
get tab() { return _router?.tabs ?? createTabsAPI(guardClient()); },
|
|
127
|
-
get navigation() { return _router?.navigation ?? createNavigationAPI(guardClient()); },
|
|
128
|
-
get interactions() { return _router?.interactions ?? createInteractionsAPI(guardClient()); },
|
|
129
|
-
get media() { return _router?.media ?? createMediaAPI(guardClient()); },
|
|
130
|
-
get capture() { return _router?.capture ?? createCaptureAPI(guardClient()); },
|
|
131
|
-
get find() { return _router?.find ?? createFindAPI(guardClient()); },
|
|
132
|
-
get provide() { return _router?.provide ?? createProvideAPI(guardClient()); },
|
|
133
|
-
get wait() { return _router?.wait ?? createWaitAPI(guardClient()); },
|
|
134
|
-
get evaluate() { return _router?.evaluate ?? createEvaluateAPI(guardClient()); },
|
|
135
|
-
get fetch() { return _router?.fetch ?? createFetchAPI(guardClient()); },
|
|
136
|
-
get captcha() { return _router?.captcha ?? createCaptchaAPI(guardClient()); },
|
|
137
|
-
get dialog() { return _router?.dialog ?? createDialogAPI(guardClient()); },
|
|
138
|
-
get human() { return _router?.human ?? createHumanAPI(guardClient()); },
|
|
139
|
-
get iframe() { return _router?.iframe ?? createIframeAPI(guardClient()); },
|
|
140
|
-
get session() { return _router?.session ?? createSessionAPI(guardClient()); },
|
|
141
|
-
get export() { return _router?.export ?? createExportAPI(guardClient()); },
|
|
142
|
-
|
|
143
|
-
// ── Proxy (global, not per-tab) ───────────────────────────────────────────
|
|
144
|
-
get proxy() {
|
|
145
|
-
const api = _router?.proxy ?? createProxyAPI(guardClient());
|
|
146
|
-
return {
|
|
147
|
-
load: (path: string) => api.load(path),
|
|
148
|
-
fetch: (url: string) => api.fetch(url),
|
|
149
|
-
ovpn: (path: string) => api.ovpn(path),
|
|
150
|
-
set: (opts: Parameters<typeof api.set>[0]) => api.set(opts),
|
|
151
|
-
test: () => api.test(),
|
|
152
|
-
testStop: () => api.testStop(),
|
|
153
|
-
next: () => api.next(),
|
|
154
|
-
rotate: () => api.rotate(),
|
|
155
|
-
disable: () => api.disable(),
|
|
156
|
-
enable: () => api.enable(),
|
|
157
|
-
current: () => api.current(),
|
|
158
|
-
stats: () => api.stats(),
|
|
159
|
-
list: (limit?: number) => api.list(limit),
|
|
160
|
-
rotation: (mode: "none" | "timed" | "perrequest", interval?: number) => api.rotation(mode, interval),
|
|
161
|
-
config: (opts: { skipDead?: boolean; autoCheck?: boolean }) => api.config(opts),
|
|
162
|
-
save: (path: string, filter?: "alive" | "dead" | "all") => api.save(path, filter),
|
|
163
|
-
on: (event: string, handler: (data: any) => void) => guardClient().onProxyEvent(event, handler),
|
|
164
|
-
};
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
// ── Global controls ───────────────────────────────────────────────────────
|
|
168
|
-
actHuman: (enable: boolean) => {
|
|
169
|
-
setHumanMode(enable);
|
|
170
|
-
logger.info(`[piggy] actHuman: ${enable}`);
|
|
171
|
-
return piggy;
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
mode: (m: TabMode) => { _tabMode = m; return piggy; },
|
|
175
|
-
|
|
176
|
-
// ── Global expose ─────────────────────────────────────────────────────────
|
|
177
|
-
expose: async (name: string, handler: (data: any) => Promise<any> | any, tabId = "default") => {
|
|
178
|
-
await guardClient().exposeFunction(name, handler, tabId);
|
|
179
|
-
logger.success(`[piggy] exposed global function: ${name}`);
|
|
180
|
-
return piggy;
|
|
181
|
-
},
|
|
182
|
-
|
|
183
|
-
unexpose: async (name: string, tabId = "default") => {
|
|
184
|
-
await guardClient().unexposeFunction(name, tabId);
|
|
185
|
-
logger.info(`[piggy] unexposed function: ${name}`);
|
|
186
|
-
return piggy;
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
// ── Elysia server ─────────────────────────────────────────────────────────
|
|
190
|
-
serve: (
|
|
191
|
-
port: number,
|
|
192
|
-
opts?: {
|
|
193
|
-
hostname?: string;
|
|
194
|
-
title?: string;
|
|
195
|
-
version?: string;
|
|
196
|
-
description?: string;
|
|
197
|
-
path?: string;
|
|
198
|
-
}
|
|
199
|
-
) => startServer(port, opts?.hostname, opts),
|
|
200
|
-
|
|
201
|
-
stopServer,
|
|
202
|
-
|
|
203
|
-
// ── Route listing ─────────────────────────────────────────────────────────
|
|
204
|
-
routes: () =>
|
|
205
|
-
Array.from(routeRegistry.entries()).map(([key, cfg]) => {
|
|
206
|
-
const [site] = key.split(":");
|
|
207
|
-
return {
|
|
208
|
-
site,
|
|
209
|
-
method: cfg.method,
|
|
210
|
-
path: `/${site}${cfg.path}`,
|
|
211
|
-
ttl: cfg.ttl,
|
|
212
|
-
middlewareCount: cfg.before.length,
|
|
213
|
-
};
|
|
214
|
-
}),
|
|
215
|
-
|
|
216
|
-
// ── Multi-site helpers ────────────────────────────────────────────────────
|
|
217
|
-
all: (sites: SiteObject[]) =>
|
|
218
|
-
new Proxy({} as any, {
|
|
219
|
-
get: (_, method: string) =>
|
|
220
|
-
(...args: any[]) => Promise.all(sites.map((s: any) => s[method]?.(...args))),
|
|
221
|
-
}),
|
|
222
|
-
|
|
223
|
-
diff: (sites: SiteObject[]) =>
|
|
224
|
-
new Proxy({} as any, {
|
|
225
|
-
get: (_, method: string) =>
|
|
226
|
-
async (...args: any[]) => {
|
|
227
|
-
const results = await Promise.all(sites.map((s: any) => s[method]?.(...args)));
|
|
228
|
-
return Object.fromEntries(sites.map((s: any, i) => [s._name ?? i, results[i]]));
|
|
229
|
-
},
|
|
230
|
-
}),
|
|
231
|
-
|
|
232
|
-
// ── Shutdown ──────────────────────────────────────────────────────────────
|
|
233
|
-
close: async (opts?: { force?: boolean }) => {
|
|
234
|
-
stopServer();
|
|
235
|
-
if (opts?.force) {
|
|
236
|
-
for (const { client: c } of _extraProcs) c.disconnect();
|
|
237
|
-
_client?.disconnect();
|
|
238
|
-
killBrowser();
|
|
239
|
-
routeRegistry.clear();
|
|
240
|
-
keepAliveSites.clear();
|
|
241
|
-
} else {
|
|
242
|
-
for (const [name, site] of Object.entries(_sites)) {
|
|
243
|
-
if (!keepAliveSites.has(name)) await (site as any).close?.();
|
|
244
|
-
}
|
|
245
|
-
if (keepAliveSites.size === 0) {
|
|
246
|
-
for (const { client: c } of _extraProcs) c.disconnect();
|
|
247
|
-
_extraProcs.length = 0;
|
|
248
|
-
_client?.disconnect();
|
|
249
|
-
_client = null;
|
|
250
|
-
_router = null;
|
|
251
|
-
setClient(null);
|
|
252
|
-
killBrowser();
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
logger.info("[piggy] closed");
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
detect: detectBinary,
|
|
259
|
-
logger,
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// ── usePiggy ──────────────────────────────────────────────────────────────────
|
|
263
|
-
|
|
264
|
-
type TypedPiggy<Sites extends string> = typeof piggy & {
|
|
265
|
-
[K in Sites]: SiteObject;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
export function usePiggy<Sites extends string>(): TypedPiggy<Sites> {
|
|
269
|
-
return piggy as TypedPiggy<Sites>;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export type { SiteObject };
|
|
273
|
-
export default piggy;
|
|
274
|
-
export { piggy };
|
|
File without changes
|