UNPKG

rwsdk

Version:

Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime

50 lines (49 loc) 2.16 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { use } from "react"; import { renderToReadableStream } from "react-dom/server.edge"; export const renderRscThenableToHtmlStream = async ({ thenable, Document, requestInfo, shouldSSR, onError, }) => { const Component = () => { const node = use(thenable).node; // todo(justinvdm, 18 Jun 2025): We can build on this later to allow users // surface context. e.g: // * we assign `user: requestInfo.clientCtx` here // * user populates requestInfo.clientCtx on worker side // * user can import a read only `import { clientCtx } from "rwsdk/client"` // on client side const clientContext = { rw: { ssr: shouldSSR, }, }; return (_jsxs(Document, { ...requestInfo, children: [_jsx("script", { nonce: requestInfo.rw.nonce, dangerouslySetInnerHTML: { __html: `globalThis.__RWSDK_CONTEXT = ${JSON.stringify(clientContext)}`, } }), _jsx("div", { id: "hydrate-root", children: node })] })); }; return await renderToReadableStream(_jsx(Component, {}), { nonce: requestInfo.rw.nonce, onError(error, { componentStack }) { try { if (!error) { error = new Error(`A falsy value was thrown during rendering: ${String(error)}.`); } const message = error ? (error.stack ?? error.message ?? error) : error; const wrappedMessage = `${message}\n\nComponent stack:${componentStack}`; if (error instanceof Error) { const wrappedError = new Error(wrappedMessage); wrappedError.stack = error.stack; error = wrappedError; } else { error = new Error(wrappedMessage); error.stack = componentStack; } onError(error); } catch { onError(error); } }, }); };