whyinstall 0.2.0 → 0.3.1
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 +33 -0
- package/dist/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +2 -8
- package/dist/analyzer.js.map +1 -1
- package/dist/cli.js +13 -5
- package/dist/cli.js.map +1 -1
- package/dist/fileFinder.d.ts +0 -8
- package/dist/fileFinder.d.ts.map +1 -1
- package/dist/fileFinder.js +0 -94
- package/dist/fileFinder.js.map +1 -1
- package/dist/formatter.d.ts +3 -2
- package/dist/formatter.d.ts.map +1 -1
- package/dist/formatter.js +19 -49
- package/dist/formatter.js.map +1 -1
- package/dist/sizeMapAnalyzer.d.ts +3 -0
- package/dist/sizeMapAnalyzer.d.ts.map +1 -0
- package/dist/sizeMapAnalyzer.js +134 -0
- package/dist/sizeMapAnalyzer.js.map +1 -0
- package/dist/types.d.ts +11 -13
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/analyzer.ts +2 -9
- package/src/cli.ts +14 -7
- package/src/fileFinder.ts +0 -111
- package/src/formatter.ts +24 -57
- package/src/sizeMapAnalyzer.ts +145 -0
- package/src/types.ts +13 -15
- package/src/impactAnalyzer.ts +0 -139
package/src/impactAnalyzer.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { ImpactAnalysis } from './types';
|
|
2
|
-
import { FileUsage, findSourceFiles, analyzeFileUsage } from './fileFinder';
|
|
3
|
-
|
|
4
|
-
function analyzeUsageContext(usage: FileUsage, content: string): string {
|
|
5
|
-
// Analyze actual usage patterns in THIS codebase, not generic assumptions
|
|
6
|
-
const lines = content.split('\n');
|
|
7
|
-
const contextLines: string[] = [];
|
|
8
|
-
|
|
9
|
-
// Get context around usage lines
|
|
10
|
-
usage.lines.forEach(lineNum => {
|
|
11
|
-
const start = Math.max(0, lineNum - 2);
|
|
12
|
-
const end = Math.min(lines.length, lineNum + 2);
|
|
13
|
-
contextLines.push(...lines.slice(start, end));
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const context = contextLines.join('\n').toLowerCase();
|
|
17
|
-
|
|
18
|
-
// Simple heuristics based on actual code patterns, not package names
|
|
19
|
-
if (context.includes('console.') || context.includes('process.stdout') || context.includes('process.stderr')) {
|
|
20
|
-
return 'Console/output';
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (context.includes('response') || context.includes('res.') || context.includes('req.')) {
|
|
24
|
-
return 'HTTP/API';
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (context.includes('database') || context.includes('db.') || context.includes('query')) {
|
|
28
|
-
return 'Database';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (context.includes('test') || context.includes('spec') || context.includes('describe')) {
|
|
32
|
-
return 'Testing';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return 'General usage';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function computeRiskLevel(files: FileUsage[], contexts: string[]): 'Low' | 'Medium' | 'High' {
|
|
39
|
-
// Risk assessment based on WHERE it's used, not WHAT package it is
|
|
40
|
-
const hasDatabase = contexts.some(c => c === 'Database');
|
|
41
|
-
const hasHTTP = contexts.some(c => c === 'HTTP/API');
|
|
42
|
-
const hasTesting = contexts.every(c => c === 'Testing');
|
|
43
|
-
const hasConsole = contexts.every(c => c === 'Console/output');
|
|
44
|
-
|
|
45
|
-
// High risk: Database, HTTP/API (core functionality)
|
|
46
|
-
if (hasDatabase || hasHTTP) {
|
|
47
|
-
return 'High';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Low risk: Only in tests, or only console output
|
|
51
|
-
if (hasTesting || (hasConsole && files.length === 1)) {
|
|
52
|
-
return 'Low';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Medium: Everything else (could be important, needs review)
|
|
56
|
-
return 'Medium';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function generateImpacts(files: FileUsage[], contexts: string[], packageName: string): string[] {
|
|
60
|
-
const impacts: string[] = [];
|
|
61
|
-
const uniqueContexts = [...new Set(contexts)];
|
|
62
|
-
|
|
63
|
-
// Base impacts on actual usage in THIS codebase
|
|
64
|
-
if (files.length === 0) {
|
|
65
|
-
impacts.push(`No direct usage found in source files`);
|
|
66
|
-
impacts.push(`May be a transitive dependency or unused`);
|
|
67
|
-
} else {
|
|
68
|
-
const totalMethods = new Set(files.flatMap(f => f.methods));
|
|
69
|
-
|
|
70
|
-
if (totalMethods.size > 0) {
|
|
71
|
-
impacts.push(`Methods used: ${Array.from(totalMethods).slice(0, 8).join(', ')}${totalMethods.size > 8 ? ` (+${totalMethods.size - 8} more)` : ''}`);
|
|
72
|
-
} else {
|
|
73
|
-
impacts.push(`Package imported but no method calls detected`);
|
|
74
|
-
impacts.push(`May be used as default export or namespace`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
impacts.push(`Used in ${files.length} file${files.length !== 1 ? 's' : ''}: ${uniqueContexts.join(', ')}`);
|
|
78
|
-
|
|
79
|
-
// Context-specific guidance (based on actual usage, not package name)
|
|
80
|
-
if (uniqueContexts.includes('Database')) {
|
|
81
|
-
impacts.push(`⚠️ Used in database operations - removal may break data access`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (uniqueContexts.includes('HTTP/API')) {
|
|
85
|
-
impacts.push(`⚠️ Used in API/HTTP layer - removal may break endpoints`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (uniqueContexts.includes('Testing')) {
|
|
89
|
-
impacts.push(`✓ Only used in tests - safe to remove from production dependencies`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (uniqueContexts.includes('Console/output') && files.length === 1) {
|
|
93
|
-
impacts.push(`✓ Only used for console output - low impact, can be replaced`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
impacts.push(`\n💡 Review the files above to assess actual impact in your codebase`);
|
|
98
|
-
|
|
99
|
-
return impacts;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function analyzeImpact(packageName: string, cwd: string): ImpactAnalysis {
|
|
103
|
-
const sourceFiles = findSourceFiles(cwd);
|
|
104
|
-
const fileUsages: FileUsage[] = [];
|
|
105
|
-
|
|
106
|
-
for (const file of sourceFiles) {
|
|
107
|
-
const usage = analyzeFileUsage(file, packageName, cwd);
|
|
108
|
-
if (usage) {
|
|
109
|
-
fileUsages.push(usage);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Analyze actual usage context in THIS codebase
|
|
114
|
-
const contexts = fileUsages.map(usage => {
|
|
115
|
-
try {
|
|
116
|
-
const fs = require('fs');
|
|
117
|
-
const path = require('path');
|
|
118
|
-
const fullPath = usage.file.startsWith(cwd) ? usage.file : path.join(cwd, usage.file);
|
|
119
|
-
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
120
|
-
return analyzeUsageContext(usage, content);
|
|
121
|
-
} catch {
|
|
122
|
-
return 'Unknown';
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const riskLevel = computeRiskLevel(fileUsages, contexts);
|
|
127
|
-
const impacts = generateImpacts(fileUsages, contexts, packageName);
|
|
128
|
-
|
|
129
|
-
// Add contexts to file usages
|
|
130
|
-
fileUsages.forEach((usage, index) => {
|
|
131
|
-
(usage as any).purpose = contexts[index];
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
files: fileUsages,
|
|
136
|
-
riskLevel,
|
|
137
|
-
impacts
|
|
138
|
-
};
|
|
139
|
-
}
|