@open-wa/driver-puppeteer 5.0.0-alpha.7 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -55,9 +55,9 @@ Licensor hereby grants permission by this license ("License"), free of charge,
55
55
  4. Compliance with Human Rights Laws and Human Rights Principles:
56
56
 
57
57
  a. **Human Rights Laws**. The Software shall not be used by any person or entity for any systems, activities, or other uses that violate any applicable laws, regulations, or rules that protect human, civil, labor, privacy, political, environmental, security, economic, due process, or similar rights (the "Human Rights Laws"). Where the Human Rights Laws of more than one jurisdiction are applicable to the use of the Software, the Human Rights Laws that are most protective of the individuals or groups harmed shall apply.
58
-
58
+
59
59
  b. **Human Rights Principles**. Licensee is advised to consult the articles of the United Nations Universal Declaration of Human Rights (https://www.un.org/en/universal-declaration-human-rights/) and the United Nations Global Compact (https://www.unglobalcompact.org/ what-is-gc/mission/principles) that define recognized principles of international human rights (the "Human Rights Principles"). It is Licensor's express intent that all use of the Software be consistent with Human Rights Principles. If Licensor receives notification or otherwise learns of an alleged violation of any Human Rights Principles relating to Licensee's use of the Software, Licensor may in its discretion and without obligation (i) (a) notify Licensee of such allegation and (b) allow Licensee 90 days from notification under (i)(a) to investigate and respond to Licensor regarding the allegation and (ii) (a) after the earlier of 90 days from notification under (i)(a), or Licensee's response under (i)(b), notify Licensee of License termination and (b) allow Licensee an additional 90 days from notification under (ii)(a) to cease use of the Software.
60
-
60
+
61
61
  c. **Indemnity**. Licensee shall hold harmless and indemnify Licensor against all losses, damages, liabilities, deficiencies, claims, actions, judgments, settlements, interest, awards, penalties, fines, costs, or expenses of whatever kind, including Licensor's reasonable attorneys' fees, arising out of or relating to Licensee's non-compliance with this License or use of the Software in violation of Human Rights Laws or Human Rights Principles. 
62
62
 
63
63
  5. Enforceability: If any portion or provision of this License is determined to be invalid, illegal, or unenforceable by a court of competent jurisdiction, then such invalidity, illegality, or unenforceability shall not affect any other term or provision of this License or invalidate or render unenforceable such term or provision in any other jurisdiction. Upon a determination that any term or provision is invalid, illegal, or unenforceable, to the extent permitted by applicable law, the court may modify this License to affect the original intent of the parties as closely as possible. The section headings are for convenience only and are not intended to affect the construction or interpretation of this License. Any rule of construction to the effect that ambiguities are to be resolved against the drafting party shall not apply in interpreting this License. The language in this License shall be interpreted as to its fair meaning and not strictly for or against any party.
package/README.md CHANGED
@@ -12,8 +12,8 @@ pnpm add @open-wa/driver-puppeteer
12
12
 
13
13
  ## Documentation
14
14
 
15
- See the [docs site](https://docs.openwa.dev).
15
+ See the [docs site](https://openwa.dev).
16
16
 
17
17
  ## License
18
18
 
19
- [H-DNH V1.0](https://github.com/open-wa/wa-automate-nodejs/blob/main/LICENSE.md) — Hippocratic + Do Not Harm
19
+ [H-DNH 1.1](https://github.com/open-wa/wa-automate-nodejs/blob/master/LICENSE.md) — Hippocratic + Do Not Harm
package/dist/index.cjs CHANGED
@@ -319,7 +319,7 @@ var PuppeteerPage = class {
319
319
  async stopTracing() {
320
320
  this.require("tracing");
321
321
  const buffer = await this.page.tracing.stop();
322
- return buffer ? new Uint8Array(buffer) : new Uint8Array();
322
+ return buffer ? new Uint8Array(buffer) : /* @__PURE__ */ new Uint8Array();
323
323
  }
324
324
  unwrap() {
325
325
  return this.page;
@@ -389,11 +389,14 @@ var PuppeteerBrowser = class {
389
389
  await this.browser.close();
390
390
  }
391
391
  isConnected() {
392
- return this.browser.isConnected();
392
+ return this.browser.connected;
393
393
  }
394
394
  async versionString() {
395
395
  return await this.browser.version();
396
396
  }
397
+ processId() {
398
+ return this.browser.process()?.pid;
399
+ }
397
400
  unwrap() {
398
401
  return this.browser;
399
402
  }
@@ -418,7 +421,9 @@ var PuppeteerDriver = class {
418
421
  },
419
422
  persistentContext: { supported: true },
420
423
  browserExtensions: { supported: true },
421
- exposeBinding: { supported: true }
424
+ exposeBinding: { supported: true },
425
+ screenshot: { supported: true },
426
+ rendering: { supported: true }
422
427
  };
423
428
  }
424
429
  async init(ctx) {
@@ -427,7 +432,8 @@ var PuppeteerDriver = class {
427
432
  this.puppeteer = pExtra.default ?? pExtra;
428
433
  try {
429
434
  const { createRequire } = await import("node:module");
430
- this.version = createRequire(__filename)("puppeteer/package.json").version;
435
+ const pkg = createRequire(__filename)("puppeteer/package.json");
436
+ this.version = pkg.version;
431
437
  } catch {}
432
438
  this.ctx?.logger?.info("PuppeteerDriver initialized", { version: this.version });
433
439
  }
package/dist/index.d.cts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { ConnectOptions, DisposableHandle, DriverCapabilities, IBrowser, IDriver, IDriverContext, IElementHandle, IFrame, IPage, LaunchOptions, NavigationWaitUntil, PageEventHandler, WaitForFunctionOptions } from "@open-wa/driver-interface";
2
2
  import { Browser, CDPSession, ElementHandle, Page } from "puppeteer";
3
-
4
3
  //#region src/PuppeteerDriver.d.ts
5
- declare class PuppeteerDriver implements IDriver {
6
- readonly name: "puppeteer";
4
+ export declare class PuppeteerDriver implements IDriver {
5
+ readonly name: 'puppeteer';
7
6
  version?: string;
8
7
  readonly capabilities: DriverCapabilities;
9
8
  private puppeteer;
@@ -18,10 +17,10 @@ declare class PuppeteerDriver implements IDriver {
18
17
  }
19
18
  //#endregion
20
19
  //#region src/PuppeteerBrowser.d.ts
21
- declare class PuppeteerBrowser implements IBrowser {
20
+ export declare class PuppeteerBrowser implements IBrowser {
22
21
  private browser;
23
22
  private capabilities;
24
- readonly name: "puppeteer";
23
+ readonly name: 'puppeteer';
25
24
  constructor(browser: Browser, capabilities: DriverCapabilities);
26
25
  newPage(options?: {
27
26
  clearFirstPage?: boolean;
@@ -30,14 +29,15 @@ declare class PuppeteerBrowser implements IBrowser {
30
29
  close(): Promise<void>;
31
30
  isConnected(): boolean;
32
31
  versionString(): Promise<string>;
32
+ processId(): number | undefined;
33
33
  unwrap(): Browser;
34
34
  }
35
35
  //#endregion
36
36
  //#region src/PuppeteerPage.d.ts
37
- declare class PuppeteerPage implements IPage {
37
+ export declare class PuppeteerPage implements IPage {
38
38
  private page;
39
39
  private capabilities;
40
- readonly name: "puppeteer";
40
+ readonly name: 'puppeteer';
41
41
  private readonly listenerWrappers;
42
42
  constructor(page: Page, capabilities: DriverCapabilities);
43
43
  goto(url: string, options?: {
@@ -60,7 +60,7 @@ declare class PuppeteerPage implements IPage {
60
60
  waitForSelector(selector: string, options?: {
61
61
  timeoutMs?: number;
62
62
  }): Promise<IElementHandle | null>;
63
- waitForFunction<Arg>(script: string, options?: WaitForFunctionOptions): Promise<void>;
63
+ waitForFunction(script: string, options?: WaitForFunctionOptions): Promise<void>;
64
64
  waitForFunction<Arg>(fn: (arg: Arg) => boolean, arg: Arg, options?: WaitForFunctionOptions): Promise<void>;
65
65
  $(selector: string): Promise<IElementHandle | null>;
66
66
  $$(selector: string): Promise<IElementHandle[]>;
@@ -98,7 +98,7 @@ declare class PuppeteerPage implements IPage {
98
98
  }
99
99
  //#endregion
100
100
  //#region src/PuppeteerElementHandle.d.ts
101
- declare class PuppeteerElementHandle implements IElementHandle {
101
+ export declare class PuppeteerElementHandle implements IElementHandle {
102
102
  private element;
103
103
  constructor(element: ElementHandle);
104
104
  click(): Promise<void>;
@@ -109,5 +109,4 @@ declare class PuppeteerElementHandle implements IElementHandle {
109
109
  unwrap(): ElementHandle;
110
110
  }
111
111
  //#endregion
112
- export { PuppeteerBrowser, PuppeteerDriver, PuppeteerElementHandle, PuppeteerPage };
113
112
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/PuppeteerDriver.ts","../src/PuppeteerBrowser.ts","../src/PuppeteerPage.ts","../src/PuppeteerElementHandle.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/PuppeteerDriver.ts","../src/PuppeteerBrowser.ts","../src/PuppeteerPage.ts","../src/PuppeteerElementHandle.ts"],"mappings":";;;qBAGa,2BAA2B;WAC3B;EACT;WACS,cAAc;UAEf;UACA;EAER;EAgBM,KAAK,MAAM,iBAAiB;EAgB5B,OAAO,UAAU,gBAAgB,QAAQ;EAoBzC,QAAQ,SAAS,iBAAiB,QAAQ;EAWhD;EAIA,IAAI,kBAAkB,KAAK;EAI3B,QAAQ,kBAAkB,KAAK;;;;qBC9EtB,4BAA4B;UAIzB;UACA;WAJH;EAET,YACY,SAAS,SACT,cAAc;EAGpB,QAAQ;IACV;MACA,QAAQ;EAWN,SAAS,QAAQ;EAKjB,SAAS;EAIf;EAIM,iBAAiB;EAIvB;EAIA,UAAU;;;;qBCoHD,yBAAyB;UAKtB;UACA;WALH;mBACQ;EAEjB,YACY,MAAM,MACN,cAAc;EAGpB,KAAK,aAAa;IAAY,YAAY;IAAqB;MAAuB;EAO5F;EAIM,UAAU;EAIhB,aAAa;EAIP,sBAAsB,KAAK,KAC7B,KAAK,KAAK,QAAQ,MAAM,QAAQ,MAChC,KAAK,MACN;EAIG,SAAS,KAAK,KAAK,KAAK,KAAK,QAAQ,MAAM,QAAQ,MAAM,KAAK,MAAM,QAAQ;EAS5E,eAAe,eAAe,iBAAiB,QAAQ;EAQvD,cAAc,iBAAiB,QAAQ;EAiBvC,YAAY;IAAY;IAAe;MAAmB;EAI1D,aAAa,aAAa;EAI1B,uBAAuB,mBAAmB;EAK1C,gBAAgB,kBAAkB;IAAY;MAAuB,QAAQ;EAY7E,gBAAgB,gBAAgB,UAAU,yBAAyB;EACnE,gBAAgB,KAAK,KAAK,KAAK,iBAAiB,KAAK,KAAK,UAAU,yBAAyB;EAoC7F,EAAE,mBAAmB,QAAQ;EAK7B,GAAG,mBAAmB,QAAQ;EAK9B,MAAM,mBAAmB;EAIzB,KAAK,kBAAkB,cAAc;IAAY;MAAqB;EAItE,WAAW;IAAY;IAAuB;MAAuB,QAAQ;EAK7E,eAAe,cAAc,QAAQ,sBAAsB;EAIjE,GAAG,kBAAkB,OAAO,GAAG,cAAc,uBAAuB,iBAAiB,wBAAwB;EAiB7G,IAAI,kBAAkB,OAAO,GAAG,cAAc,uBAAuB,iBAAiB;EAchF,SAAS;EAIf;EAIA,IAAI,kBAAkB,KAAK;EAI3B,QAAQ,kBAAkB,KAAK;EAUzB,OAAO,QAAQ;EAKf,uBAAuB,kBAAkB;EAKzC,IAAI;IAAY;IAAe;MAAoB,QAAQ;EAM3D,aAAa;IAAY;IAAe;MAA0B;EAKlE,eAAe,QAAQ;EAM7B,UAAU;UAIF;UAgBA;UAkBA;UAcA;;;;qBCjcC,kCAAkC;UACvB;EAApB,YAAoB,SAAS;EAEvB,SAAS;EAIT,KAAK,eAAe;EAIpB,aAAa,eAAe;EAK5B,eAAe;EAKf,WAAW;EAIjB,UAAU"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-wa/driver-puppeteer",
3
- "version": "5.0.0-alpha.7",
3
+ "version": "5.0.0",
4
4
  "description": "Puppeteer driver implementation for open-wa",
5
5
  "main": "./dist/index.cjs",
6
6
  "types": "./dist/index.d.cts",
@@ -12,14 +12,14 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "puppeteer": "^24.40.0",
16
- "puppeteer-extra": "^3.3.6",
17
- "@open-wa/driver-interface": "5.0.0-alpha.7"
15
+ "@open-wa/driver-interface": "5.0.0",
16
+ "puppeteer": "^25.12.0",
17
+ "puppeteer-extra": "^3.3.6"
18
18
  },
19
19
  "devDependencies": {
20
- "@types/node": "^25.9.1",
21
- "typescript": "^6.0.3",
22
- "vitest": "4.1.2"
20
+ "@types/node": "^26.6.3",
21
+ "typescript": "^7.0.2",
22
+ "vitest": "5.0.2"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"
@@ -28,6 +28,10 @@
28
28
  "type": "git",
29
29
  "url": "https://github.com/open-wa/wa-automate-nodejs.git"
30
30
  },
31
+ "license": "SEE LICENSE IN LICENSE.md",
32
+ "files": [
33
+ "dist"
34
+ ],
31
35
  "scripts": {
32
36
  "build": "tsdown src/index.ts --format cjs",
33
37
  "dev": "tsdown src/index.ts --format cjs --watch",
@@ -1,22 +0,0 @@
1
-
2
- > @open-wa/driver-puppeteer@5.0.0-alpha.7 build /Users/Mohammed/projects/tools/wa/packages/driver-puppeteer
3
- > tsdown src/index.ts --format cjs
4
-
5
- ℹ tsdown v0.21.7 powered by rolldown v1.0.0-rc.12
6
- ℹ entry: src/index.ts
7
- ℹ tsconfig: tsconfig.json
8
- ℹ Build start
9
- ℹ Cleaning 3 files
10
- ℹ dist/index.cjs 13.63 kB │ gzip: 3.41 kB
11
- ℹ 1 files, total: 13.63 kB
12
- [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugin `tsdown:deps`. See https://rolldown.rs/options/checks#plugintimings for more details.
13
-
14
- ℹ dist/index.d.cts.map 2.94 kB │ gzip: 0.92 kB
15
- ℹ dist/index.d.cts 4.28 kB │ gzip: 1.24 kB
16
- ℹ 2 files, total: 7.22 kB
17
- [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:
18
- - rolldown-plugin-dts:generate (65%)
19
- - tsdown:deps (32%)
20
- See https://rolldown.rs/options/checks#plugintimings for more details.
21
-
22
- ✔ Build complete in 12218ms
@@ -1,6 +0,0 @@
1
-
2
- > @open-wa/driver-puppeteer@5.0.0-alpha.1 lint /Users/Mohammed/projects/tools/wa/packages/driver-puppeteer
3
- > oxlint src
4
-
5
- Found 0 warnings and 0 errors.
6
- Finished in 265ms on 5 files with 93 rules using 8 threads.
@@ -1,14 +0,0 @@
1
-
2
- > @open-wa/driver-puppeteer@5.0.0-alpha.0 test /Users/Mohammed/projects/tools/wa/packages/driver-puppeteer
3
- > vitest run
4
-
5
-
6
-  RUN  v4.1.2 /Users/Mohammed/projects/tools/wa/packages/driver-puppeteer
7
-
8
- ✓ src/__tests__/PuppeteerPage.test.ts (3 tests) 11ms
9
-
10
-  Test Files  1 passed (1)
11
-  Tests  3 passed (3)
12
-  Start at  15:25:43
13
-  Duration  1.12s (transform 233ms, setup 0ms, import 484ms, tests 11ms, environment 0ms)
14
-
package/CHANGELOG.md DELETED
@@ -1,63 +0,0 @@
1
- # @open-wa/driver-puppeteer
2
-
3
- ## 5.0.0-alpha.7
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies []:
8
- - @open-wa/driver-interface@5.0.0-alpha.7
9
-
10
- ## 5.0.0-alpha.6
11
-
12
- ### Patch Changes
13
-
14
- - Updated dependencies []:
15
- - @open-wa/driver-interface@5.0.0-alpha.6
16
-
17
- ## 5.0.0-alpha.5
18
-
19
- ### Patch Changes
20
-
21
- - Updated dependencies []:
22
- - @open-wa/driver-interface@5.0.0-alpha.5
23
-
24
- ## 5.0.0-alpha.4
25
-
26
- ### Patch Changes
27
-
28
- - Updated dependencies []:
29
- - @open-wa/driver-interface@5.0.0-alpha.4
30
-
31
- ## 5.0.0-alpha.3
32
-
33
- ### Patch Changes
34
-
35
- - Updated dependencies []:
36
- - @open-wa/driver-interface@5.0.0-alpha.3
37
-
38
- ## 5.0.0-alpha.2
39
-
40
- ### Patch Changes
41
-
42
- - Updated dependencies []:
43
- - @open-wa/driver-interface@5.0.0-alpha.2
44
-
45
- ## 6.0.0-alpha.2
46
-
47
- ### Minor Changes
48
-
49
- - Dry run minor bump
50
-
51
- ### Patch Changes
52
-
53
- - Updated dependencies []:
54
- - @open-wa/driver-interface@6.0.0-alpha.2
55
-
56
- ## 5.0.1-alpha.2
57
-
58
- ### Patch Changes
59
-
60
- - Dry run patch bump
61
-
62
- - Updated dependencies []:
63
- - @open-wa/driver-interface@5.0.1-alpha.2
@@ -1,46 +0,0 @@
1
- import { IBrowser, IPage, DriverCapabilities } from '@open-wa/driver-interface';
2
- import type { Browser } from 'puppeteer';
3
- import { PuppeteerPage } from './PuppeteerPage';
4
-
5
- export class PuppeteerBrowser implements IBrowser {
6
- readonly name = 'puppeteer' as const;
7
-
8
- constructor(
9
- private browser: Browser,
10
- private capabilities: DriverCapabilities
11
- ) { }
12
-
13
- async newPage(options?: {
14
- clearFirstPage?: boolean
15
- }): Promise<IPage> {
16
- const page = await this.browser.newPage();
17
- if (options?.clearFirstPage) {
18
- const pages = await this.browser.pages();
19
- if (pages.length > 0) {
20
- await pages[0].close();
21
- }
22
- }
23
- return new PuppeteerPage(page, this.capabilities);
24
- }
25
-
26
- async pages(): Promise<IPage[]> {
27
- const pages = await this.browser.pages();
28
- return pages.map(p => new PuppeteerPage(p, this.capabilities));
29
- }
30
-
31
- async close(): Promise<void> {
32
- await this.browser.close();
33
- }
34
-
35
- isConnected(): boolean {
36
- return this.browser.isConnected();
37
- }
38
-
39
- async versionString(): Promise<string> {
40
- return await this.browser.version();
41
- }
42
-
43
- unwrap(): Browser {
44
- return this.browser;
45
- }
46
- }
@@ -1,91 +0,0 @@
1
- import { IDriver, IBrowser, LaunchOptions, ConnectOptions, IDriverContext, DriverCapabilities } from '@open-wa/driver-interface';
2
- import { PuppeteerBrowser } from './PuppeteerBrowser';
3
-
4
- export class PuppeteerDriver implements IDriver {
5
- readonly name = 'puppeteer' as const;
6
- version?: string;
7
- readonly capabilities: DriverCapabilities;
8
-
9
- private puppeteer: any;
10
- private ctx?: IDriverContext;
11
-
12
- constructor() {
13
- this.capabilities = {
14
- cdp: { supported: true },
15
- requestInterception: { supported: true },
16
- serviceWorkerBypass: { supported: true },
17
- stealth: { supported: true, notes: 'Via puppeteer-extra plugins' },
18
- pdf: { supported: true },
19
- tracing: { supported: true, notes: 'Basic tracing support' },
20
- persistentContext: { supported: true },
21
- browserExtensions: { supported: true },
22
- exposeBinding: { supported: true },
23
- };
24
- }
25
-
26
- async init(ctx?: IDriverContext): Promise<void> {
27
- this.ctx = ctx;
28
-
29
- const pExtra = await import('puppeteer-extra');
30
- this.puppeteer = pExtra.default ?? pExtra;
31
-
32
- try {
33
- const { createRequire } = await import('node:module');
34
- const _require = createRequire(__filename);
35
- const pkg = _require('puppeteer/package.json');
36
- this.version = pkg.version;
37
- } catch {}
38
-
39
- this.ctx?.logger?.info('PuppeteerDriver initialized', { version: this.version });
40
- }
41
-
42
- async launch(options?: LaunchOptions): Promise<IBrowser> {
43
- if (!this.puppeteer) await this.init();
44
-
45
- const browser = await this.puppeteer.launch({
46
- headless: options?.headless ?? true,
47
- executablePath: options?.executablePath,
48
- args: options?.args || [],
49
- defaultViewport: options?.defaultViewport,
50
- userDataDir: options?.userDataDir,
51
- timeout: options?.timeoutMs,
52
- });
53
-
54
- try {
55
- const browserVersion = await browser.version();
56
- this.ctx?.logger?.info('Browser executable version', { version: browserVersion });
57
- } catch {}
58
-
59
- return new PuppeteerBrowser(browser, this.capabilities);
60
- }
61
-
62
- async connect(options: ConnectOptions): Promise<IBrowser> {
63
- if (!this.puppeteer) await this.init();
64
-
65
- const browser = await this.puppeteer.connect({
66
- browserWSEndpoint: options.wsEndpoint,
67
- timeout: options?.timeoutMs,
68
- });
69
-
70
- return new PuppeteerBrowser(browser, this.capabilities);
71
- }
72
-
73
- unwrap(): any {
74
- return this.puppeteer;
75
- }
76
-
77
- has<C extends string>(cap: C): boolean {
78
- return (this.capabilities as any)[cap]?.supported === true;
79
- }
80
-
81
- require<C extends string>(cap: C): void {
82
- if (!this.has(cap)) {
83
- const capability = (this.capabilities as any)[cap];
84
- throw new Error(
85
- `Driver '${this.name}' does not support capability '${cap}'${
86
- capability?.reason ? `: ${capability.reason}` : ''
87
- }`
88
- );
89
- }
90
- }
91
- }
@@ -1,32 +0,0 @@
1
- import { IElementHandle } from '@open-wa/driver-interface';
2
- import type { ElementHandle } from 'puppeteer';
3
-
4
- export class PuppeteerElementHandle implements IElementHandle {
5
- constructor(private element: ElementHandle) {}
6
-
7
- async click(): Promise<void> {
8
- await this.element.click();
9
- }
10
-
11
- async type(text: string): Promise<void> {
12
- await this.element.type(text);
13
- }
14
-
15
- async getAttribute(name: string): Promise<string | null> {
16
- const value = await this.element.evaluate((el, attr) => el.getAttribute(attr), name);
17
- return value;
18
- }
19
-
20
- async textContent(): Promise<string | null> {
21
- const text = await this.element.evaluate(el => el.textContent);
22
- return text;
23
- }
24
-
25
- async dispose(): Promise<void> {
26
- await this.element.dispose();
27
- }
28
-
29
- unwrap(): ElementHandle {
30
- return this.element;
31
- }
32
- }
@@ -1,470 +0,0 @@
1
- import {
2
- IPage,
3
- IElementHandle,
4
- DriverCapabilities,
5
- type DisposableHandle,
6
- type IConsoleMessage,
7
- type IFrame,
8
- type IRequest,
9
- type IRequestContinueOverrides,
10
- type IRequestResponse,
11
- type NavigationWaitUntil,
12
- type PageEventHandler,
13
- type WaitForFunctionOptions,
14
- } from '@open-wa/driver-interface';
15
- import type { ConsoleMessage, Frame, HTTPRequest, Page, CDPSession } from 'puppeteer';
16
- import { PuppeteerElementHandle } from './PuppeteerElementHandle';
17
-
18
- type ListenerWrapper = (...args: any[]) => void | Promise<void>;
19
-
20
- class PuppeteerDisposableHandle implements DisposableHandle {
21
- constructor(private readonly disposer: () => Promise<void> | void) { }
22
-
23
- dispose(): Promise<void> | void {
24
- return this.disposer();
25
- }
26
- }
27
-
28
- class PuppeteerFrame implements IFrame {
29
- constructor(private readonly frame: Frame, private readonly isMain: boolean) { }
30
-
31
- url(): string {
32
- return this.frame.url();
33
- }
34
-
35
- name(): string {
36
- return this.frame.name();
37
- }
38
-
39
- isMainFrame(): boolean {
40
- return this.isMain;
41
- }
42
-
43
- parentFrame(): IFrame | null {
44
- const parent = this.frame.parentFrame();
45
- return parent ? new PuppeteerFrame(parent, false) : null;
46
- }
47
-
48
- async content(): Promise<string> {
49
- return this.frame.content();
50
- }
51
-
52
- unwrap(): Frame {
53
- return this.frame;
54
- }
55
- }
56
-
57
- function normalizeSnippet(input: string): string {
58
- return input.replace(/\s+/g, ' ').trim().slice(0, 160);
59
- }
60
-
61
- function enrichEvaluateError(kind: 'evaluate' | 'evaluateScript', source: string, error: unknown): never {
62
- const normalized = error instanceof Error ? error : new Error(String(error));
63
- const preview = normalizeSnippet(source);
64
- const enriched = new Error(
65
- `[puppeteer:${kind}] ${normalized.message} | scriptBytes=${source.length} | scriptPreview=${preview}`,
66
- );
67
- enriched.stack = normalized.stack ?? enriched.message;
68
- throw enriched;
69
- }
70
-
71
- function enrichWaitError(
72
- kind: 'waitForSelector' | 'waitForFunction' | 'waitForFunctionFn',
73
- details: Record<string, unknown>,
74
- error: unknown,
75
- ): never {
76
- const normalized = error instanceof Error ? error : new Error(String(error));
77
- const detailText = Object.entries(details)
78
- .filter(([, value]) => typeof value !== 'undefined')
79
- .map(([key, value]) => `${key}=${typeof value === 'string' ? value : JSON.stringify(value)}`)
80
- .join(' | ');
81
- const enriched = new Error(`[puppeteer:${kind}] ${normalized.message}${detailText ? ` | ${detailText}` : ''}`);
82
- enriched.stack = normalized.stack ?? enriched.message;
83
- throw enriched;
84
- }
85
-
86
- class PuppeteerRequest implements IRequest {
87
- constructor(private readonly request: HTTPRequest, private readonly page: Page) { }
88
-
89
- url(): string {
90
- return this.request.url();
91
- }
92
-
93
- method(): string {
94
- return this.request.method();
95
- }
96
-
97
- headers(): Record<string, string> {
98
- return this.request.headers();
99
- }
100
-
101
- resourceType(): string | null {
102
- return this.request.resourceType?.() ?? null;
103
- }
104
-
105
- isNavigationRequest(): boolean {
106
- return this.request.isNavigationRequest();
107
- }
108
-
109
- frame(): IFrame | null {
110
- const frame = this.request.frame();
111
- return frame ? new PuppeteerFrame(frame, frame === this.page.mainFrame()) : null;
112
- }
113
-
114
- async abort(errorCode?: string): Promise<void> {
115
- await this.request.abort(errorCode as never);
116
- }
117
-
118
- async continue(overrides?: IRequestContinueOverrides): Promise<void> {
119
- await this.request.continue(overrides);
120
- }
121
-
122
- async respond(response: IRequestResponse): Promise<void> {
123
- await this.request.respond({
124
- ...response,
125
- body: response.body instanceof Uint8Array ? Buffer.from(response.body) : response.body,
126
- } as never);
127
- }
128
-
129
- unwrap(): HTTPRequest {
130
- return this.request;
131
- }
132
- }
133
-
134
- class PuppeteerConsoleMessage implements IConsoleMessage {
135
- constructor(private readonly message: ConsoleMessage) { }
136
-
137
- type(): string {
138
- return this.message.type();
139
- }
140
-
141
- text(): string {
142
- return this.message.text();
143
- }
144
-
145
- location(): { url?: string; lineNumber?: number; columnNumber?: number } {
146
- const location = this.message.location();
147
- return {
148
- url: location.url,
149
- lineNumber: location.lineNumber,
150
- columnNumber: location.columnNumber,
151
- };
152
- }
153
-
154
- args(): unknown[] {
155
- return this.message.args();
156
- }
157
-
158
- unwrap(): ConsoleMessage {
159
- return this.message;
160
- }
161
- }
162
-
163
- export class PuppeteerPage implements IPage {
164
- readonly name = 'puppeteer' as const;
165
- private readonly listenerWrappers = new Map<string, Map<Function, Set<ListenerWrapper>>>();
166
-
167
- constructor(
168
- private page: Page,
169
- private capabilities: DriverCapabilities
170
- ) { }
171
-
172
- async goto(url: string, options?: { waitUntil?: NavigationWaitUntil; timeoutMs?: number }): Promise<void> {
173
- await this.page.goto(url, {
174
- waitUntil: options?.waitUntil as any,
175
- timeout: options?.timeoutMs,
176
- });
177
- }
178
-
179
- url(): string {
180
- return this.page.url();
181
- }
182
-
183
- async reload(): Promise<void> {
184
- await this.page.reload();
185
- }
186
-
187
- mainFrame(): IFrame {
188
- return new PuppeteerFrame(this.page.mainFrame(), true);
189
- }
190
-
191
- async evaluateOnNewDocument<Arg, Ret>(
192
- fn: (arg: Arg) => Ret | Promise<Ret>,
193
- arg: Arg
194
- ): Promise<void> {
195
- await this.page.evaluateOnNewDocument(fn as any, arg as any);
196
- }
197
-
198
- async evaluate<Arg, Ret>(fn: (arg: Arg) => Ret | Promise<Ret>, arg: Arg): Promise<Ret> {
199
- try {
200
- return await this.page.evaluate(fn as any, arg as any) as Ret;
201
- } catch (error) {
202
- const fnSource = typeof fn === 'function' ? fn.toString() : '[anonymous evaluate fn]';
203
- return enrichEvaluateError('evaluate', fnSource, error);
204
- }
205
- }
206
-
207
- async evaluateScript<Ret = unknown>(script: string): Promise<Ret> {
208
- try {
209
- return await this.page.evaluate(script) as Ret;
210
- } catch (error) {
211
- return enrichEvaluateError('evaluateScript', script, error);
212
- }
213
- }
214
-
215
- async addInitScript(script: string): Promise<DisposableHandle> {
216
- const registration = await (this.page as any).evaluateOnNewDocument(script);
217
- const identifier = this.getInitScriptIdentifier(registration);
218
- let disposed = false;
219
-
220
- return new PuppeteerDisposableHandle(async () => {
221
- if (disposed) {
222
- return;
223
- }
224
-
225
- disposed = true;
226
- if (identifier && typeof (this.page as any).removeScriptToEvaluateOnNewDocument === 'function') {
227
- await (this.page as any).removeScriptToEvaluateOnNewDocument(identifier);
228
- }
229
- });
230
- }
231
-
232
- async setViewport(viewport: { width: number; height: number }): Promise<void> {
233
- await this.page.setViewport(viewport);
234
- }
235
-
236
- async setUserAgent(ua: string): Promise<void> {
237
- await this.page.setUserAgent(ua);
238
- }
239
-
240
- async setRequestInterception(enabled: boolean): Promise<void> {
241
- this.require('requestInterception');
242
- await this.page.setRequestInterception(enabled);
243
- }
244
-
245
- async waitForSelector(selector: string, options?: { timeoutMs?: number }): Promise<IElementHandle | null> {
246
- try {
247
- const element = await this.page.waitForSelector(selector, { timeout: options?.timeoutMs });
248
- return element ? new PuppeteerElementHandle(element) : null;
249
- } catch (error) {
250
- return enrichWaitError('waitForSelector', {
251
- selector,
252
- timeoutMs: options?.timeoutMs,
253
- }, error);
254
- }
255
- }
256
-
257
- async waitForFunction<Arg>(script: string, options?: WaitForFunctionOptions): Promise<void>;
258
- async waitForFunction<Arg>(fn: (arg: Arg) => boolean, arg: Arg, options?: WaitForFunctionOptions): Promise<void>;
259
- async waitForFunction<Arg>(fnOrScript: string | ((arg: Arg) => boolean), argOrOptions?: Arg | WaitForFunctionOptions, maybeOptions?: WaitForFunctionOptions): Promise<void> {
260
- if (typeof fnOrScript === 'string') {
261
- const options = argOrOptions as WaitForFunctionOptions | undefined;
262
- try {
263
- await this.page.waitForFunction(fnOrScript, {
264
- timeout: options?.timeoutMs,
265
- polling: options?.polling as any,
266
- });
267
- return;
268
- } catch (error) {
269
- return enrichWaitError('waitForFunction', {
270
- timeoutMs: options?.timeoutMs,
271
- polling: options?.polling,
272
- scriptBytes: fnOrScript.length,
273
- scriptPreview: normalizeSnippet(fnOrScript),
274
- }, error);
275
- }
276
- }
277
-
278
- const options = maybeOptions;
279
- try {
280
- await this.page.waitForFunction(fnOrScript as any, {
281
- timeout: options?.timeoutMs,
282
- polling: options?.polling as any,
283
- }, argOrOptions as any);
284
- } catch (error) {
285
- return enrichWaitError('waitForFunctionFn', {
286
- timeoutMs: options?.timeoutMs,
287
- polling: options?.polling,
288
- fnPreview: normalizeSnippet(fnOrScript.toString()),
289
- argPreview: typeof argOrOptions === 'undefined' ? undefined : normalizeSnippet(JSON.stringify(argOrOptions)),
290
- }, error);
291
- }
292
- }
293
-
294
- async $(selector: string): Promise<IElementHandle | null> {
295
- const element = await this.page.$(selector);
296
- return element ? new PuppeteerElementHandle(element) : null;
297
- }
298
-
299
- async $$(selector: string): Promise<IElementHandle[]> {
300
- const elements = await this.page.$$(selector);
301
- return elements.map(el => new PuppeteerElementHandle(el));
302
- }
303
-
304
- async click(selector: string): Promise<void> {
305
- await this.page.click(selector);
306
- }
307
-
308
- async type(selector: string, text: string, options?: { delayMs?: number }): Promise<void> {
309
- await this.page.type(selector, text, { delay: options?.delayMs });
310
- }
311
-
312
- async screenshot(options?: { type?: 'png' | 'jpeg'; fullPage?: boolean }): Promise<Uint8Array> {
313
- const buffer = await this.page.screenshot(options);
314
- return new Uint8Array(buffer);
315
- }
316
-
317
- async exposeFunction(name: string, fn: (...args: any[]) => any): Promise<void> {
318
- await this.page.exposeFunction(name, fn);
319
- }
320
-
321
- on<K extends string>(event: K, handler: ((...args: any[]) => void | Promise<void>) | PageEventHandler<any>): DisposableHandle {
322
- const wrapped = (...args: any[]) => {
323
- const payload = this.wrapEventPayload(event, args);
324
- if (event === 'close') {
325
- return (handler as () => void | Promise<void>)();
326
- }
327
- return (handler as (payload: unknown) => void | Promise<void>)(payload);
328
- };
329
-
330
- this.getWrapperSet(event, handler as Function).add(wrapped);
331
- this.page.on(event as any, wrapped as any);
332
-
333
- return new PuppeteerDisposableHandle(() => {
334
- this.removeWrappedListener(event, handler as Function, wrapped);
335
- });
336
- }
337
-
338
- off<K extends string>(event: K, handler: ((...args: any[]) => void | Promise<void>) | PageEventHandler<any>): void {
339
- const wrappers = this.listenerWrappers.get(event)?.get(handler as Function);
340
- if (!wrappers || wrappers.size === 0) {
341
- this.page.off(event as any, handler as any);
342
- return;
343
- }
344
-
345
- for (const wrapped of wrappers) {
346
- this.page.off(event as any, wrapped as any);
347
- }
348
-
349
- this.listenerWrappers.get(event)?.delete(handler as Function);
350
- }
351
-
352
- async close(): Promise<void> {
353
- await this.page.close();
354
- }
355
-
356
- isClosed(): boolean {
357
- return this.page.isClosed();
358
- }
359
-
360
- has<C extends string>(cap: C): boolean {
361
- return (this.capabilities as any)[cap]?.supported === true;
362
- }
363
-
364
- require<C extends string>(cap: C): void {
365
- if (!this.has(cap)) {
366
- const capability = (this.capabilities as any)[cap];
367
- throw new Error(
368
- `Page does not support capability '${cap}'${capability?.reason ? `: ${capability.reason}` : ''
369
- }`
370
- );
371
- }
372
- }
373
-
374
- async cdp(): Promise<CDPSession> {
375
- this.require('cdp');
376
- return await this.page.createCDPSession();
377
- }
378
-
379
- async setBypassServiceWorker(bypass: boolean): Promise<void> {
380
- this.require('serviceWorkerBypass');
381
- await this.page.setBypassServiceWorker(bypass);
382
- }
383
-
384
- async pdf(options?: { path?: string; format?: string }): Promise<Uint8Array> {
385
- this.require('pdf');
386
- const buffer = await this.page.pdf(options as any);
387
- return new Uint8Array(buffer);
388
- }
389
-
390
- async startTracing(options?: { path?: string; screenshots?: boolean }): Promise<void> {
391
- this.require('tracing');
392
- await this.page.tracing.start(options);
393
- }
394
-
395
- async stopTracing(): Promise<Uint8Array> {
396
- this.require('tracing');
397
- const buffer = await this.page.tracing.stop();
398
- return buffer ? new Uint8Array(buffer) : new Uint8Array();
399
- }
400
-
401
- unwrap(): Page {
402
- return this.page;
403
- }
404
-
405
- private getWrapperSet(event: string, handler: Function): Set<ListenerWrapper> {
406
- let wrappers = this.listenerWrappers.get(event);
407
- if (!wrappers) {
408
- wrappers = new Map();
409
- this.listenerWrappers.set(event, wrappers);
410
- }
411
-
412
- let handlerWrappers = wrappers.get(handler);
413
- if (!handlerWrappers) {
414
- handlerWrappers = new Set();
415
- wrappers.set(handler, handlerWrappers);
416
- }
417
-
418
- return handlerWrappers;
419
- }
420
-
421
- private removeWrappedListener(event: string, handler: Function, wrapped: ListenerWrapper): void {
422
- this.page.off(event as any, wrapped as any);
423
-
424
- const eventWrappers = this.listenerWrappers.get(event);
425
- const handlerWrappers = eventWrappers?.get(handler);
426
- if (!handlerWrappers) {
427
- return;
428
- }
429
-
430
- handlerWrappers.delete(wrapped);
431
- if (handlerWrappers.size === 0) {
432
- eventWrappers?.delete(handler);
433
- }
434
- if (eventWrappers && eventWrappers.size === 0) {
435
- this.listenerWrappers.delete(event);
436
- }
437
- }
438
-
439
- private getInitScriptIdentifier(registration: unknown): string | undefined {
440
- if (typeof registration === 'string') {
441
- return registration;
442
- }
443
-
444
- if (registration && typeof registration === 'object') {
445
- const candidate = (registration as { identifier?: unknown; id?: unknown }).identifier
446
- ?? (registration as { identifier?: unknown; id?: unknown }).id;
447
- return typeof candidate === 'string' ? candidate : undefined;
448
- }
449
-
450
- return undefined;
451
- }
452
-
453
- private wrapEventPayload(event: string, args: any[]): unknown {
454
- const [payload] = args;
455
- switch (event) {
456
- case 'request':
457
- case 'requestfailed':
458
- case 'requestfinished':
459
- return new PuppeteerRequest(payload as HTTPRequest, this.page);
460
- case 'framenavigated':
461
- return new PuppeteerFrame(payload as Frame, payload === this.page.mainFrame());
462
- case 'console':
463
- return new PuppeteerConsoleMessage(payload as ConsoleMessage);
464
- case 'pageerror':
465
- return payload as Error;
466
- default:
467
- return payload;
468
- }
469
- }
470
- }
@@ -1,149 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { PuppeteerPage } from '../PuppeteerPage';
3
-
4
- type MockHandler = (...args: any[]) => void | Promise<void>;
5
-
6
- class MockPuppeteerPage {
7
- private readonly listeners = new Map<string, Set<MockHandler>>();
8
-
9
- readonly mainFrameValue = {
10
- url: () => 'https://example.test',
11
- name: () => 'main',
12
- parentFrame: () => null,
13
- content: vi.fn(async () => '<html></html>'),
14
- };
15
-
16
- readonly setViewport = vi.fn(async () => undefined);
17
- readonly setUserAgent = vi.fn(async () => undefined);
18
- readonly setRequestInterception = vi.fn(async () => undefined);
19
- readonly waitForSelector = vi.fn(async () => null);
20
- readonly waitForFunction = vi.fn(async () => undefined);
21
- readonly $ = vi.fn(async () => null);
22
- readonly $$ = vi.fn(async () => []);
23
- readonly click = vi.fn(async () => undefined);
24
- readonly type = vi.fn(async () => undefined);
25
- readonly screenshot = vi.fn(async () => Buffer.from([]));
26
- readonly exposeFunction = vi.fn(async () => undefined);
27
- readonly close = vi.fn(async () => undefined);
28
- readonly goto = vi.fn(async () => undefined);
29
- readonly reload = vi.fn(async () => undefined);
30
- readonly evaluate = vi.fn(async () => undefined);
31
- readonly url = vi.fn(() => 'about:blank');
32
- readonly isClosed = vi.fn(() => false);
33
- readonly evaluateOnNewDocument = vi.fn(async () => ({ identifier: 'init-script-1' }));
34
- readonly removeScriptToEvaluateOnNewDocument = vi.fn(async () => undefined);
35
-
36
- mainFrame() {
37
- return this.mainFrameValue;
38
- }
39
-
40
- on(event: string, handler: MockHandler): void {
41
- const handlers = this.listeners.get(event) ?? new Set<MockHandler>();
42
- handlers.add(handler);
43
- this.listeners.set(event, handlers);
44
- }
45
-
46
- off(event: string, handler: MockHandler): void {
47
- this.listeners.get(event)?.delete(handler);
48
- }
49
-
50
- async emit(event: string, payload?: unknown): Promise<void> {
51
- const handlers = [...(this.listeners.get(event) ?? [])];
52
- await Promise.all(handlers.map((handler) => Promise.resolve(handler(payload))));
53
- }
54
- }
55
-
56
- const capabilities = {
57
- cdp: { supported: true },
58
- requestInterception: { supported: true },
59
- serviceWorkerBypass: { supported: true },
60
- stealth: { supported: true },
61
- pdf: { supported: true },
62
- tracing: { supported: true },
63
- persistentContext: { supported: true },
64
- browserExtensions: { supported: true },
65
- exposeBinding: { supported: true },
66
- };
67
-
68
- describe('PuppeteerPage', () => {
69
- it('keeps duplicate listeners independently disposable', async () => {
70
- const rawPage = new MockPuppeteerPage();
71
- const page = new PuppeteerPage(rawPage as any, capabilities as any);
72
- const handler = vi.fn();
73
-
74
- const first = page.on('request', handler);
75
- const second = page.on('request', handler);
76
-
77
- const request = {
78
- url: () => 'https://example.test',
79
- method: () => 'GET',
80
- headers: () => ({ accept: 'application/json' }),
81
- resourceType: () => 'document',
82
- isNavigationRequest: () => true,
83
- frame: () => rawPage.mainFrameValue,
84
- abort: vi.fn(async () => undefined),
85
- continue: vi.fn(async () => undefined),
86
- respond: vi.fn(async () => undefined),
87
- };
88
-
89
- await rawPage.emit('request', request);
90
- expect(handler).toHaveBeenCalledTimes(2);
91
-
92
- await first.dispose();
93
- await rawPage.emit('request', request);
94
- expect(handler).toHaveBeenCalledTimes(3);
95
-
96
- await second.dispose();
97
- await rawPage.emit('request', request);
98
- expect(handler).toHaveBeenCalledTimes(3);
99
- });
100
-
101
- it('removes init scripts via returned identifiers and makes disposal idempotent', async () => {
102
- const rawPage = new MockPuppeteerPage();
103
- const page = new PuppeteerPage(rawPage as any, capabilities as any);
104
-
105
- const handle = await page.addInitScript('window.__OPENWA__ = true;');
106
-
107
- await handle.dispose();
108
- await handle.dispose();
109
-
110
- expect(rawPage.evaluateOnNewDocument).toHaveBeenCalledWith('window.__OPENWA__ = true;');
111
- expect(rawPage.removeScriptToEvaluateOnNewDocument).toHaveBeenCalledTimes(1);
112
- expect(rawPage.removeScriptToEvaluateOnNewDocument).toHaveBeenCalledWith('init-script-1');
113
- });
114
-
115
- it('wraps request payloads and normalizes Uint8Array response bodies', async () => {
116
- const rawPage = new MockPuppeteerPage();
117
- const page = new PuppeteerPage(rawPage as any, capabilities as any);
118
- const respond = vi.fn(async () => undefined);
119
- let wrappedRequest: any;
120
-
121
- page.on('request', (request: any) => {
122
- wrappedRequest = request;
123
- });
124
-
125
- await rawPage.emit('request', {
126
- url: () => 'https://example.test/api',
127
- method: () => 'POST',
128
- headers: () => ({ 'content-type': 'application/json' }),
129
- resourceType: () => 'xhr',
130
- isNavigationRequest: () => false,
131
- frame: () => rawPage.mainFrameValue,
132
- abort: vi.fn(async () => undefined),
133
- continue: vi.fn(async () => undefined),
134
- respond,
135
- });
136
-
137
- await wrappedRequest.respond({
138
- status: 200,
139
- body: new Uint8Array([1, 2, 3]),
140
- });
141
-
142
- expect(wrappedRequest.url()).toBe('https://example.test/api');
143
- expect(wrappedRequest.frame()?.isMainFrame()).toBe(true);
144
- expect(respond).toHaveBeenCalledWith({
145
- status: 200,
146
- body: Buffer.from([1, 2, 3]),
147
- });
148
- });
149
- });
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './PuppeteerDriver';
2
- export * from './PuppeteerBrowser';
3
- export * from './PuppeteerPage';
4
- export * from './PuppeteerElementHandle';
package/tsconfig.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src"
6
- },
7
- "include": [
8
- "src/**/*"
9
- ]
10
- }