@infly/libs 2.0.36 → 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 -22
- package/build/build-dist/index.js +211 -46
- package/build/webpack5/webpack.base.js +10 -1
- package/build/webpack5/webpack.base.test.js +59 -0
- package/module/Permission.js +43 -36
- package/module/REST.js +109 -46
- package/module/Uts.js +90 -52
- 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 +6 -6
- 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 +229 -104
- 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 +72 -2
- package/store/modules/user.js +63 -46
- package/tools/auto-export.js +56 -0
- package/tools/file-export.js +16 -12
- package/tools/project-preview.js +110 -97
- package/types/unused.index.d.ts +0 -71
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const sameValue = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
2
|
+
|
|
3
|
+
const hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target, key);
|
|
4
|
+
|
|
5
|
+
function mergePageConfig(...sources) {
|
|
6
|
+
const pageConfig = {};
|
|
7
|
+
|
|
8
|
+
sources.forEach((source) => {
|
|
9
|
+
Object.keys(source || {}).forEach((key) => {
|
|
10
|
+
const value = source[key];
|
|
11
|
+
|
|
12
|
+
if (hasOwn(pageConfig, key) && !sameValue(pageConfig[key], value)) {
|
|
13
|
+
console.warn(
|
|
14
|
+
`[page-config] duplicate pageConfig key "${key}" has different values.`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pageConfig[key] = value;
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return pageConfig;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalizePlatforms(platforms = [], platformGroups = {}) {
|
|
26
|
+
return platforms.reduce((result, platform) => {
|
|
27
|
+
if (platformGroups[platform]) {
|
|
28
|
+
result.push(...platformGroups[platform]);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
result.push(platform);
|
|
32
|
+
return result;
|
|
33
|
+
}, []);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizePlatformKey(key, platformGroups) {
|
|
37
|
+
return normalizePlatforms(
|
|
38
|
+
key.split(",").map((platform) => platform.trim()),
|
|
39
|
+
platformGroups
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getPlatformChain(platform, platformExtends = {}) {
|
|
44
|
+
const chain = [];
|
|
45
|
+
let current = platform;
|
|
46
|
+
|
|
47
|
+
while (current && !chain.includes(current)) {
|
|
48
|
+
chain.push(current);
|
|
49
|
+
current = platformExtends[current];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return chain;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function resolvePageConfigValue(config, platform, options = {}) {
|
|
56
|
+
const { platformGroups = {}, platformExtends = {} } = options;
|
|
57
|
+
const platformChain = getPlatformChain(platform, platformExtends);
|
|
58
|
+
|
|
59
|
+
if (Array.isArray(config)) {
|
|
60
|
+
const platforms = normalizePlatforms(config, platformGroups);
|
|
61
|
+
return platformChain.some((item) => platforms.includes(item))
|
|
62
|
+
? true
|
|
63
|
+
: undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!config || typeof config !== "object") {
|
|
67
|
+
return config;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const exactPlatform = platformChain.find((item) => hasOwn(config, item));
|
|
71
|
+
|
|
72
|
+
if (exactPlatform) {
|
|
73
|
+
return config[exactPlatform];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const matchedKey = Object.keys(config).find((key) => {
|
|
77
|
+
if (key === "DEFAULT") {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const platforms = normalizePlatformKey(key, platformGroups);
|
|
81
|
+
return platformChain.some((item) => platforms.includes(item));
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (matchedKey) {
|
|
85
|
+
return config[matchedKey];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return config.DEFAULT;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolvePlatformPageConfig(pageConfig = {}, platform = "DEFAULT", options = {}) {
|
|
92
|
+
const resolvedConfig = {};
|
|
93
|
+
const keys = Object.keys(pageConfig);
|
|
94
|
+
const normalKeys = keys.filter((key) => !key.startsWith("!"));
|
|
95
|
+
const negatedKeys = keys.filter((key) => key.startsWith("!"));
|
|
96
|
+
|
|
97
|
+
normalKeys.forEach((key) => {
|
|
98
|
+
const value = resolvePageConfigValue(pageConfig[key], platform, options);
|
|
99
|
+
if (value !== undefined) {
|
|
100
|
+
resolvedConfig[key] = value;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// "!showXxx": ["PARTNER"] → 命中平台时解析为 showXxx: false
|
|
105
|
+
negatedKeys.forEach((key) => {
|
|
106
|
+
const configKey = key.slice(1);
|
|
107
|
+
const value = resolvePageConfigValue(pageConfig[key], platform, options);
|
|
108
|
+
if (value === true) {
|
|
109
|
+
resolvedConfig[configKey] = false;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return resolvedConfig;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = {
|
|
117
|
+
mergePageConfig,
|
|
118
|
+
resolvePlatformPageConfig
|
|
119
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
function normalizeRuleDomains(domains) {
|
|
2
|
+
if (!Array.isArray(domains)) {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return domains
|
|
7
|
+
.filter(Boolean)
|
|
8
|
+
.map((domain) => String(domain).trim().replace(/\/+$/, ""));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function normalizePathIncludes(pathIncludes) {
|
|
12
|
+
if (!Array.isArray(pathIncludes)) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return pathIncludes.filter(Boolean).map((path) => String(path));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function resolveInternalServiceURL(url, rules = []) {
|
|
20
|
+
if (!url || !Array.isArray(rules) || rules.length === 0) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = new URL(url);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const requestOrigin = parsed.origin.replace(/\/+$/, "");
|
|
32
|
+
const requestPath = parsed.pathname || "/";
|
|
33
|
+
|
|
34
|
+
for (const rule of rules) {
|
|
35
|
+
const domains = normalizeRuleDomains(rule.domains);
|
|
36
|
+
const pathIncludes = normalizePathIncludes(rule.pathIncludes);
|
|
37
|
+
const domainMatched = domains.includes(requestOrigin);
|
|
38
|
+
const pathMatched =
|
|
39
|
+
pathIncludes.length === 0 ||
|
|
40
|
+
pathIncludes.some((path) => requestPath.includes(path));
|
|
41
|
+
|
|
42
|
+
if (domainMatched && pathMatched) {
|
|
43
|
+
return {
|
|
44
|
+
url: `${requestPath}${parsed.search || ""}`,
|
|
45
|
+
baseURL: rule.baseURL || "/"
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
resolveInternalServiceURL
|
|
55
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infly/libs",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.37",
|
|
4
4
|
"description": "工具组件库",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"author": "Kahal",
|
|
36
36
|
"license": "ISC",
|
|
37
37
|
"dependencies": {},
|
|
38
|
-
"devDependencies
|
|
39
|
-
"@babel/core": "^7.
|
|
40
|
-
"@babel/preset-env": "^7.
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@babel/core": "^7.23.3",
|
|
40
|
+
"@babel/preset-env": "^7.23.3",
|
|
41
41
|
"babel-loader": "^10.0.0",
|
|
42
|
-
"webpack": "^5.
|
|
43
|
-
"webpack-cli": "^
|
|
42
|
+
"webpack": "^5.88.2",
|
|
43
|
+
"webpack-cli": "^5.1.4",
|
|
44
44
|
"webpack-node-externals": "^3.0.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const { spawn } = require("child_process");
|
|
2
|
+
|
|
3
|
+
function run(command, args, options = {}) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const child = spawn(command, args, {
|
|
6
|
+
cwd: options.cwd || process.cwd(),
|
|
7
|
+
env: {
|
|
8
|
+
...process.env,
|
|
9
|
+
...(options.env || {})
|
|
10
|
+
},
|
|
11
|
+
stdio: options.stdio || "inherit",
|
|
12
|
+
shell: process.platform === "win32"
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
child.on("close", (code) => {
|
|
16
|
+
if (code === 0) {
|
|
17
|
+
resolve();
|
|
18
|
+
} else {
|
|
19
|
+
reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code}`));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
child.on("error", reject);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function spawnBackground(command, args, options = {}) {
|
|
28
|
+
const child = spawn(command, args, {
|
|
29
|
+
cwd: options.cwd || process.cwd(),
|
|
30
|
+
env: {
|
|
31
|
+
...process.env,
|
|
32
|
+
...(options.env || {})
|
|
33
|
+
},
|
|
34
|
+
stdio: options.stdio || "inherit",
|
|
35
|
+
shell: process.platform === "win32"
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("error", (error) => {
|
|
39
|
+
console.error(error.message);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return child;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = {
|
|
46
|
+
run,
|
|
47
|
+
spawnBackground
|
|
48
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const ENV = {
|
|
2
|
+
buildContext: "INFLY_BUILD_CONTEXT",
|
|
3
|
+
batchWebhookFile: "INFLY_BATCH_WEBHOOK_FILE",
|
|
4
|
+
batchPreview: "INFLY_BATCH_PREVIEW",
|
|
5
|
+
skipPreview: "INFLY_SKIP_PREVIEW",
|
|
6
|
+
skipPackagesUpdate: "INFLY_SKIP_PACKAGES_UPDATE",
|
|
7
|
+
skipBranchUpdate: "INFLY_SKIP_BRANCH_UPDATE"
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function parseBuildContext() {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(process.env[ENV.buildContext] || "{}");
|
|
13
|
+
} catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createBuildContext(value) {
|
|
19
|
+
return {
|
|
20
|
+
[ENV.buildContext]: JSON.stringify(value || {})
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
ENV,
|
|
26
|
+
parseBuildContext,
|
|
27
|
+
createBuildContext
|
|
28
|
+
};
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { checkAndUpdatePackages } = require("../git-automation");
|
|
4
|
+
const { gitOutput, findGitRepo, getGitCommonDir } = require("../git-automation/git-utils");
|
|
5
|
+
const { run } = require("./command");
|
|
6
|
+
|
|
7
|
+
function getTargetBranch(rootPackageJson, mode) {
|
|
8
|
+
const branchMap = rootPackageJson.projectConfig?.buildBranchMap || {};
|
|
9
|
+
return branchMap[mode] || (mode === "prod" ? "master" : "develop");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function hasPackageGitRepos(rootDir) {
|
|
13
|
+
const packagesDir = path.join(rootDir, "packages");
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(packagesDir)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return ["infly-libs", "infly-ui"].some((name) => fs.existsSync(path.join(packagesDir, name, ".git")));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function updatePackageSources(rootDir) {
|
|
23
|
+
console.log("\x1b[32m%s\x1b[0m", "更新 admin-monorepo / packages 源码");
|
|
24
|
+
|
|
25
|
+
if (hasPackageGitRepos(rootDir)) {
|
|
26
|
+
console.log(" 使用 packages/* 独立 git 仓库模式,拉取 master");
|
|
27
|
+
} else {
|
|
28
|
+
console.log(" 使用 admin-monorepo 根仓库模式,拉取 master");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
global.logColor = global.logColor || {
|
|
32
|
+
success: "\n\x1b[32m%s\x1b[0m",
|
|
33
|
+
error: "\n\x1b[31m%s\x1b[0m",
|
|
34
|
+
warning: "\n\x1b[33m%s\x1b[0m",
|
|
35
|
+
link: "\x1b[34m%s\x1b[0m",
|
|
36
|
+
info: "\n\x1b[36m%s\x1b[0m"
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const packagesDir = path.join(rootDir, "packages");
|
|
40
|
+
await checkAndUpdatePackages(fs.existsSync(packagesDir) ? packagesDir : undefined, "master");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getPackageSourcesKey(rootDir) {
|
|
44
|
+
if (!hasPackageGitRepos(rootDir)) {
|
|
45
|
+
return getGitCommonDir(rootDir);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return path.join(rootDir, "packages");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function findExistingAncestor(targetDir) {
|
|
52
|
+
let current = targetDir;
|
|
53
|
+
|
|
54
|
+
while (!fs.existsSync(current)) {
|
|
55
|
+
const parent = path.dirname(current);
|
|
56
|
+
|
|
57
|
+
if (parent === current) {
|
|
58
|
+
return "";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
current = parent;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return current;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getDistRepoInfo(rootDir, pkg, targetBranch, options = {}) {
|
|
68
|
+
const packageRoot = path.join(rootDir, pkg.dir);
|
|
69
|
+
const vueConfigPath = path.join(packageRoot, "vue.config.js");
|
|
70
|
+
const nextConfigJs = path.join(packageRoot, "next.config.js");
|
|
71
|
+
const nextConfigMjs = path.join(packageRoot, "next.config.mjs");
|
|
72
|
+
const nextConfigTs = path.join(packageRoot, "next.config.ts");
|
|
73
|
+
const hasVueConfig = fs.existsSync(vueConfigPath);
|
|
74
|
+
const hasNextConfig = !hasVueConfig && (
|
|
75
|
+
fs.existsSync(nextConfigJs) ||
|
|
76
|
+
fs.existsSync(nextConfigMjs) ||
|
|
77
|
+
fs.existsSync(nextConfigTs)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
let outputDir;
|
|
81
|
+
|
|
82
|
+
if (hasVueConfig) {
|
|
83
|
+
outputDir = require(vueConfigPath).outputDir;
|
|
84
|
+
} else if (hasNextConfig) {
|
|
85
|
+
outputDir = pkg.packageJson.infly?.buildConfigs?.outputPath;
|
|
86
|
+
} else {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (outputDir && !path.isAbsolute(outputDir)) {
|
|
91
|
+
outputDir = path.resolve(packageRoot, outputDir);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!outputDir) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const existingOutputDir = fs.existsSync(outputDir) ? outputDir : findExistingAncestor(outputDir);
|
|
99
|
+
|
|
100
|
+
if (!existingOutputDir) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const branchMap = pkg.packageJson.infly?.buildConfigs?.gitAutoPushReposBranchMap || {};
|
|
105
|
+
const distBranch = branchMap[targetBranch] || targetBranch;
|
|
106
|
+
let repoRoot = existingOutputDir;
|
|
107
|
+
let repoKey = existingOutputDir;
|
|
108
|
+
const repo = findGitRepo(existingOutputDir);
|
|
109
|
+
|
|
110
|
+
if (repo) {
|
|
111
|
+
repoRoot = repo.root;
|
|
112
|
+
repoKey = repo.commonDir;
|
|
113
|
+
} else {
|
|
114
|
+
try {
|
|
115
|
+
repoRoot = gitOutput(["-C", existingOutputDir, "rev-parse", "--show-toplevel"], rootDir);
|
|
116
|
+
repoKey = getGitCommonDir(existingOutputDir);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (!options.allowPathFallback) {
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
cwd: repoRoot,
|
|
126
|
+
branch: distBranch,
|
|
127
|
+
key: repoKey,
|
|
128
|
+
label: `dist(${path.relative(rootDir, repoRoot)})`
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function getDistRepoTasks(rootDir, packages, targetBranch, options = {}) {
|
|
133
|
+
const repos = new Map();
|
|
134
|
+
|
|
135
|
+
packages.forEach((pkg) => {
|
|
136
|
+
const repo = getDistRepoInfo(rootDir, pkg, targetBranch, options);
|
|
137
|
+
|
|
138
|
+
if (repo && !repos.has(repo.key)) {
|
|
139
|
+
repos.set(repo.key, {
|
|
140
|
+
cwd: repo.cwd,
|
|
141
|
+
branch: repo.branch,
|
|
142
|
+
key: repo.key,
|
|
143
|
+
label: repo.label
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
return Array.from(repos.values());
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function pullGitRepo(task) {
|
|
152
|
+
console.log("\x1b[32m%s\x1b[0m", `更新 ${task.label} -> ${task.branch}`);
|
|
153
|
+
const status = gitOutput(["status", "--porcelain"], task.cwd);
|
|
154
|
+
|
|
155
|
+
if (status) {
|
|
156
|
+
throw new Error(`${task.label} 存在未提交的更改,无法自动切换并拉取 ${task.branch}\n${status}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await run("git", ["checkout", task.branch], { cwd: task.cwd });
|
|
160
|
+
await run("git", ["pull", "origin", task.branch], { cwd: task.cwd });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function getAppAndDistSourceTasks(rootDir, packages, targetBranch) {
|
|
164
|
+
const appTasks = packages.map((pkg) => {
|
|
165
|
+
const cwd = path.join(rootDir, pkg.dir);
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
cwd,
|
|
169
|
+
branch: targetBranch,
|
|
170
|
+
label: pkg.name,
|
|
171
|
+
key: getGitCommonDir(cwd),
|
|
172
|
+
run: pullGitRepo
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
const distTasks = getDistRepoTasks(rootDir, packages, targetBranch).map((task) => ({
|
|
176
|
+
...task,
|
|
177
|
+
run: pullGitRepo
|
|
178
|
+
}));
|
|
179
|
+
|
|
180
|
+
return [...appTasks, ...distTasks];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function runSourceTasksWithOverlapCheck(tasks) {
|
|
184
|
+
const groups = new Map();
|
|
185
|
+
|
|
186
|
+
tasks.forEach((task) => {
|
|
187
|
+
const key = task.key || task.cwd || task.label;
|
|
188
|
+
|
|
189
|
+
if (!groups.has(key)) {
|
|
190
|
+
groups.set(key, []);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
groups.get(key).push(task);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await Promise.all(
|
|
197
|
+
Array.from(groups.values()).map(async (group) => {
|
|
198
|
+
for (const task of group) {
|
|
199
|
+
await task.run(task);
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function updateAppAndDistSources(rootDir, packages, targetBranch) {
|
|
206
|
+
const tasks = getAppAndDistSourceTasks(rootDir, packages, targetBranch);
|
|
207
|
+
|
|
208
|
+
console.log("\x1b[32m%s\x1b[0m", "并行更新 app / dist 源码");
|
|
209
|
+
|
|
210
|
+
await runSourceTasksWithOverlapCheck(tasks);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function updateAllSources(rootDir, packages, targetBranch) {
|
|
214
|
+
const tasks = [
|
|
215
|
+
{
|
|
216
|
+
label: "admin-monorepo/packages",
|
|
217
|
+
key: getPackageSourcesKey(rootDir),
|
|
218
|
+
run: () => updatePackageSources(rootDir)
|
|
219
|
+
},
|
|
220
|
+
...getAppAndDistSourceTasks(rootDir, packages, targetBranch)
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
await runSourceTasksWithOverlapCheck(tasks);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function printDryRunSourceUpdatePlan(rootDir, packages, targetBranch) {
|
|
227
|
+
console.log("并行拉取:");
|
|
228
|
+
console.log(" 1. admin-monorepo/packages -> master");
|
|
229
|
+
packages.forEach((pkg, index) => {
|
|
230
|
+
console.log(` ${index + 2}. ${pkg.name} -> ${targetBranch} (${pkg.dir})`);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const distTasks = getDistRepoTasks(rootDir, packages, targetBranch, { allowPathFallback: true });
|
|
234
|
+
|
|
235
|
+
if (distTasks.length === 0) {
|
|
236
|
+
console.log(` ${packages.length + 2}. dist 仓库 -> 未解析到可拉取仓库`);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
distTasks.forEach((task, index) => {
|
|
241
|
+
console.log(` ${packages.length + 2 + index}. ${task.label} -> ${task.branch} (${path.relative(rootDir, task.cwd)})`);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
module.exports = {
|
|
246
|
+
getTargetBranch,
|
|
247
|
+
updatePackageSources,
|
|
248
|
+
updateAppAndDistSources,
|
|
249
|
+
updateAllSources,
|
|
250
|
+
getDistRepoTasks,
|
|
251
|
+
printDryRunSourceUpdatePlan
|
|
252
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const { spawn } = require("child_process");
|
|
3
|
+
const { spawnBackground } = require("./command");
|
|
4
|
+
const { createBuildContext } = require("./env");
|
|
5
|
+
|
|
6
|
+
function killPreviewChild(child) {
|
|
7
|
+
if (!child || child.killed) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (process.platform === "win32") {
|
|
12
|
+
spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
|
|
13
|
+
stdio: "ignore",
|
|
14
|
+
windowsHide: true
|
|
15
|
+
});
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
child.kill();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function startBatchPreviews(rootDir, packages) {
|
|
23
|
+
const previewPackages = packages.filter((pkg) => {
|
|
24
|
+
return pkg.packageJson.infly?.buildConfigs?.enablePreview !== false;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (previewPackages.length === 0) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log("\n\x1b[32m%s\x1b[0m", "\x1b[42m\x1b[30m DONE \x1b[0m\x1b[32m 项目构建预览,CTRL + C 结束:");
|
|
32
|
+
|
|
33
|
+
const children = previewPackages.map((pkg) => {
|
|
34
|
+
const child = spawnBackground("infly-libs", ["preview", "--no-build"], {
|
|
35
|
+
cwd: path.join(rootDir, pkg.dir),
|
|
36
|
+
env: createBuildContext({
|
|
37
|
+
batchPreview: true
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// console.log(`preview ${pkg.name}: pid ${child.pid}`);
|
|
42
|
+
|
|
43
|
+
child.on("close", (code, signal) => {
|
|
44
|
+
if (code === 0 || signal) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(`preview ${pkg.name} 已退出,code=${code}`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
child.on("error", (error) => {
|
|
52
|
+
console.error(`preview ${pkg.name} 启动失败:${error.message}`);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return child;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const stop = () => {
|
|
59
|
+
children.forEach(killPreviewChild);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
process.on("SIGINT", () => {
|
|
63
|
+
stop();
|
|
64
|
+
process.exit(0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
process.on("SIGTERM", () => {
|
|
68
|
+
stop();
|
|
69
|
+
process.exit(0);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
startBatchPreviews
|
|
75
|
+
};
|