diff --git a/packages/vinext/src/index.ts b/packages/vinext/src/index.ts
index f59c80d5..f8a94687 100644
--- a/packages/vinext/src/index.ts
+++ b/packages/vinext/src/index.ts
@@ -3044,6 +3044,7 @@ hydrate();
) {
const apiRoutes = await apiRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
const handled = await handleApiRoute(
+ getPagesRunner(),
server,
req,
res,
@@ -3082,7 +3083,7 @@ hydrate();
return;
}
- const handler = createSSRHandler(server, routes, pagesDir, nextConfig?.i18n, fileMatcher);
+ const handler = createSSRHandler(getPagesRunner(), server, routes, pagesDir, nextConfig?.i18n, fileMatcher);
const mwStatus = (req as any).__vinextRewriteStatus as number | undefined;
// Try rendering the resolved URL
diff --git a/packages/vinext/src/server/api-handler.ts b/packages/vinext/src/server/api-handler.ts
index 4a63d3cc..ca775102 100644
--- a/packages/vinext/src/server/api-handler.ts
+++ b/packages/vinext/src/server/api-handler.ts
@@ -8,6 +8,7 @@
* Next.js extensions: req.query, req.body, res.json(), res.status(), etc.
*/
import type { ViteDevServer } from "vite";
+import type { ModuleRunner } from "vite/module-runner";
import type { IncomingMessage, ServerResponse } from "node:http";
import { type Route, matchRoute } from "../routing/pages-router.js";
import { reportRequestError } from "./instrumentation.js";
@@ -163,6 +164,7 @@ function enhanceApiObjects(
* Returns true if the request was handled, false if no API route matched.
*/
export async function handleApiRoute(
+ runner: ModuleRunner,
server: ViteDevServer,
req: IncomingMessage,
res: ServerResponse,
@@ -176,7 +178,7 @@ export async function handleApiRoute(
try {
// Load the API route module through Vite
- const apiModule = await server.ssrLoadModule(route.filePath);
+ const apiModule = await runner.import(route.filePath);
const handler = apiModule.default;
if (typeof handler !== "function") {
@@ -206,7 +208,7 @@ export async function handleApiRoute(
await handler(apiReq, apiRes);
return true;
} catch (e) {
- server.ssrFixStacktrace(e as Error);
+ server.ssrFixStacktrace?.(e as Error);
console.error(e);
reportRequestError(
e instanceof Error ? e : new Error(String(e)),
diff --git a/packages/vinext/src/server/dev-server.ts b/packages/vinext/src/server/dev-server.ts
index 70aae84f..b4439cfc 100644
--- a/packages/vinext/src/server/dev-server.ts
+++ b/packages/vinext/src/server/dev-server.ts
@@ -1,4 +1,5 @@
import type { ViteDevServer } from "vite";
+import type { ModuleRunner } from "vite/module-runner";
import type { IncomingMessage, ServerResponse } from "node:http";
import type { Route } from "../routing/pages-router.js";
import { matchRoute, patternToNextFormat } from "../routing/pages-router.js";
@@ -64,7 +65,7 @@ async function streamPageToResponse(
element: React.ReactElement,
options: {
url: string;
- server: ViteDevServer;
+ server: ViteDevServer; // needed only for transformIndexHtml
fontHeadHTML: string;
scripts: string;
DocumentComponent: React.ComponentType | null;
@@ -272,6 +273,7 @@ export function parseCookieLocale(
* 5. Wrap in _document shell and send response
*/
export function createSSRHandler(
+ runner: ModuleRunner,
server: ViteDevServer,
routes: Route[],
pagesDir: string,
@@ -344,7 +346,7 @@ export function createSSRHandler(
if (!match) {
// No route matched — try to render custom 404 page
- await renderErrorPage(server, req, res, url, pagesDir, 404, undefined, matcher);
+ await renderErrorPage(runner, server, req, res, url, pagesDir, 404, undefined, matcher);
return;
}
@@ -360,7 +362,7 @@ export function createSSRHandler(
try {
// Set SSR context for the router shim so useRouter() returns
// the correct URL and params during server-side rendering.
- const routerShim = await server.ssrLoadModule("next/router");
+ const routerShim = await runner.import("next/router");
if (typeof routerShim.setSSRContext === "function") {
routerShim.setSSRContext({
pathname: localeStrippedUrl.split("?")[0],
@@ -381,7 +383,7 @@ export function createSSRHandler(
// Load the page module through Vite's SSR pipeline
// This gives us HMR and transform support for free
- const pageModule = await server.ssrLoadModule(route.filePath);
+ const pageModule = await runner.import(route.filePath);
// Mark end of compile phase: everything from here is rendering.
_compileEnd = now();
@@ -422,7 +424,7 @@ export function createSSRHandler(
});
if (!isValidPath) {
- await renderErrorPage(server, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, matcher);
+ await renderErrorPage(runner, server, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext as ((el: React.ReactElement) => React.ReactElement) | undefined, matcher);
return;
}
}
@@ -483,7 +485,7 @@ export function createSSRHandler(
return;
}
if (result && "notFound" in result && result.notFound) {
- await renderErrorPage(server, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext);
+ await renderErrorPage(runner, server, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext as ((el: React.ReactElement) => React.ReactElement) | undefined);
return;
}
// Preserve any status code set by gSSP (e.g. res.statusCode = 201).
@@ -511,11 +513,11 @@ export function createSSRHandler(
let earlyFontLinkHeader = "";
try {
const earlyPreloads: Array<{ href: string; type: string }> = [];
- const fontGoogleEarly = await server.ssrLoadModule("next/font/google");
+ const fontGoogleEarly = await runner.import("next/font/google");
if (typeof fontGoogleEarly.getSSRFontPreloads === "function") {
earlyPreloads.push(...fontGoogleEarly.getSSRFontPreloads());
}
- const fontLocalEarly = await server.ssrLoadModule("next/font/local");
+ const fontLocalEarly = await runner.import("next/font/local");
if (typeof fontLocalEarly.getSSRFontPreloads === "function") {
earlyPreloads.push(...fontLocalEarly.getSSRFontPreloads());
}
@@ -607,7 +609,7 @@ export function createSSRHandler(
return;
}
if (result && "notFound" in result && result.notFound) {
- await renderErrorPage(server, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext);
+ await renderErrorPage(runner, server, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext as ((el: React.ReactElement) => React.ReactElement) | undefined);
return;
}
@@ -623,7 +625,7 @@ export function createSSRHandler(
const appPath = path.join(pagesDir, "_app");
if (findFileWithExtensions(appPath, matcher)) {
try {
- const appModule = await server.ssrLoadModule(appPath);
+ const appModule = await runner.import(appPath);
AppComponent = appModule.default ?? null;
} catch {
// _app exists but failed to load
@@ -654,13 +656,13 @@ export function createSSRHandler(
}
// Reset SSR head collector before rendering so
tags are captured
- const headShim = await server.ssrLoadModule("next/head");
+ const headShim = await runner.import("next/head");
if (typeof headShim.resetSSRHead === "function") {
headShim.resetSSRHead();
}
// Flush any pending dynamic() preloads so components are ready
- const dynamicShim = await server.ssrLoadModule("next/dynamic");
+ const dynamicShim = await runner.import("next/dynamic");
if (typeof dynamicShim.flushPreloads === "function") {
await dynamicShim.flushPreloads();
}
@@ -674,7 +676,7 @@ export function createSSRHandler(
const allFontStyles: string[] = [];
const allFontPreloads: Array<{ href: string; type: string }> = [];
try {
- const fontGoogle = await server.ssrLoadModule("next/font/google");
+ const fontGoogle = await runner.import("next/font/google");
if (typeof fontGoogle.getSSRFontLinks === "function") {
const fontUrls = fontGoogle.getSSRFontLinks();
for (const fontUrl of fontUrls) {
@@ -693,7 +695,7 @@ export function createSSRHandler(
// next/font/google not used — skip
}
try {
- const fontLocal = await server.ssrLoadModule("next/font/local");
+ const fontLocal = await runner.import("next/font/local");
if (typeof fontLocal.getSSRFontStyles === "function") {
allFontStyles.push(...fontLocal.getSSRFontStyles());
}
@@ -777,7 +779,7 @@ hydrate();
let DocumentComponent: any = null;
if (findFileWithExtensions(docPath, matcher)) {
try {
- const docModule = await server.ssrLoadModule(docPath);
+ const docModule = await runner.import(docPath);
DocumentComponent = docModule.default ?? null;
} catch {
// _document exists but failed to load
@@ -865,7 +867,7 @@ hydrate();
).catch(() => { /* ignore reporting errors */ });
// Try to render custom 500 error page
try {
- await renderErrorPage(server, req, res, url, pagesDir, 500, undefined, matcher);
+ await renderErrorPage(runner, server, req, res, url, pagesDir, 500, undefined, matcher);
} catch (fallbackErr) {
// If error page itself fails, fall back to plain text.
// This is a dev-only code path (prod uses prod-server.ts), so
@@ -894,6 +896,7 @@ hydrate();
* - other: pages/_error.tsx -> default
*/
async function renderErrorPage(
+ runner: ModuleRunner,
server: ViteDevServer,
_req: IncomingMessage,
res: ServerResponse,
@@ -917,7 +920,7 @@ async function renderErrorPage(
const candidatePath = path.join(pagesDir, candidate);
if (!findFileWithExtensions(candidatePath, matcher)) continue;
- const errorModule = await server.ssrLoadModule(candidatePath);
+ const errorModule = await runner.import(candidatePath);
const ErrorComponent = errorModule.default;
if (!ErrorComponent) continue;
@@ -926,7 +929,7 @@ async function renderErrorPage(
const appPathErr = path.join(pagesDir, "_app");
if (findFileWithExtensions(appPathErr, matcher)) {
try {
- const appModule = await server.ssrLoadModule(appPathErr);
+ const appModule = await runner.import(appPathErr);
AppComponent = appModule.default ?? null;
} catch {
// _app exists but failed to load
@@ -941,7 +944,7 @@ async function renderErrorPage(
let wrapFn = wrapWithRouterContext;
if (!wrapFn) {
try {
- const errRouterShim = await server.ssrLoadModule("next/router");
+ const errRouterShim = await runner.import("next/router");
wrapFn = errRouterShim.wrapWithRouterContext;
} catch {
// router shim not available — continue without it
@@ -970,7 +973,7 @@ async function renderErrorPage(
const docPathErr = path.join(pagesDir, "_document");
if (findFileWithExtensions(docPathErr, matcher)) {
try {
- const docModule = await server.ssrLoadModule(docPathErr);
+ const docModule = await runner.import(docPathErr);
DocumentComponent = docModule.default ?? null;
} catch {
// _document exists but failed to load
diff --git a/tests/api-handler.test.ts b/tests/api-handler.test.ts
index f6d7cca8..3875bb24 100644
--- a/tests/api-handler.test.ts
+++ b/tests/api-handler.test.ts
@@ -8,7 +8,7 @@
*
* Since parseBody, parseCookies, and enhanceApiObjects are not exported,
* all behavior is tested indirectly through handleApiRoute with a mocked
- * ViteDevServer.
+ * ModuleRunner and ViteDevServer.
*/
import { describe, it, expect, vi } from "vitest";
import { PassThrough } from "node:stream";
@@ -16,6 +16,7 @@ import http from "node:http";
import { handleApiRoute } from "../packages/vinext/src/server/api-handler.js";
import type { Route } from "../packages/vinext/src/routing/pages-router.js";
import type { ViteDevServer } from "vite";
+import type { ModuleRunner } from "vite/module-runner";
// ── Helpers ──────────────────────────────────────────────────────────────
@@ -121,13 +122,21 @@ function route(pattern: string, filePath = "/fake/api/handler.ts"): Route {
}
/**
- * Build a minimal mock ViteDevServer with configurable ssrLoadModule behavior.
+ * Build a minimal mock ModuleRunner with configurable import behavior.
*/
-function mockServer(
+function mockRunner(
moduleExport: Record,
-): ViteDevServer {
+): ModuleRunner {
+ return {
+ import: vi.fn().mockResolvedValue(moduleExport),
+ } as unknown as ModuleRunner;
+}
+
+/**
+ * Build a minimal mock ViteDevServer (only needs ssrFixStacktrace for error handling).
+ */
+function mockServer(): ViteDevServer {
return {
- ssrLoadModule: vi.fn().mockResolvedValue(moduleExport),
ssrFixStacktrace: vi.fn(),
} as unknown as ViteDevServer;
}
@@ -140,11 +149,13 @@ describe("handleApiRoute", () => {
describe("route matching", () => {
it("returns false when no route matches", async () => {
const handler = vi.fn();
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/nonexistent");
const res = mockRes();
const handled = await handleApiRoute(
+ runner,
server,
req,
res,
@@ -158,11 +169,13 @@ describe("handleApiRoute", () => {
it("returns true when a route matches", async () => {
const handler = vi.fn();
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
const handled = await handleApiRoute(
+ runner,
server,
req,
res,
@@ -183,14 +196,15 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const payload = JSON.stringify({ name: "Alice", age: 30 });
const req = mockReq("POST", "/api/users", payload, {
"content-type": "application/json",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -202,13 +216,14 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("POST", "/api/users", "{not json", {
"content-type": "application/json",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -220,13 +235,14 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("POST", "/api/users", "name=Alice&role=admin", {
"content-type": "application/x-www-form-urlencoded",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -238,13 +254,14 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("POST", "/api/users", "plain text body", {
"content-type": "text/plain",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -256,11 +273,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -272,11 +290,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("POST", "/api/users", "some data");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -289,7 +308,8 @@ describe("handleApiRoute", () => {
describe("MAX_BODY_SIZE enforcement", () => {
it("rejects bodies exceeding 1 MB with 413 status", async () => {
const handler = vi.fn();
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
// Create a stream that pushes > 1 MB.
// Do NOT override destroy — let PassThrough's native destroy work
@@ -329,7 +349,7 @@ describe("handleApiRoute", () => {
}
});
- await handleApiRoute(server, req, res, "/api/upload", [
+ await handleApiRoute(runner, server, req, res, "/api/upload", [
route("/api/upload"),
]);
@@ -343,7 +363,8 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedBody = req.body;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
// Send exactly 512 KB — well within the 1 MB limit
const body = "x".repeat(512 * 1024);
@@ -352,7 +373,7 @@ describe("handleApiRoute", () => {
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/upload", [
+ await handleApiRoute(runner, server, req, res, "/api/upload", [
route("/api/upload"),
]);
@@ -369,13 +390,14 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedCookies = req.cookies;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users", undefined, {
cookie: "session=abc123",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -387,13 +409,14 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedCookies = req.cookies;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users", undefined, {
cookie: "session=abc123; theme=dark; lang=en",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -409,13 +432,14 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedCookies = req.cookies;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users", undefined, {
cookie: "token=abc=def=ghi",
});
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -427,11 +451,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedCookies = req.cookies;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -448,11 +473,12 @@ describe("handleApiRoute", () => {
// Should return res for chaining
returned.json({ ok: true });
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("POST", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -467,11 +493,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.json({ message: "hello" });
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -484,11 +511,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.json(data);
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -501,11 +529,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.send({ key: "value" });
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -517,11 +546,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.send("hello world");
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -533,11 +563,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.send(42);
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -550,11 +581,12 @@ describe("handleApiRoute", () => {
res.setHeader("Content-Type", "text/html");
res.send("Hello
");
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/page");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/page", [
+ await handleApiRoute(runner, server, req, res, "/api/page", [
route("/api/page"),
]);
@@ -568,11 +600,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.send(null);
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -586,11 +619,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.redirect("/dashboard");
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/login");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/login", [
+ await handleApiRoute(runner, server, req, res, "/api/login", [
route("/api/login"),
]);
@@ -603,11 +637,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.redirect(301, "/new-location");
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/old");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/old", [
+ await handleApiRoute(runner, server, req, res, "/api/old", [
route("/api/old"),
]);
@@ -619,11 +654,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((_req: any, res: any) => {
res.redirect(302, "https://external.com");
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/external");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/external", [
+ await handleApiRoute(runner, server, req, res, "/api/external", [
route("/api/external"),
]);
@@ -640,11 +676,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedQuery = req.query;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users?page=2&limit=10");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users?page=2&limit=10", [
+ await handleApiRoute(runner, server, req, res, "/api/users?page=2&limit=10", [
route("/api/users"),
]);
@@ -657,11 +694,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedQuery = req.query;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users/42");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users/42", [
+ await handleApiRoute(runner, server, req, res, "/api/users/42", [
route("/api/users/:id"),
]);
@@ -673,11 +711,13 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedQuery = req.query;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users/42?fields=name,email");
const res = mockRes();
await handleApiRoute(
+ runner,
server,
req,
res,
@@ -694,11 +734,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedQuery = req.query;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users?tag=a&tag=b");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users?tag=a&tag=b", [
+ await handleApiRoute(runner, server, req, res, "/api/users?tag=a&tag=b", [
route("/api/users"),
]);
@@ -710,11 +751,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn((req: any) => {
capturedQuery = req.query;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -726,11 +768,12 @@ describe("handleApiRoute", () => {
describe("error handling", () => {
it("returns 500 when module has no default export", async () => {
- const server = mockServer({ notDefault: () => {} });
+ const runner = mockRunner({ notDefault: () => {} });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- const handled = await handleApiRoute(server, req, res, "/api/users", [
+ const handled = await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -740,11 +783,12 @@ describe("handleApiRoute", () => {
});
it("returns 500 when default export is not a function", async () => {
- const server = mockServer({ default: "not a function" });
+ const runner = mockRunner({ default: "not a function" });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- const handled = await handleApiRoute(server, req, res, "/api/users", [
+ const handled = await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -757,11 +801,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn(() => {
throw new Error("something broke");
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- const handled = await handleApiRoute(server, req, res, "/api/users", [
+ const handled = await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);
@@ -775,11 +820,12 @@ describe("handleApiRoute", () => {
const handler = vi.fn(() => {
throw error;
});
- const server = mockServer({ default: handler });
+ const runner = mockRunner({ default: handler });
+ const server = mockServer();
const req = mockReq("GET", "/api/users");
const res = mockRes();
- await handleApiRoute(server, req, res, "/api/users", [
+ await handleApiRoute(runner, server, req, res, "/api/users", [
route("/api/users"),
]);