UNPKG

smart-renamer

Version:

šŸš€ Intelligent file and code naming suggestions based on project-specific naming conventions. Interactive CLI tool with AST-based code analysis for variables, functions, components, and more.

643 lines • 30.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createProgram = createProgram; const commander_1 = require("commander"); const config_manager_1 = require("../config/config-manager"); const naming_validator_1 = require("../core/naming-validator"); const suggestion_engine_1 = require("../core/suggestion-engine"); const file_watcher_1 = require("../core/file-watcher"); const ast_analyzer_1 = require("../core/ast-analyzer"); const code_validator_1 = require("../core/code-validator"); const inquirer_1 = __importDefault(require("inquirer")); const fs_1 = require("fs"); const path_1 = require("path"); function createProgram() { const program = new commander_1.Command(); program .name('renamer') .description('Intelligent file naming suggestions based on project conventions') .version('1.2.0'); program .command('init') .description('Initialize naming convention for the current project') .action(initCommand); program .command('set-convention <convention>') .description('Set the naming convention for the project') .action(setConventionCommand); program .command('watch') .description('Monitor for new files and suggest names') .option('-p, --patterns <patterns>', 'File patterns to watch (comma-separated)', '**/*') .action(watchCommand); program .command('validate') .description('Validate existing file names against the project convention') .option('-f, --fix', 'Show suggested fixes for invalid names') .action(validateCommand); program .command('suggest <filename>') .description('Get naming suggestions for a specific file') .action(suggestCommand); program .command('analyze') .description('Analyze project structure and naming patterns (files + code)') .option('--patterns <patterns>', 'Code file patterns to analyze (comma-separated)', '**/*.ts,**/*.tsx,**/*.js,**/*.jsx') .option('--files-only', 'Analyze only file naming patterns') .option('--code-only', 'Analyze only code naming patterns') .action(analyzeCommand); program .command('rename') .description('Rename files to follow the project naming convention') .option('-d, --dry-run', 'Show what would be renamed without actually renaming') .option('-f, --force', 'Rename all files without individual prompts') .option('-i, --interactive', 'Ask yes/no for each file individually (default)') .option('--keep <files>', 'Comma-separated list of files to keep unchanged') .action(renameCommand); program .command('validate-code') .description('Validate code naming conventions (variables, functions, components, etc.)') .option('-f, --fix', 'Show suggested fixes for naming violations') .option('--patterns <patterns>', 'File patterns to analyze (comma-separated)', '**/*.ts,**/*.tsx,**/*.js,**/*.jsx') .action(validateCodeCommand); program .command('analyze-code') .description('Analyze code structure and naming patterns') .option('--patterns <patterns>', 'File patterns to analyze (comma-separated)', '**/*.ts,**/*.tsx,**/*.js,**/*.jsx') .action(analyzeCodeCommand); program .command('fix-code') .description('Interactive code renaming to follow naming conventions') .option('-d, --dry-run', 'Show what would be changed without making changes') .option('--patterns <patterns>', 'File patterns to analyze (comma-separated)', '**/*.ts,**/*.tsx,**/*.js,**/*.jsx') .action(fixCodeCommand); return program; } async function initCommand() { console.log('šŸš€ Initializing Renamer for your project...\n'); const configManager = new config_manager_1.ConfigManager(); if (configManager.configExists()) { const { overwrite } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'overwrite', message: 'naming.config already exists. Do you want to overwrite it?', default: false }]); if (!overwrite) { console.log('āœ… Keeping existing configuration.'); return; } } const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); const detectedConvention = suggestionEngine.detectProjectConvention(); const questions = [ { type: 'list', name: 'convention', message: 'Choose your preferred file naming convention:', choices: [ 'camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE' ], default: detectedConvention || 'camelCase' }, { type: 'input', name: 'files', message: 'File patterns to apply convention to:', default: '*.ts,*.js' }, { type: 'list', name: 'folders', message: 'Folder naming convention:', choices: [ 'camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE' ], default: 'kebab-case' }, { type: 'input', name: 'exceptions', message: 'Files to exclude from convention (comma-separated):', default: 'index,main,app' }, { type: 'confirm', name: 'setupCodeConventions', message: 'Do you want to set up code-level naming conventions (variables, functions, etc.)?', default: true } ]; const answers = await inquirer_1.default.prompt(questions); const config = { convention: answers.convention, files: answers.files.split(',').map((s) => s.trim()), folders: answers.folders, exceptions: answers.exceptions.split(',').map((s) => s.trim()).filter(Boolean) }; if (answers.setupCodeConventions) { const codeQuestions = [ { type: 'list', name: 'variables', message: 'Variable naming convention:', choices: ['camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE'], default: 'camelCase' }, { type: 'list', name: 'functions', message: 'Function naming convention:', choices: ['camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE'], default: 'camelCase' }, { type: 'list', name: 'components', message: 'React Component naming convention:', choices: ['camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE'], default: 'PascalCase' }, { type: 'list', name: 'constants', message: 'Constant naming convention:', choices: ['camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE'], default: 'UPPER_SNAKE_CASE' }, { type: 'list', name: 'classes', message: 'Class naming convention:', choices: ['camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE'], default: 'PascalCase' } ]; const codeAnswers = await inquirer_1.default.prompt(codeQuestions); config.code = { variables: codeAnswers.variables, functions: codeAnswers.functions, components: codeAnswers.components, constants: codeAnswers.constants, classes: codeAnswers.classes, interfaces: 'PascalCase', types: 'PascalCase', enums: 'PascalCase' }; } configManager.saveConfig(config); console.log('\nāœ… Configuration saved to naming.config'); console.log(`šŸ“ File convention: ${config.convention}`); console.log(`šŸ“ Folder convention: ${config.folders}`); if (config.code) { console.log(`šŸ”§ Code conventions:`); console.log(` Variables: ${config.code.variables}`); console.log(` Functions: ${config.code.functions}`); console.log(` Components: ${config.code.components}`); console.log(` Constants: ${config.code.constants}`); console.log(` Classes: ${config.code.classes}`); } if (detectedConvention && detectedConvention !== config.convention) { console.log(`\nšŸ’” Note: Detected '${detectedConvention}' in existing files, but you chose '${config.convention}'`); } if (config.code) { console.log(`\nšŸš€ Try these commands:`); console.log(` renamer validate-code # Check your code conventions`); console.log(` renamer analyze-code # Analyze code patterns`); } } async function setConventionCommand(convention) { const validConventions = ['camelCase', 'snake_case', 'kebab-case', 'PascalCase', 'UPPER_SNAKE_CASE']; if (!validConventions.includes(convention)) { console.error(`āŒ Invalid convention '${convention}'. Valid options: ${validConventions.join(', ')}`); process.exit(1); } const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); config.convention = convention; configManager.saveConfig(config); console.log(`āœ… Convention set to '${convention}'`); } async function watchCommand(options) { const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); const patterns = options.patterns.split(',').map(p => p.trim()); const watcher = new file_watcher_1.FileWatcher(process.cwd(), patterns); console.log(`šŸ‘€ Watching for new files with convention: ${config.convention}`); console.log(`šŸ“‚ Patterns: ${patterns.join(', ')}\n`); watcher.on('fileAdded', (fileInfo) => { const suggestion = suggestionEngine.suggestName(fileInfo.name, config.convention, config.exceptions); if (suggestion.original !== suggestion.suggested) { console.log(`\nšŸ“ New file detected: ${fileInfo.name}`); console.log(`šŸ’” Suggested name: ${suggestion.suggested}`); console.log(`šŸŽÆ Convention: ${suggestion.convention}`); console.log(`šŸ“Š Confidence: ${(suggestion.confidence * 100).toFixed(1)}%`); } }); watcher.on('error', (error) => { console.error('āŒ File watcher error:', error); }); watcher.start(); process.on('SIGINT', () => { console.log('\nšŸ›‘ Stopping file watcher...'); watcher.stop(); process.exit(0); }); } async function validateCommand(options) { const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); console.log(`šŸ” Validating files against '${config.convention}' convention...\n`); const files = suggestionEngine['getAllProjectFiles'](); const invalidFiles = []; for (const file of files) { if (file.isDirectory) continue; const validation = naming_validator_1.NamingValidator.validateName(file.name, config.convention, config.exceptions); if (!validation.isValid && validation.expectedName) { invalidFiles.push({ name: file.name, suggested: validation.expectedName, path: file.path }); console.log(`āŒ ${file.name}`); console.log(` šŸ’” Should be: ${validation.expectedName}`); console.log(` šŸ“ Path: ${file.path}\n`); } } if (invalidFiles.length === 0) { console.log('āœ… All files follow the naming convention!'); } else { console.log(`\nšŸ“Š Found ${invalidFiles.length} files that don't follow the convention.`); if (options.fix) { console.log('\nšŸ”§ Suggested fixes:'); for (const file of invalidFiles) { console.log(`mv "${file.name}" "${file.suggested}"`); } } } } async function suggestCommand(filename) { const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); console.log(`šŸ’­ Generating suggestions for: ${filename}\n`); const suggestions = suggestionEngine.suggestMultipleNames(filename, config.convention, config.exceptions); for (const suggestion of suggestions) { const icon = suggestion.convention === config.convention ? '⭐' : ' '; console.log(`${icon} ${suggestion.convention.padEnd(20)} ${suggestion.suggested.padEnd(30)} (${(suggestion.confidence * 100).toFixed(1)}%)`); } } async function analyzeCommand(options) { const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); console.log('šŸ“Š Project Analysis\n'); // Analyze file naming patterns (unless code-only) if (!options.codeOnly) { console.log('šŸ“ File Naming Analysis'); console.log('═'.repeat(40)); const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); const analysis = suggestionEngine.analyzeProjectStructure(); console.log(`šŸ“ Total files: ${analysis.totalFiles}`); console.log(`šŸŽÆ Most common convention: ${analysis.mostCommon || 'None detected'}`); console.log(`šŸ“ˆ File consistency: ${(analysis.consistency * 100).toFixed(1)}%\n`); console.log('šŸ“‹ File convention breakdown:'); for (const [convention, count] of Object.entries(analysis.conventions)) { const percentage = analysis.totalFiles > 0 ? (count / analysis.totalFiles * 100).toFixed(1) : '0.0'; console.log(` ${convention.padEnd(20)} ${count.toString().padStart(3)} files (${percentage}%)`); } console.log(''); } // Analyze code naming patterns (unless files-only) if (!options.filesOnly) { if (!config.code) { console.log('āš ļø No code conventions configured. Run `renamer init` to set up code conventions.'); return; } console.log('šŸ’» Code Naming Analysis'); console.log('═'.repeat(40)); const analyzer = new ast_analyzer_1.ASTAnalyzer(); const validator = new code_validator_1.CodeValidator(); const patterns = options.patterns ? options.patterns.split(',').map(p => p.trim()) : ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx']; const analysis = analyzer.analyzeProject(process.cwd(), patterns); const validationResult = validator.validateIdentifiers(analysis.identifiers, config.code); console.log(`šŸ’» Total identifiers: ${analysis.totalIdentifiers}`); console.log(`šŸ“ˆ Code consistency: ${(analysis.consistencyScore * 100).toFixed(1)}%`); console.log(`šŸŽÆ Violations found: ${validationResult.totalViolations}\n`); // Show breakdown by category const categories = ['variables', 'functions', 'classes', 'constants']; console.log('šŸ“‹ Code convention breakdown:'); for (const category of categories) { const conventions = analysis.conventions[category]; const total = Object.values(conventions).reduce((a, b) => a + b, 0); if (total > 0) { console.log(`\n ${category.charAt(0).toUpperCase() + category.slice(1)} (${total} total):`); for (const [convention, count] of Object.entries(conventions)) { const percentage = (count / total * 100).toFixed(1); const icon = convention === config.code[category] ? 'āœ…' : ' '; console.log(` ${icon} ${convention.padEnd(20)} ${count.toString().padStart(3)} (${percentage}%)`); } } } console.log(''); // Show violations summary if any if (validationResult.totalViolations > 0) { console.log('āŒ Top Violations:'); for (const [type, count] of Object.entries(validationResult.violationsByType)) { console.log(` ${type}: ${count} violations`); } console.log(''); } } // Overall recommendations console.log('šŸŽÆ Recommendations'); console.log('═'.repeat(40)); if (!options.codeOnly) { const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); const fileAnalysis = suggestionEngine.analyzeProjectStructure(); if (fileAnalysis.consistency < 0.8) { console.log('šŸ“ File naming could be improved:'); console.log(' • Run `renamer validate --fix` to see file suggestions'); console.log(' • Run `renamer rename --dry-run` to preview changes'); } else { console.log('āœ… File naming is consistent!'); } } if (!options.filesOnly && config.code) { const analyzer = new ast_analyzer_1.ASTAnalyzer(); const patterns = options.patterns ? options.patterns.split(',').map(p => p.trim()) : ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx']; const codeAnalysis = analyzer.analyzeProject(process.cwd(), patterns); const validator = new code_validator_1.CodeValidator(); const validationResult = validator.validateIdentifiers(codeAnalysis.identifiers, config.code); if (validationResult.totalViolations > 0) { console.log('šŸ’» Code naming could be improved:'); console.log(' • Run `renamer validate-code --fix` to see code suggestions'); console.log(' • Consider updating your naming conventions with `renamer init`'); } else { console.log('āœ… Code naming follows conventions!'); } } console.log('\nšŸ’” Tip: Run `renamer init` to update your naming conventions'); } async function renameCommand(options) { const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); const suggestionEngine = new suggestion_engine_1.SuggestionEngine(); // Parse keep list const keepFiles = options.keep ? options.keep.split(',').map(f => f.trim()) : []; // Default exclusions - system files, config files, and common files const defaultExclusions = [ 'package.json', 'tsconfig.json', 'bun.lockb', 'naming.config', 'package-lock.json', 'yarn.lock', '.gitignore', 'LICENSE', // Config files '.eslintrc.js', '.eslintrc.json', '.prettierrc', '.prettierrc.json', 'babel.config.js', 'webpack.config.js', 'vite.config.js', 'rollup.config.js', 'jest.config.js', 'vitest.config.js', '.env.example', 'Dockerfile', 'docker-compose.yml', 'docker-compose.yaml' ]; // File extensions to exclude by default const excludedExtensions = [ // Image files '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp', '.ico', '.tiff', // Markdown files '.md', '.markdown', // Declaration files (all languages) '.d.ts', '.d.mts', '.d.cts', // TypeScript declarations '.h', '.hpp', '.hxx', // C/C++ headers '.hi', // Haskell interface files '.pyi', // Python stub files '.rbi', // Ruby interface files '.rei', // ReasonML interface files '.mli', // OCaml interface files '.sig', // Standard ML signature files '.fsi', // F# signature files '.spec', // RPM spec files '.def', // Definition files (various languages) // Config file extensions '.config.js', '.config.ts', '.config.json', '.yml', '.yaml', '.toml', '.ini' ]; console.log(`šŸ”„ Finding files to rename to '${config.convention}' convention...\n`); const files = suggestionEngine['getAllProjectFiles'](); const filesToRename = []; for (const file of files) { if (file.isDirectory) continue; // Skip files that should be ignored if (file.name.startsWith('.') && file.name !== '.gitignore') continue; if (defaultExclusions.includes(file.name)) continue; if (keepFiles.includes(file.name)) continue; // Check if file extension should be excluded const fileExtension = file.extension.toLowerCase(); const hasExcludedExtension = excludedExtensions.some(ext => file.name.toLowerCase().endsWith(ext.toLowerCase())); if (hasExcludedExtension) { const fileType = fileExtension.match(/\.(jpg|jpeg|png|gif|bmp|svg|webp|ico|tiff)$/i) ? 'image' : fileExtension.match(/\.(md|markdown)$/i) ? 'markdown' : file.name.match(/\.d\.(ts|mts|cts)$/i) ? 'TypeScript declaration' : fileExtension.match(/\.(h|hpp|hxx)$/i) ? 'C/C++ header' : fileExtension.match(/\.(hi|pyi|rbi|rei|mli|sig|fsi|spec|def)$/i) ? 'declaration' : 'config'; console.log(`šŸ“„ Skipping ${file.name} (${fileType} files excluded by default)`); continue; } // Skip files containing 'config' in the filename if (file.name.toLowerCase().includes('config')) { console.log(`šŸ“„ Skipping ${file.name} (config files excluded by default)`); continue; } const validation = naming_validator_1.NamingValidator.validateName(file.name, config.convention, config.exceptions); if (!validation.isValid && validation.expectedName) { const newPath = (0, path_1.join)((0, path_1.dirname)(file.path), validation.expectedName); filesToRename.push({ oldPath: file.path, newPath, oldName: file.name, newName: validation.expectedName }); } } if (filesToRename.length === 0) { console.log('āœ… All files already follow the naming convention!'); return; } if (options.dryRun) { console.log(`šŸ“ Would rename ${filesToRename.length} files:\n`); for (const file of filesToRename) { console.log(` ${file.oldName} → ${file.newName}`); } console.log('\nšŸ” Dry run complete. No files were actually renamed.'); return; } // Interactive mode (default) - ask for each file individually if (!options.force) { console.log(`šŸ“ Found ${filesToRename.length} files that can be renamed:\n`); let successCount = 0; let errorCount = 0; let skippedCount = 0; for (const file of filesToRename) { const { shouldRename } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'shouldRename', message: `Rename "${file.oldName}" to "${file.newName}"?`, default: true }]); if (shouldRename) { try { (0, fs_1.renameSync)(file.oldPath, file.newPath); console.log(`āœ… ${file.oldName} → ${file.newName}`); successCount++; } catch (error) { console.log(`āŒ Failed to rename ${file.oldName}: ${error}`); errorCount++; } } else { console.log(`ā­ļø Skipped ${file.oldName}`); skippedCount++; } console.log(''); // Empty line for readability } console.log(`šŸ“Š Completed: ${successCount} renamed, ${skippedCount} skipped, ${errorCount} failed`); return; } // Force mode - rename all without asking console.log(`šŸ”„ Renaming ${filesToRename.length} files...\n`); let successCount = 0; let errorCount = 0; for (const file of filesToRename) { try { (0, fs_1.renameSync)(file.oldPath, file.newPath); console.log(`āœ… ${file.oldName} → ${file.newName}`); successCount++; } catch (error) { console.log(`āŒ Failed to rename ${file.oldName}: ${error}`); errorCount++; } } console.log(`\nšŸ“Š Completed: ${successCount} renamed, ${errorCount} failed`); } async function validateCodeCommand(options) { const configManager = new config_manager_1.ConfigManager(); const config = configManager.loadConfig(); if (!config.code) { console.log('āš ļø No code conventions configured. Run `renamer init` to set up code conventions.'); return; } const analyzer = new ast_analyzer_1.ASTAnalyzer(); const validator = new code_validator_1.CodeValidator(); const patterns = options.patterns ? options.patterns.split(',').map(p => p.trim()) : ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx']; console.log(`šŸ” Validating code conventions...\n`); console.log(`šŸ“ Variables: ${config.code.variables}`); console.log(`šŸ”§ Functions: ${config.code.functions}`); console.log(`āš›ļø Components: ${config.code.components}`); console.log(`šŸ“Š Constants: ${config.code.constants}`); console.log(`šŸ›ļø Classes: ${config.code.classes}\n`); const analysis = analyzer.analyzeProject(process.cwd(), patterns); const validationResult = validator.validateIdentifiers(analysis.identifiers, config.code); if (validationResult.totalViolations === 0) { console.log('āœ… All code follows the naming conventions!'); console.log(`šŸ“Š Analyzed ${validationResult.totalChecked} identifiers across ${analysis.identifiers.length > 0 ? 'multiple files' : 'no files'}`); return; } console.log(`āŒ Found ${validationResult.totalViolations} naming violations:\n`); // Group violations by file const violationsByFile = {}; for (const violation of validationResult.violations) { const filePath = violation.identifier.filePath; if (!violationsByFile[filePath]) { violationsByFile[filePath] = []; } violationsByFile[filePath].push(violation); } // Display violations by file for (const [filePath, violations] of Object.entries(violationsByFile)) { console.log(`šŸ“ ${filePath}:`); for (const violation of violations) { const line = violation.identifier.line; const type = violation.identifier.isReactComponent ? 'React Component' : violation.identifier.type; console.log(` Line ${line}: ${type} "${violation.identifier.name}" should be "${violation.suggestedName}"`); if (options.fix) { const suggestions = validator.suggestFixes(violation.identifier, config.code); if (suggestions.length > 0) { console.log(` šŸ’” Alternatives: ${suggestions.join(', ')}`); } } } console.log(''); } // Summary console.log('šŸ“‹ Violation Summary:'); for (const [type, count] of Object.entries(validationResult.violationsByType)) { console.log(` ${type}: ${count} violations`); } console.log(`\nšŸ“Š Total: ${validationResult.totalViolations} violations in ${Object.keys(violationsByFile).length} files`); if (!options.fix) { console.log('\nšŸ’” Use --fix to see suggested alternatives'); } } async function analyzeCodeCommand(options) { const analyzer = new ast_analyzer_1.ASTAnalyzer(); const patterns = options.patterns ? options.patterns.split(',').map(p => p.trim()) : ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx']; console.log('šŸ“Š Analyzing code structure and naming patterns...\n'); const analysis = analyzer.analyzeProject(process.cwd(), patterns); console.log(`šŸ“ Total identifiers: ${analysis.totalIdentifiers}`); console.log(`šŸ“ˆ Consistency score: ${(analysis.consistencyScore * 100).toFixed(1)}%\n`); // Show breakdown by category const categories = ['variables', 'functions', 'classes', 'constants']; for (const category of categories) { const conventions = analysis.conventions[category]; const total = Object.values(conventions).reduce((a, b) => a + b, 0); if (total > 0) { console.log(`šŸ“‹ ${category.charAt(0).toUpperCase() + category.slice(1)} (${total} total):`); for (const [convention, count] of Object.entries(conventions)) { const percentage = (count / total * 100).toFixed(1); console.log(` ${convention.padEnd(20)} ${count.toString().padStart(3)} (${percentage}%)`); } console.log(''); } } // Recommendations if (analysis.consistencyScore < 0.8) { console.log('šŸ’” Recommendations:'); console.log(' - Consider standardizing naming conventions across the project'); console.log(' - Use `renamer validate-code --fix` to see specific suggestions'); console.log(' - Run `renamer fix-code` for interactive refactoring'); } else { console.log('āœ… Good consistency! Your code follows consistent naming patterns.'); } } async function fixCodeCommand(_options) { console.log('🚧 Code transformation feature coming soon!'); console.log(''); console.log('For now, you can:'); console.log('1. Use `renamer validate-code --fix` to see suggested changes'); console.log('2. Manually apply the suggestions in your IDE'); console.log('3. Set up ESLint rules for automated enforcement'); console.log(''); console.log('Interactive code refactoring will be available in a future update.'); } //# sourceMappingURL=commands.js.map