@tanstack/start-server-core 1.132.0-alpha.9 → 1.132.0
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/createStartHandler.d.ts +3 -6
- package/dist/esm/createStartHandler.js +261 -220
- package/dist/esm/createStartHandler.js.map +1 -1
- package/dist/esm/index.d.ts +1 -3
- package/dist/esm/index.js +0 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/loadVirtualModule.js +0 -2
- package/dist/esm/loadVirtualModule.js.map +1 -1
- package/dist/esm/request-handler.d.ts +19 -0
- package/dist/esm/request-response.d.ts +2 -2
- package/dist/esm/request-response.js +5 -2
- package/dist/esm/request-response.js.map +1 -1
- package/dist/esm/serializer/ServerFunctionSerializationAdapter.js +1 -1
- package/dist/esm/serializer/ServerFunctionSerializationAdapter.js.map +1 -1
- package/dist/esm/server-functions-handler.d.ts +2 -1
- package/dist/esm/server-functions-handler.js +16 -13
- package/dist/esm/server-functions-handler.js.map +1 -1
- package/dist/esm/virtual-modules.d.ts +0 -2
- package/dist/esm/virtual-modules.js +0 -1
- package/dist/esm/virtual-modules.js.map +1 -1
- package/package.json +7 -7
- package/src/createStartHandler.ts +353 -326
- package/src/index.tsx +2 -42
- package/src/loadVirtualModule.ts +0 -2
- package/src/request-handler.ts +31 -0
- package/src/request-response.ts +8 -5
- package/src/serializer/ServerFunctionSerializationAdapter.ts +1 -1
- package/src/server-functions-handler.ts +21 -16
- package/src/tanstack-start.d.ts +0 -2
- package/src/virtual-modules.ts +0 -2
- package/dist/esm/serializer/getSerovalPlugins.d.ts +0 -3
- package/dist/esm/serializer/getSerovalPlugins.js +0 -13
- package/dist/esm/serializer/getSerovalPlugins.js.map +0 -1
- package/dist/esm/serverRoute.d.ts +0 -124
- package/dist/esm/serverRoute.js +0 -103
- package/dist/esm/serverRoute.js.map +0 -1
- package/src/serializer/getSerovalPlugins.ts +0 -10
- package/src/serverRoute.ts +0 -736
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { RequestHandler } from './request-
|
|
2
|
-
import { AnyRouter,
|
|
1
|
+
import { RequestHandler } from './request-handler.js';
|
|
2
|
+
import { AnyRouter, Register } from '@tanstack/router-core';
|
|
3
3
|
import { HandlerCallback } from '@tanstack/router-core/ssr/server';
|
|
4
|
-
export
|
|
5
|
-
export declare function createStartHandler<TRouter extends AnyRouter>({ createRouter, }: {
|
|
6
|
-
createRouter: () => Awaitable<TRouter>;
|
|
7
|
-
}): CustomizeStartHandler<TRouter>;
|
|
4
|
+
export declare function createStartHandler<TRegister = Register>(cb: HandlerCallback<AnyRouter>): RequestHandler<TRegister>;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { createMemoryHistory } from "@tanstack/history";
|
|
2
|
-
import { json, mergeHeaders
|
|
3
|
-
import { joinPaths, trimPath,
|
|
2
|
+
import { flattenMiddlewares, json, mergeHeaders } from "@tanstack/start-client-core";
|
|
3
|
+
import { joinPaths, trimPath, isRedirect, isResolvedRedirect, executeRewriteInput } from "@tanstack/router-core";
|
|
4
4
|
import { attachRouterServerSsrUtils } from "@tanstack/router-core/ssr/server";
|
|
5
5
|
import { runWithStartContext } from "@tanstack/start-storage-context";
|
|
6
6
|
import { requestHandler, getResponseHeaders } from "./request-response.js";
|
|
7
7
|
import { getStartManifest } from "./router-manifest.js";
|
|
8
8
|
import { handleServerAction } from "./server-functions-handler.js";
|
|
9
|
-
import { VIRTUAL_MODULES } from "./virtual-modules.js";
|
|
10
|
-
import { loadVirtualModule } from "./loadVirtualModule.js";
|
|
11
9
|
import { HEADERS } from "./constants.js";
|
|
12
10
|
import { ServerFunctionSerializationAdapter } from "./serializer/ServerFunctionSerializationAdapter.js";
|
|
13
11
|
function getStartResponseHeaders(opts) {
|
|
@@ -22,172 +20,180 @@ function getStartResponseHeaders(opts) {
|
|
|
22
20
|
);
|
|
23
21
|
return headers;
|
|
24
22
|
}
|
|
25
|
-
function createStartHandler({
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
function createStartHandler(cb) {
|
|
24
|
+
if (!process.env.TSS_SERVER_FN_BASE) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
"tanstack/start-server-core: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()"
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const APP_BASE = process.env.TSS_APP_BASE || "/";
|
|
30
|
+
const serverFnBase = joinPaths([
|
|
31
|
+
APP_BASE,
|
|
32
|
+
trimPath(process.env.TSS_SERVER_FN_BASE),
|
|
33
|
+
"/"
|
|
34
|
+
]);
|
|
29
35
|
let startRoutesManifest = null;
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
36
|
+
let startEntry = null;
|
|
37
|
+
let routerEntry = null;
|
|
38
|
+
const getEntries = async () => {
|
|
39
|
+
if (routerEntry === null) {
|
|
40
|
+
routerEntry = await import("#tanstack-router-entry");
|
|
41
|
+
}
|
|
42
|
+
if (startEntry === null) {
|
|
43
|
+
startEntry = await import("#tanstack-start-entry");
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
startEntry,
|
|
47
|
+
routerEntry
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const originalFetch = globalThis.fetch;
|
|
51
|
+
const startRequestResolver = async (request, requestOpts) => {
|
|
52
|
+
function getOrigin() {
|
|
53
|
+
const originHeader = request.headers.get("Origin");
|
|
54
|
+
if (originHeader) {
|
|
55
|
+
return originHeader;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
return new URL(request.url).origin;
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
return "http://localhost";
|
|
62
|
+
}
|
|
63
|
+
globalThis.fetch = async function(input, init) {
|
|
64
|
+
function resolve(url2, requestOptions) {
|
|
65
|
+
const fetchRequest = new Request(url2, requestOptions);
|
|
66
|
+
return startRequestResolver(fetchRequest, requestOpts);
|
|
67
|
+
}
|
|
68
|
+
if (typeof input === "string" && input.startsWith("/")) {
|
|
69
|
+
const url2 = new URL(input, getOrigin());
|
|
70
|
+
return resolve(url2, init);
|
|
71
|
+
} else if (typeof input === "object" && "url" in input && typeof input.url === "string" && input.url.startsWith("/")) {
|
|
72
|
+
const url2 = new URL(input.url, getOrigin());
|
|
73
|
+
return resolve(url2, init);
|
|
74
|
+
}
|
|
75
|
+
return originalFetch(input, init);
|
|
76
|
+
};
|
|
77
|
+
const url = new URL(request.url);
|
|
78
|
+
const href = url.href.replace(url.origin, "");
|
|
79
|
+
let router = null;
|
|
80
|
+
const getRouter = async () => {
|
|
81
|
+
if (router) return router;
|
|
82
|
+
router = await (await getEntries()).routerEntry.getRouter();
|
|
58
83
|
const isPrerendering = process.env.TSS_PRERENDERING === "true";
|
|
59
84
|
let isShell = process.env.TSS_SHELL === "true";
|
|
60
85
|
if (isPrerendering && !isShell) {
|
|
61
86
|
isShell = request.headers.get(HEADERS.TSS_SHELL) === "true";
|
|
62
87
|
}
|
|
63
|
-
const
|
|
88
|
+
const history = createMemoryHistory({
|
|
89
|
+
initialEntries: [href]
|
|
90
|
+
});
|
|
91
|
+
const origin = router.options.origin ?? getOrigin();
|
|
64
92
|
router.update({
|
|
65
93
|
history,
|
|
66
94
|
isShell,
|
|
67
95
|
isPrerendering,
|
|
68
|
-
|
|
96
|
+
origin,
|
|
97
|
+
...{
|
|
98
|
+
defaultSsr: startOptions.defaultSsr,
|
|
99
|
+
serializationAdapters: startOptions.serializationAdapters
|
|
100
|
+
}
|
|
69
101
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
if (routeTreeModule === null) {
|
|
102
|
+
return router;
|
|
103
|
+
};
|
|
104
|
+
const startOptions = await (await getEntries()).startEntry.startInstance?.getOptions() || {};
|
|
105
|
+
startOptions.serializationAdapters = startOptions.serializationAdapters || [];
|
|
106
|
+
startOptions.serializationAdapters.push(ServerFunctionSerializationAdapter);
|
|
107
|
+
const requestHandlerMiddleware = handlerToMiddleware(
|
|
108
|
+
async ({ context }) => {
|
|
109
|
+
const response2 = await runWithStartContext(
|
|
110
|
+
{
|
|
111
|
+
getRouter,
|
|
112
|
+
startOptions,
|
|
113
|
+
contextAfterGlobalMiddlewares: context
|
|
114
|
+
},
|
|
115
|
+
async () => {
|
|
86
116
|
try {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
processedServerRouteTree = processRouteTree({
|
|
92
|
-
routeTree: routeTreeModule.serverRouteTree,
|
|
93
|
-
initRoute: (route, i) => {
|
|
94
|
-
route.init({
|
|
95
|
-
originalIndex: i
|
|
96
|
-
});
|
|
97
|
-
}
|
|
117
|
+
if (href.startsWith(serverFnBase)) {
|
|
118
|
+
return await handleServerAction({
|
|
119
|
+
request,
|
|
120
|
+
context: requestOpts?.context
|
|
98
121
|
});
|
|
99
122
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
const executeRouter = async ({
|
|
124
|
+
serverContext
|
|
125
|
+
}) => {
|
|
126
|
+
const requestAcceptHeader = request.headers.get("Accept") || "*/*";
|
|
127
|
+
const splitRequestAcceptHeader = requestAcceptHeader.split(",");
|
|
128
|
+
const supportedMimeTypes = ["*/*", "text/html"];
|
|
129
|
+
const isRouterAcceptSupported = supportedMimeTypes.some(
|
|
130
|
+
(mimeType) => splitRequestAcceptHeader.some(
|
|
131
|
+
(acceptedMimeType) => acceptedMimeType.trim().startsWith(mimeType)
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
if (!isRouterAcceptSupported) {
|
|
135
|
+
return json(
|
|
136
|
+
{
|
|
137
|
+
error: "Only HTML requests are supported here"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
status: 500
|
|
141
|
+
}
|
|
142
|
+
);
|
|
120
143
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
144
|
+
if (startRoutesManifest === null) {
|
|
145
|
+
startRoutesManifest = await getStartManifest({
|
|
146
|
+
basePath: APP_BASE
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const router2 = await getRouter();
|
|
150
|
+
attachRouterServerSsrUtils({
|
|
151
|
+
router: router2,
|
|
152
|
+
manifest: startRoutesManifest
|
|
153
|
+
});
|
|
154
|
+
router2.update({ additionalContext: { serverContext } });
|
|
155
|
+
await router2.load();
|
|
156
|
+
if (router2.state.redirect) {
|
|
157
|
+
return router2.state.redirect;
|
|
158
|
+
}
|
|
159
|
+
await router2.serverSsr.dehydrate();
|
|
160
|
+
const responseHeaders = getStartResponseHeaders({ router: router2 });
|
|
161
|
+
const response4 = await cb({
|
|
162
|
+
request,
|
|
163
|
+
router: router2,
|
|
164
|
+
responseHeaders
|
|
165
|
+
});
|
|
166
|
+
return response4;
|
|
167
|
+
};
|
|
168
|
+
const response3 = await handleServerRoutes({
|
|
169
|
+
getRouter,
|
|
170
|
+
request,
|
|
171
|
+
executeRouter
|
|
126
172
|
});
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return router.state.redirect;
|
|
132
|
-
}
|
|
133
|
-
await router.serverSsr.dehydrate();
|
|
134
|
-
const responseHeaders = getStartResponseHeaders({ router });
|
|
135
|
-
const response2 = await cb({
|
|
136
|
-
request,
|
|
137
|
-
router,
|
|
138
|
-
responseHeaders
|
|
139
|
-
});
|
|
140
|
-
return response2;
|
|
141
|
-
};
|
|
142
|
-
if (processedServerRouteTree) {
|
|
143
|
-
const [_matchedRoutes, response2] = await handleServerRoutes({
|
|
144
|
-
processedServerRouteTree,
|
|
145
|
-
router,
|
|
146
|
-
request,
|
|
147
|
-
basePath: APP_BASE,
|
|
148
|
-
executeRouter
|
|
149
|
-
});
|
|
150
|
-
if (response2) return response2;
|
|
151
|
-
}
|
|
152
|
-
const routerResponse = await executeRouter();
|
|
153
|
-
return routerResponse;
|
|
154
|
-
} catch (err) {
|
|
155
|
-
if (err instanceof Response) {
|
|
156
|
-
return err;
|
|
157
|
-
}
|
|
158
|
-
throw err;
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
if (isRedirect(response)) {
|
|
162
|
-
if (isResolvedRedirect(response)) {
|
|
163
|
-
if (request.headers.get("x-tsr-redirect") === "manual") {
|
|
164
|
-
return json(
|
|
165
|
-
{
|
|
166
|
-
...response.options,
|
|
167
|
-
isSerializedRedirect: true
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
headers: response.headers
|
|
173
|
+
return response3;
|
|
174
|
+
} catch (err) {
|
|
175
|
+
if (err instanceof Response) {
|
|
176
|
+
return err;
|
|
171
177
|
}
|
|
172
|
-
|
|
178
|
+
throw err;
|
|
179
|
+
}
|
|
173
180
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const redirect = router.resolveRedirect(response);
|
|
181
|
+
);
|
|
182
|
+
return response2;
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
const flattenedMiddlewares = startOptions.requestMiddleware ? flattenMiddlewares(startOptions.requestMiddleware) : [];
|
|
186
|
+
const middlewares = flattenedMiddlewares.map((d) => d.options.server);
|
|
187
|
+
const ctx = await executeMiddleware(
|
|
188
|
+
[...middlewares, requestHandlerMiddleware],
|
|
189
|
+
{
|
|
190
|
+
request,
|
|
191
|
+
context: requestOpts?.context || {}
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
const response = ctx.response;
|
|
195
|
+
if (isRedirect(response)) {
|
|
196
|
+
if (isResolvedRedirect(response)) {
|
|
191
197
|
if (request.headers.get("x-tsr-redirect") === "manual") {
|
|
192
198
|
return json(
|
|
193
199
|
{
|
|
@@ -199,96 +205,131 @@ function createStartHandler({
|
|
|
199
205
|
}
|
|
200
206
|
);
|
|
201
207
|
}
|
|
202
|
-
return
|
|
208
|
+
return response;
|
|
203
209
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
if (response.options.to && typeof response.options.to === "string" && !response.options.to.startsWith("/")) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`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)}`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
if (["params", "search", "hash"].some(
|
|
216
|
+
(d) => typeof response.options[d] === "function"
|
|
217
|
+
)) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys(
|
|
220
|
+
response.options
|
|
221
|
+
).filter((d) => typeof response.options[d] === "function").map((d) => `"${d}"`).join(", ")}`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
const router2 = await getRouter();
|
|
225
|
+
const redirect = router2.resolveRedirect(response);
|
|
226
|
+
if (request.headers.get("x-tsr-redirect") === "manual") {
|
|
227
|
+
return json(
|
|
228
|
+
{
|
|
229
|
+
...response.options,
|
|
230
|
+
isSerializedRedirect: true
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
headers: response.headers
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
return redirect;
|
|
238
|
+
}
|
|
239
|
+
return response;
|
|
207
240
|
};
|
|
241
|
+
return requestHandler(startRequestResolver);
|
|
208
242
|
}
|
|
209
|
-
async function handleServerRoutes(
|
|
210
|
-
|
|
243
|
+
async function handleServerRoutes({
|
|
244
|
+
getRouter,
|
|
245
|
+
request,
|
|
246
|
+
executeRouter
|
|
247
|
+
}) {
|
|
248
|
+
const router = await getRouter();
|
|
249
|
+
let url = new URL(request.url);
|
|
250
|
+
url = executeRewriteInput(router.rewrite, url);
|
|
211
251
|
const pathname = url.pathname;
|
|
212
|
-
const
|
|
252
|
+
const { matchedRoutes, foundRoute, routeParams } = router.getMatchedRoutes(
|
|
213
253
|
pathname,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
});
|
|
229
|
-
if (closestCommon) {
|
|
230
|
-
let routeId = closestCommon.id;
|
|
231
|
-
matchedRoutes = [];
|
|
232
|
-
do {
|
|
233
|
-
const route = opts.processedServerRouteTree.routesById[routeId];
|
|
234
|
-
if (!route) {
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
matchedRoutes.push(route);
|
|
238
|
-
routeId = route.parentRoute?.id;
|
|
239
|
-
} while (routeId);
|
|
240
|
-
matchedRoutes.reverse();
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (matchedRoutes.length) {
|
|
245
|
-
const middlewares = flattenMiddlewares(
|
|
246
|
-
matchedRoutes.flatMap((r) => r.options.middleware).filter(Boolean)
|
|
247
|
-
).map((d) => d.options.server);
|
|
248
|
-
if (serverTreeResult.foundRoute?.options.methods) {
|
|
249
|
-
const method = Object.keys(
|
|
250
|
-
serverTreeResult.foundRoute.options.methods
|
|
251
|
-
).find(
|
|
252
|
-
(method2) => method2.toLowerCase() === opts.request.method.toLowerCase()
|
|
254
|
+
void 0
|
|
255
|
+
);
|
|
256
|
+
const middlewares = flattenMiddlewares(
|
|
257
|
+
matchedRoutes.flatMap((r) => r.options.server?.middleware).filter(Boolean)
|
|
258
|
+
).map((d) => d.options.server);
|
|
259
|
+
const server = foundRoute?.options.server;
|
|
260
|
+
if (server) {
|
|
261
|
+
if (server.handlers) {
|
|
262
|
+
const handlers = typeof server.handlers === "function" ? server.handlers({
|
|
263
|
+
createHandlers: (d) => d
|
|
264
|
+
}) : server.handlers;
|
|
265
|
+
const requestMethod = request.method.toLowerCase();
|
|
266
|
+
let method = Object.keys(handlers).find(
|
|
267
|
+
(method2) => method2.toLowerCase() === requestMethod
|
|
253
268
|
);
|
|
269
|
+
if (!method) {
|
|
270
|
+
method = Object.keys(handlers).find(
|
|
271
|
+
(method2) => method2.toLowerCase() === "all"
|
|
272
|
+
) ? "all" : void 0;
|
|
273
|
+
}
|
|
254
274
|
if (method) {
|
|
255
|
-
const handler =
|
|
275
|
+
const handler = handlers[method];
|
|
256
276
|
if (handler) {
|
|
277
|
+
const mayDefer = !!foundRoute.options.component;
|
|
257
278
|
if (typeof handler === "function") {
|
|
258
|
-
middlewares.push(handlerToMiddleware(handler));
|
|
279
|
+
middlewares.push(handlerToMiddleware(handler, mayDefer));
|
|
259
280
|
} else {
|
|
260
|
-
|
|
281
|
+
const { middleware } = handler;
|
|
282
|
+
if (middleware && middleware.length) {
|
|
261
283
|
middlewares.push(
|
|
262
|
-
...flattenMiddlewares(
|
|
263
|
-
(d) => d.options.server
|
|
264
|
-
)
|
|
284
|
+
...flattenMiddlewares(middleware).map((d) => d.options.server)
|
|
265
285
|
);
|
|
266
286
|
}
|
|
267
|
-
if (handler.
|
|
268
|
-
middlewares.push(handlerToMiddleware(handler.
|
|
287
|
+
if (handler.handler) {
|
|
288
|
+
middlewares.push(handlerToMiddleware(handler.handler, mayDefer));
|
|
269
289
|
}
|
|
270
290
|
}
|
|
271
291
|
}
|
|
272
292
|
}
|
|
273
293
|
}
|
|
274
|
-
middlewares.push(handlerToMiddleware(opts.executeRouter));
|
|
275
|
-
const ctx = await executeMiddleware(middlewares, {
|
|
276
|
-
request: opts.request,
|
|
277
|
-
context: {},
|
|
278
|
-
params: serverTreeResult.routeParams,
|
|
279
|
-
pathname
|
|
280
|
-
});
|
|
281
|
-
response = ctx.response;
|
|
282
294
|
}
|
|
283
|
-
|
|
295
|
+
middlewares.push(
|
|
296
|
+
handlerToMiddleware((ctx2) => executeRouter({ serverContext: ctx2.context }))
|
|
297
|
+
);
|
|
298
|
+
const ctx = await executeMiddleware(middlewares, {
|
|
299
|
+
request,
|
|
300
|
+
context: {},
|
|
301
|
+
params: routeParams,
|
|
302
|
+
pathname
|
|
303
|
+
});
|
|
304
|
+
const response = ctx.response;
|
|
305
|
+
return response;
|
|
284
306
|
}
|
|
285
|
-
function
|
|
307
|
+
function throwRouteHandlerError() {
|
|
308
|
+
if (process.env.NODE_ENV === "development") {
|
|
309
|
+
throw new Error(
|
|
310
|
+
`It looks like you forgot to return a response from your server route handler. If you want to defer to the app router, make sure to have a component set in this route.`
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
throw new Error("Internal Server Error");
|
|
314
|
+
}
|
|
315
|
+
function throwIfMayNotDefer() {
|
|
316
|
+
if (process.env.NODE_ENV === "development") {
|
|
317
|
+
throw new Error(
|
|
318
|
+
`You cannot defer to the app router if there is no component defined on this route.`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
throw new Error("Internal Server Error");
|
|
322
|
+
}
|
|
323
|
+
function handlerToMiddleware(handler, mayDefer = false) {
|
|
324
|
+
if (mayDefer) {
|
|
325
|
+
return handler;
|
|
326
|
+
}
|
|
286
327
|
return async ({ next: _next, ...rest }) => {
|
|
287
|
-
const response = await handler(rest);
|
|
288
|
-
if (response) {
|
|
289
|
-
|
|
328
|
+
const response = await handler({ ...rest, next: throwIfMayNotDefer });
|
|
329
|
+
if (!response) {
|
|
330
|
+
throwRouteHandlerError();
|
|
290
331
|
}
|
|
291
|
-
return
|
|
332
|
+
return response;
|
|
292
333
|
};
|
|
293
334
|
}
|
|
294
335
|
function executeMiddleware(middlewares, ctx) {
|