UNPKG

@tanstack/solid-router

Version:

Modern and scalable routing for Solid applications

86 lines (85 loc) 3.07 kB
import { makeSsrSerovalPlugin } from "@tanstack/router-core"; import * as Solid from "solid-js/web"; import { memo } from "solid-js/web"; import { createSsrStreamResponse, transformReadableStreamWithRouter } from "@tanstack/router-core/ssr/server"; import { isbot } from "isbot"; //#region src/ssr/renderRouterToStream.tsx var noop = () => {}; async function waitForReadyOrAbort(ready, signal) { let cleanup = noop; try { await Promise.race([ready, new Promise((resolve) => { const onAbort = () => resolve(); cleanup = () => signal.removeEventListener("abort", onAbort); signal.addEventListener("abort", onAbort, { once: true }); if (signal.aborted) resolve(); })]); } finally { cleanup(); } } var renderRouterToStream = async ({ request, router, responseHeaders, children }) => { const { writable, readable } = new TransformStream(); const docType = Solid.ssr("<!DOCTYPE html>"); const serovalPlugins = (router.options?.serializationAdapters || router.options.ssr?.serializationAdapters)?.map((adapter) => { return makeSsrSerovalPlugin(adapter, { didRun: false }); }); const stream = Solid.renderToStream(() => [docType, memo(children)], { nonce: router.options.ssr?.nonce, plugins: serovalPlugins }); const innerWriter = writable.getWriter(); let writerDone = false; const releaseWriter = () => { try { innerWriter.releaseLock(); } catch {} }; const abortSolidPipe = (reason) => { if (writerDone) return; writerDone = true; innerWriter.abort(reason).catch(() => {}).finally(releaseWriter); }; const onRequestAbort = () => { abortSolidPipe(request.signal.reason); }; if (request.signal.aborted) onRequestAbort(); else { request.signal.addEventListener("abort", onRequestAbort, { once: true }); router.serverSsr?.onCleanup(() => { request.signal.removeEventListener("abort", onRequestAbort); }); } if (isbot(request.headers.get("User-Agent"))) await waitForReadyOrAbort(Promise.resolve(stream), request.signal); const solidWritable = new WritableStream({ write(chunk) { return innerWriter.write(chunk); }, close() { writerDone = true; return innerWriter.close().finally(releaseWriter); }, abort(reason) { writerDone = true; return innerWriter.abort(reason).finally(releaseWriter); } }); if (!request.signal.aborted) try { Promise.resolve(stream.pipeTo(solidWritable)).catch((err) => { if (writerDone || err?.name === "AbortError" || err?.code === "ABORT_ERR") return; console.error("Error in Solid render stream:", err); abortSolidPipe(err); }); } catch (err) { if (err?.name !== "AbortError" && err?.code !== "ABORT_ERR") console.error("Error in Solid render stream:", err); abortSolidPipe(err); } const responseStream = transformReadableStreamWithRouter(router, readable, { onAbort: abortSolidPipe }); return createSsrStreamResponse(router, new Response(responseStream, { status: router.stores.statusCode.get(), headers: responseHeaders })); }; //#endregion export { renderRouterToStream }; //# sourceMappingURL=renderRouterToStream.js.map