@tanstack/solid-router
Version:
Modern and scalable routing for Solid applications
86 lines (85 loc) • 3.07 kB
JavaScript
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