From d16bc80ac8cb61fbc6648de788c32469e9cf8f58 Mon Sep 17 00:00:00 2001 From: devilreef Date: Thu, 30 Apr 2026 09:33:37 +0600 Subject: [PATCH] feat(frontend): add /api/stations.json and /api/stations/:id/cover --- frontend/src/pages/api/stations.json.ts | 17 +++++++++ frontend/src/pages/api/stations/[id]/cover.ts | 37 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 frontend/src/pages/api/stations.json.ts create mode 100644 frontend/src/pages/api/stations/[id]/cover.ts diff --git a/frontend/src/pages/api/stations.json.ts b/frontend/src/pages/api/stations.json.ts new file mode 100644 index 0000000..705b0d4 --- /dev/null +++ b/frontend/src/pages/api/stations.json.ts @@ -0,0 +1,17 @@ +import type { APIRoute } from 'astro'; +import { listStations } from '@lib/stations'; + +export const prerender = false; + +export const GET: APIRoute = async () => { + const root = process.env.LIBRARY_ROOT ?? '/library'; + const stations = await listStations(root); + return new Response(JSON.stringify(stations), { + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8', + 'Cache-Control': 'max-age=30, public', + 'Access-Control-Allow-Origin': '*', + }, + }); +}; diff --git a/frontend/src/pages/api/stations/[id]/cover.ts b/frontend/src/pages/api/stations/[id]/cover.ts new file mode 100644 index 0000000..4b5a63b --- /dev/null +++ b/frontend/src/pages/api/stations/[id]/cover.ts @@ -0,0 +1,37 @@ +import type { APIRoute } from 'astro'; +import { access, readFile } from 'node:fs/promises'; +import path from 'node:path'; + +export const prerender = false; + +const ID_RE = /^[a-z0-9-]+$/; +const CANDIDATES: Array<[string, string]> = [ + ['cover.jpg', 'image/jpeg'], + ['cover.png', 'image/png'], + ['cover.webp', 'image/webp'], +]; + +export const GET: APIRoute = async ({ params }) => { + const id = params.id ?? ''; + if (!ID_RE.test(id)) { + return new Response('not found', { status: 404 }); + } + const root = process.env.LIBRARY_ROOT ?? '/library'; + for (const [name, mime] of CANDIDATES) { + const p = path.join(root, id, name); + try { + await access(p); + const buf = await readFile(p); + return new Response(new Uint8Array(buf), { + status: 200, + headers: { + 'Content-Type': mime, + 'Cache-Control': 'max-age=300, public', + }, + }); + } catch { + // try next + } + } + return new Response('not found', { status: 404 }); +};