Files
onebox/ts/onebox.cli.ts

367 lines
8.5 KiB
TypeScript
Raw Normal View History

/**
* CLI Router for Onebox
*/
import { logger } from './onebox.logging.ts';
import { projectInfo } from './onebox.info.ts';
import { Onebox } from './onebox.classes.onebox.ts';
export async function runCli(): Promise<void> {
const args = Deno.args;
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
printHelp();
return;
}
if (args.includes('--version') || args.includes('-v')) {
console.log(`${projectInfo.name} v${projectInfo.version}`);
return;
}
const command = args[0];
const subcommand = args[1];
try {
// Initialize Onebox
const onebox = new Onebox();
await onebox.init();
// Route commands
switch (command) {
case 'service':
await handleServiceCommand(onebox, subcommand, args.slice(2));
break;
case 'registry':
await handleRegistryCommand(onebox, subcommand, args.slice(2));
break;
case 'dns':
await handleDnsCommand(onebox, subcommand, args.slice(2));
break;
case 'ssl':
await handleSslCommand(onebox, subcommand, args.slice(2));
break;
case 'nginx':
await handleNginxCommand(onebox, subcommand, args.slice(2));
break;
case 'daemon':
await handleDaemonCommand(onebox, subcommand, args.slice(2));
break;
case 'config':
await handleConfigCommand(onebox, subcommand, args.slice(2));
break;
case 'status':
await handleStatusCommand(onebox);
break;
default:
logger.error(`Unknown command: ${command}`);
printHelp();
Deno.exit(1);
}
// Cleanup
await onebox.shutdown();
} catch (error) {
logger.error(error.message);
Deno.exit(1);
}
}
// Service commands
async function handleServiceCommand(onebox: Onebox, subcommand: string, args: string[]) {
switch (subcommand) {
case 'add': {
const name = args[0];
const image = getArg(args, '--image');
const domain = getArg(args, '--domain');
const port = parseInt(getArg(args, '--port') || '80', 10);
const envArgs = args.filter((a) => a.startsWith('--env=')).map((a) => a.slice(6));
const envVars: Record<string, string> = {};
for (const env of envArgs) {
const [key, value] = env.split('=');
envVars[key] = value;
}
await onebox.services.deployService({ name, image, port, domain, envVars });
break;
}
case 'remove':
await onebox.services.removeService(args[0]);
break;
case 'start':
await onebox.services.startService(args[0]);
break;
case 'stop':
await onebox.services.stopService(args[0]);
break;
case 'restart':
await onebox.services.restartService(args[0]);
break;
case 'list': {
const services = onebox.services.listServices();
logger.table(
['Name', 'Image', 'Status', 'Domain', 'Port'],
services.map((s) => [s.name, s.image, s.status, s.domain || '-', s.port.toString()])
);
break;
}
case 'logs': {
const logs = await onebox.services.getServiceLogs(args[0]);
console.log(logs);
break;
}
default:
logger.error(`Unknown service subcommand: ${subcommand}`);
}
}
// Registry commands
async function handleRegistryCommand(onebox: Onebox, subcommand: string, args: string[]) {
switch (subcommand) {
case 'add': {
const url = getArg(args, '--url');
const username = getArg(args, '--username');
const password = getArg(args, '--password');
await onebox.registries.addRegistry(url, username, password);
break;
}
case 'remove':
await onebox.registries.removeRegistry(getArg(args, '--url'));
break;
case 'list': {
const registries = onebox.registries.listRegistries();
logger.table(
['URL', 'Username'],
registries.map((r) => [r.url, r.username])
);
break;
}
default:
logger.error(`Unknown registry subcommand: ${subcommand}`);
}
}
// DNS commands
async function handleDnsCommand(onebox: Onebox, subcommand: string, args: string[]) {
switch (subcommand) {
case 'add':
await onebox.dns.addDNSRecord(args[0]);
break;
case 'remove':
await onebox.dns.removeDNSRecord(args[0]);
break;
case 'list': {
const records = onebox.dns.listDNSRecords();
logger.table(
['Domain', 'Type', 'Value'],
records.map((r) => [r.domain, r.type, r.value])
);
break;
}
case 'sync':
await onebox.dns.syncFromCloudflare();
break;
default:
logger.error(`Unknown dns subcommand: ${subcommand}`);
}
}
// SSL commands
async function handleSslCommand(onebox: Onebox, subcommand: string, args: string[]) {
switch (subcommand) {
case 'renew':
if (args[0]) {
await onebox.ssl.renewCertificate(args[0]);
} else {
await onebox.ssl.renewExpiring();
}
break;
case 'list': {
const certs = onebox.ssl.listCertificates();
logger.table(
['Domain', 'Expiry', 'Issuer'],
certs.map((c) => [c.domain, new Date(c.expiryDate).toISOString(), c.issuer])
);
break;
}
case 'force-renew':
await onebox.ssl.renewCertificate(args[0]);
break;
default:
logger.error(`Unknown ssl subcommand: ${subcommand}`);
}
}
// Nginx commands
async function handleNginxCommand(onebox: Onebox, subcommand: string, _args: string[]) {
switch (subcommand) {
case 'reload':
await onebox.nginx.reload();
break;
case 'test':
await onebox.nginx.test();
break;
case 'status': {
const status = await onebox.nginx.getStatus();
logger.info(`Nginx status: ${status}`);
break;
}
default:
logger.error(`Unknown nginx subcommand: ${subcommand}`);
}
}
// Daemon commands
async function handleDaemonCommand(onebox: Onebox, subcommand: string, _args: string[]) {
switch (subcommand) {
case 'install':
await onebox.daemon.installService();
break;
case 'start':
await onebox.startDaemon();
break;
case 'stop':
await onebox.stopDaemon();
break;
case 'logs': {
const command = new Deno.Command('journalctl', {
args: ['-u', 'smartdaemon_onebox', '-f'],
stdout: 'inherit',
stderr: 'inherit',
});
await command.output();
break;
}
case 'status': {
const status = await onebox.daemon.getServiceStatus();
logger.info(`Daemon status: ${status}`);
break;
}
default:
logger.error(`Unknown daemon subcommand: ${subcommand}`);
}
}
// Config commands
async function handleConfigCommand(onebox: Onebox, subcommand: string, args: string[]) {
switch (subcommand) {
case 'show': {
const settings = onebox.database.getAllSettings();
logger.table(
['Key', 'Value'],
Object.entries(settings).map(([k, v]) => [k, v])
);
break;
}
case 'set':
onebox.database.setSetting(args[0], args[1]);
logger.success(`Setting ${args[0]} updated`);
break;
default:
logger.error(`Unknown config subcommand: ${subcommand}`);
}
}
// Status command
async function handleStatusCommand(onebox: Onebox) {
const status = await onebox.getSystemStatus();
console.log(JSON.stringify(status, null, 2));
}
// Helpers
function getArg(args: string[], flag: string): string {
const arg = args.find((a) => a.startsWith(`${flag}=`));
return arg ? arg.split('=')[1] : '';
}
function printHelp(): void {
console.log(`
Onebox v${projectInfo.version} - Self-hosted container platform
Usage: onebox <command> [options]
Commands:
service add <name> --image <image> [--domain <domain>] [--port <port>] [--env KEY=VALUE]
service remove <name>
service start <name>
service stop <name>
service restart <name>
service list
service logs <name>
registry add --url <url> --username <user> --password <pass>
registry remove --url <url>
registry list
dns add <domain>
dns remove <domain>
dns list
dns sync
ssl renew [domain]
ssl list
ssl force-renew <domain>
nginx reload
nginx test
nginx status
daemon install
daemon start
daemon stop
daemon logs
daemon status
config show
config set <key> <value>
status
Options:
--help, -h Show this help message
--version, -v Show version
--debug Enable debug logging
Examples:
onebox service add myapp --image nginx:latest --domain app.example.com --port 80
onebox registry add --url registry.example.com --username user --password pass
onebox daemon install
onebox daemon start
`);
}