@tanstack/router-core 1.114.24 → 1.114.25
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/history.d.cts +8 -0
- package/dist/cjs/index.cjs +6 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -2
- package/dist/cjs/router.cjs +1695 -0
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +117 -55
- package/dist/esm/history.d.ts +8 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +7 -1
- package/dist/esm/router.d.ts +117 -55
- package/dist/esm/router.js +1696 -1
- package/dist/esm/router.js.map +1 -1
- package/package.json +2 -1
- package/src/history.ts +9 -0
- package/src/index.ts +11 -2
- package/src/router.ts +2511 -106
package/dist/cjs/router.cjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const store = require("@tanstack/store");
|
|
4
|
+
const history = require("@tanstack/history");
|
|
5
|
+
const invariant = require("tiny-invariant");
|
|
6
|
+
const utils = require("./utils.cjs");
|
|
7
|
+
const path = require("./path.cjs");
|
|
8
|
+
const notFound = require("./not-found.cjs");
|
|
9
|
+
const scrollRestoration = require("./scroll-restoration.cjs");
|
|
10
|
+
const searchParams = require("./searchParams.cjs");
|
|
11
|
+
const root = require("./root.cjs");
|
|
12
|
+
const redirect = require("./redirect.cjs");
|
|
3
13
|
function defaultSerializeError(err) {
|
|
4
14
|
if (err instanceof Error) {
|
|
5
15
|
const obj = {
|
|
@@ -23,6 +33,1691 @@ function getLocationChangeInfo(routerState) {
|
|
|
23
33
|
const hashChanged = (fromLocation == null ? void 0 : fromLocation.hash) !== toLocation.hash;
|
|
24
34
|
return { fromLocation, toLocation, pathChanged, hrefChanged, hashChanged };
|
|
25
35
|
}
|
|
36
|
+
class RouterCore {
|
|
37
|
+
/**
|
|
38
|
+
* @deprecated Use the `createRouter` function instead
|
|
39
|
+
*/
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.tempLocationKey = `${Math.round(
|
|
42
|
+
Math.random() * 1e7
|
|
43
|
+
)}`;
|
|
44
|
+
this.resetNextScroll = true;
|
|
45
|
+
this.shouldViewTransition = void 0;
|
|
46
|
+
this.isViewTransitionTypesSupported = void 0;
|
|
47
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
|
48
|
+
this.isScrollRestoring = false;
|
|
49
|
+
this.isScrollRestorationSetup = false;
|
|
50
|
+
this.startTransition = (fn) => fn();
|
|
51
|
+
this.update = (newOptions) => {
|
|
52
|
+
var _a;
|
|
53
|
+
if (newOptions.notFoundRoute) {
|
|
54
|
+
console.warn(
|
|
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."
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const previousOptions = this.options;
|
|
59
|
+
this.options = {
|
|
60
|
+
...this.options,
|
|
61
|
+
...newOptions
|
|
62
|
+
};
|
|
63
|
+
this.isServer = this.options.isServer ?? typeof document === "undefined";
|
|
64
|
+
this.pathParamsDecodeCharMap = this.options.pathParamsAllowedCharacters ? new Map(
|
|
65
|
+
this.options.pathParamsAllowedCharacters.map((char) => [
|
|
66
|
+
encodeURIComponent(char),
|
|
67
|
+
char
|
|
68
|
+
])
|
|
69
|
+
) : void 0;
|
|
70
|
+
if (!this.basepath || newOptions.basepath && newOptions.basepath !== previousOptions.basepath) {
|
|
71
|
+
if (newOptions.basepath === void 0 || newOptions.basepath === "" || newOptions.basepath === "/") {
|
|
72
|
+
this.basepath = "/";
|
|
73
|
+
} else {
|
|
74
|
+
this.basepath = `/${path.trimPath(newOptions.basepath)}`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
79
|
+
!this.history || this.options.history && this.options.history !== this.history
|
|
80
|
+
) {
|
|
81
|
+
this.history = this.options.history ?? (this.isServer ? history.createMemoryHistory({
|
|
82
|
+
initialEntries: [this.basepath || "/"]
|
|
83
|
+
}) : history.createBrowserHistory());
|
|
84
|
+
this.latestLocation = this.parseLocation();
|
|
85
|
+
}
|
|
86
|
+
if (this.options.routeTree !== this.routeTree) {
|
|
87
|
+
this.routeTree = this.options.routeTree;
|
|
88
|
+
this.buildRouteTree();
|
|
89
|
+
}
|
|
90
|
+
if (!this.__store) {
|
|
91
|
+
this.__store = new store.Store(getInitialRouterState(this.latestLocation), {
|
|
92
|
+
onUpdate: () => {
|
|
93
|
+
this.__store.state = {
|
|
94
|
+
...this.state,
|
|
95
|
+
cachedMatches: this.state.cachedMatches.filter(
|
|
96
|
+
(d) => !["redirected"].includes(d.status)
|
|
97
|
+
)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
scrollRestoration.setupScrollRestoration(this);
|
|
102
|
+
}
|
|
103
|
+
if (typeof window !== "undefined" && "CSS" in window && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
104
|
+
typeof ((_a = window.CSS) == null ? void 0 : _a.supports) === "function") {
|
|
105
|
+
this.isViewTransitionTypesSupported = window.CSS.supports(
|
|
106
|
+
"selector(:active-view-transition-type(a)"
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
this.buildRouteTree = () => {
|
|
111
|
+
this.routesById = {};
|
|
112
|
+
this.routesByPath = {};
|
|
113
|
+
const notFoundRoute = this.options.notFoundRoute;
|
|
114
|
+
if (notFoundRoute) {
|
|
115
|
+
notFoundRoute.init({
|
|
116
|
+
originalIndex: 99999999999,
|
|
117
|
+
defaultSsr: this.options.defaultSsr
|
|
118
|
+
});
|
|
119
|
+
this.routesById[notFoundRoute.id] = notFoundRoute;
|
|
120
|
+
}
|
|
121
|
+
const recurseRoutes = (childRoutes) => {
|
|
122
|
+
childRoutes.forEach((childRoute, i) => {
|
|
123
|
+
childRoute.init({
|
|
124
|
+
originalIndex: i,
|
|
125
|
+
defaultSsr: this.options.defaultSsr
|
|
126
|
+
});
|
|
127
|
+
const existingRoute = this.routesById[childRoute.id];
|
|
128
|
+
invariant(
|
|
129
|
+
!existingRoute,
|
|
130
|
+
`Duplicate routes found with id: ${String(childRoute.id)}`
|
|
131
|
+
);
|
|
132
|
+
this.routesById[childRoute.id] = childRoute;
|
|
133
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
134
|
+
const trimmedFullPath = path.trimPathRight(childRoute.fullPath);
|
|
135
|
+
if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
|
|
136
|
+
this.routesByPath[trimmedFullPath] = childRoute;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const children = childRoute.children;
|
|
140
|
+
if (children == null ? void 0 : children.length) {
|
|
141
|
+
recurseRoutes(children);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
recurseRoutes([this.routeTree]);
|
|
146
|
+
const scoredRoutes = [];
|
|
147
|
+
const routes = Object.values(this.routesById);
|
|
148
|
+
routes.forEach((d, i) => {
|
|
149
|
+
var _a;
|
|
150
|
+
if (d.isRoot || !d.path) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const trimmed = path.trimPathLeft(d.fullPath);
|
|
154
|
+
const parsed = path.parsePathname(trimmed);
|
|
155
|
+
while (parsed.length > 1 && ((_a = parsed[0]) == null ? void 0 : _a.value) === "/") {
|
|
156
|
+
parsed.shift();
|
|
157
|
+
}
|
|
158
|
+
const scores = parsed.map((segment) => {
|
|
159
|
+
if (segment.value === "/") {
|
|
160
|
+
return 0.75;
|
|
161
|
+
}
|
|
162
|
+
if (segment.type === "param") {
|
|
163
|
+
return 0.5;
|
|
164
|
+
}
|
|
165
|
+
if (segment.type === "wildcard") {
|
|
166
|
+
return 0.25;
|
|
167
|
+
}
|
|
168
|
+
return 1;
|
|
169
|
+
});
|
|
170
|
+
scoredRoutes.push({ child: d, trimmed, parsed, index: i, scores });
|
|
171
|
+
});
|
|
172
|
+
this.flatRoutes = scoredRoutes.sort((a, b) => {
|
|
173
|
+
const minLength = Math.min(a.scores.length, b.scores.length);
|
|
174
|
+
for (let i = 0; i < minLength; i++) {
|
|
175
|
+
if (a.scores[i] !== b.scores[i]) {
|
|
176
|
+
return b.scores[i] - a.scores[i];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (a.scores.length !== b.scores.length) {
|
|
180
|
+
return b.scores.length - a.scores.length;
|
|
181
|
+
}
|
|
182
|
+
for (let i = 0; i < minLength; i++) {
|
|
183
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
184
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return a.index - b.index;
|
|
188
|
+
}).map((d, i) => {
|
|
189
|
+
d.child.rank = i;
|
|
190
|
+
return d.child;
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
this.subscribe = (eventType, fn) => {
|
|
194
|
+
const listener = {
|
|
195
|
+
eventType,
|
|
196
|
+
fn
|
|
197
|
+
};
|
|
198
|
+
this.subscribers.add(listener);
|
|
199
|
+
return () => {
|
|
200
|
+
this.subscribers.delete(listener);
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
this.emit = (routerEvent) => {
|
|
204
|
+
this.subscribers.forEach((listener) => {
|
|
205
|
+
if (listener.eventType === routerEvent.type) {
|
|
206
|
+
listener.fn(routerEvent);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
this.parseLocation = (previousLocation, locationToParse) => {
|
|
211
|
+
const parse = ({
|
|
212
|
+
pathname,
|
|
213
|
+
search,
|
|
214
|
+
hash,
|
|
215
|
+
state
|
|
216
|
+
}) => {
|
|
217
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
218
|
+
const searchStr = this.options.stringifySearch(parsedSearch);
|
|
219
|
+
return {
|
|
220
|
+
pathname,
|
|
221
|
+
searchStr,
|
|
222
|
+
search: utils.replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
|
|
223
|
+
hash: hash.split("#").reverse()[0] ?? "",
|
|
224
|
+
href: `${pathname}${searchStr}${hash}`,
|
|
225
|
+
state: utils.replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.state, state)
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
const location = parse(locationToParse ?? this.history.location);
|
|
229
|
+
const { __tempLocation, __tempKey } = location.state;
|
|
230
|
+
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
231
|
+
const parsedTempLocation = parse(__tempLocation);
|
|
232
|
+
parsedTempLocation.state.key = location.state.key;
|
|
233
|
+
delete parsedTempLocation.state.__tempLocation;
|
|
234
|
+
return {
|
|
235
|
+
...parsedTempLocation,
|
|
236
|
+
maskedLocation: location
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return location;
|
|
240
|
+
};
|
|
241
|
+
this.resolvePathWithBase = (from, path$1) => {
|
|
242
|
+
const resolvedPath = path.resolvePath({
|
|
243
|
+
basepath: this.basepath,
|
|
244
|
+
base: from,
|
|
245
|
+
to: path.cleanPath(path$1),
|
|
246
|
+
trailingSlash: this.options.trailingSlash,
|
|
247
|
+
caseSensitive: this.options.caseSensitive
|
|
248
|
+
});
|
|
249
|
+
return resolvedPath;
|
|
250
|
+
};
|
|
251
|
+
this.matchRoutes = (pathnameOrNext, locationSearchOrOpts, opts) => {
|
|
252
|
+
if (typeof pathnameOrNext === "string") {
|
|
253
|
+
return this.matchRoutesInternal(
|
|
254
|
+
{
|
|
255
|
+
pathname: pathnameOrNext,
|
|
256
|
+
search: locationSearchOrOpts
|
|
257
|
+
},
|
|
258
|
+
opts
|
|
259
|
+
);
|
|
260
|
+
} else {
|
|
261
|
+
return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
this.getMatchedRoutes = (next, dest) => {
|
|
265
|
+
let routeParams = {};
|
|
266
|
+
const trimmedPath = path.trimPathRight(next.pathname);
|
|
267
|
+
const getMatchedParams = (route) => {
|
|
268
|
+
const result = path.matchPathname(this.basepath, trimmedPath, {
|
|
269
|
+
to: route.fullPath,
|
|
270
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
|
|
271
|
+
fuzzy: true
|
|
272
|
+
});
|
|
273
|
+
return result;
|
|
274
|
+
};
|
|
275
|
+
let foundRoute = (dest == null ? void 0 : dest.to) !== void 0 ? this.routesByPath[dest.to] : void 0;
|
|
276
|
+
if (foundRoute) {
|
|
277
|
+
routeParams = getMatchedParams(foundRoute);
|
|
278
|
+
} else {
|
|
279
|
+
foundRoute = this.flatRoutes.find((route) => {
|
|
280
|
+
const matchedParams = getMatchedParams(route);
|
|
281
|
+
if (matchedParams) {
|
|
282
|
+
routeParams = matchedParams;
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
let routeCursor = foundRoute || this.routesById[root.rootRouteId];
|
|
289
|
+
const matchedRoutes = [routeCursor];
|
|
290
|
+
while (routeCursor.parentRoute) {
|
|
291
|
+
routeCursor = routeCursor.parentRoute;
|
|
292
|
+
matchedRoutes.unshift(routeCursor);
|
|
293
|
+
}
|
|
294
|
+
return { matchedRoutes, routeParams, foundRoute };
|
|
295
|
+
};
|
|
296
|
+
this.cancelMatch = (id) => {
|
|
297
|
+
const match = this.getMatch(id);
|
|
298
|
+
if (!match) return;
|
|
299
|
+
match.abortController.abort();
|
|
300
|
+
clearTimeout(match.pendingTimeout);
|
|
301
|
+
};
|
|
302
|
+
this.cancelMatches = () => {
|
|
303
|
+
var _a;
|
|
304
|
+
(_a = this.state.pendingMatches) == null ? void 0 : _a.forEach((match) => {
|
|
305
|
+
this.cancelMatch(match.id);
|
|
306
|
+
});
|
|
307
|
+
};
|
|
308
|
+
this.buildLocation = (opts) => {
|
|
309
|
+
const build = (dest = {}, matchedRoutesResult) => {
|
|
310
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
311
|
+
const fromMatches = dest._fromLocation ? this.matchRoutes(dest._fromLocation, { _buildLocation: true }) : this.state.matches;
|
|
312
|
+
const fromMatch = dest.from != null ? fromMatches.find(
|
|
313
|
+
(d) => path.matchPathname(this.basepath, path.trimPathRight(d.pathname), {
|
|
314
|
+
to: dest.from,
|
|
315
|
+
caseSensitive: false,
|
|
316
|
+
fuzzy: false
|
|
317
|
+
})
|
|
318
|
+
) : void 0;
|
|
319
|
+
const fromPath = (fromMatch == null ? void 0 : fromMatch.pathname) || this.latestLocation.pathname;
|
|
320
|
+
invariant(
|
|
321
|
+
dest.from == null || fromMatch != null,
|
|
322
|
+
"Could not find match for from: " + dest.from
|
|
323
|
+
);
|
|
324
|
+
const fromSearch = ((_a = this.state.pendingMatches) == null ? void 0 : _a.length) ? (_b = utils.last(this.state.pendingMatches)) == null ? void 0 : _b.search : ((_c = utils.last(fromMatches)) == null ? void 0 : _c.search) || this.latestLocation.search;
|
|
325
|
+
const stayingMatches = matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.filter(
|
|
326
|
+
(d) => fromMatches.find((e) => e.routeId === d.id)
|
|
327
|
+
);
|
|
328
|
+
let pathname;
|
|
329
|
+
if (dest.to) {
|
|
330
|
+
const resolvePathTo = (fromMatch == null ? void 0 : fromMatch.fullPath) || ((_d = utils.last(fromMatches)) == null ? void 0 : _d.fullPath) || this.latestLocation.pathname;
|
|
331
|
+
pathname = this.resolvePathWithBase(resolvePathTo, `${dest.to}`);
|
|
332
|
+
} else {
|
|
333
|
+
const fromRouteByFromPathRouteId = this.routesById[(_e = stayingMatches == null ? void 0 : stayingMatches.find((route) => {
|
|
334
|
+
const interpolatedPath = path.interpolatePath({
|
|
335
|
+
path: route.fullPath,
|
|
336
|
+
params: (matchedRoutesResult == null ? void 0 : matchedRoutesResult.routeParams) ?? {},
|
|
337
|
+
decodeCharMap: this.pathParamsDecodeCharMap
|
|
338
|
+
}).interpolatedPath;
|
|
339
|
+
const pathname2 = path.joinPaths([this.basepath, interpolatedPath]);
|
|
340
|
+
return pathname2 === fromPath;
|
|
341
|
+
})) == null ? void 0 : _e.id];
|
|
342
|
+
pathname = this.resolvePathWithBase(
|
|
343
|
+
fromPath,
|
|
344
|
+
(fromRouteByFromPathRouteId == null ? void 0 : fromRouteByFromPathRouteId.to) ?? fromPath
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
const prevParams = { ...(_f = utils.last(fromMatches)) == null ? void 0 : _f.params };
|
|
348
|
+
let nextParams = (dest.params ?? true) === true ? prevParams : {
|
|
349
|
+
...prevParams,
|
|
350
|
+
...utils.functionalUpdate(dest.params, prevParams)
|
|
351
|
+
};
|
|
352
|
+
if (Object.keys(nextParams).length > 0) {
|
|
353
|
+
matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.map((route) => {
|
|
354
|
+
var _a2;
|
|
355
|
+
return ((_a2 = route.options.params) == null ? void 0 : _a2.stringify) ?? route.options.stringifyParams;
|
|
356
|
+
}).filter(Boolean).forEach((fn) => {
|
|
357
|
+
nextParams = { ...nextParams, ...fn(nextParams) };
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
pathname = path.interpolatePath({
|
|
361
|
+
path: pathname,
|
|
362
|
+
params: nextParams ?? {},
|
|
363
|
+
leaveWildcards: false,
|
|
364
|
+
leaveParams: opts.leaveParams,
|
|
365
|
+
decodeCharMap: this.pathParamsDecodeCharMap
|
|
366
|
+
}).interpolatedPath;
|
|
367
|
+
let search = fromSearch;
|
|
368
|
+
if (opts._includeValidateSearch && ((_g = this.options.search) == null ? void 0 : _g.strict)) {
|
|
369
|
+
let validatedSearch = {};
|
|
370
|
+
matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.forEach((route) => {
|
|
371
|
+
try {
|
|
372
|
+
if (route.options.validateSearch) {
|
|
373
|
+
validatedSearch = {
|
|
374
|
+
...validatedSearch,
|
|
375
|
+
...validateSearch(route.options.validateSearch, {
|
|
376
|
+
...validatedSearch,
|
|
377
|
+
...search
|
|
378
|
+
}) ?? {}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
} catch {
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
search = validatedSearch;
|
|
385
|
+
}
|
|
386
|
+
const applyMiddlewares = (search2) => {
|
|
387
|
+
const allMiddlewares = (matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.reduce(
|
|
388
|
+
(acc, route) => {
|
|
389
|
+
var _a2;
|
|
390
|
+
const middlewares = [];
|
|
391
|
+
if ("search" in route.options) {
|
|
392
|
+
if ((_a2 = route.options.search) == null ? void 0 : _a2.middlewares) {
|
|
393
|
+
middlewares.push(...route.options.search.middlewares);
|
|
394
|
+
}
|
|
395
|
+
} else if (route.options.preSearchFilters || route.options.postSearchFilters) {
|
|
396
|
+
const legacyMiddleware = ({
|
|
397
|
+
search: search3,
|
|
398
|
+
next
|
|
399
|
+
}) => {
|
|
400
|
+
let nextSearch = search3;
|
|
401
|
+
if ("preSearchFilters" in route.options && route.options.preSearchFilters) {
|
|
402
|
+
nextSearch = route.options.preSearchFilters.reduce(
|
|
403
|
+
(prev, next2) => next2(prev),
|
|
404
|
+
search3
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
const result = next(nextSearch);
|
|
408
|
+
if ("postSearchFilters" in route.options && route.options.postSearchFilters) {
|
|
409
|
+
return route.options.postSearchFilters.reduce(
|
|
410
|
+
(prev, next2) => next2(prev),
|
|
411
|
+
result
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
return result;
|
|
415
|
+
};
|
|
416
|
+
middlewares.push(legacyMiddleware);
|
|
417
|
+
}
|
|
418
|
+
if (opts._includeValidateSearch && route.options.validateSearch) {
|
|
419
|
+
const validate = ({ search: search3, next }) => {
|
|
420
|
+
const result = next(search3);
|
|
421
|
+
try {
|
|
422
|
+
const validatedSearch = {
|
|
423
|
+
...result,
|
|
424
|
+
...validateSearch(
|
|
425
|
+
route.options.validateSearch,
|
|
426
|
+
result
|
|
427
|
+
) ?? {}
|
|
428
|
+
};
|
|
429
|
+
return validatedSearch;
|
|
430
|
+
} catch {
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
middlewares.push(validate);
|
|
435
|
+
}
|
|
436
|
+
return acc.concat(middlewares);
|
|
437
|
+
},
|
|
438
|
+
[]
|
|
439
|
+
)) ?? [];
|
|
440
|
+
const final = ({ search: search3 }) => {
|
|
441
|
+
if (!dest.search) {
|
|
442
|
+
return {};
|
|
443
|
+
}
|
|
444
|
+
if (dest.search === true) {
|
|
445
|
+
return search3;
|
|
446
|
+
}
|
|
447
|
+
return utils.functionalUpdate(dest.search, search3);
|
|
448
|
+
};
|
|
449
|
+
allMiddlewares.push(final);
|
|
450
|
+
const applyNext = (index, currentSearch) => {
|
|
451
|
+
if (index >= allMiddlewares.length) {
|
|
452
|
+
return currentSearch;
|
|
453
|
+
}
|
|
454
|
+
const middleware = allMiddlewares[index];
|
|
455
|
+
const next = (newSearch) => {
|
|
456
|
+
return applyNext(index + 1, newSearch);
|
|
457
|
+
};
|
|
458
|
+
return middleware({ search: currentSearch, next });
|
|
459
|
+
};
|
|
460
|
+
return applyNext(0, search2);
|
|
461
|
+
};
|
|
462
|
+
search = applyMiddlewares(search);
|
|
463
|
+
search = utils.replaceEqualDeep(fromSearch, search);
|
|
464
|
+
const searchStr = this.options.stringifySearch(search);
|
|
465
|
+
const hash = dest.hash === true ? this.latestLocation.hash : dest.hash ? utils.functionalUpdate(dest.hash, this.latestLocation.hash) : void 0;
|
|
466
|
+
const hashStr = hash ? `#${hash}` : "";
|
|
467
|
+
let nextState = dest.state === true ? this.latestLocation.state : dest.state ? utils.functionalUpdate(dest.state, this.latestLocation.state) : {};
|
|
468
|
+
nextState = utils.replaceEqualDeep(this.latestLocation.state, nextState);
|
|
469
|
+
return {
|
|
470
|
+
pathname,
|
|
471
|
+
search,
|
|
472
|
+
searchStr,
|
|
473
|
+
state: nextState,
|
|
474
|
+
hash: hash ?? "",
|
|
475
|
+
href: `${pathname}${searchStr}${hashStr}`,
|
|
476
|
+
unmaskOnReload: dest.unmaskOnReload
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
const buildWithMatches = (dest = {}, maskedDest) => {
|
|
480
|
+
var _a;
|
|
481
|
+
const next = build(dest);
|
|
482
|
+
let maskedNext = maskedDest ? build(maskedDest) : void 0;
|
|
483
|
+
if (!maskedNext) {
|
|
484
|
+
let params = {};
|
|
485
|
+
const foundMask = (_a = this.options.routeMasks) == null ? void 0 : _a.find((d) => {
|
|
486
|
+
const match = path.matchPathname(this.basepath, next.pathname, {
|
|
487
|
+
to: d.from,
|
|
488
|
+
caseSensitive: false,
|
|
489
|
+
fuzzy: false
|
|
490
|
+
});
|
|
491
|
+
if (match) {
|
|
492
|
+
params = match;
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
495
|
+
return false;
|
|
496
|
+
});
|
|
497
|
+
if (foundMask) {
|
|
498
|
+
const { from: _from, ...maskProps } = foundMask;
|
|
499
|
+
maskedDest = {
|
|
500
|
+
...utils.pick(opts, ["from"]),
|
|
501
|
+
...maskProps,
|
|
502
|
+
params
|
|
503
|
+
};
|
|
504
|
+
maskedNext = build(maskedDest);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const nextMatches = this.getMatchedRoutes(next, dest);
|
|
508
|
+
const final = build(dest, nextMatches);
|
|
509
|
+
if (maskedNext) {
|
|
510
|
+
const maskedMatches = this.getMatchedRoutes(maskedNext, maskedDest);
|
|
511
|
+
const maskedFinal = build(maskedDest, maskedMatches);
|
|
512
|
+
final.maskedLocation = maskedFinal;
|
|
513
|
+
}
|
|
514
|
+
return final;
|
|
515
|
+
};
|
|
516
|
+
if (opts.mask) {
|
|
517
|
+
return buildWithMatches(opts, {
|
|
518
|
+
...utils.pick(opts, ["from"]),
|
|
519
|
+
...opts.mask
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
return buildWithMatches(opts);
|
|
523
|
+
};
|
|
524
|
+
this.commitLocation = ({
|
|
525
|
+
viewTransition,
|
|
526
|
+
ignoreBlocker,
|
|
527
|
+
...next
|
|
528
|
+
}) => {
|
|
529
|
+
const isSameState = () => {
|
|
530
|
+
const ignoredProps = [
|
|
531
|
+
"key",
|
|
532
|
+
"__TSR_index",
|
|
533
|
+
"__hashScrollIntoViewOptions"
|
|
534
|
+
];
|
|
535
|
+
ignoredProps.forEach((prop) => {
|
|
536
|
+
next.state[prop] = this.latestLocation.state[prop];
|
|
537
|
+
});
|
|
538
|
+
const isEqual = utils.deepEqual(next.state, this.latestLocation.state);
|
|
539
|
+
ignoredProps.forEach((prop) => {
|
|
540
|
+
delete next.state[prop];
|
|
541
|
+
});
|
|
542
|
+
return isEqual;
|
|
543
|
+
};
|
|
544
|
+
const isSameUrl = this.latestLocation.href === next.href;
|
|
545
|
+
const previousCommitPromise = this.commitLocationPromise;
|
|
546
|
+
this.commitLocationPromise = utils.createControlledPromise(() => {
|
|
547
|
+
previousCommitPromise == null ? void 0 : previousCommitPromise.resolve();
|
|
548
|
+
});
|
|
549
|
+
if (isSameUrl && isSameState()) {
|
|
550
|
+
this.load();
|
|
551
|
+
} else {
|
|
552
|
+
let { maskedLocation, hashScrollIntoView, ...nextHistory } = next;
|
|
553
|
+
if (maskedLocation) {
|
|
554
|
+
nextHistory = {
|
|
555
|
+
...maskedLocation,
|
|
556
|
+
state: {
|
|
557
|
+
...maskedLocation.state,
|
|
558
|
+
__tempKey: void 0,
|
|
559
|
+
__tempLocation: {
|
|
560
|
+
...nextHistory,
|
|
561
|
+
search: nextHistory.searchStr,
|
|
562
|
+
state: {
|
|
563
|
+
...nextHistory.state,
|
|
564
|
+
__tempKey: void 0,
|
|
565
|
+
__tempLocation: void 0,
|
|
566
|
+
key: void 0
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
572
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
|
|
576
|
+
this.shouldViewTransition = viewTransition;
|
|
577
|
+
this.history[next.replace ? "replace" : "push"](
|
|
578
|
+
nextHistory.href,
|
|
579
|
+
nextHistory.state,
|
|
580
|
+
{ ignoreBlocker }
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
584
|
+
if (!this.history.subscribers.size) {
|
|
585
|
+
this.load();
|
|
586
|
+
}
|
|
587
|
+
return this.commitLocationPromise;
|
|
588
|
+
};
|
|
589
|
+
this.buildAndCommitLocation = ({
|
|
590
|
+
replace,
|
|
591
|
+
resetScroll,
|
|
592
|
+
hashScrollIntoView,
|
|
593
|
+
viewTransition,
|
|
594
|
+
ignoreBlocker,
|
|
595
|
+
href,
|
|
596
|
+
...rest
|
|
597
|
+
} = {}) => {
|
|
598
|
+
if (href) {
|
|
599
|
+
const currentIndex = this.history.location.state.__TSR_index;
|
|
600
|
+
const parsed = history.parseHref(href, {
|
|
601
|
+
__TSR_index: replace ? currentIndex : currentIndex + 1
|
|
602
|
+
});
|
|
603
|
+
rest.to = parsed.pathname;
|
|
604
|
+
rest.search = this.options.parseSearch(parsed.search);
|
|
605
|
+
rest.hash = parsed.hash.slice(1);
|
|
606
|
+
}
|
|
607
|
+
const location = this.buildLocation({
|
|
608
|
+
...rest,
|
|
609
|
+
_includeValidateSearch: true
|
|
610
|
+
});
|
|
611
|
+
return this.commitLocation({
|
|
612
|
+
...location,
|
|
613
|
+
viewTransition,
|
|
614
|
+
replace,
|
|
615
|
+
resetScroll,
|
|
616
|
+
hashScrollIntoView,
|
|
617
|
+
ignoreBlocker
|
|
618
|
+
});
|
|
619
|
+
};
|
|
620
|
+
this.navigate = ({ to, reloadDocument, href, ...rest }) => {
|
|
621
|
+
if (reloadDocument) {
|
|
622
|
+
if (!href) {
|
|
623
|
+
const location = this.buildLocation({ to, ...rest });
|
|
624
|
+
href = this.history.createHref(location.href);
|
|
625
|
+
}
|
|
626
|
+
if (rest.replace) {
|
|
627
|
+
window.location.replace(href);
|
|
628
|
+
} else {
|
|
629
|
+
window.location.href = href;
|
|
630
|
+
}
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
return this.buildAndCommitLocation({
|
|
634
|
+
...rest,
|
|
635
|
+
href,
|
|
636
|
+
to
|
|
637
|
+
});
|
|
638
|
+
};
|
|
639
|
+
this.load = async (opts) => {
|
|
640
|
+
this.latestLocation = this.parseLocation(this.latestLocation);
|
|
641
|
+
let redirect$1;
|
|
642
|
+
let notFound$1;
|
|
643
|
+
let loadPromise;
|
|
644
|
+
loadPromise = new Promise((resolve) => {
|
|
645
|
+
this.startTransition(async () => {
|
|
646
|
+
var _a;
|
|
647
|
+
try {
|
|
648
|
+
const next = this.latestLocation;
|
|
649
|
+
const prevLocation = this.state.resolvedLocation;
|
|
650
|
+
this.cancelMatches();
|
|
651
|
+
let pendingMatches;
|
|
652
|
+
store.batch(() => {
|
|
653
|
+
pendingMatches = this.matchRoutes(next);
|
|
654
|
+
this.__store.setState((s) => ({
|
|
655
|
+
...s,
|
|
656
|
+
status: "pending",
|
|
657
|
+
isLoading: true,
|
|
658
|
+
location: next,
|
|
659
|
+
pendingMatches,
|
|
660
|
+
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
661
|
+
cachedMatches: s.cachedMatches.filter((d) => {
|
|
662
|
+
return !pendingMatches.find((e) => e.id === d.id);
|
|
663
|
+
})
|
|
664
|
+
}));
|
|
665
|
+
});
|
|
666
|
+
if (!this.state.redirect) {
|
|
667
|
+
this.emit({
|
|
668
|
+
type: "onBeforeNavigate",
|
|
669
|
+
...getLocationChangeInfo({
|
|
670
|
+
resolvedLocation: prevLocation,
|
|
671
|
+
location: next
|
|
672
|
+
})
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
this.emit({
|
|
676
|
+
type: "onBeforeLoad",
|
|
677
|
+
...getLocationChangeInfo({
|
|
678
|
+
resolvedLocation: prevLocation,
|
|
679
|
+
location: next
|
|
680
|
+
})
|
|
681
|
+
});
|
|
682
|
+
await this.loadMatches({
|
|
683
|
+
sync: opts == null ? void 0 : opts.sync,
|
|
684
|
+
matches: pendingMatches,
|
|
685
|
+
location: next,
|
|
686
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
687
|
+
onReady: async () => {
|
|
688
|
+
this.startViewTransition(async () => {
|
|
689
|
+
let exitingMatches;
|
|
690
|
+
let enteringMatches;
|
|
691
|
+
let stayingMatches;
|
|
692
|
+
store.batch(() => {
|
|
693
|
+
this.__store.setState((s) => {
|
|
694
|
+
const previousMatches = s.matches;
|
|
695
|
+
const newMatches = s.pendingMatches || s.matches;
|
|
696
|
+
exitingMatches = previousMatches.filter(
|
|
697
|
+
(match) => !newMatches.find((d) => d.id === match.id)
|
|
698
|
+
);
|
|
699
|
+
enteringMatches = newMatches.filter(
|
|
700
|
+
(match) => !previousMatches.find((d) => d.id === match.id)
|
|
701
|
+
);
|
|
702
|
+
stayingMatches = previousMatches.filter(
|
|
703
|
+
(match) => newMatches.find((d) => d.id === match.id)
|
|
704
|
+
);
|
|
705
|
+
return {
|
|
706
|
+
...s,
|
|
707
|
+
isLoading: false,
|
|
708
|
+
loadedAt: Date.now(),
|
|
709
|
+
matches: newMatches,
|
|
710
|
+
pendingMatches: void 0,
|
|
711
|
+
cachedMatches: [
|
|
712
|
+
...s.cachedMatches,
|
|
713
|
+
...exitingMatches.filter((d) => d.status !== "error")
|
|
714
|
+
]
|
|
715
|
+
};
|
|
716
|
+
});
|
|
717
|
+
this.clearExpiredCache();
|
|
718
|
+
});
|
|
719
|
+
[
|
|
720
|
+
[exitingMatches, "onLeave"],
|
|
721
|
+
[enteringMatches, "onEnter"],
|
|
722
|
+
[stayingMatches, "onStay"]
|
|
723
|
+
].forEach(([matches, hook]) => {
|
|
724
|
+
matches.forEach((match) => {
|
|
725
|
+
var _a2, _b;
|
|
726
|
+
(_b = (_a2 = this.looseRoutesById[match.routeId].options)[hook]) == null ? void 0 : _b.call(_a2, match);
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
} catch (err) {
|
|
733
|
+
if (redirect.isResolvedRedirect(err)) {
|
|
734
|
+
redirect$1 = err;
|
|
735
|
+
if (!this.isServer) {
|
|
736
|
+
this.navigate({
|
|
737
|
+
...redirect$1,
|
|
738
|
+
replace: true,
|
|
739
|
+
ignoreBlocker: true
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
} else if (notFound.isNotFound(err)) {
|
|
743
|
+
notFound$1 = err;
|
|
744
|
+
}
|
|
745
|
+
this.__store.setState((s) => ({
|
|
746
|
+
...s,
|
|
747
|
+
statusCode: redirect$1 ? redirect$1.statusCode : notFound$1 ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
|
|
748
|
+
redirect: redirect$1
|
|
749
|
+
}));
|
|
750
|
+
}
|
|
751
|
+
if (this.latestLoadPromise === loadPromise) {
|
|
752
|
+
(_a = this.commitLocationPromise) == null ? void 0 : _a.resolve();
|
|
753
|
+
this.latestLoadPromise = void 0;
|
|
754
|
+
this.commitLocationPromise = void 0;
|
|
755
|
+
}
|
|
756
|
+
resolve();
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
this.latestLoadPromise = loadPromise;
|
|
760
|
+
await loadPromise;
|
|
761
|
+
while (this.latestLoadPromise && loadPromise !== this.latestLoadPromise) {
|
|
762
|
+
await this.latestLoadPromise;
|
|
763
|
+
}
|
|
764
|
+
if (this.hasNotFoundMatch()) {
|
|
765
|
+
this.__store.setState((s) => ({
|
|
766
|
+
...s,
|
|
767
|
+
statusCode: 404
|
|
768
|
+
}));
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
this.startViewTransition = (fn) => {
|
|
772
|
+
const shouldViewTransition = this.shouldViewTransition ?? this.options.defaultViewTransition;
|
|
773
|
+
delete this.shouldViewTransition;
|
|
774
|
+
if (shouldViewTransition && typeof document !== "undefined" && "startViewTransition" in document && typeof document.startViewTransition === "function") {
|
|
775
|
+
let startViewTransitionParams;
|
|
776
|
+
if (typeof shouldViewTransition === "object" && this.isViewTransitionTypesSupported) {
|
|
777
|
+
startViewTransitionParams = {
|
|
778
|
+
update: fn,
|
|
779
|
+
types: shouldViewTransition.types
|
|
780
|
+
};
|
|
781
|
+
} else {
|
|
782
|
+
startViewTransitionParams = fn;
|
|
783
|
+
}
|
|
784
|
+
document.startViewTransition(startViewTransitionParams);
|
|
785
|
+
} else {
|
|
786
|
+
fn();
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
this.updateMatch = (id, updater) => {
|
|
790
|
+
var _a;
|
|
791
|
+
let updated;
|
|
792
|
+
const isPending = (_a = this.state.pendingMatches) == null ? void 0 : _a.find((d) => d.id === id);
|
|
793
|
+
const isMatched = this.state.matches.find((d) => d.id === id);
|
|
794
|
+
const isCached = this.state.cachedMatches.find((d) => d.id === id);
|
|
795
|
+
const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : isCached ? "cachedMatches" : "";
|
|
796
|
+
if (matchesKey) {
|
|
797
|
+
this.__store.setState((s) => {
|
|
798
|
+
var _a2;
|
|
799
|
+
return {
|
|
800
|
+
...s,
|
|
801
|
+
[matchesKey]: (_a2 = s[matchesKey]) == null ? void 0 : _a2.map(
|
|
802
|
+
(d) => d.id === id ? updated = updater(d) : d
|
|
803
|
+
)
|
|
804
|
+
};
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
return updated;
|
|
808
|
+
};
|
|
809
|
+
this.getMatch = (matchId) => {
|
|
810
|
+
return [
|
|
811
|
+
...this.state.cachedMatches,
|
|
812
|
+
...this.state.pendingMatches ?? [],
|
|
813
|
+
...this.state.matches
|
|
814
|
+
].find((d) => d.id === matchId);
|
|
815
|
+
};
|
|
816
|
+
this.loadMatches = async ({
|
|
817
|
+
location,
|
|
818
|
+
matches,
|
|
819
|
+
preload: allPreload,
|
|
820
|
+
onReady,
|
|
821
|
+
updateMatch = this.updateMatch,
|
|
822
|
+
sync
|
|
823
|
+
}) => {
|
|
824
|
+
let firstBadMatchIndex;
|
|
825
|
+
let rendered = false;
|
|
826
|
+
const triggerOnReady = async () => {
|
|
827
|
+
if (!rendered) {
|
|
828
|
+
rendered = true;
|
|
829
|
+
await (onReady == null ? void 0 : onReady());
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
const resolvePreload = (matchId) => {
|
|
833
|
+
return !!(allPreload && !this.state.matches.find((d) => d.id === matchId));
|
|
834
|
+
};
|
|
835
|
+
if (!this.isServer && !this.state.matches.length) {
|
|
836
|
+
triggerOnReady();
|
|
837
|
+
}
|
|
838
|
+
const handleRedirectAndNotFound = (match, err) => {
|
|
839
|
+
var _a, _b, _c, _d;
|
|
840
|
+
if (redirect.isResolvedRedirect(err)) {
|
|
841
|
+
if (!err.reloadDocument) {
|
|
842
|
+
throw err;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (redirect.isRedirect(err) || notFound.isNotFound(err)) {
|
|
846
|
+
updateMatch(match.id, (prev) => ({
|
|
847
|
+
...prev,
|
|
848
|
+
status: redirect.isRedirect(err) ? "redirected" : notFound.isNotFound(err) ? "notFound" : "error",
|
|
849
|
+
isFetching: false,
|
|
850
|
+
error: err,
|
|
851
|
+
beforeLoadPromise: void 0,
|
|
852
|
+
loaderPromise: void 0
|
|
853
|
+
}));
|
|
854
|
+
if (!err.routeId) {
|
|
855
|
+
err.routeId = match.routeId;
|
|
856
|
+
}
|
|
857
|
+
(_a = match.beforeLoadPromise) == null ? void 0 : _a.resolve();
|
|
858
|
+
(_b = match.loaderPromise) == null ? void 0 : _b.resolve();
|
|
859
|
+
(_c = match.loadPromise) == null ? void 0 : _c.resolve();
|
|
860
|
+
if (redirect.isRedirect(err)) {
|
|
861
|
+
rendered = true;
|
|
862
|
+
err = this.resolveRedirect({ ...err, _fromLocation: location });
|
|
863
|
+
throw err;
|
|
864
|
+
} else if (notFound.isNotFound(err)) {
|
|
865
|
+
this._handleNotFound(matches, err, {
|
|
866
|
+
updateMatch
|
|
867
|
+
});
|
|
868
|
+
(_d = this.serverSsr) == null ? void 0 : _d.onMatchSettled({
|
|
869
|
+
router: this,
|
|
870
|
+
match: this.getMatch(match.id)
|
|
871
|
+
});
|
|
872
|
+
throw err;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
try {
|
|
877
|
+
await new Promise((resolveAll, rejectAll) => {
|
|
878
|
+
;
|
|
879
|
+
(async () => {
|
|
880
|
+
var _a, _b, _c, _d;
|
|
881
|
+
try {
|
|
882
|
+
const handleSerialError = (index, err, routerCode) => {
|
|
883
|
+
var _a2, _b2;
|
|
884
|
+
const { id: matchId, routeId } = matches[index];
|
|
885
|
+
const route = this.looseRoutesById[routeId];
|
|
886
|
+
if (err instanceof Promise) {
|
|
887
|
+
throw err;
|
|
888
|
+
}
|
|
889
|
+
err.routerCode = routerCode;
|
|
890
|
+
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
891
|
+
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
892
|
+
try {
|
|
893
|
+
(_b2 = (_a2 = route.options).onError) == null ? void 0 : _b2.call(_a2, err);
|
|
894
|
+
} catch (errorHandlerErr) {
|
|
895
|
+
err = errorHandlerErr;
|
|
896
|
+
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
897
|
+
}
|
|
898
|
+
updateMatch(matchId, (prev) => {
|
|
899
|
+
var _a3, _b3;
|
|
900
|
+
(_a3 = prev.beforeLoadPromise) == null ? void 0 : _a3.resolve();
|
|
901
|
+
(_b3 = prev.loadPromise) == null ? void 0 : _b3.resolve();
|
|
902
|
+
return {
|
|
903
|
+
...prev,
|
|
904
|
+
error: err,
|
|
905
|
+
status: "error",
|
|
906
|
+
isFetching: false,
|
|
907
|
+
updatedAt: Date.now(),
|
|
908
|
+
abortController: new AbortController(),
|
|
909
|
+
beforeLoadPromise: void 0
|
|
910
|
+
};
|
|
911
|
+
});
|
|
912
|
+
};
|
|
913
|
+
for (const [index, { id: matchId, routeId }] of matches.entries()) {
|
|
914
|
+
const existingMatch = this.getMatch(matchId);
|
|
915
|
+
const parentMatchId = (_a = matches[index - 1]) == null ? void 0 : _a.id;
|
|
916
|
+
const route = this.looseRoutesById[routeId];
|
|
917
|
+
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
918
|
+
const shouldPending = !!(onReady && !this.isServer && !resolvePreload(matchId) && (route.options.loader || route.options.beforeLoad) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? ((_b = this.options) == null ? void 0 : _b.defaultPendingComponent)));
|
|
919
|
+
let executeBeforeLoad = true;
|
|
920
|
+
if (
|
|
921
|
+
// If we are in the middle of a load, either of these will be present
|
|
922
|
+
// (not to be confused with `loadPromise`, which is always defined)
|
|
923
|
+
existingMatch.beforeLoadPromise || existingMatch.loaderPromise
|
|
924
|
+
) {
|
|
925
|
+
if (shouldPending) {
|
|
926
|
+
setTimeout(() => {
|
|
927
|
+
try {
|
|
928
|
+
triggerOnReady();
|
|
929
|
+
} catch {
|
|
930
|
+
}
|
|
931
|
+
}, pendingMs);
|
|
932
|
+
}
|
|
933
|
+
await existingMatch.beforeLoadPromise;
|
|
934
|
+
executeBeforeLoad = this.getMatch(matchId).status !== "success";
|
|
935
|
+
}
|
|
936
|
+
if (executeBeforeLoad) {
|
|
937
|
+
try {
|
|
938
|
+
updateMatch(matchId, (prev) => {
|
|
939
|
+
const prevLoadPromise = prev.loadPromise;
|
|
940
|
+
return {
|
|
941
|
+
...prev,
|
|
942
|
+
loadPromise: utils.createControlledPromise(() => {
|
|
943
|
+
prevLoadPromise == null ? void 0 : prevLoadPromise.resolve();
|
|
944
|
+
}),
|
|
945
|
+
beforeLoadPromise: utils.createControlledPromise()
|
|
946
|
+
};
|
|
947
|
+
});
|
|
948
|
+
const abortController = new AbortController();
|
|
949
|
+
let pendingTimeout;
|
|
950
|
+
if (shouldPending) {
|
|
951
|
+
pendingTimeout = setTimeout(() => {
|
|
952
|
+
try {
|
|
953
|
+
triggerOnReady();
|
|
954
|
+
} catch {
|
|
955
|
+
}
|
|
956
|
+
}, pendingMs);
|
|
957
|
+
}
|
|
958
|
+
const { paramsError, searchError } = this.getMatch(matchId);
|
|
959
|
+
if (paramsError) {
|
|
960
|
+
handleSerialError(index, paramsError, "PARSE_PARAMS");
|
|
961
|
+
}
|
|
962
|
+
if (searchError) {
|
|
963
|
+
handleSerialError(index, searchError, "VALIDATE_SEARCH");
|
|
964
|
+
}
|
|
965
|
+
const getParentMatchContext = () => parentMatchId ? this.getMatch(parentMatchId).context : this.options.context ?? {};
|
|
966
|
+
updateMatch(matchId, (prev) => ({
|
|
967
|
+
...prev,
|
|
968
|
+
isFetching: "beforeLoad",
|
|
969
|
+
fetchCount: prev.fetchCount + 1,
|
|
970
|
+
abortController,
|
|
971
|
+
pendingTimeout,
|
|
972
|
+
context: {
|
|
973
|
+
...getParentMatchContext(),
|
|
974
|
+
...prev.__routeContext
|
|
975
|
+
}
|
|
976
|
+
}));
|
|
977
|
+
const { search, params, context, cause } = this.getMatch(matchId);
|
|
978
|
+
const preload = resolvePreload(matchId);
|
|
979
|
+
const beforeLoadFnContext = {
|
|
980
|
+
search,
|
|
981
|
+
abortController,
|
|
982
|
+
params,
|
|
983
|
+
preload,
|
|
984
|
+
context,
|
|
985
|
+
location,
|
|
986
|
+
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
987
|
+
buildLocation: this.buildLocation,
|
|
988
|
+
cause: preload ? "preload" : cause,
|
|
989
|
+
matches
|
|
990
|
+
};
|
|
991
|
+
const beforeLoadContext = await ((_d = (_c = route.options).beforeLoad) == null ? void 0 : _d.call(_c, beforeLoadFnContext)) ?? {};
|
|
992
|
+
if (redirect.isRedirect(beforeLoadContext) || notFound.isNotFound(beforeLoadContext)) {
|
|
993
|
+
handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
|
|
994
|
+
}
|
|
995
|
+
updateMatch(matchId, (prev) => {
|
|
996
|
+
return {
|
|
997
|
+
...prev,
|
|
998
|
+
__beforeLoadContext: beforeLoadContext,
|
|
999
|
+
context: {
|
|
1000
|
+
...getParentMatchContext(),
|
|
1001
|
+
...prev.__routeContext,
|
|
1002
|
+
...beforeLoadContext
|
|
1003
|
+
},
|
|
1004
|
+
abortController
|
|
1005
|
+
};
|
|
1006
|
+
});
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
handleSerialError(index, err, "BEFORE_LOAD");
|
|
1009
|
+
}
|
|
1010
|
+
updateMatch(matchId, (prev) => {
|
|
1011
|
+
var _a2;
|
|
1012
|
+
(_a2 = prev.beforeLoadPromise) == null ? void 0 : _a2.resolve();
|
|
1013
|
+
return {
|
|
1014
|
+
...prev,
|
|
1015
|
+
beforeLoadPromise: void 0,
|
|
1016
|
+
isFetching: false
|
|
1017
|
+
};
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
1022
|
+
const matchPromises = [];
|
|
1023
|
+
validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
|
|
1024
|
+
matchPromises.push(
|
|
1025
|
+
(async () => {
|
|
1026
|
+
const { loaderPromise: prevLoaderPromise } = this.getMatch(matchId);
|
|
1027
|
+
let loaderShouldRunAsync = false;
|
|
1028
|
+
let loaderIsRunningAsync = false;
|
|
1029
|
+
if (prevLoaderPromise) {
|
|
1030
|
+
await prevLoaderPromise;
|
|
1031
|
+
const match = this.getMatch(matchId);
|
|
1032
|
+
if (match.error) {
|
|
1033
|
+
handleRedirectAndNotFound(match, match.error);
|
|
1034
|
+
}
|
|
1035
|
+
} else {
|
|
1036
|
+
const parentMatchPromise = matchPromises[index - 1];
|
|
1037
|
+
const route = this.looseRoutesById[routeId];
|
|
1038
|
+
const getLoaderContext = () => {
|
|
1039
|
+
const {
|
|
1040
|
+
params,
|
|
1041
|
+
loaderDeps,
|
|
1042
|
+
abortController,
|
|
1043
|
+
context,
|
|
1044
|
+
cause
|
|
1045
|
+
} = this.getMatch(matchId);
|
|
1046
|
+
const preload2 = resolvePreload(matchId);
|
|
1047
|
+
return {
|
|
1048
|
+
params,
|
|
1049
|
+
deps: loaderDeps,
|
|
1050
|
+
preload: !!preload2,
|
|
1051
|
+
parentMatchPromise,
|
|
1052
|
+
abortController,
|
|
1053
|
+
context,
|
|
1054
|
+
location,
|
|
1055
|
+
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
1056
|
+
cause: preload2 ? "preload" : cause,
|
|
1057
|
+
route
|
|
1058
|
+
};
|
|
1059
|
+
};
|
|
1060
|
+
const age = Date.now() - this.getMatch(matchId).updatedAt;
|
|
1061
|
+
const preload = resolvePreload(matchId);
|
|
1062
|
+
const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
1063
|
+
const shouldReloadOption = route.options.shouldReload;
|
|
1064
|
+
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
|
|
1065
|
+
updateMatch(matchId, (prev) => ({
|
|
1066
|
+
...prev,
|
|
1067
|
+
loaderPromise: utils.createControlledPromise(),
|
|
1068
|
+
preload: !!preload && !this.state.matches.find((d) => d.id === matchId)
|
|
1069
|
+
}));
|
|
1070
|
+
const runLoader = async () => {
|
|
1071
|
+
var _a2, _b2, _c2, _d2, _e, _f, _g, _h, _i, _j, _k;
|
|
1072
|
+
try {
|
|
1073
|
+
const potentialPendingMinPromise = async () => {
|
|
1074
|
+
const latestMatch = this.getMatch(matchId);
|
|
1075
|
+
if (latestMatch.minPendingPromise) {
|
|
1076
|
+
await latestMatch.minPendingPromise;
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
try {
|
|
1080
|
+
this.loadRouteChunk(route);
|
|
1081
|
+
updateMatch(matchId, (prev) => ({
|
|
1082
|
+
...prev,
|
|
1083
|
+
isFetching: "loader"
|
|
1084
|
+
}));
|
|
1085
|
+
const loaderData = await ((_b2 = (_a2 = route.options).loader) == null ? void 0 : _b2.call(_a2, getLoaderContext()));
|
|
1086
|
+
handleRedirectAndNotFound(
|
|
1087
|
+
this.getMatch(matchId),
|
|
1088
|
+
loaderData
|
|
1089
|
+
);
|
|
1090
|
+
await route._lazyPromise;
|
|
1091
|
+
await potentialPendingMinPromise();
|
|
1092
|
+
const assetContext = {
|
|
1093
|
+
matches,
|
|
1094
|
+
match: this.getMatch(matchId),
|
|
1095
|
+
params: this.getMatch(matchId).params,
|
|
1096
|
+
loaderData
|
|
1097
|
+
};
|
|
1098
|
+
const headFnContent = (_d2 = (_c2 = route.options).head) == null ? void 0 : _d2.call(_c2, assetContext);
|
|
1099
|
+
const meta = headFnContent == null ? void 0 : headFnContent.meta;
|
|
1100
|
+
const links = headFnContent == null ? void 0 : headFnContent.links;
|
|
1101
|
+
const headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
|
|
1102
|
+
const scripts = (_f = (_e = route.options).scripts) == null ? void 0 : _f.call(_e, assetContext);
|
|
1103
|
+
const headers = (_h = (_g = route.options).headers) == null ? void 0 : _h.call(_g, {
|
|
1104
|
+
loaderData
|
|
1105
|
+
});
|
|
1106
|
+
updateMatch(matchId, (prev) => ({
|
|
1107
|
+
...prev,
|
|
1108
|
+
error: void 0,
|
|
1109
|
+
status: "success",
|
|
1110
|
+
isFetching: false,
|
|
1111
|
+
updatedAt: Date.now(),
|
|
1112
|
+
loaderData,
|
|
1113
|
+
meta,
|
|
1114
|
+
links,
|
|
1115
|
+
headScripts,
|
|
1116
|
+
headers,
|
|
1117
|
+
scripts
|
|
1118
|
+
}));
|
|
1119
|
+
} catch (e) {
|
|
1120
|
+
let error = e;
|
|
1121
|
+
await potentialPendingMinPromise();
|
|
1122
|
+
handleRedirectAndNotFound(this.getMatch(matchId), e);
|
|
1123
|
+
try {
|
|
1124
|
+
(_j = (_i = route.options).onError) == null ? void 0 : _j.call(_i, e);
|
|
1125
|
+
} catch (onErrorError) {
|
|
1126
|
+
error = onErrorError;
|
|
1127
|
+
handleRedirectAndNotFound(
|
|
1128
|
+
this.getMatch(matchId),
|
|
1129
|
+
onErrorError
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
updateMatch(matchId, (prev) => ({
|
|
1133
|
+
...prev,
|
|
1134
|
+
error,
|
|
1135
|
+
status: "error",
|
|
1136
|
+
isFetching: false
|
|
1137
|
+
}));
|
|
1138
|
+
}
|
|
1139
|
+
(_k = this.serverSsr) == null ? void 0 : _k.onMatchSettled({
|
|
1140
|
+
router: this,
|
|
1141
|
+
match: this.getMatch(matchId)
|
|
1142
|
+
});
|
|
1143
|
+
await route._componentsPromise;
|
|
1144
|
+
} catch (err) {
|
|
1145
|
+
updateMatch(matchId, (prev) => ({
|
|
1146
|
+
...prev,
|
|
1147
|
+
loaderPromise: void 0
|
|
1148
|
+
}));
|
|
1149
|
+
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1152
|
+
const { status, invalid } = this.getMatch(matchId);
|
|
1153
|
+
loaderShouldRunAsync = status === "success" && (invalid || (shouldReload ?? age > staleAge));
|
|
1154
|
+
if (preload && route.options.preload === false) {
|
|
1155
|
+
} else if (loaderShouldRunAsync && !sync) {
|
|
1156
|
+
loaderIsRunningAsync = true;
|
|
1157
|
+
(async () => {
|
|
1158
|
+
try {
|
|
1159
|
+
await runLoader();
|
|
1160
|
+
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1161
|
+
loaderPromise == null ? void 0 : loaderPromise.resolve();
|
|
1162
|
+
loadPromise == null ? void 0 : loadPromise.resolve();
|
|
1163
|
+
updateMatch(matchId, (prev) => ({
|
|
1164
|
+
...prev,
|
|
1165
|
+
loaderPromise: void 0
|
|
1166
|
+
}));
|
|
1167
|
+
} catch (err) {
|
|
1168
|
+
if (redirect.isResolvedRedirect(err)) {
|
|
1169
|
+
await this.navigate(err);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
})();
|
|
1173
|
+
} else if (status !== "success" || loaderShouldRunAsync && sync) {
|
|
1174
|
+
await runLoader();
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
if (!loaderIsRunningAsync) {
|
|
1178
|
+
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1179
|
+
loaderPromise == null ? void 0 : loaderPromise.resolve();
|
|
1180
|
+
loadPromise == null ? void 0 : loadPromise.resolve();
|
|
1181
|
+
}
|
|
1182
|
+
updateMatch(matchId, (prev) => ({
|
|
1183
|
+
...prev,
|
|
1184
|
+
isFetching: loaderIsRunningAsync ? prev.isFetching : false,
|
|
1185
|
+
loaderPromise: loaderIsRunningAsync ? prev.loaderPromise : void 0,
|
|
1186
|
+
invalid: false
|
|
1187
|
+
}));
|
|
1188
|
+
return this.getMatch(matchId);
|
|
1189
|
+
})()
|
|
1190
|
+
);
|
|
1191
|
+
});
|
|
1192
|
+
await Promise.all(matchPromises);
|
|
1193
|
+
resolveAll();
|
|
1194
|
+
} catch (err) {
|
|
1195
|
+
rejectAll(err);
|
|
1196
|
+
}
|
|
1197
|
+
})();
|
|
1198
|
+
});
|
|
1199
|
+
await triggerOnReady();
|
|
1200
|
+
} catch (err) {
|
|
1201
|
+
if (redirect.isRedirect(err) || notFound.isNotFound(err)) {
|
|
1202
|
+
if (notFound.isNotFound(err) && !allPreload) {
|
|
1203
|
+
await triggerOnReady();
|
|
1204
|
+
}
|
|
1205
|
+
throw err;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
return matches;
|
|
1209
|
+
};
|
|
1210
|
+
this.invalidate = (opts) => {
|
|
1211
|
+
const invalidate = (d) => {
|
|
1212
|
+
var _a;
|
|
1213
|
+
if (((_a = opts == null ? void 0 : opts.filter) == null ? void 0 : _a.call(opts, d)) ?? true) {
|
|
1214
|
+
return {
|
|
1215
|
+
...d,
|
|
1216
|
+
invalid: true,
|
|
1217
|
+
...d.status === "error" ? { status: "pending", error: void 0 } : {}
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
return d;
|
|
1221
|
+
};
|
|
1222
|
+
this.__store.setState((s) => {
|
|
1223
|
+
var _a;
|
|
1224
|
+
return {
|
|
1225
|
+
...s,
|
|
1226
|
+
matches: s.matches.map(invalidate),
|
|
1227
|
+
cachedMatches: s.cachedMatches.map(invalidate),
|
|
1228
|
+
pendingMatches: (_a = s.pendingMatches) == null ? void 0 : _a.map(invalidate)
|
|
1229
|
+
};
|
|
1230
|
+
});
|
|
1231
|
+
return this.load({ sync: opts == null ? void 0 : opts.sync });
|
|
1232
|
+
};
|
|
1233
|
+
this.resolveRedirect = (err) => {
|
|
1234
|
+
const redirect2 = err;
|
|
1235
|
+
if (!redirect2.href) {
|
|
1236
|
+
redirect2.href = this.buildLocation(redirect2).href;
|
|
1237
|
+
}
|
|
1238
|
+
return redirect2;
|
|
1239
|
+
};
|
|
1240
|
+
this.clearCache = (opts) => {
|
|
1241
|
+
const filter = opts == null ? void 0 : opts.filter;
|
|
1242
|
+
if (filter !== void 0) {
|
|
1243
|
+
this.__store.setState((s) => {
|
|
1244
|
+
return {
|
|
1245
|
+
...s,
|
|
1246
|
+
cachedMatches: s.cachedMatches.filter(
|
|
1247
|
+
(m) => !filter(m)
|
|
1248
|
+
)
|
|
1249
|
+
};
|
|
1250
|
+
});
|
|
1251
|
+
} else {
|
|
1252
|
+
this.__store.setState((s) => {
|
|
1253
|
+
return {
|
|
1254
|
+
...s,
|
|
1255
|
+
cachedMatches: []
|
|
1256
|
+
};
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
this.clearExpiredCache = () => {
|
|
1261
|
+
const filter = (d) => {
|
|
1262
|
+
const route = this.looseRoutesById[d.routeId];
|
|
1263
|
+
if (!route.options.loader) {
|
|
1264
|
+
return true;
|
|
1265
|
+
}
|
|
1266
|
+
const gcTime = (d.preload ? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime : route.options.gcTime ?? this.options.defaultGcTime) ?? 5 * 60 * 1e3;
|
|
1267
|
+
return !(d.status !== "error" && Date.now() - d.updatedAt < gcTime);
|
|
1268
|
+
};
|
|
1269
|
+
this.clearCache({ filter });
|
|
1270
|
+
};
|
|
1271
|
+
this.loadRouteChunk = (route) => {
|
|
1272
|
+
if (route._lazyPromise === void 0) {
|
|
1273
|
+
if (route.lazyFn) {
|
|
1274
|
+
route._lazyPromise = route.lazyFn().then((lazyRoute) => {
|
|
1275
|
+
const { id: _id, ...options2 } = lazyRoute.options;
|
|
1276
|
+
Object.assign(route.options, options2);
|
|
1277
|
+
});
|
|
1278
|
+
} else {
|
|
1279
|
+
route._lazyPromise = Promise.resolve();
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
if (route._componentsPromise === void 0) {
|
|
1283
|
+
route._componentsPromise = route._lazyPromise.then(
|
|
1284
|
+
() => Promise.all(
|
|
1285
|
+
componentTypes.map(async (type) => {
|
|
1286
|
+
const component = route.options[type];
|
|
1287
|
+
if (component == null ? void 0 : component.preload) {
|
|
1288
|
+
await component.preload();
|
|
1289
|
+
}
|
|
1290
|
+
})
|
|
1291
|
+
)
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
return route._componentsPromise;
|
|
1295
|
+
};
|
|
1296
|
+
this.preloadRoute = async (opts) => {
|
|
1297
|
+
const next = this.buildLocation(opts);
|
|
1298
|
+
let matches = this.matchRoutes(next, {
|
|
1299
|
+
throwOnError: true,
|
|
1300
|
+
preload: true,
|
|
1301
|
+
dest: opts
|
|
1302
|
+
});
|
|
1303
|
+
const activeMatchIds = new Set(
|
|
1304
|
+
[...this.state.matches, ...this.state.pendingMatches ?? []].map(
|
|
1305
|
+
(d) => d.id
|
|
1306
|
+
)
|
|
1307
|
+
);
|
|
1308
|
+
const loadedMatchIds = /* @__PURE__ */ new Set([
|
|
1309
|
+
...activeMatchIds,
|
|
1310
|
+
...this.state.cachedMatches.map((d) => d.id)
|
|
1311
|
+
]);
|
|
1312
|
+
store.batch(() => {
|
|
1313
|
+
matches.forEach((match) => {
|
|
1314
|
+
if (!loadedMatchIds.has(match.id)) {
|
|
1315
|
+
this.__store.setState((s) => ({
|
|
1316
|
+
...s,
|
|
1317
|
+
cachedMatches: [...s.cachedMatches, match]
|
|
1318
|
+
}));
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
});
|
|
1322
|
+
try {
|
|
1323
|
+
matches = await this.loadMatches({
|
|
1324
|
+
matches,
|
|
1325
|
+
location: next,
|
|
1326
|
+
preload: true,
|
|
1327
|
+
updateMatch: (id, updater) => {
|
|
1328
|
+
if (activeMatchIds.has(id)) {
|
|
1329
|
+
matches = matches.map((d) => d.id === id ? updater(d) : d);
|
|
1330
|
+
} else {
|
|
1331
|
+
this.updateMatch(id, updater);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
return matches;
|
|
1336
|
+
} catch (err) {
|
|
1337
|
+
if (redirect.isRedirect(err)) {
|
|
1338
|
+
if (err.reloadDocument) {
|
|
1339
|
+
return void 0;
|
|
1340
|
+
}
|
|
1341
|
+
return await this.preloadRoute({
|
|
1342
|
+
...err,
|
|
1343
|
+
_fromLocation: next
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
if (!notFound.isNotFound(err)) {
|
|
1347
|
+
console.error(err);
|
|
1348
|
+
}
|
|
1349
|
+
return void 0;
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
this.matchRoute = (location, opts) => {
|
|
1353
|
+
const matchLocation = {
|
|
1354
|
+
...location,
|
|
1355
|
+
to: location.to ? this.resolvePathWithBase(
|
|
1356
|
+
location.from || "",
|
|
1357
|
+
location.to
|
|
1358
|
+
) : void 0,
|
|
1359
|
+
params: location.params || {},
|
|
1360
|
+
leaveParams: true
|
|
1361
|
+
};
|
|
1362
|
+
const next = this.buildLocation(matchLocation);
|
|
1363
|
+
if ((opts == null ? void 0 : opts.pending) && this.state.status !== "pending") {
|
|
1364
|
+
return false;
|
|
1365
|
+
}
|
|
1366
|
+
const pending = (opts == null ? void 0 : opts.pending) === void 0 ? !this.state.isLoading : opts.pending;
|
|
1367
|
+
const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
|
|
1368
|
+
const match = path.matchPathname(this.basepath, baseLocation.pathname, {
|
|
1369
|
+
...opts,
|
|
1370
|
+
to: next.pathname
|
|
1371
|
+
});
|
|
1372
|
+
if (!match) {
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
if (location.params) {
|
|
1376
|
+
if (!utils.deepEqual(match, location.params, { partial: true })) {
|
|
1377
|
+
return false;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
if (match && ((opts == null ? void 0 : opts.includeSearch) ?? true)) {
|
|
1381
|
+
return utils.deepEqual(baseLocation.search, next.search, { partial: true }) ? match : false;
|
|
1382
|
+
}
|
|
1383
|
+
return match;
|
|
1384
|
+
};
|
|
1385
|
+
this._handleNotFound = (matches, err, {
|
|
1386
|
+
updateMatch = this.updateMatch
|
|
1387
|
+
} = {}) => {
|
|
1388
|
+
var _a;
|
|
1389
|
+
const routeCursor = this.routesById[err.routeId ?? ""] ?? this.routeTree;
|
|
1390
|
+
const matchesByRouteId = {};
|
|
1391
|
+
for (const match of matches) {
|
|
1392
|
+
matchesByRouteId[match.routeId] = match;
|
|
1393
|
+
}
|
|
1394
|
+
if (!routeCursor.options.notFoundComponent && ((_a = this.options) == null ? void 0 : _a.defaultNotFoundComponent)) {
|
|
1395
|
+
routeCursor.options.notFoundComponent = this.options.defaultNotFoundComponent;
|
|
1396
|
+
}
|
|
1397
|
+
invariant(
|
|
1398
|
+
routeCursor.options.notFoundComponent,
|
|
1399
|
+
"No notFoundComponent found. Please set a notFoundComponent on your route or provide a defaultNotFoundComponent to the router."
|
|
1400
|
+
);
|
|
1401
|
+
const matchForRoute = matchesByRouteId[routeCursor.id];
|
|
1402
|
+
invariant(
|
|
1403
|
+
matchForRoute,
|
|
1404
|
+
"Could not find match for route: " + routeCursor.id
|
|
1405
|
+
);
|
|
1406
|
+
updateMatch(matchForRoute.id, (prev) => ({
|
|
1407
|
+
...prev,
|
|
1408
|
+
status: "notFound",
|
|
1409
|
+
error: err,
|
|
1410
|
+
isFetching: false
|
|
1411
|
+
}));
|
|
1412
|
+
if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
|
|
1413
|
+
err.routeId = routeCursor.parentRoute.id;
|
|
1414
|
+
this._handleNotFound(matches, err, {
|
|
1415
|
+
updateMatch
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
this.hasNotFoundMatch = () => {
|
|
1420
|
+
return this.__store.state.matches.some(
|
|
1421
|
+
(d) => d.status === "notFound" || d.globalNotFound
|
|
1422
|
+
);
|
|
1423
|
+
};
|
|
1424
|
+
this.update({
|
|
1425
|
+
defaultPreloadDelay: 50,
|
|
1426
|
+
defaultPendingMs: 1e3,
|
|
1427
|
+
defaultPendingMinMs: 500,
|
|
1428
|
+
context: void 0,
|
|
1429
|
+
...options,
|
|
1430
|
+
caseSensitive: options.caseSensitive ?? false,
|
|
1431
|
+
notFoundMode: options.notFoundMode ?? "fuzzy",
|
|
1432
|
+
stringifySearch: options.stringifySearch ?? searchParams.defaultStringifySearch,
|
|
1433
|
+
parseSearch: options.parseSearch ?? searchParams.defaultParseSearch
|
|
1434
|
+
});
|
|
1435
|
+
if (typeof document !== "undefined") {
|
|
1436
|
+
window.__TSR_ROUTER__ = this;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
get state() {
|
|
1440
|
+
return this.__store.state;
|
|
1441
|
+
}
|
|
1442
|
+
get looseRoutesById() {
|
|
1443
|
+
return this.routesById;
|
|
1444
|
+
}
|
|
1445
|
+
matchRoutesInternal(next, opts) {
|
|
1446
|
+
const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
1447
|
+
next,
|
|
1448
|
+
opts == null ? void 0 : opts.dest
|
|
1449
|
+
);
|
|
1450
|
+
let isGlobalNotFound = false;
|
|
1451
|
+
if (
|
|
1452
|
+
// If we found a route, and it's not an index route and we have left over path
|
|
1453
|
+
foundRoute ? foundRoute.path !== "/" && routeParams["**"] : (
|
|
1454
|
+
// Or if we didn't find a route and we have left over path
|
|
1455
|
+
path.trimPathRight(next.pathname)
|
|
1456
|
+
)
|
|
1457
|
+
) {
|
|
1458
|
+
if (this.options.notFoundRoute) {
|
|
1459
|
+
matchedRoutes.push(this.options.notFoundRoute);
|
|
1460
|
+
} else {
|
|
1461
|
+
isGlobalNotFound = true;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
const globalNotFoundRouteId = (() => {
|
|
1465
|
+
if (!isGlobalNotFound) {
|
|
1466
|
+
return void 0;
|
|
1467
|
+
}
|
|
1468
|
+
if (this.options.notFoundMode !== "root") {
|
|
1469
|
+
for (let i = matchedRoutes.length - 1; i >= 0; i--) {
|
|
1470
|
+
const route = matchedRoutes[i];
|
|
1471
|
+
if (route.children) {
|
|
1472
|
+
return route.id;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
return root.rootRouteId;
|
|
1477
|
+
})();
|
|
1478
|
+
const parseErrors = matchedRoutes.map((route) => {
|
|
1479
|
+
var _a;
|
|
1480
|
+
let parsedParamsError;
|
|
1481
|
+
const parseParams = ((_a = route.options.params) == null ? void 0 : _a.parse) ?? route.options.parseParams;
|
|
1482
|
+
if (parseParams) {
|
|
1483
|
+
try {
|
|
1484
|
+
const parsedParams = parseParams(routeParams);
|
|
1485
|
+
Object.assign(routeParams, parsedParams);
|
|
1486
|
+
} catch (err) {
|
|
1487
|
+
parsedParamsError = new PathParamError(err.message, {
|
|
1488
|
+
cause: err
|
|
1489
|
+
});
|
|
1490
|
+
if (opts == null ? void 0 : opts.throwOnError) {
|
|
1491
|
+
throw parsedParamsError;
|
|
1492
|
+
}
|
|
1493
|
+
return parsedParamsError;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return;
|
|
1497
|
+
});
|
|
1498
|
+
const matches = [];
|
|
1499
|
+
const getParentContext = (parentMatch) => {
|
|
1500
|
+
const parentMatchId = parentMatch == null ? void 0 : parentMatch.id;
|
|
1501
|
+
const parentContext = !parentMatchId ? this.options.context ?? {} : parentMatch.context ?? this.options.context ?? {};
|
|
1502
|
+
return parentContext;
|
|
1503
|
+
};
|
|
1504
|
+
matchedRoutes.forEach((route, index) => {
|
|
1505
|
+
var _a, _b;
|
|
1506
|
+
const parentMatch = matches[index - 1];
|
|
1507
|
+
const [preMatchSearch, strictMatchSearch, searchError] = (() => {
|
|
1508
|
+
const parentSearch = (parentMatch == null ? void 0 : parentMatch.search) ?? next.search;
|
|
1509
|
+
const parentStrictSearch = (parentMatch == null ? void 0 : parentMatch._strictSearch) ?? {};
|
|
1510
|
+
try {
|
|
1511
|
+
const strictSearch = validateSearch(route.options.validateSearch, { ...parentSearch }) ?? {};
|
|
1512
|
+
return [
|
|
1513
|
+
{
|
|
1514
|
+
...parentSearch,
|
|
1515
|
+
...strictSearch
|
|
1516
|
+
},
|
|
1517
|
+
{ ...parentStrictSearch, ...strictSearch },
|
|
1518
|
+
void 0
|
|
1519
|
+
];
|
|
1520
|
+
} catch (err) {
|
|
1521
|
+
let searchParamError = err;
|
|
1522
|
+
if (!(err instanceof SearchParamError)) {
|
|
1523
|
+
searchParamError = new SearchParamError(err.message, {
|
|
1524
|
+
cause: err
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
if (opts == null ? void 0 : opts.throwOnError) {
|
|
1528
|
+
throw searchParamError;
|
|
1529
|
+
}
|
|
1530
|
+
return [parentSearch, {}, searchParamError];
|
|
1531
|
+
}
|
|
1532
|
+
})();
|
|
1533
|
+
const loaderDeps = ((_b = (_a = route.options).loaderDeps) == null ? void 0 : _b.call(_a, {
|
|
1534
|
+
search: preMatchSearch
|
|
1535
|
+
})) ?? "";
|
|
1536
|
+
const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
|
|
1537
|
+
const { usedParams, interpolatedPath } = path.interpolatePath({
|
|
1538
|
+
path: route.fullPath,
|
|
1539
|
+
params: routeParams,
|
|
1540
|
+
decodeCharMap: this.pathParamsDecodeCharMap
|
|
1541
|
+
});
|
|
1542
|
+
const matchId = path.interpolatePath({
|
|
1543
|
+
path: route.id,
|
|
1544
|
+
params: routeParams,
|
|
1545
|
+
leaveWildcards: true,
|
|
1546
|
+
decodeCharMap: this.pathParamsDecodeCharMap
|
|
1547
|
+
}).interpolatedPath + loaderDepsHash;
|
|
1548
|
+
const existingMatch = this.getMatch(matchId);
|
|
1549
|
+
const previousMatch = this.state.matches.find(
|
|
1550
|
+
(d) => d.routeId === route.id
|
|
1551
|
+
);
|
|
1552
|
+
const cause = previousMatch ? "stay" : "enter";
|
|
1553
|
+
let match;
|
|
1554
|
+
if (existingMatch) {
|
|
1555
|
+
match = {
|
|
1556
|
+
...existingMatch,
|
|
1557
|
+
cause,
|
|
1558
|
+
params: previousMatch ? utils.replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
|
|
1559
|
+
_strictParams: usedParams,
|
|
1560
|
+
search: previousMatch ? utils.replaceEqualDeep(previousMatch.search, preMatchSearch) : utils.replaceEqualDeep(existingMatch.search, preMatchSearch),
|
|
1561
|
+
_strictSearch: strictMatchSearch
|
|
1562
|
+
};
|
|
1563
|
+
} else {
|
|
1564
|
+
const status = route.options.loader || route.options.beforeLoad || route.lazyFn || routeNeedsPreload(route) ? "pending" : "success";
|
|
1565
|
+
match = {
|
|
1566
|
+
id: matchId,
|
|
1567
|
+
index,
|
|
1568
|
+
routeId: route.id,
|
|
1569
|
+
params: previousMatch ? utils.replaceEqualDeep(previousMatch.params, routeParams) : routeParams,
|
|
1570
|
+
_strictParams: usedParams,
|
|
1571
|
+
pathname: path.joinPaths([this.basepath, interpolatedPath]),
|
|
1572
|
+
updatedAt: Date.now(),
|
|
1573
|
+
search: previousMatch ? utils.replaceEqualDeep(previousMatch.search, preMatchSearch) : preMatchSearch,
|
|
1574
|
+
_strictSearch: strictMatchSearch,
|
|
1575
|
+
searchError: void 0,
|
|
1576
|
+
status,
|
|
1577
|
+
isFetching: false,
|
|
1578
|
+
error: void 0,
|
|
1579
|
+
paramsError: parseErrors[index],
|
|
1580
|
+
__routeContext: {},
|
|
1581
|
+
__beforeLoadContext: {},
|
|
1582
|
+
context: {},
|
|
1583
|
+
abortController: new AbortController(),
|
|
1584
|
+
fetchCount: 0,
|
|
1585
|
+
cause,
|
|
1586
|
+
loaderDeps: previousMatch ? utils.replaceEqualDeep(previousMatch.loaderDeps, loaderDeps) : loaderDeps,
|
|
1587
|
+
invalid: false,
|
|
1588
|
+
preload: false,
|
|
1589
|
+
links: void 0,
|
|
1590
|
+
scripts: void 0,
|
|
1591
|
+
headScripts: void 0,
|
|
1592
|
+
meta: void 0,
|
|
1593
|
+
staticData: route.options.staticData || {},
|
|
1594
|
+
loadPromise: utils.createControlledPromise(),
|
|
1595
|
+
fullPath: route.fullPath
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
if (!(opts == null ? void 0 : opts.preload)) {
|
|
1599
|
+
match.globalNotFound = globalNotFoundRouteId === route.id;
|
|
1600
|
+
}
|
|
1601
|
+
match.searchError = searchError;
|
|
1602
|
+
const parentContext = getParentContext(parentMatch);
|
|
1603
|
+
match.context = {
|
|
1604
|
+
...parentContext,
|
|
1605
|
+
...match.__routeContext,
|
|
1606
|
+
...match.__beforeLoadContext
|
|
1607
|
+
};
|
|
1608
|
+
matches.push(match);
|
|
1609
|
+
});
|
|
1610
|
+
matches.forEach((match, index) => {
|
|
1611
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1612
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1613
|
+
const existingMatch = this.getMatch(match.id);
|
|
1614
|
+
if (!existingMatch && (opts == null ? void 0 : opts._buildLocation) !== true) {
|
|
1615
|
+
const parentMatch = matches[index - 1];
|
|
1616
|
+
const parentContext = getParentContext(parentMatch);
|
|
1617
|
+
const contextFnContext = {
|
|
1618
|
+
deps: match.loaderDeps,
|
|
1619
|
+
params: match.params,
|
|
1620
|
+
context: parentContext,
|
|
1621
|
+
location: next,
|
|
1622
|
+
navigate: (opts2) => this.navigate({ ...opts2, _fromLocation: next }),
|
|
1623
|
+
buildLocation: this.buildLocation,
|
|
1624
|
+
cause: match.cause,
|
|
1625
|
+
abortController: match.abortController,
|
|
1626
|
+
preload: !!match.preload,
|
|
1627
|
+
matches
|
|
1628
|
+
};
|
|
1629
|
+
match.__routeContext = ((_b = (_a = route.options).context) == null ? void 0 : _b.call(_a, contextFnContext)) ?? {};
|
|
1630
|
+
match.context = {
|
|
1631
|
+
...parentContext,
|
|
1632
|
+
...match.__routeContext,
|
|
1633
|
+
...match.__beforeLoadContext
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
if (match.status === "success") {
|
|
1637
|
+
match.headers = (_d = (_c = route.options).headers) == null ? void 0 : _d.call(_c, {
|
|
1638
|
+
loaderData: match.loaderData
|
|
1639
|
+
});
|
|
1640
|
+
const assetContext = {
|
|
1641
|
+
matches,
|
|
1642
|
+
match,
|
|
1643
|
+
params: match.params,
|
|
1644
|
+
loaderData: match.loaderData
|
|
1645
|
+
};
|
|
1646
|
+
const headFnContent = (_f = (_e = route.options).head) == null ? void 0 : _f.call(_e, assetContext);
|
|
1647
|
+
match.links = headFnContent == null ? void 0 : headFnContent.links;
|
|
1648
|
+
match.headScripts = headFnContent == null ? void 0 : headFnContent.scripts;
|
|
1649
|
+
match.meta = headFnContent == null ? void 0 : headFnContent.meta;
|
|
1650
|
+
match.scripts = (_h = (_g = route.options).scripts) == null ? void 0 : _h.call(_g, assetContext);
|
|
1651
|
+
}
|
|
1652
|
+
});
|
|
1653
|
+
return matches;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
class SearchParamError extends Error {
|
|
1657
|
+
}
|
|
1658
|
+
class PathParamError extends Error {
|
|
1659
|
+
}
|
|
1660
|
+
function lazyFn(fn, key) {
|
|
1661
|
+
return async (...args) => {
|
|
1662
|
+
const imported = await fn();
|
|
1663
|
+
return imported[key || "default"](...args);
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
function getInitialRouterState(location) {
|
|
1667
|
+
return {
|
|
1668
|
+
loadedAt: 0,
|
|
1669
|
+
isLoading: false,
|
|
1670
|
+
isTransitioning: false,
|
|
1671
|
+
status: "idle",
|
|
1672
|
+
resolvedLocation: void 0,
|
|
1673
|
+
location,
|
|
1674
|
+
matches: [],
|
|
1675
|
+
pendingMatches: [],
|
|
1676
|
+
cachedMatches: [],
|
|
1677
|
+
statusCode: 200
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
function validateSearch(validateSearch2, input) {
|
|
1681
|
+
if (validateSearch2 == null) return {};
|
|
1682
|
+
if ("~standard" in validateSearch2) {
|
|
1683
|
+
const result = validateSearch2["~standard"].validate(input);
|
|
1684
|
+
if (result instanceof Promise)
|
|
1685
|
+
throw new SearchParamError("Async validation not supported");
|
|
1686
|
+
if (result.issues)
|
|
1687
|
+
throw new SearchParamError(JSON.stringify(result.issues, void 0, 2), {
|
|
1688
|
+
cause: result
|
|
1689
|
+
});
|
|
1690
|
+
return result.value;
|
|
1691
|
+
}
|
|
1692
|
+
if ("parse" in validateSearch2) {
|
|
1693
|
+
return validateSearch2.parse(input);
|
|
1694
|
+
}
|
|
1695
|
+
if (typeof validateSearch2 === "function") {
|
|
1696
|
+
return validateSearch2(input);
|
|
1697
|
+
}
|
|
1698
|
+
return {};
|
|
1699
|
+
}
|
|
1700
|
+
const componentTypes = [
|
|
1701
|
+
"component",
|
|
1702
|
+
"errorComponent",
|
|
1703
|
+
"pendingComponent",
|
|
1704
|
+
"notFoundComponent"
|
|
1705
|
+
];
|
|
1706
|
+
function routeNeedsPreload(route) {
|
|
1707
|
+
var _a;
|
|
1708
|
+
for (const componentType of componentTypes) {
|
|
1709
|
+
if ((_a = route.options[componentType]) == null ? void 0 : _a.preload) {
|
|
1710
|
+
return true;
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
return false;
|
|
1714
|
+
}
|
|
1715
|
+
exports.PathParamError = PathParamError;
|
|
1716
|
+
exports.RouterCore = RouterCore;
|
|
1717
|
+
exports.SearchParamError = SearchParamError;
|
|
1718
|
+
exports.componentTypes = componentTypes;
|
|
26
1719
|
exports.defaultSerializeError = defaultSerializeError;
|
|
1720
|
+
exports.getInitialRouterState = getInitialRouterState;
|
|
27
1721
|
exports.getLocationChangeInfo = getLocationChangeInfo;
|
|
1722
|
+
exports.lazyFn = lazyFn;
|
|
28
1723
|
//# sourceMappingURL=router.cjs.map
|