#!/usr/bin/env bun import {$} from "bun"; const SERVICES = { ap: "phone-ap", web: "phone-web", phone: "phone", } as const; const COMMANDS = { status: "Show service status", logs: "Show recent logs (last 50 lines)", tail: "Tail logs in real-time", restart: "Restart service (requires sudo)", stop: "Stop service (requires sudo)", start: "Start service (requires sudo)", } as const; const showHelp = () => { console.log(` Phone CLI - Service Management Usage: cli SERVICE COMMAND [-v] Services: ap WiFi AP Monitor (phone-ap.service) web Web Server (phone-web.service) phone Phone Application (phone.service) Commands: status Show service status logs Show recent logs (last 50 lines) tail Tail logs in real-time restart Restart service (requires sudo) stop Stop service (requires sudo) start Start service (requires sudo) Options: -v Verbose mode - show actual systemd commands Examples: cli ap status cli web logs cli phone tail cli -v ap status sudo cli ap restart `); }; // Parse arguments const args = process.argv.slice(2); // Check for help if (args.length === 0 || args[0] === "help") { showHelp(); process.exit(0); } // Extract verbose flag and remaining args const verbose = args.includes("-v"); const [service, command] = args.filter(arg => arg !== "-v"); // Validate service if (!service || !(service in SERVICES)) { console.error(`āŒ Unknown service: ${service || "(missing)"}`); console.log(`Available services: ${Object.keys(SERVICES).join(", ")}`); process.exit(1); } // Validate command if (!command || !(command in COMMANDS)) { console.error(`āŒ Unknown command: ${command || "(missing)"}`); console.log(`Available commands: ${Object.keys(COMMANDS).join(", ")}`); process.exit(1); } // Get systemd service name const serviceName = SERVICES[service as keyof typeof SERVICES]; // Execute command console.log(`\nšŸ”§ Phone CLI - ${service} ${command}\n`); const logCommand = (cmd: string) => { if (verbose) { console.log(`→ ${cmd}\n`); } }; switch (command) { case "status": logCommand(`systemctl status ${serviceName}.service --no-pager -l`); await $`systemctl status ${serviceName}.service --no-pager -l`.nothrow(); break; case "logs": console.log(`šŸ“‹ Recent logs (last 50 lines):\n`); logCommand(`journalctl -u ${serviceName}.service -n 50 --no-pager`); await $`journalctl -u ${serviceName}.service -n 50 --no-pager`.nothrow(); break; case "tail": console.log(`šŸ“” Tailing logs (Ctrl+C to stop)...\n`); logCommand(`journalctl -u ${serviceName}.service -f --no-pager`); await $`journalctl -u ${serviceName}.service -f --no-pager`.nothrow(); break; case "restart": console.log(`šŸ”„ Restarting ${serviceName}.service...\n`); logCommand(`sudo systemctl restart ${serviceName}.service`); await $`sudo systemctl restart ${serviceName}.service`; console.log(`āœ“ ${serviceName}.service restarted!`); break; case "stop": console.log(`šŸ›‘ Stopping ${serviceName}.service...\n`); logCommand(`sudo systemctl stop ${serviceName}.service`); await $`sudo systemctl stop ${serviceName}.service`; console.log(`āœ“ ${serviceName}.service stopped!`); break; case "start": console.log(`ā–¶ļø Starting ${serviceName}.service...\n`); logCommand(`sudo systemctl start ${serviceName}.service`); await $`sudo systemctl start ${serviceName}.service`; console.log(`āœ“ ${serviceName}.service started!`); break; } console.log("");