@iflyrpa/playwright 1.0.15 → 1.1.1

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.mjs CHANGED
@@ -1,16 +1,18 @@
1
+ import { Action } from '@iflyrpa/actions';
1
2
  import fs from 'node:fs';
2
3
  import path from 'node:path';
3
- import https from 'node:https';
4
4
  import childProcess from 'node:child_process';
5
5
  import os from 'node:os';
6
6
  import { downloadArtifact } from '@electron/get';
7
7
  import extract from 'extract-zip';
8
+ import { ensureFileSync, pathExists, ensureFile, writeFile } from '@iflyrpa/share';
8
9
  import log from 'loglevel';
9
- import { PluginManager } from 'live-plugin-manager';
10
+ import { NodeClient } from '@sentry/node';
11
+ import pacote from 'pacote';
10
12
 
11
13
  const name = "@iflyrpa/playwright";
12
14
  const type = "module";
13
- const version$1 = "1.0.15";
15
+ const version$1 = "1.1.1";
14
16
  const main = "./dist/index.cjs";
15
17
  const module = "./dist/index.mjs";
16
18
  const types = "./dist/index.d.ts";
@@ -24,21 +26,26 @@ const license = "ISC";
24
26
  const files = [
25
27
  "dist"
26
28
  ];
27
- const dependencies = {
28
- "@electron/get": "^2.0.0",
29
- "extract-zip": "^2.0.1",
30
- "live-plugin-manager": "^1.0.0",
31
- loglevel: "^1.9.2"
32
- };
33
29
  const peerDependencies = {
34
30
  playwright: "^1.46.1"
35
31
  };
36
32
  const devDependencies = {
33
+ "@iflyrpa/share": "workspace:*",
34
+ "@types/pacote": "^11.1.8",
37
35
  esno: "^4.7.0",
38
36
  playwright: "^1.46.1",
39
37
  typescript: "^5.5.2",
40
38
  unbuild: "^2.0.0"
41
39
  };
40
+ const dependencies = {
41
+ "@iflyrpa/actions": "workspace:*",
42
+ "@iflyrpa/share": "workspace:*",
43
+ "@electron/get": "^2.0.0",
44
+ "@sentry/node": "^5.5.0",
45
+ "extract-zip": "^2.0.1",
46
+ loglevel: "^1.9.2",
47
+ pacote: "^20.0.0"
48
+ };
42
49
  const packageJson = {
43
50
  name: name,
44
51
  type: type,
@@ -50,307 +57,29 @@ const packageJson = {
50
57
  author: author,
51
58
  license: license,
52
59
  files: files,
53
- dependencies: dependencies,
54
60
  peerDependencies: peerDependencies,
55
- devDependencies: devDependencies
56
- };
57
-
58
- async function downloadImage(url, savePath) {
59
- await ensureFile(savePath);
60
- return new Promise((resolve, reject) => {
61
- https.get(url, (response) => {
62
- if (response.statusCode === 200) {
63
- const fileStream = fs.createWriteStream(savePath);
64
- response.pipe(fileStream);
65
- fileStream.on("finish", () => {
66
- fileStream.close();
67
- console.log("\u4E0B\u8F7D\u5B8C\u6210\uFF0C\u6587\u4EF6\u5DF2\u4FDD\u5B58\u81F3:", savePath);
68
- resolve(savePath);
69
- });
70
- } else {
71
- console.log("\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25:", response.statusCode);
72
- response.resume();
73
- reject();
74
- }
75
- }).on("error", (error) => {
76
- console.error("\u8BF7\u6C42\u56FE\u7247\u65F6\u53D1\u751F\u9519\u8BEF:", error.message);
77
- reject();
78
- });
79
- });
80
- }
81
- function getFilenameFromUrl(imageUrl) {
82
- const parsedUrl = new URL(imageUrl);
83
- return path.basename(parsedUrl.pathname);
84
- }
85
- function pathExists(path2) {
86
- return new Promise((resolve) => {
87
- fs.stat(path2, (err) => {
88
- resolve(!err);
89
- });
90
- });
91
- }
92
- function ensureFile(filePath) {
93
- return new Promise((resolve, reject) => {
94
- const dirPath = path.dirname(filePath);
95
- fs.stat(dirPath, (err, stats) => {
96
- if (err) {
97
- if (err.code === "ENOENT") {
98
- fs.mkdir(dirPath, { recursive: true }, (err2) => {
99
- if (err2) {
100
- return reject(err2);
101
- }
102
- createFile();
103
- });
104
- } else {
105
- return reject(err);
106
- }
107
- } else if (stats.isDirectory()) {
108
- checkFile();
109
- } else {
110
- reject(new Error(`${dirPath} is not a directory`));
111
- }
112
- });
113
- function checkFile() {
114
- fs.stat(filePath, (err, stats) => {
115
- if (err) {
116
- if (err.code === "ENOENT") {
117
- createFile();
118
- } else {
119
- reject(err);
120
- }
121
- } else if (stats.isFile()) {
122
- resolve();
123
- } else {
124
- reject(new Error(`${filePath} is not a file`));
125
- }
126
- });
127
- }
128
- function createFile() {
129
- fs.writeFile(filePath, "", (err) => {
130
- if (err) {
131
- reject(err);
132
- } else {
133
- resolve();
134
- }
135
- });
136
- }
137
- });
138
- }
139
- function ensureFileSync(filePath) {
140
- const dirPath = path.dirname(filePath);
141
- try {
142
- if (!fs.existsSync(dirPath)) {
143
- fs.mkdirSync(dirPath, { recursive: true });
144
- }
145
- } catch (err) {
146
- if (err instanceof Error) {
147
- throw new Error(`Error creating directory: ${err.message}`);
148
- }
149
- }
150
- try {
151
- if (!fs.existsSync(filePath)) {
152
- fs.writeFileSync(filePath, "");
153
- }
154
- } catch (err) {
155
- if (err instanceof Error) {
156
- throw new Error(`Error creating file: ${err.message}`);
157
- }
158
- }
159
- }
160
- function writeFile(filePath, data) {
161
- return new Promise((resolve, reject) => {
162
- fs.writeFile(filePath, data, (err) => {
163
- if (err) {
164
- console.error("Error writing file:", err);
165
- reject();
166
- } else {
167
- console.log("File written successfully");
168
- resolve();
169
- }
170
- });
171
- });
172
- }
173
- function compareVersions(v1, v2) {
174
- const parts1 = v1.split(".").map(Number);
175
- const parts2 = v2.split(".").map(Number);
176
- for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
177
- const num1 = i < parts1.length ? parts1[i] : 0;
178
- const num2 = i < parts2.length ? parts2[i] : 0;
179
- if (num1 > num2)
180
- return 1;
181
- if (num1 < num2)
182
- return -1;
183
- }
184
- return 0;
185
- }
186
- const semver = {
187
- gt: (v1, v2) => compareVersions(v1, v2) === 1
188
- };
189
- function fetchJSON(url) {
190
- return new Promise((resolve, reject) => {
191
- https.get(url, (res) => {
192
- let data = "";
193
- res.on("data", (chunk) => {
194
- data += chunk;
195
- });
196
- res.on("end", () => {
197
- try {
198
- const parsedData = JSON.parse(data);
199
- resolve(parsedData);
200
- } catch (e) {
201
- if (e instanceof Error) {
202
- reject(new Error(`Error parsing JSON: ${e.message}`));
203
- }
204
- }
205
- });
206
- }).on("error", (err) => {
207
- reject(new Error(`Request failed: ${err.message}`));
208
- });
209
- });
210
- }
211
- function isNil(value) {
212
- return value === null || value === void 0;
213
- }
214
-
215
- const visibleRangeTexts = {
216
- public: "\u516C\u5F00",
217
- private: "\u79C1\u5BC6"
218
- };
219
- const xiaohongshuPublishAction = async (props) => {
220
- const { page, tmpCachePath, params } = props;
221
- const selectAddress = async (selector, address) => {
222
- const instance = typeof selector === "string" ? page.locator(selector) : selector;
223
- await instance.click();
224
- await instance.locator("input").fill(address);
225
- const poperInstance = page.locator(
226
- '.d-popover:not([style*="display: none"]) .d-options .d-grid-item'
227
- );
228
- await poperInstance.first().waitFor();
229
- await poperInstance.first().click();
230
- };
231
- const selectDate = async (selector, date) => {
232
- const instance = typeof selector === "string" ? page.locator(selector) : selector;
233
- await instance.click();
234
- await instance.fill(date);
235
- await instance.blur();
236
- };
237
- await page.waitForSelector("#CreatorPlatform", { state: "visible" }).catch(() => {
238
- throw new Error("\u767B\u5F55\u5931\u8D25");
239
- });
240
- await page.locator("#content-area .menu-container .publish-video a").click().catch(() => {
241
- throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u7B14\u8BB0\u6309\u94AE");
242
- });
243
- await page.locator(".creator-container .header .title").filter({ hasText: /^上传图文$/ }).click().catch(() => {
244
- throw new Error("\u672A\u627E\u5230\u4E0A\u4F20\u56FE\u6587\u6309\u94AE");
245
- });
246
- const images = await Promise.all(
247
- params.banners.map((url) => {
248
- const fileName = getFilenameFromUrl(url);
249
- return downloadImage(url, path.join(tmpCachePath, fileName));
250
- })
251
- );
252
- const fileChooserPromise = page.waitForEvent("filechooser");
253
- await page.getByRole("textbox").click();
254
- const fileChooser = await fileChooserPromise;
255
- await fileChooser.setFiles(images);
256
- const titleInstance = page.locator(".titleInput input");
257
- await titleInstance.click();
258
- await titleInstance.fill(params.title);
259
- const descInstance = page.locator("#post-textarea");
260
- await descInstance.click();
261
- await descInstance.fill(params.content);
262
- const container = page.locator(".creator-container .content .scroll-content");
263
- await container.focus();
264
- await page.mouse.wheel(0, 500);
265
- if (params.address) {
266
- await selectAddress(
267
- page.locator(".media-extension .address-input").filter({ hasText: "\u6DFB\u52A0\u5730\u70B9" }),
268
- params.address
269
- );
270
- }
271
- if (params.selfDeclaration) {
272
- await page.locator(".declaration-wrapper").click();
273
- const selfDeclarationInstance = page.locator(
274
- ".el-popper[aria-hidden=false] ul li[role=menuitem]"
275
- );
276
- if (params.selfDeclaration.type === "fictional-rendition") {
277
- await selfDeclarationInstance.filter({ hasText: "\u865A\u6784\u6F14\u7ECE\uFF0C\u4EC5\u4F9B\u5A31\u4E50" }).click();
278
- } else if (params.selfDeclaration.type === "ai-generated") {
279
- await selfDeclarationInstance.filter({ hasText: "\u7B14\u8BB0\u542BAI\u5408\u6210\u5185\u5BB9" }).click();
280
- } else if (params.selfDeclaration.type === "source-statement") {
281
- await selfDeclarationInstance.filter({ hasText: "\u5185\u5BB9\u6765\u6E90\u58F0\u660E" }).click();
282
- const selfDeclarationSecondaryMenuInstance = page.locator(".el-popper[aria-hidden=false] .el-cascader-menu").nth(1).locator("ul li[role=menuitem]");
283
- await selfDeclarationSecondaryMenuInstance.first().waitFor();
284
- if (params.selfDeclaration.childType === "self-labeling") {
285
- await selfDeclarationSecondaryMenuInstance.filter({ hasText: "\u5DF2\u81EA\u4E3B\u6807\u6CE8" }).click();
286
- } else if (params.selfDeclaration.childType === "self-shooting") {
287
- const { shootingDate, shootingLocation } = params.selfDeclaration;
288
- await selfDeclarationSecondaryMenuInstance.filter({ hasText: "\u81EA\u4E3B\u62CD\u6444" }).click();
289
- const selfShootingPopup = page.locator(".el-overlay-dialog[aria-modal=true][role=dialog]").filter({ hasText: "\u81EA\u4E3B\u62CD\u6444" });
290
- await selfShootingPopup.waitFor();
291
- const hasCustomContent = shootingDate || shootingLocation;
292
- if (shootingLocation) {
293
- await selectAddress(
294
- selfShootingPopup.locator(".address-input"),
295
- shootingLocation
296
- );
297
- }
298
- if (shootingDate) {
299
- await selectDate(
300
- selfShootingPopup.locator(".date-picker input"),
301
- shootingDate
302
- );
303
- }
304
- await selfShootingPopup.locator("footer button").filter({ hasText: hasCustomContent ? "\u786E\u8BA4" : "\u53D6\u6D88" }).click();
305
- } else if (params.selfDeclaration.childType === "transshipment") {
306
- await selfDeclarationSecondaryMenuInstance.filter({ hasText: "\u6765\u6E90\u8F6C\u8F7D" }).click();
307
- const selfShootingPopup = page.locator(".el-overlay-dialog[aria-modal=true][role=dialog]").filter({ hasText: "\u6765\u6E90\u5A92\u4F53" });
308
- await selfShootingPopup.waitFor();
309
- const sourceMedia = params.selfDeclaration.sourceMedia;
310
- if (sourceMedia) {
311
- await selfShootingPopup.locator(".el-input input").fill(sourceMedia);
312
- }
313
- await selfShootingPopup.locator("footer button").filter({ hasText: sourceMedia ? "\u786E\u8BA4" : "\u53D6\u6D88" }).click();
314
- }
315
- }
316
- }
317
- const publicLabelInstance = page.locator("label").filter({ hasText: visibleRangeTexts[params.visibleRange] });
318
- await publicLabelInstance.click();
319
- const releaseTimeInstance = page.locator("label").filter({ hasText: params.isImmediatelyPublish ? "\u7ACB\u5373\u53D1\u5E03" : "\u5B9A\u65F6\u53D1\u5E03" });
320
- await releaseTimeInstance.click();
321
- if (params.scheduledPublish) {
322
- await selectDate(".date-picker input", params.scheduledPublish);
323
- }
324
- const response = await new Promise((resolve) => {
325
- const handleResponse = async (response2) => {
326
- if (response2.url().includes("/web_api/sns/v2/note")) {
327
- const jsonResponse = await response2.json();
328
- page.off("response", handleResponse);
329
- resolve(jsonResponse?.data?.id);
330
- }
331
- };
332
- page.on("response", handleResponse);
333
- page.locator(".submit .publishBtn").click();
334
- });
335
- await page.close();
336
- return response;
61
+ devDependencies: devDependencies,
62
+ dependencies: dependencies
337
63
  };
338
64
 
339
- var __defProp$3 = Object.defineProperty;
340
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
341
- var __publicField$3 = (obj, key, value) => {
342
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
65
+ var __defProp$4 = Object.defineProperty;
66
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
67
+ var __publicField$4 = (obj, key, value) => {
68
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
343
69
  return value;
344
70
  };
71
+ const ELECTRON_MIRROR = "http://npmmirror.com/mirrors/electron/";
72
+ const ELECTRON_VERSION = "22.3.27";
345
73
  class ElectronInstall {
346
- constructor(rootDir, version, logger) {
347
- this.rootDir = rootDir;
348
- this.version = version;
349
- this.logger = logger;
350
- __publicField$3(this, "electronPath");
351
- __publicField$3(this, "platformPath");
74
+ constructor(task) {
75
+ this.task = task;
76
+ __publicField$4(this, "rootDir");
77
+ __publicField$4(this, "electronPath");
78
+ __publicField$4(this, "platformPath");
79
+ __publicField$4(this, "version", ELECTRON_VERSION);
352
80
  this.platformPath = this.getPlatformPath();
353
- this.electronPath = path.join(rootDir, this.platformPath);
81
+ this.rootDir = path.join(task.packagesDir, `electron@${this.version}`);
82
+ this.electronPath = path.join(this.rootDir, this.platformPath);
354
83
  }
355
84
  isInstalled() {
356
85
  try {
@@ -383,7 +112,7 @@ class ElectronInstall {
383
112
  }
384
113
  async install() {
385
114
  const installed = this.isInstalled();
386
- this.logger.info(`electron@${this.version} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${installed}`);
115
+ this.task.logger.info(`electron@${this.version} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${installed}`);
387
116
  if (installed)
388
117
  return this.electronPath;
389
118
  const platform = process.env.npm_config_platform || process.platform;
@@ -400,28 +129,52 @@ class ElectronInstall {
400
129
  }
401
130
  }
402
131
  try {
403
- this.logger.info(`electron@${this.version} \u5F00\u59CB\u4E0B\u8F7D\u8D44\u6E90`);
132
+ this.task.logger.info(`electron@${this.version} \u5F00\u59CB\u4E0B\u8F7D\u8D44\u6E90`);
404
133
  const zipPath = await downloadArtifact({
405
134
  version: this.version,
406
135
  artifactName: "electron",
407
136
  force: process.env.force_no_cache === "true",
408
137
  cacheRoot: process.env.electron_config_cache,
409
138
  checksums: void 0,
139
+ mirrorOptions: { mirror: ELECTRON_MIRROR },
140
+ // 使用国内镜像下载
410
141
  platform,
411
142
  arch
412
143
  });
413
- this.logger.info(`electron@${this.version} \u5F00\u59CB\u89E3\u538B\u8D44\u6E90`);
144
+ this.task.logger.info(`electron@${this.version} \u5F00\u59CB\u89E3\u538B\u8D44\u6E90`);
414
145
  process.noAsar = true;
415
146
  await extract(zipPath, { dir: this.rootDir });
416
- this.logger.info(`electron@${this.version} \u4E0B\u8F7D\u6210\u529F`);
147
+ this.task.logger.info(`electron@${this.version} \u4E0B\u8F7D\u6210\u529F`);
417
148
  return this.electronPath;
418
149
  } catch (error) {
419
- this.logger.error(`electron@${this.version} \u4E0B\u8F7D\u5931\u8D25`, error);
150
+ this.task.logger.error(`electron@${this.version} \u4E0B\u8F7D\u5931\u8D25`, error);
420
151
  throw error;
421
152
  }
422
153
  }
423
154
  }
424
155
 
156
+ var __defProp$3 = Object.defineProperty;
157
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
158
+ var __publicField$3 = (obj, key, value) => {
159
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
160
+ return value;
161
+ };
162
+ class SentryInstance {
163
+ constructor(dsn) {
164
+ __publicField$3(this, "sentry");
165
+ if (!dsn)
166
+ return;
167
+ this.sentry = new NodeClient({
168
+ dsn,
169
+ defaultIntegrations: false
170
+ });
171
+ }
172
+ captureException(error) {
173
+ this.sentry?.captureException(error);
174
+ }
175
+ }
176
+ const sentry = new SentryInstance(process.env.RPA_SENTRY_DSN);
177
+
425
178
  var __defProp$2 = Object.defineProperty;
426
179
  var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
427
180
  var __publicField$2 = (obj, key, value) => {
@@ -435,12 +188,13 @@ const _Logger = class _Logger {
435
188
  return _Logger.instance;
436
189
  }
437
190
  const logFile = path.join(cachePath, "rpa.log");
191
+ ensureFileSync(logFile);
438
192
  this.stream = fs.createWriteStream(logFile, { flags: "a" });
439
193
  log.setLevel("debug");
440
194
  log.methodFactory = (methodName) => {
441
195
  return (message) => {
442
196
  this.stream.write(
443
- `[${( new Date()).toISOString()}] ${methodName.toUpperCase()}: ${message}
197
+ `[${( new Date()).toLocaleString()}] ${methodName.toUpperCase()}: ${message}
444
198
  `
445
199
  );
446
200
  };
@@ -466,12 +220,14 @@ const _Logger = class _Logger {
466
220
  warn(...msg) {
467
221
  log.warn(...msg);
468
222
  }
469
- error(prefix, error) {
470
- log.error(prefix);
471
- if (error instanceof Error) {
472
- log.error(`${error.message}
473
- Error stack: ${error.stack}`);
223
+ // error 级别的日志上报 sentry
224
+ error(prefix, err) {
225
+ const error = err || prefix;
226
+ if (err instanceof Error) {
227
+ err.message = `${prefix}\uFF1A${err.message}`;
474
228
  }
229
+ log.error(error);
230
+ sentry.captureException(error);
475
231
  }
476
232
  close() {
477
233
  this.stream.end();
@@ -488,7 +244,7 @@ app.whenReady().then(() => {});
488
244
  app.on("window-all-closed", (e) => e.preventDefault());
489
245
  `;
490
246
  const generateFile = async (dir) => {
491
- const filePath = path.join(dir, "src", "main.js");
247
+ const filePath = path.join(dir, "main.js");
492
248
  const isPathExists = await pathExists(filePath);
493
249
  if (!isPathExists) {
494
250
  await ensureFile(filePath);
@@ -514,121 +270,92 @@ const launchElectronApp = async (cachePath, playwright, electronPath) => {
514
270
  }
515
271
  };
516
272
 
517
- var __defProp$1 = Object.defineProperty;
518
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
519
- var __publicField$1 = (obj, key, value) => {
520
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
521
- return value;
522
- };
523
273
  const NPM_REGISTRY = "https://registry.npmmirror.com/";
524
- class PackageManager extends PluginManager {
525
- constructor(params) {
526
- super({
527
- cwd: params.cacheDir,
528
- pluginsPath: path.join(params.cacheDir, "node_modules"),
529
- npmRegistryUrl: NPM_REGISTRY
530
- });
531
- __publicField$1(this, "cacheDir");
532
- // 依赖安装目录
533
- __publicField$1(this, "forceUpdate");
534
- // 是否强制更新
535
- __publicField$1(this, "initPromise");
536
- __publicField$1(this, "logger");
537
- this.logger = Logger.getInstance(params.cacheDir);
538
- this.cacheDir = params.cacheDir;
539
- this.forceUpdate = isNil(params.forceUpdate) ? true : params.forceUpdate;
540
- this.initCacheProject();
541
- this.initPromise = this.init(params.packageName, params.packageVersion);
542
- }
543
- // 构建 package.json 文件,有了该文件后,依赖可以安装在该目录下,避免污染全局环境
544
- initCacheProject() {
545
- const packagePath = path.join(this.cacheDir, "package.json");
546
- if (!fs.existsSync(packagePath)) {
547
- this.logger.info("package.json \u4E0D\u5B58\u5728\uFF0C\u6DFB\u52A0\u8BE5\u6587\u4EF6");
548
- const pkg = {
549
- name: "rpa-plugins",
550
- description: "rpa-plugins",
551
- license: "MIT",
552
- main: "./src/main.js"
553
- };
554
- ensureFileSync(packagePath);
555
- fs.writeFileSync(packagePath, JSON.stringify(pkg), "utf8");
556
- }
274
+ class PackageManager {
275
+ constructor(task) {
276
+ this.task = task;
557
277
  }
558
278
  // 获取依赖信息
559
- async getPluginInfo(module) {
560
- const res = await fetchJSON(
561
- `https://registry.npmjs.com/-/v1/search?text=${module}`
562
- );
563
- const packages = res.objects;
564
- return packages.find((it) => it.package.name === module)?.package;
565
- }
566
- // 查询本地安装的依赖
567
- getPlugin(module) {
568
- const pluginDir = path.join(this.cacheDir, "node_modules");
279
+ async getManifest(module) {
569
280
  try {
570
- return require(path.join(pluginDir, module));
281
+ return pacote.manifest(module, { registry: NPM_REGISTRY });
571
282
  } catch (error) {
572
- return null;
283
+ this.task.logger.error("\u83B7\u53D6\u4F9D\u8D56\u4FE1\u606F\u5931\u8D25", error);
284
+ throw error;
573
285
  }
574
286
  }
575
- async getPluginAfterInit(module) {
576
- await this.initPromise;
577
- return this.getPlugin(module);
578
- }
579
287
  // 安装依赖
580
- async installPackage(name, version) {
288
+ async extract(name, version = "latest") {
289
+ const packageName = `${name}@${version}`;
581
290
  try {
582
- this.logger.info(`${name} \u5F00\u59CB\u5B89\u88C5`);
583
- await this.install(name, version);
584
- this.logger.info(`${name} \u5B89\u88C5\u6210\u529F`);
291
+ this.task.logger.info(`${packageName} \u5F00\u59CB\u5B89\u88C5`);
292
+ await pacote.extract(
293
+ packageName,
294
+ path.join(this.task.packagesDir, packageName),
295
+ { registry: NPM_REGISTRY }
296
+ );
297
+ this.task.logger.info(`${packageName} \u5B89\u88C5\u6210\u529F`);
585
298
  } catch (error) {
586
- this.logger.error(`${name} \u5B89\u88C5\u5931\u8D25`, error);
299
+ this.task.logger.error(`${packageName} \u5B89\u88C5\u5931\u8D25`, error);
587
300
  }
588
301
  }
589
- async init(name, version) {
590
- const plugin = this.getPlugin(path.join(name, "package.json"));
591
- this.logger.info(`${name} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
302
+ // 查询本地安装的依赖
303
+ require(module) {
592
304
  try {
593
- if (!plugin) {
594
- await this.installPackage(name, version);
595
- } else if (this.forceUpdate) {
596
- const pkInfo = await this.getPluginInfo(name);
597
- if (!pkInfo)
598
- return;
599
- const hasNewVersion = semver.gt(pkInfo.version, plugin.version);
600
- if (hasNewVersion) {
601
- this.logger.info(`${name} \u68C0\u67E5\u5230\u65B0\u7248\u672C ${pkInfo.version}`);
602
- await this.installPackage(name, pkInfo.version);
603
- }
604
- }
605
- this.logger.info(`${name} package manager init done!`);
305
+ return require(path.join(this.task.packagesDir, module));
606
306
  } catch (error) {
607
- this.logger.error(`${name} package manager init error`, error);
307
+ return null;
608
308
  }
609
309
  }
310
+ // 安装依赖
311
+ async install(name, version) {
312
+ const packageName = `${name}@${version}`;
313
+ const plugin = this.require(packageName);
314
+ this.task.logger.info(`${packageName} \u662F\u5426\u5DF2\u5B89\u88C5\uFF1A${!!plugin}`);
315
+ if (!plugin) {
316
+ await this.extract(name, version);
317
+ }
318
+ }
319
+ // 更新依赖
320
+ async update(name) {
321
+ const manifest = await this.getManifest(`${name}@latest`);
322
+ const version = manifest.version;
323
+ const plugin = this.require(`${name}@${version}`);
324
+ if (!plugin) {
325
+ await this.extract(name, version);
326
+ }
327
+ return version;
328
+ }
610
329
  }
611
330
 
612
- var __defProp = Object.defineProperty;
613
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
614
- var __publicField = (obj, key, value) => {
615
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
331
+ var __defProp$1 = Object.defineProperty;
332
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
333
+ var __publicField$1 = (obj, key, value) => {
334
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
616
335
  return value;
617
336
  };
618
337
  const PLAYWRIGHT_VERSION = "1.46.1";
619
338
  const PLAYWRIGHT_NAME = "playwright-core";
620
- const ELECTRON_VERSION = "22.3.27";
621
- class LocalAutomateTask {
339
+ class Task {
622
340
  constructor({ cachePath, debug }) {
623
- __publicField(this, "logger");
624
- __publicField(this, "cachePath");
625
- __publicField(this, "debug");
626
- __publicField(this, "playwrightPackage");
627
- __publicField(this, "electronPackage");
628
- __publicField(this, "_electronApp", null);
341
+ __publicField$1(this, "logger");
342
+ __publicField$1(this, "cachePath");
343
+ __publicField$1(this, "debug");
344
+ __publicField$1(this, "packagesDir");
345
+ // 依赖安装目录
346
+ __publicField$1(this, "packageManager");
347
+ __publicField$1(this, "playwrightPackage");
348
+ __publicField$1(this, "electronPackage");
349
+ __publicField$1(this, "_electronApp", null);
350
+ /**
351
+ * 应用是否已关闭
352
+ */
353
+ __publicField$1(this, "isClosed", false);
629
354
  this.cachePath = cachePath;
355
+ this.packagesDir = path.join(cachePath, "packages");
630
356
  this.debug = debug || false;
631
357
  this.logger = Logger.getInstance(cachePath);
358
+ this.packageManager = new PackageManager(this);
632
359
  this.playwrightPackage = this.installPlaywright();
633
360
  this.electronPackage = this.installElectron();
634
361
  }
@@ -636,26 +363,17 @@ class LocalAutomateTask {
636
363
  * 安装 playwright
637
364
  * @returns
638
365
  */
639
- installPlaywright() {
640
- const playwrightPackageManager = new PackageManager({
641
- packageName: PLAYWRIGHT_NAME,
642
- packageVersion: PLAYWRIGHT_VERSION,
643
- cacheDir: this.cachePath,
644
- forceUpdate: false
645
- });
646
- return playwrightPackageManager.getPluginAfterInit(PLAYWRIGHT_NAME);
366
+ async installPlaywright() {
367
+ const packageName = `${PLAYWRIGHT_NAME}@${PLAYWRIGHT_VERSION}`;
368
+ await this.packageManager.install(PLAYWRIGHT_NAME, PLAYWRIGHT_VERSION);
369
+ return this.packageManager.require(packageName);
647
370
  }
648
371
  /**
649
372
  * 安装 electron
650
373
  * @returns
651
374
  */
652
375
  installElectron() {
653
- const electronInstall = new ElectronInstall(
654
- path.join(this.cachePath, "electron"),
655
- ELECTRON_VERSION,
656
- this.logger
657
- );
658
- return electronInstall.install();
376
+ return new ElectronInstall(this).install();
659
377
  }
660
378
  /**
661
379
  * 启动 Electron
@@ -700,31 +418,15 @@ class LocalAutomateTask {
700
418
  * @returns
701
419
  */
702
420
  async close() {
703
- this.logger.close();
421
+ this.logger.info("\u5173\u95ED\u5E94\u7528");
704
422
  this.clearTmpPath();
705
- const electronApp = await this.launchApp();
706
- return electronApp.close();
423
+ this.logger.close();
424
+ await this._electronApp?.close();
425
+ this.isClosed = true;
426
+ this._electronApp = null;
707
427
  }
708
- /**
709
- * 小红书自动化发布
710
- */
711
- async xiaohongshuPublish(params) {
712
- this.logger.info("\u5F00\u59CB\u5C0F\u7EA2\u4E66\u53D1\u5E03");
428
+ async createPage(pageParams) {
713
429
  const electronApp = await this.launchApp();
714
- this.logger.info("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u4E13\u7528\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8");
715
- const commonCookies = {
716
- path: "/",
717
- sameSite: "lax",
718
- secure: false,
719
- domain: "xiaohongshu.com",
720
- url: "https://creator.xiaohongshu.com",
721
- httpOnly: true
722
- };
723
- const pageParams = {
724
- show: this.debug,
725
- url: params.url || "https://creator.xiaohongshu.com/publish/publish",
726
- cookies: params.cookies?.map((it) => Object.assign(commonCookies, it)) || []
727
- };
728
430
  const [page] = await Promise.all([
729
431
  electronApp.waitForEvent("window"),
730
432
  electronApp.evaluate(
@@ -751,38 +453,34 @@ class LocalAutomateTask {
751
453
  { pageParams }
752
454
  )
753
455
  ]);
754
- this.logger.info("\u5DF2\u6253\u5F00\u5C0F\u7EA2\u4E66\u53D1\u5E03\u9875\u9762");
456
+ return page;
457
+ }
458
+ }
459
+
460
+ var __defProp = Object.defineProperty;
461
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
462
+ var __publicField = (obj, key, value) => {
463
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
464
+ return value;
465
+ };
466
+ class RpaTask extends Task {
467
+ constructor(params) {
468
+ super(params);
469
+ __publicField(this, "actions");
470
+ this.actions = new Action(this);
471
+ params.forceUpdate && this.update();
472
+ }
473
+ async update() {
755
474
  try {
756
- const res = await xiaohongshuPublishAction({
757
- page,
758
- params,
759
- tmpCachePath: this.getTmpPath(),
760
- debug: !!this.debug
761
- });
762
- this.logger.info(`\u5C0F\u7EA2\u4E66\u53D1\u5E03\u6210\u529F\uFF1A${res}`);
763
- return res;
475
+ const name = "@iflyrpa/actions";
476
+ const version2 = await this.packageManager.update(name);
477
+ const actionPackage = this.packageManager.require(`${name}@${version2}`);
478
+ actionPackage?.actions && (this.actions = actionPackage.actions);
764
479
  } catch (error) {
765
- this.logger.error("\u5C0F\u7EA2\u4E66\u53D1\u5E03\u5931\u8D25", error);
766
- throw error;
480
+ this.logger.error("\u66F4\u65B0\u4F9D\u8D56\u5931\u8D25", error);
767
481
  }
768
482
  }
769
483
  }
770
- const RpaTask = (params) => {
771
- const logger = Logger.getInstance(params.cachePath);
772
- if (params.forceUpdate) {
773
- logger.info("\u5C1D\u8BD5\u4F7F\u7528\u8FDC\u7A0B\u6700\u65B0\u7248\u672C");
774
- const packageManager = new PackageManager({
775
- packageName: packageJson.name,
776
- cacheDir: params.cachePath
777
- });
778
- const localPackge = packageManager.getPlugin(packageJson.name);
779
- if (localPackge?.LocalAutomateTask && localPackge?.version && semver.gt(localPackge.version, packageJson.version)) {
780
- logger.info(`\u4F7F\u7528\u8FDC\u7A0B\u7684\u65B0\u7248\u672C\uFF0C\u7248\u672C\u53F7\u4E3A\uFF1A${localPackge.version}`);
781
- return new localPackge.LocalAutomateTask(params);
782
- }
783
- }
784
- return new LocalAutomateTask(params);
785
- };
786
484
  const version = packageJson.version;
787
485
 
788
- export { LocalAutomateTask, RpaTask, version };
486
+ export { RpaTask, version };