ma7engine: ядро, шаблон панели, скаффолдер и доктор
Первый коммит существующего состояния. Ядро кладётся под git ради того, чтобы половины разъезжались в продуктовые репозитории через git subtree, а не копированием: subtree делает настоящий merge, хранит историю и умеет отдавать правки обратно. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LeBkZLiQrvdECf5nfgiMz
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
// Раздача собранного фронта. Панель — один процесс и один образ: сервер сам
|
||||
// отдаёт 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'));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user