UNPKG

@tanstack/solid-start

Version:

Modern and scalable routing for Solid applications

126 lines (125 loc) 5.48 kB
import { getSolidStartServerFunctionCodec } from "./solid-rpc-codec.js"; import { collectSolidStartFlightData } from "./solid-rpc-flight-server.js"; import { redirect } from "@tanstack/solid-router"; import { FUNCTION_HEADER, configureServerFunctionsServer, createNoJSHandler, handleServerFunctionRequest } from "@solidjs/web/server-functions/server"; import { getServerFnById } from "#tanstack-start-server-fn-resolver"; import { provideRequestEvent } from "@solidjs/web/storage"; import { getStartContext, runWithStartContext } from "@tanstack/start-storage-context"; //#region src/server-functions-handler.ts configureServerFunctionsServer({ provideEvent: provideRequestEvent }); var solidNoJSHandler = createNoJSHandler(); async function handleSolidServerFunctionRequest(request, options = {}) { const serverFnId = getSolidServerFunctionId(request); if (!serverFnId) throw new Error("Unable to resolve Solid server function id from request"); await getServerFnById(serverFnId, { origin: "client" }); const requestWithId = withSolidServerFunctionId(request, serverFnId); const { startContext, ...solidOptions } = options; const transformResult = solidOptions.transformResult; const handleNoJS = solidOptions.handleNoJS; const collectFlightData = solidOptions.collectFlightData; const existingStartContext = getStartContext({ throwIfNotFound: false }); const handlerOptions = { ...solidOptions, collectFlightData: collectFlightData ?? collectSolidStartFlightData, transformResult: async (event, result, context) => { return adaptTanStackResult(transformResult ? await transformResult(event, result, context) : result); }, handleNoJS: async (result, currentRequest, args, thrown) => { if (handleNoJS) return await handleNoJS(result, currentRequest, args, thrown); return await handleSolidStartNoJS(result, currentRequest, args, thrown); } }; const handleRequest = () => handleServerFunctionRequest(requestWithId, { codec: getSolidStartServerFunctionCodec(), ...handlerOptions }); if (existingStartContext) return await handleRequest(); return await runWithStartContext({ getRouter: unavailableRouter, request, startOptions: {}, contextAfterGlobalMiddlewares: {}, executedRequestMiddlewares: /* @__PURE__ */ new Set(), handlerType: "serverFn", ...startContext }, handleRequest); } function getSolidServerFunctionId(request) { const headerId = request.headers.get(FUNCTION_HEADER); if (headerId) return headerId; const url = new URL(request.url); const queryId = url.searchParams.get("id"); if (queryId) return queryId; const serverFnBase = process.env.TSS_SERVER_FN_BASE; if (serverFnBase && url.pathname.startsWith(serverFnBase)) return url.pathname.slice(serverFnBase.length).split("/")[0]; } function withSolidServerFunctionId(request, serverFnId) { if (request.headers.has(FUNCTION_HEADER)) return request; try { request.headers.set(FUNCTION_HEADER, serverFnId); return request; } catch { const clonedRequest = request.clone(); clonedRequest.headers.set(FUNCTION_HEADER, serverFnId); return clonedRequest; } } function serializeTanStackRedirect(result) { if (!isObject(result) || !isTanStackRedirect(result.error)) return result; const redirectResponse = result.error; return { ...result, error: { ...redirectResponse.options, headers: Object.fromEntries(redirectResponse.headers), isSerializedRedirect: true } }; } function adaptTanStackResult(result) { const serialized = serializeTanStackRedirect(result); if (!isTanStackResultEnvelope(serialized)) return serialized; return Object.fromEntries(Object.entries(serialized).filter(([, value]) => value !== void 0)); } async function handleSolidStartNoJS(result, request, args, thrown) { if (isObject(result) && isSerializedRedirect(result.error)) { const startContext = getStartContext({ throwIfNotFound: false }); if (startContext) return (await startContext.getRouter()).resolveRedirect(redirect(result.error)); } if (isObject(result)) { const unwrapped = result.result ?? result.error; if (isResponseLike(unwrapped)) return normalizeResponse(unwrapped); if (typeof unwrapped === "string") return new Response(unwrapped); if (unwrapped !== void 0) return Response.json(unwrapped); } return solidNoJSHandler(result, request, args, thrown); } function isTanStackRedirect(value) { return isResponseLike(value) && isObject(value.options); } function isTanStackResultEnvelope(value) { return isObject(value) && ("result" in value || "error" in value || "context" in value); } function isResponseLike(value) { return isObject(value) && typeof value.status === "number" && isObject(value.headers) && typeof value.headers.forEach === "function" && ("body" in value || typeof value.text === "function"); } function normalizeResponse(response) { if (response instanceof Response) return response; return new Response(response.body, { headers: response.headers, status: response.status, statusText: response.statusText }); } function isSerializedRedirect(value) { return isObject(value) && value.isSerializedRedirect === true; } function isObject(value) { return !!value && typeof value === "object"; } function unavailableRouter() { throw new Error("Router context is not available in handleSolidServerFunctionRequest. Use it inside createStartHandler or pass startContext.getRouter."); } //#endregion export { handleSolidServerFunctionRequest }; //# sourceMappingURL=server-functions-handler.js.map