@tanstack/start-server-core 1.121.0-alpha.26 → 1.121.0-alpha.28

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.
Files changed (103) hide show
  1. package/dist/esm/constants.d.ts +3 -0
  2. package/dist/esm/constants.js +7 -0
  3. package/dist/esm/constants.js.map +1 -0
  4. package/dist/esm/createStartHandler.d.ts +4 -7
  5. package/dist/esm/createStartHandler.js +169 -102
  6. package/dist/esm/createStartHandler.js.map +1 -1
  7. package/dist/esm/index.d.ts +6 -8
  8. package/dist/esm/index.js +10 -97
  9. package/dist/esm/index.js.map +1 -1
  10. package/dist/esm/loadVirtualModule.js +2 -0
  11. package/dist/esm/loadVirtualModule.js.map +1 -1
  12. package/dist/esm/request-response.d.ts +124 -0
  13. package/dist/esm/request-response.js +177 -0
  14. package/dist/esm/request-response.js.map +1 -0
  15. package/dist/esm/router-manifest.d.ts +1 -0
  16. package/dist/esm/router-manifest.js +17 -17
  17. package/dist/esm/router-manifest.js.map +1 -1
  18. package/dist/esm/server-functions-handler.js +6 -7
  19. package/dist/esm/server-functions-handler.js.map +1 -1
  20. package/dist/esm/serverRoute.d.ts +6 -2
  21. package/dist/esm/serverRoute.js +3 -2
  22. package/dist/esm/serverRoute.js.map +1 -1
  23. package/dist/esm/session.d.ts +66 -0
  24. package/dist/esm/virtual-modules.d.ts +2 -0
  25. package/dist/esm/virtual-modules.js +2 -1
  26. package/dist/esm/virtual-modules.js.map +1 -1
  27. package/package.json +9 -19
  28. package/src/constants.ts +3 -0
  29. package/src/createStartHandler.ts +241 -143
  30. package/src/global.d.ts +10 -2
  31. package/src/index.tsx +42 -13
  32. package/src/loadVirtualModule.ts +2 -0
  33. package/src/request-response.ts +335 -0
  34. package/src/router-manifest.ts +17 -38
  35. package/src/server-functions-handler.ts +6 -5
  36. package/src/serverRoute.ts +22 -3
  37. package/src/session.ts +75 -0
  38. package/src/tanstack-start.d.ts +18 -5
  39. package/src/virtual-modules.ts +2 -0
  40. package/dist/cjs/createRequestHandler.cjs +0 -50
  41. package/dist/cjs/createRequestHandler.cjs.map +0 -1
  42. package/dist/cjs/createRequestHandler.d.cts +0 -8
  43. package/dist/cjs/createStartHandler.cjs +0 -274
  44. package/dist/cjs/createStartHandler.cjs.map +0 -1
  45. package/dist/cjs/createStartHandler.d.cts +0 -10
  46. package/dist/cjs/h3.cjs +0 -355
  47. package/dist/cjs/h3.cjs.map +0 -1
  48. package/dist/cjs/h3.d.cts +0 -109
  49. package/dist/cjs/handlerCallback.cjs +0 -7
  50. package/dist/cjs/handlerCallback.cjs.map +0 -1
  51. package/dist/cjs/handlerCallback.d.cts +0 -9
  52. package/dist/cjs/index.cjs +0 -245
  53. package/dist/cjs/index.cjs.map +0 -1
  54. package/dist/cjs/index.d.cts +0 -12
  55. package/dist/cjs/loadVirtualModule.cjs +0 -39
  56. package/dist/cjs/loadVirtualModule.cjs.map +0 -1
  57. package/dist/cjs/loadVirtualModule.d.cts +0 -6
  58. package/dist/cjs/router-manifest.cjs +0 -49
  59. package/dist/cjs/router-manifest.cjs.map +0 -1
  60. package/dist/cjs/router-manifest.d.cts +0 -16
  61. package/dist/cjs/server-functions-handler.cjs +0 -148
  62. package/dist/cjs/server-functions-handler.cjs.map +0 -1
  63. package/dist/cjs/server-functions-handler.d.cts +0 -3
  64. package/dist/cjs/serverRoute.cjs +0 -102
  65. package/dist/cjs/serverRoute.cjs.map +0 -1
  66. package/dist/cjs/serverRoute.d.cts +0 -120
  67. package/dist/cjs/ssr-server.cjs +0 -247
  68. package/dist/cjs/ssr-server.cjs.map +0 -1
  69. package/dist/cjs/ssr-server.d.cts +0 -29
  70. package/dist/cjs/transformStreamWithRouter.cjs +0 -183
  71. package/dist/cjs/transformStreamWithRouter.cjs.map +0 -1
  72. package/dist/cjs/transformStreamWithRouter.d.cts +0 -6
  73. package/dist/cjs/tsrScript.cjs +0 -4
  74. package/dist/cjs/tsrScript.cjs.map +0 -1
  75. package/dist/cjs/tsrScript.d.cts +0 -1
  76. package/dist/cjs/virtual-modules.cjs +0 -9
  77. package/dist/cjs/virtual-modules.cjs.map +0 -1
  78. package/dist/cjs/virtual-modules.d.cts +0 -10
  79. package/dist/esm/createRequestHandler.d.ts +0 -8
  80. package/dist/esm/createRequestHandler.js +0 -50
  81. package/dist/esm/createRequestHandler.js.map +0 -1
  82. package/dist/esm/h3.d.ts +0 -109
  83. package/dist/esm/h3.js +0 -248
  84. package/dist/esm/h3.js.map +0 -1
  85. package/dist/esm/handlerCallback.d.ts +0 -9
  86. package/dist/esm/handlerCallback.js +0 -7
  87. package/dist/esm/handlerCallback.js.map +0 -1
  88. package/dist/esm/ssr-server.d.ts +0 -29
  89. package/dist/esm/ssr-server.js +0 -247
  90. package/dist/esm/ssr-server.js.map +0 -1
  91. package/dist/esm/transformStreamWithRouter.d.ts +0 -6
  92. package/dist/esm/transformStreamWithRouter.js +0 -183
  93. package/dist/esm/transformStreamWithRouter.js.map +0 -1
  94. package/dist/esm/tsrScript.d.ts +0 -1
  95. package/dist/esm/tsrScript.js +0 -5
  96. package/dist/esm/tsrScript.js.map +0 -1
  97. package/src/createRequestHandler.ts +0 -73
  98. package/src/h3.ts +0 -492
  99. package/src/handlerCallback.ts +0 -15
  100. package/src/ssr-server.ts +0 -352
  101. package/src/transformStreamWithRouter.ts +0 -258
  102. package/src/tsrScript.ts +0 -91
  103. package/src/vite-env.d.ts +0 -4
@@ -10,19 +10,30 @@ import {
10
10
  isResolvedRedirect,
11
11
  joinPaths,
12
12
  processRouteTree,
13
- rootRouteId,
14
13
  trimPath,
15
14
  } from '@tanstack/router-core'
16
- import { getResponseHeaders, requestHandler } from './h3'
17
- import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'
15
+ import { attachRouterServerSsrUtils } from '@tanstack/router-core/ssr/server'
16
+ import { runWithStartContext } from '@tanstack/start-storage-context'
17
+ import { getResponseHeaders, requestHandler } from './request-response'
18
18
  import { getStartManifest } from './router-manifest'
19
19
  import { handleServerAction } from './server-functions-handler'
20
20
  import { VIRTUAL_MODULES } from './virtual-modules'
21
21
  import { loadVirtualModule } from './loadVirtualModule'
22
- import type { AnyServerRoute, AnyServerRouteWithTypes } from './serverRoute'
23
- import type { RequestHandler } from './h3'
24
- import type { AnyRouter } from '@tanstack/router-core'
25
- import type { HandlerCallback } from './handlerCallback'
22
+
23
+ import { HEADERS } from './constants'
24
+ import type {
25
+ AnyServerRouteWithTypes,
26
+ ServerRouteMethodHandlerFn,
27
+ } from './serverRoute'
28
+ import type { RequestHandler } from './request-response'
29
+ import type {
30
+ AnyRoute,
31
+ AnyRouter,
32
+ Awaitable,
33
+ Manifest,
34
+ ProcessRouteTreeResult,
35
+ } from '@tanstack/router-core'
36
+ import type { HandlerCallback } from '@tanstack/router-core/ssr/server'
26
37
 
27
38
  type TODO = any
28
39
 
@@ -30,36 +41,37 @@ export type CustomizeStartHandler<TRouter extends AnyRouter> = (
30
41
  cb: HandlerCallback<TRouter>,
31
42
  ) => RequestHandler
32
43
 
33
- export function getStartResponseHeaders(opts: { router: AnyRouter }) {
34
- let headers = mergeHeaders(
35
- getResponseHeaders(),
44
+ function getStartResponseHeaders(opts: { router: AnyRouter }) {
45
+ const headers = mergeHeaders(
46
+ getResponseHeaders() as Headers,
36
47
  {
37
- 'Content-Type': 'text/html; charset=UTF-8',
48
+ 'Content-Type': 'text/html; charset=utf-8',
38
49
  },
39
50
  ...opts.router.state.matches.map((match) => {
40
51
  return match.headers
41
52
  }),
42
53
  )
43
- // Handle Redirects
44
- const { redirect } = opts.router.state
45
-
46
- if (redirect) {
47
- headers = mergeHeaders(headers, redirect.headers)
48
- }
49
54
  return headers
50
55
  }
51
56
 
52
57
  export function createStartHandler<TRouter extends AnyRouter>({
53
58
  createRouter,
54
59
  }: {
55
- createRouter: () => TRouter
60
+ createRouter: () => Awaitable<TRouter>
56
61
  }): CustomizeStartHandler<TRouter> {
57
- let serverRouteTree: AnyServerRoute | undefined | null = null
62
+ let routeTreeModule: {
63
+ serverRouteTree: AnyServerRouteWithTypes | undefined
64
+ routeTree: AnyRoute | undefined
65
+ } | null = null
66
+ let startRoutesManifest: Manifest | null = null
67
+ let processedServerRouteTree:
68
+ | ProcessRouteTreeResult<AnyServerRouteWithTypes>
69
+ | undefined = undefined
58
70
 
59
71
  return (cb) => {
60
72
  const originalFetch = globalThis.fetch
61
73
 
62
- const startRequestResolver: RequestHandler = async ({ request }) => {
74
+ const startRequestResolver: RequestHandler = async (request) => {
63
75
  // Patching fetch function to use our request resolver
64
76
  // if the input starts with `/` which is a common pattern for
65
77
  // client-side routing.
@@ -68,7 +80,7 @@ export function createStartHandler<TRouter extends AnyRouter>({
68
80
  globalThis.fetch = async function (input, init) {
69
81
  function resolve(url: URL, requestOptions: RequestInit | undefined) {
70
82
  const fetchRequest = new Request(url, requestOptions)
71
- return startRequestResolver({ request: fetchRequest })
83
+ return startRequestResolver(fetchRequest)
72
84
  }
73
85
 
74
86
  function getOrigin() {
@@ -99,27 +111,32 @@ export function createStartHandler<TRouter extends AnyRouter>({
99
111
  }
100
112
 
101
113
  const url = new URL(request.url)
102
- const href = url.href.replace(url.origin, '')
114
+ const href = decodeURIComponent(url.href.replace(url.origin, ''))
115
+
116
+ const APP_BASE = process.env.TSS_APP_BASE || '/'
117
+
118
+ // TODO how does this work with base path? does the router need to be configured the same as APP_BASE?
119
+ const router = await createRouter()
103
120
 
104
121
  // Create a history for the client-side router
105
122
  const history = createMemoryHistory({
106
123
  initialEntries: [href],
107
124
  })
108
125
 
109
- const APP_BASE = process.env.TSS_APP_BASE || '/'
110
-
111
- // TODO do not create a router instance before we need it
112
- // Create the client-side router
113
- const router = createRouter()
114
-
115
- // TODO only build startRoutesManifest once, not per request
116
- // Attach the server-side SSR utils to the client-side router
117
- const startRoutesManifest = await getStartManifest({ basePath: APP_BASE })
118
- attachRouterServerSsrUtils(router, startRoutesManifest)
119
-
120
- // Update the client-side router with the history and context
126
+ // Update the client-side router with the history
127
+ const isPrerendering = process.env.TSS_PRERENDERING === 'true'
128
+ // env var is set during dev is SPA mode is enabled
129
+ let isShell = process.env.TSS_SHELL === 'true'
130
+ if (isPrerendering && !isShell) {
131
+ // only read the shell header if we are prerendering
132
+ // to avoid runtime behavior changes by injecting this header
133
+ // the header is set by the prerender plugin
134
+ isShell = request.headers.get(HEADERS.TSS_SHELL) === 'true'
135
+ }
121
136
  router.update({
122
137
  history,
138
+ isShell,
139
+ isPrerendering,
123
140
  })
124
141
 
125
142
  const response = await (async () => {
@@ -141,67 +158,97 @@ export function createStartHandler<TRouter extends AnyRouter>({
141
158
  return await handleServerAction({ request })
142
159
  }
143
160
 
144
- if (serverRouteTree === null) {
161
+ if (routeTreeModule === null) {
145
162
  try {
146
- serverRouteTree = (
147
- await loadVirtualModule(VIRTUAL_MODULES.routeTree)
148
- ).serverRouteTree
163
+ routeTreeModule = await loadVirtualModule(
164
+ VIRTUAL_MODULES.routeTree,
165
+ )
166
+ if (routeTreeModule.serverRouteTree) {
167
+ processedServerRouteTree =
168
+ processRouteTree<AnyServerRouteWithTypes>({
169
+ routeTree: routeTreeModule.serverRouteTree,
170
+ initRoute: (route, i) => {
171
+ route.init({
172
+ originalIndex: i,
173
+ })
174
+ },
175
+ })
176
+ }
149
177
  } catch (e) {
150
178
  console.log(e)
151
179
  }
152
180
  }
153
181
 
182
+ const executeRouter = () =>
183
+ runWithStartContext({ router }, async () => {
184
+ const requestAcceptHeader = request.headers.get('Accept') || '*/*'
185
+ const splitRequestAcceptHeader = requestAcceptHeader.split(',')
186
+
187
+ const supportedMimeTypes = ['*/*', 'text/html']
188
+ const isRouterAcceptSupported = supportedMimeTypes.some(
189
+ (mimeType) =>
190
+ splitRequestAcceptHeader.some((acceptedMimeType) =>
191
+ acceptedMimeType.trim().startsWith(mimeType),
192
+ ),
193
+ )
194
+
195
+ if (!isRouterAcceptSupported) {
196
+ return json(
197
+ {
198
+ error: 'Only HTML requests are supported here',
199
+ },
200
+ {
201
+ status: 500,
202
+ },
203
+ )
204
+ }
205
+
206
+ // if the startRoutesManifest is not loaded yet, load it once
207
+ if (startRoutesManifest === null) {
208
+ startRoutesManifest = await getStartManifest({
209
+ basePath: APP_BASE,
210
+ })
211
+ }
212
+
213
+ // Attach the server-side SSR utils to the client-side router
214
+ attachRouterServerSsrUtils(router, startRoutesManifest)
215
+
216
+ await router.load()
217
+
218
+ // If there was a redirect, skip rendering the page at all
219
+ if (router.state.redirect) {
220
+ return router.state.redirect
221
+ }
222
+
223
+ await router.serverSsr!.dehydrate()
224
+
225
+ const responseHeaders = getStartResponseHeaders({ router })
226
+ const response = await cb({
227
+ request,
228
+ router,
229
+ responseHeaders,
230
+ })
231
+
232
+ return response
233
+ })
234
+
154
235
  // If we have a server route tree, then we try matching to see if we have a
155
236
  // server route that matches the request.
156
- if (serverRouteTree) {
237
+ if (processedServerRouteTree) {
157
238
  const [_matchedRoutes, response] = await handleServerRoutes({
158
- routeTree: serverRouteTree,
239
+ processedServerRouteTree,
240
+ router,
159
241
  request,
160
242
  basePath: APP_BASE,
243
+ executeRouter,
161
244
  })
162
245
 
163
246
  if (response) return response
164
247
  }
165
248
 
166
- const requestAcceptHeader = request.headers.get('Accept') || '*/*'
167
- const splitRequestAcceptHeader = requestAcceptHeader.split(',')
168
-
169
- const supportedMimeTypes = ['*/*', 'text/html']
170
- const isRouterAcceptSupported = supportedMimeTypes.some((mimeType) =>
171
- splitRequestAcceptHeader.some((acceptedMimeType) =>
172
- acceptedMimeType.trim().startsWith(mimeType),
173
- ),
174
- )
175
-
176
- if (!isRouterAcceptSupported) {
177
- return json(
178
- {
179
- error: 'Only HTML requests are supported here',
180
- },
181
- {
182
- status: 500,
183
- },
184
- )
185
- }
186
-
187
- // If no Server Routes were found, so fallback to normal SSR matching using
188
- // the router
189
-
190
- await router.load()
191
-
192
- // If there was a redirect, skip rendering the page at all
193
- if (router.state.redirect) return router.state.redirect
194
-
195
- dehydrateRouter(router)
196
-
197
- const responseHeaders = getStartResponseHeaders({ router })
198
- const response = await cb({
199
- request,
200
- router,
201
- responseHeaders,
202
- })
203
-
204
- return response
249
+ // Server Routes did not produce a response, so fallback to normal SSR matching using the router
250
+ const routerResponse = await executeRouter()
251
+ return routerResponse
205
252
  } catch (err) {
206
253
  if (err instanceof Response) {
207
254
  return err
@@ -232,7 +279,7 @@ export function createStartHandler<TRouter extends AnyRouter>({
232
279
  !response.options.to.startsWith('/')
233
280
  ) {
234
281
  throw new Error(
235
- `Server side redirects must use absolute paths via the 'href' or 'to' options. Received: ${JSON.stringify(response.options)}`,
282
+ `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(response.options)}`,
236
283
  )
237
284
  }
238
285
 
@@ -275,78 +322,112 @@ export function createStartHandler<TRouter extends AnyRouter>({
275
322
  }
276
323
  }
277
324
 
278
- async function handleServerRoutes({
279
- routeTree,
280
- request,
281
- basePath,
282
- }: {
283
- routeTree: AnyServerRouteWithTypes
325
+ async function handleServerRoutes(opts: {
326
+ router: AnyRouter
327
+ processedServerRouteTree: ProcessRouteTreeResult<AnyServerRouteWithTypes>
284
328
  request: Request
285
329
  basePath: string
330
+ executeRouter: () => Promise<Response>
286
331
  }) {
287
- // TODO only process server route tree once, not per request
288
- const { flatRoutes, routesById, routesByPath } = processRouteTree({
289
- routeTree,
290
- initRoute: (route, i) => {
291
- route.init({
292
- originalIndex: i,
293
- })
294
- },
295
- })
296
-
297
- const url = new URL(request.url)
332
+ const url = new URL(opts.request.url)
298
333
  const pathname = url.pathname
299
334
 
300
- // TODO history seems not to be needed, we can just use the pathname
301
- const history = createMemoryHistory({
302
- initialEntries: [pathname],
335
+ const serverTreeResult = getMatchedRoutes<AnyServerRouteWithTypes>({
336
+ pathname,
337
+ basepath: opts.basePath,
338
+ caseSensitive: true,
339
+ routesByPath: opts.processedServerRouteTree.routesByPath,
340
+ routesById: opts.processedServerRouteTree.routesById,
341
+ flatRoutes: opts.processedServerRouteTree.flatRoutes,
303
342
  })
304
343
 
305
- const { matchedRoutes, foundRoute, routeParams } =
306
- getMatchedRoutes<AnyServerRouteWithTypes>({
307
- pathname: history.location.pathname,
308
- basepath: basePath,
309
- caseSensitive: true,
310
- routesByPath,
311
- routesById,
312
- flatRoutes,
313
- })
344
+ const routeTreeResult = opts.router.getMatchedRoutes(pathname, undefined)
314
345
 
315
346
  let response: Response | undefined
347
+ let matchedRoutes: Array<AnyServerRouteWithTypes> = []
348
+ matchedRoutes = serverTreeResult.matchedRoutes
349
+ // check if the app route tree found a match that is deeper than the server route tree
350
+ if (routeTreeResult.foundRoute) {
351
+ if (
352
+ serverTreeResult.matchedRoutes.length <
353
+ routeTreeResult.matchedRoutes.length
354
+ ) {
355
+ const closestCommon = [...routeTreeResult.matchedRoutes]
356
+ .reverse()
357
+ .find((r) => {
358
+ return opts.processedServerRouteTree.routesById[r.id] !== undefined
359
+ })
360
+ if (closestCommon) {
361
+ // walk up the tree and collect all parents
362
+ let routeId = closestCommon.id
363
+ matchedRoutes = []
364
+ do {
365
+ const route = opts.processedServerRouteTree.routesById[routeId]
366
+ if (!route) {
367
+ break
368
+ }
369
+ matchedRoutes.push(route)
370
+ routeId = route.parentRoute?.id
371
+ } while (routeId)
316
372
 
317
- if (foundRoute && foundRoute.id !== rootRouteId) {
318
- // We've found a server route that matches the request, so we can call it.
319
- // TODO: Get the input type-signature correct
320
- // TODO: Perform the middlewares?
321
- // TODO: Error handling? What happens when its `throw redirect()` vs `throw new Error()`?
322
-
323
- const method = Object.keys(foundRoute.options.methods).find(
324
- (method) => method.toLowerCase() === request.method.toLowerCase(),
325
- )
326
-
327
- if (method) {
328
- const handler = foundRoute.options.methods[method]
329
-
330
- if (handler) {
331
- const middlewares = flattenMiddlewares(
332
- matchedRoutes.flatMap((r) => r.options.middleware).filter(Boolean),
333
- ).map((d) => d.options.server)
334
-
335
- middlewares.push(handlerToMiddleware(handler) as TODO)
373
+ matchedRoutes.reverse()
374
+ }
375
+ }
376
+ }
336
377
 
337
- // TODO: This is starting to feel too much like a server function
338
- // Do generalize the existing middleware execution? Or do we need to
339
- // build a new middleware execution system for server routes?
340
- const ctx = await executeMiddleware(middlewares, {
341
- request,
342
- context: {},
343
- params: routeParams,
344
- pathname: history.location.pathname,
345
- })
378
+ if (matchedRoutes.length) {
379
+ // We've found a server route that (partially) matches the request, so we can call it.
380
+ // TODO: Error handling? What happens when its `throw redirect()` vs `throw new Error()`?
346
381
 
347
- response = ctx.response
382
+ const middlewares = flattenMiddlewares(
383
+ matchedRoutes.flatMap((r) => r.options.middleware).filter(Boolean),
384
+ ).map((d) => d.options.server)
385
+
386
+ if (serverTreeResult.foundRoute?.options.methods) {
387
+ const method = Object.keys(
388
+ serverTreeResult.foundRoute.options.methods,
389
+ ).find(
390
+ (method) => method.toLowerCase() === opts.request.method.toLowerCase(),
391
+ )
392
+
393
+ if (method) {
394
+ const handler = serverTreeResult.foundRoute.options.methods[method]
395
+ if (handler) {
396
+ if (typeof handler === 'function') {
397
+ middlewares.push(handlerToMiddleware(handler) as TODO)
398
+ } else {
399
+ if (
400
+ handler._options.middlewares &&
401
+ handler._options.middlewares.length
402
+ ) {
403
+ middlewares.push(
404
+ ...flattenMiddlewares(handler._options.middlewares as any).map(
405
+ (d) => d.options.server,
406
+ ),
407
+ )
408
+ }
409
+ if (handler._options.handler) {
410
+ middlewares.push(handlerToMiddleware(handler._options.handler))
411
+ }
412
+ }
413
+ }
348
414
  }
349
415
  }
416
+
417
+ // eventually, execute the router
418
+ middlewares.push(handlerToMiddleware(opts.executeRouter))
419
+
420
+ // TODO: This is starting to feel too much like a server function
421
+ // Do generalize the existing middleware execution? Or do we need to
422
+ // build a new middleware execution system for server routes?
423
+ const ctx = await executeMiddleware(middlewares, {
424
+ request: opts.request,
425
+ context: {},
426
+ params: serverTreeResult.routeParams,
427
+ pathname,
428
+ })
429
+
430
+ response = ctx.response
350
431
  }
351
432
 
352
433
  // We return the matched routes too so if
@@ -356,11 +437,21 @@ async function handleServerRoutes({
356
437
  }
357
438
 
358
439
  function handlerToMiddleware(
359
- handler: AnyServerRouteWithTypes['options']['methods'][string],
440
+ handler: ServerRouteMethodHandlerFn<
441
+ AnyServerRouteWithTypes,
442
+ any,
443
+ any,
444
+ any,
445
+ any
446
+ >,
360
447
  ) {
361
- return async ({ next: _next, ...rest }: TODO) => ({
362
- response: await handler(rest),
363
- })
448
+ return async ({ next: _next, ...rest }: TODO) => {
449
+ const response = await handler(rest)
450
+ if (response) {
451
+ return { response }
452
+ }
453
+ return _next(rest)
454
+ }
364
455
  }
365
456
 
366
457
  function executeMiddleware(middlewares: TODO, ctx: TODO) {
@@ -376,7 +467,14 @@ function executeMiddleware(middlewares: TODO, ctx: TODO) {
376
467
  // Allow the middleware to call the next middleware in the chain
377
468
  next: async (nextCtx: TODO) => {
378
469
  // Allow the caller to extend the context for the next middleware
379
- const nextResult = await next({ ...ctx, ...nextCtx })
470
+ const nextResult = await next({
471
+ ...ctx,
472
+ ...nextCtx,
473
+ context: {
474
+ ...ctx.context,
475
+ ...(nextCtx?.context || {}),
476
+ },
477
+ })
380
478
 
381
479
  // Merge the result into the context\
382
480
  return Object.assign(ctx, handleCtxResult(nextResult))
package/src/global.d.ts CHANGED
@@ -1,6 +1,14 @@
1
1
  declare global {
2
- // eslint-disable-next-line no-var
3
- var TSS_INJECTED_HEAD_SCRIPTS: string | undefined
2
+ namespace NodeJS {
3
+ interface ProcessEnv {
4
+ TSS_APP_BASE?: string
5
+ TSS_SERVER_FN_BASE?: string
6
+ TSS_OUTPUT_PUBLIC_DIR?: string
7
+ TSS_SHELL?: 'true' | 'false'
8
+ TSS_PRERENDERING?: 'true' | 'false'
9
+ TSS_DEV_SERVER?: 'true' | 'false'
10
+ }
11
+ }
4
12
  }
5
13
 
6
14
  export {}
package/src/index.tsx CHANGED
@@ -1,22 +1,18 @@
1
+ export { createStartHandler } from './createStartHandler'
2
+ export type { CustomizeStartHandler } from './createStartHandler'
3
+
1
4
  export {
5
+ attachRouterServerSsrUtils,
6
+ createRequestHandler,
7
+ defineHandlerCallback,
2
8
  transformReadableStreamWithRouter,
3
9
  transformPipeableStreamWithRouter,
4
- } from './transformStreamWithRouter'
10
+ } from '@tanstack/router-core/ssr/server'
11
+ export type { HandlerCallback } from '@tanstack/router-core/ssr/server'
5
12
 
6
- export {
7
- getStartResponseHeaders,
8
- createStartHandler,
9
- } from './createStartHandler'
10
- export type { CustomizeStartHandler } from './createStartHandler'
11
- export { createRequestHandler } from './createRequestHandler'
12
-
13
- export { defineHandlerCallback } from './handlerCallback'
14
- export type { HandlerCallback } from './handlerCallback'
15
-
16
- export { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'
17
13
  export { handleServerAction } from './server-functions-handler'
18
14
 
19
- export * from './h3'
15
+ export * from './request-response'
20
16
 
21
17
  export {
22
18
  createServerRoute,
@@ -26,6 +22,39 @@ export {
26
22
  export type {
27
23
  CreateServerFileRoute,
28
24
  ServerFileRoutesByPath,
25
+ ServerRouteOptions,
26
+ ServerRouteManifest,
27
+ ServerRouteAddFileChildrenFn,
28
+ ServerRouteMethodBuilderOptions,
29
+ AnyServerRouteWithTypes,
30
+ ServerRouteWithTypes,
31
+ ServerRouteTypes,
32
+ ResolveAllServerContext,
33
+ AnyServerRoute,
34
+ ServerRoute,
35
+ ServerRouteMiddleware,
36
+ ServerRouteAfterMiddleware,
37
+ ServerRouteMethods,
38
+ ServerRouteMethodsOptions,
39
+ ServerRouteMethodsRecord,
40
+ ServerRouteMethodRecordValue,
41
+ ServerRouteVerb,
42
+ ServerRouteMethodHandlerFn,
43
+ ServerRouteMethodHandlerCtx,
44
+ MergeMethodMiddlewares,
45
+ AssignAllMethodContext,
46
+ AnyRouteMethodsBuilder,
47
+ ServerRouteMethodBuilder,
48
+ ServerRouteMethodBuilderWithTypes,
49
+ ServerRouteMethodBuilderTypes,
50
+ ServerRouteMethodBuilderMiddleware,
51
+ ServerRouteMethodBuilderAfterMiddleware,
52
+ ServerRouteMethodBuilderHandler,
53
+ ServerRouteMethodBuilderAfterHandler,
54
+ ServerRouteMethod,
55
+ ServerRouteAfterMethods,
29
56
  } from './serverRoute'
30
57
 
31
58
  export * from './virtual-modules'
59
+
60
+ export { HEADERS } from './constants'
@@ -15,6 +15,8 @@ export async function loadVirtualModule<TId extends keyof VirtualModules>(
15
15
  return (await import('tanstack-start-manifest:v')) as any
16
16
  case VIRTUAL_MODULES.serverFnManifest:
17
17
  return (await import('tanstack-start-server-fn-manifest:v')) as any
18
+ case VIRTUAL_MODULES.injectedHeadScripts:
19
+ return (await import('tanstack-start-injected-head-scripts:v')) as any
18
20
  default:
19
21
  throw new Error(`Unknown virtual module: ${id}`)
20
22
  }