@tanstack/start-server-core 1.120.4-alpha.7 → 1.120.4

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