Files
DESKTOP-PUHFO60\dsx2016 a59aaf1c8d Add multi-board selector and scalable firmware catalog UI.
Board chips reserve future models; firmware uses searchable cards with detail pane and optional meta.json media/docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-19 19:45:24 +08:00

44 lines
1.2 KiB
TypeScript

import fs from "fs";
import path from "path";
import { NextResponse } from "next/server";
import { resolveMediaFile } from "@/lib/firmware";
export const dynamic = "force-dynamic";
const MIME: Record<string, string> = {
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".webp": "image/webp",
".gif": "image/gif",
".mp4": "video/mp4",
".webm": "video/webm",
".md": "text/markdown; charset=utf-8",
".txt": "text/plain; charset=utf-8",
".html": "text/html; charset=utf-8",
".pdf": "application/pdf",
};
type Params = {
params: Promise<{ project: string; variant: string; path: string[] }>;
};
export async function GET(_req: Request, { params }: Params) {
const { project, variant, path: parts } = await params;
const rel = parts.join("/");
const abs = resolveMediaFile(project, variant, rel);
if (!abs) {
return NextResponse.json({ error: "not found" }, { status: 404 });
}
const ext = path.extname(abs).toLowerCase();
const buf = fs.readFileSync(abs);
return new NextResponse(buf, {
headers: {
"Content-Type": MIME[ext] || "application/octet-stream",
"Content-Length": String(buf.length),
"Cache-Control": "public, max-age=3600",
},
});
}