Add managed catalog sync and player UX improvements

This commit is contained in:
2026-04-29 13:49:16 +02:00
parent b866845b6a
commit c8f8c76e8a
21 changed files with 71429 additions and 148 deletions

View File

@@ -1,11 +1,77 @@
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()],
plugins: [react(), managedCatalogApiPlugin()],
base: './',
build: {
rollupOptions: {