@mhdd_24/angular-mcp-server 1.0.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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/dist/analyzers/architecture-auditor.d.ts +34 -0
  4. package/dist/analyzers/architecture-auditor.d.ts.map +1 -0
  5. package/dist/analyzers/architecture-auditor.js +332 -0
  6. package/dist/analyzers/architecture-auditor.js.map +1 -0
  7. package/dist/analyzers/route-analyzer.d.ts +14 -0
  8. package/dist/analyzers/route-analyzer.d.ts.map +1 -0
  9. package/dist/analyzers/route-analyzer.js +171 -0
  10. package/dist/analyzers/route-analyzer.js.map +1 -0
  11. package/dist/generators/crud-generator.d.ts +5 -0
  12. package/dist/generators/crud-generator.d.ts.map +1 -0
  13. package/dist/generators/crud-generator.js +67 -0
  14. package/dist/generators/crud-generator.js.map +1 -0
  15. package/dist/generators/crud-types.d.ts +31 -0
  16. package/dist/generators/crud-types.d.ts.map +1 -0
  17. package/dist/generators/crud-types.js +2 -0
  18. package/dist/generators/crud-types.js.map +1 -0
  19. package/dist/generators/kendo-crud-templates.d.ts +19 -0
  20. package/dist/generators/kendo-crud-templates.d.ts.map +1 -0
  21. package/dist/generators/kendo-crud-templates.js +309 -0
  22. package/dist/generators/kendo-crud-templates.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +13 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/parsers/angular-project.d.ts +14 -0
  28. package/dist/parsers/angular-project.d.ts.map +1 -0
  29. package/dist/parsers/angular-project.js +46 -0
  30. package/dist/parsers/angular-project.js.map +1 -0
  31. package/dist/parsers/component-parser.d.ts +12 -0
  32. package/dist/parsers/component-parser.d.ts.map +1 -0
  33. package/dist/parsers/component-parser.js +48 -0
  34. package/dist/parsers/component-parser.js.map +1 -0
  35. package/dist/server/create-server.d.ts +3 -0
  36. package/dist/server/create-server.d.ts.map +1 -0
  37. package/dist/server/create-server.js +11 -0
  38. package/dist/server/create-server.js.map +1 -0
  39. package/dist/tools/audit-architecture.d.ts +3 -0
  40. package/dist/tools/audit-architecture.d.ts.map +1 -0
  41. package/dist/tools/audit-architecture.js +74 -0
  42. package/dist/tools/audit-architecture.js.map +1 -0
  43. package/dist/tools/find-component.d.ts +3 -0
  44. package/dist/tools/find-component.d.ts.map +1 -0
  45. package/dist/tools/find-component.js +50 -0
  46. package/dist/tools/find-component.js.map +1 -0
  47. package/dist/tools/generate-crud.d.ts +3 -0
  48. package/dist/tools/generate-crud.d.ts.map +1 -0
  49. package/dist/tools/generate-crud.js +55 -0
  50. package/dist/tools/generate-crud.js.map +1 -0
  51. package/dist/tools/get-project-info.d.ts +3 -0
  52. package/dist/tools/get-project-info.d.ts.map +1 -0
  53. package/dist/tools/get-project-info.js +25 -0
  54. package/dist/tools/get-project-info.js.map +1 -0
  55. package/dist/tools/index.d.ts +3 -0
  56. package/dist/tools/index.d.ts.map +1 -0
  57. package/dist/tools/index.js +13 -0
  58. package/dist/tools/index.js.map +1 -0
  59. package/dist/tools/list-routes.d.ts +3 -0
  60. package/dist/tools/list-routes.d.ts.map +1 -0
  61. package/dist/tools/list-routes.js +42 -0
  62. package/dist/tools/list-routes.js.map +1 -0
  63. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Angular MCP Server Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # Angular MCP Server
2
+
3
+ **Model Context Protocol tools built for Angular — not generic file search.**
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![Version](https://img.shields.io/badge/version-1.0.0-blue)](CHANGELOG.md)
7
+ [![Building in Public](https://img.shields.io/badge/Series-Building%20in%20Public-orange)](docs/building-in-public.md)
8
+
9
+ > **v1.0.0** — Open source under MIT. Works with Cursor, Claude Desktop, and any MCP-compatible client.
10
+
11
+ ---
12
+
13
+ ## Why Angular needs its own MCP Server
14
+
15
+ Generic MCP servers treat your codebase like a bag of files. Angular applications are not.
16
+
17
+ Angular projects have **structure**: components, directives, pipes, routes, lazy-loaded modules, standalone APIs, signals, dependency injection, and template syntax that generic tools cannot reliably parse or reason about.
18
+
19
+ An Angular-native MCP server gives AI assistants **real project intelligence**:
20
+
21
+ | Capability | Generic MCP | Angular MCP Server |
22
+ |---|---|---|
23
+ | Find components by selector | ❌ Text search | ✅ Decorator analysis |
24
+ | Map route → component | ❌ Guess from filenames | ✅ Router config parsing |
25
+ | Audit enterprise architecture | ❌ | ✅ 7 rules + health score |
26
+ | Generate CRUD with Kendo UI | ❌ | ✅ Angular 20 + Kendo patterns |
27
+
28
+ ---
29
+
30
+ ## MCP Tools (v1.0.0)
31
+
32
+ | Tool | Description |
33
+ |---|---|
34
+ | `get_project_info` | Read `angular.json` and summarize workspace projects |
35
+ | `find_component` | Search components by selector, class name, or path |
36
+ | `list_routes` | Parse `*.routes.ts` files into a route tree |
37
+ | `audit_architecture` | Enterprise audit: 7 rules, health score, grade (A-F) |
38
+ | `generate_crud` | Generate Angular 20 + Kendo UI CRUD scaffold |
39
+
40
+ ---
41
+
42
+ ## Quick Start
43
+
44
+ ### Option A — npm (recommended)
45
+
46
+ ```bash
47
+ npx @mhdd_24/angular-mcp-server
48
+ ```
49
+
50
+ Or install globally:
51
+
52
+ ```bash
53
+ npm install -g @mhdd_24/angular-mcp-server
54
+ angular-mcp-server
55
+ ```
56
+
57
+ ### Option B — clone from GitHub
58
+
59
+ ```bash
60
+ git clone https://github.com/Mhdd-24/angular-mcp-server.git
61
+ cd angular-mcp-server
62
+ npm install
63
+ npm run build
64
+ ```
65
+
66
+ ### Cursor / Claude Desktop MCP config
67
+
68
+ **Using npx (no install):**
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "angular-mcp-server": {
74
+ "command": "npx",
75
+ "args": ["-y", "@mhdd_24/angular-mcp-server"]
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ **Using a local clone:**
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "angular-mcp-server": {
87
+ "command": "node",
88
+ "args": ["/absolute/path/to/angular-mcp-server/dist/index.js"]
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ See [examples/cursor-mcp-config.json](examples/cursor-mcp-config.json) for a template.
95
+
96
+ ---
97
+
98
+ ## Examples
99
+
100
+ | Workspace | Demo |
101
+ |---|---|
102
+ | [basic-standalone](examples/basic-standalone/) | `find_component`, `list_routes` |
103
+ | [enterprise-layered](examples/enterprise-layered/) | `audit_architecture` |
104
+
105
+ ---
106
+
107
+ ## Building in Public (series complete)
108
+
109
+ | # | Topic | Link |
110
+ |---|---|---|
111
+ | 1 | Why Angular needs its own MCP Server | [Read →](docs/posts/01-why-angular-mcp.md) |
112
+ | 2 | Architecture | [Read →](docs/posts/02-architecture.md) |
113
+ | 3 | Live demo: components and routes | [Demo →](docs/posts/03-demo-script.md) |
114
+ | 4 | CRUD generation with Kendo UI | [Demo →](docs/posts/04-demo-script.md) |
115
+ | 5 | Enterprise architecture audit | [Demo →](docs/posts/05-demo-script.md) |
116
+ | 6 | Open-source release and roadmap | [Read →](docs/posts/06-open-source-release.md) |
117
+
118
+ ---
119
+
120
+ ## Roadmap
121
+
122
+ See [ROADMAP.md](ROADMAP.md) for planned features:
123
+
124
+ - **v1.1** — TypeScript AST parser, `find_service`
125
+ - **v1.2** — `analyze_dependencies` (DI graph)
126
+ - **v1.3** — OpenAPI → services, Kendo dialogs
127
+ - **v1.4** — Custom rules, monorepo support
128
+
129
+ ---
130
+
131
+ ## Contributing
132
+
133
+ Contributions welcome — especially from enterprise Angular teams. See [CONTRIBUTING.md](CONTRIBUTING.md).
134
+
135
+ ```bash
136
+ npm run dev # watch mode
137
+ npm test # run tests
138
+ npm run build # compile
139
+ ```
140
+
141
+ ---
142
+
143
+ ## License
144
+
145
+ [MIT](LICENSE) © 2026
@@ -0,0 +1,34 @@
1
+ export type Severity = "error" | "warning" | "info";
2
+ export type RuleId = "layer-boundary" | "cross-feature-import" | "circular-dependency" | "deep-relative-import" | "lazy-loading" | "naming-convention" | "file-size";
3
+ export interface ArchitectureFinding {
4
+ severity: Severity;
5
+ rule: RuleId;
6
+ file: string;
7
+ message: string;
8
+ }
9
+ export interface SourceFile {
10
+ path: string;
11
+ source: string;
12
+ }
13
+ export interface AuditSummary {
14
+ errorCount: number;
15
+ warningCount: number;
16
+ infoCount: number;
17
+ scannedFileCount: number;
18
+ score: number;
19
+ grade: "A" | "B" | "C" | "D" | "F";
20
+ }
21
+ export interface AuditReport {
22
+ summary: AuditSummary;
23
+ findingsByRule: Record<string, ArchitectureFinding[]>;
24
+ findings: ArchitectureFinding[];
25
+ }
26
+ export interface AuditOptions {
27
+ rules?: RuleId[];
28
+ maxFileLines?: number;
29
+ maxRelativeDepth?: number;
30
+ }
31
+ export declare function auditSourceFile(filePath: string, source: string, workspaceRoot: string, options?: AuditOptions): ArchitectureFinding[];
32
+ export declare function summarizeAudit(findings: ArchitectureFinding[], scannedFileCount?: number): AuditSummary;
33
+ export declare function auditWorkspace(files: SourceFile[], workspaceRoot: string, options?: AuditOptions): AuditReport;
34
+ //# sourceMappingURL=architecture-auditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architecture-auditor.d.ts","sourceRoot":"","sources":["../../src/analyzers/architecture-auditor.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpD,MAAM,MAAM,MAAM,GACd,gBAAgB,GAChB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,GACtB,cAAc,GACd,mBAAmB,GACnB,WAAW,CAAC;AAEhB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACtD,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2TD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,YAAiB,GACzB,mBAAmB,EAAE,CA6BvB;AAUD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,SAAI,GACnB,YAAY,CAgBd;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EAAE,EACnB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,YAAiB,GACzB,WAAW,CAsBb"}
@@ -0,0 +1,332 @@
1
+ import { dirname, relative, resolve } from "node:path";
2
+ const LAYER_RULES = [
3
+ {
4
+ layer: "core",
5
+ pattern: /(?:^|\/)core(?:\/|$)/i,
6
+ allowedImports: [/(?:^|\/)shared(?:\/|$)/i, /(?:^|\/)core(?:\/|$)/i],
7
+ },
8
+ {
9
+ layer: "shared",
10
+ pattern: /(?:^|\/)shared(?:\/|$)/i,
11
+ allowedImports: [/(?:^|\/)shared(?:\/|$)/i],
12
+ },
13
+ {
14
+ layer: "features",
15
+ pattern: /(?:^|\/)features(?:\/|$)/i,
16
+ allowedImports: [
17
+ /(?:^|\/)shared(?:\/|$)/i,
18
+ /(?:^|\/)core(?:\/|$)/i,
19
+ /(?:^|\/)features(?:\/|$)/i,
20
+ ],
21
+ },
22
+ ];
23
+ const DEFAULT_MAX_FILE_LINES = 400;
24
+ const DEFAULT_MAX_RELATIVE_DEPTH = 3;
25
+ function toPosix(value) {
26
+ return value.split("\\").join("/");
27
+ }
28
+ function detectLayer(relativePath) {
29
+ for (const rule of LAYER_RULES) {
30
+ if (rule.pattern.test(relativePath)) {
31
+ return rule.layer;
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ function featureName(relativePath) {
37
+ const match = relativePath.match(/features\/([^/]+)/i);
38
+ return match?.[1] ?? null;
39
+ }
40
+ function getImportPaths(source) {
41
+ const paths = [];
42
+ const importFrom = source.matchAll(/from\s+['"]([^'"]+)['"]/g);
43
+ for (const match of importFrom) {
44
+ paths.push(match[1]);
45
+ }
46
+ const dynamicImport = source.matchAll(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g);
47
+ for (const match of dynamicImport) {
48
+ paths.push(match[1]);
49
+ }
50
+ return paths;
51
+ }
52
+ function checkLayerBoundary(file, relativePath) {
53
+ const layer = detectLayer(relativePath);
54
+ if (!layer) {
55
+ return [];
56
+ }
57
+ const rule = LAYER_RULES.find((entry) => entry.layer === layer);
58
+ if (!rule) {
59
+ return [];
60
+ }
61
+ const findings = [];
62
+ for (const importPath of getImportPaths(file.source)) {
63
+ // Only reason about project-internal (relative) imports. External packages
64
+ // like "@angular/core" must never be interpreted as an architecture layer.
65
+ if (!importPath.startsWith(".")) {
66
+ continue;
67
+ }
68
+ const resolvedPath = toPosix(resolve(dirname(file.path), importPath));
69
+ const targetLayer = detectLayer(resolvedPath);
70
+ if (!targetLayer) {
71
+ continue;
72
+ }
73
+ const allowed = rule.allowedImports.some((pattern) => pattern.test(resolvedPath));
74
+ if (allowed) {
75
+ continue;
76
+ }
77
+ findings.push({
78
+ severity: "error",
79
+ rule: "layer-boundary",
80
+ file: relativePath,
81
+ message: `${layer} layer must not import from ${targetLayer}: ${importPath}`,
82
+ });
83
+ }
84
+ return findings;
85
+ }
86
+ function checkCrossFeature(file, relativePath) {
87
+ const ownFeature = featureName(relativePath);
88
+ if (!ownFeature) {
89
+ return [];
90
+ }
91
+ const findings = [];
92
+ for (const importPath of getImportPaths(file.source)) {
93
+ const resolvedPath = importPath.startsWith(".")
94
+ ? toPosix(resolve(dirname(file.path), importPath))
95
+ : importPath;
96
+ const importedFeature = featureName(resolvedPath);
97
+ if (importedFeature && importedFeature !== ownFeature) {
98
+ findings.push({
99
+ severity: "warning",
100
+ rule: "cross-feature-import",
101
+ file: relativePath,
102
+ message: `Feature "${ownFeature}" imports from feature "${importedFeature}": ${importPath}. Move shared code to shared/.`,
103
+ });
104
+ }
105
+ }
106
+ return findings;
107
+ }
108
+ function checkDeepRelativeImports(file, relativePath, maxRelativeDepth) {
109
+ const findings = [];
110
+ for (const importPath of getImportPaths(file.source)) {
111
+ const upLevels = importPath.match(/\.\.\//g)?.length ?? 0;
112
+ if (upLevels > maxRelativeDepth) {
113
+ findings.push({
114
+ severity: "warning",
115
+ rule: "deep-relative-import",
116
+ file: relativePath,
117
+ message: `Deep relative import (${upLevels} levels): ${importPath}. Consider a TypeScript path alias.`,
118
+ });
119
+ }
120
+ }
121
+ return findings;
122
+ }
123
+ function checkNamingConvention(file, relativePath) {
124
+ const findings = [];
125
+ const posix = toPosix(relativePath);
126
+ const componentClass = file.source.match(/@Component\b[\s\S]*?export\s+class\s+(\w+)/);
127
+ if (componentClass && !componentClass[1].endsWith("Component")) {
128
+ findings.push({
129
+ severity: "info",
130
+ rule: "naming-convention",
131
+ file: relativePath,
132
+ message: `Component class "${componentClass[1]}" should end with "Component".`,
133
+ });
134
+ }
135
+ const serviceClass = file.source.match(/@Injectable\b[\s\S]*?export\s+class\s+(\w+)/);
136
+ if (serviceClass && !/(Service|Store|Guard|Resolver|Interceptor)$/.test(serviceClass[1])) {
137
+ findings.push({
138
+ severity: "info",
139
+ rule: "naming-convention",
140
+ file: relativePath,
141
+ message: `Injectable "${serviceClass[1]}" should end with a role suffix (Service, Store, Guard, Resolver, Interceptor).`,
142
+ });
143
+ }
144
+ if (/@Component\b/.test(file.source) && !posix.endsWith(".component.ts")) {
145
+ findings.push({
146
+ severity: "info",
147
+ rule: "naming-convention",
148
+ file: relativePath,
149
+ message: `File declares a @Component but is not named *.component.ts.`,
150
+ });
151
+ }
152
+ return findings;
153
+ }
154
+ function checkFileSize(file, relativePath, maxFileLines) {
155
+ const lineCount = file.source.split("\n").length;
156
+ if (lineCount <= maxFileLines) {
157
+ return [];
158
+ }
159
+ return [
160
+ {
161
+ severity: "warning",
162
+ rule: "file-size",
163
+ file: relativePath,
164
+ message: `File has ${lineCount} lines (limit ${maxFileLines}). Consider splitting responsibilities.`,
165
+ },
166
+ ];
167
+ }
168
+ function checkLazyLoading(file, relativePath) {
169
+ const posix = toPosix(relativePath);
170
+ const isRootRoutes = /(?:^|\/)app\.routes\.ts$/.test(posix) || /(?:^|\/)app-routing/.test(posix);
171
+ if (!isRootRoutes) {
172
+ return [];
173
+ }
174
+ const findings = [];
175
+ const eagerFeatureImport = /import\s*\{[^}]*\}\s*from\s*['"][^'"]*features\/[^'"]+['"]/g;
176
+ for (const match of file.source.matchAll(eagerFeatureImport)) {
177
+ findings.push({
178
+ severity: "info",
179
+ rule: "lazy-loading",
180
+ file: relativePath,
181
+ message: `Root routes eagerly import a feature: ${match[0].trim()}. Prefer loadChildren/loadComponent for features.`,
182
+ });
183
+ }
184
+ return findings;
185
+ }
186
+ function resolveImportTarget(fromFile, importPath) {
187
+ if (!importPath.startsWith(".")) {
188
+ return null;
189
+ }
190
+ const resolved = toPosix(resolve(dirname(fromFile), importPath));
191
+ return resolved.replace(/\.(ts|tsx|js)$/, "");
192
+ }
193
+ function detectCircularDependencies(files, workspaceRoot) {
194
+ const normalized = files.map((file) => ({
195
+ key: toPosix(file.path).replace(/\.(ts|tsx|js)$/, ""),
196
+ file,
197
+ }));
198
+ const keySet = new Set(normalized.map((entry) => entry.key));
199
+ const graph = new Map();
200
+ for (const { key, file } of normalized) {
201
+ const edges = [];
202
+ for (const importPath of getImportPaths(file.source)) {
203
+ const target = resolveImportTarget(file.path, importPath);
204
+ if (target && keySet.has(target)) {
205
+ edges.push(target);
206
+ }
207
+ }
208
+ graph.set(key, edges);
209
+ }
210
+ const findings = [];
211
+ const reported = new Set();
212
+ const visiting = new Set();
213
+ const visited = new Set();
214
+ const stack = [];
215
+ const pathToRelative = new Map(normalized.map((entry) => [entry.key, toPosix(relative(workspaceRoot, entry.file.path))]));
216
+ function dfs(node) {
217
+ visiting.add(node);
218
+ stack.push(node);
219
+ for (const next of graph.get(node) ?? []) {
220
+ if (visiting.has(next)) {
221
+ const cycleStart = stack.indexOf(next);
222
+ const cycle = stack.slice(cycleStart).concat(next);
223
+ const signature = [...cycle].sort().join("|");
224
+ if (!reported.has(signature)) {
225
+ reported.add(signature);
226
+ const readable = cycle
227
+ .map((key) => pathToRelative.get(key) ?? key)
228
+ .join(" → ");
229
+ findings.push({
230
+ severity: "error",
231
+ rule: "circular-dependency",
232
+ file: pathToRelative.get(node) ?? node,
233
+ message: `Circular dependency: ${readable}`,
234
+ });
235
+ }
236
+ }
237
+ else if (!visited.has(next)) {
238
+ dfs(next);
239
+ }
240
+ }
241
+ stack.pop();
242
+ visiting.delete(node);
243
+ visited.add(node);
244
+ }
245
+ for (const { key } of normalized) {
246
+ if (!visited.has(key)) {
247
+ dfs(key);
248
+ }
249
+ }
250
+ return findings;
251
+ }
252
+ const PER_FILE_RULES = [
253
+ "layer-boundary",
254
+ "cross-feature-import",
255
+ "deep-relative-import",
256
+ "naming-convention",
257
+ "file-size",
258
+ "lazy-loading",
259
+ ];
260
+ export function auditSourceFile(filePath, source, workspaceRoot, options = {}) {
261
+ const relativePath = toPosix(relative(workspaceRoot, filePath));
262
+ const file = { path: filePath, source };
263
+ const enabled = new Set(options.rules ?? PER_FILE_RULES);
264
+ const maxFileLines = options.maxFileLines ?? DEFAULT_MAX_FILE_LINES;
265
+ const maxRelativeDepth = options.maxRelativeDepth ?? DEFAULT_MAX_RELATIVE_DEPTH;
266
+ const findings = [];
267
+ if (enabled.has("layer-boundary")) {
268
+ findings.push(...checkLayerBoundary(file, relativePath));
269
+ }
270
+ if (enabled.has("cross-feature-import")) {
271
+ findings.push(...checkCrossFeature(file, relativePath));
272
+ }
273
+ if (enabled.has("deep-relative-import")) {
274
+ findings.push(...checkDeepRelativeImports(file, relativePath, maxRelativeDepth));
275
+ }
276
+ if (enabled.has("naming-convention")) {
277
+ findings.push(...checkNamingConvention(file, relativePath));
278
+ }
279
+ if (enabled.has("file-size")) {
280
+ findings.push(...checkFileSize(file, relativePath, maxFileLines));
281
+ }
282
+ if (enabled.has("lazy-loading")) {
283
+ findings.push(...checkLazyLoading(file, relativePath));
284
+ }
285
+ return findings;
286
+ }
287
+ function scoreToGrade(score) {
288
+ if (score >= 90)
289
+ return "A";
290
+ if (score >= 80)
291
+ return "B";
292
+ if (score >= 70)
293
+ return "C";
294
+ if (score >= 60)
295
+ return "D";
296
+ return "F";
297
+ }
298
+ export function summarizeAudit(findings, scannedFileCount = 0) {
299
+ const errorCount = findings.filter((finding) => finding.severity === "error").length;
300
+ const warningCount = findings.filter((finding) => finding.severity === "warning").length;
301
+ const infoCount = findings.filter((finding) => finding.severity === "info").length;
302
+ const penalty = errorCount * 10 + warningCount * 3 + infoCount * 1;
303
+ const score = Math.max(0, Math.min(100, 100 - penalty));
304
+ return {
305
+ errorCount,
306
+ warningCount,
307
+ infoCount,
308
+ scannedFileCount,
309
+ score,
310
+ grade: scoreToGrade(score),
311
+ };
312
+ }
313
+ export function auditWorkspace(files, workspaceRoot, options = {}) {
314
+ const enabled = new Set(options.rules ?? [...PER_FILE_RULES, "circular-dependency"]);
315
+ const findings = [];
316
+ for (const file of files) {
317
+ findings.push(...auditSourceFile(file.path, file.source, workspaceRoot, options));
318
+ }
319
+ if (enabled.has("circular-dependency")) {
320
+ findings.push(...detectCircularDependencies(files, workspaceRoot));
321
+ }
322
+ const findingsByRule = {};
323
+ for (const finding of findings) {
324
+ (findingsByRule[finding.rule] ??= []).push(finding);
325
+ }
326
+ return {
327
+ summary: summarizeAudit(findings, files.length),
328
+ findingsByRule,
329
+ findings,
330
+ };
331
+ }
332
+ //# sourceMappingURL=architecture-auditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architecture-auditor.js","sourceRoot":"","sources":["../../src/analyzers/architecture-auditor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface RouteEntry {
2
+ path: string;
3
+ component: string | null;
4
+ loadChildren: string | null;
5
+ loadComponent: string | null;
6
+ redirectTo: string | null;
7
+ children: RouteEntry[];
8
+ }
9
+ export declare function analyzeRoutesFile(filePath: string, workspaceRoot: string): Promise<{
10
+ file: string;
11
+ routes: RouteEntry[];
12
+ }>;
13
+ export declare function flattenRoutes(routes: RouteEntry[]): RouteEntry[];
14
+ //# sourceMappingURL=route-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/route-analyzer.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AA0LD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CAiBjD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAWhE"}