UNPKG

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
/** * 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`; }