import { hydrateRoot } from "https://esm.sh/react-dom@18.3.1/client";
import { renderToReadableStream } from "https://esm.sh/react-dom@18.3.1/server";
import * as React from "https://esm.sh/react@18.3.1";
type RequestHandler = (request: Request) => Promise<Response>;
type DataFetcher = (request: Request) => Promise<any>;
export function render(Component: React.ComponentType<any>, module: string, requestHandler?: RequestHandler, dataFetcher?: DataFetcher) {
console.log("resrv.render");
if (typeof document !== "undefined") {
console.log("resrv.hydrateRoot");
const props = window.__data;
hydrateRoot(document, <Component {...props} />);
}
return async function(req: Request): Promise<Response> {
if (requestHandler && req.method !== "GET") {
return await requestHandler(req);
}
const url = new URL(req.url);
const { pathname, search } = url;
const searchParams = paramsToObject(new URLSearchParams(url.search));
const cookie = req.headers.get("cookie");
let data = {};
if (dataFetcher) {
data = await dataFetcher(req);
}
const props = {
url,
pathname,
search,
searchParams,
headers: req.headers,
cookie,
data,
};
const stream = await renderToReadableStream(<Component {...props} />, {
bootstrapModules: [
module,
],
bootstrapScriptContent: `window.__data=${JSON.stringify(props)}`,
});
return new Response(stream, { headers: { "Content-Type": "text/html" } });
};
}
export default render;
function paramsToObject(entries) {
const result = {};
for (const [key, value] of entries) {
result[key] = value;
}
return result;
}
export { React };
export {
useCallback,
useContext,
useEffect,
useMemo,
useReducer,
useRef,
useState,
} from "https://esm.sh/react@18.3.1";