@mathonsunday/dead-code-toolkit 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.
- package/README.md +356 -0
- package/dist/analyzer.d.ts +23 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +173 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/checkers/knipChecker.d.ts +11 -0
- package/dist/checkers/knipChecker.d.ts.map +1 -0
- package/dist/checkers/knipChecker.js +226 -0
- package/dist/checkers/knipChecker.js.map +1 -0
- package/dist/checkers/typescriptChecker.d.ts +10 -0
- package/dist/checkers/typescriptChecker.d.ts.map +1 -0
- package/dist/checkers/typescriptChecker.js +174 -0
- package/dist/checkers/typescriptChecker.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +204 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/detectors.d.ts +29 -0
- package/dist/config/detectors.d.ts.map +1 -0
- package/dist/config/detectors.js +159 -0
- package/dist/config/detectors.js.map +1 -0
- package/dist/config/templates.d.ts +76 -0
- package/dist/config/templates.d.ts.map +1 -0
- package/dist/config/templates.js +191 -0
- package/dist/config/templates.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/reporters/jsonReporter.d.ts +68 -0
- package/dist/reporters/jsonReporter.d.ts.map +1 -0
- package/dist/reporters/jsonReporter.js +161 -0
- package/dist/reporters/jsonReporter.js.map +1 -0
- package/dist/setup/hookInstaller.d.ts +36 -0
- package/dist/setup/hookInstaller.d.ts.map +1 -0
- package/dist/setup/hookInstaller.js +196 -0
- package/dist/setup/hookInstaller.js.map +1 -0
- package/dist/setup/installer.d.ts +10 -0
- package/dist/setup/installer.d.ts.map +1 -0
- package/dist/setup/installer.js +156 -0
- package/dist/setup/installer.js.map +1 -0
- package/dist/setup/packageJsonUpdater.d.ts +54 -0
- package/dist/setup/packageJsonUpdater.d.ts.map +1 -0
- package/dist/setup/packageJsonUpdater.js +129 -0
- package/dist/setup/packageJsonUpdater.js.map +1 -0
- package/dist/src/analyzer.d.ts +23 -0
- package/dist/src/analyzer.d.ts.map +1 -0
- package/dist/src/analyzer.js +173 -0
- package/dist/src/analyzer.js.map +1 -0
- package/dist/src/checkers/knipChecker.d.ts +11 -0
- package/dist/src/checkers/knipChecker.d.ts.map +1 -0
- package/dist/src/checkers/knipChecker.js +226 -0
- package/dist/src/checkers/knipChecker.js.map +1 -0
- package/dist/src/checkers/typescriptChecker.d.ts +10 -0
- package/dist/src/checkers/typescriptChecker.d.ts.map +1 -0
- package/dist/src/checkers/typescriptChecker.js +174 -0
- package/dist/src/checkers/typescriptChecker.js.map +1 -0
- package/dist/src/config/detectors.d.ts +29 -0
- package/dist/src/config/detectors.d.ts.map +1 -0
- package/dist/src/config/detectors.js +159 -0
- package/dist/src/config/detectors.js.map +1 -0
- package/dist/src/config/templates.d.ts +76 -0
- package/dist/src/config/templates.d.ts.map +1 -0
- package/dist/src/config/templates.js +191 -0
- package/dist/src/config/templates.js.map +1 -0
- package/dist/src/index.d.ts +13 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +17 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/reporters/jsonReporter.d.ts +68 -0
- package/dist/src/reporters/jsonReporter.d.ts.map +1 -0
- package/dist/src/reporters/jsonReporter.js +161 -0
- package/dist/src/reporters/jsonReporter.js.map +1 -0
- package/dist/src/setup/hookInstaller.d.ts +36 -0
- package/dist/src/setup/hookInstaller.d.ts.map +1 -0
- package/dist/src/setup/hookInstaller.js +196 -0
- package/dist/src/setup/hookInstaller.js.map +1 -0
- package/dist/src/setup/installer.d.ts +10 -0
- package/dist/src/setup/installer.d.ts.map +1 -0
- package/dist/src/setup/installer.js +156 -0
- package/dist/src/setup/installer.js.map +1 -0
- package/dist/src/setup/packageJsonUpdater.d.ts +54 -0
- package/dist/src/setup/packageJsonUpdater.d.ts.map +1 -0
- package/dist/src/setup/packageJsonUpdater.js +129 -0
- package/dist/src/setup/packageJsonUpdater.js.map +1 -0
- package/dist/src/types.d.ts +177 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/types.d.ts +177 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# @mathonsunday/dead-code-toolkit
|
|
2
|
+
|
|
3
|
+
**Comprehensive dead code detection and cleanup toolkit for TypeScript projects**
|
|
4
|
+
|
|
5
|
+
Detects unused exports, files, dependencies, type errors, and more via Knip, TypeScript, ESLint, and custom analysis. Perfect for keeping TypeScript codebases clean and maintaining high code quality.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
✨ **Multi-layered Detection**
|
|
10
|
+
- **Knip**: Unused exports, files, dependencies (symbol-level)
|
|
11
|
+
- **TypeScript**: Type errors and unused variables
|
|
12
|
+
- **ESLint**: Linting issues and redundant types
|
|
13
|
+
- **Type Coverage**: Measures properly typed code percentage (future)
|
|
14
|
+
- **Union Exhaustiveness**: Validates discriminated unions (future)
|
|
15
|
+
|
|
16
|
+
🔧 **Automated Setup**
|
|
17
|
+
- One-command project setup: `npx @mathonsunday/dead-code-toolkit setup`
|
|
18
|
+
- Detects project type (React, Node, full-stack)
|
|
19
|
+
- Generates optimal configurations
|
|
20
|
+
- Installs dependencies and Git hooks
|
|
21
|
+
|
|
22
|
+
🚀 **LLM-Friendly**
|
|
23
|
+
- Callable as an MCP tool for AI assistance
|
|
24
|
+
- Structured JSON output for easy interpretation
|
|
25
|
+
- Action items and recommendations
|
|
26
|
+
- Perfect for Claude, ChatGPT, and other LLMs
|
|
27
|
+
|
|
28
|
+
🛡️ **Pre-commit Prevention**
|
|
29
|
+
- Blocks commits with new dead code
|
|
30
|
+
- 4-stage validation (lint → type-check → dead-code → tests)
|
|
31
|
+
- Helpful error messages
|
|
32
|
+
- Easy skip option when needed
|
|
33
|
+
|
|
34
|
+
📊 **Reporting**
|
|
35
|
+
- Human-readable terminal output
|
|
36
|
+
- JSON format for programmatic use
|
|
37
|
+
- LLM-friendly summaries
|
|
38
|
+
- Detailed suggestions for fixes
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install --save-dev @mathonsunday/dead-code-toolkit
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
### CLI Usage
|
|
49
|
+
|
|
50
|
+
**Analyze your project for dead code:**
|
|
51
|
+
```bash
|
|
52
|
+
npx dead-code-toolkit analyze
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Output as JSON (for LLMs):**
|
|
56
|
+
```bash
|
|
57
|
+
npx dead-code-toolkit analyze --json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Get brief summary:**
|
|
61
|
+
```bash
|
|
62
|
+
npx dead-code-toolkit analyze --summary
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Specific checks:**
|
|
66
|
+
```bash
|
|
67
|
+
npx dead-code-toolkit analyze --checks knip,typescript
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Run individual checks:**
|
|
71
|
+
```bash
|
|
72
|
+
npx dead-code-toolkit check:knip
|
|
73
|
+
npx dead-code-toolkit check:types
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Programmatic Usage
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { analyzeDeadCode, createJSONReport } from '@mathonsunday/dead-code-toolkit';
|
|
80
|
+
|
|
81
|
+
const result = await analyzeDeadCode({
|
|
82
|
+
projectRoot: process.cwd(),
|
|
83
|
+
checks: ['knip', 'typescript'],
|
|
84
|
+
verbose: true,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
console.log(`Found ${result.summary.totalIssues} issues`);
|
|
88
|
+
console.log(`${result.summary.fixableCount} can be auto-fixed`);
|
|
89
|
+
|
|
90
|
+
// Get JSON report for LLM consumption
|
|
91
|
+
const report = createJSONReport(result);
|
|
92
|
+
console.log(JSON.stringify(report, null, 2));
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Setup in New Project
|
|
96
|
+
|
|
97
|
+
**Automatic setup** (not yet implemented):
|
|
98
|
+
```bash
|
|
99
|
+
npx @mathonsunday/dead-code-toolkit setup
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Manual setup:**
|
|
103
|
+
```bash
|
|
104
|
+
# Install dependencies
|
|
105
|
+
npm install --save-dev knip typescript
|
|
106
|
+
|
|
107
|
+
# Create knip.json (from template)
|
|
108
|
+
# Create eslint.config.js (with dead code rules)
|
|
109
|
+
# Setup Husky hooks (optional)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Configuration
|
|
113
|
+
|
|
114
|
+
The toolkit auto-detects your project structure and generates appropriate configs. You can override defaults:
|
|
115
|
+
|
|
116
|
+
**knip.json** - Symbol-level dead code detection
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"entry": ["src/main.ts", "api/handler.ts"],
|
|
120
|
+
"project": ["src/**/*.ts", "api/**/*.ts"],
|
|
121
|
+
"ignore": ["dist/**", "node_modules/**"]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**ESLint rules** - Add to `eslint.config.js`:
|
|
126
|
+
```javascript
|
|
127
|
+
@typescript-eslint/no-redundant-type-constituents
|
|
128
|
+
@typescript-eslint/no-unused-vars
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**package.json scripts:**
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"scripts": {
|
|
135
|
+
"dead-code": "knip",
|
|
136
|
+
"dead-code:fix": "knip --fix",
|
|
137
|
+
"dead-code:analyze": "dead-code-toolkit analyze",
|
|
138
|
+
"verify": "npm run type-check && npm run lint && npm run dead-code"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Pre-commit Hooks
|
|
144
|
+
|
|
145
|
+
The toolkit can setup automated checks via Husky:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Install Husky
|
|
149
|
+
npx husky install
|
|
150
|
+
npx husky add .husky/pre-commit "npm run verify"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**4-stage pre-commit validation:**
|
|
154
|
+
1. **lint-staged** - ESLint + Prettier on staged files
|
|
155
|
+
2. **Type Check** - Full TypeScript compilation
|
|
156
|
+
3. **Dead Code** - Knip analysis
|
|
157
|
+
4. **Tests** - Jest/Vitest
|
|
158
|
+
|
|
159
|
+
If any stage fails, the commit is blocked with helpful guidance.
|
|
160
|
+
|
|
161
|
+
## LLM Integration
|
|
162
|
+
|
|
163
|
+
Use with Claude or other LLMs as an MCP tool:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// In your tool registry
|
|
167
|
+
const deadCodeTool = {
|
|
168
|
+
name: 'dead_code_analysis',
|
|
169
|
+
description: 'Analyze TypeScript project for dead code',
|
|
170
|
+
execute: async (input) => {
|
|
171
|
+
const result = await analyzeDeadCode({
|
|
172
|
+
projectRoot: input.projectRoot,
|
|
173
|
+
checks: input.checks || ['knip', 'typescript'],
|
|
174
|
+
});
|
|
175
|
+
return createJSONReport(result);
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**LLM Workflow:**
|
|
181
|
+
1. User: "Help clean up dead code"
|
|
182
|
+
2. LLM: Calls `dead_code_analysis` tool
|
|
183
|
+
3. Tool: Returns structured findings
|
|
184
|
+
4. LLM: Interprets results and guides user
|
|
185
|
+
5. User: Approves fixes
|
|
186
|
+
6. LLM: Applies changes
|
|
187
|
+
|
|
188
|
+
## Architecture
|
|
189
|
+
|
|
190
|
+
### Checker Layers
|
|
191
|
+
|
|
192
|
+
| Layer | Detection Method | Scope |
|
|
193
|
+
|-------|-----------------|-------|
|
|
194
|
+
| **Knip** | Symbol analysis | Exports, files, dependencies |
|
|
195
|
+
| **TypeScript** | Type compiler | Type errors, unused variables |
|
|
196
|
+
| **ESLint** | Linting rules | Unused variables, redundant types |
|
|
197
|
+
| **Type Coverage** | AST analysis | Code with implicit `any` |
|
|
198
|
+
| **Exhaustiveness** | Pattern matching | Unhandled union variants |
|
|
199
|
+
|
|
200
|
+
### Finding Categories
|
|
201
|
+
|
|
202
|
+
- `unused-export` - Exported but never used
|
|
203
|
+
- `unused-file` - File never imported
|
|
204
|
+
- `unused-dependency` - Package in package.json but unused
|
|
205
|
+
- `type-error` - TypeScript compilation error
|
|
206
|
+
- `unused-var` - Variable declared but never used
|
|
207
|
+
- `unused-param` - Function parameter never used
|
|
208
|
+
- `redundant-type` - Union with overlapping members
|
|
209
|
+
- `union-issue` - Discriminated union not exhaustively handled
|
|
210
|
+
|
|
211
|
+
## Known Limitations
|
|
212
|
+
|
|
213
|
+
1. **Semantic dead code** - Cannot detect if code serves no business purpose
|
|
214
|
+
2. **Dynamic imports** - May miss `import(`./${variant}`)`
|
|
215
|
+
3. **Reflection** - Runtime string-based access not tracked
|
|
216
|
+
4. **Cross-project usage** - Only analyzes within single project
|
|
217
|
+
5. **Performance** - May be slow on 100k+ LOC projects (optimization in progress)
|
|
218
|
+
|
|
219
|
+
## Troubleshooting
|
|
220
|
+
|
|
221
|
+
**"Knip not installed"**
|
|
222
|
+
```bash
|
|
223
|
+
npm install --save-dev knip
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**"TypeScript not found"**
|
|
227
|
+
```bash
|
|
228
|
+
npm install --save-dev typescript
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**"No issues found but I think there's dead code"**
|
|
232
|
+
- Run with `--verbose` flag for detailed output
|
|
233
|
+
- Check `knip.json` entry points are correct
|
|
234
|
+
- Verify project structure matches config
|
|
235
|
+
|
|
236
|
+
**"Pre-commit hook is blocking my commit"**
|
|
237
|
+
```bash
|
|
238
|
+
# Skip hooks temporarily
|
|
239
|
+
git commit --no-verify
|
|
240
|
+
|
|
241
|
+
# Fix and try again
|
|
242
|
+
npm run dead-code:fix
|
|
243
|
+
git add .
|
|
244
|
+
git commit -m "chore: cleanup dead code"
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## API Reference
|
|
248
|
+
|
|
249
|
+
### `analyzeDeadCode(options)`
|
|
250
|
+
|
|
251
|
+
Main analysis function.
|
|
252
|
+
|
|
253
|
+
**Options:**
|
|
254
|
+
- `projectRoot` (string, required) - Path to project
|
|
255
|
+
- `checks` (CheckType[], optional) - Checks to run
|
|
256
|
+
- `fix` (boolean, optional) - Auto-fix issues
|
|
257
|
+
- `verbose` (boolean, optional) - Detailed logging
|
|
258
|
+
|
|
259
|
+
**Returns:** Promise<AnalysisResult>
|
|
260
|
+
|
|
261
|
+
### `fixFindings(findings, options)`
|
|
262
|
+
|
|
263
|
+
Apply fixes to findings.
|
|
264
|
+
|
|
265
|
+
**Options:**
|
|
266
|
+
- `dryRun` (boolean, optional) - Don't modify files
|
|
267
|
+
- `verbose` (boolean, optional) - Detailed logging
|
|
268
|
+
|
|
269
|
+
### `createJSONReport(result)`
|
|
270
|
+
|
|
271
|
+
Convert analysis result to JSON for LLMs.
|
|
272
|
+
|
|
273
|
+
**Returns:** JSONReport with findings and recommendations
|
|
274
|
+
|
|
275
|
+
### `createLLMSummary(result)`
|
|
276
|
+
|
|
277
|
+
Generate concise summary for LLM interpretation.
|
|
278
|
+
|
|
279
|
+
**Returns:** LLMSummaryReport with actionable items
|
|
280
|
+
|
|
281
|
+
## Examples
|
|
282
|
+
|
|
283
|
+
### Example 1: CI/CD Integration
|
|
284
|
+
|
|
285
|
+
```yaml
|
|
286
|
+
# .github/workflows/dead-code.yml
|
|
287
|
+
name: Dead Code Check
|
|
288
|
+
on: [pull_request]
|
|
289
|
+
|
|
290
|
+
jobs:
|
|
291
|
+
dead-code:
|
|
292
|
+
runs-on: ubuntu-latest
|
|
293
|
+
steps:
|
|
294
|
+
- uses: actions/checkout@v3
|
|
295
|
+
- uses: actions/setup-node@v3
|
|
296
|
+
- run: npm ci
|
|
297
|
+
- run: npx dead-code-toolkit analyze --json > report.json
|
|
298
|
+
- uses: actions/upload-artifact@v3
|
|
299
|
+
with:
|
|
300
|
+
name: dead-code-report
|
|
301
|
+
path: report.json
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Example 2: LLM-Guided Cleanup
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
// In Claude or ChatGPT context
|
|
308
|
+
const findings = await analyzeDeadCode({
|
|
309
|
+
projectRoot: '/path/to/project',
|
|
310
|
+
checks: ['knip', 'typescript'],
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const summary = createLLMSummary(findings);
|
|
314
|
+
// LLM sees: summary.actionItems with recommendations
|
|
315
|
+
// LLM can then guide user or apply fixes
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Example 3: Programmatic Filtering
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
import { analyzeDeadCode } from '@mathonsunday/dead-code-toolkit';
|
|
322
|
+
|
|
323
|
+
const result = await analyzeDeadCode({
|
|
324
|
+
projectRoot: process.cwd(),
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Get only auto-fixable issues
|
|
328
|
+
const fixable = result.findings.filter(f => f.fixable);
|
|
329
|
+
|
|
330
|
+
// Get only errors
|
|
331
|
+
const errors = result.findings.filter(f => f.severity === 'error');
|
|
332
|
+
|
|
333
|
+
// Group by file
|
|
334
|
+
const byFile = new Map();
|
|
335
|
+
for (const finding of result.findings) {
|
|
336
|
+
if (!byFile.has(finding.file)) {
|
|
337
|
+
byFile.set(finding.file, []);
|
|
338
|
+
}
|
|
339
|
+
byFile.get(finding.file).push(finding);
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Contributing
|
|
344
|
+
|
|
345
|
+
Contributions welcome! Areas for improvement:
|
|
346
|
+
|
|
347
|
+
- [ ] Implement `setup` command for automated configuration
|
|
348
|
+
- [ ] Add ESLint and type-coverage checkers
|
|
349
|
+
- [ ] Implement union exhaustiveness checking
|
|
350
|
+
- [ ] Add comprehensive test suite
|
|
351
|
+
- [ ] Improve performance for large projects
|
|
352
|
+
- [ ] Add more fix strategies
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core analyzer - orchestrates all checkers and produces unified analysis results
|
|
3
|
+
*/
|
|
4
|
+
import type { AnalysisOptions, AnalysisResult, Finding } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Main entry point: analyze dead code in a project
|
|
7
|
+
*
|
|
8
|
+
* @param options Configuration for the analysis
|
|
9
|
+
* @returns Complete analysis results
|
|
10
|
+
*/
|
|
11
|
+
export declare function analyzeDeadCode(options: AnalysisOptions): Promise<AnalysisResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Apply fixes to a set of findings
|
|
14
|
+
*
|
|
15
|
+
* @param findings The findings to fix
|
|
16
|
+
* @param options Options for fixing
|
|
17
|
+
* @returns Result of fix attempt
|
|
18
|
+
*/
|
|
19
|
+
export declare function fixFindings(findings: Finding[], options?: {
|
|
20
|
+
dryRun?: boolean;
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAEd,OAAO,EAGR,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAiEvF;AA4FD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GACpD,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
package/dist/analyzer.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core analyzer - orchestrates all checkers and produces unified analysis results
|
|
3
|
+
*/
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import { runKnipCheck } from './checkers/knipChecker.js';
|
|
7
|
+
import { runTypeScriptCheck } from './checkers/typescriptChecker.js';
|
|
8
|
+
/**
|
|
9
|
+
* Main entry point: analyze dead code in a project
|
|
10
|
+
*
|
|
11
|
+
* @param options Configuration for the analysis
|
|
12
|
+
* @returns Complete analysis results
|
|
13
|
+
*/
|
|
14
|
+
export async function analyzeDeadCode(options) {
|
|
15
|
+
const startTime = Date.now();
|
|
16
|
+
// Normalize and validate project root
|
|
17
|
+
const projectRoot = resolve(options.projectRoot);
|
|
18
|
+
if (!existsSync(projectRoot)) {
|
|
19
|
+
return {
|
|
20
|
+
status: 'failure',
|
|
21
|
+
summary: {
|
|
22
|
+
totalIssues: 0,
|
|
23
|
+
byCategory: {},
|
|
24
|
+
fixableCount: 0,
|
|
25
|
+
errorCount: 0,
|
|
26
|
+
warningCount: 0,
|
|
27
|
+
infoCount: 0,
|
|
28
|
+
},
|
|
29
|
+
findings: [],
|
|
30
|
+
checkResults: [],
|
|
31
|
+
executionTime: Date.now() - startTime,
|
|
32
|
+
error: `Project root does not exist: ${projectRoot}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Determine which checks to run
|
|
36
|
+
const checksToRun = getChecksToRun(options.checks);
|
|
37
|
+
if (options.verbose) {
|
|
38
|
+
console.log(`[Dead Code Toolkit] Analyzing: ${projectRoot}`);
|
|
39
|
+
console.log(`[Dead Code Toolkit] Running checks: ${checksToRun.join(', ')}`);
|
|
40
|
+
}
|
|
41
|
+
// Run all checks in parallel
|
|
42
|
+
const checkResults = await Promise.all(checksToRun.map((checkType) => runCheck(checkType, projectRoot, options)));
|
|
43
|
+
// Aggregate results
|
|
44
|
+
const allFindings = checkResults.flatMap((r) => r.findings);
|
|
45
|
+
// Calculate summary
|
|
46
|
+
const summary = calculateSummary(allFindings);
|
|
47
|
+
// Determine overall status
|
|
48
|
+
let status = 'success';
|
|
49
|
+
if (allFindings.some((f) => f.severity === 'error')) {
|
|
50
|
+
status = 'failure';
|
|
51
|
+
}
|
|
52
|
+
else if (allFindings.length > 0) {
|
|
53
|
+
status = 'partial';
|
|
54
|
+
}
|
|
55
|
+
const result = {
|
|
56
|
+
status,
|
|
57
|
+
summary,
|
|
58
|
+
findings: allFindings,
|
|
59
|
+
checkResults,
|
|
60
|
+
executionTime: Date.now() - startTime,
|
|
61
|
+
};
|
|
62
|
+
if (options.verbose) {
|
|
63
|
+
console.log(`[Dead Code Toolkit] Analysis complete: ${allFindings.length} issues found`);
|
|
64
|
+
console.log(`[Dead Code Toolkit] Execution time: ${result.executionTime}ms`);
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Run a specific check and handle errors gracefully
|
|
70
|
+
*/
|
|
71
|
+
async function runCheck(checkType, projectRoot, _options) {
|
|
72
|
+
try {
|
|
73
|
+
switch (checkType) {
|
|
74
|
+
case 'knip':
|
|
75
|
+
return await runKnipCheck(projectRoot);
|
|
76
|
+
case 'typescript':
|
|
77
|
+
return await runTypeScriptCheck(projectRoot);
|
|
78
|
+
default:
|
|
79
|
+
return {
|
|
80
|
+
type: checkType,
|
|
81
|
+
status: 'skipped',
|
|
82
|
+
findings: [],
|
|
83
|
+
executionTime: 0,
|
|
84
|
+
error: `Check '${checkType}' not yet implemented`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
90
|
+
return {
|
|
91
|
+
type: checkType,
|
|
92
|
+
status: 'failure',
|
|
93
|
+
findings: [],
|
|
94
|
+
executionTime: 0,
|
|
95
|
+
error: `${checkType} check failed: ${message}`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Determine which checks to run
|
|
101
|
+
*/
|
|
102
|
+
function getChecksToRun(specified) {
|
|
103
|
+
if (!specified || specified.length === 0) {
|
|
104
|
+
// Default: run all available checks
|
|
105
|
+
return ['knip', 'typescript'];
|
|
106
|
+
}
|
|
107
|
+
if (specified.includes('all')) {
|
|
108
|
+
return ['knip', 'typescript'];
|
|
109
|
+
}
|
|
110
|
+
return specified.filter((c) => c !== 'all');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Calculate summary statistics from findings
|
|
114
|
+
*/
|
|
115
|
+
function calculateSummary(findings) {
|
|
116
|
+
const byCategory = {};
|
|
117
|
+
let errorCount = 0;
|
|
118
|
+
let warningCount = 0;
|
|
119
|
+
let infoCount = 0;
|
|
120
|
+
let fixableCount = 0;
|
|
121
|
+
for (const finding of findings) {
|
|
122
|
+
// Count by category
|
|
123
|
+
byCategory[finding.category] = (byCategory[finding.category] || 0) + 1;
|
|
124
|
+
// Count by severity
|
|
125
|
+
if (finding.severity === 'error') {
|
|
126
|
+
errorCount++;
|
|
127
|
+
}
|
|
128
|
+
else if (finding.severity === 'warning') {
|
|
129
|
+
warningCount++;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
infoCount++;
|
|
133
|
+
}
|
|
134
|
+
// Count fixable
|
|
135
|
+
if (finding.fixable) {
|
|
136
|
+
fixableCount++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
totalIssues: findings.length,
|
|
141
|
+
byCategory,
|
|
142
|
+
fixableCount,
|
|
143
|
+
errorCount,
|
|
144
|
+
warningCount,
|
|
145
|
+
infoCount,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Apply fixes to a set of findings
|
|
150
|
+
*
|
|
151
|
+
* @param findings The findings to fix
|
|
152
|
+
* @param options Options for fixing
|
|
153
|
+
* @returns Result of fix attempt
|
|
154
|
+
*/
|
|
155
|
+
export async function fixFindings(findings, options = {}) {
|
|
156
|
+
const fixableFindings = findings.filter((f) => f.fixable);
|
|
157
|
+
if (options.verbose) {
|
|
158
|
+
console.log(`[Dead Code Toolkit] Found ${fixableFindings.length} fixable issues`);
|
|
159
|
+
if (options.dryRun) {
|
|
160
|
+
console.log('[Dead Code Toolkit] DRY RUN - no files will be modified');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// TODO: Implement fix logic
|
|
164
|
+
// This would involve:
|
|
165
|
+
// 1. Parsing each file
|
|
166
|
+
// 2. Removing/modifying the problematic code
|
|
167
|
+
// 3. Writing back to disk (unless dryRun)
|
|
168
|
+
// 4. Validating the changes
|
|
169
|
+
if (options.verbose) {
|
|
170
|
+
console.log(`[Dead Code Toolkit] Fix complete`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Knip integration for detecting unused exports, files, and dependencies
|
|
3
|
+
* Knip performs symbol-level analysis to find unused code
|
|
4
|
+
*/
|
|
5
|
+
import type { CheckResult } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Run Knip analysis on a project
|
|
8
|
+
* Requires Knip to be installed as a dependency
|
|
9
|
+
*/
|
|
10
|
+
export declare function runKnipCheck(projectRoot: string): Promise<CheckResult>;
|
|
11
|
+
//# sourceMappingURL=knipChecker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knipChecker.d.ts","sourceRoot":"","sources":["../../src/checkers/knipChecker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,aAAa,CAAC;AAcxD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAqC5E"}
|