@defai.digital/ax-cli 3.4.6 → 3.5.4
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/LICENSE +2 -6
- package/README.md +109 -2
- package/dist/analyzers/ast/index.d.ts +9 -0
- package/dist/analyzers/ast/index.js +10 -0
- package/dist/analyzers/ast/index.js.map +1 -0
- package/dist/analyzers/ast/node-helpers.d.ts +81 -0
- package/dist/analyzers/ast/node-helpers.js +128 -0
- package/dist/analyzers/ast/node-helpers.js.map +1 -0
- package/dist/analyzers/ast/parser.d.ts +59 -0
- package/dist/analyzers/ast/parser.js +293 -0
- package/dist/analyzers/ast/parser.js.map +1 -0
- package/dist/analyzers/ast/traverser.d.ts +67 -0
- package/dist/analyzers/ast/traverser.js +156 -0
- package/dist/analyzers/ast/traverser.js.map +1 -0
- package/dist/analyzers/ast/types.d.ts +107 -0
- package/dist/analyzers/ast/types.js +7 -0
- package/dist/analyzers/ast/types.js.map +1 -0
- package/dist/analyzers/best-practices/index.d.ts +10 -0
- package/dist/analyzers/best-practices/index.js +11 -0
- package/dist/analyzers/best-practices/index.js.map +1 -0
- package/dist/analyzers/code-smells/base-smell-detector.d.ts +30 -0
- package/dist/analyzers/code-smells/base-smell-detector.js +44 -0
- package/dist/analyzers/code-smells/base-smell-detector.js.map +1 -0
- package/dist/analyzers/code-smells/code-smell-analyzer.d.ts +30 -0
- package/dist/analyzers/code-smells/code-smell-analyzer.js +167 -0
- package/dist/analyzers/code-smells/code-smell-analyzer.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.js +66 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/dead-code-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/dead-code-detector.js +53 -0
- package/dist/analyzers/code-smells/detectors/dead-code-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js +51 -0
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.js +64 -0
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js +56 -0
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/large-class-detector.d.ts +13 -0
- package/dist/analyzers/code-smells/detectors/large-class-detector.js +58 -0
- package/dist/analyzers/code-smells/detectors/large-class-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/long-method-detector.d.ts +12 -0
- package/dist/analyzers/code-smells/detectors/long-method-detector.js +52 -0
- package/dist/analyzers/code-smells/detectors/long-method-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.d.ts +12 -0
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js +50 -0
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.d.ts +12 -0
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js +54 -0
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.d.ts +13 -0
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js +71 -0
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js.map +1 -0
- package/dist/analyzers/code-smells/index.d.ts +16 -0
- package/dist/analyzers/code-smells/index.js +19 -0
- package/dist/analyzers/code-smells/index.js.map +1 -0
- package/dist/analyzers/code-smells/types.d.ts +82 -0
- package/dist/analyzers/code-smells/types.js +30 -0
- package/dist/analyzers/code-smells/types.js.map +1 -0
- package/dist/analyzers/dependency/circular-detector.d.ts +17 -0
- package/dist/analyzers/dependency/circular-detector.js +71 -0
- package/dist/analyzers/dependency/circular-detector.js.map +1 -0
- package/dist/analyzers/dependency/coupling-calculator.d.ts +24 -0
- package/dist/analyzers/dependency/coupling-calculator.js +86 -0
- package/dist/analyzers/dependency/coupling-calculator.js.map +1 -0
- package/dist/analyzers/dependency/dependency-analyzer.d.ts +40 -0
- package/dist/analyzers/dependency/dependency-analyzer.js +214 -0
- package/dist/analyzers/dependency/dependency-analyzer.js.map +1 -0
- package/dist/analyzers/dependency/dependency-graph.d.ts +57 -0
- package/dist/analyzers/dependency/dependency-graph.js +186 -0
- package/dist/analyzers/dependency/dependency-graph.js.map +1 -0
- package/dist/analyzers/dependency/index.d.ts +8 -0
- package/dist/analyzers/dependency/index.js +8 -0
- package/dist/analyzers/dependency/index.js.map +1 -0
- package/dist/analyzers/dependency/types.d.ts +105 -0
- package/dist/analyzers/dependency/types.js +5 -0
- package/dist/analyzers/dependency/types.js.map +1 -0
- package/dist/analyzers/git/churn-calculator.d.ts +34 -0
- package/dist/analyzers/git/churn-calculator.js +214 -0
- package/dist/analyzers/git/churn-calculator.js.map +1 -0
- package/dist/analyzers/git/git-analyzer.d.ts +19 -0
- package/dist/analyzers/git/git-analyzer.js +71 -0
- package/dist/analyzers/git/git-analyzer.js.map +1 -0
- package/dist/analyzers/git/hotspot-detector.d.ts +34 -0
- package/dist/analyzers/git/hotspot-detector.js +170 -0
- package/dist/analyzers/git/hotspot-detector.js.map +1 -0
- package/dist/analyzers/git/index.d.ts +7 -0
- package/dist/analyzers/git/index.js +7 -0
- package/dist/analyzers/git/index.js.map +1 -0
- package/dist/analyzers/git/types.d.ts +88 -0
- package/dist/analyzers/git/types.js +5 -0
- package/dist/analyzers/git/types.js.map +1 -0
- package/dist/analyzers/metrics/halstead-calculator.d.ts +30 -0
- package/dist/analyzers/metrics/halstead-calculator.js +150 -0
- package/dist/analyzers/metrics/halstead-calculator.js.map +1 -0
- package/dist/analyzers/metrics/index.d.ts +9 -0
- package/dist/analyzers/metrics/index.js +9 -0
- package/dist/analyzers/metrics/index.js.map +1 -0
- package/dist/analyzers/metrics/maintainability-calculator.d.ts +17 -0
- package/dist/analyzers/metrics/maintainability-calculator.js +46 -0
- package/dist/analyzers/metrics/maintainability-calculator.js.map +1 -0
- package/dist/analyzers/metrics/metrics-analyzer.d.ts +32 -0
- package/dist/analyzers/metrics/metrics-analyzer.js +140 -0
- package/dist/analyzers/metrics/metrics-analyzer.js.map +1 -0
- package/dist/analyzers/metrics/types.d.ts +67 -0
- package/dist/analyzers/metrics/types.js +5 -0
- package/dist/analyzers/metrics/types.js.map +1 -0
- package/dist/analyzers/security/base-detector.d.ts +58 -0
- package/dist/analyzers/security/base-detector.js +104 -0
- package/dist/analyzers/security/base-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/command-injection-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/command-injection-detector.js +84 -0
- package/dist/analyzers/security/detectors/command-injection-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/hardcoded-secrets-detector.d.ts +16 -0
- package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js +140 -0
- package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/insecure-deserialization-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/insecure-deserialization-detector.js +109 -0
- package/dist/analyzers/security/detectors/insecure-deserialization-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/insecure-random-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/insecure-random-detector.js +61 -0
- package/dist/analyzers/security/detectors/insecure-random-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/path-traversal-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/path-traversal-detector.js +82 -0
- package/dist/analyzers/security/detectors/path-traversal-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/sql-injection-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/sql-injection-detector.js +88 -0
- package/dist/analyzers/security/detectors/sql-injection-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/weak-crypto-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/weak-crypto-detector.js +104 -0
- package/dist/analyzers/security/detectors/weak-crypto-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/xss-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/xss-detector.js +90 -0
- package/dist/analyzers/security/detectors/xss-detector.js.map +1 -0
- package/dist/analyzers/security/index.d.ts +16 -0
- package/dist/analyzers/security/index.js +18 -0
- package/dist/analyzers/security/index.js.map +1 -0
- package/dist/analyzers/security/security-analyzer.d.ts +38 -0
- package/dist/analyzers/security/security-analyzer.js +215 -0
- package/dist/analyzers/security/security-analyzer.js.map +1 -0
- package/dist/analyzers/security/types.d.ts +95 -0
- package/dist/analyzers/security/types.js +7 -0
- package/dist/analyzers/security/types.js.map +1 -0
- package/dist/hooks/use-enhanced-input.d.ts +0 -1
- package/dist/hooks/use-enhanced-input.js.map +1 -1
- package/dist/index.js +0 -0
- package/dist/mcp/validation.js +12 -6
- package/dist/mcp/validation.js.map +1 -1
- package/dist/tools/analysis-tools.d.ts +73 -0
- package/dist/tools/analysis-tools.js +422 -0
- package/dist/tools/analysis-tools.js.map +1 -0
- package/dist/tools/bash.js +2 -1
- package/dist/tools/bash.js.map +1 -1
- package/dist/ui/components/toast-notification.js +0 -1
- package/dist/ui/components/toast-notification.js.map +1 -1
- package/dist/ui/components/welcome-panel.js +1 -1
- package/dist/ui/components/welcome-panel.js.map +1 -1
- package/dist/ui/hooks/use-input-history.d.ts +9 -0
- package/dist/ui/hooks/use-input-history.js +117 -0
- package/dist/ui/hooks/use-input-history.js.map +1 -0
- package/dist/utils/parallel-analyzer.js +30 -17
- package/dist/utils/parallel-analyzer.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +5 -5
- package/vitest.config.ts +1 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
- package/automatosx.config.json +0 -333
- package/config/messages.yaml +0 -75
- package/config/models.yaml +0 -66
- package/config/prompts.yaml +0 -156
- package/config/settings.yaml +0 -86
- package/dist/commands/weather.d.ts +0 -8
- package/dist/commands/weather.js +0 -160
- package/dist/commands/weather.js.map +0 -1
- package/dist/grok/client.d.ts +0 -144
- package/dist/grok/client.js +0 -237
- package/dist/grok/client.js.map +0 -1
- package/dist/grok/tools.d.ts +0 -8
- package/dist/grok/tools.js +0 -318
- package/dist/grok/tools.js.map +0 -1
- package/dist/grok/types.d.ts +0 -291
- package/dist/grok/types.js +0 -127
- package/dist/grok/types.js.map +0 -1
- package/dist/tools/morph-editor.d.ts +0 -36
- package/dist/tools/morph-editor.js +0 -308
- package/dist/tools/morph-editor.js.map +0 -1
- package/dist/ui/components/session-recovery.d.ts +0 -12
- package/dist/ui/components/session-recovery.js +0 -93
- package/dist/ui/components/session-recovery.js.map +0 -1
- package/dist/utils/model-config.d.ts +0 -28
- package/dist/utils/model-config.js +0 -43
- package/dist/utils/model-config.js.map +0 -1
- package/dist/utils/tool-helpers.d.ts +0 -25
- package/dist/utils/tool-helpers.js +0 -79
- package/dist/utils/tool-helpers.js.map +0 -1
- package/packages/schemas/dist/index.d.ts +0 -14
- package/packages/schemas/dist/index.d.ts.map +0 -1
- package/packages/schemas/dist/index.js +0 -19
- package/packages/schemas/dist/index.js.map +0 -1
- package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
- package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/brand-types.js +0 -243
- package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
- package/packages/schemas/dist/public/core/enums.d.ts +0 -227
- package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/enums.js +0 -222
- package/packages/schemas/dist/public/core/enums.js.map +0 -1
- package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
- package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/id-types.js +0 -136
- package/packages/schemas/dist/public/core/id-types.js.map +0 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Graph Implementation
|
|
3
|
+
*
|
|
4
|
+
* Adjacency list-based directed graph for file dependencies
|
|
5
|
+
*/
|
|
6
|
+
export class DependencyGraph {
|
|
7
|
+
nodes;
|
|
8
|
+
adjacencyList;
|
|
9
|
+
reverseAdjacencyList; // For efficient afferent lookup
|
|
10
|
+
constructor() {
|
|
11
|
+
this.nodes = new Map();
|
|
12
|
+
this.adjacencyList = new Map();
|
|
13
|
+
this.reverseAdjacencyList = new Map();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Add node to graph
|
|
17
|
+
*/
|
|
18
|
+
addNode(node) {
|
|
19
|
+
this.nodes.set(node.filePath, node);
|
|
20
|
+
if (!this.adjacencyList.has(node.filePath)) {
|
|
21
|
+
this.adjacencyList.set(node.filePath, new Set());
|
|
22
|
+
}
|
|
23
|
+
if (!this.reverseAdjacencyList.has(node.filePath)) {
|
|
24
|
+
this.reverseAdjacencyList.set(node.filePath, new Set());
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Add directed edge from -> to
|
|
29
|
+
*/
|
|
30
|
+
addEdge(from, to) {
|
|
31
|
+
// Ensure nodes exist
|
|
32
|
+
if (!this.adjacencyList.has(from)) {
|
|
33
|
+
this.adjacencyList.set(from, new Set());
|
|
34
|
+
}
|
|
35
|
+
if (!this.reverseAdjacencyList.has(to)) {
|
|
36
|
+
this.reverseAdjacencyList.set(to, new Set());
|
|
37
|
+
}
|
|
38
|
+
// Add edge
|
|
39
|
+
this.adjacencyList.get(from).add(to);
|
|
40
|
+
this.reverseAdjacencyList.get(to).add(from);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get node by file path
|
|
44
|
+
*/
|
|
45
|
+
getNode(file) {
|
|
46
|
+
return this.nodes.get(file);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get all nodes
|
|
50
|
+
*/
|
|
51
|
+
getNodes() {
|
|
52
|
+
return Array.from(this.nodes.values());
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get afferent dependencies (files that depend on this file)
|
|
56
|
+
*/
|
|
57
|
+
getAfferentDependencies(file) {
|
|
58
|
+
const deps = this.reverseAdjacencyList.get(file);
|
|
59
|
+
return deps ? Array.from(deps) : [];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get efferent dependencies (files this file depends on)
|
|
63
|
+
*/
|
|
64
|
+
getEfferentDependencies(file) {
|
|
65
|
+
const deps = this.adjacencyList.get(file);
|
|
66
|
+
return deps ? Array.from(deps) : [];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get total number of edges
|
|
70
|
+
*/
|
|
71
|
+
getTotalEdges() {
|
|
72
|
+
let total = 0;
|
|
73
|
+
for (const deps of this.adjacencyList.values()) {
|
|
74
|
+
total += deps.size;
|
|
75
|
+
}
|
|
76
|
+
return total;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if path exists from -> to using BFS
|
|
80
|
+
*/
|
|
81
|
+
hasPath(from, to) {
|
|
82
|
+
if (from === to)
|
|
83
|
+
return true;
|
|
84
|
+
const visited = new Set();
|
|
85
|
+
const queue = [from];
|
|
86
|
+
while (queue.length > 0) {
|
|
87
|
+
const current = queue.shift();
|
|
88
|
+
if (current === to)
|
|
89
|
+
return true;
|
|
90
|
+
if (visited.has(current))
|
|
91
|
+
continue;
|
|
92
|
+
visited.add(current);
|
|
93
|
+
const neighbors = this.adjacencyList.get(current) || new Set();
|
|
94
|
+
for (const neighbor of neighbors) {
|
|
95
|
+
if (!visited.has(neighbor)) {
|
|
96
|
+
queue.push(neighbor);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Topological sort using DFS
|
|
104
|
+
* Returns sorted list and whether cycle was detected
|
|
105
|
+
*/
|
|
106
|
+
topologicalSort() {
|
|
107
|
+
const visited = new Set();
|
|
108
|
+
const recursionStack = new Set();
|
|
109
|
+
const sorted = [];
|
|
110
|
+
let hasCycle = false;
|
|
111
|
+
const dfs = (node) => {
|
|
112
|
+
if (recursionStack.has(node)) {
|
|
113
|
+
hasCycle = true;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (visited.has(node))
|
|
117
|
+
return;
|
|
118
|
+
visited.add(node);
|
|
119
|
+
recursionStack.add(node);
|
|
120
|
+
const neighbors = this.adjacencyList.get(node) || new Set();
|
|
121
|
+
for (const neighbor of neighbors) {
|
|
122
|
+
dfs(neighbor);
|
|
123
|
+
}
|
|
124
|
+
recursionStack.delete(node);
|
|
125
|
+
sorted.unshift(node); // Add to front for reverse post-order
|
|
126
|
+
};
|
|
127
|
+
// Visit all nodes
|
|
128
|
+
for (const node of this.nodes.keys()) {
|
|
129
|
+
if (!visited.has(node)) {
|
|
130
|
+
dfs(node);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { sorted, hasCycle };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get strongly connected components using Tarjan's algorithm
|
|
137
|
+
* (Used for circular dependency detection)
|
|
138
|
+
*/
|
|
139
|
+
getStronglyConnectedComponents() {
|
|
140
|
+
const index = new Map();
|
|
141
|
+
const lowLink = new Map();
|
|
142
|
+
const onStack = new Set();
|
|
143
|
+
const stack = [];
|
|
144
|
+
const sccs = [];
|
|
145
|
+
let currentIndex = 0;
|
|
146
|
+
const strongConnect = (node) => {
|
|
147
|
+
index.set(node, currentIndex);
|
|
148
|
+
lowLink.set(node, currentIndex);
|
|
149
|
+
currentIndex++;
|
|
150
|
+
stack.push(node);
|
|
151
|
+
onStack.add(node);
|
|
152
|
+
const neighbors = this.adjacencyList.get(node) || new Set();
|
|
153
|
+
for (const neighbor of neighbors) {
|
|
154
|
+
if (!index.has(neighbor)) {
|
|
155
|
+
strongConnect(neighbor);
|
|
156
|
+
lowLink.set(node, Math.min(lowLink.get(node), lowLink.get(neighbor)));
|
|
157
|
+
}
|
|
158
|
+
else if (onStack.has(neighbor)) {
|
|
159
|
+
lowLink.set(node, Math.min(lowLink.get(node), index.get(neighbor)));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// If node is a root node, pop the stack and create SCC
|
|
163
|
+
if (lowLink.get(node) === index.get(node)) {
|
|
164
|
+
const scc = [];
|
|
165
|
+
let w;
|
|
166
|
+
do {
|
|
167
|
+
w = stack.pop();
|
|
168
|
+
onStack.delete(w);
|
|
169
|
+
scc.push(w);
|
|
170
|
+
} while (w !== node);
|
|
171
|
+
// Only add if SCC has more than 1 node (circular dependency)
|
|
172
|
+
if (scc.length > 1) {
|
|
173
|
+
sccs.push(scc);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
// Run on all nodes
|
|
178
|
+
for (const node of this.nodes.keys()) {
|
|
179
|
+
if (!index.has(node)) {
|
|
180
|
+
strongConnect(node);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return sccs;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=dependency-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../../src/analyzers/dependency/dependency-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Analyzer Module
|
|
3
|
+
*/
|
|
4
|
+
export { DependencyAnalyzer } from './dependency-analyzer.js';
|
|
5
|
+
export { DependencyGraph } from './dependency-graph.js';
|
|
6
|
+
export { CircularDependencyDetector } from './circular-detector.js';
|
|
7
|
+
export { CouplingCalculator } from './coupling-calculator.js';
|
|
8
|
+
export type { DependencyNode, ImportEdge, ExportEdge, CircularDependency, CouplingMetrics, DependencyAnalysisResult, DependencySummary, DependencyAnalysisOptions, } from './types.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Analyzer Module
|
|
3
|
+
*/
|
|
4
|
+
export { DependencyAnalyzer } from './dependency-analyzer.js';
|
|
5
|
+
export { DependencyGraph } from './dependency-graph.js';
|
|
6
|
+
export { CircularDependencyDetector } from './circular-detector.js';
|
|
7
|
+
export { CouplingCalculator } from './coupling-calculator.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/dependency/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Analyzer Types
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Dependency node representing a file
|
|
6
|
+
*/
|
|
7
|
+
export interface DependencyNode {
|
|
8
|
+
readonly filePath: string;
|
|
9
|
+
readonly imports: ReadonlyArray<ImportEdge>;
|
|
10
|
+
readonly exports: ReadonlyArray<ExportEdge>;
|
|
11
|
+
readonly size: number;
|
|
12
|
+
readonly loc: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Import edge in dependency graph
|
|
16
|
+
*/
|
|
17
|
+
export interface ImportEdge {
|
|
18
|
+
readonly from: string;
|
|
19
|
+
readonly to: string;
|
|
20
|
+
readonly importedSymbols: ReadonlyArray<string>;
|
|
21
|
+
readonly isDynamic: boolean;
|
|
22
|
+
readonly isTypeOnly: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Export edge
|
|
26
|
+
*/
|
|
27
|
+
export interface ExportEdge {
|
|
28
|
+
readonly from: string;
|
|
29
|
+
readonly symbols: ReadonlyArray<string>;
|
|
30
|
+
readonly isDefault: boolean;
|
|
31
|
+
readonly isReExport: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Circular dependency cycle
|
|
35
|
+
*/
|
|
36
|
+
export interface CircularDependency {
|
|
37
|
+
readonly cycle: ReadonlyArray<string>;
|
|
38
|
+
readonly length: number;
|
|
39
|
+
readonly severity: 'critical' | 'high' | 'medium' | 'low';
|
|
40
|
+
readonly impact: number;
|
|
41
|
+
readonly description: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Coupling metrics for a file
|
|
45
|
+
*/
|
|
46
|
+
export interface CouplingMetrics {
|
|
47
|
+
readonly file: string;
|
|
48
|
+
readonly afferentCoupling: number;
|
|
49
|
+
readonly efferentCoupling: number;
|
|
50
|
+
readonly instability: number;
|
|
51
|
+
readonly abstractness: number;
|
|
52
|
+
readonly distanceFromMainSequence: number;
|
|
53
|
+
readonly zone: 'useless' | 'painful' | 'balanced';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Dependency analysis result
|
|
57
|
+
*/
|
|
58
|
+
export interface DependencyAnalysisResult {
|
|
59
|
+
readonly graph: DependencyGraph;
|
|
60
|
+
readonly circularDependencies: ReadonlyArray<CircularDependency>;
|
|
61
|
+
readonly couplingMetrics: ReadonlyArray<CouplingMetrics>;
|
|
62
|
+
readonly orphanedFiles: ReadonlyArray<string>;
|
|
63
|
+
readonly hubFiles: ReadonlyArray<string>;
|
|
64
|
+
readonly summary: DependencySummary;
|
|
65
|
+
readonly timestamp: Date;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Summary statistics
|
|
69
|
+
*/
|
|
70
|
+
export interface DependencySummary {
|
|
71
|
+
readonly totalFiles: number;
|
|
72
|
+
readonly totalDependencies: number;
|
|
73
|
+
readonly averageAfferentCoupling: number;
|
|
74
|
+
readonly averageEfferentCoupling: number;
|
|
75
|
+
readonly averageInstability: number;
|
|
76
|
+
readonly circularDependencyCount: number;
|
|
77
|
+
readonly maxCycleLength: number;
|
|
78
|
+
readonly healthScore: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Dependency graph interface
|
|
82
|
+
*/
|
|
83
|
+
export interface DependencyGraph {
|
|
84
|
+
addNode(node: DependencyNode): void;
|
|
85
|
+
addEdge(from: string, to: string): void;
|
|
86
|
+
getNode(file: string): DependencyNode | undefined;
|
|
87
|
+
getNodes(): DependencyNode[];
|
|
88
|
+
getAfferentDependencies(file: string): string[];
|
|
89
|
+
getEfferentDependencies(file: string): string[];
|
|
90
|
+
getTotalEdges(): number;
|
|
91
|
+
hasPath(from: string, to: string): boolean;
|
|
92
|
+
topologicalSort(): {
|
|
93
|
+
sorted: string[];
|
|
94
|
+
hasCycle: boolean;
|
|
95
|
+
};
|
|
96
|
+
getStronglyConnectedComponents(): string[][];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Analysis options
|
|
100
|
+
*/
|
|
101
|
+
export interface DependencyAnalysisOptions {
|
|
102
|
+
readonly includeNodeModules?: boolean;
|
|
103
|
+
readonly maxDepth?: number;
|
|
104
|
+
readonly ignorePatterns?: readonly string[];
|
|
105
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/dependency/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Churn Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates file churn metrics from git history
|
|
5
|
+
*/
|
|
6
|
+
import type { FileChurn, GitAnalysisOptions, ContributorStats } from './types.js';
|
|
7
|
+
export declare class ChurnCalculator {
|
|
8
|
+
private repositoryPath;
|
|
9
|
+
constructor(repositoryPath: string);
|
|
10
|
+
/**
|
|
11
|
+
* Calculate churn for all files
|
|
12
|
+
*/
|
|
13
|
+
calculateChurn(options?: GitAnalysisOptions): Promise<FileChurn[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Calculate contributor statistics
|
|
16
|
+
*/
|
|
17
|
+
calculateContributorStats(options?: GitAnalysisOptions): Promise<ContributorStats[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Get git log with file stats
|
|
20
|
+
*/
|
|
21
|
+
private getGitLog;
|
|
22
|
+
/**
|
|
23
|
+
* Parse git log output
|
|
24
|
+
*/
|
|
25
|
+
private parseGitLog;
|
|
26
|
+
/**
|
|
27
|
+
* Check if file should be included based on patterns
|
|
28
|
+
*/
|
|
29
|
+
private shouldIncludeFile;
|
|
30
|
+
/**
|
|
31
|
+
* Simple pattern matching (supports * wildcard)
|
|
32
|
+
*/
|
|
33
|
+
private matchPattern;
|
|
34
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Churn Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates file churn metrics from git history
|
|
5
|
+
*/
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
export class ChurnCalculator {
|
|
8
|
+
repositoryPath;
|
|
9
|
+
constructor(repositoryPath) {
|
|
10
|
+
this.repositoryPath = repositoryPath;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Calculate churn for all files
|
|
14
|
+
*/
|
|
15
|
+
async calculateChurn(options = {}) {
|
|
16
|
+
const gitLogOutput = this.getGitLog(options);
|
|
17
|
+
const fileChurnMap = new Map();
|
|
18
|
+
// Parse git log output
|
|
19
|
+
const commits = this.parseGitLog(gitLogOutput);
|
|
20
|
+
for (const commit of commits) {
|
|
21
|
+
for (const file of commit.files) {
|
|
22
|
+
if (!this.shouldIncludeFile(file.path, options))
|
|
23
|
+
continue;
|
|
24
|
+
if (!fileChurnMap.has(file.path)) {
|
|
25
|
+
fileChurnMap.set(file.path, {
|
|
26
|
+
commits: 0,
|
|
27
|
+
additions: 0,
|
|
28
|
+
deletions: 0,
|
|
29
|
+
lastModified: commit.date,
|
|
30
|
+
authors: new Set(),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const churn = fileChurnMap.get(file.path);
|
|
34
|
+
churn.commits++;
|
|
35
|
+
churn.additions += file.additions;
|
|
36
|
+
churn.deletions += file.deletions;
|
|
37
|
+
churn.authors.add(commit.author);
|
|
38
|
+
// Update last modified date
|
|
39
|
+
if (commit.date > churn.lastModified) {
|
|
40
|
+
churn.lastModified = commit.date;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Convert to FileChurn array
|
|
45
|
+
const result = [];
|
|
46
|
+
for (const [filePath, data] of fileChurnMap.entries()) {
|
|
47
|
+
result.push(Object.freeze({
|
|
48
|
+
filePath,
|
|
49
|
+
commitCount: data.commits,
|
|
50
|
+
additions: data.additions,
|
|
51
|
+
deletions: data.deletions,
|
|
52
|
+
totalChurn: data.additions + data.deletions,
|
|
53
|
+
lastModified: data.lastModified,
|
|
54
|
+
authors: Object.freeze(Array.from(data.authors)),
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
// Sort by total churn (descending)
|
|
58
|
+
return result.sort((a, b) => b.totalChurn - a.totalChurn);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Calculate contributor statistics
|
|
62
|
+
*/
|
|
63
|
+
async calculateContributorStats(options = {}) {
|
|
64
|
+
const gitLogOutput = this.getGitLog(options);
|
|
65
|
+
const commits = this.parseGitLog(gitLogOutput);
|
|
66
|
+
const contributorMap = new Map();
|
|
67
|
+
for (const commit of commits) {
|
|
68
|
+
if (!contributorMap.has(commit.author)) {
|
|
69
|
+
contributorMap.set(commit.author, {
|
|
70
|
+
commits: 0,
|
|
71
|
+
files: new Set(),
|
|
72
|
+
added: 0,
|
|
73
|
+
deleted: 0,
|
|
74
|
+
firstCommit: commit.date,
|
|
75
|
+
lastCommit: commit.date,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const stats = contributorMap.get(commit.author);
|
|
79
|
+
stats.commits++;
|
|
80
|
+
for (const file of commit.files) {
|
|
81
|
+
if (this.shouldIncludeFile(file.path, options)) {
|
|
82
|
+
stats.files.add(file.path);
|
|
83
|
+
stats.added += file.additions;
|
|
84
|
+
stats.deleted += file.deletions;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Update date range
|
|
88
|
+
if (commit.date < stats.firstCommit) {
|
|
89
|
+
stats.firstCommit = commit.date;
|
|
90
|
+
}
|
|
91
|
+
if (commit.date > stats.lastCommit) {
|
|
92
|
+
stats.lastCommit = commit.date;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Convert to ContributorStats array
|
|
96
|
+
const result = [];
|
|
97
|
+
for (const [author, data] of contributorMap.entries()) {
|
|
98
|
+
result.push(Object.freeze({
|
|
99
|
+
author,
|
|
100
|
+
commitCount: data.commits,
|
|
101
|
+
filesChanged: data.files.size,
|
|
102
|
+
linesAdded: data.added,
|
|
103
|
+
linesDeleted: data.deleted,
|
|
104
|
+
firstCommit: data.firstCommit,
|
|
105
|
+
lastCommit: data.lastCommit,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
// Sort by commit count (descending)
|
|
109
|
+
return result.sort((a, b) => b.commitCount - a.commitCount);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get git log with file stats
|
|
113
|
+
*/
|
|
114
|
+
getGitLog(options) {
|
|
115
|
+
const args = ['log', '--numstat', '--pretty=format:%H|%an|%ad|%s'];
|
|
116
|
+
if (options.since) {
|
|
117
|
+
args.push(`--since="${options.since}"`);
|
|
118
|
+
}
|
|
119
|
+
if (options.until) {
|
|
120
|
+
args.push(`--until="${options.until}"`);
|
|
121
|
+
}
|
|
122
|
+
if (options.branch) {
|
|
123
|
+
args.push(options.branch);
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
return execSync(`git ${args.join(' ')}`, {
|
|
127
|
+
cwd: this.repositoryPath,
|
|
128
|
+
encoding: 'utf-8',
|
|
129
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
130
|
+
stdio: ['pipe', 'pipe', 'ignore'], // Ignore stderr to suppress shell warnings
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
// If git command fails, return empty string
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parse git log output
|
|
140
|
+
*/
|
|
141
|
+
parseGitLog(output) {
|
|
142
|
+
const commits = [];
|
|
143
|
+
const lines = output.split('\n');
|
|
144
|
+
let currentCommit = null;
|
|
145
|
+
for (const line of lines) {
|
|
146
|
+
if (!line.trim())
|
|
147
|
+
continue;
|
|
148
|
+
// Commit line: hash|author|date|message
|
|
149
|
+
if (line.includes('|')) {
|
|
150
|
+
const parts = line.split('|');
|
|
151
|
+
if (parts.length >= 4) {
|
|
152
|
+
// Save previous commit
|
|
153
|
+
if (currentCommit) {
|
|
154
|
+
commits.push(currentCommit);
|
|
155
|
+
}
|
|
156
|
+
// Start new commit
|
|
157
|
+
currentCommit = {
|
|
158
|
+
hash: parts[0],
|
|
159
|
+
author: parts[1],
|
|
160
|
+
date: new Date(parts[2]),
|
|
161
|
+
message: parts[3],
|
|
162
|
+
files: [],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (currentCommit) {
|
|
167
|
+
// File stat line: additions deletions filename
|
|
168
|
+
const parts = line.split('\t');
|
|
169
|
+
if (parts.length >= 3) {
|
|
170
|
+
const additions = parts[0] === '-' ? 0 : parseInt(parts[0], 10);
|
|
171
|
+
const deletions = parts[1] === '-' ? 0 : parseInt(parts[1], 10);
|
|
172
|
+
const path = parts[2];
|
|
173
|
+
currentCommit.files.push({ path, additions, deletions });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Add last commit
|
|
178
|
+
if (currentCommit) {
|
|
179
|
+
commits.push(currentCommit);
|
|
180
|
+
}
|
|
181
|
+
return commits;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if file should be included based on patterns
|
|
185
|
+
*/
|
|
186
|
+
shouldIncludeFile(filePath, options) {
|
|
187
|
+
// Check exclude patterns
|
|
188
|
+
if (options.excludePatterns) {
|
|
189
|
+
for (const pattern of options.excludePatterns) {
|
|
190
|
+
if (this.matchPattern(filePath, pattern)) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Check include patterns
|
|
196
|
+
if (options.includePatterns && options.includePatterns.length > 0) {
|
|
197
|
+
for (const pattern of options.includePatterns) {
|
|
198
|
+
if (this.matchPattern(filePath, pattern)) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Simple pattern matching (supports * wildcard)
|
|
208
|
+
*/
|
|
209
|
+
matchPattern(filePath, pattern) {
|
|
210
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
211
|
+
return regex.test(filePath);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=churn-calculator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"churn-calculator.js","sourceRoot":"","sources":["../../../src/analyzers/git/churn-calculator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator for Git history analysis
|
|
5
|
+
*/
|
|
6
|
+
import type { GitAnalysisResult, GitAnalysisOptions } from './types.js';
|
|
7
|
+
export declare class GitAnalyzer {
|
|
8
|
+
private churnCalculator;
|
|
9
|
+
private hotspotDetector;
|
|
10
|
+
constructor(repositoryPath: string);
|
|
11
|
+
/**
|
|
12
|
+
* Perform complete Git analysis
|
|
13
|
+
*/
|
|
14
|
+
analyze(options?: GitAnalysisOptions): Promise<GitAnalysisResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Calculate summary statistics
|
|
17
|
+
*/
|
|
18
|
+
private calculateSummary;
|
|
19
|
+
}
|