helpforbegs 0.0.0-stage â 1.0.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/LICENSE +21 -0
- package/README.md +146 -2
- package/bin/cli.js +108 -0
- package/package.json +43 -4
- package/src/analyzer.js +348 -0
- package/src/args.js +116 -0
- package/src/astParser.js +228 -0
- package/src/binMapper.js +167 -0
- package/src/configReader.js +351 -0
- package/src/fallbackParser.js +130 -0
- package/src/fileFinder.js +196 -0
- package/src/messages.js +82 -0
- package/src/remover.js +184 -0
- package/src/reporter.js +186 -0
- package/src/safeList.js +91 -0
- package/src/scorer.js +150 -0
- package/src/why.js +103 -0
package/src/why.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/why.js
|
|
2
|
+
// WHY: When a tool says a package is "used" or "unused", a beginner needs proof!
|
|
3
|
+
// The `why` command shows exact filenames and line numbers so the developer
|
|
4
|
+
// understands their project and can verify everything for themselves.
|
|
5
|
+
|
|
6
|
+
const { analyzeProject } = require('./analyzer');
|
|
7
|
+
const { createStyler } = require('./reporter');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Explains in plain English why a package is used, unused, or missing.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} projectDir
|
|
13
|
+
* @param {string} targetPkg
|
|
14
|
+
* @param {object} [options]
|
|
15
|
+
* @param {boolean} [options.noColor=false]
|
|
16
|
+
* @returns {number} Exit code
|
|
17
|
+
*/
|
|
18
|
+
function explainPackage(projectDir, targetPkg, options = {}) {
|
|
19
|
+
const styler = createStyler(options.noColor);
|
|
20
|
+
|
|
21
|
+
if (!targetPkg) {
|
|
22
|
+
console.log(styler.red('â Please specify a package name to inspect.'));
|
|
23
|
+
console.log(styler.dim(' Example: npx helpforbegs why lodash'));
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const analysis = analyzeProject(projectDir);
|
|
28
|
+
|
|
29
|
+
console.log();
|
|
30
|
+
console.log(styler.bold(`đ Investigating "${targetPkg}" in your project:`));
|
|
31
|
+
console.log();
|
|
32
|
+
|
|
33
|
+
// 1. Check if it's missing (imported in code but not installed)
|
|
34
|
+
const missingEntry = analysis.missing.find((m) => m.name === targetPkg);
|
|
35
|
+
if (missingEntry) {
|
|
36
|
+
console.log(styler.red(`â ī¸ "${targetPkg}" is USED in your code, but MISSING from package.json!`));
|
|
37
|
+
console.log(' Found in the following files:');
|
|
38
|
+
for (const loc of missingEntry.locations) {
|
|
39
|
+
console.log(` âĸ ${styler.cyan(loc.file)}:${styler.yellow(loc.line)}`);
|
|
40
|
+
}
|
|
41
|
+
console.log();
|
|
42
|
+
console.log(styler.dim(` đ Fix: run \`npm install ${targetPkg}\` to add it properly.`));
|
|
43
|
+
console.log();
|
|
44
|
+
return 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 2. Check if it's confirmed USED
|
|
48
|
+
if (analysis.used.has(targetPkg)) {
|
|
49
|
+
const usage = analysis.used.get(targetPkg);
|
|
50
|
+
console.log(styler.green(`â
"${targetPkg}" is ACTIVELY USED in your project.`));
|
|
51
|
+
console.log();
|
|
52
|
+
|
|
53
|
+
console.log(' Why it is kept:');
|
|
54
|
+
for (const reason of usage.reasons) {
|
|
55
|
+
console.log(` âĸ ${reason}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (usage.locations.length > 0) {
|
|
59
|
+
console.log();
|
|
60
|
+
console.log(' Import locations in source code:');
|
|
61
|
+
for (const loc of usage.locations) {
|
|
62
|
+
const typeNote = loc.isTypeOnly ? styler.gray(' (type-only import)') : '';
|
|
63
|
+
console.log(` âĸ ${styler.cyan(loc.file)}:${styler.yellow(loc.line)}${typeNote}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log();
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 3. Check if it's PROBABLY UNUSED
|
|
72
|
+
const probablyEntry = analysis.probablyUnused.find((p) => p.name === targetPkg);
|
|
73
|
+
if (probablyEntry) {
|
|
74
|
+
console.log(styler.yellow(`đ¤ "${targetPkg}" is PROBABLY UNUSED.`));
|
|
75
|
+
console.log(` ${probablyEntry.reason}`);
|
|
76
|
+
console.log();
|
|
77
|
+
console.log(' Because this is a known development tool, check your npm scripts');
|
|
78
|
+
console.log(' or config files before uninstalling it.');
|
|
79
|
+
console.log();
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 4. Check if it's UNUSED
|
|
84
|
+
const unusedEntry = analysis.unused.find((u) => u.name === targetPkg);
|
|
85
|
+
if (unusedEntry) {
|
|
86
|
+
console.log(styler.red(`â "${targetPkg}" is INSTALLED but UNUSED.`));
|
|
87
|
+
console.log(` ${unusedEntry.reason}.`);
|
|
88
|
+
console.log(` We scanned ${analysis.filesReadCount} files and found zero imports or script commands for it.`);
|
|
89
|
+
console.log();
|
|
90
|
+
console.log(styler.dim(` đ You can safely remove it with: \`npx helpforbegs remove\``));
|
|
91
|
+
console.log();
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 5. Not found anywhere
|
|
96
|
+
console.log(styler.gray(`âšī¸ "${targetPkg}" was not found in your package.json or your code.`));
|
|
97
|
+
console.log();
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = {
|
|
102
|
+
explainPackage,
|
|
103
|
+
};
|