@angular-modernizer/api 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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +507 -0
  3. package/dist/analysis/complexity-metrics-calculator.d.ts +99 -0
  4. package/dist/analysis/complexity-metrics-calculator.d.ts.map +1 -0
  5. package/dist/analysis/complexity-metrics-calculator.js +195 -0
  6. package/dist/analysis/complexity-metrics-calculator.js.map +1 -0
  7. package/dist/analysis/dependency-analyzer.d.ts +227 -0
  8. package/dist/analysis/dependency-analyzer.d.ts.map +1 -0
  9. package/dist/analysis/dependency-analyzer.js +451 -0
  10. package/dist/analysis/dependency-analyzer.js.map +1 -0
  11. package/dist/analysis/external-template-loader.d.ts +44 -0
  12. package/dist/analysis/external-template-loader.d.ts.map +1 -0
  13. package/dist/analysis/external-template-loader.js +69 -0
  14. package/dist/analysis/external-template-loader.js.map +1 -0
  15. package/dist/analysis/selector-mapper.d.ts +77 -0
  16. package/dist/analysis/selector-mapper.d.ts.map +1 -0
  17. package/dist/analysis/selector-mapper.js +146 -0
  18. package/dist/analysis/selector-mapper.js.map +1 -0
  19. package/dist/analysis/service-detector.d.ts +164 -0
  20. package/dist/analysis/service-detector.d.ts.map +1 -0
  21. package/dist/analysis/service-detector.js +231 -0
  22. package/dist/analysis/service-detector.js.map +1 -0
  23. package/dist/analysis/service-pattern-recognizer.d.ts +247 -0
  24. package/dist/analysis/service-pattern-recognizer.d.ts.map +1 -0
  25. package/dist/analysis/service-pattern-recognizer.js +444 -0
  26. package/dist/analysis/service-pattern-recognizer.js.map +1 -0
  27. package/dist/analysis/symbol-locator.d.ts +81 -0
  28. package/dist/analysis/symbol-locator.d.ts.map +1 -0
  29. package/dist/analysis/symbol-locator.js +128 -0
  30. package/dist/analysis/symbol-locator.js.map +1 -0
  31. package/dist/analysis/template-analyzer-usage.d.ts +144 -0
  32. package/dist/analysis/template-analyzer-usage.d.ts.map +1 -0
  33. package/dist/analysis/template-analyzer-usage.js +474 -0
  34. package/dist/analysis/template-analyzer-usage.js.map +1 -0
  35. package/dist/analysis/template-analyzer.d.ts +80 -0
  36. package/dist/analysis/template-analyzer.d.ts.map +1 -0
  37. package/dist/analysis/template-analyzer.js +146 -0
  38. package/dist/analysis/template-analyzer.js.map +1 -0
  39. package/dist/index.d.ts +23 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +22 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/investigation/angular-symbol-finder.d.ts +76 -0
  44. package/dist/investigation/angular-symbol-finder.d.ts.map +1 -0
  45. package/dist/investigation/angular-symbol-finder.js +199 -0
  46. package/dist/investigation/angular-symbol-finder.js.map +1 -0
  47. package/dist/investigation/call-graph-builder.d.ts +85 -0
  48. package/dist/investigation/call-graph-builder.d.ts.map +1 -0
  49. package/dist/investigation/call-graph-builder.js +196 -0
  50. package/dist/investigation/call-graph-builder.js.map +1 -0
  51. package/dist/investigation/codebase-searcher.d.ts +99 -0
  52. package/dist/investigation/codebase-searcher.d.ts.map +1 -0
  53. package/dist/investigation/codebase-searcher.js +201 -0
  54. package/dist/investigation/codebase-searcher.js.map +1 -0
  55. package/dist/investigation/stack-trace-parser.d.ts +70 -0
  56. package/dist/investigation/stack-trace-parser.d.ts.map +1 -0
  57. package/dist/investigation/stack-trace-parser.js +117 -0
  58. package/dist/investigation/stack-trace-parser.js.map +1 -0
  59. package/dist/investigation/type-resolver.d.ts +59 -0
  60. package/dist/investigation/type-resolver.d.ts.map +1 -0
  61. package/dist/investigation/type-resolver.js +111 -0
  62. package/dist/investigation/type-resolver.js.map +1 -0
  63. package/dist/investigation/usage-finder.d.ts +69 -0
  64. package/dist/investigation/usage-finder.d.ts.map +1 -0
  65. package/dist/investigation/usage-finder.js +132 -0
  66. package/dist/investigation/usage-finder.js.map +1 -0
  67. package/dist/metrics/complexity-metrics.d.ts +196 -0
  68. package/dist/metrics/complexity-metrics.d.ts.map +1 -0
  69. package/dist/metrics/complexity-metrics.js +445 -0
  70. package/dist/metrics/complexity-metrics.js.map +1 -0
  71. package/dist/public-api.d.ts +77 -0
  72. package/dist/public-api.d.ts.map +1 -0
  73. package/dist/public-api.js +50 -0
  74. package/dist/public-api.js.map +1 -0
  75. package/dist/transformation/import-manager.d.ts +276 -0
  76. package/dist/transformation/import-manager.d.ts.map +1 -0
  77. package/dist/transformation/import-manager.js +488 -0
  78. package/dist/transformation/import-manager.js.map +1 -0
  79. package/dist/transformation/ng-morph-adapter.d.ts +111 -0
  80. package/dist/transformation/ng-morph-adapter.d.ts.map +1 -0
  81. package/dist/transformation/ng-morph-adapter.js +179 -0
  82. package/dist/transformation/ng-morph-adapter.js.map +1 -0
  83. package/dist/transformation/ngmodule-manager.d.ts +145 -0
  84. package/dist/transformation/ngmodule-manager.d.ts.map +1 -0
  85. package/dist/transformation/ngmodule-manager.js +356 -0
  86. package/dist/transformation/ngmodule-manager.js.map +1 -0
  87. package/package.json +62 -0
  88. package/src/analysis/complexity-metrics-calculator.ts +253 -0
  89. package/src/analysis/dependency-analyzer.ts +720 -0
  90. package/src/analysis/external-template-loader.ts +79 -0
  91. package/src/analysis/selector-mapper.ts +186 -0
  92. package/src/analysis/service-detector.ts +280 -0
  93. package/src/analysis/service-pattern-recognizer.ts +545 -0
  94. package/src/analysis/symbol-locator.ts +170 -0
  95. package/src/analysis/template-analyzer-usage.ts +614 -0
  96. package/src/analysis/template-analyzer.ts +208 -0
  97. package/src/index.ts +51 -0
  98. package/src/investigation/angular-symbol-finder.ts +263 -0
  99. package/src/investigation/call-graph-builder.ts +298 -0
  100. package/src/investigation/codebase-searcher.ts +286 -0
  101. package/src/investigation/stack-trace-parser.ts +166 -0
  102. package/src/investigation/type-resolver.ts +144 -0
  103. package/src/investigation/usage-finder.ts +198 -0
  104. package/src/metrics/complexity-metrics.ts +617 -0
  105. package/src/public-api.ts +119 -0
  106. package/src/transformation/import-manager.ts +626 -0
  107. package/src/transformation/ng-morph-adapter.ts +252 -0
  108. package/src/transformation/ngmodule-manager.ts +450 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christian Weiss<CWOIDA>
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,507 @@
1
+ # @angular-modernizer/api
2
+
3
+ Analysis and transformation utilities used by plugins. Plugins must use this API and never manipulate the AST directly.
4
+
5
+ ## Overview
6
+
7
+ The `@angular-modernizer/api` package provides high-level, reusable tools that plugins use to analyze and transform Angular codebases. This package contains the core business logic that powers the entire platform.
8
+
9
+ ## Architecture
10
+
11
+ The API follows the "API-Driven Plugin" pattern:
12
+
13
+ ```typescript
14
+ // Incorrect: plugin implements low-level AST logic
15
+ class BadPlugin {
16
+ analyze(sourceFile: SourceFile) {
17
+ // 100 lines of AST manipulation code
18
+ }
19
+ }
20
+
21
+ // Correct: plugin uses API tools
22
+ class GoodPlugin {
23
+ analyze(context: AnalysisContext) {
24
+ const usages = context.api.analysis.templateAnalyzer.analyze(template);
25
+ const deps = context.api.analysis.dependencyAnalyzer.analyzeDependencies(sourceFile);
26
+ // Focus on business logic, not implementation details
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Core Components
32
+
33
+ ### PublicApi
34
+
35
+ The `PublicApi` is the single entry point for all analysis and transformation tools:
36
+
37
+ ```typescript
38
+ import { createPublicApi } from '@angular-modernizer/api';
39
+
40
+ const api = createPublicApi();
41
+
42
+ const templateUsages = api.analysis.templateAnalyzer.analyze(template);
43
+ const dependencies = api.analysis.dependencyAnalyzer.analyzeDependencies(sourceFile);
44
+ const imports = api.transformation.importManager.addImport(
45
+ sourceFile,
46
+ 'Inject',
47
+ '@angular/core',
48
+ );
49
+ ```
50
+
51
+ ### Analysis Tools
52
+
53
+ #### TemplateAnalyzer
54
+
55
+ Purpose: extract all template usages.
56
+
57
+ ```typescript
58
+ interface TemplateAnalyzer {
59
+ analyze(template: string): TemplateUsage[];
60
+ }
61
+
62
+ interface TemplateUsage {
63
+ element: string;
64
+ selector: string;
65
+ attributes: string[];
66
+ inputs: string[];
67
+ outputs: string[];
68
+ content: string;
69
+ }
70
+ ```
71
+
72
+ Design: extracts all usages from templates without filtering or heuristics. Provides raw data for downstream decision-making.
73
+
74
+ Example:
75
+
76
+ ```typescript
77
+ const api = createPublicApi();
78
+ const usages = api.analysis.templateAnalyzer.analyze(`
79
+ <app-user [user]="currentUser" (save)="onSave()">
80
+ <div *ngIf="loading">Loading...</div>
81
+ <input [(ngModel)]="name">
82
+ </app-user>
83
+ `);
84
+
85
+ // Result:
86
+ // - app-user component with [user] input and (save) output
87
+ // - *ngIf directive usage
88
+ // - ngModel directive usage
89
+ ```
90
+
91
+ #### DependencyAnalyzer
92
+
93
+ Purpose: build comprehensive symbol maps.
94
+
95
+ ```typescript
96
+ interface DependencyAnalyzer {
97
+ analyzeDependencies(sourceFile: SourceFile): DependencyMap;
98
+ findNgModules(project: Project): NgModuleInfo[];
99
+ resolveSelector(selector: string, project: Project): SymbolInfo | null;
100
+ }
101
+
102
+ interface DependencyMap {
103
+ components: Map<string, ComponentInfo>;
104
+ directives: Map<string, DirectiveInfo>;
105
+ pipes: Map<string, PipeInfo>;
106
+ modules: Map<string, NgModuleInfo>;
107
+ }
108
+
109
+ interface ComponentInfo {
110
+ className: string;
111
+ selector: string;
112
+ inputs: PropertyInfo[];
113
+ outputs: PropertyInfo[];
114
+ module?: string;
115
+ }
116
+
117
+ interface PropertyInfo {
118
+ name: string;
119
+ alias?: string;
120
+ type?: string;
121
+ }
122
+ ```
123
+
124
+ Key features:
125
+ - Maps selectors to class names
126
+ - Handles aliased @Input/@Output bindings
127
+ - Resolves module declarations
128
+ - Builds complete dependency graphs
129
+
130
+ Example:
131
+
132
+ ```typescript
133
+ const api = createPublicApi();
134
+ const sourceFile = project.addSourceFileAtPath('user.module.ts');
135
+ const dependencies = api.analysis.dependencyAnalyzer.analyzeDependencies(sourceFile);
136
+
137
+ // Result: complete symbol map
138
+ // - UserComponent: selector 'app-user', inputs: ['user'], outputs: ['save']
139
+ // - UserModule: declarations: [UserComponent], exports: [UserComponent]
140
+ ```
141
+
142
+ Also supports advanced analysis:
143
+
144
+ ```typescript
145
+ const analyzer = new DependencyAnalyzer();
146
+
147
+ // Build comprehensive symbol map
148
+ const symbolMap = analyzer.buildSymbolMap(moduleFile, project);
149
+ console.log(symbolMap.available); // All available symbols in scope
150
+
151
+ // Detect circular dependencies
152
+ const cycles = analyzer.detectCircularDependencies(project);
153
+
154
+ // Get transitive dependencies
155
+ const transitiveDeps = analyzer.getTransitiveDependencies(sourceFile, project);
156
+
157
+ // Extract symbol information
158
+ const symbolInfo = analyzer.extractSymbolInfo(sourceFile, 'MyComponent');
159
+ console.log(symbolInfo?.inputs); // ['input1', 'customAlias']
160
+ console.log(symbolInfo?.outputs); // ['output1']
161
+ ```
162
+
163
+ #### ComplexityMetricsCalculator
164
+
165
+ Purpose: calculate code complexity and maintainability metrics.
166
+
167
+ ```typescript
168
+ interface ComplexityMetricsCalculator {
169
+ calculateForFile(sourceFile: SourceFile): FileMetrics;
170
+ calculateForProject(project: Project): ProjectMetrics;
171
+ }
172
+
173
+ interface FileMetrics {
174
+ linesOfCode: number;
175
+ cyclomaticComplexity: number;
176
+ maintainabilityIndex: number;
177
+ halsteadMetrics: HalsteadMetrics;
178
+ cognitiveComplexity: number;
179
+ }
180
+
181
+ interface ProjectMetrics {
182
+ totalFiles: number;
183
+ averageComplexity: number;
184
+ complexityDistribution: ComplexityDistribution;
185
+ maintainabilityScore: number;
186
+ }
187
+ ```
188
+
189
+ Example:
190
+
191
+ ```typescript
192
+ const calculator = new ComplexityMetricsCalculator();
193
+
194
+ const score = calculator.calculateOverallComplexity(componentClass);
195
+ const cyclomatic = calculator.calculateCyclomaticComplexity(method);
196
+ const loc = calculator.calculateLOC(sourceFile);
197
+ const angularMetrics = calculator.calculateAngularSpecificMetrics(classDecl);
198
+ console.log(angularMetrics.lifecycleHooks);
199
+ console.log(angularMetrics.inputs);
200
+ console.log(angularMetrics.outputs);
201
+ ```
202
+
203
+ ### Transformation Tools
204
+
205
+ #### ImportManager
206
+
207
+ Purpose: safely manage TypeScript import statements.
208
+
209
+ ```typescript
210
+ interface ImportManager {
211
+ addImport(sourceFile: SourceFile, symbol: string, module: string): boolean;
212
+ removeImport(sourceFile: SourceFile, symbol: string): boolean;
213
+ organizeImports(sourceFile: SourceFile): void;
214
+ hasImport(sourceFile: SourceFile, symbol: string, module?: string): boolean;
215
+ }
216
+ ```
217
+
218
+ Key features:
219
+ - Prevents duplicate imports
220
+ - Handles default vs named imports
221
+ - Organizes import statements
222
+ - Resolves import conflicts
223
+
224
+ Example:
225
+
226
+ ```typescript
227
+ const importManager = new ImportManager();
228
+
229
+ importManager.addNamedImport(sourceFile, 'OnInit', '@angular/core');
230
+ importManager.addNamedImport(sourceFile, 'Directive', '@angular/core', 'NgDirective');
231
+
232
+ importManager.removeNamedImport(sourceFile, 'OnInit', '@angular/core');
233
+
234
+ const hasImport = importManager.hasImport(sourceFile, 'Component', '@angular/core');
235
+ const alias = importManager.getImportAlias(sourceFile, 'Component', '@angular/core');
236
+
237
+ importManager.mergeImports(sourceFile);
238
+ importManager.cleanupEmptyImports(sourceFile);
239
+ ```
240
+
241
+ ## Performance Characteristics
242
+
243
+ - ComplexityMetricsCalculator: <100ms for large components
244
+ - ImportManager: <50ms for 20+ import operations
245
+ - DependencyAnalyzer: <200ms for comprehensive analysis
246
+ - Memory usage: <50MB increase during repeated operations
247
+
248
+ ## Usage Examples
249
+
250
+ ### Standalone Migration Workflow
251
+
252
+ ```typescript
253
+ import { createPublicApi } from '@angular-modernizer/api';
254
+ import { ContextFactory } from '@angular-modernizer/plugin-system';
255
+
256
+ const api = createPublicApi();
257
+
258
+ // 1. Analyze template dependencies
259
+ const template = `<div *ngIf="loading" [user]="user" (save)="onSave()"></div>`;
260
+ const templateUsages = api.analysis.templateAnalyzer.analyze(template);
261
+
262
+ // 2. Get component dependencies
263
+ const sourceFile = project.addSourceFileAtPath('user.component.ts');
264
+ const dependencies = api.analysis.dependencyAnalyzer.analyzeDependencies(sourceFile);
265
+
266
+ // 3. Transform component to standalone
267
+ const context = ContextFactory.createTransformContext({
268
+ sourceFile,
269
+ project,
270
+ api,
271
+ config: {},
272
+ });
273
+
274
+ // The plugin uses the API to:
275
+ // - Add standalone: true to @Component decorator
276
+ // - Build imports array from templateUsages + dependencies
277
+ // - Add necessary import statements
278
+ ```
279
+
280
+ ### SOLID Principle Analysis
281
+
282
+ ```typescript
283
+ const api = createPublicApi();
284
+
285
+ function findDirectInstantiations(sourceFile: SourceFile): Violation[] {
286
+ const violations: Violation[] = [];
287
+
288
+ sourceFile.forEachDescendant((node) => {
289
+ if (ts.isNewExpression(node)) {
290
+ const className = node.expression.getText();
291
+
292
+ if (className.endsWith('Service')) {
293
+ violations.push({
294
+ type: 'direct-instantiation',
295
+ location: getLocation(node),
296
+ message: `Direct instantiation of ${className} violates Dependency Inversion Principle`,
297
+ suggestion: 'Use dependency injection instead',
298
+ });
299
+ }
300
+ }
301
+ });
302
+
303
+ return violations;
304
+ }
305
+ ```
306
+
307
+ ### Complexity Analysis
308
+
309
+ ```typescript
310
+ const api = createPublicApi();
311
+
312
+ const projectMetrics = api.analysis.complexityMetricsCalculator.calculateForProject(project);
313
+
314
+ const complexFiles = projectMetrics.fileMetrics.filter(
315
+ (metrics) =>
316
+ metrics.cyclomaticComplexity > 10 || metrics.maintainabilityIndex < 50,
317
+ );
318
+
319
+ complexFiles.forEach((file) => {
320
+ console.log(`${file.filePath}:`);
321
+ console.log(` - Complexity: ${file.cyclomaticComplexity}`);
322
+ console.log(` - Maintainability: ${file.maintainabilityIndex}`);
323
+ console.log(' -> Consider breaking down into smaller functions');
324
+ });
325
+ ```
326
+
327
+ ## API Design Principles
328
+
329
+ ### Stateless and Pure
330
+
331
+ All API methods are stateless and side-effect free:
332
+
333
+ ```typescript
334
+ const result1 = api.analysis.templateAnalyzer.analyze(template);
335
+ const result2 = api.analysis.templateAnalyzer.analyze(template);
336
+ assert.deepEqual(result1, result2); // Always true
337
+ ```
338
+
339
+ ### Composable
340
+
341
+ Tools work together seamlessly:
342
+
343
+ ```typescript
344
+ const templateUsages = api.analysis.templateAnalyzer.analyze(template);
345
+ const dependencies = api.analysis.dependencyAnalyzer.analyzeDependencies(sourceFile);
346
+ const complexity = api.analysis.complexityMetricsCalculator.calculateForFile(sourceFile);
347
+
348
+ const transformationPlan = createTransformationPlan({
349
+ templateUsages,
350
+ dependencies,
351
+ complexity,
352
+ });
353
+ ```
354
+
355
+ ### Error-Resilient
356
+
357
+ APIs handle edge cases gracefully:
358
+
359
+ ```typescript
360
+ // Handles malformed templates
361
+ const usages = api.analysis.templateAnalyzer.analyze('<invalid html>>>');
362
+ // Returns empty array or best-effort parsing
363
+
364
+ // Handles missing files
365
+ const dependencies = api.analysis.dependencyAnalyzer.analyzeDependencies(missingFile);
366
+ // Returns empty map, no crash
367
+ ```
368
+
369
+ ### Performance-Conscious
370
+
371
+ Efficient algorithms for large codebases:
372
+ - Lazy evaluation where possible
373
+ - Caching of expensive operations
374
+ - Streaming processing for large files
375
+ - Incremental analysis support
376
+
377
+ ## Testing
378
+
379
+ ```bash
380
+ pnpm test --filter @angular-modernizer/api
381
+ pnpm test --filter @angular-modernizer/api --coverage
382
+ ```
383
+
384
+ Test categories:
385
+ - Unit tests: individual tool functionality
386
+ - Integration tests: tool composition and workflows
387
+ - Performance tests: large codebase handling
388
+ - Edge case tests: error conditions and malformed input
389
+
390
+ Testing patterns:
391
+
392
+ ```typescript
393
+ import { createPublicApi } from '@angular-modernizer/api';
394
+ import { Project } from 'ts-morph';
395
+
396
+ describe('TemplateAnalyzer', () => {
397
+ let api: PublicApi;
398
+ let project: Project;
399
+
400
+ beforeEach(() => {
401
+ api = createPublicApi();
402
+ project = new Project();
403
+ });
404
+
405
+ it('should extract component usages', () => {
406
+ const template = '<app-user [user]="user"></app-user>';
407
+ const usages = api.analysis.templateAnalyzer.analyze(template);
408
+
409
+ expect(usages).toContainEqual({
410
+ element: 'app-user',
411
+ selector: 'app-user',
412
+ inputs: ['user'],
413
+ attributes: [],
414
+ outputs: [],
415
+ content: '',
416
+ });
417
+ });
418
+ });
419
+ ```
420
+
421
+ ## Package Structure
422
+
423
+ ```
424
+ packages/api/
425
+ ├── src/
426
+ │ ├── analysis/
427
+ │ │ ├── template-analyzer.ts
428
+ │ │ ├── dependency-analyzer.ts
429
+ │ │ └── complexity-metrics-calculator.ts
430
+ │ ├── transformation/
431
+ │ │ └── import-manager.ts
432
+ │ ├── index.ts
433
+ │ └── types.ts
434
+ ├── __tests__/
435
+ │ ├── analysis/
436
+ │ │ ├── template-analyzer.test.ts
437
+ │ │ ├── dependency-analyzer.test.ts
438
+ │ │ └── complexity-metrics-calculator.test.ts
439
+ │ ├── transformation/
440
+ │ │ └── import-manager.test.ts
441
+ │ └── integration.test.ts
442
+ ├── package.json
443
+ ├── tsconfig.json
444
+ ├── jest.config.js
445
+ └── README.md
446
+ ```
447
+
448
+ ## Dependencies
449
+
450
+ - **ts-morph:** TypeScript AST manipulation
451
+ - **typescript:** TypeScript compiler API
452
+ - **@angular-modernizer/core:** Kernel and infrastructure (peer dependency)
453
+
454
+ ## Contributing
455
+
456
+ When adding new API tools:
457
+
458
+ 1. Follow the PublicApi pattern - add to the unified interface
459
+ 2. Write comprehensive tests (unit, integration, and edge cases)
460
+ 3. Document with examples and update this README
461
+ 4. Maintain backward compatibility
462
+ 5. Optimize for large codebases
463
+
464
+ ### Adding a New Analysis Tool
465
+
466
+ ```typescript
467
+ // 1. Create the tool interface
468
+ export interface NewAnalyzer {
469
+ analyze(input: InputType): OutputType;
470
+ }
471
+
472
+ // 2. Implement the tool
473
+ export class NewAnalyzerImpl implements NewAnalyzer {
474
+ analyze(input: InputType): OutputType {
475
+ // Implementation
476
+ }
477
+ }
478
+
479
+ // 3. Add to PublicApi interface
480
+ interface PublicApi {
481
+ analysis: {
482
+ templateAnalyzer: TemplateAnalyzer;
483
+ dependencyAnalyzer: DependencyAnalyzer;
484
+ newAnalyzer: NewAnalyzer;
485
+ };
486
+ }
487
+
488
+ // 4. Update factory function
489
+ export function createPublicApi(): PublicApi {
490
+ return {
491
+ analysis: {
492
+ templateAnalyzer: new TemplateAnalyzerImpl(),
493
+ dependencyAnalyzer: new DependencyAnalyzerImpl(),
494
+ newAnalyzer: new NewAnalyzerImpl(),
495
+ },
496
+ };
497
+ }
498
+ ```
499
+
500
+ ## See Also
501
+
502
+ - [packages/core/README.md](../core/README.md) - Kernel infrastructure
503
+ - [packages/plugin-system/README.md](../plugin-system/README.md) - Plugin contracts
504
+
505
+ ## License
506
+
507
+ MIT License - See LICENSE file for details
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @angular-modernizer/api - Complexity Metrics Calculator
3
+ *
4
+ * Calculates code complexity and maintainability metrics for Angular applications.
5
+ * Provides quantitative measures to prioritize refactoring efforts.
6
+ */
7
+ import type { SourceFile, ClassDeclaration } from 'ts-morph';
8
+ /**
9
+ * Angular-specific metrics for components and directives.
10
+ */
11
+ export interface AngularMetrics {
12
+ /**
13
+ * Number of lifecycle hooks (ngOnInit, ngOnDestroy, etc.).
14
+ */
15
+ lifecycleHooks: number;
16
+ /**
17
+ * Number of @Input properties.
18
+ */
19
+ inputs: number;
20
+ /**
21
+ * Number of @Output properties.
22
+ */
23
+ outputs: number;
24
+ /**
25
+ * Number of Angular decorators (@Component, @Directive, etc.).
26
+ */
27
+ decorators: number;
28
+ }
29
+ /**
30
+ * Complexity Metrics Calculator - analyzes code complexity and maintainability.
31
+ */
32
+ export declare class ComplexityMetricsCalculator {
33
+ /**
34
+ * Calculate overall complexity score for a class (0-100 scale).
35
+ * Custom weighted heuristic combining established metrics (McCabe's Cyclomatic Complexity,
36
+ * LOC, method count from CK metrics) with Angular-specific indicators.
37
+ *
38
+ * Combines multiple metrics:
39
+ * - Cyclomatic complexity
40
+ * - Lines of code
41
+ * - Method count
42
+ * - Angular-specific complexity
43
+ *
44
+ * @param classDecl - The class declaration to analyze
45
+ * @returns Complexity score (0-100)
46
+ */
47
+ calculateOverallComplexity(classDecl: ClassDeclaration): number;
48
+ /**
49
+ * Calculate cyclomatic complexity for a class.
50
+ *
51
+ * Measures the number of linearly independent paths through the code.
52
+ * Higher values indicate more complex control flow.
53
+ *
54
+ * @param classDecl - The class declaration
55
+ * @returns Cyclomatic complexity score
56
+ */
57
+ calculateCyclomaticComplexity(classDecl: ClassDeclaration): number;
58
+ /**
59
+ * Calculate cyclomatic complexity for a single method.
60
+ * Implements McCabe's algorithm by counting decision points:
61
+ * if/else if, loops, switch cases, ternary operators, logical operators.
62
+ */
63
+ private calculateMethodComplexity;
64
+ /**
65
+ * Calculate lines of code for a source file.
66
+ *
67
+ * Excludes comments and whitespace for meaningful LOC count.
68
+ *
69
+ * @param sourceFile - The source file
70
+ * @returns Number of lines of code
71
+ */
72
+ calculateLOC(sourceFile: SourceFile): number;
73
+ /**
74
+ * Calculate the number of methods in a class.
75
+ *
76
+ * @param classDecl - The class declaration
77
+ * @returns Number of methods
78
+ */
79
+ calculateMethodCount(classDecl: ClassDeclaration): number;
80
+ /**
81
+ * Calculate dependency count for a source file.
82
+ *
83
+ * Counts unique external dependencies (imports from node_modules).
84
+ *
85
+ * @param sourceFile - The source file
86
+ * @returns Number of unique dependencies
87
+ */
88
+ calculateDependencyCount(sourceFile: SourceFile): number;
89
+ /**
90
+ * Calculate Angular-specific metrics for a class.
91
+ *
92
+ * Analyzes Angular decorators and patterns.
93
+ *
94
+ * @param classDecl - The class declaration
95
+ * @returns Angular-specific metrics
96
+ */
97
+ calculateAngularSpecificMetrics(classDecl: ClassDeclaration): AngularMetrics;
98
+ }
99
+ //# sourceMappingURL=complexity-metrics-calculator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity-metrics-calculator.d.ts","sourceRoot":"","sources":["../../src/analysis/complexity-metrics-calculator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAqB,MAAM,UAAU,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,2BAA2B;IACtC;;;;;;;;;;;;;OAaG;IACH,0BAA0B,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM;IAyB/D;;;;;;;;OAQG;IACH,6BAA6B,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM;IAWlE;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAuBjC;;;;;;;OAOG;IACH,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;IAqB5C;;;;;OAKG;IACH,oBAAoB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM;IAIzD;;;;;;;OAOG;IACH,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;IAkBxD;;;;;;;OAOG;IACH,+BAA+B,CAAC,SAAS,EAAE,gBAAgB,GAAG,cAAc;CAsD7E"}