From 3f170b8ec710d407d5c8e414d2ec287cddfea5b4 Mon Sep 17 00:00:00 2001 From: TinyAGI Date: Tue, 24 Mar 2026 20:53:40 +0000 Subject: [PATCH 1/2] Harden API port handling and startup logging --- packages/main/src/index.ts | 9 ++++++++- packages/server/src/index.ts | 13 ++++++++++--- zoobot-office/src/lib/api.ts | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index afa0fe5..9ce959a 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts @@ -8,6 +8,7 @@ import fs from 'fs'; import path from 'path'; +import http from 'http'; import { MessageJobData, getSettings, getAgents, getTeams, LOG_FILE, FILES_DIR, @@ -214,7 +215,13 @@ function logAgentConfig(): void { initQueueDb(); -const apiServer = startApiServer(); +let apiServer: http.Server; +try { + apiServer = startApiServer(); +} catch (error) { + log('ERROR', `Failed to start API server: ${(error as Error).message}`); + process.exit(1); +} // Event-driven: process queue when a new message arrives queueEvents.on('message:enqueued', () => processQueue()); diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index fbc437b..f21d5c7 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -28,7 +28,14 @@ import agentMessagesRoutes from './routes/agent-messages'; import servicesRoutes from './routes/services'; import schedulesRoutes from './routes/schedules'; -const API_PORT = parseInt(process.env.ZOOBOT_API_PORT || '3777', 10); +export function resolveApiPort(): number { + const raw = process.env.ZOOBOT_API_PORT || '3777'; + const port = parseInt(raw, 10); + if (!Number.isInteger(port) || port < 1 || port > 65535) { + throw new Error(`Invalid ZOOBOT_API_PORT: ${raw}`); + } + return port; +} /** * Create and start the API server. @@ -84,9 +91,9 @@ export function startApiServer(): http.Server { const server = serve({ fetch: app.fetch, - port: API_PORT, + port: resolveApiPort(), }, () => { - log('INFO', `API server listening on http://localhost:${API_PORT}`); + log('INFO', `API server listening on http://localhost:${resolveApiPort()}`); }); return server as unknown as http.Server; diff --git a/zoobot-office/src/lib/api.ts b/zoobot-office/src/lib/api.ts index ea3e97c..ac1269d 100644 --- a/zoobot-office/src/lib/api.ts +++ b/zoobot-office/src/lib/api.ts @@ -1,4 +1,4 @@ -const DEFAULT_API_BASE = "http://localhost:3777"; +const DEFAULT_API_BASE = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3777"; const STORAGE_KEY = "zoobot_api_base"; /** Resolve the API base URL. Priority: env > localStorage > default. */ From ac4fa361148615c9269ec25990241751d67a7cab Mon Sep 17 00:00:00 2001 From: TinyAGI Date: Tue, 24 Mar 2026 21:00:25 +0000 Subject: [PATCH 2/2] Fix ZooOffice standalone start command --- zoobot-office/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zoobot-office/package.json b/zoobot-office/package.json index d718be5..1b55f64 100644 --- a/zoobot-office/package.json +++ b/zoobot-office/package.json @@ -4,7 +4,7 @@ "scripts": { "dev": "next dev --webpack", "build": "next build", - "start": "next start", + "start": "node .next/standalone/zoobot-office/server.js", "lint": "eslint" }, "dependencies": {