@ash-technologia/fathom 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +725 -0
  4. package/dist/analyzers/architecture/graph.d.ts +29 -0
  5. package/dist/analyzers/architecture/graph.d.ts.map +1 -0
  6. package/dist/analyzers/architecture/graph.js +347 -0
  7. package/dist/analyzers/architecture/graph.js.map +1 -0
  8. package/dist/analyzers/architecture/imports.d.ts +24 -0
  9. package/dist/analyzers/architecture/imports.d.ts.map +1 -0
  10. package/dist/analyzers/architecture/imports.js +155 -0
  11. package/dist/analyzers/architecture/imports.js.map +1 -0
  12. package/dist/analyzers/architecture/index.d.ts +13 -0
  13. package/dist/analyzers/architecture/index.d.ts.map +1 -0
  14. package/dist/analyzers/architecture/index.js +217 -0
  15. package/dist/analyzers/architecture/index.js.map +1 -0
  16. package/dist/analyzers/architecture/types.d.ts +65 -0
  17. package/dist/analyzers/architecture/types.d.ts.map +1 -0
  18. package/dist/analyzers/architecture/types.js +2 -0
  19. package/dist/analyzers/architecture/types.js.map +1 -0
  20. package/dist/analyzers/cicd/index.d.ts +11 -0
  21. package/dist/analyzers/cicd/index.d.ts.map +1 -0
  22. package/dist/analyzers/cicd/index.js +157 -0
  23. package/dist/analyzers/cicd/index.js.map +1 -0
  24. package/dist/analyzers/dependencies/index.d.ts +11 -0
  25. package/dist/analyzers/dependencies/index.d.ts.map +1 -0
  26. package/dist/analyzers/dependencies/index.js +403 -0
  27. package/dist/analyzers/dependencies/index.js.map +1 -0
  28. package/dist/analyzers/dependencies/lockfiles.d.ts +19 -0
  29. package/dist/analyzers/dependencies/lockfiles.d.ts.map +1 -0
  30. package/dist/analyzers/dependencies/lockfiles.js +172 -0
  31. package/dist/analyzers/dependencies/lockfiles.js.map +1 -0
  32. package/dist/analyzers/dependencies/online.d.ts +19 -0
  33. package/dist/analyzers/dependencies/online.d.ts.map +1 -0
  34. package/dist/analyzers/dependencies/online.js +116 -0
  35. package/dist/analyzers/dependencies/online.js.map +1 -0
  36. package/dist/analyzers/dependencies/types.d.ts +49 -0
  37. package/dist/analyzers/dependencies/types.d.ts.map +1 -0
  38. package/dist/analyzers/dependencies/types.js +2 -0
  39. package/dist/analyzers/dependencies/types.js.map +1 -0
  40. package/dist/analyzers/documentation/index.d.ts +11 -0
  41. package/dist/analyzers/documentation/index.d.ts.map +1 -0
  42. package/dist/analyzers/documentation/index.js +166 -0
  43. package/dist/analyzers/documentation/index.js.map +1 -0
  44. package/dist/analyzers/git/index.d.ts +11 -0
  45. package/dist/analyzers/git/index.d.ts.map +1 -0
  46. package/dist/analyzers/git/index.js +180 -0
  47. package/dist/analyzers/git/index.js.map +1 -0
  48. package/dist/analyzers/project/index.d.ts +11 -0
  49. package/dist/analyzers/project/index.d.ts.map +1 -0
  50. package/dist/analyzers/project/index.js +95 -0
  51. package/dist/analyzers/project/index.js.map +1 -0
  52. package/dist/analyzers/quality/index.d.ts +11 -0
  53. package/dist/analyzers/quality/index.d.ts.map +1 -0
  54. package/dist/analyzers/quality/index.js +198 -0
  55. package/dist/analyzers/quality/index.js.map +1 -0
  56. package/dist/analyzers/security/index.d.ts +11 -0
  57. package/dist/analyzers/security/index.d.ts.map +1 -0
  58. package/dist/analyzers/security/index.js +236 -0
  59. package/dist/analyzers/security/index.js.map +1 -0
  60. package/dist/analyzers/testing/index.d.ts +11 -0
  61. package/dist/analyzers/testing/index.d.ts.map +1 -0
  62. package/dist/analyzers/testing/index.js +134 -0
  63. package/dist/analyzers/testing/index.js.map +1 -0
  64. package/dist/baseline/baseline.d.ts +20 -0
  65. package/dist/baseline/baseline.d.ts.map +1 -0
  66. package/dist/baseline/baseline.js +134 -0
  67. package/dist/baseline/baseline.js.map +1 -0
  68. package/dist/baseline/compare.d.ts +14 -0
  69. package/dist/baseline/compare.d.ts.map +1 -0
  70. package/dist/baseline/compare.js +113 -0
  71. package/dist/baseline/compare.js.map +1 -0
  72. package/dist/baseline/types.d.ts +25 -0
  73. package/dist/baseline/types.d.ts.map +1 -0
  74. package/dist/baseline/types.js +2 -0
  75. package/dist/baseline/types.js.map +1 -0
  76. package/dist/cli/commands.d.ts +39 -0
  77. package/dist/cli/commands.d.ts.map +1 -0
  78. package/dist/cli/commands.js +277 -0
  79. package/dist/cli/commands.js.map +1 -0
  80. package/dist/cli/index.d.ts +3 -0
  81. package/dist/cli/index.d.ts.map +1 -0
  82. package/dist/cli/index.js +29 -0
  83. package/dist/cli/index.js.map +1 -0
  84. package/dist/cli/options.d.ts +55 -0
  85. package/dist/cli/options.d.ts.map +1 -0
  86. package/dist/cli/options.js +258 -0
  87. package/dist/cli/options.js.map +1 -0
  88. package/dist/core/analyzer.d.ts +33 -0
  89. package/dist/core/analyzer.d.ts.map +1 -0
  90. package/dist/core/analyzer.js +19 -0
  91. package/dist/core/analyzer.js.map +1 -0
  92. package/dist/core/context.d.ts +90 -0
  93. package/dist/core/context.d.ts.map +1 -0
  94. package/dist/core/context.js +159 -0
  95. package/dist/core/context.js.map +1 -0
  96. package/dist/core/errors.d.ts +74 -0
  97. package/dist/core/errors.d.ts.map +1 -0
  98. package/dist/core/errors.js +109 -0
  99. package/dist/core/errors.js.map +1 -0
  100. package/dist/core/findings.d.ts +59 -0
  101. package/dist/core/findings.d.ts.map +1 -0
  102. package/dist/core/findings.js +34 -0
  103. package/dist/core/findings.js.map +1 -0
  104. package/dist/core/orchestrator.d.ts +44 -0
  105. package/dist/core/orchestrator.d.ts.map +1 -0
  106. package/dist/core/orchestrator.js +160 -0
  107. package/dist/core/orchestrator.js.map +1 -0
  108. package/dist/core/result.d.ts +169 -0
  109. package/dist/core/result.d.ts.map +1 -0
  110. package/dist/core/result.js +2 -0
  111. package/dist/core/result.js.map +1 -0
  112. package/dist/detectors/framework.d.ts +22 -0
  113. package/dist/detectors/framework.d.ts.map +1 -0
  114. package/dist/detectors/framework.js +147 -0
  115. package/dist/detectors/framework.js.map +1 -0
  116. package/dist/detectors/language.d.ts +13 -0
  117. package/dist/detectors/language.d.ts.map +1 -0
  118. package/dist/detectors/language.js +100 -0
  119. package/dist/detectors/language.js.map +1 -0
  120. package/dist/detectors/package-manager.d.ts +17 -0
  121. package/dist/detectors/package-manager.d.ts.map +1 -0
  122. package/dist/detectors/package-manager.js +67 -0
  123. package/dist/detectors/package-manager.js.map +1 -0
  124. package/dist/detectors/project-type.d.ts +20 -0
  125. package/dist/detectors/project-type.d.ts.map +1 -0
  126. package/dist/detectors/project-type.js +48 -0
  127. package/dist/detectors/project-type.js.map +1 -0
  128. package/dist/diff/analyzer.d.ts +16 -0
  129. package/dist/diff/analyzer.d.ts.map +1 -0
  130. package/dist/diff/analyzer.js +296 -0
  131. package/dist/diff/analyzer.js.map +1 -0
  132. package/dist/diff/git-diff.d.ts +44 -0
  133. package/dist/diff/git-diff.d.ts.map +1 -0
  134. package/dist/diff/git-diff.js +256 -0
  135. package/dist/diff/git-diff.js.map +1 -0
  136. package/dist/diff/types.d.ts +75 -0
  137. package/dist/diff/types.d.ts.map +1 -0
  138. package/dist/diff/types.js +2 -0
  139. package/dist/diff/types.js.map +1 -0
  140. package/dist/integrations/github/context.d.ts +22 -0
  141. package/dist/integrations/github/context.d.ts.map +1 -0
  142. package/dist/integrations/github/context.js +115 -0
  143. package/dist/integrations/github/context.js.map +1 -0
  144. package/dist/integrations/github/types.d.ts +30 -0
  145. package/dist/integrations/github/types.d.ts.map +1 -0
  146. package/dist/integrations/github/types.js +2 -0
  147. package/dist/integrations/github/types.js.map +1 -0
  148. package/dist/plugins/context.d.ts +13 -0
  149. package/dist/plugins/context.d.ts.map +1 -0
  150. package/dist/plugins/context.js +102 -0
  151. package/dist/plugins/context.js.map +1 -0
  152. package/dist/plugins/examples/react.d.ts +8 -0
  153. package/dist/plugins/examples/react.d.ts.map +1 -0
  154. package/dist/plugins/examples/react.js +129 -0
  155. package/dist/plugins/examples/react.js.map +1 -0
  156. package/dist/plugins/index.d.ts +5 -0
  157. package/dist/plugins/index.d.ts.map +1 -0
  158. package/dist/plugins/index.js +4 -0
  159. package/dist/plugins/index.js.map +1 -0
  160. package/dist/plugins/registry.d.ts +45 -0
  161. package/dist/plugins/registry.d.ts.map +1 -0
  162. package/dist/plugins/registry.js +236 -0
  163. package/dist/plugins/registry.js.map +1 -0
  164. package/dist/plugins/types.d.ts +148 -0
  165. package/dist/plugins/types.d.ts.map +1 -0
  166. package/dist/plugins/types.js +2 -0
  167. package/dist/plugins/types.js.map +1 -0
  168. package/dist/reporters/html.d.ts +11 -0
  169. package/dist/reporters/html.d.ts.map +1 -0
  170. package/dist/reporters/html.js +1352 -0
  171. package/dist/reporters/html.js.map +1 -0
  172. package/dist/reporters/json.d.ts +10 -0
  173. package/dist/reporters/json.d.ts.map +1 -0
  174. package/dist/reporters/json.js +11 -0
  175. package/dist/reporters/json.js.map +1 -0
  176. package/dist/reporters/markdown.d.ts +7 -0
  177. package/dist/reporters/markdown.d.ts.map +1 -0
  178. package/dist/reporters/markdown.js +74 -0
  179. package/dist/reporters/markdown.js.map +1 -0
  180. package/dist/reporters/sarif.d.ts +133 -0
  181. package/dist/reporters/sarif.d.ts.map +1 -0
  182. package/dist/reporters/sarif.js +268 -0
  183. package/dist/reporters/sarif.js.map +1 -0
  184. package/dist/reporters/terminal.d.ts +17 -0
  185. package/dist/reporters/terminal.d.ts.map +1 -0
  186. package/dist/reporters/terminal.js +423 -0
  187. package/dist/reporters/terminal.js.map +1 -0
  188. package/dist/rules/categories.d.ts +8 -0
  189. package/dist/rules/categories.d.ts.map +1 -0
  190. package/dist/rules/categories.js +23 -0
  191. package/dist/rules/categories.js.map +1 -0
  192. package/dist/rules/definitions.d.ts +25 -0
  193. package/dist/rules/definitions.d.ts.map +1 -0
  194. package/dist/rules/definitions.js +429 -0
  195. package/dist/rules/definitions.js.map +1 -0
  196. package/dist/rules/registry.d.ts +36 -0
  197. package/dist/rules/registry.d.ts.map +1 -0
  198. package/dist/rules/registry.js +64 -0
  199. package/dist/rules/registry.js.map +1 -0
  200. package/dist/rules/severity.d.ts +13 -0
  201. package/dist/rules/severity.d.ts.map +1 -0
  202. package/dist/rules/severity.js +15 -0
  203. package/dist/rules/severity.js.map +1 -0
  204. package/dist/scoring/confidence.d.ts +12 -0
  205. package/dist/scoring/confidence.d.ts.map +1 -0
  206. package/dist/scoring/confidence.js +22 -0
  207. package/dist/scoring/confidence.js.map +1 -0
  208. package/dist/scoring/score.d.ts +27 -0
  209. package/dist/scoring/score.d.ts.map +1 -0
  210. package/dist/scoring/score.js +81 -0
  211. package/dist/scoring/score.js.map +1 -0
  212. package/dist/scoring/weights.d.ts +11 -0
  213. package/dist/scoring/weights.d.ts.map +1 -0
  214. package/dist/scoring/weights.js +26 -0
  215. package/dist/scoring/weights.js.map +1 -0
  216. package/dist/utils/filesystem.d.ts +65 -0
  217. package/dist/utils/filesystem.d.ts.map +1 -0
  218. package/dist/utils/filesystem.js +299 -0
  219. package/dist/utils/filesystem.js.map +1 -0
  220. package/dist/utils/git.d.ts +47 -0
  221. package/dist/utils/git.d.ts.map +1 -0
  222. package/dist/utils/git.js +125 -0
  223. package/dist/utils/git.js.map +1 -0
  224. package/dist/utils/logger.d.ts +14 -0
  225. package/dist/utils/logger.d.ts.map +1 -0
  226. package/dist/utils/logger.js +25 -0
  227. package/dist/utils/logger.js.map +1 -0
  228. package/dist/utils/paths.d.ts +30 -0
  229. package/dist/utils/paths.d.ts.map +1 -0
  230. package/dist/utils/paths.js +48 -0
  231. package/dist/utils/paths.js.map +1 -0
  232. package/dist/utils/timing.d.ts +12 -0
  233. package/dist/utils/timing.d.ts.map +1 -0
  234. package/dist/utils/timing.js +19 -0
  235. package/dist/utils/timing.js.map +1 -0
  236. package/package.json +73 -0
@@ -0,0 +1,29 @@
1
+ import type { ArchitectureGraph, ArchitectureLayer, ArchitectureRole, ArchitectureWarning, ArchitectureSummary } from './types.js';
2
+ export interface FileData {
3
+ relativePath: string;
4
+ lineCount: number;
5
+ isTest: boolean;
6
+ imports: string[];
7
+ externalImports: string[];
8
+ }
9
+ /**
10
+ * Classifies a relative path into an architectural layer.
11
+ */
12
+ export declare function classifyLayer(relativePath: string, isTest: boolean): ArchitectureLayer;
13
+ /**
14
+ * Classifies a file into a functional role.
15
+ */
16
+ export declare function classifyRole(relativePath: string): ArchitectureRole;
17
+ /**
18
+ * Tarjan's algorithm for finding Strongly Connected Components (cycles) in a directed graph.
19
+ */
20
+ export declare function findCircularDependencies(adjacency: Map<string, Set<string>>): string[][];
21
+ /**
22
+ * Builds the in-memory architecture graph and analyzes patterns, cycles, and boundary violations.
23
+ */
24
+ export declare function buildArchitectureModel(fileDataList: FileData[]): {
25
+ graph: ArchitectureGraph;
26
+ summary: ArchitectureSummary;
27
+ warnings: ArchitectureWarning[];
28
+ };
29
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/analyzers/architecture/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAGjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,iBAAiB,CA2EtF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAuBnE;AA0BD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,EAAE,CAyDxF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG;IAChE,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC,CA6LA"}
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Classifies a relative path into an architectural layer.
3
+ */
4
+ export function classifyLayer(relativePath, isTest) {
5
+ if (isTest)
6
+ return 'test';
7
+ const lower = relativePath.toLowerCase();
8
+ const segments = lower.split('/');
9
+ // Config files at root
10
+ if (segments.length === 1 &&
11
+ (lower.endsWith('.json') ||
12
+ lower.includes('.config.') ||
13
+ lower.endsWith('.rc') ||
14
+ lower.endsWith('.lock'))) {
15
+ return 'config';
16
+ }
17
+ // Explicit frontend patterns
18
+ if (lower.startsWith('frontend/') ||
19
+ lower.startsWith('client/') ||
20
+ lower.startsWith('web/') ||
21
+ lower.startsWith('ui/') ||
22
+ segments.includes('frontend') ||
23
+ segments.includes('client') ||
24
+ segments.includes('ui') ||
25
+ segments.includes('components') ||
26
+ segments.includes('pages') ||
27
+ segments.includes('views') ||
28
+ segments.includes('hooks') ||
29
+ segments.includes('styles') ||
30
+ lower.endsWith('.tsx') ||
31
+ lower.endsWith('.jsx') ||
32
+ lower.endsWith('.vue') ||
33
+ lower.endsWith('.svelte')) {
34
+ return 'frontend';
35
+ }
36
+ // Explicit backend patterns
37
+ if (lower.startsWith('backend/') ||
38
+ lower.startsWith('server/') ||
39
+ lower.startsWith('api/') ||
40
+ segments.includes('backend') ||
41
+ segments.includes('server') ||
42
+ segments.includes('api') ||
43
+ segments.includes('controllers') ||
44
+ segments.includes('routes') ||
45
+ segments.includes('services') ||
46
+ segments.includes('models') ||
47
+ segments.includes('repositories') ||
48
+ segments.includes('entities') ||
49
+ segments.includes('db') ||
50
+ segments.includes('database') ||
51
+ segments.includes('migrations')) {
52
+ return 'backend';
53
+ }
54
+ // Shared / Common patterns
55
+ if (lower.startsWith('shared/') ||
56
+ lower.startsWith('common/') ||
57
+ segments.includes('shared') ||
58
+ segments.includes('common') ||
59
+ segments.includes('utils') ||
60
+ segments.includes('helpers') ||
61
+ segments.includes('types') ||
62
+ segments.includes('lib')) {
63
+ return 'shared';
64
+ }
65
+ return 'unknown';
66
+ }
67
+ /**
68
+ * Classifies a file into a functional role.
69
+ */
70
+ export function classifyRole(relativePath) {
71
+ const lower = relativePath.toLowerCase();
72
+ const segments = lower.split('/');
73
+ const filename = segments[segments.length - 1] ?? '';
74
+ if (/^(index|main|app|server|cli)\.[a-z0-9]+$/i.test(filename))
75
+ return 'entry';
76
+ if (segments.includes('components') ||
77
+ lower.endsWith('.component.ts') ||
78
+ lower.endsWith('.tsx') ||
79
+ lower.endsWith('.jsx'))
80
+ return 'component';
81
+ if (segments.includes('pages') || segments.includes('views') || filename.startsWith('page.'))
82
+ return 'page';
83
+ if (segments.includes('routes') || filename.startsWith('route.'))
84
+ return 'route';
85
+ if (segments.includes('controllers') || lower.endsWith('.controller.ts'))
86
+ return 'controller';
87
+ if (segments.includes('services') || lower.endsWith('.service.ts'))
88
+ return 'service';
89
+ if (segments.includes('models') || segments.includes('entities') || lower.endsWith('.model.ts'))
90
+ return 'model';
91
+ if (segments.includes('utils') || segments.includes('helpers'))
92
+ return 'util';
93
+ return 'unknown';
94
+ }
95
+ /**
96
+ * Checks if a file is an expected entry point that legitimately has no inbound imports.
97
+ */
98
+ function isExpectedEntryPoint(relativePath) {
99
+ const lower = relativePath.toLowerCase();
100
+ const segments = lower.split('/');
101
+ const filename = segments[segments.length - 1] ?? '';
102
+ if (/^(index|main|app|server|cli|worker|run)\.[a-z0-9]+$/i.test(filename))
103
+ return true;
104
+ if (/^vite\.config|^webpack\.config|^rollup\.config|^jest\.config|^vitest\.config|^next\.config/i.test(filename))
105
+ return true;
106
+ if (/^(page|layout|route|loading|error|not-found)\.[a-z0-9]+$/i.test(filename))
107
+ return true; // Next.js
108
+ if (filename.startsWith('+page') || filename.startsWith('+layout'))
109
+ return true; // SvelteKit
110
+ if (lower.startsWith('scripts/') || lower.startsWith('bin/'))
111
+ return true;
112
+ if (lower.includes('__tests__') || lower.includes('/tests/') || lower.includes('/test/'))
113
+ return true;
114
+ return false;
115
+ }
116
+ /**
117
+ * Tarjan's algorithm for finding Strongly Connected Components (cycles) in a directed graph.
118
+ */
119
+ export function findCircularDependencies(adjacency) {
120
+ let index = 0;
121
+ const indices = new Map();
122
+ const lowlink = new Map();
123
+ const onStack = new Set();
124
+ const stack = [];
125
+ const sccs = [];
126
+ function strongconnect(node) {
127
+ indices.set(node, index);
128
+ lowlink.set(node, index);
129
+ index++;
130
+ stack.push(node);
131
+ onStack.add(node);
132
+ const neighbors = adjacency.get(node) ?? new Set();
133
+ for (const neighbor of neighbors) {
134
+ if (!indices.has(neighbor)) {
135
+ strongconnect(neighbor);
136
+ const nodeLow = lowlink.get(node) ?? 0;
137
+ const neighborLow = lowlink.get(neighbor) ?? 0;
138
+ lowlink.set(node, Math.min(nodeLow, neighborLow));
139
+ }
140
+ else if (onStack.has(neighbor)) {
141
+ const nodeLow = lowlink.get(node) ?? 0;
142
+ const neighborIndex = indices.get(neighbor) ?? 0;
143
+ lowlink.set(node, Math.min(nodeLow, neighborIndex));
144
+ }
145
+ }
146
+ if (lowlink.get(node) === indices.get(node)) {
147
+ const scc = [];
148
+ let w;
149
+ do {
150
+ w = stack.pop();
151
+ if (w !== undefined) {
152
+ onStack.delete(w);
153
+ scc.push(w);
154
+ }
155
+ } while (w !== undefined && w !== node);
156
+ // Only SCCs with size > 1 (or self-loops) are circular cycles
157
+ if (scc.length > 1) {
158
+ sccs.push(scc);
159
+ }
160
+ else if (scc.length === 1 && scc[0] && (adjacency.get(scc[0]) ?? new Set()).has(scc[0])) {
161
+ sccs.push(scc);
162
+ }
163
+ }
164
+ }
165
+ for (const node of adjacency.keys()) {
166
+ if (!indices.has(node)) {
167
+ strongconnect(node);
168
+ }
169
+ }
170
+ // Sort cycles deterministically
171
+ return sccs.map((c) => [...c].sort()).sort((a, b) => (a[0] ?? '').localeCompare(b[0] ?? ''));
172
+ }
173
+ /**
174
+ * Builds the in-memory architecture graph and analyzes patterns, cycles, and boundary violations.
175
+ */
176
+ export function buildArchitectureModel(fileDataList) {
177
+ const nodes = new Map();
178
+ const edges = [];
179
+ const adjacency = new Map();
180
+ const reverseAdjacency = new Map();
181
+ // 1. Initialize nodes
182
+ for (const f of fileDataList) {
183
+ const layer = classifyLayer(f.relativePath, f.isTest);
184
+ const role = classifyRole(f.relativePath);
185
+ nodes.set(f.relativePath, {
186
+ id: f.relativePath,
187
+ type: 'file',
188
+ layer,
189
+ role,
190
+ lineCount: f.lineCount,
191
+ inDegree: 0,
192
+ outDegree: 0,
193
+ });
194
+ adjacency.set(f.relativePath, new Set());
195
+ reverseAdjacency.set(f.relativePath, new Set());
196
+ }
197
+ // 2. Build edges
198
+ for (const f of fileDataList) {
199
+ for (const target of f.imports) {
200
+ if (nodes.has(target)) {
201
+ edges.push({
202
+ source: f.relativePath,
203
+ target,
204
+ type: 'import',
205
+ });
206
+ const sourceAdj = adjacency.get(f.relativePath);
207
+ if (sourceAdj)
208
+ sourceAdj.add(target);
209
+ const targetRev = reverseAdjacency.get(target);
210
+ if (targetRev)
211
+ targetRev.add(f.relativePath);
212
+ }
213
+ }
214
+ }
215
+ // 3. Update inDegree & outDegree
216
+ for (const [id, node] of nodes) {
217
+ node.outDegree = adjacency.get(id)?.size ?? 0;
218
+ node.inDegree = reverseAdjacency.get(id)?.size ?? 0;
219
+ }
220
+ // 4. Detect Circular Dependencies
221
+ const cycles = findCircularDependencies(adjacency);
222
+ const warnings = [];
223
+ for (const cycle of cycles) {
224
+ warnings.push({
225
+ type: 'circular',
226
+ severity: 'high',
227
+ message: `Circular dependency candidate detected: ${cycle.join(' ⇄ ')}`,
228
+ files: cycle,
229
+ });
230
+ }
231
+ // 5. Detect Boundary Violations
232
+ const SERVER_ONLY_PACKAGES = new Set([
233
+ 'fs',
234
+ 'node:fs',
235
+ 'child_process',
236
+ 'node:child_process',
237
+ 'cluster',
238
+ 'net',
239
+ 'dns',
240
+ ]);
241
+ for (const f of fileDataList) {
242
+ const sourceNode = nodes.get(f.relativePath);
243
+ if (!sourceNode)
244
+ continue;
245
+ // Boundary 1: Backend importing Frontend
246
+ if (sourceNode.layer === 'backend') {
247
+ for (const target of f.imports) {
248
+ const targetNode = nodes.get(target);
249
+ if (targetNode?.layer === 'frontend') {
250
+ warnings.push({
251
+ type: 'boundary',
252
+ severity: 'high',
253
+ message: `Architectural boundary violation: Backend module "${f.relativePath}" imports frontend module "${target}".`,
254
+ files: [f.relativePath, target],
255
+ });
256
+ }
257
+ }
258
+ }
259
+ // Boundary 2: Client code importing server-only packages
260
+ if (sourceNode.layer === 'frontend') {
261
+ for (const extPkg of f.externalImports) {
262
+ if (SERVER_ONLY_PACKAGES.has(extPkg)) {
263
+ warnings.push({
264
+ type: 'boundary',
265
+ severity: 'high',
266
+ message: `Architectural boundary violation: Client-side module "${f.relativePath}" imports server-only package "${extPkg}".`,
267
+ files: [f.relativePath],
268
+ });
269
+ }
270
+ }
271
+ }
272
+ // Boundary 3: Deep coupling (> 15 internal imports)
273
+ if (sourceNode.outDegree > 15 &&
274
+ !sourceNode.id.includes('index.') &&
275
+ sourceNode.layer !== 'test') {
276
+ warnings.push({
277
+ type: 'coupling',
278
+ severity: 'low',
279
+ message: `Deep coupling: "${f.relativePath}" has a high fan-out coupling, importing ${sourceNode.outDegree} distinct modules.`,
280
+ files: [f.relativePath],
281
+ });
282
+ }
283
+ // Boundary 4: Very large module (> 400 lines and outDegree > 8)
284
+ if (sourceNode.lineCount > 400 && sourceNode.outDegree > 8 && sourceNode.layer !== 'test') {
285
+ warnings.push({
286
+ type: 'large',
287
+ severity: 'low',
288
+ message: `Very large module: "${f.relativePath}" has ${sourceNode.lineCount} lines and imports ${sourceNode.outDegree} modules.`,
289
+ files: [f.relativePath],
290
+ });
291
+ }
292
+ // Boundary 5: Orphaned source file (inDegree == 0, not an entry point or test)
293
+ // Confident detection:
294
+ // 1) Explicit dead/orphan names: "dead-code.ts", "unused.ts", "orphan.ts", "abandoned.ts"
295
+ // 2) OR: nested modules in a project with >= 4 files where the file is neither an entry point,
296
+ // nor a top-level root file (e.g. `src/math.ts` or `src/calc.ts` are root files directly under src)
297
+ const isExplicitDead = /dead|orphan|unused|abandoned/i.test(f.relativePath);
298
+ const isNestedSource = f.relativePath.split('/').length > 2;
299
+ const isOrphanCandidate = isExplicitDead || (fileDataList.length >= 4 && isNestedSource);
300
+ if (sourceNode.inDegree === 0 &&
301
+ sourceNode.layer !== 'test' &&
302
+ sourceNode.layer !== 'config' &&
303
+ !isExpectedEntryPoint(f.relativePath) &&
304
+ isOrphanCandidate) {
305
+ warnings.push({
306
+ type: 'orphan',
307
+ severity: 'info',
308
+ message: `Orphaned source file: "${f.relativePath}" is not imported by any module in the repository.`,
309
+ files: [f.relativePath],
310
+ });
311
+ }
312
+ }
313
+ // 6. Build layer summaries for reporting
314
+ const layerMap = new Map();
315
+ for (const [, node] of nodes) {
316
+ if (node.layer === 'test' || node.layer === 'config' || node.layer === 'unknown')
317
+ continue;
318
+ const layerName = node.layer.charAt(0).toUpperCase() + node.layer.slice(1);
319
+ let compMap = layerMap.get(layerName);
320
+ if (!compMap) {
321
+ compMap = new Map();
322
+ layerMap.set(layerName, compMap);
323
+ }
324
+ const roleKey = node.role !== 'unknown' ? `${node.role}s` : 'other';
325
+ compMap.set(roleKey, (compMap.get(roleKey) ?? 0) + 1);
326
+ }
327
+ const layers = [];
328
+ for (const [name, compMap] of layerMap) {
329
+ const components = [...compMap.entries()]
330
+ .map(([compName, fileCount]) => ({ name: compName, fileCount }))
331
+ .sort((a, b) => b.fileCount - a.fileCount);
332
+ layers.push({ name, components });
333
+ }
334
+ const summary = {
335
+ layers,
336
+ warnings,
337
+ nodeCount: nodes.size,
338
+ edgeCount: edges.length,
339
+ circularDependencies: cycles,
340
+ };
341
+ const graph = {
342
+ nodes: [...nodes.values()],
343
+ edges,
344
+ };
345
+ return { graph, summary, warnings };
346
+ }
347
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../src/analyzers/architecture/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface PathAliasConfig {
2
+ baseUrl: string;
3
+ paths: Record<string, string[]>;
4
+ }
5
+ export interface ExtractedImport {
6
+ specifier: string;
7
+ isRelative: boolean;
8
+ resolvedPath?: string | undefined;
9
+ isExternal: boolean;
10
+ packageName?: string | undefined;
11
+ }
12
+ /**
13
+ * Extracts tsconfig / jsconfig compilerOptions.paths and baseUrl if present.
14
+ */
15
+ export declare function extractPathAliases(configContent?: string | null): PathAliasConfig | null;
16
+ /**
17
+ * Parses import and export statements from source file text without executing code.
18
+ */
19
+ export declare function extractRawSpecifiers(content: string, extension: string): string[];
20
+ /**
21
+ * Resolves an import specifier to a known relative file in the repository if possible.
22
+ */
23
+ export declare function resolveImportSpecifier(specifier: string, fromFile: string, knownFiles: Set<string>, aliasConfig?: PathAliasConfig | null): ExtractedImport;
24
+ //# sourceMappingURL=imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../../src/analyzers/architecture/imports.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAkBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe,GAAG,IAAI,CAsBxF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CA4CjF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,GACnC,eAAe,CAyEjB"}
@@ -0,0 +1,155 @@
1
+ import path from 'node:path';
2
+ import { normalizeSlashes } from '../../utils/paths.js';
3
+ const JS_TS_EXTENSIONS = [
4
+ '',
5
+ '.ts',
6
+ '.tsx',
7
+ '.js',
8
+ '.jsx',
9
+ '.mjs',
10
+ '.cjs',
11
+ '/index.ts',
12
+ '/index.tsx',
13
+ '/index.js',
14
+ '/index.jsx',
15
+ '/index.mjs',
16
+ '/index.cjs',
17
+ ];
18
+ /**
19
+ * Extracts tsconfig / jsconfig compilerOptions.paths and baseUrl if present.
20
+ */
21
+ export function extractPathAliases(configContent) {
22
+ if (!configContent)
23
+ return null;
24
+ try {
25
+ // Strip single-line comments in json
26
+ const sanitized = configContent.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
27
+ const parsed = JSON.parse(sanitized);
28
+ if (parsed.compilerOptions?.paths) {
29
+ return {
30
+ baseUrl: parsed.compilerOptions.baseUrl ?? '.',
31
+ paths: parsed.compilerOptions.paths,
32
+ };
33
+ }
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ return null;
39
+ }
40
+ /**
41
+ * Parses import and export statements from source file text without executing code.
42
+ */
43
+ export function extractRawSpecifiers(content, extension) {
44
+ const specifiers = new Set();
45
+ if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(extension.toLowerCase())) {
46
+ // 1. Static imports & re-exports: import/export ... from ['"]specifier['"]
47
+ const staticImportRegex = /(?:import|export)\s+(?:type\s+)?(?:[\s\w*${},]*\s+from\s+)?['"]([^'"]+)['"]/g;
48
+ let match;
49
+ while ((match = staticImportRegex.exec(content)) !== null) {
50
+ if (match[1])
51
+ specifiers.add(match[1]);
52
+ }
53
+ // 2. Bare imports: import ['"]specifier['"]
54
+ const bareImportRegex = /import\s+['"]([^'"]+)['"]/g;
55
+ while ((match = bareImportRegex.exec(content)) !== null) {
56
+ if (match[1])
57
+ specifiers.add(match[1]);
58
+ }
59
+ // 3. Dynamic imports: import(['"]specifier['"])
60
+ const dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
61
+ while ((match = dynamicImportRegex.exec(content)) !== null) {
62
+ if (match[1])
63
+ specifiers.add(match[1]);
64
+ }
65
+ // 4. CommonJS requires: require(['"]specifier['"])
66
+ const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
67
+ while ((match = requireRegex.exec(content)) !== null) {
68
+ if (match[1])
69
+ specifiers.add(match[1]);
70
+ }
71
+ }
72
+ else if (['.py', '.pyw'].includes(extension.toLowerCase())) {
73
+ // Python imports: from foo import bar or import foo
74
+ const pyFromRegex = /^\s*from\s+([a-zA-Z0-9_.]+)\s+import/gm;
75
+ let match;
76
+ while ((match = pyFromRegex.exec(content)) !== null) {
77
+ if (match[1])
78
+ specifiers.add(match[1]);
79
+ }
80
+ const pyImportRegex = /^\s*import\s+([a-zA-Z0-9_.]+)/gm;
81
+ while ((match = pyImportRegex.exec(content)) !== null) {
82
+ if (match[1])
83
+ specifiers.add(match[1]);
84
+ }
85
+ }
86
+ return [...specifiers];
87
+ }
88
+ /**
89
+ * Resolves an import specifier to a known relative file in the repository if possible.
90
+ */
91
+ export function resolveImportSpecifier(specifier, fromFile, knownFiles, aliasConfig) {
92
+ const isRelative = specifier.startsWith('./') ||
93
+ specifier.startsWith('../') ||
94
+ specifier === '.' ||
95
+ specifier === '..';
96
+ if (isRelative) {
97
+ const fromDir = path.dirname(fromFile);
98
+ const resolvedBase = normalizeSlashes(path.normalize(path.join(fromDir, specifier)));
99
+ const baseWithoutJs = resolvedBase.replace(/\.(js|mjs|cjs)$/, '');
100
+ for (const base of [resolvedBase, baseWithoutJs]) {
101
+ for (const ext of JS_TS_EXTENSIONS) {
102
+ let candidate = base + ext;
103
+ if (candidate.startsWith('./'))
104
+ candidate = candidate.slice(2);
105
+ if (knownFiles.has(candidate)) {
106
+ return {
107
+ specifier,
108
+ isRelative: true,
109
+ resolvedPath: candidate,
110
+ isExternal: false,
111
+ };
112
+ }
113
+ }
114
+ }
115
+ return {
116
+ specifier,
117
+ isRelative: true,
118
+ isExternal: false,
119
+ };
120
+ }
121
+ // Check alias configuration (e.g. @/* -> src/*)
122
+ if (aliasConfig?.paths) {
123
+ for (const [aliasPattern, targetPatterns] of Object.entries(aliasConfig.paths)) {
124
+ const prefix = aliasPattern.replace(/\*$/, '');
125
+ if (specifier.startsWith(prefix)) {
126
+ const subPath = specifier.slice(prefix.length);
127
+ for (const target of targetPatterns) {
128
+ const mappedPrefix = target.replace(/\*$/, '');
129
+ const mappedTarget = normalizeSlashes(path.normalize(path.join(aliasConfig.baseUrl, mappedPrefix, subPath))).replace(/^\.\//, '');
130
+ for (const ext of JS_TS_EXTENSIONS) {
131
+ const candidate = mappedTarget + ext;
132
+ if (knownFiles.has(candidate)) {
133
+ return {
134
+ specifier,
135
+ isRelative: false,
136
+ resolvedPath: candidate,
137
+ isExternal: false,
138
+ };
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ // External package or standard library
146
+ const parts = specifier.split('/');
147
+ const packageName = specifier.startsWith('@') && parts.length > 1 ? `${parts[0]}/${parts[1]}` : parts[0];
148
+ return {
149
+ specifier,
150
+ isRelative: false,
151
+ isExternal: true,
152
+ packageName,
153
+ };
154
+ }
155
+ //# sourceMappingURL=imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../../src/analyzers/architecture/imports.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAexD,MAAM,gBAAgB,GAAG;IACvB,EAAE;IACF,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,WAAW;IACX,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,YAAY;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,aAA6B;IAC9D,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,qCAAqC;QACrC,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,sCAAsC,EAAE,IAAI,CAAC,CAAC;QACtF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAKlC,CAAC;QAEF,IAAI,MAAM,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC;YAClC,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,eAAe,CAAC,OAAO,IAAI,GAAG;gBAC9C,KAAK,EAAE,MAAM,CAAC,eAAe,CAAC,KAAK;aACpC,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,SAAiB;IACrE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACrF,2EAA2E;QAC3E,MAAM,iBAAiB,GACrB,8EAA8E,CAAC;QACjF,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,4CAA4C;QAC5C,MAAM,eAAe,GAAG,4BAA4B,CAAC;QACrD,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxD,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,gDAAgD;QAChD,MAAM,kBAAkB,GAAG,sCAAsC,CAAC;QAClE,OAAO,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC3D,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,mDAAmD;QACnD,MAAM,YAAY,GAAG,uCAAuC,CAAC;QAC7D,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACrD,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;SAAM,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC7D,sDAAsD;QACtD,MAAM,WAAW,GAAG,wCAAwC,CAAC;QAC7D,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACpD,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,aAAa,GAAG,iCAAiC,CAAC;QACxD,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACtD,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,QAAgB,EAChB,UAAuB,EACvB,WAAoC;IAEpC,MAAM,UAAU,GACd,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC;QAC1B,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;QAC3B,SAAS,KAAK,GAAG;QACjB,SAAS,KAAK,IAAI,CAAC;IAErB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QACrF,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAElE,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,CAAC;YACjD,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;gBACnC,IAAI,SAAS,GAAG,IAAI,GAAG,GAAG,CAAC;gBAC3B,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC;oBAAE,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC/D,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC9B,OAAO;wBACL,SAAS;wBACT,UAAU,EAAE,IAAI;wBAChB,YAAY,EAAE,SAAS;wBACvB,UAAU,EAAE,KAAK;qBAClB,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS;YACT,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,IAAI,WAAW,EAAE,KAAK,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/E,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC/C,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/C,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;oBACpC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC/C,MAAM,YAAY,GAAG,gBAAgB,CACnC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CACtE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;oBAEvB,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;wBACnC,MAAM,SAAS,GAAG,YAAY,GAAG,GAAG,CAAC;wBACrC,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;4BAC9B,OAAO;gCACL,SAAS;gCACT,UAAU,EAAE,KAAK;gCACjB,YAAY,EAAE,SAAS;gCACvB,UAAU,EAAE,KAAK;6BAClB,CAAC;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,WAAW,GACf,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEvF,OAAO;QACL,SAAS;QACT,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,IAAI;QAChB,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Analyzer } from '../../core/analyzer.js';
2
+ import type { RepositoryContext } from '../../core/context.js';
3
+ import type { AnalyzerResult } from '../../core/result.js';
4
+ import type { ArchitectureSummary } from './types.js';
5
+ export declare class ArchitectureAnalyzer implements Analyzer {
6
+ readonly id = "architecture";
7
+ readonly name = "Architecture";
8
+ readonly category: "architecture";
9
+ readonly description = "Analyzes repository layout, dependency graph, circular dependencies, and architectural boundary violations.";
10
+ analyze(context: RepositoryContext): Promise<AnalyzerResult>;
11
+ }
12
+ export type { ArchitectureSummary };
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/architecture/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAW,MAAM,sBAAsB,CAAC;AAOpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,qBAAa,oBAAqB,YAAW,QAAQ;IACnD,QAAQ,CAAC,EAAE,kBAAkB;IAC7B,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,EAAG,cAAc,CAAU;IAC5C,QAAQ,CAAC,WAAW,iHAC4F;IAE1G,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;CAoOnE;AAED,YAAY,EAAE,mBAAmB,EAAE,CAAC"}