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
JavaScript
;
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