UNPKG

intent-cli

Version:

A fully functional CLI built with TypeScript and modern tools

551 lines • 20.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fileCommand = void 0; const commander_1 = require("commander"); const chalk_1 = __importDefault(require("chalk")); const inquirer_1 = __importDefault(require("inquirer")); const spinner_1 = require("../utils/spinner"); const logger_1 = require("../utils/logger"); const promises_1 = require("fs/promises"); const path_1 = require("path"); exports.fileCommand = new commander_1.Command('file') .description('File management utilities') .option('-a, --action <action>', 'Action to perform (create, read, list, search, copy, move, delete, organize)') .option('-p, --path <path>', 'File or directory path') .option('-c, --content <content>', 'Content for file creation') .option('--pattern <pattern>', 'Search pattern for files') .option('-d, --destination <destination>', 'Destination path for copy/move') .option('-i, --interactive', 'Interactive mode', false) .option('-r, --recursive', 'Recursive for directory operations', false) .action(async (options) => { try { const result = await executeFileCommand(options); handleResult(result); } catch (error) { handleError(error); } }); async function executeFileCommand(options) { logger_1.logger.debug('Executing file command with options:', options); if (options.interactive || !options.action) { return await interactiveFileMode(); } switch (options.action) { case 'create': return await createFile(options.path, options.content); case 'read': return await readFileContent(options.path); case 'list': return await listDirectory(options.path, options.recursive); case 'search': return await searchFiles(options.path, options.pattern, options.recursive); case 'copy': return await copyFileOrDirectory(options.path, options.destination); case 'move': return await moveFileOrDirectory(options.path, options.destination); case 'delete': return await deleteFileOrDirectory(options.path); case 'organize': return await organizeDirectory(options.path); default: return { success: false, error: new Error(`Unknown action: ${options.action}`) }; } } async function interactiveFileMode() { console.log(chalk_1.default.cyan.bold('šŸ“ File Management Mode')); console.log(chalk_1.default.dim('Choose a file operation to perform.\n')); const { action } = await inquirer_1.default.prompt([ { type: 'list', name: 'action', message: 'What would you like to do?', choices: [ { name: 'šŸ“ Create a new file', value: 'create' }, { name: 'šŸ“– Read a file', value: 'read' }, { name: 'šŸ“‚ List directory contents', value: 'list' }, { name: 'šŸ” Search for files', value: 'search' }, { name: 'šŸ“‹ Copy file/directory', value: 'copy' }, { name: 'āœ‚ļø Move file/directory', value: 'move' }, { name: 'šŸ—‘ļø Delete file/directory', value: 'delete' }, { name: 'šŸ—‚ļø Organize directory', value: 'organize' }, ], }, ]); const answers = await getActionSpecificInputs(action); const options = { action, interactive: true, ...answers, }; return await executeFileCommand(options); } async function getActionSpecificInputs(action) { const commonQuestions = []; switch (action) { case 'create': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: 'Enter file path:', validate: (input) => { if (!input.trim()) { return 'File path is required'; } return true; }, }, { type: 'input', name: 'content', message: 'Enter file content (press Enter when done):', default: '', }, ]); case 'read': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: 'Enter file path to read:', validate: (input) => { if (!input.trim()) { return 'File path is required'; } return true; }, }, ]); case 'list': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: 'Enter directory path:', default: '.', }, { type: 'confirm', name: 'recursive', message: 'List recursively?', default: false, }, ]); case 'search': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: 'Search directory:', default: '.', }, { type: 'input', name: 'pattern', message: 'Search pattern (wildcards supported):', validate: (input) => { if (!input.trim()) { return 'Search pattern is required'; } return true; }, }, { type: 'confirm', name: 'recursive', message: 'Search recursively?', default: true, }, ]); case 'copy': case 'move': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: `Enter ${action} source path:`, validate: (input) => { if (!input.trim()) { return 'Source path is required'; } return true; }, }, { type: 'input', name: 'destination', message: `Enter ${action} destination path:`, validate: (input) => { if (!input.trim()) { return 'Destination path is required'; } return true; }, }, ]); case 'delete': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: 'Enter path to delete:', validate: (input) => { if (!input.trim()) { return 'Path is required'; } return true; }, }, { type: 'confirm', name: 'confirm', message: 'Are you sure you want to delete this?', default: false, }, ]); case 'organize': return await inquirer_1.default.prompt([ { type: 'input', name: 'path', message: 'Enter directory path to organize:', default: '.', }, ]); default: return {}; } } async function createFile(path, content) { if (!path) { return { success: false, error: new Error('File path is required'), }; } const spinner = (0, spinner_1.createSpinner)(); spinner.start('Creating file...'); try { // Ensure directory exists const dir = (0, path_1.dirname)(path); await (0, promises_1.mkdir)(dir, { recursive: true }); // Write file content const fileContent = content || ''; await (0, promises_1.writeFile)(path, fileContent, 'utf8'); spinner.succeed(`File created: ${chalk_1.default.cyan(path)}`); return { success: true, message: `File created successfully at ${path}`, data: { path, content: fileContent, size: fileContent.length }, }; } catch (error) { spinner.fail('Failed to create file'); throw error; } } async function readFileContent(path) { if (!path) { return { success: false, error: new Error('File path is required'), }; } const spinner = (0, spinner_1.createSpinner)(); spinner.start('Reading file...'); try { const stats = await (0, promises_1.stat)(path); const content = await (0, promises_1.readFile)(path, 'utf8'); spinner.succeed(`File read: ${chalk_1.default.cyan(path)}`); console.log(chalk_1.default.green.bold('\nšŸ“„ File Content:')); console.log(chalk_1.default.dim(`Path: ${path}`)); console.log(chalk_1.default.dim(`Size: ${stats.size} bytes`)); console.log(chalk_1.default.dim(`Last modified: ${stats.mtime.toLocaleString()}`)); console.log(''); // Display content with line numbers const lines = content.split('\n'); const maxLineNum = lines.length.toString().length; lines.forEach((line, index) => { const lineNumber = (index + 1).toString().padStart(maxLineNum, ' '); const code = line || ' '; console.log(chalk_1.default.dim(`${lineNumber} │`) + ' ' + code); }); return { success: true, message: `File read successfully (${content.length} characters)`, data: { path, content, size: stats.size }, }; } catch (error) { spinner.fail('Failed to read file'); throw error; } } async function listDirectory(path, recursive = false) { const dirPath = path || '.'; const spinner = (0, spinner_1.createSpinner)(); spinner.start('Listing directory...'); try { const items = await (0, promises_1.readdir)(dirPath, { withFileTypes: true }); spinner.succeed(`Directory listed: ${chalk_1.default.cyan(dirPath)}`); console.log(chalk_1.default.green.bold(`\nšŸ“‚ Contents of ${dirPath}:`)); if (items.length === 0) { console.log(chalk_1.default.yellow(' (empty directory)')); } else { for (const item of items) { const itemPath = (0, path_1.join)(dirPath, item.name); const stats = await (0, promises_1.stat)(itemPath); const isDir = item.isDirectory(); const icon = isDir ? 'šŸ“' : 'šŸ“„'; const name = isDir ? chalk_1.default.blue.bold(item.name) : item.name; const size = isDir ? '' : ` (${stats.size} bytes)`; const modified = stats.mtime.toLocaleDateString(); console.log(` ${icon} ${name}${chalk_1.default.dim(size)} ${chalk_1.default.dim(`[${modified}]`)}`); // If recursive and it's a directory, list its contents if (recursive && isDir && item.name !== '.' && item.name !== '..') { const subResult = await listDirectory(itemPath, false); if (subResult.success && subResult.data) { console.log(chalk_1.default.dim(' └─ ' + '-'.repeat(30))); } } } } const stats = await (0, promises_1.stat)(dirPath); return { success: true, message: `Listed ${items.length} items`, data: { path: dirPath, itemCount: items.length, isDirectory: stats.isDirectory() }, }; } catch (error) { spinner.fail('Failed to list directory'); throw error; } } async function searchFiles(path, pattern, recursive = true) { const searchPath = path || '.'; const searchPattern = pattern || '*'; if (!pattern) { return { success: false, error: new Error('Search pattern is required'), }; } const spinner = (0, spinner_1.createSpinner)(); spinner.start('Searching files...'); try { const results = await searchInDirectory(searchPath, searchPattern, recursive); spinner.succeed(`Search completed in ${chalk_1.default.cyan(searchPath)}`); console.log(chalk_1.default.green.bold(`\nšŸ” Search Results for "${pattern}":`)); if (results.length === 0) { console.log(chalk_1.default.yellow(' No files found')); } else { results.forEach((filePath, index) => { console.log(` ${chalk_1.default.dim(`${index + 1}.`)} ${chalk_1.default.cyan(filePath)}`); }); } return { success: true, message: `Found ${results.length} matching files`, data: { pattern, path: searchPath, results, count: results.length }, }; } catch (error) { spinner.fail('Search failed'); throw error; } } async function searchInDirectory(dir, pattern, recursive) { const results = []; const items = await (0, promises_1.readdir)(dir, { withFileTypes: true }); // Simple wildcard matching (can be enhanced) const regexPattern = pattern .replace(/\*/g, '.*') .replace(/\?/g, '.'); const regex = new RegExp(regexPattern, 'i'); for (const item of items) { const itemPath = (0, path_1.join)(dir, item.name); if (regex.test(item.name)) { results.push(itemPath); } if (recursive && item.isDirectory() && item.name !== '.' && item.name !== '..') { const subResults = await searchInDirectory(itemPath, pattern, recursive); results.push(...subResults); } } return results; } async function copyFileOrDirectory(source, destination) { if (!source || !destination) { return { success: false, error: new Error('Both source and destination paths are required'), }; } const spinner = (0, spinner_1.createSpinner)(); spinner.start('Copying...'); try { const sourceStats = await (0, promises_1.stat)(source); if (sourceStats.isDirectory()) { await copyDirectory(source, destination); } else { await (0, promises_1.copyFile)(source, destination); } spinner.succeed(`Copied to ${chalk_1.default.cyan(destination)}`); return { success: true, message: `Successfully copied ${source} to ${destination}`, data: { source, destination, isDirectory: sourceStats.isDirectory() }, }; } catch (error) { spinner.fail('Copy failed'); throw error; } } async function copyDirectory(source, destination) { await (0, promises_1.mkdir)(destination, { recursive: true }); const items = await (0, promises_1.readdir)(source, { withFileTypes: true }); for (const item of items) { const sourcePath = (0, path_1.join)(source, item.name); const destPath = (0, path_1.join)(destination, item.name); if (item.isDirectory()) { await copyDirectory(sourcePath, destPath); } else { await (0, promises_1.copyFile)(sourcePath, destPath); } } } async function moveFileOrDirectory(source, destination) { if (!source || !destination) { return { success: false, error: new Error('Both source and destination paths are required'), }; } const spinner = (0, spinner_1.createSpinner)(); spinner.start('Moving...'); try { await (0, promises_1.rename)(source, destination); spinner.succeed(`Moved to ${chalk_1.default.cyan(destination)}`); return { success: true, message: `Successfully moved ${source} to ${destination}`, data: { source, destination }, }; } catch (error) { spinner.fail('Move failed'); throw error; } } async function deleteFileOrDirectory(path) { if (!path) { return { success: false, error: new Error('Path is required'), }; } const spinner = (0, spinner_1.createSpinner)(); spinner.start('Deleting...'); try { const stats = await (0, promises_1.stat)(path); if (stats.isDirectory()) { await deleteDirectory(path); } else { await (0, promises_1.unlink)(path); } spinner.succeed(`Deleted: ${chalk_1.default.cyan(path)}`); return { success: true, message: `Successfully deleted ${path}`, data: { path, wasDirectory: stats.isDirectory() }, }; } catch (error) { spinner.fail('Delete failed'); throw error; } } async function deleteDirectory(dirPath) { const items = await (0, promises_1.readdir)(dirPath, { withFileTypes: true }); for (const item of items) { const itemPath = (0, path_1.join)(dirPath, item.name); if (item.isDirectory()) { await deleteDirectory(itemPath); } else { await (0, promises_1.unlink)(itemPath); } } // Remove the empty directory await (0, promises_1.unlink)(dirPath); } async function organizeDirectory(path) { const dirPath = path || '.'; const spinner = (0, spinner_1.createSpinner)(); spinner.start('Organizing directory...'); try { const items = await (0, promises_1.readdir)(dirPath, { withFileTypes: true }); const fileItems = items.filter(item => !item.isDirectory()); let organizedCount = 0; for (const item of fileItems) { const filePath = (0, path_1.join)(dirPath, item.name); const extension = (0, path_1.extname)(item.name).toLowerCase(); if (extension) { const folderName = extension.substring(1); // Remove the dot const targetDir = (0, path_1.join)(dirPath, folderName); // Create folder if it doesn't exist await (0, promises_1.mkdir)(targetDir, { recursive: true }); // Move file to appropriate folder const targetPath = (0, path_1.join)(targetDir, item.name); await (0, promises_1.rename)(filePath, targetPath); organizedCount++; } } spinner.succeed(`Organized ${organizedCount} files`); return { success: true, message: `Successfully organized ${organizedCount} files in ${dirPath}`, data: { path: dirPath, organizedCount }, }; } catch (error) { spinner.fail('Organization failed'); throw error; } } function handleResult(result) { if (result.success) { logger_1.logger.info('File command executed successfully'); if (result.message) { logger_1.logger.debug(`Result: ${result.message}`); } } else { handleError(result.error); } } function handleError(error) { logger_1.logger.error('File command failed:', error); if (error instanceof Error) { console.error(chalk_1.default.red('Error:'), error.message); } else { console.error(chalk_1.default.red('An unknown error occurred')); } process.exit(1); } //# sourceMappingURL=file.js.map