import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { resolve } from 'node:path'; import { readFile, stat } from 'node:fs/promises'; const MANAGED_CATALOG_API_PATH = '/api/managed-stations.json'; async function loadManagedCatalogEnvelope(repoRoot) { const candidates = [ resolve(repoRoot, 'public', 'stations.json'), resolve(repoRoot, 'dist', 'stations.json'), resolve(repoRoot, 'stations.json'), ]; let found = null; for (const p of candidates) { try { const s = await stat(p); if (s.isFile()) { found = { filePath: p, mtime: s.mtime }; break; } } catch { /* try next */ } } if (!found) throw new Error('Managed catalog source file was not found.'); const raw = JSON.parse(await readFile(found.filePath, 'utf8')); const stations = Array.isArray(raw) ? raw : raw.stations; return { schemaVersion: 1, updatedAt: found.mtime.toISOString(), stations }; } const buildStamp = `${Date.now()}`; function managedCatalogApiPlugin() { async function handleManagedCatalogRequest(req, res, next) { if (!req.url) { next(); return; } const requestUrl = new URL(req.url, 'http://127.0.0.1'); if (requestUrl.pathname !== MANAGED_CATALOG_API_PATH) { next(); return; } try { const payload = await loadManagedCatalogEnvelope(process.cwd()); res.statusCode = 200; res.setHeader('content-type', 'application/json; charset=utf-8'); res.setHeader('cache-control', 'no-store'); res.end(`${JSON.stringify(payload)}\n`); } catch (error) { res.statusCode = 500; res.setHeader('content-type', 'application/json; charset=utf-8'); res.end(JSON.stringify({ error: 'Failed to load managed catalog', message: error instanceof Error ? error.message : 'Unknown error', })); } } return { name: 'managed-catalog-api', configureServer(server) { server.middlewares.use((req, res, next) => { void handleManagedCatalogRequest(req, res, next); }); }, configurePreviewServer(server) { server.middlewares.use((req, res, next) => { void handleManagedCatalogRequest(req, res, next); }); }, }; } export default defineConfig({ plugins: [react(), managedCatalogApiPlugin()], base: './', build: { rollupOptions: { input: { main: resolve(process.cwd(), 'index.html'), privacy: resolve(process.cwd(), 'privacy.html'), }, output: { entryFileNames: `assets/[name]-${buildStamp}-[hash].js`, chunkFileNames: `assets/[name]-${buildStamp}-[hash].js`, assetFileNames: `assets/[name]-${buildStamp}-[hash][extname]`, }, }, }, server: { host: '127.0.0.1', port: 5173, strictPort: false, proxy: { '/radio-si-data': { target: 'https://data.radio.si', changeOrigin: true, secure: true, rewrite: (path) => path.replace(/^\/radio-si-data/, ''), }, }, }, preview: { host: '127.0.0.1', port: 4173, strictPort: false, }, });