@lifesavertech/archguard-cli 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +26 -18
- package/dist/style.d.ts +5 -0
- package/dist/style.js +20 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -34,9 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
return result;
|
|
35
35
|
};
|
|
36
36
|
})();
|
|
37
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
38
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
39
|
-
};
|
|
40
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
38
|
exports.initializeArchguard = initializeArchguard;
|
|
42
39
|
exports.detectReactTypeScript = detectReactTypeScript;
|
|
@@ -47,15 +44,26 @@ exports.resolveImportPath = resolveImportPath;
|
|
|
47
44
|
const commander_1 = require("commander");
|
|
48
45
|
const fs = __importStar(require("fs"));
|
|
49
46
|
const path = __importStar(require("path"));
|
|
50
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
51
47
|
const archguard_core_1 = require("@lifesavertech/archguard-core");
|
|
52
48
|
const archguard_rules_react_1 = require("@lifesavertech/archguard-rules-react");
|
|
53
49
|
const archguard_guidance_1 = require("@lifesavertech/archguard-guidance");
|
|
54
50
|
const presets_1 = require("./presets");
|
|
51
|
+
const style = __importStar(require("./style"));
|
|
52
|
+
const MIN_NODE_MAJOR = 20;
|
|
53
|
+
const nodeMajor = Number(process.versions.node.split(".")[0] ?? "0");
|
|
54
|
+
if (nodeMajor < MIN_NODE_MAJOR) {
|
|
55
|
+
console.error(`Error: ArchGuard requires Node.js >=${MIN_NODE_MAJOR}. Current: ${process.versions.node}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
55
58
|
const program = new commander_1.Command();
|
|
56
59
|
const DEFAULT_BASELINE_PATH = ".archguard-baseline.json";
|
|
57
60
|
const SARIF_SCHEMA_URL = "https://json.schemastore.org/sarif-2.1.0.json";
|
|
58
|
-
|
|
61
|
+
function readCliVersion() {
|
|
62
|
+
const packageJsonPath = path.join(__dirname, "..", "package.json");
|
|
63
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
64
|
+
return packageJson.version ?? "0.0.0";
|
|
65
|
+
}
|
|
66
|
+
program.name("archguard").description("Architecture guard for React + TypeScript projects").version(readCliVersion());
|
|
59
67
|
program
|
|
60
68
|
.command("init")
|
|
61
69
|
.description("Initialize archguard in the current project")
|
|
@@ -63,10 +71,10 @@ program
|
|
|
63
71
|
.action((options) => {
|
|
64
72
|
try {
|
|
65
73
|
initializeArchguard(options.preset);
|
|
66
|
-
console.log(
|
|
74
|
+
console.log(style.green("✓ archguard initialized successfully"));
|
|
67
75
|
}
|
|
68
76
|
catch (error) {
|
|
69
|
-
console.error(
|
|
77
|
+
console.error(style.red(`✗ Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
70
78
|
process.exit(1);
|
|
71
79
|
}
|
|
72
80
|
});
|
|
@@ -99,7 +107,7 @@ program
|
|
|
99
107
|
}
|
|
100
108
|
}
|
|
101
109
|
catch (error) {
|
|
102
|
-
console.error(
|
|
110
|
+
console.error(style.red(`✗ Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
103
111
|
process.exit(1);
|
|
104
112
|
}
|
|
105
113
|
});
|
|
@@ -270,7 +278,7 @@ function installPreCommitHook(cwd) {
|
|
|
270
278
|
}
|
|
271
279
|
const preCommitPath = path.join(gitHooksDir, "pre-commit");
|
|
272
280
|
if (fs.existsSync(preCommitPath)) {
|
|
273
|
-
console.log(
|
|
281
|
+
console.log(style.yellow("! Existing pre-commit hook detected. ArchGuard did not overwrite it; add the check command manually."));
|
|
274
282
|
return;
|
|
275
283
|
}
|
|
276
284
|
// Use the installed CLI name so hooks keep working after npm install or global linking.
|
|
@@ -312,7 +320,7 @@ function collectViolations(scanRoot, options = {}) {
|
|
|
312
320
|
allViolations.push(...result.violations);
|
|
313
321
|
}
|
|
314
322
|
if (options.verbose) {
|
|
315
|
-
console.error(
|
|
323
|
+
console.error(style.gray(`ArchGuard scanned ${sourceFiles.length} file(s) from ${path.relative(scanRoot, scanRoot) || "."} using ${normalizeViolationPath(configPath, scanRoot)}`));
|
|
316
324
|
}
|
|
317
325
|
return {
|
|
318
326
|
violations: sortViolations(allViolations.map((violation) => ({
|
|
@@ -324,7 +332,7 @@ function collectViolations(scanRoot, options = {}) {
|
|
|
324
332
|
}
|
|
325
333
|
function printViolations(violations) {
|
|
326
334
|
for (const violation of violations) {
|
|
327
|
-
console.log(
|
|
335
|
+
console.log(style.yellow(`${violation.file}:${violation.line}:${violation.column}`) +
|
|
328
336
|
` - ${violation.message} (${violation.rule})`);
|
|
329
337
|
}
|
|
330
338
|
}
|
|
@@ -338,24 +346,24 @@ function printCheckSummary(summary, format) {
|
|
|
338
346
|
return;
|
|
339
347
|
}
|
|
340
348
|
if (summary.mode === "update-baseline") {
|
|
341
|
-
console.log(
|
|
349
|
+
console.log(style.green(`✓ Wrote ${summary.violations.length} violation(s) to baseline ${summary.baselinePath}`));
|
|
342
350
|
return;
|
|
343
351
|
}
|
|
344
352
|
if (summary.mode === "baseline" && !summary.passed) {
|
|
345
|
-
console.log(
|
|
353
|
+
console.log(style.red(`\n✗ Found ${summary.violationCount} new violation(s) (${summary.suppressedViolationCount} matched baseline):\n`));
|
|
346
354
|
printViolations(summary.violations);
|
|
347
355
|
return;
|
|
348
356
|
}
|
|
349
357
|
if (summary.mode === "baseline" && summary.suppressedViolationCount > 0) {
|
|
350
|
-
console.log(
|
|
358
|
+
console.log(style.green(`✓ No new violations. ${summary.suppressedViolationCount} violation(s) matched baseline ${summary.baselinePath}`));
|
|
351
359
|
return;
|
|
352
360
|
}
|
|
353
361
|
if (!summary.passed) {
|
|
354
|
-
console.log(
|
|
362
|
+
console.log(style.red(`\n✗ Found ${summary.violationCount} violation(s):\n`));
|
|
355
363
|
printViolations(summary.violations);
|
|
356
364
|
return;
|
|
357
365
|
}
|
|
358
|
-
console.log(
|
|
366
|
+
console.log(style.green("✓ All checks passed"));
|
|
359
367
|
}
|
|
360
368
|
function normalizeOptionalString(optionValue) {
|
|
361
369
|
if (optionValue === undefined) {
|
|
@@ -375,9 +383,9 @@ function resolveScanRoot(cwd, projectRoot) {
|
|
|
375
383
|
return scanRoot;
|
|
376
384
|
}
|
|
377
385
|
function printUnresolvedImports(unresolvedImports, scanRoot) {
|
|
378
|
-
console.error(
|
|
386
|
+
console.error(style.yellow(`\nUnresolved imports (${unresolvedImports.length}):`));
|
|
379
387
|
for (const unresolvedImport of unresolvedImports) {
|
|
380
|
-
console.error(
|
|
388
|
+
console.error(style.yellow(` ${normalizeViolationPath(unresolvedImport.file, scanRoot)} -> ${unresolvedImport.importPath}`));
|
|
381
389
|
}
|
|
382
390
|
}
|
|
383
391
|
function normalizeOptionalPath(optionValue) {
|
package/dist/style.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Terminal styling via Node built-ins (no ESM-only deps in CJS output). */
|
|
2
|
+
export declare function green(text: string): string;
|
|
3
|
+
export declare function red(text: string): string;
|
|
4
|
+
export declare function yellow(text: string): string;
|
|
5
|
+
export declare function gray(text: string): string;
|
package/dist/style.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Terminal styling via Node built-ins (no ESM-only deps in CJS output). */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.green = green;
|
|
5
|
+
exports.red = red;
|
|
6
|
+
exports.yellow = yellow;
|
|
7
|
+
exports.gray = gray;
|
|
8
|
+
const node_util_1 = require("node:util");
|
|
9
|
+
function green(text) {
|
|
10
|
+
return (0, node_util_1.styleText)("green", text);
|
|
11
|
+
}
|
|
12
|
+
function red(text) {
|
|
13
|
+
return (0, node_util_1.styleText)("red", text);
|
|
14
|
+
}
|
|
15
|
+
function yellow(text) {
|
|
16
|
+
return (0, node_util_1.styleText)("yellow", text);
|
|
17
|
+
}
|
|
18
|
+
function gray(text) {
|
|
19
|
+
return (0, node_util_1.styleText)("gray", text);
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifesavertech/archguard-cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Command-line interface for ArchGuard",
|
|
5
5
|
"bin": {
|
|
6
6
|
"archguard": "dist/index.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
|
-
"dist"
|
|
9
|
+
"dist",
|
|
10
|
+
"package.json"
|
|
10
11
|
],
|
|
11
12
|
"engines": {
|
|
12
13
|
"node": ">=20"
|
|
@@ -31,8 +32,7 @@
|
|
|
31
32
|
"@lifesavertech/archguard-guidance": "2.0.1",
|
|
32
33
|
"@lifesavertech/archguard-core": "2.0.1",
|
|
33
34
|
"@lifesavertech/archguard-rules-react": "2.0.1",
|
|
34
|
-
"commander": "^11.0.0"
|
|
35
|
-
"chalk": "^5.3.0"
|
|
35
|
+
"commander": "^11.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.0.0"
|