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.
Files changed (135) hide show
  1. package/README.md +14 -6
  2. package/THIRD_PARTY_NOTICES.md +60 -0
  3. package/bin/bootstrap.js +9 -4
  4. package/bin/bootstrap.test.ts +82 -1
  5. package/bin/nodeVersionWarning.js +17 -0
  6. package/bin/nodeVersionWarning.test.ts +30 -0
  7. package/dist/action-BD56SQh4.mjs +254 -0
  8. package/dist/action-CPtgEl6p.mjs +94 -0
  9. package/dist/action-le0bNff_.mjs +1102 -0
  10. package/dist/action-ytG5oFAw.mjs +138 -0
  11. package/dist/action-zmJrU8PC.mjs +245 -0
  12. package/dist/{analyze-ZJUvEdaY.mjs → analyze-DCZo-sJd.mjs} +4 -71
  13. package/dist/artifacts-TrTX9_jj.mjs +104 -0
  14. package/dist/assets-XyhpYtGl.mjs +630 -0
  15. package/dist/auto-import-components/resolvers.d.mts +1 -1
  16. package/dist/auto-import-components/resolvers.mjs +1 -1
  17. package/dist/auto-import-presets/wevu-router.d.mts +1 -1
  18. package/dist/auto-import-presets/wevu-router.mjs +1 -1
  19. package/dist/auto-import-presets/wevu.d.mts +1 -1
  20. package/dist/auto-import-presets/wevu.mjs +1 -1
  21. package/dist/auto-import-presets.d.mts +2 -2
  22. package/dist/auto-import-presets.mjs +2 -2
  23. package/dist/auto-routes.d.mts +1 -3
  24. package/dist/auto-routes.mjs +3 -4
  25. package/dist/{budget-BD7VqLCl.d.mts → budget-DTPngJU0.d.mts} +1 -10
  26. package/dist/budget-_Mu-4GKn.mjs +63 -0
  27. package/dist/builtProject-B145uOt5.mjs +534 -0
  28. package/dist/{package-7swhyLmf.mjs → classifier-CNTJOYQL.mjs} +5 -9
  29. package/dist/cli-acceptance.mjs +3 -4
  30. package/dist/cli.mjs +142 -4569
  31. package/dist/{config-DRGcCi3h.mjs → config-59ZWhCIf.mjs} +1 -2
  32. package/dist/{config-V0L-IAJf.d.mts → config-BNx2BODw.d.mts} +145 -150
  33. package/dist/config.d.mts +2 -2
  34. package/dist/config.mjs +3 -3
  35. package/dist/{constants-DEZdcsMn.mjs → constants-BOe8mgqL.mjs} +2 -4
  36. package/dist/{createCompilerContextInstance-DJH_P_nZ.mjs → createCompilerContextInstance-BXSdH2E8.mjs} +19930 -14019
  37. package/dist/{createContext-BqYzHhY9.mjs → createContext-W0TeXxbo.mjs} +7 -5
  38. package/dist/dashboard/analyze.d.mts +1 -7
  39. package/dist/dashboard/analyze.mjs +3 -1
  40. package/dist/dashboard/vite.d.mts +2 -4
  41. package/dist/dashboard/vite.mjs +1 -2
  42. package/dist/dashboard.d.mts +2 -2
  43. package/dist/dashboard.mjs +1733 -1
  44. package/dist/dashboardTransport-C9290QgS.mjs +15 -0
  45. package/dist/{dashboardViteBridge-Dy3nAD4m.mjs → dashboardViteBridge-B7QgQo94.mjs} +11 -11
  46. package/dist/{dev-fR5GiJRO.mjs → dev-D1QSExwk.mjs} +6 -3
  47. package/dist/devProvider-Bcvz5nu4.mjs +4966 -0
  48. package/dist/docs/README.md +14 -6
  49. package/dist/docs/ai-workflows.md +2 -0
  50. package/dist/docs/mcp.md +11 -1
  51. package/dist/docs/troubleshooting.md +16 -0
  52. package/dist/docs/vue-sfc.md +25 -2
  53. package/dist/docs/weapp-config.md +29 -0
  54. package/dist/docs/wevu-authoring.md +2 -0
  55. package/dist/doctor-worker.mjs +5 -5
  56. package/dist/doctor.d.mts +2 -8
  57. package/dist/doctor.mjs +24 -31
  58. package/dist/engine-Mnnm_ALP.mjs +53 -0
  59. package/dist/file-5eEfbK60.mjs +1 -0
  60. package/dist/{file-sC3jD7Fh.mjs → file-D8mp5GmB.mjs} +50 -26
  61. package/dist/{files-BqxFIPRp.mjs → files-Cy9jURJu.mjs} +1 -2
  62. package/dist/forwardConsole-D2Q0RIqc.mjs +509 -0
  63. package/dist/getInstance-BXNVH7sU.mjs +1 -0
  64. package/dist/{getInstance-DiGSzBNI.mjs → getInstance-DfNlbr-X.mjs} +2 -3
  65. package/dist/history-dKxzoHmN.mjs +774 -0
  66. package/dist/i18n.d.mts +1 -3
  67. package/dist/i18n.mjs +1 -2
  68. package/dist/{index-C9HjUX5c.d.mts → index-DIZJRrvK.d.mts} +1 -24
  69. package/dist/{index-CaXAtb9e.d.mts → index-SnaW3cvA.d.mts} +0 -12
  70. package/dist/index.d.mts +3 -7
  71. package/dist/index.mjs +6 -6
  72. package/dist/{json-BL8Dhhk6.mjs → json-Cvon2mw5.mjs} +1 -2
  73. package/dist/json.d.mts +1 -1
  74. package/dist/json.mjs +1 -1
  75. package/dist/lib-CJyMBzoe.mjs +140 -0
  76. package/dist/{lifecycle-BROTlwSL.mjs → lifecycle-CUo8PMQc.mjs} +123 -33
  77. package/dist/{loadConfig-C3BQhz7F.mjs → loadConfig-CKIdfW4o.mjs} +2 -3
  78. package/dist/loadConfig-D4WGJcYp.mjs +1 -0
  79. package/dist/logBuildAppFinish-DOBoof6S.mjs +54 -0
  80. package/dist/mcp-D88QvQgG.mjs +84 -0
  81. package/dist/{mcp-Cj8Maqo6.mjs → mcp-ovJgl1N9.mjs} +2 -4
  82. package/dist/mcp.d.mts +1 -3
  83. package/dist/mcp.mjs +1 -1
  84. package/dist/mcpClient-C8JzVZ46.mjs +283 -0
  85. package/dist/{processCleanup-B6KA30Zc.mjs → metadata-HlDKtlsu.mjs} +2 -21
  86. package/dist/nodeEnv-zq1EymWj.mjs +6 -0
  87. package/dist/openIde-QoYKhuuM.mjs +643 -0
  88. package/dist/options-Cz8vZ-0w.mjs +33 -0
  89. package/dist/{chunkStrategy-DRA5WpB-.mjs → package-DR62fAzP.mjs} +32 -31
  90. package/dist/path-E1OjBJAl.mjs +43 -0
  91. package/dist/{platform-CnkySBKz.mjs → platform-BiMpsZIb.mjs} +1 -2
  92. package/dist/{pluginHost--CaeyWpA.mjs → pluginHost-vn8Vty1J.mjs} +1 -2
  93. package/dist/processCleanup-DzB64WI8.mjs +18 -0
  94. package/dist/{protocol-vg8HGJ4n.mjs → protocol-HiSJRrSO.mjs} +43 -41
  95. package/dist/reader-wzPH_W8A.mjs +92 -0
  96. package/dist/realpathScope-DwlLaCk3.mjs +22 -0
  97. package/dist/report-PJVyo-UZ.mjs +105 -0
  98. package/dist/{path-doV773b7.mjs → resolvedId-DaxPh_yV.mjs} +5 -50
  99. package/dist/{resolvers-Dod-euqX.mjs → resolvers-CKYqmRD_.mjs} +10 -20
  100. package/dist/resolvers.d.mts +1 -1
  101. package/dist/resolvers.mjs +1 -1
  102. package/dist/{routes-C7fCmf92.d.mts → routes-DvAFX29h.d.mts} +0 -2
  103. package/dist/{runtime-Ee2HY6gR.d.mts → runtime-BL4RjBRa.d.mts} +1 -9
  104. package/dist/runtime-CKtMVERT.mjs +42 -0
  105. package/dist/{runtime-D6VCNhNY.mjs → runtime-DDUCb7pP.mjs} +4 -8
  106. package/dist/runtime.d.mts +1 -1
  107. package/dist/runtime.mjs +1 -1
  108. package/dist/schematics-DikfOjMD.mjs +90 -0
  109. package/dist/{session-PskhD-nZ.mjs → session-COrQJYif.mjs} +81 -21
  110. package/dist/test.d.mts +1 -3
  111. package/dist/test.mjs +54 -30
  112. package/dist/types-BK2EQ3Jm.d.mts +37 -0
  113. package/dist/{types-CgZn5X6j.d.mts → types-e2BMP9NU.d.mts} +1 -4
  114. package/dist/types.d.mts +4 -4
  115. package/dist/{upload-D4msblBf.mjs → upload-Chal5b3w.mjs} +118 -24
  116. package/dist/upload-worker.mjs +3 -5
  117. package/dist/{utils-CJSCgEj6.mjs → utils-CTGSZp4j.mjs} +72 -146
  118. package/dist/vite.d.mts +2 -4
  119. package/dist/vite.mjs +55 -21
  120. package/dist/volar.mjs +1 -2
  121. package/dist/{wevu-BQWUU7br.mjs → wevu-BaihCXO9.mjs} +1 -2
  122. package/dist/wevu-DTtSOyxB.d.mts +3 -0
  123. package/dist/{wevu-router-Dg1LnBlg.mjs → wevu-router-BIoxDbnu.mjs} +1 -2
  124. package/dist/wevu-router-CdWurGQ4.d.mts +3 -0
  125. package/dist/wxs-7V7MPzeW.mjs +1 -0
  126. package/dist/wxs-BdHHXltv.mjs +110 -0
  127. package/package.json +62 -53
  128. package/dist/dashboard-DvqF3Key.mjs +0 -1842
  129. package/dist/devProvider-BGBkw28J.mjs +0 -1050
  130. package/dist/file-DRb4eWqw.mjs +0 -1
  131. package/dist/getInstance-SiE6WZRh.mjs +0 -1
  132. package/dist/loadConfig-VGtBF4qm.mjs +0 -1
  133. package/dist/mcp-D3Yh24Cj.mjs +0 -529
  134. package/dist/wevu-C4KEC5kO.d.mts +0 -5
  135. package/dist/wevu-router-Cg2sIkIE.d.mts +0 -5
@@ -0,0 +1,138 @@
1
+ import { r as logger_default } from "./logger-DGn5iEVN.mjs";
2
+ import { o as resolveConfigFile } from "./options-Cz8vZ-0w.mjs";
3
+ import { c as startWeappViteMcpServer, s as resolveWeappMcpConfig } from "./mcp-ovJgl1N9.mjs";
4
+ import { a as inspectMcpClientConfig, i as resolveSupportedMcpClient, n as buildMcpClientConfigPlan, r as formatMcpQuickStart, t as writeMcpClientConfig } from "./mcpClient-C8JzVZ46.mjs";
5
+ import process from "node:process";
6
+ import path from "pathe";
7
+ import { runWithSuspendedSharedInput } from "weapp-ide-cli";
8
+ import { createInterface } from "node:readline/promises";
9
+ // src/cli/commands/mcp/action.ts
10
+ function resolvePort(port) {
11
+ if (typeof port === "number" && Number.isInteger(port)) return port;
12
+ if (typeof port === "string" && port.trim()) {
13
+ const parsed = Number.parseInt(port, 10);
14
+ if (Number.isInteger(parsed)) return parsed;
15
+ }
16
+ }
17
+ async function resolveHttpUrl(options) {
18
+ if (options.url?.trim()) return options.url.trim();
19
+ const workspaceRoot = options.workspaceRoot ? path.resolve(options.workspaceRoot) : process.cwd();
20
+ const originalCwd = process.cwd();
21
+ try {
22
+ if (workspaceRoot !== originalCwd) process.chdir(workspaceRoot);
23
+ const configFile = resolveConfigFile(options);
24
+ const { loadConfig } = await import("./loadConfig-D4WGJcYp.mjs");
25
+ const loaded = await loadConfig(configFile);
26
+ const resolved = resolveWeappMcpConfig(loaded?.config?.weapp?.mcp);
27
+ return `http://${resolved.host}:${resolved.port}${resolved.endpoint}`;
28
+ } catch {
29
+ const resolved = resolveWeappMcpConfig(void 0);
30
+ return `http://${resolved.host}:${resolved.port}${resolved.endpoint}`;
31
+ } finally {
32
+ if (process.cwd() !== originalCwd) process.chdir(originalCwd);
33
+ }
34
+ }
35
+ async function confirmWrite() {
36
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
37
+ return await runWithSuspendedSharedInput(async () => {
38
+ const rl = createInterface({
39
+ input: process.stdin,
40
+ output: process.stdout
41
+ });
42
+ try {
43
+ const normalized = (await rl.question("是否写入配置文件?(Y/n) ")).trim().toLowerCase();
44
+ return normalized === "" || normalized === "y" || normalized === "yes";
45
+ } finally {
46
+ rl.close();
47
+ }
48
+ });
49
+ }
50
+ function resolveClientTransport(transport) {
51
+ return transport === "http" ? "http" : "command";
52
+ }
53
+ async function handlePrint(clientName, options, write = false) {
54
+ const client = resolveSupportedMcpClient(clientName);
55
+ const workspaceRoot = options.workspaceRoot ?? process.cwd();
56
+ const transport = resolveClientTransport(options.transport);
57
+ const httpUrl = transport === "http" ? await resolveHttpUrl(options) : void 0;
58
+ const plan = buildMcpClientConfigPlan({
59
+ client,
60
+ transport,
61
+ url: httpUrl,
62
+ workspaceRoot
63
+ });
64
+ logger_default.info(`${plan.target.displayName} 配置文件:${plan.target.configPath}`);
65
+ logger_default.info(`服务器名称:${plan.target.serverName}`);
66
+ process.stdout.write(`${plan.preview}\n`);
67
+ if (!write) return;
68
+ if (options.yes || await confirmWrite()) {
69
+ await writeMcpClientConfig(plan);
70
+ logger_default.success(`已写入 ${plan.target.displayName} MCP 配置。`);
71
+ logger_default.info(`请重启 ${plan.target.displayName},然后执行:wv mcp doctor ${client}`);
72
+ return;
73
+ }
74
+ logger_default.info("已取消写入。");
75
+ }
76
+ async function handleDoctor(clientName, options) {
77
+ const client = resolveSupportedMcpClient(clientName);
78
+ const result = await inspectMcpClientConfig({
79
+ client,
80
+ workspaceRoot: options.workspaceRoot ?? process.cwd()
81
+ });
82
+ logger_default.info(`${result.displayName} 配置文件:${result.configPath}`);
83
+ logger_default.info(`服务器名称:${result.serverName}`);
84
+ if (!result.configExists || result.issues.length > 0) {
85
+ for (const issue of result.issues) logger_default.warn(issue);
86
+ throw new Error("MCP 客户端配置检查未通过。");
87
+ }
88
+ if (result.transport) logger_default.info(`传输模式:${result.transport}`);
89
+ if (result.httpReachable !== void 0) logger_default.info(`HTTP 服务可达:${result.httpReachable ? "是" : "否"}`);
90
+ logger_default.success("MCP 客户端配置检查通过。");
91
+ }
92
+ async function handleServer(options) {
93
+ const resolvedTransport = options.transport === "http" ? "streamable-http" : options.transport === "command" ? void 0 : options.transport;
94
+ const handle = await startWeappViteMcpServer({
95
+ endpoint: options.endpoint,
96
+ host: options.host,
97
+ port: resolvePort(options.port),
98
+ restEndpoint: options.rest === false ? false : options.restEndpoint,
99
+ transport: resolvedTransport,
100
+ unref: options.unref,
101
+ workspaceRoot: options.workspaceRoot
102
+ });
103
+ const shutdown = async () => {
104
+ process.off("SIGINT", shutdown);
105
+ process.off("SIGTERM", shutdown);
106
+ process.stdin.off("end", shutdown);
107
+ await handle.close?.();
108
+ };
109
+ process.once("SIGINT", shutdown);
110
+ process.once("SIGTERM", shutdown);
111
+ if (resolvedTransport !== "streamable-http") process.stdin.once("end", shutdown);
112
+ for (const line of formatMcpQuickStart({
113
+ httpUrl: resolvedTransport === "streamable-http" ? `http://${options.host ?? "127.0.0.1"}:${resolvePort(options.port) ?? 3088}${options.endpoint ?? "/mcp"}` : void 0,
114
+ transport: resolvedTransport === "streamable-http" ? "http" : "command"
115
+ })) logger_default.info(line);
116
+ }
117
+ /** 执行 MCP 子命令,注册与帮助阶段不加载服务依赖。 */
118
+ async function runMcpCommand(args, options) {
119
+ const [subcommand, client] = args;
120
+ if (subcommand === "init") {
121
+ if (!client) throw new Error("缺少客户端名称,请使用:wv mcp init <codex|claude-code|cursor>");
122
+ await handlePrint(client, options, true);
123
+ return;
124
+ }
125
+ if (subcommand === "print") {
126
+ if (!client) throw new Error("缺少客户端名称,请使用:wv mcp print <codex|claude-code|cursor>");
127
+ await handlePrint(client, options, false);
128
+ return;
129
+ }
130
+ if (subcommand === "doctor") {
131
+ if (!client) throw new Error("缺少客户端名称,请使用:wv mcp doctor <codex|claude-code|cursor>");
132
+ await handleDoctor(client, options);
133
+ return;
134
+ }
135
+ if (subcommand) throw new Error(`未知的 mcp 子命令:${subcommand}`);
136
+ await handleServer(options);
137
+ }
138
+ export { runMcpCommand };
@@ -0,0 +1,245 @@
1
+ import { c as getBackendForCapability, n as formatBytes, u as CompilerSession } from "./createCompilerContextInstance-BXSdH2E8.mjs";
2
+ import { r as logger_default, t as colors } from "./logger-DGn5iEVN.mjs";
3
+ import { i as resolveRuntimeTargets, n as logRuntimeTarget, r as resolveConfiguredRuntimeTargets, t as createInlineConfig } from "./runtime-CKtMVERT.mjs";
4
+ import { i as resolveIdeProjectPath, n as openIde } from "./openIde-QoYKhuuM.mjs";
5
+ import { a as parseDashboardUiHost, i as isUiEnabled, o as resolveConfigFile, r as filterDuplicateOptions } from "./options-Cz8vZ-0w.mjs";
6
+ import { n as formatDuration, r as scheduleCompletedProductionBuildExit, t as logBuildAppFinish } from "./logBuildAppFinish-DOBoof6S.mjs";
7
+ import { n as createDashboardArtifactSnapshot } from "./artifacts-TrTX9_jj.mjs";
8
+ import { i as startAnalyzeDashboard, n as writeAnalyzeHistorySnapshot, r as analyzeSubpackages, t as readLatestAnalyzeHistorySnapshot } from "./history-dKxzoHmN.mjs";
9
+ import { t as setCommandNodeEnv } from "./nodeEnv-zq1EymWj.mjs";
10
+ import { a as resolveBuildUploadOptions } from "./report-PJVyo-UZ.mjs";
11
+ import { a as prepareAutoUploadMetadataWithRollback, n as executeUploadTarget, o as validateAutoUploadMetadata, t as createUploadTarget } from "./builtProject-B145uOt5.mjs";
12
+ import process from "node:process";
13
+ import { Buffer } from "node:buffer";
14
+ const WINDOWS_SEPARATOR_RE = /\\/g;
15
+ function normalizeFileName(fileName) {
16
+ return fileName.replace(WINDOWS_SEPARATOR_RE, "/");
17
+ }
18
+ function getOutputItemBytes(item) {
19
+ if (item.type === "chunk") return typeof item.code === "string" ? Buffer.byteLength(item.code, "utf8") : 0;
20
+ if (typeof item.source === "string") return Buffer.byteLength(item.source, "utf8");
21
+ if (item.source instanceof Uint8Array) return item.source.byteLength;
22
+ return 0;
23
+ }
24
+ function resolveSubPackageRoot(fileName, roots) {
25
+ const normalized = normalizeFileName(fileName);
26
+ return roots.find((root) => normalized === root || normalized.startsWith(`${root}/`));
27
+ }
28
+ function collectPackageSizeReports(output, subPackageMap) {
29
+ const outputs = Array.isArray(output) ? output : [output];
30
+ const roots = [...subPackageMap?.keys() ?? []].filter(Boolean).sort((a, b) => b.length - a.length || a.localeCompare(b));
31
+ const packageBytes = /* @__PURE__ */ new Map([["__main__", 0]]);
32
+ for (const root of roots) packageBytes.set(root, 0);
33
+ for (const current of outputs) for (const item of current.output ?? []) {
34
+ const root = resolveSubPackageRoot(item.fileName, roots) ?? "__main__";
35
+ packageBytes.set(root, (packageBytes.get(root) ?? 0) + getOutputItemBytes(item));
36
+ }
37
+ const reports = [{
38
+ root: "__main__",
39
+ label: "主包",
40
+ bytes: packageBytes.get("__main__") ?? 0
41
+ }];
42
+ for (const root of roots) {
43
+ const meta = subPackageMap?.get(root);
44
+ const isIndependent = Boolean(meta?.subPackage.independent);
45
+ reports.push({
46
+ root,
47
+ label: `${isIndependent ? "独立分包" : "分包"} ${root}`,
48
+ bytes: packageBytes.get(root) ?? 0
49
+ });
50
+ }
51
+ return reports;
52
+ }
53
+ function logBuildPackageSizeReport(options) {
54
+ const warningBytes = Number(options.warningBytes ?? 2097152);
55
+ const reports = collectPackageSizeReports(options.output, options.subPackageMap);
56
+ logger_default.success("主包/分包体积报告:");
57
+ for (const report of reports) logger_default.info(`${report.label}:${formatBytes(report.bytes)}`);
58
+ if (!(Number.isFinite(warningBytes) && warningBytes > 0)) return;
59
+ for (const report of reports) {
60
+ if (report.bytes <= warningBytes) continue;
61
+ logger_default.warn(`[包体积] ${colors.yellow(report.label)} 体积 ${colors.yellow(formatBytes(report.bytes))},已超过阈值 ${colors.yellow(formatBytes(warningBytes))}。`);
62
+ }
63
+ }
64
+ // src/cli/commands/build/action.ts
65
+ function emitDashboardEvents(handle, events) {
66
+ handle?.emitRuntimeEvents(events);
67
+ }
68
+ function normalizeBuildSourcemap(value) {
69
+ if (value === "true") return true;
70
+ if (value === "false") return false;
71
+ return value;
72
+ }
73
+ function normalizeBuildMinify(value) {
74
+ if (value === "true") return true;
75
+ if (value === "false") return false;
76
+ return value;
77
+ }
78
+ function hasCliOption(options, key) {
79
+ return Object.prototype.hasOwnProperty.call(options, key);
80
+ }
81
+ function createBuildInlineConfig(options) {
82
+ const build = {};
83
+ if (typeof options.outDir === "string") build.outDir = options.outDir;
84
+ if (hasCliOption(options, "sourcemap")) build.sourcemap = normalizeBuildSourcemap(options.sourcemap);
85
+ if (hasCliOption(options, "minify")) build.minify = normalizeBuildMinify(options.minify);
86
+ if (typeof options.emptyOutDir === "boolean") build.emptyOutDir = options.emptyOutDir;
87
+ return Object.keys(build).length ? { build } : void 0;
88
+ }
89
+ /** 执行已完成参数校验的生产构建,复用注册器持有的原始命令参数。 */
90
+ async function runBuildCommand(cli, root, options) {
91
+ let analyzeHandle;
92
+ let session;
93
+ let ctx;
94
+ let targets;
95
+ let uploadMetadataRollback;
96
+ let buildCompleted = false;
97
+ let buildFailed = false;
98
+ try {
99
+ options = { ...options };
100
+ filterDuplicateOptions(options);
101
+ options.uiHost = parseDashboardUiHost(options.uiHost);
102
+ let uploadOptions = resolveBuildUploadOptions(cli, options);
103
+ setCommandNodeEnv("production");
104
+ const cwd = root ?? process.cwd();
105
+ const configFile = resolveConfigFile(options);
106
+ targets = resolveRuntimeTargets(options);
107
+ if (uploadOptions) validateAutoUploadMetadata(uploadOptions, "upload");
108
+ if (uploadOptions && !getBackendForCapability(targets, "miniprogram", "build")) throw new Error("--upload 仅支持包含小程序目标的构建,不能用于纯 Web 构建。");
109
+ const inlineConfig = createInlineConfig(targets, {
110
+ scope: options.scope,
111
+ inlineConfig: createBuildInlineConfig(options)
112
+ });
113
+ if (uploadOptions) {
114
+ const prepared = await prepareAutoUploadMetadataWithRollback(cwd, uploadOptions, "upload");
115
+ uploadOptions = prepared.options;
116
+ uploadMetadataRollback = prepared.rollback;
117
+ }
118
+ session = new CompilerSession();
119
+ ctx = await session.initialize({
120
+ cwd,
121
+ mode: options.mode ?? "production",
122
+ configFile,
123
+ inlineConfig,
124
+ cliPlatform: targets.rawPlatform,
125
+ projectConfigPath: options.projectConfig,
126
+ emitDefaultAutoImportOutputs: false,
127
+ preloadAppEntry: false
128
+ });
129
+ targets = resolveConfiguredRuntimeTargets(targets, ctx.configService.options?.sourceConfig?.weapp?.platform);
130
+ if (uploadOptions && !getBackendForCapability(targets, "miniprogram", "build")) {
131
+ await uploadMetadataRollback?.();
132
+ uploadMetadataRollback = void 0;
133
+ throw new Error("--upload 仅支持包含小程序目标的构建,不能用于纯 Web 构建。");
134
+ }
135
+ uploadMetadataRollback = void 0;
136
+ for (const backend of targets.select("build")) session.onClose(() => backend.driver.close(ctx));
137
+ const { configService } = ctx;
138
+ const uploadTarget = uploadOptions ? await createUploadTarget(configService, uploadOptions, "upload") : void 0;
139
+ const miniBackend = getBackendForCapability(targets, "miniprogram", "build");
140
+ const webBackend = getBackendForCapability(targets, "web", "build");
141
+ logRuntimeTarget(targets, { resolvedConfigPlatform: configService.platform });
142
+ const enableAnalyze = Boolean(isUiEnabled(options) && miniBackend);
143
+ for (const backend of targets.select("build")) {
144
+ if (backend.descriptor.id === "miniprogram") {
145
+ const miniBuildStartedAt = Date.now();
146
+ const output = await session.run(() => backend.driver.build(ctx, options));
147
+ const miniBuildDurationMs = Date.now() - miniBuildStartedAt;
148
+ logger_default.success(`小程序构建完成,耗时:${colors.green(formatDuration(miniBuildDurationMs))}`);
149
+ if (!Array.isArray(output) && "output" in output) logBuildPackageSizeReport({
150
+ output,
151
+ subPackageMap: ctx.scanService?.subPackageMap,
152
+ warningBytes: configService.weappViteConfig.packageSizeWarningBytes
153
+ });
154
+ if (enableAnalyze) {
155
+ const analyzeStartedAt = Date.now();
156
+ const previousAnalyzeResult = await readLatestAnalyzeHistorySnapshot(configService);
157
+ const artifactSnapshot = createDashboardArtifactSnapshot();
158
+ const analyzeResult = await analyzeSubpackages(ctx, { onArtifact: artifactSnapshot.capture });
159
+ await writeAnalyzeHistorySnapshot(analyzeResult, configService);
160
+ const analyzeDurationMs = Date.now() - analyzeStartedAt;
161
+ analyzeHandle = await startAnalyzeDashboard(analyzeResult, {
162
+ watch: true,
163
+ uiHost: options.uiHost,
164
+ artifacts: artifactSnapshot.files,
165
+ cwd: configService.cwd,
166
+ packageManagerAgent: configService.packageManager.agent,
167
+ pluginRoot: configService.absolutePluginRoot,
168
+ srcRoot: configService.absoluteSrcRoot,
169
+ previousResult: previousAnalyzeResult,
170
+ initialEvents: [{
171
+ kind: "build",
172
+ level: "success",
173
+ title: "mini build completed",
174
+ detail: `生产构建已完成,当前 analyze 结果包含 ${analyzeResult.packages.length} 个包。`,
175
+ durationMs: miniBuildDurationMs,
176
+ tags: ["build", "mini"]
177
+ }, {
178
+ kind: "build",
179
+ level: "success",
180
+ title: "analyze completed",
181
+ detail: `分析已完成,当前包含 ${analyzeResult.packages.length} 个包与 ${analyzeResult.modules.length} 个模块。`,
182
+ durationMs: analyzeDurationMs,
183
+ tags: ["build", "analyze"]
184
+ }]
185
+ }) ?? void 0;
186
+ }
187
+ continue;
188
+ }
189
+ const webConfig = configService.weappWebConfig;
190
+ if (backend.descriptor.id !== "web" || !webConfig?.enabled) continue;
191
+ const webBuildStartedAt = Date.now();
192
+ try {
193
+ await session.run(() => backend.driver.build(ctx, options));
194
+ const webBuildDurationMs = Date.now() - webBuildStartedAt;
195
+ logger_default.success(`Web 构建完成,输出目录:${colors.green(configService.relativeCwd(webConfig.outDir))},耗时:${colors.green(formatDuration(webBuildDurationMs))}`);
196
+ emitDashboardEvents(analyzeHandle, [{
197
+ kind: "build",
198
+ level: "success",
199
+ title: "web build completed",
200
+ detail: `Web 构建已完成,输出目录 ${configService.relativeCwd(webConfig.outDir)}。`,
201
+ durationMs: webBuildDurationMs,
202
+ tags: ["build", "web"]
203
+ }]);
204
+ } catch (error) {
205
+ emitDashboardEvents(analyzeHandle, [{
206
+ kind: "diagnostic",
207
+ level: "error",
208
+ title: "web build failed",
209
+ detail: error instanceof Error ? error.message : String(error),
210
+ durationMs: Date.now() - webBuildStartedAt,
211
+ tags: ["build", "web"]
212
+ }]);
213
+ logger_default.error(error);
214
+ throw error;
215
+ }
216
+ }
217
+ if (uploadTarget && uploadOptions) await executeUploadTarget(uploadTarget, uploadOptions, "upload");
218
+ if (miniBackend) logBuildAppFinish(configService, void 0, { skipWeb: !webBackend });
219
+ if (options.open && getBackendForCapability(targets, "miniprogram", "ide")) {
220
+ emitDashboardEvents(analyzeHandle, [{
221
+ kind: "command",
222
+ level: "info",
223
+ title: "opening ide",
224
+ detail: "构建完成后准备打开 IDE 项目。",
225
+ tags: ["ide", "open"]
226
+ }]);
227
+ const generatedProjectConfig = configService.multiPlatform.projectConfigs !== void 0;
228
+ await openIde(configService.platform, resolveIdeProjectPath(generatedProjectConfig ? configService.outDir : configService.mpDistRoot, generatedProjectConfig), {
229
+ openRecovery: options.openRecovery,
230
+ trustProject: options.trustProject,
231
+ openStrategy: options.ideOpenStrategy
232
+ });
233
+ }
234
+ if (analyzeHandle) await analyzeHandle.waitForExit();
235
+ buildCompleted = true;
236
+ } catch (error) {
237
+ buildFailed = true;
238
+ throw error;
239
+ } finally {
240
+ if (buildFailed) await session?.close().catch((error) => logger_default.error(error));
241
+ else await session?.close();
242
+ if (buildCompleted) scheduleCompletedProductionBuildExit(options, analyzeHandle);
243
+ }
244
+ }
245
+ export { runBuildCommand };
@@ -1,68 +1,4 @@
1
- //#region src/analyze/subpackages/artifacts/category.ts
2
- function isRuntimeCategory(category) {
3
- return category === "runtime" || category === "reactivity" || category === "host" || category === "helper";
4
- }
5
- //#endregion
6
- //#region src/analyze/subpackages/budget.ts
7
- const defaultBudgets = {
8
- totalBytes: 20971520,
9
- mainBytes: 2097152,
10
- subPackageBytes: 2097152,
11
- independentBytes: 2097152,
12
- warningRatio: .85,
13
- source: "default"
14
- };
15
- function createAnalyzeBudgetCheck(result) {
16
- const budgets = result.metadata?.budgets ?? defaultBudgets;
17
- const createItem = (options, unknown = false) => {
18
- const ratio = options.limitBytes > 0 ? options.currentBytes / options.limitBytes : options.currentBytes > 0 ? 1 : 0;
19
- return {
20
- ...options,
21
- ratio,
22
- status: unknown ? "unknown" : ratio >= 1 ? "exceeded" : ratio >= budgets.warningRatio ? "warning" : "ok"
23
- };
24
- };
25
- const files = result.packages.flatMap((pkg) => pkg.files);
26
- const unique = new Map(files.map((file) => [file.file, file]));
27
- const sizeUnknown = (items) => items.some((file) => typeof file.size !== "number" || !Number.isFinite(file.size) || file.size < 0);
28
- const items = [createItem({
29
- id: "__total__",
30
- label: "总包",
31
- scope: "total",
32
- currentBytes: [...unique.values()].reduce((sum, file) => sum + (file.size ?? 0), 0),
33
- limitBytes: budgets.totalBytes,
34
- measurement: "file-bytes",
35
- files: [...unique.keys()].sort()
36
- }, sizeUnknown(files))];
37
- for (const pkg of result.packages) {
38
- const limitBytes = budgets.packageBytes?.[pkg.id] ?? (pkg.type === "main" ? budgets.mainBytes : pkg.type === "subPackage" ? budgets.subPackageBytes : pkg.type === "independent" ? budgets.independentBytes : void 0);
39
- if (limitBytes === void 0) continue;
40
- items.push(createItem({
41
- id: pkg.id,
42
- label: pkg.label,
43
- scope: pkg.type,
44
- currentBytes: pkg.files.reduce((sum, file) => sum + (file.size ?? 0), 0),
45
- limitBytes,
46
- measurement: "file-bytes",
47
- files: pkg.files.map((file) => file.file).sort()
48
- }, sizeUnknown(pkg.files)));
49
- }
50
- if (budgets.runtimeBytes !== void 0) {
51
- const artifacts = result.artifacts;
52
- items.push(createItem({
53
- id: "__runtime__",
54
- label: "Runtime(含混合 chunk 的文件上界)",
55
- scope: "runtime",
56
- currentBytes: artifacts?.runtime.upperBoundBytes ?? 0,
57
- limitBytes: budgets.runtimeBytes,
58
- measurement: artifacts ? "upper-bound" : "unavailable",
59
- files: artifacts?.files.filter((file) => artifacts.runtime.unknownFiles.includes(file.file) || file.modules.some((module) => isRuntimeCategory(module.category))).map((file) => file.file) ?? files.filter((file) => file.type === "chunk" || /\.[cm]?js$/i.test(file.file)).map((file) => file.file)
60
- }, !artifacts || artifacts.runtime.unknownFiles.length > 0));
61
- }
62
- return items.sort((a, b) => b.ratio - a.ratio || a.label.localeCompare(b.label));
63
- }
64
- //#endregion
65
- //#region src/dashboard/analyze/comparison.ts
1
+ // src/dashboard/analyze/comparison.ts
66
2
  function createModuleComparisonKey(source, sourceType) {
67
3
  const origin = sourceType === "node_modules" || sourceType === "workspace" ? "dependency" : sourceType;
68
4
  const queryIndex = source.indexOf("?");
@@ -205,16 +141,14 @@ function createAnalyzeComparison(current, previous) {
205
141
  modules: compareSizeMaps(currentMaps.modules, previousMaps.modules)
206
142
  };
207
143
  }
208
- //#endregion
209
- //#region src/dashboard/analyze/moduleBytes.ts
144
+ // src/dashboard/analyze/moduleBytes.ts
210
145
  /** 取每个原始模块 ID 的最大已知贡献,缺少产物贡献时使用原始体积。 */
211
146
  function createModuleByteMap(result) {
212
147
  const bytes = /* @__PURE__ */ new Map();
213
148
  for (const pkg of result.packages) for (const file of pkg.files) for (const mod of file.modules ?? []) bytes.set(mod.id, Math.max(bytes.get(mod.id) ?? 0, mod.bytes ?? mod.originalBytes ?? 0));
214
149
  return bytes;
215
150
  }
216
- //#endregion
217
- //#region src/dashboard/analyze/duplicates.ts
151
+ // src/dashboard/analyze/duplicates.ts
218
152
  function createDuplicateAdvice(sourceType, hasIndependentPackage, estimatedSavingBytes) {
219
153
  if (hasIndependentPackage) return estimatedSavingBytes > 0 ? "含独立分包,先确认隔离要求,再评估是否抽公共入口。" : "含独立分包,重复可能来自隔离边界。";
220
154
  if (sourceType === "node_modules") return "依赖被多个包带入,检查引用边界或考虑主包公共入口。";
@@ -244,5 +178,4 @@ function createDuplicateModuleInsights(result) {
244
178
  };
245
179
  }).sort((a, b) => b.estimatedSavingBytes - a.estimatedSavingBytes || b.packageCount - a.packageCount || b.bytes - a.bytes || a.source.localeCompare(b.source) || a.id.localeCompare(b.id));
246
180
  }
247
- //#endregion
248
- export { isRuntimeCategory as a, createAnalyzeBudgetCheck as i, createModuleByteMap as n, createAnalyzeComparison as r, createDuplicateModuleInsights as t };
181
+ export { createModuleByteMap as n, createAnalyzeComparison as r, createDuplicateModuleInsights as t };
@@ -0,0 +1,104 @@
1
+ import { createRequire } from "node:module";
2
+ import process from "node:process";
3
+ import path from "pathe";
4
+ import fs from "node:fs";
5
+ import { Buffer } from "node:buffer";
6
+ // src/dashboard/assets.ts
7
+ const ANALYZE_DASHBOARD_PACKAGE_NAME = "@weapp-vite/dashboard";
8
+ const require = createRequire(import.meta.url);
9
+ function parseDashboardManifest(source) {
10
+ const parsed = JSON.parse(source);
11
+ const metadata = parsed && typeof parsed === "object" && "weappViteDashboard" in parsed ? parsed.weappViteDashboard : void 0;
12
+ if (!metadata || typeof metadata !== "object") return;
13
+ return { weappViteDashboard: {
14
+ devConfigFile: "devConfigFile" in metadata && typeof metadata.devConfigFile === "string" ? metadata.devConfigFile : void 0,
15
+ devRoot: "devRoot" in metadata && typeof metadata.devRoot === "string" ? metadata.devRoot : void 0,
16
+ distDir: "distDir" in metadata && typeof metadata.distDir === "string" ? metadata.distDir : void 0
17
+ } };
18
+ }
19
+ function resolveDashboardPackage(cwd) {
20
+ const resolvePaths = cwd && cwd !== process.cwd() ? [cwd, process.cwd()] : cwd ? [cwd] : void 0;
21
+ try {
22
+ const packageJsonPath = require.resolve(`${ANALYZE_DASHBOARD_PACKAGE_NAME}/package.json`, { paths: resolvePaths });
23
+ let manifest;
24
+ try {
25
+ manifest = parseDashboardManifest(fs.readFileSync(packageJsonPath, "utf8"));
26
+ } catch {
27
+ manifest = void 0;
28
+ }
29
+ return {
30
+ root: path.dirname(packageJsonPath),
31
+ manifest,
32
+ packageJsonPath
33
+ };
34
+ } catch {
35
+ return;
36
+ }
37
+ }
38
+ function resolveDashboardDistRoot(packageRoot, manifest) {
39
+ const root = path.resolve(packageRoot, manifest?.weappViteDashboard?.distDir ?? "dist");
40
+ return fs.existsSync(path.join(root, "index.html")) ? { root } : void 0;
41
+ }
42
+ function resolveDashboardDevRoot(packageRoot, manifest) {
43
+ const devRoot = manifest?.weappViteDashboard?.devRoot;
44
+ const devConfigFile = manifest?.weappViteDashboard?.devConfigFile;
45
+ if (!devRoot || !devConfigFile) return;
46
+ const root = path.resolve(packageRoot, devRoot);
47
+ const configFile = path.resolve(root, devConfigFile);
48
+ return fs.existsSync(root) && fs.existsSync(configFile) ? {
49
+ root,
50
+ configFile
51
+ } : void 0;
52
+ }
53
+ /** 同一次解析绑定 Dashboard 资源目录及其传输依赖的安装所有者。 */
54
+ function resolveDashboardInstallation(options) {
55
+ const resolved = resolveDashboardPackage(options.cwd);
56
+ if (!resolved) return;
57
+ const assets = options.watch ? resolveDashboardDevRoot(resolved.root, resolved.manifest) ?? resolveDashboardDistRoot(resolved.root, resolved.manifest) : resolveDashboardDistRoot(resolved.root, resolved.manifest) ?? resolveDashboardDevRoot(resolved.root, resolved.manifest);
58
+ return assets ? {
59
+ ...assets,
60
+ packageJsonPath: resolved.packageJsonPath
61
+ } : void 0;
62
+ }
63
+ /** 定位可选仪表盘包的原生构建 SPA;未安装或尚未构建时返回 undefined。 */
64
+ function resolveDashboardClientAssets(cwd) {
65
+ const resolved = resolveDashboardPackage(cwd);
66
+ return resolved ? resolveDashboardDistRoot(resolved.root, resolved.manifest)?.root : void 0;
67
+ }
68
+ // src/dashboard/artifacts.ts
69
+ const MAX_DASHBOARD_FILE_CONTENT_BYTES = 2097152;
70
+ /** 保留同一次分析的产物内容,不读取或改写开发构建目录。 */
71
+ function createDashboardArtifactSnapshot() {
72
+ const files = /* @__PURE__ */ new Map();
73
+ let retainedBytes = 0;
74
+ return {
75
+ files,
76
+ capture(fileName, source) {
77
+ const key = fileName.replaceAll("\\", "/");
78
+ const previous = files.get(key);
79
+ if (previous?.content !== void 0) retainedBytes -= previous.size;
80
+ const size = typeof source === "string" ? Buffer.byteLength(source, "utf8") : source.byteLength;
81
+ if (size > 2097152) {
82
+ files.set(key, {
83
+ size,
84
+ error: `文件超过 ${MAX_DASHBOARD_FILE_CONTENT_BYTES} 字节,已拒绝读取。`
85
+ });
86
+ return;
87
+ }
88
+ if (retainedBytes + size > 33554432) {
89
+ files.set(key, {
90
+ size,
91
+ error: "分析产物内容超过快照容量上限,已拒绝读取。"
92
+ });
93
+ return;
94
+ }
95
+ const content = typeof source === "string" ? source : Buffer.from(source.buffer, source.byteOffset, source.byteLength).toString("utf8");
96
+ files.set(key, {
97
+ content,
98
+ size
99
+ });
100
+ retainedBytes += size;
101
+ }
102
+ };
103
+ }
104
+ export { resolveDashboardInstallation as a, resolveDashboardClientAssets as i, createDashboardArtifactSnapshot as n, ANALYZE_DASHBOARD_PACKAGE_NAME as r, MAX_DASHBOARD_FILE_CONTENT_BYTES as t };