import { Hono } from 'hono'; import { serveStatic } from 'hono/bun'; import { spawn } from 'bun'; import fs from 'fs'; // Configuration const MODES_DIR = '/home/admin/Job-Info-Test'; const MODE_CONFIG_FILE = `${MODES_DIR}/ModeSwitch/activeMode.txt`; const SHARED_PORT = 3005; const ORCHESTRATOR_PORT = 3006; // Mode folder mappings const MODE_FOLDERS: Record = { 'Mode1Test': 'Mode1Test', 'Mode2Test': 'Mode2Test', }; let currentMode: string = 'Mode1Test'; let currentProcess: any = null; // Helper: Read active mode from config file function readActiveMode(): string { try { if (fs.existsSync(MODE_CONFIG_FILE)) { const content = fs.readFileSync(MODE_CONFIG_FILE, 'utf-8').trim(); return content || 'Test1Mode'; } } catch (err) { console.error('Failed to read mode config:', err); } return 'Mode1Test'; } // Helper: Write active mode to config file function writeActiveMode(mode: string): void { try { fs.writeFileSync(MODE_CONFIG_FILE, mode, 'utf-8'); } catch (err) { console.error('Failed to write mode config:', err); } } // Helper: Kill process on shared port async function killProcessOnPort(port: number): Promise { try { await Bun.spawn({ cmd: ['pkill', '-f', `bun.*:${port}`], stdout: 'ignore', stderr: 'ignore', }); // Fallback: Try to kill any Bun process we spawned if (currentProcess) { currentProcess.kill(); currentProcess = null; } // Give OS time to release the port await new Promise(resolve => setTimeout(resolve, 500)); } catch (err) { console.error(`Failed to kill process on port ${port}:`, err); } } // Helper: Start a mode async function startMode(mode: string): Promise { try { // Kill any existing process await killProcessOnPort(SHARED_PORT); const folderName = MODE_FOLDERS[mode]; if (!folderName) { console.error(`Unknown mode: ${mode}`); return false; } const modePath = `${MODES_DIR}/${folderName}`; if (!fs.existsSync(modePath)) { console.error(`Mode folder not found: ${modePath}`); return false; } console.log(`[ModeSwitch] Starting ${mode} (${folderName}/) on port ${SHARED_PORT}...`); // Determine server path based on mode // Mode2Test uses AuthAndToken/backend/server.ts // Mode1Test uses backend/server.ts let serverPath = 'backend/server.ts'; if (mode === 'Mode2Test') { serverPath = 'AuthAndToken/backend/server.ts'; } // Start the mode's backend server currentProcess = Bun.spawn({ cmd: ['bun', 'run', serverPath], cwd: modePath, stdout: 'pipe', stderr: 'pipe', env: { ...process.env, PORT: String(SHARED_PORT), }, }); currentMode = mode; writeActiveMode(mode); // Read and log output from the spawned process if (currentProcess.stdout) { (async () => { const reader = currentProcess.stdout.getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; console.log(`[${mode}]`, new TextDecoder().decode(value)); } })(); } console.log(`✓ ${mode} started successfully on port ${SHARED_PORT}`); return true; } catch (err) { console.error(`Failed to start ${mode}:`, err); return false; } } // Initialize app const app = new Hono(); // Health check app.get('/health', (c) => { return c.json({ status: 'ok', orchestratorPort: ORCHESTRATOR_PORT, sharedPort: SHARED_PORT }); }); // Get current mode app.get('/api/mode', (c) => { return c.json({ currentMode, availableModes: ['Mode1Test', 'Mode2Test'] }); }); // Switch mode (with graceful restart) app.post('/api/mode/switch/:mode', async (c) => { const newMode = c.req.param('mode'); const validModes = ['Mode1Test', 'Mode2Test']; if (!validModes.includes(newMode)) { return c.json({ error: 'Invalid mode', availableModes: validModes }, 400); } if (newMode === currentMode) { return c.json({ message: 'Already in this mode', currentMode }); } const success = await startMode(newMode); if (success) { return c.json({ message: 'Mode switched successfully', currentMode: newMode }); } else { return c.json({ error: 'Failed to switch mode' }, 500); } }); // Startup message console.log(` ================================================================================ [ModeSwitch Orchestrator] ================================================================================ Listening on port: ${ORCHESTRATOR_PORT} Shared mode port: ${SHARED_PORT} Config file: ${MODE_CONFIG_FILE} ================================================================================ `); // Start initial mode const initialMode = readActiveMode(); await startMode(initialMode); // Export for Bun export default { port: ORCHESTRATOR_PORT, fetch: app.fetch, };