@tanstack/start-server-core 1.166.9 → 1.166.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,439 +1,377 @@
1
- import { createMemoryHistory } from "@tanstack/history";
2
- import { flattenMiddlewares, createNullProtoObject, mergeHeaders, safeObjectMerge } from "@tanstack/start-client-core";
3
- import { isRedirect, isResolvedRedirect, executeRewriteInput } from "@tanstack/router-core";
4
- import { getNormalizedURL, getOrigin, attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
5
- import { runWithStartContext } from "@tanstack/start-storage-context";
6
1
  import { requestHandler } from "./request-response.js";
7
2
  import { getStartManifest } from "./router-manifest.js";
8
3
  import { handleServerAction } from "./server-functions-handler.js";
9
- import { resolveTransformConfig, transformManifestUrls, buildManifestWithClientEntry } from "./transformAssetUrls.js";
4
+ import { buildManifestWithClientEntry, resolveTransformConfig, transformManifestUrls } from "./transformAssetUrls.js";
10
5
  import { HEADERS } from "./constants.js";
11
6
  import { ServerFunctionSerializationAdapter } from "./serializer/ServerFunctionSerializationAdapter.js";
7
+ import { createMemoryHistory } from "@tanstack/history";
8
+ import { createNullProtoObject, flattenMiddlewares, mergeHeaders, safeObjectMerge } from "@tanstack/start-client-core";
9
+ import { executeRewriteInput, isRedirect, isResolvedRedirect } from "@tanstack/router-core";
10
+ import { attachRouterServerSsrUtils, getNormalizedURL, getOrigin } from "@tanstack/router-core/ssr/server";
11
+ import { runWithStartContext } from "@tanstack/start-storage-context";
12
+ //#region src/createStartHandler.ts
12
13
  function getStartResponseHeaders(opts) {
13
- const headers = mergeHeaders(
14
- {
15
- "Content-Type": "text/html; charset=utf-8"
16
- },
17
- ...opts.router.state.matches.map((match) => {
18
- return match.headers;
19
- })
20
- );
21
- return headers;
14
+ return mergeHeaders({ "Content-Type": "text/html; charset=utf-8" }, ...opts.router.state.matches.map((match) => {
15
+ return match.headers;
16
+ }));
22
17
  }
23
- let entriesPromise;
24
- let baseManifestPromise;
25
- let cachedFinalManifestPromise;
18
+ var entriesPromise;
19
+ var baseManifestPromise;
20
+ /**
21
+ * Cached final manifest (with client entry script tag). In production,
22
+ * this is computed once and reused for every request when caching is enabled.
23
+ */
24
+ var cachedFinalManifestPromise;
26
25
  async function loadEntries() {
27
- const routerEntry = await import("#tanstack-router-entry");
28
- const startEntry = await import("#tanstack-start-entry");
29
- return { startEntry, routerEntry };
26
+ const routerEntry = await import("#tanstack-router-entry");
27
+ return {
28
+ startEntry: await import("#tanstack-start-entry"),
29
+ routerEntry
30
+ };
30
31
  }
31
32
  function getEntries() {
32
- if (!entriesPromise) {
33
- entriesPromise = loadEntries();
34
- }
35
- return entriesPromise;
33
+ if (!entriesPromise) entriesPromise = loadEntries();
34
+ return entriesPromise;
36
35
  }
36
+ /**
37
+ * Returns the raw manifest data (without client entry script tag baked in).
38
+ * In dev mode, always returns fresh data. In prod, cached.
39
+ */
37
40
  function getBaseManifest(matchedRoutes) {
38
- if (process.env.TSS_DEV_SERVER === "true") {
39
- return getStartManifest(matchedRoutes);
40
- }
41
- if (!baseManifestPromise) {
42
- baseManifestPromise = getStartManifest();
43
- }
44
- return baseManifestPromise;
41
+ if (process.env.TSS_DEV_SERVER === "true") return getStartManifest(matchedRoutes);
42
+ if (!baseManifestPromise) baseManifestPromise = getStartManifest();
43
+ return baseManifestPromise;
45
44
  }
45
+ /**
46
+ * Resolves a final Manifest for a given request.
47
+ *
48
+ * - No transform: builds client entry script tag and returns (cached in prod).
49
+ * - Cached transform: transforms all URLs + builds script tag, caches result.
50
+ * - Per-request transform: deep-clones base manifest, transforms per-request.
51
+ */
46
52
  async function resolveManifest(matchedRoutes, transformFn, cache) {
47
- const base = await getBaseManifest(matchedRoutes);
48
- const computeFinalManifest = async () => {
49
- return transformFn ? await transformManifestUrls(base, transformFn, { clone: !cache }) : buildManifestWithClientEntry(base);
50
- };
51
- if (process.env.TSS_DEV_SERVER === "true") {
52
- return computeFinalManifest();
53
- }
54
- if (!transformFn || cache) {
55
- if (!cachedFinalManifestPromise) {
56
- cachedFinalManifestPromise = computeFinalManifest();
57
- }
58
- return cachedFinalManifestPromise;
59
- }
60
- return computeFinalManifest();
53
+ const base = await getBaseManifest(matchedRoutes);
54
+ const computeFinalManifest = async () => {
55
+ return transformFn ? await transformManifestUrls(base, transformFn, { clone: !cache }) : buildManifestWithClientEntry(base);
56
+ };
57
+ if (process.env.TSS_DEV_SERVER === "true") return computeFinalManifest();
58
+ if (!transformFn || cache) {
59
+ if (!cachedFinalManifestPromise) cachedFinalManifestPromise = computeFinalManifest();
60
+ return cachedFinalManifestPromise;
61
+ }
62
+ return computeFinalManifest();
61
63
  }
62
- const ROUTER_BASEPATH = process.env.TSS_ROUTER_BASEPATH || "/";
63
- const SERVER_FN_BASE = process.env.TSS_SERVER_FN_BASE;
64
- const IS_PRERENDERING = process.env.TSS_PRERENDERING === "true";
65
- const IS_SHELL_ENV = process.env.TSS_SHELL === "true";
66
- const IS_DEV = process.env.NODE_ENV === "development";
67
- const ERR_NO_RESPONSE = IS_DEV ? `It looks like you forgot to return a response from your server route handler. If you want to defer to the app router, make sure to have a component set in this route.` : "Internal Server Error";
68
- const ERR_NO_DEFER = IS_DEV ? `You cannot defer to the app router if there is no component defined on this route.` : "Internal Server Error";
64
+ var ROUTER_BASEPATH = process.env.TSS_ROUTER_BASEPATH || "/";
65
+ var SERVER_FN_BASE = process.env.TSS_SERVER_FN_BASE;
66
+ var IS_PRERENDERING = process.env.TSS_PRERENDERING === "true";
67
+ var IS_SHELL_ENV = process.env.TSS_SHELL === "true";
68
+ var IS_DEV = process.env.NODE_ENV === "development";
69
+ var ERR_NO_RESPONSE = IS_DEV ? `It looks like you forgot to return a response from your server route handler. If you want to defer to the app router, make sure to have a component set in this route.` : "Internal Server Error";
70
+ var ERR_NO_DEFER = IS_DEV ? `You cannot defer to the app router if there is no component defined on this route.` : "Internal Server Error";
69
71
  function throwRouteHandlerError() {
70
- throw new Error(ERR_NO_RESPONSE);
72
+ throw new Error(ERR_NO_RESPONSE);
71
73
  }
72
74
  function throwIfMayNotDefer() {
73
- throw new Error(ERR_NO_DEFER);
75
+ throw new Error(ERR_NO_DEFER);
74
76
  }
77
+ /**
78
+ * Check if a value is a special response (Response or Redirect)
79
+ */
75
80
  function isSpecialResponse(value) {
76
- return value instanceof Response || isRedirect(value);
81
+ return value instanceof Response || isRedirect(value);
77
82
  }
83
+ /**
84
+ * Normalize middleware result to context shape
85
+ */
78
86
  function handleCtxResult(result) {
79
- if (isSpecialResponse(result)) {
80
- return { response: result };
81
- }
82
- return result;
87
+ if (isSpecialResponse(result)) return { response: result };
88
+ return result;
83
89
  }
90
+ /**
91
+ * Execute a middleware chain
92
+ */
84
93
  function executeMiddleware(middlewares, ctx) {
85
- let index = -1;
86
- const next = async (nextCtx) => {
87
- if (nextCtx) {
88
- if (nextCtx.context) {
89
- ctx.context = safeObjectMerge(ctx.context, nextCtx.context);
90
- }
91
- for (const key of Object.keys(nextCtx)) {
92
- if (key !== "context") {
93
- ctx[key] = nextCtx[key];
94
- }
95
- }
96
- }
97
- index++;
98
- const middleware = middlewares[index];
99
- if (!middleware) return ctx;
100
- let result;
101
- try {
102
- result = await middleware({ ...ctx, next });
103
- } catch (err) {
104
- if (isSpecialResponse(err)) {
105
- ctx.response = err;
106
- return ctx;
107
- }
108
- throw err;
109
- }
110
- const normalized = handleCtxResult(result);
111
- if (normalized) {
112
- if (normalized.response !== void 0) {
113
- ctx.response = normalized.response;
114
- }
115
- if (normalized.context) {
116
- ctx.context = safeObjectMerge(ctx.context, normalized.context);
117
- }
118
- }
119
- return ctx;
120
- };
121
- return next();
94
+ let index = -1;
95
+ const next = async (nextCtx) => {
96
+ if (nextCtx) {
97
+ if (nextCtx.context) ctx.context = safeObjectMerge(ctx.context, nextCtx.context);
98
+ for (const key of Object.keys(nextCtx)) if (key !== "context") ctx[key] = nextCtx[key];
99
+ }
100
+ index++;
101
+ const middleware = middlewares[index];
102
+ if (!middleware) return ctx;
103
+ let result;
104
+ try {
105
+ result = await middleware({
106
+ ...ctx,
107
+ next
108
+ });
109
+ } catch (err) {
110
+ if (isSpecialResponse(err)) {
111
+ ctx.response = err;
112
+ return ctx;
113
+ }
114
+ throw err;
115
+ }
116
+ const normalized = handleCtxResult(result);
117
+ if (normalized) {
118
+ if (normalized.response !== void 0) ctx.response = normalized.response;
119
+ if (normalized.context) ctx.context = safeObjectMerge(ctx.context, normalized.context);
120
+ }
121
+ return ctx;
122
+ };
123
+ return next();
122
124
  }
125
+ /**
126
+ * Wrap a route handler as middleware
127
+ */
123
128
  function handlerToMiddleware(handler, mayDefer = false) {
124
- if (mayDefer) {
125
- return handler;
126
- }
127
- return async (ctx) => {
128
- const response = await handler({ ...ctx, next: throwIfMayNotDefer });
129
- if (!response) {
130
- throwRouteHandlerError();
131
- }
132
- return response;
133
- };
129
+ if (mayDefer) return handler;
130
+ return async (ctx) => {
131
+ const response = await handler({
132
+ ...ctx,
133
+ next: throwIfMayNotDefer
134
+ });
135
+ if (!response) throwRouteHandlerError();
136
+ return response;
137
+ };
134
138
  }
139
+ /**
140
+ * Creates the TanStack Start request handler.
141
+ *
142
+ * @example Backwards-compatible usage (handler callback only):
143
+ * ```ts
144
+ * export default createStartHandler(defaultStreamHandler)
145
+ * ```
146
+ *
147
+ * @example With CDN URL rewriting:
148
+ * ```ts
149
+ * export default createStartHandler({
150
+ * handler: defaultStreamHandler,
151
+ * transformAssetUrls: 'https://cdn.example.com',
152
+ * })
153
+ * ```
154
+ *
155
+ * @example With per-request URL rewriting:
156
+ * ```ts
157
+ * export default createStartHandler({
158
+ * handler: defaultStreamHandler,
159
+ * transformAssetUrls: {
160
+ * transform: ({ url }) => {
161
+ * const cdnBase = getRequest().headers.get('x-cdn-base') || ''
162
+ * return `${cdnBase}${url}`
163
+ * },
164
+ * cache: false,
165
+ * },
166
+ * })
167
+ * ```
168
+ */
135
169
  function createStartHandler(cbOrOptions) {
136
- const cb = typeof cbOrOptions === "function" ? cbOrOptions : cbOrOptions.handler;
137
- const transformAssetUrlsOption = typeof cbOrOptions === "function" ? void 0 : cbOrOptions.transformAssetUrls;
138
- const warmupTransformManifest = !!transformAssetUrlsOption && typeof transformAssetUrlsOption === "object" && transformAssetUrlsOption.warmup === true;
139
- const resolvedTransformConfig = transformAssetUrlsOption ? resolveTransformConfig(transformAssetUrlsOption) : void 0;
140
- const cache = resolvedTransformConfig ? resolvedTransformConfig.cache : true;
141
- let cachedCreateTransformPromise;
142
- const getTransformFn = async (opts) => {
143
- if (!resolvedTransformConfig) return void 0;
144
- if (resolvedTransformConfig.type === "createTransform") {
145
- if (cache) {
146
- if (!cachedCreateTransformPromise) {
147
- cachedCreateTransformPromise = Promise.resolve(
148
- resolvedTransformConfig.createTransform(opts)
149
- );
150
- }
151
- return cachedCreateTransformPromise;
152
- }
153
- return resolvedTransformConfig.createTransform(opts);
154
- }
155
- return resolvedTransformConfig.transformFn;
156
- };
157
- if (warmupTransformManifest && cache && process.env.TSS_DEV_SERVER !== "true" && !cachedFinalManifestPromise) {
158
- const warmupPromise = (async () => {
159
- const base = await getBaseManifest(void 0);
160
- const transformFn = await getTransformFn({ warmup: true });
161
- return transformFn ? await transformManifestUrls(base, transformFn, { clone: false }) : buildManifestWithClientEntry(base);
162
- })();
163
- cachedFinalManifestPromise = warmupPromise;
164
- warmupPromise.catch(() => {
165
- if (cachedFinalManifestPromise === warmupPromise) {
166
- cachedFinalManifestPromise = void 0;
167
- }
168
- cachedCreateTransformPromise = void 0;
169
- });
170
- }
171
- const startRequestResolver = async (request, requestOpts) => {
172
- let router = null;
173
- let cbWillCleanup = false;
174
- try {
175
- const { url, handledProtocolRelativeURL } = getNormalizedURL(request.url);
176
- const href = url.pathname + url.search + url.hash;
177
- const origin = getOrigin(request);
178
- if (handledProtocolRelativeURL) {
179
- return Response.redirect(url, 308);
180
- }
181
- const entries = await getEntries();
182
- const startOptions = await entries.startEntry.startInstance?.getOptions() || {};
183
- const serializationAdapters = [
184
- ...startOptions.serializationAdapters || [],
185
- ServerFunctionSerializationAdapter
186
- ];
187
- const requestStartOptions = {
188
- ...startOptions,
189
- serializationAdapters
190
- };
191
- const flattenedRequestMiddlewares = startOptions.requestMiddleware ? flattenMiddlewares(startOptions.requestMiddleware) : [];
192
- const executedRequestMiddlewares = new Set(
193
- flattenedRequestMiddlewares
194
- );
195
- const getRouter = async () => {
196
- if (router) return router;
197
- router = await entries.routerEntry.getRouter();
198
- let isShell = IS_SHELL_ENV;
199
- if (IS_PRERENDERING && !isShell) {
200
- isShell = request.headers.get(HEADERS.TSS_SHELL) === "true";
201
- }
202
- const history = createMemoryHistory({
203
- initialEntries: [href]
204
- });
205
- router.update({
206
- history,
207
- isShell,
208
- isPrerendering: IS_PRERENDERING,
209
- origin: router.options.origin ?? origin,
210
- ...{
211
- defaultSsr: requestStartOptions.defaultSsr,
212
- serializationAdapters: [
213
- ...requestStartOptions.serializationAdapters,
214
- ...router.options.serializationAdapters || []
215
- ]
216
- },
217
- basepath: ROUTER_BASEPATH
218
- });
219
- return router;
220
- };
221
- if (SERVER_FN_BASE && url.pathname.startsWith(SERVER_FN_BASE)) {
222
- const serverFnId = url.pathname.slice(SERVER_FN_BASE.length).split("/")[0];
223
- if (!serverFnId) {
224
- throw new Error("Invalid server action param for serverFnId");
225
- }
226
- const serverFnHandler = async ({ context }) => {
227
- return runWithStartContext(
228
- {
229
- getRouter,
230
- startOptions: requestStartOptions,
231
- contextAfterGlobalMiddlewares: context,
232
- request,
233
- executedRequestMiddlewares
234
- },
235
- () => handleServerAction({
236
- request,
237
- context: requestOpts?.context,
238
- serverFnId
239
- })
240
- );
241
- };
242
- const middlewares2 = flattenedRequestMiddlewares.map(
243
- (d) => d.options.server
244
- );
245
- const ctx2 = await executeMiddleware([...middlewares2, serverFnHandler], {
246
- request,
247
- pathname: url.pathname,
248
- context: createNullProtoObject(requestOpts?.context)
249
- });
250
- return handleRedirectResponse(ctx2.response, request, getRouter);
251
- }
252
- const executeRouter = async (serverContext, matchedRoutes) => {
253
- const acceptHeader = request.headers.get("Accept") || "*/*";
254
- const acceptParts = acceptHeader.split(",");
255
- const supportedMimeTypes = ["*/*", "text/html"];
256
- const isSupported = supportedMimeTypes.some(
257
- (mimeType) => acceptParts.some((part) => part.trim().startsWith(mimeType))
258
- );
259
- if (!isSupported) {
260
- return Response.json(
261
- { error: "Only HTML requests are supported here" },
262
- { status: 500 }
263
- );
264
- }
265
- const manifest = await resolveManifest(
266
- matchedRoutes,
267
- await getTransformFn({ warmup: false, request }),
268
- cache
269
- );
270
- const routerInstance = await getRouter();
271
- attachRouterServerSsrUtils({
272
- router: routerInstance,
273
- manifest
274
- });
275
- routerInstance.update({ additionalContext: { serverContext } });
276
- await routerInstance.load();
277
- if (routerInstance.state.redirect) {
278
- return routerInstance.state.redirect;
279
- }
280
- await routerInstance.serverSsr.dehydrate();
281
- const responseHeaders = getStartResponseHeaders({
282
- router: routerInstance
283
- });
284
- cbWillCleanup = true;
285
- return cb({
286
- request,
287
- router: routerInstance,
288
- responseHeaders
289
- });
290
- };
291
- const requestHandlerMiddleware = async ({ context }) => {
292
- return runWithStartContext(
293
- {
294
- getRouter,
295
- startOptions: requestStartOptions,
296
- contextAfterGlobalMiddlewares: context,
297
- request,
298
- executedRequestMiddlewares
299
- },
300
- async () => {
301
- try {
302
- return await handleServerRoutes({
303
- getRouter,
304
- request,
305
- url,
306
- executeRouter,
307
- context,
308
- executedRequestMiddlewares
309
- });
310
- } catch (err) {
311
- if (err instanceof Response) {
312
- return err;
313
- }
314
- throw err;
315
- }
316
- }
317
- );
318
- };
319
- const middlewares = flattenedRequestMiddlewares.map(
320
- (d) => d.options.server
321
- );
322
- const ctx = await executeMiddleware(
323
- [...middlewares, requestHandlerMiddleware],
324
- {
325
- request,
326
- pathname: url.pathname,
327
- context: createNullProtoObject(requestOpts?.context)
328
- }
329
- );
330
- return handleRedirectResponse(ctx.response, request, getRouter);
331
- } finally {
332
- if (router && !cbWillCleanup) {
333
- router.serverSsr?.cleanup();
334
- }
335
- router = null;
336
- }
337
- };
338
- return requestHandler(startRequestResolver);
170
+ const cb = typeof cbOrOptions === "function" ? cbOrOptions : cbOrOptions.handler;
171
+ const transformAssetUrlsOption = typeof cbOrOptions === "function" ? void 0 : cbOrOptions.transformAssetUrls;
172
+ const warmupTransformManifest = !!transformAssetUrlsOption && typeof transformAssetUrlsOption === "object" && transformAssetUrlsOption.warmup === true;
173
+ const resolvedTransformConfig = transformAssetUrlsOption ? resolveTransformConfig(transformAssetUrlsOption) : void 0;
174
+ const cache = resolvedTransformConfig ? resolvedTransformConfig.cache : true;
175
+ let cachedCreateTransformPromise;
176
+ const getTransformFn = async (opts) => {
177
+ if (!resolvedTransformConfig) return void 0;
178
+ if (resolvedTransformConfig.type === "createTransform") {
179
+ if (cache) {
180
+ if (!cachedCreateTransformPromise) cachedCreateTransformPromise = Promise.resolve(resolvedTransformConfig.createTransform(opts));
181
+ return cachedCreateTransformPromise;
182
+ }
183
+ return resolvedTransformConfig.createTransform(opts);
184
+ }
185
+ return resolvedTransformConfig.transformFn;
186
+ };
187
+ if (warmupTransformManifest && cache && process.env.TSS_DEV_SERVER !== "true" && !cachedFinalManifestPromise) {
188
+ const warmupPromise = (async () => {
189
+ const base = await getBaseManifest(void 0);
190
+ const transformFn = await getTransformFn({ warmup: true });
191
+ return transformFn ? await transformManifestUrls(base, transformFn, { clone: false }) : buildManifestWithClientEntry(base);
192
+ })();
193
+ cachedFinalManifestPromise = warmupPromise;
194
+ warmupPromise.catch(() => {
195
+ if (cachedFinalManifestPromise === warmupPromise) cachedFinalManifestPromise = void 0;
196
+ cachedCreateTransformPromise = void 0;
197
+ });
198
+ }
199
+ const startRequestResolver = async (request, requestOpts) => {
200
+ let router = null;
201
+ let cbWillCleanup = false;
202
+ try {
203
+ const { url, handledProtocolRelativeURL } = getNormalizedURL(request.url);
204
+ const href = url.pathname + url.search + url.hash;
205
+ const origin = getOrigin(request);
206
+ if (handledProtocolRelativeURL) return Response.redirect(url, 308);
207
+ const entries = await getEntries();
208
+ const startOptions = await entries.startEntry.startInstance?.getOptions() || {};
209
+ const serializationAdapters = [...startOptions.serializationAdapters || [], ServerFunctionSerializationAdapter];
210
+ const requestStartOptions = {
211
+ ...startOptions,
212
+ serializationAdapters
213
+ };
214
+ const flattenedRequestMiddlewares = startOptions.requestMiddleware ? flattenMiddlewares(startOptions.requestMiddleware) : [];
215
+ const executedRequestMiddlewares = new Set(flattenedRequestMiddlewares);
216
+ const getRouter = async () => {
217
+ if (router) return router;
218
+ router = await entries.routerEntry.getRouter();
219
+ let isShell = IS_SHELL_ENV;
220
+ if (IS_PRERENDERING && !isShell) isShell = request.headers.get(HEADERS.TSS_SHELL) === "true";
221
+ const history = createMemoryHistory({ initialEntries: [href] });
222
+ router.update({
223
+ history,
224
+ isShell,
225
+ isPrerendering: IS_PRERENDERING,
226
+ origin: router.options.origin ?? origin,
227
+ defaultSsr: requestStartOptions.defaultSsr,
228
+ serializationAdapters: [...requestStartOptions.serializationAdapters, ...router.options.serializationAdapters || []],
229
+ basepath: ROUTER_BASEPATH
230
+ });
231
+ return router;
232
+ };
233
+ if (SERVER_FN_BASE && url.pathname.startsWith(SERVER_FN_BASE)) {
234
+ const serverFnId = url.pathname.slice(SERVER_FN_BASE.length).split("/")[0];
235
+ if (!serverFnId) throw new Error("Invalid server action param for serverFnId");
236
+ const serverFnHandler = async ({ context }) => {
237
+ return runWithStartContext({
238
+ getRouter,
239
+ startOptions: requestStartOptions,
240
+ contextAfterGlobalMiddlewares: context,
241
+ request,
242
+ executedRequestMiddlewares
243
+ }, () => handleServerAction({
244
+ request,
245
+ context: requestOpts?.context,
246
+ serverFnId
247
+ }));
248
+ };
249
+ return handleRedirectResponse((await executeMiddleware([...flattenedRequestMiddlewares.map((d) => d.options.server), serverFnHandler], {
250
+ request,
251
+ pathname: url.pathname,
252
+ context: createNullProtoObject(requestOpts?.context)
253
+ })).response, request, getRouter);
254
+ }
255
+ const executeRouter = async (serverContext, matchedRoutes) => {
256
+ const acceptParts = (request.headers.get("Accept") || "*/*").split(",");
257
+ if (!["*/*", "text/html"].some((mimeType) => acceptParts.some((part) => part.trim().startsWith(mimeType)))) return Response.json({ error: "Only HTML requests are supported here" }, { status: 500 });
258
+ const manifest = await resolveManifest(matchedRoutes, await getTransformFn({
259
+ warmup: false,
260
+ request
261
+ }), cache);
262
+ const routerInstance = await getRouter();
263
+ attachRouterServerSsrUtils({
264
+ router: routerInstance,
265
+ manifest
266
+ });
267
+ routerInstance.update({ additionalContext: { serverContext } });
268
+ await routerInstance.load();
269
+ if (routerInstance.state.redirect) return routerInstance.state.redirect;
270
+ await routerInstance.serverSsr.dehydrate();
271
+ const responseHeaders = getStartResponseHeaders({ router: routerInstance });
272
+ cbWillCleanup = true;
273
+ return cb({
274
+ request,
275
+ router: routerInstance,
276
+ responseHeaders
277
+ });
278
+ };
279
+ const requestHandlerMiddleware = async ({ context }) => {
280
+ return runWithStartContext({
281
+ getRouter,
282
+ startOptions: requestStartOptions,
283
+ contextAfterGlobalMiddlewares: context,
284
+ request,
285
+ executedRequestMiddlewares
286
+ }, async () => {
287
+ try {
288
+ return await handleServerRoutes({
289
+ getRouter,
290
+ request,
291
+ url,
292
+ executeRouter,
293
+ context,
294
+ executedRequestMiddlewares
295
+ });
296
+ } catch (err) {
297
+ if (err instanceof Response) return err;
298
+ throw err;
299
+ }
300
+ });
301
+ };
302
+ return handleRedirectResponse((await executeMiddleware([...flattenedRequestMiddlewares.map((d) => d.options.server), requestHandlerMiddleware], {
303
+ request,
304
+ pathname: url.pathname,
305
+ context: createNullProtoObject(requestOpts?.context)
306
+ })).response, request, getRouter);
307
+ } finally {
308
+ if (router && !cbWillCleanup) router.serverSsr?.cleanup();
309
+ router = null;
310
+ }
311
+ };
312
+ return requestHandler(startRequestResolver);
339
313
  }
340
314
  async function handleRedirectResponse(response, request, getRouter) {
341
- if (!isRedirect(response)) {
342
- return response;
343
- }
344
- if (isResolvedRedirect(response)) {
345
- if (request.headers.get("x-tsr-serverFn") === "true") {
346
- return Response.json(
347
- { ...response.options, isSerializedRedirect: true },
348
- { headers: response.headers }
349
- );
350
- }
351
- return response;
352
- }
353
- const opts = response.options;
354
- if (opts.to && typeof opts.to === "string" && !opts.to.startsWith("/")) {
355
- throw new Error(
356
- `Server side redirects must use absolute paths via the 'href' or 'to' options. The redirect() method's "to" property accepts an internal path only. Use the "href" property to provide an external URL. Received: ${JSON.stringify(opts)}`
357
- );
358
- }
359
- if (["params", "search", "hash"].some(
360
- (d) => typeof opts[d] === "function"
361
- )) {
362
- throw new Error(
363
- `Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys(
364
- opts
365
- ).filter((d) => typeof opts[d] === "function").map((d) => `"${d}"`).join(", ")}`
366
- );
367
- }
368
- const router = await getRouter();
369
- const redirect = router.resolveRedirect(response);
370
- if (request.headers.get("x-tsr-serverFn") === "true") {
371
- return Response.json(
372
- { ...response.options, isSerializedRedirect: true },
373
- { headers: response.headers }
374
- );
375
- }
376
- return redirect;
315
+ if (!isRedirect(response)) return response;
316
+ if (isResolvedRedirect(response)) {
317
+ if (request.headers.get("x-tsr-serverFn") === "true") return Response.json({
318
+ ...response.options,
319
+ isSerializedRedirect: true
320
+ }, { headers: response.headers });
321
+ return response;
322
+ }
323
+ const opts = response.options;
324
+ if (opts.to && typeof opts.to === "string" && !opts.to.startsWith("/")) throw new Error(`Server side redirects must use absolute paths via the 'href' or 'to' options. The redirect() method's "to" property accepts an internal path only. Use the "href" property to provide an external URL. Received: ${JSON.stringify(opts)}`);
325
+ if ([
326
+ "params",
327
+ "search",
328
+ "hash"
329
+ ].some((d) => typeof opts[d] === "function")) throw new Error(`Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys(opts).filter((d) => typeof opts[d] === "function").map((d) => `"${d}"`).join(", ")}`);
330
+ const redirect = (await getRouter()).resolveRedirect(response);
331
+ if (request.headers.get("x-tsr-serverFn") === "true") return Response.json({
332
+ ...response.options,
333
+ isSerializedRedirect: true
334
+ }, { headers: response.headers });
335
+ return redirect;
377
336
  }
378
- async function handleServerRoutes({
379
- getRouter,
380
- request,
381
- url,
382
- executeRouter,
383
- context,
384
- executedRequestMiddlewares
385
- }) {
386
- const router = await getRouter();
387
- const rewrittenUrl = executeRewriteInput(router.rewrite, url);
388
- const pathname = rewrittenUrl.pathname;
389
- const { matchedRoutes, foundRoute, routeParams } = router.getMatchedRoutes(pathname);
390
- const isExactMatch = foundRoute && routeParams["**"] === void 0;
391
- const routeMiddlewares = [];
392
- for (const route of matchedRoutes) {
393
- const serverMiddleware = route.options.server?.middleware;
394
- if (serverMiddleware) {
395
- const flattened = flattenMiddlewares(serverMiddleware);
396
- for (const m of flattened) {
397
- if (!executedRequestMiddlewares.has(m)) {
398
- routeMiddlewares.push(m.options.server);
399
- }
400
- }
401
- }
402
- }
403
- const server = foundRoute?.options.server;
404
- if (server?.handlers && isExactMatch) {
405
- const handlers = typeof server.handlers === "function" ? server.handlers({ createHandlers: (d) => d }) : server.handlers;
406
- const requestMethod = request.method.toUpperCase();
407
- const handler = handlers[requestMethod] ?? handlers["ANY"];
408
- if (handler) {
409
- const mayDefer = !!foundRoute.options.component;
410
- if (typeof handler === "function") {
411
- routeMiddlewares.push(handlerToMiddleware(handler, mayDefer));
412
- } else {
413
- if (handler.middleware?.length) {
414
- const handlerMiddlewares = flattenMiddlewares(handler.middleware);
415
- for (const m of handlerMiddlewares) {
416
- routeMiddlewares.push(m.options.server);
417
- }
418
- }
419
- if (handler.handler) {
420
- routeMiddlewares.push(handlerToMiddleware(handler.handler, mayDefer));
421
- }
422
- }
423
- }
424
- }
425
- routeMiddlewares.push(
426
- (ctx2) => executeRouter(ctx2.context, matchedRoutes)
427
- );
428
- const ctx = await executeMiddleware(routeMiddlewares, {
429
- request,
430
- context,
431
- params: routeParams,
432
- pathname
433
- });
434
- return ctx.response;
337
+ async function handleServerRoutes({ getRouter, request, url, executeRouter, context, executedRequestMiddlewares }) {
338
+ const router = await getRouter();
339
+ const pathname = executeRewriteInput(router.rewrite, url).pathname;
340
+ const { matchedRoutes, foundRoute, routeParams } = router.getMatchedRoutes(pathname);
341
+ const isExactMatch = foundRoute && routeParams["**"] === void 0;
342
+ const routeMiddlewares = [];
343
+ for (const route of matchedRoutes) {
344
+ const serverMiddleware = route.options.server?.middleware;
345
+ if (serverMiddleware) {
346
+ const flattened = flattenMiddlewares(serverMiddleware);
347
+ for (const m of flattened) if (!executedRequestMiddlewares.has(m)) routeMiddlewares.push(m.options.server);
348
+ }
349
+ }
350
+ const server = foundRoute?.options.server;
351
+ if (server?.handlers && isExactMatch) {
352
+ const handlers = typeof server.handlers === "function" ? server.handlers({ createHandlers: (d) => d }) : server.handlers;
353
+ const handler = handlers[request.method.toUpperCase()] ?? handlers["ANY"];
354
+ if (handler) {
355
+ const mayDefer = !!foundRoute.options.component;
356
+ if (typeof handler === "function") routeMiddlewares.push(handlerToMiddleware(handler, mayDefer));
357
+ else {
358
+ if (handler.middleware?.length) {
359
+ const handlerMiddlewares = flattenMiddlewares(handler.middleware);
360
+ for (const m of handlerMiddlewares) routeMiddlewares.push(m.options.server);
361
+ }
362
+ if (handler.handler) routeMiddlewares.push(handlerToMiddleware(handler.handler, mayDefer));
363
+ }
364
+ }
365
+ }
366
+ routeMiddlewares.push((ctx) => executeRouter(ctx.context, matchedRoutes));
367
+ return (await executeMiddleware(routeMiddlewares, {
368
+ request,
369
+ context,
370
+ params: routeParams,
371
+ pathname
372
+ })).response;
435
373
  }
436
- export {
437
- createStartHandler
438
- };
439
- //# sourceMappingURL=createStartHandler.js.map
374
+ //#endregion
375
+ export { createStartHandler };
376
+
377
+ //# sourceMappingURL=createStartHandler.js.map