tech-debt-score 0.1.4 → 0.1.6
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.
- package/dist/adapters/input/FileSystemReader.d.ts.map +1 -1
- package/dist/adapters/input/FileSystemReader.js +4 -5
- package/dist/adapters/input/FileSystemReader.js.map +1 -1
- package/dist/adapters/output/TerminalReporter.d.ts.map +1 -1
- package/dist/adapters/output/TerminalReporter.js +8 -0
- package/dist/adapters/output/TerminalReporter.js.map +1 -1
- package/dist/application/config/AnalysisConfig.d.ts.map +1 -1
- package/dist/application/config/AnalysisConfig.js +10 -2
- package/dist/application/config/AnalysisConfig.js.map +1 -1
- package/dist/application/services/AnalysisService.d.ts.map +1 -1
- package/dist/application/services/AnalysisService.js +29 -11
- package/dist/application/services/AnalysisService.js.map +1 -1
- package/dist/cli/commands/analyze.d.ts.map +1 -1
- package/dist/cli/commands/analyze.js +8 -7
- package/dist/cli/commands/analyze.js.map +1 -1
- package/package.json +8 -2
- package/DEVELOPMENT.md +0 -147
- package/SETUP_COMPLETE.md +0 -188
- package/TECHNICAL_DESIGN.md +0 -563
- package/src/adapters/input/FileSystemReader.ts +0 -47
- package/src/adapters/input/TypeScriptParser.ts +0 -367
- package/src/adapters/output/JsonExporter.ts +0 -48
- package/src/adapters/output/TerminalReporter.ts +0 -88
- package/src/application/config/AnalysisConfig.ts +0 -58
- package/src/application/ports/IFileReader.ts +0 -36
- package/src/application/ports/IParser.ts +0 -40
- package/src/application/ports/IReporter.ts +0 -26
- package/src/application/services/AnalysisService.ts +0 -199
- package/src/application/services/DependencyAnalyzer.ts +0 -158
- package/src/application/services/DuplicationDetector.ts +0 -207
- package/src/cli/commands/analyze.ts +0 -77
- package/src/cli/index.ts +0 -81
- package/src/domain/entities/Finding.ts +0 -79
- package/src/domain/entities/Metric.ts +0 -70
- package/src/domain/entities/Rule.ts +0 -49
- package/src/domain/entities/Score.ts +0 -94
- package/src/domain/index.ts +0 -15
- package/src/domain/rules/CircularDependencyRule.ts +0 -65
- package/src/domain/rules/ComplexityRule.ts +0 -88
- package/src/domain/rules/DuplicationRule.ts +0 -70
- package/src/domain/rules/SizeRule.ts +0 -98
- package/src/domain/rules/TypeSafetyRule.ts +0 -63
- package/src/index.ts +0 -0
- package/src/shared/types.ts +0 -18
- package/tests/application/index.test.ts +0 -12
- package/tests/domain/index.test.ts +0 -14
- package/tests/e2e/index.test.ts +0 -13
- package/tsconfig.json +0 -31
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain Rule: Size Rule
|
|
3
|
-
* Evaluates file and function size metrics
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { BaseRule } from '../entities/Rule.js';
|
|
7
|
-
import type { Metric } from '../entities/Metric.js';
|
|
8
|
-
import type { Finding } from '../entities/Finding.js';
|
|
9
|
-
import { FindingBuilder } from '../entities/Finding.js';
|
|
10
|
-
|
|
11
|
-
export class SizeRule extends BaseRule {
|
|
12
|
-
// Thresholds (configurable in future versions)
|
|
13
|
-
private readonly MAX_FILE_LINES = 300;
|
|
14
|
-
private readonly MAX_FUNCTION_LINES = 50;
|
|
15
|
-
private readonly MAX_PARAMETERS = 5;
|
|
16
|
-
|
|
17
|
-
constructor() {
|
|
18
|
-
super(
|
|
19
|
-
'size',
|
|
20
|
-
'Size Rule',
|
|
21
|
-
'Evaluates file and function size to identify overly large code units'
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
evaluate(metrics: Metric[]): Finding[] {
|
|
26
|
-
const findings: Finding[] = [];
|
|
27
|
-
|
|
28
|
-
const sizeMetrics = metrics.filter(
|
|
29
|
-
m => m.name === 'file-length' || m.name === 'function-length' || m.name === 'parameter-count'
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
for (const metric of sizeMetrics) {
|
|
33
|
-
if (metric.name === 'file-length' && metric.value > this.MAX_FILE_LINES) {
|
|
34
|
-
findings.push(
|
|
35
|
-
new FindingBuilder()
|
|
36
|
-
.withRuleId(this.id)
|
|
37
|
-
.withSeverity(metric.value > 500 ? 'high' : 'medium')
|
|
38
|
-
.withMessage(`Large file (${metric.value} lines)`)
|
|
39
|
-
.withFilePath(metric.filePath)
|
|
40
|
-
.withSuggestion('Consider splitting this file into smaller, more focused modules')
|
|
41
|
-
.build()
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (metric.name === 'function-length' && metric.value > this.MAX_FUNCTION_LINES) {
|
|
46
|
-
const builder = new FindingBuilder()
|
|
47
|
-
.withRuleId(this.id)
|
|
48
|
-
.withSeverity(metric.value > 100 ? 'high' : 'medium')
|
|
49
|
-
.withMessage(
|
|
50
|
-
`Large function (${metric.value} lines) in ${metric.context || 'unknown'}`
|
|
51
|
-
)
|
|
52
|
-
.withFilePath(metric.filePath)
|
|
53
|
-
.withSuggestion('Break this function into smaller, single-purpose functions');
|
|
54
|
-
|
|
55
|
-
if (metric.location) {
|
|
56
|
-
builder.withLocation(metric.location);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
findings.push(builder.build());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (metric.name === 'parameter-count' && metric.value > this.MAX_PARAMETERS) {
|
|
63
|
-
const builder = new FindingBuilder()
|
|
64
|
-
.withRuleId(this.id)
|
|
65
|
-
.withSeverity('medium')
|
|
66
|
-
.withMessage(
|
|
67
|
-
`Too many parameters (${metric.value}) in ${metric.context || 'function'}`
|
|
68
|
-
)
|
|
69
|
-
.withFilePath(metric.filePath)
|
|
70
|
-
.withSuggestion('Consider using an options object or builder pattern');
|
|
71
|
-
|
|
72
|
-
if (metric.location) {
|
|
73
|
-
builder.withLocation(metric.location);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
findings.push(builder.build());
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return findings;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
calculateScore(findings: Finding[]): number {
|
|
84
|
-
if (findings.length === 0) return 100;
|
|
85
|
-
|
|
86
|
-
const penalty = findings.reduce((sum, finding) => {
|
|
87
|
-
switch (finding.severity) {
|
|
88
|
-
case 'high': return sum + 8;
|
|
89
|
-
case 'medium': return sum + 4;
|
|
90
|
-
case 'low': return sum + 2;
|
|
91
|
-
default: return sum;
|
|
92
|
-
}
|
|
93
|
-
}, 0);
|
|
94
|
-
|
|
95
|
-
const score = Math.max(0, 100 - penalty);
|
|
96
|
-
return Math.round(score * 100) / 100;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain Rule: Type Safety Rule
|
|
3
|
-
* Evaluates TypeScript type safety indicators
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { BaseRule } from '../entities/Rule.js';
|
|
7
|
-
import type { Metric } from '../entities/Metric.js';
|
|
8
|
-
import type { Finding } from '../entities/Finding.js';
|
|
9
|
-
import { FindingBuilder } from '../entities/Finding.js';
|
|
10
|
-
|
|
11
|
-
export class TypeSafetyRule extends BaseRule {
|
|
12
|
-
constructor() {
|
|
13
|
-
super(
|
|
14
|
-
'type-safety',
|
|
15
|
-
'Type Safety Rule',
|
|
16
|
-
'Evaluates TypeScript type safety by detecting usage of the `any` type'
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
evaluate(metrics: Metric[]): Finding[] {
|
|
21
|
-
const findings: Finding[] = [];
|
|
22
|
-
|
|
23
|
-
const anyUsageMetrics = metrics.filter(m => m.name === 'any-usage');
|
|
24
|
-
|
|
25
|
-
for (const metric of anyUsageMetrics) {
|
|
26
|
-
if (metric.value > 0) {
|
|
27
|
-
const builder = new FindingBuilder()
|
|
28
|
-
.withRuleId(this.id)
|
|
29
|
-
.withSeverity(metric.value > 5 ? 'high' : 'medium')
|
|
30
|
-
.withMessage(
|
|
31
|
-
`Found ${metric.value} usage(s) of 'any' type in ${metric.context || 'code'}`
|
|
32
|
-
)
|
|
33
|
-
.withFilePath(metric.filePath)
|
|
34
|
-
.withSuggestion('Replace `any` with specific types or use `unknown` for better type safety');
|
|
35
|
-
|
|
36
|
-
if (metric.location) {
|
|
37
|
-
builder.withLocation(metric.location);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
findings.push(builder.build());
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return findings;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
calculateScore(findings: Finding[]): number {
|
|
48
|
-
if (findings.length === 0) return 100;
|
|
49
|
-
|
|
50
|
-
// Each 'any' usage reduces the score
|
|
51
|
-
const totalAnyUsages = findings.reduce((sum, finding) => {
|
|
52
|
-
// Extract count from message (hacky, but works for v1)
|
|
53
|
-
const match = finding.message.match(/Found (\d+) usage/);
|
|
54
|
-
return sum + (match ? parseInt(match[1] ?? '0', 10) : 1);
|
|
55
|
-
}, 0);
|
|
56
|
-
|
|
57
|
-
// Each 'any' costs 3 points
|
|
58
|
-
const penalty = Math.min(100, totalAnyUsages * 3);
|
|
59
|
-
const score = Math.max(0, 100 - penalty);
|
|
60
|
-
|
|
61
|
-
return Math.round(score * 100) / 100;
|
|
62
|
-
}
|
|
63
|
-
}
|
package/src/index.ts
DELETED
|
File without changes
|
package/src/shared/types.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared type definitions used across the application
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export interface SourceLocation {
|
|
6
|
-
startLine: number;
|
|
7
|
-
endLine: number;
|
|
8
|
-
startColumn: number;
|
|
9
|
-
endColumn: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type Severity = 'low' | 'medium' | 'high';
|
|
13
|
-
|
|
14
|
-
export interface FileMetadata {
|
|
15
|
-
path: string;
|
|
16
|
-
size: number;
|
|
17
|
-
linesOfCode: number;
|
|
18
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain Layer Tests
|
|
3
|
-
*
|
|
4
|
-
* Unit tests for pure business logic (no I/O, no mocks needed)
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// TODO: Add tests for:
|
|
8
|
-
// - Score calculation
|
|
9
|
-
// - Metric builder
|
|
10
|
-
// - Finding builder
|
|
11
|
-
// - Rule evaluation (ComplexityRule, SizeRule, TypeSafetyRule)
|
|
12
|
-
// - ScoreCalculator normalization
|
|
13
|
-
|
|
14
|
-
export {};
|
package/tests/e2e/index.test.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
/* File Layout */
|
|
4
|
-
"rootDir": "./src",
|
|
5
|
-
"outDir": "./dist",
|
|
6
|
-
|
|
7
|
-
/* Environment */
|
|
8
|
-
"target": "ES2020",
|
|
9
|
-
"module": "NodeNext",
|
|
10
|
-
"moduleResolution": "NodeNext",
|
|
11
|
-
"types": ["node"],
|
|
12
|
-
|
|
13
|
-
/* Output */
|
|
14
|
-
"sourceMap": true,
|
|
15
|
-
"declaration": true,
|
|
16
|
-
"declarationMap": true,
|
|
17
|
-
|
|
18
|
-
/* Type Safety */
|
|
19
|
-
"strict": true,
|
|
20
|
-
"noUncheckedIndexedAccess": true,
|
|
21
|
-
"exactOptionalPropertyTypes": true,
|
|
22
|
-
|
|
23
|
-
/* Module / Build Safety */
|
|
24
|
-
"verbatimModuleSyntax": true,
|
|
25
|
-
"isolatedModules": true,
|
|
26
|
-
"moduleDetection": "force",
|
|
27
|
-
"skipLibCheck": true
|
|
28
|
-
},
|
|
29
|
-
"include": ["src"],
|
|
30
|
-
"exclude": ["node_modules", "dist"]
|
|
31
|
-
}
|