@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.
- package/bin/cli.js +29 -21
- package/build/build-dist/index.js +258 -61
- package/build/webpack5/remove-legacy-assets-plugin.js +84 -0
- package/build/webpack5/webpack.base.js +228 -20
- package/build/webpack5/webpack.base.test.js +59 -0
- package/index.js +10 -0
- package/module/Permission.js +121 -55
- package/module/REST.js +136 -26
- package/module/Router.js +15 -0
- package/module/Uts.js +380 -331
- package/module/cjs/deep-merge.cjs +38 -0
- package/module/cjs/page-config.cjs +119 -0
- package/module/cjs/request-url-rules.cjs +55 -0
- package/package.json +11 -10
- package/script/build/command.js +48 -0
- package/script/build/env.js +28 -0
- package/script/build/git.js +252 -0
- package/script/build/preview.js +75 -0
- package/script/build/webhook.js +118 -0
- package/script/git-automation/check-packages.js +11 -8
- package/script/git-automation/git-utils.js +67 -0
- package/script/git-automation/index.js +378 -106
- package/script/index.js +8 -8
- package/script/pts/cloud-scenes.mjs +65 -0
- package/script/pts/cloud.js +151 -0
- package/script/pts/generate-cloud-params.mjs +210 -0
- package/script/pts/generate-cloud-params.test.mjs +67 -0
- package/script/webhook/webhook.js +75 -4
- package/store/modules/user.js +111 -9
- package/tools/auto-export.js +56 -0
- package/tools/file-export.js +32 -9
- package/tools/file-process.js +3 -0
- package/tools/project-preview.js +110 -97
- package/dataInit/commonTypeMap.js +0 -31
- package/dataInit/marketingActivitiesMap.js +0 -214
- package/dataInit/orderMap.js +0 -13
- package/dataInit/personalMap.js +0 -19
- package/dataInit/settlementMap.js +0 -17
- 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
|
-
|
|
4
|
-
|
|
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:
|
|
9
|
-
initZip:
|
|
10
|
-
preview:
|
|
11
|
-
|
|
13
|
+
afterBuild: () => loadBuildDist().init(),
|
|
14
|
+
initZip: () => loadBuildDist().init(),
|
|
15
|
+
preview: () => loadPreview().init(),
|
|
16
|
+
"--preview": () => loadPreview().init(),
|
|
17
|
+
beforeBuild: () => loadBuildDist().beforeBuild(),
|
|
12
18
|
scriptOverride: () => {
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
21
|
-
} else {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
);
|
|
29
|
-
|
|
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 = "
|
|
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:
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
let tempPlatformName = "";
|
|
82
|
+
|
|
83
|
+
buildConfig = normalizeBuildConfig(buildConfig, npmPackageConfigKey, currentBranch, projectTitle);
|
|
77
84
|
|
|
78
85
|
// 准备构建信息
|
|
79
|
-
const {
|
|
86
|
+
const { buildConfigs, versionConfig } = buildConfig || {};
|
|
80
87
|
const {
|
|
81
88
|
buildFoldName: zipBuildFoldName, // 构建后文件名称
|
|
82
89
|
outputPath, // 输出路径
|
|
83
90
|
gitAuto, // 是否自动提交git
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
} =
|
|
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,
|
|
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 = `${
|
|
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
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
290
|
+
const webhookParams = {
|
|
179
291
|
projectName,
|
|
180
292
|
newFileName,
|
|
181
293
|
gitInfo,
|
|
182
294
|
targetProjectOutputDir,
|
|
183
|
-
|
|
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?.
|
|
239
|
-
console.warn(
|
|
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 (
|
|
398
|
+
if (!buildConfig?.buildConfigs?.gitAutoPushReposBranchMap[targetBranch]) {
|
|
244
399
|
if (![testScript].includes(scriptEvent)) {
|
|
245
|
-
console.error(
|
|
400
|
+
console.error(
|
|
401
|
+
global.logColor.error,
|
|
402
|
+
`❌ 目标分支 ${targetBranch} 非 gitAutoPushReposBranchMap 配置可构建分支,请检查`
|
|
403
|
+
);
|
|
246
404
|
process.exit(1);
|
|
247
405
|
}
|
|
248
406
|
}
|
|
249
407
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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 (
|
|
258
|
-
console.error(global.logColor.error, `❌
|
|
413
|
+
if (targetBranch === "master" && !isProdBuild) {
|
|
414
|
+
console.error(global.logColor.error, `❌ 目标分支为 master 分支,请使用正式环境构建命令进行构建`);
|
|
259
415
|
process.exit(1);
|
|
260
416
|
}
|
|
261
417
|
|
|
262
|
-
if (
|
|
263
|
-
console.warn(global.logColor.warning, `⚠️
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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 = {},
|
|
719
|
+
const { versionConfig = {}, buildConfigs = {} } = tempInflyConfig || {};
|
|
545
720
|
if (versionConfig.versionList) {
|
|
546
721
|
tempInflyConfig.versionConfig.versionList = []; // 删除旧版本列表
|
|
547
722
|
}
|
|
548
|
-
if (
|
|
549
|
-
tempInflyConfig.
|
|
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.
|
|
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
|
-
|
|
624
|
-
|
|
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
|
-
|
|
636
|
-
|
|
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;
|