@iflyrpa/playwright 1.0.10 → 1.0.12

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.12";
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,
@@ -215,13 +212,16 @@ function fetchJSON(url) {
215
212
  });
216
213
  });
217
214
  }
215
+ function isNil(value) {
216
+ return value === null || value === void 0;
217
+ }
218
218
 
219
219
  const visibleRangeTexts = {
220
220
  public: "\u516C\u5F00",
221
221
  private: "\u79C1\u5BC6"
222
222
  };
223
223
  const xiaohongshuPublishAction = async (props) => {
224
- const { page, cachePath, params } = props;
224
+ const { page, tmpCachePath, params } = props;
225
225
  const selectAddress = async (selector, address) => {
226
226
  const instance = typeof selector === "string" ? page.locator(selector) : selector;
227
227
  await instance.click();
@@ -244,11 +244,13 @@ const xiaohongshuPublishAction = async (props) => {
244
244
  await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
245
245
  throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
246
246
  });
247
- await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click();
247
+ await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
248
+ throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
249
+ });
248
250
  const images = await Promise.all(
249
251
  params.banners.map((url) => {
250
252
  const fileName = getFilenameFromUrl(url);
251
- return downloadImage(url, path__default.join(cachePath, "image-tmp", fileName));
253
+ return downloadImage(url, path__default.join(tmpCachePath, fileName));
252
254
  })
253
255
  );
254
256
  const fileChooserPromise = page.waitForEvent("filechooser");
@@ -383,12 +385,11 @@ const _Logger = class _Logger {
383
385
  log__default.warn(...msg);
384
386
  }
385
387
  error(prefix, error) {
386
- let errorMessage = error;
388
+ log__default.error(prefix);
387
389
  if (error instanceof Error) {
388
- errorMessage = `${error.message}
389
- Error stack: ${error.stack}`;
390
+ log__default.error(`${error.message}
391
+ Error stack: ${error.stack}`);
390
392
  }
391
- log__default.error(prefix, errorMessage);
392
393
  }
393
394
  close() {
394
395
  this.stream.end();
@@ -413,7 +414,7 @@ const generateFile = async (dir) => {
413
414
  }
414
415
  return filePath;
415
416
  };
416
- const createElectronApp = async (cachePath, playwrightPackage) => {
417
+ const createElectronApp = async (cachePath, playwright) => {
417
418
  const logger = Logger.getInstance(cachePath);
418
419
  try {
419
420
  const executablePath = path__default.join(
@@ -422,7 +423,6 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
422
423
  ".bin",
423
424
  "electron"
424
425
  );
425
- const playwright = await playwrightPackage;
426
426
  const mainPath = await generateFile(cachePath);
427
427
  const electronApp = await playwright._electron.launch({
428
428
  executablePath,
@@ -434,6 +434,7 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
434
434
  return electronApp;
435
435
  } catch (error) {
436
436
  logger.error("electron \u542F\u52A8\u5931\u8D25\uFF1A", error);
437
+ throw error;
437
438
  }
438
439
  };
439
440
 
@@ -443,6 +444,7 @@ var __publicField$1 = (obj, key, value) => {
443
444
  __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
444
445
  return value;
445
446
  };
447
+ const NPM_REGISTRY = "https://registry.npmmirror.com/";
446
448
  class PackageManager {
447
449
  constructor(params) {
448
450
  __publicField$1(this, "cacheDir");
@@ -453,41 +455,10 @@ class PackageManager {
453
455
  __publicField$1(this, "logger");
454
456
  this.logger = Logger.getInstance(params.cacheDir);
455
457
  this.cacheDir = params.cacheDir;
456
- this.forceUpdate = params.forceUpdate || true;
458
+ this.forceUpdate = isNil(params.forceUpdate) ? true : params.forceUpdate;
457
459
  this.initCacheProject();
458
460
  this.initPromise = this.init(params.packageName, params.packageVersion);
459
461
  }
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
462
  // 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
492
463
  initCacheProject() {
493
464
  const packagePath = path__default.join(this.cacheDir, "package.json");
@@ -526,28 +497,33 @@ class PackageManager {
526
497
  return this.getPlugin(module);
527
498
  }
528
499
  // 安装依赖
529
- 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]);
500
+ install(name, version) {
501
+ return npminstall__default({
502
+ root: this.cacheDir,
503
+ pkgs: [{ name, version }],
504
+ registry: NPM_REGISTRY
505
+ });
536
506
  }
537
507
  async init(name, version) {
538
508
  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);
509
+ this.logger.info(`${name} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
510
+ try {
511
+ if (!plugin) {
512
+ await this.install(name, version);
513
+ } else if (this.forceUpdate) {
514
+ const pkInfo = await this.getPluginInfo(name);
515
+ if (!pkInfo)
516
+ return;
517
+ const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
518
+ if (hasNewVersion) {
519
+ this.logger.info(`${name} \u68C0\u67E5\u5230\u65B0\u7248\u672C ${pkInfo.version}\uFF0C\u66F4\u65B0\u4F9D\u8D56`);
520
+ await this.install(name, pkInfo.version);
521
+ }
548
522
  }
523
+ this.logger.info(`${name} package manager init done!`);
524
+ } catch (error) {
525
+ this.logger.error(`${name} package manager init error`, error);
549
526
  }
550
- this.logger.info(`${name} package manager init done!`);
551
527
  }
552
528
  }
553
529
 
@@ -558,17 +534,20 @@ var __publicField = (obj, key, value) => {
558
534
  return value;
559
535
  };
560
536
  const PLAYWRIGHT_VERSION = "1.46.1";
537
+ const ELECTRON_VERSION = "22.3.27";
561
538
  class LocalAutomateTask {
562
539
  constructor({ cachePath, debug }) {
540
+ __publicField(this, "logger");
563
541
  __publicField(this, "cachePath");
564
542
  __publicField(this, "debug");
565
543
  __publicField(this, "playwrightPackage");
566
- __publicField(this, "logger");
544
+ __publicField(this, "electronPackage");
567
545
  __publicField(this, "_electronApp", null);
568
546
  this.cachePath = cachePath;
569
547
  this.debug = debug || false;
570
548
  this.logger = Logger.getInstance(cachePath);
571
549
  this.playwrightPackage = this.installPlaywright();
550
+ this.electronPackage = this.installElectron();
572
551
  }
573
552
  /**
574
553
  * 安装 playwright
@@ -578,29 +557,65 @@ class LocalAutomateTask {
578
557
  const playwrightPackageManager = new PackageManager({
579
558
  packageName: "playwright",
580
559
  packageVersion: PLAYWRIGHT_VERSION,
581
- cacheDir: this.cachePath
560
+ cacheDir: this.cachePath,
561
+ forceUpdate: false
582
562
  });
583
563
  return playwrightPackageManager.getPluginAfterInit("playwright");
584
564
  }
565
+ /**
566
+ * 安装 electron
567
+ * @returns
568
+ */
569
+ installElectron() {
570
+ const playwrightPackageManager = new PackageManager({
571
+ packageName: "electron",
572
+ packageVersion: ELECTRON_VERSION,
573
+ cacheDir: this.cachePath,
574
+ forceUpdate: false
575
+ });
576
+ return playwrightPackageManager.getPluginAfterInit("electron");
577
+ }
585
578
  /**
586
579
  * 启动 Electron
587
580
  * @returns
588
581
  */
589
582
  async getElectronApp() {
590
583
  if (!this._electronApp) {
591
- this._electronApp = await createElectronApp(
592
- this.cachePath,
593
- this.playwrightPackage
594
- );
584
+ const [playwright] = await Promise.all([
585
+ this.playwrightPackage,
586
+ this.electronPackage
587
+ ]);
588
+ this._electronApp = await createElectronApp(this.cachePath, playwright);
595
589
  }
596
590
  return this._electronApp;
597
591
  }
592
+ /**
593
+ * 临时文件目录
594
+ * @returns
595
+ */
596
+ getTmpPath() {
597
+ return path__default.join(this.cachePath, "tmp");
598
+ }
599
+ /**
600
+ * 清空临时文件
601
+ */
602
+ clearTmpPath() {
603
+ const tmpPath = this.getTmpPath();
604
+ return fs__default.rm(tmpPath, { recursive: true, force: true }, (err) => {
605
+ if (err) {
606
+ this.logger.error("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u5931\u8D25\uFF0C", err);
607
+ } else {
608
+ this.logger.info("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u6210\u529F");
609
+ }
610
+ });
611
+ }
598
612
  /**
599
613
  * 关闭 playwright 启动的 electron 客户端
600
614
  * @returns
601
615
  */
602
616
  async close() {
603
617
  this.logger.close();
618
+ this.clearTmpPath();
604
619
  const electronApp = await this.getElectronApp();
605
620
  return electronApp.close();
606
621
  }
@@ -652,13 +667,13 @@ class LocalAutomateTask {
652
667
  const res = await xiaohongshuPublishAction({
653
668
  page,
654
669
  params,
655
- cachePath: this.cachePath,
670
+ tmpCachePath: this.getTmpPath(),
656
671
  debug: !!this.debug
657
672
  });
658
673
  return res;
659
674
  } catch (error) {
660
675
  this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
661
- return error;
676
+ throw error;
662
677
  }
663
678
  }
664
679
  }
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.12";
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,
@@ -206,13 +202,16 @@ function fetchJSON(url) {
206
202
  });
207
203
  });
208
204
  }
205
+ function isNil(value) {
206
+ return value === null || value === void 0;
207
+ }
209
208
 
210
209
  const visibleRangeTexts = {
211
210
  public: "\u516C\u5F00",
212
211
  private: "\u79C1\u5BC6"
213
212
  };
214
213
  const xiaohongshuPublishAction = async (props) => {
215
- const { page, cachePath, params } = props;
214
+ const { page, tmpCachePath, params } = props;
216
215
  const selectAddress = async (selector, address) => {
217
216
  const instance = typeof selector === "string" ? page.locator(selector) : selector;
218
217
  await instance.click();
@@ -235,11 +234,13 @@ const xiaohongshuPublishAction = async (props) => {
235
234
  await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
236
235
  throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
237
236
  });
238
- await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click();
237
+ await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
238
+ throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
239
+ });
239
240
  const images = await Promise.all(
240
241
  params.banners.map((url) => {
241
242
  const fileName = getFilenameFromUrl(url);
242
- return downloadImage(url, path.join(cachePath, "image-tmp", fileName));
243
+ return downloadImage(url, path.join(tmpCachePath, fileName));
243
244
  })
244
245
  );
245
246
  const fileChooserPromise = page.waitForEvent("filechooser");
@@ -374,12 +375,11 @@ const _Logger = class _Logger {
374
375
  log.warn(...msg);
375
376
  }
376
377
  error(prefix, error) {
377
- let errorMessage = error;
378
+ log.error(prefix);
378
379
  if (error instanceof Error) {
379
- errorMessage = `${error.message}
380
- Error stack: ${error.stack}`;
380
+ log.error(`${error.message}
381
+ Error stack: ${error.stack}`);
381
382
  }
382
- log.error(prefix, errorMessage);
383
383
  }
384
384
  close() {
385
385
  this.stream.end();
@@ -404,7 +404,7 @@ const generateFile = async (dir) => {
404
404
  }
405
405
  return filePath;
406
406
  };
407
- const createElectronApp = async (cachePath, playwrightPackage) => {
407
+ const createElectronApp = async (cachePath, playwright) => {
408
408
  const logger = Logger.getInstance(cachePath);
409
409
  try {
410
410
  const executablePath = path.join(
@@ -413,7 +413,6 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
413
413
  ".bin",
414
414
  "electron"
415
415
  );
416
- const playwright = await playwrightPackage;
417
416
  const mainPath = await generateFile(cachePath);
418
417
  const electronApp = await playwright._electron.launch({
419
418
  executablePath,
@@ -425,6 +424,7 @@ const createElectronApp = async (cachePath, playwrightPackage) => {
425
424
  return electronApp;
426
425
  } catch (error) {
427
426
  logger.error("electron \u542F\u52A8\u5931\u8D25\uFF1A", error);
427
+ throw error;
428
428
  }
429
429
  };
430
430
 
@@ -434,6 +434,7 @@ var __publicField$1 = (obj, key, value) => {
434
434
  __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
435
435
  return value;
436
436
  };
437
+ const NPM_REGISTRY = "https://registry.npmmirror.com/";
437
438
  class PackageManager {
438
439
  constructor(params) {
439
440
  __publicField$1(this, "cacheDir");
@@ -444,41 +445,10 @@ class PackageManager {
444
445
  __publicField$1(this, "logger");
445
446
  this.logger = Logger.getInstance(params.cacheDir);
446
447
  this.cacheDir = params.cacheDir;
447
- this.forceUpdate = params.forceUpdate || true;
448
+ this.forceUpdate = isNil(params.forceUpdate) ? true : params.forceUpdate;
448
449
  this.initCacheProject();
449
450
  this.initPromise = this.init(params.packageName, params.packageVersion);
450
451
  }
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
452
  // 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
483
453
  initCacheProject() {
484
454
  const packagePath = path.join(this.cacheDir, "package.json");
@@ -517,28 +487,33 @@ class PackageManager {
517
487
  return this.getPlugin(module);
518
488
  }
519
489
  // 安装依赖
520
- 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]);
490
+ install(name, version) {
491
+ return npminstall({
492
+ root: this.cacheDir,
493
+ pkgs: [{ name, version }],
494
+ registry: NPM_REGISTRY
495
+ });
527
496
  }
528
497
  async init(name, version) {
529
498
  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);
499
+ this.logger.info(`${name} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
500
+ try {
501
+ if (!plugin) {
502
+ await this.install(name, version);
503
+ } else if (this.forceUpdate) {
504
+ const pkInfo = await this.getPluginInfo(name);
505
+ if (!pkInfo)
506
+ return;
507
+ const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
508
+ if (hasNewVersion) {
509
+ this.logger.info(`${name} \u68C0\u67E5\u5230\u65B0\u7248\u672C ${pkInfo.version}\uFF0C\u66F4\u65B0\u4F9D\u8D56`);
510
+ await this.install(name, pkInfo.version);
511
+ }
539
512
  }
513
+ this.logger.info(`${name} package manager init done!`);
514
+ } catch (error) {
515
+ this.logger.error(`${name} package manager init error`, error);
540
516
  }
541
- this.logger.info(`${name} package manager init done!`);
542
517
  }
543
518
  }
544
519
 
@@ -549,17 +524,20 @@ var __publicField = (obj, key, value) => {
549
524
  return value;
550
525
  };
551
526
  const PLAYWRIGHT_VERSION = "1.46.1";
527
+ const ELECTRON_VERSION = "22.3.27";
552
528
  class LocalAutomateTask {
553
529
  constructor({ cachePath, debug }) {
530
+ __publicField(this, "logger");
554
531
  __publicField(this, "cachePath");
555
532
  __publicField(this, "debug");
556
533
  __publicField(this, "playwrightPackage");
557
- __publicField(this, "logger");
534
+ __publicField(this, "electronPackage");
558
535
  __publicField(this, "_electronApp", null);
559
536
  this.cachePath = cachePath;
560
537
  this.debug = debug || false;
561
538
  this.logger = Logger.getInstance(cachePath);
562
539
  this.playwrightPackage = this.installPlaywright();
540
+ this.electronPackage = this.installElectron();
563
541
  }
564
542
  /**
565
543
  * 安装 playwright
@@ -569,29 +547,65 @@ class LocalAutomateTask {
569
547
  const playwrightPackageManager = new PackageManager({
570
548
  packageName: "playwright",
571
549
  packageVersion: PLAYWRIGHT_VERSION,
572
- cacheDir: this.cachePath
550
+ cacheDir: this.cachePath,
551
+ forceUpdate: false
573
552
  });
574
553
  return playwrightPackageManager.getPluginAfterInit("playwright");
575
554
  }
555
+ /**
556
+ * 安装 electron
557
+ * @returns
558
+ */
559
+ installElectron() {
560
+ const playwrightPackageManager = new PackageManager({
561
+ packageName: "electron",
562
+ packageVersion: ELECTRON_VERSION,
563
+ cacheDir: this.cachePath,
564
+ forceUpdate: false
565
+ });
566
+ return playwrightPackageManager.getPluginAfterInit("electron");
567
+ }
576
568
  /**
577
569
  * 启动 Electron
578
570
  * @returns
579
571
  */
580
572
  async getElectronApp() {
581
573
  if (!this._electronApp) {
582
- this._electronApp = await createElectronApp(
583
- this.cachePath,
584
- this.playwrightPackage
585
- );
574
+ const [playwright] = await Promise.all([
575
+ this.playwrightPackage,
576
+ this.electronPackage
577
+ ]);
578
+ this._electronApp = await createElectronApp(this.cachePath, playwright);
586
579
  }
587
580
  return this._electronApp;
588
581
  }
582
+ /**
583
+ * 临时文件目录
584
+ * @returns
585
+ */
586
+ getTmpPath() {
587
+ return path.join(this.cachePath, "tmp");
588
+ }
589
+ /**
590
+ * 清空临时文件
591
+ */
592
+ clearTmpPath() {
593
+ const tmpPath = this.getTmpPath();
594
+ return fs.rm(tmpPath, { recursive: true, force: true }, (err) => {
595
+ if (err) {
596
+ this.logger.error("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u5931\u8D25\uFF0C", err);
597
+ } else {
598
+ this.logger.info("\u5220\u9664\u4E34\u65F6\u6587\u4EF6\u6210\u529F");
599
+ }
600
+ });
601
+ }
589
602
  /**
590
603
  * 关闭 playwright 启动的 electron 客户端
591
604
  * @returns
592
605
  */
593
606
  async close() {
594
607
  this.logger.close();
608
+ this.clearTmpPath();
595
609
  const electronApp = await this.getElectronApp();
596
610
  return electronApp.close();
597
611
  }
@@ -643,13 +657,13 @@ class LocalAutomateTask {
643
657
  const res = await xiaohongshuPublishAction({
644
658
  page,
645
659
  params,
646
- cachePath: this.cachePath,
660
+ tmpCachePath: this.getTmpPath(),
647
661
  debug: !!this.debug
648
662
  });
649
663
  return res;
650
664
  } catch (error) {
651
665
  this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
652
- return error;
666
+ throw error;
653
667
  }
654
668
  }
655
669
  }
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.12",
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": {