const path = require('node:path'); const { spawnSync } = require('node:child_process'); const { createLogger, isVerbose, startTimer } = require('../src/generator/utils/logger'); const { startServer } = require('./serve-dist'); const log = createLogger('dev'); let serverRef = null; let shuttingDown = false; function runNode(scriptPath) { const result = spawnSync(process.execPath, [scriptPath], { stdio: 'inherit' }); return result && Number.isFinite(result.status) ? result.status : 1; } function closeServer(server, exitCode) { if (!server) { process.exit(exitCode); return; } try { if (typeof server.closeIdleConnections === 'function') server.closeIdleConnections(); if (typeof server.closeAllConnections === 'function') server.closeAllConnections(); } catch { // ignore } const forceTimer = setTimeout(() => process.exit(exitCode), 2000); if (typeof forceTimer.unref === 'function') forceTimer.unref(); server.close(() => { clearTimeout(forceTimer); process.exit(exitCode); }); } async function main() { const elapsedMs = startTimer(); log.info('开始', { version: process.env.npm_package_version }); const repoRoot = path.resolve(__dirname, '..'); // best-effort:同步失败不阻断 dev const syncProjectsExit = runNode(path.join(repoRoot, 'scripts', 'sync-projects.js')); if (syncProjectsExit !== 0) log.warn('sync-projects 异常退出,已继续(best-effort)', { exit: syncProjectsExit }); const syncHeatmapExit = runNode(path.join(repoRoot, 'scripts', 'sync-heatmap.js')); if (syncHeatmapExit !== 0) log.warn('sync-heatmap 异常退出,已继续(best-effort)', { exit: syncHeatmapExit }); const syncArticlesExit = runNode(path.join(repoRoot, 'scripts', 'sync-articles.js')); if (syncArticlesExit !== 0) log.warn('sync-articles 异常退出,已继续(best-effort)', { exit: syncArticlesExit }); const generatorExit = runNode(path.join(repoRoot, 'src', 'generator.js')); if (generatorExit !== 0) { log.error('生成失败', { exit: generatorExit }); process.exitCode = generatorExit; return; } const portRaw = process.env.PORT || process.env.MENAV_PORT || '5173'; const port = Number.parseInt(portRaw, 10) || 5173; const { server, port: actualPort } = await startServer({ rootDir: path.join(repoRoot, 'dist'), host: process.env.HOST || '0.0.0.0', port, }); serverRef = server; log.ok('就绪', { ms: elapsedMs(), url: `http://localhost:${actualPort}` }); const shutdown = (signal) => { if (shuttingDown) return; shuttingDown = true; process.stdout.write('\n'); log.info('正在关闭...', { signal }); process.once('SIGINT', () => process.exit(130)); const exit = signal === 'SIGINT' ? 130 : 0; closeServer(serverRef, exit); }; process.once('SIGINT', () => shutdown('SIGINT')); process.once('SIGTERM', () => shutdown('SIGTERM')); } if (require.main === module) { main().catch((error) => { log.error('启动失败', { message: error && error.message ? error.message : String(error) }); if (isVerbose() && error && error.stack) console.error(error.stack); process.exitCode = 1; }); }