UNPKG

@netlify/remix-edge-adapter

Version:

Remix Adapter for Netlify Edge Functions

129 lines (122 loc) 3.96 kB
import { __commonJS, __toESM } from "./chunk-UJCSKKID.mjs"; // src/common/globals.ts var require_globals = __commonJS({ "src/common/globals.ts"() { "use strict"; globalThis.process ||= { env: Netlify.env.toObject() }; } }); // src/index.ts var import_globals = __toESM(require_globals()); // src/common/server.ts import { createRequestHandler as createRemixRequestHandler } from "@netlify/remix-runtime"; function createRequestHandler({ build, mode, getLoadContext }) { const remixHandler = createRemixRequestHandler(build, mode); const assetPath = build.assets.url.split("/").slice(0, -1).join("/"); return async (request, context) => { const { pathname } = new URL(request.url); if (pathname.startsWith(`${assetPath}/`)) { return; } try { const loadContext = await (getLoadContext == null ? void 0 : getLoadContext(request, context)) || context; const response = await remixHandler(request, loadContext); response.headers.set("x-nf-runtime", "Edge"); if (response.status === 404) { const originResponse = await loadContext.next({ sendConditionalRequest: true }); if (originResponse && (originResponse == null ? void 0 : originResponse.status) !== 404) { return originResponse; } } return response; } catch (error) { console.error(error); return new Response("Internal Error", { status: 500 }); } }; } // src/classic-compiler/defaultRemixConfig.ts var config = { server: "./server.ts", ignoredRouteFiles: ["**/.*"], serverBuildPath: ".netlify/edge-functions/server.js", serverConditions: ["deno", "worker"], serverDependenciesToBundle: "all", serverMainFields: ["module", "main"], serverModuleFormat: "esm", serverPlatform: "neutral" }; // src/common/entry.server.tsx import { RemixServer } from "@remix-run/react"; import { isbot } from "isbot"; import * as ReactDOMServer from "react-dom/server"; import { jsx } from "react/jsx-runtime"; async function handleRequest(request, responseStatusCode, responseHeaders, remixContext, _loadContext) { let isStreamClosing = false; const abortController = new AbortController(); request.signal.addEventListener("abort", () => { if (!isStreamClosing) { abortController.abort(request.signal.reason); } }); const body = await ReactDOMServer.renderToReadableStream(/* @__PURE__ */ jsx(RemixServer, { context: remixContext, url: request.url }), { signal: abortController.signal, onError(error) { console.error(error); responseStatusCode = 500; } }); const transformedBody = body.pipeThrough( new TransformStream({ flush() { isStreamClosing = true; } }) ); if (isbot(request.headers.get("user-agent") || "")) { await body.allReady; } responseHeaders.set("Content-Type", "text/html"); return new Response(transformedBody, { headers: responseHeaders, status: responseStatusCode }); } // src/vite/hydrogen.ts var executionContext = { /** * Hydrogen expects a `waitUntil` function like the one in the workerd runtime: * https://developers.cloudflare.com/workers/runtime-apis/context/#waituntil. * Netlify Edge Functions don't have such a function, but Deno Deploy isolates make a best-effort * attempt to wait for the event loop to drain, so just awaiting the promise here is equivalent. */ async waitUntil(p) { await p; } }; var getEnv = () => { if (globalThis.Netlify) { return globalThis.Netlify.env.toObject(); } return process.env; }; var createHydrogenAppLoadContext = async (request, netlifyContext, createAppLoadContext) => { const env = getEnv(); const userHydrogenContext = await createAppLoadContext(request, env, executionContext); return Object.assign(netlifyContext, userHydrogenContext); }; export { config, createHydrogenAppLoadContext, createRequestHandler, handleRequest };