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.
- package/README.md +176 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +103 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/src/detectors/drift.d.ts +12 -0
- package/dist/src/detectors/drift.d.ts.map +1 -0
- package/dist/src/detectors/drift.js +95 -0
- package/dist/src/detectors/drift.js.map +1 -0
- package/dist/src/detectors/duplicates.d.ts +13 -0
- package/dist/src/detectors/duplicates.d.ts.map +1 -0
- package/dist/src/detectors/duplicates.js +151 -0
- package/dist/src/detectors/duplicates.js.map +1 -0
- package/dist/src/detectors/ghosts.d.ts +13 -0
- package/dist/src/detectors/ghosts.d.ts.map +1 -0
- package/dist/src/detectors/ghosts.js +209 -0
- package/dist/src/detectors/ghosts.js.map +1 -0
- package/dist/src/detectors/zombies.d.ts +22 -0
- package/dist/src/detectors/zombies.d.ts.map +1 -0
- package/dist/src/detectors/zombies.js +127 -0
- package/dist/src/detectors/zombies.js.map +1 -0
- package/dist/src/health.d.ts +22 -0
- package/dist/src/health.d.ts.map +1 -0
- package/dist/src/health.js +123 -0
- package/dist/src/health.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/reporter.d.ts +9 -0
- package/dist/src/reporter.d.ts.map +1 -0
- package/dist/src/reporter.js +115 -0
- package/dist/src/reporter.js.map +1 -0
- package/dist/src/scanner.d.ts +12 -0
- package/dist/src/scanner.d.ts.map +1 -0
- package/dist/src/scanner.js +62 -0
- package/dist/src/scanner.js.map +1 -0
- package/dist/src/types.d.ts +115 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/fs.d.ts +29 -0
- package/dist/src/utils/fs.d.ts.map +1 -0
- package/dist/src/utils/fs.js +72 -0
- package/dist/src/utils/fs.js.map +1 -0
- package/dist/src/utils/packageManager.d.ts +20 -0
- package/dist/src/utils/packageManager.d.ts.map +1 -0
- package/dist/src/utils/packageManager.js +74 -0
- package/dist/src/utils/packageManager.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
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 function reportToConsole(report) {
|
|
9
|
+
const { project, durationMs, ghosts, zombies, duplicates, drifts, health } = report;
|
|
10
|
+
// Header Banner
|
|
11
|
+
console.log('\n' + chalk.bold.cyan('👻 ghostdep') + chalk.dim(` v0.1.0`));
|
|
12
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
13
|
+
console.log(`${chalk.bold('Target Project:')} ${chalk.white(project.name)}`);
|
|
14
|
+
console.log(`${chalk.bold('Version:')} ${chalk.white(project.version)}`);
|
|
15
|
+
console.log(`${chalk.bold('Scan Time:')} ${chalk.white(durationMs)}ms`);
|
|
16
|
+
console.log(chalk.gray('─'.repeat(60)) + '\n');
|
|
17
|
+
// 1. Ghost Dependencies (Highest Priority - Missing Declarations)
|
|
18
|
+
if (ghosts.length > 0) {
|
|
19
|
+
console.log(chalk.bold.red(`👻 Ghost Dependencies (${ghosts.length})`));
|
|
20
|
+
console.log(chalk.dim(' Packages imported in code but not declared in package.json'));
|
|
21
|
+
console.log(chalk.gray(' ' + '─'.repeat(54)));
|
|
22
|
+
for (const ghost of ghosts) {
|
|
23
|
+
console.log(` ${chalk.red('✗')} ${chalk.bold.white(ghost.name)}`);
|
|
24
|
+
const filesLimit = 5;
|
|
25
|
+
const formattedFiles = ghost.files
|
|
26
|
+
.slice(0, filesLimit)
|
|
27
|
+
.map((f) => chalk.gray(f))
|
|
28
|
+
.join(', ');
|
|
29
|
+
const overflow = ghost.files.length > filesLimit ? chalk.dim(` (+${ghost.files.length - filesLimit} more)`) : '';
|
|
30
|
+
console.log(` ${chalk.dim('Files:')} ${formattedFiles}${overflow}`);
|
|
31
|
+
console.log(` ${chalk.dim('Imports:')} ${chalk.gray(ghost.specifiers.join(', '))}`);
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
// 2. Zombie Dependencies (Unused Declarations)
|
|
36
|
+
if (zombies.length > 0) {
|
|
37
|
+
console.log(chalk.bold.yellow(`🧟 Zombie Dependencies (${zombies.length})`));
|
|
38
|
+
console.log(chalk.dim(' Declared in package.json but never imported or required in code'));
|
|
39
|
+
console.log(chalk.gray(' ' + '─'.repeat(54)));
|
|
40
|
+
for (const zombie of zombies) {
|
|
41
|
+
console.log(` ${chalk.yellow('âš ')} ${chalk.bold.white(zombie.name)} ${chalk.dim(`(${zombie.declaredVersion})`)} [${chalk.cyan(zombie.type)}]`);
|
|
42
|
+
}
|
|
43
|
+
console.log();
|
|
44
|
+
}
|
|
45
|
+
// 3. Duplicate Dependency Versions
|
|
46
|
+
if (duplicates.length > 0) {
|
|
47
|
+
console.log(chalk.bold.magenta(`📦 Duplicate Package Versions (${duplicates.length})`));
|
|
48
|
+
console.log(chalk.dim(' Multiple conflicting versions of the same package resolved in node_modules'));
|
|
49
|
+
console.log(chalk.gray(' ' + '─'.repeat(54)));
|
|
50
|
+
for (const dup of duplicates) {
|
|
51
|
+
console.log(` ${chalk.magenta('⇄')} ${chalk.bold.white(dup.name)}`);
|
|
52
|
+
for (const instance of dup.versions) {
|
|
53
|
+
console.log(` ${chalk.bold.white(instance.version)} resolved at:`);
|
|
54
|
+
for (const path of instance.paths) {
|
|
55
|
+
console.log(` ${chalk.gray(path)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
console.log();
|
|
60
|
+
}
|
|
61
|
+
// 4. Version Drifts
|
|
62
|
+
if (drifts.length > 0) {
|
|
63
|
+
console.log(chalk.bold.blue(`🔄 Version Drift Mismatches (${drifts.length})`));
|
|
64
|
+
console.log(chalk.dim(' Difference between declared semver ranges and actual installed versions'));
|
|
65
|
+
console.log(chalk.gray(' ' + '─'.repeat(54)));
|
|
66
|
+
for (const drift of drifts) {
|
|
67
|
+
const typeColor = drift.driftType === 'major' || drift.driftType === 'missing'
|
|
68
|
+
? chalk.red
|
|
69
|
+
: drift.driftType === 'minor'
|
|
70
|
+
? chalk.yellow
|
|
71
|
+
: chalk.green;
|
|
72
|
+
const installedStr = drift.installedVersion
|
|
73
|
+
? chalk.white(drift.installedVersion)
|
|
74
|
+
: chalk.red.bold('NOT INSTALLED');
|
|
75
|
+
console.log(` ${chalk.blue('ℹ')} ${chalk.bold.white(drift.name)} [${chalk.cyan(drift.dependencyType)}]`);
|
|
76
|
+
console.log(` Declared Range: ${chalk.gray(drift.declaredVersion)}`);
|
|
77
|
+
console.log(` Installed Version: ${installedStr}`);
|
|
78
|
+
console.log(` Drift Category: ${typeColor(drift.driftType.toUpperCase())}`);
|
|
79
|
+
}
|
|
80
|
+
console.log();
|
|
81
|
+
}
|
|
82
|
+
// 5. Overall Health Report Card
|
|
83
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
84
|
+
const gradeColor = health.grade === 'A'
|
|
85
|
+
? chalk.bold.green
|
|
86
|
+
: health.grade === 'B'
|
|
87
|
+
? chalk.bold.green
|
|
88
|
+
: health.grade === 'C'
|
|
89
|
+
? chalk.bold.yellow
|
|
90
|
+
: health.grade === 'D'
|
|
91
|
+
? chalk.bold.yellow
|
|
92
|
+
: chalk.bold.red;
|
|
93
|
+
const scoreColor = health.score >= 90
|
|
94
|
+
? chalk.bold.green
|
|
95
|
+
: health.score >= 75
|
|
96
|
+
? chalk.bold.cyan
|
|
97
|
+
: health.score >= 60
|
|
98
|
+
? chalk.bold.yellow
|
|
99
|
+
: chalk.bold.red;
|
|
100
|
+
console.log(chalk.bold('📊 HEALTH REPORT CARD'));
|
|
101
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
102
|
+
console.log(`Overall Health Score: ${scoreColor(health.score)} / 100`);
|
|
103
|
+
console.log(`Letter Grade Summary: ${gradeColor(health.grade)}`);
|
|
104
|
+
if (health.deductions.length > 0) {
|
|
105
|
+
console.log(`\n${chalk.bold('Deductions Details:')}`);
|
|
106
|
+
for (const deduction of health.deductions) {
|
|
107
|
+
console.log(` ${chalk.red('•')} ${deduction.reason}: ${chalk.red(`-${deduction.penalty} pts`)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(`\n${chalk.bold.green('✨ Clean Audit! All dependencies are fully optimized and healthy.')}`);
|
|
112
|
+
}
|
|
113
|
+
console.log(chalk.gray('─'.repeat(60)) + '\n');
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ScanReport, ScanOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Executes a full dependency audit scan of the target project directory.
|
|
4
|
+
*
|
|
5
|
+
* Runs all detectors (ghosts, zombies, duplicates, drifts) concurrently,
|
|
6
|
+
* computes the overall project health score, and generates a structured report.
|
|
7
|
+
*
|
|
8
|
+
* @param partialOptions Configuration overrides for the scanning process
|
|
9
|
+
* @returns Fully populated ScanReport
|
|
10
|
+
*/
|
|
11
|
+
export declare function runScan(partialOptions?: Partial<ScanOptions>): Promise<ScanReport>;
|
|
12
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/scanner.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,cAAc,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmD5F"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { readPackageJson, scanFiles } from './utils/fs.js';
|
|
2
|
+
import { detectGhosts } from './detectors/ghosts.js';
|
|
3
|
+
import { detectZombies } from './detectors/zombies.js';
|
|
4
|
+
import { detectDuplicates } from './detectors/duplicates.js';
|
|
5
|
+
import { detectDrifts } from './detectors/drift.js';
|
|
6
|
+
import { calculateHealthScore } from './health.js';
|
|
7
|
+
/**
|
|
8
|
+
* Executes a full dependency audit scan of the target project directory.
|
|
9
|
+
*
|
|
10
|
+
* Runs all detectors (ghosts, zombies, duplicates, drifts) concurrently,
|
|
11
|
+
* computes the overall project health score, and generates a structured report.
|
|
12
|
+
*
|
|
13
|
+
* @param partialOptions Configuration overrides for the scanning process
|
|
14
|
+
* @returns Fully populated ScanReport
|
|
15
|
+
*/
|
|
16
|
+
export async function runScan(partialOptions = {}) {
|
|
17
|
+
const startTime = Date.now();
|
|
18
|
+
// 1. Resolve configuration options with defaults
|
|
19
|
+
const options = {
|
|
20
|
+
cwd: partialOptions.cwd || process.cwd(),
|
|
21
|
+
include: partialOptions.include || ['**/*.{js,jsx,ts,tsx,mjs,cjs}'],
|
|
22
|
+
exclude: partialOptions.exclude || [],
|
|
23
|
+
includeDev: partialOptions.includeDev ?? false,
|
|
24
|
+
...(partialOptions.penalties ? { penalties: partialOptions.penalties } : {}),
|
|
25
|
+
};
|
|
26
|
+
try {
|
|
27
|
+
// 2. Read package.json metadata
|
|
28
|
+
const packageJson = await readPackageJson(options.cwd);
|
|
29
|
+
// 3. Scan the codebase directory for source files
|
|
30
|
+
const sourceFiles = await scanFiles(options.cwd, options.include, options.exclude);
|
|
31
|
+
// 4. Run diagnostics concurrently for optimal performance
|
|
32
|
+
const [ghosts, zombies, duplicates, drifts] = await Promise.all([
|
|
33
|
+
detectGhosts(options.cwd, sourceFiles, packageJson, options.includeDev),
|
|
34
|
+
detectZombies(sourceFiles, packageJson, options.includeDev),
|
|
35
|
+
detectDuplicates(options.cwd),
|
|
36
|
+
detectDrifts(options.cwd, packageJson, options.includeDev),
|
|
37
|
+
]);
|
|
38
|
+
// 5. Calculate dependency health score
|
|
39
|
+
const health = calculateHealthScore(ghosts, zombies, duplicates, drifts, options.penalties);
|
|
40
|
+
const endTime = Date.now();
|
|
41
|
+
const durationMs = endTime - startTime;
|
|
42
|
+
// 6. Build and return the final report
|
|
43
|
+
return {
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
45
|
+
durationMs,
|
|
46
|
+
project: {
|
|
47
|
+
name: packageJson.name || 'unnamed-project',
|
|
48
|
+
version: packageJson.version || '0.0.0',
|
|
49
|
+
},
|
|
50
|
+
ghosts,
|
|
51
|
+
zombies,
|
|
52
|
+
duplicates,
|
|
53
|
+
drifts,
|
|
54
|
+
health,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const err = error;
|
|
59
|
+
throw new Error(`Scan execution failed: ${err.message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,iBAAuC,EAAE;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,iDAAiD;IACjD,MAAM,OAAO,GAAgB;QAC3B,GAAG,EAAE,cAAc,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACxC,OAAO,EAAE,cAAc,CAAC,OAAO,IAAI,CAAC,8BAA8B,CAAC;QACnE,OAAO,EAAE,cAAc,CAAC,OAAO,IAAI,EAAE;QACrC,UAAU,EAAE,cAAc,CAAC,UAAU,IAAI,KAAK;QAC9C,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7E,CAAC;IAEF,IAAI,CAAC;QACH,gCAAgC;QAChC,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEvD,kDAAkD;QAClD,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAEnF,0DAA0D;QAC1D,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC9D,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC;YACvE,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC;YAC3D,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC;YAC7B,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC;SAC3D,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAE5F,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;QAEvC,uCAAuC;QACvC,OAAO;YACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,WAAW,CAAC,IAAI,IAAI,iBAAiB;gBAC3C,OAAO,EAAE,WAAW,CAAC,OAAO,IAAI,OAAO;aACxC;YACD,MAAM;YACN,OAAO;YACP,UAAU;YACV,MAAM;YACN,MAAM;SACP,CAAC;IACJ,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAc,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export interface GhostDependency {
|
|
2
|
+
/** Name of the imported package that is not declared in package.json */
|
|
3
|
+
name: string;
|
|
4
|
+
/** List of files (relative paths) where this package was imported */
|
|
5
|
+
files: string[];
|
|
6
|
+
/** The import specifiers used in code (e.g. "lodash/map") */
|
|
7
|
+
specifiers: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ZombieDependency {
|
|
10
|
+
/** Name of the package declared in package.json but not used in code */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Section under which it is declared in package.json */
|
|
13
|
+
type: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies';
|
|
14
|
+
/** The version range declared in package.json */
|
|
15
|
+
declaredVersion: string;
|
|
16
|
+
}
|
|
17
|
+
export interface DuplicateDependencyInstance {
|
|
18
|
+
/** The resolved actual version */
|
|
19
|
+
version: string;
|
|
20
|
+
/** Paths to the directory in node_modules resolving to this version */
|
|
21
|
+
paths: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface DuplicateDependency {
|
|
24
|
+
/** Name of the package with duplicate versions installed */
|
|
25
|
+
name: string;
|
|
26
|
+
/** Array of installed versions and their locations */
|
|
27
|
+
versions: DuplicateDependencyInstance[];
|
|
28
|
+
}
|
|
29
|
+
export interface VersionDrift {
|
|
30
|
+
/** Name of the package */
|
|
31
|
+
name: string;
|
|
32
|
+
/** Section under which it is declared in package.json */
|
|
33
|
+
dependencyType: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies';
|
|
34
|
+
/** The version range declared in package.json */
|
|
35
|
+
declaredVersion: string;
|
|
36
|
+
/** The actual version resolved/installed in node_modules (null if not installed) */
|
|
37
|
+
installedVersion: string | null;
|
|
38
|
+
/** Categorization of the drift gap */
|
|
39
|
+
driftType: 'major' | 'minor' | 'patch' | 'missing' | 'none';
|
|
40
|
+
}
|
|
41
|
+
export interface HealthDeduction {
|
|
42
|
+
/** Reason for the deduction (e.g. "2 ghost dependencies detected") */
|
|
43
|
+
reason: string;
|
|
44
|
+
/** Points deducted from the 100 base score */
|
|
45
|
+
penalty: number;
|
|
46
|
+
}
|
|
47
|
+
export interface HealthScore {
|
|
48
|
+
/** Overall calculated health score from 0 to 100 */
|
|
49
|
+
score: number;
|
|
50
|
+
/** Letter grade based on the score */
|
|
51
|
+
grade: 'A' | 'B' | 'C' | 'D' | 'F';
|
|
52
|
+
/** Quantities of various issues found */
|
|
53
|
+
metrics: {
|
|
54
|
+
ghosts: number;
|
|
55
|
+
zombies: number;
|
|
56
|
+
duplicates: number;
|
|
57
|
+
drifts: number;
|
|
58
|
+
};
|
|
59
|
+
/** Detail of deductions applied to reach the final score */
|
|
60
|
+
deductions: HealthDeduction[];
|
|
61
|
+
}
|
|
62
|
+
export interface ProjectMetadata {
|
|
63
|
+
/** Name of the analyzed project from package.json */
|
|
64
|
+
name: string;
|
|
65
|
+
/** Version of the analyzed project from package.json */
|
|
66
|
+
version: string;
|
|
67
|
+
}
|
|
68
|
+
export interface PackageJson {
|
|
69
|
+
name?: string;
|
|
70
|
+
version?: string;
|
|
71
|
+
packageManager?: string;
|
|
72
|
+
dependencies?: Record<string, string>;
|
|
73
|
+
devDependencies?: Record<string, string>;
|
|
74
|
+
peerDependencies?: Record<string, string>;
|
|
75
|
+
optionalDependencies?: Record<string, string>;
|
|
76
|
+
}
|
|
77
|
+
export interface ScanReport {
|
|
78
|
+
/** Timestamp when the scan was executed */
|
|
79
|
+
timestamp: string;
|
|
80
|
+
/** Time taken to run the analysis in milliseconds */
|
|
81
|
+
durationMs: number;
|
|
82
|
+
/** Analyzed project's metadata */
|
|
83
|
+
project: ProjectMetadata;
|
|
84
|
+
/** Detected ghost dependencies */
|
|
85
|
+
ghosts: GhostDependency[];
|
|
86
|
+
/** Detected zombie dependencies */
|
|
87
|
+
zombies: ZombieDependency[];
|
|
88
|
+
/** Detected duplicate package versions */
|
|
89
|
+
duplicates: DuplicateDependency[];
|
|
90
|
+
/** Detected version drift issues */
|
|
91
|
+
drifts: VersionDrift[];
|
|
92
|
+
/** Overall calculated health metrics */
|
|
93
|
+
health: HealthScore;
|
|
94
|
+
}
|
|
95
|
+
export interface ScanOptions {
|
|
96
|
+
/** Working directory to scan (defaults to process.cwd()) */
|
|
97
|
+
cwd: string;
|
|
98
|
+
/** Glob patterns to search for source code files */
|
|
99
|
+
include: string[];
|
|
100
|
+
/** Glob patterns to exclude from source code scan (e.g. node_modules, dist, test files) */
|
|
101
|
+
exclude: string[];
|
|
102
|
+
/** Whether to scan and include devDependencies in audits */
|
|
103
|
+
includeDev: boolean;
|
|
104
|
+
/** Custom penalties for issues when calculating the health score */
|
|
105
|
+
penalties?: {
|
|
106
|
+
ghost?: number;
|
|
107
|
+
zombie?: number;
|
|
108
|
+
duplicate?: number;
|
|
109
|
+
driftMajor?: number;
|
|
110
|
+
driftMinor?: number;
|
|
111
|
+
driftPatch?: number;
|
|
112
|
+
missing?: number;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { PackageJson } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generic utility to read and parse a JSON file asynchronously.
|
|
4
|
+
*
|
|
5
|
+
* @param filePath Absolute path to the JSON file
|
|
6
|
+
* @returns Parsed JSON object of type T
|
|
7
|
+
* @throws Error if the file cannot be read or parsed
|
|
8
|
+
*/
|
|
9
|
+
export declare function readJson<T = unknown>(filePath: string): Promise<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Reads and parses package.json from the specified directory path.
|
|
12
|
+
*
|
|
13
|
+
* @param projectRoot Absolute path to the project root directory
|
|
14
|
+
* @returns Parsed PackageJson object
|
|
15
|
+
* @throws Error if the file cannot be read or parsed
|
|
16
|
+
*/
|
|
17
|
+
export declare function readPackageJson(projectRoot: string): Promise<PackageJson>;
|
|
18
|
+
/**
|
|
19
|
+
* Recursively scans folders for source files matching specified patterns,
|
|
20
|
+
* ignoring .git, node_modules, and common build/output directories.
|
|
21
|
+
*
|
|
22
|
+
* @param directory Absolute path to the directory to scan
|
|
23
|
+
* @param patterns Array of glob patterns to match (defaults to common JS/TS extensions)
|
|
24
|
+
* @param extraIgnores Optional array of extra glob patterns to ignore
|
|
25
|
+
* @returns List of absolute file paths matching the scan
|
|
26
|
+
* @throws Error if directory scanning fails
|
|
27
|
+
*/
|
|
28
|
+
export declare function scanFiles(directory: string, patterns?: string[], extraIgnores?: string[]): Promise<string[]>;
|
|
29
|
+
//# sourceMappingURL=fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../src/utils/fs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAWxE;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAG/E;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,MAAM,EAAqC,EACrD,YAAY,GAAE,MAAM,EAAO,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import fg from 'fast-glob';
|
|
4
|
+
/**
|
|
5
|
+
* Generic utility to read and parse a JSON file asynchronously.
|
|
6
|
+
*
|
|
7
|
+
* @param filePath Absolute path to the JSON file
|
|
8
|
+
* @returns Parsed JSON object of type T
|
|
9
|
+
* @throws Error if the file cannot be read or parsed
|
|
10
|
+
*/
|
|
11
|
+
export async function readJson(filePath) {
|
|
12
|
+
try {
|
|
13
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
14
|
+
return JSON.parse(content);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
const err = error;
|
|
18
|
+
if (err.code === 'ENOENT') {
|
|
19
|
+
throw new Error(`JSON file was not found at "${filePath}".`);
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`Failed to read or parse JSON file at "${filePath}": ${err.message}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Reads and parses package.json from the specified directory path.
|
|
26
|
+
*
|
|
27
|
+
* @param projectRoot Absolute path to the project root directory
|
|
28
|
+
* @returns Parsed PackageJson object
|
|
29
|
+
* @throws Error if the file cannot be read or parsed
|
|
30
|
+
*/
|
|
31
|
+
export async function readPackageJson(projectRoot) {
|
|
32
|
+
const filePath = join(projectRoot, 'package.json');
|
|
33
|
+
return readJson(filePath);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Recursively scans folders for source files matching specified patterns,
|
|
37
|
+
* ignoring .git, node_modules, and common build/output directories.
|
|
38
|
+
*
|
|
39
|
+
* @param directory Absolute path to the directory to scan
|
|
40
|
+
* @param patterns Array of glob patterns to match (defaults to common JS/TS extensions)
|
|
41
|
+
* @param extraIgnores Optional array of extra glob patterns to ignore
|
|
42
|
+
* @returns List of absolute file paths matching the scan
|
|
43
|
+
* @throws Error if directory scanning fails
|
|
44
|
+
*/
|
|
45
|
+
export async function scanFiles(directory, patterns = ['**/*.{js,jsx,ts,tsx,mjs,cjs}'], extraIgnores = []) {
|
|
46
|
+
try {
|
|
47
|
+
const defaultIgnores = [
|
|
48
|
+
'**/node_modules/**',
|
|
49
|
+
'**/.git/**',
|
|
50
|
+
'**/dist/**',
|
|
51
|
+
'**/build/**',
|
|
52
|
+
'**/coverage/**',
|
|
53
|
+
'**/.nyc_output/**',
|
|
54
|
+
];
|
|
55
|
+
const ignore = [...defaultIgnores, ...extraIgnores];
|
|
56
|
+
// fast-glob requires forward slashes for cross-platform glob matching
|
|
57
|
+
const cleanDir = directory.replace(/\\/g, '/');
|
|
58
|
+
const files = await fg(patterns, {
|
|
59
|
+
cwd: cleanDir,
|
|
60
|
+
ignore,
|
|
61
|
+
absolute: true,
|
|
62
|
+
onlyFiles: true,
|
|
63
|
+
dot: false, // Don't match dotfiles by default (e.g. .eslintrc) unless specified
|
|
64
|
+
});
|
|
65
|
+
return files;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const err = error;
|
|
69
|
+
throw new Error(`Failed to scan files in directory "${directory}": ${err.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../../src/utils/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,MAAM,WAAW,CAAC;AAG3B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAc,QAAgB;IAC1D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;IAClC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAA8B,CAAC;QAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,IAAI,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACnD,OAAO,QAAQ,CAAc,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAAiB,EACjB,WAAqB,CAAC,8BAA8B,CAAC,EACrD,eAAyB,EAAE;IAE3B,IAAI,CAAC;QACH,MAAM,cAAc,GAAG;YACrB,oBAAoB;YACpB,YAAY;YACZ,YAAY;YACZ,aAAa;YACb,gBAAgB;YAChB,mBAAmB;SACpB,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,YAAY,CAAC,CAAC;QAEpD,sEAAsE;QACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAE/C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC/B,GAAG,EAAE,QAAQ;YACb,MAAM;YACN,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,KAAK,EAAE,oEAAoE;SACjF,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAc,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,sCAAsC,SAAS,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PackageJson } from '../types.js';
|
|
2
|
+
export type PackageManagerType = 'npm' | 'yarn' | 'pnpm';
|
|
3
|
+
/**
|
|
4
|
+
* Reads and parses package.json from the specified directory path.
|
|
5
|
+
*
|
|
6
|
+
* @param projectRoot Absolute path to the project root directory
|
|
7
|
+
* @returns Parsed PackageJson object
|
|
8
|
+
* @throws Error if the file cannot be read or parsed
|
|
9
|
+
*/
|
|
10
|
+
export declare function readPackageJson(projectRoot: string): Promise<PackageJson>;
|
|
11
|
+
/**
|
|
12
|
+
* Detects the active package manager of the project by verifying lockfiles
|
|
13
|
+
* or inspecting the "packageManager" property in package.json.
|
|
14
|
+
* Defaults to "npm" if no package manager can be identified.
|
|
15
|
+
*
|
|
16
|
+
* @param projectRoot Absolute path to the project root directory
|
|
17
|
+
* @returns The identified package manager ('npm' | 'yarn' | 'pnpm')
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectPackageManager(projectRoot: string): Promise<PackageManagerType>;
|
|
20
|
+
//# sourceMappingURL=packageManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageManager.d.ts","sourceRoot":"","sources":["../../../src/utils/packageManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAY/E;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuC3F"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
/**
|
|
4
|
+
* Reads and parses package.json from the specified directory path.
|
|
5
|
+
*
|
|
6
|
+
* @param projectRoot Absolute path to the project root directory
|
|
7
|
+
* @returns Parsed PackageJson object
|
|
8
|
+
* @throws Error if the file cannot be read or parsed
|
|
9
|
+
*/
|
|
10
|
+
export async function readPackageJson(projectRoot) {
|
|
11
|
+
const filePath = join(projectRoot, 'package.json');
|
|
12
|
+
try {
|
|
13
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
14
|
+
return JSON.parse(content);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
const err = error;
|
|
18
|
+
if (err.code === 'ENOENT') {
|
|
19
|
+
throw new Error(`package.json was not found at "${filePath}".`);
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`Failed to parse package.json at "${filePath}": ${err.message}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Detects the active package manager of the project by verifying lockfiles
|
|
26
|
+
* or inspecting the "packageManager" property in package.json.
|
|
27
|
+
* Defaults to "npm" if no package manager can be identified.
|
|
28
|
+
*
|
|
29
|
+
* @param projectRoot Absolute path to the project root directory
|
|
30
|
+
* @returns The identified package manager ('npm' | 'yarn' | 'pnpm')
|
|
31
|
+
*/
|
|
32
|
+
export async function detectPackageManager(projectRoot) {
|
|
33
|
+
try {
|
|
34
|
+
const checkFileExists = async (filename) => {
|
|
35
|
+
try {
|
|
36
|
+
await fs.access(join(projectRoot, filename));
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const [hasPnpm, hasYarn, hasNpm] = await Promise.all([
|
|
44
|
+
checkFileExists('pnpm-lock.yaml'),
|
|
45
|
+
checkFileExists('yarn.lock'),
|
|
46
|
+
checkFileExists('package-lock.json'),
|
|
47
|
+
]);
|
|
48
|
+
if (hasPnpm)
|
|
49
|
+
return 'pnpm';
|
|
50
|
+
if (hasYarn)
|
|
51
|
+
return 'yarn';
|
|
52
|
+
if (hasNpm)
|
|
53
|
+
return 'npm';
|
|
54
|
+
// Fallback: inspect packageManager field inside package.json
|
|
55
|
+
try {
|
|
56
|
+
const pkg = await readPackageJson(projectRoot);
|
|
57
|
+
if (pkg.packageManager) {
|
|
58
|
+
const [name] = pkg.packageManager.split('@');
|
|
59
|
+
if (name === 'npm' || name === 'yarn' || name === 'pnpm') {
|
|
60
|
+
return name;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Fallback silently if package.json does not exist or fails parsing
|
|
66
|
+
}
|
|
67
|
+
return 'npm';
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const err = error;
|
|
71
|
+
throw new Error(`Package manager detection failed: ${err.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=packageManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageManager.js","sourceRoot":"","sources":["../../../src/utils/packageManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AAKpC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAA8B,CAAC;QAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,IAAI,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,WAAmB;IAC5D,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,KAAK,EAAE,QAAgB,EAAoB,EAAE;YACnE,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAC7C,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACnD,eAAe,CAAC,gBAAgB,CAAC;YACjC,eAAe,CAAC,WAAW,CAAC;YAC5B,eAAe,CAAC,mBAAmB,CAAC;SACrC,CAAC,CAAC;QAEH,IAAI,OAAO;YAAE,OAAO,MAAM,CAAC;QAC3B,IAAI,OAAO;YAAE,OAAO,MAAM,CAAC;QAC3B,IAAI,MAAM;YAAE,OAAO,KAAK,CAAC;QAEzB,6DAA6D;QAC7D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;YAC/C,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC7C,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;oBACzD,OAAO,IAA0B,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAc,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ghostdep",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A production-ready CLI and library to detect ghost, zombie, duplicate, and drifted dependencies in Node.js and TypeScript projects.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ghost-dependencies",
|
|
7
|
+
"zombie-dependencies",
|
|
8
|
+
"dependency-drift",
|
|
9
|
+
"duplicate-dependencies",
|
|
10
|
+
"dependency-health",
|
|
11
|
+
"npm",
|
|
12
|
+
"typescript",
|
|
13
|
+
"cli",
|
|
14
|
+
"esm"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/yourusername/ghostdep#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/yourusername/ghostdep/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/yourusername/ghostdep.git"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": "./dist/src/index.js",
|
|
29
|
+
"types": "./dist/src/index.d.ts"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"main": "./dist/src/index.js",
|
|
33
|
+
"types": "./dist/src/index.d.ts",
|
|
34
|
+
"bin": {
|
|
35
|
+
"ghostdep": "./dist/bin/cli.js"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc --project tsconfig.build.json",
|
|
44
|
+
"build:watch": "tsc --project tsconfig.build.json --watch",
|
|
45
|
+
"clean": "rimraf dist",
|
|
46
|
+
"prebuild": "npm run clean",
|
|
47
|
+
"dev": "tsx bin/cli.ts",
|
|
48
|
+
"lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\" \"bin/**/*.ts\"",
|
|
49
|
+
"lint:fix": "eslint \"src/**/*.ts\" \"tests/**/*.ts\" \"bin/**/*.ts\" --fix",
|
|
50
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"bin/**/*.ts\" \"*.json\"",
|
|
51
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"bin/**/*.ts\" \"*.json\"",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest",
|
|
54
|
+
"test:coverage": "vitest run --coverage",
|
|
55
|
+
"typecheck": "tsc --noEmit",
|
|
56
|
+
"prepublishOnly": "npm run clean && npm run lint && npm run typecheck && npm run test && npm run build"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"chalk": "^5.3.0",
|
|
60
|
+
"commander": "^12.1.0",
|
|
61
|
+
"fast-glob": "^3.3.2",
|
|
62
|
+
"semver": "^7.6.2",
|
|
63
|
+
"typescript": "^5.4.5"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@types/node": "^20.14.2",
|
|
67
|
+
"@types/semver": "^7.5.8",
|
|
68
|
+
"@typescript-eslint/eslint-plugin": "^7.13.0",
|
|
69
|
+
"@typescript-eslint/parser": "^7.13.0",
|
|
70
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
71
|
+
"eslint": "^8.57.0",
|
|
72
|
+
"eslint-config-prettier": "^9.1.0",
|
|
73
|
+
"eslint-plugin-import": "^2.29.1",
|
|
74
|
+
"prettier": "^3.3.1",
|
|
75
|
+
"rimraf": "^5.0.7",
|
|
76
|
+
"tsx": "^4.15.1",
|
|
77
|
+
"vitest": "^1.6.0"
|
|
78
|
+
},
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": ">=18.0.0"
|
|
81
|
+
},
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"access": "public"
|
|
84
|
+
}
|
|
85
|
+
}
|