#!/usr/bin/env node import { spawn } from 'node:child_process'; import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..'); const portalPort = Number(process.env.H5_PORT ?? 8081); const portalUrl = `http://127.0.0.1:${portalPort}`; function loadEnvFile(filePath) { if (!fs.existsSync(filePath)) return; for (const line of fs.readFileSync(filePath, 'utf8').split('\n')) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#')) continue; const eq = trimmed.indexOf('='); if (eq < 0) continue; const key = trimmed.slice(0, eq).trim(); const value = trimmed.slice(eq + 1).trim(); if (!process.env[key]) process.env[key] = value; } } loadEnvFile(path.join(root, '../../.env.local')); loadEnvFile(path.join(root, '.env')); function spawnChild(command, args, label) { const child = spawn(command, args, { cwd: root, env: process.env, stdio: 'inherit', }); child.on('exit', (code, signal) => { if (signal) return; if (code && code !== 0) { console.error(`[${label}] exited with code ${code}`); shutdown(code ?? 1); } }); return child; } let server; let vite; let stopping = false; function shutdown(code = 0) { if (stopping) return; stopping = true; server?.kill('SIGTERM'); vite?.kill('SIGTERM'); setTimeout(() => process.exit(code), 300); } process.on('SIGINT', () => shutdown(0)); process.on('SIGTERM', () => shutdown(0)); async function waitForPortal(retries = 40) { for (let i = 0; i < retries; i += 1) { try { const res = await fetch(`${portalUrl}/auth/status`); if (res.ok) return; } catch { // portal still starting } await new Promise((resolve) => setTimeout(resolve, 250)); } throw new Error(`Portal 未在 ${portalUrl} 启动,请检查 MySQL 配置与 ${portalPort} 端口`); } console.log('==> 启动 portal (server.mjs)...'); server = spawnChild('node', ['server.mjs'], 'portal'); try { await waitForPortal(); console.log(`==> Portal 就绪: ${portalUrl}`); console.log('==> 启动 Vite @ http://127.0.0.1:5173'); console.log('==> 我的空间 UI 预览: http://127.0.0.1:5173/?preview=mindspace'); vite = spawnChild('npx', ['vite'], 'vite'); } catch (err) { console.error(err instanceof Error ? err.message : err); shutdown(1); }