@weapp-vite/miniprogram-automator 1.2.3 → 1.2.5

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.d.mts CHANGED
@@ -54,7 +54,7 @@ declare class Connection extends EventEmitter {
54
54
  dispose(): void;
55
55
  private onMessage;
56
56
  private onClose;
57
- static create(url: string): Promise<Connection>;
57
+ static create(url: string, timeout?: number): Promise<Connection>;
58
58
  }
59
59
  //#endregion
60
60
  //#region src/Native.d.ts
@@ -232,6 +232,7 @@ declare class Page {
232
232
  //#region src/MiniProgram.d.ts
233
233
  interface IScreenshotOptions {
234
234
  path?: string;
235
+ timeout?: number;
235
236
  }
236
237
  interface IAuditsOptions {
237
238
  path?: string;
@@ -251,6 +252,7 @@ interface CurrentPageOptions {
251
252
  declare class MiniProgram extends EventEmitter {
252
253
  private connection;
253
254
  private appBindings;
255
+ private logEnabled;
254
256
  private pageMap;
255
257
  private nativeIns?;
256
258
  constructor(connection: Connection);
@@ -274,6 +276,7 @@ declare class MiniProgram extends EventEmitter {
274
276
  close(): Promise<void>;
275
277
  remote(auto?: boolean): Promise<void>;
276
278
  disconnect(): void;
279
+ enableLog(): Promise<void>;
277
280
  on(event: string | symbol, listener: (...args: any[]) => void): this;
278
281
  exposeFunction(name: string, bindingFunction: AutomatorCallable): Promise<void>;
279
282
  checkVersion(): Promise<void>;
@@ -281,7 +284,7 @@ declare class MiniProgram extends EventEmitter {
281
284
  * @description 等待小程序 App 域协议可用,避免返回半就绪自动化会话。
282
285
  */
283
286
  waitForAppReady(timeout?: number): Promise<void>;
284
- screenshot(options?: IScreenshotOptions): Promise<any>;
287
+ screenshot(options?: IScreenshotOptions): Promise<string | undefined>;
285
288
  testAccounts(): Promise<any>;
286
289
  /**
287
290
  * @description 获取开发者工具 Tool 域基础信息。
@@ -413,7 +416,7 @@ declare class SmartappApp {
413
416
  retry?: number;
414
417
  timeout?: number;
415
418
  }): Promise<SmartappPage>;
416
- screenshot(options?: ScreenshotOptions): Promise<any>;
419
+ screenshot(options?: ScreenshotOptions): Promise<string | undefined>;
417
420
  currentPage(): Promise<SmartappPage>;
418
421
  data(): Promise<any>;
419
422
  tabs(): Promise<never[]>;
@@ -488,6 +491,7 @@ declare function normalizePlatform(platform?: MiniprogramAutomatorPlatform): Nor
488
491
  //#region src/Launcher.d.ts
489
492
  interface IConnectOptions {
490
493
  wsEndpoint: string;
494
+ timeout?: number;
491
495
  platform?: MiniprogramAutomatorPlatform;
492
496
  }
493
497
  /** ILaunchOptions 的类型定义。 */
package/dist/index.mjs CHANGED
@@ -503,6 +503,7 @@ var Transport = class extends EventEmitter {
503
503
  const debugProtocol = createDebug("automator:protocol");
504
504
  const closeErrTip = "Connection closed, check if wechat web devTools is still running";
505
505
  const REQUEST_TIMEOUT = 3e4;
506
+ const CONNECT_TIMEOUT = 3e4;
506
507
  /** Connection 的实现。 */
507
508
  var Connection = class Connection extends EventEmitter {
508
509
  transport;
@@ -571,20 +572,35 @@ var Connection = class Connection extends EventEmitter {
571
572
  }
572
573
  this.callbacks.clear();
573
574
  };
574
- static create(url) {
575
+ static create(url, timeout = CONNECT_TIMEOUT) {
575
576
  return new Promise((resolve, reject) => {
576
577
  const ws = new WebSocket(url);
578
+ let settled = false;
579
+ const timer = setTimeout(() => {
580
+ if (settled) return;
581
+ settled = true;
582
+ ws.close();
583
+ reject(/* @__PURE__ */ new Error(`Timed out connecting to DevTools websocket ${url} after ${timeout}ms`));
584
+ }, timeout);
577
585
  ws.on("open", () => {
586
+ if (settled) return;
587
+ settled = true;
588
+ clearTimeout(timer);
578
589
  resolve(new Connection(new Transport(ws)));
579
590
  });
580
- ws.on("error", reject);
591
+ ws.on("error", (error) => {
592
+ if (settled) return;
593
+ settled = true;
594
+ clearTimeout(timer);
595
+ reject(error);
596
+ });
581
597
  });
582
598
  }
583
599
  };
584
600
  //#endregion
585
601
  //#region src/headless.ts
586
602
  async function launchHeadlessAutomator(options) {
587
- return await (await import("./launch-2X75zDRY.mjs")).launch({ projectPath: options.projectPath });
603
+ return await (await import("./launch-mRKloPOa.mjs")).launch({ projectPath: options.projectPath });
588
604
  }
589
605
  //#endregion
590
606
  //#region src/launcher/portLease.ts
@@ -683,7 +699,7 @@ async function acquireAutomatorPortLease(preferredPort) {
683
699
  }
684
700
  //#endregion
685
701
  //#region package.json
686
- var version = "1.2.3";
702
+ var version = "1.2.5";
687
703
  //#endregion
688
704
  //#region src/Native.ts
689
705
  /** Native 的实现。 */
@@ -885,6 +901,8 @@ const CHANGE_ROUTE_POLL_DELAY = 500;
885
901
  const APP_READY_TIMEOUT = 2e4;
886
902
  const APP_READY_PROBE_TIMEOUT = 3e3;
887
903
  const APP_READY_POLL_DELAY = 500;
904
+ const SCREENSHOT_RETRIES = 2;
905
+ const SCREENSHOT_RETRY_DELAY = 500;
888
906
  const CHANGE_ROUTE_DEBUG_ENABLED = process.env.WEAPP_VITE_E2E_CHANGE_ROUTE_DEBUG === "1";
889
907
  function sleep(ms) {
890
908
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -920,6 +938,11 @@ function isPageStackProtocolTimeout(error) {
920
938
  function isCallWxMethodProtocolTimeout(error) {
921
939
  return error instanceof Error && "code" in error && error.code === "DEVTOOLS_PROTOCOL_TIMEOUT" && "method" in error && error.method === "App.callWxMethod";
922
940
  }
941
+ function isCaptureScreenshotRecoverableError(error) {
942
+ if (!(error instanceof Error)) return false;
943
+ if ("code" in error && error.code === "DEVTOOLS_PROTOCOL_TIMEOUT" && "method" in error && error.method === "App.captureScreenshot") return true;
944
+ return error.message.includes("fail to capture screenshot") || error.message.includes("App.captureScreenshot");
945
+ }
923
946
  function isRouteContextProbeError(error) {
924
947
  return isCurrentPageProtocolTimeout(error) || isPageStackProtocolTimeout(error);
925
948
  }
@@ -934,6 +957,7 @@ function logChangeRouteDebug(message) {
934
957
  var MiniProgram = class extends EventEmitter {
935
958
  connection;
936
959
  appBindings = /* @__PURE__ */ new Map();
960
+ logEnabled = false;
937
961
  pageMap = /* @__PURE__ */ new Map();
938
962
  nativeIns;
939
963
  constructor(connection) {
@@ -1098,8 +1122,12 @@ var MiniProgram = class extends EventEmitter {
1098
1122
  disconnect() {
1099
1123
  this.connection.dispose();
1100
1124
  }
1125
+ async enableLog() {
1126
+ await this.send("App.enableLog");
1127
+ this.logEnabled = true;
1128
+ }
1101
1129
  on(event, listener) {
1102
- if (event === "console") this.send("App.enableLog").catch(() => {});
1130
+ if (event === "console" && !this.logEnabled) this.enableLog().catch(() => {});
1103
1131
  super.on(event, listener);
1104
1132
  return this;
1105
1133
  }
@@ -1128,9 +1156,20 @@ var MiniProgram = class extends EventEmitter {
1128
1156
  throw lastError instanceof Error ? lastError : /* @__PURE__ */ new Error(`Timed out waiting App domain readiness after ${timeout}ms`);
1129
1157
  }
1130
1158
  async screenshot(options = {}) {
1131
- const { data } = await this.send("App.captureScreenshot");
1132
- if (!options.path) return data;
1133
- await fs.writeFile(options.path, data, "base64");
1159
+ const sendOptions = options.timeout ? { timeout: options.timeout } : void 0;
1160
+ let lastError;
1161
+ let data;
1162
+ for (let attempt = 1; attempt <= SCREENSHOT_RETRIES; attempt += 1) try {
1163
+ data = (await this.send("App.captureScreenshot", {}, sendOptions)).data;
1164
+ if (!options.path) return data;
1165
+ await fs.writeFile(options.path, data, "base64");
1166
+ return;
1167
+ } catch (error) {
1168
+ lastError = error;
1169
+ if (!isCaptureScreenshotRecoverableError(error) || attempt === SCREENSHOT_RETRIES) throw error;
1170
+ await sleep(SCREENSHOT_RETRY_DELAY);
1171
+ }
1172
+ throw lastError;
1134
1173
  }
1135
1174
  async testAccounts() {
1136
1175
  return (await this.send("Tool.getTestAccounts")).accounts;
@@ -1860,7 +1899,10 @@ var Launcher = class {
1860
1899
  await waitUntil(async () => {
1861
1900
  try {
1862
1901
  if (processError) return true;
1863
- const candidate = await this.connectTool({ wsEndpoint: `ws://127.0.0.1:${port}` });
1902
+ const candidate = await this.connectTool({
1903
+ timeout: 3e3,
1904
+ wsEndpoint: `ws://127.0.0.1:${port}`
1905
+ });
1864
1906
  try {
1865
1907
  await candidate.checkVersion();
1866
1908
  if (typeof candidate.waitForAppReady === "function") await candidate.waitForAppReady(timeout);
@@ -1912,7 +1954,7 @@ var Launcher = class {
1912
1954
  }
1913
1955
  async connectTool(options) {
1914
1956
  try {
1915
- return new MiniProgram(await Connection.create(options.wsEndpoint));
1957
+ return new MiniProgram(await Connection.create(options.wsEndpoint, options.timeout));
1916
1958
  } catch {
1917
1959
  throw new Error(`Failed connecting to ${options.wsEndpoint}, check if target project window is opened with automation enabled`);
1918
1960
  }
@@ -437,7 +437,7 @@ function createPageInstance(route, definition, options = {}, pageState = {}) {
437
437
  }
438
438
  //#endregion
439
439
  //#region ../../node_modules/.pnpm/entities@8.0.0/node_modules/entities/dist/decode-codepoint.js
440
- const decodeMap = new Map([
440
+ const decodeMap = /* @__PURE__ */ new Map([
441
441
  [0, 65533],
442
442
  [128, 8364],
443
443
  [130, 8218],
@@ -952,7 +952,7 @@ var QuoteType;
952
952
  * sequences with an increased offset.
953
953
  */
954
954
  const Sequences = {
955
- Empty: new Uint8Array(0),
955
+ Empty: /* @__PURE__ */ new Uint8Array(0),
956
956
  Cdata: new Uint8Array([
957
957
  67,
958
958
  68,
@@ -1081,7 +1081,7 @@ const Sequences = {
1081
1081
  * where index 2 is the first tag-name character, so matching always
1082
1082
  * continues from offset 3.
1083
1083
  */
1084
- const specialStartSequences = new Map([
1084
+ const specialStartSequences = /* @__PURE__ */ new Map([
1085
1085
  [Sequences.IframeEnd[2], Sequences.IframeEnd],
1086
1086
  [Sequences.NoembedEnd[2], Sequences.NoembedEnd],
1087
1087
  [Sequences.Plaintext[2], Sequences.Plaintext],
@@ -1773,7 +1773,7 @@ var Tokenizer = class {
1773
1773
  //#endregion
1774
1774
  //#region ../../node_modules/.pnpm/htmlparser2@12.0.0/node_modules/htmlparser2/dist/Parser.js
1775
1775
  const { fromCodePoint } = String;
1776
- const formTags = new Set([
1776
+ const formTags = /* @__PURE__ */ new Set([
1777
1777
  "input",
1778
1778
  "option",
1779
1779
  "optgroup",
@@ -1782,8 +1782,8 @@ const formTags = new Set([
1782
1782
  "datalist",
1783
1783
  "textarea"
1784
1784
  ]);
1785
- const pTag = new Set(["p"]);
1786
- const headingTags = new Set([
1785
+ const pTag = /* @__PURE__ */ new Set(["p"]);
1786
+ const headingTags = /* @__PURE__ */ new Set([
1787
1787
  "h1",
1788
1788
  "h2",
1789
1789
  "h3",
@@ -1792,28 +1792,28 @@ const headingTags = new Set([
1792
1792
  "h6",
1793
1793
  "p"
1794
1794
  ]);
1795
- const tableSectionTags = new Set(["thead", "tbody"]);
1796
- const ddtTags = new Set(["dd", "dt"]);
1797
- const rtpTags = new Set(["rt", "rp"]);
1798
- const openImpliesClose = new Map([
1799
- ["tr", new Set([
1795
+ const tableSectionTags = /* @__PURE__ */ new Set(["thead", "tbody"]);
1796
+ const ddtTags = /* @__PURE__ */ new Set(["dd", "dt"]);
1797
+ const rtpTags = /* @__PURE__ */ new Set(["rt", "rp"]);
1798
+ const openImpliesClose = /* @__PURE__ */ new Map([
1799
+ ["tr", /* @__PURE__ */ new Set([
1800
1800
  "tr",
1801
1801
  "th",
1802
1802
  "td"
1803
1803
  ])],
1804
- ["th", new Set(["th"])],
1805
- ["td", new Set([
1804
+ ["th", /* @__PURE__ */ new Set(["th"])],
1805
+ ["td", /* @__PURE__ */ new Set([
1806
1806
  "thead",
1807
1807
  "th",
1808
1808
  "td"
1809
1809
  ])],
1810
- ["body", new Set([
1810
+ ["body", /* @__PURE__ */ new Set([
1811
1811
  "head",
1812
1812
  "link",
1813
1813
  "script"
1814
1814
  ])],
1815
- ["a", new Set(["a"])],
1816
- ["li", new Set(["li"])],
1815
+ ["a", /* @__PURE__ */ new Set(["a"])],
1816
+ ["li", /* @__PURE__ */ new Set(["li"])],
1817
1817
  ["p", pTag],
1818
1818
  ["h1", headingTags],
1819
1819
  ["h2", headingTags],
@@ -1827,8 +1827,8 @@ const openImpliesClose = new Map([
1827
1827
  ["button", formTags],
1828
1828
  ["datalist", formTags],
1829
1829
  ["textarea", formTags],
1830
- ["option", new Set(["option"])],
1831
- ["optgroup", new Set(["optgroup", "option"])],
1830
+ ["option", /* @__PURE__ */ new Set(["option"])],
1831
+ ["optgroup", /* @__PURE__ */ new Set(["optgroup", "option"])],
1832
1832
  ["dd", ddtTags],
1833
1833
  ["dt", ddtTags],
1834
1834
  ["address", pTag],
@@ -1858,7 +1858,7 @@ const openImpliesClose = new Map([
1858
1858
  ["tfoot", tableSectionTags]
1859
1859
  ]);
1860
1860
  const DOCUMENT_TYPE = "doctype";
1861
- const voidElements = new Set([
1861
+ const voidElements = /* @__PURE__ */ new Set([
1862
1862
  "area",
1863
1863
  "base",
1864
1864
  "basefont",
@@ -1879,14 +1879,14 @@ const voidElements = new Set([
1879
1879
  "track",
1880
1880
  "wbr"
1881
1881
  ]);
1882
- const foreignContextElements = new Set(["math", "svg"]);
1882
+ const foreignContextElements = /* @__PURE__ */ new Set(["math", "svg"]);
1883
1883
  /**
1884
1884
  * Elements that can be used to integrate HTML content within foreign namespaces (e.g., SVG or MathML).
1885
1885
  *
1886
1886
  * Entries must use the SVG-adjusted casing (e.g. "foreignObject" not
1887
1887
  * "foreignobject") since they are compared against adjusted tag names.
1888
1888
  */
1889
- const htmlIntegrationElements = new Set([
1889
+ const htmlIntegrationElements = /* @__PURE__ */ new Set([
1890
1890
  "mi",
1891
1891
  "mo",
1892
1892
  "mn",
@@ -1897,7 +1897,7 @@ const htmlIntegrationElements = new Set([
1897
1897
  "desc",
1898
1898
  "title"
1899
1899
  ]);
1900
- const svgTagNameAdjustments = new Map([
1900
+ const svgTagNameAdjustments = /* @__PURE__ */ new Map([
1901
1901
  ["altglyph", "altGlyph"],
1902
1902
  ["altglyphdef", "altGlyphDef"],
1903
1903
  ["altglyphitem", "altGlyphItem"],
@@ -2865,7 +2865,7 @@ const STRUCTURAL_ATTRS = [
2865
2865
  "wx:for-index",
2866
2866
  "wx:key"
2867
2867
  ];
2868
- const WX_ELSE_ATTRS = new Set(["wx:elif", "wx:else"]);
2868
+ const WX_ELSE_ATTRS = /* @__PURE__ */ new Set(["wx:elif", "wx:else"]);
2869
2869
  const CLASS_SPLIT_RE = /\s+/;
2870
2870
  const JS_FILE_RE = /\.js$/;
2871
2871
  function isMustacheOnly(value) {
@@ -5262,7 +5262,7 @@ const SAVED_FILE_PREFIXES = ["headless://saved/", "headless://wxfile/saved/"];
5262
5262
  const textEncoder = new TextEncoder();
5263
5263
  const IMAGE_EXTENSION_RE = /\.([^.?#/]+)(?:[?#].*)?$/;
5264
5264
  const LEADING_DOT_RE = /^\.+/;
5265
- const IMAGE_FILE_EXTENSIONS = new Set([
5265
+ const IMAGE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
5266
5266
  "bmp",
5267
5267
  "gif",
5268
5268
  "heic",
@@ -5271,7 +5271,7 @@ const IMAGE_FILE_EXTENSIONS = new Set([
5271
5271
  "png",
5272
5272
  "webp"
5273
5273
  ]);
5274
- const VIDEO_FILE_EXTENSIONS = new Set([
5274
+ const VIDEO_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
5275
5275
  "avi",
5276
5276
  "m4v",
5277
5277
  "mov",
@@ -7547,7 +7547,7 @@ var HeadlessSession = class {
7547
7547
  };
7548
7548
  }
7549
7549
  unloadAllPages() {
7550
- const pagesToUnload = new Set([...this.pages, ...this.tabPages.values()]);
7550
+ const pagesToUnload = /* @__PURE__ */ new Set([...this.pages, ...this.tabPages.values()]);
7551
7551
  for (const page of [...pagesToUnload].reverse()) this.unloadPage(page);
7552
7552
  this.pages.length = 0;
7553
7553
  this.tabPages.clear();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@weapp-vite/miniprogram-automator",
3
3
  "type": "module",
4
- "version": "1.2.3",
4
+ "version": "1.2.5",
5
5
  "description": "完全兼容微信 miniprogram-automator 的现代化替代实现",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/ws": "^8.18.1",
54
- "sharp": "^0.35.1"
54
+ "sharp": "^0.35.2"
55
55
  },
56
56
  "scripts": {
57
57
  "dev": "tsdown -w --sourcemap",