feat(core): Initial project scaffold and implementation: Deno CLI, ISO tooling, cloud-init generation, packaging and installer scripts

This commit is contained in:
2025-10-24 08:10:02 +00:00
commit ce06b5855a
31 changed files with 2873 additions and 0 deletions

275
ts/cli.ts Normal file
View File

@@ -0,0 +1,275 @@
/**
* 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);
}
}