@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.
- package/dist/esm/constants.d.ts +3 -0
- package/dist/esm/constants.js +7 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/createStartHandler.d.ts +4 -7
- package/dist/esm/createStartHandler.js +169 -102
- package/dist/esm/createStartHandler.js.map +1 -1
- package/dist/esm/index.d.ts +6 -8
- package/dist/esm/index.js +10 -97
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/loadVirtualModule.js +2 -0
- package/dist/esm/loadVirtualModule.js.map +1 -1
- package/dist/esm/request-response.d.ts +124 -0
- package/dist/esm/request-response.js +177 -0
- package/dist/esm/request-response.js.map +1 -0
- package/dist/esm/router-manifest.d.ts +1 -0
- package/dist/esm/router-manifest.js +17 -17
- package/dist/esm/router-manifest.js.map +1 -1
- package/dist/esm/server-functions-handler.js +6 -7
- package/dist/esm/server-functions-handler.js.map +1 -1
- package/dist/esm/serverRoute.d.ts +6 -2
- package/dist/esm/serverRoute.js +3 -2
- package/dist/esm/serverRoute.js.map +1 -1
- package/dist/esm/session.d.ts +66 -0
- package/dist/esm/virtual-modules.d.ts +2 -0
- package/dist/esm/virtual-modules.js +2 -1
- package/dist/esm/virtual-modules.js.map +1 -1
- package/package.json +9 -19
- package/src/constants.ts +3 -0
- package/src/createStartHandler.ts +241 -143
- package/src/global.d.ts +10 -2
- package/src/index.tsx +42 -13
- package/src/loadVirtualModule.ts +2 -0
- package/src/request-response.ts +335 -0
- package/src/router-manifest.ts +17 -38
- package/src/server-functions-handler.ts +6 -5
- package/src/serverRoute.ts +22 -3
- package/src/session.ts +75 -0
- package/src/tanstack-start.d.ts +18 -5
- package/src/virtual-modules.ts +2 -0
- package/dist/cjs/createRequestHandler.cjs +0 -50
- package/dist/cjs/createRequestHandler.cjs.map +0 -1
- package/dist/cjs/createRequestHandler.d.cts +0 -8
- package/dist/cjs/createStartHandler.cjs +0 -274
- package/dist/cjs/createStartHandler.cjs.map +0 -1
- package/dist/cjs/createStartHandler.d.cts +0 -10
- package/dist/cjs/h3.cjs +0 -355
- package/dist/cjs/h3.cjs.map +0 -1
- package/dist/cjs/h3.d.cts +0 -109
- package/dist/cjs/handlerCallback.cjs +0 -7
- package/dist/cjs/handlerCallback.cjs.map +0 -1
- package/dist/cjs/handlerCallback.d.cts +0 -9
- package/dist/cjs/index.cjs +0 -245
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/index.d.cts +0 -12
- package/dist/cjs/loadVirtualModule.cjs +0 -39
- package/dist/cjs/loadVirtualModule.cjs.map +0 -1
- package/dist/cjs/loadVirtualModule.d.cts +0 -6
- package/dist/cjs/router-manifest.cjs +0 -49
- package/dist/cjs/router-manifest.cjs.map +0 -1
- package/dist/cjs/router-manifest.d.cts +0 -16
- package/dist/cjs/server-functions-handler.cjs +0 -148
- package/dist/cjs/server-functions-handler.cjs.map +0 -1
- package/dist/cjs/server-functions-handler.d.cts +0 -3
- package/dist/cjs/serverRoute.cjs +0 -102
- package/dist/cjs/serverRoute.cjs.map +0 -1
- package/dist/cjs/serverRoute.d.cts +0 -120
- package/dist/cjs/ssr-server.cjs +0 -247
- package/dist/cjs/ssr-server.cjs.map +0 -1
- package/dist/cjs/ssr-server.d.cts +0 -29
- package/dist/cjs/transformStreamWithRouter.cjs +0 -183
- package/dist/cjs/transformStreamWithRouter.cjs.map +0 -1
- package/dist/cjs/transformStreamWithRouter.d.cts +0 -6
- package/dist/cjs/tsrScript.cjs +0 -4
- package/dist/cjs/tsrScript.cjs.map +0 -1
- package/dist/cjs/tsrScript.d.cts +0 -1
- package/dist/cjs/virtual-modules.cjs +0 -9
- package/dist/cjs/virtual-modules.cjs.map +0 -1
- package/dist/cjs/virtual-modules.d.cts +0 -10
- package/dist/esm/createRequestHandler.d.ts +0 -8
- package/dist/esm/createRequestHandler.js +0 -50
- package/dist/esm/createRequestHandler.js.map +0 -1
- package/dist/esm/h3.d.ts +0 -109
- package/dist/esm/h3.js +0 -248
- package/dist/esm/h3.js.map +0 -1
- package/dist/esm/handlerCallback.d.ts +0 -9
- package/dist/esm/handlerCallback.js +0 -7
- package/dist/esm/handlerCallback.js.map +0 -1
- package/dist/esm/ssr-server.d.ts +0 -29
- package/dist/esm/ssr-server.js +0 -247
- package/dist/esm/ssr-server.js.map +0 -1
- package/dist/esm/transformStreamWithRouter.d.ts +0 -6
- package/dist/esm/transformStreamWithRouter.js +0 -183
- package/dist/esm/transformStreamWithRouter.js.map +0 -1
- package/dist/esm/tsrScript.d.ts +0 -1
- package/dist/esm/tsrScript.js +0 -5
- package/dist/esm/tsrScript.js.map +0 -1
- package/src/createRequestHandler.ts +0 -73
- package/src/h3.ts +0 -492
- package/src/handlerCallback.ts +0 -15
- package/src/ssr-server.ts +0 -352
- package/src/transformStreamWithRouter.ts +0 -258
- package/src/tsrScript.ts +0 -91
- 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 {
|
|
17
|
-
import {
|
|
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
|
-
|
|
23
|
-
import
|
|
24
|
-
import type {
|
|
25
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
getResponseHeaders(),
|
|
44
|
+
function getStartResponseHeaders(opts: { router: AnyRouter }) {
|
|
45
|
+
const headers = mergeHeaders(
|
|
46
|
+
getResponseHeaders() as Headers,
|
|
36
47
|
{
|
|
37
|
-
'Content-Type': 'text/html; charset=
|
|
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
|
|
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 (
|
|
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(
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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 (
|
|
161
|
+
if (routeTreeModule === null) {
|
|
145
162
|
try {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
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 (
|
|
237
|
+
if (processedServerRouteTree) {
|
|
157
238
|
const [_matchedRoutes, response] = await handleServerRoutes({
|
|
158
|
-
|
|
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
|
-
|
|
167
|
-
const
|
|
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
|
-
|
|
280
|
-
|
|
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
|
-
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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({
|
|
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
|
-
|
|
3
|
-
|
|
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 '
|
|
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 './
|
|
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'
|
package/src/loadVirtualModule.ts
CHANGED
|
@@ -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
|
}
|