impact-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +390 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var import_commander = require("commander");
|
|
28
|
+
|
|
29
|
+
// src/cli/impact.ts
|
|
30
|
+
var import_chalk = __toESM(require("chalk"));
|
|
31
|
+
var import_ora = __toESM(require("ora"));
|
|
32
|
+
|
|
33
|
+
// src/utils/git.ts
|
|
34
|
+
var import_node_child_process = require("child_process");
|
|
35
|
+
function runGitCommand(command, cwd = process.cwd()) {
|
|
36
|
+
try {
|
|
37
|
+
return (0, import_node_child_process.execSync)(`git ${command}`, { cwd, encoding: "utf8" }).trim();
|
|
38
|
+
} catch (error) {
|
|
39
|
+
throw new Error(`\u6267\u884C Git \u547D\u4EE4\u5931\u8D25: git ${command}
|
|
40
|
+
\u9519\u8BEF\u4FE1\u606F: ${error.message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function getChangedFiles(baseBranch, cwd = process.cwd()) {
|
|
44
|
+
try {
|
|
45
|
+
const output = runGitCommand(`diff --name-only ${baseBranch}...HEAD`, cwd);
|
|
46
|
+
if (!output) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return output.split("\n").map((file) => file.trim()).filter(Boolean);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
try {
|
|
52
|
+
const output = runGitCommand(`diff --name-only ${baseBranch} HEAD`, cwd);
|
|
53
|
+
if (!output) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
return output.split("\n").map((file) => file.trim()).filter(Boolean);
|
|
57
|
+
} catch (innerError) {
|
|
58
|
+
throw new Error(`\u65E0\u6CD5\u83B7\u53D6\u4E0E\u57FA\u51C6\u5206\u652F ${baseBranch} \u7684\u5DEE\u5F02\u6587\u4EF6\u5217\u8868\u3002\u8BF7\u786E\u4FDD\u8BE5\u5206\u652F\u5B58\u5728\u3002`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function getCurrentBranch(cwd = process.cwd()) {
|
|
63
|
+
try {
|
|
64
|
+
return runGitCommand("rev-parse --abbrev-ref HEAD", cwd);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return "unknown";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function fetchRemote(cwd = process.cwd()) {
|
|
70
|
+
runGitCommand("fetch --all --prune", cwd);
|
|
71
|
+
}
|
|
72
|
+
function listRemoteBranches(cwd = process.cwd()) {
|
|
73
|
+
try {
|
|
74
|
+
const output = runGitCommand(
|
|
75
|
+
`for-each-ref --format=%(refname:short) refs/remotes/origin/`,
|
|
76
|
+
cwd
|
|
77
|
+
);
|
|
78
|
+
if (!output) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return output.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
82
|
+
} catch {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function getBlobFingerprint(branch, filePath, cwd = process.cwd()) {
|
|
87
|
+
try {
|
|
88
|
+
return runGitCommand(`rev-parse ${branch}:${filePath}`, cwd);
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function isMerged(branch, target, cwd = process.cwd()) {
|
|
94
|
+
try {
|
|
95
|
+
runGitCommand(`merge-base --is-ancestor ${branch} ${target}`, cwd);
|
|
96
|
+
return true;
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/utils/workspace.ts
|
|
103
|
+
var import_node_fs = __toESM(require("fs"));
|
|
104
|
+
var import_node_path = __toESM(require("path"));
|
|
105
|
+
var import_glob = require("glob");
|
|
106
|
+
function getWorkspacePackages(rootDir = process.cwd()) {
|
|
107
|
+
const rootPackageJsonPath = import_node_path.default.join(rootDir, "package.json");
|
|
108
|
+
if (!import_node_fs.default.existsSync(rootPackageJsonPath)) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
const rootPackageJson = JSON.parse(import_node_fs.default.readFileSync(rootPackageJsonPath, "utf8"));
|
|
112
|
+
const workspaces = rootPackageJson.workspaces;
|
|
113
|
+
if (!workspaces) {
|
|
114
|
+
return [{
|
|
115
|
+
name: rootPackageJson.name || "root",
|
|
116
|
+
path: rootDir,
|
|
117
|
+
relativeDir: ".",
|
|
118
|
+
dependencies: []
|
|
119
|
+
}];
|
|
120
|
+
}
|
|
121
|
+
const workspacePatterns = Array.isArray(workspaces) ? workspaces : workspaces.packages || [];
|
|
122
|
+
const packages = [];
|
|
123
|
+
for (const pattern of workspacePatterns) {
|
|
124
|
+
const globPattern = pattern.replace(/\\/g, "/") + "/package.json";
|
|
125
|
+
const packageJsonFiles = (0, import_glob.globSync)(globPattern, { cwd: rootDir });
|
|
126
|
+
for (const packageJsonFile of packageJsonFiles) {
|
|
127
|
+
const fullPath = import_node_path.default.join(rootDir, packageJsonFile);
|
|
128
|
+
const dirPath = import_node_path.default.dirname(fullPath);
|
|
129
|
+
try {
|
|
130
|
+
const pkgContent = JSON.parse(import_node_fs.default.readFileSync(fullPath, "utf8"));
|
|
131
|
+
const allDeps = {
|
|
132
|
+
...pkgContent.dependencies || {},
|
|
133
|
+
...pkgContent.devDependencies || {},
|
|
134
|
+
...pkgContent.peerDependencies || {}
|
|
135
|
+
};
|
|
136
|
+
packages.push({
|
|
137
|
+
name: pkgContent.name,
|
|
138
|
+
path: dirPath,
|
|
139
|
+
relativeDir: import_node_path.default.dirname(packageJsonFile).replace(/\\/g, "/"),
|
|
140
|
+
dependencies: Object.keys(allDeps)
|
|
141
|
+
});
|
|
142
|
+
} catch (e) {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const packageNames = new Set(packages.map((p) => p.name));
|
|
147
|
+
packages.forEach((pkg) => {
|
|
148
|
+
pkg.dependencies = pkg.dependencies.filter((dep) => packageNames.has(dep));
|
|
149
|
+
});
|
|
150
|
+
return packages;
|
|
151
|
+
}
|
|
152
|
+
function findPackageForFile(filePath, packages) {
|
|
153
|
+
const normalizedFilePath = filePath.replace(/\\/g, "/");
|
|
154
|
+
const sortedPackages = [...packages].sort((a, b) => b.relativeDir.length - a.relativeDir.length);
|
|
155
|
+
for (const pkg of sortedPackages) {
|
|
156
|
+
if (pkg.relativeDir === ".") {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (normalizedFilePath.startsWith(pkg.relativeDir + "/")) {
|
|
160
|
+
return pkg;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const rootPkg = packages.find((p) => p.relativeDir === ".");
|
|
164
|
+
return rootPkg || null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/cli/impact.ts
|
|
168
|
+
async function analyzeImpact(options) {
|
|
169
|
+
const { base } = options;
|
|
170
|
+
const spinner = (0, import_ora.default)("\u6B63\u5728\u5206\u6790\u4EE3\u7801\u53D8\u66F4\u5F71\u54CD...").start();
|
|
171
|
+
const rootDir = process.cwd();
|
|
172
|
+
try {
|
|
173
|
+
const currentBranch = getCurrentBranch(rootDir);
|
|
174
|
+
const changedFiles = getChangedFiles(base, rootDir);
|
|
175
|
+
const allPackages = getWorkspacePackages(rootDir);
|
|
176
|
+
spinner.succeed("\u5206\u6790\u5B8C\u6210");
|
|
177
|
+
console.log("\n" + import_chalk.default.bold.cyan("Change Impact Analysis"));
|
|
178
|
+
console.log(import_chalk.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
179
|
+
console.log(`${import_chalk.default.bold("Current branch:")} ${currentBranch}`);
|
|
180
|
+
console.log(`${import_chalk.default.bold("Base:")} ${base}`);
|
|
181
|
+
console.log(import_chalk.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
182
|
+
if (changedFiles.length === 0) {
|
|
183
|
+
console.log(import_chalk.default.green("\n\u6CA1\u6709\u68C0\u6D4B\u5230\u4EFB\u4F55\u4EE3\u7801\u53D8\u66F4\u3002"));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const directlyAffected = /* @__PURE__ */ new Map();
|
|
187
|
+
const filesByPackage = /* @__PURE__ */ new Map();
|
|
188
|
+
for (const file of changedFiles) {
|
|
189
|
+
const pkg = findPackageForFile(file, allPackages);
|
|
190
|
+
if (pkg) {
|
|
191
|
+
directlyAffected.set(pkg.name, pkg);
|
|
192
|
+
if (!filesByPackage.has(pkg.name)) {
|
|
193
|
+
filesByPackage.set(pkg.name, []);
|
|
194
|
+
}
|
|
195
|
+
filesByPackage.get(pkg.name)?.push(file);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const indirectlyAffected = /* @__PURE__ */ new Map();
|
|
199
|
+
allPackages.forEach((pkg) => {
|
|
200
|
+
if (directlyAffected.has(pkg.name)) return;
|
|
201
|
+
const changedDeps = pkg.dependencies.filter((dep) => directlyAffected.has(dep));
|
|
202
|
+
if (changedDeps.length > 0) {
|
|
203
|
+
indirectlyAffected.set(pkg.name, changedDeps);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
console.log(import_chalk.default.bold(`
|
|
207
|
+
Directly changed: ${directlyAffected.size} packages`));
|
|
208
|
+
directlyAffected.forEach((pkg, name) => {
|
|
209
|
+
const files = filesByPackage.get(name) || [];
|
|
210
|
+
console.log(`
|
|
211
|
+
${import_chalk.default.yellow("\u26A0")} ${import_chalk.default.bold(name)} ${import_chalk.default.gray(`(${pkg.relativeDir})`)}`);
|
|
212
|
+
files.slice(0, 5).forEach((file) => {
|
|
213
|
+
console.log(` ${import_chalk.default.gray("-")} ${file}`);
|
|
214
|
+
});
|
|
215
|
+
if (files.length > 5) {
|
|
216
|
+
console.log(` ${import_chalk.default.gray("... \u53CA\u5176\u4ED6 " + (files.length - 5) + " \u4E2A\u6587\u4EF6")}`);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
if (indirectlyAffected.size > 0) {
|
|
220
|
+
console.log(import_chalk.default.bold(`
|
|
221
|
+
Potentially affected dependents: ${indirectlyAffected.size} packages`));
|
|
222
|
+
indirectlyAffected.forEach((deps, name) => {
|
|
223
|
+
console.log(` ${import_chalk.default.cyan("\u21B3")} ${import_chalk.default.bold(name)} ${import_chalk.default.gray(`(depends on: ${deps.join(", ")})`)}`);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
console.log("\n" + import_chalk.default.blue("\u5EFA\u8BAE:"));
|
|
227
|
+
if (indirectlyAffected.size > 0) {
|
|
228
|
+
console.log(` \u8BF7\u901A\u77E5\u4E0A\u8FF0 ${indirectlyAffected.size} \u4E2A\u53D7\u5F71\u54CD\u5305\u7684\u8D1F\u8D23\u4EBA\uFF0C\u68C0\u67E5 API \u53D8\u66F4\u662F\u5426\u4F1A\u5BFC\u81F4\u8FD0\u884C\u65F6\u9519\u8BEF\u3002`);
|
|
229
|
+
} else {
|
|
230
|
+
console.log(` \u8BF7\u91CD\u70B9\u68C0\u67E5\u4E0A\u8FF0 ${directlyAffected.size} \u4E2A\u53D7\u5F71\u54CD\u5305\u7684\u53D8\u66F4\uFF0C\u786E\u4FDD\u5176 API \u517C\u5BB9\u6027\u3002`);
|
|
231
|
+
}
|
|
232
|
+
} catch (error) {
|
|
233
|
+
spinner.fail("\u5206\u6790\u5931\u8D25");
|
|
234
|
+
console.error(import_chalk.default.red(`
|
|
235
|
+
\u9519\u8BEF: ${error.message}`));
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/cli/sync.ts
|
|
241
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
242
|
+
var import_ora2 = __toESM(require("ora"));
|
|
243
|
+
|
|
244
|
+
// src/utils/manifest.ts
|
|
245
|
+
var import_node_fs2 = __toESM(require("fs"));
|
|
246
|
+
var import_node_path2 = __toESM(require("path"));
|
|
247
|
+
var import_glob2 = require("glob");
|
|
248
|
+
var DEFAULT_DIRECTORY_CONVENTIONS = ["src/shared/**", "src/components/**"];
|
|
249
|
+
function loadConfig(rootDir) {
|
|
250
|
+
const rcPath = import_node_path2.default.join(rootDir, ".impactrc");
|
|
251
|
+
if (!import_node_fs2.default.existsSync(rcPath)) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
return JSON.parse(import_node_fs2.default.readFileSync(rcPath, "utf8"));
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function resolvePublicComponents(rootDir = process.cwd()) {
|
|
261
|
+
const config = loadConfig(rootDir);
|
|
262
|
+
let patterns;
|
|
263
|
+
let source;
|
|
264
|
+
if (config && Array.isArray(config.publicComponents) && config.publicComponents.length > 0) {
|
|
265
|
+
patterns = config.publicComponents;
|
|
266
|
+
source = "config";
|
|
267
|
+
} else {
|
|
268
|
+
patterns = DEFAULT_DIRECTORY_CONVENTIONS;
|
|
269
|
+
source = "directory";
|
|
270
|
+
}
|
|
271
|
+
const components = [];
|
|
272
|
+
const seen = /* @__PURE__ */ new Set();
|
|
273
|
+
for (const pattern of patterns) {
|
|
274
|
+
const normalized = pattern.replace(/\\/g, "/");
|
|
275
|
+
for (const file of (0, import_glob2.globSync)(normalized, { cwd: rootDir, nodir: true })) {
|
|
276
|
+
const rel = file.replace(/\\/g, "/");
|
|
277
|
+
if (!seen.has(rel)) {
|
|
278
|
+
seen.add(rel);
|
|
279
|
+
components.push({ path: rel, source });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return components;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/cli/sync.ts
|
|
287
|
+
async function analyzeSync(options) {
|
|
288
|
+
const { base } = options;
|
|
289
|
+
const spinner = (0, import_ora2.default)("\u6B63\u5728\u68C0\u6D4B\u5206\u652F\u540C\u6B65\u72B6\u6001...").start();
|
|
290
|
+
const rootDir = process.cwd();
|
|
291
|
+
try {
|
|
292
|
+
const components = resolvePublicComponents(rootDir);
|
|
293
|
+
if (components.length === 0) {
|
|
294
|
+
spinner.warn("\u672A\u627E\u5230\u516C\u5171\u7EC4\u4EF6\u6E05\u5355\uFF0C\u8BF7\u914D\u7F6E .impactrc \u7684 publicComponents \u6216\u4F7F\u7528\u76EE\u5F55\u7EA6\u5B9A");
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
spinner.text = "\u62C9\u53D6\u8FDC\u7AEF...";
|
|
298
|
+
fetchRemote(rootDir);
|
|
299
|
+
const currentBranch = getCurrentBranch(rootDir);
|
|
300
|
+
spinner.text = "\u679A\u4E3E\u5019\u9009\u5206\u652F...";
|
|
301
|
+
const branches = listRemoteBranches(rootDir);
|
|
302
|
+
const excluded = /* @__PURE__ */ new Set([
|
|
303
|
+
base,
|
|
304
|
+
"origin/master",
|
|
305
|
+
"origin/main",
|
|
306
|
+
"origin/HEAD",
|
|
307
|
+
currentBranch,
|
|
308
|
+
`origin/${currentBranch}`
|
|
309
|
+
]);
|
|
310
|
+
const candidates = branches.filter((b) => !excluded.has(b));
|
|
311
|
+
spinner.text = "\u6BD4\u5BF9\u5185\u5BB9\u6307\u7EB9...";
|
|
312
|
+
const results = [];
|
|
313
|
+
for (const component of components) {
|
|
314
|
+
const baseline = getBlobFingerprint(base, component.path, rootDir);
|
|
315
|
+
if (!baseline) {
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const warnings = [];
|
|
319
|
+
for (const branch of candidates) {
|
|
320
|
+
const fp = getBlobFingerprint(branch, component.path, rootDir);
|
|
321
|
+
if (!fp || fp === baseline) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (isMerged(branch, base, rootDir)) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
warnings.push({ branch, baselineFingerprint: baseline, branchFingerprint: fp });
|
|
328
|
+
}
|
|
329
|
+
if (warnings.length > 0) {
|
|
330
|
+
results.push({ component, warnings });
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
spinner.succeed("\u68C0\u6D4B\u5B8C\u6210");
|
|
334
|
+
render(results, base, components.length);
|
|
335
|
+
if (results.length > 0) {
|
|
336
|
+
process.exitCode = 1;
|
|
337
|
+
}
|
|
338
|
+
} catch (error) {
|
|
339
|
+
spinner.fail("\u68C0\u6D4B\u5931\u8D25");
|
|
340
|
+
console.error(import_chalk2.default.red(`
|
|
341
|
+
\u9519\u8BEF: ${error.message}`));
|
|
342
|
+
process.exit(1);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function render(results, base, total) {
|
|
346
|
+
console.log("\n" + import_chalk2.default.bold.magenta("Branch Sync Status"));
|
|
347
|
+
console.log(import_chalk2.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
348
|
+
console.log(`${import_chalk2.default.bold("Baseline:")} ${base}`);
|
|
349
|
+
console.log(`${import_chalk2.default.bold("Components:")} ${total}`);
|
|
350
|
+
console.log(import_chalk2.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
351
|
+
if (results.length === 0) {
|
|
352
|
+
console.log(import_chalk2.default.green("\n\u6240\u6709\u516C\u5171\u7EC4\u4EF6\u5728\u5404\u672A\u5408\u5165\u5206\u652F\u4E0A\u5747\u65E0\u6539\u52A8\uFF0C\u540C\u6B65\u6B63\u5E38\u3002"));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
console.log(
|
|
356
|
+
import_chalk2.default.bold.yellow(`
|
|
357
|
+
\u53D1\u73B0 ${results.length} \u4E2A\u516C\u5171\u7EC4\u4EF6\u5728\u672A\u5408\u5165\u5206\u652F\u4E0A\u88AB\u6539\u52A8\uFF1A`)
|
|
358
|
+
);
|
|
359
|
+
for (const r of results) {
|
|
360
|
+
console.log(
|
|
361
|
+
`
|
|
362
|
+
${import_chalk2.default.yellow("\u26A0")} ${import_chalk2.default.bold(r.component.path)} ${import_chalk2.default.gray(`(${r.component.source})`)}`
|
|
363
|
+
);
|
|
364
|
+
for (const w of r.warnings) {
|
|
365
|
+
console.log(` ${import_chalk2.default.red("\u25CF")} ${w.branch} ${import_chalk2.default.gray(`\u2014 \u5DF2\u6539\u52A8\u4F46\u672A\u5408\u5165 ${base}`)}`);
|
|
366
|
+
console.log(
|
|
367
|
+
` ${import_chalk2.default.gray(
|
|
368
|
+
`\u6307\u7EB9 ${w.baselineFingerprint.slice(0, 8)} \u2192 ${w.branchFingerprint.slice(0, 8)}`
|
|
369
|
+
)}`
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
console.log("\n" + import_chalk2.default.blue("\u5EFA\u8BAE:"));
|
|
374
|
+
console.log(" \u8BF7\u63D0\u9192\u4E0A\u8FF0\u5206\u652F\u7684\u8D1F\u8D23\u4EBA\u5C3D\u5FEB\u5408\u5E76\uFF0C\u6216\u786E\u8BA4\u6539\u52A8\u662F\u5426\u5E94\u540C\u6B65\u5230\u4F60\u6240\u4F9D\u8D56\u7684\u7248\u672C\u3002");
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/index.ts
|
|
378
|
+
function main() {
|
|
379
|
+
const program = new import_commander.Command();
|
|
380
|
+
program.name("impact").description("\u5171\u4EAB\u7EC4\u4EF6\u53D8\u66F4\u5F71\u54CD\u5206\u6790\u4E0E\u5206\u652F\u540C\u6B65\u68C0\u67E5\u5DE5\u5177").version("0.1.0");
|
|
381
|
+
program.command("sync").description("\u53CD\u5411\u68C0\u6D4B\uFF1A\u68C0\u67E5\u516C\u5171\u7EC4\u4EF6\u5728\u54EA\u4E9B\u672A\u5408\u5165\u5206\u652F\u4E0A\u88AB\u6539\u52A8").option("-b, --base <branch>", "\u57FA\u51C6\u5206\u652F", "origin/develop").action((options) => {
|
|
382
|
+
analyzeSync({ base: options.base });
|
|
383
|
+
});
|
|
384
|
+
program.command("impact").description("\u6B63\u5411\u68C0\u6D4B\uFF1A\u8BC6\u522B\u5F53\u524D\u53D8\u66F4\u53D7\u5F71\u54CD\u7684 Workspace Packages").option("-b, --base <branch>", "\u57FA\u51C6\u5206\u652F\uFF0C\u7528\u4E8E\u5BF9\u6BD4\u53D8\u66F4", "origin/develop").action((options) => {
|
|
385
|
+
analyzeImpact(options);
|
|
386
|
+
});
|
|
387
|
+
program.parse(process.argv);
|
|
388
|
+
}
|
|
389
|
+
main();
|
|
390
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "impact-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "共享组件变更影响分析与分支同步检查工具",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"impact": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsup",
|
|
11
|
+
"dev": "tsup --watch",
|
|
12
|
+
"check": "node ./dist/index.js check",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "cwj",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/index.js"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"registry": "https://registry.npmjs.org"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
|
+
"commander": "^15.0.0",
|
|
28
|
+
"glob": "^11.0.0",
|
|
29
|
+
"ora": "^5.4.1"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/chalk": "^2.2.0",
|
|
33
|
+
"@types/glob": "^8.1.0",
|
|
34
|
+
"@types/node": "^22.0.0",
|
|
35
|
+
"@types/ora": "^3.2.0",
|
|
36
|
+
"tsup": "^8.0.0",
|
|
37
|
+
"typescript": "^5.0.0"
|
|
38
|
+
}
|
|
39
|
+
}
|