@neuxnet/neux-cli 0.2.3

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 (73) hide show
  1. package/README.md +438 -0
  2. package/README.zh-CN.md +554 -0
  3. package/assets/container/assets/index.css +1 -0
  4. package/assets/container/assets/index.js +137 -0
  5. package/assets/container/assets/pageFrame.css +1 -0
  6. package/assets/container/assets/pageFrame.js +56 -0
  7. package/assets/container/assets/service.js +6 -0
  8. package/assets/container/assets/vconsole.js +931 -0
  9. package/assets/container/favicon.ico +0 -0
  10. package/assets/container/images/icon-arrow.png +0 -0
  11. package/assets/container/images/mini-action-white.png +0 -0
  12. package/assets/container/images/mini-action.png +0 -0
  13. package/assets/container/images/mini-arrow-left-white.png +0 -0
  14. package/assets/container/images/mini-arrow-left.jpg +0 -0
  15. package/assets/container/images/mini-arrow-left.png +0 -0
  16. package/assets/container/images/mini-close-white.png +0 -0
  17. package/assets/container/images/mini-close.png +0 -0
  18. package/assets/container/images/more.png +0 -0
  19. package/assets/container/images/search.jpg +0 -0
  20. package/assets/container/index.html +1 -0
  21. package/assets/container/pageFrame.html +1 -0
  22. package/assets/init/tabbar/home-active.png +0 -0
  23. package/assets/init/tabbar/home.png +0 -0
  24. package/assets/init/tabbar/list-active.png +0 -0
  25. package/assets/init/tabbar/list.png +0 -0
  26. package/assets/init/types/neux-api.d.ts +1402 -0
  27. package/package.json +68 -0
  28. package/scripts/generate-init-types.js +210 -0
  29. package/scripts/sync-compiler.js +22 -0
  30. package/scripts/sync-web-container.js +34 -0
  31. package/src/bin/cli.js +646 -0
  32. package/src/core/brand.js +11 -0
  33. package/src/core/compiler.js +305 -0
  34. package/src/core/defaults.js +12 -0
  35. package/src/core/dev.js +15 -0
  36. package/src/core/errors.js +17 -0
  37. package/src/core/fs.js +66 -0
  38. package/src/core/i18n.js +37 -0
  39. package/src/core/init.js +866 -0
  40. package/src/core/lifecycle.js +32 -0
  41. package/src/core/manifest.js +72 -0
  42. package/src/core/pack.js +156 -0
  43. package/src/core/package-info.js +27 -0
  44. package/src/core/preview-server.js +123 -0
  45. package/src/core/project.js +101 -0
  46. package/src/core/prompts.js +71 -0
  47. package/src/core/proxy-security.js +141 -0
  48. package/src/core/proxy.js +156 -0
  49. package/src/core/qr.js +41 -0
  50. package/src/core/terminal-qr.js +72 -0
  51. package/src/core/update.js +278 -0
  52. package/src/core/watch.js +113 -0
  53. package/src/core/web.js +649 -0
  54. package/src/core/zip.js +120 -0
  55. package/src/index.js +20 -0
  56. package/src/providers/service-client.js +149 -0
  57. package/src/providers/service-config.js +264 -0
  58. package/src/providers/service.js +146 -0
  59. package/src/providers/upload.js +112 -0
  60. package/vendor/dimina-compiler/bin/index.cjs +265 -0
  61. package/vendor/dimina-compiler/bin/index.js +263 -0
  62. package/vendor/dimina-compiler/compatibility-B-DoZtUX.cjs +395 -0
  63. package/vendor/dimina-compiler/compatibility-Cl3-DO6V.js +366 -0
  64. package/vendor/dimina-compiler/core/logic-compiler.cjs +378 -0
  65. package/vendor/dimina-compiler/core/logic-compiler.js +374 -0
  66. package/vendor/dimina-compiler/core/style-compiler.cjs +392 -0
  67. package/vendor/dimina-compiler/core/style-compiler.js +377 -0
  68. package/vendor/dimina-compiler/core/view-compiler.cjs +1601 -0
  69. package/vendor/dimina-compiler/core/view-compiler.js +1582 -0
  70. package/vendor/dimina-compiler/index.cjs +762 -0
  71. package/vendor/dimina-compiler/index.js +751 -0
  72. package/vendor/dimina-compiler/sourcemap-BgtIgqkC.cjs +1377 -0
  73. package/vendor/dimina-compiler/sourcemap-CKjhV9h7.js +1135 -0
@@ -0,0 +1,762 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_sourcemap = require("./sourcemap-BgtIgqkC.cjs");
6
+ const require_core_style_compiler = require("./core/style-compiler.cjs");
7
+ const require_core_view_compiler = require("./core/view-compiler.cjs");
8
+ let node_fs = require("node:fs");
9
+ node_fs = require_sourcemap.__toESM(node_fs, 1);
10
+ let node_path = require("node:path");
11
+ node_path = require_sourcemap.__toESM(node_path, 1);
12
+ let node_process = require("node:process");
13
+ node_process = require_sourcemap.__toESM(node_process, 1);
14
+ let node_url = require("node:url");
15
+ let node_worker_threads = require("node:worker_threads");
16
+ let listr2 = require("listr2");
17
+ let node_os = require("node:os");
18
+ node_os = require_sourcemap.__toESM(node_os, 1);
19
+ //#region src/common/compile-progress.js
20
+ var DEFAULT_TERMINAL_COLUMNS = 80;
21
+ var MIN_PROGRESS_WIDTH = 8;
22
+ var MAX_PROGRESS_WIDTH = 28;
23
+ var RENDERER_CHROME_WIDTH = 14;
24
+ var PROGRESS_BRACKETS_WIDTH = 2;
25
+ /**
26
+ * Format worker progress without assuming a fixed terminal width.
27
+ * The completed count remains the source of truth. Whole cells avoid the
28
+ * visible gap that partial block glyphs leave before the unfilled section.
29
+ */
30
+ function formatCompileProgress(completed, total, options = {}) {
31
+ const unicode = options.unicode ?? (0, listr2.isUnicodeSupported)();
32
+ const columns = normalizePositiveInteger(options.columns) || node_process.default.stdout.columns || DEFAULT_TERMINAL_COLUMNS;
33
+ const safeTotal = normalizePositiveInteger(total);
34
+ const safeCompleted = Math.min(normalizePositiveInteger(completed), safeTotal);
35
+ const ratio = safeTotal === 0 ? 0 : safeCompleted / safeTotal;
36
+ const percentage = Math.round(ratio * 100);
37
+ const separator = unicode ? "·" : "|";
38
+ const metadata = `${String(safeCompleted).padStart(String(safeTotal).length)}/${safeTotal} ${separator} ${String(percentage).padStart(3)}%`;
39
+ const availableWidth = columns - metadata.length - RENDERER_CHROME_WIDTH - PROGRESS_BRACKETS_WIDTH;
40
+ if (availableWidth < MIN_PROGRESS_WIDTH) return metadata;
41
+ const width = Math.min(availableWidth, MAX_PROGRESS_WIDTH);
42
+ return `[${unicode ? createUnicodeBar(ratio, width) : createAsciiBar(ratio, width)}] ${metadata}`;
43
+ }
44
+ function createUnicodeBar(ratio, width) {
45
+ const completeWidth = Math.round(ratio * width);
46
+ const emptyWidth = width - completeWidth;
47
+ return `${"█".repeat(completeWidth)}${"░".repeat(emptyWidth)}`;
48
+ }
49
+ function createAsciiBar(ratio, width) {
50
+ const completeWidth = Math.floor(ratio * width);
51
+ const showHead = ratio > 0 && ratio < 1;
52
+ const bodyWidth = Math.max(0, completeWidth - (showHead ? 1 : 0));
53
+ const emptyWidth = width - bodyWidth - (showHead ? 1 : 0);
54
+ return `${"=".repeat(bodyWidth)}${showHead ? ">" : ""}${"-".repeat(emptyWidth)}`;
55
+ }
56
+ function normalizePositiveInteger(value) {
57
+ return Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
58
+ }
59
+ //#endregion
60
+ //#region src/common/publish.js
61
+ function createDist(seedPath) {
62
+ const distPath = require_sourcemap.getTargetPath();
63
+ if (node_fs.default.existsSync(distPath)) node_fs.default.rmSync(distPath, {
64
+ recursive: true,
65
+ force: true
66
+ });
67
+ node_fs.default.mkdirSync(distPath, { recursive: true });
68
+ if (seedPath && node_fs.default.existsSync(seedPath)) node_fs.default.cpSync(seedPath, distPath, { recursive: true });
69
+ }
70
+ /**
71
+ * 发布到指定目录
72
+ * @param {string} dist 目标路径
73
+ * @param {boolean} useAppIdDir 是否在路径中包含appId
74
+ */
75
+ function publishToDist(dist, useAppIdDir = true) {
76
+ const distPath = require_sourcemap.getTargetPath();
77
+ const appId = require_sourcemap.getAppId();
78
+ const absolutePath = useAppIdDir ? `${node_path.default.resolve(node_process.default.cwd(), dist)}${node_path.default.sep}${appId}` : `${node_path.default.resolve(node_process.default.cwd(), dist)}`;
79
+ if (node_fs.default.existsSync(absolutePath)) node_fs.default.rmSync(absolutePath, {
80
+ recursive: true,
81
+ force: true
82
+ });
83
+ node_fs.default.mkdirSync(absolutePath, { recursive: true });
84
+ function copyDir(src, dest) {
85
+ node_fs.default.mkdirSync(dest, { recursive: true });
86
+ const entries = node_fs.default.readdirSync(src, { withFileTypes: true });
87
+ for (const entry of entries) {
88
+ const srcPath = node_path.default.join(src, entry.name);
89
+ const destPath = node_path.default.join(dest, entry.name);
90
+ if (entry.isDirectory()) copyDir(srcPath, destPath);
91
+ else node_fs.default.copyFileSync(srcPath, destPath);
92
+ }
93
+ }
94
+ copyDir(distPath, absolutePath);
95
+ }
96
+ //#endregion
97
+ //#region src/common/worker-pool.js
98
+ function getCGroupCPUCount() {
99
+ try {
100
+ const quotaPath = "/sys/fs/cgroup/cpu/cpu.cfs_quota_us";
101
+ const periodPath = "/sys/fs/cgroup/cpu/cpu.cfs_period_us";
102
+ if (node_fs.default.existsSync(quotaPath) && node_fs.default.existsSync(periodPath)) {
103
+ const quota = Number.parseInt(node_fs.default.readFileSync(quotaPath, "utf8"));
104
+ const period = Number.parseInt(node_fs.default.readFileSync(periodPath, "utf8"));
105
+ if (quota > 0) return Math.max(1, Math.floor(quota / period));
106
+ }
107
+ } catch (e) {
108
+ console.warn("Failed to read CPU limits from cgroup:", e.message);
109
+ }
110
+ return node_os.default.cpus().length;
111
+ }
112
+ function getCGroupMemoryLimit() {
113
+ try {
114
+ const memLimitPath = "/sys/fs/cgroup/memory/memory.limit_in_bytes";
115
+ if (node_fs.default.existsSync(memLimitPath)) {
116
+ const memLimit = Number.parseInt(node_fs.default.readFileSync(memLimitPath, "utf8"));
117
+ if (memLimit < Number.Infinity && memLimit > 0) return memLimit;
118
+ }
119
+ } catch (e) {
120
+ console.warn("Failed to read memory limits from cgroup:", e.message);
121
+ }
122
+ return node_os.default.totalmem();
123
+ }
124
+ var MAX_WORKERS = Math.max(1, Math.min(4, Math.floor(getCGroupCPUCount() / 4)));
125
+ var WorkerPool = class {
126
+ constructor(maxWorkers = MAX_WORKERS) {
127
+ this.maxWorkers = maxWorkers;
128
+ this.activeWorkers = 0;
129
+ this.queue = [];
130
+ this.memoryLimit = Math.floor(getCGroupMemoryLimit() * .6 / maxWorkers);
131
+ }
132
+ async runWorker(workerCreator) {
133
+ if (this.activeWorkers >= this.maxWorkers) await new Promise((resolve) => this.queue.push(resolve));
134
+ this.activeWorkers++;
135
+ try {
136
+ return await workerCreator();
137
+ } finally {
138
+ this.activeWorkers--;
139
+ if (this.queue.length > 0) this.queue.shift()();
140
+ }
141
+ }
142
+ getWorkerOptions() {
143
+ const memoryMb = Math.floor(this.memoryLimit / (1024 * 1024));
144
+ return { resourceLimits: {
145
+ maxOldGenerationSizeMb: Math.max(256, memoryMb),
146
+ maxYoungGenerationSizeMb: Math.max(64, Math.floor(memoryMb / 4)),
147
+ codeRangeSizeMb: 64
148
+ } };
149
+ }
150
+ };
151
+ var workerPool = new WorkerPool();
152
+ //#endregion
153
+ //#region src/common/npm-builder.js
154
+ /**
155
+ * npm 构建工具
156
+ * 用于处理小程序 npm 包的构建和管理
157
+ */
158
+ var NpmBuilder = class {
159
+ constructor(workPath, targetPath, dependencyGraph = null) {
160
+ this.workPath = workPath;
161
+ this.targetPath = targetPath;
162
+ this.dependencyGraph = dependencyGraph;
163
+ this.builtPackages = /* @__PURE__ */ new Set();
164
+ this.packageDependencies = /* @__PURE__ */ new Map();
165
+ }
166
+ /**
167
+ * 构建 npm 包
168
+ * 扫描 miniprogram_npm 目录并构建相关包
169
+ */
170
+ async buildNpmPackages() {
171
+ const miniprogramNpmPaths = this.findMiniprogramNpmDirs();
172
+ for (const npmPath of miniprogramNpmPaths) await this.buildNpmDir(npmPath);
173
+ }
174
+ /**
175
+ * 查找所有 miniprogram_npm 目录
176
+ * @returns {string[]} miniprogram_npm 目录路径数组
177
+ */
178
+ findMiniprogramNpmDirs() {
179
+ const npmDirs = [];
180
+ const scanDir = (dir, relativePath = "") => {
181
+ if (!node_fs.default.existsSync(dir)) return;
182
+ const items = node_fs.default.readdirSync(dir, { withFileTypes: true });
183
+ for (const item of items) if (item.isDirectory()) {
184
+ const itemPath = node_path.default.join(dir, item.name);
185
+ const itemRelativePath = relativePath ? `${relativePath}/${item.name}` : item.name;
186
+ if (item.name === "miniprogram_npm") npmDirs.push(itemRelativePath);
187
+ else scanDir(itemPath, itemRelativePath);
188
+ }
189
+ };
190
+ scanDir(this.workPath);
191
+ return npmDirs;
192
+ }
193
+ /**
194
+ * 构建指定的 miniprogram_npm 目录
195
+ * @param {string} npmDirPath miniprogram_npm 目录路径
196
+ */
197
+ async buildNpmDir(npmDirPath) {
198
+ const fullNpmPath = node_path.default.join(this.workPath, npmDirPath);
199
+ if (!node_fs.default.existsSync(fullNpmPath)) return;
200
+ const packages = node_fs.default.readdirSync(fullNpmPath, { withFileTypes: true }).filter((item) => item.isDirectory()).map((item) => item.name);
201
+ for (const packageName of packages) await this.buildPackage(packageName, npmDirPath);
202
+ }
203
+ /**
204
+ * 构建单个 npm 包
205
+ * @param {string} packageName 包名
206
+ * @param {string} npmDirPath miniprogram_npm 目录路径
207
+ */
208
+ async buildPackage(packageName, npmDirPath) {
209
+ const packageKey = `${npmDirPath}/${packageName}`;
210
+ if (this.builtPackages.has(packageKey)) return;
211
+ const packagePath = node_path.default.join(this.workPath, npmDirPath, packageName);
212
+ const targetPackagePath = node_path.default.join(this.targetPath, npmDirPath, packageName);
213
+ if (!node_fs.default.existsSync(node_path.default.dirname(targetPackagePath))) node_fs.default.mkdirSync(node_path.default.dirname(targetPackagePath), { recursive: true });
214
+ await this.copyPackageFiles(packagePath, targetPackagePath);
215
+ await this.processDependencies(packageName, packagePath, npmDirPath);
216
+ this.builtPackages.add(packageKey);
217
+ }
218
+ /**
219
+ * 复制包文件
220
+ * @param {string} sourcePath 源路径
221
+ * @param {string} targetPath 目标路径
222
+ */
223
+ async copyPackageFiles(sourcePath, targetPath) {
224
+ if (!node_fs.default.existsSync(sourcePath)) return;
225
+ if (!node_fs.default.existsSync(targetPath)) node_fs.default.mkdirSync(targetPath, { recursive: true });
226
+ const items = node_fs.default.readdirSync(sourcePath, { withFileTypes: true });
227
+ for (const item of items) {
228
+ const sourceItemPath = node_path.default.join(sourcePath, item.name);
229
+ const targetItemPath = node_path.default.join(targetPath, item.name);
230
+ if (item.isDirectory()) await this.copyPackageFiles(sourceItemPath, targetItemPath);
231
+ else if (this.isMiniprogramFile(item.name)) {
232
+ this.dependencyGraph?.addFile("app", sourceItemPath, "config");
233
+ node_fs.default.copyFileSync(sourceItemPath, targetItemPath);
234
+ }
235
+ }
236
+ }
237
+ /**
238
+ * 检查是否为小程序相关文件
239
+ * @param {string} filename 文件名
240
+ * @returns {boolean} 是否为小程序文件
241
+ */
242
+ isMiniprogramFile(filename) {
243
+ const miniprogramExts = [
244
+ ".js",
245
+ ".json",
246
+ ".ts",
247
+ ...require_sourcemap.getTemplateExts(),
248
+ ...require_sourcemap.getStyleExts(),
249
+ ...require_sourcemap.getViewScriptExts()
250
+ ];
251
+ const ext = node_path.default.extname(filename).toLowerCase();
252
+ return miniprogramExts.includes(ext) || filename === "package.json" || filename === "README.md" || filename.startsWith(".");
253
+ }
254
+ /**
255
+ * 处理包依赖
256
+ * @param {string} packageName 包名
257
+ * @param {string} packagePath 包路径
258
+ * @param {string} npmDirPath npm 目录路径
259
+ */
260
+ async processDependencies(packageName, packagePath, npmDirPath) {
261
+ const packageJsonPath = node_path.default.join(packagePath, "package.json");
262
+ if (!node_fs.default.existsSync(packageJsonPath)) return;
263
+ try {
264
+ const packageJson = JSON.parse(node_fs.default.readFileSync(packageJsonPath, "utf-8"));
265
+ const dependencies = {
266
+ ...packageJson.dependencies,
267
+ ...packageJson.peerDependencies
268
+ };
269
+ if (dependencies && Object.keys(dependencies).length > 0) {
270
+ this.packageDependencies.set(packageName, dependencies);
271
+ for (const depName of Object.keys(dependencies)) await this.buildPackage(depName, npmDirPath);
272
+ }
273
+ } catch (e) {
274
+ console.warn(`[npm-builder] 解析 package.json 失败: ${packageJsonPath}`, e.message);
275
+ }
276
+ }
277
+ /**
278
+ * 验证 npm 包的完整性
279
+ * @param {string} packageName 包名
280
+ * @param {string} packagePath 包路径
281
+ * @returns {boolean} 是否有效
282
+ */
283
+ validatePackage(packageName, packagePath) {
284
+ for (const file of ["package.json"]) if (!node_fs.default.existsSync(node_path.default.join(packagePath, file))) {
285
+ console.warn(`[npm-builder] 包 ${packageName} 缺少必要文件: ${file}`);
286
+ return false;
287
+ }
288
+ try {
289
+ const packageJsonPath = node_path.default.join(packagePath, "package.json");
290
+ const packageJson = JSON.parse(node_fs.default.readFileSync(packageJsonPath, "utf-8"));
291
+ if (!packageJson.name || !packageJson.version) {
292
+ console.warn(`[npm-builder] 包 ${packageName} 的 package.json 格式不正确`);
293
+ return false;
294
+ }
295
+ } catch (e) {
296
+ console.warn(`[npm-builder] 包 ${packageName} 的 package.json 解析失败:`, e.message);
297
+ return false;
298
+ }
299
+ return true;
300
+ }
301
+ /**
302
+ * 获取已构建的包列表
303
+ * @returns {string[]} 已构建的包列表
304
+ */
305
+ getBuiltPackages() {
306
+ return Array.from(this.builtPackages);
307
+ }
308
+ /**
309
+ * 获取包依赖关系
310
+ * @returns {Map} 包依赖关系映射
311
+ */
312
+ getPackageDependencies() {
313
+ return this.packageDependencies;
314
+ }
315
+ /**
316
+ * 清理构建缓存
317
+ */
318
+ clearCache() {
319
+ this.builtPackages.clear();
320
+ this.packageDependencies.clear();
321
+ }
322
+ };
323
+ //#endregion
324
+ //#region src/core/config-compiler.js
325
+ /**
326
+ * 处理 tabBar.list 中的 iconPath / selectedIconPath。
327
+ * 视为相对小程序根目录的资源,复用 collectAssets 拷贝到 main/static/,
328
+ * 并把 list 中的路径改写成产物 URL,避免容器侧再做特殊解析。
329
+ *
330
+ * 注意:会在原 app 配置上原地修改,不影响后续输出(compileConfig 是
331
+ * 整个流水线最后才走到的环节,不会被再次读取)。
332
+ */
333
+ function processTabBarIcons(app) {
334
+ const list = app?.tabBar?.list;
335
+ if (!Array.isArray(list) || list.length === 0) return;
336
+ const workPath = require_sourcemap.getWorkPath();
337
+ const targetPath = require_sourcemap.getTargetPath();
338
+ const appId = require_sourcemap.getAppId();
339
+ for (const item of list) {
340
+ if (item.iconPath) item.iconPath = require_sourcemap.collectAssets(workPath, "", item.iconPath, targetPath, appId);
341
+ if (item.selectedIconPath) item.selectedIconPath = require_sourcemap.collectAssets(workPath, "", item.selectedIconPath, targetPath, appId);
342
+ }
343
+ }
344
+ /**
345
+ *
346
+ * 编译项目配置文件 app-config.json
347
+ */
348
+ function compileConfig() {
349
+ const app = require_sourcemap.getAppConfigInfo();
350
+ processTabBarIcons(app);
351
+ const compileResInfo = {
352
+ app,
353
+ modules: require_sourcemap.getPageConfigInfo(),
354
+ projectName: require_sourcemap.getAppName()
355
+ };
356
+ const apiNamespaces = require_sourcemap.getProjectConfig().apiNamespaces;
357
+ if (Array.isArray(apiNamespaces) && apiNamespaces.length > 0) compileResInfo.apiNamespaces = apiNamespaces;
358
+ const json = JSON.stringify(compileResInfo, null, 4);
359
+ const mainDir = `${require_sourcemap.getTargetPath()}/main`;
360
+ if (!node_fs.default.existsSync(mainDir)) node_fs.default.mkdirSync(mainDir, { recursive: true });
361
+ node_fs.default.writeFileSync(`${mainDir}/app-config.json`, json);
362
+ }
363
+ //#endregion
364
+ //#region src/index.js
365
+ var previousCompatibilityWarnings = /* @__PURE__ */ new Map();
366
+ var COMPILE_STAGE_ORDER = [
367
+ "view",
368
+ "logic",
369
+ "style"
370
+ ];
371
+ var BUILD_LABELS = {
372
+ en: {
373
+ initialize: "Prepare project build environment",
374
+ collectConfig: "Collect project configuration",
375
+ prepareOutput: "Prepare output directory",
376
+ compileConfig: "Compile project configuration",
377
+ buildNpm: "Build npm packages",
378
+ compile: "Compile project",
379
+ view: "Compile view files",
380
+ logic: "Compile logic files",
381
+ style: "Compile style files",
382
+ writeOutput: "Write build output"
383
+ },
384
+ "zh-CN": {
385
+ initialize: "初始化项目",
386
+ collectConfig: "收集配置信息",
387
+ prepareOutput: "准备产物目录",
388
+ compileConfig: "编译配置信息",
389
+ buildNpm: "构建 npm 包",
390
+ compile: "编译项目",
391
+ view: "编译视图",
392
+ logic: "编译逻辑",
393
+ style: "编译样式",
394
+ writeOutput: "写入编译产物"
395
+ }
396
+ };
397
+ function resolveBuildLabels(options = {}) {
398
+ return BUILD_LABELS[String(options.lang || node_process.default.env.NEUX_CLI_LANG || "en").toLowerCase().startsWith("zh") ? "zh-CN" : "en"];
399
+ }
400
+ function getStyleOnlyChangedPathPattern() {
401
+ return createExtensionPattern([
402
+ ...require_sourcemap.getStyleExts(),
403
+ ".acss",
404
+ ".css"
405
+ ]);
406
+ }
407
+ function getViewOnlyChangedPathPattern() {
408
+ return createExtensionPattern([...require_sourcemap.getTemplateExts(), ".axml"]);
409
+ }
410
+ /**
411
+ * 构建命令入口
412
+ * @param {string} targetPath 编译产物目标路径
413
+ * @param {string} workPath 编译工作目录
414
+ * @param {boolean} useAppIdDir 产物根目录是否包含 appId
415
+ * @param {object} [options] 构建选项
416
+ * @param {boolean} [options.sourcemap] 是否生成 sourcemap
417
+ * @param {{ template?: string[], style?: string[], viewScript?: string[] }} [options.fileTypes]
418
+ * 自定义文件类型,在内置 wx/dd 类型基础上追加;template 为模板扩展名,style 为样式扩展名,
419
+ * viewScript 为视图脚本扩展名和内联标签名
420
+ * @param {string[]} [options.affectedEntries] 仅重编这些页面的视图和样式;逻辑仍按包重建
421
+ * @param {string} [options.seedPath] 增量构建前用于保留未受影响产物的已发布目录
422
+ * @param {object} [options.dependencyGraph] 上一次构建的依赖图快照
423
+ * @param {Array<'view'|'logic'|'style'>} [options.stages] 仅运行指定编译阶段
424
+ */
425
+ async function build(targetPath, workPath, useAppIdDir = true, options = {}) {
426
+ const { sourcemap = false, fileTypes, affectedEntries, seedPath, dependencyGraph, stages } = options;
427
+ const labels = resolveBuildLabels(options);
428
+ if (stages !== void 0 && (!Array.isArray(stages) || stages.some((stage) => !COMPILE_STAGE_ORDER.includes(stage)))) throw new TypeError(`Invalid compiler stages: ${JSON.stringify(stages)}`);
429
+ const enabledStages = new Set(stages === void 0 ? COMPILE_STAGE_ORDER : COMPILE_STAGE_ORDER.filter((stage) => stages.includes(stage)));
430
+ require_sourcemap.resetAssetCache();
431
+ const context = await new listr2.Listr([
432
+ {
433
+ title: labels.initialize,
434
+ task: (_, task) => task.newListr([
435
+ {
436
+ title: labels.collectConfig,
437
+ task: (ctx) => {
438
+ ctx.storeInfo = require_sourcemap.storeInfo(workPath, {
439
+ fileTypes,
440
+ dependencyGraph
441
+ });
442
+ ctx.dependencyGraph = new require_sourcemap.DependencyGraph(ctx.storeInfo.dependencyGraph);
443
+ }
444
+ },
445
+ {
446
+ title: labels.prepareOutput,
447
+ task: () => {
448
+ createDist(seedPath);
449
+ }
450
+ },
451
+ {
452
+ title: labels.compileConfig,
453
+ task: () => {
454
+ compileConfig();
455
+ }
456
+ },
457
+ {
458
+ title: labels.buildNpm,
459
+ task: async (ctx) => {
460
+ await new NpmBuilder(require_sourcemap.getWorkPath(), require_sourcemap.getTargetPath(), ctx.dependencyGraph).buildNpmPackages();
461
+ }
462
+ }
463
+ ], { concurrent: false })
464
+ },
465
+ {
466
+ title: `${labels.compile} · ${node_path.default.basename(node_path.default.resolve(workPath))}`,
467
+ task: (ctx, task) => {
468
+ const allPages = require_sourcemap.getPages();
469
+ ctx.allPages = allPages;
470
+ ctx.pages = filterPagesByEntries(allPages, affectedEntries);
471
+ ctx.compatibilityWarnings = /* @__PURE__ */ new Set();
472
+ const compileTasks = [];
473
+ if (enabledStages.has("view")) compileTasks.push({
474
+ title: labels.view,
475
+ rendererOptions: {
476
+ outputBar: true,
477
+ persistentOutput: false
478
+ },
479
+ task: async (ctx, task) => {
480
+ return runCompileInWorker("view", ctx, task, { sourcemap });
481
+ }
482
+ });
483
+ if (enabledStages.has("logic")) compileTasks.push({
484
+ title: labels.logic,
485
+ rendererOptions: {
486
+ outputBar: true,
487
+ persistentOutput: false
488
+ },
489
+ task: async (ctx, task) => {
490
+ return runCompileInWorker("logic", ctx, task, {
491
+ sourcemap,
492
+ pages: ctx.allPages
493
+ });
494
+ }
495
+ });
496
+ if (enabledStages.has("style")) compileTasks.push({
497
+ title: labels.style,
498
+ rendererOptions: {
499
+ outputBar: true,
500
+ persistentOutput: false
501
+ },
502
+ task: async (ctx, task) => {
503
+ const stylePages = {
504
+ ...ctx.pages,
505
+ mainPages: [{
506
+ path: "app",
507
+ id: require_sourcemap.getAppStyleScopeId()
508
+ }, ...ctx.pages.mainPages]
509
+ };
510
+ return runCompileInWorker("style", ctx, task, {
511
+ sourcemap,
512
+ pages: stylePages
513
+ });
514
+ }
515
+ });
516
+ if (compileTasks.length > 0) return task.newListr(compileTasks, { concurrent: true });
517
+ }
518
+ },
519
+ {
520
+ title: labels.writeOutput,
521
+ task: () => {
522
+ publishToDist(targetPath, useAppIdDir);
523
+ }
524
+ }
525
+ ], {
526
+ concurrent: false,
527
+ rendererOptions: {
528
+ collapseSubtasks: true,
529
+ formatOutput: "truncate",
530
+ timer: listr2.PRESET_TIMER
531
+ },
532
+ fallbackRendererOptions: { timer: listr2.PRESET_TIMER }
533
+ }).run();
534
+ printCompatibilityWarnings(workPath, context.compatibilityWarnings);
535
+ return {
536
+ appId: require_sourcemap.getAppId(),
537
+ name: require_sourcemap.getAppName(),
538
+ path: require_sourcemap.getAppConfigInfo().entryPagePath || context.allPages.mainPages[0].path,
539
+ dependencyGraph: context.dependencyGraph.toJSON()
540
+ };
541
+ }
542
+ function filterPagesByEntries(pages, affectedEntries) {
543
+ if (!Array.isArray(affectedEntries)) return pages;
544
+ const selected = new Set(affectedEntries);
545
+ return {
546
+ mainPages: pages.mainPages.filter((page) => selected.has(page.path)),
547
+ subPages: Object.fromEntries(Object.entries(pages.subPages).map(([root, subPackage]) => [root, {
548
+ ...subPackage,
549
+ info: subPackage.info.filter((page) => selected.has(page.path))
550
+ }]).filter(([, subPackage]) => subPackage.info.length > 0))
551
+ };
552
+ }
553
+ async function buildStyleOnly(targetPath, workPath, useAppIdDir = true, options = {}) {
554
+ require_sourcemap.storeInfo(workPath, { fileTypes: options.fileTypes });
555
+ const pages = require_sourcemap.getPages();
556
+ const affectedPages = getAffectedPages(pages, options.changedPath, getStyleOnlyChangedPathPattern());
557
+ const progress = { completedTasks: 0 };
558
+ await require_core_style_compiler.compileSS(affectedPages.mainPages, null, progress);
559
+ for (const [root, subPages] of Object.entries(affectedPages.subPages)) await require_core_style_compiler.compileSS(subPages.info, root, progress);
560
+ publishCssToDist(targetPath, useAppIdDir);
561
+ return {
562
+ appId: require_sourcemap.getAppId(),
563
+ name: require_sourcemap.getAppName(),
564
+ path: require_sourcemap.getAppConfigInfo().entryPagePath || pages.mainPages[0]?.path,
565
+ styleOnly: true,
566
+ compiledTasks: progress.completedTasks
567
+ };
568
+ }
569
+ async function buildViewOnly(targetPath, workPath, useAppIdDir = true, options = {}) {
570
+ require_core_view_compiler.resetViewCompilerCache();
571
+ require_sourcemap.storeInfo(workPath, { fileTypes: options.fileTypes });
572
+ const pages = require_sourcemap.getPages();
573
+ const affectedPages = getAffectedPages(pages, options.changedPath, getViewOnlyChangedPathPattern());
574
+ const progress = { completedTasks: 0 };
575
+ await require_core_view_compiler.compileML(affectedPages.mainPages, null, progress);
576
+ for (const [root, subPages] of Object.entries(affectedPages.subPages)) await require_core_view_compiler.compileML(subPages.info, root, progress);
577
+ publishFilesToDist(targetPath, useAppIdDir, ".js");
578
+ return {
579
+ appId: require_sourcemap.getAppId(),
580
+ name: require_sourcemap.getAppName(),
581
+ path: require_sourcemap.getAppConfigInfo().entryPagePath || pages.mainPages[0].path,
582
+ viewOnly: true,
583
+ compiledTasks: progress.completedTasks,
584
+ updatedPages: collectUpdatedPages(affectedPages)
585
+ };
586
+ }
587
+ async function buildLogicOnly(targetPath, workPath, useAppIdDir = true, options = {}) {
588
+ const currentStoreInfo = require_sourcemap.storeInfo(workPath, { fileTypes: options.fileTypes });
589
+ const pages = require_sourcemap.getPages();
590
+ await runCompileInWorker("logic", {
591
+ pages,
592
+ storeInfo: currentStoreInfo
593
+ }, {}, { sourcemap: options.sourcemap });
594
+ publishFilesToDist(targetPath, useAppIdDir, ".js");
595
+ return {
596
+ appId: require_sourcemap.getAppId(),
597
+ name: require_sourcemap.getAppName(),
598
+ path: require_sourcemap.getAppConfigInfo().entryPagePath || pages.mainPages[0].path,
599
+ logicOnly: true,
600
+ compiledTasks: pages.mainPages.length + Object.values(pages.subPages).reduce((sum, item) => sum + item.info.length, 0),
601
+ updatedPages: collectUpdatedPages(pages)
602
+ };
603
+ }
604
+ function collectUpdatedPages(pages) {
605
+ return [...pages.mainPages.map((page) => ({
606
+ pagePath: page.path,
607
+ root: "main"
608
+ })), ...Object.entries(pages.subPages).flatMap(([root, subPackage]) => subPackage.info.map((page) => ({
609
+ pagePath: page.path,
610
+ root
611
+ })))];
612
+ }
613
+ function getAffectedPages(pages, changedPath, extensionPattern) {
614
+ const appStylePage = {
615
+ path: "app",
616
+ id: ""
617
+ };
618
+ if (!changedPath) return {
619
+ mainPages: extensionPattern.test("app.wxss") ? [appStylePage, ...pages.mainPages] : pages.mainPages,
620
+ subPages: pages.subPages
621
+ };
622
+ const modulePath = normalizeChangedModulePath(changedPath, extensionPattern);
623
+ if (!modulePath) return {
624
+ mainPages: extensionPattern.test("app.wxss") ? [appStylePage, ...pages.mainPages] : pages.mainPages,
625
+ subPages: pages.subPages
626
+ };
627
+ if (modulePath === "app") return {
628
+ mainPages: [appStylePage],
629
+ subPages: {}
630
+ };
631
+ const mainPages = pages.mainPages.filter((page) => isStyleModuleAffected(page, modulePath));
632
+ const subPages = {};
633
+ for (const [root, subPackage] of Object.entries(pages.subPages)) {
634
+ const info = subPackage.info.filter((page) => isStyleModuleAffected(page, modulePath));
635
+ if (info.length) subPages[root] = {
636
+ ...subPackage,
637
+ info
638
+ };
639
+ }
640
+ if (!mainPages.length && !Object.keys(subPages).length) return {
641
+ mainPages: extensionPattern.test("app.wxss") ? [appStylePage, ...pages.mainPages] : pages.mainPages,
642
+ subPages: pages.subPages
643
+ };
644
+ return {
645
+ mainPages,
646
+ subPages
647
+ };
648
+ }
649
+ function normalizeChangedModulePath(changedPath, extensionPattern) {
650
+ const relativePath = node_path.default.relative(require_sourcemap.getWorkPath(), changedPath);
651
+ if (!relativePath || relativePath.startsWith("..") || node_path.default.isAbsolute(relativePath)) return null;
652
+ return relativePath.replace(/\\/g, "/").replace(extensionPattern, "");
653
+ }
654
+ function isStyleModuleAffected(page, modulePath, visited = /* @__PURE__ */ new Set()) {
655
+ if (isSameStyleModulePath(page.path, modulePath)) return true;
656
+ if (!page.usingComponents || visited.has(page.path)) return false;
657
+ visited.add(page.path);
658
+ for (const componentPath of Object.values(page.usingComponents)) {
659
+ if (isSameStyleModulePath(componentPath, modulePath)) return true;
660
+ const component = require_sourcemap.getComponent(componentPath);
661
+ if (component && isStyleModuleAffected(component, modulePath, visited)) return true;
662
+ }
663
+ return false;
664
+ }
665
+ function isSameStyleModulePath(left, right) {
666
+ return String(left || "").replace(/^\/+/, "") === String(right || "").replace(/^\/+/, "");
667
+ }
668
+ function createExtensionPattern(extensions) {
669
+ const normalizedExts = [...new Set(extensions)].map((ext) => String(ext).trim().toLowerCase()).filter(Boolean).map((ext) => ext.startsWith(".") ? ext.slice(1) : ext).map((ext) => ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
670
+ return new RegExp(`\\.(?:${normalizedExts.join("|")})$`, "i");
671
+ }
672
+ function publishCssToDist(dist, useAppIdDir = true) {
673
+ publishFilesToDist(dist, useAppIdDir, ".css");
674
+ }
675
+ function publishFilesToDist(dist, useAppIdDir = true, extension) {
676
+ const sourceRoot = require_sourcemap.getTargetPath();
677
+ const targetRoot = useAppIdDir ? node_path.default.join(node_path.default.resolve(node_process.default.cwd(), dist), require_sourcemap.getAppId()) : node_path.default.resolve(node_process.default.cwd(), dist);
678
+ function copyFiles(src, dest) {
679
+ if (!node_fs.default.existsSync(src)) return;
680
+ node_fs.default.mkdirSync(dest, { recursive: true });
681
+ for (const entry of node_fs.default.readdirSync(src, { withFileTypes: true })) {
682
+ const srcPath = node_path.default.join(src, entry.name);
683
+ const destPath = node_path.default.join(dest, entry.name);
684
+ if (entry.isDirectory()) copyFiles(srcPath, destPath);
685
+ else if (entry.isFile() && entry.name.endsWith(extension)) node_fs.default.copyFileSync(srcPath, destPath);
686
+ }
687
+ }
688
+ copyFiles(sourceRoot, targetRoot);
689
+ }
690
+ function runCompileInWorker(script, ctx, task, options = {}) {
691
+ return workerPool.runWorker(() => new Promise((resolve, reject) => {
692
+ const worker = new node_worker_threads.Worker(node_path.default.join(node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href)), `core/${script}-compiler.js`), workerPool.getWorkerOptions());
693
+ const pages = options.pages || ctx.pages;
694
+ const totalTasks = Object.keys(pages.mainPages).length + Object.values(pages.subPages).reduce((sum, item) => sum + item.info.length, 0);
695
+ let isResolved = false;
696
+ let workerError = null;
697
+ const handleError = (error) => {
698
+ if (isResolved) return;
699
+ isResolved = true;
700
+ worker.terminate();
701
+ reject(error);
702
+ };
703
+ worker.postMessage({
704
+ pages,
705
+ storeInfo: ctx.storeInfo,
706
+ sourcemap: !!options.sourcemap
707
+ });
708
+ worker.on("message", (message) => {
709
+ try {
710
+ for (const warning of message.compatibilityWarnings || []) ctx.compatibilityWarnings.add(warning);
711
+ if (node_process.default.stdout.isTTY && message.completedTasks !== void 0) task.output = formatCompileProgress(message.completedTasks, totalTasks);
712
+ if (message.success) {
713
+ if (isResolved) return;
714
+ isResolved = true;
715
+ if (node_process.default.stdout.isTTY && totalTasks > 0) task.output = formatCompileProgress(totalTasks, totalTasks);
716
+ ctx.dependencyGraph.merge(message.dependencyGraph);
717
+ worker.terminate();
718
+ resolve();
719
+ } else if (message.error) {
720
+ const error = new Error(message.error.message || message.error);
721
+ if (message.error.name) error.name = message.error.name;
722
+ if (message.error.stack) error.stack = message.error.stack;
723
+ if (message.error.file) error.file = message.error.file;
724
+ if (message.error.line != null) error.line = message.error.line;
725
+ if (message.error.column != null) error.column = message.error.column;
726
+ if (message.error.stage) error.stage = message.error.stage;
727
+ handleError(error);
728
+ }
729
+ } catch (err) {
730
+ handleError(/* @__PURE__ */ new Error(`Error processing worker message: ${err.message}\n${err.stack}`));
731
+ }
732
+ });
733
+ worker.on("error", (err) => {
734
+ workerError = err;
735
+ handleError(err);
736
+ });
737
+ worker.on("exit", (code) => {
738
+ if (code !== 0 && !isResolved) {
739
+ const error = workerError || /* @__PURE__ */ new Error(code === 1 ? "Worker terminated due to reaching memory limit: JS heap out of memory" : `Worker stopped with exit code ${code}`);
740
+ handleError(error);
741
+ }
742
+ });
743
+ }));
744
+ }
745
+ function printCompatibilityWarnings(workPath, warnings = /* @__PURE__ */ new Set()) {
746
+ const projectPath = node_path.default.resolve(workPath);
747
+ const hasPreviousResult = previousCompatibilityWarnings.has(projectPath);
748
+ const previousWarnings = previousCompatibilityWarnings.get(projectPath) || /* @__PURE__ */ new Set();
749
+ const currentWarnings = new Set(warnings);
750
+ const newWarnings = [...currentWarnings].filter((warning) => !previousWarnings.has(warning));
751
+ previousCompatibilityWarnings.set(projectPath, currentWarnings);
752
+ if (newWarnings.length === 0) return;
753
+ const qualifier = hasPreviousResult ? " new" : "";
754
+ const suffix = newWarnings.length === 1 ? "" : "s";
755
+ console.warn(`\n[compat] ${newWarnings.length}${qualifier} compatibility warning${suffix}`);
756
+ for (const warning of newWarnings) console.warn(` - ${warning.replace(/^\[compat\]\s*/, "")}`);
757
+ }
758
+ //#endregion
759
+ exports.buildLogicOnly = buildLogicOnly;
760
+ exports.buildStyleOnly = buildStyleOnly;
761
+ exports.buildViewOnly = buildViewOnly;
762
+ exports.default = build;