Add daemonUrl config for remote daemon support

- Add optional daemonUrl field to RoutstrdConfig
- Update callDaemon and isDaemonRunning to use configurable base URL
- Disable auto-start when daemonUrl is set (Option A)
- Gate local-only commands: onboard, start, restart, mode, logs, service install
This commit is contained in:
redshift
2026-04-28 09:26:50 +05:30
parent b6520b5ef0
commit 7dfed2c052
3 changed files with 30 additions and 2 deletions
+16
View File
@@ -95,6 +95,16 @@ async function installCocodOrExit(): Promise<void> {
logger.log("cocod installed successfully.");
}
async function requireLocalDaemon(): Promise<void> {
const config = await loadConfig();
if (config.daemonUrl) {
console.error(
`This command is not available when using a remote daemon (${config.daemonUrl}).`,
);
process.exit(1);
}
}
async function initDaemon(): Promise<void> {
logger.log("Initializing routstrd...");
@@ -292,6 +302,7 @@ program
"Initialize routstrd (creates config directory and initializes cocod)",
)
.action(async () => {
await requireLocalDaemon();
await initDaemon();
});
@@ -302,6 +313,7 @@ program
.option("--port <port>", "Port to listen on")
.option("-p, --provider <provider>", "Default provider to use")
.action(async (options: { port?: string; provider?: string }) => {
await requireLocalDaemon();
const config = await loadConfig();
if (!(await isCocodInstalled(config.cocodPath))) {
const installHint = config.cocodPath
@@ -1103,6 +1115,7 @@ serviceCmd
.command("install")
.description("Install and start routstrd using PM2 for persistence")
.action(async () => {
await requireLocalDaemon();
// 1. Check if PM2 is installed
try {
execSync("pm2 -v", { stdio: "ignore" });
@@ -1184,6 +1197,7 @@ program
.option("--port <port>", "Port to listen on")
.option("-p, --provider <provider>", "Default provider to use")
.action(async (options: { port?: string; provider?: string }) => {
await requireLocalDaemon();
const config = await loadConfig();
const wasRunning = await isDaemonRunning();
@@ -1221,6 +1235,7 @@ program
.command("mode")
.description("Set the client mode (lazyrefund/apikeys or xcashu)")
.action(async () => {
await requireLocalDaemon();
const config = await loadConfig();
const currentMode = config.mode || "apikeys";
@@ -1311,6 +1326,7 @@ program
.option("-f, --follow", "Follow log output", false)
.option("-n, --lines <number>", "Number of lines to show", "50")
.action(async (options: { follow: boolean; lines: string }) => {
await requireLocalDaemon();
const todayFile = getLogFileForDate();
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
+1
View File
@@ -12,6 +12,7 @@ export interface RoutstrdConfig {
provider: string | null;
cocodPath: string | null;
mode?: "xcashu" | "apikeys";
daemonUrl?: string;
}
export const DEFAULT_CONFIG: RoutstrdConfig = {
+13 -2
View File
@@ -23,14 +23,19 @@ export async function loadConfig(): Promise<RoutstrdConfig> {
return DEFAULT_CONFIG;
}
function getDaemonBaseUrl(config: RoutstrdConfig): string {
return config.daemonUrl?.replace(/\/$/, "") || `http://localhost:${config.port}`;
}
export async function callDaemon(
path: string,
options: { method?: "GET" | "POST"; body?: object } = {},
): Promise<CommandResponse> {
const { method = "GET", body } = options;
const config = await loadConfig();
const baseUrl = getDaemonBaseUrl(config);
const response = await fetch(`http://localhost:${config.port}${path}`, {
const response = await fetch(`${baseUrl}${path}`, {
method,
headers: body ? { "Content-Type": "application/json" } : {},
body: body ? JSON.stringify(body) : undefined,
@@ -47,7 +52,8 @@ export async function callDaemon(
export async function isDaemonRunning(): Promise<boolean> {
try {
const config = await loadConfig();
const response = await fetch(`http://localhost:${config.port}/health`);
const baseUrl = getDaemonBaseUrl(config);
const response = await fetch(`${baseUrl}/health`);
return response.ok;
} catch {
return false;
@@ -84,6 +90,11 @@ export async function ensureDaemonRunning(): Promise<void> {
return;
}
const config = await loadConfig();
if (config.daemonUrl) {
throw new Error(`Daemon is not reachable at ${config.daemonUrl}`);
}
console.log("Starting daemon...");
await startDaemonProcess();
}