@skrillex1224/playwright-toolkit 2.1.286 → 2.1.287

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.
@@ -32,6 +32,25 @@ const state = {
32
32
  : null,
33
33
  };
34
34
 
35
+ const formatFatalError = (error) => {
36
+ if (error instanceof Error) {
37
+ return error.stack || error.message || String(error);
38
+ }
39
+ try {
40
+ return JSON.stringify(error);
41
+ } catch {
42
+ return String(error);
43
+ }
44
+ };
45
+
46
+ const exitAfterFatal = (kind, error) => {
47
+ try {
48
+ console.error(`[proxy-meter] fatal ${kind}: ${formatFatalError(error)}`);
49
+ } catch {}
50
+ flushSnapshot();
51
+ process.exit(1);
52
+ };
53
+
35
54
  const getHostBucket = (host) => {
36
55
  if (!host) return null;
37
56
  if (!state.hosts[host]) {
@@ -60,6 +79,21 @@ const safeError = (error) => {
60
79
  return message.length > 240 ? message.slice(0, 240) : message;
61
80
  };
62
81
 
82
+ const sendBadGateway = (res, error = null) => {
83
+ if (!res || res.destroyed || res.writableEnded) return;
84
+
85
+ try {
86
+ if (!res.headersSent) {
87
+ res.writeHead(502);
88
+ res.end('Bad Gateway');
89
+ return;
90
+ }
91
+
92
+ // Headers are already committed; the only truthful error signal left is closing the stream.
93
+ res.destroy(error instanceof Error ? error : undefined);
94
+ } catch {}
95
+ };
96
+
63
97
  const statusLabel = (statusCode, error) => {
64
98
  const code = Number(statusCode) || 0;
65
99
  if (error || code <= 0) return 'ERR';
@@ -349,8 +383,7 @@ const forwardHttp = (req, res) => {
349
383
 
350
384
  if (!target) {
351
385
  tracker.close({ statusCode: 0, error: 'invalid_target_url' });
352
- res.writeHead(502);
353
- res.end('Bad Gateway');
386
+ sendBadGateway(res);
354
387
  return;
355
388
  }
356
389
 
@@ -381,7 +414,19 @@ const forwardHttp = (req, res) => {
381
414
  let responseStatus = 0;
382
415
  const proxyReq = http.request(requestOptions, (proxyRes) => {
383
416
  responseStatus = Number(proxyRes.statusCode) || 0;
384
- res.writeHead(responseStatus || 502, proxyRes.headers);
417
+ if (res.destroyed || res.writableEnded) {
418
+ tracker.close({ statusCode: responseStatus || 499, error: 'client_response_closed' });
419
+ proxyRes.resume();
420
+ return;
421
+ }
422
+ try {
423
+ res.writeHead(responseStatus || 502, proxyRes.headers);
424
+ } catch (error) {
425
+ tracker.close({ statusCode: responseStatus, error: safeError(error) });
426
+ proxyRes.resume();
427
+ sendBadGateway(res, error);
428
+ return;
429
+ }
385
430
  proxyRes.on('data', (chunk) => {
386
431
  const size = chunk?.length || 0;
387
432
  addTraffic(hostname, 'in', size);
@@ -412,8 +457,7 @@ const forwardHttp = (req, res) => {
412
457
 
413
458
  proxyReq.on('error', (error) => {
414
459
  tracker.close({ statusCode: responseStatus, error: safeError(error) });
415
- res.writeHead(502);
416
- res.end('Bad Gateway');
460
+ sendBadGateway(res, error);
417
461
  });
418
462
  };
419
463
 
@@ -545,5 +589,7 @@ const shutdown = () => {
545
589
  process.exit(0);
546
590
  };
547
591
 
592
+ process.on('uncaughtException', (error) => exitAfterFatal('uncaughtException', error));
593
+ process.on('unhandledRejection', (error) => exitAfterFatal('unhandledRejection', error));
548
594
  process.on('SIGINT', shutdown);
549
595
  process.on('SIGTERM', shutdown);
package/index.d.ts CHANGED
@@ -18,23 +18,14 @@ export interface StatusType {
18
18
  Failed: 'FAILED';
19
19
  }
20
20
 
21
- export interface ModeType {
22
- Default: 'default';
23
- CloakBrowser: 'cloakbrowser';
24
- }
25
-
26
- export type ToolkitMode = 'default' | 'cloakbrowser';
27
-
28
21
  export interface ConstantsModule {
29
22
  Code: CodeType;
30
23
  Status: StatusType;
31
- Mode: ModeType;
32
24
  PresetOfLiveViewKey: string;
33
25
  Device: {
34
26
  Desktop: 'desktop';
35
27
  Mobile: 'mobile';
36
28
  };
37
- normalizeMode(value?: unknown, fallback?: ToolkitMode): ToolkitMode;
38
29
  normalizeDevice(value?: unknown, fallback?: RuntimeDevice): RuntimeDevice;
39
30
  ActorInfo: Record<string, ActorInfoItem>;
40
31
  }
@@ -42,7 +33,7 @@ export interface ConstantsModule {
42
33
  export type RuntimeDevice = 'desktop' | 'mobile';
43
34
 
44
35
  export interface ActorShareInfo {
45
- mode: 'dom' | 'response' | 'custom';
36
+ mode: 'dom' | 'response';
46
37
  prefix: string;
47
38
  xurl: Array<string | string[]>;
48
39
  }
@@ -426,6 +417,10 @@ export interface CrawlerNavigationHook {
426
417
  (crawlingContext: any, gotoOptions: Record<string, any>): Promise<void> | void;
427
418
  }
428
419
 
420
+ export interface LaunchHooks {
421
+ modifyPageOptions?: (pageOptions: Record<string, any>, context: { pageId: string; browserController: any }) => Promise<void> | void;
422
+ }
423
+
429
424
  export interface GetPlaywrightCrawlerOptionsInput {
430
425
  customArgs?: string[];
431
426
  proxyConfiguration?: ProxyConfiguration;
@@ -437,6 +432,7 @@ export interface GetPlaywrightCrawlerOptionsInput {
437
432
  isRunningOnApify?: boolean;
438
433
  launcher?: any;
439
434
  runtimeState?: RuntimeEnvState | null;
435
+ hooks?: LaunchHooks;
440
436
  preNavigationHooks?: CrawlerNavigationHook[];
441
437
  postNavigationHooks?: CrawlerNavigationHook[];
442
438
  }
@@ -450,47 +446,6 @@ export interface LaunchModule {
450
446
  getPlaywrightCrawlerOptions(options?: GetPlaywrightCrawlerOptionsInput): PlaywrightCrawlerOptions;
451
447
  }
452
448
 
453
- export interface CloakBrowserResolvedProxy {
454
- server: string;
455
- username?: string;
456
- password?: string;
457
- bypass?: string;
458
- }
459
-
460
- export interface CreateCloakBrowserCrawlerRuntimeInput {
461
- proxyConfiguration?: ProxyConfiguration;
462
- runInHeadfulMode?: boolean;
463
- isRunningOnApify?: boolean;
464
- launcher?: any;
465
- cloakOptions?: Record<string, any>;
466
- humanizeOptions?: boolean | Record<string, any>;
467
- crawlerBaseOptions?: Partial<CrawlerBaseOptions>;
468
- browserPoolOptions?: Record<string, any>;
469
- launchContext?: Record<string, any>;
470
- preNavigationHooks?: CrawlerNavigationHook[];
471
- postNavigationHooks?: CrawlerNavigationHook[];
472
- recommendedGotoOptions?: Record<string, any>;
473
- }
474
-
475
- export interface CloakBrowserCrawlerRuntime {
476
- headless: boolean;
477
- launchOptions: LaunchOptions;
478
- fingerprintArg: string;
479
- crawlerOptions: PlaywrightCrawlerOptions;
480
- closeActiveBrowsers(): Promise<void>;
481
- forceTerminateActiveProcesses(): Promise<void>;
482
- cleanup(): Promise<void>;
483
- }
484
-
485
- export interface CloakLaunchModule extends Omit<LaunchModule, 'getPlaywrightCrawlerOptions'> {
486
- getPlaywrightCrawlerOptions(options?: GetPlaywrightCrawlerOptionsInput | CreateCloakBrowserCrawlerRuntimeInput): Promise<PlaywrightCrawlerOptions>;
487
- resolveProxyConfiguration(proxyConfiguration?: ProxyConfiguration): string | CloakBrowserResolvedProxy | null;
488
- extractFingerprintArg(launchOptions?: LaunchOptions): string;
489
- createStableGotoHook(recommendedGotoOptions?: Record<string, any>): CrawlerNavigationHook;
490
- buildLaunchOptions(options?: Record<string, any>): Promise<LaunchOptions>;
491
- createPlaywrightCrawlerRuntime(options?: CreateCloakBrowserCrawlerRuntimeInput): Promise<CloakBrowserCrawlerRuntime>;
492
- }
493
-
494
449
  // =============================================================================
495
450
  // LiveView
496
451
  // =============================================================================
@@ -704,8 +659,6 @@ export interface ShareScreenCaptureOptions {
704
659
  restore?: boolean;
705
660
  /** 最大截图高度 (默认: 8000px) */
706
661
  maxHeight?: number;
707
- /** 截图水印合成模式;`cloakbrowser` 时走兼容分支。 */
708
- mode?: 'default' | 'cloakbrowser';
709
662
  /** 返回 base64 字符串的最大字节数,默认 5MiB。 */
710
663
  maxBytes?: number;
711
664
  /** maxBytes 的别名。 */
@@ -892,10 +845,6 @@ export interface PlaywrightToolKit {
892
845
  };
893
846
  }
894
847
 
895
- export interface CloakPlaywrightToolKit extends PlaywrightToolKit {
896
- Launch: CloakLaunchModule;
897
- }
898
-
899
848
  /** Browser/Extension version of the toolkit */
900
849
  export interface BrowserPlaywrightToolKit {
901
850
  Logger: LoggerModule;
@@ -910,5 +859,3 @@ export interface BrowserPlaywrightToolKit {
910
859
  }
911
860
 
912
861
  export declare function usePlaywrightToolKit(): PlaywrightToolKit;
913
- export declare function usePlaywrightToolKit(mode: 'default'): PlaywrightToolKit;
914
- export declare function usePlaywrightToolKit(mode: 'cloakbrowser'): CloakPlaywrightToolKit;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skrillex1224/playwright-toolkit",
3
- "version": "2.1.286",
3
+ "version": "2.1.287",
4
4
  "description": "一个在 Apify/Crawlee Actor 中启用实时截图视图的实用工具库。",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -59,16 +59,10 @@
59
59
  },
60
60
  "peerDependencies": {
61
61
  "apify": "*",
62
- "cloakbrowser": "*",
63
62
  "crawlee": "*",
64
63
  "ghost-cursor-playwright": "*",
65
64
  "playwright": "*"
66
65
  },
67
- "peerDependenciesMeta": {
68
- "cloakbrowser": {
69
- "optional": true
70
- }
71
- },
72
66
  "devDependencies": {
73
67
  "esbuild": "^0.24.2"
74
68
  }