weapp-ide-cli 5.1.2 → 5.1.3

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.
@@ -1,9 +1,11 @@
1
- import net from "node:net";
2
- import automator from "miniprogram-automator";
3
- import process from "node:process";
1
+ import { Launcher } from "@weapp-vite/miniprogram-automator";
2
+ import fs from "fs-extra";
4
3
  import logger, { colors } from "@weapp-core/logger";
4
+ import os from "node:os";
5
+ import process from "node:process";
6
+ import path from "pathe";
5
7
  import { Buffer as Buffer$1 } from "node:buffer";
6
- import fs from "node:fs/promises";
8
+ import fs$1 from "node:fs/promises";
7
9
  //#region \0rolldown/runtime.js
8
10
  var __defProp = Object.defineProperty;
9
11
  var __exportAll = (all, no_symbols) => {
@@ -16,7 +18,232 @@ var __exportAll = (all, no_symbols) => {
16
18
  return target;
17
19
  };
18
20
  //#endregion
21
+ //#region src/logger.ts
22
+ var logger_default = logger;
23
+ //#endregion
24
+ //#region src/runtime/platform.ts
25
+ /**
26
+ * @description 官方微信开发者工具只支持 Windows、macOS,Linux 只有社区版
27
+ * https://github.com/msojocs/wechat-web-devtools-linux
28
+ */
29
+ const SupportedPlatformsMap = {
30
+ Windows_NT: "Windows_NT",
31
+ Darwin: "Darwin",
32
+ Linux: "Linux"
33
+ };
34
+ /**
35
+ * @description 判断当前系统是否支持微信开发者工具
36
+ */
37
+ function isOperatingSystemSupported(osName = os.type()) {
38
+ return osName === SupportedPlatformsMap.Windows_NT || osName === SupportedPlatformsMap.Darwin || osName === SupportedPlatformsMap.Linux;
39
+ }
40
+ /**
41
+ * @description 当前系统名称
42
+ */
43
+ const operatingSystemName = os.type();
44
+ function createLinuxCliResolver() {
45
+ let resolvedPath;
46
+ let attempted = false;
47
+ let pending = null;
48
+ return async () => {
49
+ if (attempted) return resolvedPath;
50
+ if (!pending) pending = (async () => {
51
+ try {
52
+ const envPath = await getFirstBinaryPath("wechat-devtools-cli");
53
+ if (envPath) resolvedPath = envPath;
54
+ } catch (error) {
55
+ const reason = error instanceof Error ? error.message : String(error);
56
+ logger_default.warn(`获取 Linux wechat-devtools-cli 路径失败:${reason}`);
57
+ } finally {
58
+ attempted = true;
59
+ }
60
+ return resolvedPath;
61
+ })();
62
+ return pending;
63
+ };
64
+ }
65
+ const linuxCliResolver = createLinuxCliResolver();
66
+ const WINDOWS_DEFAULT_CLI = "C:\\Program Files (x86)\\Tencent\\微信web开发者工具\\cli.bat";
67
+ const DARWIN_DEFAULT_CLI = "/Applications/wechatwebdevtools.app/Contents/MacOS/cli";
68
+ const cliPathResolvers = {
69
+ [SupportedPlatformsMap.Windows_NT]: async () => WINDOWS_DEFAULT_CLI,
70
+ [SupportedPlatformsMap.Darwin]: async () => DARWIN_DEFAULT_CLI,
71
+ [SupportedPlatformsMap.Linux]: linuxCliResolver
72
+ };
73
+ /**
74
+ * @description 获取默认 CLI 路径(按系统)
75
+ */
76
+ async function getDefaultCliPath(targetOs = operatingSystemName) {
77
+ if (!isOperatingSystemSupported(targetOs)) return;
78
+ const resolver = cliPathResolvers[targetOs];
79
+ return await resolver();
80
+ }
81
+ async function getFirstBinaryPath(command) {
82
+ const pathDirs = (process.env.PATH || "").split(path.delimiter);
83
+ for (const dir of pathDirs) {
84
+ const fullPath = path.join(dir, command);
85
+ try {
86
+ await fs.access(fullPath, fs.constants.X_OK);
87
+ return fullPath;
88
+ } catch {
89
+ continue;
90
+ }
91
+ }
92
+ }
93
+ //#endregion
94
+ //#region src/utils/path.ts
95
+ /**
96
+ * @description 解析为绝对路径(基于当前工作目录)
97
+ */
98
+ function resolvePath(filePath) {
99
+ if (path.isAbsolute(filePath)) return filePath;
100
+ return path.resolve(process.cwd(), filePath);
101
+ }
102
+ //#endregion
103
+ //#region src/config/paths.ts
104
+ const homedir = os.homedir();
105
+ /**
106
+ * @description 默认自定义配置目录
107
+ */
108
+ const defaultCustomConfigDirPath = path.join(homedir, ".weapp-ide-cli");
109
+ /**
110
+ * @description 默认自定义配置文件路径
111
+ */
112
+ const defaultCustomConfigFilePath = path.join(defaultCustomConfigDirPath, "config.json");
113
+ //#endregion
114
+ //#region src/config/custom.ts
115
+ const JSON_OPTIONS = {
116
+ encoding: "utf8",
117
+ spaces: 2
118
+ };
119
+ /**
120
+ * @description 写入自定义 CLI 路径配置
121
+ */
122
+ async function createCustomConfig(params) {
123
+ const trimmedCliPath = params.cliPath.trim();
124
+ if (!trimmedCliPath) throw new Error("cliPath cannot be empty");
125
+ const normalizedCliPath = resolvePath(trimmedCliPath);
126
+ await writeCustomConfig({ cliPath: normalizedCliPath });
127
+ return normalizedCliPath;
128
+ }
129
+ /**
130
+ * @description 写入语言配置(zh / en)。
131
+ */
132
+ async function createLocaleConfig(locale) {
133
+ await writeCustomConfig({ locale });
134
+ return locale;
135
+ }
136
+ /**
137
+ * @description 删除指定配置项。
138
+ */
139
+ async function removeCustomConfigKey(key) {
140
+ const currentConfig = await readCustomConfig();
141
+ if (!(key in currentConfig)) return;
142
+ const nextConfig = { ...currentConfig };
143
+ delete nextConfig[key];
144
+ await writeCustomConfig(nextConfig, { replace: true });
145
+ }
146
+ /**
147
+ * @description 覆盖写入配置内容(会替换原内容)。
148
+ */
149
+ async function overwriteCustomConfig(config) {
150
+ const nextConfig = {};
151
+ if (typeof config.cliPath === "string" && config.cliPath.trim()) nextConfig.cliPath = resolvePath(config.cliPath.trim());
152
+ if (config.locale === "zh" || config.locale === "en") nextConfig.locale = config.locale;
153
+ await writeCustomConfig(nextConfig, { replace: true });
154
+ }
155
+ /**
156
+ * @description 读取原始自定义配置。
157
+ */
158
+ async function readCustomConfig() {
159
+ if (!await fs.pathExists(defaultCustomConfigFilePath)) return {};
160
+ try {
161
+ const config = await fs.readJSON(defaultCustomConfigFilePath);
162
+ if (!config || typeof config !== "object") return {};
163
+ const candidate = config;
164
+ const next = {};
165
+ if (typeof candidate.cliPath === "string" && candidate.cliPath.trim()) next.cliPath = candidate.cliPath.trim();
166
+ if (candidate.locale === "zh" || candidate.locale === "en") next.locale = candidate.locale;
167
+ return next;
168
+ } catch {
169
+ return {};
170
+ }
171
+ }
172
+ async function writeCustomConfig(patch, options = {}) {
173
+ const nextConfig = {
174
+ ...options.replace ? {} : await readCustomConfig(),
175
+ ...patch
176
+ };
177
+ await fs.ensureDir(defaultCustomConfigDirPath);
178
+ await fs.writeJSON(defaultCustomConfigFilePath, nextConfig, JSON_OPTIONS);
179
+ }
180
+ //#endregion
181
+ //#region src/config/resolver.ts
182
+ /**
183
+ * @description 读取并解析 CLI 配置(自定义优先)
184
+ */
185
+ async function getConfig() {
186
+ if (await fs.pathExists(defaultCustomConfigFilePath)) try {
187
+ const config = await fs.readJSON(defaultCustomConfigFilePath);
188
+ const cliPath = typeof config.cliPath === "string" ? config.cliPath.trim() : "";
189
+ const locale = config.locale === "zh" || config.locale === "en" ? config.locale : void 0;
190
+ if (cliPath) {
191
+ logger_default.info(`全局配置文件路径:${colors.green(defaultCustomConfigFilePath)}`);
192
+ logger_default.info(`自定义 CLI 路径:${colors.green(cliPath)}`);
193
+ return {
194
+ cliPath,
195
+ locale,
196
+ source: "custom"
197
+ };
198
+ }
199
+ logger_default.warn("自定义配置文件缺少有效的 CLI 路径,将尝试使用默认路径。");
200
+ } catch (error) {
201
+ const reason = error instanceof Error ? error.message : String(error);
202
+ logger_default.warn(`解析自定义配置失败,将尝试使用默认路径。原因:${reason}`);
203
+ }
204
+ const fallbackPath = await getDefaultCliPath();
205
+ if (fallbackPath) return {
206
+ cliPath: fallbackPath,
207
+ locale: void 0,
208
+ source: "default"
209
+ };
210
+ return {
211
+ cliPath: "",
212
+ locale: void 0,
213
+ source: "missing"
214
+ };
215
+ }
216
+ /**
217
+ * @description 获取用户配置的语言偏好。
218
+ */
219
+ async function getConfiguredLocale() {
220
+ return (await readCustomConfig()).locale;
221
+ }
222
+ //#endregion
223
+ //#region src/cli/resolver.ts
224
+ /**
225
+ * @description 解析 CLI 路径并校验可用性
226
+ */
227
+ async function resolveCliPath() {
228
+ const config = await getConfig();
229
+ if (!config.cliPath) return {
230
+ cliPath: null,
231
+ source: config.source
232
+ };
233
+ return {
234
+ cliPath: await fs.pathExists(config.cliPath) ? config.cliPath : null,
235
+ source: config.source
236
+ };
237
+ }
238
+ //#endregion
19
239
  //#region src/cli/automator.ts
240
+ const ERROR_STACK_PREFIX_RE = /^at /;
241
+ const ERROR_PREFIX_RE = /^\[error\]\s*/i;
242
+ const ERROR_LABEL_PREFIX_RE = /^error\s*:\s*/i;
243
+ const ERROR_LINE_SPLIT_RE = /\r?\n/;
244
+ const LOGIN_REQUIRED_CN_RE = /需要重新登录/;
245
+ const LOGIN_REQUIRED_EN_RE = /need\s+re-?login|re-?login/i;
246
+ const LOGIN_REQUIRED_CODE_RE = /code\s*[:=]\s*(\d+)/i;
20
247
  const DEVTOOLS_HTTP_PORT_ERROR = "Failed to launch wechat web devTools, please make sure http port is open";
21
248
  const DEVTOOLS_INFRA_ERROR_PATTERNS = [
22
249
  /listen EPERM/i,
@@ -31,57 +258,40 @@ const DEVTOOLS_LOGIN_REQUIRED_PATTERNS = [
31
258
  /need\s+re-?login/i,
32
259
  /re-?login/i
33
260
  ];
34
- let localhostListenPatched = false;
35
- function patchNetListenToLoopback() {
36
- if (localhostListenPatched) return;
37
- localhostListenPatched = true;
38
- const rawListen = net.Server.prototype.listen;
39
- net.Server.prototype.listen = function patchedListen(...args) {
40
- const firstArg = args[0];
41
- if (firstArg && typeof firstArg === "object" && !Array.isArray(firstArg)) {
42
- if (!("host" in firstArg) || !firstArg.host) args[0] = {
43
- ...firstArg,
44
- host: "127.0.0.1"
45
- };
46
- return rawListen.apply(this, args);
47
- }
48
- if ((typeof firstArg === "number" || typeof firstArg === "string") && typeof args[1] !== "string") args.splice(1, 0, "127.0.0.1");
49
- return rawListen.apply(this, args);
50
- };
51
- }
52
261
  /**
53
- * @description Extract error text from various error types
262
+ * @description 从错误对象中提取可读文本。
54
263
  */
55
264
  function extractErrorText(error) {
56
265
  if (!error || typeof error !== "object") return "";
57
- const parts = [];
58
266
  const candidate = error;
59
- for (const field of [
267
+ return [
60
268
  candidate.message,
61
269
  candidate.shortMessage,
62
270
  candidate.stderr,
63
271
  candidate.stdout
64
- ]) if (typeof field === "string" && field.trim()) parts.push(field);
65
- return parts.join("\n");
272
+ ].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n");
66
273
  }
274
+ /**
275
+ * @description 提取登录失效时最适合展示给用户的一行信息。
276
+ */
67
277
  function extractLoginRequiredMessage(text) {
68
278
  if (!text) return "";
69
- if (/需要重新登录/.test(text)) return "需要重新登录";
70
- const englishMatch = text.match(/need\s+re-?login|re-?login/i);
279
+ if (LOGIN_REQUIRED_CN_RE.test(text)) return "需要重新登录";
280
+ const englishMatch = text.match(LOGIN_REQUIRED_EN_RE);
71
281
  if (englishMatch?.[0]) return englishMatch[0].toLowerCase();
72
- const firstLine = text.split(/\r?\n/).map((line) => line.trim()).find((line) => Boolean(line) && !line.startsWith("at "));
282
+ const firstLine = text.split(ERROR_LINE_SPLIT_RE).map((line) => line.trim()).find((line) => Boolean(line) && !ERROR_STACK_PREFIX_RE.test(line));
73
283
  if (!firstLine) return "";
74
- return firstLine.replace(/^\[error\]\s*/i, "").replace(/^error\s*:\s*/i, "").slice(0, 120);
284
+ return firstLine.replace(ERROR_PREFIX_RE, "").replace(ERROR_LABEL_PREFIX_RE, "").slice(0, 120);
75
285
  }
76
286
  /**
77
- * @description Check if error is a DevTools HTTP port error
287
+ * @description 判断错误是否属于开发者工具服务端口不可用。
78
288
  */
79
289
  function isDevtoolsHttpPortError(error) {
80
290
  const message = error instanceof Error ? error.message : String(error);
81
291
  return message.includes(DEVTOOLS_HTTP_PORT_ERROR) || DEVTOOLS_INFRA_ERROR_PATTERNS.some((pattern) => pattern.test(message));
82
292
  }
83
293
  /**
84
- * @description Check if error is a login required error
294
+ * @description 判断错误是否属于开发者工具登录失效。
85
295
  */
86
296
  function isAutomatorLoginError(error) {
87
297
  const text = extractErrorText(error);
@@ -89,11 +299,11 @@ function isAutomatorLoginError(error) {
89
299
  return DEVTOOLS_LOGIN_REQUIRED_PATTERNS.some((pattern) => pattern.test(text));
90
300
  }
91
301
  /**
92
- * @description Format login error for display
302
+ * @description 格式化开发者工具登录失效错误,便于终端展示。
93
303
  */
94
304
  function formatAutomatorLoginError(error) {
95
305
  const text = extractErrorText(error);
96
- const code = text.match(/code\s*[:=]\s*(\d+)/i)?.[1];
306
+ const code = text.match(LOGIN_REQUIRED_CODE_RE)?.[1];
97
307
  const message = extractLoginRequiredMessage(text);
98
308
  const lines = ["微信开发者工具返回登录错误:"];
99
309
  if (code) lines.push(`- code: ${code}`);
@@ -102,12 +312,13 @@ function formatAutomatorLoginError(error) {
102
312
  return lines.join("\n");
103
313
  }
104
314
  /**
105
- * @description Launch automator with default options
315
+ * @description 基于当前配置解析 CLI 路径,并通过现代化 automator 入口启动会话。
106
316
  */
107
317
  async function launchAutomator(options) {
108
- patchNetListenToLoopback();
109
- const { projectPath, timeout = 3e4 } = options;
110
- return automator.launch({
318
+ const { cliPath, projectPath, timeout = 3e4 } = options;
319
+ const resolvedCliPath = cliPath ?? (await resolveCliPath()).cliPath ?? void 0;
320
+ return await new Launcher().launch({
321
+ cliPath: resolvedCliPath,
111
322
  projectPath,
112
323
  timeout
113
324
  });
@@ -178,10 +389,20 @@ function readLangOption(argv) {
178
389
  }
179
390
  }
180
391
  //#endregion
181
- //#region src/logger.ts
182
- var logger_default = logger;
183
- //#endregion
184
392
  //#region src/cli/automator-session.ts
393
+ function normalizeMiniProgramConnectionError(error) {
394
+ if (isAutomatorLoginError(error)) {
395
+ logger_default.error(i18nText("检测到微信开发者工具登录状态失效,请先登录后重试。", "Wechat DevTools login has expired. Please login and retry."));
396
+ logger_default.warn(formatAutomatorLoginError(error));
397
+ return /* @__PURE__ */ new Error("DEVTOOLS_LOGIN_REQUIRED");
398
+ }
399
+ if (isDevtoolsHttpPortError(error)) {
400
+ logger_default.error(i18nText("无法连接到微信开发者工具,请确保已开启 HTTP 服务端口。", "Cannot connect to Wechat DevTools. Please ensure HTTP service port is enabled."));
401
+ logger_default.warn(i18nText("请在微信开发者工具中:设置 -> 安全设置 -> 开启服务端口", "Please enable service port in Wechat DevTools: Settings -> Security -> Service Port"));
402
+ return /* @__PURE__ */ new Error("DEVTOOLS_HTTP_PORT_ERROR");
403
+ }
404
+ return error instanceof Error ? error : new Error(String(error));
405
+ }
185
406
  /**
186
407
  * @description 建立 automator 会话,并统一处理常见连接错误提示。
187
408
  */
@@ -193,7 +414,7 @@ async function connectMiniProgram(options) {
193
414
  }
194
415
  }
195
416
  /**
196
- * @description 统一管理 automator 会话生命周期与常见连接错误提示。
417
+ * @description 统一管理 automator 会话生命周期。
197
418
  */
198
419
  async function withMiniProgram(options, runner) {
199
420
  let miniProgram = null;
@@ -206,19 +427,6 @@ async function withMiniProgram(options, runner) {
206
427
  if (miniProgram) await miniProgram.close();
207
428
  }
208
429
  }
209
- function normalizeMiniProgramConnectionError(error) {
210
- if (isAutomatorLoginError(error)) {
211
- logger_default.error(i18nText("检测到微信开发者工具登录状态失效,请先登录后重试。", "Wechat DevTools login has expired. Please login and retry."));
212
- logger_default.warn(formatAutomatorLoginError(error));
213
- return /* @__PURE__ */ new Error("DEVTOOLS_LOGIN_REQUIRED");
214
- }
215
- if (isDevtoolsHttpPortError(error)) {
216
- logger_default.error(i18nText("无法连接到微信开发者工具,请确保已开启 HTTP 服务端口。", "Cannot connect to Wechat DevTools. Please ensure HTTP service port is enabled."));
217
- logger_default.warn(i18nText("请在微信开发者工具中:设置 -> 安全设置 -> 开启服务端口", "Please enable service port in Wechat DevTools: Settings -> Security -> Service Port"));
218
- return /* @__PURE__ */ new Error("DEVTOOLS_HTTP_PORT_ERROR");
219
- }
220
- return error instanceof Error ? error : new Error(String(error));
221
- }
222
430
  //#endregion
223
431
  //#region src/cli/commands.ts
224
432
  var commands_exports = /* @__PURE__ */ __exportAll({
@@ -238,50 +446,106 @@ var commands_exports = /* @__PURE__ */ __exportAll({
238
446
  takeScreenshot: () => takeScreenshot,
239
447
  tap: () => tap
240
448
  });
449
+ async function runRouteCommand(options, startMessage, successMessage, action) {
450
+ await withMiniProgram(options, async (miniProgram) => {
451
+ logger_default.info(startMessage);
452
+ await action(miniProgram);
453
+ logger_default.success(successMessage);
454
+ });
455
+ }
456
+ function toPageSnapshot(page) {
457
+ return {
458
+ path: page.path ?? "",
459
+ query: page.query
460
+ };
461
+ }
462
+ function printStructuredResult(result, json, title) {
463
+ if (json) {
464
+ console.log(JSON.stringify(result, null, 2));
465
+ return;
466
+ }
467
+ logger_default.info(title);
468
+ console.log(JSON.stringify(result, null, 2));
469
+ }
470
+ async function requireElement(page, selector) {
471
+ const element = await page.$(selector);
472
+ if (!element) throw new Error(i18nText(`未找到元素: ${selector}`, `Element not found: ${selector}`));
473
+ return element;
474
+ }
475
+ /**
476
+ * @description 执行保留栈页面跳转。
477
+ */
241
478
  async function navigateTo(options) {
242
479
  await runRouteCommand(options, i18nText(`正在跳转到 ${colors.cyan(options.url)}...`, `Navigating to ${colors.cyan(options.url)}...`), i18nText(`已跳转到 ${colors.cyan(options.url)}`, `Navigated to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.navigateTo(options.url));
243
480
  }
481
+ /**
482
+ * @description 执行关闭当前页的重定向。
483
+ */
244
484
  async function redirectTo(options) {
245
485
  await runRouteCommand(options, i18nText(`正在重定向到 ${colors.cyan(options.url)}...`, `Redirecting to ${colors.cyan(options.url)}...`), i18nText(`已重定向到 ${colors.cyan(options.url)}`, `Redirected to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.redirectTo(options.url));
246
486
  }
487
+ /**
488
+ * @description 返回上一页。
489
+ */
247
490
  async function navigateBack(options) {
248
491
  await runRouteCommand(options, i18nText("正在返回上一页...", "Navigating back..."), i18nText("已返回上一页", "Navigated back"), (miniProgram) => miniProgram.navigateBack());
249
492
  }
493
+ /**
494
+ * @description 重启到指定页面。
495
+ */
250
496
  async function reLaunch(options) {
251
497
  await runRouteCommand(options, i18nText(`正在重启到 ${colors.cyan(options.url)}...`, `Relaunching to ${colors.cyan(options.url)}...`), i18nText(`已重启到 ${colors.cyan(options.url)}`, `Relaunched to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.reLaunch(options.url));
252
498
  }
499
+ /**
500
+ * @description 切换到 tabBar 页面。
501
+ */
253
502
  async function switchTab(options) {
254
503
  await runRouteCommand(options, i18nText(`正在切换 tab 到 ${colors.cyan(options.url)}...`, `Switching tab to ${colors.cyan(options.url)}...`), i18nText(`已切换 tab 到 ${colors.cyan(options.url)}`, `Switched tab to ${colors.cyan(options.url)}`), (miniProgram) => miniProgram.switchTab(options.url));
255
504
  }
505
+ /**
506
+ * @description 获取页面栈。
507
+ */
256
508
  async function pageStack(options) {
257
- return withMiniProgram(options, async (miniProgram) => {
509
+ return await withMiniProgram(options, async (miniProgram) => {
258
510
  const result = (await miniProgram.pageStack()).map(toPageSnapshot);
259
511
  printStructuredResult(result, options.json, i18nText("页面栈:", "Page stack:"));
260
512
  return result;
261
513
  });
262
514
  }
515
+ /**
516
+ * @description 获取当前页面信息。
517
+ */
263
518
  async function currentPage(options) {
264
- return withMiniProgram(options, async (miniProgram) => {
519
+ return await withMiniProgram(options, async (miniProgram) => {
265
520
  const result = toPageSnapshot(await miniProgram.currentPage());
266
521
  if (options.json) console.log(JSON.stringify(result, null, 2));
267
522
  else logger_default.info(i18nText(`当前页面: ${result.path}${result.query ? ` ${JSON.stringify(result.query)}` : ""}`, `Current page: ${result.path}${result.query ? ` ${JSON.stringify(result.query)}` : ""}`));
268
523
  return result;
269
524
  });
270
525
  }
526
+ /**
527
+ * @description 获取系统信息。
528
+ */
271
529
  async function systemInfo(options) {
272
- return withMiniProgram(options, async (miniProgram) => {
273
- const info = await miniProgram.systemInfo();
274
- printStructuredResult(info, options.json, i18nText("系统信息:", "System info:"));
275
- return info;
530
+ return await withMiniProgram(options, async (miniProgram) => {
531
+ const result = await miniProgram.systemInfo();
532
+ printStructuredResult(result, options.json, i18nText("系统信息:", "System info:"));
533
+ return result;
276
534
  });
277
535
  }
536
+ /**
537
+ * @description 获取当前页面数据。
538
+ */
278
539
  async function pageData(options) {
279
- return withMiniProgram(options, async (miniProgram) => {
280
- const data = await (await miniProgram.currentPage()).data(options.path);
281
- printStructuredResult(data, options.json, i18nText("页面数据:", "Page data:"));
282
- return data;
540
+ return await withMiniProgram(options, async (miniProgram) => {
541
+ const result = await (await miniProgram.currentPage()).data(options.path);
542
+ printStructuredResult(result, options.json, i18nText("页面数据:", "Page data:"));
543
+ return result;
283
544
  });
284
545
  }
546
+ /**
547
+ * @description 点击页面元素。
548
+ */
285
549
  async function tap(options) {
286
550
  await withMiniProgram(options, async (miniProgram) => {
287
551
  logger_default.info(i18nText(`正在点击元素 ${colors.cyan(options.selector)}...`, `Tapping element ${colors.cyan(options.selector)}...`));
@@ -289,6 +553,9 @@ async function tap(options) {
289
553
  logger_default.success(i18nText(`已点击元素 ${colors.cyan(options.selector)}`, `Tapped element ${colors.cyan(options.selector)}`));
290
554
  });
291
555
  }
556
+ /**
557
+ * @description 向页面元素输入文本。
558
+ */
292
559
  async function input(options) {
293
560
  await withMiniProgram(options, async (miniProgram) => {
294
561
  logger_default.info(i18nText(`正在向 ${colors.cyan(options.selector)} 输入 "${colors.cyan(options.value)}"...`, `Inputting "${colors.cyan(options.value)}" into ${colors.cyan(options.selector)}...`));
@@ -298,6 +565,9 @@ async function input(options) {
298
565
  logger_default.success(i18nText(`已向 ${colors.cyan(options.selector)} 输入 "${colors.cyan(options.value)}"`, `Inputted "${colors.cyan(options.value)}" into ${colors.cyan(options.selector)}`));
299
566
  });
300
567
  }
568
+ /**
569
+ * @description 滚动页面到指定位置。
570
+ */
301
571
  async function scrollTo(options) {
302
572
  await withMiniProgram(options, async (miniProgram) => {
303
573
  logger_default.info(i18nText(`正在滚动到位置 ${colors.cyan(String(options.scrollTop))}...`, `Scrolling to position ${colors.cyan(String(options.scrollTop))}...`));
@@ -305,12 +575,15 @@ async function scrollTo(options) {
305
575
  logger_default.success(i18nText(`已滚动到位置 ${colors.cyan(String(options.scrollTop))}`, `Scrolled to position ${colors.cyan(String(options.scrollTop))}`));
306
576
  });
307
577
  }
578
+ /**
579
+ * @description 执行体验评分审计。
580
+ */
308
581
  async function audit(options) {
309
- return withMiniProgram(options, async (miniProgram) => {
582
+ return await withMiniProgram(options, async (miniProgram) => {
310
583
  logger_default.info(i18nText("正在执行体验审计...", "Running experience audit..."));
311
584
  const result = await miniProgram.stopAudits();
312
585
  if (options.outputPath) {
313
- await fs.writeFile(options.outputPath, JSON.stringify(result, null, 2));
586
+ await fs$1.writeFile(options.outputPath, JSON.stringify(result, null, 2));
314
587
  logger_default.success(i18nText(`审计报告已保存到 ${colors.cyan(options.outputPath)}`, `Audit report saved to ${colors.cyan(options.outputPath)}`));
315
588
  return result;
316
589
  }
@@ -318,8 +591,11 @@ async function audit(options) {
318
591
  return result;
319
592
  });
320
593
  }
594
+ /**
595
+ * @description 获取当前小程序截图。
596
+ */
321
597
  async function takeScreenshot(options) {
322
- return withMiniProgram(options, async (miniProgram) => {
598
+ return await withMiniProgram(options, async (miniProgram) => {
323
599
  logger_default.info(i18nText(`正在连接 DevTools:${colors.cyan(options.projectPath)}...`, `Connecting to DevTools at ${colors.cyan(options.projectPath)}...`));
324
600
  if (options.page) {
325
601
  logger_default.info(i18nText(`正在跳转页面 ${colors.cyan(options.page)}...`, `Navigating to page ${colors.cyan(options.page)}...`));
@@ -330,13 +606,16 @@ async function takeScreenshot(options) {
330
606
  const base64 = typeof screenshot === "string" ? screenshot : Buffer$1.from(screenshot).toString("base64");
331
607
  if (!base64) throw new Error(i18nText("截图失败", "Failed to capture screenshot"));
332
608
  if (options.outputPath) {
333
- await fs.writeFile(options.outputPath, Buffer$1.from(base64, "base64"));
609
+ await fs$1.writeFile(options.outputPath, Buffer$1.from(base64, "base64"));
334
610
  logger_default.success(i18nText(`截图已保存到 ${colors.cyan(options.outputPath)}`, `Screenshot saved to ${colors.cyan(options.outputPath)}`));
335
611
  return { path: options.outputPath };
336
612
  }
337
613
  return { base64 };
338
614
  });
339
615
  }
616
+ /**
617
+ * @description 开关远程调试。
618
+ */
340
619
  async function remote(options) {
341
620
  const enable = options.enable ?? true;
342
621
  await withMiniProgram(options, async (miniProgram) => {
@@ -345,31 +624,5 @@ async function remote(options) {
345
624
  logger_default.success(enable ? i18nText("远程调试已开启", "Remote debugging enabled") : i18nText("远程调试已关闭", "Remote debugging disabled"));
346
625
  });
347
626
  }
348
- async function runRouteCommand(options, startMessage, successMessage, run) {
349
- await withMiniProgram(options, async (miniProgram) => {
350
- logger_default.info(startMessage);
351
- await run(miniProgram);
352
- logger_default.success(successMessage);
353
- });
354
- }
355
- function toPageSnapshot(page) {
356
- return {
357
- path: page.path ?? "",
358
- query: page.query
359
- };
360
- }
361
- function printStructuredResult(result, json, title) {
362
- if (json) {
363
- console.log(JSON.stringify(result, null, 2));
364
- return;
365
- }
366
- logger_default.info(title);
367
- console.log(JSON.stringify(result, null, 2));
368
- }
369
- async function requireElement(page, selector) {
370
- const element = await page.$(selector);
371
- if (!element) throw new Error(i18nText(`未找到元素: ${selector}`, `Element not found: ${selector}`));
372
- return element;
373
- }
374
627
  //#endregion
375
- export { validateLocaleOption as C, launchAutomator as D, isDevtoolsHttpPortError as E, i18nText as S, isAutomatorLoginError as T, connectMiniProgram as _, navigateBack as a, logger_default as b, pageStack as c, remote as d, scrollTo as f, tap as g, takeScreenshot as h, input as i, reLaunch as l, systemInfo as m, commands_exports as n, navigateTo as o, switchTab as p, currentPage as r, pageData as s, audit as t, redirectTo as u, withMiniProgram as v, formatAutomatorLoginError as w, configureLocaleFromArgv as x, colors as y };
628
+ export { createLocaleConfig as A, operatingSystemName as B, isAutomatorLoginError as C, getConfig as D, resolveCliPath as E, defaultCustomConfigFilePath as F, logger_default as H, resolvePath as I, SupportedPlatformsMap as L, readCustomConfig as M, removeCustomConfigKey as N, getConfiguredLocale as O, defaultCustomConfigDirPath as P, getDefaultCliPath as R, formatAutomatorLoginError as S, launchAutomator as T, colors as V, connectMiniProgram as _, navigateBack as a, i18nText as b, pageStack as c, remote as d, scrollTo as f, tap as g, takeScreenshot as h, input as i, overwriteCustomConfig as j, createCustomConfig as k, reLaunch as l, systemInfo as m, commands_exports as n, navigateTo as o, switchTab as p, currentPage as r, pageData as s, audit as t, redirectTo as u, withMiniProgram as v, isDevtoolsHttpPortError as w, validateLocaleOption as x, configureLocaleFromArgv as y, isOperatingSystemSupported as z };