accs-cli
Version:
ACCS CLI — Full-featured developer tool for scaffolding, running, building, and managing multi-language projects
169 lines (145 loc) • 4.67 kB
JavaScript
/**
* Clean command - Remove build artifacts
*/
import path from 'path';
import chalk from 'chalk';
import inquirer from 'inquirer';
import { logger } from '../utils/logger.js';
import { FileUtils } from '../utils/file-utils.js';
import { configManager } from '../config/config-manager.js';
export function cleanCommand(program) {
program
.command('clean')
.option('-f, --force', 'Force clean without confirmation')
.option('-a, --all', 'Clean all generated directories')
.option('-v, --verbose', 'Verbose output')
.description('Clean build artifacts and temporary files')
.action(async (options) => {
try {
await cleanProject(options);
} catch (error) {
logger.error('Clean failed:', error.message);
process.exit(1);
}
});
}
async function cleanProject(options) {
const projectRoot = FileUtils.getProjectRoot();
const buildDir = configManager.get('buildDir', 'dist');
// Define directories to clean
const cleanTargets = [
{
path: path.join(projectRoot, buildDir),
name: buildDir,
description: 'Build output directory'
}
];
if (options.all) {
cleanTargets.push(
{
path: path.join(projectRoot, 'node_modules'),
name: 'node_modules',
description: 'Node.js dependencies'
},
{
path: path.join(projectRoot, '.cache'),
name: '.cache',
description: 'Cache directory'
},
{
path: path.join(projectRoot, 'coverage'),
name: 'coverage',
description: 'Test coverage reports'
},
{
path: path.join(projectRoot, '.nyc_output'),
name: '.nyc_output',
description: 'NYC coverage data'
}
);
}
// Filter existing directories
const existingTargets = cleanTargets.filter(target => FileUtils.exists(target.path));
if (existingTargets.length === 0) {
logger.info('Nothing to clean - all directories are already clean');
return;
}
// Show what will be cleaned
logger.info('The following directories will be cleaned:');
existingTargets.forEach(target => {
const size = getDirectorySize(target.path);
logger.info(` ${chalk.yellow(target.name)} - ${target.description} ${chalk.gray(`(${size})`)}`);
});
// Confirm deletion unless forced
if (!options.force) {
logger.separator();
const { confirm } = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: `Are you sure you want to delete ${existingTargets.length} director${existingTargets.length === 1 ? 'y' : 'ies'}?`,
default: false
}
]);
if (!confirm) {
logger.info('Clean operation cancelled');
return;
}
}
// Perform cleanup
logger.separator();
let totalCleaned = 0;
for (const target of existingTargets) {
try {
logger.startSpinner(`Cleaning ${target.name}...`);
await FileUtils.remove(target.path);
logger.succeedSpinner(`Cleaned ${target.name}`);
totalCleaned++;
if (options.verbose) {
logger.debug(`Removed: ${target.path}`, true);
}
} catch (error) {
logger.error(`Failed to clean ${target.name}: ${error.message}`);
}
}
logger.separator();
logger.success(`Cleaned ${totalCleaned} director${totalCleaned === 1 ? 'y' : 'ies'} successfully`);
// Show space freed (rough estimate)
const spaceFreed = existingTargets.reduce((total, target) => {
return total + (FileUtils.exists(target.path) ? 0 : 1); // Simple estimate
}, 0);
if (spaceFreed > 0) {
logger.info(`Space freed: ${chalk.green('~' + estimateSpaceFreed(existingTargets))}`);
}
}
function getDirectorySize(dirPath) {
try {
if (!FileUtils.exists(dirPath)) return '0 B';
// This is a simplified size estimation
// In a real implementation, you'd recursively calculate actual size
if (dirPath.includes('node_modules')) return '~50-200 MB';
if (dirPath.includes('dist') || dirPath.includes('build')) return '~1-10 MB';
if (dirPath.includes('coverage')) return '~1-5 MB';
if (dirPath.includes('.cache')) return '~1-50 MB';
return '~1 MB';
} catch {
return 'Unknown';
}
}
function estimateSpaceFreed(targets) {
const estimates = {
'node_modules': 100, // MB
'dist': 5,
'build': 5,
'coverage': 2,
'.cache': 10,
'.nyc_output': 1
};
let totalMB = 0;
targets.forEach(target => {
totalMB += estimates[target.name] || 1;
});
if (totalMB < 1) return '< 1 MB';
if (totalMB > 1000) return `~${Math.round(totalMB / 1000)} GB`;
return `~${Math.round(totalMB)} MB`;
}