@tanstack/start-server-core 1.120.3 → 1.120.4-alpha.1

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 (62) hide show
  1. package/README.md +6 -27
  2. package/dist/cjs/createRequestHandler.cjs +1 -3
  3. package/dist/cjs/createRequestHandler.cjs.map +1 -1
  4. package/dist/cjs/createStartHandler.cjs +228 -30
  5. package/dist/cjs/createStartHandler.cjs.map +1 -1
  6. package/dist/cjs/createStartHandler.d.cts +8 -6
  7. package/dist/cjs/h3.cjs +30 -73
  8. package/dist/cjs/h3.cjs.map +1 -1
  9. package/dist/cjs/h3.d.cts +11 -7
  10. package/dist/cjs/handlerCallback.cjs.map +1 -1
  11. package/dist/cjs/handlerCallback.d.cts +3 -4
  12. package/dist/cjs/index.cjs +20 -14
  13. package/dist/cjs/index.cjs.map +1 -1
  14. package/dist/cjs/index.d.cts +7 -1
  15. package/dist/cjs/router-manifest.cjs +44 -0
  16. package/dist/cjs/router-manifest.cjs.map +1 -0
  17. package/dist/cjs/router-manifest.d.cts +17 -0
  18. package/dist/cjs/server-functions-handler.cjs +154 -0
  19. package/dist/cjs/server-functions-handler.cjs.map +1 -0
  20. package/dist/cjs/server-functions-handler.d.cts +4 -0
  21. package/dist/cjs/serverRoute.cjs +100 -0
  22. package/dist/cjs/serverRoute.cjs.map +1 -0
  23. package/dist/cjs/serverRoute.d.cts +115 -0
  24. package/dist/cjs/undici.cjs +14 -0
  25. package/dist/cjs/undici.cjs.map +1 -0
  26. package/dist/cjs/undici.d.cts +43 -0
  27. package/dist/esm/createRequestHandler.js +1 -3
  28. package/dist/esm/createRequestHandler.js.map +1 -1
  29. package/dist/esm/createStartHandler.d.ts +8 -6
  30. package/dist/esm/createStartHandler.js +208 -32
  31. package/dist/esm/createStartHandler.js.map +1 -1
  32. package/dist/esm/h3.d.ts +11 -7
  33. package/dist/esm/h3.js +26 -63
  34. package/dist/esm/h3.js.map +1 -1
  35. package/dist/esm/handlerCallback.d.ts +3 -4
  36. package/dist/esm/handlerCallback.js.map +1 -1
  37. package/dist/esm/index.d.ts +7 -1
  38. package/dist/esm/index.js +17 -5
  39. package/dist/esm/index.js.map +1 -1
  40. package/dist/esm/router-manifest.d.ts +17 -0
  41. package/dist/esm/router-manifest.js +44 -0
  42. package/dist/esm/router-manifest.js.map +1 -0
  43. package/dist/esm/server-functions-handler.d.ts +4 -0
  44. package/dist/esm/server-functions-handler.js +154 -0
  45. package/dist/esm/server-functions-handler.js.map +1 -0
  46. package/dist/esm/serverRoute.d.ts +115 -0
  47. package/dist/esm/serverRoute.js +100 -0
  48. package/dist/esm/serverRoute.js.map +1 -0
  49. package/dist/esm/undici.d.ts +43 -0
  50. package/dist/esm/undici.js +14 -0
  51. package/dist/esm/undici.js.map +1 -0
  52. package/package.json +9 -6
  53. package/src/createRequestHandler.ts +1 -3
  54. package/src/createStartHandler.ts +313 -47
  55. package/src/h3.ts +71 -78
  56. package/src/handlerCallback.ts +5 -12
  57. package/src/index.tsx +13 -1
  58. package/src/router-manifest.ts +79 -0
  59. package/src/server-functions-handler.ts +273 -0
  60. package/src/serverRoute.ts +661 -0
  61. package/src/tanstack-start.d.ts +5 -0
  62. package/src/undici.ts +60 -0
@@ -1,82 +1,348 @@
1
+ import path from 'node:path'
1
2
  import { createMemoryHistory } from '@tanstack/history'
2
- import { mergeHeaders } from '@tanstack/start-client-core'
3
- import { eventHandler, getResponseHeaders, toWebRequest } from 'h3'
3
+ import {
4
+ flattenMiddlewares,
5
+ json,
6
+ mergeHeaders,
7
+ } from '@tanstack/start-client-core'
8
+ import {
9
+ getMatchedRoutes,
10
+ isRedirect,
11
+ processRouteTree,
12
+ rootRouteId,
13
+ tsrRedirectHeaderKey,
14
+ } from '@tanstack/router-core'
15
+ import { getResponseHeaders, requestHandler } from './h3'
4
16
  import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'
17
+ import { getStartManifest } from './router-manifest'
18
+ import { handleServerAction } from './server-functions-handler'
19
+ import type { AnyServerRoute, AnyServerRouteWithTypes } from './serverRoute'
20
+ import type { RequestHandler } from './h3'
21
+ import type { AnyRouter } from '@tanstack/router-core'
5
22
  import type { HandlerCallback } from './handlerCallback'
6
- import type { EventHandlerResponse, H3Event } from 'h3'
7
- import type { AnyRouter, Manifest } from '@tanstack/router-core'
8
-
9
- export type CustomizeStartHandler<
10
- TRouter extends AnyRouter,
11
- TResponse extends EventHandlerResponse = EventHandlerResponse,
12
- > = (cb: HandlerCallback<TRouter, TResponse>) => ReturnType<typeof eventHandler>
13
-
14
- export function createStartHandler<
15
- TRouter extends AnyRouter,
16
- TResponse extends EventHandlerResponse = EventHandlerResponse,
17
- >({
23
+
24
+ type TODO = any
25
+
26
+ export type CustomizeStartHandler<TRouter extends AnyRouter> = (
27
+ cb: HandlerCallback<TRouter>,
28
+ ) => RequestHandler
29
+
30
+ export function getStartResponseHeaders(opts: { router: AnyRouter }) {
31
+ let headers = mergeHeaders(
32
+ getResponseHeaders(),
33
+ {
34
+ 'Content-Type': 'text/html; charset=UTF-8',
35
+ },
36
+ ...opts.router.state.matches.map((match) => {
37
+ return match.headers
38
+ }),
39
+ )
40
+ // Handle Redirects
41
+ const { redirect } = opts.router.state
42
+
43
+ if (redirect) {
44
+ headers = mergeHeaders(headers, redirect.headers)
45
+ }
46
+ return headers
47
+ }
48
+
49
+ export function createStartHandler<TRouter extends AnyRouter>({
18
50
  createRouter,
19
- getRouterManifest,
20
51
  }: {
21
52
  createRouter: () => TRouter
22
- getRouterManifest?: () => Manifest | Promise<Manifest>
23
- }): CustomizeStartHandler<TRouter, TResponse> {
53
+ }): CustomizeStartHandler<TRouter> {
24
54
  return (cb) => {
25
- return eventHandler(async (event) => {
26
- const request = toWebRequest(event)
27
-
55
+ return requestHandler(async ({ request }) => {
28
56
  const url = new URL(request.url)
29
57
  const href = url.href.replace(url.origin, '')
30
58
 
31
- // Create a history for the router
59
+ // Create a history for the client-side router
32
60
  const history = createMemoryHistory({
33
61
  initialEntries: [href],
34
62
  })
35
63
 
64
+ // Create the client-side router
36
65
  const router = createRouter()
37
66
 
38
- attachRouterServerSsrUtils(router, await getRouterManifest?.())
67
+ // Attach the server-side SSR utils to the client-side router
68
+ attachRouterServerSsrUtils(router, getStartManifest())
39
69
 
40
- // Update the router with the history and context
70
+ // Update the client-side router with the history and context
41
71
  router.update({
42
72
  history,
43
73
  })
44
74
 
45
- await router.load()
75
+ const response = await (async () => {
76
+ try {
77
+ if (!process.env.TSS_SERVER_FN_BASE) {
78
+ throw new Error(
79
+ 'tanstack/start-server-core: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()',
80
+ )
81
+ }
46
82
 
47
- dehydrateRouter(router)
83
+ // First, let's attempt to handle server functions
84
+ if (
85
+ href.startsWith(path.join('/', process.env.TSS_SERVER_FN_BASE, '/'))
86
+ ) {
87
+ return await handleServerAction({ request })
88
+ }
48
89
 
49
- const responseHeaders = getStartResponseHeaders({ event, router })
50
- const response = await cb({
51
- request,
52
- router,
53
- responseHeaders,
54
- })
90
+ // Then move on to attempting to load server routes
91
+ const serverRouteTreeModule = await (async () => {
92
+ try {
93
+ // @ts-expect-error
94
+ return (await import('tanstack:server-routes')) as {
95
+ routeTree: AnyServerRoute
96
+ }
97
+ } catch (e) {
98
+ console.log(e)
99
+ return undefined
100
+ }
101
+ })()
102
+
103
+ // If we have a server route tree, then we try matching to see if we have a
104
+ // server route that matches the request.
105
+ if (serverRouteTreeModule) {
106
+ const [matchedRoutes, response] = await handleServerRoutes({
107
+ routeTree: serverRouteTreeModule.routeTree,
108
+ request,
109
+ })
110
+
111
+ if (response) return response
112
+ }
113
+
114
+ const requestAcceptHeader = request.headers.get('Accept') || '*/*'
115
+ const splitRequestAcceptHeader = requestAcceptHeader.split(',')
116
+
117
+ const supportedMimeTypes = ['*/*', 'text/html']
118
+ const isRouterAcceptSupported = supportedMimeTypes.some((mimeType) =>
119
+ splitRequestAcceptHeader.some((acceptedMimeType) =>
120
+ acceptedMimeType.trim().startsWith(mimeType),
121
+ ),
122
+ )
123
+
124
+ if (!isRouterAcceptSupported) {
125
+ return json(
126
+ {
127
+ error: 'Only HTML requests are supported here',
128
+ },
129
+ {
130
+ status: 500,
131
+ },
132
+ )
133
+ }
134
+
135
+ // If no Server Routes were found, so fallback to normal SSR matching using
136
+ // the router
137
+
138
+ await router.load()
139
+
140
+ // If there was a redirect, skip rendering the page at all
141
+ if (router.state.redirect) return router.state.redirect
142
+
143
+ dehydrateRouter(router)
144
+
145
+ const responseHeaders = getStartResponseHeaders({ router })
146
+ const response = await cb({
147
+ request,
148
+ router,
149
+ responseHeaders,
150
+ })
151
+
152
+ return response
153
+ } catch (err) {
154
+ if (err instanceof Response) {
155
+ return err
156
+ }
157
+
158
+ throw err
159
+ }
160
+ })()
161
+
162
+ if (isRedirect(response)) {
163
+ if (
164
+ response.options.to &&
165
+ typeof response.options.to === 'string' &&
166
+ !response.options.to.startsWith('/')
167
+ ) {
168
+ throw new Error(
169
+ `Server side redirects must use absolute paths via the 'href' or 'to' options. Received: ${JSON.stringify(response.options)}`,
170
+ )
171
+ }
172
+
173
+ if (
174
+ ['params', 'search', 'hash'].some(
175
+ (d) => typeof (response.options as any)[d] === 'function',
176
+ )
177
+ ) {
178
+ throw new Error(
179
+ `Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys(
180
+ response.options,
181
+ )
182
+ .filter((d) => typeof (response.options as any)[d] === 'function')
183
+ .map((d) => `"${d}"`)
184
+ .join(', ')}`,
185
+ )
186
+ }
187
+
188
+ const redirect = router.resolveRedirect(response)
189
+
190
+ if (request.headers.get('x-tsr-redirect') === 'manual') {
191
+ return json(
192
+ {
193
+ ...response.options,
194
+ isSerializedRedirect: true,
195
+ },
196
+ {
197
+ headers: redirect.headers,
198
+ },
199
+ )
200
+ }
201
+
202
+ return redirect
203
+ }
204
+
205
+ response.headers.append(
206
+ 'Access-Control-Expose-Headers',
207
+ tsrRedirectHeaderKey,
208
+ )
55
209
 
56
210
  return response
57
211
  })
58
212
  }
59
213
  }
60
214
 
61
- function getStartResponseHeaders(opts: { event: H3Event; router: AnyRouter }) {
62
- let headers = mergeHeaders(
63
- getResponseHeaders(opts.event),
64
- (opts.event as any).___ssrRpcResponseHeaders,
65
- {
66
- 'Content-Type': 'text/html; charset=UTF-8',
215
+ async function handleServerRoutes({
216
+ routeTree,
217
+ request,
218
+ }: {
219
+ routeTree: AnyServerRouteWithTypes
220
+ request: Request
221
+ }) {
222
+ const { flatRoutes, routesById, routesByPath } = processRouteTree({
223
+ routeTree,
224
+ initRoute: (route, i) => {
225
+ route.init({
226
+ originalIndex: i,
227
+ })
67
228
  },
68
- ...opts.router.state.matches.map((match) => {
69
- return match.headers
70
- }),
71
- )
229
+ })
72
230
 
73
- // Handle Redirects
74
- const { redirect } = opts.router.state
231
+ const url = new URL(request.url)
232
+ const pathname = url.pathname
75
233
 
76
- if (redirect) {
77
- headers = mergeHeaders(headers, redirect.headers, {
78
- Location: redirect.href,
234
+ const history = createMemoryHistory({
235
+ initialEntries: [pathname],
236
+ })
237
+
238
+ const { matchedRoutes, foundRoute, routeParams } =
239
+ getMatchedRoutes<AnyServerRouteWithTypes>({
240
+ pathname: history.location.pathname,
241
+ basepath: '/',
242
+ caseSensitive: true,
243
+ routesByPath,
244
+ routesById,
245
+ flatRoutes,
246
+ })
247
+
248
+ let response: Response | undefined
249
+
250
+ if (foundRoute && foundRoute.id !== rootRouteId) {
251
+ // We've found a server route that matches the request, so we can call it.
252
+ // TODO: Get the input type-signature correct
253
+ // TODO: Perform the middlewares?
254
+ // TODO: Error handling? What happens when its `throw redirect()` vs `throw new Error()`?
255
+
256
+ const method = Object.keys(foundRoute.options.methods).find(
257
+ (method) => method.toLowerCase() === request.method.toLowerCase(),
258
+ )
259
+
260
+ if (method) {
261
+ const handler = foundRoute.options.methods[method]
262
+
263
+ if (handler) {
264
+ const middlewares = flattenMiddlewares(
265
+ matchedRoutes.flatMap((r) => r.options.middleware).filter(Boolean),
266
+ ).map((d) => d.options.server)
267
+
268
+ middlewares.push(handlerToMiddleware(handler) as TODO)
269
+
270
+ // TODO: This is starting to feel too much like a server function
271
+ // Do generalize the existing middleware execution? Or do we need to
272
+ // build a new middleware execution system for server routes?
273
+ const ctx = await executeMiddleware(middlewares, {
274
+ request,
275
+ context: {},
276
+ params: routeParams,
277
+ pathname: history.location.pathname,
278
+ })
279
+
280
+ response = ctx.response
281
+ }
282
+ }
283
+ }
284
+
285
+ // We return the matched routes too so if
286
+ // the app router happens to match the same path,
287
+ // it can use any request middleware from server routes
288
+ return [matchedRoutes, response] as const
289
+ }
290
+
291
+ function handlerToMiddleware(
292
+ handler: AnyServerRouteWithTypes['options']['methods'][string],
293
+ ) {
294
+ return async ({ next, ...rest }: TODO) => ({
295
+ response: await handler(rest),
296
+ })
297
+ }
298
+
299
+ function executeMiddleware(middlewares: TODO, ctx: TODO) {
300
+ let index = -1
301
+
302
+ const next = async (ctx: TODO) => {
303
+ index++
304
+ const middleware = middlewares[index]
305
+ if (!middleware) return ctx
306
+
307
+ const result = await middleware({
308
+ ...ctx,
309
+ // Allow the middleware to call the next middleware in the chain
310
+ next: async (nextCtx: TODO) => {
311
+ // Allow the caller to extend the context for the next middleware
312
+ const nextResult = await next({ ...ctx, ...nextCtx })
313
+
314
+ // Merge the result into the context\
315
+ return Object.assign(ctx, handleCtxResult(nextResult))
316
+ },
317
+ // Allow the middleware result to extend the return context
318
+ }).catch((err: TODO) => {
319
+ if (isSpecialResponse(err)) {
320
+ return {
321
+ response: err,
322
+ }
323
+ }
324
+
325
+ throw err
79
326
  })
327
+
328
+ // Merge the middleware result into the context, just in case it
329
+ // returns a partial context
330
+ return Object.assign(ctx, handleCtxResult(result))
80
331
  }
81
- return headers
332
+
333
+ return handleCtxResult(next(ctx))
334
+ }
335
+
336
+ function handleCtxResult(result: TODO) {
337
+ if (isSpecialResponse(result)) {
338
+ return {
339
+ response: result,
340
+ }
341
+ }
342
+
343
+ return result
344
+ }
345
+
346
+ function isSpecialResponse(err: TODO) {
347
+ return err instanceof Response || isRedirect(err)
82
348
  }
package/src/h3.ts CHANGED
@@ -11,7 +11,9 @@ import {
11
11
  clearResponseHeaders as _clearResponseHeaders,
12
12
  clearSession as _clearSession,
13
13
  defaultContentType as _defaultContentType,
14
+ defineEventHandler as _defineEventHandler,
14
15
  deleteCookie as _deleteCookie,
16
+ eventHandler as _eventHandler,
15
17
  fetchWithEvent as _fetchWithEvent,
16
18
  getCookie as _getCookie,
17
19
  getHeader as _getHeader,
@@ -61,20 +63,24 @@ import {
61
63
  setResponseHeader as _setResponseHeader,
62
64
  setResponseHeaders as _setResponseHeaders,
63
65
  setResponseStatus as _setResponseStatus,
66
+ toWebRequest as _toWebRequest,
64
67
  unsealSession as _unsealSession,
65
68
  updateSession as _updateSession,
66
69
  useSession as _useSession,
67
70
  writeEarlyHints as _writeEarlyHints,
68
71
  } from 'h3'
69
- import { getContext as getUnctxContext } from 'unctx'
72
+
70
73
  import type {
71
74
  Encoding,
75
+ EventHandler,
72
76
  HTTPHeaderName,
73
77
  InferEventInput,
74
78
  _RequestMiddleware,
75
79
  _ResponseMiddleware,
76
80
  } from 'h3'
77
81
 
82
+ const eventStorage = new AsyncLocalStorage()
83
+
78
84
  function _setContext(event: H3Event, key: string, value: any) {
79
85
  event.context[key] = value
80
86
  }
@@ -90,46 +96,38 @@ export function defineMiddleware(options: {
90
96
  return options
91
97
  }
92
98
 
93
- function toWebRequestH3(event: H3Event) {
94
- /**
95
- * @type {ReadableStream | undefined}
96
- */
97
- let readableStream: ReadableStream | undefined
99
+ // function toWebRequestH3(event: H3Event) {
100
+ // /**
101
+ // * @type {ReadableStream | undefined}
102
+ // */
103
+ // let readableStream: ReadableStream | undefined
98
104
 
99
- const url = getRequestURL(event)
100
- const base = {
101
- // @ts-ignore Undici option
102
- duplex: 'half',
103
- method: event.method,
104
- headers: event.headers,
105
- }
106
-
107
- if ((event.node.req as any).body instanceof ArrayBuffer) {
108
- return new Request(url, {
109
- ...base,
110
- body: (event.node.req as any).body,
111
- })
112
- }
105
+ // const url = _getRequestURL(event)
106
+ // const base = {
107
+ // // @ts-ignore Undici option
108
+ // duplex: 'half',
109
+ // method: event.method,
110
+ // headers: event.headers,
111
+ // }
113
112
 
114
- return new Request(url, {
115
- ...base,
116
- get body() {
117
- if (readableStream) {
118
- return readableStream
119
- }
120
- readableStream = getRequestWebStream(event)
121
- return readableStream
122
- },
123
- })
124
- }
113
+ // if ((event.node.req as any).body instanceof ArrayBuffer) {
114
+ // return new Request(url, {
115
+ // ...base,
116
+ // body: (event.node.req as any).body,
117
+ // })
118
+ // }
125
119
 
126
- export function toWebRequest(event: H3Event) {
127
- event.web ??= {
128
- request: toWebRequestH3(event),
129
- url: getRequestURL(event),
130
- }
131
- return event.web.request
132
- }
120
+ // return new Request(url, {
121
+ // ...base,
122
+ // get body() {
123
+ // if (readableStream) {
124
+ // return readableStream
125
+ // }
126
+ // readableStream = _getRequestWebStream(event)
127
+ // return readableStream
128
+ // },
129
+ // })
130
+ // }
133
131
 
134
132
  export {
135
133
  H3Error,
@@ -140,7 +138,6 @@ export {
140
138
  createAppEventHandler,
141
139
  createEvent,
142
140
  createRouter,
143
- defineEventHandler,
144
141
  defineLazyEventHandler,
145
142
  defineNodeListener,
146
143
  defineNodeMiddleware,
@@ -148,7 +145,6 @@ export {
148
145
  defineResponseMiddleware,
149
146
  dynamicEventHandler,
150
147
  defineWebSocket,
151
- eventHandler,
152
148
  splitCookiesString,
153
149
  fromNodeMiddleware,
154
150
  fromPlainHandler,
@@ -163,6 +159,7 @@ export {
163
159
  toNodeListener,
164
160
  toPlainHandler,
165
161
  toWebHandler,
162
+ toWebRequest,
166
163
  isCorsOriginAllowed,
167
164
  isStream,
168
165
  createError,
@@ -221,8 +218,33 @@ export {
221
218
  type _ResponseMiddleware,
222
219
  } from 'h3'
223
220
 
224
- function getHTTPEvent() {
225
- return getEvent()
221
+ export function defineEventHandler(handler: EventHandler) {
222
+ return _defineEventHandler((event) => {
223
+ return runWithEvent(event, () => handler(event))
224
+ })
225
+ }
226
+
227
+ export function eventHandler(handler: EventHandler) {
228
+ return _eventHandler((event) => {
229
+ return runWithEvent(event, () => handler(event))
230
+ })
231
+ }
232
+
233
+ export async function runWithEvent<T>(
234
+ event: H3Event,
235
+ fn: () => T | Promise<T>,
236
+ ): Promise<T> {
237
+ return eventStorage.run(event, fn)
238
+ }
239
+
240
+ export function getEvent() {
241
+ const event = eventStorage.getStore() as H3Event | undefined
242
+ if (!event) {
243
+ throw new Error(
244
+ `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`,
245
+ )
246
+ }
247
+ return event
226
248
  }
227
249
 
228
250
  export const HTTPEventSymbol = Symbol('$HTTPEvent')
@@ -262,12 +284,7 @@ function createWrapperFunction<TFn extends (...args: Array<any>) => any>(
262
284
  return function (...args: Array<any>) {
263
285
  const event = args[0]
264
286
  if (!isEvent(event)) {
265
- if (!(globalThis as any).app.config.server.experimental?.asyncContext) {
266
- throw new Error(
267
- 'AsyncLocalStorage was not enabled. Use the `server.experimental.asyncContext: true` option in your app configuration to enable it. Or, pass the instance of HTTPEvent that you have as the first argument to the function.',
268
- )
269
- }
270
- args.unshift(getHTTPEvent())
287
+ args.unshift(getEvent())
271
288
  } else {
272
289
  args[0] =
273
290
  event instanceof H3Event || (event as any).__is_event__
@@ -463,37 +480,13 @@ export const readValidatedBody: PrependOverload<
463
480
  export const removeResponseHeader = createWrapperFunction(_removeResponseHeader)
464
481
  export const getContext = createWrapperFunction(_getContext)
465
482
  export const setContext = createWrapperFunction(_setContext)
466
-
467
483
  export const clearResponseHeaders = createWrapperFunction(_clearResponseHeaders)
484
+ export const getWebRequest = createWrapperFunction(_toWebRequest)
468
485
 
469
- export const getWebRequest = createWrapperFunction(toWebRequest)
470
-
471
- export { createApp as createServer } from 'h3'
472
-
473
- function getNitroAsyncContext() {
474
- const nitroAsyncContext = getUnctxContext('nitro-app', {
475
- asyncContext: (globalThis as any).app.config.server.experimental
476
- ?.asyncContext
477
- ? true
478
- : false,
479
- AsyncLocalStorage,
480
- })
481
-
482
- return nitroAsyncContext
483
- }
484
-
485
- export function getEvent() {
486
- const event = (getNitroAsyncContext().use() as any).event as
487
- | H3Event
488
- | undefined
489
- if (!event) {
490
- throw new Error(
491
- `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`,
492
- )
493
- }
494
- return event
495
- }
486
+ export type RequestHandler = (ctx: {
487
+ request: Request
488
+ }) => Promise<Response> | Response
496
489
 
497
- export async function handleHTTPEvent(event: H3Event) {
498
- return await (globalThis as any).$handle(event)
490
+ export function requestHandler(handler: RequestHandler) {
491
+ return handler
499
492
  }
@@ -1,22 +1,15 @@
1
- import type { EventHandlerResponse } from 'h3'
2
1
  import type { AnyRouter } from '@tanstack/router-core'
3
2
 
4
- export interface HandlerCallback<
5
- TRouter extends AnyRouter,
6
- TResponse extends EventHandlerResponse = EventHandlerResponse,
7
- > {
3
+ export interface HandlerCallback<TRouter extends AnyRouter> {
8
4
  (ctx: {
9
5
  request: Request
10
6
  router: TRouter
11
7
  responseHeaders: Headers
12
- }): TResponse
8
+ }): Response | Promise<Response>
13
9
  }
14
10
 
15
- export function defineHandlerCallback<
16
- TRouter extends AnyRouter,
17
- TResponse = EventHandlerResponse,
18
- >(
19
- handler: HandlerCallback<TRouter, TResponse>,
20
- ): HandlerCallback<TRouter, TResponse> {
11
+ export function defineHandlerCallback<TRouter extends AnyRouter>(
12
+ handler: HandlerCallback<TRouter>,
13
+ ): HandlerCallback<TRouter> {
21
14
  return handler
22
15
  }
package/src/index.tsx CHANGED
@@ -3,10 +3,22 @@ export {
3
3
  transformPipeableStreamWithRouter,
4
4
  } from './transformStreamWithRouter'
5
5
 
6
- export { createStartHandler } from './createStartHandler'
6
+ export {
7
+ getStartResponseHeaders,
8
+ createStartHandler,
9
+ } from './createStartHandler'
10
+ export type { CustomizeStartHandler } from './createStartHandler'
7
11
  export { createRequestHandler } from './createRequestHandler'
8
12
 
9
13
  export { defineHandlerCallback } from './handlerCallback'
10
14
  export type { HandlerCallback } from './handlerCallback'
11
15
 
16
+ export { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'
17
+ export { handleServerAction } from './server-functions-handler'
18
+
12
19
  export * from './h3'
20
+
21
+ export { createServerRoute, createServerFileRoute } from './serverRoute'
22
+ export type { CreateServerFileRoute } from './serverRoute'
23
+
24
+ export { __getAbsoluteUrl, __setGlobalOrigin } from './undici'