weapp-vite 6.15.13 → 6.15.14

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/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { S as isPathInside, _ as DEFAULT_MP_PLATFORM, b as resolveMiniPlatform, c as createSharedBuildConfig, d as resolveWeappConfigFile, f as checkRuntime, g as createCjsConfigLoadError, h as parseCommentJson, l as SHARED_CHUNK_VIRTUAL_PREFIX, m as loadViteConfigFile, n as syncProjectSupportFiles, p as getProjectConfigFileName, r as syncManagedTsconfigBootstrapFiles, s as formatBytes, t as createCompilerContext, v as getDefaultIdeProjectRoot, x as shouldPassPlatformArgToIdeOpen, y as normalizeMiniPlatform } from "./createContext-CBnOZ_FN.mjs";
1
+ import { S as isPathInside, _ as DEFAULT_MP_PLATFORM, b as resolveMiniPlatform, c as createSharedBuildConfig, d as resolveWeappConfigFile, f as checkRuntime, g as createCjsConfigLoadError, h as parseCommentJson, l as SHARED_CHUNK_VIRTUAL_PREFIX, m as loadViteConfigFile, n as syncProjectSupportFiles, p as getProjectConfigFileName, r as syncManagedTsconfigBootstrapFiles, s as formatBytes, t as createCompilerContext, v as getDefaultIdeProjectRoot, x as shouldPassPlatformArgToIdeOpen, y as normalizeMiniPlatform } from "./createContext-BcX4FNt9.mjs";
2
2
  import { r as logger_default, t as colors } from "./logger-CgxdNjvb.mjs";
3
- import { h as VERSION } from "./file-CycxGM0E.mjs";
3
+ import { h as VERSION } from "./file-BR4Z0ErL.mjs";
4
4
  import { a as resolveWeappMcpConfig, o as startWeappViteMcpServer } from "./mcp-DRlj32v4.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import path, { posix } from "pathe";
@@ -15,14 +15,13 @@ import { execFile } from "node:child_process";
15
15
  import { Buffer } from "node:buffer";
16
16
  import { cac } from "cac";
17
17
  import { resolveCommand } from "package-manager-detector/commands";
18
+ import { RETRY_CANCEL_KEYS, RETRY_CONFIRM_KEYS, bootstrapWechatDevtoolsSettings, buildWechatIdeNpm, clearWechatIdeCache, clearWechatIdeCacheByAutomator, closeSharedMiniProgram, closeWechatIdeProject, compileWechatIdeByAutomator, connectOpenedAutomator, createSharedInputSession, dispatchWechatCliCommand, formatAutomatorLoginError, getConfig, getWechatIdeTestAccounts, getWechatIdeTicket, getWechatIdeToolInfo, isAutomatorLoginError, isWeappIdeTopLevelCommand, isWechatIdeLoginRequiredError, launchAutomator, openWechatIdeProjectByHttp, parse, promptRetryKeypress, promptWechatIdeLoginRetry, quitWechatIde, refreshWechatIdeTicket, resetWechatIdeFileUtilsByHttp, runRetryableCommand, runWechatIdeEngineBuild, runWithSuspendedSharedInput, setWechatIdeTicket, startForwardConsole, takeScreenshot } from "weapp-ide-cli";
18
19
  import { promisify } from "node:util";
19
- import { bootstrapWechatDevtoolsSettings, closeSharedMiniProgram, connectOpenedAutomator, formatAutomatorLoginError, formatRetryHotkeyPrompt, formatWechatIdeLoginRequiredError, getConfig, isAutomatorLoginError, isWeappIdeTopLevelCommand, isWechatIdeLoginRequiredError, launchAutomator, parse, startForwardConsole, takeScreenshot, waitForRetryKeypress } from "weapp-ide-cli";
20
20
  import { generateJs, generateJson, generateWxml, generateWxss } from "@weapp-core/schematics";
21
21
  import { determineAgent } from "@vercel/detect-agent";
22
22
  import { initConfig } from "@weapp-core/init";
23
23
  import { createInterface } from "node:readline/promises";
24
24
  import { clearTimeout, setTimeout as setTimeout$1 } from "node:timers";
25
- import { emitKeypressEvents } from "node:readline";
26
25
  //#region src/analyze/subpackages/classifier.ts
27
26
  const VIRTUAL_MODULE_INDICATOR = "\0";
28
27
  const VIRTUAL_PREFIX = `${SHARED_CHUNK_VIRTUAL_PREFIX}/`;
@@ -952,42 +951,133 @@ function logBuildPackageSizeReport(options) {
952
951
  }
953
952
  }
954
953
  //#endregion
955
- //#region src/cli/openIde.ts
956
- const execFileAsync = promisify(execFile);
957
- function shouldLogAutomatorFallbackError() {
958
- const flag = process.env.WEAPP_VITE_DEBUG_AUTOMATOR_OPEN;
959
- return flag === "1" || flag === "true";
954
+ //#region src/cli/openIde/execute.ts
955
+ function readArgOption(argv, ...names) {
956
+ for (let index = 0; index < argv.length; index += 1) {
957
+ const current = argv[index];
958
+ if (!names.includes(current)) continue;
959
+ const next = argv[index + 1];
960
+ if (typeof next === "string" && !next.startsWith("-")) return next;
961
+ }
960
962
  }
961
- async function openWechatIdeByAutomator(projectPath) {
962
- (await launchAutomator({
963
- projectPath,
964
- trustProject: true
965
- })).disconnect();
963
+ async function tryExecuteWechatIdeCliCommandByAutomator(argv, projectPath) {
964
+ if (!projectPath) return false;
965
+ const command = argv[0];
966
+ if (!command) return false;
967
+ if (command === "compile") {
968
+ await compileWechatIdeByAutomator({ projectPath });
969
+ return true;
970
+ }
971
+ if (command === "cache") {
972
+ const cleanType = readArgOption(argv, "--clean", "-c");
973
+ if (cleanType !== "compile" && cleanType !== "all") return false;
974
+ await clearWechatIdeCacheByAutomator({
975
+ clean: cleanType,
976
+ projectPath
977
+ });
978
+ return true;
979
+ }
980
+ return false;
981
+ }
982
+ async function tryExecuteWechatIdeCliCommandByHttp(argv, projectPath) {
983
+ const command = argv[0];
984
+ if (!command) return false;
985
+ if (command === "compile") {
986
+ if (!projectPath) return false;
987
+ await openWechatIdeProjectByHttp(projectPath);
988
+ return true;
989
+ }
990
+ if (command === "reset-fileutils") {
991
+ if (!projectPath) return false;
992
+ await resetWechatIdeFileUtilsByHttp(projectPath);
993
+ return true;
994
+ }
995
+ if (command === "engine" && argv[1] === "build") {
996
+ const engineProjectPath = argv[2] || projectPath;
997
+ if (!engineProjectPath) return false;
998
+ await runWechatIdeEngineBuild(engineProjectPath, { logPath: readArgOption(argv, "--logPath", "-l") });
999
+ return true;
1000
+ }
1001
+ return false;
1002
+ }
1003
+ async function tryExecuteWechatIdeCliCommandByHelper(argv) {
1004
+ const command = argv[0];
1005
+ if (!command) return false;
1006
+ if (command === "close") {
1007
+ await closeWechatIdeProject();
1008
+ return true;
1009
+ }
1010
+ if (command === "quit") {
1011
+ await quitWechatIde();
1012
+ return true;
1013
+ }
1014
+ if (command === "cache") {
1015
+ const cleanType = readArgOption(argv, "--clean", "-c");
1016
+ if (!cleanType) return false;
1017
+ await clearWechatIdeCache({ clean: cleanType });
1018
+ return true;
1019
+ }
1020
+ return false;
966
1021
  }
967
1022
  /**
968
- * @description 执行 IDE 打开流程,并在登录失效时允许按键重试。
1023
+ * @description 统一执行 weapp-ide-cli 命令,并在登录失效时复用同一套重试交互。
969
1024
  */
970
- async function runWechatIdeOpenWithRetry(argv) {
971
- let retrying = true;
972
- while (retrying) try {
973
- await parse(argv);
974
- return;
975
- } catch (error) {
976
- if (!isWechatIdeLoginRequiredError(error)) {
977
- logger_default.error(error);
978
- return;
1025
+ async function executeWechatIdeCliCommand(argv, options = {}) {
1026
+ const { automatorMode = "prefer", cancelLevel = "warn", httpMode = "prefer", onNonLoginError, onRetry, projectPath } = options;
1027
+ await runWithSuspendedSharedInput(async () => {
1028
+ try {
1029
+ if (await tryExecuteWechatIdeCliCommandByHttp(argv, projectPath)) return;
1030
+ } catch (error) {
1031
+ if (httpMode === "require") throw error;
979
1032
  }
980
- logger_default.error("检测到微信开发者工具登录状态失效,请先登录后重试。");
981
- logger_default.warn(formatWechatIdeLoginRequiredError(error));
982
- logger_default.info(formatRetryHotkeyPrompt());
983
- if (await waitForRetryKeypress() !== "retry") {
984
- logger_default.warn("已取消重试。完成登录后请重新执行当前命令。");
985
- retrying = false;
986
- continue;
1033
+ try {
1034
+ if (await tryExecuteWechatIdeCliCommandByAutomator(argv, projectPath)) return;
1035
+ } catch (error) {
1036
+ if (automatorMode === "require") throw error;
987
1037
  }
988
- logger_default.info(colors.bold(colors.green("正在重试连接微信开发者工具...")));
989
- }
1038
+ try {
1039
+ if (await tryExecuteWechatIdeCliCommandByHelper(argv)) return;
1040
+ } catch (error) {
1041
+ if (onNonLoginError) {
1042
+ onNonLoginError(error);
1043
+ return;
1044
+ }
1045
+ throw error;
1046
+ }
1047
+ await runRetryableCommand({
1048
+ createCancelError: () => /* @__PURE__ */ new Error("cancelled"),
1049
+ execute: async () => {
1050
+ try {
1051
+ await parse(argv);
1052
+ return null;
1053
+ } catch (error) {
1054
+ if (!isWechatIdeLoginRequiredError(error)) {
1055
+ if (onNonLoginError) {
1056
+ onNonLoginError(error);
1057
+ return null;
1058
+ }
1059
+ throw error;
1060
+ }
1061
+ return error;
1062
+ }
1063
+ },
1064
+ isRetryableResult: (result) => result !== null,
1065
+ onCancel: () => {},
1066
+ onRetry: () => {
1067
+ onRetry?.();
1068
+ },
1069
+ promptRetry: async (error) => await promptWechatIdeLoginRetry({
1070
+ cancelLevel,
1071
+ error,
1072
+ logger: logger_default
1073
+ }),
1074
+ shouldRetry: (action) => action === "retry"
1075
+ });
1076
+ });
990
1077
  }
1078
+ //#endregion
1079
+ //#region src/cli/openIde/close.ts
1080
+ const execFileAsync = promisify(execFile);
991
1081
  async function closeIdeByAppleScript() {
992
1082
  if (process.platform !== "darwin") return false;
993
1083
  const appName = process.env.WEAPP_DEVTOOLS_APP_NAME || "wechatwebdevtools";
@@ -1009,29 +1099,21 @@ async function closeIdeByProcessKill(cliPath) {
1009
1099
  }
1010
1100
  }
1011
1101
  /**
1012
- * @description 根据 mpDistRoot 推导 IDE 项目目录(目录内应包含 project/mini 配置)
1013
- */
1014
- function resolveIdeProjectPath(mpDistRoot) {
1015
- if (!mpDistRoot || !mpDistRoot.trim()) return;
1016
- const parent = path.dirname(mpDistRoot);
1017
- if (!parent || parent === "." || parent === "/") return;
1018
- return parent;
1019
- }
1020
- /**
1021
- * @description 结合 mpDistRoot 与配置根目录解析最终 IDE 项目目录。
1102
+ * @description 关闭微信开发者工具,并在 CLI 不可用时回退到系统级关闭。
1022
1103
  */
1023
- function resolveIdeProjectRoot(mpDistRoot, cwd) {
1024
- return resolveIdeProjectPath(mpDistRoot) ?? cwd;
1025
- }
1026
- async function closeIde() {
1104
+ async function closeIde$1() {
1027
1105
  const config = await getConfig();
1028
1106
  const cliPath = config.cliPath?.trim() ? config.cliPath : null;
1029
1107
  try {
1030
- await parse(["close"]);
1108
+ await closeWechatIdeProject();
1031
1109
  return true;
1032
1110
  } catch (error) {
1033
1111
  if (isWechatIdeLoginRequiredError(error)) try {
1034
- await runWechatIdeOpenWithRetry(["close"]);
1112
+ await executeWechatIdeCliCommand(["close"], {
1113
+ cancelLevel: "warn",
1114
+ onNonLoginError: (retryError) => logger_default.error(retryError),
1115
+ onRetry: () => logger_default.info("正在重试连接微信开发者工具...")
1116
+ });
1035
1117
  return true;
1036
1118
  } catch (retryError) {
1037
1119
  logger_default.error(retryError);
@@ -1051,25 +1133,36 @@ async function closeIde() {
1051
1133
  return false;
1052
1134
  }
1053
1135
  }
1136
+ //#endregion
1137
+ //#region src/cli/openIde/reuse.ts
1054
1138
  function formatReuseOpenedWechatIdePrompt() {
1055
1139
  return `目标项目已在微信开发者工具中打开,已跳过重复打开。按 ${colors.bold(colors.green("r"))} 关闭当前窗口后重新打开。`;
1056
1140
  }
1057
- /**
1058
- * @description 若当前项目已在微信开发者工具中打开且自动化可连通,则直接复用现有会话,避免重复拉起 IDE。
1059
- */
1060
- async function tryReuseOpenedWechatIde(projectPath) {
1061
- let miniProgram;
1141
+ async function openWechatIdeByAutomator(projectPath) {
1142
+ (await launchAutomator({
1143
+ projectPath,
1144
+ trustProject: true
1145
+ })).disconnect();
1146
+ }
1147
+ async function connectOpenedProject(projectPath) {
1062
1148
  try {
1063
- miniProgram = await connectOpenedAutomator({
1149
+ return await connectOpenedAutomator({
1064
1150
  projectPath,
1065
1151
  timeout: 3e3
1066
1152
  });
1067
1153
  } catch {
1068
1154
  return null;
1069
1155
  }
1156
+ }
1157
+ /**
1158
+ * @description 若当前项目已在微信开发者工具中打开且自动化可连通,则直接复用现有会话,避免重复拉起 IDE。
1159
+ */
1160
+ async function tryReuseOpenedWechatIde(projectPath, closeIde) {
1161
+ const miniProgram = await connectOpenedProject(projectPath);
1162
+ if (!miniProgram) return null;
1070
1163
  miniProgram.disconnect();
1071
1164
  logger_default.info(formatReuseOpenedWechatIdePrompt());
1072
- if (await waitForRetryKeypress() !== "retry") return {
1165
+ if (await promptRetryKeypress({ logger: logger_default }) !== "retry") return {
1073
1166
  reopened: false,
1074
1167
  reused: true
1075
1168
  };
@@ -1081,22 +1174,70 @@ async function tryReuseOpenedWechatIde(projectPath) {
1081
1174
  reused: false
1082
1175
  };
1083
1176
  }
1084
- async function reopenOpenedWechatIde(projectPath) {
1085
- let miniProgram;
1086
- try {
1087
- miniProgram = await connectOpenedAutomator({
1088
- projectPath,
1089
- timeout: 3e3
1090
- });
1091
- } catch {
1092
- return false;
1093
- }
1177
+ /**
1178
+ * @description 对已打开的目标项目执行强制重开,以刷新最新构建产物。
1179
+ */
1180
+ async function reopenOpenedWechatIde(projectPath, closeIde) {
1181
+ const miniProgram = await connectOpenedProject(projectPath);
1182
+ if (!miniProgram) return false;
1094
1183
  miniProgram.disconnect();
1095
1184
  logger_default.info("目标项目已在微信开发者工具中打开,当前命令将主动重开以刷新最新构建产物。");
1096
1185
  if (!await closeIde()) logger_default.warn("关闭当前微信开发者工具失败,仍继续尝试重新打开目标项目。");
1097
1186
  await openWechatIdeByAutomator(projectPath);
1098
1187
  return true;
1099
1188
  }
1189
+ //#endregion
1190
+ //#region src/cli/openIde/index.ts
1191
+ function shouldLogAutomatorFallbackError() {
1192
+ const flag = process.env.WEAPP_VITE_DEBUG_AUTOMATOR_OPEN;
1193
+ return flag === "1" || flag === "true";
1194
+ }
1195
+ /**
1196
+ * @description 执行 IDE 打开流程,并在登录失效时允许按键重试。
1197
+ */
1198
+ async function runWechatIdeOpenWithRetry(argv) {
1199
+ await executeWechatIdeCliCommand(argv, {
1200
+ cancelLevel: "warn",
1201
+ onNonLoginError: (error) => logger_default.error(error),
1202
+ onRetry: () => {
1203
+ logger_default.info(colors.bold(colors.green("正在重试连接微信开发者工具...")));
1204
+ }
1205
+ });
1206
+ }
1207
+ /**
1208
+ * @description 根据 mpDistRoot 推导 IDE 项目目录(目录内应包含 project/mini 配置)
1209
+ */
1210
+ function resolveIdeProjectPath(mpDistRoot) {
1211
+ if (!mpDistRoot || !mpDistRoot.trim()) return;
1212
+ const parent = path.dirname(mpDistRoot);
1213
+ if (!parent || parent === "." || parent === "/") return;
1214
+ return parent;
1215
+ }
1216
+ /**
1217
+ * @description 结合 mpDistRoot 与配置根目录解析最终 IDE 项目目录。
1218
+ */
1219
+ function resolveIdeProjectRoot(mpDistRoot, cwd) {
1220
+ return resolveIdeProjectPath(mpDistRoot) ?? cwd;
1221
+ }
1222
+ async function closeIde() {
1223
+ return await closeIde$1();
1224
+ }
1225
+ async function tryOpenWechatIdeByAutomator(projectPath, options) {
1226
+ if (options.reuseOpenedProject === false) {
1227
+ if (await reopenOpenedWechatIde(projectPath, closeIde)) return true;
1228
+ }
1229
+ const reuseResult = await tryReuseOpenedWechatIde(projectPath, closeIde);
1230
+ if (reuseResult?.reused || reuseResult?.reopened) return true;
1231
+ await openWechatIdeByAutomator(projectPath);
1232
+ return true;
1233
+ }
1234
+ function createIdeOpenArgv(platform, projectPath, options = {}) {
1235
+ const argv = ["open", "-p"];
1236
+ if (projectPath) argv.push(projectPath);
1237
+ if (platform === "weapp" && options.trustProject !== false) argv.push("--trust-project");
1238
+ if (platform && shouldPassPlatformArgToIdeOpen(platform)) argv.push("--platform", platform);
1239
+ return argv;
1240
+ }
1100
1241
  async function openIde(platform, projectPath, options = {}) {
1101
1242
  let bootstrapResult;
1102
1243
  if (platform === "weapp" && projectPath) try {
@@ -1110,13 +1251,7 @@ async function openIde(platform, projectPath, options = {}) {
1110
1251
  }
1111
1252
  if (platform === "weapp" && projectPath && bootstrapResult?.servicePortEnabled === false) logger_default.warn("检测到微信开发者工具服务端口当前处于关闭状态,已保留用户设置并回退到普通 open 流程。");
1112
1253
  if (platform === "weapp" && projectPath && options.trustProject !== false && bootstrapResult?.servicePortEnabled !== false) try {
1113
- if (options.reuseOpenedProject === false) {
1114
- if (await reopenOpenedWechatIde(projectPath)) return;
1115
- }
1116
- const reuseResult = await tryReuseOpenedWechatIde(projectPath);
1117
- if (reuseResult?.reused || reuseResult?.reopened) return;
1118
- await openWechatIdeByAutomator(projectPath);
1119
- return;
1254
+ if (await tryOpenWechatIdeByAutomator(projectPath, options)) return;
1120
1255
  } catch (error) {
1121
1256
  if (isAutomatorLoginError(error)) {
1122
1257
  logger_default.error("检测到微信开发者工具登录状态失效,请先登录后重试。");
@@ -1125,11 +1260,7 @@ async function openIde(platform, projectPath, options = {}) {
1125
1260
  logger_default.warn("通过 automator 启动微信开发者工具并自动信任项目失败,回退到普通 open 流程。");
1126
1261
  if (shouldLogAutomatorFallbackError()) logger_default.error(error);
1127
1262
  }
1128
- const argv = ["open", "-p"];
1129
- if (projectPath) argv.push(projectPath);
1130
- if (platform === "weapp" && options.trustProject !== false) argv.push("--trust-project");
1131
- if (platform && shouldPassPlatformArgToIdeOpen(platform)) argv.push("--platform", platform);
1132
- await runWechatIdeOpenWithRetry(argv);
1263
+ await runWechatIdeOpenWithRetry(createIdeOpenArgv(platform, projectPath, options));
1133
1264
  }
1134
1265
  /**
1135
1266
  * @description 解析 IDE 相关命令所需的平台、项目目录与配置上下文。
@@ -1608,11 +1739,15 @@ async function waitForTermination(cleanup) {
1608
1739
  }
1609
1740
  });
1610
1741
  }
1742
+ function formatIdeOutput(data, options) {
1743
+ if (options.json) return JSON.stringify(data, null, 2);
1744
+ return JSON.stringify(data, null, 2);
1745
+ }
1611
1746
  /**
1612
1747
  * @description 执行 ide 子命令。
1613
1748
  */
1614
1749
  async function runIdeCommand(action, root, options) {
1615
- if (action !== "logs" && action !== "setup") throw new Error(`未知 ide 子命令: ${action ?? "(empty)"}`);
1750
+ if (action !== "logs" && action !== "setup" && action !== "info" && action !== "test-accounts" && action !== "ticket" && action !== "ticket:set" && action !== "ticket:refresh") throw new Error(`未知 ide 子命令: ${action ?? "(empty)"}`);
1616
1751
  filterDuplicateOptions(options);
1617
1752
  const configFile = resolveConfigFile(options);
1618
1753
  const targets = resolveRuntimeTargets(options);
@@ -1634,6 +1769,35 @@ async function runIdeCommand(action, root, options) {
1634
1769
  return;
1635
1770
  }
1636
1771
  if (options.open) await openIde(resolved.platform, resolved.projectPath, { trustProject: options.trustProject });
1772
+ if (action === "info") {
1773
+ const result = await getWechatIdeToolInfo({ projectPath: resolved.projectPath });
1774
+ logger_default.info(formatIdeOutput(result, options));
1775
+ return;
1776
+ }
1777
+ if (action === "test-accounts") {
1778
+ const result = await getWechatIdeTestAccounts({ projectPath: resolved.projectPath });
1779
+ logger_default.info(formatIdeOutput(result, options));
1780
+ return;
1781
+ }
1782
+ if (action === "ticket") {
1783
+ const result = await getWechatIdeTicket({ projectPath: resolved.projectPath });
1784
+ logger_default.info(formatIdeOutput(result, options));
1785
+ return;
1786
+ }
1787
+ if (action === "ticket:set") {
1788
+ if (!options.ticket) throw new Error("`weapp-vite ide ticket:set` 需要提供 --ticket。");
1789
+ await setWechatIdeTicket({
1790
+ projectPath: resolved.projectPath,
1791
+ ticket: options.ticket
1792
+ });
1793
+ logger_default.info(`已设置微信开发者工具 ticket:${options.ticket}`);
1794
+ return;
1795
+ }
1796
+ if (action === "ticket:refresh") {
1797
+ await refreshWechatIdeTicket({ projectPath: resolved.projectPath });
1798
+ logger_default.info("已刷新微信开发者工具 ticket。");
1799
+ return;
1800
+ }
1637
1801
  const forwardConsoleOptions = await resolveForwardConsoleOptions({
1638
1802
  ...resolved.weappViteConfig,
1639
1803
  forwardConsole: resolved.weappViteConfig?.forwardConsole === false ? { enabled: true } : {
@@ -1657,7 +1821,7 @@ async function runIdeCommand(action, root, options) {
1657
1821
  * @description 注册 IDE 相关子命令。
1658
1822
  */
1659
1823
  function registerIdeCommand(cli) {
1660
- cli.command("ide [action] [root]", "forward Wechat DevTools console logs to terminal").option("-o, --open", "[boolean] open ide before attaching log bridge").option("-p, --platform <platform>", "[string] target platform (weapp | h5)").option("--project-config <path>", "[string] project config path (miniprogram only)").option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).action(async (action, root, options) => {
1824
+ 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 | h5)").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 }).action(async (action, root, options) => {
1661
1825
  await runIdeCommand(action, root, options);
1662
1826
  });
1663
1827
  }
@@ -1979,16 +2143,18 @@ async function resolveHttpUrl(options) {
1979
2143
  }
1980
2144
  async function confirmWrite() {
1981
2145
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
1982
- const rl = createInterface({
1983
- input: process.stdin,
1984
- output: process.stdout
2146
+ return await runWithSuspendedSharedInput(async () => {
2147
+ const rl = createInterface({
2148
+ input: process.stdin,
2149
+ output: process.stdout
2150
+ });
2151
+ try {
2152
+ const normalized = (await rl.question("是否写入配置文件?(Y/n) ")).trim().toLowerCase();
2153
+ return normalized === "" || normalized === "y" || normalized === "yes";
2154
+ } finally {
2155
+ rl.close();
2156
+ }
1985
2157
  });
1986
- try {
1987
- const normalized = (await rl.question("是否写入配置文件?(Y/n) ")).trim().toLowerCase();
1988
- return normalized === "" || normalized === "y" || normalized === "yes";
1989
- } finally {
1990
- rl.close();
1991
- }
1992
2158
  }
1993
2159
  function resolveClientTransport(transport) {
1994
2160
  return transport === "http" ? "http" : "command";
@@ -2072,7 +2238,7 @@ function registerMcpCommand(cli) {
2072
2238
  function registerNpmCommand(cli) {
2073
2239
  cli.command("npm").alias("build:npm").alias("build-npm").action(async () => {
2074
2240
  try {
2075
- await parse(["build-npm", "-p"]);
2241
+ await buildWechatIdeNpm({ projectPath: process.cwd() });
2076
2242
  } catch (error) {
2077
2243
  logger_default.error(error);
2078
2244
  }
@@ -2114,6 +2280,7 @@ function registerPrepareCommand(cli) {
2114
2280
  isDev: false,
2115
2281
  mode: typeof options.mode === "string" ? options.mode : "development",
2116
2282
  configFile: resolveConfigFile(options),
2283
+ configLoader: "native",
2117
2284
  syncSupportFiles: false,
2118
2285
  preloadAppEntry: false
2119
2286
  }));
@@ -2124,8 +2291,208 @@ function registerPrepareCommand(cli) {
2124
2291
  });
2125
2292
  }
2126
2293
  //#endregion
2294
+ //#region src/cli/devHotkeys/devtools.ts
2295
+ /**
2296
+ * @description 重置当前 DevTools automator 共享会话。
2297
+ */
2298
+ async function runResetDevtoolsSessionAction(options) {
2299
+ logger_default.info("[dev action] 正在重置当前 DevTools 会话...");
2300
+ await closeSharedMiniProgram(options.projectPath);
2301
+ logger_default.success("[dev action] 当前 DevTools 会话已重置。");
2302
+ return "已重置当前 DevTools 会话";
2303
+ }
2304
+ /**
2305
+ * @description 重置共享会话并重开当前项目,以恢复 DevTools 状态。
2306
+ */
2307
+ async function runResetAndReopenDevtoolsAction(options) {
2308
+ if (!options.openIde) {
2309
+ logger_default.warn("[dev action] 当前 dev 会话未提供重新打开微信开发者工具的能力。");
2310
+ return "重置并重开微信开发者工具不可用";
2311
+ }
2312
+ logger_default.info("[dev action] 正在重置当前 DevTools 会话并重开项目...");
2313
+ await closeSharedMiniProgram(options.projectPath);
2314
+ const summary = await options.openIde();
2315
+ logger_default.success("[dev action] 当前 DevTools 会话已重置,并已重新打开项目。");
2316
+ return summary ?? "已重置当前 DevTools 会话并重新打开项目";
2317
+ }
2318
+ /**
2319
+ * @description 手动触发一次当前小程序 dev 重新构建。
2320
+ */
2321
+ async function runDevRebuildAction(options) {
2322
+ if (!options.rebuild) {
2323
+ logger_default.warn("[dev action] 当前 dev 会话未提供手动重新构建能力。");
2324
+ return "手动重新构建不可用";
2325
+ }
2326
+ logger_default.info("[dev action] 正在手动重新构建当前小程序产物...");
2327
+ const summary = await options.rebuild();
2328
+ logger_default.success("[dev action] 当前小程序产物已手动重新构建。");
2329
+ return summary ?? "已手动重新构建当前小程序产物";
2330
+ }
2331
+ /**
2332
+ * @description 重新打开当前微信开发者工具项目,并主动清理共享 automator 会话。
2333
+ */
2334
+ async function runOpenIdeAction(options) {
2335
+ if (!options.openIde) {
2336
+ logger_default.warn("[dev action] 当前 dev 会话未提供重新打开微信开发者工具的能力。");
2337
+ return "重新打开微信开发者工具不可用";
2338
+ }
2339
+ logger_default.info(`[dev action] 正在重新打开微信开发者工具项目:${colors.cyan(options.projectPath)}`);
2340
+ await closeSharedMiniProgram(options.projectPath);
2341
+ const summary = await options.openIde();
2342
+ logger_default.success("[dev action] 微信开发者工具项目已重新打开。");
2343
+ return summary ?? "已重新打开微信开发者工具项目";
2344
+ }
2345
+ //#endregion
2346
+ //#region src/cli/devHotkeys/screenshot.ts
2347
+ const DEV_SCREENSHOT_DIR = ".weapp-vite/dev-screenshots";
2348
+ const DEFAULT_SCREENSHOT_TIMEOUT = 3e4;
2349
+ /**
2350
+ * @description 生成开发态截图输出路径。
2351
+ */
2352
+ function resolveDevScreenshotOutputPath(cwd, now = /* @__PURE__ */ new Date()) {
2353
+ const stamp = now.toISOString().replace(/[:.]/g, "-");
2354
+ return path.join(cwd, DEV_SCREENSHOT_DIR, `screenshot-${stamp}.png`);
2355
+ }
2356
+ function formatLogPath(cwd, targetPath) {
2357
+ const relativePath = path.relative(cwd, targetPath);
2358
+ if (!relativePath || relativePath.startsWith("..")) return targetPath;
2359
+ return relativePath;
2360
+ }
2361
+ function formatResolvedScreenshotPath(cwd, fallbackPath, result) {
2362
+ return formatLogPath(cwd, result.path ?? fallbackPath);
2363
+ }
2364
+ /**
2365
+ * @description 执行当前页面截图并输出结果日志。
2366
+ */
2367
+ async function runScreenshotAction(options) {
2368
+ const outputPath = resolveDevScreenshotOutputPath(options.cwd);
2369
+ await fs$2.mkdir(path.dirname(outputPath), { recursive: true });
2370
+ logger_default.info(`[dev action] 正在截图当前页面,输出到 ${colors.cyan(formatLogPath(options.cwd, outputPath))}`);
2371
+ const result = await takeScreenshot({
2372
+ fullPage: true,
2373
+ projectPath: options.projectPath,
2374
+ sharedSession: true,
2375
+ outputPath,
2376
+ timeout: DEFAULT_SCREENSHOT_TIMEOUT
2377
+ });
2378
+ const resolvedPath = formatResolvedScreenshotPath(options.cwd, outputPath, result);
2379
+ logger_default.success(`[dev action] 当前页面截图完成:${colors.cyan(resolvedPath)}`);
2380
+ return resolvedPath;
2381
+ }
2382
+ //#endregion
2383
+ //#region src/cli/devHotkeys/actions.ts
2384
+ const DEV_HOTKEY_GROUPS = [
2385
+ {
2386
+ key: "development",
2387
+ title: "开发动作"
2388
+ },
2389
+ {
2390
+ key: "devtools",
2391
+ title: "会话动作"
2392
+ },
2393
+ {
2394
+ key: "process",
2395
+ title: "进程控制"
2396
+ },
2397
+ {
2398
+ key: "help",
2399
+ title: "帮助"
2400
+ }
2401
+ ];
2402
+ const DEV_HOTKEY_DEFINITIONS = [
2403
+ {
2404
+ description: "截图当前页面并保存到本地",
2405
+ group: "development",
2406
+ key: "s",
2407
+ label: "截图",
2408
+ pendingLabel: "正在截图当前页面",
2409
+ run: async ({ options }) => {
2410
+ return `截图已保存到 ${await runScreenshotAction(options)}`;
2411
+ }
2412
+ },
2413
+ {
2414
+ description: "手动重新构建当前小程序产物",
2415
+ group: "development",
2416
+ key: "r",
2417
+ label: "手动重新构建产物",
2418
+ pendingLabel: "正在手动重新构建当前小程序产物",
2419
+ run: async ({ options }) => {
2420
+ return await runDevRebuildAction(options);
2421
+ }
2422
+ },
2423
+ {
2424
+ description: "重置当前 DevTools automator 会话",
2425
+ group: "devtools",
2426
+ key: "c",
2427
+ label: "重置 DevTools 会话",
2428
+ pendingLabel: "正在重置当前 DevTools 会话",
2429
+ run: async ({ options }) => {
2430
+ return await runResetDevtoolsSessionAction(options);
2431
+ }
2432
+ },
2433
+ {
2434
+ description: "重置会话并重开当前微信开发者工具项目",
2435
+ group: "devtools",
2436
+ key: "C",
2437
+ label: "重置并重开项目",
2438
+ pendingLabel: "正在重置当前 DevTools 会话并重开项目",
2439
+ run: async ({ options }) => {
2440
+ return await runResetAndReopenDevtoolsAction(options);
2441
+ }
2442
+ },
2443
+ {
2444
+ description: "重新打开当前微信开发者工具项目",
2445
+ group: "devtools",
2446
+ key: "o",
2447
+ label: "重新打开微信开发者工具",
2448
+ pendingLabel: "正在重新打开微信开发者工具项目",
2449
+ run: async ({ options }) => {
2450
+ return await runOpenIdeAction(options);
2451
+ }
2452
+ },
2453
+ {
2454
+ description: "开关 MCP 服务",
2455
+ group: "devtools",
2456
+ key: "m",
2457
+ label: "MCP 切换",
2458
+ run: async ({ toggleMcp }) => {
2459
+ return await toggleMcp();
2460
+ }
2461
+ },
2462
+ {
2463
+ description: "退出当前 dev",
2464
+ group: "process",
2465
+ key: "q"
2466
+ },
2467
+ {
2468
+ description: "强制中断当前 dev",
2469
+ group: "process",
2470
+ key: "Ctrl+C"
2471
+ },
2472
+ {
2473
+ description: "暂时挂起当前 dev,恢复终端控制",
2474
+ group: "process",
2475
+ key: "Ctrl+Z"
2476
+ },
2477
+ {
2478
+ description: "重新显示这份帮助",
2479
+ group: "help",
2480
+ key: "h"
2481
+ }
2482
+ ];
2483
+ function resolveDevHotkeyRowsByGroup() {
2484
+ return DEV_HOTKEY_GROUPS.map((group) => ({
2485
+ key: group.key,
2486
+ rows: DEV_HOTKEY_DEFINITIONS.filter((action) => action.group === group.key),
2487
+ title: group.title
2488
+ }));
2489
+ }
2490
+ function resolveRunnableHotkeyDefinition(input) {
2491
+ return DEV_HOTKEY_DEFINITIONS.find((action) => action.run && action.key === input);
2492
+ }
2493
+ //#endregion
2127
2494
  //#region package.json
2128
- var version = "6.15.13";
2495
+ var version = "6.15.14";
2129
2496
  //#endregion
2130
2497
  //#region src/cli/devHotkeys/format.ts
2131
2498
  const FULLWIDTH_ASCII_START = 65281;
@@ -2143,55 +2510,45 @@ function formatFooterLine(state) {
2143
2510
  if (state.currentAction) return `执行中 ${state.currentAction}`;
2144
2511
  return "就绪 等待操作...";
2145
2512
  }
2513
+ function formatHotkeyRows(rows) {
2514
+ const key = (value) => colors.bold(colors.green(value));
2515
+ const formattedRows = rows.map((row) => ({
2516
+ description: row.description,
2517
+ key: key(row.key)
2518
+ }));
2519
+ const keyColumnWidth = Math.max(...formattedRows.map((row) => row.key.length));
2520
+ return formattedRows.map(({ key, description }) => `按 ${key.padEnd(keyColumnWidth)} ${description}`);
2521
+ }
2522
+ function formatExtraHotkeyRows(rows) {
2523
+ const key = (value) => colors.bold(colors.green(value));
2524
+ const formattedRows = rows.map(([hotkey, description]) => ({
2525
+ description,
2526
+ key: key(hotkey)
2527
+ }));
2528
+ const keyColumnWidth = Math.max(...formattedRows.map((row) => row.key.length));
2529
+ return formattedRows.map(({ key, description }) => `按 ${key.padEnd(keyColumnWidth)} ${description}`);
2530
+ }
2146
2531
  /**
2147
2532
  * @description 生成带状态的开发态快捷键帮助文本。
2148
2533
  */
2149
2534
  function formatDevHotkeyHelpWithState(state) {
2150
- const key = (value) => colors.bold(colors.green(value));
2151
- const actionRows = [{
2152
- key: key("s"),
2153
- description: "截图当前页面并保存到本地"
2154
- }, {
2155
- key: key("m"),
2156
- description: "开关 MCP 服务"
2157
- }];
2158
- const processRows = [
2159
- {
2160
- key: key("q"),
2161
- description: "退出当前 dev"
2162
- },
2163
- {
2164
- key: key("Ctrl+C"),
2165
- description: "强制中断当前 dev"
2166
- },
2167
- {
2168
- key: key("Ctrl+Z"),
2169
- description: "暂时挂起当前 dev,恢复终端控制"
2170
- }
2535
+ const sections = resolveDevHotkeyRowsByGroup().filter((section) => section.rows.length > 0).flatMap((section) => [
2536
+ "",
2537
+ section.title,
2538
+ ...formatHotkeyRows(section.rows)
2539
+ ]);
2540
+ const retrySections = [
2541
+ "",
2542
+ "登录重试",
2543
+ ...formatExtraHotkeyRows([[RETRY_CONFIRM_KEYS.join(" / "), "微信开发者工具登录失效后确认重试当前命令"], [RETRY_CANCEL_KEYS.join(" / "), "取消当前登录重试提示"]])
2171
2544
  ];
2172
- const helpRows = [{
2173
- key: key("h"),
2174
- description: "重新显示这份帮助"
2175
- }];
2176
- const keyColumnWidth = Math.max(...[
2177
- ...actionRows,
2178
- ...processRows,
2179
- ...helpRows
2180
- ].map((row) => row.key.length));
2181
- const formatRows = (rows) => rows.map(({ key, description }) => `按 ${key.padEnd(keyColumnWidth)} ${description}`);
2182
2545
  return [
2183
2546
  `${colors.bold(colors.green("DEV"))} weapp-vite v${version} ${state.projectLabel ?? "weapp"}`,
2547
+ ...sections,
2548
+ ...retrySections,
2184
2549
  "",
2185
- "快捷命令",
2186
- ...formatRows(actionRows),
2187
- "",
2188
- "进程控制",
2189
- ...formatRows(processRows),
2190
- "",
2191
- "帮助",
2192
- ...formatRows(helpRows),
2193
- "",
2194
- `当前状态:${state.currentAction ?? "等待操作"} / MCP ${formatMcpStatus(state)}`
2550
+ `当前状态:${state.currentAction ?? "等待操作"} / MCP ${formatMcpStatus(state)}`,
2551
+ ...state.lastAction ? [`最近操作:${state.lastAction}`] : []
2195
2552
  ].join("\n");
2196
2553
  }
2197
2554
  /**
@@ -2200,6 +2557,7 @@ function formatDevHotkeyHelpWithState(state) {
2200
2557
  function formatDevHotkeyHintWithState(state) {
2201
2558
  const key = (value) => colors.bold(colors.green(value));
2202
2559
  if (state.currentAction) return `${formatFooterLine(state)},按 ${key("h")} 显示帮助,按 ${key("q")} 退出`;
2560
+ if (state.lastAction) return `开发快捷键已就绪,最近操作:${state.lastAction},按 ${key("h")} 显示帮助,按 ${key("q")} 退出`;
2203
2561
  return `开发快捷键已就绪,按 ${key("h")} 显示帮助,按 ${key("q")} 退出`;
2204
2562
  }
2205
2563
  function normalizeInputChar(input) {
@@ -2252,43 +2610,6 @@ function createToggleMcpAction(options) {
2252
2610
  };
2253
2611
  }
2254
2612
  //#endregion
2255
- //#region src/cli/devHotkeys/screenshot.ts
2256
- const DEV_SCREENSHOT_DIR = ".weapp-vite/dev-screenshots";
2257
- const DEFAULT_SCREENSHOT_TIMEOUT = 3e4;
2258
- /**
2259
- * @description 生成开发态截图输出路径。
2260
- */
2261
- function resolveDevScreenshotOutputPath(cwd, now = /* @__PURE__ */ new Date()) {
2262
- const stamp = now.toISOString().replace(/[:.]/g, "-");
2263
- return path.join(cwd, DEV_SCREENSHOT_DIR, `screenshot-${stamp}.png`);
2264
- }
2265
- function formatLogPath(cwd, targetPath) {
2266
- const relativePath = path.relative(cwd, targetPath);
2267
- if (!relativePath || relativePath.startsWith("..")) return targetPath;
2268
- return relativePath;
2269
- }
2270
- function formatResolvedScreenshotPath(cwd, fallbackPath, result) {
2271
- return formatLogPath(cwd, result.path ?? fallbackPath);
2272
- }
2273
- /**
2274
- * @description 执行当前页面截图并输出结果日志。
2275
- */
2276
- async function runScreenshotAction(options) {
2277
- const outputPath = resolveDevScreenshotOutputPath(options.cwd);
2278
- await fs$2.mkdir(path.dirname(outputPath), { recursive: true });
2279
- logger_default.info(`[dev action] 正在截图当前页面,输出到 ${colors.cyan(formatLogPath(options.cwd, outputPath))}`);
2280
- const result = await takeScreenshot({
2281
- fullPage: true,
2282
- projectPath: options.projectPath,
2283
- sharedSession: true,
2284
- outputPath,
2285
- timeout: DEFAULT_SCREENSHOT_TIMEOUT
2286
- });
2287
- const resolvedPath = formatResolvedScreenshotPath(options.cwd, outputPath, result);
2288
- logger_default.success(`[dev action] 当前页面截图完成:${colors.cyan(resolvedPath)}`);
2289
- return resolvedPath;
2290
- }
2291
- //#endregion
2292
2613
  //#region src/cli/devHotkeys/index.ts
2293
2614
  function forwardSigint() {
2294
2615
  process.kill(process.pid, "SIGINT");
@@ -2301,10 +2622,6 @@ function forwardSigtstp() {
2301
2622
  */
2302
2623
  function startDevHotkeys(options) {
2303
2624
  if (options.platform !== "weapp" || !process.stdin.isTTY) return;
2304
- emitKeypressEvents(process.stdin);
2305
- const hasSetRawMode = typeof process.stdin.setRawMode === "function";
2306
- if (hasSetRawMode) process.stdin.setRawMode(true);
2307
- process.stdin.resume();
2308
2625
  let closed = false;
2309
2626
  let running = false;
2310
2627
  let mcpHandle;
@@ -2323,27 +2640,20 @@ function startDevHotkeys(options) {
2323
2640
  mcpRunning: Boolean(mcpHandle?.close),
2324
2641
  projectLabel: resolveProjectLabel(options.cwd)
2325
2642
  });
2326
- const detachTerminal = () => {
2327
- if (hasSetRawMode) process.stdin.setRawMode(false);
2328
- process.stdin.pause();
2329
- };
2330
- const attachTerminal = () => {
2331
- if (closed) return;
2332
- if (hasSetRawMode) process.stdin.setRawMode(true);
2333
- process.stdin.resume();
2334
- };
2335
- const ensureTerminalActive = () => {
2336
- if (closed) return;
2337
- if (hasSetRawMode) process.stdin.setRawMode(true);
2338
- process.stdin.resume();
2339
- };
2643
+ let inputSession = createSharedInputSession({
2644
+ onData: (chunk) => {
2645
+ onData?.(chunk);
2646
+ },
2647
+ onKeypress: (str, key) => {
2648
+ onKeypress?.(str, key);
2649
+ }
2650
+ });
2340
2651
  const close = () => {
2341
2652
  if (closed) return;
2342
2653
  closed = true;
2343
- if (onData) process.stdin.off("data", onData);
2344
- if (onKeypress) process.stdin.off("keypress", onKeypress);
2345
2654
  if (onSigcont) process.off("SIGCONT", onSigcont);
2346
- detachTerminal();
2655
+ inputSession?.close();
2656
+ inputSession = void 0;
2347
2657
  if (mcpHandle?.close) mcpHandle.close().catch((error) => {
2348
2658
  logger_default.warn(`[dev action] MCP 服务关闭失败:${error instanceof Error ? error.message : String(error)}`);
2349
2659
  });
@@ -2358,24 +2668,18 @@ function startDevHotkeys(options) {
2358
2668
  };
2359
2669
  const printHelp = () => {
2360
2670
  printPanel(formatDevHotkeyHelpWithState(getState()), true);
2361
- ensureTerminalActive();
2362
2671
  };
2363
2672
  const printHint = () => {
2364
2673
  printPanel(formatDevHotkeyHintWithState(getState()));
2365
- ensureTerminalActive();
2366
2674
  };
2367
2675
  const restore = () => {
2368
2676
  if (closed) return;
2369
- if (onData) process.stdin.off("data", onData);
2370
- if (onKeypress) process.stdin.off("keypress", onKeypress);
2371
- attachTerminal();
2372
- if (onData) process.stdin.on("data", onData);
2373
- if (onKeypress) process.stdin.on("keypress", onKeypress);
2677
+ inputSession?.resume();
2374
2678
  printHint();
2375
2679
  };
2376
2680
  const suspend = () => {
2377
2681
  lastRenderedPanel = "";
2378
- detachTerminal();
2682
+ inputSession?.suspend();
2379
2683
  forwardSigtstp();
2380
2684
  };
2381
2685
  const toggleMcp = createToggleMcpAction({
@@ -2386,6 +2690,9 @@ function startDevHotkeys(options) {
2386
2690
  mcpHandle = handle;
2387
2691
  }
2388
2692
  });
2693
+ const resolvePendingLabel = (input) => {
2694
+ if (input === "m") return mcpHandle?.close ? "正在关闭 MCP 服务" : "正在启动 MCP 服务";
2695
+ };
2389
2696
  const runAction = (label, pendingLabel, action) => {
2390
2697
  if (running) {
2391
2698
  const current = currentAction ?? "已有命令";
@@ -2427,14 +2734,12 @@ function startDevHotkeys(options) {
2427
2734
  printHelp();
2428
2735
  return;
2429
2736
  }
2430
- if (normalized === "s") {
2431
- runAction("截图", "正在截图当前页面", async () => {
2432
- return `截图已保存到 ${await runScreenshotAction(options)}`;
2737
+ const action = resolveRunnableHotkeyDefinition(normalizedInput) ?? resolveRunnableHotkeyDefinition(normalized);
2738
+ if (action?.run) runAction(action.label ?? action.description, resolvePendingLabel(normalized) ?? action.pendingLabel ?? `正在执行 ${action.description}`, async () => {
2739
+ return await action.run({
2740
+ options,
2741
+ toggleMcp
2433
2742
  });
2434
- return;
2435
- }
2436
- if (normalized === "m") runAction("MCP 切换", mcpHandle?.close ? "正在关闭 MCP 服务" : "正在启动 MCP 服务", async () => {
2437
- return await toggleMcp();
2438
2743
  });
2439
2744
  };
2440
2745
  const handleInputOnce = (input, source) => {
@@ -2454,7 +2759,6 @@ function startDevHotkeys(options) {
2454
2759
  const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
2455
2760
  for (const char of text) handleInputOnce(char, "data");
2456
2761
  };
2457
- process.stdin.on("data", onData);
2458
2762
  onKeypress = (str, key) => {
2459
2763
  if (key?.ctrl && key.name === "c") {
2460
2764
  handleInputOnce("", "keypress");
@@ -2466,7 +2770,6 @@ function startDevHotkeys(options) {
2466
2770
  }
2467
2771
  if (typeof str === "string" && str) handleInputOnce(str, "keypress");
2468
2772
  };
2469
- process.stdin.on("keypress", onKeypress);
2470
2773
  onSigcont = () => {
2471
2774
  restore();
2472
2775
  };
@@ -2697,6 +3000,24 @@ function resolveWebHost(host) {
2697
3000
  if (typeof host === "string") return host;
2698
3001
  return String(host);
2699
3002
  }
3003
+ /**
3004
+ * @description 为 serve 模式构造统一的小程序开发动作,供热键与命令复用。
3005
+ */
3006
+ function createServeMiniProgramDevActions(options) {
3007
+ const projectPath = options.projectPath ?? options.fallbackProjectPath;
3008
+ return {
3009
+ projectPath,
3010
+ openIde: async () => {
3011
+ if (await options.tryReuseForwardConsole?.()) return "已通过控制台转发复用当前开发者工具会话";
3012
+ await options.openIde(projectPath);
3013
+ return "已重新打开微信开发者工具项目";
3014
+ },
3015
+ rebuild: async () => {
3016
+ await options.build();
3017
+ return "已手动重新构建当前小程序产物";
3018
+ }
3019
+ };
3020
+ }
2700
3021
  function waitForServeShutdownSignal() {
2701
3022
  return new Promise((resolve) => {
2702
3023
  const onSignal = () => {
@@ -2758,11 +3079,34 @@ function registerServeCommand(cli) {
2758
3079
  logRuntimeTarget(targets, { resolvedConfigPlatform: configService.platform });
2759
3080
  const enableAnalyze = Boolean(isUiEnabled(options) && targets.runMini);
2760
3081
  let analyzeHandle;
3082
+ const miniProgramDevActions = createServeMiniProgramDevActions({
3083
+ build: async () => {
3084
+ await buildService.build(options);
3085
+ },
3086
+ fallbackProjectPath: configService.cwd,
3087
+ openIde: async (projectPath) => {
3088
+ await openIde(configService.platform, projectPath, {
3089
+ reuseOpenedProject: false,
3090
+ trustProject: options.trustProject
3091
+ });
3092
+ },
3093
+ projectPath: resolveIdeProjectRoot(configService.mpDistRoot, configService.cwd),
3094
+ tryReuseForwardConsole: async () => {
3095
+ return await maybeStartForwardConsole({
3096
+ platform: configService.platform,
3097
+ mpDistRoot: configService.mpDistRoot,
3098
+ cwd: configService.cwd,
3099
+ weappViteConfig: configService.weappViteConfig
3100
+ });
3101
+ }
3102
+ });
2761
3103
  const devHotkeysSession = targets.runMini ? startDevHotkeys({
2762
3104
  cwd: configService.cwd,
2763
3105
  mcpConfig: configService.weappViteConfig?.mcp,
3106
+ openIde: miniProgramDevActions.openIde,
2764
3107
  platform: configService.platform,
2765
- projectPath: resolveIdeProjectRoot(configService.mpDistRoot, configService.cwd) ?? configService.cwd,
3108
+ projectPath: miniProgramDevActions.projectPath ?? configService.cwd,
3109
+ rebuild: miniProgramDevActions.rebuild,
2766
3110
  silentStartupHint: true
2767
3111
  }) : void 0;
2768
3112
  try {
@@ -2824,15 +3168,7 @@ function registerServeCommand(cli) {
2824
3168
  detail: "开发服务已就绪,准备打开 IDE 项目。",
2825
3169
  tags: ["ide", "open"]
2826
3170
  }]);
2827
- if (!await maybeStartForwardConsole({
2828
- platform: configService.platform,
2829
- mpDistRoot: configService.mpDistRoot,
2830
- cwd: configService.cwd,
2831
- weappViteConfig: configService.weappViteConfig
2832
- })) await openIde(configService.platform, resolveIdeProjectRoot(configService.mpDistRoot, configService.cwd), {
2833
- reuseOpenedProject: false,
2834
- trustProject: options.trustProject
2835
- });
3171
+ await miniProgramDevActions.openIde();
2836
3172
  devHotkeysSession?.restore();
2837
3173
  }
2838
3174
  if (analyzeHandle) await analyzeController.waitForExit();
@@ -2904,18 +3240,18 @@ async function tryRunIdeCommand(argv) {
2904
3240
  if (!command) return false;
2905
3241
  if (command === "ide") {
2906
3242
  if (argv[1] === "logs") return false;
2907
- await parse(argv.slice(1));
3243
+ if (!await dispatchWechatCliCommand(argv.slice(1))) await executeWechatIdeCliCommand(argv.slice(1));
2908
3244
  return true;
2909
3245
  }
2910
3246
  if (command.startsWith("-")) return false;
2911
3247
  if (command === "help") {
2912
3248
  const target = argv[1];
2913
3249
  if (!target || WEAPP_VITE_NATIVE_COMMANDS.has(target) || !isWeappIdeTopLevelCommand(target)) return false;
2914
- await parse(argv);
3250
+ await executeWechatIdeCliCommand(argv);
2915
3251
  return true;
2916
3252
  }
2917
3253
  if (WEAPP_VITE_NATIVE_COMMANDS.has(command) || !isWeappIdeTopLevelCommand(command)) return false;
2918
- await parse(argv);
3254
+ if (!await dispatchWechatCliCommand(argv)) await executeWechatIdeCliCommand(argv);
2919
3255
  return true;
2920
3256
  }
2921
3257
  //#endregion