import express from 'express'; import compression from 'compression'; import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROOT = path.resolve(__dirname, '..'); const DIST = path.join(ROOT, 'dist'); const DATA = path.join(ROOT, 'data'); const UPLOADS = path.join(ROOT, 'public', 'uploads'); const NEWS_FILE = path.join(DATA, 'news.json'); const PORT = Number(process.env.PORT) || 3000; const app = express(); app.disable('x-powered-by'); app.use(compression()); app.get('/api/health', (_req, res) => res.json({ ok: true, ts: Date.now() })); app.get('/api/news.json', (_req, res) => { try { if (!fs.existsSync(NEWS_FILE)) { return res.json({ updatedAt: null, items: [] }); } const stat = fs.statSync(NEWS_FILE); res.setHeader('Cache-Control', 'public, max-age=300'); res.setHeader('Last-Modified', stat.mtime.toUTCString()); res.sendFile(NEWS_FILE); } catch (e) { res.status(500).json({ error: e.message }); } }); app.use('/uploads', express.static(UPLOADS, { maxAge: '7d', fallthrough: true })); const FEED_FILE = path.join(DIST, 'feed.xml'); app.get(['/feed', '/feed/', '/feed/rss2', '/feed/rss2/', '/rss', '/rss.xml'], (_req, res) => { res.type('application/rss+xml; charset=utf-8'); res.sendFile(FEED_FILE); }); app.use(express.static(DIST, { maxAge: '1h', etag: true })); app.get('*', (req, res) => { const candidate = path.join(DIST, req.path, 'index.html'); if (fs.existsSync(candidate)) { return res.sendFile(candidate); } res.status(200).sendFile(path.join(DIST, 'index.html')); }); app.listen(PORT, () => { console.log(`pushkinohistory-ru-v2 listening on :${PORT}`); });