fix: correct Vercel Bun runtime config and handler export format

Per Vercel docs (vercel.com/docs/functions/runtimes/bun):
- Use top-level "bunVersion": "1.x" in vercel.json (NOT functions block)
- Export default { async fetch(request) { ... } } — object with fetch method
  (not a bare default function)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-10 21:20:16 +07:00
co-authored by Claude Fable 5
parent 591c1fa199
commit 9dc32e8b10
2 changed files with 41 additions and 39 deletions
+40 -34
View File
@@ -1,8 +1,9 @@
/** /**
* Vercel-compatible relay handler. * Vercel-compatible relay handler (Bun runtime).
* *
* This file is the entry point for Vercel serverless function deployments. * This file is the entry point for Vercel serverless function deployments.
* It exports a `default` fetch handler that Vercel invokes per-request. * It exports `{ fetch }` — the contract Vercel's Bun runtime expects for
* serverless functions.
* *
* It reuses the same relay logic from `src/lib/` and `src/middleware/` as * It reuses the same relay logic from `src/lib/` and `src/middleware/` as
* the standalone Bun.serve() server, but: * the standalone Bun.serve() server, but:
@@ -348,41 +349,46 @@ async function handleRelay(req: Request): Promise<Response> {
// ─── Exported Vercel Function Handler ─────────────────────────────────────────── // ─── Exported Vercel Function Handler ───────────────────────────────────────────
/** /**
* Vercel serverless function handler. * Vercel Bun runtime handler.
* *
* Invoked per-request by Vercel's infrastructure. Handles routing, * Vercel's Bun runtime expects a `default` export that is an object with
* middleware, and relay logic — same semantics as the standalone * a `fetch` method — NOT a bare default function. This matches the
* Bun.serve() server, minus WebSocket support. * standard `Bun.serve()` handler shape.
*
* Handles routing, middleware, and relay logic — same semantics as the
* standalone Bun.serve() server, minus WebSocket support.
*/ */
export default async function handler(req: Request): Promise<Response> { export default {
const url = new URL(req.url); async fetch(req: Request): Promise<Response> {
const url = new URL(req.url);
// Static routes // Static routes
if (url.pathname === "/health") return handleHealth(); if (url.pathname === "/health") return handleHealth();
if (url.pathname === "/docs") return handleDocs(); if (url.pathname === "/docs") return handleDocs();
if (url.pathname === "/" && req.method === "GET") return handleIndex(); if (url.pathname === "/" && req.method === "GET") return handleIndex();
// WebSocket upgrade — not supported in Vercel Functions // WebSocket upgrade — not supported in Vercel Functions
if ( if (
req.method === "GET" && req.method === "GET" &&
req.headers.get("upgrade")?.toLowerCase() === "websocket" req.headers.get("upgrade")?.toLowerCase() === "websocket"
) { ) {
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
error: true, error: true,
code: "UNSUPPORTED", code: "UNSUPPORTED",
message: "WebSocket relay is not supported on this deployment", message: "WebSocket relay is not supported on this deployment",
}), }),
{ {
status: 400, status: 400,
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
},
}, },
}, );
); }
}
// Generic HTTP relay // Generic HTTP relay
return handleRelay(req); return handleRelay(req);
} },
};
+1 -5
View File
@@ -1,9 +1,5 @@
{ {
"functions": { "bunVersion": "1.x",
"api/relay.ts": {
"runtime": "@vercel/node@5"
}
},
"rewrites": [ "rewrites": [
{ "source": "/(.*)", "destination": "/api/relay" } { "source": "/(.*)", "destination": "/api/relay" }
] ]