// Раздача собранного фронта. Панель — один процесс и один образ: сервер сам // отдаёт frontend/dist, отдельный nginx ей не нужен. // // Монтируется последним, после всех API-маршрутов: fallback отвечает на любой // GET, поэтому маршрут, зарегистрированный после него, уже не сработает. import express, { type Express, type Request, type Response } from 'express'; import fs from 'node:fs'; import path from 'node:path'; // Пути под этими префиксами получают 404, а не index.html: иначе опечатка в // адресе API возвращает HTML со статусом 200, и клиент падает на разборе JSON // вместо внятной ошибки. const API_PREFIXES = ['/api']; export function serveSpa(app: Express, dir: string) { const root = path.resolve(dir); if (!fs.existsSync(path.join(root, 'index.html'))) { console.warn(`panel-server: в ${root} нет index.html — фронт не собран (npm run build) ` + 'или STATIC_DIR указывает не туда'); } app.use(express.static(root)); app.get('*', (req: Request, res: Response) => { if (API_PREFIXES.some(p => req.path.startsWith(p))) { res.status(404).json({ message: 'Не найдено' }); return; } res.sendFile(path.join(root, 'index.html')); }); }