weapp-vite 7.4.0 → 7.6.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 (126) hide show
  1. package/README.md +59 -3
  2. package/THIRD_PARTY_NOTICES.md +60 -0
  3. package/bin/bootstrap.js +14 -1
  4. package/dist/action-B3YZMA-h.mjs +255 -0
  5. package/dist/action-BELcDNNv.mjs +139 -0
  6. package/dist/action-BOk3vGI7.mjs +1110 -0
  7. package/dist/action-DlC6JYpt.mjs +95 -0
  8. package/dist/action-zEDY7oh_.mjs +247 -0
  9. package/dist/adapters-CcHrsYaj.mjs +1 -0
  10. package/dist/analyze-DN79YOAH.mjs +184 -0
  11. package/dist/artifacts-BOyC9Fy-.mjs +106 -0
  12. package/dist/assets-C5_YYXNk.mjs +637 -0
  13. package/dist/auto-import-components/resolvers.mjs +1 -2
  14. package/dist/auto-import-presets/wevu-router.mjs +1 -2
  15. package/dist/auto-import-presets/wevu.mjs +1 -2
  16. package/dist/auto-routes.mjs +2 -1
  17. package/dist/budget-CTLOHwgI.d.mts +177 -0
  18. package/dist/budget-EOeEycc_.mjs +65 -0
  19. package/dist/builtProject-C29udgXY.mjs +541 -0
  20. package/dist/chunkStrategy-DY_LZIIe.mjs +1448 -0
  21. package/dist/classifier-DBJY__kg.mjs +88 -0
  22. package/dist/cli-acceptance.d.mts +1 -0
  23. package/dist/cli-acceptance.mjs +21 -0
  24. package/dist/cli.mjs +519 -5049
  25. package/dist/compatibility.mjs +1 -2
  26. package/dist/{config-Dbvj5yK7.d.mts → config-Bf6DWhyb.d.mts} +220 -76
  27. package/dist/config.d.mts +3 -3
  28. package/dist/config.mjs +1 -1
  29. package/dist/{constants-WOsG3Eqd.mjs → constants-DEZdcsMn.mjs} +1 -1
  30. package/dist/{createContext-UOEgeYnA.mjs → createCompilerContextInstance-aYwi8wQt.mjs} +36862 -32020
  31. package/dist/createContext-tApLtII-.mjs +15 -0
  32. package/dist/dashboard/analyze.d.mts +48 -0
  33. package/dist/dashboard/analyze.mjs +3 -0
  34. package/dist/dashboard/vite.d.mts +1 -1
  35. package/dist/dashboard.d.mts +3 -2
  36. package/dist/dashboard.mjs +1748 -1
  37. package/dist/dashboardTransport-C_Y6jMp-.mjs +16 -0
  38. package/dist/dashboardViteBridge-DCGR43aM.mjs +302 -0
  39. package/dist/dev-C2fgr_Xd.mjs +67 -0
  40. package/dist/devProvider-D-hTfsEO.mjs +3027 -0
  41. package/dist/docs/README.md +59 -3
  42. package/dist/docs/ai-workflows.md +4 -0
  43. package/dist/docs/doctor.md +38 -0
  44. package/dist/docs/getting-started.md +3 -1
  45. package/dist/docs/index.md +3 -1
  46. package/dist/docs/mcp.md +104 -1
  47. package/dist/docs/testing.md +29 -2
  48. package/dist/docs/troubleshooting.md +16 -0
  49. package/dist/docs/uni-app-component-libraries.md +8 -7
  50. package/dist/docs/upload.md +40 -3
  51. package/dist/docs/vite-plugin.md +171 -0
  52. package/dist/docs/vue-sfc.md +42 -0
  53. package/dist/docs/weapp-config.md +54 -0
  54. package/dist/docs/wevu-authoring.md +10 -0
  55. package/dist/doctor-worker.d.mts +1 -0
  56. package/dist/doctor-worker.mjs +60 -0
  57. package/dist/doctor.d.mts +144 -0
  58. package/dist/doctor.mjs +850 -0
  59. package/dist/engine-C66J0HLz.mjs +54 -0
  60. package/dist/eslint.mjs +1 -2
  61. package/dist/{file-giE9UMZa.mjs → file-CcIOmqhC.mjs} +58 -24
  62. package/dist/file-DtcteQ4G.mjs +1 -0
  63. package/dist/files-BqxFIPRp.mjs +45 -0
  64. package/dist/forwardConsole-B0Reo8Lf.mjs +511 -0
  65. package/dist/getInstance-BAIaU2y9.mjs +1 -0
  66. package/dist/getInstance-Dt9IQDKr.mjs +28 -0
  67. package/dist/history-BIiRCzbq.mjs +784 -0
  68. package/dist/i18n.d.mts +1 -1
  69. package/dist/index-D5rgBzYZ.d.mts +740 -0
  70. package/dist/index.d.mts +12 -10
  71. package/dist/index.mjs +3 -2
  72. package/dist/json.d.mts +1 -1
  73. package/dist/json.mjs +1 -2
  74. package/dist/lib-DjccSI1B.mjs +143 -0
  75. package/dist/lifecycle-C36WSbQS.mjs +413 -0
  76. package/dist/loadConfig-BWIsDXR4.mjs +59 -0
  77. package/dist/loadConfig-D-BpBgsk.mjs +1 -0
  78. package/dist/logBuildAppFinish-ChjwATMv.mjs +57 -0
  79. package/dist/logger-DGn5iEVN.mjs +1 -0
  80. package/dist/mcp-CYgX9HpO.mjs +86 -0
  81. package/dist/{mcp-BG6TliEg.mjs → mcp-Cj8Maqo6.mjs} +16 -7
  82. package/dist/mcp.d.mts +6 -3
  83. package/dist/mcp.mjs +1 -2
  84. package/dist/mcpClient-DVLvFLZv.mjs +287 -0
  85. package/dist/metadata-hwF7QRcS.mjs +59 -0
  86. package/dist/nodeEnv-BmH8UZPR.mjs +7 -0
  87. package/dist/openIde-CroqOgk5.mjs +648 -0
  88. package/dist/options-jqFwfD1G.mjs +34 -0
  89. package/dist/package-Cmakyy3J.mjs +4 -0
  90. package/dist/path-CYYIQGS7.mjs +44 -0
  91. package/dist/{platform-DTWs5QRi.mjs → platform-CnkySBKz.mjs} +1 -1
  92. package/dist/processCleanup-BQn2kTcK.mjs +19 -0
  93. package/dist/protocol-Cg6Jdlvb.mjs +141 -0
  94. package/dist/reader-sh_POQ9-.mjs +93 -0
  95. package/dist/realpathScope-Tf9mz-fh.mjs +23 -0
  96. package/dist/report-hyonPGbZ.mjs +107 -0
  97. package/dist/resolvedId-CiDl7SC1.mjs +60 -0
  98. package/dist/{resolvers-icNxkpcy.mjs → resolvers-Dod-euqX.mjs} +4 -1
  99. package/dist/resolvers.mjs +1 -2
  100. package/dist/runtime-CLUhQsdA.mjs +43 -0
  101. package/dist/{runtime-Ee2HY6gR.d.mts → runtime-DpVf714f.d.mts} +1 -1
  102. package/dist/runtime.d.mts +1 -1
  103. package/dist/runtime.mjs +1 -2
  104. package/dist/schematics-kO26eQRT.mjs +91 -0
  105. package/dist/session-D3zsdzIy.mjs +452 -0
  106. package/dist/test.d.mts +1 -0
  107. package/dist/test.mjs +204 -45
  108. package/dist/{types-CgZn5X6j.d.mts → types-D-kfuyVa.d.mts} +1 -2
  109. package/dist/types-D0FFexRF.d.mts +39 -0
  110. package/dist/types.d.mts +3 -3
  111. package/dist/{upload-D0RcEWrq.mjs → upload-DozK8UdN.mjs} +278 -15
  112. package/dist/upload-worker.mjs +136 -3
  113. package/dist/utils-Dy51PYAC.mjs +1034 -0
  114. package/dist/vite.d.mts +9 -0
  115. package/dist/vite.mjs +309 -0
  116. package/dist/volar.d.mts +2 -2
  117. package/dist/web-apis.mjs +1 -2
  118. package/dist/wxs-BT8btflA.mjs +112 -0
  119. package/dist/wxs-Z4VQDeJ_.mjs +1 -0
  120. package/package.json +80 -48
  121. package/dist/adapters-BwnMMIZR.mjs +0 -2
  122. package/dist/dashboard-BzaVesmQ.mjs +0 -558
  123. package/dist/file-D19nbDoN.mjs +0 -2
  124. package/dist/getInstance-CYF1vl5l.mjs +0 -2
  125. package/dist/index-DbqVupg0.d.mts +0 -246
  126. package/dist/logger-mt4mSTqV.mjs +0 -2
@@ -1,12 +1,225 @@
1
- import { m as resolveMiniPlatform } from "./platform-DTWs5QRi.mjs";
2
- import { r as logger_default } from "./logger-mt4mSTqV.mjs";
1
+ import { m as resolveMiniPlatform } from "./platform-CnkySBKz.mjs";
2
+ import { r as logger_default } from "./logger-DGn5iEVN.mjs";
3
3
  import { createRequire } from "node:module";
4
+ import process from "node:process";
4
5
  import { pathToFileURL } from "node:url";
5
6
  import path from "node:path";
6
- import process from "node:process";
7
7
  import { mkdir, readFile, stat } from "node:fs/promises";
8
8
  import { getPackageInfo } from "local-pkg";
9
- import { execFile } from "node:child_process";
9
+ import { Buffer } from "node:buffer";
10
+ import { performance } from "node:perf_hooks";
11
+ import { execFile, execFileSync } from "node:child_process";
12
+ //#region src/cli/upload/processTreeDiagnostics.ts
13
+ const diagnostics = /* @__PURE__ */ new WeakMap();
14
+ const MARKER_PREFIX = "[weapp-vite:upload-process-tree:v1]";
15
+ const MARKER_RE = /^\[weapp-vite:upload-process-tree:v1\] (script-enter|parent-query-start|parent-query-end|children-query-start|children-query-end) (\d{1,9}) (\d{1,16})$/;
16
+ const ERROR_CODES = /* @__PURE__ */ new Set([
17
+ "ETIMEDOUT",
18
+ "ENOENT",
19
+ "EACCES",
20
+ "EPERM",
21
+ "ENOBUFS",
22
+ "EIO",
23
+ "UNKNOWN"
24
+ ]);
25
+ const SIGNALS = /* @__PURE__ */ new Set([
26
+ "SIGTERM",
27
+ "SIGKILL",
28
+ "SIGINT",
29
+ "SIGABRT"
30
+ ]);
31
+ /** 标记只写入诊断管道,不进入供清理使用的 PID 输出。 */
32
+ const WINDOWS_PROCESS_TREE_DIAGNOSTIC_SETUP = `\$wvTreeClock = [Diagnostics.Stopwatch]::StartNew(); function Write-WvTreeStage([string]\$stage) { [Console]::Error.WriteLine('${MARKER_PREFIX} ' + $stage + ' ' + $wvTreeClock.ElapsedMilliseconds + ' ' + [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()) }; `;
33
+ function processTreeStageCommand(stage) {
34
+ return `Write-WvTreeStage '${stage}'; `;
35
+ }
36
+ function readMarkers(stderr, elapsedMs) {
37
+ const text = Buffer.isBuffer(stderr) ? stderr.subarray(0, 8192).toString("utf8") : typeof stderr === "string" ? Buffer.from(stderr.slice(0, 8192)).subarray(0, 8192).toString("utf8") : "";
38
+ const markers = [];
39
+ for (const line of text.split(/\r?\n/)) {
40
+ const match = MARKER_RE.exec(line);
41
+ if (!match) continue;
42
+ const elapsed = Number(match[2]);
43
+ const utc = Number(match[3]);
44
+ if (!Number.isSafeInteger(elapsed) || elapsed > elapsedMs || !Number.isSafeInteger(utc) || markers.length >= 8) return [];
45
+ markers.push({
46
+ stage: match[1],
47
+ elapsedMs: elapsed,
48
+ utcMs: utc
49
+ });
50
+ }
51
+ const expected = markers[1]?.stage === "parent-query-start" ? [
52
+ "script-enter",
53
+ "parent-query-start",
54
+ "parent-query-end",
55
+ "children-query-start",
56
+ "children-query-end"
57
+ ] : [
58
+ "script-enter",
59
+ "children-query-start",
60
+ "children-query-end"
61
+ ];
62
+ return markers.every((marker, index) => marker.stage === expected[index] && marker.elapsedMs >= (markers[index - 1]?.elapsedMs ?? 0)) ? markers : [];
63
+ }
64
+ function describeQuery(error, elapsedMs, utcStart, utcEnd) {
65
+ const failure = error;
66
+ const markers = readMarkers(failure.stderr, elapsedMs);
67
+ const first = markers[0];
68
+ const last = markers.at(-1);
69
+ const result = {
70
+ elapsedMs,
71
+ stage: last?.stage ?? "before-script-entry-or-unobserved"
72
+ };
73
+ if (typeof failure.code === "string" && ERROR_CODES.has(failure.code)) result.code = failure.code;
74
+ if (typeof failure.signal === "string" && SIGNALS.has(failure.signal)) result.signal = failure.signal;
75
+ if (typeof failure.status === "number" && Number.isSafeInteger(failure.status)) result.status = failure.status;
76
+ const startupMs = first && first.utcMs - utcStart;
77
+ if (first && startupMs !== void 0 && startupMs >= 0 && startupMs <= elapsedMs && Math.abs(utcEnd - utcStart - elapsedMs) <= 5 && markers.every((marker) => Math.abs(marker.utcMs - first.utcMs - (marker.elapsedMs - first.elapsedMs)) <= 5)) {
78
+ result.startupMs = startupMs;
79
+ if (last?.stage === "parent-query-start" || last?.stage === "children-query-start") result.activeQueryMs = Math.max(0, elapsedMs - startupMs - (last.elapsedMs - first.elapsedMs));
80
+ }
81
+ for (const [name, key] of [["parent", "parentQueryMs"], ["children", "childrenQueryMs"]]) {
82
+ const start = markers.find((marker) => marker.stage === `${name}-query-start`);
83
+ const end = markers.find((marker) => marker.stage === `${name}-query-end`);
84
+ if (start && end) result[key] = end.elapsedMs - start.elapsedMs;
85
+ }
86
+ return result;
87
+ }
88
+ /** 只附带标量诊断,保持清理失败的原始异常身份与控制流。 */
89
+ function observeWindowsProcessTreeQuery(run) {
90
+ const startedAt = performance.now();
91
+ const utcStart = Date.now();
92
+ try {
93
+ return run();
94
+ } catch (error) {
95
+ if (error && typeof error === "object") {
96
+ const elapsedMs = Math.max(0, Math.round(performance.now() - startedAt));
97
+ diagnostics.set(error, {
98
+ elapsedMs,
99
+ stage: "before-script-entry-or-unobserved"
100
+ });
101
+ try {
102
+ diagnostics.set(error, describeQuery(error, elapsedMs, utcStart, Date.now()));
103
+ } catch {}
104
+ }
105
+ throw error;
106
+ }
107
+ }
108
+ /** Windows 查询只展示白名单诊断,不能回显异常中携带的命令或原始 stderr。 */
109
+ function describeUploadProcessTreeError(error) {
110
+ const diagnostic = error && typeof error === "object" ? diagnostics.get(error) : void 0;
111
+ return diagnostic ? `PowerShell 进程归属查询失败 ${JSON.stringify(diagnostic)}` : String(error);
112
+ }
113
+ //#endregion
114
+ //#region src/cli/upload/processTree.ts
115
+ function childPids(pid, lifetime) {
116
+ if (process.platform === "win32") {
117
+ const since = lifetime ? `[DateTimeOffset]::FromUnixTimeMilliseconds(${lifetime.start}).UtcDateTime` : `(Get-CimInstance Win32_Process -Filter 'ProcessId = ${pid}').CreationDate.ToUniversalTime()`;
118
+ const until = lifetime ? `[DateTimeOffset]::FromUnixTimeMilliseconds(${lifetime.end}).UtcDateTime` : "[DateTime]::UtcNow";
119
+ return observeWindowsProcessTreeQuery(() => execFileSync("powershell.exe", [
120
+ "-NoProfile",
121
+ "-NonInteractive",
122
+ "-Command",
123
+ `$ErrorActionPreference = 'Stop'; ${WINDOWS_PROCESS_TREE_DIAGNOSTIC_SETUP}${processTreeStageCommand("script-enter")}${lifetime ? "" : processTreeStageCommand("parent-query-start")}$since = ${since}; ${lifetime ? "" : processTreeStageCommand("parent-query-end")}$until = ${until}; ${processTreeStageCommand("children-query-start")}Get-CimInstance Win32_Process -Filter 'ParentProcessId = ${pid}' | Where-Object { $_.CreationDate.ToUniversalTime() -ge $since -and $_.CreationDate.ToUniversalTime() -le $until } | Select-Object -ExpandProperty ProcessId; ${processTreeStageCommand("children-query-end")}`
124
+ ], {
125
+ encoding: "utf8",
126
+ windowsHide: true,
127
+ timeout: 3e4,
128
+ stdio: [
129
+ "ignore",
130
+ "pipe",
131
+ "pipe"
132
+ ]
133
+ })).split(/\s+/).map(Number).filter((value) => Number.isSafeInteger(value) && value > 0);
134
+ }
135
+ const output = execFileSync("ps", [
136
+ "-A",
137
+ "-o",
138
+ "pid=,ppid="
139
+ ], {
140
+ encoding: "utf8",
141
+ timeout: 5e3,
142
+ stdio: [
143
+ "ignore",
144
+ "pipe",
145
+ "ignore"
146
+ ]
147
+ });
148
+ const children = /* @__PURE__ */ new Map();
149
+ for (const line of output.trim().split(/\r?\n/)) {
150
+ const [child, parent] = line.trim().split(/\s+/).map(Number);
151
+ if (child && parent) {
152
+ const siblings = children.get(parent) ?? [];
153
+ siblings.push(child);
154
+ children.set(parent, siblings);
155
+ }
156
+ }
157
+ const descendants = [];
158
+ const visit = (parent) => {
159
+ for (const child of children.get(parent) ?? []) {
160
+ visit(child);
161
+ descendants.push(child);
162
+ }
163
+ };
164
+ visit(pid);
165
+ return descendants;
166
+ }
167
+ function killPid(pid) {
168
+ try {
169
+ process.kill(pid, "SIGKILL");
170
+ } catch (error) {
171
+ if (error.code !== "ESRCH") throw error;
172
+ }
173
+ }
174
+ /** POSIX 使用独立进程组;已退出的根进程不再授权向其正 PID 发信号。 */
175
+ function terminateUploadProcess(pid, options) {
176
+ if (process.platform === "win32") {
177
+ if (options?.exited) {
178
+ if (!options.lifetime) throw new Error("缺少已退出进程的生命周期,无法确认子进程归属。");
179
+ for (const child of childPids(pid, options.lifetime)) terminateUploadProcess(child);
180
+ return;
181
+ }
182
+ try {
183
+ execFileSync("taskkill", [
184
+ "/PID",
185
+ String(pid),
186
+ "/T",
187
+ "/F"
188
+ ], {
189
+ windowsHide: true,
190
+ timeout: 5e3,
191
+ stdio: "ignore"
192
+ });
193
+ } catch (error) {
194
+ try {
195
+ process.kill(pid, 0);
196
+ } catch (probeError) {
197
+ if (probeError.code === "ESRCH") {
198
+ if (!options?.lifetime) throw new Error("根进程已消失,无法确认子进程归属。");
199
+ for (const child of childPids(pid, options.lifetime)) terminateUploadProcess(child);
200
+ return;
201
+ }
202
+ }
203
+ throw error;
204
+ }
205
+ return;
206
+ }
207
+ if (options?.processGroup) {
208
+ try {
209
+ process.kill(-pid, "SIGKILL");
210
+ } catch (error) {
211
+ if (error.code !== "ESRCH") throw error;
212
+ if (!options.exited) killPid(pid);
213
+ }
214
+ return;
215
+ }
216
+ if (!options?.exited) killPid(pid);
217
+ }
218
+ /** 只终止当前 worker 所属的本地子进程,不推断远端任务状态。 */
219
+ function terminateUploadDescendants(pid) {
220
+ for (const child of childPids(pid)) terminateUploadProcess(child);
221
+ }
222
+ //#endregion
10
223
  //#region src/cli/upload/tools.ts
11
224
  function requireUploadEnv(context, name) {
12
225
  const value = context.env[name]?.trim();
@@ -56,7 +269,14 @@ async function runUploadCli(context, packageName, binName, args, secrets, captur
56
269
  resolve(stdout);
57
270
  });
58
271
  function cancel() {
59
- child.kill("SIGKILL");
272
+ if (child.pid) try {
273
+ if (process.platform !== "win32") terminateUploadDescendants(child.pid);
274
+ terminateUploadProcess(child.pid);
275
+ } catch {
276
+ child.kill("SIGKILL");
277
+ process.stderr.write("无法确认上传 CLI 子进程已全部终止。\n");
278
+ process.exitCode = 1;
279
+ }
60
280
  }
61
281
  process.once("exit", cancel);
62
282
  child.once("close", () => process.off("exit", cancel));
@@ -97,7 +317,7 @@ async function prepareAlipayUpload(context, action = "upload") {
97
317
  if (!alipay || typeof alipay !== "object" || !("authentication" in alipay) || !alipay.authentication) throw new Error("支付宝身份密钥文件缺少 alipay.authentication。请从开放平台重新获取身份密钥。");
98
318
  return {
99
319
  secrets,
100
- async run() {
320
+ async run(onProgress) {
101
321
  const sdk = await loadUploadPackage("minidev", context.cwd);
102
322
  if (action === "preview") {
103
323
  const result = await sdk.minidev.preview({
@@ -118,7 +338,20 @@ async function prepareAlipayUpload(context, action = "upload") {
118
338
  version: context.version,
119
339
  versionDescription: context.desc,
120
340
  experience: false
121
- });
341
+ }, onProgress ? {
342
+ onLog: (message) => onProgress({
343
+ type: "log",
344
+ message: redactUploadSecrets(message, secrets)
345
+ }),
346
+ onTaskCreated: (taskId) => onProgress({
347
+ type: "task-created",
348
+ message: redactUploadSecrets(taskId, secrets)
349
+ }),
350
+ onVersionCreated: (version) => onProgress({
351
+ type: "version-created",
352
+ message: redactUploadSecrets(version, secrets)
353
+ })
354
+ } : void 0);
122
355
  }
123
356
  };
124
357
  }
@@ -264,7 +497,13 @@ async function prepareSwanUpload(context, action = "upload") {
264
497
  if (typeof previewUrl !== "string" || !previewUrl.trim()) throw new Error("百度预览未返回有效的预览链接。");
265
498
  return { previewUrl: previewUrl.trim() };
266
499
  }
267
- return runUploadCli(context, "swan-toolkit", "swan", [
500
+ const output = await runUploadCli({
501
+ ...context,
502
+ env: {
503
+ ...context.env,
504
+ IS_NODE_JS: "true"
505
+ }
506
+ }, "swan-toolkit", "swan", [
268
507
  "upload",
269
508
  "--project-path",
270
509
  context.projectPath,
@@ -277,7 +516,14 @@ async function prepareSwanUpload(context, action = "upload") {
277
516
  "--desc",
278
517
  context.desc,
279
518
  "--json"
280
- ], secrets);
519
+ ], secrets, true);
520
+ try {
521
+ const marker = /^NODE_JS_ENV_RESULT:/m.exec(output);
522
+ if (!marker) throw new Error("缺少官方 JSON 结果标记。");
523
+ return JSON.parse(output.slice(marker.index + marker[0].length));
524
+ } catch {
525
+ throw new Error("百度上传未返回有效的 JSON 结果。");
526
+ }
281
527
  }
282
528
  };
283
529
  }
@@ -301,9 +547,10 @@ async function prepareWechatUpload(context, action = "upload") {
301
547
  throw new Error("无法读取 WEAPP_CI_PRIVATE_KEY_PATH 指定的私钥文件;相对路径以项目根目录为基准。");
302
548
  }
303
549
  if (!privateKey.trim()) throw new Error("WEAPP_CI_PRIVATE_KEY_PATH 指定的私钥文件不能为空。");
550
+ const secrets = [privateKey, privateKey.trim()];
304
551
  return {
305
- secrets: [privateKey, privateKey.trim()],
306
- async run() {
552
+ secrets,
553
+ async run(onProgress) {
307
554
  const ci = await loadUploadPackage("miniprogram-ci", context.cwd);
308
555
  const project = new ci.Project({
309
556
  appid,
@@ -333,7 +580,13 @@ async function prepareWechatUpload(context, action = "upload") {
333
580
  version: context.version,
334
581
  desc: context.desc,
335
582
  robot,
336
- setting: { useProjectConfig: true }
583
+ setting: { useProjectConfig: true },
584
+ onProgressUpdate: onProgress ? (task) => {
585
+ onProgress({
586
+ type: "progress",
587
+ message: redactUploadSecrets(typeof task === "string" ? task : `${task.status}: ${task.message}`, secrets)
588
+ });
589
+ } : void 0
337
590
  });
338
591
  }
339
592
  };
@@ -348,7 +601,7 @@ async function prepareXhsUpload(context, action = "upload") {
348
601
  if (JSON.parse(await readFile(path.join(context.projectPath, "project.config.json"), "utf8"))?.appid !== appid) throw new Error("小红书 project.config.json 的 appid 必须与 XHS_APP_ID 或项目配置的 AppID 一致,禁止向其他小程序上传。");
349
602
  return {
350
603
  secrets: [token],
351
- async run() {
604
+ async run(onProgress) {
352
605
  const { CI } = await loadUploadPackage("xhs-mp-cli/dist/ci.js", context.cwd);
353
606
  const sdk = new CI();
354
607
  sdk.core.login = async () => {
@@ -370,7 +623,17 @@ async function prepareXhsUpload(context, action = "upload") {
370
623
  project: { projectPath: context.projectPath },
371
624
  version: context.version,
372
625
  desc: context.desc,
373
- verbose: false
626
+ verbose: false,
627
+ progressCallback: onProgress ? (progress) => {
628
+ if (progress === -1) onProgress({
629
+ type: "log",
630
+ message: "小红书 SDK 报告上传失败。"
631
+ });
632
+ else if (Number.isFinite(progress) && progress >= 0 && progress <= 100) onProgress({
633
+ type: "progress",
634
+ percent: progress
635
+ });
636
+ } : void 0
374
637
  });
375
638
  }
376
639
  };
@@ -400,4 +663,4 @@ function prepareUpload(platform, context, action = "upload") {
400
663
  return providers[platform](context, action);
401
664
  }
402
665
  //#endregion
403
- export { resolveUploadPlatforms as n, redactUploadSecrets as r, prepareUpload as t };
666
+ export { terminateUploadProcess as a, terminateUploadDescendants as i, resolveUploadPlatforms as n, describeUploadProcessTreeError as o, redactUploadSecrets as r, prepareUpload as t };
@@ -1,20 +1,153 @@
1
- import { t as prepareUpload } from "./upload-D0RcEWrq.mjs";
1
+ import { i as terminateUploadDescendants, r as redactUploadSecrets, t as prepareUpload } from "./upload-DozK8UdN.mjs";
2
2
  import process from "node:process";
3
+ //#region src/cli/upload/uploadResult.ts
4
+ function record(value) {
5
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
6
+ }
7
+ function text(value, secrets) {
8
+ if (typeof value !== "string" || !value.trim() || value.includes("\0")) return;
9
+ return redactUploadSecrets(value.trim(), secrets);
10
+ }
11
+ function bytes(value) {
12
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
13
+ }
14
+ function link(value, secrets, scheme = false) {
15
+ if (typeof value !== "string" || !value.trim() || /[\s\p{Cc}]/u.test(value.trim())) return;
16
+ try {
17
+ const url = new URL(value);
18
+ if (!(scheme ? [
19
+ "http:",
20
+ "https:",
21
+ "baiduboxapp:",
22
+ "swan:"
23
+ ] : ["http:", "https:"]).includes(url.protocol) || url.username || url.password) return;
24
+ return text(value, secrets);
25
+ } catch {
26
+ return;
27
+ }
28
+ }
29
+ function base64(value, secrets) {
30
+ if (typeof value !== "string") return;
31
+ const source = value.trim();
32
+ const content = source.replace(/^data:image\/(?:png|jpe?g|gif|webp);base64,/i, "");
33
+ if (!content || !/^(?:[a-z\d+/]{4})*(?:[a-z\d+/]{2}==|[a-z\d+/]{3}=)?$/i.test(content)) return;
34
+ return text(source, secrets);
35
+ }
36
+ /** 按官方上传结果选择字段;可选信息无效时丢弃,不把已完成上传改判失败。 */
37
+ function normalizeUploadResult(platform, value, secrets) {
38
+ const input = record(value);
39
+ const result = {};
40
+ if (!input) return result;
41
+ if (platform === "weapp") {
42
+ if (Array.isArray(input.subPackageInfo)) result.subPackages = input.subPackageInfo.flatMap((value) => {
43
+ const item = record(value);
44
+ const name = text(item?.name, secrets);
45
+ const size = bytes(item?.size);
46
+ return name !== void 0 && size !== void 0 ? [{
47
+ name,
48
+ size
49
+ }] : [];
50
+ });
51
+ if (Array.isArray(input.pluginInfo)) result.plugins = input.pluginInfo.flatMap((value) => {
52
+ const item = record(value);
53
+ const appid = text(item?.pluginProviderAppid, secrets);
54
+ const version = text(item?.version, secrets);
55
+ const size = bytes(item?.size);
56
+ return appid !== void 0 && version !== void 0 && size !== void 0 ? [{
57
+ appid,
58
+ version,
59
+ size
60
+ }] : [];
61
+ });
62
+ } else if (platform === "alipay") {
63
+ const sdkVersion = text(input.version, secrets);
64
+ const qrCodeUrl = link(input.experienceQrCodeUrl, secrets);
65
+ if (sdkVersion !== void 0) result.sdkVersion = sdkVersion;
66
+ if (qrCodeUrl !== void 0) result.qrCodeUrl = qrCodeUrl;
67
+ } else if (platform === "tt") {
68
+ const previewUrl = link(input.shortUrl, secrets);
69
+ const qrCodeFile = text(input.qrcodeFilePath, secrets);
70
+ if (previewUrl !== void 0) result.previewUrl = previewUrl;
71
+ if (qrCodeFile !== void 0) result.qrCodeFile = qrCodeFile;
72
+ } else if (platform === "jd") {
73
+ const qrCodeUrl = link(input.imgUrl, secrets);
74
+ const qrCodeBase64 = base64(input.base64Data, secrets);
75
+ if (qrCodeUrl !== void 0) result.qrCodeUrl = qrCodeUrl;
76
+ if (qrCodeBase64 !== void 0) result.qrCodeBase64 = qrCodeBase64;
77
+ } else if (platform === "swan") {
78
+ const previewUrl = link(input.schemeUrlOpti, secrets, true) ?? link(input.schemeUrl, secrets, true);
79
+ const fileSize = bytes(input.fileSize);
80
+ if (previewUrl !== void 0) result.previewUrl = previewUrl;
81
+ if (fileSize !== void 0) result.fileSize = fileSize;
82
+ if (Array.isArray(input.warningList)) result.warnings = input.warningList.flatMap((value) => {
83
+ const warning = text(value, secrets);
84
+ return warning === void 0 ? [] : [warning];
85
+ });
86
+ }
87
+ return result;
88
+ }
89
+ //#endregion
3
90
  //#region src/cli/upload/worker.ts
4
91
  process.once("disconnect", () => process.exit(1));
5
92
  process.once("SIGINT", () => process.exit(1));
6
93
  process.once("SIGTERM", () => process.exit(1));
94
+ process.once("exit", () => {
95
+ try {
96
+ terminateUploadDescendants(process.pid);
97
+ } catch {
98
+ process.stderr.write("无法确认本地 SDK 子进程已全部终止。\n");
99
+ process.exitCode = 1;
100
+ }
101
+ });
7
102
  try {
8
103
  let input = "";
9
104
  for await (const chunk of process.stdin) input += String(chunk);
10
105
  const { platform, context, action } = JSON.parse(input);
11
106
  if (action !== "upload" && action !== "preview") throw new Error("不支持的上传或预览操作。");
12
- const result = await (await prepareUpload(platform, context, action)).run();
107
+ const upload = await prepareUpload(platform, context, action);
108
+ await new Promise((resolve, reject) => {
109
+ const onMessage = (message) => {
110
+ if (message && typeof message === "object" && "type" in message && message.type === "run" && "action" in message && message.action === action) {
111
+ process.off("message", onMessage);
112
+ resolve();
113
+ }
114
+ };
115
+ if (!process.send) {
116
+ reject(/* @__PURE__ */ new Error("上传 worker 缺少父进程 IPC 通道。"));
117
+ return;
118
+ }
119
+ process.on("message", onMessage);
120
+ process.send({
121
+ type: "started",
122
+ action
123
+ }, (error) => {
124
+ if (error) {
125
+ process.off("message", onMessage);
126
+ reject(error);
127
+ }
128
+ });
129
+ });
130
+ const onProgress = (event) => {
131
+ const safeEvent = {
132
+ type: event.type,
133
+ ...typeof event.message === "string" ? { message: redactUploadSecrets(event.message, upload.secrets) } : {},
134
+ ...typeof event.percent === "number" && Number.isFinite(event.percent) ? { percent: event.percent } : {}
135
+ };
136
+ process.send?.({
137
+ type: "progress",
138
+ action,
139
+ event: safeEvent
140
+ }, (error) => {
141
+ if (error) process.exit(1);
142
+ });
143
+ };
144
+ const rawResult = await upload.run(onProgress);
145
+ const result = action === "upload" ? normalizeUploadResult(platform, rawResult, upload.secrets) : rawResult;
13
146
  const finish = () => process.stderr.write("", () => process.stdout.write("", () => process.exit(0)));
14
147
  if (process.send) process.send({
15
148
  type: "completed",
16
149
  action,
17
- result: action === "preview" ? result : void 0
150
+ result
18
151
  }, (error) => {
19
152
  if (error) process.exit(1);
20
153
  finish();