@iflyrpa/playwright 1.0.10 → 1.0.11

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/index.cjs CHANGED
@@ -1,22 +1,22 @@
1
1
  'use strict';
2
2
 
3
- const path = require('node:path');
4
3
  const fs = require('node:fs');
4
+ const path = require('node:path');
5
5
  const https = require('node:https');
6
6
  const log = require('loglevel');
7
- const node_child_process = require('node:child_process');
7
+ const npminstall = require('npminstall');
8
8
 
9
9
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
10
10
 
11
- const path__default = /*#__PURE__*/_interopDefaultCompat(path);
12
11
  const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
12
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
13
13
  const https__default = /*#__PURE__*/_interopDefaultCompat(https);
14
14
  const log__default = /*#__PURE__*/_interopDefaultCompat(log);
15
+ const npminstall__default = /*#__PURE__*/_interopDefaultCompat(npminstall);
15
16
 
16
17
  const name = "@iflyrpa/playwright";
17
18
  const type = "module";
18
- const version$1 = "1.0.10";
19
- const description = "";
19
+ const version$1 = "1.0.11";
20
20
  const main = "./dist/index.cjs";
21
21
  const module$1 = "./dist/index.mjs";
22
22
  const types = "./dist/index.d.ts";
@@ -25,8 +25,6 @@ const scripts = {
25
25
  dev: "unbuild --stub",
26
26
  start: "esno src/index.ts"
27
27
  };
28
- const keywords = [
29
- ];
30
28
  const author = "bijinfeng";
31
29
  const license = "ISC";
32
30
  const files = [
@@ -34,6 +32,7 @@ const files = [
34
32
  ];
35
33
  const dependencies = {
36
34
  loglevel: "^1.9.2",
35
+ npminstall: "^7.12.0",
37
36
  playwright: "^1.46.1"
38
37
  };
39
38
  const peerDependencies = {
@@ -48,12 +47,10 @@ const packageJson = {
48
47
  name: name,
49
48
  type: type,
50
49
  version: version$1,
51
- description: description,
52
50
  main: main,
53
51
  module: module$1,
54
52
  types: types,
55
53
  scripts: scripts,
56
- keywords: keywords,
57
54
  author: author,
58
55
  license: license,
59
56
  files: files,
@@ -221,7 +218,7 @@ const visibleRangeTexts = {
221
218
  private: "\u79C1\u5BC6"
222
219
  };
223
220
  const xiaohongshuPublishAction = async (props) => {
224
- const { page, cachePath, params } = props;
221
+ const { page, tmpCachePath, params } = props;
225
222
  const selectAddress = async (selector, address) => {
226
223
  const instance = typeof selector === "string" ? page.locator(selector) : selector;
227
224
  await instance.click();
@@ -244,11 +241,13 @@ const xiaohongshuPublishAction = async (props) => {
244
241
  await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
245
242
  throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
246
243
  });
247
- await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click();
244
+ await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
245
+ throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
246
+ });
248
247
  const images = await Promise.all(
249
248
  params.banners.map((url) => {
250
249
  const fileName = getFilenameFromUrl(url);
251
- return downloadImage(url, path__default.join(cachePath, "image-tmp", fileName));
250
+ return downloadImage(url, path__default.join(tmpCachePath, fileName));
252
251
  })
253
252
  );
254
253
  const fileChooserPromise = page.waitForEvent("filechooser");
@@ -383,12 +382,11 @@ const _Logger = class _Logger {
383
382
  log__default.warn(...msg);
384
383
  }
385
384
  error(prefix, error) {
386
- let errorMessage = error;
385
+ log__default.error(prefix);
387
386
  if (error instanceof Error) {
388
- errorMessage = `${error.message}
389
- Error stack: ${error.stack}`;
387
+ log__default.error(`${error.message}
388
+ Error stack: ${error.stack}`);
390
389
  }
391
- log__default.error(prefix, errorMessage);
392
390
  }
393
391
  close() {
394
392
  this.stream.end();
@@ -413,7 +411,7 @@ const generateFile = async (dir) => {
413
411
  }
414
412
  return filePath;
415
413
  };
416
- const createElectronApp = async (cachePath, playwrightPackage) => {
414
+ const createElectronApp = async (cachePath, playwright) => {
417
415
  const logger = Logger.getInstance(cachePath);
418
416
  try {
419
417
  const executablePath = path__default.join(
@@ -422,7 +420,6 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
422
420
  ".bin",
423
421
  "electron"
424
422
  );
425
- const playwright = await playwrightPackage;
426
423
  const mainPath = await generateFile(cachePath);
427
424
  const electronApp = await playwright._electron.launch({
428
425
  executablePath,
@@ -434,6 +431,7 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
434
431
  return electronApp;
435
432
  } catch (error) {
436
433
  logger.error("electron \u542F\u52A8\u5931\u8D25\uFF1A", error);
434
+ throw error;
437
435
  }
438
436
  };
439
437
 
@@ -443,6 +441,7 @@ var __publicField$1 = (obj, key, value) => {
443
441
  __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
444
442
  return value;
445
443
  };
444
+ const NPM_REGISTRY = "https://registry.npmmirror.com/";
446
445
  class PackageManager {
447
446
  constructor(params) {
448
447
  __publicField$1(this, "cacheDir");
@@ -457,37 +456,6 @@ class PackageManager {
457
456
  this.initCacheProject();
458
457
  this.initPromise = this.init(params.packageName, params.packageVersion);
459
458
  }
460
- // 在子线程执行 npm 命令
461
- execCommand(cmd, modules, where = this.cacheDir) {
462
- return new Promise((resolve) => {
463
- const args = [cmd].concat(modules).concat("--color=always").concat("--save");
464
- try {
465
- const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
466
- const npm = node_child_process.spawn(npmCmd, args, { cwd: where });
467
- let output = "";
468
- npm.stdout?.on("data", (data) => {
469
- output += data;
470
- }).pipe(process.stdout);
471
- npm.stderr?.on("data", (data) => {
472
- output += data;
473
- }).pipe(process.stderr);
474
- npm.on("close", (code) => {
475
- if (!code) {
476
- resolve({ code: 0, data: output });
477
- } else {
478
- resolve({ code, data: output });
479
- }
480
- });
481
- npm.on("error", (err) => {
482
- console.error("NPM is not installed");
483
- console.error(err);
484
- });
485
- } catch (error) {
486
- this.logger.error(`npm ${args.join(" ")}: `, error);
487
- console.error(error);
488
- }
489
- });
490
- }
491
459
  // 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
492
460
  initCacheProject() {
493
461
  const packagePath = path__default.join(this.cacheDir, "package.json");
@@ -527,27 +495,30 @@ class PackageManager {
527
495
  }
528
496
  // 安装依赖
529
497
  install(module, version) {
530
- const moduleName = version ? `${module}@${version}` : module;
531
- return this.execCommand("install", [moduleName, "--save"]);
532
- }
533
- // 更新依赖
534
- update(module) {
535
- return this.execCommand("update", [module]);
498
+ return npminstall__default({
499
+ root: this.cacheDir,
500
+ pkgs: [{ name: module, version }],
501
+ registry: NPM_REGISTRY
502
+ });
536
503
  }
537
504
  async init(name, version) {
538
505
  const plugin = this.getPlugin(path__default.join(name, "package.json"));
539
- if (!plugin) {
540
- await this.install(name, version);
541
- } else if (this.forceUpdate) {
542
- const pkInfo = await this.getPluginInfo(name);
543
- if (!pkInfo)
544
- return;
545
- const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
546
- if (hasNewVersion) {
547
- await this.install(name, pkInfo.version);
506
+ try {
507
+ if (!plugin) {
508
+ await this.install(name, version);
509
+ } else if (this.forceUpdate) {
510
+ const pkInfo = await this.getPluginInfo(name);
511
+ if (!pkInfo)
512
+ return;
513
+ const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
514
+ if (hasNewVersion) {
515
+ await this.install(name, pkInfo.version);
516
+ }
548
517
  }
518
+ this.logger.info(`${name} package manager init done!`);
519
+ } catch (error) {
520
+ this.logger.error(`${name} package manager init error`, error);
549
521
  }
550
- this.logger.info(`${name} package manager init done!`);
551
522
  }
552
523
  }
553
524
 
@@ -558,17 +529,20 @@ var __publicField = (obj, key, value) => {
558
529
  return value;
559
530
  };
560
531
  const PLAYWRIGHT_VERSION = "1.46.1";
532
+ const ELECTRON_VERSION = "22.3.27";
561
533
  class LocalAutomateTask {
562
534
  constructor({ cachePath, debug }) {
535
+ __publicField(this, "logger");
563
536
  __publicField(this, "cachePath");
564
537
  __publicField(this, "debug");
565
538
  __publicField(this, "playwrightPackage");
566
- __publicField(this, "logger");
539
+ __publicField(this, "electronPackage");
567
540
  __publicField(this, "_electronApp", null);
568
541
  this.cachePath = cachePath;
569
542
  this.debug = debug || false;
570
543
  this.logger = Logger.getInstance(cachePath);
571
544
  this.playwrightPackage = this.installPlaywright();
545
+ this.electronPackage = this.installElectron();
572
546
  }
573
547
  /**
574
548
  * 安装 playwright
@@ -582,25 +556,59 @@ class LocalAutomateTask {
582
556
  });
583
557
  return playwrightPackageManager.getPluginAfterInit("playwright");
584
558
  }
559
+ /**
560
+ * 安装 electron
561
+ * @returns
562
+ */
563
+ installElectron() {
564
+ const playwrightPackageManager = new PackageManager({
565
+ packageName: "electron",
566
+ packageVersion: ELECTRON_VERSION,
567
+ cacheDir: this.cachePath
568
+ });
569
+ return playwrightPackageManager.getPluginAfterInit("electron");
570
+ }
585
571
  /**
586
572
  * 启动 Electron
587
573
  * @returns
588
574
  */
589
575
  async getElectronApp() {
590
576
  if (!this._electronApp) {
591
- this._electronApp = await createElectronApp(
592
- this.cachePath,
593
- this.playwrightPackage
594
- );
577
+ const [playwright] = await Promise.all([
578
+ this.playwrightPackage,
579
+ this.electronPackage
580
+ ]);
581
+ this._electronApp = await createElectronApp(this.cachePath, playwright);
595
582
  }
596
583
  return this._electronApp;
597
584
  }
585
+ /**
586
+ * 临时文件目录
587
+ * @returns
588
+ */
589
+ getTmpPath() {
590
+ return path__default.join(this.cachePath, "tmp");
591
+ }
592
+ /**
593
+ * 清空临时文件
594
+ */
595
+ clearTmpPath() {
596
+ const tmpPath = this.getTmpPath();
597
+ return fs__default.rm(tmpPath, { recursive: true, force: true }, (err) => {
598
+ if (err) {
599
+ this.logger.error("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u5931\u8D25\uFF0C", err);
600
+ } else {
601
+ this.logger.info("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u6210\u529F");
602
+ }
603
+ });
604
+ }
598
605
  /**
599
606
  * 关闭 playwright 启动的 electron 客户端
600
607
  * @returns
601
608
  */
602
609
  async close() {
603
610
  this.logger.close();
611
+ this.clearTmpPath();
604
612
  const electronApp = await this.getElectronApp();
605
613
  return electronApp.close();
606
614
  }
@@ -652,13 +660,13 @@ class LocalAutomateTask {
652
660
  const res = await xiaohongshuPublishAction({
653
661
  page,
654
662
  params,
655
- cachePath: this.cachePath,
663
+ tmpCachePath: this.getTmpPath(),
656
664
  debug: !!this.debug
657
665
  });
658
666
  return res;
659
667
  } catch (error) {
660
668
  this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
661
- return error;
669
+ throw error;
662
670
  }
663
671
  }
664
672
  }
package/dist/index.d.cts CHANGED
@@ -1,17 +1,5 @@
1
1
  import { CookiesSetDetails } from 'electron';
2
2
 
3
- declare class Logger {
4
- static instance: Logger | null;
5
- private stream;
6
- constructor(cachePath: string);
7
- static getInstance(cachePath: string): Logger;
8
- debug(...msg: any[]): void;
9
- info(...msg: any[]): void;
10
- warn(...msg: any[]): void;
11
- error(prefix: string, error: unknown): void;
12
- close(): void;
13
- }
14
-
15
3
  type CookieMap = CookiesSetDetails[];
16
4
 
17
5
  interface FictionalRendition {
@@ -55,10 +43,11 @@ interface TaskParams {
55
43
  cachePath: string;
56
44
  }
57
45
  declare class LocalAutomateTask implements TaskParams {
46
+ private logger;
58
47
  cachePath: string;
59
48
  debug: boolean;
60
- playwrightPackage: Promise<unknown>;
61
- logger: Logger;
49
+ private playwrightPackage;
50
+ private electronPackage;
62
51
  private _electronApp;
63
52
  constructor({ cachePath, debug }: TaskParams);
64
53
  /**
@@ -66,11 +55,25 @@ declare class LocalAutomateTask implements TaskParams {
66
55
  * @returns
67
56
  */
68
57
  private installPlaywright;
58
+ /**
59
+ * 安装 electron
60
+ * @returns
61
+ */
62
+ private installElectron;
69
63
  /**
70
64
  * 启动 Electron
71
65
  * @returns
72
66
  */
73
67
  private getElectronApp;
68
+ /**
69
+ * 临时文件目录
70
+ * @returns
71
+ */
72
+ private getTmpPath;
73
+ /**
74
+ * 清空临时文件
75
+ */
76
+ private clearTmpPath;
74
77
  /**
75
78
  * 关闭 playwright 启动的 electron 客户端
76
79
  * @returns
@@ -79,7 +82,7 @@ declare class LocalAutomateTask implements TaskParams {
79
82
  /**
80
83
  * 小红书自动化发布
81
84
  */
82
- xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<unknown>;
85
+ xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<string>;
83
86
  }
84
87
  declare const RpaTask: (params: TaskParams) => LocalAutomateTask;
85
88
 
package/dist/index.d.mts CHANGED
@@ -1,17 +1,5 @@
1
1
  import { CookiesSetDetails } from 'electron';
2
2
 
3
- declare class Logger {
4
- static instance: Logger | null;
5
- private stream;
6
- constructor(cachePath: string);
7
- static getInstance(cachePath: string): Logger;
8
- debug(...msg: any[]): void;
9
- info(...msg: any[]): void;
10
- warn(...msg: any[]): void;
11
- error(prefix: string, error: unknown): void;
12
- close(): void;
13
- }
14
-
15
3
  type CookieMap = CookiesSetDetails[];
16
4
 
17
5
  interface FictionalRendition {
@@ -55,10 +43,11 @@ interface TaskParams {
55
43
  cachePath: string;
56
44
  }
57
45
  declare class LocalAutomateTask implements TaskParams {
46
+ private logger;
58
47
  cachePath: string;
59
48
  debug: boolean;
60
- playwrightPackage: Promise<unknown>;
61
- logger: Logger;
49
+ private playwrightPackage;
50
+ private electronPackage;
62
51
  private _electronApp;
63
52
  constructor({ cachePath, debug }: TaskParams);
64
53
  /**
@@ -66,11 +55,25 @@ declare class LocalAutomateTask implements TaskParams {
66
55
  * @returns
67
56
  */
68
57
  private installPlaywright;
58
+ /**
59
+ * 安装 electron
60
+ * @returns
61
+ */
62
+ private installElectron;
69
63
  /**
70
64
  * 启动 Electron
71
65
  * @returns
72
66
  */
73
67
  private getElectronApp;
68
+ /**
69
+ * 临时文件目录
70
+ * @returns
71
+ */
72
+ private getTmpPath;
73
+ /**
74
+ * 清空临时文件
75
+ */
76
+ private clearTmpPath;
74
77
  /**
75
78
  * 关闭 playwright 启动的 electron 客户端
76
79
  * @returns
@@ -79,7 +82,7 @@ declare class LocalAutomateTask implements TaskParams {
79
82
  /**
80
83
  * 小红书自动化发布
81
84
  */
82
- xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<unknown>;
85
+ xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<string>;
83
86
  }
84
87
  declare const RpaTask: (params: TaskParams) => LocalAutomateTask;
85
88
 
package/dist/index.d.ts CHANGED
@@ -1,17 +1,5 @@
1
1
  import { CookiesSetDetails } from 'electron';
2
2
 
3
- declare class Logger {
4
- static instance: Logger | null;
5
- private stream;
6
- constructor(cachePath: string);
7
- static getInstance(cachePath: string): Logger;
8
- debug(...msg: any[]): void;
9
- info(...msg: any[]): void;
10
- warn(...msg: any[]): void;
11
- error(prefix: string, error: unknown): void;
12
- close(): void;
13
- }
14
-
15
3
  type CookieMap = CookiesSetDetails[];
16
4
 
17
5
  interface FictionalRendition {
@@ -55,10 +43,11 @@ interface TaskParams {
55
43
  cachePath: string;
56
44
  }
57
45
  declare class LocalAutomateTask implements TaskParams {
46
+ private logger;
58
47
  cachePath: string;
59
48
  debug: boolean;
60
- playwrightPackage: Promise<unknown>;
61
- logger: Logger;
49
+ private playwrightPackage;
50
+ private electronPackage;
62
51
  private _electronApp;
63
52
  constructor({ cachePath, debug }: TaskParams);
64
53
  /**
@@ -66,11 +55,25 @@ declare class LocalAutomateTask implements TaskParams {
66
55
  * @returns
67
56
  */
68
57
  private installPlaywright;
58
+ /**
59
+ * 安装 electron
60
+ * @returns
61
+ */
62
+ private installElectron;
69
63
  /**
70
64
  * 启动 Electron
71
65
  * @returns
72
66
  */
73
67
  private getElectronApp;
68
+ /**
69
+ * 临时文件目录
70
+ * @returns
71
+ */
72
+ private getTmpPath;
73
+ /**
74
+ * 清空临时文件
75
+ */
76
+ private clearTmpPath;
74
77
  /**
75
78
  * 关闭 playwright 启动的 electron 客户端
76
79
  * @returns
@@ -79,7 +82,7 @@ declare class LocalAutomateTask implements TaskParams {
79
82
  /**
80
83
  * 小红书自动化发布
81
84
  */
82
- xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<unknown>;
85
+ xiaohongshuPublish(params: XiaohonshuPublishParams): Promise<string>;
83
86
  }
84
87
  declare const RpaTask: (params: TaskParams) => LocalAutomateTask;
85
88
 
package/dist/index.mjs CHANGED
@@ -1,13 +1,12 @@
1
- import path from 'node:path';
2
1
  import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import https from 'node:https';
4
4
  import log from 'loglevel';
5
- import { spawn } from 'node:child_process';
5
+ import npminstall from 'npminstall';
6
6
 
7
7
  const name = "@iflyrpa/playwright";
8
8
  const type = "module";
9
- const version$1 = "1.0.10";
10
- const description = "";
9
+ const version$1 = "1.0.11";
11
10
  const main = "./dist/index.cjs";
12
11
  const module = "./dist/index.mjs";
13
12
  const types = "./dist/index.d.ts";
@@ -16,8 +15,6 @@ const scripts = {
16
15
  dev: "unbuild --stub",
17
16
  start: "esno src/index.ts"
18
17
  };
19
- const keywords = [
20
- ];
21
18
  const author = "bijinfeng";
22
19
  const license = "ISC";
23
20
  const files = [
@@ -25,6 +22,7 @@ const files = [
25
22
  ];
26
23
  const dependencies = {
27
24
  loglevel: "^1.9.2",
25
+ npminstall: "^7.12.0",
28
26
  playwright: "^1.46.1"
29
27
  };
30
28
  const peerDependencies = {
@@ -39,12 +37,10 @@ const packageJson = {
39
37
  name: name,
40
38
  type: type,
41
39
  version: version$1,
42
- description: description,
43
40
  main: main,
44
41
  module: module,
45
42
  types: types,
46
43
  scripts: scripts,
47
- keywords: keywords,
48
44
  author: author,
49
45
  license: license,
50
46
  files: files,
@@ -212,7 +208,7 @@ const visibleRangeTexts = {
212
208
  private: "\u79C1\u5BC6"
213
209
  };
214
210
  const xiaohongshuPublishAction = async (props) => {
215
- const { page, cachePath, params } = props;
211
+ const { page, tmpCachePath, params } = props;
216
212
  const selectAddress = async (selector, address) => {
217
213
  const instance = typeof selector === "string" ? page.locator(selector) : selector;
218
214
  await instance.click();
@@ -235,11 +231,13 @@ const xiaohongshuPublishAction = async (props) => {
235
231
  await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
236
232
  throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
237
233
  });
238
- await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click();
234
+ await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
235
+ throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
236
+ });
239
237
  const images = await Promise.all(
240
238
  params.banners.map((url) => {
241
239
  const fileName = getFilenameFromUrl(url);
242
- return downloadImage(url, path.join(cachePath, "image-tmp", fileName));
240
+ return downloadImage(url, path.join(tmpCachePath, fileName));
243
241
  })
244
242
  );
245
243
  const fileChooserPromise = page.waitForEvent("filechooser");
@@ -374,12 +372,11 @@ const _Logger = class _Logger {
374
372
  log.warn(...msg);
375
373
  }
376
374
  error(prefix, error) {
377
- let errorMessage = error;
375
+ log.error(prefix);
378
376
  if (error instanceof Error) {
379
- errorMessage = `${error.message}
380
- Error stack: ${error.stack}`;
377
+ log.error(`${error.message}
378
+ Error stack: ${error.stack}`);
381
379
  }
382
- log.error(prefix, errorMessage);
383
380
  }
384
381
  close() {
385
382
  this.stream.end();
@@ -404,7 +401,7 @@ const generateFile = async (dir) => {
404
401
  }
405
402
  return filePath;
406
403
  };
407
- const createElectronApp = async (cachePath, playwrightPackage) => {
404
+ const createElectronApp = async (cachePath, playwright) => {
408
405
  const logger = Logger.getInstance(cachePath);
409
406
  try {
410
407
  const executablePath = path.join(
@@ -413,7 +410,6 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
413
410
  ".bin",
414
411
  "electron"
415
412
  );
416
- const playwright = await playwrightPackage;
417
413
  const mainPath = await generateFile(cachePath);
418
414
  const electronApp = await playwright._electron.launch({
419
415
  executablePath,
@@ -425,6 +421,7 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
425
421
  return electronApp;
426
422
  } catch (error) {
427
423
  logger.error("electron \u542F\u52A8\u5931\u8D25\uFF1A", error);
424
+ throw error;
428
425
  }
429
426
  };
430
427
 
@@ -434,6 +431,7 @@ var __publicField$1 = (obj, key, value) => {
434
431
  __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
435
432
  return value;
436
433
  };
434
+ const NPM_REGISTRY = "https://registry.npmmirror.com/";
437
435
  class PackageManager {
438
436
  constructor(params) {
439
437
  __publicField$1(this, "cacheDir");
@@ -448,37 +446,6 @@ class PackageManager {
448
446
  this.initCacheProject();
449
447
  this.initPromise = this.init(params.packageName, params.packageVersion);
450
448
  }
451
- // 在子线程执行 npm 命令
452
- execCommand(cmd, modules, where = this.cacheDir) {
453
- return new Promise((resolve) => {
454
- const args = [cmd].concat(modules).concat("--color=always").concat("--save");
455
- try {
456
- const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
457
- const npm = spawn(npmCmd, args, { cwd: where });
458
- let output = "";
459
- npm.stdout?.on("data", (data) => {
460
- output += data;
461
- }).pipe(process.stdout);
462
- npm.stderr?.on("data", (data) => {
463
- output += data;
464
- }).pipe(process.stderr);
465
- npm.on("close", (code) => {
466
- if (!code) {
467
- resolve({ code: 0, data: output });
468
- } else {
469
- resolve({ code, data: output });
470
- }
471
- });
472
- npm.on("error", (err) => {
473
- console.error("NPM is not installed");
474
- console.error(err);
475
- });
476
- } catch (error) {
477
- this.logger.error(`npm ${args.join(" ")}: `, error);
478
- console.error(error);
479
- }
480
- });
481
- }
482
449
  // 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
483
450
  initCacheProject() {
484
451
  const packagePath = path.join(this.cacheDir, "package.json");
@@ -518,27 +485,30 @@ class PackageManager {
518
485
  }
519
486
  // 安装依赖
520
487
  install(module, version) {
521
- const moduleName = version ? `${module}@${version}` : module;
522
- return this.execCommand("install", [moduleName, "--save"]);
523
- }
524
- // 更新依赖
525
- update(module) {
526
- return this.execCommand("update", [module]);
488
+ return npminstall({
489
+ root: this.cacheDir,
490
+ pkgs: [{ name: module, version }],
491
+ registry: NPM_REGISTRY
492
+ });
527
493
  }
528
494
  async init(name, version) {
529
495
  const plugin = this.getPlugin(path.join(name, "package.json"));
530
- if (!plugin) {
531
- await this.install(name, version);
532
- } else if (this.forceUpdate) {
533
- const pkInfo = await this.getPluginInfo(name);
534
- if (!pkInfo)
535
- return;
536
- const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
537
- if (hasNewVersion) {
538
- await this.install(name, pkInfo.version);
496
+ try {
497
+ if (!plugin) {
498
+ await this.install(name, version);
499
+ } else if (this.forceUpdate) {
500
+ const pkInfo = await this.getPluginInfo(name);
501
+ if (!pkInfo)
502
+ return;
503
+ const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
504
+ if (hasNewVersion) {
505
+ await this.install(name, pkInfo.version);
506
+ }
539
507
  }
508
+ this.logger.info(`${name} package manager init done!`);
509
+ } catch (error) {
510
+ this.logger.error(`${name} package manager init error`, error);
540
511
  }
541
- this.logger.info(`${name} package manager init done!`);
542
512
  }
543
513
  }
544
514
 
@@ -549,17 +519,20 @@ var __publicField = (obj, key, value) => {
549
519
  return value;
550
520
  };
551
521
  const PLAYWRIGHT_VERSION = "1.46.1";
522
+ const ELECTRON_VERSION = "22.3.27";
552
523
  class LocalAutomateTask {
553
524
  constructor({ cachePath, debug }) {
525
+ __publicField(this, "logger");
554
526
  __publicField(this, "cachePath");
555
527
  __publicField(this, "debug");
556
528
  __publicField(this, "playwrightPackage");
557
- __publicField(this, "logger");
529
+ __publicField(this, "electronPackage");
558
530
  __publicField(this, "_electronApp", null);
559
531
  this.cachePath = cachePath;
560
532
  this.debug = debug || false;
561
533
  this.logger = Logger.getInstance(cachePath);
562
534
  this.playwrightPackage = this.installPlaywright();
535
+ this.electronPackage = this.installElectron();
563
536
  }
564
537
  /**
565
538
  * 安装 playwright
@@ -573,25 +546,59 @@ class LocalAutomateTask {
573
546
  });
574
547
  return playwrightPackageManager.getPluginAfterInit("playwright");
575
548
  }
549
+ /**
550
+ * 安装 electron
551
+ * @returns
552
+ */
553
+ installElectron() {
554
+ const playwrightPackageManager = new PackageManager({
555
+ packageName: "electron",
556
+ packageVersion: ELECTRON_VERSION,
557
+ cacheDir: this.cachePath
558
+ });
559
+ return playwrightPackageManager.getPluginAfterInit("electron");
560
+ }
576
561
  /**
577
562
  * 启动 Electron
578
563
  * @returns
579
564
  */
580
565
  async getElectronApp() {
581
566
  if (!this._electronApp) {
582
- this._electronApp = await createElectronApp(
583
- this.cachePath,
584
- this.playwrightPackage
585
- );
567
+ const [playwright] = await Promise.all([
568
+ this.playwrightPackage,
569
+ this.electronPackage
570
+ ]);
571
+ this._electronApp = await createElectronApp(this.cachePath, playwright);
586
572
  }
587
573
  return this._electronApp;
588
574
  }
575
+ /**
576
+ * 临时文件目录
577
+ * @returns
578
+ */
579
+ getTmpPath() {
580
+ return path.join(this.cachePath, "tmp");
581
+ }
582
+ /**
583
+ * 清空临时文件
584
+ */
585
+ clearTmpPath() {
586
+ const tmpPath = this.getTmpPath();
587
+ return fs.rm(tmpPath, { recursive: true, force: true }, (err) => {
588
+ if (err) {
589
+ this.logger.error("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u5931\u8D25\uFF0C", err);
590
+ } else {
591
+ this.logger.info("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u6210\u529F");
592
+ }
593
+ });
594
+ }
589
595
  /**
590
596
  * 关闭 playwright 启动的 electron 客户端
591
597
  * @returns
592
598
  */
593
599
  async close() {
594
600
  this.logger.close();
601
+ this.clearTmpPath();
595
602
  const electronApp = await this.getElectronApp();
596
603
  return electronApp.close();
597
604
  }
@@ -643,13 +650,13 @@ class LocalAutomateTask {
643
650
  const res = await xiaohongshuPublishAction({
644
651
  page,
645
652
  params,
646
- cachePath: this.cachePath,
653
+ tmpCachePath: this.getTmpPath(),
647
654
  debug: !!this.debug
648
655
  });
649
656
  return res;
650
657
  } catch (error) {
651
658
  this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
652
- return error;
659
+ throw error;
653
660
  }
654
661
  }
655
662
  }
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@iflyrpa/playwright",
3
3
  "type": "module",
4
- "version": "1.0.10",
5
- "description": "",
4
+ "version": "1.0.11",
6
5
  "main": "./dist/index.cjs",
7
6
  "module": "./dist/index.mjs",
8
7
  "types": "./dist/index.d.ts",
@@ -11,12 +10,12 @@
11
10
  "dev": "unbuild --stub",
12
11
  "start": "esno src/index.ts"
13
12
  },
14
- "keywords": [],
15
13
  "author": "bijinfeng",
16
14
  "license": "ISC",
17
15
  "files": ["dist"],
18
16
  "dependencies": {
19
17
  "loglevel": "^1.9.2",
18
+ "npminstall": "^7.12.0",
20
19
  "playwright": "^1.46.1"
21
20
  },
22
21
  "peerDependencies": {