@iflyrpa/playwright 1.0.15 → 1.1.0

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