(
createPageEvent: (e: FetchEvent) => Promise<PageEvent>,
fn: (context: PageEvent) => JSX.Element,
options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {},
)
| 16 | const SERVER_FN_BASE = "/_server"; |
| 17 | |
| 18 | export function createBaseHandler( |
| 19 | createPageEvent: (e: FetchEvent) => Promise<PageEvent>, |
| 20 | fn: (context: PageEvent) => JSX.Element, |
| 21 | options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {}, |
| 22 | ) { |
| 23 | const handler = defineHandler({ |
| 24 | middleware: middleware.length ? middleware.map(decorateMiddleware) : undefined, |
| 25 | handler: decorateHandler(async (e: H3Event) => { |
| 26 | const event = getRequestEvent()!; |
| 27 | const url = new URL(event.request.url); |
| 28 | const pathname = stripBaseUrl(url.pathname); |
| 29 | |
| 30 | if (pathname.startsWith(SERVER_FN_BASE)) { |
| 31 | const serverFnResponse = await handleServerFunction(e); |
| 32 | |
| 33 | if (serverFnResponse instanceof Response) |
| 34 | return produceResponseWithEventHeaders(serverFnResponse); |
| 35 | |
| 36 | return new Response(serverFnResponse as any, { |
| 37 | headers: e.res.headers, |
| 38 | }); |
| 39 | } |
| 40 | |
| 41 | const match = matchAPIRoute(pathname, event.request.method); |
| 42 | if (match) { |
| 43 | const mod = await match.handler.import(); |
| 44 | const fn = |
| 45 | event.request.method === "HEAD" ? mod["HEAD"] || mod["GET"] : mod[event.request.method]; |
| 46 | if (typeof fn === "function") { |
| 47 | (event as APIEvent).params = match.params || {}; |
| 48 | // @ts-expect-error |
| 49 | sharedConfig.context = { event }; |
| 50 | const res = await fn(event); |
| 51 | if (res !== undefined) { |
| 52 | if (res instanceof Response) return produceResponseWithEventHeaders(res); |
| 53 | |
| 54 | return res; |
| 55 | } |
| 56 | if (event.request.method !== "GET") { |
| 57 | throw new Error( |
| 58 | `API handler for ${event.request.method} "${event.request.url}" did not return a response.`, |
| 59 | ); |
| 60 | } |
| 61 | if (!match.isPage) return; |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | const context = await createPageEvent(event); |
| 66 | |
| 67 | const resolvedOptions = |
| 68 | typeof options === "function" ? await options(context) : { ...options }; |
| 69 | const mode = resolvedOptions.mode || "stream"; |
| 70 | if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce; |
| 71 | |
| 72 | if (mode === "sync" || !import.meta.env.START_SSR) { |
| 73 | const html = renderToString(() => { |
| 74 | (sharedConfig.context as any).event = context; |
| 75 | return fn(context); |
no test coverage detected