@workglow/electron 0.2.32
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/ElectronBackend.d.ts +55 -0
- package/dist/ElectronBackend.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +247 -0
- package/dist/index.js.map +10 -0
- package/package.json +56 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Steven Roussey <sroussey@gmail.com>
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { CDPBrowserBackend } from "@workglow/browser-control/task";
|
|
7
|
+
import type { BrowserConnectOptions, DialogAction, DialogInfo, DownloadOptions, DownloadResult, ElementRef, IBrowserContext, NavigateOptions, ScreenshotOptions, TabInfo, WaitOptions } from "@workglow/browser-control/task";
|
|
8
|
+
/**
|
|
9
|
+
* IBrowserContext implementation using Electron's native webContents + CDP.
|
|
10
|
+
*
|
|
11
|
+
* This file is only imported from the Electron main process. It must NOT be
|
|
12
|
+
* included in browser/bun/node entry points.
|
|
13
|
+
*
|
|
14
|
+
* Session isolation is achieved via `session.fromPartition(partitionString)`
|
|
15
|
+
* scoped to projectId + profileName.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ElectronBackend extends CDPBrowserBackend implements IBrowserContext {
|
|
18
|
+
/** @type {AnyBrowserWindow} Electron BrowserWindow instance */
|
|
19
|
+
private _window;
|
|
20
|
+
/** @type {AnyWebContents} Electron webContents instance */
|
|
21
|
+
private _webContents;
|
|
22
|
+
private _connected;
|
|
23
|
+
private _dialogHandler;
|
|
24
|
+
protected readonly backendName = "ElectronBackend";
|
|
25
|
+
/**
|
|
26
|
+
* Send a Chrome DevTools Protocol command via the Electron debugger.
|
|
27
|
+
* @param method CDP method name (e.g. "DOM.getBoxModel")
|
|
28
|
+
* @param params CDP parameters
|
|
29
|
+
*/
|
|
30
|
+
protected cdp(method: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
31
|
+
protected evaluateInPage<T>(script: string): Promise<T>;
|
|
32
|
+
connect(options?: BrowserConnectOptions): Promise<void>;
|
|
33
|
+
disconnect(): Promise<void>;
|
|
34
|
+
isConnected(): boolean;
|
|
35
|
+
private get wc();
|
|
36
|
+
navigate(url: string, _options?: NavigateOptions): Promise<void>;
|
|
37
|
+
goBack(_options?: NavigateOptions): Promise<void>;
|
|
38
|
+
goForward(_options?: NavigateOptions): Promise<void>;
|
|
39
|
+
reload(_options?: NavigateOptions): Promise<void>;
|
|
40
|
+
currentUrl(): Promise<string>;
|
|
41
|
+
title(): Promise<string>;
|
|
42
|
+
content(): Promise<string>;
|
|
43
|
+
evaluate<T>(expression: string): Promise<T>;
|
|
44
|
+
screenshot(options?: ScreenshotOptions): Promise<Buffer>;
|
|
45
|
+
download(trigger: () => Promise<void>, options?: DownloadOptions): Promise<DownloadResult>;
|
|
46
|
+
onDialog(handler: (info: DialogInfo) => DialogAction | Promise<DialogAction>): void;
|
|
47
|
+
tabs(): Promise<readonly TabInfo[]>;
|
|
48
|
+
switchTab(_tabId: string): Promise<void>;
|
|
49
|
+
newTab(url?: string): Promise<TabInfo>;
|
|
50
|
+
closeTab(_tabId: string): Promise<void>;
|
|
51
|
+
waitForNavigation(options?: NavigateOptions): Promise<void>;
|
|
52
|
+
waitForSelector(selector: string, options?: WaitOptions): Promise<ElementRef>;
|
|
53
|
+
waitForIdle(options?: WaitOptions): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ElectronBackend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ElectronBackend.d.ts","sourceRoot":"","sources":["../src/ElectronBackend.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EACV,qBAAqB,EACrB,YAAY,EACZ,UAAU,EACV,eAAe,EACf,cAAc,EACd,UAAU,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,WAAW,EACZ,MAAM,gCAAgC,CAAC;AAwCxC;;;;;;;;GAQG;AACH,qBAAa,eAAgB,SAAQ,iBAAkB,YAAW,eAAe;IAC/E,+DAA+D;IAC/D,OAAO,CAAC,OAAO,CAAiC;IAEhD,2DAA2D;IAC3D,OAAO,CAAC,YAAY,CAA+B;IAEnD,OAAO,CAAC,UAAU,CAAS;IAG3B,OAAO,CAAC,cAAc,CACf;IAEP,SAAS,CAAC,QAAQ,CAAC,WAAW,qBAAqB;IAMnD;;;;OAIG;IACH,UAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK1F;IAMD,UAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE5D;IAMK,OAAO,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ChE;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBhC;IAED,WAAW,IAAI,OAAO,CAErB;IAMD,OAAO,KAAK,EAAE,GAKb;IAMK,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE;IAEK,MAAM,CAAC,QAAQ,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1D;IAEK,SAAS,CAAC,QAAQ,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7D;IAEK,MAAM,CAAC,QAAQ,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1D;IAEK,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAElC;IAEK,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAE7B;IAMK,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAE/B;IAMK,QAAQ,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAEhD;IAMK,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CASjE;IAMK,QAAQ,CACZ,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC5B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CA6CzB;IAMD,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAkClF;IAMK,IAAI,IAAI,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAIxC;IAEK,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7C;IAEK,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3C;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5C;IAMK,iBAAiB,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpE;IAEK,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBtF;IAEK,WAAW,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAY1D;CAUF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined")
|
|
5
|
+
return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// src/ElectronBackend.ts
|
|
10
|
+
import { sleep } from "@workglow/util";
|
|
11
|
+
import { CDPBrowserBackend } from "@workglow/browser-control/task";
|
|
12
|
+
var electronModule = null;
|
|
13
|
+
async function getElectron() {
|
|
14
|
+
if (!electronModule) {
|
|
15
|
+
electronModule = await new Function("m", "return import(m)")("electron");
|
|
16
|
+
}
|
|
17
|
+
return electronModule;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class ElectronBackend extends CDPBrowserBackend {
|
|
21
|
+
_window = null;
|
|
22
|
+
_webContents = null;
|
|
23
|
+
_connected = false;
|
|
24
|
+
_dialogHandler = null;
|
|
25
|
+
backendName = "ElectronBackend";
|
|
26
|
+
async cdp(method, params = {}) {
|
|
27
|
+
if (!this._webContents) {
|
|
28
|
+
throw new Error("ElectronBackend: not connected — call connect() first");
|
|
29
|
+
}
|
|
30
|
+
return this._webContents.debugger.sendCommand(method, params);
|
|
31
|
+
}
|
|
32
|
+
async evaluateInPage(script) {
|
|
33
|
+
return this.wc.executeJavaScript(script);
|
|
34
|
+
}
|
|
35
|
+
async connect(options = {}) {
|
|
36
|
+
const electron = await getElectron();
|
|
37
|
+
const { BrowserWindow, session: electronSession } = electron;
|
|
38
|
+
const { projectId = "default", profileName = "default", headless = false } = options;
|
|
39
|
+
const partitionString = `persist:${projectId}:${profileName}`;
|
|
40
|
+
const sess = electronSession.fromPartition(partitionString);
|
|
41
|
+
this._window = new BrowserWindow({
|
|
42
|
+
width: 1280,
|
|
43
|
+
height: 800,
|
|
44
|
+
show: !headless,
|
|
45
|
+
webPreferences: {
|
|
46
|
+
session: sess,
|
|
47
|
+
nodeIntegration: false,
|
|
48
|
+
contextIsolation: true
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
this._webContents = this._window.webContents;
|
|
52
|
+
try {
|
|
53
|
+
this._webContents.debugger.attach("1.3");
|
|
54
|
+
} catch {}
|
|
55
|
+
await this.cdp("Accessibility.enable");
|
|
56
|
+
this._webContents.on("select-client-certificate", (_event, _url, _list, callback) => {
|
|
57
|
+
callback(undefined);
|
|
58
|
+
});
|
|
59
|
+
this._webContents.on("will-prevent-unload", (event) => {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
});
|
|
62
|
+
this._connected = true;
|
|
63
|
+
}
|
|
64
|
+
async disconnect() {
|
|
65
|
+
this._connected = false;
|
|
66
|
+
try {
|
|
67
|
+
if (this._webContents) {
|
|
68
|
+
try {
|
|
69
|
+
this._webContents.debugger.detach();
|
|
70
|
+
} catch {}
|
|
71
|
+
}
|
|
72
|
+
if (this._window && !this._window.isDestroyed()) {
|
|
73
|
+
this._window.close();
|
|
74
|
+
}
|
|
75
|
+
} finally {
|
|
76
|
+
this._window = null;
|
|
77
|
+
this._webContents = null;
|
|
78
|
+
this._refMap.clear();
|
|
79
|
+
this._refCounter.count = 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
isConnected() {
|
|
83
|
+
return this._connected && this._window !== null && !this._window.isDestroyed();
|
|
84
|
+
}
|
|
85
|
+
get wc() {
|
|
86
|
+
if (!this._webContents || !this._connected) {
|
|
87
|
+
throw new Error("ElectronBackend: not connected — call connect() first");
|
|
88
|
+
}
|
|
89
|
+
return this._webContents;
|
|
90
|
+
}
|
|
91
|
+
async navigate(url, _options = {}) {
|
|
92
|
+
await this.wc.loadURL(url);
|
|
93
|
+
}
|
|
94
|
+
async goBack(_options = {}) {
|
|
95
|
+
this.wc.navigationHistory.goBack();
|
|
96
|
+
await this.waitForNavigation();
|
|
97
|
+
}
|
|
98
|
+
async goForward(_options = {}) {
|
|
99
|
+
this.wc.navigationHistory.goForward();
|
|
100
|
+
await this.waitForNavigation();
|
|
101
|
+
}
|
|
102
|
+
async reload(_options = {}) {
|
|
103
|
+
this.wc.reload();
|
|
104
|
+
await this.waitForNavigation();
|
|
105
|
+
}
|
|
106
|
+
async currentUrl() {
|
|
107
|
+
return this.wc.getURL();
|
|
108
|
+
}
|
|
109
|
+
async title() {
|
|
110
|
+
return this.wc.getTitle();
|
|
111
|
+
}
|
|
112
|
+
async content() {
|
|
113
|
+
return this.wc.executeJavaScript("document.documentElement.outerHTML");
|
|
114
|
+
}
|
|
115
|
+
async evaluate(expression) {
|
|
116
|
+
return this.wc.executeJavaScript(expression);
|
|
117
|
+
}
|
|
118
|
+
async screenshot(options = {}) {
|
|
119
|
+
const { format = "png", quality } = options;
|
|
120
|
+
const image = await this.wc.capturePage();
|
|
121
|
+
if (format === "jpeg") {
|
|
122
|
+
return image.toJPEG(quality ?? 90);
|
|
123
|
+
}
|
|
124
|
+
return image.toPNG();
|
|
125
|
+
}
|
|
126
|
+
async download(trigger, options = {}) {
|
|
127
|
+
const os = await import("node:os");
|
|
128
|
+
const downloadDir = os.tmpdir();
|
|
129
|
+
const timeout = options.timeout ?? 30000;
|
|
130
|
+
await this.cdp("Browser.setDownloadBehavior", {
|
|
131
|
+
behavior: "allow",
|
|
132
|
+
downloadPath: downloadDir
|
|
133
|
+
});
|
|
134
|
+
let downloadPath = "";
|
|
135
|
+
let suggestedFilename = "";
|
|
136
|
+
const downloadPromise = new Promise((resolve, reject) => {
|
|
137
|
+
const timer = setTimeout(() => {
|
|
138
|
+
reject(new Error("ElectronBackend: download timed out"));
|
|
139
|
+
}, timeout);
|
|
140
|
+
const handler = (_event, item, _webContents) => {
|
|
141
|
+
suggestedFilename = item.getFilename ? item.getFilename() : "download";
|
|
142
|
+
item.once?.("done", (_e, state) => {
|
|
143
|
+
clearTimeout(timer);
|
|
144
|
+
if (state === "completed") {
|
|
145
|
+
downloadPath = item.getSavePath ? item.getSavePath() : downloadDir + "/" + suggestedFilename;
|
|
146
|
+
}
|
|
147
|
+
resolve();
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
this.wc.session.once("will-download", handler);
|
|
151
|
+
});
|
|
152
|
+
await trigger();
|
|
153
|
+
await downloadPromise;
|
|
154
|
+
if (!downloadPath) {
|
|
155
|
+
throw new Error("ElectronBackend: download failed — no path received");
|
|
156
|
+
}
|
|
157
|
+
return { path: downloadPath, suggestedFilename };
|
|
158
|
+
}
|
|
159
|
+
onDialog(handler) {
|
|
160
|
+
this._dialogHandler = handler;
|
|
161
|
+
this.cdp("Page.enable").then(() => {
|
|
162
|
+
this.wc.debugger.on("message", async (_event, method, params) => {
|
|
163
|
+
if (method !== "Page.javascriptDialogOpening")
|
|
164
|
+
return;
|
|
165
|
+
const info = {
|
|
166
|
+
type: params.type,
|
|
167
|
+
message: params.message,
|
|
168
|
+
defaultValue: params.defaultPrompt || undefined
|
|
169
|
+
};
|
|
170
|
+
if (this._dialogHandler) {
|
|
171
|
+
const action = await this._dialogHandler(info);
|
|
172
|
+
const accept = action.accept;
|
|
173
|
+
const promptText = accept && "promptText" in action ? action.promptText : undefined;
|
|
174
|
+
await this.cdp("Page.handleJavaScriptDialog", {
|
|
175
|
+
accept,
|
|
176
|
+
...promptText !== undefined && { promptText }
|
|
177
|
+
});
|
|
178
|
+
} else {
|
|
179
|
+
await this.cdp("Page.handleJavaScriptDialog", { accept: false });
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
async tabs() {
|
|
185
|
+
const url = this.wc.getURL();
|
|
186
|
+
const title = this.wc.getTitle();
|
|
187
|
+
return [{ tabId: "0", url, title }];
|
|
188
|
+
}
|
|
189
|
+
async switchTab(_tabId) {}
|
|
190
|
+
async newTab(url) {
|
|
191
|
+
if (url) {
|
|
192
|
+
await this.navigate(url);
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
tabId: "0",
|
|
196
|
+
url: this.wc.getURL(),
|
|
197
|
+
title: this.wc.getTitle()
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
async closeTab(_tabId) {
|
|
201
|
+
await this.disconnect();
|
|
202
|
+
}
|
|
203
|
+
async waitForNavigation(options = {}) {
|
|
204
|
+
const timeout = options.timeout ?? 30000;
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
const timer = setTimeout(() => {
|
|
207
|
+
reject(new Error("ElectronBackend: waitForNavigation timed out"));
|
|
208
|
+
}, timeout);
|
|
209
|
+
this.wc.once("did-finish-load", () => {
|
|
210
|
+
clearTimeout(timer);
|
|
211
|
+
resolve();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
async waitForSelector(selector, options = {}) {
|
|
216
|
+
const timeout = options.timeout ?? 30000;
|
|
217
|
+
const interval = 100;
|
|
218
|
+
const deadline = Date.now() + timeout;
|
|
219
|
+
while (Date.now() < deadline) {
|
|
220
|
+
const found = await this.wc.executeJavaScript(`!!document.querySelector(${JSON.stringify(selector)})`);
|
|
221
|
+
if (found) {
|
|
222
|
+
const ref = await this.querySelector(selector);
|
|
223
|
+
if (ref)
|
|
224
|
+
return ref;
|
|
225
|
+
}
|
|
226
|
+
await sleep(interval);
|
|
227
|
+
}
|
|
228
|
+
throw new Error(`ElectronBackend: waitForSelector timed out for "${selector}"`);
|
|
229
|
+
}
|
|
230
|
+
async waitForIdle(options = {}) {
|
|
231
|
+
const timeout = options.timeout ?? 30000;
|
|
232
|
+
const interval = 100;
|
|
233
|
+
const deadline = Date.now() + timeout;
|
|
234
|
+
while (Date.now() < deadline) {
|
|
235
|
+
const ready = await this.wc.executeJavaScript(`document.readyState === "complete"`);
|
|
236
|
+
if (ready)
|
|
237
|
+
return;
|
|
238
|
+
await sleep(interval);
|
|
239
|
+
}
|
|
240
|
+
throw new Error("ElectronBackend: waitForIdle timed out");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export {
|
|
244
|
+
ElectronBackend
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
//# debugId=C66266ED378CDCB864756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/ElectronBackend.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { sleep } from \"@workglow/util\";\nimport { CDPBrowserBackend } from \"@workglow/browser-control/task\";\nimport type {\n BrowserConnectOptions,\n DialogAction,\n DialogInfo,\n DownloadOptions,\n DownloadResult,\n ElementRef,\n IBrowserContext,\n NavigateOptions,\n ScreenshotOptions,\n TabInfo,\n WaitOptions,\n} from \"@workglow/browser-control/task\";\n\n// ---------------------------------------------------------------------------\n// Electron types (not imported at module level — lazy optional dependency)\n// ---------------------------------------------------------------------------\n\n/** @type {import(\"electron\").BrowserWindow} */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyBrowserWindow = any;\n\n/** @type {import(\"electron\").WebContents} */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyWebContents = any;\n\n// ---------------------------------------------------------------------------\n// Lazy Electron loader\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet electronModule: Record<string, any> | null = null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function getElectron(): Promise<Record<string, any>> {\n if (!electronModule) {\n // Dynamic import keeps electron as a true optional dependency.\n // The `Function` cast avoids a static \"cannot find module\" TS error\n // when electron types are not installed in the current environment.\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n electronModule = (await new Function(\"m\", \"return import(m)\")(\"electron\")) as Record<\n string,\n any\n >;\n }\n return electronModule;\n}\n\n// ---------------------------------------------------------------------------\n// ElectronBackend\n// ---------------------------------------------------------------------------\n\n/**\n * IBrowserContext implementation using Electron's native webContents + CDP.\n *\n * This file is only imported from the Electron main process. It must NOT be\n * included in browser/bun/node entry points.\n *\n * Session isolation is achieved via `session.fromPartition(partitionString)`\n * scoped to projectId + profileName.\n */\nexport class ElectronBackend extends CDPBrowserBackend implements IBrowserContext {\n /** @type {AnyBrowserWindow} Electron BrowserWindow instance */\n private _window: AnyBrowserWindow | null = null;\n\n /** @type {AnyWebContents} Electron webContents instance */\n private _webContents: AnyWebContents | null = null;\n\n private _connected = false;\n\n // Dialog handler\n private _dialogHandler: ((info: DialogInfo) => DialogAction | Promise<DialogAction>) | null =\n null;\n\n protected readonly backendName = \"ElectronBackend\";\n\n // ---------------------------------------------------------------------------\n // CDP helper\n // ---------------------------------------------------------------------------\n\n /**\n * Send a Chrome DevTools Protocol command via the Electron debugger.\n * @param method CDP method name (e.g. \"DOM.getBoxModel\")\n * @param params CDP parameters\n */\n protected async cdp(method: string, params: Record<string, unknown> = {}): Promise<unknown> {\n if (!this._webContents) {\n throw new Error(\"ElectronBackend: not connected — call connect() first\");\n }\n return this._webContents.debugger.sendCommand(method, params);\n }\n\n // ---------------------------------------------------------------------------\n // evaluateInPage (abstract from CDPBrowserBackend)\n // ---------------------------------------------------------------------------\n\n protected async evaluateInPage<T>(script: string): Promise<T> {\n return this.wc.executeJavaScript(script);\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async connect(options: BrowserConnectOptions = {}): Promise<void> {\n const electron = await getElectron();\n const { BrowserWindow, session: electronSession } = electron;\n\n const { projectId = \"default\", profileName = \"default\", headless = false } = options;\n\n const partitionString = `persist:${projectId}:${profileName}`;\n const sess = electronSession.fromPartition(partitionString);\n\n this._window = new BrowserWindow({\n width: 1280,\n height: 800,\n show: !headless,\n webPreferences: {\n session: sess,\n nodeIntegration: false,\n contextIsolation: true,\n },\n }) as AnyBrowserWindow;\n\n this._webContents = this._window.webContents as AnyWebContents;\n\n // Attach CDP debugger\n try {\n this._webContents.debugger.attach(\"1.3\");\n } catch {\n // Already attached or version not supported — continue\n }\n\n // Enable Accessibility domain\n await this.cdp(\"Accessibility.enable\");\n\n // Wire dialog handler\n this._webContents.on(\n \"select-client-certificate\",\n (_event: unknown, _url: unknown, _list: unknown, callback: (cert: unknown) => void) => {\n callback(undefined);\n }\n );\n\n this._webContents.on(\"will-prevent-unload\", (event: { preventDefault: () => void }) => {\n event.preventDefault();\n });\n\n this._connected = true;\n }\n\n async disconnect(): Promise<void> {\n this._connected = false;\n try {\n if (this._webContents) {\n try {\n this._webContents.debugger.detach();\n } catch {\n // Ignore detach errors\n }\n }\n if (this._window && !this._window.isDestroyed()) {\n this._window.close();\n }\n } finally {\n this._window = null;\n this._webContents = null;\n this._refMap.clear();\n this._refCounter.count = 0;\n }\n }\n\n isConnected(): boolean {\n return this._connected && this._window !== null && !this._window.isDestroyed();\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n private get wc(): AnyWebContents {\n if (!this._webContents || !this._connected) {\n throw new Error(\"ElectronBackend: not connected — call connect() first\");\n }\n return this._webContents;\n }\n\n // ---------------------------------------------------------------------------\n // Navigation\n // ---------------------------------------------------------------------------\n\n async navigate(url: string, _options: NavigateOptions = {}): Promise<void> {\n await this.wc.loadURL(url);\n }\n\n async goBack(_options: NavigateOptions = {}): Promise<void> {\n this.wc.navigationHistory.goBack();\n await this.waitForNavigation();\n }\n\n async goForward(_options: NavigateOptions = {}): Promise<void> {\n this.wc.navigationHistory.goForward();\n await this.waitForNavigation();\n }\n\n async reload(_options: NavigateOptions = {}): Promise<void> {\n this.wc.reload();\n await this.waitForNavigation();\n }\n\n async currentUrl(): Promise<string> {\n return this.wc.getURL();\n }\n\n async title(): Promise<string> {\n return this.wc.getTitle();\n }\n\n // ---------------------------------------------------------------------------\n // Content extraction\n // ---------------------------------------------------------------------------\n\n async content(): Promise<string> {\n return this.wc.executeJavaScript(\"document.documentElement.outerHTML\") as Promise<string>;\n }\n\n // ---------------------------------------------------------------------------\n // JS evaluation\n // ---------------------------------------------------------------------------\n\n async evaluate<T>(expression: string): Promise<T> {\n return this.wc.executeJavaScript(expression) as Promise<T>;\n }\n\n // ---------------------------------------------------------------------------\n // Capture\n // ---------------------------------------------------------------------------\n\n async screenshot(options: ScreenshotOptions = {}): Promise<Buffer> {\n const { format = \"png\", quality } = options;\n\n const image = await this.wc.capturePage();\n\n if (format === \"jpeg\") {\n return image.toJPEG(quality ?? 90) as Buffer;\n }\n return image.toPNG() as Buffer;\n }\n\n // ---------------------------------------------------------------------------\n // File operations\n // ---------------------------------------------------------------------------\n\n async download(\n trigger: () => Promise<void>,\n options: DownloadOptions = {}\n ): Promise<DownloadResult> {\n const os = await import(\"node:os\");\n const downloadDir = os.tmpdir();\n const timeout = options.timeout ?? 30_000;\n\n // Set up download behavior via CDP\n await this.cdp(\"Browser.setDownloadBehavior\", {\n behavior: \"allow\",\n downloadPath: downloadDir,\n });\n\n let downloadPath = \"\";\n let suggestedFilename = \"\";\n\n // Listen for download completion.\n // Electron's will-download signature: (event, item, webContents)\n const downloadPromise = new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new Error(\"ElectronBackend: download timed out\"));\n }, timeout);\n\n const handler = (_event: unknown, item: AnyWebContents, _webContents: unknown) => {\n // item is a DownloadItem\n suggestedFilename = item.getFilename ? item.getFilename() : \"download\";\n item.once?.(\"done\", (_e: unknown, state: string) => {\n clearTimeout(timer);\n if (state === \"completed\") {\n downloadPath = item.getSavePath\n ? item.getSavePath()\n : downloadDir + \"/\" + suggestedFilename;\n }\n resolve();\n });\n };\n this.wc.session.once(\"will-download\", handler);\n });\n\n await trigger();\n await downloadPromise;\n\n if (!downloadPath) {\n throw new Error(\"ElectronBackend: download failed — no path received\");\n }\n\n return { path: downloadPath, suggestedFilename };\n }\n\n // ---------------------------------------------------------------------------\n // Dialogs\n // ---------------------------------------------------------------------------\n\n onDialog(handler: (info: DialogInfo) => DialogAction | Promise<DialogAction>): void {\n this._dialogHandler = handler;\n\n // Use CDP Page.javascriptDialogOpening to intercept alert/confirm/prompt dialogs.\n // This requires Page domain to be enabled.\n void this.cdp(\"Page.enable\").then(() => {\n this.wc.debugger.on(\n \"message\",\n async (_event: unknown, method: string, params: Record<string, unknown>) => {\n if (method !== \"Page.javascriptDialogOpening\") return;\n\n const info: DialogInfo = {\n type: params.type as DialogInfo[\"type\"],\n message: params.message as string,\n defaultValue: (params.defaultPrompt as string) || undefined,\n };\n\n if (this._dialogHandler) {\n const action = await this._dialogHandler(info);\n const accept = action.accept;\n const promptText =\n accept && \"promptText\" in action\n ? (action as { accept: true; promptText?: string }).promptText\n : undefined;\n await this.cdp(\"Page.handleJavaScriptDialog\", {\n accept,\n ...(promptText !== undefined && { promptText }),\n });\n } else {\n await this.cdp(\"Page.handleJavaScriptDialog\", { accept: false });\n }\n }\n );\n });\n }\n\n // ---------------------------------------------------------------------------\n // Tabs (simplified single-window model)\n // ---------------------------------------------------------------------------\n\n async tabs(): Promise<readonly TabInfo[]> {\n const url = this.wc.getURL();\n const title = this.wc.getTitle();\n return [{ tabId: \"0\", url, title }];\n }\n\n async switchTab(_tabId: string): Promise<void> {\n // Single-window model: no-op\n }\n\n async newTab(url?: string): Promise<TabInfo> {\n if (url) {\n await this.navigate(url);\n }\n return {\n tabId: \"0\",\n url: this.wc.getURL(),\n title: this.wc.getTitle(),\n };\n }\n\n async closeTab(_tabId: string): Promise<void> {\n // Single-window model: closing the tab means closing the window\n await this.disconnect();\n }\n\n // ---------------------------------------------------------------------------\n // Wait\n // ---------------------------------------------------------------------------\n\n async waitForNavigation(options: NavigateOptions = {}): Promise<void> {\n const timeout = options.timeout ?? 30_000;\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new Error(\"ElectronBackend: waitForNavigation timed out\"));\n }, timeout);\n\n this.wc.once(\"did-finish-load\", () => {\n clearTimeout(timer);\n resolve();\n });\n });\n }\n\n async waitForSelector(selector: string, options: WaitOptions = {}): Promise<ElementRef> {\n const timeout = options.timeout ?? 30_000;\n const interval = 100;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const found = await this.wc.executeJavaScript(\n `!!document.querySelector(${JSON.stringify(selector)})`\n );\n if (found) {\n const ref = await this.querySelector(selector);\n if (ref) return ref;\n }\n await sleep(interval);\n }\n\n throw new Error(`ElectronBackend: waitForSelector timed out for \"${selector}\"`);\n }\n\n async waitForIdle(options: WaitOptions = {}): Promise<void> {\n const timeout = options.timeout ?? 30_000;\n const interval = 100;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const ready = await this.wc.executeJavaScript(`document.readyState === \"complete\"`);\n if (ready) return;\n await sleep(interval);\n }\n\n throw new Error(\"ElectronBackend: waitForIdle timed out\");\n }\n\n // ---------------------------------------------------------------------------\n // Optional capabilities\n // ---------------------------------------------------------------------------\n //\n // networkRequests and consoleMessages are intentionally undefined: this\n // backend does not implement them. The IBrowserContext contract is that\n // optional methods are either fully implemented or undefined — never\n // empty-stub functions that defeat feature detection.\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "C66266ED378CDCB864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@workglow/electron",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"version": "0.2.32",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/workglow-dev/workglow.git",
|
|
9
|
+
"directory": "providers/electron"
|
|
10
|
+
},
|
|
11
|
+
"description": "Electron native-webContents browser backend for @workglow/browser-control.",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"watch": "concurrently -c 'auto' 'bun:watch-*'",
|
|
14
|
+
"watch-code": "bun build --watch --no-clear-screen --sourcemap=external --packages=external --root ./src --outdir ./dist ./src/index.ts",
|
|
15
|
+
"watch-types": "tsc --watch --preserveWatchOutput",
|
|
16
|
+
"build-package": "concurrently -c 'auto' -n 'code,types' 'bun run build-code' 'bun run build-types'",
|
|
17
|
+
"build-js": "bun run build-code",
|
|
18
|
+
"build-clean": "rm -fr dist/* tsconfig.tsbuildinfo",
|
|
19
|
+
"build-code": "bun build --sourcemap=external --packages=external --root ./src --outdir ./dist ./src/index.ts",
|
|
20
|
+
"build-types": "rm -f tsconfig.tsbuildinfo && tsgo",
|
|
21
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
22
|
+
"test": "bun test"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"electron": "^42.0.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@workglow/browser-control": "0.2.32",
|
|
35
|
+
"@workglow/util": "0.2.32"
|
|
36
|
+
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"@workglow/browser-control": {
|
|
39
|
+
"optional": false
|
|
40
|
+
},
|
|
41
|
+
"@workglow/util": {
|
|
42
|
+
"optional": false
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@workglow/browser-control": "0.2.32",
|
|
47
|
+
"@workglow/util": "0.2.32"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"dist",
|
|
51
|
+
"src/**/*.md"
|
|
52
|
+
],
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
}
|
|
56
|
+
}
|