UNPKG

fully-react

Version:
190 lines (187 loc) 5.65 kB
import { getURLFromRedirectError, isRedirectError } from "./chunk-EHJL7JPJ.js"; import { requestAsyncContext } from "./chunk-UXXZ4F7M.js"; import { createHTMLResponse } from "./chunk-K4W7QR7B.js"; import { createActionResponse, createServerComponentResponse } from "./chunk-U26WWCBL.js"; import { decodeReply } from "./chunk-2LNACUKM.js"; // src/server/handler.tsx import { createRouter } from "@hattip/router"; async function handleActionRequest(request, env) { let actionId = request.headers.get("x-action"); const isAction = !!actionId; const isForm = request.headers.get("content-type") === "application/x-www-form-urlencoded"; const isMultiPartForm = request.headers.get("content-type")?.startsWith("multipart/form-data"); if (!isAction && !isForm && !isMultiPartForm) { return new Response("Not Found", { status: 404 }); } let data; if (isForm || isMultiPartForm) { const formData = await request.formData(); data = [formData]; actionId = formData.get("$$id"); } else { const encodedArgs = await request.text(); data = await decodeReply(encodedArgs); } const [filePath, name] = actionId.split("#"); const action = (await env.loadModule(filePath))[name]; const isMutating = request.headers.get("x-mutation") === "1"; if (isMutating) { const responseInit = {}; return requestAsyncContext.run( { request, response: responseInit }, async () => { try { await action(...data); const url = new URL(request.url); return createServerComponentResponse( "root", { url: url.href, searchParams: Object.fromEntries(url.searchParams.entries()), headers: Object.fromEntries(request.headers.entries()), params: {} }, env ); } catch (e) { console.error(e); if (isRedirectError(e)) { const redirectPath = getURLFromRedirectError(e); const url = new URL(redirectPath, request.url); return createServerComponentResponse( "root", { url: url.href, searchParams: Object.fromEntries(url.searchParams.entries()), headers: Object.fromEntries(request.headers.entries()), params: {} }, env, { status: 200, headers: { "x-redirect": redirectPath } } ); } } } ); } else if (isForm || isMultiPartForm) { try { await action(...data); const url = new URL(request.url); const responseInit = {}; return requestAsyncContext.run( { request, response: responseInit }, async () => { return createHTMLResponse( "root", { url: url.href, searchParams: Object.fromEntries(url.searchParams.entries()), headers: Object.fromEntries(request.headers.entries()), params: {} }, env, responseInit ); } ); } catch (e) { if (isRedirectError(e)) { return new Response("", { status: 302, headers: { Location: getURLFromRedirectError(e) } }); } } } return createActionResponse(action, data, env); } async function handlePageRequest(request, env) { const url = new URL(request.url); const responseInit = {}; const response = await requestAsyncContext.run( { request, response: responseInit }, async () => await createHTMLResponse( "root", { url: request.url, searchParams: Object.fromEntries(url.searchParams.entries()), headers: Object.fromEntries(request.headers.entries()), params: {} }, env, responseInit ) ); console.log("response", response.status, response.url); return response; } async function handleServerComponentRequest(request, env) { const url = new URL(request.headers.get("x-navigate") ?? "/", request.url); const response = {}; return requestAsyncContext.run( { request, response }, () => createServerComponentResponse( "root", { url: request.url, searchParams: Object.fromEntries(url.searchParams.entries()), headers: Object.fromEntries(request.headers.entries()), params: {} }, env, response ) ); } function createServerRouter(env) { const router = createRouter(); Object.entries(env.routesConfig).forEach(([entry, route]) => { if (route.routeHandler) { router.get(route.path, async (context) => { const mod = await env.loadModule(route.file); const handler = mod[context.request.method]; return await handler(context.request); }); router.post(route.path, async (context) => { const mod = await env.loadModule(route.file); const handler = mod[context.request.method]; return await handler(context.request); }); } }); router.post("/*", async (context) => { return handleActionRequest(context.request, env); }); router.get("/*", async (context) => { if (context.request.headers.get("accept") === "text/x-component") { return handleServerComponentRequest(context.request, env); } return await handlePageRequest(context.request, env); }); return router; } export { handleActionRequest, handlePageRequest, handleServerComponentRequest, createServerRouter };