UNPKG

@tanstack/solid-start

Version:

Modern and scalable routing for Solid applications

126 lines (125 loc) 4.35 kB
import { handleSolidServerFunctionRequest } from "./server-functions-handler.js"; import { createMemoryHistory } from "@tanstack/solid-router"; import { createNullProtoObject, flattenMiddlewares, safeObjectMerge } from "@tanstack/start-client-core"; import { provideRequestEvent } from "@solidjs/web/storage"; import { createStartHandler } from "@tanstack/solid-start-server"; import { getResponse, requestHandler } from "@tanstack/start-server-core/request-response"; //#region src/createSolidStartHandler.ts function createSolidStartHandler(cbOrOptions) { const startHandler = createStartHandler(cbOrOptions); const solidServerFnHandler = requestHandler(async (request, requestOptions) => { const getRouter = createRequestRouterGetter(request); const startOptions = await getRequestStartOptions(getRouter); const requestMiddlewares = flattenMiddlewares(startOptions.requestMiddleware ?? []); const response = await executeRequestMiddleware(request, requestMiddlewares, requestOptions?.context, async (context) => { return await handleSolidServerFunctionRequest(request, { startContext: { contextAfterGlobalMiddlewares: context, executedRequestMiddlewares: new Set(requestMiddlewares), getRouter, request, startOptions } }); }); const startResponse = getResponse(); const status = startResponse.status || 200; const statusText = startResponse.statusText || ""; if (response.status !== 200 || response.status === status && response.statusText === statusText) return response; return new Response(response.body, { headers: response.headers, status, statusText }); }); return (async (request, requestOptions) => { return await provideRequestEvent({ request, locals: {} }, async () => { const serverFnBase = process.env.TSS_SERVER_FN_BASE; const url = new URL(request.url); if (serverFnBase && url.pathname.startsWith(serverFnBase)) return await solidServerFnHandler(request, requestOptions); return await startHandler(request, requestOptions); }); }); } async function executeRequestMiddleware(request, middlewares, initialContext, handler) { const pathname = new URL(request.url).pathname; const dispatch = async (index, context) => { request.signal.throwIfAborted(); const middleware = middlewares[index]?.options.server; if (!middleware) { if (index < middlewares.length) return await dispatch(index + 1, context); return { request, pathname, context, response: await handler(context) }; } let nextCalled = false; const next = async (options) => { if (nextCalled) throw new Error("Request middleware called next() more than once"); nextCalled = true; return await dispatch(index + 1, safeObjectMerge(context, options?.context)); }; try { const result = await middleware({ request, pathname, handlerType: "serverFn", context, next }); if (result instanceof Response) return { request, pathname, context, response: result }; return result; } catch (error) { if (error instanceof Response) return { request, pathname, context, response: error }; throw error; } }; return (await dispatch(0, createNullProtoObject(initialContext))).response; } async function getRequestStartOptions(getRouter) { const [startEntry, pluginAdapters, router] = await Promise.all([ import("#tanstack-start-entry"), import("#tanstack-start-plugin-adapters"), getRouter() ]); const startOptions = await startEntry.startInstance?.getOptions() ?? {}; return { ...startOptions, serializationAdapters: [ ...startOptions.serializationAdapters ?? [], ...pluginAdapters.hasPluginAdapters ? pluginAdapters.pluginSerializationAdapters : [], ...router.options.serializationAdapters ?? [] ] }; } function createRequestRouterGetter(request) { let routerPromise; return async () => { routerPromise ??= import("#tanstack-router-entry").then(async ({ getRouter }) => { const router = await getRouter(); const url = new URL(request.url); router.update({ history: createMemoryHistory({ initialEntries: [url.pathname + url.search + url.hash] }), origin: url.origin }); return router; }); return await routerPromise; }; } //#endregion export { createSolidStartHandler }; //# sourceMappingURL=createSolidStartHandler.js.map