tech-debt-score 0.1.5 → 0.1.7

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 (48) hide show
  1. package/dist/adapters/input/FileSystemReader.d.ts.map +1 -1
  2. package/dist/adapters/input/FileSystemReader.js +4 -5
  3. package/dist/adapters/input/FileSystemReader.js.map +1 -1
  4. package/dist/adapters/output/TerminalReporter.d.ts.map +1 -1
  5. package/dist/adapters/output/TerminalReporter.js +8 -0
  6. package/dist/adapters/output/TerminalReporter.js.map +1 -1
  7. package/dist/application/config/AnalysisConfig.d.ts.map +1 -1
  8. package/dist/application/config/AnalysisConfig.js +10 -2
  9. package/dist/application/config/AnalysisConfig.js.map +1 -1
  10. package/dist/application/services/AnalysisService.d.ts.map +1 -1
  11. package/dist/application/services/AnalysisService.js +29 -11
  12. package/dist/application/services/AnalysisService.js.map +1 -1
  13. package/dist/cli/commands/analyze.d.ts.map +1 -1
  14. package/dist/cli/commands/analyze.js +8 -7
  15. package/dist/cli/commands/analyze.js.map +1 -1
  16. package/package.json +8 -2
  17. package/DEVELOPMENT.md +0 -147
  18. package/SETUP_COMPLETE.md +0 -188
  19. package/TECHNICAL_DESIGN.md +0 -563
  20. package/src/adapters/input/FileSystemReader.ts +0 -47
  21. package/src/adapters/input/TypeScriptParser.ts +0 -367
  22. package/src/adapters/output/JsonExporter.ts +0 -48
  23. package/src/adapters/output/TerminalReporter.ts +0 -94
  24. package/src/application/config/AnalysisConfig.ts +0 -58
  25. package/src/application/ports/IFileReader.ts +0 -36
  26. package/src/application/ports/IParser.ts +0 -40
  27. package/src/application/ports/IReporter.ts +0 -26
  28. package/src/application/services/AnalysisService.ts +0 -218
  29. package/src/application/services/DependencyAnalyzer.ts +0 -158
  30. package/src/application/services/DuplicationDetector.ts +0 -207
  31. package/src/cli/commands/analyze.ts +0 -77
  32. package/src/cli/index.ts +0 -81
  33. package/src/domain/entities/Finding.ts +0 -79
  34. package/src/domain/entities/Metric.ts +0 -70
  35. package/src/domain/entities/Rule.ts +0 -49
  36. package/src/domain/entities/Score.ts +0 -94
  37. package/src/domain/index.ts +0 -15
  38. package/src/domain/rules/CircularDependencyRule.ts +0 -65
  39. package/src/domain/rules/ComplexityRule.ts +0 -88
  40. package/src/domain/rules/DuplicationRule.ts +0 -70
  41. package/src/domain/rules/SizeRule.ts +0 -98
  42. package/src/domain/rules/TypeSafetyRule.ts +0 -63
  43. package/src/index.ts +0 -0
  44. package/src/shared/types.ts +0 -18
  45. package/tests/application/index.test.ts +0 -12
  46. package/tests/domain/index.test.ts +0 -14
  47. package/tests/e2e/index.test.ts +0 -13
  48. package/tsconfig.json +0 -31
@@ -1,563 +0,0 @@
1
- # Technical Design Document: tech-debt-score
2
-
3
- > **Version:** 1.0
4
- > **Last Updated:** 2026-01-20
5
- > **Status:** Design Phase
6
-
7
- ---
8
-
9
- ## Table of Contents
10
-
11
- 1. [Overview](#overview)
12
- 2. [Goals and Non-Goals](#goals-and-non-goals)
13
- 3. [Supported Languages and Scope](#supported-languages-and-scope)
14
- 4. [Metrics Specification](#metrics-specification)
15
- 5. [Architecture](#architecture)
16
- 6. [Directory Structure](#directory-structure)
17
- 7. [Data Flow](#data-flow)
18
- 8. [Implementation Guidelines](#implementation-guidelines)
19
- 9. [Future Considerations](#future-considerations)
20
-
21
- ---
22
-
23
- ## Overview
24
-
25
- `tech-debt-score` is an open-source CLI tool and analysis engine that quantifies technical debt in a codebase using a single, actionable score (0-100).
26
-
27
- ### Key Principles
28
-
29
- - **Developer-focused**: Built by developers, for developers
30
- - **Actionable over comprehensive**: Measures what teams can control
31
- - **AST-based analysis**: No regex, language-aware parsing
32
- - **Clean architecture**: Hexagonal/Ports & Adapters pattern
33
- - **CI-friendly**: Easy integration into automated workflows
34
-
35
- ### Value Proposition
36
-
37
- Unlike traditional tools that focus on lint errors and code smells, `tech-debt-score` answers critical questions:
38
- - *How bad is our technical debt, really?*
39
- - *Is it getting better or worse over time?*
40
- - *Where should we focus first?*
41
-
42
- ---
43
-
44
- ## Goals and Non-Goals
45
-
46
- ### ✅ Goals (V1)
47
-
48
- - Provide a **normalized 0-100 technical debt score**
49
- - Measure **team-controllable factors** only
50
- - Support **TypeScript and JavaScript** codebases
51
- - Generate **human-readable and JSON reports**
52
- - Enable **trend tracking** over time
53
- - Maintain **fast execution** and minimal configuration
54
-
55
- ### ❌ Non-Goals (V1)
56
-
57
- - Deprecated dependencies detection
58
- - Security vulnerability scanning
59
- - Runtime performance analysis
60
- - External API/service health checks
61
- - Supporting languages beyond JS/TS
62
-
63
- ---
64
-
65
- ## Supported Languages and Scope
66
-
67
- ### Supported Languages
68
-
69
- - **TypeScript** (`.ts` files)
70
- - **JavaScript** (`.js` files)
71
-
72
- ### Default File Patterns
73
-
74
- **Analyzed:**
75
- - `src/**/*.ts`
76
- - `src/**/*.js`
77
-
78
- **Ignored:**
79
- - `node_modules/`
80
- - `dist/`
81
- - `build/`
82
- - `coverage/`
83
- - `.git/`
84
- - Generated files
85
-
86
- ### Future Configuration
87
-
88
- CLI flags will allow customization of these patterns.
89
-
90
- ---
91
-
92
- ## Metrics Specification
93
-
94
- ### 1. Structural Code Metrics (AST-based)
95
-
96
- **Implementation Approach:** All metrics use AST parsing (not regex) for accuracy.
97
-
98
- #### File-Level Metrics
99
-
100
- | Metric | Description | Purpose |
101
- |--------|-------------|---------|
102
- | **File Length (LOC)** | Lines of code per file | Identify overly large files |
103
- | **TODO Comments** | Count of `// TODO` comments | Track deferred work |
104
- | **FIXME Comments** | Count of `// FIXME` comments | Track known issues |
105
-
106
- #### Function-Level Metrics
107
-
108
- | Metric | Description | Purpose |
109
- |--------|-------------|---------|
110
- | **Function Length** | Lines of code per function | Identify complex functions |
111
- | **Nesting Depth** | Maximum nesting level | Measure code complexity |
112
- | **Cyclomatic Complexity** | Number of decision paths | Measure testability |
113
- | **Parameter Count** | Number of function parameters | Identify hard-to-use functions |
114
-
115
- #### TypeScript-Specific Metrics
116
-
117
- | Metric | Description | Purpose |
118
- |--------|-------------|---------|
119
- | **`any` Usage** | Usage of the `any` type | Track type safety violations |
120
-
121
- ### 2. Project-Level Signals (Aggregated)
122
-
123
- These provide the "big picture" view:
124
-
125
- | Signal | Calculation | Purpose |
126
- |--------|-------------|---------|
127
- | **Total Files** | Count of analyzed files | Scope indicator |
128
- | **Average Complexity** | Mean complexity per file | Overall health indicator |
129
- | **Large Files %** | Percentage of files exceeding threshold | Hotspot identification |
130
- | **Complex Functions %** | Percentage of functions exceeding threshold | Risk assessment |
131
-
132
- ### 3. Scoring Algorithm (High-Level)
133
-
134
- ```
135
- 1. Collect raw metrics per file
136
- 2. Normalize metrics to 0-100 scale
137
- 3. Apply category weights:
138
- - Complexity: 30%
139
- - Size: 25%
140
- - Type Safety: 20%
141
- - Code Quality: 15%
142
- - Structure: 10%
143
- 4. Calculate weighted average
144
- 5. Generate final score (inverse: 100 = no debt)
145
- ```
146
-
147
- ---
148
-
149
- ## Architecture
150
-
151
- ### Architectural Style
152
-
153
- **Hexagonal Architecture (Ports & Adapters)**
154
-
155
- This pattern ensures:
156
- - Clear separation of concerns
157
- - High testability
158
- - Easy adapter swapping
159
- - Framework independence
160
-
161
- ### Layer Definitions
162
-
163
- ```
164
- ┌─────────────────────────────────────────┐
165
- │ CLI Adapter (Entry) │
166
- │ (No Business Logic) │
167
- └─────────────────┬───────────────────────┘
168
-
169
- ┌─────────────────▼───────────────────────┐
170
- │ Application Layer │
171
- │ - Orchestrates analysis │
172
- │ - Applies rules │
173
- │ - Aggregates scores │
174
- └─────┬───────────────────────┬───────────┘
175
- │ │
176
- ┌─────▼─────────┐ ┌────────▼──────────┐
177
- │ Input Adapters│ │ Output Adapters │
178
- │ - File Reader │ │ - Terminal Report │
179
- │ - AST Parser │ │ - JSON Exporter │
180
- └─────┬─────────┘ └────────┬──────────┘
181
- │ │
182
- └───────────┬───────────┘
183
-
184
- ┌─────────▼──────────┐
185
- │ Domain Layer │
186
- │ (Pure Logic) │
187
- │ - Score │
188
- │ - Metric │
189
- │ - Rule │
190
- │ - Finding │
191
- └────────────────────┘
192
- ```
193
-
194
- ### Layer Details
195
-
196
- #### 1. Domain Layer (Pure Logic)
197
-
198
- **Core Entities:**
199
- - `Score` - Represents technical debt scores and calculations
200
- - `Metric` - Individual measurement data
201
- - `Rule` - Evaluation and scoring rules
202
- - `Finding` - Identified code issues
203
-
204
- **Constraints:**
205
- - ❌ No filesystem access
206
- - ❌ No CLI dependencies
207
- - ❌ No Node.js APIs
208
- - ❌ No external libraries (except utility functions)
209
- - ✅ Pure TypeScript/JavaScript logic only
210
- - ✅ 100% unit testable
211
-
212
- **Example Domain Interfaces:**
213
-
214
- ```typescript
215
- interface Metric {
216
- name: string;
217
- value: number;
218
- filePath: string;
219
- location?: SourceLocation;
220
- }
221
-
222
- interface Rule {
223
- id: string;
224
- name: string;
225
- evaluate(metrics: Metric[]): Finding[];
226
- calculateScore(findings: Finding[]): number;
227
- }
228
-
229
- interface Score {
230
- overall: number; // 0-100
231
- categories: CategoryScore[];
232
- timestamp: Date;
233
- }
234
-
235
- interface Finding {
236
- ruleId: string;
237
- severity: 'low' | 'medium' | 'high';
238
- message: string;
239
- filePath: string;
240
- location?: SourceLocation;
241
- }
242
- ```
243
-
244
- #### 2. Application Layer (Use Cases)
245
-
246
- **Responsibilities:**
247
- - Orchestrate the analysis workflow
248
- - Coordinate between domain and adapters
249
- - Apply business rules
250
- - Aggregate results
251
-
252
- **Example Services:**
253
-
254
- ```typescript
255
- class AnalysisService {
256
- constructor(
257
- private fileReader: IFileReader,
258
- private parser: IParser,
259
- private rules: Rule[]
260
- ) {}
261
-
262
- async analyze(config: AnalysisConfig): Promise<AnalysisResult> {
263
- // 1. Read files
264
- // 2. Parse to AST
265
- // 3. Extract metrics
266
- // 4. Apply rules
267
- // 5. Calculate scores
268
- // 6. Return results
269
- }
270
- }
271
- ```
272
-
273
- #### 3. Adapters Layer (External Interfaces)
274
-
275
- ##### Input Adapters (Inbound Ports)
276
-
277
- **File System Reader:**
278
- - Scans directories
279
- - Filters files by patterns
280
- - Respects ignore rules
281
- - Returns file metadata
282
-
283
- **AST Parser:**
284
- - Parses TypeScript/JavaScript
285
- - Extracts structural information
286
- - Handles syntax errors gracefully
287
- - Technology: `@typescript-eslint/parser`, `@babel/parser`, or `acorn`
288
-
289
- ##### Output Adapters (Outbound Ports)
290
-
291
- **Terminal Reporter:**
292
- - Formats results for console
293
- - Uses colors and formatting
294
- - Provides actionable output
295
- - Technology: `chalk`, `cli-table3`
296
-
297
- **JSON Exporter:**
298
- - Exports structured data
299
- - CI/CD friendly format
300
- - Version-stamped output
301
-
302
- #### 4. Entry Point
303
-
304
- **CLI Adapter:**
305
- - Parses command-line arguments
306
- - Maps to application commands
307
- - Handles errors and exit codes
308
- - **No business logic**
309
- - Technology: `commander` or `yargs`
310
-
311
- ### Dependency Rules
312
-
313
- **The Dependency Rule:** Dependencies point **inward only**
314
-
315
- ```
316
- CLI → Application → Domain
317
-
318
- Adapters (depend on Domain interfaces)
319
- ```
320
-
321
- - Domain layer has **zero dependencies**
322
- - Application layer depends on **Domain only**
323
- - Adapters depend on **Domain interfaces**
324
- - CLI depends on **Application and Adapters**
325
-
326
- ---
327
-
328
- ## Directory Structure
329
-
330
- ```
331
- tech-debt-score/
332
- ├── src/
333
- │ ├── domain/ # Pure business logic
334
- │ │ ├── entities/
335
- │ │ │ ├── Score.ts
336
- │ │ │ ├── Metric.ts
337
- │ │ │ ├── Rule.ts
338
- │ │ │ └── Finding.ts
339
- │ │ ├── rules/ # Scoring rules
340
- │ │ │ ├── ComplexityRule.ts
341
- │ │ │ ├── SizeRule.ts
342
- │ │ │ └── TypeSafetyRule.ts
343
- │ │ └── services/
344
- │ │ └── ScoreCalculator.ts
345
- │ │
346
- │ ├── application/ # Use cases & orchestration
347
- │ │ ├── services/
348
- │ │ │ └── AnalysisService.ts
349
- │ │ ├── ports/ # Interface definitions
350
- │ │ │ ├── IFileReader.ts
351
- │ │ │ ├── IParser.ts
352
- │ │ │ └── IReporter.ts
353
- │ │ └── config/
354
- │ │ └── AnalysisConfig.ts
355
- │ │
356
- │ ├── adapters/ # External integrations
357
- │ │ ├── input/
358
- │ │ │ ├── FileSystemReader.ts
359
- │ │ │ └── TypeScriptParser.ts
360
- │ │ └── output/
361
- │ │ ├── TerminalReporter.ts
362
- │ │ └── JsonExporter.ts
363
- │ │
364
- │ ├── cli/ # Command-line interface
365
- │ │ ├── index.ts # Entry point
366
- │ │ └── commands/
367
- │ │ └── analyze.ts
368
- │ │
369
- │ └── shared/ # Shared utilities
370
- │ ├── types.ts
371
- │ └── utils.ts
372
-
373
- ├── tests/
374
- │ ├── domain/ # Unit tests (no I/O)
375
- │ ├── application/ # Integration tests
376
- │ └── e2e/ # End-to-end tests
377
-
378
- ├── docs/
379
- ├── package.json
380
- ├── tsconfig.json
381
- └── README.md
382
- ```
383
-
384
- ---
385
-
386
- ## Data Flow
387
-
388
- ### Analysis Flow
389
-
390
- ```
391
- 1. User runs CLI command
392
-
393
- 2. CLI adapter parses arguments
394
-
395
- 3. Application layer receives config
396
-
397
- 4. FileReader adapter scans files
398
-
399
- 5. Parser adapter generates ASTs
400
-
401
- 6. Application extracts Metrics
402
-
403
- 7. Domain Rules evaluate Metrics → Findings
404
-
405
- 8. Domain ScoreCalculator → Score
406
-
407
- 9. Application returns AnalysisResult
408
-
409
- 10. Reporter adapter formats output
410
-
411
- 11. CLI displays results
412
- ```
413
-
414
- ### Data Structures
415
-
416
- ```typescript
417
- // Input
418
- AnalysisConfig {
419
- rootPath: string;
420
- patterns: string[];
421
- ignore: string[];
422
- }
423
-
424
- // Processing
425
- File[] → AST[] → Metric[] → Finding[] → Score
426
-
427
- // Output
428
- AnalysisResult {
429
- score: Score;
430
- findings: Finding[];
431
- metadata: {
432
- filesAnalyzed: number;
433
- duration: number;
434
- timestamp: Date;
435
- }
436
- }
437
- ```
438
-
439
- ---
440
-
441
- ## Implementation Guidelines
442
-
443
- ### Technology Stack
444
-
445
- - **Language:** TypeScript
446
- - **Runtime:** Node.js (v18+)
447
- - **Package Manager:** npm
448
- - **Build Tool:** tsc (TypeScript compiler)
449
-
450
- ### Recommended Libraries
451
-
452
- | Purpose | Library | Why |
453
- |---------|---------|-----|
454
- | AST Parsing | `@typescript-eslint/parser` | TypeScript support |
455
- | JS Parsing | `@babel/parser` or `acorn` | JavaScript support |
456
- | File Scanning | `fast-glob` | Fast pattern matching |
457
- | CLI Framework | `commander` | Intuitive API |
458
- | Terminal Output | `chalk` + `cli-table3` | Beautiful formatting |
459
- | Testing | `vitest` or `jest` | Fast, modern testing |
460
-
461
- ### Code Quality Standards
462
-
463
- - **TypeScript strict mode:** Enabled
464
- - **No `any` types** in core codebase (except adapters if needed)
465
- - **100% test coverage** for domain layer
466
- - **ESLint + Prettier** for consistency
467
- - **Clear error messages** for users
468
-
469
- ### Testing Strategy
470
-
471
- 1. **Unit Tests** (Domain layer)
472
- - Test pure functions
473
- - No mocks needed (no I/O)
474
- - Fast execution
475
-
476
- 2. **Integration Tests** (Application layer)
477
- - Test with mock adapters
478
- - Verify orchestration logic
479
-
480
- 3. **E2E Tests**
481
- - Test real codebases
482
- - Verify actual output
483
- - Performance benchmarks
484
-
485
- ---
486
-
487
- ## Future Considerations
488
-
489
- ### V2 Features (Potential)
490
-
491
- - **Additional Languages:** Python, Go, Java
492
- - **Code Duplication Detection:** AST-based clone detection
493
- - **Test Coverage Integration:** Parse coverage reports
494
- - **Custom Rules:** User-defined scoring rules
495
- - **Configuration File:** `.tech-debt-score.json`
496
- - **Git Integration:** Track score over commits
497
- - **Web Dashboard:** Visualize trends
498
- - **IDE Extensions:** VS Code, IntelliJ
499
- - **CI Platform Integrations:** GitHub Actions, GitLab CI
500
-
501
- ### Scalability Considerations
502
-
503
- - **Caching:** Cache AST parsing results
504
- - **Parallelization:** Process files in parallel
505
- - **Incremental Analysis:** Only analyze changed files
506
- - **Large Codebases:** Stream processing for memory efficiency
507
-
508
- ### Extensibility Points
509
-
510
- The architecture supports:
511
- - New input adapters (e.g., read from Git, API)
512
- - New output adapters (e.g., HTML report, database)
513
- - New parsing adapters (e.g., Python, Go)
514
- - New rules (plugin system)
515
- - Different scoring algorithms
516
-
517
- ---
518
-
519
- ## Questions & Decisions Log
520
-
521
- ### Open Questions
522
-
523
- 1. **Scoring thresholds:** What defines a "large file" or "complex function"?
524
- - Proposal: Configurable, with sensible defaults (e.g., 300 LOC, cyclomatic > 10)
525
-
526
- 2. **Weighting system:** How to balance different metric categories?
527
- - Proposal: Start with equal weights, tune based on user feedback
528
-
529
- 3. **Trend storage:** Where to store historical scores?
530
- - Proposal: V1 outputs JSON, users can track; V2 adds built-in storage
531
-
532
- ### Decisions Made
533
-
534
- - ✅ **Architecture:** Hexagonal/Ports & Adapters (2026-01-20)
535
- - ✅ **Languages (V1):** TypeScript and JavaScript only (2026-01-20)
536
- - ✅ **Analysis Method:** AST-based, no regex (2026-01-20)
537
- - ✅ **Scope (V1):** Team-controllable metrics only (2026-01-20)
538
-
539
- ---
540
-
541
- ## Appendix
542
-
543
- ### References
544
-
545
- - [Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/)
546
- - [AST Explorer](https://astexplorer.net/) - For testing AST parsing
547
- - [TypeScript Compiler API](https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API)
548
- - [Cyclomatic Complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity)
549
-
550
- ### Contributors
551
-
552
- - Initial Design: 2026-01-20
553
-
554
- ---
555
-
556
- **Next Steps:**
557
- 1. Review and approve this design
558
- 2. Set up project structure
559
- 3. Implement domain layer (pure logic)
560
- 4. Implement AST parser adapter
561
- 5. Build CLI and reporting
562
- 6. Add comprehensive tests
563
- 7. Package and publish
@@ -1,47 +0,0 @@
1
- /**
2
- * Input Adapter: File System Reader
3
- * Implements IFileReader using Node.js filesystem
4
- */
5
-
6
- import { readFile } from 'node:fs/promises';
7
- import { stat } from 'node:fs/promises';
8
- import { resolve, join } from 'node:path';
9
- import fg from 'fast-glob';
10
- import type { IFileReader, FileReadResult } from '../../application/ports/IFileReader.js';
11
-
12
- export class FileSystemReader implements IFileReader {
13
- async scan(rootPath: string, patterns: string[], ignore: string[]): Promise<string[]> {
14
- // Resolve the root path to absolute
15
- const absoluteRoot = resolve(rootPath);
16
-
17
- // Scan for files using cwd - this is more robust for glob matching
18
- const files = await fg(patterns, {
19
- cwd: absoluteRoot,
20
- ignore,
21
- absolute: true,
22
- onlyFiles: true,
23
- dot: false,
24
- });
25
-
26
- return files;
27
- }
28
-
29
- async read(filePath: string): Promise<FileReadResult> {
30
- const content = await readFile(filePath, 'utf-8');
31
- const stats = await stat(filePath);
32
- const lines = content.split('\n');
33
-
34
- return {
35
- content,
36
- metadata: {
37
- path: filePath,
38
- size: stats.size,
39
- linesOfCode: lines.length,
40
- },
41
- };
42
- }
43
-
44
- async readBatch(filePaths: string[]): Promise<FileReadResult[]> {
45
- return Promise.all(filePaths.map(path => this.read(path)));
46
- }
47
- }