cli-node-graph 1.0.1

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.
Files changed (180) hide show
  1. package/README.md +69 -0
  2. package/dist/analysis/CircularDependencyAnalyzer.d.ts +13 -0
  3. package/dist/analysis/CircularDependencyAnalyzer.d.ts.map +1 -0
  4. package/dist/analysis/CircularDependencyAnalyzer.js +15 -0
  5. package/dist/analysis/CircularDependencyAnalyzer.js.map +1 -0
  6. package/dist/analysis/DeadCodeAnalyzer.d.ts +13 -0
  7. package/dist/analysis/DeadCodeAnalyzer.d.ts.map +1 -0
  8. package/dist/analysis/DeadCodeAnalyzer.js +37 -0
  9. package/dist/analysis/DeadCodeAnalyzer.js.map +1 -0
  10. package/dist/analysis/DependencyAnalyzer.d.ts +16 -0
  11. package/dist/analysis/DependencyAnalyzer.d.ts.map +1 -0
  12. package/dist/analysis/DependencyAnalyzer.js +26 -0
  13. package/dist/analysis/DependencyAnalyzer.js.map +1 -0
  14. package/dist/analysis/ImpactAnalyzer.d.ts +16 -0
  15. package/dist/analysis/ImpactAnalyzer.d.ts.map +1 -0
  16. package/dist/analysis/ImpactAnalyzer.js +26 -0
  17. package/dist/analysis/ImpactAnalyzer.js.map +1 -0
  18. package/dist/analysis/LayerViolationAnalyzer.d.ts +31 -0
  19. package/dist/analysis/LayerViolationAnalyzer.d.ts.map +1 -0
  20. package/dist/analysis/LayerViolationAnalyzer.js +71 -0
  21. package/dist/analysis/LayerViolationAnalyzer.js.map +1 -0
  22. package/dist/cli/ProjectLoader.d.ts +13 -0
  23. package/dist/cli/ProjectLoader.d.ts.map +1 -0
  24. package/dist/cli/ProjectLoader.js +48 -0
  25. package/dist/cli/ProjectLoader.js.map +1 -0
  26. package/dist/cli/index.d.ts +3 -0
  27. package/dist/cli/index.d.ts.map +1 -0
  28. package/dist/cli/index.js +139 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/config/AnalysisConfig.d.ts +22 -0
  31. package/dist/config/AnalysisConfig.d.ts.map +1 -0
  32. package/dist/config/AnalysisConfig.js +6 -0
  33. package/dist/config/AnalysisConfig.js.map +1 -0
  34. package/dist/exporters/CytoscapeExporter.d.ts +18 -0
  35. package/dist/exporters/CytoscapeExporter.d.ts.map +1 -0
  36. package/dist/exporters/CytoscapeExporter.js +85 -0
  37. package/dist/exporters/CytoscapeExporter.js.map +1 -0
  38. package/dist/exporters/DotExporter.d.ts +13 -0
  39. package/dist/exporters/DotExporter.d.ts.map +1 -0
  40. package/dist/exporters/DotExporter.js +38 -0
  41. package/dist/exporters/DotExporter.js.map +1 -0
  42. package/dist/exporters/GraphExporter.d.ts +7 -0
  43. package/dist/exporters/GraphExporter.d.ts.map +1 -0
  44. package/dist/exporters/GraphExporter.js +2 -0
  45. package/dist/exporters/GraphExporter.js.map +1 -0
  46. package/dist/exporters/GraphMLExporter.d.ts +8 -0
  47. package/dist/exporters/GraphMLExporter.d.ts.map +1 -0
  48. package/dist/exporters/GraphMLExporter.js +30 -0
  49. package/dist/exporters/GraphMLExporter.js.map +1 -0
  50. package/dist/exporters/JsonExporter.d.ts +8 -0
  51. package/dist/exporters/JsonExporter.d.ts.map +1 -0
  52. package/dist/exporters/JsonExporter.js +16 -0
  53. package/dist/exporters/JsonExporter.js.map +1 -0
  54. package/dist/graph/EdgeFactory.d.ts +13 -0
  55. package/dist/graph/EdgeFactory.d.ts.map +1 -0
  56. package/dist/graph/EdgeFactory.js +15 -0
  57. package/dist/graph/EdgeFactory.js.map +1 -0
  58. package/dist/graph/Graph.d.ts +37 -0
  59. package/dist/graph/Graph.d.ts.map +1 -0
  60. package/dist/graph/Graph.js +137 -0
  61. package/dist/graph/Graph.js.map +1 -0
  62. package/dist/graph/GraphAlgorithms.d.ts +28 -0
  63. package/dist/graph/GraphAlgorithms.d.ts.map +1 -0
  64. package/dist/graph/GraphAlgorithms.js +233 -0
  65. package/dist/graph/GraphAlgorithms.js.map +1 -0
  66. package/dist/graph/GraphBuilder.d.ts +10 -0
  67. package/dist/graph/GraphBuilder.d.ts.map +1 -0
  68. package/dist/graph/GraphBuilder.js +71 -0
  69. package/dist/graph/GraphBuilder.js.map +1 -0
  70. package/dist/graph/NodeFactory.d.ts +21 -0
  71. package/dist/graph/NodeFactory.d.ts.map +1 -0
  72. package/dist/graph/NodeFactory.js +53 -0
  73. package/dist/graph/NodeFactory.js.map +1 -0
  74. package/dist/index.d.ts +35 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +24 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/model/EdgeKind.d.ts +22 -0
  79. package/dist/model/EdgeKind.d.ts.map +1 -0
  80. package/dist/model/EdgeKind.js +23 -0
  81. package/dist/model/EdgeKind.js.map +1 -0
  82. package/dist/model/GraphEdge.d.ts +22 -0
  83. package/dist/model/GraphEdge.d.ts.map +1 -0
  84. package/dist/model/GraphEdge.js +2 -0
  85. package/dist/model/GraphEdge.js.map +1 -0
  86. package/dist/model/GraphNode.d.ts +22 -0
  87. package/dist/model/GraphNode.d.ts.map +1 -0
  88. package/dist/model/GraphNode.js +2 -0
  89. package/dist/model/GraphNode.js.map +1 -0
  90. package/dist/model/NodeKind.d.ts +21 -0
  91. package/dist/model/NodeKind.d.ts.map +1 -0
  92. package/dist/model/NodeKind.js +22 -0
  93. package/dist/model/NodeKind.js.map +1 -0
  94. package/dist/parser/ASTWalker.d.ts +21 -0
  95. package/dist/parser/ASTWalker.d.ts.map +1 -0
  96. package/dist/parser/ASTWalker.js +23 -0
  97. package/dist/parser/ASTWalker.js.map +1 -0
  98. package/dist/parser/ProgramFactory.d.ts +15 -0
  99. package/dist/parser/ProgramFactory.d.ts.map +1 -0
  100. package/dist/parser/ProgramFactory.js +65 -0
  101. package/dist/parser/ProgramFactory.js.map +1 -0
  102. package/dist/parser/visitors/CallVisitor.d.ts +17 -0
  103. package/dist/parser/visitors/CallVisitor.d.ts.map +1 -0
  104. package/dist/parser/visitors/CallVisitor.js +111 -0
  105. package/dist/parser/visitors/CallVisitor.js.map +1 -0
  106. package/dist/parser/visitors/ClassVisitor.d.ts +14 -0
  107. package/dist/parser/visitors/ClassVisitor.d.ts.map +1 -0
  108. package/dist/parser/visitors/ClassVisitor.js +87 -0
  109. package/dist/parser/visitors/ClassVisitor.js.map +1 -0
  110. package/dist/parser/visitors/DecoratorVisitor.d.ts +13 -0
  111. package/dist/parser/visitors/DecoratorVisitor.d.ts.map +1 -0
  112. package/dist/parser/visitors/DecoratorVisitor.js +65 -0
  113. package/dist/parser/visitors/DecoratorVisitor.js.map +1 -0
  114. package/dist/parser/visitors/EnumVisitor.d.ts +11 -0
  115. package/dist/parser/visitors/EnumVisitor.d.ts.map +1 -0
  116. package/dist/parser/visitors/EnumVisitor.js +26 -0
  117. package/dist/parser/visitors/EnumVisitor.js.map +1 -0
  118. package/dist/parser/visitors/ExportVisitor.d.ts +16 -0
  119. package/dist/parser/visitors/ExportVisitor.d.ts.map +1 -0
  120. package/dist/parser/visitors/ExportVisitor.js +95 -0
  121. package/dist/parser/visitors/ExportVisitor.js.map +1 -0
  122. package/dist/parser/visitors/FunctionVisitor.d.ts +14 -0
  123. package/dist/parser/visitors/FunctionVisitor.d.ts.map +1 -0
  124. package/dist/parser/visitors/FunctionVisitor.js +74 -0
  125. package/dist/parser/visitors/FunctionVisitor.js.map +1 -0
  126. package/dist/parser/visitors/HeritageVisitor.d.ts +14 -0
  127. package/dist/parser/visitors/HeritageVisitor.d.ts.map +1 -0
  128. package/dist/parser/visitors/HeritageVisitor.js +87 -0
  129. package/dist/parser/visitors/HeritageVisitor.js.map +1 -0
  130. package/dist/parser/visitors/ImportVisitor.d.ts +14 -0
  131. package/dist/parser/visitors/ImportVisitor.d.ts.map +1 -0
  132. package/dist/parser/visitors/ImportVisitor.js +96 -0
  133. package/dist/parser/visitors/ImportVisitor.js.map +1 -0
  134. package/dist/parser/visitors/InterfaceVisitor.d.ts +11 -0
  135. package/dist/parser/visitors/InterfaceVisitor.d.ts.map +1 -0
  136. package/dist/parser/visitors/InterfaceVisitor.js +28 -0
  137. package/dist/parser/visitors/InterfaceVisitor.js.map +1 -0
  138. package/dist/parser/visitors/MethodVisitor.d.ts +11 -0
  139. package/dist/parser/visitors/MethodVisitor.d.ts.map +1 -0
  140. package/dist/parser/visitors/MethodVisitor.js +30 -0
  141. package/dist/parser/visitors/MethodVisitor.js.map +1 -0
  142. package/dist/parser/visitors/TypeReferenceVisitor.d.ts +15 -0
  143. package/dist/parser/visitors/TypeReferenceVisitor.d.ts.map +1 -0
  144. package/dist/parser/visitors/TypeReferenceVisitor.js +85 -0
  145. package/dist/parser/visitors/TypeReferenceVisitor.js.map +1 -0
  146. package/dist/parser/visitors/VariableVisitor.d.ts +11 -0
  147. package/dist/parser/visitors/VariableVisitor.d.ts.map +1 -0
  148. package/dist/parser/visitors/VariableVisitor.js +27 -0
  149. package/dist/parser/visitors/VariableVisitor.js.map +1 -0
  150. package/dist/parser/visitors/context.d.ts +54 -0
  151. package/dist/parser/visitors/context.d.ts.map +1 -0
  152. package/dist/parser/visitors/context.js +117 -0
  153. package/dist/parser/visitors/context.js.map +1 -0
  154. package/dist/resolver/ModuleResolver.d.ts +16 -0
  155. package/dist/resolver/ModuleResolver.d.ts.map +1 -0
  156. package/dist/resolver/ModuleResolver.js +40 -0
  157. package/dist/resolver/ModuleResolver.js.map +1 -0
  158. package/dist/resolver/SymbolResolver.d.ts +15 -0
  159. package/dist/resolver/SymbolResolver.d.ts.map +1 -0
  160. package/dist/resolver/SymbolResolver.js +62 -0
  161. package/dist/resolver/SymbolResolver.js.map +1 -0
  162. package/dist/resolver/TypeResolver.d.ts +13 -0
  163. package/dist/resolver/TypeResolver.d.ts.map +1 -0
  164. package/dist/resolver/TypeResolver.js +32 -0
  165. package/dist/resolver/TypeResolver.js.map +1 -0
  166. package/dist/utils/cache.d.ts +12 -0
  167. package/dist/utils/cache.d.ts.map +1 -0
  168. package/dist/utils/cache.js +38 -0
  169. package/dist/utils/cache.js.map +1 -0
  170. package/dist/utils/id.d.ts +7 -0
  171. package/dist/utils/id.d.ts.map +1 -0
  172. package/dist/utils/id.js +15 -0
  173. package/dist/utils/id.js.map +1 -0
  174. package/dist/utils/path.d.ts +9 -0
  175. package/dist/utils/path.d.ts.map +1 -0
  176. package/dist/utils/path.js +18 -0
  177. package/dist/utils/path.js.map +1 -0
  178. package/docs/ARCHITECTURE.md +100 -0
  179. package/docs/CLI.md +62 -0
  180. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # cli-node-graph
2
+
3
+ TypeScript codebase knowledge graph analyzer — an Nx-style dependency graph tool with deep symbol-level analysis.
4
+
5
+ ## Features
6
+
7
+ - **Full AST analysis** using the TypeScript Compiler API
8
+ - **Rich graph model** — files, classes, interfaces, functions, methods, imports, calls, inheritance, decorators, and more
9
+ - **Graph algorithms** — cycle detection, shortest path, impact analysis, topological sort
10
+ - **Multiple export formats** — JSON, DOT, GraphML, Mermaid, Cytoscape, React Flow, Neo4j CSV
11
+ - **CLI** for analysis, export, and querying
12
+ - **React Flow visualization** with search, filtering, path finder, and layouts
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ npm install
18
+ npm run build
19
+ npm test
20
+
21
+ # Analyze a project
22
+ npm run cli-node-graph analyze ./tests/fixtures/sample-project
23
+
24
+ # Export graph
25
+ npm run cli-node-graph export ./tests/fixtures/sample-project --format reactflow -o graph.json
26
+
27
+ # Detect cycles
28
+ npm run cli-node-graph cycles ./tests/fixtures/sample-project
29
+
30
+ # Impact analysis
31
+ npm run cli-node-graph impact UserService ./tests/fixtures/sample-project
32
+
33
+ # Statistics
34
+ npm run cli-node-graph stats ./tests/fixtures/sample-project
35
+ ```
36
+
37
+ ## Visualization
38
+
39
+ ```bash
40
+ cd visualization
41
+ npm install
42
+ npm run dev
43
+ ```
44
+
45
+ Load a React Flow JSON export from the CLI to visualize your codebase graph interactively.
46
+
47
+ ## Architecture
48
+
49
+ ```
50
+ CLI → Project Loader → TypeScript Program → AST Walker → Visitors → Resolvers → Graph Builder → Graph → Exporters / Analyzers
51
+ ```
52
+
53
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for details.
54
+
55
+ ## API
56
+
57
+ ```typescript
58
+ import { GraphBuilder, GraphAlgorithms, JsonExporter } from 'cli-node-graph';
59
+
60
+ const graph = new GraphBuilder().build({ projectRoot: './my-project' });
61
+ const cycles = new GraphAlgorithms(graph).detectCycles();
62
+ const json = new JsonExporter().export(graph);
63
+ ```
64
+
65
+ See [docs/API.md](docs/API.md) for the full API reference.
66
+
67
+ ## License
68
+
69
+ MIT
@@ -0,0 +1,13 @@
1
+ import type { Graph } from '../graph/Graph.js';
2
+ /** Detects circular dependencies in the graph. */
3
+ export declare class CircularDependencyAnalyzer {
4
+ analyze(graph: Graph): CycleReport[];
5
+ }
6
+ /** Report of a single dependency cycle. */
7
+ export interface CycleReport {
8
+ id: string;
9
+ nodes: string[];
10
+ length: number;
11
+ labels: string[];
12
+ }
13
+ //# sourceMappingURL=CircularDependencyAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CircularDependencyAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/CircularDependencyAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,kDAAkD;AAClD,qBAAa,0BAA0B;IACrC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,EAAE;CAWrC;AAED,2CAA2C;AAC3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB"}
@@ -0,0 +1,15 @@
1
+ import { GraphAlgorithms } from '../graph/GraphAlgorithms.js';
2
+ /** Detects circular dependencies in the graph. */
3
+ export class CircularDependencyAnalyzer {
4
+ analyze(graph) {
5
+ const algorithms = new GraphAlgorithms(graph);
6
+ const cycles = algorithms.detectCycles();
7
+ return cycles.map((cycle, index) => ({
8
+ id: `cycle-${String(index + 1)}`,
9
+ nodes: cycle,
10
+ length: cycle.length,
11
+ labels: cycle.map((id) => graph.getNode(id)?.label ?? id),
12
+ }));
13
+ }
14
+ }
15
+ //# sourceMappingURL=CircularDependencyAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CircularDependencyAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/CircularDependencyAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,kDAAkD;AAClD,MAAM,OAAO,0BAA0B;IACrC,OAAO,CAAC,KAAY;QAClB,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;QAEzC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACnC,EAAE,EAAE,SAAS,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE;YAChC,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;SAC1D,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { Graph } from '../graph/Graph.js';
2
+ /** Finds potentially unused code in the graph. */
3
+ export declare class DeadCodeAnalyzer {
4
+ analyze(graph: Graph): DeadCodeReport;
5
+ }
6
+ /** Report of dead/unused code findings. */
7
+ export interface DeadCodeReport {
8
+ unusedExports: string[];
9
+ unusedFunctions: string[];
10
+ unreachableClasses: string[];
11
+ orphanModules: string[];
12
+ }
13
+ //# sourceMappingURL=DeadCodeAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeadCodeAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/DeadCodeAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C,kDAAkD;AAClD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc;CAwCtC;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB"}
@@ -0,0 +1,37 @@
1
+ import { EdgeKind } from '../model/EdgeKind.js';
2
+ import { NodeKind } from '../model/NodeKind.js';
3
+ /** Finds potentially unused code in the graph. */
4
+ export class DeadCodeAnalyzer {
5
+ analyze(graph) {
6
+ const unusedExports = [];
7
+ const unusedFunctions = [];
8
+ const unreachableClasses = [];
9
+ const orphanModules = [];
10
+ for (const node of graph.getNodes()) {
11
+ const incoming = graph.getIncomingEdges(node.id);
12
+ const hasReferences = incoming.some((e) => e.kind === EdgeKind.IMPORTS ||
13
+ e.kind === EdgeKind.CALLS ||
14
+ e.kind === EdgeKind.REFERENCES ||
15
+ e.kind === EdgeKind.EXTENDS ||
16
+ e.kind === EdgeKind.IMPLEMENTS);
17
+ if (node.metadata['exported'] === true && !hasReferences && incoming.length === 0) {
18
+ unusedExports.push(node.id);
19
+ }
20
+ if (node.kind === NodeKind.Function && !hasReferences) {
21
+ unusedFunctions.push(node.id);
22
+ }
23
+ if (node.kind === NodeKind.Class && !hasReferences) {
24
+ unreachableClasses.push(node.id);
25
+ }
26
+ if (node.kind === NodeKind.File) {
27
+ const imports = graph.getOutgoingEdges(node.id).filter((e) => e.kind === EdgeKind.IMPORTS);
28
+ const importedBy = graph.getIncomingEdges(node.id).filter((e) => e.kind === EdgeKind.IMPORTS);
29
+ if (imports.length === 0 && importedBy.length === 0) {
30
+ orphanModules.push(node.id);
31
+ }
32
+ }
33
+ }
34
+ return { unusedExports, unusedFunctions, unreachableClasses, orphanModules };
35
+ }
36
+ }
37
+ //# sourceMappingURL=DeadCodeAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeadCodeAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/DeadCodeAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,kDAAkD;AAClD,MAAM,OAAO,gBAAgB;IAC3B,OAAO,CAAC,KAAY;QAClB,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,MAAM,eAAe,GAAa,EAAE,CAAC;QACrC,MAAM,kBAAkB,GAAa,EAAE,CAAC;QACxC,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjD,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO;gBAC3B,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK;gBACzB,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,UAAU;gBAC9B,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO;gBAC3B,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,UAAU,CACjC,CAAC;YAEF,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClF,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9B,CAAC;YAED,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,QAAQ,IAAI,CAAC,aAAa,EAAE,CAAC;gBACtD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChC,CAAC;YAED,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnD,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnC,CAAC;YAED,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAChC,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC3F,MAAM,UAAU,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC9F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACpD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;IAC/E,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { Graph } from '../graph/Graph.js';
2
+ /** Analyzes dependency relationships between nodes. */
3
+ export declare class DependencyAnalyzer {
4
+ analyze(graph: Graph): DependencyReport;
5
+ }
6
+ /** Summary of dependency relationships. */
7
+ export interface DependencyReport {
8
+ totalImports: number;
9
+ totalCalls: number;
10
+ tightlyCoupled: {
11
+ nodeId: string;
12
+ importCount: number;
13
+ label: string;
14
+ }[];
15
+ }
16
+ //# sourceMappingURL=DependencyAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DependencyAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/DependencyAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,uDAAuD;AACvD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB;CAwBxC;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1E"}
@@ -0,0 +1,26 @@
1
+ import { EdgeKind } from '../model/EdgeKind.js';
2
+ /** Analyzes dependency relationships between nodes. */
3
+ export class DependencyAnalyzer {
4
+ analyze(graph) {
5
+ const importEdges = graph.getEdgesByKind(EdgeKind.IMPORTS);
6
+ const callEdges = graph.getEdgesByKind(EdgeKind.CALLS);
7
+ const fileImportCounts = new Map();
8
+ for (const edge of importEdges) {
9
+ fileImportCounts.set(edge.source, (fileImportCounts.get(edge.source) ?? 0) + 1);
10
+ }
11
+ const tightlyCoupled = [...fileImportCounts.entries()]
12
+ .filter(([, count]) => count >= 5)
13
+ .map(([id, count]) => ({
14
+ nodeId: id,
15
+ importCount: count,
16
+ label: graph.getNode(id)?.label ?? id,
17
+ }))
18
+ .sort((a, b) => b.importCount - a.importCount);
19
+ return {
20
+ totalImports: importEdges.length,
21
+ totalCalls: callEdges.length,
22
+ tightlyCoupled,
23
+ };
24
+ }
25
+ }
26
+ //# sourceMappingURL=DependencyAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DependencyAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/DependencyAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,uDAAuD;AACvD,MAAM,OAAO,kBAAkB;IAC7B,OAAO,CAAC,KAAY;QAClB,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;QAEnD,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,cAAc,GAAG,CAAC,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC;aACnD,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC;aACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YACrB,MAAM,EAAE,EAAE;YACV,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE;SACtC,CAAC,CAAC;aACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;QAEjD,OAAO;YACL,YAAY,EAAE,WAAW,CAAC,MAAM;YAChC,UAAU,EAAE,SAAS,CAAC,MAAM;YAC5B,cAAc;SACf,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { Graph } from '../graph/Graph.js';
2
+ /** Analyzes downstream impact of changing a node. */
3
+ export declare class ImpactAnalyzer {
4
+ analyze(graph: Graph, nodeId: string): ImpactReport;
5
+ analyzeByFile(graph: Graph, filePath: string): ImpactReport[];
6
+ }
7
+ /** Report of downstream impact from a change. */
8
+ export interface ImpactReport {
9
+ source: string;
10
+ sourceLabel?: string;
11
+ affected: string[];
12
+ affectedCount: number;
13
+ depth: number;
14
+ affectedLabels?: string[];
15
+ }
16
+ //# sourceMappingURL=ImpactAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImpactAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/ImpactAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,qDAAqD;AACrD,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY;IAoBnD,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE;CAI9D;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B"}
@@ -0,0 +1,26 @@
1
+ import { GraphAlgorithms } from '../graph/GraphAlgorithms.js';
2
+ /** Analyzes downstream impact of changing a node. */
3
+ export class ImpactAnalyzer {
4
+ analyze(graph, nodeId) {
5
+ const node = graph.getNode(nodeId);
6
+ if (!node) {
7
+ return { source: nodeId, affected: [], affectedCount: 0, depth: 0 };
8
+ }
9
+ const algorithms = new GraphAlgorithms(graph);
10
+ const affected = [...algorithms.reverseDependencies(nodeId)];
11
+ const depth = algorithms.dependencyDepth(nodeId);
12
+ return {
13
+ source: nodeId,
14
+ sourceLabel: node.label,
15
+ affected,
16
+ affectedCount: affected.length,
17
+ depth,
18
+ affectedLabels: affected.map((id) => graph.getNode(id)?.label ?? id),
19
+ };
20
+ }
21
+ analyzeByFile(graph, filePath) {
22
+ const fileNodes = graph.getNodesByFile(filePath);
23
+ return fileNodes.map((n) => this.analyze(graph, n.id));
24
+ }
25
+ }
26
+ //# sourceMappingURL=ImpactAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImpactAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/ImpactAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,qDAAqD;AACrD,MAAM,OAAO,cAAc;IACzB,OAAO,CAAC,KAAY,EAAE,MAAc;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACtE,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,CAAC,GAAG,UAAU,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAEjD,OAAO;YACL,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,QAAQ;YACR,aAAa,EAAE,QAAQ,CAAC,MAAM;YAC9B,KAAK;YACL,cAAc,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;SACrE,CAAC;IACJ,CAAC;IAED,aAAa,CAAC,KAAY,EAAE,QAAgB;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ import type { LayerRule } from '../config/AnalysisConfig.js';
2
+ import type { Graph } from '../graph/Graph.js';
3
+ /** Detects layer architecture violations. */
4
+ export declare class LayerViolationAnalyzer {
5
+ analyze(graph: Graph, rules: LayerRule[]): LayerViolationReport[];
6
+ private buildLayerMap;
7
+ private resolveLayer;
8
+ }
9
+ /** A single layer violation. */
10
+ export interface LayerViolationReport {
11
+ source: string;
12
+ target: string;
13
+ sourceLayer: string;
14
+ targetLayer: string;
15
+ sourceFile: string;
16
+ targetFile: string;
17
+ }
18
+ /** Computes graph statistics. */
19
+ export declare function computeStats(graph: Graph): GraphStats;
20
+ /** Summary statistics for a graph. */
21
+ export interface GraphStats {
22
+ nodeCount: number;
23
+ edgeCount: number;
24
+ fileCount: number;
25
+ classCount: number;
26
+ functionCount: number;
27
+ interfaceCount: number;
28
+ nodesByKind: Record<string, number>;
29
+ edgesByKind: Record<string, number>;
30
+ }
31
+ //# sourceMappingURL=LayerViolationAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LayerViolationAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/LayerViolationAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C,6CAA6C;AAC7C,qBAAa,sBAAsB;IACjC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,oBAAoB,EAAE;IA+BjE,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;CASrB;AAED,gCAAgC;AAChC,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,iCAAiC;AACjC,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAqBrD;AAED,sCAAsC;AACtC,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC"}
@@ -0,0 +1,71 @@
1
+ import { EdgeKind } from '../model/EdgeKind.js';
2
+ import { NodeKind } from '../model/NodeKind.js';
3
+ /** Detects layer architecture violations. */
4
+ export class LayerViolationAnalyzer {
5
+ analyze(graph, rules) {
6
+ const violations = [];
7
+ const layerMap = this.buildLayerMap(rules);
8
+ for (const edge of graph.getEdgesByKind(EdgeKind.IMPORTS)) {
9
+ const sourceNode = graph.getNode(edge.source);
10
+ const targetNode = graph.getNode(edge.target);
11
+ if (!sourceNode?.file || !targetNode?.file)
12
+ continue;
13
+ const sourceLayer = this.resolveLayer(sourceNode.file, layerMap);
14
+ const targetLayer = this.resolveLayer(targetNode.file, layerMap);
15
+ if (!sourceLayer || !targetLayer)
16
+ continue;
17
+ const sourceRule = rules.find((r) => r.name === sourceLayer);
18
+ if (!sourceRule?.allowedImports)
19
+ continue;
20
+ if (!sourceRule.allowedImports.includes(targetLayer)) {
21
+ violations.push({
22
+ source: edge.source,
23
+ target: edge.target,
24
+ sourceLayer,
25
+ targetLayer,
26
+ sourceFile: sourceNode.file,
27
+ targetFile: targetNode.file,
28
+ });
29
+ }
30
+ }
31
+ return violations;
32
+ }
33
+ buildLayerMap(rules) {
34
+ const map = new Map();
35
+ for (const rule of rules) {
36
+ map.set(rule.name, rule.name);
37
+ }
38
+ return map;
39
+ }
40
+ resolveLayer(filePath, _layerMap) {
41
+ for (const [layer] of _layerMap) {
42
+ const rule = layer;
43
+ if (filePath.includes(`/${rule.toLowerCase()}/`) || filePath.includes(`\\${rule.toLowerCase()}\\`)) {
44
+ return layer;
45
+ }
46
+ }
47
+ return undefined;
48
+ }
49
+ }
50
+ /** Computes graph statistics. */
51
+ export function computeStats(graph) {
52
+ const nodesByKind = {};
53
+ const edgesByKind = {};
54
+ for (const node of graph.getNodes()) {
55
+ nodesByKind[node.kind] = (nodesByKind[node.kind] ?? 0) + 1;
56
+ }
57
+ for (const edge of graph.getEdges()) {
58
+ edgesByKind[edge.kind] = (edgesByKind[edge.kind] ?? 0) + 1;
59
+ }
60
+ return {
61
+ nodeCount: graph.nodeCount,
62
+ edgeCount: graph.edgeCount,
63
+ fileCount: graph.getNodesByKind(NodeKind.File).length,
64
+ classCount: graph.getNodesByKind(NodeKind.Class).length,
65
+ functionCount: graph.getNodesByKind(NodeKind.Function).length,
66
+ interfaceCount: graph.getNodesByKind(NodeKind.Interface).length,
67
+ nodesByKind,
68
+ edgesByKind,
69
+ };
70
+ }
71
+ //# sourceMappingURL=LayerViolationAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LayerViolationAnalyzer.js","sourceRoot":"","sources":["../../src/analysis/LayerViolationAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { AnalysisConfig } from '../config/AnalysisConfig.js';
2
+ import { Graph } from '../graph/Graph.js';
3
+ /** Loads and caches project analysis results. */
4
+ export declare class ProjectLoader {
5
+ private graph;
6
+ private config;
7
+ analyze(config: AnalysisConfig): Graph;
8
+ getGraph(): Graph | null;
9
+ getConfig(): AnalysisConfig | null;
10
+ loadCache(projectRoot: string): Graph | null;
11
+ private saveCache;
12
+ }
13
+ //# sourceMappingURL=ProjectLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectLoader.d.ts","sourceRoot":"","sources":["../../src/cli/ProjectLoader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,iDAAiD;AACjD,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,MAAM,CAA+B;IAE7C,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,KAAK;IAQtC,QAAQ,IAAI,KAAK,GAAG,IAAI;IAIxB,SAAS,IAAI,cAAc,GAAG,IAAI;IAIlC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAsB5C,OAAO,CAAC,SAAS;CAQlB"}
@@ -0,0 +1,48 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join, resolve } from 'node:path';
3
+ import { GraphBuilder } from '../graph/GraphBuilder.js';
4
+ import { Graph } from '../graph/Graph.js';
5
+ const CACHE_DIR = '.cli-node-graph';
6
+ const CACHE_FILE = 'graph.json';
7
+ /** Loads and caches project analysis results. */
8
+ export class ProjectLoader {
9
+ graph = null;
10
+ config = null;
11
+ analyze(config) {
12
+ this.config = config;
13
+ const builder = new GraphBuilder();
14
+ this.graph = builder.build(config);
15
+ this.saveCache(config.projectRoot, this.graph);
16
+ return this.graph;
17
+ }
18
+ getGraph() {
19
+ return this.graph;
20
+ }
21
+ getConfig() {
22
+ return this.config;
23
+ }
24
+ loadCache(projectRoot) {
25
+ try {
26
+ const cachePath = join(resolve(projectRoot), CACHE_DIR, CACHE_FILE);
27
+ const data = JSON.parse(readFileSync(cachePath, 'utf-8'));
28
+ const graph = new Graph();
29
+ for (const node of data.nodes) {
30
+ graph.addNode(node);
31
+ }
32
+ for (const edge of data.edges) {
33
+ graph.addEdge(edge);
34
+ }
35
+ this.graph = graph;
36
+ return graph;
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ saveCache(projectRoot, graph) {
43
+ const cacheDir = join(resolve(projectRoot), CACHE_DIR);
44
+ mkdirSync(cacheDir, { recursive: true });
45
+ writeFileSync(join(cacheDir, CACHE_FILE), JSON.stringify({ nodes: graph.getNodes(), edges: graph.getEdges() }));
46
+ }
47
+ }
48
+ //# sourceMappingURL=ProjectLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectLoader.js","sourceRoot":"","sources":["../../src/cli/ProjectLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C,MAAM,SAAS,GAAG,iBAAiB,CAAC;AACpC,MAAM,UAAU,GAAG,YAAY,CAAC;AAEhC,iDAAiD;AACjD,MAAM,OAAO,aAAa;IAChB,KAAK,GAAiB,IAAI,CAAC;IAC3B,MAAM,GAA0B,IAAI,CAAC;IAE7C,OAAO,CAAC,MAAsB;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,SAAS,CAAC,WAAmB;QAC3B,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACpE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAGvD,CAAC;YAEF,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,WAAmB,EAAE,KAAY;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,CAAC;QACvD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,aAAa,CACX,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAC1B,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CACrE,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ import { writeFileSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { Command } from 'commander';
5
+ import { CircularDependencyAnalyzer } from '../analysis/CircularDependencyAnalyzer.js';
6
+ import { computeStats } from '../analysis/LayerViolationAnalyzer.js';
7
+ import { ImpactAnalyzer } from '../analysis/ImpactAnalyzer.js';
8
+ import { CytoscapeExporter } from '../exporters/CytoscapeExporter.js';
9
+ import { DotExporter, MermaidExporter } from '../exporters/DotExporter.js';
10
+ import { GraphMLExporter } from '../exporters/GraphMLExporter.js';
11
+ import { JsonExporter } from '../exporters/JsonExporter.js';
12
+ import { Neo4jExporter, ReactFlowExporter } from '../exporters/CytoscapeExporter.js';
13
+ import { ProjectLoader } from './ProjectLoader.js';
14
+ const program = new Command();
15
+ const loader = new ProjectLoader();
16
+ program
17
+ .name('cli-node-graph')
18
+ .description('TypeScript codebase knowledge graph analyzer')
19
+ .version('1.0.1');
20
+ program
21
+ .command('analyze')
22
+ .description('Analyze a TypeScript project and build the dependency graph')
23
+ .argument('[path]', 'Project root path', '.')
24
+ .option('--tsconfig <path>', 'Path to tsconfig.json', 'tsconfig.json')
25
+ .action((path, options) => {
26
+ const projectRoot = resolve(path);
27
+ console.error(`Analyzing ${projectRoot}...`);
28
+ const graph = loader.analyze({ projectRoot, tsconfigPath: options.tsconfig });
29
+ console.error(`Done: ${String(graph.nodeCount)} nodes, ${String(graph.edgeCount)} edges`);
30
+ console.log(JSON.stringify({ nodeCount: graph.nodeCount, edgeCount: graph.edgeCount }));
31
+ });
32
+ program
33
+ .command('graph')
34
+ .description('Show summary of the last analyzed graph')
35
+ .argument('[path]', 'Project root path', '.')
36
+ .action((path) => {
37
+ let graph = loader.getGraph();
38
+ if (!graph)
39
+ graph = loader.loadCache(resolve(path));
40
+ if (!graph) {
41
+ console.error('No graph found. Run: cli-node-graph analyze');
42
+ process.exit(1);
43
+ }
44
+ const stats = computeStats(graph);
45
+ console.log(JSON.stringify(stats, null, 2));
46
+ });
47
+ program
48
+ .command('export')
49
+ .description('Export the graph to a file format')
50
+ .argument('[path]', 'Project root path', '.')
51
+ .requiredOption('--format <format>', 'Export format (json|dot|graphml|cytoscape|reactflow|neo4j|mermaid)')
52
+ .option('-o, --output <file>', 'Output file path')
53
+ .action((path, options) => {
54
+ let graph = loader.getGraph();
55
+ if (!graph)
56
+ graph = loader.loadCache(resolve(path));
57
+ if (!graph) {
58
+ graph = loader.analyze({ projectRoot: resolve(path) });
59
+ }
60
+ const exporter = getExporter(options.format);
61
+ const output = exporter.export(graph);
62
+ const outFile = options.output ?? `cli-node-graph.${options.format === 'reactflow' ? 'json' : options.format}`;
63
+ if (options.output || !process.stdout.isTTY) {
64
+ writeFileSync(outFile, output);
65
+ console.error(`Exported to ${outFile}`);
66
+ }
67
+ else {
68
+ console.log(output);
69
+ }
70
+ });
71
+ program
72
+ .command('cycles')
73
+ .description('Detect circular dependencies')
74
+ .argument('[path]', 'Project root path', '.')
75
+ .action((path) => {
76
+ let graph = loader.getGraph();
77
+ if (!graph)
78
+ graph = loader.loadCache(resolve(path));
79
+ if (!graph) {
80
+ graph = loader.analyze({ projectRoot: resolve(path) });
81
+ }
82
+ const analyzer = new CircularDependencyAnalyzer();
83
+ const cycles = analyzer.analyze(graph);
84
+ console.log(JSON.stringify(cycles, null, 2));
85
+ });
86
+ program
87
+ .command('impact')
88
+ .description('Analyze downstream impact of a file or symbol')
89
+ .argument('<target>', 'File path or node id')
90
+ .argument('[path]', 'Project root path', '.')
91
+ .action((target, path) => {
92
+ let graph = loader.getGraph();
93
+ if (!graph)
94
+ graph = loader.loadCache(resolve(path));
95
+ if (!graph) {
96
+ graph = loader.analyze({ projectRoot: resolve(path) });
97
+ }
98
+ const analyzer = new ImpactAnalyzer();
99
+ const fileNode = graph.getNodes().find((n) => n.file?.includes(target) || n.id === target);
100
+ if (!fileNode) {
101
+ console.error(`Node not found: ${target}`);
102
+ process.exit(1);
103
+ }
104
+ const report = analyzer.analyze(graph, fileNode.id);
105
+ console.log(JSON.stringify(report, null, 2));
106
+ });
107
+ program
108
+ .command('stats')
109
+ .description('Show graph statistics')
110
+ .argument('[path]', 'Project root path', '.')
111
+ .action((path) => {
112
+ let graph = loader.getGraph();
113
+ if (!graph)
114
+ graph = loader.loadCache(resolve(path));
115
+ if (!graph) {
116
+ graph = loader.analyze({ projectRoot: resolve(path) });
117
+ }
118
+ const stats = computeStats(graph);
119
+ console.log(JSON.stringify(stats, null, 2));
120
+ });
121
+ function getExporter(format) {
122
+ const exporters = {
123
+ json: new JsonExporter(),
124
+ dot: new DotExporter(),
125
+ graphml: new GraphMLExporter(),
126
+ cytoscape: new CytoscapeExporter(),
127
+ reactflow: new ReactFlowExporter(),
128
+ neo4j: new Neo4jExporter(),
129
+ mermaid: new MermaidExporter(),
130
+ };
131
+ const exporter = exporters[format];
132
+ if (!exporter) {
133
+ console.error(`Unknown format: ${format}. Available: ${Object.keys(exporters).join(', ')}`);
134
+ process.exit(1);
135
+ }
136
+ return exporter;
137
+ }
138
+ program.parse();
139
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;AAEnC,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,8CAA8C,CAAC;KAC3D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,6DAA6D,CAAC;KAC1E,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAC5C,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,eAAe,CAAC;KACrE,MAAM,CAAC,CAAC,IAAY,EAAE,OAA6B,EAAE,EAAE;IACtD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,KAAK,CAAC,aAAa,WAAW,KAAK,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9E,OAAO,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1F,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;AAC1F,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yCAAyC,CAAC;KACtD,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAC5C,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;IACvB,IAAI,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mCAAmC,CAAC;KAChD,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAC5C,cAAc,CAAC,mBAAmB,EAAE,oEAAoE,CAAC;KACzG,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;KACjD,MAAM,CAAC,CAAC,IAAY,EAAE,OAA4C,EAAE,EAAE;IACrE,IAAI,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,kBAAkB,OAAO,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IAE/G,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC5C,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,8BAA8B,CAAC;KAC3C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAC5C,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;IACvB,IAAI,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,0BAA0B,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;KAC5C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAC5C,MAAM,CAAC,CAAC,MAAc,EAAE,IAAY,EAAE,EAAE;IACvC,IAAI,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IAC3F,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,uBAAuB,CAAC;KACpC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAC5C,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;IACvB,IAAI,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEL,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,SAAS,GAAkC;QAC/C,IAAI,EAAE,IAAI,YAAY,EAAE;QACxB,GAAG,EAAE,IAAI,WAAW,EAAE;QACtB,OAAO,EAAE,IAAI,eAAe,EAAE;QAC9B,SAAS,EAAE,IAAI,iBAAiB,EAAE;QAClC,SAAS,EAAE,IAAI,iBAAiB,EAAE;QAClC,KAAK,EAAE,IAAI,aAAa,EAAE;QAC1B,OAAO,EAAE,IAAI,eAAe,EAAE;KAC/B,CAAC;IACF,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,gBAAgB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,KAAK,EAAE,CAAC"}