#!/usr/bin/env node /** * Server Manager Script for Maven Integration * Handles starting and stopping the React development server */ const { spawn, exec } = require('child_process'); const fs = require('fs'); const path = require('path'); const PID_FILE = path.join(__dirname, '..', '.react-server.pid'); const PORT = process.env.PORT || 3001; function writePidFile(pid) { fs.writeFileSync(PID_FILE, pid.toString()); } function readPidFile() { try { return fs.readFileSync(PID_FILE, 'utf8').trim(); } catch (error) { return null; } } function deletePidFile() { try { fs.unlinkSync(PID_FILE); } catch (error) { // Ignore if file doesn't exist } } function isServerRunning(pid) { try { process.kill(pid, 0); return true; } catch (error) { return false; } } function waitForServer(maxAttempts = 30, interval = 1000) { return new Promise((resolve, reject) => { let attempts = 0; // Detect CI environment for different behavior const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true' || process.env.QQQ_SELENIUM_HEADLESS === 'true'; if (isCI) { console.log('šŸ” CI environment detected - using extended server wait parameters'); maxAttempts = Math.max(maxAttempts, 60); // Minimum 60 attempts in CI interval = Math.max(interval, 2000); // Minimum 2 second intervals in CI } const checkServer = () => { attempts++; // Use curl to check if server is ready (more reliable for HTTPS) const { exec } = require('child_process'); const curlCommand = `curl -k -s -o /dev/null -w "%{http_code}" https://localhost:${PORT}`; exec(curlCommand, (error, stdout, stderr) => { if (stdout && stdout.trim() !== '000') { console.log(`āœ… React server is ready on port ${PORT} (HTTP ${stdout.trim()}) after ${attempts} attempts`); resolve(); } else if (attempts >= maxAttempts) { reject(new Error(`Server failed to start after ${maxAttempts} attempts (${maxAttempts * interval / 1000} seconds)`)); } else { // Log every 5th attempt, or every attempt in CI if (attempts % 5 === 0 || isCI) { console.log(`ā³ Waiting for React server on port ${PORT}... (attempt ${attempts}/${maxAttempts})`); if (isCI && attempts > 10) { console.log(` Error details: ${error ? error.message : 'Connection refused'}`); } } setTimeout(checkServer, interval); } }); }; checkServer(); }); } function startServer() { console.log('šŸš€ Starting React development server...'); // Detect CI environment for different behavior const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true' || process.env.QQQ_SELENIUM_HEADLESS === 'true'; if (isCI) { console.log('šŸ” CI environment detected - using enhanced startup process'); } // Start the server in the background and exit immediately const child = spawn('npm', ['start'], { stdio: 'ignore', // Don't capture output - let it run independently detached: true, // Detach from parent process env: { ...process.env, BROWSER: 'none', PORT: PORT, HTTPS: 'true', GENERATE_SOURCEMAP: 'false', FAST_REFRESH: 'false' } }); writePidFile(child.pid); console.log(`šŸ“‹ Server PID: ${child.pid}`); console.log('šŸš€ React server started in background'); // Unref so parent can exit without killing child child.unref(); // Exit immediately - server runs in background process.exit(0); } function stopServer() { console.log('šŸ›‘ Stopping React development server...'); const pid = readPidFile(); if (pid && isServerRunning(pid)) { try { process.kill(pid, 'SIGTERM'); console.log(`āœ… Stopped server (PID: ${pid})`); } catch (error) { console.error('āŒ Failed to stop server:', error.message); } } else { console.log('ā„¹ļø No running server found'); } deletePidFile(); } function waitForServerOnly() { console.log('ā³ Waiting for React server to be ready...'); const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true' || process.env.QQQ_SELENIUM_HEADLESS === 'true'; const maxAttempts = isCI ? 60 : 30; const interval = isCI ? 2000 : 1000; if (isCI) { console.log('šŸ” CI environment detected - using extended wait parameters'); } waitForServer(maxAttempts, interval) .then(() => { console.log('āœ… React server is ready for integration tests'); process.exit(0); }) .catch((error) => { console.error('āŒ Server wait failed:', error.message); process.exit(1); }); } // Handle command line arguments const command = process.argv[2]; switch (command) { case 'start': startServer(); break; case 'stop': stopServer(); break; case 'wait': waitForServerOnly(); break; default: console.log('Usage: node server-manager.js [start|stop|wait]'); process.exit(1); } // Handle process termination process.on('SIGINT', () => { console.log('\nšŸ›‘ Received SIGINT, stopping server...'); stopServer(); process.exit(0); }); process.on('SIGTERM', () => { console.log('\nšŸ›‘ Received SIGTERM, stopping server...'); stopServer(); process.exit(0); });