mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-10 00:04:27 +00:00
65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
import { stat } from "node:fs/promises"
|
|
import path from "node:path"
|
|
import { parseArgs } from "node:util"
|
|
|
|
// Serves the e2e build with vite preview's routing rules. vite preview checks the case of every requested
|
|
// path with a synchronous directory read on case-insensitive file systems (Windows, macOS), and the
|
|
// 3000-file _assets directory makes that the bottleneck for every page load across all workers.
|
|
const options = parseArgs({ options: { host: { type: "string" }, port: { type: "string" } } }).values
|
|
|
|
const dist = path.resolve(import.meta.dirname, "../../dist")
|
|
|
|
// Sent as text like vite's index.html middleware, so a media Range request that falls back gets a plain 200.
|
|
const index = await Bun.file(path.join(dist, "index.html")).text()
|
|
|
|
Bun.serve({
|
|
hostname: options.host,
|
|
port: Number(options.port),
|
|
async fetch(request) {
|
|
const pathname = decode(new URL(request.url).pathname)
|
|
|
|
if (pathname === undefined) return new Response(null, { status: 404 })
|
|
|
|
const target = path.resolve(dist, `.${pathname}`)
|
|
|
|
// Like vite's existsSync, a name the file system rejects (too long, NUL) is treated as missing.
|
|
const stats = target.startsWith(dist + path.sep) ? await stat(target).catch(() => undefined) : undefined
|
|
|
|
if (stats?.isFile()) {
|
|
const file = Bun.file(target)
|
|
|
|
return new Response(file, {
|
|
// Bun names .aac audio/x-aac, and only keeps the type on HEAD responses when it is set explicitly.
|
|
headers: { "content-type": path.extname(target) === ".aac" ? "audio/aac" : file.type },
|
|
})
|
|
}
|
|
|
|
if (fallback(request, pathname))
|
|
return new Response(index, { headers: { "content-type": "text/html;charset=utf-8" } })
|
|
|
|
return new Response(null, { status: 404 })
|
|
},
|
|
})
|
|
|
|
function decode(pathname: string) {
|
|
try {
|
|
return decodeURIComponent(pathname)
|
|
} catch {
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
// Mirrors vite's htmlFallbackMiddleware: only page loads get index.html, so a missing script or a fetch
|
|
// asking for JSON still sees a 404.
|
|
function fallback(request: Request, pathname: string) {
|
|
if (request.method !== "GET" && request.method !== "HEAD") return false
|
|
|
|
if (pathname === "/favicon.ico") return false
|
|
|
|
// vite's index.html middleware never answers a script load with the page, so a missing chunk stays a 404.
|
|
if (request.headers.get("sec-fetch-dest") === "script") return false
|
|
|
|
const accept = request.headers.get("accept")
|
|
|
|
return !accept || accept.includes("text/html") || accept.includes("*/*")
|
|
}
|