@stacker/remove-unused-deps
Version:
A CLI tool to remove unused dependencies from your project
191 lines (168 loc) ⢠5.83 kB
JavaScript
const { execSync } = require('child_process');
const depcheck = require('depcheck');
const fs = require('fs');
const path = require('path');
const inquirer = require('inquirer');
const ora = require('ora');
const chalk = require('chalk');
// Get the current working directory where the command is executed
const projectDir = process.cwd();
function getPackageManager() {
if (fs.existsSync(path.join(projectDir, 'pnpm-lock.yaml'))) {
return 'pnpm';
}
if (fs.existsSync(path.join(projectDir, 'yarn.lock'))) {
return 'yarn';
}
return 'npm';
}
function removePackage(dep) {
const packageManager = getPackageManager();
const commands = {
pnpm: `pnpm remove ${dep}`,
yarn: `yarn remove ${dep}`,
npm: `npm uninstall ${dep}`
};
const command = commands[packageManager];
return execSync(command, { stdio: 'inherit' });
}
function installPackage(dep) {
const packageManager = getPackageManager();
const commands = {
pnpm: `pnpm add ${dep}`,
yarn: `yarn add ${dep}`,
npm: `npm install ${dep}`
};
const command = commands[packageManager];
return execSync(command, { stdio: 'inherit' });
}
async function handleDependencies() {
try {
const spinner = ora({
text: 'Scanning dependencies...',
color: 'yellow'
}).start();
const unused = await depcheck(projectDir, {});
const { dependencies, devDependencies, missing } = unused;
const missingDeps = Object.keys(missing);
spinner.stop();
if (dependencies.length === 0 && devDependencies.length === 0 && missingDeps.length === 0) {
console.log(chalk.green('ā All dependencies are properly configured'));
return;
}
// Print summary
console.log(chalk.bold('\nš¦ Dependencies Status'));
if (dependencies.length > 0 || devDependencies.length > 0) {
console.log(
chalk.yellow('ā ļø Unused Dependencies: ') +
chalk.red(`${dependencies.length} unused`)
);
console.log(
chalk.yellow('ā ļø Unused DevDependencies: ') +
chalk.red(`${devDependencies.length} unused`)
);
}
if (missingDeps.length > 0) {
console.log(
chalk.yellow('ā ļø Missing Dependencies: ') +
chalk.red(`${missingDeps.length} missing`)
);
}
console.log();
// Create choices for both unused and missing dependencies
const choices = [
...(dependencies.length > 0 ? [
new inquirer.Separator(chalk.bold.blue('āāā Unused Dependencies āāā')),
...dependencies.map(dep => ({
name: `${chalk.yellow(dep)} ${chalk.gray('(remove)')}`,
value: { name: dep, action: 'remove' },
type: 'dependencies'
}))
] : []),
...(devDependencies.length > 0 ? [
new inquirer.Separator(chalk.bold.magenta('āāā Unused DevDependencies āāā')),
...devDependencies.map(dep => ({
name: `${chalk.yellow(dep)} ${chalk.gray('(remove)')}`,
value: { name: dep, action: 'remove' },
type: 'devDependencies'
}))
] : []),
...(missingDeps.length > 0 ? [
new inquirer.Separator(chalk.bold.green('āāā Missing Dependencies āāā')),
...missingDeps.map(dep => ({
name: `${chalk.yellow(dep)} ${chalk.gray('(install)')}`,
value: { name: dep, action: 'install' },
type: 'missing'
}))
] : [])
];
const { selectedDeps } = await inquirer.prompt([
{
type: 'checkbox',
name: 'selectedDeps',
message: chalk.cyan('Select dependencies to manage:'),
choices,
pageSize: 10,
loop: false
}
]);
if (selectedDeps.length === 0) {
console.log(chalk.yellow('\nā ļø No dependencies selected. Operation cancelled.'));
return;
}
// Group selected dependencies by action
const toRemove = selectedDeps.filter(dep => dep.action === 'remove').map(dep => dep.name);
const toInstall = selectedDeps.filter(dep => dep.action === 'install').map(dep => dep.name);
// Show summary of actions
if (toRemove.length > 0) {
console.log(chalk.yellow('\nPackages to remove:'));
console.log(chalk.red(toRemove.join(', ')));
}
if (toInstall.length > 0) {
console.log(chalk.yellow('\nPackages to install:'));
console.log(chalk.green(toInstall.join(', ')));
}
const { confirm } = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: chalk.yellow('ā ļø Are you sure you want to proceed with these changes?'),
default: false
}
]);
if (!confirm) {
console.log(chalk.yellow('\nā ļø Operation cancelled'));
return;
}
// Execute removal
for (const dep of toRemove) {
try {
const removalSpinner = ora({
text: `Removing ${chalk.cyan(dep)}...`,
color: 'yellow'
}).start();
removePackage(dep);
removalSpinner.succeed(`Removed ${chalk.cyan(dep)}`);
} catch (error) {
console.error(chalk.red(`\nā Error while removing ${dep}:`), error);
}
}
// Execute installation
for (const dep of toInstall) {
try {
const installSpinner = ora({
text: `Installing ${chalk.cyan(dep)}...`,
color: 'yellow'
}).start();
installPackage(dep);
installSpinner.succeed(`Installed ${chalk.cyan(dep)}`);
} catch (error) {
console.error(chalk.red(`\nā Error while installing ${dep}:`), error);
}
}
console.log(chalk.green('\n⨠All selected operations completed successfully!'));
} catch (error) {
console.error(chalk.red('\nā Error while checking dependencies:'), error);
}
}
handleDependencies();