@tanstack/router-core 1.121.0-alpha.22 → 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 +2 -4
- package/dist/cjs/qss.cjs.map +1 -1
- package/dist/cjs/qss.d.cts +9 -0
- 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 +454 -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 -30
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -18
- 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.d.ts +9 -0
- package/dist/esm/qss.js +2 -4
- 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 +463 -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 -18
- package/dist/esm/utils.js +8 -31
- 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/qss.ts +2 -6
- package/src/redirect.ts +3 -0
- package/src/route.ts +44 -13
- package/src/router.ts +581 -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 -56
- 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,26 +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
|
-
|
|
1094
|
-
|
|
1095
|
-
});
|
|
1096
|
-
return this.load({ sync: opts == null ? void 0 : opts.sync });
|
|
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
|
+
}));
|
|
1212
|
+
this.shouldViewTransition = false;
|
|
1213
|
+
return this.load({ sync: opts?.sync });
|
|
1097
1214
|
};
|
|
1098
1215
|
this.resolveRedirect = (redirect2) => {
|
|
1099
1216
|
if (!redirect2.options.href) {
|
|
@@ -1106,7 +1223,7 @@ class RouterCore {
|
|
|
1106
1223
|
return redirect2;
|
|
1107
1224
|
};
|
|
1108
1225
|
this.clearCache = (opts) => {
|
|
1109
|
-
const filter = opts
|
|
1226
|
+
const filter = opts?.filter;
|
|
1110
1227
|
if (filter !== void 0) {
|
|
1111
1228
|
this.__store.setState((s) => {
|
|
1112
1229
|
return {
|
|
@@ -1132,7 +1249,10 @@ class RouterCore {
|
|
|
1132
1249
|
return true;
|
|
1133
1250
|
}
|
|
1134
1251
|
const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 5 * 60 * 1e3;
|
|
1135
|
-
|
|
1252
|
+
const isError = d.status === "error";
|
|
1253
|
+
if (isError) return true;
|
|
1254
|
+
const gcEligible = Date.now() - d.updatedAt >= gcTime;
|
|
1255
|
+
return gcEligible;
|
|
1136
1256
|
};
|
|
1137
1257
|
this.clearCache({ filter });
|
|
1138
1258
|
};
|
|
@@ -1152,7 +1272,7 @@ class RouterCore {
|
|
|
1152
1272
|
() => Promise.all(
|
|
1153
1273
|
componentTypes.map(async (type) => {
|
|
1154
1274
|
const component = route.options[type];
|
|
1155
|
-
if (component
|
|
1275
|
+
if (component?.preload) {
|
|
1156
1276
|
await component.preload();
|
|
1157
1277
|
}
|
|
1158
1278
|
})
|
|
@@ -1228,15 +1348,20 @@ class RouterCore {
|
|
|
1228
1348
|
leaveParams: true
|
|
1229
1349
|
};
|
|
1230
1350
|
const next = this.buildLocation(matchLocation);
|
|
1231
|
-
if (
|
|
1351
|
+
if (opts?.pending && this.state.status !== "pending") {
|
|
1232
1352
|
return false;
|
|
1233
1353
|
}
|
|
1234
|
-
const pending =
|
|
1354
|
+
const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
|
|
1235
1355
|
const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
|
|
1236
|
-
const match = path.matchPathname(
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1356
|
+
const match = path.matchPathname(
|
|
1357
|
+
this.basepath,
|
|
1358
|
+
baseLocation.pathname,
|
|
1359
|
+
{
|
|
1360
|
+
...opts,
|
|
1361
|
+
to: next.pathname
|
|
1362
|
+
},
|
|
1363
|
+
this.parsePathnameCache
|
|
1364
|
+
);
|
|
1240
1365
|
if (!match) {
|
|
1241
1366
|
return false;
|
|
1242
1367
|
}
|
|
@@ -1245,7 +1370,7 @@ class RouterCore {
|
|
|
1245
1370
|
return false;
|
|
1246
1371
|
}
|
|
1247
1372
|
}
|
|
1248
|
-
if (match && (
|
|
1373
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
1249
1374
|
return utils.deepEqual(baseLocation.search, next.search, { partial: true }) ? match : false;
|
|
1250
1375
|
}
|
|
1251
1376
|
return match;
|
|
@@ -1253,13 +1378,12 @@ class RouterCore {
|
|
|
1253
1378
|
this._handleNotFound = (matches, err, {
|
|
1254
1379
|
updateMatch = this.updateMatch
|
|
1255
1380
|
} = {}) => {
|
|
1256
|
-
var _a;
|
|
1257
1381
|
const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
|
|
1258
1382
|
const matchesByRouteId = {};
|
|
1259
1383
|
for (const match of matches) {
|
|
1260
1384
|
matchesByRouteId[match.routeId] = match;
|
|
1261
1385
|
}
|
|
1262
|
-
if (!routeCursor.options.notFoundComponent &&
|
|
1386
|
+
if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
|
|
1263
1387
|
routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
|
|
1264
1388
|
}
|
|
1265
1389
|
invariant(
|
|
@@ -1301,9 +1425,15 @@ class RouterCore {
|
|
|
1301
1425
|
parseSearch: options.parseSearch ?? searchParams.defaultParseSearch
|
|
1302
1426
|
});
|
|
1303
1427
|
if (typeof document !== "undefined") {
|
|
1304
|
-
|
|
1428
|
+
self.__TSR_ROUTER__ = this;
|
|
1305
1429
|
}
|
|
1306
1430
|
}
|
|
1431
|
+
isShell() {
|
|
1432
|
+
return !!this.options.isShell;
|
|
1433
|
+
}
|
|
1434
|
+
isPrerendering() {
|
|
1435
|
+
return !!this.options.isPrerendering;
|
|
1436
|
+
}
|
|
1307
1437
|
get state() {
|
|
1308
1438
|
return this.__store.state;
|
|
1309
1439
|
}
|
|
@@ -1311,10 +1441,9 @@ class RouterCore {
|
|
|
1311
1441
|
return this.routesById;
|
|
1312
1442
|
}
|
|
1313
1443
|
matchRoutesInternal(next, opts) {
|
|
1314
|
-
var _a;
|
|
1315
1444
|
const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
1316
1445
|
next.pathname,
|
|
1317
|
-
|
|
1446
|
+
opts?.dest?.to
|
|
1318
1447
|
);
|
|
1319
1448
|
let isGlobalNotFound = false;
|
|
1320
1449
|
if (
|
|
@@ -1345,9 +1474,8 @@ class RouterCore {
|
|
|
1345
1474
|
return root.rootRouteId;
|
|
1346
1475
|
})();
|
|
1347
1476
|
const parseErrors = matchedRoutes.map((route) => {
|
|
1348
|
-
var _a2;
|
|
1349
1477
|
let parsedParamsError;
|
|
1350
|
-
const parseParams =
|
|
1478
|
+
const parseParams = route.options.params?.parse ?? route.options.parseParams;
|
|
1351
1479
|
if (parseParams) {
|
|
1352
1480
|
try {
|
|
1353
1481
|
const parsedParams = parseParams(routeParams);
|
|
@@ -1356,7 +1484,7 @@ class RouterCore {
|
|
|
1356
1484
|
parsedParamsError = new PathParamError(err.message, {
|
|
1357
1485
|
cause: err
|
|
1358
1486
|
});
|
|
1359
|
-
if (opts
|
|
1487
|
+
if (opts?.throwOnError) {
|
|
1360
1488
|
throw parsedParamsError;
|
|
1361
1489
|
}
|
|
1362
1490
|
return parsedParamsError;
|
|
@@ -1366,16 +1494,15 @@ class RouterCore {
|
|
|
1366
1494
|
});
|
|
1367
1495
|
const matches = [];
|
|
1368
1496
|
const getParentContext = (parentMatch) => {
|
|
1369
|
-
const parentMatchId = parentMatch
|
|
1497
|
+
const parentMatchId = parentMatch?.id;
|
|
1370
1498
|
const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
|
|
1371
1499
|
return parentContext;
|
|
1372
1500
|
};
|
|
1373
1501
|
matchedRoutes.forEach((route, index) => {
|
|
1374
|
-
var _a2, _b;
|
|
1375
1502
|
const parentMatch = matches[index - 1];
|
|
1376
1503
|
const [preMatchSearch, strictMatchSearch, searchError] = (() => {
|
|
1377
|
-
const parentSearch =
|
|
1378
|
-
const parentStrictSearch =
|
|
1504
|
+
const parentSearch = parentMatch?.search ?? next.search;
|
|
1505
|
+
const parentStrictSearch = parentMatch?._strictSearch ?? {};
|
|
1379
1506
|
try {
|
|
1380
1507
|
const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
|
|
1381
1508
|
return [
|
|
@@ -1393,15 +1520,15 @@ class RouterCore {
|
|
|
1393
1520
|
cause: err
|
|
1394
1521
|
});
|
|
1395
1522
|
}
|
|
1396
|
-
if (opts
|
|
1523
|
+
if (opts?.throwOnError) {
|
|
1397
1524
|
throw searchParamError;
|
|
1398
1525
|
}
|
|
1399
1526
|
return [parentSearch, {}, searchParamError];
|
|
1400
1527
|
}
|
|
1401
1528
|
})();
|
|
1402
|
-
const loaderDeps =
|
|
1529
|
+
const loaderDeps = route.options.loaderDeps?.({
|
|
1403
1530
|
search: preMatchSearch
|
|
1404
|
-
})
|
|
1531
|
+
}) ?? "";
|
|
1405
1532
|
const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
|
|
1406
1533
|
const { usedParams, interpolatedPath } = path.interpolatePath({
|
|
1407
1534
|
path: route.fullPath,
|
|
@@ -1412,7 +1539,8 @@ class RouterCore {
|
|
|
1412
1539
|
path: route.id,
|
|
1413
1540
|
params: routeParams,
|
|
1414
1541
|
leaveWildcards: true,
|
|
1415
|
-
decodeCharMap: this.pathParamsDecodeCharMap
|
|
1542
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1543
|
+
parseCache: this.parsePathnameCache
|
|
1416
1544
|
}).interpolatedPath + loaderDepsHash;
|
|
1417
1545
|
const existingMatch = this.getMatch(matchId);
|
|
1418
1546
|
const previousMatch = this.state.matches.find(
|
|
@@ -1447,7 +1575,7 @@ class RouterCore {
|
|
|
1447
1575
|
error: void 0,
|
|
1448
1576
|
paramsError: parseErrors[index],
|
|
1449
1577
|
__routeContext: {},
|
|
1450
|
-
__beforeLoadContext:
|
|
1578
|
+
__beforeLoadContext: void 0,
|
|
1451
1579
|
context: {},
|
|
1452
1580
|
abortController: new AbortController(),
|
|
1453
1581
|
fetchCount: 0,
|
|
@@ -1464,7 +1592,7 @@ class RouterCore {
|
|
|
1464
1592
|
fullPath: route.fullPath
|
|
1465
1593
|
};
|
|
1466
1594
|
}
|
|
1467
|
-
if (!
|
|
1595
|
+
if (!opts?.preload) {
|
|
1468
1596
|
match.globalNotFound = globalNotFoundRouteId === route.id;
|
|
1469
1597
|
}
|
|
1470
1598
|
match.searchError = searchError;
|
|
@@ -1477,10 +1605,9 @@ class RouterCore {
|
|
|
1477
1605
|
matches.push(match);
|
|
1478
1606
|
});
|
|
1479
1607
|
matches.forEach((match, index) => {
|
|
1480
|
-
var _a2, _b;
|
|
1481
1608
|
const route = this.looseRoutesById[match.routeId];
|
|
1482
1609
|
const existingMatch = this.getMatch(match.id);
|
|
1483
|
-
if (!existingMatch &&
|
|
1610
|
+
if (!existingMatch && opts?._buildLocation !== true) {
|
|
1484
1611
|
const parentMatch = matches[index - 1];
|
|
1485
1612
|
const parentContext = getParentContext(parentMatch);
|
|
1486
1613
|
const contextFnContext = {
|
|
@@ -1495,7 +1622,7 @@ class RouterCore {
|
|
|
1495
1622
|
preload: !!match.preload,
|
|
1496
1623
|
matches
|
|
1497
1624
|
};
|
|
1498
|
-
match.__routeContext =
|
|
1625
|
+
match.__routeContext = route.options.context?.(contextFnContext) ?? {};
|
|
1499
1626
|
match.context = {
|
|
1500
1627
|
...parentContext,
|
|
1501
1628
|
...match.__routeContext,
|
|
@@ -1510,6 +1637,10 @@ class SearchParamError extends Error {
|
|
|
1510
1637
|
}
|
|
1511
1638
|
class PathParamError extends Error {
|
|
1512
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
|
+
}
|
|
1513
1644
|
function lazyFn(fn, key) {
|
|
1514
1645
|
return async (...args) => {
|
|
1515
1646
|
const imported = await fn();
|
|
@@ -1557,14 +1688,33 @@ const componentTypes = [
|
|
|
1557
1688
|
"notFoundComponent"
|
|
1558
1689
|
];
|
|
1559
1690
|
function routeNeedsPreload(route) {
|
|
1560
|
-
var _a;
|
|
1561
1691
|
for (const componentType of componentTypes) {
|
|
1562
|
-
if (
|
|
1692
|
+
if (route.options[componentType]?.preload) {
|
|
1563
1693
|
return true;
|
|
1564
1694
|
}
|
|
1565
1695
|
}
|
|
1566
1696
|
return false;
|
|
1567
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
|
+
}
|
|
1568
1718
|
function processRouteTree({
|
|
1569
1719
|
routeTree,
|
|
1570
1720
|
initRoute
|
|
@@ -1573,7 +1723,7 @@ function processRouteTree({
|
|
|
1573
1723
|
const routesByPath = {};
|
|
1574
1724
|
const recurseRoutes = (childRoutes) => {
|
|
1575
1725
|
childRoutes.forEach((childRoute, i) => {
|
|
1576
|
-
initRoute
|
|
1726
|
+
initRoute?.(childRoute, i);
|
|
1577
1727
|
const existingRoute = routesById[childRoute.id];
|
|
1578
1728
|
invariant(
|
|
1579
1729
|
!existingRoute,
|
|
@@ -1587,7 +1737,7 @@ function processRouteTree({
|
|
|
1587
1737
|
}
|
|
1588
1738
|
}
|
|
1589
1739
|
const children = childRoute.children;
|
|
1590
|
-
if (children
|
|
1740
|
+
if (children?.length) {
|
|
1591
1741
|
recurseRoutes(children);
|
|
1592
1742
|
}
|
|
1593
1743
|
});
|
|
@@ -1596,46 +1746,52 @@ function processRouteTree({
|
|
|
1596
1746
|
const scoredRoutes = [];
|
|
1597
1747
|
const routes = Object.values(routesById);
|
|
1598
1748
|
routes.forEach((d, i) => {
|
|
1599
|
-
var _a;
|
|
1600
1749
|
if (d.isRoot || !d.path) {
|
|
1601
1750
|
return;
|
|
1602
1751
|
}
|
|
1603
1752
|
const trimmed = path.trimPathLeft(d.fullPath);
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1753
|
+
let parsed = path.parsePathname(trimmed);
|
|
1754
|
+
let skip = 0;
|
|
1755
|
+
while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
|
|
1756
|
+
skip++;
|
|
1607
1757
|
}
|
|
1608
|
-
|
|
1758
|
+
if (skip > 0) parsed = parsed.slice(skip);
|
|
1759
|
+
let optionalParamCount = 0;
|
|
1760
|
+
let hasStaticAfter = false;
|
|
1761
|
+
const scores = parsed.map((segment, index) => {
|
|
1609
1762
|
if (segment.value === "/") {
|
|
1610
1763
|
return 0.75;
|
|
1611
1764
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
if (segment.type ===
|
|
1616
|
-
|
|
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;
|
|
1617
1773
|
}
|
|
1618
|
-
if (
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
if (segment.type === "wildcard" && segment.prefixSegment) {
|
|
1628
|
-
return 0.27;
|
|
1629
|
-
}
|
|
1630
|
-
if (segment.type === "wildcard" && segment.suffixSegment) {
|
|
1631
|
-
return 0.26;
|
|
1632
|
-
}
|
|
1633
|
-
if (segment.type === "wildcard") {
|
|
1634
|
-
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);
|
|
1635
1783
|
}
|
|
1636
1784
|
return 1;
|
|
1637
1785
|
});
|
|
1638
|
-
scoredRoutes.push({
|
|
1786
|
+
scoredRoutes.push({
|
|
1787
|
+
child: d,
|
|
1788
|
+
trimmed,
|
|
1789
|
+
parsed,
|
|
1790
|
+
index: i,
|
|
1791
|
+
scores,
|
|
1792
|
+
optionalParamCount,
|
|
1793
|
+
hasStaticAfter
|
|
1794
|
+
});
|
|
1639
1795
|
});
|
|
1640
1796
|
const flatRoutes = scoredRoutes.sort((a, b) => {
|
|
1641
1797
|
const minLength = Math.min(a.scores.length, b.scores.length);
|
|
@@ -1645,6 +1801,15 @@ function processRouteTree({
|
|
|
1645
1801
|
}
|
|
1646
1802
|
}
|
|
1647
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
|
+
}
|
|
1648
1813
|
return b.scores.length - a.scores.length;
|
|
1649
1814
|
}
|
|
1650
1815
|
for (let i = 0; i < minLength; i++) {
|
|
@@ -1666,38 +1831,56 @@ function getMatchedRoutes({
|
|
|
1666
1831
|
caseSensitive,
|
|
1667
1832
|
routesByPath,
|
|
1668
1833
|
routesById,
|
|
1669
|
-
flatRoutes
|
|
1834
|
+
flatRoutes,
|
|
1835
|
+
parseCache
|
|
1670
1836
|
}) {
|
|
1671
1837
|
let routeParams = {};
|
|
1672
1838
|
const trimmedPath = path.trimPathRight(pathname);
|
|
1673
1839
|
const getMatchedParams = (route) => {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
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
|
+
);
|
|
1680
1851
|
return result;
|
|
1681
1852
|
};
|
|
1682
1853
|
let foundRoute = routePathname !== void 0 ? routesByPath[routePathname] : void 0;
|
|
1683
1854
|
if (foundRoute) {
|
|
1684
1855
|
routeParams = getMatchedParams(foundRoute);
|
|
1685
1856
|
} else {
|
|
1686
|
-
|
|
1857
|
+
let fuzzyMatch = void 0;
|
|
1858
|
+
for (const route of flatRoutes) {
|
|
1687
1859
|
const matchedParams = getMatchedParams(route);
|
|
1688
1860
|
if (matchedParams) {
|
|
1689
|
-
|
|
1690
|
-
|
|
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
|
+
}
|
|
1691
1870
|
}
|
|
1692
|
-
|
|
1693
|
-
|
|
1871
|
+
}
|
|
1872
|
+
if (!foundRoute && fuzzyMatch) {
|
|
1873
|
+
foundRoute = fuzzyMatch.foundRoute;
|
|
1874
|
+
routeParams = fuzzyMatch.routeParams;
|
|
1875
|
+
}
|
|
1694
1876
|
}
|
|
1695
1877
|
let routeCursor = foundRoute || routesById[root.rootRouteId];
|
|
1696
1878
|
const matchedRoutes = [routeCursor];
|
|
1697
1879
|
while (routeCursor.parentRoute) {
|
|
1698
1880
|
routeCursor = routeCursor.parentRoute;
|
|
1699
|
-
matchedRoutes.
|
|
1881
|
+
matchedRoutes.push(routeCursor);
|
|
1700
1882
|
}
|
|
1883
|
+
matchedRoutes.reverse();
|
|
1701
1884
|
return { matchedRoutes, routeParams, foundRoute };
|
|
1702
1885
|
}
|
|
1703
1886
|
function applySearchMiddleware({
|
|
@@ -1708,10 +1891,9 @@ function applySearchMiddleware({
|
|
|
1708
1891
|
}) {
|
|
1709
1892
|
const allMiddlewares = destRoutes.reduce(
|
|
1710
1893
|
(acc, route) => {
|
|
1711
|
-
var _a;
|
|
1712
1894
|
const middlewares = [];
|
|
1713
1895
|
if ("search" in route.options) {
|
|
1714
|
-
if (
|
|
1896
|
+
if (route.options.search?.middlewares) {
|
|
1715
1897
|
middlewares.push(...route.options.search.middlewares);
|
|
1716
1898
|
}
|
|
1717
1899
|
} else if (route.options.preSearchFilters || route.options.postSearchFilters) {
|