@tanstack/router-core 1.132.0-alpha.1 → 1.132.0-alpha.15
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 +9 -11
- package/dist/cjs/config.cjs +10 -0
- package/dist/cjs/config.cjs.map +1 -0
- package/dist/cjs/config.d.cts +17 -0
- package/dist/cjs/fileRoute.d.cts +3 -2
- package/dist/cjs/index.cjs +15 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +11 -4
- package/dist/cjs/load-matches.cjs +636 -0
- package/dist/cjs/load-matches.cjs.map +1 -0
- package/dist/cjs/load-matches.d.cts +16 -0
- package/dist/cjs/location.d.cts +38 -0
- package/dist/cjs/path.cjs +6 -49
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +3 -6
- package/dist/cjs/qss.cjs +19 -19
- package/dist/cjs/qss.cjs.map +1 -1
- package/dist/cjs/qss.d.cts +6 -4
- package/dist/cjs/redirect.cjs +3 -3
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/rewrite.cjs +63 -0
- package/dist/cjs/rewrite.cjs.map +1 -0
- package/dist/cjs/rewrite.d.cts +22 -0
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +42 -41
- package/dist/cjs/router.cjs +134 -681
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +68 -25
- package/dist/cjs/scroll-restoration.cjs +32 -29
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +1 -10
- package/dist/cjs/searchParams.cjs +7 -15
- package/dist/cjs/searchParams.cjs.map +1 -1
- package/dist/cjs/ssr/constants.cjs +5 -0
- package/dist/cjs/ssr/constants.cjs.map +1 -0
- package/dist/cjs/ssr/constants.d.cts +1 -0
- package/dist/cjs/ssr/{seroval-plugins.cjs → serializer/ShallowErrorPlugin.cjs} +2 -2
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -0
- package/dist/cjs/ssr/{seroval-plugins.d.cts → serializer/ShallowErrorPlugin.d.cts} +1 -2
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs +11 -0
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -0
- package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -0
- package/dist/cjs/ssr/serializer/transformer.cjs +52 -0
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -0
- package/dist/cjs/ssr/serializer/transformer.d.cts +56 -0
- package/dist/cjs/ssr/server.d.cts +5 -0
- package/dist/cjs/ssr/ssr-client.cjs +53 -40
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-client.d.cts +5 -1
- package/dist/cjs/ssr/ssr-server.cjs +12 -10
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +0 -1
- package/dist/cjs/ssr/tsrScript.cjs +1 -1
- package/dist/cjs/ssr/tsrScript.cjs.map +1 -1
- package/dist/cjs/typePrimitives.d.cts +6 -6
- package/dist/cjs/utils.cjs +14 -7
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +2 -1
- package/dist/esm/Matches.d.ts +9 -11
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/config.d.ts +17 -0
- package/dist/esm/config.js +10 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/fileRoute.d.ts +3 -2
- package/dist/esm/index.d.ts +11 -4
- package/dist/esm/index.js +17 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/load-matches.d.ts +16 -0
- package/dist/esm/load-matches.js +636 -0
- package/dist/esm/load-matches.js.map +1 -0
- package/dist/esm/location.d.ts +38 -0
- package/dist/esm/path.d.ts +3 -6
- package/dist/esm/path.js +6 -49
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/qss.d.ts +6 -4
- package/dist/esm/qss.js +19 -19
- package/dist/esm/qss.js.map +1 -1
- package/dist/esm/redirect.js +3 -3
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/rewrite.d.ts +22 -0
- package/dist/esm/rewrite.js +63 -0
- package/dist/esm/rewrite.js.map +1 -0
- package/dist/esm/route.d.ts +42 -41
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +68 -25
- package/dist/esm/router.js +136 -683
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +1 -10
- package/dist/esm/scroll-restoration.js +32 -29
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/searchParams.js +7 -15
- package/dist/esm/searchParams.js.map +1 -1
- package/dist/esm/ssr/constants.d.ts +1 -0
- package/dist/esm/ssr/constants.js +5 -0
- package/dist/esm/ssr/constants.js.map +1 -0
- package/dist/esm/ssr/{seroval-plugins.d.ts → serializer/ShallowErrorPlugin.d.ts} +1 -2
- package/dist/esm/ssr/{seroval-plugins.js → serializer/ShallowErrorPlugin.js} +2 -2
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -0
- package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -0
- package/dist/esm/ssr/serializer/seroval-plugins.js +11 -0
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -0
- package/dist/esm/ssr/serializer/transformer.d.ts +56 -0
- package/dist/esm/ssr/serializer/transformer.js +52 -0
- package/dist/esm/ssr/serializer/transformer.js.map +1 -0
- package/dist/esm/ssr/server.d.ts +5 -0
- package/dist/esm/ssr/ssr-client.d.ts +5 -1
- package/dist/esm/ssr/ssr-client.js +53 -40
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/dist/esm/ssr/ssr-server.d.ts +0 -1
- package/dist/esm/ssr/ssr-server.js +12 -10
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/tsrScript.js +1 -1
- package/dist/esm/ssr/tsrScript.js.map +1 -1
- package/dist/esm/typePrimitives.d.ts +6 -6
- package/dist/esm/utils.d.ts +2 -1
- package/dist/esm/utils.js +14 -7
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/Matches.ts +18 -10
- package/src/config.ts +42 -0
- package/src/fileRoute.ts +15 -3
- package/src/index.ts +32 -3
- package/src/load-matches.ts +955 -0
- package/src/location.ts +38 -0
- package/src/path.ts +5 -66
- package/src/qss.ts +27 -24
- package/src/redirect.ts +3 -3
- package/src/rewrite.ts +70 -0
- package/src/route.ts +146 -35
- package/src/router.ts +263 -972
- package/src/scroll-restoration.ts +42 -37
- package/src/searchParams.ts +8 -19
- package/src/ssr/constants.ts +1 -0
- package/src/ssr/{seroval-plugins.ts → serializer/ShallowErrorPlugin.ts} +2 -2
- package/src/ssr/serializer/seroval-plugins.ts +9 -0
- package/src/ssr/serializer/transformer.ts +215 -0
- package/src/ssr/server.ts +6 -0
- package/src/ssr/ssr-client.ts +72 -44
- package/src/ssr/ssr-server.ts +18 -10
- package/src/ssr/tsrScript.ts +5 -1
- package/src/typePrimitives.ts +6 -6
- package/src/utils.ts +21 -10
- package/dist/cjs/ssr/seroval-plugins.cjs.map +0 -1
- package/dist/esm/ssr/seroval-plugins.js.map +0 -1
package/dist/esm/router.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { Store, batch } from "@tanstack/store";
|
|
2
|
-
import {
|
|
2
|
+
import { createBrowserHistory, parseHref } from "@tanstack/history";
|
|
3
3
|
import invariant from "tiny-invariant";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { createControlledPromise, deepEqual, replaceEqualDeep, last, findLast, functionalUpdate } from "./utils.js";
|
|
5
|
+
import { resolvePath, cleanPath, trimPathRight, trimPath, matchPathname, interpolatePath, trimPathLeft, parsePathname, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM, SEGMENT_TYPE_WILDCARD, SEGMENT_TYPE_PATHNAME } from "./path.js";
|
|
6
6
|
import { isNotFound } from "./not-found.js";
|
|
7
7
|
import { setupScrollRestoration } from "./scroll-restoration.js";
|
|
8
8
|
import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
|
|
9
9
|
import { rootRouteId } from "./root.js";
|
|
10
10
|
import { redirect, isRedirect } from "./redirect.js";
|
|
11
11
|
import { createLRUCache } from "./lru-cache.js";
|
|
12
|
+
import { loadMatches, loadRouteChunk, routeNeedsPreload } from "./load-matches.js";
|
|
13
|
+
import { rewriteBasepath, composeRewrites, executeRewriteInput, executeRewriteOutput } from "./rewrite.js";
|
|
12
14
|
function defaultSerializeError(err) {
|
|
13
15
|
if (err instanceof Error) {
|
|
14
16
|
const obj = {
|
|
@@ -53,7 +55,6 @@ class RouterCore {
|
|
|
53
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."
|
|
54
56
|
);
|
|
55
57
|
}
|
|
56
|
-
const previousOptions = this.options;
|
|
57
58
|
this.options = {
|
|
58
59
|
...this.options,
|
|
59
60
|
...newOptions
|
|
@@ -65,24 +66,43 @@ class RouterCore {
|
|
|
65
66
|
char
|
|
66
67
|
])
|
|
67
68
|
) : void 0;
|
|
68
|
-
if (!this.
|
|
69
|
-
if (
|
|
70
|
-
this.
|
|
69
|
+
if (!this.history || this.options.history && this.options.history !== this.history) {
|
|
70
|
+
if (!this.options.history) {
|
|
71
|
+
if (!this.isServer) {
|
|
72
|
+
this.history = createBrowserHistory();
|
|
73
|
+
}
|
|
71
74
|
} else {
|
|
72
|
-
this.
|
|
75
|
+
this.history = this.options.history;
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
})
|
|
79
|
-
|
|
78
|
+
if (this.options.basepath) {
|
|
79
|
+
const basepathRewrite = rewriteBasepath({
|
|
80
|
+
basepath: this.options.basepath
|
|
81
|
+
});
|
|
82
|
+
if (this.options.rewrite) {
|
|
83
|
+
this.rewrite = composeRewrites([basepathRewrite, this.options.rewrite]);
|
|
84
|
+
} else {
|
|
85
|
+
this.rewrite = basepathRewrite;
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
this.rewrite = this.options.rewrite;
|
|
89
|
+
}
|
|
90
|
+
this.origin = this.options.origin;
|
|
91
|
+
if (!this.origin) {
|
|
92
|
+
if (!this.isServer) {
|
|
93
|
+
this.origin = window.origin;
|
|
94
|
+
} else {
|
|
95
|
+
this.origin = "http://localhost";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (this.history) {
|
|
99
|
+
this.updateLatestLocation();
|
|
80
100
|
}
|
|
81
101
|
if (this.options.routeTree !== this.routeTree) {
|
|
82
102
|
this.routeTree = this.options.routeTree;
|
|
83
103
|
this.buildRouteTree();
|
|
84
104
|
}
|
|
85
|
-
if (!this.__store) {
|
|
105
|
+
if (!this.__store && this.latestLocation) {
|
|
86
106
|
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
87
107
|
onUpdate: () => {
|
|
88
108
|
this.__store.state = {
|
|
@@ -101,6 +121,12 @@ class RouterCore {
|
|
|
101
121
|
);
|
|
102
122
|
}
|
|
103
123
|
};
|
|
124
|
+
this.updateLatestLocation = () => {
|
|
125
|
+
this.latestLocation = this.parseLocation(
|
|
126
|
+
this.history.location,
|
|
127
|
+
this.latestLocation
|
|
128
|
+
);
|
|
129
|
+
};
|
|
104
130
|
this.buildRouteTree = () => {
|
|
105
131
|
const { routesById, routesByPath, flatRoutes } = processRouteTree({
|
|
106
132
|
routeTree: this.routeTree,
|
|
@@ -138,25 +164,30 @@ class RouterCore {
|
|
|
138
164
|
}
|
|
139
165
|
});
|
|
140
166
|
};
|
|
141
|
-
this.parseLocation = (
|
|
167
|
+
this.parseLocation = (locationToParse, previousLocation) => {
|
|
142
168
|
const parse = ({
|
|
143
|
-
|
|
144
|
-
search,
|
|
145
|
-
hash,
|
|
169
|
+
href,
|
|
146
170
|
state
|
|
147
171
|
}) => {
|
|
148
|
-
const
|
|
172
|
+
const fullUrl = new URL(href, this.origin);
|
|
173
|
+
const url = executeRewriteInput(this.rewrite, fullUrl);
|
|
174
|
+
const parsedSearch = this.options.parseSearch(url.search);
|
|
149
175
|
const searchStr = this.options.stringifySearch(parsedSearch);
|
|
176
|
+
url.search = searchStr;
|
|
177
|
+
const fullPath = url.href.replace(url.origin, "");
|
|
178
|
+
const { pathname, hash } = url;
|
|
150
179
|
return {
|
|
180
|
+
href: fullPath,
|
|
181
|
+
publicHref: href,
|
|
182
|
+
url: url.href,
|
|
151
183
|
pathname,
|
|
152
184
|
searchStr,
|
|
153
185
|
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
154
186
|
hash: hash.split("#").reverse()[0] ?? "",
|
|
155
|
-
href: `${pathname}${searchStr}${hash}`,
|
|
156
187
|
state: replaceEqualDeep(previousLocation?.state, state)
|
|
157
188
|
};
|
|
158
189
|
};
|
|
159
|
-
const location = parse(locationToParse
|
|
190
|
+
const location = parse(locationToParse);
|
|
160
191
|
const { __tempLocation, __tempKey } = location.state;
|
|
161
192
|
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
162
193
|
const parsedTempLocation = parse(__tempLocation);
|
|
@@ -172,11 +203,9 @@ class RouterCore {
|
|
|
172
203
|
};
|
|
173
204
|
this.resolvePathWithBase = (from, path) => {
|
|
174
205
|
const resolvedPath = resolvePath({
|
|
175
|
-
basepath: this.basepath,
|
|
176
206
|
base: from,
|
|
177
207
|
to: cleanPath(path),
|
|
178
208
|
trailingSlash: this.options.trailingSlash,
|
|
179
|
-
caseSensitive: this.options.caseSensitive,
|
|
180
209
|
parseCache: this.parsePathnameCache
|
|
181
210
|
});
|
|
182
211
|
return resolvedPath;
|
|
@@ -198,7 +227,6 @@ class RouterCore {
|
|
|
198
227
|
return getMatchedRoutes({
|
|
199
228
|
pathname,
|
|
200
229
|
routePathname,
|
|
201
|
-
basepath: this.basepath,
|
|
202
230
|
caseSensitive: this.options.caseSensitive,
|
|
203
231
|
routesByPath: this.routesByPath,
|
|
204
232
|
routesById: this.routesById,
|
|
@@ -210,13 +238,8 @@ class RouterCore {
|
|
|
210
238
|
const match = this.getMatch(id);
|
|
211
239
|
if (!match) return;
|
|
212
240
|
match.abortController.abort();
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return {
|
|
216
|
-
...prev,
|
|
217
|
-
pendingTimeout: void 0
|
|
218
|
-
};
|
|
219
|
-
});
|
|
241
|
+
clearTimeout(match._nonReactive.pendingTimeout);
|
|
242
|
+
match._nonReactive.pendingTimeout = void 0;
|
|
220
243
|
};
|
|
221
244
|
this.cancelMatches = () => {
|
|
222
245
|
this.state.pendingMatches?.forEach((match) => {
|
|
@@ -230,60 +253,51 @@ class RouterCore {
|
|
|
230
253
|
_buildLocation: true
|
|
231
254
|
});
|
|
232
255
|
const lastMatch = last(allCurrentLocationMatches);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return comparePaths(d.fullPath, fromPath);
|
|
247
|
-
});
|
|
248
|
-
const matchedCurrent = [...allFromMatches].reverse().find((d) => {
|
|
249
|
-
return comparePaths(d.fullPath, currentLocation.pathname);
|
|
250
|
-
});
|
|
251
|
-
if (!matchedFrom && !matchedCurrent) {
|
|
252
|
-
console.warn(`Could not find match for from: ${fromPath}`);
|
|
253
|
-
}
|
|
256
|
+
if (dest.from && process.env.NODE_ENV !== "production" && dest._isNavigate) {
|
|
257
|
+
const allFromMatches = this.getMatchedRoutes(
|
|
258
|
+
dest.from,
|
|
259
|
+
void 0
|
|
260
|
+
).matchedRoutes;
|
|
261
|
+
const matchedFrom = findLast(allCurrentLocationMatches, (d) => {
|
|
262
|
+
return comparePaths(d.fullPath, dest.from);
|
|
263
|
+
});
|
|
264
|
+
const matchedCurrent = findLast(allFromMatches, (d) => {
|
|
265
|
+
return comparePaths(d.fullPath, lastMatch.fullPath);
|
|
266
|
+
});
|
|
267
|
+
if (!matchedFrom && !matchedCurrent) {
|
|
268
|
+
console.warn(`Could not find match for from: ${dest.from}`);
|
|
254
269
|
}
|
|
255
270
|
}
|
|
271
|
+
const defaultedFromPath = dest.unsafeRelative === "path" ? currentLocation.pathname : dest.from ?? lastMatch.fullPath;
|
|
272
|
+
const fromPath = this.resolvePathWithBase(defaultedFromPath, ".");
|
|
256
273
|
const fromSearch = lastMatch.search;
|
|
257
274
|
const fromParams = { ...lastMatch.params };
|
|
258
275
|
const nextTo = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(fromPath, ".");
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
276
|
+
const nextParams = dest.params === false || dest.params === null ? {} : (dest.params ?? true) === true ? fromParams : Object.assign(
|
|
277
|
+
fromParams,
|
|
278
|
+
functionalUpdate(dest.params, fromParams)
|
|
279
|
+
);
|
|
263
280
|
const interpolatedNextTo = interpolatePath({
|
|
264
281
|
path: nextTo,
|
|
265
|
-
params: nextParams
|
|
282
|
+
params: nextParams,
|
|
266
283
|
parseCache: this.parsePathnameCache
|
|
267
284
|
}).interpolatedPath;
|
|
268
|
-
const destRoutes = this.matchRoutes(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
{
|
|
272
|
-
_buildLocation: true
|
|
273
|
-
}
|
|
274
|
-
).map((d) => this.looseRoutesById[d.routeId]);
|
|
285
|
+
const destRoutes = this.matchRoutes(interpolatedNextTo, void 0, {
|
|
286
|
+
_buildLocation: true
|
|
287
|
+
}).map((d) => this.looseRoutesById[d.routeId]);
|
|
275
288
|
if (Object.keys(nextParams).length > 0) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
289
|
+
for (const route of destRoutes) {
|
|
290
|
+
const fn = route.options.params?.stringify ?? route.options.stringifyParams;
|
|
291
|
+
if (fn) {
|
|
292
|
+
Object.assign(nextParams, fn(nextParams));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
281
295
|
}
|
|
282
296
|
const nextPathname = interpolatePath({
|
|
283
297
|
// Use the original template path for interpolation
|
|
284
298
|
// This preserves the original parameter syntax including optional parameters
|
|
285
299
|
path: nextTo,
|
|
286
|
-
params: nextParams
|
|
300
|
+
params: nextParams,
|
|
287
301
|
leaveWildcards: false,
|
|
288
302
|
leaveParams: opts.leaveParams,
|
|
289
303
|
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
@@ -291,19 +305,19 @@ class RouterCore {
|
|
|
291
305
|
}).interpolatedPath;
|
|
292
306
|
let nextSearch = fromSearch;
|
|
293
307
|
if (opts._includeValidateSearch && this.options.search?.strict) {
|
|
294
|
-
|
|
308
|
+
const validatedSearch = {};
|
|
295
309
|
destRoutes.forEach((route) => {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
310
|
+
if (route.options.validateSearch) {
|
|
311
|
+
try {
|
|
312
|
+
Object.assign(
|
|
313
|
+
validatedSearch,
|
|
314
|
+
validateSearch(route.options.validateSearch, {
|
|
301
315
|
...validatedSearch,
|
|
302
316
|
...nextSearch
|
|
303
|
-
})
|
|
304
|
-
|
|
317
|
+
})
|
|
318
|
+
);
|
|
319
|
+
} catch {
|
|
305
320
|
}
|
|
306
|
-
} catch {
|
|
307
321
|
}
|
|
308
322
|
});
|
|
309
323
|
nextSearch = validatedSearch;
|
|
@@ -320,13 +334,18 @@ class RouterCore {
|
|
|
320
334
|
const hashStr = hash ? `#${hash}` : "";
|
|
321
335
|
let nextState = dest.state === true ? currentLocation.state : dest.state ? functionalUpdate(dest.state, currentLocation.state) : {};
|
|
322
336
|
nextState = replaceEqualDeep(currentLocation.state, nextState);
|
|
337
|
+
const fullPath = `${nextPathname}${searchStr}${hashStr}`;
|
|
338
|
+
const url = new URL(fullPath, this.origin);
|
|
339
|
+
const rewrittenUrl = executeRewriteOutput(this.rewrite, url);
|
|
323
340
|
return {
|
|
341
|
+
publicHref: rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
|
|
342
|
+
href: fullPath,
|
|
343
|
+
url: rewrittenUrl.href,
|
|
324
344
|
pathname: nextPathname,
|
|
325
345
|
search: nextSearch,
|
|
326
346
|
searchStr,
|
|
327
347
|
state: nextState,
|
|
328
348
|
hash: hash ?? "",
|
|
329
|
-
href: `${nextPathname}${searchStr}${hashStr}`,
|
|
330
349
|
unmaskOnReload: dest.unmaskOnReload
|
|
331
350
|
};
|
|
332
351
|
};
|
|
@@ -337,7 +356,6 @@ class RouterCore {
|
|
|
337
356
|
let params = {};
|
|
338
357
|
const foundMask = this.options.routeMasks?.find((d) => {
|
|
339
358
|
const match = matchPathname(
|
|
340
|
-
this.basepath,
|
|
341
359
|
next.pathname,
|
|
342
360
|
{
|
|
343
361
|
to: d.from,
|
|
@@ -355,7 +373,7 @@ class RouterCore {
|
|
|
355
373
|
if (foundMask) {
|
|
356
374
|
const { from: _from, ...maskProps } = foundMask;
|
|
357
375
|
maskedDest = {
|
|
358
|
-
|
|
376
|
+
from: opts.from,
|
|
359
377
|
...maskProps,
|
|
360
378
|
params
|
|
361
379
|
};
|
|
@@ -370,7 +388,7 @@ class RouterCore {
|
|
|
370
388
|
};
|
|
371
389
|
if (opts.mask) {
|
|
372
390
|
return buildWithMatches(opts, {
|
|
373
|
-
|
|
391
|
+
from: opts.from,
|
|
374
392
|
...opts.mask
|
|
375
393
|
});
|
|
376
394
|
}
|
|
@@ -398,7 +416,7 @@ class RouterCore {
|
|
|
398
416
|
});
|
|
399
417
|
return isEqual;
|
|
400
418
|
};
|
|
401
|
-
const isSameUrl = this.latestLocation.href === next.href;
|
|
419
|
+
const isSameUrl = trimPathRight(this.latestLocation.href) === trimPathRight(next.href);
|
|
402
420
|
const previousCommitPromise = this.commitLocationPromise;
|
|
403
421
|
this.commitLocationPromise = createControlledPromise(() => {
|
|
404
422
|
previousCommitPromise?.resolve();
|
|
@@ -434,7 +452,7 @@ class RouterCore {
|
|
|
434
452
|
nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
|
|
435
453
|
this.shouldViewTransition = viewTransition;
|
|
436
454
|
this.history[next.replace ? "replace" : "push"](
|
|
437
|
-
nextHistory.
|
|
455
|
+
nextHistory.publicHref,
|
|
438
456
|
nextHistory.state,
|
|
439
457
|
{ ignoreBlocker }
|
|
440
458
|
);
|
|
@@ -487,7 +505,7 @@ class RouterCore {
|
|
|
487
505
|
if (reloadDocument) {
|
|
488
506
|
if (!href) {
|
|
489
507
|
const location = this.buildLocation({ to, ...rest });
|
|
490
|
-
href =
|
|
508
|
+
href = location.href;
|
|
491
509
|
}
|
|
492
510
|
if (rest.replace) {
|
|
493
511
|
window.location.replace(href);
|
|
@@ -505,7 +523,7 @@ class RouterCore {
|
|
|
505
523
|
};
|
|
506
524
|
this.beforeLoad = () => {
|
|
507
525
|
this.cancelMatches();
|
|
508
|
-
this.
|
|
526
|
+
this.updateLatestLocation();
|
|
509
527
|
if (this.isServer) {
|
|
510
528
|
const nextLocation = this.buildLocation({
|
|
511
529
|
to: this.latestLocation.pathname,
|
|
@@ -566,10 +584,12 @@ class RouterCore {
|
|
|
566
584
|
location: next
|
|
567
585
|
})
|
|
568
586
|
});
|
|
569
|
-
await
|
|
587
|
+
await loadMatches({
|
|
588
|
+
router: this,
|
|
570
589
|
sync: opts?.sync,
|
|
571
590
|
matches: this.state.pendingMatches,
|
|
572
591
|
location: next,
|
|
592
|
+
updateMatch: this.updateMatch,
|
|
573
593
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
574
594
|
onReady: async () => {
|
|
575
595
|
this.startViewTransition(async () => {
|
|
@@ -693,510 +713,13 @@ class RouterCore {
|
|
|
693
713
|
const findFn = (d) => d.id === matchId;
|
|
694
714
|
return this.state.cachedMatches.find(findFn) ?? this.state.pendingMatches?.find(findFn) ?? this.state.matches.find(findFn);
|
|
695
715
|
};
|
|
696
|
-
this.loadMatches = async ({
|
|
697
|
-
location,
|
|
698
|
-
matches,
|
|
699
|
-
preload: allPreload,
|
|
700
|
-
onReady,
|
|
701
|
-
updateMatch = this.updateMatch,
|
|
702
|
-
sync
|
|
703
|
-
}) => {
|
|
704
|
-
let firstBadMatchIndex;
|
|
705
|
-
let rendered = false;
|
|
706
|
-
const triggerOnReady = async () => {
|
|
707
|
-
if (!rendered) {
|
|
708
|
-
rendered = true;
|
|
709
|
-
await onReady?.();
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
const resolvePreload = (matchId) => {
|
|
713
|
-
return !!(allPreload && !this.state.matches.some((d) => d.id === matchId));
|
|
714
|
-
};
|
|
715
|
-
if (!this.isServer && this.state.matches.some((d) => d._forcePending)) {
|
|
716
|
-
triggerOnReady();
|
|
717
|
-
}
|
|
718
|
-
const handleRedirectAndNotFound = (match, err) => {
|
|
719
|
-
if (isRedirect(err) || isNotFound(err)) {
|
|
720
|
-
if (isRedirect(err)) {
|
|
721
|
-
if (err.redirectHandled) {
|
|
722
|
-
if (!err.options.reloadDocument) {
|
|
723
|
-
throw err;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
match.beforeLoadPromise?.resolve();
|
|
728
|
-
match.loaderPromise?.resolve();
|
|
729
|
-
updateMatch(match.id, (prev) => ({
|
|
730
|
-
...prev,
|
|
731
|
-
status: isRedirect(err) ? "redirected" : isNotFound(err) ? "notFound" : "error",
|
|
732
|
-
isFetching: false,
|
|
733
|
-
error: err,
|
|
734
|
-
beforeLoadPromise: void 0,
|
|
735
|
-
loaderPromise: void 0
|
|
736
|
-
}));
|
|
737
|
-
if (!err.routeId) {
|
|
738
|
-
err.routeId = match.routeId;
|
|
739
|
-
}
|
|
740
|
-
match.loadPromise?.resolve();
|
|
741
|
-
if (isRedirect(err)) {
|
|
742
|
-
rendered = true;
|
|
743
|
-
err.options._fromLocation = location;
|
|
744
|
-
err.redirectHandled = true;
|
|
745
|
-
err = this.resolveRedirect(err);
|
|
746
|
-
throw err;
|
|
747
|
-
} else if (isNotFound(err)) {
|
|
748
|
-
this._handleNotFound(matches, err, {
|
|
749
|
-
updateMatch
|
|
750
|
-
});
|
|
751
|
-
throw err;
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
};
|
|
755
|
-
const shouldSkipLoader = (matchId) => {
|
|
756
|
-
const match = this.getMatch(matchId);
|
|
757
|
-
if (!this.isServer && match._dehydrated) {
|
|
758
|
-
return true;
|
|
759
|
-
}
|
|
760
|
-
if (this.isServer) {
|
|
761
|
-
if (match.ssr === false) {
|
|
762
|
-
return true;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
return false;
|
|
766
|
-
};
|
|
767
|
-
try {
|
|
768
|
-
await new Promise((resolveAll, rejectAll) => {
|
|
769
|
-
;
|
|
770
|
-
(async () => {
|
|
771
|
-
try {
|
|
772
|
-
const handleSerialError = (index, err, routerCode) => {
|
|
773
|
-
const { id: matchId, routeId } = matches[index];
|
|
774
|
-
const route = this.looseRoutesById[routeId];
|
|
775
|
-
if (err instanceof Promise) {
|
|
776
|
-
throw err;
|
|
777
|
-
}
|
|
778
|
-
err.routerCode = routerCode;
|
|
779
|
-
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
780
|
-
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
781
|
-
try {
|
|
782
|
-
route.options.onError?.(err);
|
|
783
|
-
} catch (errorHandlerErr) {
|
|
784
|
-
err = errorHandlerErr;
|
|
785
|
-
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
786
|
-
}
|
|
787
|
-
updateMatch(matchId, (prev) => {
|
|
788
|
-
prev.beforeLoadPromise?.resolve();
|
|
789
|
-
prev.loadPromise?.resolve();
|
|
790
|
-
return {
|
|
791
|
-
...prev,
|
|
792
|
-
error: err,
|
|
793
|
-
status: "error",
|
|
794
|
-
isFetching: false,
|
|
795
|
-
updatedAt: Date.now(),
|
|
796
|
-
abortController: new AbortController(),
|
|
797
|
-
beforeLoadPromise: void 0
|
|
798
|
-
};
|
|
799
|
-
});
|
|
800
|
-
};
|
|
801
|
-
for (const [index, { id: matchId, routeId }] of matches.entries()) {
|
|
802
|
-
const existingMatch = this.getMatch(matchId);
|
|
803
|
-
const parentMatchId = matches[index - 1]?.id;
|
|
804
|
-
const parentMatch = parentMatchId ? this.getMatch(parentMatchId) : void 0;
|
|
805
|
-
const route = this.looseRoutesById[routeId];
|
|
806
|
-
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
807
|
-
if (this.isServer) {
|
|
808
|
-
let ssr;
|
|
809
|
-
if (this.isShell()) {
|
|
810
|
-
ssr = matchId === rootRouteId;
|
|
811
|
-
} else {
|
|
812
|
-
const defaultSsr = this.options.defaultSsr ?? true;
|
|
813
|
-
if (parentMatch?.ssr === false) {
|
|
814
|
-
ssr = false;
|
|
815
|
-
} else {
|
|
816
|
-
let tempSsr;
|
|
817
|
-
if (route.options.ssr === void 0) {
|
|
818
|
-
tempSsr = defaultSsr;
|
|
819
|
-
} else if (typeof route.options.ssr === "function") {
|
|
820
|
-
let makeMaybe = function(value, error) {
|
|
821
|
-
if (error) {
|
|
822
|
-
return { status: "error", error };
|
|
823
|
-
}
|
|
824
|
-
return { status: "success", value };
|
|
825
|
-
};
|
|
826
|
-
const { search, params } = this.getMatch(matchId);
|
|
827
|
-
const ssrFnContext = {
|
|
828
|
-
search: makeMaybe(search, existingMatch.searchError),
|
|
829
|
-
params: makeMaybe(params, existingMatch.paramsError),
|
|
830
|
-
location,
|
|
831
|
-
matches: matches.map((match) => ({
|
|
832
|
-
index: match.index,
|
|
833
|
-
pathname: match.pathname,
|
|
834
|
-
fullPath: match.fullPath,
|
|
835
|
-
staticData: match.staticData,
|
|
836
|
-
id: match.id,
|
|
837
|
-
routeId: match.routeId,
|
|
838
|
-
search: makeMaybe(match.search, match.searchError),
|
|
839
|
-
params: makeMaybe(match.params, match.paramsError),
|
|
840
|
-
ssr: match.ssr
|
|
841
|
-
}))
|
|
842
|
-
};
|
|
843
|
-
tempSsr = await route.options.ssr(ssrFnContext) ?? defaultSsr;
|
|
844
|
-
} else {
|
|
845
|
-
tempSsr = route.options.ssr;
|
|
846
|
-
}
|
|
847
|
-
if (tempSsr === true && parentMatch?.ssr === "data-only") {
|
|
848
|
-
ssr = "data-only";
|
|
849
|
-
} else {
|
|
850
|
-
ssr = tempSsr;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
updateMatch(matchId, (prev) => ({
|
|
855
|
-
...prev,
|
|
856
|
-
ssr
|
|
857
|
-
}));
|
|
858
|
-
}
|
|
859
|
-
if (shouldSkipLoader(matchId)) {
|
|
860
|
-
continue;
|
|
861
|
-
}
|
|
862
|
-
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));
|
|
863
|
-
let executeBeforeLoad = true;
|
|
864
|
-
const setupPendingTimeout = () => {
|
|
865
|
-
if (shouldPending && this.getMatch(matchId).pendingTimeout === void 0) {
|
|
866
|
-
const pendingTimeout = setTimeout(() => {
|
|
867
|
-
try {
|
|
868
|
-
triggerOnReady();
|
|
869
|
-
} catch {
|
|
870
|
-
}
|
|
871
|
-
}, pendingMs);
|
|
872
|
-
updateMatch(matchId, (prev) => ({
|
|
873
|
-
...prev,
|
|
874
|
-
pendingTimeout
|
|
875
|
-
}));
|
|
876
|
-
}
|
|
877
|
-
};
|
|
878
|
-
if (
|
|
879
|
-
// If we are in the middle of a load, either of these will be present
|
|
880
|
-
// (not to be confused with `loadPromise`, which is always defined)
|
|
881
|
-
existingMatch.beforeLoadPromise || existingMatch.loaderPromise
|
|
882
|
-
) {
|
|
883
|
-
setupPendingTimeout();
|
|
884
|
-
await existingMatch.beforeLoadPromise;
|
|
885
|
-
const match = this.getMatch(matchId);
|
|
886
|
-
if (match.status === "error") {
|
|
887
|
-
executeBeforeLoad = true;
|
|
888
|
-
} else if (match.preload && (match.status === "redirected" || match.status === "notFound")) {
|
|
889
|
-
handleRedirectAndNotFound(match, match.error);
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
if (executeBeforeLoad) {
|
|
893
|
-
try {
|
|
894
|
-
updateMatch(matchId, (prev) => {
|
|
895
|
-
const prevLoadPromise = prev.loadPromise;
|
|
896
|
-
return {
|
|
897
|
-
...prev,
|
|
898
|
-
loadPromise: createControlledPromise(() => {
|
|
899
|
-
prevLoadPromise?.resolve();
|
|
900
|
-
}),
|
|
901
|
-
beforeLoadPromise: createControlledPromise()
|
|
902
|
-
};
|
|
903
|
-
});
|
|
904
|
-
const { paramsError, searchError } = this.getMatch(matchId);
|
|
905
|
-
if (paramsError) {
|
|
906
|
-
handleSerialError(index, paramsError, "PARSE_PARAMS");
|
|
907
|
-
}
|
|
908
|
-
if (searchError) {
|
|
909
|
-
handleSerialError(index, searchError, "VALIDATE_SEARCH");
|
|
910
|
-
}
|
|
911
|
-
setupPendingTimeout();
|
|
912
|
-
const abortController = new AbortController();
|
|
913
|
-
const parentMatchContext = parentMatch?.context ?? this.options.context ?? {};
|
|
914
|
-
updateMatch(matchId, (prev) => ({
|
|
915
|
-
...prev,
|
|
916
|
-
isFetching: "beforeLoad",
|
|
917
|
-
fetchCount: prev.fetchCount + 1,
|
|
918
|
-
abortController,
|
|
919
|
-
context: {
|
|
920
|
-
...parentMatchContext,
|
|
921
|
-
...prev.__routeContext
|
|
922
|
-
}
|
|
923
|
-
}));
|
|
924
|
-
const { search, params, context, cause } = this.getMatch(matchId);
|
|
925
|
-
const preload = resolvePreload(matchId);
|
|
926
|
-
const beforeLoadFnContext = {
|
|
927
|
-
search,
|
|
928
|
-
abortController,
|
|
929
|
-
params,
|
|
930
|
-
preload,
|
|
931
|
-
context,
|
|
932
|
-
location,
|
|
933
|
-
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
934
|
-
buildLocation: this.buildLocation,
|
|
935
|
-
cause: preload ? "preload" : cause,
|
|
936
|
-
matches
|
|
937
|
-
};
|
|
938
|
-
const beforeLoadContext = await route.options.beforeLoad?.(beforeLoadFnContext);
|
|
939
|
-
if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
|
|
940
|
-
handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
|
|
941
|
-
}
|
|
942
|
-
updateMatch(matchId, (prev) => {
|
|
943
|
-
return {
|
|
944
|
-
...prev,
|
|
945
|
-
__beforeLoadContext: beforeLoadContext,
|
|
946
|
-
context: {
|
|
947
|
-
...parentMatchContext,
|
|
948
|
-
...prev.__routeContext,
|
|
949
|
-
...beforeLoadContext
|
|
950
|
-
},
|
|
951
|
-
abortController
|
|
952
|
-
};
|
|
953
|
-
});
|
|
954
|
-
} catch (err) {
|
|
955
|
-
handleSerialError(index, err, "BEFORE_LOAD");
|
|
956
|
-
}
|
|
957
|
-
updateMatch(matchId, (prev) => {
|
|
958
|
-
prev.beforeLoadPromise?.resolve();
|
|
959
|
-
return {
|
|
960
|
-
...prev,
|
|
961
|
-
beforeLoadPromise: void 0,
|
|
962
|
-
isFetching: false
|
|
963
|
-
};
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
968
|
-
const matchPromises = [];
|
|
969
|
-
validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
|
|
970
|
-
matchPromises.push(
|
|
971
|
-
(async () => {
|
|
972
|
-
let loaderShouldRunAsync = false;
|
|
973
|
-
let loaderIsRunningAsync = false;
|
|
974
|
-
const route = this.looseRoutesById[routeId];
|
|
975
|
-
const executeHead = async () => {
|
|
976
|
-
const match = this.getMatch(matchId);
|
|
977
|
-
if (!match) {
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
|
-
const assetContext = {
|
|
981
|
-
matches,
|
|
982
|
-
match,
|
|
983
|
-
params: match.params,
|
|
984
|
-
loaderData: match.loaderData
|
|
985
|
-
};
|
|
986
|
-
const headFnContent = await route.options.head?.(assetContext);
|
|
987
|
-
const meta = headFnContent?.meta;
|
|
988
|
-
const links = headFnContent?.links;
|
|
989
|
-
const headScripts = headFnContent?.scripts;
|
|
990
|
-
const styles = headFnContent?.styles;
|
|
991
|
-
const scripts = await route.options.scripts?.(assetContext);
|
|
992
|
-
const headers = await route.options.headers?.(assetContext);
|
|
993
|
-
return {
|
|
994
|
-
meta,
|
|
995
|
-
links,
|
|
996
|
-
headScripts,
|
|
997
|
-
headers,
|
|
998
|
-
scripts,
|
|
999
|
-
styles
|
|
1000
|
-
};
|
|
1001
|
-
};
|
|
1002
|
-
const potentialPendingMinPromise = async () => {
|
|
1003
|
-
const latestMatch = this.getMatch(matchId);
|
|
1004
|
-
if (latestMatch.minPendingPromise) {
|
|
1005
|
-
await latestMatch.minPendingPromise;
|
|
1006
|
-
}
|
|
1007
|
-
};
|
|
1008
|
-
const prevMatch = this.getMatch(matchId);
|
|
1009
|
-
if (shouldSkipLoader(matchId)) {
|
|
1010
|
-
if (this.isServer) {
|
|
1011
|
-
const head = await executeHead();
|
|
1012
|
-
updateMatch(matchId, (prev) => ({
|
|
1013
|
-
...prev,
|
|
1014
|
-
...head
|
|
1015
|
-
}));
|
|
1016
|
-
return this.getMatch(matchId);
|
|
1017
|
-
}
|
|
1018
|
-
} else if (prevMatch.loaderPromise) {
|
|
1019
|
-
if (prevMatch.status === "success" && !sync && !prevMatch.preload) {
|
|
1020
|
-
return this.getMatch(matchId);
|
|
1021
|
-
}
|
|
1022
|
-
await prevMatch.loaderPromise;
|
|
1023
|
-
const match = this.getMatch(matchId);
|
|
1024
|
-
if (match.error) {
|
|
1025
|
-
handleRedirectAndNotFound(match, match.error);
|
|
1026
|
-
}
|
|
1027
|
-
} else {
|
|
1028
|
-
const parentMatchPromise = matchPromises[index - 1];
|
|
1029
|
-
const getLoaderContext = () => {
|
|
1030
|
-
const {
|
|
1031
|
-
params,
|
|
1032
|
-
loaderDeps,
|
|
1033
|
-
abortController,
|
|
1034
|
-
context,
|
|
1035
|
-
cause
|
|
1036
|
-
} = this.getMatch(matchId);
|
|
1037
|
-
const preload2 = resolvePreload(matchId);
|
|
1038
|
-
return {
|
|
1039
|
-
params,
|
|
1040
|
-
deps: loaderDeps,
|
|
1041
|
-
preload: !!preload2,
|
|
1042
|
-
parentMatchPromise,
|
|
1043
|
-
abortController,
|
|
1044
|
-
context,
|
|
1045
|
-
location,
|
|
1046
|
-
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
1047
|
-
cause: preload2 ? "preload" : cause,
|
|
1048
|
-
route
|
|
1049
|
-
};
|
|
1050
|
-
};
|
|
1051
|
-
const age = Date.now() - this.getMatch(matchId).updatedAt;
|
|
1052
|
-
const preload = resolvePreload(matchId);
|
|
1053
|
-
const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
1054
|
-
const shouldReloadOption = route.options.shouldReload;
|
|
1055
|
-
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
|
|
1056
|
-
updateMatch(matchId, (prev) => ({
|
|
1057
|
-
...prev,
|
|
1058
|
-
loaderPromise: createControlledPromise(),
|
|
1059
|
-
preload: !!preload && !this.state.matches.some((d) => d.id === matchId)
|
|
1060
|
-
}));
|
|
1061
|
-
const runLoader = async () => {
|
|
1062
|
-
try {
|
|
1063
|
-
try {
|
|
1064
|
-
if (!this.isServer || this.isServer && this.getMatch(matchId).ssr === true) {
|
|
1065
|
-
this.loadRouteChunk(route);
|
|
1066
|
-
}
|
|
1067
|
-
updateMatch(matchId, (prev) => ({
|
|
1068
|
-
...prev,
|
|
1069
|
-
isFetching: "loader"
|
|
1070
|
-
}));
|
|
1071
|
-
const loaderData = await route.options.loader?.(getLoaderContext());
|
|
1072
|
-
handleRedirectAndNotFound(
|
|
1073
|
-
this.getMatch(matchId),
|
|
1074
|
-
loaderData
|
|
1075
|
-
);
|
|
1076
|
-
updateMatch(matchId, (prev) => ({
|
|
1077
|
-
...prev,
|
|
1078
|
-
loaderData
|
|
1079
|
-
}));
|
|
1080
|
-
await route._lazyPromise;
|
|
1081
|
-
const head = await executeHead();
|
|
1082
|
-
await potentialPendingMinPromise();
|
|
1083
|
-
await route._componentsPromise;
|
|
1084
|
-
updateMatch(matchId, (prev) => ({
|
|
1085
|
-
...prev,
|
|
1086
|
-
error: void 0,
|
|
1087
|
-
status: "success",
|
|
1088
|
-
isFetching: false,
|
|
1089
|
-
updatedAt: Date.now(),
|
|
1090
|
-
...head
|
|
1091
|
-
}));
|
|
1092
|
-
} catch (e) {
|
|
1093
|
-
let error = e;
|
|
1094
|
-
await potentialPendingMinPromise();
|
|
1095
|
-
handleRedirectAndNotFound(this.getMatch(matchId), e);
|
|
1096
|
-
try {
|
|
1097
|
-
route.options.onError?.(e);
|
|
1098
|
-
} catch (onErrorError) {
|
|
1099
|
-
error = onErrorError;
|
|
1100
|
-
handleRedirectAndNotFound(
|
|
1101
|
-
this.getMatch(matchId),
|
|
1102
|
-
onErrorError
|
|
1103
|
-
);
|
|
1104
|
-
}
|
|
1105
|
-
const head = await executeHead();
|
|
1106
|
-
updateMatch(matchId, (prev) => ({
|
|
1107
|
-
...prev,
|
|
1108
|
-
error,
|
|
1109
|
-
status: "error",
|
|
1110
|
-
isFetching: false,
|
|
1111
|
-
...head
|
|
1112
|
-
}));
|
|
1113
|
-
}
|
|
1114
|
-
} catch (err) {
|
|
1115
|
-
const head = await executeHead();
|
|
1116
|
-
updateMatch(matchId, (prev) => ({
|
|
1117
|
-
...prev,
|
|
1118
|
-
loaderPromise: void 0,
|
|
1119
|
-
...head
|
|
1120
|
-
}));
|
|
1121
|
-
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
1122
|
-
}
|
|
1123
|
-
};
|
|
1124
|
-
const { status, invalid } = this.getMatch(matchId);
|
|
1125
|
-
loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
|
|
1126
|
-
if (preload && route.options.preload === false) {
|
|
1127
|
-
} else if (loaderShouldRunAsync && !sync) {
|
|
1128
|
-
loaderIsRunningAsync = true;
|
|
1129
|
-
(async () => {
|
|
1130
|
-
try {
|
|
1131
|
-
await runLoader();
|
|
1132
|
-
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1133
|
-
loaderPromise?.resolve();
|
|
1134
|
-
loadPromise?.resolve();
|
|
1135
|
-
updateMatch(matchId, (prev) => ({
|
|
1136
|
-
...prev,
|
|
1137
|
-
loaderPromise: void 0
|
|
1138
|
-
}));
|
|
1139
|
-
} catch (err) {
|
|
1140
|
-
if (isRedirect(err)) {
|
|
1141
|
-
await this.navigate(err.options);
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
})();
|
|
1145
|
-
} else if (status !== "success" || loaderShouldRunAsync && sync) {
|
|
1146
|
-
await runLoader();
|
|
1147
|
-
} else {
|
|
1148
|
-
const head = await executeHead();
|
|
1149
|
-
updateMatch(matchId, (prev) => ({
|
|
1150
|
-
...prev,
|
|
1151
|
-
...head
|
|
1152
|
-
}));
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
if (!loaderIsRunningAsync) {
|
|
1156
|
-
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1157
|
-
loaderPromise?.resolve();
|
|
1158
|
-
loadPromise?.resolve();
|
|
1159
|
-
}
|
|
1160
|
-
updateMatch(matchId, (prev) => {
|
|
1161
|
-
clearTimeout(prev.pendingTimeout);
|
|
1162
|
-
return {
|
|
1163
|
-
...prev,
|
|
1164
|
-
isFetching: loaderIsRunningAsync ? prev.isFetching : false,
|
|
1165
|
-
loaderPromise: loaderIsRunningAsync ? prev.loaderPromise : void 0,
|
|
1166
|
-
invalid: false,
|
|
1167
|
-
pendingTimeout: void 0,
|
|
1168
|
-
_dehydrated: void 0
|
|
1169
|
-
};
|
|
1170
|
-
});
|
|
1171
|
-
return this.getMatch(matchId);
|
|
1172
|
-
})()
|
|
1173
|
-
);
|
|
1174
|
-
});
|
|
1175
|
-
await Promise.all(matchPromises);
|
|
1176
|
-
resolveAll();
|
|
1177
|
-
} catch (err) {
|
|
1178
|
-
rejectAll(err);
|
|
1179
|
-
}
|
|
1180
|
-
})();
|
|
1181
|
-
});
|
|
1182
|
-
await triggerOnReady();
|
|
1183
|
-
} catch (err) {
|
|
1184
|
-
if (isRedirect(err) || isNotFound(err)) {
|
|
1185
|
-
if (isNotFound(err) && !allPreload) {
|
|
1186
|
-
await triggerOnReady();
|
|
1187
|
-
}
|
|
1188
|
-
throw err;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
return matches;
|
|
1192
|
-
};
|
|
1193
716
|
this.invalidate = (opts) => {
|
|
1194
717
|
const invalidate = (d) => {
|
|
1195
718
|
if (opts?.filter?.(d) ?? true) {
|
|
1196
719
|
return {
|
|
1197
720
|
...d,
|
|
1198
721
|
invalid: true,
|
|
1199
|
-
...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } :
|
|
722
|
+
...opts?.forcePending || d.status === "error" ? { status: "pending", error: void 0 } : void 0
|
|
1200
723
|
};
|
|
1201
724
|
}
|
|
1202
725
|
return d;
|
|
@@ -1254,31 +777,7 @@ class RouterCore {
|
|
|
1254
777
|
};
|
|
1255
778
|
this.clearCache({ filter });
|
|
1256
779
|
};
|
|
1257
|
-
this.loadRouteChunk =
|
|
1258
|
-
if (route._lazyPromise === void 0) {
|
|
1259
|
-
if (route.lazyFn) {
|
|
1260
|
-
route._lazyPromise = route.lazyFn().then((lazyRoute) => {
|
|
1261
|
-
const { id: _id, ...options2 } = lazyRoute.options;
|
|
1262
|
-
Object.assign(route.options, options2);
|
|
1263
|
-
});
|
|
1264
|
-
} else {
|
|
1265
|
-
route._lazyPromise = Promise.resolve();
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
if (route._componentsPromise === void 0) {
|
|
1269
|
-
route._componentsPromise = route._lazyPromise.then(
|
|
1270
|
-
() => Promise.all(
|
|
1271
|
-
componentTypes.map(async (type) => {
|
|
1272
|
-
const component = route.options[type];
|
|
1273
|
-
if (component?.preload) {
|
|
1274
|
-
await component.preload();
|
|
1275
|
-
}
|
|
1276
|
-
})
|
|
1277
|
-
)
|
|
1278
|
-
);
|
|
1279
|
-
}
|
|
1280
|
-
return route._componentsPromise;
|
|
1281
|
-
};
|
|
780
|
+
this.loadRouteChunk = loadRouteChunk;
|
|
1282
781
|
this.preloadRoute = async (opts) => {
|
|
1283
782
|
const next = this.buildLocation(opts);
|
|
1284
783
|
let matches = this.matchRoutes(next, {
|
|
@@ -1306,7 +805,8 @@ class RouterCore {
|
|
|
1306
805
|
});
|
|
1307
806
|
});
|
|
1308
807
|
try {
|
|
1309
|
-
matches = await
|
|
808
|
+
matches = await loadMatches({
|
|
809
|
+
router: this,
|
|
1310
810
|
matches,
|
|
1311
811
|
location: next,
|
|
1312
812
|
preload: true,
|
|
@@ -1352,7 +852,6 @@ class RouterCore {
|
|
|
1352
852
|
const pending = opts?.pending === void 0 ? !this.state.isLoading : opts.pending;
|
|
1353
853
|
const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
|
|
1354
854
|
const match = matchPathname(
|
|
1355
|
-
this.basepath,
|
|
1356
855
|
baseLocation.pathname,
|
|
1357
856
|
{
|
|
1358
857
|
...opts,
|
|
@@ -1373,39 +872,6 @@ class RouterCore {
|
|
|
1373
872
|
}
|
|
1374
873
|
return match;
|
|
1375
874
|
};
|
|
1376
|
-
this._handleNotFound = (matches, err, {
|
|
1377
|
-
updateMatch = this.updateMatch
|
|
1378
|
-
} = {}) => {
|
|
1379
|
-
const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
|
|
1380
|
-
const matchesByRouteId = {};
|
|
1381
|
-
for (const match of matches) {
|
|
1382
|
-
matchesByRouteId[match.routeId] = match;
|
|
1383
|
-
}
|
|
1384
|
-
if (!routeCursor.options.notFoundComponent && this.options?.defaultNotFoundComponent) {
|
|
1385
|
-
routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
|
|
1386
|
-
}
|
|
1387
|
-
invariant(
|
|
1388
|
-
routeCursor.options.notFoundComponent,
|
|
1389
|
-
"No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router."
|
|
1390
|
-
);
|
|
1391
|
-
const matchForRoute = matchesByRouteId[routeCursor.id];
|
|
1392
|
-
invariant(
|
|
1393
|
-
matchForRoute,
|
|
1394
|
-
"Could not find match for route: " + routeCursor.id
|
|
1395
|
-
);
|
|
1396
|
-
updateMatch(matchForRoute.id, (prev) => ({
|
|
1397
|
-
...prev,
|
|
1398
|
-
status: "notFound",
|
|
1399
|
-
error: err,
|
|
1400
|
-
isFetching: false
|
|
1401
|
-
}));
|
|
1402
|
-
if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
|
|
1403
|
-
err.routeId = routeCursor.parentRoute.id;
|
|
1404
|
-
this._handleNotFound(matches, err, {
|
|
1405
|
-
updateMatch
|
|
1406
|
-
});
|
|
1407
|
-
}
|
|
1408
|
-
};
|
|
1409
875
|
this.hasNotFoundMatch = () => {
|
|
1410
876
|
return this.__store.state.matches.some(
|
|
1411
877
|
(d) => d.status === "notFound" || d.globalNotFound
|
|
@@ -1493,16 +959,16 @@ class RouterCore {
|
|
|
1493
959
|
const matches = [];
|
|
1494
960
|
const getParentContext = (parentMatch) => {
|
|
1495
961
|
const parentMatchId = parentMatch?.id;
|
|
1496
|
-
const parentContext = !parentMatchId ? this.options.context ??
|
|
962
|
+
const parentContext = !parentMatchId ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
|
|
1497
963
|
return parentContext;
|
|
1498
964
|
};
|
|
1499
965
|
matchedRoutes.forEach((route, index) => {
|
|
1500
966
|
const parentMatch = matches[index - 1];
|
|
1501
967
|
const [preMatchSearch, strictMatchSearch, searchError] = (() => {
|
|
1502
968
|
const parentSearch = parentMatch?.search ?? next.search;
|
|
1503
|
-
const parentStrictSearch = parentMatch?._strictSearch ??
|
|
969
|
+
const parentStrictSearch = parentMatch?._strictSearch ?? void 0;
|
|
1504
970
|
try {
|
|
1505
|
-
const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ??
|
|
971
|
+
const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? void 0;
|
|
1506
972
|
return [
|
|
1507
973
|
{
|
|
1508
974
|
...parentSearch,
|
|
@@ -1563,7 +1029,7 @@ class RouterCore {
|
|
|
1563
1029
|
routeId: route.id,
|
|
1564
1030
|
params: previousMatch ? replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
|
|
1565
1031
|
_strictParams: usedParams,
|
|
1566
|
-
pathname:
|
|
1032
|
+
pathname: interpolatedPath,
|
|
1567
1033
|
updatedAt: Date.now(),
|
|
1568
1034
|
search: previousMatch ? replaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
|
|
1569
1035
|
_strictSearch: strictMatchSearch,
|
|
@@ -1572,7 +1038,10 @@ class RouterCore {
|
|
|
1572
1038
|
isFetching: false,
|
|
1573
1039
|
error: void 0,
|
|
1574
1040
|
paramsError: parseErrors[index],
|
|
1575
|
-
__routeContext:
|
|
1041
|
+
__routeContext: void 0,
|
|
1042
|
+
_nonReactive: {
|
|
1043
|
+
loadPromise: createControlledPromise()
|
|
1044
|
+
},
|
|
1576
1045
|
__beforeLoadContext: void 0,
|
|
1577
1046
|
context: {},
|
|
1578
1047
|
abortController: new AbortController(),
|
|
@@ -1586,7 +1055,6 @@ class RouterCore {
|
|
|
1586
1055
|
headScripts: void 0,
|
|
1587
1056
|
meta: void 0,
|
|
1588
1057
|
staticData: route.options.staticData || {},
|
|
1589
|
-
loadPromise: createControlledPromise(),
|
|
1590
1058
|
fullPath: route.fullPath
|
|
1591
1059
|
};
|
|
1592
1060
|
}
|
|
@@ -1608,19 +1076,21 @@ class RouterCore {
|
|
|
1608
1076
|
if (!existingMatch && opts?._buildLocation !== true) {
|
|
1609
1077
|
const parentMatch = matches[index - 1];
|
|
1610
1078
|
const parentContext = getParentContext(parentMatch);
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1079
|
+
if (route.options.context) {
|
|
1080
|
+
const contextFnContext = {
|
|
1081
|
+
deps: match.loaderDeps,
|
|
1082
|
+
params: match.params,
|
|
1083
|
+
context: parentContext ?? {},
|
|
1084
|
+
location: next,
|
|
1085
|
+
navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
|
|
1086
|
+
buildLocation: this.buildLocation,
|
|
1087
|
+
cause: match.cause,
|
|
1088
|
+
abortController: match.abortController,
|
|
1089
|
+
preload: !!match.preload,
|
|
1090
|
+
matches
|
|
1091
|
+
};
|
|
1092
|
+
match.__routeContext = route.options.context(contextFnContext) ?? void 0;
|
|
1093
|
+
}
|
|
1624
1094
|
match.context = {
|
|
1625
1095
|
...parentContext,
|
|
1626
1096
|
...match.__routeContext,
|
|
@@ -1679,20 +1149,6 @@ function validateSearch(validateSearch2, input) {
|
|
|
1679
1149
|
}
|
|
1680
1150
|
return {};
|
|
1681
1151
|
}
|
|
1682
|
-
const componentTypes = [
|
|
1683
|
-
"component",
|
|
1684
|
-
"errorComponent",
|
|
1685
|
-
"pendingComponent",
|
|
1686
|
-
"notFoundComponent"
|
|
1687
|
-
];
|
|
1688
|
-
function routeNeedsPreload(route) {
|
|
1689
|
-
for (const componentType of componentTypes) {
|
|
1690
|
-
if (route.options[componentType]?.preload) {
|
|
1691
|
-
return true;
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
return false;
|
|
1695
|
-
}
|
|
1696
1152
|
const REQUIRED_PARAM_BASE_SCORE = 0.5;
|
|
1697
1153
|
const OPTIONAL_PARAM_BASE_SCORE = 0.4;
|
|
1698
1154
|
const WILDCARD_PARAM_BASE_SCORE = 0.25;
|
|
@@ -1825,7 +1281,6 @@ function processRouteTree({
|
|
|
1825
1281
|
function getMatchedRoutes({
|
|
1826
1282
|
pathname,
|
|
1827
1283
|
routePathname,
|
|
1828
|
-
basepath,
|
|
1829
1284
|
caseSensitive,
|
|
1830
1285
|
routesByPath,
|
|
1831
1286
|
routesById,
|
|
@@ -1836,7 +1291,6 @@ function getMatchedRoutes({
|
|
|
1836
1291
|
const trimmedPath = trimPathRight(pathname);
|
|
1837
1292
|
const getMatchedParams = (route) => {
|
|
1838
1293
|
const result = matchPathname(
|
|
1839
|
-
basepath,
|
|
1840
1294
|
trimmedPath,
|
|
1841
1295
|
{
|
|
1842
1296
|
to: route.fullPath,
|
|
@@ -1923,7 +1377,7 @@ function applySearchMiddleware({
|
|
|
1923
1377
|
try {
|
|
1924
1378
|
const validatedSearch = {
|
|
1925
1379
|
...result,
|
|
1926
|
-
...validateSearch(route.options.validateSearch, result) ??
|
|
1380
|
+
...validateSearch(route.options.validateSearch, result) ?? void 0
|
|
1927
1381
|
};
|
|
1928
1382
|
return validatedSearch;
|
|
1929
1383
|
} catch {
|
|
@@ -1962,7 +1416,6 @@ export {
|
|
|
1962
1416
|
PathParamError,
|
|
1963
1417
|
RouterCore,
|
|
1964
1418
|
SearchParamError,
|
|
1965
|
-
componentTypes,
|
|
1966
1419
|
defaultSerializeError,
|
|
1967
1420
|
getInitialRouterState,
|
|
1968
1421
|
getLocationChangeInfo,
|