weapp-vite 6.20.1 → 6.20.2

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/README.md CHANGED
@@ -219,8 +219,14 @@ weapp-vite ide logs --open
219
219
  # 等价写法
220
220
  wv ide logs
221
221
  wv ide logs --open
222
+
223
+ # 检查 DevTools CLI、服务端口、登录和已打开 automator 会话
224
+ wv ide doctor
225
+ wv ide doctor --json
222
226
  ```
223
227
 
228
+ `wv open`、`wv dev -o`、`wv build -o` 和 `wv ide logs --open` 默认使用官方 CLI 打开项目,再连接 automator。需要调试旧版自动化启动链路时,可显式传入 `--ide-open-strategy automator`;项目自动信任与打开策略相互独立。
229
+
224
230
  除了日志桥接,`ide` 子命令现在也支持直接读取已打开 DevTools 会话的信息:
225
231
 
226
232
  ```sh
@@ -1,4 +1,4 @@
1
- import { n as getCompilerContext, v as getRouteRuntimeGlobalKeys } from "./createContext-DutRdQ_I.mjs";
1
+ import { n as getCompilerContext, v as getRouteRuntimeGlobalKeys } from "./createContext-DiBG4uOB.mjs";
2
2
  //#region src/auto-routes.ts
3
3
  const ROUTE_RUNTIME_OVERRIDE_KEY = Symbol.for("weapp-vite.route-runtime");
4
4
  function createGetter(resolver) {
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { C as parseCommentJson, D as isPathInside, E as shouldPassPlatformArgToIdeOpen, S as loadViteConfigFile, T as getDefaultIdeProjectRoot, _ as resolveHmrProfileJsonPath, a as formatBytes, b as checkRuntime, d as getBackendForCapability, f as resolveBackendExecution, g as SHARED_CHUNK_VIRTUAL_PREFIX, h as createSharedBuildConfig, m as syncManagedTsconfigBootstrapFiles, p as syncProjectSupportFiles, t as createCompilerContext, w as createCjsConfigLoadError, x as getProjectConfigFileName, y as resolveWeappConfigFile } from "./createContext-DutRdQ_I.mjs";
1
+ import { C as parseCommentJson, D as isPathInside, E as shouldPassPlatformArgToIdeOpen, S as loadViteConfigFile, T as getDefaultIdeProjectRoot, _ as resolveHmrProfileJsonPath, a as formatBytes, b as checkRuntime, d as getBackendForCapability, f as resolveBackendExecution, g as SHARED_CHUNK_VIRTUAL_PREFIX, h as createSharedBuildConfig, m as syncManagedTsconfigBootstrapFiles, p as syncProjectSupportFiles, t as createCompilerContext, w as createCjsConfigLoadError, x as getProjectConfigFileName, y as resolveWeappConfigFile } from "./createContext-DiBG4uOB.mjs";
2
2
  import { r as logger_default, t as colors } from "./logger-mt4mSTqV.mjs";
3
- import { h as VERSION } from "./file-Bwxu2veP.mjs";
3
+ import { h as VERSION } from "./file-DQ5FlYd5.mjs";
4
4
  import { c as startWeappViteMcpServer, l as detectAiDevelopmentEnvironment, s as resolveWeappMcpConfig } from "./mcp-BG6TliEg.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import fs from "node:fs";
@@ -15,7 +15,7 @@ import os from "node:os";
15
15
  import { execFile, spawn } from "node:child_process";
16
16
  import { Buffer } from "node:buffer";
17
17
  import { cac } from "cac";
18
- import { RETRY_CANCEL_KEYS, RETRY_CONFIRM_KEYS, bootstrapWechatDevtoolsSettings, buildWechatIdeNpm, clearWechatIdeCache, clearWechatIdeCacheByAutomator, closeSharedMiniProgram, closeWechatIdeProject, compileWechatIdeByAutomator, connectOpenedAutomator, createSharedInputSession, createWechatIdeLoginRequiredExitError, dispatchWechatCliCommand, formatAutomatorLoginError, getConfig, getWechatIdeTestAccounts, getWechatIdeTicket, getWechatIdeToolInfo, isAutomatorLoginError, isWeappIdeTopLevelCommand, isWechatIdeEngineBuildEndpointMissingError, isWechatIdeLoginRequiredError, isWechatIdeLoginRequiredExitError, launchAutomator, parse, promptRetryKeypress, promptWechatIdeLoginRetry, quitWechatIde, refreshWechatIdeTicket, resetWechatIdeFileUtilsByHttp, resolveProjectAutomatorPort, runRetryableCommand, runWechatIdeEngineBuild, runWithSuspendedSharedInput, setWechatIdeTicket, startForwardConsole, takeScreenshot } from "weapp-ide-cli";
18
+ import { RETRY_CANCEL_KEYS, RETRY_CONFIRM_KEYS, bootstrapWechatDevtoolsSettings, buildWechatIdeNpm, clearWechatIdeCache, clearWechatIdeCacheByAutomator, closeSharedMiniProgram, closeWechatIdeProject, compileWechatIdeByAutomator, connectOpenedAutomator, createSharedInputSession, createWechatIdeLoginRequiredExitError, defaultCustomConfigFilePath, detectWechatDevtoolsServicePort, dispatchWechatCliCommand, formatAutomatorLoginError, getConfig, getWechatIdeTestAccounts, getWechatIdeTicket, getWechatIdeToolInfo, isAutomatorLoginError, isWeappIdeTopLevelCommand, isWechatIdeEngineBuildEndpointMissingError, isWechatIdeLoggedIn, isWechatIdeLoginRequiredError, isWechatIdeLoginRequiredExitError, launchAutomator, parse, promptRetryKeypress, promptWechatIdeLoginRetry, quitWechatIde, refreshWechatIdeTicket, resetWechatIdeFileUtilsByHttp, resolveCliPath, resolveProjectAutomatorPort, runRetryableCommand, runWechatIdeEngineBuild, runWithSuspendedSharedInput, setWechatIdeTicket, startForwardConsole, takeScreenshot } from "weapp-ide-cli";
19
19
  import { promisify } from "node:util";
20
20
  import { brotliCompressSync, gzipSync } from "node:zlib";
21
21
  import { resolveCommand } from "package-manager-detector/commands";
@@ -251,6 +251,17 @@ async function closeIde$1() {
251
251
  //#endregion
252
252
  //#region src/cli/openIde/diagnostics.ts
253
253
  /**
254
+ * @description 将 automator 启动错误归类为用户可执行的恢复提示。
255
+ */
256
+ function formatWechatIdeAutomatorFailure(error) {
257
+ const message = error instanceof Error ? error.message : String(error);
258
+ if (/需要重新登录|need\s+re-?login|code\s*[:=]\s*10/i.test(message)) return "登录状态失效,请先登录微信开发者工具。";
259
+ if (/service port|http port|ECONNREFUSED|listen EPERM|EACCES/i.test(message)) return "服务端口不可用,请在设置 -> 安全设置中开启服务端口。";
260
+ if (/protocol method|protocol timeout|automator.*timeout|Wait timed out|websocket|ws:\/\//i.test(message)) return "自动化 websocket 或协议尚未就绪,已保留普通 CLI 打开的项目。";
261
+ if (/cliPath|not found|spawn/i.test(message)) return "微信开发者工具 CLI 路径不可用,请执行 `wv ide doctor` 检查配置。";
262
+ return "当前 DevTools 自动化能力不可用,已保留普通 CLI 打开的项目。";
263
+ }
264
+ /**
254
265
  * @description 输出微信开发者工具打开后的自助恢复步骤。
255
266
  */
256
267
  function logWechatIdeRecoveryHint(options) {
@@ -302,14 +313,14 @@ async function verifyOpenedProjectHealth(miniProgram) {
302
313
  if (typeof miniProgram.screenshot !== "function") return;
303
314
  await withTimeout(miniProgram.screenshot({ timeout: OPENED_PROJECT_HEALTH_CHECK_TIMEOUT }), OPENED_PROJECT_HEALTH_CHECK_TIMEOUT);
304
315
  }
305
- async function openWechatIdeByAutomator(projectPath) {
316
+ async function openWechatIdeByAutomator(projectPath, options = {}) {
306
317
  disconnectMiniProgram(await launchAutomator({
307
318
  persistAsDefaultSession: true,
308
- preserveProjectRoot: true,
319
+ preserveProjectRoot: options.preserveProjectRoot ?? true,
309
320
  projectPath,
310
321
  port: resolveProjectAutomatorPort(projectPath),
311
322
  timeout: OPEN_AUTOMATOR_TIMEOUT,
312
- trustProject: true
323
+ trustProject: options.trustProject !== false
313
324
  }));
314
325
  }
315
326
  async function connectOpenedProject(projectPath) {
@@ -361,7 +372,10 @@ async function tryReuseOpenedWechatIde(projectPath, closeIde, options = {}) {
361
372
  };
362
373
  logger_default.info(colors.bold(colors.green("正在关闭当前已打开项目,并重新拉起微信开发者工具...")));
363
374
  if (!await closeIde()) logger_default.warn("关闭当前微信开发者工具失败,仍继续尝试重新打开目标项目。");
364
- await openWechatIdeByAutomator(projectPath);
375
+ await openWechatIdeByAutomator(projectPath, {
376
+ preserveProjectRoot: options.preserveProjectRoot,
377
+ trustProject: options.trustProject
378
+ });
365
379
  return {
366
380
  reopened: true,
367
381
  reused: false
@@ -370,14 +384,14 @@ async function tryReuseOpenedWechatIde(projectPath, closeIde, options = {}) {
370
384
  /**
371
385
  * @description 对已打开的目标项目执行强制重开,以刷新最新构建产物。
372
386
  */
373
- async function reopenOpenedWechatIde(projectPath, closeIde) {
387
+ async function reopenOpenedWechatIde(projectPath, closeIde, options = {}) {
374
388
  const connection = await connectOpenedProject(projectPath);
375
389
  if (connection.status !== "connected") return false;
376
390
  const { miniProgram } = connection;
377
391
  disconnectMiniProgram(miniProgram);
378
392
  logger_default.info("目标项目已在微信开发者工具中打开,当前命令将主动重开以刷新最新构建产物。");
379
393
  if (!await closeIde()) logger_default.warn("关闭当前微信开发者工具失败,仍继续尝试重新打开目标项目。");
380
- await openWechatIdeByAutomator(projectPath);
394
+ await openWechatIdeByAutomator(projectPath, options);
381
395
  return true;
382
396
  }
383
397
  //#endregion
@@ -388,6 +402,19 @@ function shouldLogAutomatorFallbackError() {
388
402
  }
389
403
  const PREPARE_AUTOMATOR_SESSION_TIMEOUT = 8e3;
390
404
  const RESET_FILEUTILS_ENV = "WEAPP_VITE_RESET_IDE_FILEUTILS";
405
+ function readProjectConfigObject(projectPath) {
406
+ try {
407
+ const raw = fs.readFileSync(path.join(projectPath, "project.config.json"), "utf8");
408
+ const value = JSON.parse(raw);
409
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
410
+ } catch {
411
+ return;
412
+ }
413
+ }
414
+ function shouldUseAutomatorProjectWrapper(projectPath) {
415
+ const projectConfig = readProjectConfigObject(projectPath);
416
+ return projectConfig?.compileType === "plugin" && typeof projectConfig.miniprogramRoot === "string" && projectConfig.miniprogramRoot.trim().length > 0;
417
+ }
391
418
  function isWechatIdeOpenRecoveryDisabled(options) {
392
419
  if (options.openRecovery === false) return true;
393
420
  const flag = process.env.WEAPP_VITE_DISABLE_IDE_OPEN_RECOVERY;
@@ -429,14 +456,25 @@ async function closeIde() {
429
456
  return await closeIde$1();
430
457
  }
431
458
  async function tryOpenWechatIdeByAutomator(projectPath, options) {
459
+ const preserveProjectRoot = !shouldUseAutomatorProjectWrapper(projectPath);
432
460
  if (options.reuseOpenedProject === false) {
433
- if (await reopenOpenedWechatIde(projectPath, closeIde)) return "reopened";
461
+ if (await reopenOpenedWechatIde(projectPath, closeIde, {
462
+ preserveProjectRoot,
463
+ trustProject: options.trustProject
464
+ })) return "reopened";
434
465
  }
435
- const reuseResult = await tryReuseOpenedWechatIde(projectPath, closeIde, { promptReopen: options.reuseOpenedProject !== true });
466
+ const reuseResult = await tryReuseOpenedWechatIde(projectPath, closeIde, {
467
+ preserveProjectRoot,
468
+ promptReopen: options.reuseOpenedProject !== true,
469
+ trustProject: options.trustProject
470
+ });
436
471
  if (reuseResult?.reused) return "reused";
437
472
  if (reuseResult?.reopened) return "reopened";
438
473
  if (reuseResult?.unhealthy) return "unhealthy";
439
- await openWechatIdeByAutomator(projectPath);
474
+ await openWechatIdeByAutomator(projectPath, {
475
+ preserveProjectRoot,
476
+ trustProject: options.trustProject
477
+ });
440
478
  return "opened";
441
479
  }
442
480
  /**
@@ -459,10 +497,11 @@ function createIdeOpenArgv(platform, projectPath, options = {}) {
459
497
  return argv;
460
498
  }
461
499
  async function prepareOpenedWechatIdeAutomatorSession(projectPath, options) {
500
+ const preserveProjectRoot = !shouldUseAutomatorProjectWrapper(projectPath);
462
501
  try {
463
502
  (await launchAutomator({
464
503
  persistAsDefaultSession: true,
465
- preserveProjectRoot: true,
504
+ preserveProjectRoot,
466
505
  projectPath,
467
506
  port: resolveProjectAutomatorPort(projectPath),
468
507
  timeout: PREPARE_AUTOMATOR_SESSION_TIMEOUT,
@@ -547,7 +586,7 @@ async function stabilizeOpenedWechatIdeProject(projectPath, servicePortEnabled,
547
586
  await executeWechatIdeCliCommand(appendLoginRetryArgv(["compile"], options), {
548
587
  automatorMode: "require",
549
588
  httpMode: "skip",
550
- preserveProjectRoot: true,
589
+ preserveProjectRoot: !shouldUseAutomatorProjectWrapper(projectPath),
551
590
  projectPath
552
591
  });
553
592
  } catch (error) {
@@ -572,7 +611,7 @@ async function stabilizeOpenedWechatIdeProject(projectPath, servicePortEnabled,
572
611
  async function verifyOpenedWechatIdeProject(projectPath, servicePortEnabled, options) {
573
612
  const stabilizeResult = await stabilizeOpenedWechatIdeProject(projectPath, servicePortEnabled, options);
574
613
  if (!stabilizeResult.ok) return stabilizeResult;
575
- if (options.useAutomatorOpen === false && servicePortEnabled !== false) return await prepareOpenedWechatIdeAutomatorSession(projectPath, options);
614
+ if (options.useAutomatorOpen === false && servicePortEnabled !== false) return await connectOpenedWechatIdeAutomatorSession(projectPath);
576
615
  return stabilizeResult;
577
616
  }
578
617
  function formatWechatIdeOpenHealthReason(result) {
@@ -603,9 +642,11 @@ async function verifyAndRecoverOpenedWechatIdeProject(platform, projectPath, ser
603
642
  }
604
643
  async function openIde(platform, projectPath, options = {}) {
605
644
  let bootstrapResult;
606
- const useAutomatorOpen = options.useAutomatorOpen === true;
645
+ const openStrategy = options.openStrategy ?? (options.useAutomatorOpen === true ? "automator" : "cli");
646
+ const useAutomatorOpen = openStrategy === "automator";
607
647
  const normalizedOptions = {
608
648
  ...options,
649
+ openStrategy,
609
650
  useAutomatorOpen
610
651
  };
611
652
  if (platform === "weapp" && projectPath) try {
@@ -618,7 +659,7 @@ async function openIde(platform, projectPath, options = {}) {
618
659
  logger_default.error(error);
619
660
  }
620
661
  if (platform === "weapp" && projectPath && bootstrapResult?.servicePortEnabled === false) logWechatIdeServicePortDisabledHint(projectPath);
621
- if (platform === "weapp" && projectPath && normalizedOptions.trustProject !== false && bootstrapResult?.servicePortEnabled !== false && useAutomatorOpen) try {
662
+ if (platform === "weapp" && projectPath && bootstrapResult?.servicePortEnabled !== false && useAutomatorOpen) try {
622
663
  const openResult = await tryOpenWechatIdeByAutomator(projectPath, normalizedOptions);
623
664
  if (openResult === "reused") return;
624
665
  if (openResult === "unhealthy") {
@@ -633,7 +674,7 @@ async function openIde(platform, projectPath, options = {}) {
633
674
  logger_default.error("检测到微信开发者工具登录状态失效,请先登录后重试。");
634
675
  logger_default.warn(formatAutomatorLoginError(error));
635
676
  }
636
- logger_default.warn("通过 automator 启动微信开发者工具并自动信任项目失败,回退到普通 open 流程。");
677
+ logger_default.warn(`通过 automator 启动微信开发者工具失败,回退到普通 open 流程:${formatWechatIdeAutomatorFailure(error)}`);
637
678
  if (shouldLogAutomatorFallbackError()) logger_default.error(error);
638
679
  }
639
680
  else if (platform === "weapp" && projectPath && normalizedOptions.reuseOpenedProject === false) {
@@ -2885,7 +2926,7 @@ function scheduleCompletedProductionBuildExit(options, analyzeHandle) {
2885
2926
  }, 0).unref?.();
2886
2927
  }
2887
2928
  function registerBuildCommand(cli) {
2888
- cli.command("build [root]", "build for production").option("--target <target>", `[string] transpile target (default: 'modules')`).option("--outDir <dir>", `[string] output directory (default: dist)`).option("-p, --platform <platform>", `[string] target platform (weapp | web | all)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).option("--sourcemap [output]", `[boolean | "inline" | "hidden"] output source maps for build (default: false)`).option("--minify [minifier]", "[boolean | \"terser\" | \"esbuild\"] enable/disable minification, or specify minifier to use (default: esbuild)").option("--emptyOutDir", `[boolean] force empty outDir when it's outside of root`).option("-w, --watch", `[boolean] rebuilds when modules have changed on disk`).option("--skipNpm", `[boolean] if skip npm build`).option("-o, --open", `[boolean] open ide`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--ui", `[boolean] 启动调试 UI(当前提供分析视图)`, { default: false }).option("--analyze", `[boolean] 输出分包分析仪表盘`, { default: false }).option("--scope <scope>", `[string] 局部构建范围,例如 main,packages/order`).action(async (root, options) => {
2929
+ cli.command("build [root]", "build for production").option("--target <target>", `[string] transpile target (default: 'modules')`).option("--outDir <dir>", `[string] output directory (default: dist)`).option("-p, --platform <platform>", `[string] target platform (weapp | web | all)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).option("--sourcemap [output]", `[boolean | "inline" | "hidden"] output source maps for build (default: false)`).option("--minify [minifier]", "[boolean | \"terser\" | \"esbuild\"] enable/disable minification, or specify minifier to use (default: esbuild)").option("--emptyOutDir", `[boolean] force empty outDir when it's outside of root`).option("-w, --watch", `[boolean] rebuilds when modules have changed on disk`).option("--skipNpm", `[boolean] if skip npm build`).option("-o, --open", `[boolean] open ide`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--ide-open-strategy <strategy>", "[string] IDE open strategy (cli | automator)", { default: "cli" }).option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--ui", `[boolean] 启动调试 UI(当前提供分析视图)`, { default: false }).option("--analyze", `[boolean] 输出分包分析仪表盘`, { default: false }).option("--scope <scope>", `[string] 局部构建范围,例如 main,packages/order`).action(async (root, options) => {
2889
2930
  let analyzeHandle;
2890
2931
  let ctx;
2891
2932
  let targets;
@@ -2996,7 +3037,8 @@ function registerBuildCommand(cli) {
2996
3037
  }]);
2997
3038
  await openIde(configService.platform, resolveIdeProjectPath(configService.mpDistRoot), {
2998
3039
  openRecovery: options.openRecovery,
2999
- trustProject: options.trustProject
3040
+ trustProject: options.trustProject,
3041
+ openStrategy: options.ideOpenStrategy
3000
3042
  });
3001
3043
  }
3002
3044
  if (analyzeHandle) await analyzeHandle.waitForExit();
@@ -3610,6 +3652,121 @@ async function readLatestHmrProfileSummary(options) {
3610
3652
  }
3611
3653
  //#endregion
3612
3654
  //#region src/cli/commands/ide.ts
3655
+ async function runIdeDoctor(projectPath, options) {
3656
+ const resolvedCli = await resolveCliPath();
3657
+ const servicePort = await detectWechatDevtoolsServicePort().catch((error) => ({
3658
+ servicePortEnabled: void 0,
3659
+ servicePort: void 0,
3660
+ error
3661
+ }));
3662
+ const cliCheck = resolvedCli.cliPath ? {
3663
+ status: "ok",
3664
+ value: {
3665
+ path: resolvedCli.cliPath,
3666
+ source: resolvedCli.source
3667
+ }
3668
+ } : {
3669
+ fix: "执行 `weapp config set cliPath <path-to-cli>` 配置微信开发者工具 CLI。",
3670
+ message: "未找到可用的微信开发者工具 CLI。",
3671
+ status: "failed",
3672
+ value: { source: resolvedCli.source }
3673
+ };
3674
+ const servicePortCheck = servicePort.servicePortEnabled === false ? {
3675
+ fix: "在微信开发者工具中打开:设置 -> 安全设置 -> 服务端口。",
3676
+ message: "微信开发者工具服务端口已关闭。",
3677
+ status: "failed",
3678
+ value: servicePort
3679
+ } : servicePort.error ? {
3680
+ fix: "执行 `wv ide doctor --json` 查看底层错误,并确认微信开发者工具已安装。",
3681
+ message: servicePort.error instanceof Error ? servicePort.error.message : String(servicePort.error),
3682
+ status: "warning"
3683
+ } : {
3684
+ status: servicePort.servicePortEnabled === true ? "ok" : "unknown",
3685
+ value: {
3686
+ enabled: servicePort.servicePortEnabled ?? null,
3687
+ port: servicePort.servicePort ?? null
3688
+ }
3689
+ };
3690
+ let loginCheck = {
3691
+ fix: "打开微信开发者工具完成登录后重试。",
3692
+ message: "暂未确认登录状态。",
3693
+ status: "unknown"
3694
+ };
3695
+ if (resolvedCli.cliPath) try {
3696
+ await isWechatIdeLoggedIn({
3697
+ nonInteractive: true,
3698
+ silent: true
3699
+ });
3700
+ loginCheck = {
3701
+ status: "ok",
3702
+ value: true
3703
+ };
3704
+ } catch (error) {
3705
+ loginCheck = {
3706
+ fix: "打开微信开发者工具完成登录后重试,或执行 `wv ide doctor --json` 查看 CLI 错误。",
3707
+ message: error instanceof Error ? error.message : String(error),
3708
+ status: "warning",
3709
+ value: false
3710
+ };
3711
+ }
3712
+ const projectCheck = projectPath ? {
3713
+ status: "ok",
3714
+ value: projectPath
3715
+ } : {
3716
+ fix: "在项目目录执行命令,或显式传入 `wv ide doctor <project-root>`。",
3717
+ message: "未解析到微信开发者工具项目目录。",
3718
+ status: "warning"
3719
+ };
3720
+ let automatorCheck = {
3721
+ message: projectPath ? "当前项目没有可连接的已打开 automator 会话。" : "缺少项目目录,跳过 automator 检查。",
3722
+ status: "unknown"
3723
+ };
3724
+ let toolCheck = {
3725
+ message: "当前没有可读取的 DevTools Tool.getInfo。",
3726
+ status: "unknown"
3727
+ };
3728
+ if (projectPath) try {
3729
+ const miniProgram = await connectOpenedAutomator({
3730
+ projectPath,
3731
+ port: resolveProjectAutomatorPort(projectPath),
3732
+ timeout: 3e3
3733
+ });
3734
+ automatorCheck = {
3735
+ status: "ok",
3736
+ value: true
3737
+ };
3738
+ if (typeof miniProgram.toolInfo === "function") toolCheck = {
3739
+ status: "ok",
3740
+ value: await miniProgram.toolInfo()
3741
+ };
3742
+ miniProgram.disconnect?.();
3743
+ } catch (error) {
3744
+ automatorCheck = {
3745
+ fix: "先执行 `wv open` 打开项目;若服务端口已开启,关闭多余 DevTools 窗口后重试。",
3746
+ message: error instanceof Error ? error.message : String(error),
3747
+ status: "warning"
3748
+ };
3749
+ }
3750
+ const report = {
3751
+ checks: {
3752
+ automator: automatorCheck,
3753
+ cli: cliCheck,
3754
+ login: loginCheck,
3755
+ project: projectCheck,
3756
+ servicePort: servicePortCheck,
3757
+ tool: toolCheck
3758
+ },
3759
+ configFile: defaultCustomConfigFilePath,
3760
+ nodeVersion: process.version,
3761
+ platform: process.platform,
3762
+ weappViteVersion: VERSION
3763
+ };
3764
+ const output = JSON.stringify(report, null, 2);
3765
+ if (options.json) process.stdout.write(`${output}\n`);
3766
+ else logger_default.info(output);
3767
+ if (options.strict && Object.values(report.checks).some((check) => check.status === "failed")) throw new Error("微信开发者工具环境诊断未通过,请根据 doctor 输出修复失败项后重试。");
3768
+ return report;
3769
+ }
3613
3770
  async function waitForTermination(cleanup) {
3614
3771
  await new Promise((resolve) => {
3615
3772
  const signals = ["SIGINT", "SIGTERM"];
@@ -3639,7 +3796,7 @@ function formatIdeOutput(data, options) {
3639
3796
  * @description 执行 ide 子命令。
3640
3797
  */
3641
3798
  async function runIdeCommand(action, root, options) {
3642
- if (action !== "logs" && action !== "setup" && action !== "info" && action !== "test-accounts" && action !== "ticket" && action !== "ticket:set" && action !== "ticket:refresh") throw new Error(`未知 ide 子命令: ${action ?? "(empty)"}`);
3799
+ if (action !== "logs" && action !== "setup" && action !== "info" && action !== "test-accounts" && action !== "ticket" && action !== "ticket:set" && action !== "ticket:refresh" && action !== "doctor") throw new Error(`未知 ide 子命令: ${action ?? "(empty)"}`);
3643
3800
  filterDuplicateOptions(options);
3644
3801
  const configFile = resolveConfigFile(options);
3645
3802
  const targets = resolveRuntimeTargets(options);
@@ -3652,8 +3809,12 @@ async function runIdeCommand(action, root, options) {
3652
3809
  projectPath: root,
3653
3810
  cliPlatform: targets.rawPlatform
3654
3811
  });
3655
- if (resolved.platform !== "weapp") throw new Error("`weapp-vite ide logs` 当前仅支持微信小程序平台。");
3656
- if (!resolved.projectPath) throw new Error("无法解析微信开发者工具项目目录,请显式传入 root 或检查 project.config.json。");
3812
+ if (action !== "doctor" && resolved.platform !== "weapp") throw new Error("`weapp-vite ide logs` 当前仅支持微信小程序平台。");
3813
+ if (action !== "doctor" && !resolved.projectPath) throw new Error("无法解析微信开发者工具项目目录,请显式传入 root 或检查 project.config.json。");
3814
+ if (action === "doctor") {
3815
+ await runIdeDoctor(resolved.projectPath, options);
3816
+ return;
3817
+ }
3657
3818
  if (action === "setup") {
3658
3819
  const result = await bootstrapWechatDevtoolsSettings({
3659
3820
  projectPath: resolved.projectPath,
@@ -3664,7 +3825,8 @@ async function runIdeCommand(action, root, options) {
3664
3825
  }
3665
3826
  if (options.open) await openIde(resolved.platform, resolved.projectPath, {
3666
3827
  openRecovery: options.openRecovery,
3667
- trustProject: options.trustProject
3828
+ trustProject: options.trustProject,
3829
+ openStrategy: options.ideOpenStrategy
3668
3830
  });
3669
3831
  if (action === "info") {
3670
3832
  const result = await getWechatIdeToolInfo({ projectPath: resolved.projectPath });
@@ -3725,7 +3887,7 @@ async function runIdeCommand(action, root, options) {
3725
3887
  * @description 注册 IDE 相关子命令。
3726
3888
  */
3727
3889
  function registerIdeCommand(cli) {
3728
- cli.command("ide [action] [root]", "run Wechat DevTools utility actions and log bridge commands").option("-o, --open", "[boolean] open ide before attaching log bridge").option("-p, --platform <platform>", "[string] target platform (weapp | web)").option("--project-config <path>", "[string] project config path (miniprogram only)").option("--ticket <value>", "[string] ticket used by `ide ticket:set`").option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").action(async (action, root, options) => {
3890
+ cli.command("ide [action] [root]", "run Wechat DevTools utility actions and log bridge commands").option("-o, --open", "[boolean] open ide before attaching log bridge").option("-p, --platform <platform>", "[string] target platform (weapp | web)").option("--project-config <path>", "[string] project config path (miniprogram only)").option("--json", "[boolean] output the doctor report as JSON").option("--ticket <value>", "[string] ticket used by `ide ticket:set`").option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--ide-open-strategy <strategy>", "[string] IDE open strategy (cli | automator)", { default: "cli" }).option("--strict", "[boolean] fail when doctor finds blocking environment errors").option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").action(async (action, root, options) => {
3729
3891
  await runIdeCommand(action, root, options);
3730
3892
  });
3731
3893
  }
@@ -4261,7 +4423,7 @@ function applyMcpCliOptions(config, options) {
4261
4423
  //#endregion
4262
4424
  //#region src/cli/commands/open.ts
4263
4425
  function registerOpenCommand(cli) {
4264
- cli.command("open [root]").option("-p, --platform <platform>", `[string] target platform (weapp | web)`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--login-retry <mode>", "[string] login retry mode for Wechat DevTools (never | once | always)").option("--login-retry-timeout <ms>", "[number] login retry prompt timeout in milliseconds").option("--non-interactive", "[boolean] fail immediately when Wechat DevTools login has expired").option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--mcp", "[boolean] auto start MCP service before opening IDE").option("--no-mcp", "[boolean] disable MCP service before opening IDE").action(async (root, options) => {
4426
+ cli.command("open [root]").option("-p, --platform <platform>", `[string] target platform (weapp | web)`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--ide-open-strategy <strategy>", "[string] IDE open strategy (cli | automator)", { default: "cli" }).option("--login-retry <mode>", "[string] login retry mode for Wechat DevTools (never | once | always)").option("--login-retry-timeout <ms>", "[number] login retry prompt timeout in milliseconds").option("--non-interactive", "[boolean] fail immediately when Wechat DevTools login has expired").option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--mcp", "[boolean] auto start MCP service before opening IDE").option("--no-mcp", "[boolean] disable MCP service before opening IDE").action(async (root, options) => {
4265
4427
  filterDuplicateOptions(options);
4266
4428
  const configFile = resolveConfigFile(options);
4267
4429
  const targets = resolveRuntimeTargets(options);
@@ -4293,7 +4455,8 @@ function registerOpenCommand(cli) {
4293
4455
  loginRetryTimeout: options.loginRetryTimeout,
4294
4456
  nonInteractive: options.nonInteractive,
4295
4457
  openRecovery: options.openRecovery,
4296
- trustProject: options.trustProject
4458
+ trustProject: options.trustProject,
4459
+ openStrategy: options.ideOpenStrategy
4297
4460
  });
4298
4461
  });
4299
4462
  }
@@ -4564,7 +4727,7 @@ function resolveRunnableHotkeyDefinition(input) {
4564
4727
  }
4565
4728
  //#endregion
4566
4729
  //#region package.json
4567
- var version = "6.20.1";
4730
+ var version = "6.20.2";
4568
4731
  //#endregion
4569
4732
  //#region src/cli/devHotkeys/format.ts
4570
4733
  const FULLWIDTH_ASCII_START = 65281;
@@ -4730,6 +4893,7 @@ function startDevHotkeys(options) {
4730
4893
  let onKeypress;
4731
4894
  let onSigcont;
4732
4895
  let currentAction;
4896
+ let actionStartedAt;
4733
4897
  let lastAction;
4734
4898
  let lastRenderedPanel = "";
4735
4899
  const recentInputs = /* @__PURE__ */ new Map();
@@ -4809,10 +4973,12 @@ function startDevHotkeys(options) {
4809
4973
  const runAction = (label, pendingLabel, action) => {
4810
4974
  if (running) {
4811
4975
  const current = currentAction ?? "已有命令";
4812
- logger_default.warn(`[dev action] 当前正在${current.replace(REG_PENDING_PREFIX, "")},请稍后再试。`);
4976
+ const elapsed = actionStartedAt === void 0 ? "" : `(已运行 ${Math.max(0, Date.now() - actionStartedAt)} ms)`;
4977
+ logger_default.warn(`[dev action] 当前正在${current.replace(REG_PENDING_PREFIX, "")}${elapsed},已忽略重复请求。`);
4813
4978
  return;
4814
4979
  }
4815
4980
  running = true;
4981
+ actionStartedAt = Date.now();
4816
4982
  currentAction = pendingLabel;
4817
4983
  printHint();
4818
4984
  action().then((summary) => {
@@ -4821,6 +4987,7 @@ function startDevHotkeys(options) {
4821
4987
  logger_default.error(`[dev action] ${label}失败:${error instanceof Error ? error.message : String(error)}`);
4822
4988
  }).finally(() => {
4823
4989
  running = false;
4990
+ actionStartedAt = void 0;
4824
4991
  currentAction = void 0;
4825
4992
  if (!closed) printHint();
4826
4993
  });
@@ -4828,6 +4995,7 @@ function startDevHotkeys(options) {
4828
4995
  const runBackgroundAction = (label, pendingLabel, action) => {
4829
4996
  if (running) return;
4830
4997
  running = true;
4998
+ actionStartedAt = Date.now();
4831
4999
  currentAction = pendingLabel;
4832
5000
  action().then((summary) => {
4833
5001
  if (summary) lastAction = summary;
@@ -4835,6 +5003,7 @@ function startDevHotkeys(options) {
4835
5003
  logger_default.error(`[dev action] ${label}失败:${error instanceof Error ? error.message : String(error)}`);
4836
5004
  }).finally(() => {
4837
5005
  running = false;
5006
+ actionStartedAt = void 0;
4838
5007
  currentAction = void 0;
4839
5008
  });
4840
5009
  };
@@ -5228,7 +5397,7 @@ function writePostOpenSeparator() {
5228
5397
  process.stdout?.write?.("\n");
5229
5398
  }
5230
5399
  function registerServeCommand(cli) {
5231
- cli.command("[root]", "start dev server").alias("serve").alias("dev").option("--skipNpm", `[boolean] if skip npm build`).option("-o, --open", `[boolean] open ide`).option("-p, --platform <platform>", `[string] target platform (weapp | web | all)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--login-retry <mode>", "[string] login retry mode for Wechat DevTools (never | once | always)").option("--login-retry-timeout <ms>", "[number] login retry prompt timeout in milliseconds").option("--non-interactive", "[boolean] fail immediately when Wechat DevTools login has expired").option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--mcp", "[boolean] auto start MCP service during dev").option("--no-mcp", "[boolean] disable MCP service during dev").option("--host [host]", `[string] web dev server host`).option("--ui", `[boolean] 启动调试 UI(当前提供分析视图)`, { default: false }).option("--analyze", `[boolean] 启动分包分析仪表盘 (实验特性)`, { default: false }).option("--scope <scope>", `[string] 局部构建范围,例如 main,packages/order`).action(async (root, options) => {
5400
+ cli.command("[root]", "start dev server").alias("serve").alias("dev").option("--skipNpm", `[boolean] if skip npm build`).option("-o, --open", `[boolean] open ide`).option("-p, --platform <platform>", `[string] target platform (weapp | web | all)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--ide-open-strategy <strategy>", "[string] IDE open strategy (cli | automator)", { default: "cli" }).option("--login-retry <mode>", "[string] login retry mode for Wechat DevTools (never | once | always)").option("--login-retry-timeout <ms>", "[number] login retry prompt timeout in milliseconds").option("--non-interactive", "[boolean] fail immediately when Wechat DevTools login has expired").option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--mcp", "[boolean] auto start MCP service during dev").option("--no-mcp", "[boolean] disable MCP service during dev").option("--host [host]", `[string] web dev server host`).option("--ui", `[boolean] 启动调试 UI(当前提供分析视图)`, { default: false }).option("--analyze", `[boolean] 启动分包分析仪表盘 (实验特性)`, { default: false }).option("--scope <scope>", `[string] 局部构建范围,例如 main,packages/order`).action(async (root, options) => {
5232
5401
  filterDuplicateOptions(options);
5233
5402
  setCommandNodeEnv("development");
5234
5403
  const cwd = root ?? process.cwd();
@@ -5265,7 +5434,7 @@ function registerServeCommand(cli) {
5265
5434
  fallbackProjectPath: configService.cwd,
5266
5435
  openIde: async (projectPath, openOptions) => {
5267
5436
  const forceReopen = openOptions?.forceReopen === true;
5268
- const useAutomatorOpen = forceReopen || openOptions?.useAutomatorOpen === true;
5437
+ const useAutomatorOpen = openOptions?.openStrategy === "automator" || openOptions?.useAutomatorOpen === true;
5269
5438
  await openIde(configService.platform, projectPath, {
5270
5439
  loginRetry: options.loginRetry,
5271
5440
  loginRetryTimeout: options.loginRetryTimeout,
@@ -5276,6 +5445,7 @@ function registerServeCommand(cli) {
5276
5445
  skipAutomatorCompile: !forceReopen,
5277
5446
  skipPostOpenHealthCheck: true,
5278
5447
  trustProject: options.trustProject,
5448
+ openStrategy: openOptions?.openStrategy ?? options.ideOpenStrategy ?? "cli",
5279
5449
  useAutomatorOpen
5280
5450
  });
5281
5451
  writePostOpenSeparator();
@@ -5388,7 +5558,7 @@ function registerServeCommand(cli) {
5388
5558
  await miniProgramDevActions.openIde({
5389
5559
  forceOpen: true,
5390
5560
  forceReopen: false,
5391
- useAutomatorOpen: options.trustProject !== false
5561
+ openStrategy: options.ideOpenStrategy ?? "cli"
5392
5562
  });
5393
5563
  } finally {
5394
5564
  devHotkeysSession?.restore();
@@ -5463,7 +5633,7 @@ async function tryRunIdeCommand(argv) {
5463
5633
  const command = argv[0];
5464
5634
  if (!command) return false;
5465
5635
  if (command === "ide") {
5466
- if (argv[1] === "logs") return false;
5636
+ if (argv[1] === "logs" || argv[1] === "doctor" || argv[1] === "--help" || argv[1] === "-h") return false;
5467
5637
  if (!await dispatchWechatCliCommand(argv.slice(1))) await executeWechatIdeCliCommand(argv.slice(1));
5468
5638
  return true;
5469
5639
  }
@@ -410,6 +410,7 @@ interface HandleWxmlOptions {
410
410
  importMetaExtension?: string;
411
411
  removeComment?: boolean;
412
412
  transformEvent?: boolean;
413
+ transformPlatformSyntax?: boolean;
413
414
  scriptModuleExtension?: string;
414
415
  scriptModuleTag?: string;
415
416
  templateExtension?: string;
package/dist/config.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { $n as WeappViteRuntime, Gn as applyWeappViteHostMeta, Jn as resolveWeappViteHostMeta, Kn as createWeappViteHostMeta, Un as WEAPP_VITE_HOST_NAME, Wn as WeappViteHostMeta, _ as definePageJson, a as UserConfigFnNoEnvPlain, at as WeappViteConfig, c as UserConfigFnPromise, d as Component, f as Page, g as defineComponentJson, h as defineAppJson, i as UserConfigFnNoEnv, l as defineConfig, m as Theme, n as UserConfigExport, o as UserConfigFnObject, p as Sitemap, qn as isWeappViteHost, r as UserConfigFn, s as UserConfigFnObjectPlain, t as UserConfig, u as App, v as defineSitemapJson, y as defineThemeJson } from "./config-Dd_PqIy2.mjs";
1
+ import { $n as WeappViteRuntime, Gn as applyWeappViteHostMeta, Jn as resolveWeappViteHostMeta, Kn as createWeappViteHostMeta, Un as WEAPP_VITE_HOST_NAME, Wn as WeappViteHostMeta, _ as definePageJson, a as UserConfigFnNoEnvPlain, at as WeappViteConfig, c as UserConfigFnPromise, d as Component, f as Page, g as defineComponentJson, h as defineAppJson, i as UserConfigFnNoEnv, l as defineConfig, m as Theme, n as UserConfigExport, o as UserConfigFnObject, p as Sitemap, qn as isWeappViteHost, r as UserConfigFn, s as UserConfigFnObjectPlain, t as UserConfig, u as App, v as defineSitemapJson, y as defineThemeJson } from "./config-C810aRQQ.mjs";
2
2
  export { type App, type Component, type Page, type Sitemap, type Theme, UserConfig, UserConfigExport, UserConfigFn, UserConfigFnNoEnv, UserConfigFnNoEnvPlain, UserConfigFnObject, UserConfigFnObjectPlain, UserConfigFnPromise, WEAPP_VITE_HOST_NAME, type WeappViteConfig, WeappViteHostMeta, type WeappViteRuntime, applyWeappViteHostMeta, createWeappViteHostMeta, defineAppJson, defineComponentJson, defineConfig, definePageJson, defineSitemapJson, defineThemeJson, isWeappViteHost, resolveWeappViteHostMeta };