one
Version:
One is a React framework for web, iOS, and Android apps.
173 lines (170 loc) • 6.78 kB
JavaScript
import colors from "picocolors";
import { labelProcess } from "./label-process.mjs";
async function daemon(args) {
const subcommand = args.subcommand || "run";
switch (subcommand) {
case "run":
case "start": return daemonStart(args);
case "stop": return daemonStop();
case "status": return daemonStatus();
case "route": return daemonRoute(args);
default:
console.log(`Unknown daemon subcommand: ${subcommand}`);
console.log("Available: start, stop, status, route");
process.exit(1);
}
}
async function daemonStart(args) {
labelProcess("daemon");
const { isDaemonRunning } = await import("../daemon/ipc.mjs");
if (await isDaemonRunning()) {
console.log(colors.yellow("Daemon is already running"));
console.log("Use 'one daemon status' to see registered servers");
process.exit(1);
}
await suggestTrayApp();
const { startDaemon } = await import("../daemon/server.mjs");
const useTUI = args.tui ?? process.stdin.isTTY;
const { state } = await startDaemon({
port: args.port ? parseInt(args.port, 10) : void 0,
host: args.host,
quiet: useTUI
});
if (useTUI) {
const { startTUI } = await import("../daemon/tui.mjs");
startTUI(state);
}
}
async function daemonStop() {
const { isDaemonRunning, getSocketPath } = await import("../daemon/ipc.mjs");
if (!await isDaemonRunning()) {
console.log(colors.yellow("Daemon is not running"));
process.exit(1);
}
console.log(colors.yellow("Note: daemon runs in foreground. Press Ctrl+C in the daemon terminal to stop."));
console.log(colors.dim(`Socket path: ${getSocketPath()}`));
}
async function daemonStatus() {
const { isDaemonRunning, getDaemonStatus, getLastActiveDaemonServer } = await import("../daemon/ipc.mjs");
if (!await isDaemonRunning()) {
console.log(colors.yellow("Daemon is not running"));
console.log(colors.dim("Start with 'one daemon'"));
process.exit(1);
}
try {
const status = await getDaemonStatus();
const lastActive = await getLastActiveDaemonServer();
console.log(colors.cyan("\n═══════════════════════════════════════════════════"));
console.log(colors.cyan(" one daemon status"));
console.log(colors.cyan("═══════════════════════════════════════════════════\n"));
if (status.servers.length === 0) {
console.log(colors.dim(" No servers registered"));
} else {
console.log(" Registered servers:");
for (const server of status.servers) {
const shortRoot = server.root.replace(process.env.HOME || "", "~");
const isActive = lastActive?.id === server.id;
const activeMarker = isActive ? colors.yellow(" ★") : "";
console.log(` ${colors.green(server.id)} ${server.bundleId} \u2192 :${server.port} (${shortRoot})${activeMarker}`);
}
if (lastActive) {
console.log(colors.dim("\n ★ = last active (used by oi/oa)"));
}
}
if (status.routes.length > 0) {
console.log("\n Active routes:");
for (const route of status.routes) {
console.log(` ${route.key} \u2192 ${route.serverId}`);
}
}
console.log("");
} catch (err) {
console.log(colors.red("Failed to get daemon status"));
console.error(err);
process.exit(1);
}
}
async function openPlatform(platform) {
const { isDaemonRunning, getDaemonStatus, setDaemonRoute, touchDaemonServer } = await import("../daemon/ipc.mjs");
const { getBundleIdFromConfig } = await import("../daemon/utils.mjs");
const cwd = process.cwd();
const bundleId = getBundleIdFromConfig(cwd);
if (!bundleId) {
console.log(colors.yellow("No app.json found in current directory"));
console.log(colors.dim("Run this command from a One project directory"));
process.exit(1);
}
if (await isDaemonRunning()) {
try {
const status = await getDaemonStatus();
const server = status.servers.find((s) => s.root === cwd);
if (server) {
await setDaemonRoute(bundleId, server.id);
await touchDaemonServer(server.id);
console.log(colors.cyan(`[daemon] Route set: ${bundleId} \u2192 this project`));
} else {
console.log(colors.yellow(`[daemon] No server registered for this project`));
console.log(colors.dim(`Run 'one dev' first, or the simulator will connect directly`));
}
} catch (err) {
console.log(colors.dim(`[daemon] Could not set route: ${err}`));
}
}
if (platform === "ios") {
const { run } = await import("./runIos.mjs");
await run({});
} else {
const { run } = await import("./runAndroid.mjs");
await run({});
}
}
async function daemonRoute(args) {
const { isDaemonRunning, getDaemonStatus, setDaemonRoute } = await import("../daemon/ipc.mjs");
if (!await isDaemonRunning()) {
console.log(colors.yellow("Daemon is not running"));
process.exit(1);
}
if (!args.app) {
console.log(colors.red("Missing --app parameter"));
console.log("Usage: one daemon route --app=com.example.app --slot=0");
console.log(" or: one daemon route --app=com.example.app --project=~/myapp");
process.exit(1);
}
const status = await getDaemonStatus();
let targetServer;
if (args.slot !== void 0) {
const slotIndex = parseInt(args.slot, 10);
const matchingServers = status.servers.filter((s) => s.bundleId === args.app);
if (slotIndex < 0 || slotIndex >= matchingServers.length) {
console.log(colors.red(`Invalid slot: ${args.slot}`));
console.log(`Available slots for ${args.app}: 0-${matchingServers.length - 1}`);
process.exit(1);
}
targetServer = matchingServers[slotIndex];
} else if (args.project) {
const normalizedProject = args.project.replace(/^~/, process.env.HOME || "");
targetServer = status.servers.find((s) => s.bundleId === args.app && s.root === normalizedProject);
if (!targetServer) {
console.log(colors.red(`No server found for ${args.app} at ${args.project}`));
process.exit(1);
}
} else {
console.log(colors.red("Missing --slot or --project parameter"));
process.exit(1);
}
await setDaemonRoute(args.app, targetServer.id);
const shortRoot = targetServer.root.replace(process.env.HOME || "", "~");
console.log(colors.green(`Route set: ${args.app} \u2192 ${targetServer.id} (${shortRoot})`));
}
async function suggestTrayApp() {
const { existsSync } = await import("node:fs");
const trayPaths = ["/Applications/OneTray.app", `${process.env.HOME}/Applications/OneTray.app`];
const installed = trayPaths.some((p) => existsSync(p));
if (!installed) {
console.log(colors.dim(" Tip: install OneTray.app for a native macOS cable interface"));
console.log(colors.dim(" https://github.com/onejs/one/releases?q=one-tray"));
console.log("");
}
}
export { daemon, openPlatform };
//# sourceMappingURL=daemon.mjs.map