weapp-vite 7.5.0 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -6
- package/THIRD_PARTY_NOTICES.md +60 -0
- package/bin/bootstrap.js +9 -4
- package/bin/bootstrap.test.ts +82 -1
- package/bin/nodeVersionWarning.js +17 -0
- package/bin/nodeVersionWarning.test.ts +30 -0
- package/dist/action-BD56SQh4.mjs +254 -0
- package/dist/action-CPtgEl6p.mjs +94 -0
- package/dist/action-le0bNff_.mjs +1102 -0
- package/dist/action-ytG5oFAw.mjs +138 -0
- package/dist/action-zmJrU8PC.mjs +245 -0
- package/dist/{analyze-ZJUvEdaY.mjs → analyze-DCZo-sJd.mjs} +4 -71
- package/dist/artifacts-TrTX9_jj.mjs +104 -0
- package/dist/assets-XyhpYtGl.mjs +630 -0
- package/dist/auto-import-components/resolvers.d.mts +1 -1
- package/dist/auto-import-components/resolvers.mjs +1 -1
- package/dist/auto-import-presets/wevu-router.d.mts +1 -1
- package/dist/auto-import-presets/wevu-router.mjs +1 -1
- package/dist/auto-import-presets/wevu.d.mts +1 -1
- package/dist/auto-import-presets/wevu.mjs +1 -1
- package/dist/auto-import-presets.d.mts +2 -2
- package/dist/auto-import-presets.mjs +2 -2
- package/dist/auto-routes.d.mts +1 -3
- package/dist/auto-routes.mjs +3 -4
- package/dist/{budget-BD7VqLCl.d.mts → budget-DTPngJU0.d.mts} +1 -10
- package/dist/budget-_Mu-4GKn.mjs +63 -0
- package/dist/builtProject-B145uOt5.mjs +534 -0
- package/dist/{package-7swhyLmf.mjs → classifier-CNTJOYQL.mjs} +5 -9
- package/dist/cli-acceptance.mjs +3 -4
- package/dist/cli.mjs +142 -4569
- package/dist/{config-DRGcCi3h.mjs → config-59ZWhCIf.mjs} +1 -2
- package/dist/{config-V0L-IAJf.d.mts → config-BNx2BODw.d.mts} +145 -150
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +3 -3
- package/dist/{constants-DEZdcsMn.mjs → constants-BOe8mgqL.mjs} +2 -4
- package/dist/{createCompilerContextInstance-DJH_P_nZ.mjs → createCompilerContextInstance-BXSdH2E8.mjs} +19930 -14019
- package/dist/{createContext-BqYzHhY9.mjs → createContext-W0TeXxbo.mjs} +7 -5
- package/dist/dashboard/analyze.d.mts +1 -7
- package/dist/dashboard/analyze.mjs +3 -1
- package/dist/dashboard/vite.d.mts +2 -4
- package/dist/dashboard/vite.mjs +1 -2
- package/dist/dashboard.d.mts +2 -2
- package/dist/dashboard.mjs +1733 -1
- package/dist/dashboardTransport-C9290QgS.mjs +15 -0
- package/dist/{dashboardViteBridge-Dy3nAD4m.mjs → dashboardViteBridge-B7QgQo94.mjs} +11 -11
- package/dist/{dev-fR5GiJRO.mjs → dev-D1QSExwk.mjs} +6 -3
- package/dist/devProvider-Bcvz5nu4.mjs +4966 -0
- package/dist/docs/README.md +14 -6
- package/dist/docs/ai-workflows.md +2 -0
- package/dist/docs/mcp.md +11 -1
- package/dist/docs/troubleshooting.md +16 -0
- package/dist/docs/vue-sfc.md +25 -2
- package/dist/docs/weapp-config.md +29 -0
- package/dist/docs/wevu-authoring.md +2 -0
- package/dist/doctor-worker.mjs +5 -5
- package/dist/doctor.d.mts +2 -8
- package/dist/doctor.mjs +24 -31
- package/dist/engine-Mnnm_ALP.mjs +53 -0
- package/dist/file-5eEfbK60.mjs +1 -0
- package/dist/{file-sC3jD7Fh.mjs → file-D8mp5GmB.mjs} +50 -26
- package/dist/{files-BqxFIPRp.mjs → files-Cy9jURJu.mjs} +1 -2
- package/dist/forwardConsole-D2Q0RIqc.mjs +509 -0
- package/dist/getInstance-BXNVH7sU.mjs +1 -0
- package/dist/{getInstance-DiGSzBNI.mjs → getInstance-DfNlbr-X.mjs} +2 -3
- package/dist/history-dKxzoHmN.mjs +774 -0
- package/dist/i18n.d.mts +1 -3
- package/dist/i18n.mjs +1 -2
- package/dist/{index-C9HjUX5c.d.mts → index-DIZJRrvK.d.mts} +1 -24
- package/dist/{index-CaXAtb9e.d.mts → index-SnaW3cvA.d.mts} +0 -12
- package/dist/index.d.mts +3 -7
- package/dist/index.mjs +6 -6
- package/dist/{json-BL8Dhhk6.mjs → json-Cvon2mw5.mjs} +1 -2
- package/dist/json.d.mts +1 -1
- package/dist/json.mjs +1 -1
- package/dist/lib-CJyMBzoe.mjs +140 -0
- package/dist/{lifecycle-BROTlwSL.mjs → lifecycle-CUo8PMQc.mjs} +123 -33
- package/dist/{loadConfig-C3BQhz7F.mjs → loadConfig-CKIdfW4o.mjs} +2 -3
- package/dist/loadConfig-D4WGJcYp.mjs +1 -0
- package/dist/logBuildAppFinish-DOBoof6S.mjs +54 -0
- package/dist/mcp-D88QvQgG.mjs +84 -0
- package/dist/{mcp-Cj8Maqo6.mjs → mcp-ovJgl1N9.mjs} +2 -4
- package/dist/mcp.d.mts +1 -3
- package/dist/mcp.mjs +1 -1
- package/dist/mcpClient-C8JzVZ46.mjs +283 -0
- package/dist/{processCleanup-B6KA30Zc.mjs → metadata-HlDKtlsu.mjs} +2 -21
- package/dist/nodeEnv-zq1EymWj.mjs +6 -0
- package/dist/openIde-QoYKhuuM.mjs +643 -0
- package/dist/options-Cz8vZ-0w.mjs +33 -0
- package/dist/{chunkStrategy-DRA5WpB-.mjs → package-DR62fAzP.mjs} +32 -31
- package/dist/path-E1OjBJAl.mjs +43 -0
- package/dist/{platform-CnkySBKz.mjs → platform-BiMpsZIb.mjs} +1 -2
- package/dist/{pluginHost--CaeyWpA.mjs → pluginHost-vn8Vty1J.mjs} +1 -2
- package/dist/processCleanup-DzB64WI8.mjs +18 -0
- package/dist/{protocol-vg8HGJ4n.mjs → protocol-HiSJRrSO.mjs} +43 -41
- package/dist/reader-wzPH_W8A.mjs +92 -0
- package/dist/realpathScope-DwlLaCk3.mjs +22 -0
- package/dist/report-PJVyo-UZ.mjs +105 -0
- package/dist/{path-doV773b7.mjs → resolvedId-DaxPh_yV.mjs} +5 -50
- package/dist/{resolvers-Dod-euqX.mjs → resolvers-CKYqmRD_.mjs} +10 -20
- package/dist/resolvers.d.mts +1 -1
- package/dist/resolvers.mjs +1 -1
- package/dist/{routes-C7fCmf92.d.mts → routes-DvAFX29h.d.mts} +0 -2
- package/dist/{runtime-Ee2HY6gR.d.mts → runtime-BL4RjBRa.d.mts} +1 -9
- package/dist/runtime-CKtMVERT.mjs +42 -0
- package/dist/{runtime-D6VCNhNY.mjs → runtime-DDUCb7pP.mjs} +4 -8
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/schematics-DikfOjMD.mjs +90 -0
- package/dist/{session-PskhD-nZ.mjs → session-COrQJYif.mjs} +81 -21
- package/dist/test.d.mts +1 -3
- package/dist/test.mjs +54 -30
- package/dist/types-BK2EQ3Jm.d.mts +37 -0
- package/dist/{types-CgZn5X6j.d.mts → types-e2BMP9NU.d.mts} +1 -4
- package/dist/types.d.mts +4 -4
- package/dist/{upload-D4msblBf.mjs → upload-Chal5b3w.mjs} +118 -24
- package/dist/upload-worker.mjs +3 -5
- package/dist/{utils-CJSCgEj6.mjs → utils-CTGSZp4j.mjs} +72 -146
- package/dist/vite.d.mts +2 -4
- package/dist/vite.mjs +55 -21
- package/dist/volar.mjs +1 -2
- package/dist/{wevu-BQWUU7br.mjs → wevu-BaihCXO9.mjs} +1 -2
- package/dist/wevu-DTtSOyxB.d.mts +3 -0
- package/dist/{wevu-router-Dg1LnBlg.mjs → wevu-router-BIoxDbnu.mjs} +1 -2
- package/dist/wevu-router-CdWurGQ4.d.mts +3 -0
- package/dist/wxs-7V7MPzeW.mjs +1 -0
- package/dist/wxs-BdHHXltv.mjs +110 -0
- package/package.json +62 -53
- package/dist/dashboard-DvqF3Key.mjs +0 -1842
- package/dist/devProvider-BGBkw28J.mjs +0 -1050
- package/dist/file-DRb4eWqw.mjs +0 -1
- package/dist/getInstance-SiE6WZRh.mjs +0 -1
- package/dist/loadConfig-VGtBF4qm.mjs +0 -1
- package/dist/mcp-D3Yh24Cj.mjs +0 -529
- package/dist/wevu-C4KEC5kO.d.mts +0 -5
- package/dist/wevu-router-Cg2sIkIE.d.mts +0 -5
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import { n as getDefaultIdeProjectRoot, w as shouldPassPlatformArgToIdeOpen } from "./platform-BiMpsZIb.mjs";
|
|
2
|
+
import { r as logger_default, t as colors } from "./logger-DGn5iEVN.mjs";
|
|
3
|
+
import { t as createCompilerContext } from "./createContext-W0TeXxbo.mjs";
|
|
4
|
+
import { i as resolveRuntimeTargets, t as createInlineConfig } from "./runtime-CKtMVERT.mjs";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import path from "pathe";
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import { RETRY_CONFIRM_KEYS, bootstrapWechatDevtoolsSettings, clearWechatIdeCache, clearWechatIdeCacheByAutomator, closeWechatIdeProject, compileWechatIdeByAutomator, connectOpenedAutomator, createWechatIdeLoginRequiredExitError, formatAutomatorLoginError, isAutomatorLoginError, isWechatIdeEngineBuildEndpointMissingError, isWechatIdeLoginRequiredError, isWechatIdeLoginRequiredExitError, launchAutomator, parse, promptRetryKeypress, promptWechatIdeLoginRetry, quitWechatIde, resetWechatIdeFileUtilsByHttp, resolveProjectAutomatorPort, runRetryableCommand, runWechatIdeEngineBuild, runWithSuspendedSharedInput, withWechatDevtoolsSelection, withWechatDevtoolsSelectionArgs } from "weapp-ide-cli";
|
|
9
|
+
// src/cli/openIde/execute.ts
|
|
10
|
+
function readArgOption(argv, ...names) {
|
|
11
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
12
|
+
const current = argv[index];
|
|
13
|
+
if (!names.includes(current)) continue;
|
|
14
|
+
const next = argv[index + 1];
|
|
15
|
+
if (typeof next === "string" && !next.startsWith("-")) return next;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function tryExecuteWechatIdeCliCommandByAutomator(argv, projectPath, options = {}) {
|
|
19
|
+
if (!projectPath) return false;
|
|
20
|
+
const command = argv[0];
|
|
21
|
+
if (!command) return false;
|
|
22
|
+
if (command === "compile") {
|
|
23
|
+
await compileWechatIdeByAutomator({
|
|
24
|
+
preserveProjectRoot: options.preserveProjectRoot,
|
|
25
|
+
projectPath
|
|
26
|
+
});
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (command === "cache") {
|
|
30
|
+
const cleanType = readArgOption(argv, "--clean", "-c");
|
|
31
|
+
if (cleanType !== "compile" && cleanType !== "all") return false;
|
|
32
|
+
await clearWechatIdeCacheByAutomator({
|
|
33
|
+
clean: cleanType,
|
|
34
|
+
preserveProjectRoot: options.preserveProjectRoot,
|
|
35
|
+
projectPath
|
|
36
|
+
});
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
async function tryExecuteWechatIdeCliCommandByHttp(argv, projectPath, engineBuildFallbackToCli = false) {
|
|
42
|
+
const command = argv[0];
|
|
43
|
+
if (!command) return false;
|
|
44
|
+
if (command === "reset-fileutils") {
|
|
45
|
+
if (!projectPath) return false;
|
|
46
|
+
await resetWechatIdeFileUtilsByHttp(projectPath);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
if (command === "engine" && argv[1] === "build") {
|
|
50
|
+
const engineProjectPath = argv[2] || projectPath;
|
|
51
|
+
if (!engineProjectPath) return false;
|
|
52
|
+
await runWechatIdeEngineBuild(engineProjectPath, {
|
|
53
|
+
fallbackToCli: engineBuildFallbackToCli,
|
|
54
|
+
logPath: readArgOption(argv, "--logPath", "-l")
|
|
55
|
+
});
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
async function tryExecuteWechatIdeCliCommandByHelper(argv) {
|
|
61
|
+
const command = argv[0];
|
|
62
|
+
if (!command) return false;
|
|
63
|
+
if (command === "close") {
|
|
64
|
+
await closeWechatIdeProject();
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (command === "quit") {
|
|
68
|
+
await quitWechatIde();
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (command === "cache") {
|
|
72
|
+
const cleanType = readArgOption(argv, "--clean", "-c");
|
|
73
|
+
if (!cleanType) return false;
|
|
74
|
+
await clearWechatIdeCache({ clean: cleanType });
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* @description 统一执行 weapp-ide-cli 命令,并在登录失效时复用同一套重试交互。
|
|
81
|
+
*/
|
|
82
|
+
async function executeSelectedWechatIdeCliCommand(argv, options = {}) {
|
|
83
|
+
const { automatorMode = "prefer", cancelLevel = "warn", engineBuildFallbackToCli = false, httpMode = "prefer", promptOpenIdeLogin = true, onNonLoginError, onRetry, projectPath, preserveProjectRoot } = options;
|
|
84
|
+
await runWithSuspendedSharedInput(async () => {
|
|
85
|
+
if (httpMode !== "skip") try {
|
|
86
|
+
if (await tryExecuteWechatIdeCliCommandByHttp(argv, projectPath, engineBuildFallbackToCli)) return;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (httpMode === "require" || isWechatIdeEngineBuildEndpointMissingError(error)) throw error;
|
|
89
|
+
}
|
|
90
|
+
if (automatorMode !== "skip") try {
|
|
91
|
+
if (await tryExecuteWechatIdeCliCommandByAutomator(argv, projectPath, { preserveProjectRoot })) return;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (automatorMode === "require") throw error;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
if (await tryExecuteWechatIdeCliCommandByHelper(argv)) return;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (isWechatIdeLoginRequiredExitError(error)) throw error;
|
|
99
|
+
if (onNonLoginError) {
|
|
100
|
+
onNonLoginError(error);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
await runRetryableCommand({
|
|
106
|
+
createCancelError: (error) => createWechatIdeLoginRequiredExitError(error, "cancelled"),
|
|
107
|
+
execute: async () => {
|
|
108
|
+
try {
|
|
109
|
+
await parse(argv);
|
|
110
|
+
return null;
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (isWechatIdeLoginRequiredExitError(error)) throw error;
|
|
113
|
+
if (!isWechatIdeLoginRequiredError(error)) {
|
|
114
|
+
if (onNonLoginError) {
|
|
115
|
+
onNonLoginError(error);
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
return error;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
isRetryableResult: (result) => result !== null,
|
|
124
|
+
onCancel: () => {},
|
|
125
|
+
onRetry: () => {
|
|
126
|
+
onRetry?.();
|
|
127
|
+
},
|
|
128
|
+
promptRetry: async (error) => await promptWechatIdeLoginRetry({
|
|
129
|
+
cancelLevel,
|
|
130
|
+
error,
|
|
131
|
+
logger: logger_default,
|
|
132
|
+
promptOpenIdeLogin
|
|
133
|
+
}),
|
|
134
|
+
shouldRetry: (action) => action === "retry"
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/** 安装选择覆盖 HTTP、automator 与 CLI 回退的完整操作。 */
|
|
139
|
+
async function executeWechatIdeCliCommand(argv, options = {}) {
|
|
140
|
+
return await withWechatDevtoolsSelectionArgs(argv, (args) => executeSelectedWechatIdeCliCommand(args, options));
|
|
141
|
+
}
|
|
142
|
+
// src/cli/openIde/close.ts
|
|
143
|
+
/**
|
|
144
|
+
* @description 执行用户显式请求的 CLI close;失败时保留宿主,不升级为系统级退出。
|
|
145
|
+
*/
|
|
146
|
+
async function closeIde$1() {
|
|
147
|
+
try {
|
|
148
|
+
await closeWechatIdeProject();
|
|
149
|
+
return true;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (isWechatIdeLoginRequiredError(error)) try {
|
|
152
|
+
await executeWechatIdeCliCommand(["close"], {
|
|
153
|
+
cancelLevel: "warn",
|
|
154
|
+
onNonLoginError: (retryError) => logger_default.error(retryError),
|
|
155
|
+
onRetry: () => logger_default.info("正在重试连接微信开发者工具...")
|
|
156
|
+
});
|
|
157
|
+
return true;
|
|
158
|
+
} catch (retryError) {
|
|
159
|
+
logger_default.error(retryError);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
logger_default.warn("微信开发者工具 CLI close 执行失败,已保留现有宿主;请在开发者工具中手动关闭目标项目。");
|
|
163
|
+
logger_default.error(error);
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// src/cli/openIde/diagnostics.ts
|
|
169
|
+
/**
|
|
170
|
+
* @description 将 automator 启动错误归类为用户可执行的恢复提示。
|
|
171
|
+
*/
|
|
172
|
+
function formatWechatIdeAutomatorFailure(error) {
|
|
173
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
174
|
+
if (/需要重新登录|need\s+re-?login|code\s*[:=]\s*10/i.test(message)) return "登录状态失效,请先登录微信开发者工具。";
|
|
175
|
+
if (/service port|http port|ECONNREFUSED|listen EPERM|EACCES/i.test(message)) return "服务端口不可用,请在设置 -> 安全设置中开启服务端口。";
|
|
176
|
+
if (/protocol method|protocol timeout|automator.*timeout|Wait timed out|websocket|ws:\/\//i.test(message)) return "自动化 websocket 或协议尚未就绪,已保留普通 CLI 打开的项目。";
|
|
177
|
+
if (/cliPath|not found|spawn/i.test(message)) return "微信开发者工具 CLI 路径不可用,请执行 `wv ide doctor` 检查配置。";
|
|
178
|
+
return "当前 DevTools 自动化能力不可用,已保留普通 CLI 打开的项目。";
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* @description 输出微信开发者工具打开后的自助恢复步骤。
|
|
182
|
+
*/
|
|
183
|
+
function logWechatIdeRecoveryHint(options) {
|
|
184
|
+
const lines = [
|
|
185
|
+
`微信开发者工具打开后状态可能不稳定:${options.reason}`,
|
|
186
|
+
"可按下面顺序恢复:",
|
|
187
|
+
"1. 在微信开发者工具中确认:设置 -> 安全设置 -> 服务端口已开启。",
|
|
188
|
+
"2. 仅当项目索引刷新失败时,默认会自动关闭并重开一次当前目标项目;如需跳过,传入 `--no-open-recovery` 或设置 `WEAPP_VITE_DISABLE_IDE_OPEN_RECOVERY=1`。",
|
|
189
|
+
"3. 如果仍然回到项目选择页,手动导入 project.config.json 所在目录,并关闭多余的微信开发者工具窗口后重试。",
|
|
190
|
+
"4. 需要查看底层错误时,设置 `WEAPP_VITE_DEBUG_AUTOMATOR_OPEN=1` 后重试。"
|
|
191
|
+
];
|
|
192
|
+
if (options.projectPath) lines.push(`当前目标项目目录:${options.projectPath}`);
|
|
193
|
+
logger_default.warn(lines.join("\n"));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* @description 输出服务端口关闭时的定向恢复提示。
|
|
197
|
+
*/
|
|
198
|
+
function logWechatIdeServicePortDisabledHint(projectPath) {
|
|
199
|
+
const lines = [
|
|
200
|
+
"检测到微信开发者工具服务端口当前处于关闭状态,已保留用户设置并回退到普通 open 流程。",
|
|
201
|
+
"自动刷新、截图、MCP 和 IDE 联动能力需要服务端口。",
|
|
202
|
+
"请在微信开发者工具中打开:设置 -> 安全设置 -> 服务端口,然后重新执行当前 dev/open 命令。"
|
|
203
|
+
];
|
|
204
|
+
if (projectPath) lines.push(`当前目标项目目录:${projectPath}`);
|
|
205
|
+
logger_default.warn(lines.join("\n"));
|
|
206
|
+
}
|
|
207
|
+
// src/cli/openIde/reuse.ts
|
|
208
|
+
const OPENED_PROJECT_HEALTH_CHECK_TIMEOUT = 3e3;
|
|
209
|
+
const OPEN_AUTOMATOR_TIMEOUT = 12e4;
|
|
210
|
+
function formatReuseOpenedWechatIdePrompt() {
|
|
211
|
+
return `目标项目已在微信开发者工具中打开,已跳过重复打开。按 ${RETRY_CONFIRM_KEYS.map((key) => colors.bold(colors.green(key))).join(" / ")} 重新连接目标项目(保留现有窗口)。`;
|
|
212
|
+
}
|
|
213
|
+
async function disconnectMiniProgram(miniProgram) {
|
|
214
|
+
await miniProgram.disconnect();
|
|
215
|
+
}
|
|
216
|
+
function withTimeout(task, timeoutMs) {
|
|
217
|
+
let timer;
|
|
218
|
+
const timeout = new Promise((_, reject) => {
|
|
219
|
+
timer = setTimeout(() => {
|
|
220
|
+
reject(/* @__PURE__ */ new Error(`opened automator health check timed out after ${timeoutMs}ms`));
|
|
221
|
+
}, timeoutMs);
|
|
222
|
+
});
|
|
223
|
+
return Promise.race([task, timeout]).finally(() => {
|
|
224
|
+
if (timer) clearTimeout(timer);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
async function verifyOpenedProjectHealth(miniProgram) {
|
|
228
|
+
if (typeof miniProgram.screenshot !== "function") return;
|
|
229
|
+
await withTimeout(miniProgram.screenshot({ timeout: OPENED_PROJECT_HEALTH_CHECK_TIMEOUT }), OPENED_PROJECT_HEALTH_CHECK_TIMEOUT);
|
|
230
|
+
}
|
|
231
|
+
async function openWechatIdeByAutomator(projectPath, options = {}) {
|
|
232
|
+
await disconnectMiniProgram(await launchAutomator({
|
|
233
|
+
persistAsDefaultSession: true,
|
|
234
|
+
preserveProjectRoot: options.preserveProjectRoot ?? true,
|
|
235
|
+
projectPath,
|
|
236
|
+
port: resolveProjectAutomatorPort(projectPath),
|
|
237
|
+
timeout: OPEN_AUTOMATOR_TIMEOUT,
|
|
238
|
+
trustProject: options.trustProject !== false
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
async function connectOpenedProject(projectPath) {
|
|
242
|
+
let miniProgram;
|
|
243
|
+
try {
|
|
244
|
+
miniProgram = await connectOpenedAutomator({
|
|
245
|
+
projectPath,
|
|
246
|
+
port: resolveProjectAutomatorPort(projectPath),
|
|
247
|
+
timeout: 3e3
|
|
248
|
+
});
|
|
249
|
+
} catch {
|
|
250
|
+
return { status: "not-connected" };
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
await verifyOpenedProjectHealth(miniProgram);
|
|
254
|
+
return {
|
|
255
|
+
status: "connected",
|
|
256
|
+
miniProgram
|
|
257
|
+
};
|
|
258
|
+
} catch {
|
|
259
|
+
await disconnectMiniProgram(miniProgram);
|
|
260
|
+
return { status: "unhealthy" };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* @description 若当前项目已在微信开发者工具中打开且自动化可连通,则直接复用现有会话,避免重复拉起 IDE。
|
|
265
|
+
*/
|
|
266
|
+
async function tryReuseOpenedWechatIde(projectPath, options = {}) {
|
|
267
|
+
const connection = await connectOpenedProject(projectPath);
|
|
268
|
+
if (connection.status === "unhealthy") return {
|
|
269
|
+
reopened: false,
|
|
270
|
+
reused: false,
|
|
271
|
+
unhealthy: true
|
|
272
|
+
};
|
|
273
|
+
if (connection.status === "not-connected") return null;
|
|
274
|
+
const { miniProgram } = connection;
|
|
275
|
+
await disconnectMiniProgram(miniProgram);
|
|
276
|
+
if (options.promptReopen === false) {
|
|
277
|
+
logger_default.info("目标项目已在微信开发者工具中打开,已跳过重复打开。");
|
|
278
|
+
return {
|
|
279
|
+
reopened: false,
|
|
280
|
+
reused: true
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
logger_default.info(formatReuseOpenedWechatIdePrompt());
|
|
284
|
+
if (await promptRetryKeypress({ logger: logger_default }) !== "retry") return {
|
|
285
|
+
reopened: false,
|
|
286
|
+
reused: true
|
|
287
|
+
};
|
|
288
|
+
logger_default.info(colors.bold(colors.green("正在重新连接目标项目,保留现有微信开发者工具窗口...")));
|
|
289
|
+
await openWechatIdeByAutomator(projectPath, {
|
|
290
|
+
preserveProjectRoot: options.preserveProjectRoot,
|
|
291
|
+
trustProject: options.trustProject
|
|
292
|
+
});
|
|
293
|
+
return {
|
|
294
|
+
reopened: true,
|
|
295
|
+
reused: false
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* @description 重新连接目标项目以刷新构建产物;连接失败不授予关闭共享宿主的权限。
|
|
300
|
+
*/
|
|
301
|
+
async function reopenOpenedWechatIde(projectPath, options = {}) {
|
|
302
|
+
const connection = await connectOpenedProject(projectPath);
|
|
303
|
+
if (connection.status === "connected") {
|
|
304
|
+
await disconnectMiniProgram(connection.miniProgram);
|
|
305
|
+
logger_default.info("目标项目已在微信开发者工具中打开,当前命令将重新连接以刷新最新构建产物,保留现有窗口。");
|
|
306
|
+
} else if (connection.status === "unhealthy") logger_default.info("目标项目的 automator 会话未通过健康检查,将重试连接目标项目,保留现有窗口。");
|
|
307
|
+
else logger_default.info("未检测到可复用的 automator 会话,将尝试打开目标项目,保留其他窗口。");
|
|
308
|
+
await openWechatIdeByAutomator(projectPath, options);
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
// src/cli/openIde/index.ts
|
|
312
|
+
function shouldLogAutomatorFallbackError() {
|
|
313
|
+
const flag = process.env.WEAPP_VITE_DEBUG_AUTOMATOR_OPEN;
|
|
314
|
+
return flag === "1" || flag === "true";
|
|
315
|
+
}
|
|
316
|
+
const PREPARE_AUTOMATOR_SESSION_TIMEOUT = 8e3;
|
|
317
|
+
const RESET_FILEUTILS_ENV = "WEAPP_VITE_RESET_IDE_FILEUTILS";
|
|
318
|
+
function readProjectConfigObject(projectPath) {
|
|
319
|
+
try {
|
|
320
|
+
const raw = fs.readFileSync(path.join(projectPath, "project.config.json"), "utf8");
|
|
321
|
+
const value = JSON.parse(raw);
|
|
322
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
323
|
+
} catch {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
function shouldUseAutomatorProjectWrapper(projectPath) {
|
|
328
|
+
const projectConfig = readProjectConfigObject(projectPath);
|
|
329
|
+
return projectConfig?.compileType === "plugin" && typeof projectConfig.miniprogramRoot === "string" && projectConfig.miniprogramRoot.trim().length > 0;
|
|
330
|
+
}
|
|
331
|
+
function isWechatIdeOpenRecoveryDisabled(options) {
|
|
332
|
+
if (options.openRecovery === false) return true;
|
|
333
|
+
const flag = process.env.WEAPP_VITE_DISABLE_IDE_OPEN_RECOVERY;
|
|
334
|
+
return flag === "1" || flag === "true";
|
|
335
|
+
}
|
|
336
|
+
function shouldResetWechatIdeFileUtils() {
|
|
337
|
+
const flag = process.env[RESET_FILEUTILS_ENV];
|
|
338
|
+
return flag === "1" || flag === "true";
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* @description 执行 IDE 打开流程,并在登录失效时允许按键重试。
|
|
342
|
+
*/
|
|
343
|
+
async function runWechatIdeOpenWithRetry(argv) {
|
|
344
|
+
await executeWechatIdeCliCommand(argv, {
|
|
345
|
+
cancelLevel: "warn",
|
|
346
|
+
onNonLoginError: (error) => {
|
|
347
|
+
logger_default.error(error);
|
|
348
|
+
if (process.env.WEAPP_IDE_MANAGED_PROJECT_JOURNAL?.trim()) throw error;
|
|
349
|
+
},
|
|
350
|
+
onRetry: () => {
|
|
351
|
+
logger_default.info(colors.bold(colors.green("正在重试连接微信开发者工具...")));
|
|
352
|
+
},
|
|
353
|
+
promptOpenIdeLogin: true
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* @description 根据代码输出目录推导 IDE 项目目录;内联项目配置与 app.json 同目录。
|
|
358
|
+
*/
|
|
359
|
+
function resolveIdeProjectPath(mpDistRoot, generatedProjectConfig = false) {
|
|
360
|
+
if (!mpDistRoot || !mpDistRoot.trim()) return;
|
|
361
|
+
if (generatedProjectConfig) return mpDistRoot;
|
|
362
|
+
const parent = path.dirname(mpDistRoot);
|
|
363
|
+
if (!parent || parent === "." || parent === "/") return;
|
|
364
|
+
return parent;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* @description 结合 mpDistRoot 与配置根目录解析最终 IDE 项目目录。
|
|
368
|
+
*/
|
|
369
|
+
function resolveIdeProjectRoot(mpDistRoot, cwd, generatedProjectConfig = false) {
|
|
370
|
+
const projectPath = resolveIdeProjectPath(mpDistRoot, generatedProjectConfig);
|
|
371
|
+
return generatedProjectConfig && projectPath && cwd ? path.resolve(cwd, projectPath) : projectPath ?? cwd;
|
|
372
|
+
}
|
|
373
|
+
async function closeIde() {
|
|
374
|
+
return await closeIde$1();
|
|
375
|
+
}
|
|
376
|
+
async function tryOpenWechatIdeByAutomator(projectPath, options) {
|
|
377
|
+
const preserveProjectRoot = !shouldUseAutomatorProjectWrapper(projectPath);
|
|
378
|
+
if (options.reuseOpenedProject === false) {
|
|
379
|
+
if (await reopenOpenedWechatIde(projectPath, {
|
|
380
|
+
preserveProjectRoot,
|
|
381
|
+
trustProject: options.trustProject
|
|
382
|
+
})) return "reopened";
|
|
383
|
+
}
|
|
384
|
+
const reuseResult = await tryReuseOpenedWechatIde(projectPath, {
|
|
385
|
+
preserveProjectRoot,
|
|
386
|
+
promptReopen: options.reuseOpenedProject !== true,
|
|
387
|
+
trustProject: options.trustProject
|
|
388
|
+
});
|
|
389
|
+
if (reuseResult?.reused) return "reused";
|
|
390
|
+
if (reuseResult?.reopened) return "reopened";
|
|
391
|
+
if (reuseResult?.unhealthy) return "unhealthy";
|
|
392
|
+
await openWechatIdeByAutomator(projectPath, {
|
|
393
|
+
preserveProjectRoot,
|
|
394
|
+
trustProject: options.trustProject
|
|
395
|
+
});
|
|
396
|
+
return "opened";
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* @description 打开后主动刷新微信开发者工具的项目索引,避免模拟器沿用过期 app 配置。
|
|
400
|
+
*/
|
|
401
|
+
function appendLoginRetryArgv(argv, options) {
|
|
402
|
+
if (options.nonInteractive) argv.push("--non-interactive");
|
|
403
|
+
if (options.loginRetry) argv.push("--login-retry", options.loginRetry);
|
|
404
|
+
if (options.loginRetryTimeout) argv.push("--login-retry-timeout", options.loginRetryTimeout);
|
|
405
|
+
return argv;
|
|
406
|
+
}
|
|
407
|
+
function createIdeOpenArgv(platform, projectPath, options = {}) {
|
|
408
|
+
const argv = ["open", "-p"];
|
|
409
|
+
if (projectPath) argv.push(projectPath);
|
|
410
|
+
if (platform === "weapp" && options.trustProject !== false) argv.push("--trust-project");
|
|
411
|
+
if (platform && shouldPassPlatformArgToIdeOpen(platform)) argv.push("--platform", platform);
|
|
412
|
+
if (options.nonInteractive) argv.push("--non-interactive");
|
|
413
|
+
if (options.loginRetry) argv.push("--login-retry", options.loginRetry);
|
|
414
|
+
if (options.loginRetryTimeout) argv.push("--login-retry-timeout", options.loginRetryTimeout);
|
|
415
|
+
return argv;
|
|
416
|
+
}
|
|
417
|
+
async function prepareOpenedWechatIdeAutomatorSession(projectPath, options) {
|
|
418
|
+
const preserveProjectRoot = !shouldUseAutomatorProjectWrapper(projectPath);
|
|
419
|
+
try {
|
|
420
|
+
(await launchAutomator({
|
|
421
|
+
persistAsDefaultSession: true,
|
|
422
|
+
preserveProjectRoot,
|
|
423
|
+
projectPath,
|
|
424
|
+
port: resolveProjectAutomatorPort(projectPath),
|
|
425
|
+
timeout: PREPARE_AUTOMATOR_SESSION_TIMEOUT,
|
|
426
|
+
trustProject: options.trustProject !== false
|
|
427
|
+
})).disconnect?.();
|
|
428
|
+
return { ok: true };
|
|
429
|
+
} catch (error) {
|
|
430
|
+
logger_default.warn("准备当前项目的微信开发者工具自动化会话失败,截图、MCP 或 IDE 联动命令首次运行时将重新连接。");
|
|
431
|
+
logWechatIdeRecoveryHint({
|
|
432
|
+
projectPath,
|
|
433
|
+
reason: "无法建立当前项目的自动化会话,常见原因是 DevTools 服务端口未就绪、窗口停留在项目选择页,或存在残留 DevTools 会话。"
|
|
434
|
+
});
|
|
435
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
436
|
+
return {
|
|
437
|
+
ok: false,
|
|
438
|
+
reason: "automator-session-failed",
|
|
439
|
+
error
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async function connectOpenedWechatIdeAutomatorSession(projectPath) {
|
|
444
|
+
try {
|
|
445
|
+
(await connectOpenedAutomator({
|
|
446
|
+
projectPath,
|
|
447
|
+
port: resolveProjectAutomatorPort(projectPath),
|
|
448
|
+
timeout: PREPARE_AUTOMATOR_SESSION_TIMEOUT
|
|
449
|
+
})).disconnect?.();
|
|
450
|
+
return { ok: true };
|
|
451
|
+
} catch (error) {
|
|
452
|
+
logger_default.warn("连接当前项目的微信开发者工具自动化会话失败,截图、MCP 或 IDE 联动命令首次运行时将重新连接。");
|
|
453
|
+
logWechatIdeRecoveryHint({
|
|
454
|
+
projectPath,
|
|
455
|
+
reason: "当前项目已完成打开流程,但尚未连接到可复用的自动化会话。"
|
|
456
|
+
});
|
|
457
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
458
|
+
return {
|
|
459
|
+
ok: false,
|
|
460
|
+
reason: "automator-session-failed",
|
|
461
|
+
error
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async function prepareWechatIdeAutomatorSession(projectPath, options) {
|
|
466
|
+
if (options.prepareAutomatorSession === "connect-opened") return await connectOpenedWechatIdeAutomatorSession(projectPath);
|
|
467
|
+
return await prepareOpenedWechatIdeAutomatorSession(projectPath, options);
|
|
468
|
+
}
|
|
469
|
+
async function stabilizeOpenedWechatIdeProject(projectPath, servicePortEnabled, options = {}) {
|
|
470
|
+
if (servicePortEnabled === false) return {
|
|
471
|
+
ok: false,
|
|
472
|
+
reason: "service-port-disabled"
|
|
473
|
+
};
|
|
474
|
+
try {
|
|
475
|
+
if (shouldResetWechatIdeFileUtils()) await executeWechatIdeCliCommand(appendLoginRetryArgv([
|
|
476
|
+
"reset-fileutils",
|
|
477
|
+
"-p",
|
|
478
|
+
projectPath
|
|
479
|
+
], options), {
|
|
480
|
+
automatorMode: options.useAutomatorOpen === false ? "skip" : "prefer",
|
|
481
|
+
httpMode: "require",
|
|
482
|
+
onNonLoginError: (error) => logger_default.error(error),
|
|
483
|
+
preserveProjectRoot: options.useAutomatorOpen === false,
|
|
484
|
+
projectPath
|
|
485
|
+
});
|
|
486
|
+
try {
|
|
487
|
+
await executeWechatIdeCliCommand(appendLoginRetryArgv([
|
|
488
|
+
"engine",
|
|
489
|
+
"build",
|
|
490
|
+
projectPath
|
|
491
|
+
], options), {
|
|
492
|
+
automatorMode: options.useAutomatorOpen === false ? "skip" : "prefer",
|
|
493
|
+
engineBuildFallbackToCli: true,
|
|
494
|
+
httpMode: "prefer",
|
|
495
|
+
onNonLoginError: (error) => logger_default.error(error),
|
|
496
|
+
preserveProjectRoot: options.useAutomatorOpen === false,
|
|
497
|
+
projectPath
|
|
498
|
+
});
|
|
499
|
+
} catch (error) {
|
|
500
|
+
if (!isWechatIdeEngineBuildEndpointMissingError(error)) throw error;
|
|
501
|
+
logger_default.warn("当前微信开发者工具不支持自动 engine build 刷新,已跳过该步骤;如模拟器显示旧状态,可在开发者工具内手动编译。");
|
|
502
|
+
}
|
|
503
|
+
if (options.useAutomatorOpen !== false && options.skipAutomatorCompile !== true) try {
|
|
504
|
+
await executeWechatIdeCliCommand(appendLoginRetryArgv(["compile"], options), {
|
|
505
|
+
automatorMode: "require",
|
|
506
|
+
httpMode: "skip",
|
|
507
|
+
preserveProjectRoot: !shouldUseAutomatorProjectWrapper(projectPath),
|
|
508
|
+
projectPath
|
|
509
|
+
});
|
|
510
|
+
} catch (error) {
|
|
511
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
512
|
+
}
|
|
513
|
+
return { ok: true };
|
|
514
|
+
} catch (error) {
|
|
515
|
+
if (isWechatIdeLoginRequiredExitError(error)) throw error;
|
|
516
|
+
logger_default.warn("刷新微信开发者工具项目索引失败,已保留当前打开状态;如模拟器仍显示旧状态,可手动刷新一次。");
|
|
517
|
+
logWechatIdeRecoveryHint({
|
|
518
|
+
projectPath,
|
|
519
|
+
reason: "打开项目后的文件索引刷新失败,DevTools 可能仍在使用旧项目状态或内部服务未就绪。"
|
|
520
|
+
});
|
|
521
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
522
|
+
return {
|
|
523
|
+
ok: false,
|
|
524
|
+
reason: "index-refresh-failed",
|
|
525
|
+
error
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
async function verifyOpenedWechatIdeProject(projectPath, servicePortEnabled, options) {
|
|
530
|
+
const stabilizeResult = await stabilizeOpenedWechatIdeProject(projectPath, servicePortEnabled, options);
|
|
531
|
+
if (!stabilizeResult.ok) return stabilizeResult;
|
|
532
|
+
if (options.useAutomatorOpen === false && servicePortEnabled !== false) return await connectOpenedWechatIdeAutomatorSession(projectPath);
|
|
533
|
+
return stabilizeResult;
|
|
534
|
+
}
|
|
535
|
+
function formatWechatIdeOpenHealthReason(result) {
|
|
536
|
+
if (result.reason === "index-refresh-failed") return "项目索引刷新失败";
|
|
537
|
+
return "服务端口未开启";
|
|
538
|
+
}
|
|
539
|
+
async function recoverOpenedWechatIdeProject(platform, projectPath, servicePortEnabled, options, failedResult) {
|
|
540
|
+
if (failedResult.reason === "service-port-disabled") return failedResult;
|
|
541
|
+
if (failedResult.reason === "automator-session-failed") {
|
|
542
|
+
logger_default.warn("已跳过微信开发者工具自动恢复;自动化会话预热失败不影响当前项目打开,截图、MCP 或 IDE 联动命令首次运行时会重新连接。");
|
|
543
|
+
return failedResult;
|
|
544
|
+
}
|
|
545
|
+
if (isWechatIdeOpenRecoveryDisabled(options)) {
|
|
546
|
+
logger_default.warn("已跳过微信开发者工具自动恢复;请按上方提示手动关闭并重新打开目标项目。");
|
|
547
|
+
return failedResult;
|
|
548
|
+
}
|
|
549
|
+
logger_default.info(`检测到微信开发者工具打开后状态不稳定(${formatWechatIdeOpenHealthReason(failedResult)}),正在重试打开目标项目(保留现有窗口)...`);
|
|
550
|
+
await runWechatIdeOpenWithRetry(createIdeOpenArgv(platform, projectPath, options));
|
|
551
|
+
const recoveredResult = await verifyOpenedWechatIdeProject(projectPath, servicePortEnabled, options);
|
|
552
|
+
if (recoveredResult.ok) logger_default.info("微信开发者工具已完成自动恢复。");
|
|
553
|
+
else logger_default.warn("微信开发者工具自动恢复未完成;可设置 `WEAPP_VITE_DISABLE_IDE_OPEN_RECOVERY=1` 或传入 `--no-open-recovery` 跳过自动重试,并按提示手动处理。");
|
|
554
|
+
return recoveredResult;
|
|
555
|
+
}
|
|
556
|
+
async function verifyAndRecoverOpenedWechatIdeProject(platform, projectPath, servicePortEnabled, options) {
|
|
557
|
+
const healthResult = await verifyOpenedWechatIdeProject(projectPath, servicePortEnabled, options);
|
|
558
|
+
if (!healthResult.ok) await recoverOpenedWechatIdeProject(platform, projectPath, servicePortEnabled, options, healthResult);
|
|
559
|
+
}
|
|
560
|
+
async function openSelectedIde(platform, projectPath, options = {}) {
|
|
561
|
+
let bootstrapResult;
|
|
562
|
+
const openStrategy = options.openStrategy ?? (options.useAutomatorOpen === true ? "automator" : "cli");
|
|
563
|
+
const useAutomatorOpen = openStrategy === "automator";
|
|
564
|
+
const normalizedOptions = {
|
|
565
|
+
...options,
|
|
566
|
+
openStrategy,
|
|
567
|
+
useAutomatorOpen
|
|
568
|
+
};
|
|
569
|
+
if (platform === "weapp" && projectPath) try {
|
|
570
|
+
bootstrapResult = await bootstrapWechatDevtoolsSettings({
|
|
571
|
+
projectPath,
|
|
572
|
+
trustProject: normalizedOptions.trustProject
|
|
573
|
+
});
|
|
574
|
+
} catch (error) {
|
|
575
|
+
logger_default.warn("检测微信开发者工具服务端口或写入项目信任状态失败,继续执行 open 流程。");
|
|
576
|
+
logger_default.error(error);
|
|
577
|
+
}
|
|
578
|
+
if (platform === "weapp" && projectPath && bootstrapResult?.servicePortEnabled === false) logWechatIdeServicePortDisabledHint(projectPath);
|
|
579
|
+
if (platform === "weapp" && projectPath && bootstrapResult?.servicePortEnabled !== false && useAutomatorOpen) try {
|
|
580
|
+
const openResult = await tryOpenWechatIdeByAutomator(projectPath, normalizedOptions);
|
|
581
|
+
if (openResult === "reused") return;
|
|
582
|
+
if (openResult === "unhealthy") {
|
|
583
|
+
logger_default.warn("已连接到目标微信开发者工具项目,但协议健康检查暂未就绪;已保留当前窗口并跳过重复启动。");
|
|
584
|
+
return;
|
|
585
|
+
} else if (openResult) {
|
|
586
|
+
if (!normalizedOptions.skipPostOpenHealthCheck) await verifyAndRecoverOpenedWechatIdeProject(platform, projectPath, bootstrapResult?.servicePortEnabled, normalizedOptions);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
} catch (error) {
|
|
590
|
+
if (process.env.WEAPP_IDE_MANAGED_PROJECT_JOURNAL?.trim()) throw error;
|
|
591
|
+
if (isAutomatorLoginError(error)) {
|
|
592
|
+
logger_default.error("检测到微信开发者工具登录状态失效,请先登录后重试。");
|
|
593
|
+
logger_default.warn(formatAutomatorLoginError(error));
|
|
594
|
+
}
|
|
595
|
+
logger_default.warn(`通过 automator 启动微信开发者工具失败,回退到普通 open 流程:${formatWechatIdeAutomatorFailure(error)}`);
|
|
596
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
597
|
+
}
|
|
598
|
+
await runWechatIdeOpenWithRetry(createIdeOpenArgv(platform, projectPath, normalizedOptions));
|
|
599
|
+
if (platform === "weapp" && projectPath && normalizedOptions.prepareAutomatorSession) await prepareWechatIdeAutomatorSession(projectPath, normalizedOptions);
|
|
600
|
+
if (platform === "weapp" && projectPath && !normalizedOptions.skipPostOpenHealthCheck) await verifyAndRecoverOpenedWechatIdeProject(platform, projectPath, bootstrapResult?.servicePortEnabled, normalizedOptions);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* @description 解析 IDE 相关命令所需的平台、项目目录与配置上下文。
|
|
604
|
+
*/
|
|
605
|
+
async function resolveIdeCommandContext(options) {
|
|
606
|
+
const cwd = options.cwd ?? process.cwd();
|
|
607
|
+
let platform = options.platform;
|
|
608
|
+
let projectPath = options.projectPath;
|
|
609
|
+
if (!platform || !projectPath) try {
|
|
610
|
+
const targets = resolveRuntimeTargets({ platform });
|
|
611
|
+
const ctx = await createCompilerContext({
|
|
612
|
+
cwd,
|
|
613
|
+
mode: options.mode ?? "development",
|
|
614
|
+
configFile: options.configFile,
|
|
615
|
+
inlineConfig: createInlineConfig(targets),
|
|
616
|
+
cliPlatform: options.cliPlatform
|
|
617
|
+
});
|
|
618
|
+
platform ??= ctx.configService.platform;
|
|
619
|
+
if (!projectPath) projectPath = resolveIdeProjectRoot(ctx.configService.mpDistRoot, ctx.configService.cwd, ctx.configService.multiPlatform.projectConfigs !== void 0);
|
|
620
|
+
return {
|
|
621
|
+
cwd: ctx.configService.cwd,
|
|
622
|
+
platform,
|
|
623
|
+
projectPath,
|
|
624
|
+
weappViteConfig: ctx.configService.weappViteConfig,
|
|
625
|
+
mpDistRoot: ctx.configService.mpDistRoot
|
|
626
|
+
};
|
|
627
|
+
} catch {}
|
|
628
|
+
if (!projectPath) {
|
|
629
|
+
const defaultProjectRoot = getDefaultIdeProjectRoot(platform);
|
|
630
|
+
if (defaultProjectRoot) projectPath = resolveIdeProjectRoot(defaultProjectRoot, cwd);
|
|
631
|
+
}
|
|
632
|
+
return {
|
|
633
|
+
cwd,
|
|
634
|
+
platform,
|
|
635
|
+
projectPath
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
/** 打开项目、健康检查与恢复共用同一安装身份。 */
|
|
639
|
+
async function openIde(platform, projectPath, options = {}) {
|
|
640
|
+
if (platform === "weapp") return await withWechatDevtoolsSelection(options, () => openSelectedIde(platform, projectPath, options));
|
|
641
|
+
return await openSelectedIde(platform, projectPath, options);
|
|
642
|
+
}
|
|
643
|
+
export { resolveIdeProjectRoot as a, resolveIdeProjectPath as i, openIde as n, shouldUseAutomatorProjectWrapper as o, resolveIdeCommandContext as r, executeWechatIdeCliCommand as s, closeIde as t };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/cli/options.ts
|
|
2
|
+
function filterDuplicateOptions(options) {
|
|
3
|
+
for (const [key, value] of Object.entries(options)) if (Array.isArray(value)) options[key] = value[value.length - 1];
|
|
4
|
+
}
|
|
5
|
+
function resolveConfigFile(options) {
|
|
6
|
+
if (typeof options.config === "string") return options.config;
|
|
7
|
+
if (typeof options.c === "string") return options.c;
|
|
8
|
+
}
|
|
9
|
+
function convertBase(value) {
|
|
10
|
+
if (value === 0) return "";
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function coerceBooleanOption(value) {
|
|
14
|
+
if (value === void 0) return;
|
|
15
|
+
if (typeof value === "boolean") return value;
|
|
16
|
+
if (typeof value === "string") {
|
|
17
|
+
const normalized = value.trim().toLowerCase();
|
|
18
|
+
if (normalized === "") return true;
|
|
19
|
+
if (normalized === "false" || normalized === "0" || normalized === "off" || normalized === "no") return false;
|
|
20
|
+
if (normalized === "true" || normalized === "1" || normalized === "on" || normalized === "yes") return true;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === "number") return value !== 0;
|
|
24
|
+
return Boolean(value);
|
|
25
|
+
}
|
|
26
|
+
function parseDashboardUiHost(value) {
|
|
27
|
+
if (value === void 0 || value === "standalone" || value === "hub") return value;
|
|
28
|
+
throw new Error(`不支持的 --ui-host 值:${String(value)}(仅支持 standalone 或 hub)`);
|
|
29
|
+
}
|
|
30
|
+
function isUiEnabled(options) {
|
|
31
|
+
return Boolean(options.ui || options.analyze || options.uiHost !== void 0);
|
|
32
|
+
}
|
|
33
|
+
export { parseDashboardUiHost as a, isUiEnabled as i, convertBase as n, resolveConfigFile as o, filterDuplicateOptions as r, coerceBooleanOption as t };
|