import { defineConfig } from "vite-plus"; import react from "@vitejs/plugin-react"; import { stat } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; const rootDir = path.dirname(fileURLToPath(import.meta.url)); const imageRootDir = path.resolve(rootDir, "img"); const imageFallbackBase = "https://ski.aarongutierrez.com"; const fileExists = async (filename: string): Promise => { try { await stat(filename); return true; } catch { return false; } }; const imageFallbackMiddleware = async ( req: { method?: string; url?: string }, res: { statusCode: number; setHeader: (name: string, value: string) => void; end: () => void }, next: () => void, ): Promise => { if ((req.method !== "GET" && req.method !== "HEAD") || !req.url) { next(); return; } const requestUrl = new URL(req.url, "http://localhost"); const pathname = decodeURIComponent(requestUrl.pathname); if (!pathname.startsWith("/img/")) { next(); return; } const relativePath = pathname.slice(1); const localFile = path.resolve(rootDir, relativePath); const relativeToImageRoot = path.relative(imageRootDir, localFile); const isWithinImageRoot = relativeToImageRoot !== "" && relativeToImageRoot !== ".." && !relativeToImageRoot.startsWith(`..${path.sep}`) && !path.isAbsolute(relativeToImageRoot); if (!isWithinImageRoot || (await fileExists(localFile))) { next(); return; } const fallbackUrl = new URL(pathname, imageFallbackBase); fallbackUrl.search = requestUrl.search; res.statusCode = 302; res.setHeader("Location", fallbackUrl.toString()); res.end(); }; export default defineConfig({ staged: { "*": "vp check --fix", }, fmt: {}, plugins: [ react({ babel: { // React Compiler must run first in the Babel pipeline. plugins: ["babel-plugin-react-compiler"], }, }), { // Rolldown-vite's JSON HMR logs an update but doesn't reload the browser. // Force a full reload when data.json changes. name: "reload-data-json", handleHotUpdate({ file, server }) { if (file.endsWith("/data.json")) { server.ws.send({ type: "full-reload" }); return []; } }, }, { name: "image-fallback-to-production", configureServer(server) { server.middlewares.use(imageFallbackMiddleware); }, configurePreviewServer(server) { server.middlewares.use(imageFallbackMiddleware); }, }, ], resolve: { alias: { "@": path.resolve(rootDir, "src"), }, }, });