@infly/libs 2.0.26 → 2.0.37

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 (39) hide show
  1. package/bin/cli.js +29 -21
  2. package/build/build-dist/index.js +258 -61
  3. package/build/webpack5/remove-legacy-assets-plugin.js +84 -0
  4. package/build/webpack5/webpack.base.js +228 -20
  5. package/build/webpack5/webpack.base.test.js +59 -0
  6. package/index.js +10 -0
  7. package/module/Permission.js +121 -55
  8. package/module/REST.js +136 -26
  9. package/module/Router.js +15 -0
  10. package/module/Uts.js +380 -331
  11. package/module/cjs/deep-merge.cjs +38 -0
  12. package/module/cjs/page-config.cjs +119 -0
  13. package/module/cjs/request-url-rules.cjs +55 -0
  14. package/package.json +11 -10
  15. package/script/build/command.js +48 -0
  16. package/script/build/env.js +28 -0
  17. package/script/build/git.js +252 -0
  18. package/script/build/preview.js +75 -0
  19. package/script/build/webhook.js +118 -0
  20. package/script/git-automation/check-packages.js +11 -8
  21. package/script/git-automation/git-utils.js +67 -0
  22. package/script/git-automation/index.js +378 -106
  23. package/script/index.js +8 -8
  24. package/script/pts/cloud-scenes.mjs +65 -0
  25. package/script/pts/cloud.js +151 -0
  26. package/script/pts/generate-cloud-params.mjs +210 -0
  27. package/script/pts/generate-cloud-params.test.mjs +67 -0
  28. package/script/webhook/webhook.js +75 -4
  29. package/store/modules/user.js +111 -9
  30. package/tools/auto-export.js +56 -0
  31. package/tools/file-export.js +32 -9
  32. package/tools/file-process.js +3 -0
  33. package/tools/project-preview.js +110 -97
  34. package/dataInit/commonTypeMap.js +0 -31
  35. package/dataInit/marketingActivitiesMap.js +0 -214
  36. package/dataInit/orderMap.js +0 -13
  37. package/dataInit/personalMap.js +0 -19
  38. package/dataInit/settlementMap.js +0 -17
  39. package/types/unused.index.d.ts +0 -71
package/bin/cli.js CHANGED
@@ -1,30 +1,38 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { init: buildInit, scriptInit: buildScriptInit, beforeBuild } = require("../build/build-dist");
4
- const { init: previewInit, scriptInit: previewScriptInit } = require("../tools/project-preview");
3
+ function loadBuildDist() {
4
+ return require("../build/build-dist");
5
+ }
6
+
7
+ function loadPreview() {
8
+ return require("../tools/project-preview");
9
+ }
5
10
 
6
11
  const command = process.argv[2];
7
12
  const commandMap = {
8
- afterBuild: buildInit,
9
- initZip: buildInit,
10
- preview: previewInit,
11
- beforeBuild: beforeBuild,
13
+ afterBuild: () => loadBuildDist().init(),
14
+ initZip: () => loadBuildDist().init(),
15
+ preview: () => loadPreview().init(),
16
+ "--preview": () => loadPreview().init(),
17
+ beforeBuild: () => loadBuildDist().beforeBuild(),
12
18
  scriptOverride: () => {
13
- previewScriptInit();
14
- buildScriptInit();
19
+ const preview = loadPreview();
20
+ const buildDist = loadBuildDist();
21
+
22
+ preview.scriptInit();
23
+ buildDist.scriptInit();
15
24
  }
16
25
  };
17
26
 
18
- // 执行命令
19
- if (command && commandMap[command]) {
20
- commandMap[command]();
21
- } else {
22
- console.error(`未知命令: ${command || "未提供命令"}`);
23
- console.log(
24
- "可用命令: " +
25
- Object.keys(commandMap)
26
- .filter((cmd) => typeof commandMap[cmd] === "function")
27
- .join(", ")
28
- );
29
- process.exit(1); // 使用非零退出码表示错误
30
- }
27
+ (async () => {
28
+ if (command && commandMap[command]) {
29
+ await commandMap[command]();
30
+ } else {
31
+ console.error(`未知命令: ${command || "未提供命令"}`);
32
+ console.log(`可用命令: ${Object.keys(commandMap).join(", ")}`);
33
+ process.exit(1);
34
+ }
35
+ })().catch((error) => {
36
+ console.error("执行失败:", error);
37
+ process.exit(1);
38
+ });
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * 构建工具
3
3
  * @description
4
4
  * 工具实现根据配置自动切换分支,构建到配置的对应文件夹路径,并且执行自动提交推送,也可执行自动压缩提交到当前项目
@@ -25,17 +25,18 @@ const { postVersionFileAndMsg } = require("../../script/webhook/webhook.js");
25
25
  const { scriptWrite, targetProjectFileResolve, currentProjectFileResolve } = require("../../tools/file-process.js");
26
26
  const {
27
27
  autoBranchProcess,
28
- checkGitStatus,
29
28
  autoGitProcess,
30
29
  getCurrentBranch,
31
30
  getLatestCommitInfo,
32
31
  getLastCommitByFile,
33
- checkAndUpdatePackages
32
+ checkAndUpdatePackages,
33
+ checkSingleDirGitStatus,
34
+ pullSingleDirFromBranch
34
35
  } = require("../../script/git-automation");
35
36
 
36
37
  const scriptEvent = process.env.npm_lifecycle_event;
37
38
  const isBuilZipScript = process.env.npm_lifecycle_event;
38
- const testScript = "infly:build:test";
39
+ const testScript = "build:test";
39
40
  const versionFileName = "package.json";
40
41
  const oldVersionFileName = "version-config.json";
41
42
  const npmPackageConfigKey = "infly";
@@ -53,36 +54,42 @@ const { infly: currentInflyConfig } = currentPackageJsonConfig || {};
53
54
  const targetProjectVersionConfigPath = targetProjectFileResolve(oldVersionFileName);
54
55
  const targetProjectVueConfigPath = targetProjectFileResolve("vue.config.js");
55
56
  const targetProjectPackageJSON = targetProjectFileResolve("package.json");
57
+ const targetProjectSettingsJS = targetProjectFileResolve("src/settings.js");
56
58
  const targetPackageJsonConfig = JSON.parse(fs.readFileSync(targetProjectPackageJSON, "utf-8"));
57
59
  const { name: projectName, version: projectVersion = "", infly: targetInflyConfig } = targetPackageJsonConfig || {};
58
60
  const [major = "", minor = "", patch = ""] = projectVersion.split(".");
61
+ const { title: projectTitle } = fs.existsSync(targetProjectSettingsJS) ? require(targetProjectSettingsJS) || {} : {};
59
62
 
60
63
  const isExistTargetProjectVersionConfig = fs.existsSync(targetProjectVersionConfigPath); // 安装依赖项目下是否存在旧版本控制文件
61
64
  const isExistVueConfigFile = fs.existsSync(targetProjectVueConfigPath); // 安装依赖项目下是否存在vue.config.js文件
65
+ const hasNextConfig = !isExistVueConfigFile && ( // Next.js 项目检测
66
+ fs.existsSync(targetProjectFileResolve("next.config.js")) ||
67
+ fs.existsSync(targetProjectFileResolve("next.config.mjs")) ||
68
+ fs.existsSync(targetProjectFileResolve("next.config.ts"))
69
+ );
62
70
  const isMaster = currentBranch === "master"; // 是否在master分支
63
- const dealBranch = isMaster ? "master" : "release";
64
71
  const isPkg = versionFileName === "package.json";
65
72
 
66
73
  const targetProjectVueConfig = isExistVueConfigFile ? require(targetProjectVueConfigPath) : {};
67
- const { outputDir: targetProjectOutputDir, configureWebpack } = targetProjectVueConfig || {};
74
+ const { outputDir: vueOutputDir, configureWebpack } = targetProjectVueConfig || {};
75
+ let targetProjectOutputDir = vueOutputDir;
68
76
 
69
- const { updateDevText } =
70
- { master: { updateDevText: "正式环境" }, release: { updateDevText: "测试环境" } }[dealBranch] || {}; // 更新环境和处理分支
77
+ const { updateDevText = "测试环境" } = { master: { updateDevText: "正式环境" } }[currentBranch] || {}; // 更新环境和处理分支
71
78
 
72
79
  const configPath = path.resolve(projectRoot, versionFileName);
73
80
  let buildConfig = JSON.parse(fs.readFileSync(configPath, "utf-8")) || {};
74
- if (buildConfig[npmPackageConfigKey]) {
75
- buildConfig = buildConfig[npmPackageConfigKey];
76
- }
81
+ let tempPlatformName = "";
82
+
83
+ buildConfig = normalizeBuildConfig(buildConfig, npmPackageConfigKey, currentBranch, projectTitle);
77
84
 
78
85
  // 准备构建信息
79
- const { zipOptions, versionConfig } = buildConfig || {};
86
+ const { buildConfigs, versionConfig } = buildConfig || {};
80
87
  const {
81
88
  buildFoldName: zipBuildFoldName, // 构建后文件名称
82
89
  outputPath, // 输出路径
83
90
  gitAuto, // 是否自动提交git
84
- gitAutoPushRepos, // 自动提交文件到对应仓库
85
- gitAutoPushReposBranchMap = {}, // 自动提交文件到对应仓库分支配置
91
+ gitAutoPushReposBranchMap, // 自动提交文件到对应仓库分支配置
92
+ gitAutoPushRepos = gitAutoPushReposBranchMap, // 自动提交文件到对应仓库
86
93
  gitAutoCommitText = "", // git自动提交信息
87
94
  enablePreview, // 启用预览
88
95
  openExplorer, // 启用打开资源管理器
@@ -90,13 +97,113 @@ const {
90
97
  webhookAtUser, // 企业微信机器人@用户
91
98
  enableClipboard, // 启用粘贴板
92
99
  disableUpdateVersionEnv // 禁止更新版本信息环境
93
- } = zipOptions || {};
100
+ } = buildConfigs || {};
101
+ // Next.js 项目:优先使用 infly.buildConfigs.outputPath
102
+ if (!targetProjectOutputDir && outputPath) {
103
+ targetProjectOutputDir = outputPath;
104
+ }
105
+ if (targetProjectOutputDir && !path.isAbsolute(targetProjectOutputDir)) {
106
+ targetProjectOutputDir = path.resolve(projectRoot, targetProjectOutputDir);
107
+ }
94
108
  const buildFoldName = zipBuildFoldName || targetProjectOutputDir || "dist";
95
- const { mainVersion: verMainVersion, platformName, baseName, versionList = [], links } = versionConfig || {};
109
+ const { mainVersion: verMainVersion, baseName, versionList = [], links } = versionConfig || {};
96
110
  const mainVersion = verMainVersion || major; // 主版本号
97
111
  const [lastestVersionItem] = versionList || [];
98
112
  const { lastVersion = projectVersion || "1.0.0" } = lastestVersionItem || {};
99
113
 
114
+ function getBuildContext() {
115
+ try {
116
+ return JSON.parse(process.env.INFLY_BUILD_CONTEXT || "{}");
117
+ } catch {
118
+ return {};
119
+ }
120
+ }
121
+
122
+ const buildContext = getBuildContext();
123
+
124
+ function hasArg(name) {
125
+ return process.argv.includes(name);
126
+ }
127
+
128
+ function appendBatchWebhookRecord(publishText, extraParams = {}) {
129
+ const batchWebhookFile = buildContext.batchWebhookFile || process.env.INFLY_BATCH_WEBHOOK_FILE;
130
+
131
+ if (!batchWebhookFile) {
132
+ return false;
133
+ }
134
+
135
+ fs.appendFileSync(batchWebhookFile, `${JSON.stringify({ publishText, extraParams })}\n`);
136
+ return true;
137
+ }
138
+
139
+ function getArgValue(name) {
140
+ const index = process.argv.indexOf(name);
141
+ return index >= 0 ? process.argv[index + 1] : "";
142
+ }
143
+
144
+ function getNextStandaloneServerPath(distPath) {
145
+ const rootServerPath = path.join(distPath, "server.js");
146
+ const workspaceServerPath = path.join(distPath, "apps", projectName, "server.js");
147
+
148
+ if (fs.existsSync(rootServerPath)) {
149
+ return rootServerPath;
150
+ }
151
+
152
+ return workspaceServerPath;
153
+ }
154
+
155
+ function getBuildMode() {
156
+ const modeArg = getArgValue("--mode");
157
+ const lifecycleText = [process.env.npm_lifecycle_event, process.env.npm_lifecycle_script, ...process.argv]
158
+ .filter(Boolean)
159
+ .join(" ");
160
+
161
+ if (modeArg === "staging" || lifecycleText.includes("build:stage") || lifecycleText.includes("--mode staging")) {
162
+ return "stage";
163
+ }
164
+
165
+ if (
166
+ modeArg === "production" ||
167
+ modeArg === "prod" ||
168
+ lifecycleText.includes("build:prod") ||
169
+ lifecycleText.includes("build:pro")
170
+ ) {
171
+ return "prod";
172
+ }
173
+
174
+ return "";
175
+ }
176
+
177
+ function getStageBranch(branchMap = {}, branch = currentBranch) {
178
+ if (branch !== "master" && branchMap[branch] && branchMap[branch] !== "master") {
179
+ return branch;
180
+ }
181
+
182
+ if (branchMap.develop && branchMap.develop !== "master") {
183
+ return "develop";
184
+ }
185
+
186
+ if (branchMap.release && branchMap.release !== "master") {
187
+ return "release";
188
+ }
189
+
190
+ return Object.keys(branchMap).find((key) => branchMap[key] && branchMap[key] !== "master") || branch;
191
+ }
192
+
193
+ function getBuildTargetBranch(branchMap = {}) {
194
+ const buildMode = getBuildMode();
195
+
196
+ if (buildMode === "prod") {
197
+ return "master";
198
+ }
199
+
200
+ if (buildMode === "stage") {
201
+ return getStageBranch(branchMap);
202
+ }
203
+
204
+ return currentBranch;
205
+ }
206
+
100
207
  async function init() {
101
208
  try {
102
209
  // validateConfig(buildConfig);
@@ -111,13 +218,16 @@ async function init() {
111
218
 
112
219
  // 处理所需版本文件信息
113
220
  const timestamp = new Date().toISOString().slice(0, 10).replace(/-/g, ".");
114
- const baseFileName = `${platformName}-${buildFoldName}-${baseName}`;
221
+ const baseFileName = `${tempPlatformName}-${buildFoldName}-${baseName}`;
115
222
  const newVersion = isMaster ? incrementVersion(lastVersion, mainVersion) : lastVersion; // 非正式环境构建不更新版本信息
116
223
  const newFileName = baseFileName.replace("{version}", newVersion).replace("{timestamp}", timestamp);
117
224
  const gitInfo = getLatestCommitInfo() || {};
118
225
  const { branch, commitMsg } = gitInfo || {};
119
- const tempLink = typeof links === "object" ? links[dealBranch] : links || "";
120
- const publishText = `${platformName}:\n更新到:${tempLink}\n更新时间:${timestamp}\n版本号:v${newVersion}\n分支:${branch}\n更新环境:${updateDevText}\n更新内容:\n${commitMsg}`;
226
+ let tempLink = typeof links === "object" ? links[branch] : links || "";
227
+ if (typeof tempLink === "object") {
228
+ tempLink = tempLink[process.env.VUE_APP_PLATFORM] || tempLink["DEFAULT"] || JSON.stringify(tempLink);
229
+ }
230
+ const publishText = `${tempPlatformName}:\n更新到:${tempLink}\n更新时间:${timestamp}\n版本号:v${newVersion}\n分支:${branch}\n更新环境:${updateDevText}\n更新内容:\n${commitMsg}`;
121
231
  const newZipFileInfo = [
122
232
  {
123
233
  version: newVersion,
@@ -133,11 +243,12 @@ async function init() {
133
243
  const outputDir = path.resolve(projectRoot, "./", outputPath);
134
244
  const outputPathFull = path.join(outputDir, newFileName);
135
245
  const distPath = gitAutoPushRepos ? targetProjectOutputDir : path.resolve(projectRoot, "./" + buildFoldName);
136
- const indexHtmlPath = path.join(distPath, "index.html");
246
+ // Next.js standalone 项目检查 server.js,Vue/SPA 项目检查 index.html
247
+ const validatePath = hasNextConfig ? getNextStandaloneServerPath(distPath) : path.join(distPath, "index.html");
137
248
 
138
249
  // 校验构建文件是否存在,确保构建成功
139
250
  validateFileExists(distPath, "distPath");
140
- validateFileExists(indexHtmlPath, "indexHtmlPath");
251
+ validateFileExists(validatePath, hasNextConfig ? "serverJsPath" : "indexHtmlPath");
141
252
 
142
253
  // 非自动推送到构建仓库,进行构建文件压缩和检查是否压缩成功
143
254
  if (!gitAutoPushRepos) {
@@ -157,11 +268,12 @@ async function init() {
157
268
  projectName
158
269
  };
159
270
 
160
- checkGitStatus(buildFoldName, newFileName, checkGitStatusParams);
161
271
  autoGitProcess(buildFoldName, newFileName, {
162
272
  gitInfo,
163
273
  gitAutoCommitText,
164
274
  gitAutoPushReposBranchMap,
275
+ gitLockDir: buildContext.gitLockDir,
276
+ gitProcessOrder: buildContext.gitProcessOrder,
165
277
  ...checkGitStatusParams
166
278
  });
167
279
  }
@@ -175,16 +287,21 @@ async function init() {
175
287
  }
176
288
 
177
289
  if (webhookUrl) {
178
- postVersionFileAndMsg(publishText, {
290
+ const webhookParams = {
179
291
  projectName,
180
292
  newFileName,
181
293
  gitInfo,
182
294
  targetProjectOutputDir,
183
- ...zipOptions
184
- });
295
+ repos: path.relative(__dirname, targetProjectOutputDir).replace(/^(\.\.\\){4}apps\\/, ""),
296
+ ...buildConfigs
297
+ };
298
+
299
+ if (!appendBatchWebhookRecord(publishText, webhookParams)) {
300
+ postVersionFileAndMsg(publishText, webhookParams);
301
+ }
185
302
  }
186
303
 
187
- if (enablePreview) {
304
+ if (enablePreview && buildContext.skipPreview !== true && process.env.INFLY_SKIP_PREVIEW !== "1") {
188
305
  await previewInit(true);
189
306
  }
190
307
  } catch (error) {
@@ -193,6 +310,41 @@ async function init() {
193
310
  }
194
311
  }
195
312
 
313
+ /**
314
+ * 规范化构建配置
315
+ * @param {Object} config - 原始配置对象
316
+ * @param {String} packageKey - 包配置键名
317
+ * @param {String} branch - 当前分支
318
+ * @param {String} title - 项目标题
319
+ * @returns {Object} 规范化后的配置对象
320
+ */
321
+ function normalizeBuildConfig(config, packageKey, branch, title) {
322
+ let normalizedConfig = config;
323
+
324
+ // 提取嵌套的配置
325
+ if (normalizedConfig[packageKey]) {
326
+ normalizedConfig = normalizedConfig[packageKey];
327
+ }
328
+
329
+ // 自动启用 gitAutoPushRepos
330
+ if (!normalizedConfig.gitAutoPushRepos && normalizedConfig.gitAutoPushReposBranchMap) {
331
+ normalizedConfig.gitAutoPushRepos = true;
332
+ }
333
+
334
+ // 处理平台名称配置
335
+ const platformName = normalizedConfig?.versionConfig?.platformName;
336
+ if (typeof platformName === "object") {
337
+ tempPlatformName = platformName[branch] || platformName["master"] || "构建平台";
338
+ } else if (typeof platformName === "string" && platformName) {
339
+ tempPlatformName = platformName;
340
+ } else if (title) {
341
+ // 使用项目标题作为默认平台名称
342
+ tempPlatformName = title;
343
+ }
344
+
345
+ return normalizedConfig;
346
+ }
347
+
196
348
  /**
197
349
  * 用户确认提示
198
350
  * @param {string} message - 提示信息
@@ -229,38 +381,42 @@ function askUserConfirmation(message, defaultYes = false) {
229
381
  * 校验配置文件
230
382
  * @param {Object} buildConfig
231
383
  */
232
- async function validateConfig(buildConfig) {
384
+ async function validateConfig(buildConfig, targetBranch = currentBranch) {
233
385
  if (!buildConfig) {
234
386
  console.error(global.logColor.error, `❌ ZIP压缩已禁用,版本控制文件${versionFileName}配置错误`);
235
387
  process.exit(1);
236
388
  }
237
389
 
238
- if (buildConfig?.zipOptions?.enabled === false) {
239
- console.warn(global.logColor.error, `⚠️ ZIP压缩已禁用,版本控制文件${versionFileName}中的enabled属性设置为false`);
390
+ if (buildConfig?.buildConfigs?.enabled === false) {
391
+ console.warn(
392
+ global.logColor.error,
393
+ `⚠️ ZIP压缩已禁用,版本控制文件${versionFileName}中的 enabled 属性设置为 false`
394
+ );
240
395
  process.exit(0);
241
396
  }
242
397
 
243
- if (!/^release/.test(currentBranch) && currentBranch !== "master") {
398
+ if (!buildConfig?.buildConfigs?.gitAutoPushReposBranchMap[targetBranch]) {
244
399
  if (![testScript].includes(scriptEvent)) {
245
- console.error(global.logColor.error, `❌ 当前分支非release、release/xx、master等可构建分支,请检查`);
400
+ console.error(
401
+ global.logColor.error,
402
+ `❌ 目标分支 ${targetBranch} 非 gitAutoPushReposBranchMap 配置可构建分支,请检查`
403
+ );
246
404
  process.exit(1);
247
405
  }
248
406
  }
249
407
 
250
- if (currentBranch !== "master" && currentBranch !== "release" && !/^release/.test(currentBranch)) {
251
- console.warn(
252
- global.logColor.warning,
253
- `⚠️ 当前分支为 ${currentBranch},非测试需求请在 master/release/release/xxx 等可构建分支上执行此脚本`
254
- );
255
- }
408
+ const buildMode = getBuildMode();
409
+ const lifecycleEvent = process.env.npm_lifecycle_event || "";
410
+ const isProdBuild = buildMode === "prod" || lifecycleEvent.includes("prod");
411
+ const isStageBuild = buildMode === "stage" || lifecycleEvent.includes("stage");
256
412
 
257
- if (currentBranch === "master" && !process.env.npm_lifecycle_event.includes("prod")) {
258
- console.error(global.logColor.error, `❌ 当前分支为 master 分支,请使用正式环境构建命令进行构建`);
413
+ if (targetBranch === "master" && !isProdBuild) {
414
+ console.error(global.logColor.error, `❌ 目标分支为 master 分支,请使用正式环境构建命令进行构建`);
259
415
  process.exit(1);
260
416
  }
261
417
 
262
- if (currentBranch === "release" && !process.env.npm_lifecycle_event.includes("stage")) {
263
- console.warn(global.logColor.warning, `⚠️ 当前分支为 release 分支,建议使用测试环境构建命令`);
418
+ if (targetBranch !== "master" && !isStageBuild) {
419
+ console.warn(global.logColor.warning, `⚠️ 目标分支为 ${targetBranch} 分支,建议使用测试环境构建命令`);
264
420
  console.log(global.logColor.info, `推荐命令: npm run infly:build:stage`);
265
421
 
266
422
  const shouldContinue = await askUserConfirmation("确定要继续当前构建吗?", false);
@@ -271,7 +427,6 @@ async function validateConfig(buildConfig) {
271
427
  }
272
428
  }
273
429
  }
274
-
275
430
  /**
276
431
  * 校验文件是否存在
277
432
  * @param {String} checkPath - 检查路径
@@ -288,6 +443,13 @@ function validateFileExists(checkPath, logKey) {
288
443
  indexHtmlPath: {
289
444
  error: "index.html文件不存在,请检查构建配置"
290
445
  },
446
+ serverJsPath: {
447
+ error: `server.js文件不存在,请检查 Next.js standalone 构建配置。支持 server.js 或 ${path.join(
448
+ "apps",
449
+ projectName,
450
+ "server.js"
451
+ )}`
452
+ },
291
453
  outputPathFull: {
292
454
  error: "压缩文件没有成功创建,请检查构建配置",
293
455
  success: `压缩完成,已成功创建文件`,
@@ -353,11 +515,14 @@ function createVersionMap(versionList = []) {
353
515
  * @param {Boolean} disableUpdateVersionEnv - 禁用环境配置
354
516
  */
355
517
  function checkIsDisableUpdateVersionEnv(disableUpdateVersionEnv = []) {
356
- let isDisableUpdateVersionEnv = process.env.npm_lifecycle_script.includes(`--mode staging`); // 默认禁用测试环境更新版本
518
+ const lifecycleText = [process.env.npm_lifecycle_event, process.env.npm_lifecycle_script, ...process.argv]
519
+ .filter(Boolean)
520
+ .join(" ");
521
+ let isDisableUpdateVersionEnv = lifecycleText.includes(`--mode staging`); // 默认禁用测试环境更新版本
357
522
 
358
523
  if (Array.isArray(disableUpdateVersionEnv) && disableUpdateVersionEnv.length > 0) {
359
524
  disableUpdateVersionEnv.forEach((item) => {
360
- if (process.env.npm_lifecycle_script.includes(`--mode ${item}`)) {
525
+ if (lifecycleText.includes(`--mode ${item}`)) {
361
526
  isDisableUpdateVersionEnv = disableUpdateVersionEnv.includes(item);
362
527
  }
363
528
  });
@@ -373,7 +538,14 @@ function checkIsDisableUpdateVersionEnv(disableUpdateVersionEnv = []) {
373
538
  */
374
539
  function updateVersionList(zipFiles = [], extraParams) {
375
540
  const { opt = "update", buildConfig, configPath } = extraParams || {};
376
- const { versionConfig, zipOptions } = buildConfig || {};
541
+ let { versionConfig } = buildConfig || {};
542
+ if (buildConfig && !versionConfig) {
543
+ buildConfig.versionConfig = {};
544
+ versionConfig = buildConfig.versionConfig;
545
+ }
546
+ if (versionConfig && !Array.isArray(versionConfig.versionList)) {
547
+ versionConfig.versionList = [];
548
+ }
377
549
  const { versionList = [] } = versionConfig || {};
378
550
  const { disableUpdateVersionEnv } = versionConfig || {};
379
551
  const isDisableUpdateVersionEnv = checkIsDisableUpdateVersionEnv(disableUpdateVersionEnv);
@@ -394,7 +566,10 @@ function updateVersionList(zipFiles = [], extraParams) {
394
566
  if (!versionMap[fileName] && Array.isArray(versionList)) {
395
567
  allVersionExist = false;
396
568
  buildConfig.versionConfig.versionList.unshift(singleVersionInfo);
397
- console.log(global.logColor.success, `✅ 新版本${version}写入${versionFileName}文件更新成功`);
569
+ const updateText = isDisableUpdateVersionEnv
570
+ ? `✅ 新版本${version}已生成,当前环境跳过写入${versionFileName}`
571
+ : `✅ 新版本${version}写入${versionFileName}文件更新成功`;
572
+ console.log(global.logColor.success, updateText);
398
573
  }
399
574
  // 如果是更新,压缩脚本进行打包则删除全部旧文件
400
575
  if (isBuilZipScript && opt === "update") {
@@ -529,7 +704,7 @@ function copyToClipboard(text) {
529
704
  */
530
705
  function scriptInit() {
531
706
  let tempInflyConfig = {};
532
- if (!isExistVueConfigFile || !fs.existsSync(targetProjectPackageJSON)) {
707
+ if ((!isExistVueConfigFile && !hasNextConfig) || !fs.existsSync(targetProjectPackageJSON)) {
533
708
  return;
534
709
  }
535
710
  scriptWrite(targetProjectPackageJSON, buildList);
@@ -541,12 +716,12 @@ function scriptInit() {
541
716
  // 如果存在以前的版本管理文件则进行配置迁移
542
717
  if (isExistTargetProjectVersionConfig) {
543
718
  tempInflyConfig = JSON.parse(fs.readFileSync(targetProjectVersionConfigPath, "utf-8"));
544
- const { versionConfig = {}, zipOptions = {} } = tempInflyConfig || {};
719
+ const { versionConfig = {}, buildConfigs = {} } = tempInflyConfig || {};
545
720
  if (versionConfig.versionList) {
546
721
  tempInflyConfig.versionConfig.versionList = []; // 删除旧版本列表
547
722
  }
548
- if (zipOptions.buildFoldName) {
549
- tempInflyConfig.zipOptions.buildFoldName = "";
723
+ if (buildConfigs.buildFoldName) {
724
+ tempInflyConfig.buildConfigs.buildFoldName = "";
550
725
  }
551
726
  }
552
727
 
@@ -564,7 +739,7 @@ function scriptInit() {
564
739
  * @returns
565
740
  */
566
741
  function copyVersionConfigFile() {
567
- if (!isExistVueConfigFile) {
742
+ if (!isExistVueConfigFile && !hasNextConfig) {
568
743
  return;
569
744
  }
570
745
  const { name: projectTitle } = configureWebpack || {};
@@ -590,10 +765,10 @@ function copyVersionConfigFile() {
590
765
  const tempVersionConfig = JSON.parse(data);
591
766
 
592
767
  if (targetProjectOutputDir) {
593
- tempVersionConfig.zipOptions.buildFoldName = targetProjectOutputDir;
768
+ tempVersionConfig.buildConfigs.buildFoldName = targetProjectOutputDir;
594
769
  }
595
770
 
596
- if (projectTitle) {
771
+ if (projectTitle && !tempVersionConfig.versionConfig?.platformName) {
597
772
  tempVersionConfig.versionConfig.platformName = projectTitle;
598
773
  }
599
774
 
@@ -620,22 +795,44 @@ function copyVersionConfigFile() {
620
795
  * 构建前分支处理
621
796
  */
622
797
  async function beforeBuild() {
623
- // 1. 先进行配置校验,如果用户取消则阻塞后续流程
624
- await validateConfig(buildConfig);
798
+ const targetBranch = getBuildTargetBranch(gitAutoPushReposBranchMap);
799
+
800
+ await validateConfig(buildConfig, targetBranch);
801
+
802
+ if (
803
+ hasArg("--check-only") ||
804
+ buildContext.checkOnly === true ||
805
+ (process.env.INFLY_SKIP_BRANCH_UPDATE === "1" && process.env.INFLY_SKIP_PACKAGES_UPDATE === "1")
806
+ ) {
807
+ return;
808
+ }
809
+
810
+ const currentProjectStatus = checkSingleDirGitStatus(projectRoot, projectName);
811
+
812
+ if (currentProjectStatus.hasUncommitted) {
813
+ console.log(global.logColor.error, `\n❌ 当前项目存在未提交的更改,请先提交或暂存后再继续构建`);
814
+ process.exit(1);
815
+ }
816
+
817
+ const currentProjectUpdateResult = pullSingleDirFromBranch(projectRoot, projectName, targetBranch);
818
+
819
+ if (!currentProjectUpdateResult.success) {
820
+ console.log(global.logColor.error, `\n❌ 当前项目切换到 ${targetBranch} 分支失败,请检查`);
821
+ process.exit(1);
822
+ }
625
823
 
626
- // 2. 执行分支切换和拉取操作
627
824
  await autoBranchProcess({
628
825
  gitAutoPushRepos,
629
826
  gitAutoPushReposBranchMap,
630
- currentBranch,
827
+ currentBranch: targetBranch,
631
828
  targetProjectOutputDir,
632
- validateConfig: () => {} // 配置验证已经在上面完成
829
+ validateConfig: () => {}
633
830
  });
634
831
 
635
- // 3. 检查和更新 packages 下的模块(如果启用了此功能)
636
- await checkAndUpdatePackages();
832
+ if (process.env.INFLY_SKIP_PACKAGES_UPDATE !== "1") {
833
+ await checkAndUpdatePackages(undefined, "master");
834
+ }
637
835
  }
638
-
639
836
  module.exports = {
640
837
  init,
641
838
  scriptInit,
@@ -0,0 +1,84 @@
1
+ /**
2
+ * RemoveLegacyAssetsPlugin
3
+ * 用于处理 Vue CLI Modern Mode 的 legacy 文件问题
4
+ *
5
+ * 功能:
6
+ * 1. 在构建前创建占位文件,防止 ModernModePlugin 读取时报错
7
+ * 2. 在构建时删除 legacy 相关的资源
8
+ * 3. 在构建完成后清理占位文件
9
+ */
10
+
11
+ "use strict";
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+
16
+ class RemoveLegacyAssetsPlugin {
17
+ constructor(options = {}) {
18
+ this.options = {
19
+ legacyFiles: [
20
+ 'legacy-assets-index.html.json',
21
+ 'modern-assets-index.html.json'
22
+ ],
23
+ ...options
24
+ };
25
+ }
26
+
27
+ apply(compiler) {
28
+ const outputPath = compiler.options.output.path;
29
+ const { legacyFiles } = this.options;
30
+
31
+ // 🔥 Hook 1: 构建开始前创建占位文件
32
+ compiler.hooks.beforeRun.tapAsync('RemoveLegacyAssetsPlugin', (compiler, callback) => {
33
+ // 确保输出目录存在
34
+ if (!fs.existsSync(outputPath)) {
35
+ fs.mkdirSync(outputPath, { recursive: true });
36
+ }
37
+
38
+ // 创建空数组的 JSON 文件(Vue CLI 期望数组格式)
39
+ legacyFiles.forEach(file => {
40
+ const filePath = path.join(outputPath, file);
41
+ try {
42
+ fs.writeFileSync(filePath, '[]');
43
+ } catch (err) {
44
+ // 忽略创建失败的错误
45
+ console.warn(`⚠ Failed to create placeholder: ${file}`, err.message);
46
+ }
47
+ });
48
+
49
+ callback();
50
+ });
51
+
52
+ // 🔥 Hook 2: 构建时删除编译产物中的 legacy 资源
53
+ compiler.hooks.emit.tapAsync('RemoveLegacyAssetsPlugin', (compilation, callback) => {
54
+ Object.keys(compilation.assets).forEach(filename => {
55
+ if (filename.includes('-legacy') || filename.includes('legacy-assets')) {
56
+ delete compilation.assets[filename];
57
+ }
58
+ });
59
+ callback();
60
+ });
61
+
62
+ // 🔥 Hook 3: 构建完成后清理占位文件
63
+ compiler.hooks.done.tapAsync('RemoveLegacyAssetsPlugin', (stats, callback) => {
64
+ // 延迟执行,确保所有读取操作完成
65
+ setTimeout(() => {
66
+ legacyFiles.forEach(file => {
67
+ const filePath = path.join(outputPath, file);
68
+ try {
69
+ if (fs.existsSync(filePath)) {
70
+ fs.unlinkSync(filePath);
71
+ console.log(`\x1b[32m✓ Cleaned up: ${file}\x1b[0m`);
72
+ }
73
+ } catch (err) {
74
+ // 忽略删除失败的错误
75
+ console.warn(`⚠ Failed to cleanup: ${file}`, err.message);
76
+ }
77
+ });
78
+ callback();
79
+ }, 100);
80
+ });
81
+ }
82
+ }
83
+
84
+ module.exports = RemoveLegacyAssetsPlugin;