UNPKG

scaffold-scripts

Version:

Simple CLI tool for managing and running your own scripts. Add any script, run it anywhere.

930 lines (925 loc) 42.8 kB
#!/usr/bin/env node "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const chalk_1 = __importDefault(require("chalk")); const fs_1 = require("fs"); const path_1 = require("path"); const prompts_1 = __importDefault(require("prompts")); const database_js_1 = require("./database.js"); const scriptExecutor_js_1 = require("./scriptExecutor.js"); const scriptValidator_js_1 = require("./scriptValidator.js"); const scriptProcessor_js_1 = require("./scriptProcessor.js"); const symbols_js_1 = require("./symbols.js"); const usageHelper_js_1 = require("./usageHelper.js"); // Get version from package.json const packageJsonPath = (0, path_1.join)(__dirname, '..', 'package.json'); const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf-8')); const program = new commander_1.Command(); const db = new database_js_1.ScaffoldDatabase(); const executor = new scriptExecutor_js_1.ScriptExecutor(); const validator = new scriptValidator_js_1.ScriptValidator(); const processor = new scriptProcessor_js_1.ScriptProcessor(); program .name('scaffold') .description('CLI tool for managing and executing scaffold scripts') .version(packageJson.version, '-v, --version', 'display version number') .helpOption('-h, --help', 'display help for command') .addHelpCommand('help [command]', 'display help for command'); // Configure custom help program.configureHelp({ helpWidth: 80, sortSubcommands: true }); // Custom help display program.on('--help', () => { usageHelper_js_1.UsageHelper.displayMainHelp(); }); // Configure Commander to use our error handling program.exitOverride(); // Override Commander's error output program.configureOutput({ writeErr: () => { }, // Suppress all Commander error output writeOut: (str) => process.stdout.write(str) }); // Main scaffolding commands program .argument('[script-name]', 'run script with specified name') .option('--original', 'run the original script version') .option('--converted', 'run the converted script version') .option('--windows', 'run the Windows-specific script version') .option('--unix', 'run the Unix-specific script version') .option('--cross-platform', 'run the cross-platform script version') .action(async (scriptName, options) => { try { if (scriptName) { await handleScriptCommand(scriptName, false, options); } else { // Interactive mode when no script name provided const selectedScript = await selectScriptInteractively(); if (!selectedScript) { return; // User cancelled or no scripts available } // Handle special actions if (selectedScript === 'list') { await listCommands(false); return; } if (selectedScript === 'add') { usageHelper_js_1.UsageHelper.displayCommandHelp('add'); return; } if (selectedScript === 'clear') { await clearAllCommands(); return; } if (selectedScript === 'exit') { console.log(chalk_1.default.blue(`Goodbye! ${symbols_js_1.sym.party()}`)); return; } // Run the selected script await handleScriptCommand(selectedScript, false); } } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check your command syntax and try again'); process.exit(1); } }); // Add command program .command('add') .alias('a') .description('add a new script') .argument('<name>', 'script name') .argument('<scriptPath>', 'path to script file') .option('-p, --platform <platform>', 'target platform: all, windows, or unix', 'all') .option('--strict', 'use strict validation') .option('--no-validate', 'skip validation (use with caution)') .on('--help', () => { usageHelper_js_1.UsageHelper.displayCommandHelp('add'); }) .action(async (name, scriptPath, options) => { try { await addCommand(name, scriptPath, options); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check your script path and try again'); process.exit(1); } }); // Update command program .command('update') .alias('u') .description('update an existing script') .argument('<name>', 'script name') .argument('<scriptPath>', 'path to new script file') .option('-p, --platform <platform>', 'update target platform') .option('--strict', 'use strict validation') .on('--help', () => { usageHelper_js_1.UsageHelper.displayCommandHelp('update'); }) .action(async (name, scriptPath, options) => { try { await updateCommand(name, scriptPath, options); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check that the script exists and path is correct'); process.exit(1); } }); // Remove command program .command('remove') .alias('r') .description('remove a script') .argument('<name>', 'script name') .on('--help', () => { usageHelper_js_1.UsageHelper.displayCommandHelp('remove'); }) .action(async (name) => { try { await removeCommand(name); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check that the script name is correct'); process.exit(1); } }); // Clear all command program .command('clear') .description('clear all scripts from database') .option('-y, --yes', 'skip confirmation prompt') .on('--help', () => { console.log(''); console.log('Examples:'); console.log(' $ scripts clear # Clear all scripts with confirmation'); console.log(' $ scripts clear -y # Clear all scripts without confirmation'); }) .action(async (options) => { try { if (options.yes) { // Skip confirmation and clear directly const deletedCount = await db.clearAllCommands(); if (deletedCount > 0) { console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Successfully cleared ${deletedCount} script(s) from the database.`)); } else { console.log(chalk_1.default.blue(`${symbols_js_1.sym.info()} No scripts were found to clear.`)); } } else { await clearAllCommands(); } } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Unable to clear scripts'); process.exit(1); } }); // List commands program .command('list') .alias('l') .description('list available scripts') .option('-d, --detailed', 'show detailed information') .on('--help', () => { usageHelper_js_1.UsageHelper.displayCommandHelp('list'); }) .action(async (options) => { try { await listCommands(options.detailed); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Unable to retrieve script list'); process.exit(1); } }); // View command program .command('view') .alias('s') .description('view script details') .argument('<name>', 'script name') .on('--help', () => { usageHelper_js_1.UsageHelper.displayCommandHelp('view'); }) .action(async (name) => { try { await handleScriptCommand(name, true); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check that the script name is correct'); process.exit(1); } }); // Export command program .command('export') .description('export all scripts to a directory') .argument('<directory>', 'directory to export scripts to') .on('--help', () => { usageHelper_js_1.UsageHelper.displayCommandHelp('export'); }) .action(async (directory) => { try { await exportCommand(directory); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check that the directory path is valid and writable'); process.exit(1); } }); // Uninstall command program .command('uninstall') .description('uninstall scaffold-scripts CLI') .action(async () => { try { await uninstallCommand(); } catch (error) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Try manual uninstallation or check the documentation'); process.exit(1); } }); // Interactive script selector async function selectScriptInteractively() { const commands = await db.listCommands(); if (commands.length === 0) { console.log(chalk_1.default.yellow('No scripts available.')); console.log(chalk_1.default.blue('Add one with: scripts add <name> <script-path>')); return null; } console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.rocket()} Available Scripts:`)); const choices = commands.map((cmd) => { const alias = cmd.alias ? ` (${cmd.alias})` : ''; const platform = cmd.platform !== 'all' ? ` [${cmd.platform}]` : ''; const description = cmd.description ? ` - ${cmd.description}` : ''; return { title: `${cmd.name}${alias}${platform}${description}`, value: cmd.name, description: cmd.description || 'No description', }; }); // Add management options choices.push({ title: '─'.repeat(50), value: 'separator', description: '─' }, { title: `${symbols_js_1.sym.list()} List all scripts`, value: 'list', description: 'Show all available scripts', }, { title: `${symbols_js_1.sym.package()} Add new script`, value: 'add', description: 'Get help adding a new script', }, { title: `${symbols_js_1.sym.warning()} Clear all scripts`, value: 'clear', description: 'Remove all scripts from the database', }, { title: `${symbols_js_1.sym.cross()} Exit`, value: 'exit', description: 'Exit interactive mode' }); try { const response = await (0, prompts_1.default)({ type: 'select', name: 'script', message: 'Select a script to run:', choices: choices, initial: 0, }); return response.script || null; } catch (error) { // Handle Ctrl+C or other interruption console.log(chalk_1.default.yellow('\nOperation cancelled.')); return null; } } // Clear all commands async function clearAllCommands() { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.warning()} This will permanently delete ALL scripts from your database.`)); const confirmation = await (0, prompts_1.default)({ type: 'confirm', name: 'proceed', message: 'Are you sure you want to clear all scripts?', initial: false }); if (!confirmation.proceed) { console.log(chalk_1.default.blue('Operation cancelled.')); return; } try { const deletedCount = await db.clearAllCommands(); if (deletedCount > 0) { console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Successfully cleared ${deletedCount} script(s) from the database.`)); } else { console.log(chalk_1.default.blue(`${symbols_js_1.sym.info()} No scripts were found to clear.`)); } } catch (error) { console.error(chalk_1.default.red(`${symbols_js_1.sym.cross()} Error clearing scripts: ${error.message}`)); } } // Handle script commands async function handleScriptCommand(scriptName, viewOnly = false, versionOptions) { // Try to find by name first, then by alias let command = await db.getCommand(scriptName); if (!command) { command = await db.getCommandByAlias(scriptName); } if (!command) { const commands = await db.listCommands(); const scriptNames = commands.map(cmd => cmd.name); usageHelper_js_1.UsageHelper.displayScriptNotFound(scriptName, scriptNames); return; } if (viewOnly) { displayCommandDetails(command); } else { console.log(chalk_1.default.blue(`Executing script: ${command.name}`)); if (command.description) { console.log(chalk_1.default.gray(command.description)); } // Determine which script version to execute based on flags let scriptToExecute = command.script_original; // default to original let versionUsed = 'original'; if (versionOptions) { if (versionOptions.original) { scriptToExecute = command.script_original; versionUsed = 'original'; } else if (versionOptions.converted) { scriptToExecute = processor.getBestScript(command); versionUsed = 'converted'; } else if (versionOptions.windows && command.script_windows) { scriptToExecute = command.script_windows; versionUsed = 'Windows'; } else if (versionOptions.unix && command.script_unix) { scriptToExecute = command.script_unix; versionUsed = 'Unix'; } else if (versionOptions.crossPlatform && command.script_cross_platform) { scriptToExecute = command.script_cross_platform; versionUsed = 'cross-platform'; } else if (versionOptions.windows && !command.script_windows) { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.warning()} Windows version not available, using original`)); scriptToExecute = command.script_original; versionUsed = 'original (Windows not available)'; } else if (versionOptions.unix && !command.script_unix) { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.warning()} Unix version not available, using original`)); scriptToExecute = command.script_original; versionUsed = 'original (Unix not available)'; } else if (versionOptions.crossPlatform && !command.script_cross_platform) { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.warning()} Cross-platform version not available, using original`)); scriptToExecute = command.script_original; versionUsed = 'original (cross-platform not available)'; } } else { // Default behavior - auto-select best version if (['powershell', 'nodejs', 'python'].includes(command.script_type)) { scriptToExecute = command.script_original; versionUsed = 'original (interpreter-based)'; } else { scriptToExecute = processor.getBestScript(command); versionUsed = 'auto-selected'; } } console.log(chalk_1.default.gray(`Using ${versionUsed} version`)); const result = await executor.executeScript(scriptToExecute, command.platform, [], command.script_type); console.log(chalk_1.default.green(`\n${symbols_js_1.sym.check()} Script completed successfully!`)); // Output is now streamed in real-time, so we don't need to display it again // Only show stderr if there were any non-fatal errors if (result.stderr && result.stderr.trim()) { console.log(chalk_1.default.yellow('\n--- Warnings/Errors ---')); console.log(result.stderr); } } } // Add new command - Production Ready Version async function addCommand(name, scriptPath, options) { try { console.log(chalk_1.default.blue(`${symbols_js_1.sym.package()} Processing script: ${name}`)); // Process the script using the production-ready processor const processedScript = await processor.processScriptFile(scriptPath, { strict: options.strict || false, allowNetworkAccess: !options.strict, allowSystemModification: !options.strict, }); // Display validation results console.log(`\n${symbols_js_1.sym.list()} Validation Results:`); if (processedScript.validation.isValid) { console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Script validation passed`)); } else { console.log(chalk_1.default.red(`${symbols_js_1.sym.cross()} Script validation failed`)); } if (processedScript.validation.errors.length > 0) { console.log(chalk_1.default.red('\nErrors:')); processedScript.validation.errors.forEach((error) => { console.log(chalk_1.default.red(` • ${error}`)); }); } if (processedScript.validation.warnings.length > 0) { console.log(chalk_1.default.yellow('\nWarnings:')); processedScript.validation.warnings.forEach((warning) => { console.log(chalk_1.default.yellow(` • ${warning}`)); }); } // Fail if validation failed and not overridden if (!processedScript.validation.isValid && options.validate !== false) { console.error(chalk_1.default.red(`\n${symbols_js_1.sym.cross()} Cannot add command due to validation errors.`)); console.log(chalk_1.default.gray('Use --no-validate to skip validation (not recommended).')); return; } // Display script processing info console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.search()} Script Analysis:`)); console.log(chalk_1.default.gray(` Original Platform: ${processedScript.originalPlatform}`)); console.log(chalk_1.default.gray(` Script Type: ${processedScript.scriptType}`)); console.log(chalk_1.default.gray(` Windows Version: ${processedScript.windows ? `${symbols_js_1.sym.check()} Generated` : `${symbols_js_1.sym.cross()} Not available`}`)); console.log(chalk_1.default.gray(` Unix Version: ${processedScript.unix ? `${symbols_js_1.sym.check()} Generated` : `${symbols_js_1.sym.cross()} Not available`}`)); console.log(chalk_1.default.gray(` Cross-Platform: ${processedScript.crossPlatform ? `${symbols_js_1.sym.check()} Generated` : `${symbols_js_1.sym.cross()} Not available`}`)); // Create the command object const command = processor.createCommand(name, processedScript, { platform: options.platform, }); // Save to database await db.addCommand(command); console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Added script "${name}"`)); // Show usage examples console.log(chalk_1.default.blue(`${symbols_js_1.sym.rocket()} Usage Examples:`)); console.log(chalk_1.default.cyan(` scripts ${name} # Run the script`)); console.log(chalk_1.default.cyan(` scripts ${name} arg1 arg2 # Run with arguments`)); console.log(chalk_1.default.cyan(` scripts view ${name} # View script details`)); console.log(chalk_1.default.cyan(` scripts remove ${name} # Remove this script`)); console.log(chalk_1.default.cyan(` scripts list # List all scripts`)); // Show platform compatibility info const compatibility = processor.validatePlatformCompatibility(command, process.platform); if (!compatibility.compatible || compatibility.warnings.length > 0) { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.warning()} Platform Compatibility:`)); compatibility.warnings.forEach((warning) => { console.log(chalk_1.default.yellow(` • ${warning}`)); }); if (compatibility.recommendations.length > 0) { console.log(chalk_1.default.blue(`${symbols_js_1.sym.bulb()} Recommendations:`)); compatibility.recommendations.forEach((rec) => { console.log(chalk_1.default.blue(` • ${rec}`)); }); } } } catch (error) { console.error(chalk_1.default.red(`${symbols_js_1.sym.cross()} Failed to add command: ${error.message}`)); throw error; } } // Update existing command - Production Ready Version async function updateCommand(name, scriptPath, options) { try { const existing = await db.getCommand(name); if (!existing) { console.error(chalk_1.default.red(`Script "${name}" not found.`)); return; } console.log(chalk_1.default.blue(`${symbols_js_1.sym.package()} Updating script: ${name}`)); // Process the new script using the production-ready processor const processedScript = await processor.processScriptFile(scriptPath, { strict: options.strict || false, allowNetworkAccess: !options.strict, allowSystemModification: !options.strict, }); // Display validation results console.log(`\n${symbols_js_1.sym.list()} Validation Results:`); if (processedScript.validation.isValid) { console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Script validation passed`)); } else { console.log(chalk_1.default.red(`${symbols_js_1.sym.cross()} Script validation failed`)); } if (processedScript.validation.errors.length > 0) { console.log(chalk_1.default.red('\nErrors:')); processedScript.validation.errors.forEach((error) => { console.log(chalk_1.default.red(` • ${error}`)); }); } if (processedScript.validation.warnings.length > 0) { console.log(chalk_1.default.yellow('\nWarnings:')); processedScript.validation.warnings.forEach((warning) => { console.log(chalk_1.default.yellow(` • ${warning}`)); }); } // Fail if validation failed and not overridden if (!processedScript.validation.isValid && options.validate !== false) { console.error(chalk_1.default.red(`\n${symbols_js_1.sym.cross()} Cannot update command due to validation errors.`)); console.log(chalk_1.default.gray('Use --no-validate to skip validation (not recommended).')); return; } // Display script processing info console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.search()} Script Analysis:`)); console.log(chalk_1.default.gray(` Original Platform: ${processedScript.originalPlatform}`)); console.log(chalk_1.default.gray(` Script Type: ${processedScript.scriptType}`)); console.log(chalk_1.default.gray(` Windows Version: ${processedScript.windows ? `${symbols_js_1.sym.check()} Generated` : `${symbols_js_1.sym.cross()} Not available`}`)); console.log(chalk_1.default.gray(` Unix Version: ${processedScript.unix ? `${symbols_js_1.sym.check()} Generated` : `${symbols_js_1.sym.cross()} Not available`}`)); console.log(chalk_1.default.gray(` Cross-Platform: ${processedScript.crossPlatform ? `${symbols_js_1.sym.check()} Generated` : `${symbols_js_1.sym.cross()} Not available`}`)); // Prepare updates with new multi-script fields const updates = { script_original: processedScript.original, script_windows: processedScript.windows, script_unix: processedScript.unix, script_cross_platform: processedScript.crossPlatform, original_platform: processedScript.originalPlatform, script_type: processedScript.scriptType, }; if (options.platform !== undefined) updates.platform = options.platform; const success = await db.updateCommand(name, updates); if (success) { console.log(chalk_1.default.green(`\n${symbols_js_1.sym.check()} Updated script "${name}"`)); // Show usage examples console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.rocket()} Usage Examples:`)); console.log(chalk_1.default.cyan(` scripts ${name} # Run the updated script`)); console.log(chalk_1.default.cyan(` scripts ${name} arg1 arg2 # Run with arguments`)); console.log(chalk_1.default.cyan(` scripts view ${name} # View script details`)); // Show platform compatibility info for updated command const updatedCommand = { ...existing, ...updates }; const compatibility = processor.validatePlatformCompatibility(updatedCommand, process.platform); if (!compatibility.compatible || compatibility.warnings.length > 0) { console.log(chalk_1.default.yellow(`\n${symbols_js_1.sym.warning()} Platform Compatibility:`)); compatibility.warnings.forEach((warning) => { console.log(chalk_1.default.yellow(` • ${warning}`)); }); if (compatibility.recommendations.length > 0) { console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.bulb()} Recommendations:`)); compatibility.recommendations.forEach((rec) => { console.log(chalk_1.default.blue(` • ${rec}`)); }); } } } else { console.error(chalk_1.default.red(`${symbols_js_1.sym.cross()} Failed to update command.`)); } } catch (error) { console.error(chalk_1.default.red(`${symbols_js_1.sym.cross()} Failed to update command: ${error.message}`)); throw error; } } // Remove command async function removeCommand(name) { const success = await db.removeCommand(name); if (success) { console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Removed script "${name}"`)); } else { console.error(chalk_1.default.red(`Script "${name}" not found.`)); } } // List commands async function listCommands(detailed = false) { const commands = await db.listCommands(); if (commands.length === 0) { console.log(chalk_1.default.gray('No scripts available.')); return; } console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.list()} Available Scripts:`)); commands.forEach((cmd) => { const alias = cmd.alias ? chalk_1.default.gray(` (${cmd.alias})`) : ''; const platform = cmd.platform !== 'all' ? chalk_1.default.gray(` [${cmd.platform}]`) : ''; if (detailed) { console.log(chalk_1.default.cyan(` • ${cmd.name}${alias}${platform}`)); if (cmd.description) { console.log(chalk_1.default.gray(` ${cmd.description}`)); } console.log(chalk_1.default.gray(` Updated: ${new Date(cmd.updatedAt).toLocaleDateString()}`)); } else { console.log(chalk_1.default.cyan(` • ${cmd.name}${alias}${platform}`)); } }); } // Display command details - Production Ready Version function displayCommandDetails(command) { console.log(chalk_1.default.blue(`\n${symbols_js_1.sym.page()} Command Details: ${command.name}`)); console.log(chalk_1.default.gray('═'.repeat(60))); // Basic info console.log(chalk_1.default.yellow('Type:'), chalk_1.default.cyan(command.type)); console.log(chalk_1.default.yellow('Name:'), chalk_1.default.cyan(command.name)); if (command.alias) { console.log(chalk_1.default.yellow('Alias:'), chalk_1.default.cyan(command.alias)); } if (command.description) { console.log(chalk_1.default.yellow('Description:'), command.description); } console.log(chalk_1.default.yellow('Platform Support:'), chalk_1.default.cyan(command.platform)); console.log(chalk_1.default.yellow('Created:'), new Date(command.createdAt).toLocaleString()); console.log(chalk_1.default.yellow('Updated:'), new Date(command.updatedAt).toLocaleString()); // Script metadata if (command.script_type) { console.log('\n' + chalk_1.default.blue(`${symbols_js_1.sym.list()} Script Information:`)); console.log(chalk_1.default.gray('─'.repeat(40))); console.log(chalk_1.default.yellow('Original Platform:'), chalk_1.default.cyan(command.original_platform)); console.log(chalk_1.default.yellow('Script Type:'), chalk_1.default.cyan(command.script_type)); } // Get version info using processor const versionInfo = processor.getScriptVersionInfo(command); console.log('\n' + chalk_1.default.blue(`${symbols_js_1.sym.page()} Script Versions:`)); console.log(chalk_1.default.gray('─'.repeat(40))); // Original script console.log(chalk_1.default.yellow(`\n${symbols_js_1.sym.diamond()} Original (${versionInfo.original.platform}, ${versionInfo.original.type}):`)); console.log(chalk_1.default.gray(versionInfo.original.content.split('\n').slice(0, 5).join('\n') + (versionInfo.original.content.split('\n').length > 5 ? '\n...' : ''))); // Windows version if (versionInfo.windows?.available) { console.log(chalk_1.default.yellow(`\n${symbols_js_1.sym.diamond()} Windows Version:`)); console.log(chalk_1.default.gray(versionInfo.windows.content.split('\n').slice(0, 3).join('\n') + '...')); } // Unix version if (versionInfo.unix?.available) { console.log(chalk_1.default.yellow(`\n${symbols_js_1.sym.diamond()} Unix Version:`)); console.log(chalk_1.default.gray(versionInfo.unix.content.split('\n').slice(0, 3).join('\n') + '...')); } // Cross-platform version if (versionInfo.crossPlatform?.available) { console.log(chalk_1.default.yellow(`\n${symbols_js_1.sym.diamond()} Cross-Platform Version:`)); console.log(chalk_1.default.gray(versionInfo.crossPlatform.content.split('\n').slice(0, 3).join('\n') + '...')); } // Best version for current platform console.log('\n' + chalk_1.default.blue(`${symbols_js_1.sym.target()} Best for Current Platform (${versionInfo.bestForCurrent.version}):`)); console.log(chalk_1.default.gray('─'.repeat(40))); console.log(versionInfo.bestForCurrent.content); // Platform compatibility const compatibility = processor.validatePlatformCompatibility(command, process.platform); if (!compatibility.compatible || compatibility.warnings.length > 0) { console.log('\n' + chalk_1.default.yellow(`${symbols_js_1.sym.warning()} Platform Compatibility:`)); console.log(chalk_1.default.gray('─'.repeat(40))); compatibility.warnings.forEach((warning) => { console.log(chalk_1.default.yellow(`• ${warning}`)); }); if (compatibility.recommendations.length > 0) { console.log('\n' + chalk_1.default.blue(`${symbols_js_1.sym.bulb()} Recommendations:`)); compatibility.recommendations.forEach((rec) => { console.log(chalk_1.default.blue(`• ${rec}`)); }); } } else { console.log('\n' + chalk_1.default.green(`${symbols_js_1.sym.check()} Fully compatible with current platform`)); } } // Export command async function exportCommand(directory) { const fs = await Promise.resolve().then(() => __importStar(require('fs'))); const path = await Promise.resolve().then(() => __importStar(require('path'))); console.log(chalk_1.default.blue(`${symbols_js_1.sym.package()} Exporting scripts to: ${directory}`)); // Create export directory if (!fs.existsSync(directory)) { fs.mkdirSync(directory, { recursive: true }); } // Get all commands const commands = await db.listCommands(); if (commands.length === 0) { console.log(chalk_1.default.yellow('No scripts to export')); return; } // Export as individual files let exported = 0; for (const command of commands) { const fileName = `${command.name}.sh`; const filePath = path.join(directory, fileName); // Create a script file with metadata header const content = `#!/bin/bash # Scaffold Script: ${command.name} # Description: ${command.description || 'No description'} # Platform: ${command.platform} # Original Platform: ${command.original_platform} # Script Type: ${command.script_type} # Created: ${command.createdAt} # Updated: ${command.updatedAt} ${command.alias ? `# Alias: ${command.alias}` : ''} ${command.script_original}`; fs.writeFileSync(filePath, content); // Make executable on Unix if (process.platform !== 'win32') { fs.chmodSync(filePath, '755'); } exported++; } // Create README const readmeContent = `# Exported Scaffold Scripts Exported on: ${new Date().toISOString()} Total scripts: ${commands.length} ## Scripts: ${commands .map((cmd) => `- **${cmd.name}** ${cmd.alias ? `(${cmd.alias})` : ''}: ${cmd.description || 'No description'}`) .join('\n')} ## Usage: Each script is exported as an individual file. You can run them directly: \`\`\`bash ./${commands[0]?.name}.sh \`\`\` To recreate in scaffold-scripts (if you reinstall): \`\`\`bash scaffold add ${commands[0]?.name} ./${commands[0]?.name}.sh \`\`\` `; fs.writeFileSync(path.join(directory, 'README.md'), readmeContent); console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Exported ${exported} scripts as individual files`)); console.log(chalk_1.default.blue(`${symbols_js_1.sym.book()} See README.md in ${directory} for usage instructions`)); } // Helper function for user input async function askUser(question, defaultValue = 'n') { return new Promise((resolve) => { console.log(chalk_1.default.yellow(question)); process.stdout.write('> '); process.stdin.once('data', (data) => { const response = data.toString().trim().toLowerCase(); resolve(response || defaultValue); }); }); } // Uninstall command async function uninstallCommand() { const fs = await Promise.resolve().then(() => __importStar(require('fs'))); const path = await Promise.resolve().then(() => __importStar(require('path'))); const os = await Promise.resolve().then(() => __importStar(require('os'))); const { exec } = await Promise.resolve().then(() => __importStar(require('child_process'))); const { promisify } = await Promise.resolve().then(() => __importStar(require('util'))); const execAsync = promisify(exec); console.log(chalk_1.default.blue(`${symbols_js_1.sym.trash()} Scaffold Scripts CLI Uninstaller`)); console.log(chalk_1.default.blue('====================================')); // Check if user has any scripts const commands = await db.listCommands(); let exportDirectory = null; let keepData = false; if (commands.length > 0) { console.log(chalk_1.default.blue(`${symbols_js_1.sym.list()} You have ${commands.length} saved scripts:`)); commands.forEach((cmd) => { const alias = cmd.alias ? ` (${cmd.alias})` : ''; console.log(chalk_1.default.cyan(` • ${cmd.name}${alias}`)); }); console.log(''); // Ask about exporting const exportResponse = await askUser('Do you want to export your scripts before uninstalling? (y/N)'); if (exportResponse === 'y' || exportResponse === 'yes') { const defaultDir = './my-scaffold-scripts'; const dirResponse = await askUser(`Export directory (default: ${defaultDir}):`); exportDirectory = dirResponse.trim() || defaultDir; console.log(chalk_1.default.blue(`${symbols_js_1.sym.package()} Exporting scripts to: ${exportDirectory}`)); await exportCommand(exportDirectory); console.log(''); } else { // Ask about keeping data const keepResponse = await askUser('Keep your scripts in ~/.scaffold-scripts? (y/N)'); keepData = keepResponse === 'y' || keepResponse === 'yes'; } } console.log(chalk_1.default.blue(`${symbols_js_1.sym.trash()} Uninstalling Scaffold Scripts CLI...`)); try { // Uninstall package console.log(chalk_1.default.yellow(`${symbols_js_1.sym.package()} Removing scaffold-scripts package...`)); try { await execAsync('npm uninstall -g scaffold-scripts'); console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Package removed`)); } catch (error) { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.warning()} Could not remove via npm (this is normal if installed differently)`)); } // Handle local data directory const dataDir = path.join(os.homedir(), '.scaffold-scripts'); if (fs.existsSync(dataDir)) { if (!keepData && !exportDirectory) { console.log(chalk_1.default.yellow(`${symbols_js_1.sym.folder()} Removing local data directory...`)); fs.rmSync(dataDir, { recursive: true, force: true }); console.log(chalk_1.default.green(`${symbols_js_1.sym.check()} Local data directory removed`)); } else { console.log(chalk_1.default.blue(`${symbols_js_1.sym.info()} Local data preserved at: ` + dataDir)); } } else { console.log(chalk_1.default.blue(`${symbols_js_1.sym.info()} No local data directory found`)); } console.log(chalk_1.default.green(`${symbols_js_1.sym.party()} Uninstallation complete!`)); console.log(''); console.log(chalk_1.default.blue(`${symbols_js_1.sym.memo()} Summary:`)); console.log(chalk_1.default.blue(` ${symbols_js_1.sym.check()} Removed scaffold command`)); if (exportDirectory) { console.log(chalk_1.default.blue(` ${symbols_js_1.sym.check()} Exported scripts to: ${exportDirectory}`)); } else if (keepData) { console.log(chalk_1.default.blue(` ${symbols_js_1.sym.info()} Scripts preserved in ~/.scaffold-scripts`)); } else if (commands.length > 0) { console.log(chalk_1.default.blue(` ${symbols_js_1.sym.check()} Removed local data directory`)); } console.log(''); console.log(chalk_1.default.blue('Thank you for using Scaffold Scripts CLI!')); console.log(chalk_1.default.yellow('Please restart your terminal for changes to take effect')); process.exit(0); } catch (error) { console.error(chalk_1.default.red(`${symbols_js_1.sym.cross()} Error during uninstallation:`), error.message); console.log(chalk_1.default.yellow('You may need to remove manually or use the online uninstaller:')); console.log(chalk_1.default.blue('Unix: curl -fsSL https://raw.githubusercontent.com/ChrisColeTech/scaffold-scripts/main/uninstall.sh | bash')); console.log(chalk_1.default.blue('Windows: irm https://raw.githubusercontent.com/ChrisColeTech/scaffold-scripts/main/uninstall.ps1 | iex')); } } // Handle process termination process.on('SIGINT', () => { db.close(); process.exit(0); }); process.on('SIGTERM', () => { db.close(); process.exit(0); }); // Parse command line arguments with error handling try { program.parse(); } catch (error) { // Handle Commander.js errors gracefully if (error.code === 'commander.missingArgument') { // Extract command name from argv or error let commandName = 'unknown'; if (process.argv.length > 2) { commandName = process.argv[2]; } if (error.command?.name()) { commandName = error.command.name(); } usageHelper_js_1.UsageHelper.displayError(`Missing required arguments`, `Use: scripts ${commandName} --help for usage information`); usageHelper_js_1.UsageHelper.displayCommandHelp(commandName); process.exit(1); } else if (error.code === 'commander.unknownOption') { usageHelper_js_1.UsageHelper.displayError(`Unknown option: ${error.option}`, 'Use --help to see available options'); process.exit(1); } else if (error.code === 'commander.unknownCommand') { usageHelper_js_1.UsageHelper.displayError(`Unknown command: ${error.command}`, 'Use --help to see available commands'); process.exit(1); } else if (error.code === 'commander.version') { // Version command succeeded - just exit cleanly process.exit(0); } else if (error.code === 'commander.helpDisplayed' || error.message === '(outputHelp)') { // Help command succeeded - just exit cleanly process.exit(0); } else { // Only show error for actual errors if (error.message && error.message !== '(outputHelp)' && !error.message.match(/^\d+\.\d+\.\d+$/)) { usageHelper_js_1.UsageHelper.displayError(error.message, 'Check your command syntax and try again'); } process.exit(error.exitCode || 1); } } //# sourceMappingURL=index.js.map