import { readFile, stat } from "node:fs/promises"; import { extname, join, normalize, resolve } from "node:path"; import type { Page } from "@playwright/test"; const contentTypes: Record = { ".css": "text/css; charset=utf-8", ".html": "text/html; charset=utf-8", ".ico": "image/x-icon", ".js": "application/javascript; charset=utf-8", ".json": "application/json; charset=utf-8", ".map": "application/json; charset=utf-8", ".mjs": "application/javascript; charset=utf-8", ".png": "image/png", ".svg": "image/svg+xml", ".txt": "text/plain; charset=utf-8", ".webp": "image/webp", ".woff": "font/woff", ".woff2": "font/woff2", }; function safeDistPath(distDir: string, pathname: string) { const decoded = decodeURIComponent(pathname); const relative = decoded.replace(/^\/+/, ""); const safe = normalize(relative).replace(/^(\.\.(?:[\\/]|$))+/, ""); return join(distDir, safe); } async function resolveStaticFile(distDir: string, pathname: string) { const indexPath = join(distDir, "index.html"); let filePath = safeDistPath( distDir, pathname === "/" ? "/index.html" : pathname, ); try { const fileStat = await stat(filePath); if (fileStat.isDirectory()) { filePath = join(filePath, "index.html"); } } catch { filePath = indexPath; } try { return { body: await readFile(filePath), contentType: contentTypes[extname(filePath).toLowerCase()] ?? "application/octet-stream", }; } catch { return null; } } export async function installDevFrontStaticRoutes( page: Page, options: { distDir?: string; origin?: string; } = {}, ) { const origin = options.origin ?? "http://devfront.test"; const distDir = resolve( options.distDir ?? process.env.DEVFRONT_DIST_DIR ?? "/tmp/baron-sso-devfront-dist", ); await page.route(`${origin}/**`, async (route) => { const url = new URL(route.request().url()); if (url.pathname === "/api" || url.pathname.startsWith("/api/")) { await route.fallback(); return; } const file = await resolveStaticFile(distDir, url.pathname); if (!file) { await route.fulfill({ status: 500, contentType: "application/json; charset=utf-8", body: JSON.stringify({ error: "devfront_dist_not_found" }), }); return; } await route.fulfill({ status: 200, contentType: file.contentType, body: file.body, }); }); }