24 lines
1.5 KiB
TypeScript
24 lines
1.5 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { NextResponse } from "next/server";
|
|
import { buildProject } from "../../../../../../lib/build";
|
|
import { errorResponse } from "../../../../../../lib/http";
|
|
import { projectRoot, touchProject } from "../../../../../../lib/storage";
|
|
|
|
export const runtime = "nodejs";
|
|
|
|
const CONTENT_TYPES: Record<string, string> = { ".html": "text/html; charset=utf-8", ".css": "text/css; charset=utf-8", ".js": "text/javascript; charset=utf-8", ".json": "application/json", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".webp": "image/webp", ".svg": "image/svg+xml", ".woff": "font/woff", ".woff2": "font/woff2" };
|
|
|
|
export async function GET(_: Request, context: { params: Promise<{ id: string; path?: string[] }> }) {
|
|
try {
|
|
const params = await context.params;
|
|
await touchProject(params.id);
|
|
const segments = params.path?.length ? params.path : ["index.html"];
|
|
const dist = path.join(projectRoot(params.id), "dist");
|
|
let target = path.resolve(dist, ...segments);
|
|
if (!target.startsWith(`${dist}${path.sep}`)) throw new Error("Invalid preview path");
|
|
try { await fs.access(target); } catch { await buildProject(params.id); target = path.resolve(dist, ...segments); }
|
|
return new NextResponse(await fs.readFile(target), { headers: { "Content-Type": CONTENT_TYPES[path.extname(target)] || "application/octet-stream", "Cache-Control": "no-store" } });
|
|
} catch (error) { return errorResponse(error); }
|
|
}
|