ghostdep 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.
Files changed (50) hide show
  1. package/README.md +176 -0
  2. package/dist/bin/cli.d.ts +3 -0
  3. package/dist/bin/cli.d.ts.map +1 -0
  4. package/dist/bin/cli.js +103 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/src/detectors/drift.d.ts +12 -0
  7. package/dist/src/detectors/drift.d.ts.map +1 -0
  8. package/dist/src/detectors/drift.js +95 -0
  9. package/dist/src/detectors/drift.js.map +1 -0
  10. package/dist/src/detectors/duplicates.d.ts +13 -0
  11. package/dist/src/detectors/duplicates.d.ts.map +1 -0
  12. package/dist/src/detectors/duplicates.js +151 -0
  13. package/dist/src/detectors/duplicates.js.map +1 -0
  14. package/dist/src/detectors/ghosts.d.ts +13 -0
  15. package/dist/src/detectors/ghosts.d.ts.map +1 -0
  16. package/dist/src/detectors/ghosts.js +209 -0
  17. package/dist/src/detectors/ghosts.js.map +1 -0
  18. package/dist/src/detectors/zombies.d.ts +22 -0
  19. package/dist/src/detectors/zombies.d.ts.map +1 -0
  20. package/dist/src/detectors/zombies.js +127 -0
  21. package/dist/src/detectors/zombies.js.map +1 -0
  22. package/dist/src/health.d.ts +22 -0
  23. package/dist/src/health.d.ts.map +1 -0
  24. package/dist/src/health.js +123 -0
  25. package/dist/src/health.js.map +1 -0
  26. package/dist/src/index.d.ts +4 -0
  27. package/dist/src/index.d.ts.map +1 -0
  28. package/dist/src/index.js +4 -0
  29. package/dist/src/index.js.map +1 -0
  30. package/dist/src/reporter.d.ts +9 -0
  31. package/dist/src/reporter.d.ts.map +1 -0
  32. package/dist/src/reporter.js +115 -0
  33. package/dist/src/reporter.js.map +1 -0
  34. package/dist/src/scanner.d.ts +12 -0
  35. package/dist/src/scanner.d.ts.map +1 -0
  36. package/dist/src/scanner.js +62 -0
  37. package/dist/src/scanner.js.map +1 -0
  38. package/dist/src/types.d.ts +115 -0
  39. package/dist/src/types.d.ts.map +1 -0
  40. package/dist/src/types.js +2 -0
  41. package/dist/src/types.js.map +1 -0
  42. package/dist/src/utils/fs.d.ts +29 -0
  43. package/dist/src/utils/fs.d.ts.map +1 -0
  44. package/dist/src/utils/fs.js +72 -0
  45. package/dist/src/utils/fs.js.map +1 -0
  46. package/dist/src/utils/packageManager.d.ts +20 -0
  47. package/dist/src/utils/packageManager.d.ts.map +1 -0
  48. package/dist/src/utils/packageManager.js +74 -0
  49. package/dist/src/utils/packageManager.js.map +1 -0
  50. package/package.json +85 -0
@@ -0,0 +1,209 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join } from 'path';
3
+ const BUILTINS = new Set([
4
+ 'assert',
5
+ 'async_hooks',
6
+ 'buffer',
7
+ 'child_process',
8
+ 'cluster',
9
+ 'console',
10
+ 'constants',
11
+ 'crypto',
12
+ 'dgram',
13
+ 'diagnostics_channel',
14
+ 'dns',
15
+ 'domain',
16
+ 'events',
17
+ 'fs',
18
+ 'http',
19
+ 'http2',
20
+ 'https',
21
+ 'inspector',
22
+ 'module',
23
+ 'net',
24
+ 'os',
25
+ 'path',
26
+ 'perf_hooks',
27
+ 'process',
28
+ 'punycode',
29
+ 'querystring',
30
+ 'readline',
31
+ 'repl',
32
+ 'stream',
33
+ 'string_decoder',
34
+ 'sys',
35
+ 'timers',
36
+ 'tls',
37
+ 'trace_events',
38
+ 'tty',
39
+ 'url',
40
+ 'util',
41
+ 'v8',
42
+ 'vm',
43
+ 'wasi',
44
+ 'worker_threads',
45
+ 'zlib',
46
+ ]);
47
+ /**
48
+ * Checks if a package name is a Node.js built-in module.
49
+ */
50
+ function isBuiltin(name) {
51
+ return name.startsWith('node:') || BUILTINS.has(name);
52
+ }
53
+ /**
54
+ * Extracts the core package name from an import specifier.
55
+ * E.g., "lodash/map" -> "lodash", "@types/node/index.d.ts" -> "@types/node"
56
+ */
57
+ function getPackageName(specifier) {
58
+ if (!specifier || specifier.startsWith('.') || specifier.startsWith('/') || specifier.startsWith('file:')) {
59
+ return null;
60
+ }
61
+ const parts = specifier.split('/');
62
+ if (specifier.startsWith('@')) {
63
+ return parts[0] && parts[1] ? `${parts[0]}/${parts[1]}` : null;
64
+ }
65
+ return parts[0] || null;
66
+ }
67
+ /**
68
+ * Scans a file to extract all external import/require specifiers.
69
+ */
70
+ async function extractImports(filePath) {
71
+ try {
72
+ const content = await fs.readFile(filePath, 'utf8');
73
+ const specifiers = new Set();
74
+ // ESM Imports & Exports matching
75
+ const esmImportRegex = /import\s+(?:[^'"]+\s+from\s+)?['"]([^'"]+)['"]/g;
76
+ const esmExportRegex = /export\s+(?:[^'"]+\s+from\s+)?['"]([^'"]+)['"]/g;
77
+ // CommonJS require & Dynamic imports matching
78
+ const dynamicOrCjsRegex = /(?:require|import)\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
79
+ let match;
80
+ while ((match = esmImportRegex.exec(content)) !== null) {
81
+ if (match[1])
82
+ specifiers.add(match[1]);
83
+ }
84
+ while ((match = esmExportRegex.exec(content)) !== null) {
85
+ if (match[1])
86
+ specifiers.add(match[1]);
87
+ }
88
+ while ((match = dynamicOrCjsRegex.exec(content)) !== null) {
89
+ if (match[1])
90
+ specifiers.add(match[1]);
91
+ }
92
+ return Array.from(specifiers);
93
+ }
94
+ catch {
95
+ // If a file cannot be read, return empty imports
96
+ return [];
97
+ }
98
+ }
99
+ /**
100
+ * Scans the node_modules folder to find all installed package names,
101
+ * ignoring internal folders starting with a dot (like .bin, .cache, .pnpm).
102
+ */
103
+ async function getInstalledPackages(projectRoot) {
104
+ const installed = new Set();
105
+ const nodeModulesPath = join(projectRoot, 'node_modules');
106
+ try {
107
+ const entries = await fs.readdir(nodeModulesPath, { withFileTypes: true });
108
+ for (const entry of entries) {
109
+ if (entry.isDirectory()) {
110
+ const name = entry.name;
111
+ // Ignore internal directories
112
+ if (name.startsWith('.')) {
113
+ continue;
114
+ }
115
+ if (name.startsWith('@')) {
116
+ // Read scope folder entries
117
+ const scopePath = join(nodeModulesPath, name);
118
+ try {
119
+ const subEntries = await fs.readdir(scopePath, { withFileTypes: true });
120
+ for (const subEntry of subEntries) {
121
+ if (subEntry.isDirectory()) {
122
+ installed.add(`${name}/${subEntry.name}`);
123
+ }
124
+ }
125
+ }
126
+ catch {
127
+ // Ignore reading sub-scopes failure
128
+ }
129
+ }
130
+ else {
131
+ installed.add(name);
132
+ }
133
+ }
134
+ }
135
+ }
136
+ catch {
137
+ // Return empty set if node_modules does not exist
138
+ }
139
+ return installed;
140
+ }
141
+ /**
142
+ * Detects ghost dependencies: packages imported in the source code
143
+ * that are installed in node_modules but not listed in package.json.
144
+ *
145
+ * @param projectRoot Absolute path to the project root directory
146
+ * @param sourceFiles List of absolute paths of source files to analyze
147
+ * @param packageJson Parsed package.json object
148
+ * @param includeDev Whether to include devDependencies as declared packages
149
+ * @returns Array of detected ghost dependencies
150
+ */
151
+ export async function detectGhosts(projectRoot, sourceFiles, packageJson, includeDev = false) {
152
+ try {
153
+ // 1. Gather all declared package names from package.json
154
+ const declaredPackages = new Set();
155
+ if (packageJson.dependencies) {
156
+ Object.keys(packageJson.dependencies).forEach((dep) => declaredPackages.add(dep));
157
+ }
158
+ if (includeDev && packageJson.devDependencies) {
159
+ Object.keys(packageJson.devDependencies).forEach((dep) => declaredPackages.add(dep));
160
+ }
161
+ if (packageJson.peerDependencies) {
162
+ Object.keys(packageJson.peerDependencies).forEach((dep) => declaredPackages.add(dep));
163
+ }
164
+ if (packageJson.optionalDependencies) {
165
+ Object.keys(packageJson.optionalDependencies).forEach((dep) => declaredPackages.add(dep));
166
+ }
167
+ // 2. Identify all installed packages in node_modules
168
+ const installedPackages = await getInstalledPackages(projectRoot);
169
+ // 3. Scan source files for imports and identify undeclared usages
170
+ const ghostMap = new Map();
171
+ for (const file of sourceFiles) {
172
+ const cleanRoot = projectRoot.replace(/\\/g, '/');
173
+ const cleanFile = file.replace(/\\/g, '/');
174
+ const relativePath = cleanFile.replace(cleanRoot, '').replace(/^[\\/]/, '');
175
+ const importSpecifiers = await extractImports(file);
176
+ for (const specifier of importSpecifiers) {
177
+ const pkgName = getPackageName(specifier);
178
+ if (!pkgName || isBuiltin(pkgName)) {
179
+ continue;
180
+ }
181
+ // It is a ghost dependency if it is NOT declared, but is installed in node_modules
182
+ if (!declaredPackages.has(pkgName) && installedPackages.has(pkgName)) {
183
+ let entry = ghostMap.get(pkgName);
184
+ if (!entry) {
185
+ entry = { files: new Set(), specifiers: new Set() };
186
+ ghostMap.set(pkgName, entry);
187
+ }
188
+ entry.files.add(relativePath);
189
+ entry.specifiers.add(specifier);
190
+ }
191
+ }
192
+ }
193
+ // 4. Map the results into the typed output
194
+ const results = [];
195
+ for (const [name, data] of ghostMap.entries()) {
196
+ results.push({
197
+ name,
198
+ files: Array.from(data.files),
199
+ specifiers: Array.from(data.specifiers),
200
+ });
201
+ }
202
+ return results;
203
+ }
204
+ catch (error) {
205
+ const err = error;
206
+ throw new Error(`Ghost dependency detection failed: ${err.message}`);
207
+ }
208
+ }
209
+ //# sourceMappingURL=ghosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghosts.js","sourceRoot":"","sources":["../../../src/detectors/ghosts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { ZombieDependency, PackageJson } from '../types.js';
2
+ /**
3
+ * Parses a TS/JS file using the TypeScript Compiler API AST,
4
+ * returning a Set of all imported package specifiers.
5
+ *
6
+ * Supports:
7
+ * - import declarations: static imports and re-exports
8
+ * - dynamic imports: import('pkg')
9
+ * - CommonJS require statements
10
+ */
11
+ export declare function findImportsInAST(filePath: string, fileContent: string): Set<string>;
12
+ /**
13
+ * Detects zombie dependencies: packages declared in package.json dependencies list
14
+ * but never imported or required in the codebase.
15
+ *
16
+ * @param sourceFiles Absolute paths of all source files in the project
17
+ * @param packageJson Parsed package.json object
18
+ * @param includeDev Whether to scan and include devDependencies as candidate zombies
19
+ * @returns Array of ZombieDependency findings
20
+ */
21
+ export declare function detectZombies(sourceFiles: string[], packageJson: PackageJson, includeDev?: boolean): Promise<ZombieDependency[]>;
22
+ //# sourceMappingURL=zombies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zombies.d.ts","sourceRoot":"","sources":["../../../src/detectors/zombies.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkB5D;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CA4CnF;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,WAAW,EACxB,UAAU,GAAE,OAAe,GAC1B,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyD7B"}
@@ -0,0 +1,127 @@
1
+ import { promises as fs } from 'fs';
2
+ import ts from 'typescript';
3
+ /**
4
+ * Extracts the base package name from an import specifier.
5
+ * E.g., "lodash/map" -> "lodash", "@types/node" -> "@types/node"
6
+ */
7
+ function getPackageName(specifier) {
8
+ if (!specifier || specifier.startsWith('.') || specifier.startsWith('/') || specifier.startsWith('file:')) {
9
+ return null;
10
+ }
11
+ const parts = specifier.split('/');
12
+ if (specifier.startsWith('@')) {
13
+ return parts[0] && parts[1] ? `${parts[0]}/${parts[1]}` : null;
14
+ }
15
+ return parts[0] || null;
16
+ }
17
+ /**
18
+ * Parses a TS/JS file using the TypeScript Compiler API AST,
19
+ * returning a Set of all imported package specifiers.
20
+ *
21
+ * Supports:
22
+ * - import declarations: static imports and re-exports
23
+ * - dynamic imports: import('pkg')
24
+ * - CommonJS require statements
25
+ */
26
+ export function findImportsInAST(filePath, fileContent) {
27
+ const imports = new Set();
28
+ // Create AST representation of the source file
29
+ const sourceFile = ts.createSourceFile(filePath, fileContent, ts.ScriptTarget.Latest, true);
30
+ function visit(node) {
31
+ // 1. Static imports: e.g. import x from 'y'
32
+ if (ts.isImportDeclaration(node)) {
33
+ if (node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
34
+ imports.add(node.moduleSpecifier.text);
35
+ }
36
+ }
37
+ // 2. Export re-exports: e.g. export * from 'y'
38
+ else if (ts.isExportDeclaration(node)) {
39
+ if (node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
40
+ imports.add(node.moduleSpecifier.text);
41
+ }
42
+ }
43
+ // 3. Dynamic imports or CJS require expressions
44
+ else if (ts.isCallExpression(node)) {
45
+ const expression = node.expression;
46
+ // Dynamic import: import('y')
47
+ if (expression.kind === ts.SyntaxKind.ImportKeyword) {
48
+ const arg = node.arguments[0];
49
+ if (arg && ts.isStringLiteral(arg)) {
50
+ imports.add(arg.text);
51
+ }
52
+ }
53
+ // require('y')
54
+ else if (ts.isIdentifier(expression) && expression.text === 'require') {
55
+ const arg = node.arguments[0];
56
+ if (arg && ts.isStringLiteral(arg)) {
57
+ imports.add(arg.text);
58
+ }
59
+ }
60
+ }
61
+ ts.forEachChild(node, visit);
62
+ }
63
+ visit(sourceFile);
64
+ return imports;
65
+ }
66
+ /**
67
+ * Detects zombie dependencies: packages declared in package.json dependencies list
68
+ * but never imported or required in the codebase.
69
+ *
70
+ * @param sourceFiles Absolute paths of all source files in the project
71
+ * @param packageJson Parsed package.json object
72
+ * @param includeDev Whether to scan and include devDependencies as candidate zombies
73
+ * @returns Array of ZombieDependency findings
74
+ */
75
+ export async function detectZombies(sourceFiles, packageJson, includeDev = false) {
76
+ try {
77
+ // 1. Map all candidate declared dependencies to check
78
+ const declaredMap = new Map();
79
+ const addCandidates = (deps, type) => {
80
+ if (deps) {
81
+ for (const [name, version] of Object.entries(deps)) {
82
+ declaredMap.set(name, { type, declaredVersion: version });
83
+ }
84
+ }
85
+ };
86
+ addCandidates(packageJson.dependencies, 'dependencies');
87
+ if (includeDev) {
88
+ addCandidates(packageJson.devDependencies, 'devDependencies');
89
+ }
90
+ addCandidates(packageJson.peerDependencies, 'peerDependencies');
91
+ addCandidates(packageJson.optionalDependencies, 'optionalDependencies');
92
+ // 2. Traverse all source files to find all imports
93
+ const usedPackages = new Set();
94
+ for (const file of sourceFiles) {
95
+ try {
96
+ const content = await fs.readFile(file, 'utf8');
97
+ const fileImports = findImportsInAST(file, content);
98
+ for (const specifier of fileImports) {
99
+ const pkgName = getPackageName(specifier);
100
+ if (pkgName) {
101
+ usedPackages.add(pkgName);
102
+ }
103
+ }
104
+ }
105
+ catch {
106
+ // Skip file quietly if reading/parsing fails (e.g. binary or empty file)
107
+ }
108
+ }
109
+ // 3. Find packages that are declared but never used in any scanned source file
110
+ const zombies = [];
111
+ for (const [name, details] of declaredMap.entries()) {
112
+ if (!usedPackages.has(name)) {
113
+ zombies.push({
114
+ name,
115
+ type: details.type,
116
+ declaredVersion: details.declaredVersion,
117
+ });
118
+ }
119
+ }
120
+ return zombies;
121
+ }
122
+ catch (error) {
123
+ const err = error;
124
+ throw new Error(`Zombie dependency detection failed: ${err.message}`);
125
+ }
126
+ }
127
+ //# sourceMappingURL=zombies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zombies.js","sourceRoot":"","sources":["../../../src/detectors/zombies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { HealthScore, GhostDependency, ZombieDependency, DuplicateDependency, VersionDrift, ScanOptions } from './types.js';
2
+ /**
3
+ * Calculates the dependency health score and grade of a project.
4
+ *
5
+ * Score Formula:
6
+ * - Starting Base: 100
7
+ * - Deductions:
8
+ * - -5 per ghost dependency
9
+ * - -5 per zombie dependency
10
+ * - -3 per duplicate dependency
11
+ * - -2 per version drift (by default)
12
+ * - Minimum bounded score: 0
13
+ *
14
+ * @param ghosts List of detected ghost dependencies
15
+ * @param zombies List of detected zombie dependencies
16
+ * @param duplicates List of detected duplicate dependencies
17
+ * @param drifts List of detected version drift issues
18
+ * @param customPenalties Optional custom penalty configuration override
19
+ * @returns Fully computed HealthScore object
20
+ */
21
+ export declare function calculateHealthScore(ghosts: GhostDependency[], zombies: ZombieDependency[], duplicates: DuplicateDependency[], drifts: VersionDrift[], customPenalties?: ScanOptions['penalties']): HealthScore;
22
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/health.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EAEZ,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EAAE,EACzB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,YAAY,EAAE,EACtB,eAAe,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GACzC,WAAW,CAsGb"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Calculates the dependency health score and grade of a project.
3
+ *
4
+ * Score Formula:
5
+ * - Starting Base: 100
6
+ * - Deductions:
7
+ * - -5 per ghost dependency
8
+ * - -5 per zombie dependency
9
+ * - -3 per duplicate dependency
10
+ * - -2 per version drift (by default)
11
+ * - Minimum bounded score: 0
12
+ *
13
+ * @param ghosts List of detected ghost dependencies
14
+ * @param zombies List of detected zombie dependencies
15
+ * @param duplicates List of detected duplicate dependencies
16
+ * @param drifts List of detected version drift issues
17
+ * @param customPenalties Optional custom penalty configuration override
18
+ * @returns Fully computed HealthScore object
19
+ */
20
+ export function calculateHealthScore(ghosts, zombies, duplicates, drifts, customPenalties) {
21
+ const deductions = [];
22
+ let score = 100;
23
+ // 1. Ghost Dependencies deduction
24
+ if (ghosts.length > 0) {
25
+ const penaltyPerGhost = customPenalties?.ghost ?? 5;
26
+ const penalty = ghosts.length * penaltyPerGhost;
27
+ deductions.push({
28
+ reason: `${ghosts.length} ghost dependenc${ghosts.length === 1 ? 'y' : 'ies'} detected`,
29
+ penalty,
30
+ });
31
+ score -= penalty;
32
+ }
33
+ // 2. Zombie Dependencies deduction
34
+ if (zombies.length > 0) {
35
+ const penaltyPerZombie = customPenalties?.zombie ?? 5;
36
+ const penalty = zombies.length * penaltyPerZombie;
37
+ deductions.push({
38
+ reason: `${zombies.length} zombie dependenc${zombies.length === 1 ? 'y' : 'ies'} detected`,
39
+ penalty,
40
+ });
41
+ score -= penalty;
42
+ }
43
+ // 3. Duplicate Dependencies deduction
44
+ if (duplicates.length > 0) {
45
+ const penaltyPerDuplicate = customPenalties?.duplicate ?? 3;
46
+ const penalty = duplicates.length * penaltyPerDuplicate;
47
+ deductions.push({
48
+ reason: `${duplicates.length} duplicate package${duplicates.length === 1 ? '' : 's'} detected`,
49
+ penalty,
50
+ });
51
+ score -= penalty;
52
+ }
53
+ // 4. Version Drift deduction (aggregating major, minor, patch, and missing)
54
+ if (drifts.length > 0) {
55
+ let driftPenaltyTotal = 0;
56
+ let majorCount = 0;
57
+ let minorCount = 0;
58
+ let patchCount = 0;
59
+ let missingCount = 0;
60
+ for (const drift of drifts) {
61
+ if (drift.driftType === 'major') {
62
+ driftPenaltyTotal += customPenalties?.driftMajor ?? 2;
63
+ majorCount++;
64
+ }
65
+ else if (drift.driftType === 'minor') {
66
+ driftPenaltyTotal += customPenalties?.driftMinor ?? 2;
67
+ minorCount++;
68
+ }
69
+ else if (drift.driftType === 'patch') {
70
+ driftPenaltyTotal += customPenalties?.driftPatch ?? 2;
71
+ patchCount++;
72
+ }
73
+ else if (drift.driftType === 'missing') {
74
+ driftPenaltyTotal += customPenalties?.missing ?? 2;
75
+ missingCount++;
76
+ }
77
+ }
78
+ if (driftPenaltyTotal > 0) {
79
+ const details = [];
80
+ if (majorCount > 0)
81
+ details.push(`${majorCount} major`);
82
+ if (minorCount > 0)
83
+ details.push(`${minorCount} minor`);
84
+ if (patchCount > 0)
85
+ details.push(`${patchCount} patch`);
86
+ if (missingCount > 0)
87
+ details.push(`${missingCount} missing`);
88
+ deductions.push({
89
+ reason: `${drifts.length} version drift${drifts.length === 1 ? '' : 's'} (${details.join(', ')})`,
90
+ penalty: driftPenaltyTotal,
91
+ });
92
+ score -= driftPenaltyTotal;
93
+ }
94
+ }
95
+ // Limit score to a minimum of 0
96
+ score = Math.max(0, score);
97
+ // Grade Assignment
98
+ let grade = 'F';
99
+ if (score >= 90) {
100
+ grade = 'A';
101
+ }
102
+ else if (score >= 80) {
103
+ grade = 'B';
104
+ }
105
+ else if (score >= 70) {
106
+ grade = 'C';
107
+ }
108
+ else if (score >= 60) {
109
+ grade = 'D';
110
+ }
111
+ return {
112
+ score,
113
+ grade,
114
+ metrics: {
115
+ ghosts: ghosts.length,
116
+ zombies: zombies.length,
117
+ duplicates: duplicates.length,
118
+ drifts: drifts.length,
119
+ },
120
+ deductions,
121
+ };
122
+ }
123
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { runScan } from './scanner.js';
2
+ export { calculateHealthScore } from './health.js';
3
+ export * from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,cAAc,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { runScan } from './scanner.js';
2
+ export { calculateHealthScore } from './health.js';
3
+ export * from './types.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,cAAc,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { ScanReport } from './types.js';
2
+ /**
3
+ * Outputs a beautifully formatted CLI report summarizing the dependency audit scan results,
4
+ * color-coded by issue severity using chalk.
5
+ *
6
+ * @param report The final ScanReport resulting from the scan
7
+ */
8
+ export declare function reportToConsole(report: ScanReport): void;
9
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/reporter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CA2HxD"}