/** * CLI Interface for isocreator */ import { log } from './logging.ts'; import { IsoBuilder } from './classes/iso-builder.ts'; import { IsoCache } from './classes/iso-cache.ts'; import { ConfigManager } from './classes/config-manager.ts'; /** * Display help information */ function showHelp() { console.log(` isocreator - Ubuntu ISO Customization Tool USAGE: isocreator [OPTIONS] COMMANDS: build Build a customized ISO cache Manage ISO cache template Generate config template validate Validate config file version Show version information help Show this help message BUILD OPTIONS: --config Use a YAML config file --ubuntu-version Ubuntu version (22.04, 24.04, etc.) --arch Architecture (amd64 or arm64) --wifi-ssid WiFi SSID --wifi-password WiFi password --hostname System hostname --output Output ISO path --ssh-key Path to SSH public key CACHE OPTIONS: cache list List cached ISOs cache download Download and cache an ISO cache clean Clean all cached ISOs TEMPLATE OPTIONS: template create Generate config template to stdout template create --output Save template to file VALIDATE OPTIONS: validate Validate a config file EXAMPLES: # Build from config file isocreator build --config myconfig.yaml # Quick build with CLI flags isocreator build \\ --ubuntu-version 24.04 \\ --arch amd64 \\ --wifi-ssid "MyWiFi" \\ --wifi-password "secret123" \\ --hostname "myserver" \\ --output ./custom-ubuntu.iso # Generate config template isocreator template create --output config.yaml # List cached ISOs isocreator cache list SYSTEM REQUIREMENTS: - xorriso (for ISO manipulation) - syslinux-utils (for USB-bootable ISOs) Install on Ubuntu/Debian: sudo apt install xorriso syslinux-utils Install on macOS: brew install xorriso syslinux For more information, visit: https://code.foss.global/serve.zone/isocreator `); } /** * Show version information */ function showVersion() { console.log('isocreator version 1.0.0'); console.log('Ubuntu ISO customization tool'); console.log('https://code.foss.global/serve.zone/isocreator'); } /** * Parse CLI arguments */ function parseArgs(args: string[]): Map { const parsed = new Map(); let i = 0; while (i < args.length) { const arg = args[i]; if (arg.startsWith('--')) { const key = arg.substring(2); const nextArg = args[i + 1]; if (nextArg && !nextArg.startsWith('--')) { parsed.set(key, nextArg); i += 2; } else { parsed.set(key, true); i += 1; } } else { parsed.set(`_arg${i}`, arg); i += 1; } } return parsed; } /** * Handle build command */ async function handleBuild(args: Map) { const builder = new IsoBuilder(); const configManager = new ConfigManager(); // Check if config file is provided if (args.has('config')) { const configPath = args.get('config') as string; const config = await configManager.loadFromFile(configPath); await builder.build(config, (step, progress) => { console.log(`[${progress}%] ${step}`); }); } else { // Build from CLI flags log.error('CLI flag mode not yet implemented. Please use --config for now.'); log.info('Generate a template: isocreator template create --output config.yaml'); Deno.exit(1); } } /** * Handle cache commands */ async function handleCache(args: Map) { const cache = new IsoCache(); const subcommand = args.get('_arg1') as string; if (!subcommand || subcommand === 'list') { const entries = await cache.list(); if (entries.length === 0) { console.log('No cached ISOs found.'); return; } console.log('\nCached ISOs:'); console.log('━'.repeat(80)); for (const entry of entries) { const sizeMB = (entry.size / 1024 / 1024).toFixed(2); const date = new Date(entry.downloadedAt).toLocaleDateString(); console.log(`${entry.version} (${entry.architecture}) - ${sizeMB} MB - ${date}`); console.log(` ${entry.path}`); } console.log('━'.repeat(80)); } else if (subcommand === 'clean') { await cache.clean(); console.log('Cache cleaned.'); } else if (subcommand === 'download') { const version = args.get('_arg2') as string; const arch = (args.get('arch') as string) || 'amd64'; if (!version) { log.error('Please specify a version: isocreator cache download '); Deno.exit(1); } await cache.downloadAndCache(version, arch as 'amd64' | 'arm64', (downloaded, total) => { const percent = ((downloaded / total) * 100).toFixed(1); process.stdout.write(`\ršŸ“„ Download progress: ${percent}%`); }); console.log(); } } /** * Handle template commands */ async function handleTemplate(args: Map) { const configManager = new ConfigManager(); const subcommand = args.get('_arg1') as string; if (!subcommand || subcommand === 'create') { const outputPath = args.get('output') as string | undefined; if (outputPath) { await configManager.saveTemplate(outputPath); } else { console.log(configManager.generateTemplate()); } } } /** * Handle validate command */ async function handleValidate(args: Map) { const configPath = args.get('_arg1') as string; if (!configPath) { log.error('Please specify a config file: isocreator validate '); Deno.exit(1); } const configManager = new ConfigManager(); try { await configManager.loadFromFile(configPath); log.success('Configuration is valid!'); } catch (err) { log.error(`Validation failed: ${err instanceof Error ? err.message : String(err)}`); Deno.exit(1); } } /** * Main CLI entry point */ export async function startCli() { const args = parseArgs(Deno.args); const command = args.get('_arg0') as string; try { switch (command) { case 'build': await handleBuild(args); break; case 'cache': await handleCache(args); break; case 'template': await handleTemplate(args); break; case 'validate': await handleValidate(args); break; case 'version': showVersion(); break; case 'help': case undefined: showHelp(); break; default: log.error(`Unknown command: ${command}`); log.info('Run "isocreator help" for usage information'); Deno.exit(1); } } catch (err) { log.error(`Error: ${err instanceof Error ? err.message : String(err)}`); Deno.exit(1); } }