pkg-clean 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 +226 -0
- package/dist/analyzer.d.ts +24 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +75 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/analyzer.test.d.ts +1 -0
- package/dist/analyzer.test.js +89 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/configLoader.d.ts +40 -0
- package/dist/configLoader.d.ts.map +1 -0
- package/dist/configLoader.js +97 -0
- package/dist/configLoader.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +179 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +316 -0
- package/dist/packageManager.d.ts +14 -0
- package/dist/packageManager.d.ts.map +1 -0
- package/dist/packageManager.js +67 -0
- package/dist/packageManager.js.map +1 -0
- package/dist/packageManagerFactory.d.ts +37 -0
- package/dist/packageManagerFactory.d.ts.map +1 -0
- package/dist/packageManagerFactory.js +158 -0
- package/dist/packageManagerFactory.js.map +1 -0
- package/dist/registry.d.ts +25 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +61 -0
- package/dist/registry.js.map +1 -0
- package/dist/registry.test.d.ts +1 -0
- package/dist/registry.test.js +72 -0
- package/dist/scanner.d.ts +20 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +89 -0
- package/dist/scanner.js.map +1 -0
- package/dist/scanner.test.d.ts +1 -0
- package/dist/scanner.test.js +79 -0
- package/package.json +53 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Cleaner = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const scanner_1 = require("./scanner");
|
|
40
|
+
const analyzer_1 = require("./analyzer");
|
|
41
|
+
const registry_1 = require("./registry");
|
|
42
|
+
function loadConfig(projectRoot) {
|
|
43
|
+
const configPath = path.join(projectRoot, "pkg-clean.config.json");
|
|
44
|
+
if (!fs.existsSync(configPath)) {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
49
|
+
const config = JSON.parse(content);
|
|
50
|
+
return { keep: config.keep };
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
console.warn(`\x1b[33m⚠\x1b[0m Warning: Could not load config file: ${message}`);
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function removeDependencies(projectRoot, packages) {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
61
|
+
if (!fs.existsSync(pkgPath)) {
|
|
62
|
+
throw new Error("package.json not found");
|
|
63
|
+
}
|
|
64
|
+
const content = fs.readFileSync(pkgPath, "utf-8");
|
|
65
|
+
const pkg = JSON.parse(content);
|
|
66
|
+
for (const packageName of packages) {
|
|
67
|
+
(_a = pkg.dependencies) === null || _a === void 0 ? true : delete _a[packageName];
|
|
68
|
+
(_b = pkg.devDependencies) === null || _b === void 0 ? true : delete _b[packageName];
|
|
69
|
+
}
|
|
70
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Main cleaner class that orchestrates the dependency analysis workflow.
|
|
75
|
+
* Scans project files, analyzes dependencies, checks for deprecation, and optionally removes unused packages.
|
|
76
|
+
*/
|
|
77
|
+
class Cleaner {
|
|
78
|
+
constructor() {
|
|
79
|
+
this.scanner = new scanner_1.Scanner();
|
|
80
|
+
this.analyzer = new analyzer_1.Analyzer();
|
|
81
|
+
this.registry = new registry_1.Registry();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Scans a project for unused dependencies and optionally removes them.
|
|
85
|
+
* @param projectRoot - The root directory of the project to scan
|
|
86
|
+
* @param options - Configuration options for the clean operation
|
|
87
|
+
* @param options.remove - If true, removes unused dependencies from package.json
|
|
88
|
+
* @param options.verbose - If true, outputs detailed diagnostic information
|
|
89
|
+
* @throws {Error} If package.json is not found in the project root
|
|
90
|
+
*/
|
|
91
|
+
async clean(projectRoot, options = {}) {
|
|
92
|
+
// Load config file and merge with provided options
|
|
93
|
+
const configOptions = loadConfig(projectRoot);
|
|
94
|
+
const mergedOptions = { ...configOptions, ...options };
|
|
95
|
+
// Validate project root is a directory
|
|
96
|
+
const resolvedPath = path.resolve(projectRoot);
|
|
97
|
+
try {
|
|
98
|
+
const stats = fs.statSync(resolvedPath);
|
|
99
|
+
if (!stats.isDirectory()) {
|
|
100
|
+
throw new Error(`"${projectRoot}" is not a directory`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error instanceof Error && error.message.includes("not a directory")) {
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
throw new Error(`Directory not found: "${projectRoot}"`);
|
|
108
|
+
}
|
|
109
|
+
// Print header
|
|
110
|
+
console.log("\n\x1b[36m◆\x1b[0m \x1b[1mpkg-clean\x1b[0m");
|
|
111
|
+
// Scan project for imports
|
|
112
|
+
console.log("\x1b[90m→\x1b[0m Scanning files...");
|
|
113
|
+
const imports = await this.scanner.scan(projectRoot);
|
|
114
|
+
console.log("\x1b[32m✓\x1b[0m Found \x1b[1m" + imports.size + "\x1b[0m imports");
|
|
115
|
+
if (options.verbose) {
|
|
116
|
+
console.log(" Imported packages:", Array.from(imports).sort());
|
|
117
|
+
}
|
|
118
|
+
// Analyze dependencies
|
|
119
|
+
console.log("\x1b[90m→\x1b[0m Analyzing dependencies...");
|
|
120
|
+
const analysis = this.analyzer.analyzeProject(projectRoot, imports);
|
|
121
|
+
if (options.verbose) {
|
|
122
|
+
console.log(" All dependencies:", analysis.allDeps.sort());
|
|
123
|
+
}
|
|
124
|
+
// Filter out packages to keep
|
|
125
|
+
const keepList = new Set(mergedOptions.keep || []);
|
|
126
|
+
if (options.verbose && keepList.size > 0) {
|
|
127
|
+
console.log(" Keeping packages:", Array.from(keepList)
|
|
128
|
+
.filter((pkg) => analysis.unused.includes(pkg))
|
|
129
|
+
.sort());
|
|
130
|
+
}
|
|
131
|
+
const unusedToRemove = analysis.unused.filter((pkg) => !keepList.has(pkg));
|
|
132
|
+
// Check for deprecated packages
|
|
133
|
+
console.log("\x1b[90m→\x1b[0m Checking for deprecated packages...");
|
|
134
|
+
let deprecated = [];
|
|
135
|
+
try {
|
|
136
|
+
deprecated = await this.registry.checkMultiple(analysis.allDeps);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
140
|
+
console.warn(`\x1b[33m⚠\x1b[0m Warning: Could not check deprecation status: ${message}`);
|
|
141
|
+
}
|
|
142
|
+
// Generate report
|
|
143
|
+
console.log("\n\x1b[36m◆\x1b[0m \x1b[1mReport\x1b[0m");
|
|
144
|
+
if (analysis.unused.length > 0) {
|
|
145
|
+
console.log(`\x1b[33m◆\x1b[0m Unused dependencies \x1b[33m(${analysis.unused.length})\x1b[0m`);
|
|
146
|
+
analysis.unused.forEach((dep) => {
|
|
147
|
+
const kept = keepList.has(dep) ? " \x1b[90m(kept)\x1b[0m" : "";
|
|
148
|
+
console.log(` \x1b[90m●\x1b[0m ${dep}${kept}`);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
console.log("\x1b[32m◆\x1b[0m No unused dependencies found");
|
|
153
|
+
}
|
|
154
|
+
if (analysis.duplicates.length > 0) {
|
|
155
|
+
console.log(`\x1b[33m◆\x1b[0m Duplicates \x1b[33m(${analysis.duplicates.length})\x1b[0m`);
|
|
156
|
+
analysis.duplicates.forEach((dep) => console.log(` \x1b[90m●\x1b[0m ${dep}`));
|
|
157
|
+
}
|
|
158
|
+
const deprecatedDeps = deprecated.filter((d) => d.deprecated);
|
|
159
|
+
if (deprecatedDeps.length > 0) {
|
|
160
|
+
console.log(`\x1b[31m◆\x1b[0m Deprecated packages \x1b[31m(${deprecatedDeps.length})\x1b[0m`);
|
|
161
|
+
deprecatedDeps.forEach((dep) => {
|
|
162
|
+
const reason = dep.reason ? ` \x1b[90m— ${dep.reason}\x1b[0m` : "";
|
|
163
|
+
console.log(` \x1b[90m●\x1b[0m ${dep.name}${reason}`);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Remove if requested
|
|
167
|
+
if (options.remove && unusedToRemove.length > 0) {
|
|
168
|
+
console.log("\n\x1b[36m◆\x1b[0m \x1b[1mRemoving\x1b[0m");
|
|
169
|
+
removeDependencies(projectRoot, unusedToRemove);
|
|
170
|
+
console.log("\x1b[32m✓\x1b[0m Removed from package.json");
|
|
171
|
+
console.log("\n Run: \x1b[1mnpm install\x1b[0m");
|
|
172
|
+
}
|
|
173
|
+
else if (!options.remove && analysis.unused.length > 0) {
|
|
174
|
+
console.log("\n\x1b[36m→\x1b[0m Run with \x1b[1m--remove\x1b[0m to clean up unused dependencies");
|
|
175
|
+
}
|
|
176
|
+
console.log();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.Cleaner = Cleaner;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const index_1 = require("./index");
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
describe("Cleaner Integration", () => {
|
|
40
|
+
const testDir = path.join(__dirname, "fixtures-cleaner-integration");
|
|
41
|
+
beforeAll(() => {
|
|
42
|
+
if (!fs.existsSync(testDir)) {
|
|
43
|
+
fs.mkdirSync(testDir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
afterAll(() => {
|
|
47
|
+
if (fs.existsSync(testDir)) {
|
|
48
|
+
fs.rmSync(testDir, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
it("should complete full clean workflow without removing", async () => {
|
|
52
|
+
// Setup test project
|
|
53
|
+
const projectDir = path.join(testDir, "test-project-1");
|
|
54
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
55
|
+
const pkg = {
|
|
56
|
+
dependencies: {
|
|
57
|
+
lodash: "^4.17.0",
|
|
58
|
+
react: "^18.0.0",
|
|
59
|
+
},
|
|
60
|
+
devDependencies: {
|
|
61
|
+
jest: "^29.0.0",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
65
|
+
// Create a source file that only imports react
|
|
66
|
+
const srcDir = path.join(projectDir, "src");
|
|
67
|
+
fs.mkdirSync(srcDir);
|
|
68
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\n");
|
|
69
|
+
// Run cleaner in dry-run mode
|
|
70
|
+
const cleaner = new index_1.Cleaner();
|
|
71
|
+
// Capture console output
|
|
72
|
+
let output = "";
|
|
73
|
+
const originalLog = console.log;
|
|
74
|
+
console.log = (...args) => {
|
|
75
|
+
output += args.join(" ") + "\n";
|
|
76
|
+
originalLog(...args);
|
|
77
|
+
};
|
|
78
|
+
try {
|
|
79
|
+
await cleaner.clean(projectDir, { remove: false });
|
|
80
|
+
// Verify output contains expected findings
|
|
81
|
+
expect(output).toContain("lodash");
|
|
82
|
+
expect(output).toContain("jest");
|
|
83
|
+
expect(output).toContain("Unused dependencies");
|
|
84
|
+
// Verify package.json was not modified
|
|
85
|
+
const updated = JSON.parse(fs.readFileSync(path.join(projectDir, "package.json"), "utf-8"));
|
|
86
|
+
expect(updated.dependencies.lodash).toBe("^4.17.0");
|
|
87
|
+
expect(updated.devDependencies.jest).toBe("^29.0.0");
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
console.log = originalLog;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
it("should detect duplicates in dependencies", async () => {
|
|
94
|
+
const projectDir = path.join(testDir, "test-project-2");
|
|
95
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
96
|
+
const pkg = {
|
|
97
|
+
dependencies: {
|
|
98
|
+
typescript: "^5.0.0",
|
|
99
|
+
react: "^18.0.0",
|
|
100
|
+
},
|
|
101
|
+
devDependencies: {
|
|
102
|
+
typescript: "^5.0.0",
|
|
103
|
+
jest: "^29.0.0",
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
107
|
+
const srcDir = path.join(projectDir, "src");
|
|
108
|
+
fs.mkdirSync(srcDir);
|
|
109
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\nimport ts from 'typescript';\n");
|
|
110
|
+
const cleaner = new index_1.Cleaner();
|
|
111
|
+
let output = "";
|
|
112
|
+
const originalLog = console.log;
|
|
113
|
+
console.log = (...args) => {
|
|
114
|
+
output += args.join(" ") + "\n";
|
|
115
|
+
originalLog(...args);
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
await cleaner.clean(projectDir, { remove: false });
|
|
119
|
+
expect(output).toContain("Duplicates");
|
|
120
|
+
expect(output).toContain("typescript");
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
console.log = originalLog;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
it("should remove unused dependencies when --remove flag is used", async () => {
|
|
127
|
+
const projectDir = path.join(testDir, "test-project-3");
|
|
128
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
129
|
+
const pkg = {
|
|
130
|
+
dependencies: {
|
|
131
|
+
lodash: "^4.17.0",
|
|
132
|
+
react: "^18.0.0",
|
|
133
|
+
},
|
|
134
|
+
devDependencies: {
|
|
135
|
+
jest: "^29.0.0",
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
139
|
+
const srcDir = path.join(projectDir, "src");
|
|
140
|
+
fs.mkdirSync(srcDir);
|
|
141
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\n");
|
|
142
|
+
const cleaner = new index_1.Cleaner();
|
|
143
|
+
let output = "";
|
|
144
|
+
const originalLog = console.log;
|
|
145
|
+
console.log = (...args) => {
|
|
146
|
+
output += args.join(" ") + "\n";
|
|
147
|
+
originalLog(...args);
|
|
148
|
+
};
|
|
149
|
+
try {
|
|
150
|
+
await cleaner.clean(projectDir, { remove: true });
|
|
151
|
+
expect(output).toContain("Removing");
|
|
152
|
+
// Verify package.json was modified
|
|
153
|
+
const updated = JSON.parse(fs.readFileSync(path.join(projectDir, "package.json"), "utf-8"));
|
|
154
|
+
expect(updated.dependencies.react).toBe("^18.0.0");
|
|
155
|
+
expect(updated.dependencies.lodash).toBeUndefined();
|
|
156
|
+
expect(updated.devDependencies.jest).toBeUndefined();
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
console.log = originalLog;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
it("should handle project with no unused dependencies", async () => {
|
|
163
|
+
const projectDir = path.join(testDir, "test-project-4");
|
|
164
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
165
|
+
const pkg = {
|
|
166
|
+
dependencies: {
|
|
167
|
+
react: "^18.0.0",
|
|
168
|
+
},
|
|
169
|
+
devDependencies: {
|
|
170
|
+
jest: "^29.0.0",
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
174
|
+
const srcDir = path.join(projectDir, "src");
|
|
175
|
+
fs.mkdirSync(srcDir);
|
|
176
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\nimport 'jest';\n");
|
|
177
|
+
const cleaner = new index_1.Cleaner();
|
|
178
|
+
let output = "";
|
|
179
|
+
const originalLog = console.log;
|
|
180
|
+
console.log = (...args) => {
|
|
181
|
+
output += args.join(" ") + "\n";
|
|
182
|
+
originalLog(...args);
|
|
183
|
+
};
|
|
184
|
+
try {
|
|
185
|
+
await cleaner.clean(projectDir, { remove: false });
|
|
186
|
+
expect(output).toContain("No unused dependencies found");
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
console.log = originalLog;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
it("should respect --keep flag to exclude packages from removal", async () => {
|
|
193
|
+
const projectDir = path.join(testDir, "test-project-5");
|
|
194
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
195
|
+
const pkg = {
|
|
196
|
+
dependencies: {
|
|
197
|
+
lodash: "^4.17.0",
|
|
198
|
+
react: "^18.0.0",
|
|
199
|
+
},
|
|
200
|
+
devDependencies: {
|
|
201
|
+
jest: "^29.0.0",
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
205
|
+
const srcDir = path.join(projectDir, "src");
|
|
206
|
+
fs.mkdirSync(srcDir);
|
|
207
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\n");
|
|
208
|
+
const cleaner = new index_1.Cleaner();
|
|
209
|
+
let output = "";
|
|
210
|
+
const originalLog = console.log;
|
|
211
|
+
console.log = (...args) => {
|
|
212
|
+
output += args.join(" ") + "\n";
|
|
213
|
+
originalLog(...args);
|
|
214
|
+
};
|
|
215
|
+
try {
|
|
216
|
+
await cleaner.clean(projectDir, {
|
|
217
|
+
remove: true,
|
|
218
|
+
keep: ["lodash"],
|
|
219
|
+
});
|
|
220
|
+
// Verify package.json was modified
|
|
221
|
+
const updated = JSON.parse(fs.readFileSync(path.join(projectDir, "package.json"), "utf-8"));
|
|
222
|
+
expect(updated.dependencies.react).toBe("^18.0.0");
|
|
223
|
+
expect(updated.dependencies.lodash).toBe("^4.17.0"); // kept
|
|
224
|
+
expect(updated.devDependencies.jest).toBeUndefined(); // removed
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
console.log = originalLog;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
it("should handle malformed package.json gracefully", async () => {
|
|
231
|
+
const projectDir = path.join(testDir, "test-project-malformed");
|
|
232
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
233
|
+
// Write invalid JSON
|
|
234
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), '{ "dependencies": { invalid json');
|
|
235
|
+
const cleaner = new index_1.Cleaner();
|
|
236
|
+
try {
|
|
237
|
+
await cleaner.clean(projectDir);
|
|
238
|
+
fail("Should have thrown an error");
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
expect(error).toBeDefined();
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
it("should load and respect config file", async () => {
|
|
245
|
+
const projectDir = path.join(testDir, "test-project-config");
|
|
246
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
247
|
+
const pkg = {
|
|
248
|
+
dependencies: {
|
|
249
|
+
lodash: "^4.17.0",
|
|
250
|
+
react: "^18.0.0",
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
254
|
+
// Create config file
|
|
255
|
+
const config = {
|
|
256
|
+
keep: ["lodash"],
|
|
257
|
+
verbose: false,
|
|
258
|
+
};
|
|
259
|
+
fs.writeFileSync(path.join(projectDir, "pkg-clean.config.json"), JSON.stringify(config));
|
|
260
|
+
const srcDir = path.join(projectDir, "src");
|
|
261
|
+
fs.mkdirSync(srcDir);
|
|
262
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\n");
|
|
263
|
+
const cleaner = new index_1.Cleaner();
|
|
264
|
+
let output = "";
|
|
265
|
+
const originalLog = console.log;
|
|
266
|
+
console.log = (...args) => {
|
|
267
|
+
output += args.join(" ") + "\n";
|
|
268
|
+
originalLog(...args);
|
|
269
|
+
};
|
|
270
|
+
try {
|
|
271
|
+
await cleaner.clean(projectDir, { remove: true });
|
|
272
|
+
// Verify config was loaded and lodash was kept
|
|
273
|
+
const updated = JSON.parse(fs.readFileSync(path.join(projectDir, "package.json"), "utf-8"));
|
|
274
|
+
expect(updated.dependencies.lodash).toBe("^4.17.0");
|
|
275
|
+
expect(updated.dependencies.react).toBe("^18.0.0");
|
|
276
|
+
}
|
|
277
|
+
finally {
|
|
278
|
+
console.log = originalLog;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
it("should warn on invalid config file", async () => {
|
|
282
|
+
const projectDir = path.join(testDir, "test-project-bad-config");
|
|
283
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
284
|
+
const pkg = {
|
|
285
|
+
dependencies: {
|
|
286
|
+
react: "^18.0.0",
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(pkg));
|
|
290
|
+
// Create invalid config
|
|
291
|
+
fs.writeFileSync(path.join(projectDir, "pkg-clean.config.json"), "{ invalid json");
|
|
292
|
+
const srcDir = path.join(projectDir, "src");
|
|
293
|
+
fs.mkdirSync(srcDir);
|
|
294
|
+
fs.writeFileSync(path.join(srcDir, "index.ts"), "import React from 'react';\n");
|
|
295
|
+
const cleaner = new index_1.Cleaner();
|
|
296
|
+
let output = "";
|
|
297
|
+
const originalLog = console.log;
|
|
298
|
+
const originalWarn = console.warn;
|
|
299
|
+
console.log = (...args) => {
|
|
300
|
+
output += args.join(" ") + "\n";
|
|
301
|
+
originalLog(...args);
|
|
302
|
+
};
|
|
303
|
+
console.warn = (...args) => {
|
|
304
|
+
output += args.join(" ") + "\n";
|
|
305
|
+
originalWarn(...args);
|
|
306
|
+
};
|
|
307
|
+
try {
|
|
308
|
+
await cleaner.clean(projectDir);
|
|
309
|
+
expect(output).toContain("Warning");
|
|
310
|
+
}
|
|
311
|
+
finally {
|
|
312
|
+
console.log = originalLog;
|
|
313
|
+
console.warn = originalWarn;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages package.json file operations for removing dependencies.
|
|
3
|
+
*/
|
|
4
|
+
export declare class PackageManager {
|
|
5
|
+
/**
|
|
6
|
+
* Removes specified packages from both dependencies and devDependencies.
|
|
7
|
+
* @param projectRoot - The root directory containing package.json
|
|
8
|
+
* @param packages - Array of package names to remove
|
|
9
|
+
* @returns True if removal was successful
|
|
10
|
+
* @throws {Error} If package.json is not found
|
|
11
|
+
*/
|
|
12
|
+
removeDependencies(projectRoot: string, packages: string[]): boolean;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=packageManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageManager.d.ts","sourceRoot":"","sources":["../src/packageManager.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,qBAAa,cAAc;IACzB;;;;;;OAMG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO;CAoBrE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PackageManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* Manages package.json file operations for removing dependencies.
|
|
41
|
+
*/
|
|
42
|
+
class PackageManager {
|
|
43
|
+
/**
|
|
44
|
+
* Removes specified packages from both dependencies and devDependencies.
|
|
45
|
+
* @param projectRoot - The root directory containing package.json
|
|
46
|
+
* @param packages - Array of package names to remove
|
|
47
|
+
* @returns True if removal was successful
|
|
48
|
+
* @throws {Error} If package.json is not found
|
|
49
|
+
*/
|
|
50
|
+
removeDependencies(projectRoot, packages) {
|
|
51
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
52
|
+
if (!fs.existsSync(pkgPath)) {
|
|
53
|
+
throw new Error("package.json not found");
|
|
54
|
+
}
|
|
55
|
+
const content = fs.readFileSync(pkgPath, "utf-8");
|
|
56
|
+
const pkg = JSON.parse(content);
|
|
57
|
+
for (const packageName of packages) {
|
|
58
|
+
delete pkg.dependencies?.[packageName];
|
|
59
|
+
delete pkg.devDependencies?.[packageName];
|
|
60
|
+
}
|
|
61
|
+
// Pretty print with 2 spaces
|
|
62
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.PackageManager = PackageManager;
|
|
67
|
+
//# sourceMappingURL=packageManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageManager.js","sourceRoot":"","sources":["../src/packageManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAE7B;;GAEG;AACH,MAAa,cAAc;IACzB;;;;;;OAMG;IACH,kBAAkB,CAAC,WAAmB,EAAE,QAAkB;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QAEvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEhC,KAAK,MAAM,WAAW,IAAI,QAAQ,EAAE,CAAC;YACnC,OAAO,GAAG,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,CAAC;YACvC,OAAO,GAAG,CAAC,eAAe,EAAE,CAAC,WAAW,CAAC,CAAC;QAC5C,CAAC;QAED,6BAA6B;QAC7B,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAE/D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA5BD,wCA4BC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type PackageManagerType = "npm" | "yarn" | "pnpm";
|
|
2
|
+
export interface IPackageManager {
|
|
3
|
+
/** Get the type of package manager */
|
|
4
|
+
getType(): PackageManagerType;
|
|
5
|
+
/** Remove dependencies from package.json */
|
|
6
|
+
removeDependencies(projectRoot: string, packages: string[]): boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface PackageJson {
|
|
9
|
+
dependencies?: Record<string, string>;
|
|
10
|
+
devDependencies?: Record<string, string>;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Factory for creating package manager instances.
|
|
15
|
+
* Detects the package manager type based on lock files in the project.
|
|
16
|
+
*/
|
|
17
|
+
export declare class PackageManagerFactory {
|
|
18
|
+
/**
|
|
19
|
+
* Detects the package manager type by looking for lock files.
|
|
20
|
+
* @param projectRoot - The project root directory
|
|
21
|
+
* @returns The detected package manager type, defaults to 'npm'
|
|
22
|
+
*/
|
|
23
|
+
static detect(projectRoot: string): PackageManagerType;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a package manager instance.
|
|
26
|
+
* @param type - The type of package manager to create
|
|
27
|
+
* @returns An instance of the specified package manager
|
|
28
|
+
*/
|
|
29
|
+
static create(type?: PackageManagerType): IPackageManager;
|
|
30
|
+
/**
|
|
31
|
+
* Creates and detects the appropriate package manager for a project.
|
|
32
|
+
* @param projectRoot - The project root directory
|
|
33
|
+
* @returns An instance of the detected package manager
|
|
34
|
+
*/
|
|
35
|
+
static createForProject(projectRoot: string): IPackageManager;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=packageManagerFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageManagerFactory.d.ts","sourceRoot":"","sources":["../src/packageManagerFactory.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,OAAO,IAAI,kBAAkB,CAAC;IAC9B,4CAA4C;IAC5C,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;CACtE;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAsFD;;;GAGG;AACH,qBAAa,qBAAqB;IAChC;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB;IAoBtD;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,GAAE,kBAA0B,GAAG,eAAe;IAYhE;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAI9D"}
|