archbyte 0.4.2 → 0.5.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/cli/diff.js DELETED
@@ -1,144 +0,0 @@
1
- import * as path from "path";
2
- import chalk from "chalk";
3
- import { resolveArchitecturePath, loadArchitectureFile, loadRulesConfig, getRuleLevel, getThreshold, } from "./shared.js";
4
- import { checkNoLayerBypass, checkMaxConnections, checkNoOrphans, checkCircularDeps, } from "./validate.js";
5
- /**
6
- * Compare two architecture snapshots and show drift report.
7
- */
8
- export async function handleDiff(options) {
9
- if (!options.baseline) {
10
- console.error(chalk.red("--baseline <path> is required"));
11
- process.exit(1);
12
- }
13
- const baseArch = loadArchitectureFile(path.resolve(process.cwd(), options.baseline));
14
- const currentPath = options.current
15
- ? path.resolve(process.cwd(), options.current)
16
- : resolveArchitecturePath({});
17
- const currentArch = loadArchitectureFile(currentPath);
18
- const projectName = process.cwd().split("/").pop() || "project";
19
- console.log();
20
- console.log(chalk.bold.cyan(`⚡ ArchByte Diff: ${projectName}`));
21
- console.log(chalk.gray(` Baseline: ${options.baseline}`));
22
- console.log(chalk.gray(` Current: ${options.current || ".archbyte/architecture.json"}`));
23
- console.log();
24
- // ── Components ──
25
- const baseNodes = new Set(baseArch.nodes.map((n) => n.id));
26
- const currentNodes = new Set(currentArch.nodes.map((n) => n.id));
27
- const added = [...currentNodes].filter((id) => !baseNodes.has(id));
28
- const removed = [...baseNodes].filter((id) => !currentNodes.has(id));
29
- const currentNodeMap = new Map();
30
- for (const n of currentArch.nodes)
31
- currentNodeMap.set(n.id, n);
32
- const baseNodeMap = new Map();
33
- for (const n of baseArch.nodes)
34
- baseNodeMap.set(n.id, n);
35
- console.log(chalk.bold(" Components:"));
36
- if (added.length === 0 && removed.length === 0) {
37
- console.log(chalk.green(" No changes"));
38
- }
39
- else {
40
- for (const id of added) {
41
- const node = currentNodeMap.get(id);
42
- console.log(chalk.green(` + ${node?.label || id} (${node?.layer || "unknown"})`));
43
- }
44
- for (const id of removed) {
45
- const node = baseNodeMap.get(id);
46
- console.log(chalk.red(` - ${node?.label || id} (${node?.layer || "unknown"})`));
47
- }
48
- }
49
- console.log();
50
- // ── Connections ──
51
- const edgeKey = (e) => `${e.source}->${e.target}`;
52
- const baseEdges = new Set(baseArch.edges.map(edgeKey));
53
- const currentEdges = new Set(currentArch.edges.map(edgeKey));
54
- const addedEdges = currentArch.edges.filter((e) => !baseEdges.has(edgeKey(e)));
55
- const removedEdges = baseArch.edges.filter((e) => !currentEdges.has(edgeKey(e)));
56
- console.log(chalk.bold(" Connections:"));
57
- if (addedEdges.length === 0 && removedEdges.length === 0) {
58
- console.log(chalk.green(" No changes"));
59
- }
60
- else {
61
- for (const e of addedEdges) {
62
- const src = currentNodeMap.get(e.source)?.label || e.source;
63
- const tgt = currentNodeMap.get(e.target)?.label || e.target;
64
- console.log(chalk.green(` + ${src} → ${tgt}`));
65
- }
66
- for (const e of removedEdges) {
67
- const src = baseNodeMap.get(e.source)?.label || e.source;
68
- const tgt = baseNodeMap.get(e.target)?.label || e.target;
69
- console.log(chalk.red(` - ${src} → ${tgt}`));
70
- }
71
- }
72
- console.log();
73
- // ── Density Change ──
74
- const calcDensity = (arch) => {
75
- const n = arch.nodes.length;
76
- const possible = n > 1 ? (n * (n - 1)) / 2 : 1;
77
- return arch.edges.length / possible;
78
- };
79
- const baseDensity = calcDensity(baseArch);
80
- const currentDensity = calcDensity(currentArch);
81
- const densityDelta = currentDensity - baseDensity;
82
- console.log(chalk.bold(" Density:"));
83
- const arrow = densityDelta > 0 ? "↑" : densityDelta < 0 ? "↓" : "=";
84
- const densityColor = Math.abs(densityDelta) < 0.01 ? chalk.gray : densityDelta > 0 ? chalk.yellow : chalk.green;
85
- console.log(densityColor(` ${baseDensity.toFixed(3)} → ${currentDensity.toFixed(3)} (${arrow} ${Math.abs(densityDelta).toFixed(3)})`));
86
- console.log();
87
- // ── Violations Diff ──
88
- const config = loadRulesConfig(options.config);
89
- const getViolations = (arch) => {
90
- const nodes = arch.nodes;
91
- const map = new Map();
92
- for (const n of nodes)
93
- map.set(n.id, n);
94
- const violations = [];
95
- const bypassLevel = getRuleLevel(config, "no-layer-bypass", "error");
96
- if (bypassLevel !== "off")
97
- violations.push(...checkNoLayerBypass(arch, nodes, map, bypassLevel));
98
- const maxLevel = getRuleLevel(config, "max-connections", "warn");
99
- if (maxLevel !== "off")
100
- violations.push(...checkMaxConnections(arch, nodes, maxLevel, getThreshold(config, "max-connections", 6)));
101
- const orphanLevel = getRuleLevel(config, "no-orphans", "warn");
102
- if (orphanLevel !== "off")
103
- violations.push(...checkNoOrphans(arch, nodes, orphanLevel));
104
- const circularLevel = getRuleLevel(config, "no-circular-deps", "error");
105
- if (circularLevel !== "off")
106
- violations.push(...checkCircularDeps(arch, nodes, map, circularLevel));
107
- return violations;
108
- };
109
- const baseViolations = getViolations(baseArch);
110
- const currentViolations = getViolations(currentArch);
111
- const violationKey = (v) => `${v.rule}:${v.message}`;
112
- const baseViolationKeys = new Set(baseViolations.map(violationKey));
113
- const currentViolationKeys = new Set(currentViolations.map(violationKey));
114
- const newViolations = currentViolations.filter((v) => !baseViolationKeys.has(violationKey(v)));
115
- const resolvedViolations = baseViolations.filter((v) => !currentViolationKeys.has(violationKey(v)));
116
- console.log(chalk.bold(" Violations:"));
117
- if (newViolations.length === 0 && resolvedViolations.length === 0) {
118
- console.log(chalk.green(" No changes"));
119
- }
120
- else {
121
- for (const v of newViolations) {
122
- const icon = v.level === "error" ? chalk.red("NEW") : chalk.yellow("NEW");
123
- console.log(` ${icon} [${v.rule}] ${v.message}`);
124
- }
125
- for (const v of resolvedViolations) {
126
- console.log(chalk.green(` RESOLVED [${v.rule}] ${v.message}`));
127
- }
128
- }
129
- // ── Summary ──
130
- console.log();
131
- const totalChanges = added.length + removed.length + addedEdges.length + removedEdges.length;
132
- if (totalChanges === 0 && newViolations.length === 0) {
133
- console.log(chalk.green(" No architectural drift detected."));
134
- }
135
- else {
136
- console.log(` Summary: ${chalk.green(`+${added.length}`)} / ${chalk.red(`-${removed.length}`)} components, ` +
137
- `${chalk.green(`+${addedEdges.length}`)} / ${chalk.red(`-${removedEdges.length}`)} connections, ` +
138
- `${chalk.red(`${newViolations.length} new`)} / ${chalk.green(`${resolvedViolations.length} resolved`)} violations`);
139
- }
140
- console.log();
141
- if (newViolations.some((v) => v.level === "error")) {
142
- process.exit(1);
143
- }
144
- }
@@ -1,18 +0,0 @@
1
- interface PatrolOptions {
2
- diagram?: string;
3
- config?: string;
4
- interval?: string;
5
- onViolation?: string;
6
- daemon?: boolean;
7
- once?: boolean;
8
- watch?: boolean;
9
- history?: boolean;
10
- }
11
- /**
12
- * Run the architecture patrol daemon.
13
- * Each cycle: snapshot → analyze (incremental) → generate → validate → diff
14
- *
15
- * --once: run a single cycle then exit (used by UI "Run Now")
16
- */
17
- export declare function handlePatrol(options: PatrolOptions): Promise<void>;
18
- export {};