@tanstack/router-core 1.121.0-alpha.27 → 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/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +31 -1
- package/dist/cjs/RouterProvider.d.cts +2 -1
- package/dist/cjs/defer.cjs +1 -1
- package/dist/cjs/defer.cjs.map +1 -1
- package/dist/cjs/global.d.cts +7 -0
- package/dist/cjs/index.cjs +1 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +6 -6
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +12 -0
- package/dist/cjs/lru-cache.cjs +62 -0
- package/dist/cjs/lru-cache.cjs.map +1 -0
- package/dist/cjs/lru-cache.d.cts +5 -0
- package/dist/cjs/not-found.cjs +1 -1
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/path.cjs +316 -148
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +18 -24
- package/dist/cjs/qss.cjs.map +1 -1
- package/dist/cjs/redirect.cjs +3 -0
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/route.cjs +6 -12
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +29 -9
- package/dist/cjs/router.cjs +453 -272
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +55 -85
- package/dist/cjs/scroll-restoration.cjs +20 -13
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +9 -1
- package/dist/cjs/searchMiddleware.cjs.map +1 -1
- package/dist/cjs/searchParams.cjs.map +1 -1
- package/dist/cjs/ssr/client.cjs +10 -0
- package/dist/cjs/ssr/client.cjs.map +1 -0
- package/dist/cjs/ssr/client.d.cts +5 -0
- package/dist/cjs/ssr/createRequestHandler.cjs +50 -0
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -0
- package/dist/cjs/ssr/createRequestHandler.d.cts +9 -0
- package/dist/cjs/ssr/handlerCallback.cjs +7 -0
- package/dist/cjs/ssr/handlerCallback.cjs.map +1 -0
- package/dist/cjs/ssr/handlerCallback.d.cts +9 -0
- package/dist/cjs/ssr/headers.cjs +39 -0
- package/dist/cjs/ssr/headers.cjs.map +1 -0
- package/dist/cjs/ssr/headers.d.cts +5 -0
- package/dist/cjs/ssr/json.cjs +14 -0
- package/dist/cjs/ssr/json.cjs.map +1 -0
- package/dist/cjs/ssr/json.d.cts +4 -0
- package/dist/cjs/ssr/seroval-plugins.cjs +34 -0
- package/dist/cjs/ssr/seroval-plugins.cjs.map +1 -0
- package/dist/cjs/ssr/seroval-plugins.d.cts +10 -0
- package/dist/cjs/ssr/server.cjs +13 -0
- package/dist/cjs/ssr/server.cjs.map +1 -0
- package/dist/cjs/ssr/server.d.cts +6 -0
- package/dist/cjs/ssr/ssr-client.cjs +159 -0
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -0
- package/dist/cjs/ssr/ssr-client.d.cts +29 -0
- package/dist/cjs/ssr/ssr-server.cjs +107 -0
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -0
- package/dist/cjs/ssr/ssr-server.d.cts +18 -0
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +183 -0
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -0
- package/dist/cjs/ssr/transformStreamWithRouter.d.cts +6 -0
- package/dist/cjs/ssr/tsrScript.cjs +4 -0
- package/dist/cjs/ssr/tsrScript.cjs.map +1 -0
- package/dist/cjs/ssr/tsrScript.d.cts +0 -0
- package/dist/cjs/utils.cjs +7 -25
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -6
- package/dist/esm/Matches.d.ts +31 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.d.ts +2 -1
- package/dist/esm/defer.js +1 -1
- package/dist/esm/defer.js.map +1 -1
- package/dist/esm/global.d.ts +7 -0
- package/dist/esm/index.d.ts +6 -6
- package/dist/esm/index.js +2 -3
- package/dist/esm/link.d.ts +12 -0
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/lru-cache.d.ts +5 -0
- package/dist/esm/lru-cache.js +62 -0
- package/dist/esm/lru-cache.js.map +1 -0
- package/dist/esm/not-found.js +1 -1
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/path.d.ts +18 -24
- package/dist/esm/path.js +316 -148
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/qss.js.map +1 -1
- package/dist/esm/redirect.js +3 -0
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/route.d.ts +29 -9
- package/dist/esm/route.js +6 -12
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +55 -85
- package/dist/esm/router.js +462 -281
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +9 -1
- package/dist/esm/scroll-restoration.js +20 -13
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/searchMiddleware.js.map +1 -1
- package/dist/esm/searchParams.js.map +1 -1
- package/dist/esm/ssr/client.d.ts +5 -0
- package/dist/esm/ssr/client.js +10 -0
- package/dist/esm/ssr/client.js.map +1 -0
- package/dist/esm/ssr/createRequestHandler.d.ts +9 -0
- package/dist/esm/ssr/createRequestHandler.js +50 -0
- package/dist/esm/ssr/createRequestHandler.js.map +1 -0
- package/dist/esm/ssr/handlerCallback.d.ts +9 -0
- package/dist/esm/ssr/handlerCallback.js +7 -0
- package/dist/esm/ssr/handlerCallback.js.map +1 -0
- package/dist/esm/ssr/headers.d.ts +5 -0
- package/dist/esm/ssr/headers.js +39 -0
- package/dist/esm/ssr/headers.js.map +1 -0
- package/dist/esm/ssr/json.d.ts +4 -0
- package/dist/esm/ssr/json.js +14 -0
- package/dist/esm/ssr/json.js.map +1 -0
- package/dist/esm/ssr/seroval-plugins.d.ts +10 -0
- package/dist/esm/ssr/seroval-plugins.js +34 -0
- package/dist/esm/ssr/seroval-plugins.js.map +1 -0
- package/dist/esm/ssr/server.d.ts +6 -0
- package/dist/esm/ssr/server.js +13 -0
- package/dist/esm/ssr/server.js.map +1 -0
- package/dist/esm/ssr/ssr-client.d.ts +29 -0
- package/dist/esm/ssr/ssr-client.js +159 -0
- package/dist/esm/ssr/ssr-client.js.map +1 -0
- package/dist/esm/ssr/ssr-server.d.ts +18 -0
- package/dist/esm/ssr/ssr-server.js +107 -0
- package/dist/esm/ssr/ssr-server.js.map +1 -0
- package/dist/esm/ssr/transformStreamWithRouter.d.ts +6 -0
- package/dist/esm/ssr/transformStreamWithRouter.js +183 -0
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -0
- package/dist/esm/ssr/tsrScript.d.ts +0 -0
- package/dist/esm/ssr/tsrScript.js +5 -0
- package/dist/esm/ssr/tsrScript.js.map +1 -0
- package/dist/esm/utils.d.ts +1 -6
- package/dist/esm/utils.js +8 -26
- package/dist/esm/utils.js.map +1 -1
- package/package.json +29 -2
- package/src/Matches.ts +40 -1
- package/src/RouterProvider.ts +2 -1
- package/src/global.ts +9 -0
- package/src/index.ts +12 -20
- package/src/link.ts +12 -0
- package/src/lru-cache.ts +68 -0
- package/src/path.ts +424 -174
- package/src/redirect.ts +3 -0
- package/src/route.ts +44 -13
- package/src/router.ts +580 -312
- package/src/scroll-restoration.ts +30 -18
- package/src/ssr/client.ts +5 -0
- package/src/ssr/createRequestHandler.ts +74 -0
- package/src/ssr/handlerCallback.ts +15 -0
- package/src/ssr/headers.ts +51 -0
- package/src/ssr/json.ts +18 -0
- package/src/ssr/seroval-plugins.ts +43 -0
- package/src/ssr/server.ts +10 -0
- package/src/ssr/ssr-client.ts +242 -0
- package/src/ssr/ssr-server.ts +132 -0
- package/src/ssr/transformStreamWithRouter.ts +259 -0
- package/src/ssr/tsrScript.ts +7 -0
- package/src/utils.ts +10 -39
- package/src/vite-env.d.ts +4 -0
- package/dist/cjs/serializer.d.cts +0 -22
- package/dist/esm/serializer.d.ts +0 -22
- package/src/serializer.ts +0 -32
package/dist/cjs/router.cjs
CHANGED
|
@@ -10,6 +10,7 @@ const scrollRestoration = require("./scroll-restoration.cjs");
|
|
|
10
10
|
const searchParams = require("./searchParams.cjs");
|
|
11
11
|
const root = require("./root.cjs");
|
|
12
12
|
const redirect = require("./redirect.cjs");
|
|
13
|
+
const lruCache = require("./lru-cache.cjs");
|
|
13
14
|
function defaultSerializeError(err) {
|
|
14
15
|
if (err instanceof Error) {
|
|
15
16
|
const obj = {
|
|
@@ -28,9 +29,9 @@ function defaultSerializeError(err) {
|
|
|
28
29
|
function getLocationChangeInfo(routerState) {
|
|
29
30
|
const fromLocation = routerState.resolvedLocation;
|
|
30
31
|
const toLocation = routerState.location;
|
|
31
|
-
const pathChanged =
|
|
32
|
-
const hrefChanged =
|
|
33
|
-
const hashChanged =
|
|
32
|
+
const pathChanged = fromLocation?.pathname !== toLocation.pathname;
|
|
33
|
+
const hrefChanged = fromLocation?.href !== toLocation.href;
|
|
34
|
+
const hashChanged = fromLocation?.hash !== toLocation.hash;
|
|
34
35
|
return { fromLocation, toLocation, pathChanged, hrefChanged, hashChanged };
|
|
35
36
|
}
|
|
36
37
|
class RouterCore {
|
|
@@ -48,9 +49,7 @@ class RouterCore {
|
|
|
48
49
|
this.isScrollRestoring = false;
|
|
49
50
|
this.isScrollRestorationSetup = false;
|
|
50
51
|
this.startTransition = (fn) => fn();
|
|
51
|
-
this.isShell = false;
|
|
52
52
|
this.update = (newOptions) => {
|
|
53
|
-
var _a;
|
|
54
53
|
if (newOptions.notFoundRoute) {
|
|
55
54
|
console.warn(
|
|
56
55
|
"The notFoundRoute API is deprecated and will be removed in the next major version. See https://tanstack.com/router/v1/docs/framework/react/guide/not-found-errors#migrating-from-notfoundroute for more info."
|
|
@@ -98,22 +97,18 @@ class RouterCore {
|
|
|
98
97
|
});
|
|
99
98
|
scrollRestoration.setupScrollRestoration(this);
|
|
100
99
|
}
|
|
101
|
-
if (typeof window !== "undefined" && "CSS" in window && typeof
|
|
100
|
+
if (typeof window !== "undefined" && "CSS" in window && typeof window.CSS?.supports === "function") {
|
|
102
101
|
this.isViewTransitionTypesSupported = window.CSS.supports(
|
|
103
102
|
"selector(:active-view-transition-type(a)"
|
|
104
103
|
);
|
|
105
104
|
}
|
|
106
|
-
if (this.latestLocation.search.__TSS_SHELL) {
|
|
107
|
-
this.isShell = true;
|
|
108
|
-
}
|
|
109
105
|
};
|
|
110
106
|
this.buildRouteTree = () => {
|
|
111
107
|
const { routesById, routesByPath, flatRoutes } = processRouteTree({
|
|
112
108
|
routeTree: this.routeTree,
|
|
113
109
|
initRoute: (route, i) => {
|
|
114
110
|
route.init({
|
|
115
|
-
originalIndex: i
|
|
116
|
-
defaultSsr: this.options.defaultSsr
|
|
111
|
+
originalIndex: i
|
|
117
112
|
});
|
|
118
113
|
}
|
|
119
114
|
});
|
|
@@ -123,8 +118,7 @@ class RouterCore {
|
|
|
123
118
|
const notFoundRoute = this.options.notFoundRoute;
|
|
124
119
|
if (notFoundRoute) {
|
|
125
120
|
notFoundRoute.init({
|
|
126
|
-
originalIndex: 99999999999
|
|
127
|
-
defaultSsr: this.options.defaultSsr
|
|
121
|
+
originalIndex: 99999999999
|
|
128
122
|
});
|
|
129
123
|
this.routesById[notFoundRoute.id] = notFoundRoute;
|
|
130
124
|
}
|
|
@@ -158,10 +152,10 @@ class RouterCore {
|
|
|
158
152
|
return {
|
|
159
153
|
pathname,
|
|
160
154
|
searchStr,
|
|
161
|
-
search: utils.replaceEqualDeep(previousLocation
|
|
155
|
+
search: utils.replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
162
156
|
hash: hash.split("#").reverse()[0] ?? "",
|
|
163
157
|
href: `${pathname}${searchStr}${hash}`,
|
|
164
|
-
state: utils.replaceEqualDeep(previousLocation
|
|
158
|
+
state: utils.replaceEqualDeep(previousLocation?.state, state)
|
|
165
159
|
};
|
|
166
160
|
};
|
|
167
161
|
const location = parse(locationToParse ?? this.history.location);
|
|
@@ -169,6 +163,7 @@ class RouterCore {
|
|
|
169
163
|
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
170
164
|
const parsedTempLocation = parse(__tempLocation);
|
|
171
165
|
parsedTempLocation.state.key = location.state.key;
|
|
166
|
+
parsedTempLocation.state.__TSR_key = location.state.__TSR_key;
|
|
172
167
|
delete parsedTempLocation.state.__tempLocation;
|
|
173
168
|
return {
|
|
174
169
|
...parsedTempLocation,
|
|
@@ -183,7 +178,8 @@ class RouterCore {
|
|
|
183
178
|
base: from,
|
|
184
179
|
to: path.cleanPath(path$1),
|
|
185
180
|
trailingSlash: this.options.trailingSlash,
|
|
186
|
-
caseSensitive: this.options.caseSensitive
|
|
181
|
+
caseSensitive: this.options.caseSensitive,
|
|
182
|
+
parseCache: this.parsePathnameCache
|
|
187
183
|
});
|
|
188
184
|
return resolvedPath;
|
|
189
185
|
};
|
|
@@ -199,6 +195,7 @@ class RouterCore {
|
|
|
199
195
|
}
|
|
200
196
|
return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
|
|
201
197
|
};
|
|
198
|
+
this.parsePathnameCache = lruCache.createLRUCache(1e3);
|
|
202
199
|
this.getMatchedRoutes = (pathname, routePathname) => {
|
|
203
200
|
return getMatchedRoutes({
|
|
204
201
|
pathname,
|
|
@@ -207,50 +204,71 @@ class RouterCore {
|
|
|
207
204
|
caseSensitive: this.options.caseSensitive,
|
|
208
205
|
routesByPath: this.routesByPath,
|
|
209
206
|
routesById: this.routesById,
|
|
210
|
-
flatRoutes: this.flatRoutes
|
|
207
|
+
flatRoutes: this.flatRoutes,
|
|
208
|
+
parseCache: this.parsePathnameCache
|
|
211
209
|
});
|
|
212
210
|
};
|
|
213
211
|
this.cancelMatch = (id) => {
|
|
214
212
|
const match = this.getMatch(id);
|
|
215
213
|
if (!match) return;
|
|
216
214
|
match.abortController.abort();
|
|
217
|
-
|
|
215
|
+
this.updateMatch(id, (prev) => {
|
|
216
|
+
clearTimeout(prev.pendingTimeout);
|
|
217
|
+
return {
|
|
218
|
+
...prev,
|
|
219
|
+
pendingTimeout: void 0
|
|
220
|
+
};
|
|
221
|
+
});
|
|
218
222
|
};
|
|
219
223
|
this.cancelMatches = () => {
|
|
220
|
-
|
|
221
|
-
(_a = this.state.pendingMatches) == null ? void 0 : _a.forEach((match) => {
|
|
224
|
+
this.state.pendingMatches?.forEach((match) => {
|
|
222
225
|
this.cancelMatch(match.id);
|
|
223
226
|
});
|
|
224
227
|
};
|
|
225
228
|
this.buildLocation = (opts) => {
|
|
226
229
|
const build = (dest = {}) => {
|
|
227
|
-
var _a;
|
|
228
230
|
const currentLocation = dest._fromLocation || this.latestLocation;
|
|
229
|
-
const
|
|
231
|
+
const allCurrentLocationMatches = this.matchRoutes(currentLocation, {
|
|
230
232
|
_buildLocation: true
|
|
231
233
|
});
|
|
232
|
-
const lastMatch = utils.last(
|
|
234
|
+
const lastMatch = utils.last(allCurrentLocationMatches);
|
|
233
235
|
let fromPath = lastMatch.fullPath;
|
|
236
|
+
const toPath = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
|
|
237
|
+
const routeIsChanging = !!dest.to && !comparePaths(dest.to.toString(), fromPath) && !comparePaths(toPath, fromPath);
|
|
234
238
|
if (dest.unsafeRelative === "path") {
|
|
235
239
|
fromPath = currentLocation.pathname;
|
|
236
|
-
} else if (
|
|
240
|
+
} else if (routeIsChanging && dest.from) {
|
|
237
241
|
fromPath = dest.from;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
242
|
+
if (process.env.NODE_ENV !== "production" && dest._isNavigate) {
|
|
243
|
+
const allFromMatches = this.getMatchedRoutes(
|
|
244
|
+
dest.from,
|
|
245
|
+
void 0
|
|
246
|
+
).matchedRoutes;
|
|
247
|
+
const matchedFrom = [...allCurrentLocationMatches].reverse().find((d) => {
|
|
248
|
+
return comparePaths(d.fullPath, fromPath);
|
|
249
|
+
});
|
|
250
|
+
const matchedCurrent = [...allFromMatches].reverse().find((d) => {
|
|
251
|
+
return comparePaths(d.fullPath, currentLocation.pathname);
|
|
252
|
+
});
|
|
253
|
+
if (!matchedFrom && !matchedCurrent) {
|
|
254
|
+
console.warn(`Could not find match for from: ${fromPath}`);
|
|
255
|
+
}
|
|
243
256
|
}
|
|
244
257
|
}
|
|
245
258
|
const fromSearch = lastMatch.search;
|
|
246
259
|
const fromParams = { ...lastMatch.params };
|
|
247
|
-
const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : fromPath;
|
|
248
|
-
let nextParams = (dest.params ?? true) === true ? fromParams : {
|
|
260
|
+
const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
|
|
261
|
+
let nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : {
|
|
249
262
|
...fromParams,
|
|
250
263
|
...utils.functionalUpdate(dest.params, fromParams)
|
|
251
264
|
};
|
|
265
|
+
const interpolatedNextTo = path.interpolatePath({
|
|
266
|
+
path: nextTo,
|
|
267
|
+
params: nextParams ?? {},
|
|
268
|
+
parseCache: this.parsePathnameCache
|
|
269
|
+
}).interpolatedPath;
|
|
252
270
|
const destRoutes = this.matchRoutes(
|
|
253
|
-
|
|
271
|
+
interpolatedNextTo,
|
|
254
272
|
{},
|
|
255
273
|
{
|
|
256
274
|
_buildLocation: true
|
|
@@ -258,21 +276,23 @@ class RouterCore {
|
|
|
258
276
|
).map((d) => this.looseRoutesById[d.routeId]);
|
|
259
277
|
if (Object.keys(nextParams).length > 0) {
|
|
260
278
|
destRoutes.map((route) => {
|
|
261
|
-
|
|
262
|
-
return ((_a2 = route.options.params) == null ? void 0 : _a2.stringify) ?? route.options.stringifyParams;
|
|
279
|
+
return route.options.params?.stringify ?? route.options.stringifyParams;
|
|
263
280
|
}).filter(Boolean).forEach((fn) => {
|
|
264
281
|
nextParams = { ...nextParams, ...fn(nextParams) };
|
|
265
282
|
});
|
|
266
283
|
}
|
|
267
284
|
const nextPathname = path.interpolatePath({
|
|
285
|
+
// Use the original template path for interpolation
|
|
286
|
+
// This preserves the original parameter syntax including optional parameters
|
|
268
287
|
path: nextTo,
|
|
269
288
|
params: nextParams ?? {},
|
|
270
289
|
leaveWildcards: false,
|
|
271
290
|
leaveParams: opts.leaveParams,
|
|
272
|
-
decodeCharMap: this.pathParamsDecodeCharMap
|
|
291
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
292
|
+
parseCache: this.parsePathnameCache
|
|
273
293
|
}).interpolatedPath;
|
|
274
294
|
let nextSearch = fromSearch;
|
|
275
|
-
if (opts._includeValidateSearch &&
|
|
295
|
+
if (opts._includeValidateSearch && this.options.search?.strict) {
|
|
276
296
|
let validatedSearch = {};
|
|
277
297
|
destRoutes.forEach((route) => {
|
|
278
298
|
try {
|
|
@@ -313,17 +333,21 @@ class RouterCore {
|
|
|
313
333
|
};
|
|
314
334
|
};
|
|
315
335
|
const buildWithMatches = (dest = {}, maskedDest) => {
|
|
316
|
-
var _a;
|
|
317
336
|
const next = build(dest);
|
|
318
337
|
let maskedNext = maskedDest ? build(maskedDest) : void 0;
|
|
319
338
|
if (!maskedNext) {
|
|
320
339
|
let params = {};
|
|
321
|
-
const foundMask =
|
|
322
|
-
const match = path.matchPathname(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
340
|
+
const foundMask = this.options.routeMasks?.find((d) => {
|
|
341
|
+
const match = path.matchPathname(
|
|
342
|
+
this.basepath,
|
|
343
|
+
next.pathname,
|
|
344
|
+
{
|
|
345
|
+
to: d.from,
|
|
346
|
+
caseSensitive: false,
|
|
347
|
+
fuzzy: false
|
|
348
|
+
},
|
|
349
|
+
this.parsePathnameCache
|
|
350
|
+
);
|
|
327
351
|
if (match) {
|
|
328
352
|
params = match;
|
|
329
353
|
return true;
|
|
@@ -362,6 +386,8 @@ class RouterCore {
|
|
|
362
386
|
const isSameState = () => {
|
|
363
387
|
const ignoredProps = [
|
|
364
388
|
"key",
|
|
389
|
+
// TODO: Remove in v2 - use __TSR_key instead
|
|
390
|
+
"__TSR_key",
|
|
365
391
|
"__TSR_index",
|
|
366
392
|
"__hashScrollIntoViewOptions"
|
|
367
393
|
];
|
|
@@ -377,7 +403,7 @@ class RouterCore {
|
|
|
377
403
|
const isSameUrl = this.latestLocation.href === next.href;
|
|
378
404
|
const previousCommitPromise = this.commitLocationPromise;
|
|
379
405
|
this.commitLocationPromise = utils.createControlledPromise(() => {
|
|
380
|
-
previousCommitPromise
|
|
406
|
+
previousCommitPromise?.resolve();
|
|
381
407
|
});
|
|
382
408
|
if (isSameUrl && isSameState()) {
|
|
383
409
|
this.load();
|
|
@@ -396,7 +422,9 @@ class RouterCore {
|
|
|
396
422
|
...nextHistory.state,
|
|
397
423
|
__tempKey: void 0,
|
|
398
424
|
__tempLocation: void 0,
|
|
425
|
+
__TSR_key: void 0,
|
|
399
426
|
key: void 0
|
|
427
|
+
// TODO: Remove in v2 - use __TSR_key instead
|
|
400
428
|
}
|
|
401
429
|
}
|
|
402
430
|
}
|
|
@@ -468,37 +496,58 @@ class RouterCore {
|
|
|
468
496
|
} else {
|
|
469
497
|
window.location.href = href;
|
|
470
498
|
}
|
|
471
|
-
return;
|
|
499
|
+
return Promise.resolve();
|
|
472
500
|
}
|
|
473
501
|
return this.buildAndCommitLocation({
|
|
474
502
|
...rest,
|
|
475
503
|
href,
|
|
476
|
-
to
|
|
504
|
+
to,
|
|
505
|
+
_isNavigate: true
|
|
477
506
|
});
|
|
478
507
|
};
|
|
479
508
|
this.beforeLoad = () => {
|
|
480
509
|
this.cancelMatches();
|
|
481
510
|
this.latestLocation = this.parseLocation(this.latestLocation);
|
|
511
|
+
if (this.isServer) {
|
|
512
|
+
const nextLocation = this.buildLocation({
|
|
513
|
+
to: this.latestLocation.pathname,
|
|
514
|
+
search: true,
|
|
515
|
+
params: true,
|
|
516
|
+
hash: true,
|
|
517
|
+
state: true,
|
|
518
|
+
_includeValidateSearch: true
|
|
519
|
+
});
|
|
520
|
+
const normalizeUrl = (url) => {
|
|
521
|
+
try {
|
|
522
|
+
return encodeURI(decodeURI(url));
|
|
523
|
+
} catch {
|
|
524
|
+
return url;
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
if (path.trimPath(normalizeUrl(this.latestLocation.href)) !== path.trimPath(normalizeUrl(nextLocation.href))) {
|
|
528
|
+
throw redirect.redirect({ href: nextLocation.href });
|
|
529
|
+
}
|
|
530
|
+
}
|
|
482
531
|
const pendingMatches = this.matchRoutes(this.latestLocation);
|
|
483
532
|
this.__store.setState((s) => ({
|
|
484
533
|
...s,
|
|
485
534
|
status: "pending",
|
|
535
|
+
statusCode: 200,
|
|
486
536
|
isLoading: true,
|
|
487
537
|
location: this.latestLocation,
|
|
488
538
|
pendingMatches,
|
|
489
539
|
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
490
|
-
cachedMatches: s.cachedMatches.filter(
|
|
491
|
-
|
|
492
|
-
|
|
540
|
+
cachedMatches: s.cachedMatches.filter(
|
|
541
|
+
(d) => !pendingMatches.some((e) => e.id === d.id)
|
|
542
|
+
)
|
|
493
543
|
}));
|
|
494
544
|
};
|
|
495
545
|
this.load = async (opts) => {
|
|
496
|
-
let
|
|
546
|
+
let redirect2;
|
|
497
547
|
let notFound$1;
|
|
498
548
|
let loadPromise;
|
|
499
549
|
loadPromise = new Promise((resolve) => {
|
|
500
550
|
this.startTransition(async () => {
|
|
501
|
-
var _a;
|
|
502
551
|
try {
|
|
503
552
|
this.beforeLoad();
|
|
504
553
|
const next = this.latestLocation;
|
|
@@ -520,7 +569,7 @@ class RouterCore {
|
|
|
520
569
|
})
|
|
521
570
|
});
|
|
522
571
|
await this.loadMatches({
|
|
523
|
-
sync: opts
|
|
572
|
+
sync: opts?.sync,
|
|
524
573
|
matches: this.state.pendingMatches,
|
|
525
574
|
location: next,
|
|
526
575
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
@@ -534,13 +583,13 @@ class RouterCore {
|
|
|
534
583
|
const previousMatches = s.matches;
|
|
535
584
|
const newMatches = s.pendingMatches || s.matches;
|
|
536
585
|
exitingMatches = previousMatches.filter(
|
|
537
|
-
(match) => !newMatches.
|
|
586
|
+
(match) => !newMatches.some((d) => d.id === match.id)
|
|
538
587
|
);
|
|
539
588
|
enteringMatches = newMatches.filter(
|
|
540
|
-
(match) => !previousMatches.
|
|
589
|
+
(match) => !previousMatches.some((d) => d.id === match.id)
|
|
541
590
|
);
|
|
542
591
|
stayingMatches = previousMatches.filter(
|
|
543
|
-
(match) => newMatches.
|
|
592
|
+
(match) => newMatches.some((d) => d.id === match.id)
|
|
544
593
|
);
|
|
545
594
|
return {
|
|
546
595
|
...s,
|
|
@@ -562,8 +611,7 @@ class RouterCore {
|
|
|
562
611
|
[stayingMatches, "onStay"]
|
|
563
612
|
].forEach(([matches, hook]) => {
|
|
564
613
|
matches.forEach((match) => {
|
|
565
|
-
|
|
566
|
-
(_b = (_a2 = this.looseRoutesById[match.routeId].options)[hook]) == null ? void 0 : _b.call(_a2, match);
|
|
614
|
+
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
567
615
|
});
|
|
568
616
|
});
|
|
569
617
|
});
|
|
@@ -571,10 +619,10 @@ class RouterCore {
|
|
|
571
619
|
});
|
|
572
620
|
} catch (err) {
|
|
573
621
|
if (redirect.isRedirect(err)) {
|
|
574
|
-
|
|
622
|
+
redirect2 = err;
|
|
575
623
|
if (!this.isServer) {
|
|
576
624
|
this.navigate({
|
|
577
|
-
...
|
|
625
|
+
...redirect2.options,
|
|
578
626
|
replace: true,
|
|
579
627
|
ignoreBlocker: true
|
|
580
628
|
});
|
|
@@ -584,12 +632,12 @@ class RouterCore {
|
|
|
584
632
|
}
|
|
585
633
|
this.__store.setState((s) => ({
|
|
586
634
|
...s,
|
|
587
|
-
statusCode:
|
|
588
|
-
redirect:
|
|
635
|
+
statusCode: redirect2 ? redirect2.status : notFound$1 ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
|
|
636
|
+
redirect: redirect2
|
|
589
637
|
}));
|
|
590
638
|
}
|
|
591
639
|
if (this.latestLoadPromise === loadPromise) {
|
|
592
|
-
|
|
640
|
+
this.commitLocationPromise?.resolve();
|
|
593
641
|
this.latestLoadPromise = void 0;
|
|
594
642
|
this.commitLocationPromise = void 0;
|
|
595
643
|
}
|
|
@@ -635,31 +683,17 @@ class RouterCore {
|
|
|
635
683
|
}
|
|
636
684
|
};
|
|
637
685
|
this.updateMatch = (id, updater) => {
|
|
638
|
-
|
|
639
|
-
let updated;
|
|
640
|
-
const isPending = (_a = this.state.pendingMatches) == null ? void 0 : _a.find((d) => d.id === id);
|
|
641
|
-
const isMatched = this.state.matches.find((d) => d.id === id);
|
|
642
|
-
const isCached = this.state.cachedMatches.find((d) => d.id === id);
|
|
643
|
-
const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : isCached ? "cachedMatches" : "";
|
|
686
|
+
const matchesKey = this.state.pendingMatches?.some((d) => d.id === id) ? "pendingMatches" : this.state.matches.some((d) => d.id === id) ? "matches" : this.state.cachedMatches.some((d) => d.id === id) ? "cachedMatches" : "";
|
|
644
687
|
if (matchesKey) {
|
|
645
|
-
this.__store.setState((s) => {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
[matchesKey]: (_a2 = s[matchesKey]) == null ? void 0 : _a2.map(
|
|
650
|
-
(d) => d.id === id ? updated = updater(d) : d
|
|
651
|
-
)
|
|
652
|
-
};
|
|
653
|
-
});
|
|
688
|
+
this.__store.setState((s) => ({
|
|
689
|
+
...s,
|
|
690
|
+
[matchesKey]: s[matchesKey]?.map((d) => d.id === id ? updater(d) : d)
|
|
691
|
+
}));
|
|
654
692
|
}
|
|
655
|
-
return updated;
|
|
656
693
|
};
|
|
657
694
|
this.getMatch = (matchId) => {
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
...this.state.pendingMatches ?? [],
|
|
661
|
-
...this.state.matches
|
|
662
|
-
].find((d) => d.id === matchId);
|
|
695
|
+
const findFn = (d) => d.id === matchId;
|
|
696
|
+
return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
|
|
663
697
|
};
|
|
664
698
|
this.loadMatches = async ({
|
|
665
699
|
location,
|
|
@@ -674,14 +708,16 @@ class RouterCore {
|
|
|
674
708
|
const triggerOnReady = async () => {
|
|
675
709
|
if (!rendered) {
|
|
676
710
|
rendered = true;
|
|
677
|
-
await
|
|
711
|
+
await onReady?.();
|
|
678
712
|
}
|
|
679
713
|
};
|
|
680
714
|
const resolvePreload = (matchId) => {
|
|
681
|
-
return !!(allPreload && !this.state.matches.
|
|
715
|
+
return !!(allPreload && !this.state.matches.some((d) => d.id === matchId));
|
|
682
716
|
};
|
|
717
|
+
if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
|
|
718
|
+
triggerOnReady();
|
|
719
|
+
}
|
|
683
720
|
const handleRedirectAndNotFound = (match, err) => {
|
|
684
|
-
var _a, _b, _c, _d;
|
|
685
721
|
if (redirect.isRedirect(err) || notFound.isNotFound(err)) {
|
|
686
722
|
if (redirect.isRedirect(err)) {
|
|
687
723
|
if (err.redirectHandled) {
|
|
@@ -690,6 +726,8 @@ class RouterCore {
|
|
|
690
726
|
}
|
|
691
727
|
}
|
|
692
728
|
}
|
|
729
|
+
match.beforeLoadPromise?.resolve();
|
|
730
|
+
match.loaderPromise?.resolve();
|
|
693
731
|
updateMatch(match.id, (prev) => ({
|
|
694
732
|
...prev,
|
|
695
733
|
status: redirect.isRedirect(err) ? "redirected" : notFound.isNotFound(err) ? "notFound" : "error",
|
|
@@ -701,9 +739,7 @@ class RouterCore {
|
|
|
701
739
|
if (!err.routeId) {
|
|
702
740
|
err.routeId = match.routeId;
|
|
703
741
|
}
|
|
704
|
-
|
|
705
|
-
(_b = match.loaderPromise) == null ? void 0 : _b.resolve();
|
|
706
|
-
(_c = match.loadPromise) == null ? void 0 : _c.resolve();
|
|
742
|
+
match.loadPromise?.resolve();
|
|
707
743
|
if (redirect.isRedirect(err)) {
|
|
708
744
|
rendered = true;
|
|
709
745
|
err.options._fromLocation = location;
|
|
@@ -714,22 +750,28 @@ class RouterCore {
|
|
|
714
750
|
this._handleNotFound(matches, err, {
|
|
715
751
|
updateMatch
|
|
716
752
|
});
|
|
717
|
-
(_d = this.serverSsr) == null ? void 0 : _d.onMatchSettled({
|
|
718
|
-
router: this,
|
|
719
|
-
match: this.getMatch(match.id)
|
|
720
|
-
});
|
|
721
753
|
throw err;
|
|
722
754
|
}
|
|
723
755
|
}
|
|
724
756
|
};
|
|
757
|
+
const shouldSkipLoader = (matchId) => {
|
|
758
|
+
const match = this.getMatch(matchId);
|
|
759
|
+
if (!this.isServer && match._dehydrated) {
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
if (this.isServer) {
|
|
763
|
+
if (match.ssr === false) {
|
|
764
|
+
return true;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return false;
|
|
768
|
+
};
|
|
725
769
|
try {
|
|
726
770
|
await new Promise((resolveAll, rejectAll) => {
|
|
727
771
|
;
|
|
728
772
|
(async () => {
|
|
729
|
-
var _a, _b, _c, _d;
|
|
730
773
|
try {
|
|
731
774
|
const handleSerialError = (index, err, routerCode) => {
|
|
732
|
-
var _a2, _b2;
|
|
733
775
|
const { id: matchId, routeId } = matches[index];
|
|
734
776
|
const route = this.looseRoutesById[routeId];
|
|
735
777
|
if (err instanceof Promise) {
|
|
@@ -739,15 +781,14 @@ class RouterCore {
|
|
|
739
781
|
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
740
782
|
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
741
783
|
try {
|
|
742
|
-
|
|
784
|
+
route.options.onError?.(err);
|
|
743
785
|
} catch (errorHandlerErr) {
|
|
744
786
|
err = errorHandlerErr;
|
|
745
787
|
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
746
788
|
}
|
|
747
789
|
updateMatch(matchId, (prev) => {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
(_b3 = prev.loadPromise) == null ? void 0 : _b3.resolve();
|
|
790
|
+
prev.beforeLoadPromise?.resolve();
|
|
791
|
+
prev.loadPromise?.resolve();
|
|
751
792
|
return {
|
|
752
793
|
...prev,
|
|
753
794
|
error: err,
|
|
@@ -761,26 +802,94 @@ class RouterCore {
|
|
|
761
802
|
};
|
|
762
803
|
for (const [index, { id: matchId, routeId }] of matches.entries()) {
|
|
763
804
|
const existingMatch = this.getMatch(matchId);
|
|
764
|
-
const parentMatchId =
|
|
805
|
+
const parentMatchId = matches[index - 1]?.id;
|
|
806
|
+
const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
|
|
765
807
|
const route = this.looseRoutesById[routeId];
|
|
766
808
|
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
767
|
-
|
|
809
|
+
if (this.isServer) {
|
|
810
|
+
let ssr;
|
|
811
|
+
if (this.isShell()) {
|
|
812
|
+
ssr = matchId === root.rootRouteId;
|
|
813
|
+
} else {
|
|
814
|
+
const defaultSsr = this.options.defaultSsr ?? true;
|
|
815
|
+
if (parentMatch?.ssr === false) {
|
|
816
|
+
ssr = false;
|
|
817
|
+
} else {
|
|
818
|
+
let tempSsr;
|
|
819
|
+
if (route.options.ssr === void 0) {
|
|
820
|
+
tempSsr = defaultSsr;
|
|
821
|
+
} else if (typeof route.options.ssr === "function") {
|
|
822
|
+
let makeMaybe = function(value, error) {
|
|
823
|
+
if (error) {
|
|
824
|
+
return { status: "error", error };
|
|
825
|
+
}
|
|
826
|
+
return { status: "success", value };
|
|
827
|
+
};
|
|
828
|
+
const { search, params } = this.getMatch(matchId);
|
|
829
|
+
const ssrFnContext = {
|
|
830
|
+
search: makeMaybe(search, existingMatch.searchError),
|
|
831
|
+
params: makeMaybe(params, existingMatch.paramsError),
|
|
832
|
+
location,
|
|
833
|
+
matches: matches.map((match) => ({
|
|
834
|
+
index: match.index,
|
|
835
|
+
pathname: match.pathname,
|
|
836
|
+
fullPath: match.fullPath,
|
|
837
|
+
staticData: match.staticData,
|
|
838
|
+
id: match.id,
|
|
839
|
+
routeId: match.routeId,
|
|
840
|
+
search: makeMaybe(match.search, match.searchError),
|
|
841
|
+
params: makeMaybe(match.params, match.paramsError),
|
|
842
|
+
ssr: match.ssr
|
|
843
|
+
}))
|
|
844
|
+
};
|
|
845
|
+
tempSsr = await route.options.ssr(ssrFnContext) ?? defaultSsr;
|
|
846
|
+
} else {
|
|
847
|
+
tempSsr = route.options.ssr;
|
|
848
|
+
}
|
|
849
|
+
if (tempSsr === true && parentMatch?.ssr === "data-only") {
|
|
850
|
+
ssr = "data-only";
|
|
851
|
+
} else {
|
|
852
|
+
ssr = tempSsr;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
updateMatch(matchId, (prev) => ({
|
|
857
|
+
...prev,
|
|
858
|
+
ssr
|
|
859
|
+
}));
|
|
860
|
+
}
|
|
861
|
+
if (shouldSkipLoader(matchId)) {
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad || routeNeedsPreload(route)) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? this.options?.defaultPendingComponent));
|
|
768
865
|
let executeBeforeLoad = true;
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
existingMatch.beforeLoadPromise || existingMatch.loaderPromise
|
|
773
|
-
) {
|
|
774
|
-
if (shouldPending) {
|
|
775
|
-
setTimeout(() => {
|
|
866
|
+
const setupPendingTimeout = () => {
|
|
867
|
+
if (shouldPending && this.getMatch(matchId).pendingTimeout === void 0) {
|
|
868
|
+
const pendingTimeout = setTimeout(() => {
|
|
776
869
|
try {
|
|
777
870
|
triggerOnReady();
|
|
778
871
|
} catch {
|
|
779
872
|
}
|
|
780
873
|
}, pendingMs);
|
|
874
|
+
updateMatch(matchId, (prev) => ({
|
|
875
|
+
...prev,
|
|
876
|
+
pendingTimeout
|
|
877
|
+
}));
|
|
781
878
|
}
|
|
879
|
+
};
|
|
880
|
+
if (
|
|
881
|
+
// If we are in the middle of a load, either of these will be present
|
|
882
|
+
// (not to be confused with `loadPromise`, which is always defined)
|
|
883
|
+
existingMatch.beforeLoadPromise || existingMatch.loaderPromise
|
|
884
|
+
) {
|
|
885
|
+
setupPendingTimeout();
|
|
782
886
|
await existingMatch.beforeLoadPromise;
|
|
783
|
-
|
|
887
|
+
const match = this.getMatch(matchId);
|
|
888
|
+
if (match.status === "error") {
|
|
889
|
+
executeBeforeLoad = true;
|
|
890
|
+
} else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
|
|
891
|
+
handleRedirectAndNotFound(match, match.error);
|
|
892
|
+
}
|
|
784
893
|
}
|
|
785
894
|
if (executeBeforeLoad) {
|
|
786
895
|
try {
|
|
@@ -789,21 +898,11 @@ class RouterCore {
|
|
|
789
898
|
return {
|
|
790
899
|
...prev,
|
|
791
900
|
loadPromise: utils.createControlledPromise(() => {
|
|
792
|
-
prevLoadPromise
|
|
901
|
+
prevLoadPromise?.resolve();
|
|
793
902
|
}),
|
|
794
903
|
beforeLoadPromise: utils.createControlledPromise()
|
|
795
904
|
};
|
|
796
905
|
});
|
|
797
|
-
const abortController = new AbortController();
|
|
798
|
-
let pendingTimeout;
|
|
799
|
-
if (shouldPending) {
|
|
800
|
-
pendingTimeout = setTimeout(() => {
|
|
801
|
-
try {
|
|
802
|
-
triggerOnReady();
|
|
803
|
-
} catch {
|
|
804
|
-
}
|
|
805
|
-
}, pendingMs);
|
|
806
|
-
}
|
|
807
906
|
const { paramsError, searchError } = this.getMatch(matchId);
|
|
808
907
|
if (paramsError) {
|
|
809
908
|
handleSerialError(index, paramsError, "PARSE_PARAMS");
|
|
@@ -811,15 +910,16 @@ class RouterCore {
|
|
|
811
910
|
if (searchError) {
|
|
812
911
|
handleSerialError(index, searchError, "VALIDATE_SEARCH");
|
|
813
912
|
}
|
|
814
|
-
|
|
913
|
+
setupPendingTimeout();
|
|
914
|
+
const abortController = new AbortController();
|
|
915
|
+
const parentMatchContext = parentMatch?.context ?? this.options.context ?? {};
|
|
815
916
|
updateMatch(matchId, (prev) => ({
|
|
816
917
|
...prev,
|
|
817
918
|
isFetching: "beforeLoad",
|
|
818
919
|
fetchCount: prev.fetchCount + 1,
|
|
819
920
|
abortController,
|
|
820
|
-
pendingTimeout,
|
|
821
921
|
context: {
|
|
822
|
-
...
|
|
922
|
+
...parentMatchContext,
|
|
823
923
|
...prev.__routeContext
|
|
824
924
|
}
|
|
825
925
|
}));
|
|
@@ -837,7 +937,7 @@ class RouterCore {
|
|
|
837
937
|
cause: preload ? "preload" : cause,
|
|
838
938
|
matches
|
|
839
939
|
};
|
|
840
|
-
const beforeLoadContext = await
|
|
940
|
+
const beforeLoadContext = await route.options.beforeLoad?.(beforeLoadFnContext);
|
|
841
941
|
if (redirect.isRedirect(beforeLoadContext) || notFound.isNotFound(beforeLoadContext)) {
|
|
842
942
|
handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
|
|
843
943
|
}
|
|
@@ -846,7 +946,7 @@ class RouterCore {
|
|
|
846
946
|
...prev,
|
|
847
947
|
__beforeLoadContext: beforeLoadContext,
|
|
848
948
|
context: {
|
|
849
|
-
...
|
|
949
|
+
...parentMatchContext,
|
|
850
950
|
...prev.__routeContext,
|
|
851
951
|
...beforeLoadContext
|
|
852
952
|
},
|
|
@@ -857,8 +957,7 @@ class RouterCore {
|
|
|
857
957
|
handleSerialError(index, err, "BEFORE_LOAD");
|
|
858
958
|
}
|
|
859
959
|
updateMatch(matchId, (prev) => {
|
|
860
|
-
|
|
861
|
-
(_a2 = prev.beforeLoadPromise) == null ? void 0 : _a2.resolve();
|
|
960
|
+
prev.beforeLoadPromise?.resolve();
|
|
862
961
|
return {
|
|
863
962
|
...prev,
|
|
864
963
|
beforeLoadPromise: void 0,
|
|
@@ -872,18 +971,63 @@ class RouterCore {
|
|
|
872
971
|
validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
|
|
873
972
|
matchPromises.push(
|
|
874
973
|
(async () => {
|
|
875
|
-
const { loaderPromise: prevLoaderPromise } = this.getMatch(matchId);
|
|
876
974
|
let loaderShouldRunAsync = false;
|
|
877
975
|
let loaderIsRunningAsync = false;
|
|
878
|
-
|
|
879
|
-
|
|
976
|
+
const route = this.looseRoutesById[routeId];
|
|
977
|
+
const executeHead = async () => {
|
|
978
|
+
const match = this.getMatch(matchId);
|
|
979
|
+
if (!match) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const assetContext = {
|
|
983
|
+
matches,
|
|
984
|
+
match,
|
|
985
|
+
params: match.params,
|
|
986
|
+
loaderData: match.loaderData
|
|
987
|
+
};
|
|
988
|
+
const headFnContent = await route.options.head?.(assetContext);
|
|
989
|
+
const meta = headFnContent?.meta;
|
|
990
|
+
const links = headFnContent?.links;
|
|
991
|
+
const headScripts = headFnContent?.scripts;
|
|
992
|
+
const styles = headFnContent?.styles;
|
|
993
|
+
const scripts = await route.options.scripts?.(assetContext);
|
|
994
|
+
const headers = await route.options.headers?.(assetContext);
|
|
995
|
+
return {
|
|
996
|
+
meta,
|
|
997
|
+
links,
|
|
998
|
+
headScripts,
|
|
999
|
+
headers,
|
|
1000
|
+
scripts,
|
|
1001
|
+
styles
|
|
1002
|
+
};
|
|
1003
|
+
};
|
|
1004
|
+
const potentialPendingMinPromise = async () => {
|
|
1005
|
+
const latestMatch = this.getMatch(matchId);
|
|
1006
|
+
if (latestMatch.minPendingPromise) {
|
|
1007
|
+
await latestMatch.minPendingPromise;
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
const prevMatch = this.getMatch(matchId);
|
|
1011
|
+
if (shouldSkipLoader(matchId)) {
|
|
1012
|
+
if (this.isServer) {
|
|
1013
|
+
const head = await executeHead();
|
|
1014
|
+
updateMatch(matchId, (prev) => ({
|
|
1015
|
+
...prev,
|
|
1016
|
+
...head
|
|
1017
|
+
}));
|
|
1018
|
+
return this.getMatch(matchId);
|
|
1019
|
+
}
|
|
1020
|
+
} else if (prevMatch.loaderPromise) {
|
|
1021
|
+
if (prevMatch.status === "success" && !sync && !prevMatch.preload) {
|
|
1022
|
+
return this.getMatch(matchId);
|
|
1023
|
+
}
|
|
1024
|
+
await prevMatch.loaderPromise;
|
|
880
1025
|
const match = this.getMatch(matchId);
|
|
881
1026
|
if (match.error) {
|
|
882
1027
|
handleRedirectAndNotFound(match, match.error);
|
|
883
1028
|
}
|
|
884
1029
|
} else {
|
|
885
1030
|
const parentMatchPromise = matchPromises[index - 1];
|
|
886
|
-
const route = this.looseRoutesById[routeId];
|
|
887
1031
|
const getLoaderContext = () => {
|
|
888
1032
|
const {
|
|
889
1033
|
params,
|
|
@@ -914,49 +1058,29 @@ class RouterCore {
|
|
|
914
1058
|
updateMatch(matchId, (prev) => ({
|
|
915
1059
|
...prev,
|
|
916
1060
|
loaderPromise: utils.createControlledPromise(),
|
|
917
|
-
preload: !!preload && !this.state.matches.
|
|
1061
|
+
preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
|
|
918
1062
|
}));
|
|
919
|
-
const executeHead = async () => {
|
|
920
|
-
var _a2, _b2, _c2, _d2, _e, _f;
|
|
921
|
-
const match = this.getMatch(matchId);
|
|
922
|
-
if (!match) {
|
|
923
|
-
return;
|
|
924
|
-
}
|
|
925
|
-
const assetContext = {
|
|
926
|
-
matches,
|
|
927
|
-
match,
|
|
928
|
-
params: match.params,
|
|
929
|
-
loaderData: match.loaderData
|
|
930
|
-
};
|
|
931
|
-
const headFnContent = await ((_b2 = (_a2 = route.options).head) == null ? void 0 : _b2.call(_a2, assetContext));
|
|
932
|
-
const meta = headFnContent == null ? void 0 : headFnContent.meta;
|
|
933
|
-
const links = headFnContent == null ? void 0 : headFnContent.links;
|
|
934
|
-
const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
|
|
935
|
-
const scripts = await ((_d2 = (_c2 = route.options).scripts) == null ? void 0 : _d2.call(_c2, assetContext));
|
|
936
|
-
const headers = await ((_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, assetContext));
|
|
937
|
-
return { meta, links, headScripts, headers, scripts };
|
|
938
|
-
};
|
|
939
1063
|
const runLoader = async () => {
|
|
940
|
-
var _a2, _b2, _c2, _d2, _e;
|
|
941
1064
|
try {
|
|
942
|
-
const potentialPendingMinPromise = async () => {
|
|
943
|
-
const latestMatch = this.getMatch(matchId);
|
|
944
|
-
if (latestMatch.minPendingPromise) {
|
|
945
|
-
await latestMatch.minPendingPromise;
|
|
946
|
-
}
|
|
947
|
-
};
|
|
948
1065
|
try {
|
|
949
|
-
this.
|
|
1066
|
+
if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
|
|
1067
|
+
this.loadRouteChunk(route);
|
|
1068
|
+
}
|
|
950
1069
|
updateMatch(matchId, (prev) => ({
|
|
951
1070
|
...prev,
|
|
952
1071
|
isFetching: "loader"
|
|
953
1072
|
}));
|
|
954
|
-
const loaderData = await
|
|
1073
|
+
const loaderData = await route.options.loader?.(getLoaderContext());
|
|
955
1074
|
handleRedirectAndNotFound(
|
|
956
1075
|
this.getMatch(matchId),
|
|
957
1076
|
loaderData
|
|
958
1077
|
);
|
|
1078
|
+
updateMatch(matchId, (prev) => ({
|
|
1079
|
+
...prev,
|
|
1080
|
+
loaderData
|
|
1081
|
+
}));
|
|
959
1082
|
await route._lazyPromise;
|
|
1083
|
+
const head = await executeHead();
|
|
960
1084
|
await potentialPendingMinPromise();
|
|
961
1085
|
await route._componentsPromise;
|
|
962
1086
|
updateMatch(matchId, (prev) => ({
|
|
@@ -965,11 +1089,6 @@ class RouterCore {
|
|
|
965
1089
|
status: "success",
|
|
966
1090
|
isFetching: false,
|
|
967
1091
|
updatedAt: Date.now(),
|
|
968
|
-
loaderData
|
|
969
|
-
}));
|
|
970
|
-
const head = await executeHead();
|
|
971
|
-
updateMatch(matchId, (prev) => ({
|
|
972
|
-
...prev,
|
|
973
1092
|
...head
|
|
974
1093
|
}));
|
|
975
1094
|
} catch (e) {
|
|
@@ -977,7 +1096,7 @@ class RouterCore {
|
|
|
977
1096
|
await potentialPendingMinPromise();
|
|
978
1097
|
handleRedirectAndNotFound(this.getMatch(matchId), e);
|
|
979
1098
|
try {
|
|
980
|
-
|
|
1099
|
+
route.options.onError?.(e);
|
|
981
1100
|
} catch (onErrorError) {
|
|
982
1101
|
error = onErrorError;
|
|
983
1102
|
handleRedirectAndNotFound(
|
|
@@ -994,10 +1113,6 @@ class RouterCore {
|
|
|
994
1113
|
...head
|
|
995
1114
|
}));
|
|
996
1115
|
}
|
|
997
|
-
(_e = this.serverSsr) == null ? void 0 : _e.onMatchSettled({
|
|
998
|
-
router: this,
|
|
999
|
-
match: this.getMatch(matchId)
|
|
1000
|
-
});
|
|
1001
1116
|
} catch (err) {
|
|
1002
1117
|
const head = await executeHead();
|
|
1003
1118
|
updateMatch(matchId, (prev) => ({
|
|
@@ -1017,8 +1132,8 @@ class RouterCore {
|
|
|
1017
1132
|
try {
|
|
1018
1133
|
await runLoader();
|
|
1019
1134
|
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1020
|
-
loaderPromise
|
|
1021
|
-
loadPromise
|
|
1135
|
+
loaderPromise?.resolve();
|
|
1136
|
+
loadPromise?.resolve();
|
|
1022
1137
|
updateMatch(matchId, (prev) => ({
|
|
1023
1138
|
...prev,
|
|
1024
1139
|
loaderPromise: void 0
|
|
@@ -1041,15 +1156,20 @@ class RouterCore {
|
|
|
1041
1156
|
}
|
|
1042
1157
|
if (!loaderIsRunningAsync) {
|
|
1043
1158
|
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1044
|
-
loaderPromise
|
|
1045
|
-
loadPromise
|
|
1159
|
+
loaderPromise?.resolve();
|
|
1160
|
+
loadPromise?.resolve();
|
|
1046
1161
|
}
|
|
1047
|
-
updateMatch(matchId, (prev) =>
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1162
|
+
updateMatch(matchId, (prev) => {
|
|
1163
|
+
clearTimeout(prev.pendingTimeout);
|
|
1164
|
+
return {
|
|
1165
|
+
...prev,
|
|
1166
|
+
isFetching: loaderIsRunningAsync ? prev.isFetching : false,
|
|
1167
|
+
loaderPromise: loaderIsRunningAsync ? prev.loaderPromise : void 0,
|
|
1168
|
+
invalid: false,
|
|
1169
|
+
pendingTimeout: void 0,
|
|
1170
|
+
_dehydrated: void 0
|
|
1171
|
+
};
|
|
1172
|
+
});
|
|
1053
1173
|
return this.getMatch(matchId);
|
|
1054
1174
|
})()
|
|
1055
1175
|
);
|
|
@@ -1074,27 +1194,23 @@ class RouterCore {
|
|
|
1074
1194
|
};
|
|
1075
1195
|
this.invalidate = (opts) => {
|
|
1076
1196
|
const invalidate = (d) => {
|
|
1077
|
-
|
|
1078
|
-
if (((_a = opts == null ? void 0 : opts.filter) == null ? void 0 : _a.call(opts, d)) ?? true) {
|
|
1197
|
+
if (opts?.filter?.(d) ?? true) {
|
|
1079
1198
|
return {
|
|
1080
1199
|
...d,
|
|
1081
1200
|
invalid: true,
|
|
1082
|
-
...d.status === "error" ? { status: "pending", error: void 0 } : {}
|
|
1201
|
+
...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : {}
|
|
1083
1202
|
};
|
|
1084
1203
|
}
|
|
1085
1204
|
return d;
|
|
1086
1205
|
};
|
|
1087
|
-
this.__store.setState((s) => {
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
pendingMatches: (_a = s.pendingMatches) == null ? void 0 : _a.map(invalidate)
|
|
1094
|
-
};
|
|
1095
|
-
});
|
|
1206
|
+
this.__store.setState((s) => ({
|
|
1207
|
+
...s,
|
|
1208
|
+
matches: s.matches.map(invalidate),
|
|
1209
|
+
cachedMatches: s.cachedMatches.map(invalidate),
|
|
1210
|
+
pendingMatches: s.pendingMatches?.map(invalidate)
|
|
1211
|
+
}));
|
|
1096
1212
|
this.shouldViewTransition = false;
|
|
1097
|
-
return this.load({ sync: opts
|
|
1213
|
+
return this.load({ sync: opts?.sync });
|
|
1098
1214
|
};
|
|
1099
1215
|
this.resolveRedirect = (redirect2) => {
|
|
1100
1216
|
if (!redirect2.options.href) {
|
|
@@ -1107,7 +1223,7 @@ class RouterCore {
|
|
|
1107
1223
|
return redirect2;
|
|
1108
1224
|
};
|
|
1109
1225
|
this.clearCache = (opts) => {
|
|
1110
|
-
const filter = opts
|
|
1226
|
+
const filter = opts?.filter;
|
|
1111
1227
|
if (filter !== void 0) {
|
|
1112
1228
|
this.__store.setState((s) => {
|
|
1113
1229
|
return {
|
|
@@ -1133,7 +1249,10 @@ class RouterCore {
|
|
|
1133
1249
|
return true;
|
|
1134
1250
|
}
|
|
1135
1251
|
const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 5 * 60 * 1e3;
|
|
1136
|
-
|
|
1252
|
+
const isError = d.status === "error";
|
|
1253
|
+
if (isError) return true;
|
|
1254
|
+
const gcEligible = Date.now() - d.updatedAt >= gcTime;
|
|
1255
|
+
return gcEligible;
|
|
1137
1256
|
};
|
|
1138
1257
|
this.clearCache({ filter });
|
|
1139
1258
|
};
|
|
@@ -1153,7 +1272,7 @@ class RouterCore {
|
|
|
1153
1272
|
() => Promise.all(
|
|
1154
1273
|
componentTypes.map(async (type) => {
|
|
1155
1274
|
const component = route.options[type];
|
|
1156
|
-
if (component
|
|
1275
|
+
if (component?.preload) {
|
|
1157
1276
|
await component.preload();
|
|
1158
1277
|
}
|
|
1159
1278
|
})
|
|
@@ -1229,15 +1348,20 @@ class RouterCore {
|
|
|
1229
1348
|
leaveParams: true
|
|
1230
1349
|
};
|
|
1231
1350
|
const next = this.buildLocation(matchLocation);
|
|
1232
|
-
if (
|
|
1351
|
+
if (opts?.pending && this.state.status !== "pending") {
|
|
1233
1352
|
return false;
|
|
1234
1353
|
}
|
|
1235
|
-
const pending =
|
|
1354
|
+
const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
|
|
1236
1355
|
const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
|
|
1237
|
-
const match = path.matchPathname(
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1356
|
+
const match = path.matchPathname(
|
|
1357
|
+
this.basepath,
|
|
1358
|
+
baseLocation.pathname,
|
|
1359
|
+
{
|
|
1360
|
+
...opts,
|
|
1361
|
+
to: next.pathname
|
|
1362
|
+
},
|
|
1363
|
+
this.parsePathnameCache
|
|
1364
|
+
);
|
|
1241
1365
|
if (!match) {
|
|
1242
1366
|
return false;
|
|
1243
1367
|
}
|
|
@@ -1246,7 +1370,7 @@ class RouterCore {
|
|
|
1246
1370
|
return false;
|
|
1247
1371
|
}
|
|
1248
1372
|
}
|
|
1249
|
-
if (match && (
|
|
1373
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
1250
1374
|
return utils.deepEqual(baseLocation.search, next.search, { partial: true }) ? match : false;
|
|
1251
1375
|
}
|
|
1252
1376
|
return match;
|
|
@@ -1254,13 +1378,12 @@ class RouterCore {
|
|
|
1254
1378
|
this._handleNotFound = (matches, err, {
|
|
1255
1379
|
updateMatch = this.updateMatch
|
|
1256
1380
|
} = {}) => {
|
|
1257
|
-
var _a;
|
|
1258
1381
|
const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
|
|
1259
1382
|
const matchesByRouteId = {};
|
|
1260
1383
|
for (const match of matches) {
|
|
1261
1384
|
matchesByRouteId[match.routeId] = match;
|
|
1262
1385
|
}
|
|
1263
|
-
if (!routeCursor.options.notFoundComponent &&
|
|
1386
|
+
if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
|
|
1264
1387
|
routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
|
|
1265
1388
|
}
|
|
1266
1389
|
invariant(
|
|
@@ -1302,9 +1425,15 @@ class RouterCore {
|
|
|
1302
1425
|
parseSearch: options.parseSearch ?? searchParams.defaultParseSearch
|
|
1303
1426
|
});
|
|
1304
1427
|
if (typeof document !== "undefined") {
|
|
1305
|
-
|
|
1428
|
+
self.__TSR_ROUTER__ = this;
|
|
1306
1429
|
}
|
|
1307
1430
|
}
|
|
1431
|
+
isShell() {
|
|
1432
|
+
return !!this.options.isShell;
|
|
1433
|
+
}
|
|
1434
|
+
isPrerendering() {
|
|
1435
|
+
return !!this.options.isPrerendering;
|
|
1436
|
+
}
|
|
1308
1437
|
get state() {
|
|
1309
1438
|
return this.__store.state;
|
|
1310
1439
|
}
|
|
@@ -1312,10 +1441,9 @@ class RouterCore {
|
|
|
1312
1441
|
return this.routesById;
|
|
1313
1442
|
}
|
|
1314
1443
|
matchRoutesInternal(next, opts) {
|
|
1315
|
-
var _a;
|
|
1316
1444
|
const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
1317
1445
|
next.pathname,
|
|
1318
|
-
|
|
1446
|
+
opts?.dest?.to
|
|
1319
1447
|
);
|
|
1320
1448
|
let isGlobalNotFound = false;
|
|
1321
1449
|
if (
|
|
@@ -1346,9 +1474,8 @@ class RouterCore {
|
|
|
1346
1474
|
return root.rootRouteId;
|
|
1347
1475
|
})();
|
|
1348
1476
|
const parseErrors = matchedRoutes.map((route) => {
|
|
1349
|
-
var _a2;
|
|
1350
1477
|
let parsedParamsError;
|
|
1351
|
-
const parseParams =
|
|
1478
|
+
const parseParams = route.options.params?.parse ?? route.options.parseParams;
|
|
1352
1479
|
if (parseParams) {
|
|
1353
1480
|
try {
|
|
1354
1481
|
const parsedParams = parseParams(routeParams);
|
|
@@ -1357,7 +1484,7 @@ class RouterCore {
|
|
|
1357
1484
|
parsedParamsError = new PathParamError(err.message, {
|
|
1358
1485
|
cause: err
|
|
1359
1486
|
});
|
|
1360
|
-
if (opts
|
|
1487
|
+
if (opts?.throwOnError) {
|
|
1361
1488
|
throw parsedParamsError;
|
|
1362
1489
|
}
|
|
1363
1490
|
return parsedParamsError;
|
|
@@ -1367,16 +1494,15 @@ class RouterCore {
|
|
|
1367
1494
|
});
|
|
1368
1495
|
const matches = [];
|
|
1369
1496
|
const getParentContext = (parentMatch) => {
|
|
1370
|
-
const parentMatchId = parentMatch
|
|
1497
|
+
const parentMatchId = parentMatch?.id;
|
|
1371
1498
|
const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
|
|
1372
1499
|
return parentContext;
|
|
1373
1500
|
};
|
|
1374
1501
|
matchedRoutes.forEach((route, index) => {
|
|
1375
|
-
var _a2, _b;
|
|
1376
1502
|
const parentMatch = matches[index - 1];
|
|
1377
1503
|
const [preMatchSearch, strictMatchSearch, searchError] = (() => {
|
|
1378
|
-
const parentSearch =
|
|
1379
|
-
const parentStrictSearch =
|
|
1504
|
+
const parentSearch = parentMatch?.search ?? next.search;
|
|
1505
|
+
const parentStrictSearch = parentMatch?._strictSearch ?? {};
|
|
1380
1506
|
try {
|
|
1381
1507
|
const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
|
|
1382
1508
|
return [
|
|
@@ -1394,15 +1520,15 @@ class RouterCore {
|
|
|
1394
1520
|
cause: err
|
|
1395
1521
|
});
|
|
1396
1522
|
}
|
|
1397
|
-
if (opts
|
|
1523
|
+
if (opts?.throwOnError) {
|
|
1398
1524
|
throw searchParamError;
|
|
1399
1525
|
}
|
|
1400
1526
|
return [parentSearch, {}, searchParamError];
|
|
1401
1527
|
}
|
|
1402
1528
|
})();
|
|
1403
|
-
const loaderDeps =
|
|
1529
|
+
const loaderDeps = route.options.loaderDeps?.({
|
|
1404
1530
|
search: preMatchSearch
|
|
1405
|
-
})
|
|
1531
|
+
}) ?? "";
|
|
1406
1532
|
const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
|
|
1407
1533
|
const { usedParams, interpolatedPath } = path.interpolatePath({
|
|
1408
1534
|
path: route.fullPath,
|
|
@@ -1413,7 +1539,8 @@ class RouterCore {
|
|
|
1413
1539
|
path: route.id,
|
|
1414
1540
|
params: routeParams,
|
|
1415
1541
|
leaveWildcards: true,
|
|
1416
|
-
decodeCharMap: this.pathParamsDecodeCharMap
|
|
1542
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1543
|
+
parseCache: this.parsePathnameCache
|
|
1417
1544
|
}).interpolatedPath + loaderDepsHash;
|
|
1418
1545
|
const existingMatch = this.getMatch(matchId);
|
|
1419
1546
|
const previousMatch = this.state.matches.find(
|
|
@@ -1448,7 +1575,7 @@ class RouterCore {
|
|
|
1448
1575
|
error: void 0,
|
|
1449
1576
|
paramsError: parseErrors[index],
|
|
1450
1577
|
__routeContext: {},
|
|
1451
|
-
__beforeLoadContext:
|
|
1578
|
+
__beforeLoadContext: void 0,
|
|
1452
1579
|
context: {},
|
|
1453
1580
|
abortController: new AbortController(),
|
|
1454
1581
|
fetchCount: 0,
|
|
@@ -1465,7 +1592,7 @@ class RouterCore {
|
|
|
1465
1592
|
fullPath: route.fullPath
|
|
1466
1593
|
};
|
|
1467
1594
|
}
|
|
1468
|
-
if (!
|
|
1595
|
+
if (!opts?.preload) {
|
|
1469
1596
|
match.globalNotFound = globalNotFoundRouteId === route.id;
|
|
1470
1597
|
}
|
|
1471
1598
|
match.searchError = searchError;
|
|
@@ -1478,10 +1605,9 @@ class RouterCore {
|
|
|
1478
1605
|
matches.push(match);
|
|
1479
1606
|
});
|
|
1480
1607
|
matches.forEach((match, index) => {
|
|
1481
|
-
var _a2, _b;
|
|
1482
1608
|
const route = this.looseRoutesById[match.routeId];
|
|
1483
1609
|
const existingMatch = this.getMatch(match.id);
|
|
1484
|
-
if (!existingMatch &&
|
|
1610
|
+
if (!existingMatch && opts?._buildLocation !== true) {
|
|
1485
1611
|
const parentMatch = matches[index - 1];
|
|
1486
1612
|
const parentContext = getParentContext(parentMatch);
|
|
1487
1613
|
const contextFnContext = {
|
|
@@ -1496,7 +1622,7 @@ class RouterCore {
|
|
|
1496
1622
|
preload: !!match.preload,
|
|
1497
1623
|
matches
|
|
1498
1624
|
};
|
|
1499
|
-
match.__routeContext =
|
|
1625
|
+
match.__routeContext = route.options.context?.(contextFnContext) ?? {};
|
|
1500
1626
|
match.context = {
|
|
1501
1627
|
...parentContext,
|
|
1502
1628
|
...match.__routeContext,
|
|
@@ -1511,6 +1637,10 @@ class SearchParamError extends Error {
|
|
|
1511
1637
|
}
|
|
1512
1638
|
class PathParamError extends Error {
|
|
1513
1639
|
}
|
|
1640
|
+
const normalize = (str) => str.endsWith("/") && str.length > 1 ? str.slice(0, -1) : str;
|
|
1641
|
+
function comparePaths(a, b) {
|
|
1642
|
+
return normalize(a) === normalize(b);
|
|
1643
|
+
}
|
|
1514
1644
|
function lazyFn(fn, key) {
|
|
1515
1645
|
return async (...args) => {
|
|
1516
1646
|
const imported = await fn();
|
|
@@ -1558,14 +1688,33 @@ const componentTypes = [
|
|
|
1558
1688
|
"notFoundComponent"
|
|
1559
1689
|
];
|
|
1560
1690
|
function routeNeedsPreload(route) {
|
|
1561
|
-
var _a;
|
|
1562
1691
|
for (const componentType of componentTypes) {
|
|
1563
|
-
if (
|
|
1692
|
+
if (route.options[componentType]?.preload) {
|
|
1564
1693
|
return true;
|
|
1565
1694
|
}
|
|
1566
1695
|
}
|
|
1567
1696
|
return false;
|
|
1568
1697
|
}
|
|
1698
|
+
const REQUIRED_PARAM_BASE_SCORE = 0.5;
|
|
1699
|
+
const OPTIONAL_PARAM_BASE_SCORE = 0.4;
|
|
1700
|
+
const WILDCARD_PARAM_BASE_SCORE = 0.25;
|
|
1701
|
+
const BOTH_PRESENCE_BASE_SCORE = 0.05;
|
|
1702
|
+
const PREFIX_PRESENCE_BASE_SCORE = 0.02;
|
|
1703
|
+
const SUFFIX_PRESENCE_BASE_SCORE = 0.01;
|
|
1704
|
+
const PREFIX_LENGTH_SCORE_MULTIPLIER = 2e-4;
|
|
1705
|
+
const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1e-4;
|
|
1706
|
+
function handleParam(segment, baseScore) {
|
|
1707
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
1708
|
+
return baseScore + BOTH_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
1709
|
+
}
|
|
1710
|
+
if (segment.prefixSegment) {
|
|
1711
|
+
return baseScore + PREFIX_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length;
|
|
1712
|
+
}
|
|
1713
|
+
if (segment.suffixSegment) {
|
|
1714
|
+
return baseScore + SUFFIX_PRESENCE_BASE_SCORE + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
1715
|
+
}
|
|
1716
|
+
return baseScore;
|
|
1717
|
+
}
|
|
1569
1718
|
function processRouteTree({
|
|
1570
1719
|
routeTree,
|
|
1571
1720
|
initRoute
|
|
@@ -1574,7 +1723,7 @@ function processRouteTree({
|
|
|
1574
1723
|
const routesByPath = {};
|
|
1575
1724
|
const recurseRoutes = (childRoutes) => {
|
|
1576
1725
|
childRoutes.forEach((childRoute, i) => {
|
|
1577
|
-
initRoute
|
|
1726
|
+
initRoute?.(childRoute, i);
|
|
1578
1727
|
const existingRoute = routesById[childRoute.id];
|
|
1579
1728
|
invariant(
|
|
1580
1729
|
!existingRoute,
|
|
@@ -1588,7 +1737,7 @@ function processRouteTree({
|
|
|
1588
1737
|
}
|
|
1589
1738
|
}
|
|
1590
1739
|
const children = childRoute.children;
|
|
1591
|
-
if (children
|
|
1740
|
+
if (children?.length) {
|
|
1592
1741
|
recurseRoutes(children);
|
|
1593
1742
|
}
|
|
1594
1743
|
});
|
|
@@ -1597,46 +1746,52 @@ function processRouteTree({
|
|
|
1597
1746
|
const scoredRoutes = [];
|
|
1598
1747
|
const routes = Object.values(routesById);
|
|
1599
1748
|
routes.forEach((d, i) => {
|
|
1600
|
-
var _a;
|
|
1601
1749
|
if (d.isRoot || !d.path) {
|
|
1602
1750
|
return;
|
|
1603
1751
|
}
|
|
1604
1752
|
const trimmed = path.trimPathLeft(d.fullPath);
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1753
|
+
let parsed = path.parsePathname(trimmed);
|
|
1754
|
+
let skip = 0;
|
|
1755
|
+
while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
|
|
1756
|
+
skip++;
|
|
1608
1757
|
}
|
|
1609
|
-
|
|
1758
|
+
if (skip > 0) parsed = parsed.slice(skip);
|
|
1759
|
+
let optionalParamCount = 0;
|
|
1760
|
+
let hasStaticAfter = false;
|
|
1761
|
+
const scores = parsed.map((segment, index) => {
|
|
1610
1762
|
if (segment.value === "/") {
|
|
1611
1763
|
return 0.75;
|
|
1612
1764
|
}
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
if (segment.type ===
|
|
1617
|
-
|
|
1765
|
+
let baseScore = void 0;
|
|
1766
|
+
if (segment.type === path.SEGMENT_TYPE_PARAM) {
|
|
1767
|
+
baseScore = REQUIRED_PARAM_BASE_SCORE;
|
|
1768
|
+
} else if (segment.type === path.SEGMENT_TYPE_OPTIONAL_PARAM) {
|
|
1769
|
+
baseScore = OPTIONAL_PARAM_BASE_SCORE;
|
|
1770
|
+
optionalParamCount++;
|
|
1771
|
+
} else if (segment.type === path.SEGMENT_TYPE_WILDCARD) {
|
|
1772
|
+
baseScore = WILDCARD_PARAM_BASE_SCORE;
|
|
1618
1773
|
}
|
|
1619
|
-
if (
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
if (segment.type === "wildcard" && segment.prefixSegment) {
|
|
1629
|
-
return 0.27;
|
|
1630
|
-
}
|
|
1631
|
-
if (segment.type === "wildcard" && segment.suffixSegment) {
|
|
1632
|
-
return 0.26;
|
|
1633
|
-
}
|
|
1634
|
-
if (segment.type === "wildcard") {
|
|
1635
|
-
return 0.25;
|
|
1774
|
+
if (baseScore) {
|
|
1775
|
+
for (let i2 = index + 1; i2 < parsed.length; i2++) {
|
|
1776
|
+
const nextSegment = parsed[i2];
|
|
1777
|
+
if (nextSegment.type === path.SEGMENT_TYPE_PATHNAME && nextSegment.value !== "/") {
|
|
1778
|
+
hasStaticAfter = true;
|
|
1779
|
+
return handleParam(segment, baseScore + 0.2);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
return handleParam(segment, baseScore);
|
|
1636
1783
|
}
|
|
1637
1784
|
return 1;
|
|
1638
1785
|
});
|
|
1639
|
-
scoredRoutes.push({
|
|
1786
|
+
scoredRoutes.push({
|
|
1787
|
+
child: d,
|
|
1788
|
+
trimmed,
|
|
1789
|
+
parsed,
|
|
1790
|
+
index: i,
|
|
1791
|
+
scores,
|
|
1792
|
+
optionalParamCount,
|
|
1793
|
+
hasStaticAfter
|
|
1794
|
+
});
|
|
1640
1795
|
});
|
|
1641
1796
|
const flatRoutes = scoredRoutes.sort((a, b) => {
|
|
1642
1797
|
const minLength = Math.min(a.scores.length, b.scores.length);
|
|
@@ -1646,6 +1801,15 @@ function processRouteTree({
|
|
|
1646
1801
|
}
|
|
1647
1802
|
}
|
|
1648
1803
|
if (a.scores.length !== b.scores.length) {
|
|
1804
|
+
if (a.optionalParamCount !== b.optionalParamCount) {
|
|
1805
|
+
if (a.hasStaticAfter === b.hasStaticAfter) {
|
|
1806
|
+
return a.optionalParamCount - b.optionalParamCount;
|
|
1807
|
+
} else if (a.hasStaticAfter && !b.hasStaticAfter) {
|
|
1808
|
+
return -1;
|
|
1809
|
+
} else if (!a.hasStaticAfter && b.hasStaticAfter) {
|
|
1810
|
+
return 1;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1649
1813
|
return b.scores.length - a.scores.length;
|
|
1650
1814
|
}
|
|
1651
1815
|
for (let i = 0; i < minLength; i++) {
|
|
@@ -1667,38 +1831,56 @@ function getMatchedRoutes({
|
|
|
1667
1831
|
caseSensitive,
|
|
1668
1832
|
routesByPath,
|
|
1669
1833
|
routesById,
|
|
1670
|
-
flatRoutes
|
|
1834
|
+
flatRoutes,
|
|
1835
|
+
parseCache
|
|
1671
1836
|
}) {
|
|
1672
1837
|
let routeParams = {};
|
|
1673
1838
|
const trimmedPath = path.trimPathRight(pathname);
|
|
1674
1839
|
const getMatchedParams = (route) => {
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1840
|
+
const result = path.matchPathname(
|
|
1841
|
+
basepath,
|
|
1842
|
+
trimmedPath,
|
|
1843
|
+
{
|
|
1844
|
+
to: route.fullPath,
|
|
1845
|
+
caseSensitive: route.options?.caseSensitive ?? caseSensitive,
|
|
1846
|
+
// we need fuzzy matching for `notFoundMode: 'fuzzy'`
|
|
1847
|
+
fuzzy: true
|
|
1848
|
+
},
|
|
1849
|
+
parseCache
|
|
1850
|
+
);
|
|
1681
1851
|
return result;
|
|
1682
1852
|
};
|
|
1683
1853
|
let foundRoute = routePathname !== void 0 ? routesByPath[routePathname] : void 0;
|
|
1684
1854
|
if (foundRoute) {
|
|
1685
1855
|
routeParams = getMatchedParams(foundRoute);
|
|
1686
1856
|
} else {
|
|
1687
|
-
|
|
1857
|
+
let fuzzyMatch = void 0;
|
|
1858
|
+
for (const route of flatRoutes) {
|
|
1688
1859
|
const matchedParams = getMatchedParams(route);
|
|
1689
1860
|
if (matchedParams) {
|
|
1690
|
-
|
|
1691
|
-
|
|
1861
|
+
if (route.path !== "/" && matchedParams["**"]) {
|
|
1862
|
+
if (!fuzzyMatch) {
|
|
1863
|
+
fuzzyMatch = { foundRoute: route, routeParams: matchedParams };
|
|
1864
|
+
}
|
|
1865
|
+
} else {
|
|
1866
|
+
foundRoute = route;
|
|
1867
|
+
routeParams = matchedParams;
|
|
1868
|
+
break;
|
|
1869
|
+
}
|
|
1692
1870
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1871
|
+
}
|
|
1872
|
+
if (!foundRoute && fuzzyMatch) {
|
|
1873
|
+
foundRoute = fuzzyMatch.foundRoute;
|
|
1874
|
+
routeParams = fuzzyMatch.routeParams;
|
|
1875
|
+
}
|
|
1695
1876
|
}
|
|
1696
1877
|
let routeCursor = foundRoute || routesById[root.rootRouteId];
|
|
1697
1878
|
const matchedRoutes = [routeCursor];
|
|
1698
1879
|
while (routeCursor.parentRoute) {
|
|
1699
1880
|
routeCursor = routeCursor.parentRoute;
|
|
1700
|
-
matchedRoutes.
|
|
1881
|
+
matchedRoutes.push(routeCursor);
|
|
1701
1882
|
}
|
|
1883
|
+
matchedRoutes.reverse();
|
|
1702
1884
|
return { matchedRoutes, routeParams, foundRoute };
|
|
1703
1885
|
}
|
|
1704
1886
|
function applySearchMiddleware({
|
|
@@ -1709,10 +1891,9 @@ function applySearchMiddleware({
|
|
|
1709
1891
|
}) {
|
|
1710
1892
|
const allMiddlewares = destRoutes.reduce(
|
|
1711
1893
|
(acc, route) => {
|
|
1712
|
-
var _a;
|
|
1713
1894
|
const middlewares = [];
|
|
1714
1895
|
if ("search" in route.options) {
|
|
1715
|
-
if (
|
|
1896
|
+
if (route.options.search?.middlewares) {
|
|
1716
1897
|
middlewares.push(...route.options.search.middlewares);
|
|
1717
1898
|
}
|
|
1718
1899
|
} else if (route.options.preSearchFilters || route.options.postSearchFilters) {
|