import { spawn } from 'child_process'; import { existsSync, copyFileSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const backendDir = join(__dirname, 'backend'); const frontendDir = join(__dirname, 'frontend'); const backendEnv = join(backendDir, '.env'); const backendEnvExample = join(backendDir, '.env.example'); if (!existsSync(backendEnv) && existsSync(backendEnvExample)) { console.log('Creating .env from .env.example...'); copyFileSync(backendEnvExample, backendEnv); console.log('Please edit backend/.env and add your DASHSCOPE_API_KEY and DASHSCOPE_APP_ID'); } const BACKEND_URL = 'http://localhost:3101'; const HEALTH_ENDPOINT = `${BACKEND_URL}/api/health`; function waitForBackend(maxRetries = 30, interval = 1000) { return new Promise((resolve, reject) => { let retries = 0; const check = async () => { try { const response = await fetch(HEALTH_ENDPOINT); if (response.ok) { console.log('Backend is ready!'); resolve(true); return; } } catch { } retries++; if (retries >= maxRetries) { reject(new Error('Backend failed to start')); return; } setTimeout(check, interval); }; check(); }); } function startBackend() { console.log('Starting backend...'); const backend = spawn('pnpm', ['dev'], { cwd: backendDir, shell: true, stdio: 'pipe' }); backend.stdout.on('data', (data) => { process.stdout.write(`[backend] ${data}`); }); backend.stderr.on('data', (data) => { process.stderr.write(`[backend] ${data}`); }); backend.on('close', (code) => { if (code !== 0) { console.error(`Backend process exited with code ${code}`); } process.exit(code); }); return backend; } function startFrontend() { console.log('Starting frontend...'); const frontend = spawn('pnpm', ['start'], { cwd: frontendDir, shell: true, stdio: 'pipe' }); frontend.stdout.on('data', (data) => { process.stdout.write(`[frontend] ${data}`); }); frontend.stderr.on('data', (data) => { process.stderr.write(`[frontend] ${data}`); }); frontend.on('close', (code) => { if (code !== 0) { console.error(`Frontend process exited with code ${code}`); } process.exit(code); }); return frontend; } async function main() { console.log('=== Starting Dev Server ===\n'); const backend = startBackend(); try { await waitForBackend(); startFrontend(); } catch (error) { console.error(error.message); backend.kill(); process.exit(1); } } main();