@tanstack/solid-start
Version:
Modern and scalable routing for Solid applications
126 lines (125 loc) • 4.35 kB
JavaScript
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