276 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * 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 <COMMAND> [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 <file>              Use a YAML config file
 | |
|   --ubuntu-version <version>   Ubuntu version (22.04, 24.04, etc.)
 | |
|   --arch <arch>                Architecture (amd64 or arm64)
 | |
|   --wifi-ssid <ssid>           WiFi SSID
 | |
|   --wifi-password <password>   WiFi password
 | |
|   --hostname <name>            System hostname
 | |
|   --output <path>              Output ISO path
 | |
|   --ssh-key <path>             Path to SSH public key
 | |
| 
 | |
| CACHE OPTIONS:
 | |
|   cache list                   List cached ISOs
 | |
|   cache download <version>     Download and cache an ISO
 | |
|   cache clean                  Clean all cached ISOs
 | |
| 
 | |
| TEMPLATE OPTIONS:
 | |
|   template create              Generate config template to stdout
 | |
|   template create --output <file>  Save template to file
 | |
| 
 | |
| VALIDATE OPTIONS:
 | |
|   validate <file>              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<string, string | boolean> {
 | |
|   const parsed = new Map<string, string | boolean>();
 | |
|   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<string, string | boolean>) {
 | |
|   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<string, string | boolean>) {
 | |
|   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 <version>');
 | |
|       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<string, string | boolean>) {
 | |
|   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<string, string | boolean>) {
 | |
|   const configPath = args.get('_arg1') as string;
 | |
| 
 | |
|   if (!configPath) {
 | |
|     log.error('Please specify a config file: isocreator validate <file>');
 | |
|     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);
 | |
|   }
 | |
| }
 |