@tanstack/react-router 1.45.2 → 1.45.4
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/CatchBoundary.cjs +1 -1
- package/dist/cjs/CatchBoundary.cjs.map +1 -1
- package/dist/cjs/CatchBoundary.d.cts +1 -1
- package/dist/cjs/Match.cjs +24 -34
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +4 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +5 -2
- package/dist/cjs/RouterProvider.cjs +0 -8
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/RouterProvider.d.cts +1 -4
- package/dist/cjs/Transitioner.cjs +5 -1
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/index.cjs +0 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +1 -0
- package/dist/cjs/router.cjs +464 -407
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +22 -10
- package/dist/esm/CatchBoundary.d.ts +1 -1
- package/dist/esm/CatchBoundary.js +1 -1
- package/dist/esm/CatchBoundary.js.map +1 -1
- package/dist/esm/Match.js +24 -34
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.d.ts +5 -2
- package/dist/esm/Matches.js +4 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.d.ts +1 -4
- package/dist/esm/RouterProvider.js +1 -9
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/Transitioner.js +5 -1
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/route.d.ts +1 -0
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +22 -10
- package/dist/esm/router.js +466 -409
- package/dist/esm/router.js.map +1 -1
- package/package.json +2 -2
- package/src/CatchBoundary.tsx +7 -3
- package/src/Match.tsx +45 -36
- package/src/Matches.tsx +10 -3
- package/src/RouterProvider.tsx +0 -11
- package/src/Transitioner.tsx +5 -1
- package/src/index.tsx +0 -1
- package/src/route.ts +1 -0
- package/src/router.ts +647 -565
package/dist/esm/router.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createMemoryHistory, createBrowserHistory } from "@tanstack/history";
|
|
2
2
|
import { Store } from "@tanstack/react-store";
|
|
3
3
|
import invariant from "tiny-invariant";
|
|
4
4
|
import warning from "tiny-warning";
|
|
5
5
|
import { rootRouteId } from "./root.js";
|
|
6
6
|
import { defaultStringifySearch, defaultParseSearch } from "./searchParams.js";
|
|
7
|
-
import { createControlledPromise, replaceEqualDeep, pick,
|
|
8
|
-
import { getRouteMatch } from "./RouterProvider.js";
|
|
7
|
+
import { createControlledPromise, replaceEqualDeep, pick, deepEqual, last, functionalUpdate } from "./utils.js";
|
|
9
8
|
import { trimPath, trimPathLeft, parsePathname, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths } from "./path.js";
|
|
10
9
|
import { isResolvedRedirect, isRedirect } from "./redirects.js";
|
|
11
10
|
import { isNotFound } from "./not-found.js";
|
|
@@ -28,9 +27,7 @@ class Router {
|
|
|
28
27
|
)}`;
|
|
29
28
|
this.resetNextScroll = true;
|
|
30
29
|
this.shouldViewTransition = void 0;
|
|
31
|
-
this.latestLoadPromise = Promise.resolve();
|
|
32
30
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
33
|
-
this.isServer = typeof document === "undefined";
|
|
34
31
|
this.startReactTransition = (fn) => fn();
|
|
35
32
|
this.update = (newOptions) => {
|
|
36
33
|
if (newOptions.notFoundRoute) {
|
|
@@ -43,6 +40,7 @@ class Router {
|
|
|
43
40
|
...this.options,
|
|
44
41
|
...newOptions
|
|
45
42
|
};
|
|
43
|
+
this.isServer = this.options.isServer ?? typeof document === "undefined";
|
|
46
44
|
if (!this.basepath || newOptions.basepath && newOptions.basepath !== previousOptions.basepath) {
|
|
47
45
|
if (newOptions.basepath === void 0 || newOptions.basepath === "" || newOptions.basepath === "/") {
|
|
48
46
|
this.basepath = "/";
|
|
@@ -54,9 +52,9 @@ class Router {
|
|
|
54
52
|
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
55
53
|
!this.history || this.options.history && this.options.history !== this.history
|
|
56
54
|
) {
|
|
57
|
-
this.history = this.options.history ?? (
|
|
58
|
-
initialEntries: [this.
|
|
59
|
-
}));
|
|
55
|
+
this.history = this.options.history ?? (this.isServer ? createMemoryHistory({
|
|
56
|
+
initialEntries: [this.basepath || "/"]
|
|
57
|
+
}) : createBrowserHistory());
|
|
60
58
|
this.latestLocation = this.parseLocation();
|
|
61
59
|
}
|
|
62
60
|
if (this.options.routeTree !== this.routeTree) {
|
|
@@ -170,11 +168,6 @@ class Router {
|
|
|
170
168
|
}
|
|
171
169
|
});
|
|
172
170
|
};
|
|
173
|
-
this.checkLatest = (promise) => {
|
|
174
|
-
if (this.latestLoadPromise !== promise) {
|
|
175
|
-
throw this.latestLoadPromise;
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
171
|
this.parseLocation = (previousLocation) => {
|
|
179
172
|
const parse = ({
|
|
180
173
|
pathname,
|
|
@@ -326,7 +319,7 @@ class Router {
|
|
|
326
319
|
params: routeParams,
|
|
327
320
|
leaveWildcards: true
|
|
328
321
|
}) + loaderDepsHash;
|
|
329
|
-
const existingMatch =
|
|
322
|
+
const existingMatch = this.getMatch(matchId);
|
|
330
323
|
const cause = this.state.matches.find((d) => d.id === matchId) ? "stay" : "enter";
|
|
331
324
|
let match;
|
|
332
325
|
if (existingMatch) {
|
|
@@ -336,11 +329,7 @@ class Router {
|
|
|
336
329
|
params: routeParams
|
|
337
330
|
};
|
|
338
331
|
} else {
|
|
339
|
-
const status = route.options.loader || route.options.beforeLoad ? "pending" : "success";
|
|
340
|
-
const loadPromise = createControlledPromise();
|
|
341
|
-
if (status === "success") {
|
|
342
|
-
loadPromise.resolve();
|
|
343
|
-
}
|
|
332
|
+
const status = route.options.loader || route.options.beforeLoad || route.lazyFn ? "pending" : "success";
|
|
344
333
|
match = {
|
|
345
334
|
id: matchId,
|
|
346
335
|
index,
|
|
@@ -350,12 +339,10 @@ class Router {
|
|
|
350
339
|
updatedAt: Date.now(),
|
|
351
340
|
search: {},
|
|
352
341
|
searchError: void 0,
|
|
353
|
-
status
|
|
342
|
+
status,
|
|
354
343
|
isFetching: false,
|
|
355
344
|
error: void 0,
|
|
356
345
|
paramsError: parseErrors[index],
|
|
357
|
-
loaderPromise: Promise.resolve(),
|
|
358
|
-
loadPromise,
|
|
359
346
|
routeContext: void 0,
|
|
360
347
|
context: void 0,
|
|
361
348
|
abortController: new AbortController(),
|
|
@@ -366,7 +353,8 @@ class Router {
|
|
|
366
353
|
preload: false,
|
|
367
354
|
links: (_d = (_c = route.options).links) == null ? void 0 : _d.call(_c),
|
|
368
355
|
scripts: (_f = (_e = route.options).scripts) == null ? void 0 : _f.call(_e),
|
|
369
|
-
staticData: route.options.staticData || {}
|
|
356
|
+
staticData: route.options.staticData || {},
|
|
357
|
+
loadPromise: createControlledPromise()
|
|
370
358
|
};
|
|
371
359
|
}
|
|
372
360
|
if (match.status === "success") {
|
|
@@ -390,8 +378,10 @@ class Router {
|
|
|
390
378
|
return matches;
|
|
391
379
|
};
|
|
392
380
|
this.cancelMatch = (id) => {
|
|
393
|
-
|
|
394
|
-
|
|
381
|
+
const match = this.getMatch(id);
|
|
382
|
+
if (!match) return;
|
|
383
|
+
match.abortController.abort();
|
|
384
|
+
clearTimeout(match.pendingTimeout);
|
|
395
385
|
};
|
|
396
386
|
this.cancelMatches = () => {
|
|
397
387
|
var _a;
|
|
@@ -515,8 +505,7 @@ class Router {
|
|
|
515
505
|
}
|
|
516
506
|
return buildWithMatches(opts);
|
|
517
507
|
};
|
|
518
|
-
this.commitLocation =
|
|
519
|
-
startTransition,
|
|
508
|
+
this.commitLocation = ({
|
|
520
509
|
viewTransition,
|
|
521
510
|
ignoreBlocker,
|
|
522
511
|
...next
|
|
@@ -528,6 +517,10 @@ class Router {
|
|
|
528
517
|
return isEqual;
|
|
529
518
|
};
|
|
530
519
|
const isSameUrl = this.latestLocation.href === next.href;
|
|
520
|
+
const previousCommitPromise = this.commitLocationPromise;
|
|
521
|
+
this.commitLocationPromise = createControlledPromise(() => {
|
|
522
|
+
previousCommitPromise == null ? void 0 : previousCommitPromise.resolve();
|
|
523
|
+
});
|
|
531
524
|
if (isSameUrl && isSameState()) {
|
|
532
525
|
this.load();
|
|
533
526
|
} else {
|
|
@@ -562,12 +555,14 @@ class Router {
|
|
|
562
555
|
);
|
|
563
556
|
}
|
|
564
557
|
this.resetNextScroll = next.resetScroll ?? true;
|
|
565
|
-
|
|
558
|
+
if (!this.history.subscribers.size) {
|
|
559
|
+
this.load();
|
|
560
|
+
}
|
|
561
|
+
return this.commitLocationPromise;
|
|
566
562
|
};
|
|
567
563
|
this.buildAndCommitLocation = ({
|
|
568
564
|
replace,
|
|
569
565
|
resetScroll,
|
|
570
|
-
startTransition,
|
|
571
566
|
viewTransition,
|
|
572
567
|
ignoreBlocker,
|
|
573
568
|
...rest
|
|
@@ -575,7 +570,6 @@ class Router {
|
|
|
575
570
|
const location = this.buildLocation(rest);
|
|
576
571
|
return this.commitLocation({
|
|
577
572
|
...location,
|
|
578
|
-
startTransition,
|
|
579
573
|
viewTransition,
|
|
580
574
|
replace,
|
|
581
575
|
resetScroll,
|
|
@@ -592,7 +586,7 @@ class Router {
|
|
|
592
586
|
}
|
|
593
587
|
invariant(
|
|
594
588
|
!isExternal,
|
|
595
|
-
"Attempting to navigate to external url with
|
|
589
|
+
"Attempting to navigate to external url with router.navigate!"
|
|
596
590
|
);
|
|
597
591
|
return this.buildAndCommitLocation({
|
|
598
592
|
...rest,
|
|
@@ -603,127 +597,162 @@ class Router {
|
|
|
603
597
|
};
|
|
604
598
|
this.load = async () => {
|
|
605
599
|
this.latestLocation = this.parseLocation(this.latestLocation);
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
this.latestLoadPromise = promise;
|
|
600
|
+
this.__store.setState((s) => ({
|
|
601
|
+
...s,
|
|
602
|
+
loadedAt: Date.now()
|
|
603
|
+
}));
|
|
611
604
|
let redirect;
|
|
612
605
|
let notFound;
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
pendingMatches
|
|
622
|
-
this.__store.
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
606
|
+
const loadPromise = new Promise((resolve) => {
|
|
607
|
+
this.startReactTransition(async () => {
|
|
608
|
+
var _a;
|
|
609
|
+
try {
|
|
610
|
+
const next = this.latestLocation;
|
|
611
|
+
const prevLocation = this.state.resolvedLocation;
|
|
612
|
+
const pathDidChange = prevLocation.href !== next.href;
|
|
613
|
+
this.cancelMatches();
|
|
614
|
+
let pendingMatches;
|
|
615
|
+
this.__store.batch(() => {
|
|
616
|
+
pendingMatches = this.matchRoutes(next.pathname, next.search);
|
|
617
|
+
this.__store.setState((s) => ({
|
|
618
|
+
...s,
|
|
619
|
+
status: "pending",
|
|
620
|
+
isLoading: true,
|
|
621
|
+
location: next,
|
|
622
|
+
pendingMatches,
|
|
623
|
+
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
624
|
+
cachedMatches: s.cachedMatches.filter((d) => {
|
|
625
|
+
return !pendingMatches.find((e) => e.id === d.id);
|
|
626
|
+
})
|
|
627
|
+
}));
|
|
628
|
+
});
|
|
629
|
+
if (!this.state.redirect) {
|
|
630
|
+
this.emit({
|
|
631
|
+
type: "onBeforeNavigate",
|
|
632
|
+
fromLocation: prevLocation,
|
|
633
|
+
toLocation: next,
|
|
634
|
+
pathChanged: pathDidChange
|
|
635
|
+
});
|
|
636
|
+
}
|
|
635
637
|
this.emit({
|
|
636
|
-
type: "
|
|
638
|
+
type: "onBeforeLoad",
|
|
637
639
|
fromLocation: prevLocation,
|
|
638
640
|
toLocation: next,
|
|
639
641
|
pathChanged: pathDidChange
|
|
640
642
|
});
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
cachedMatches: [
|
|
676
|
-
...s.cachedMatches,
|
|
677
|
-
...exitingMatches.filter((d) => d.status !== "error")
|
|
678
|
-
]
|
|
679
|
-
};
|
|
643
|
+
await this.loadMatches({
|
|
644
|
+
matches: pendingMatches,
|
|
645
|
+
location: next,
|
|
646
|
+
// eslint-disable-next-line ts/require-await
|
|
647
|
+
onReady: async () => {
|
|
648
|
+
this.startViewTransition(async () => {
|
|
649
|
+
let exitingMatches;
|
|
650
|
+
let enteringMatches;
|
|
651
|
+
let stayingMatches;
|
|
652
|
+
this.__store.batch(() => {
|
|
653
|
+
this.__store.setState((s) => {
|
|
654
|
+
const previousMatches = s.matches;
|
|
655
|
+
const newMatches = s.pendingMatches || s.matches;
|
|
656
|
+
exitingMatches = previousMatches.filter(
|
|
657
|
+
(match) => !newMatches.find((d) => d.id === match.id)
|
|
658
|
+
);
|
|
659
|
+
enteringMatches = newMatches.filter(
|
|
660
|
+
(match) => !previousMatches.find((d) => d.id === match.id)
|
|
661
|
+
);
|
|
662
|
+
stayingMatches = previousMatches.filter(
|
|
663
|
+
(match) => newMatches.find((d) => d.id === match.id)
|
|
664
|
+
);
|
|
665
|
+
return {
|
|
666
|
+
...s,
|
|
667
|
+
isLoading: false,
|
|
668
|
+
matches: newMatches,
|
|
669
|
+
pendingMatches: void 0,
|
|
670
|
+
cachedMatches: [
|
|
671
|
+
...s.cachedMatches,
|
|
672
|
+
...exitingMatches.filter((d) => d.status !== "error")
|
|
673
|
+
]
|
|
674
|
+
};
|
|
675
|
+
});
|
|
676
|
+
this.cleanCache();
|
|
680
677
|
});
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
[
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
(_b = (_a = this.looseRoutesById[match.routeId].options)[hook]) == null ? void 0 : _b.call(_a, match);
|
|
678
|
+
[
|
|
679
|
+
[exitingMatches, "onLeave"],
|
|
680
|
+
[enteringMatches, "onEnter"],
|
|
681
|
+
[stayingMatches, "onStay"]
|
|
682
|
+
].forEach(([matches, hook]) => {
|
|
683
|
+
matches.forEach((match) => {
|
|
684
|
+
var _a2, _b;
|
|
685
|
+
(_b = (_a2 = this.looseRoutesById[match.routeId].options)[hook]) == null ? void 0 : _b.call(_a2, match);
|
|
686
|
+
});
|
|
691
687
|
});
|
|
692
688
|
});
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
})
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
} catch (err) {
|
|
692
|
+
if (isResolvedRedirect(err)) {
|
|
693
|
+
redirect = err;
|
|
694
|
+
if (!this.isServer) {
|
|
695
|
+
this.navigate({ ...err, replace: true, __isRedirect: true });
|
|
696
|
+
}
|
|
697
|
+
} else if (isNotFound(err)) {
|
|
698
|
+
notFound = err;
|
|
701
699
|
}
|
|
702
|
-
|
|
703
|
-
|
|
700
|
+
this.__store.setState((s) => ({
|
|
701
|
+
...s,
|
|
702
|
+
statusCode: redirect ? redirect.statusCode : notFound ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200,
|
|
703
|
+
redirect
|
|
704
|
+
}));
|
|
704
705
|
}
|
|
705
|
-
this.
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
|
|
706
|
+
if (this.latestLoadPromise === loadPromise) {
|
|
707
|
+
(_a = this.commitLocationPromise) == null ? void 0 : _a.resolve();
|
|
708
|
+
this.latestLoadPromise = void 0;
|
|
709
|
+
this.commitLocationPromise = void 0;
|
|
710
|
+
}
|
|
711
|
+
resolve();
|
|
712
|
+
});
|
|
712
713
|
});
|
|
713
|
-
|
|
714
|
+
this.latestLoadPromise = loadPromise;
|
|
715
|
+
await loadPromise;
|
|
716
|
+
while (this.latestLoadPromise && loadPromise !== this.latestLoadPromise) {
|
|
717
|
+
await this.latestLoadPromise;
|
|
718
|
+
}
|
|
714
719
|
};
|
|
715
|
-
this.startViewTransition =
|
|
720
|
+
this.startViewTransition = (fn) => {
|
|
716
721
|
var _a, _b;
|
|
717
722
|
const shouldViewTransition = this.shouldViewTransition ?? this.options.defaultViewTransition;
|
|
718
723
|
delete this.shouldViewTransition;
|
|
719
724
|
((_b = (_a = shouldViewTransition && typeof document !== "undefined" ? document : void 0) == null ? void 0 : _a.startViewTransition) == null ? void 0 : _b.call(_a, fn)) || fn();
|
|
720
725
|
};
|
|
726
|
+
this.updateMatch = (id, updater) => {
|
|
727
|
+
var _a;
|
|
728
|
+
let updated;
|
|
729
|
+
const isPending = (_a = this.state.pendingMatches) == null ? void 0 : _a.find((d) => d.id === id);
|
|
730
|
+
const isMatched = this.state.matches.find((d) => d.id === id);
|
|
731
|
+
const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : "cachedMatches";
|
|
732
|
+
this.__store.setState((s) => {
|
|
733
|
+
var _a2;
|
|
734
|
+
return {
|
|
735
|
+
...s,
|
|
736
|
+
[matchesKey]: (_a2 = s[matchesKey]) == null ? void 0 : _a2.map(
|
|
737
|
+
(d) => d.id === id ? updated = updater(d) : d
|
|
738
|
+
)
|
|
739
|
+
};
|
|
740
|
+
});
|
|
741
|
+
return updated;
|
|
742
|
+
};
|
|
743
|
+
this.getMatch = (matchId) => {
|
|
744
|
+
return [
|
|
745
|
+
...this.state.cachedMatches,
|
|
746
|
+
...this.state.pendingMatches ?? [],
|
|
747
|
+
...this.state.matches
|
|
748
|
+
].find((d) => d.id === matchId);
|
|
749
|
+
};
|
|
721
750
|
this.loadMatches = async ({
|
|
722
|
-
checkLatest,
|
|
723
751
|
location,
|
|
724
752
|
matches,
|
|
725
753
|
preload,
|
|
726
|
-
onReady
|
|
754
|
+
onReady,
|
|
755
|
+
updateMatch = this.updateMatch
|
|
727
756
|
}) => {
|
|
728
757
|
let firstBadMatchIndex;
|
|
729
758
|
let rendered = false;
|
|
@@ -736,41 +765,32 @@ class Router {
|
|
|
736
765
|
if (!this.isServer && !this.state.matches.length) {
|
|
737
766
|
triggerOnReady();
|
|
738
767
|
}
|
|
739
|
-
const updateMatch = (id, updater, opts) => {
|
|
740
|
-
var _a;
|
|
741
|
-
let updated;
|
|
742
|
-
const isPending = (_a = this.state.pendingMatches) == null ? void 0 : _a.find((d) => d.id === id);
|
|
743
|
-
const isMatched = this.state.matches.find((d) => d.id === id);
|
|
744
|
-
const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : "cachedMatches";
|
|
745
|
-
this.__store.setState((s) => {
|
|
746
|
-
var _a2;
|
|
747
|
-
return {
|
|
748
|
-
...s,
|
|
749
|
-
[matchesKey]: (_a2 = s[matchesKey]) == null ? void 0 : _a2.map(
|
|
750
|
-
(d) => d.id === id ? updated = updater(d) : d
|
|
751
|
-
)
|
|
752
|
-
};
|
|
753
|
-
});
|
|
754
|
-
return updated;
|
|
755
|
-
};
|
|
756
768
|
const handleRedirectAndNotFound = (match, err) => {
|
|
769
|
+
var _a, _b, _c;
|
|
757
770
|
if (isResolvedRedirect(err)) throw err;
|
|
758
771
|
if (isRedirect(err) || isNotFound(err)) {
|
|
759
772
|
updateMatch(match.id, (prev) => ({
|
|
760
773
|
...prev,
|
|
761
774
|
status: isRedirect(err) ? "redirected" : isNotFound(err) ? "notFound" : "error",
|
|
762
775
|
isFetching: false,
|
|
763
|
-
error: err
|
|
776
|
+
error: err,
|
|
777
|
+
beforeLoadPromise: void 0,
|
|
778
|
+
loaderPromise: void 0
|
|
764
779
|
}));
|
|
765
780
|
if (!err.routeId) {
|
|
766
781
|
err.routeId = match.routeId;
|
|
767
782
|
}
|
|
783
|
+
(_a = match.beforeLoadPromise) == null ? void 0 : _a.resolve();
|
|
784
|
+
(_b = match.loaderPromise) == null ? void 0 : _b.resolve();
|
|
785
|
+
(_c = match.loadPromise) == null ? void 0 : _c.resolve();
|
|
768
786
|
if (isRedirect(err)) {
|
|
769
787
|
rendered = true;
|
|
770
788
|
err = this.resolveRedirect({ ...err, _fromLocation: location });
|
|
771
789
|
throw err;
|
|
772
790
|
} else if (isNotFound(err)) {
|
|
773
|
-
this.
|
|
791
|
+
this._handleNotFound(matches, err, {
|
|
792
|
+
updateMatch
|
|
793
|
+
});
|
|
774
794
|
throw err;
|
|
775
795
|
}
|
|
776
796
|
}
|
|
@@ -779,268 +799,295 @@ class Router {
|
|
|
779
799
|
await new Promise((resolveAll, rejectAll) => {
|
|
780
800
|
;
|
|
781
801
|
(async () => {
|
|
802
|
+
var _a, _b, _c;
|
|
782
803
|
try {
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
const shouldPending = !!(onReady && !this.isServer && !preload && (route.options.loader || route.options.beforeLoad) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? this.options.defaultPendingComponent));
|
|
790
|
-
if (shouldPending) {
|
|
791
|
-
setTimeout(() => {
|
|
792
|
-
try {
|
|
793
|
-
checkLatest();
|
|
794
|
-
triggerOnReady();
|
|
795
|
-
} catch {
|
|
796
|
-
}
|
|
797
|
-
}, pendingMs);
|
|
804
|
+
const handleSerialError = (index, err, routerCode) => {
|
|
805
|
+
var _a2, _b2;
|
|
806
|
+
const { id: matchId, routeId } = matches[index];
|
|
807
|
+
const route = this.looseRoutesById[routeId];
|
|
808
|
+
if (err instanceof Promise) {
|
|
809
|
+
throw err;
|
|
798
810
|
}
|
|
799
|
-
|
|
800
|
-
|
|
811
|
+
err.routerCode = routerCode;
|
|
812
|
+
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
813
|
+
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
814
|
+
try {
|
|
815
|
+
(_b2 = (_a2 = route.options).onError) == null ? void 0 : _b2.call(_a2, err);
|
|
816
|
+
} catch (errorHandlerErr) {
|
|
817
|
+
err = errorHandlerErr;
|
|
818
|
+
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
801
819
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
matches[index] = match = updateMatch(match.id, (prev) => ({
|
|
808
|
-
...prev,
|
|
809
|
-
isFetching: "beforeLoad",
|
|
810
|
-
loadPromise
|
|
811
|
-
}));
|
|
812
|
-
const handleSerialError = (err, routerCode) => {
|
|
813
|
-
var _a, _b;
|
|
814
|
-
if (err instanceof Promise) {
|
|
815
|
-
throw err;
|
|
816
|
-
}
|
|
817
|
-
err.routerCode = routerCode;
|
|
818
|
-
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
819
|
-
handleRedirectAndNotFound(match, err);
|
|
820
|
-
try {
|
|
821
|
-
(_b = (_a = route.options).onError) == null ? void 0 : _b.call(_a, err);
|
|
822
|
-
} catch (errorHandlerErr) {
|
|
823
|
-
err = errorHandlerErr;
|
|
824
|
-
handleRedirectAndNotFound(match, err);
|
|
825
|
-
}
|
|
826
|
-
matches[index] = match = updateMatch(match.id, () => ({
|
|
827
|
-
...match,
|
|
820
|
+
updateMatch(matchId, (prev) => {
|
|
821
|
+
var _a3;
|
|
822
|
+
(_a3 = prev.beforeLoadPromise) == null ? void 0 : _a3.resolve();
|
|
823
|
+
return {
|
|
824
|
+
...prev,
|
|
828
825
|
error: err,
|
|
829
826
|
status: "error",
|
|
827
|
+
isFetching: false,
|
|
830
828
|
updatedAt: Date.now(),
|
|
831
|
-
abortController: new AbortController()
|
|
832
|
-
|
|
833
|
-
};
|
|
834
|
-
if (match.paramsError) {
|
|
835
|
-
handleSerialError(match.paramsError, "PARSE_PARAMS");
|
|
836
|
-
}
|
|
837
|
-
if (match.searchError) {
|
|
838
|
-
handleSerialError(match.searchError, "VALIDATE_SEARCH");
|
|
839
|
-
}
|
|
840
|
-
try {
|
|
841
|
-
const parentContext = (parentMatch == null ? void 0 : parentMatch.context) ?? this.options.context ?? {};
|
|
842
|
-
matches[index] = match = {
|
|
843
|
-
...match,
|
|
844
|
-
routeContext: replaceEqualDeep(
|
|
845
|
-
match.routeContext,
|
|
846
|
-
parentContext
|
|
847
|
-
),
|
|
848
|
-
context: replaceEqualDeep(match.context, parentContext),
|
|
849
|
-
abortController
|
|
850
|
-
};
|
|
851
|
-
const beforeLoadFnContext = {
|
|
852
|
-
search: match.search,
|
|
853
|
-
abortController,
|
|
854
|
-
params: match.params,
|
|
855
|
-
preload: !!preload,
|
|
856
|
-
context: match.routeContext,
|
|
857
|
-
location,
|
|
858
|
-
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
859
|
-
buildLocation: this.buildLocation,
|
|
860
|
-
cause: preload ? "preload" : match.cause
|
|
829
|
+
abortController: new AbortController(),
|
|
830
|
+
beforeLoadPromise: void 0
|
|
861
831
|
};
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
832
|
+
});
|
|
833
|
+
};
|
|
834
|
+
for (const [index, { id: matchId, routeId }] of matches.entries()) {
|
|
835
|
+
const existingMatch = this.getMatch(matchId);
|
|
836
|
+
if (
|
|
837
|
+
// If we are in the middle of a load, either of these will be present
|
|
838
|
+
// (not to be confused with `loadPromise`, which is always defined)
|
|
839
|
+
existingMatch.beforeLoadPromise || existingMatch.loaderPromise
|
|
840
|
+
) {
|
|
841
|
+
await existingMatch.beforeLoadPromise;
|
|
842
|
+
} else {
|
|
843
|
+
try {
|
|
844
|
+
updateMatch(matchId, (prev) => ({
|
|
845
|
+
...prev,
|
|
846
|
+
loadPromise: createControlledPromise(() => {
|
|
847
|
+
var _a2;
|
|
848
|
+
(_a2 = prev.loadPromise) == null ? void 0 : _a2.resolve();
|
|
849
|
+
}),
|
|
850
|
+
beforeLoadPromise: createControlledPromise()
|
|
851
|
+
}));
|
|
852
|
+
const route = this.looseRoutesById[routeId];
|
|
853
|
+
const abortController = new AbortController();
|
|
854
|
+
const parentMatchId = (_a = matches[index - 1]) == null ? void 0 : _a.id;
|
|
855
|
+
const getParentContext = () => {
|
|
856
|
+
if (!parentMatchId) {
|
|
857
|
+
return this.options.context ?? {};
|
|
858
|
+
}
|
|
859
|
+
return this.getMatch(parentMatchId).context ?? this.options.context ?? {};
|
|
860
|
+
};
|
|
861
|
+
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
862
|
+
const shouldPending = !!(onReady && !this.isServer && !preload && (route.options.loader || route.options.beforeLoad) && typeof pendingMs === "number" && pendingMs !== Infinity && (route.options.pendingComponent ?? this.options.defaultPendingComponent));
|
|
863
|
+
let pendingTimeout;
|
|
864
|
+
if (shouldPending) {
|
|
865
|
+
pendingTimeout = setTimeout(() => {
|
|
866
|
+
try {
|
|
867
|
+
triggerOnReady();
|
|
868
|
+
} catch {
|
|
869
|
+
}
|
|
870
|
+
}, pendingMs);
|
|
871
|
+
}
|
|
872
|
+
const { paramsError, searchError } = this.getMatch(matchId);
|
|
873
|
+
if (paramsError) {
|
|
874
|
+
handleSerialError(index, paramsError, "PARSE_PARAMS");
|
|
875
|
+
}
|
|
876
|
+
if (searchError) {
|
|
877
|
+
handleSerialError(index, searchError, "VALIDATE_SEARCH");
|
|
878
|
+
}
|
|
879
|
+
const parentContext = getParentContext();
|
|
880
|
+
updateMatch(matchId, (prev) => ({
|
|
881
|
+
...prev,
|
|
882
|
+
isFetching: "beforeLoad",
|
|
883
|
+
fetchCount: prev.fetchCount + 1,
|
|
884
|
+
routeContext: replaceEqualDeep(
|
|
885
|
+
prev.routeContext,
|
|
886
|
+
parentContext
|
|
887
|
+
),
|
|
888
|
+
context: replaceEqualDeep(prev.context, parentContext),
|
|
889
|
+
abortController,
|
|
890
|
+
pendingTimeout
|
|
891
|
+
}));
|
|
892
|
+
const { search, params, routeContext, cause } = this.getMatch(matchId);
|
|
893
|
+
const beforeLoadFnContext = {
|
|
894
|
+
search,
|
|
895
|
+
abortController,
|
|
896
|
+
params,
|
|
897
|
+
preload: !!preload,
|
|
898
|
+
context: routeContext,
|
|
899
|
+
location,
|
|
900
|
+
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
901
|
+
buildLocation: this.buildLocation,
|
|
902
|
+
cause: preload ? "preload" : cause
|
|
903
|
+
};
|
|
904
|
+
const beforeLoadContext = await ((_c = (_b = route.options).beforeLoad) == null ? void 0 : _c.call(_b, beforeLoadFnContext)) ?? {};
|
|
905
|
+
if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
|
|
906
|
+
handleSerialError(index, beforeLoadContext, "BEFORE_LOAD");
|
|
907
|
+
}
|
|
908
|
+
updateMatch(matchId, (prev) => {
|
|
909
|
+
const routeContext2 = {
|
|
910
|
+
...prev.routeContext,
|
|
911
|
+
...beforeLoadContext
|
|
912
|
+
};
|
|
913
|
+
return {
|
|
914
|
+
...prev,
|
|
915
|
+
routeContext: replaceEqualDeep(
|
|
916
|
+
prev.routeContext,
|
|
917
|
+
routeContext2
|
|
918
|
+
),
|
|
919
|
+
context: replaceEqualDeep(prev.context, routeContext2),
|
|
920
|
+
abortController
|
|
921
|
+
};
|
|
922
|
+
});
|
|
923
|
+
} catch (err) {
|
|
924
|
+
handleSerialError(index, err, "BEFORE_LOAD");
|
|
866
925
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
),
|
|
877
|
-
context: replaceEqualDeep(match.context, context),
|
|
878
|
-
abortController
|
|
879
|
-
};
|
|
880
|
-
updateMatch(match.id, () => match);
|
|
881
|
-
} catch (err) {
|
|
882
|
-
handleSerialError(err, "BEFORE_LOAD");
|
|
883
|
-
break;
|
|
926
|
+
updateMatch(matchId, (prev) => {
|
|
927
|
+
var _a2;
|
|
928
|
+
(_a2 = prev.beforeLoadPromise) == null ? void 0 : _a2.resolve();
|
|
929
|
+
return {
|
|
930
|
+
...prev,
|
|
931
|
+
beforeLoadPromise: void 0,
|
|
932
|
+
isFetching: false
|
|
933
|
+
};
|
|
934
|
+
});
|
|
884
935
|
}
|
|
885
936
|
}
|
|
886
|
-
checkLatest();
|
|
887
937
|
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
888
938
|
const matchPromises = [];
|
|
889
|
-
validResolvedMatches.forEach((
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
matches[index] = match = updateMatch(
|
|
925
|
-
match.id,
|
|
926
|
-
(prev) => ({
|
|
927
|
-
...prev,
|
|
928
|
-
isFetching: "loader",
|
|
929
|
-
fetchCount: match.fetchCount + 1
|
|
930
|
-
})
|
|
931
|
-
);
|
|
932
|
-
lazyPromise = ((_a = route.lazyFn) == null ? void 0 : _a.call(route).then((lazyRoute) => {
|
|
933
|
-
Object.assign(route.options, lazyRoute.options);
|
|
934
|
-
})) || Promise.resolve();
|
|
935
|
-
componentsPromise = lazyPromise.then(
|
|
936
|
-
() => Promise.all(
|
|
937
|
-
componentTypes.map(async (type) => {
|
|
938
|
-
const component = route.options[type];
|
|
939
|
-
if (component == null ? void 0 : component.preload) {
|
|
940
|
-
await component.preload();
|
|
941
|
-
}
|
|
942
|
-
})
|
|
943
|
-
)
|
|
944
|
-
);
|
|
945
|
-
await lazyPromise;
|
|
946
|
-
checkLatest();
|
|
947
|
-
loaderPromise = (_c = (_b = route.options).loader) == null ? void 0 : _c.call(_b, loaderContext);
|
|
948
|
-
matches[index] = match = updateMatch(
|
|
949
|
-
match.id,
|
|
950
|
-
(prev) => ({
|
|
951
|
-
...prev,
|
|
952
|
-
loaderPromise
|
|
953
|
-
})
|
|
954
|
-
);
|
|
955
|
-
}
|
|
956
|
-
let loaderData = await loaderPromise;
|
|
957
|
-
if (this.serializeLoaderData) {
|
|
958
|
-
loaderData = this.serializeLoaderData(loaderData, {
|
|
959
|
-
router: this,
|
|
960
|
-
match
|
|
961
|
-
});
|
|
962
|
-
}
|
|
963
|
-
checkLatest();
|
|
964
|
-
handleRedirectAndNotFound(match, loaderData);
|
|
965
|
-
await potentialPendingMinPromise();
|
|
966
|
-
checkLatest();
|
|
967
|
-
const meta = (_e = (_d = route.options).meta) == null ? void 0 : _e.call(_d, {
|
|
968
|
-
matches,
|
|
969
|
-
match,
|
|
970
|
-
params: match.params,
|
|
971
|
-
loaderData
|
|
972
|
-
});
|
|
973
|
-
const headers = (_g = (_f = route.options).headers) == null ? void 0 : _g.call(_f, {
|
|
974
|
-
loaderData
|
|
975
|
-
});
|
|
976
|
-
matches[index] = match = updateMatch(match.id, (prev) => ({
|
|
939
|
+
validResolvedMatches.forEach(({ id: matchId, routeId }, index) => {
|
|
940
|
+
matchPromises.push(
|
|
941
|
+
(async () => {
|
|
942
|
+
const { loaderPromise: prevLoaderPromise } = this.getMatch(matchId);
|
|
943
|
+
if (prevLoaderPromise) {
|
|
944
|
+
await prevLoaderPromise;
|
|
945
|
+
} else {
|
|
946
|
+
const parentMatchPromise = matchPromises[index - 1];
|
|
947
|
+
const route = this.looseRoutesById[routeId];
|
|
948
|
+
const getLoaderContext = () => {
|
|
949
|
+
const {
|
|
950
|
+
params,
|
|
951
|
+
loaderDeps,
|
|
952
|
+
abortController,
|
|
953
|
+
context,
|
|
954
|
+
cause
|
|
955
|
+
} = this.getMatch(matchId);
|
|
956
|
+
return {
|
|
957
|
+
params,
|
|
958
|
+
deps: loaderDeps,
|
|
959
|
+
preload: !!preload,
|
|
960
|
+
parentMatchPromise,
|
|
961
|
+
abortController,
|
|
962
|
+
context,
|
|
963
|
+
location,
|
|
964
|
+
navigate: (opts) => this.navigate({ ...opts, _fromLocation: location }),
|
|
965
|
+
cause: preload ? "preload" : cause,
|
|
966
|
+
route
|
|
967
|
+
};
|
|
968
|
+
};
|
|
969
|
+
const age = Date.now() - this.getMatch(matchId).updatedAt;
|
|
970
|
+
const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
971
|
+
const shouldReloadOption = route.options.shouldReload;
|
|
972
|
+
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(getLoaderContext()) : shouldReloadOption;
|
|
973
|
+
updateMatch(matchId, (prev) => ({
|
|
977
974
|
...prev,
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
isFetching: false,
|
|
981
|
-
updatedAt: Date.now(),
|
|
982
|
-
loaderData,
|
|
983
|
-
meta,
|
|
984
|
-
headers
|
|
975
|
+
loaderPromise: createControlledPromise(),
|
|
976
|
+
preload: !!preload && !this.state.matches.find((d) => d.id === matchId)
|
|
985
977
|
}));
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
978
|
+
const runLoader = async () => {
|
|
979
|
+
var _a2, _b2, _c2, _d, _e, _f, _g, _h;
|
|
980
|
+
try {
|
|
981
|
+
const potentialPendingMinPromise = async () => {
|
|
982
|
+
const latestMatch = this.getMatch(matchId);
|
|
983
|
+
if (latestMatch.minPendingPromise) {
|
|
984
|
+
await latestMatch.minPendingPromise;
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
try {
|
|
988
|
+
route._lazyPromise = route._lazyPromise || (route.lazyFn ? route.lazyFn().then((lazyRoute) => {
|
|
989
|
+
Object.assign(
|
|
990
|
+
route.options,
|
|
991
|
+
lazyRoute.options
|
|
992
|
+
);
|
|
993
|
+
}) : Promise.resolve());
|
|
994
|
+
const componentsPromise = this.getMatch(matchId).componentsPromise || route._lazyPromise.then(
|
|
995
|
+
() => Promise.all(
|
|
996
|
+
componentTypes.map(async (type) => {
|
|
997
|
+
const component = route.options[type];
|
|
998
|
+
if (component == null ? void 0 : component.preload) {
|
|
999
|
+
await component.preload();
|
|
1000
|
+
}
|
|
1001
|
+
})
|
|
1002
|
+
)
|
|
1003
|
+
);
|
|
1004
|
+
updateMatch(matchId, (prev) => ({
|
|
1005
|
+
...prev,
|
|
1006
|
+
isFetching: "loader",
|
|
1007
|
+
componentsPromise
|
|
1008
|
+
}));
|
|
1009
|
+
await route._lazyPromise;
|
|
1010
|
+
let loaderData = await ((_b2 = (_a2 = route.options).loader) == null ? void 0 : _b2.call(_a2, getLoaderContext()));
|
|
1011
|
+
if (this.serializeLoaderData) {
|
|
1012
|
+
loaderData = this.serializeLoaderData(loaderData, {
|
|
1013
|
+
router: this,
|
|
1014
|
+
match: this.getMatch(matchId)
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
handleRedirectAndNotFound(
|
|
1018
|
+
this.getMatch(matchId),
|
|
1019
|
+
loaderData
|
|
1020
|
+
);
|
|
1021
|
+
await potentialPendingMinPromise();
|
|
1022
|
+
const meta = (_d = (_c2 = route.options).meta) == null ? void 0 : _d.call(_c2, {
|
|
1023
|
+
matches,
|
|
1024
|
+
match: this.getMatch(matchId),
|
|
1025
|
+
params: this.getMatch(matchId).params,
|
|
1026
|
+
loaderData
|
|
1027
|
+
});
|
|
1028
|
+
const headers = (_f = (_e = route.options).headers) == null ? void 0 : _f.call(_e, {
|
|
1029
|
+
loaderData
|
|
1030
|
+
});
|
|
1031
|
+
updateMatch(matchId, (prev) => ({
|
|
1032
|
+
...prev,
|
|
1033
|
+
error: void 0,
|
|
1034
|
+
status: "success",
|
|
1035
|
+
isFetching: false,
|
|
1036
|
+
updatedAt: Date.now(),
|
|
1037
|
+
loaderData,
|
|
1038
|
+
meta,
|
|
1039
|
+
headers
|
|
1040
|
+
}));
|
|
1041
|
+
} catch (e) {
|
|
1042
|
+
let error = e;
|
|
1043
|
+
await potentialPendingMinPromise();
|
|
1044
|
+
handleRedirectAndNotFound(this.getMatch(matchId), e);
|
|
1045
|
+
try {
|
|
1046
|
+
(_h = (_g = route.options).onError) == null ? void 0 : _h.call(_g, e);
|
|
1047
|
+
} catch (onErrorError) {
|
|
1048
|
+
error = onErrorError;
|
|
1049
|
+
handleRedirectAndNotFound(
|
|
1050
|
+
this.getMatch(matchId),
|
|
1051
|
+
onErrorError
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
updateMatch(matchId, (prev) => ({
|
|
1055
|
+
...prev,
|
|
1056
|
+
error,
|
|
1057
|
+
status: "error",
|
|
1058
|
+
isFetching: false
|
|
1059
|
+
}));
|
|
1060
|
+
}
|
|
1061
|
+
await this.getMatch(matchId).componentsPromise;
|
|
1062
|
+
} catch (err) {
|
|
1063
|
+
handleRedirectAndNotFound(this.getMatch(matchId), err);
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
const { status, invalid } = this.getMatch(matchId);
|
|
1067
|
+
if (status === "success" && (invalid || (shouldReload ?? age > staleAge))) {
|
|
1068
|
+
;
|
|
1069
|
+
(async () => {
|
|
1070
|
+
try {
|
|
1071
|
+
await runLoader();
|
|
1072
|
+
} catch (err) {
|
|
1073
|
+
}
|
|
1074
|
+
})();
|
|
1075
|
+
} else if (status !== "success") {
|
|
1076
|
+
await runLoader();
|
|
997
1077
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
status: "error",
|
|
1002
|
-
isFetching: false
|
|
1003
|
-
}));
|
|
1004
|
-
}
|
|
1005
|
-
await componentsPromise;
|
|
1006
|
-
checkLatest();
|
|
1007
|
-
match.loadPromise.resolve();
|
|
1008
|
-
};
|
|
1009
|
-
const age = Date.now() - match.updatedAt;
|
|
1010
|
-
const staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
1011
|
-
const shouldReloadOption = route.options.shouldReload;
|
|
1012
|
-
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(loaderContext) : shouldReloadOption;
|
|
1013
|
-
matches[index] = match = {
|
|
1014
|
-
...match,
|
|
1015
|
-
preload: !!preload && !this.state.matches.find((d) => d.id === match.id)
|
|
1016
|
-
};
|
|
1017
|
-
const fetchWithRedirectAndNotFound = async () => {
|
|
1018
|
-
try {
|
|
1019
|
-
await fetchAndResolveInLoaderLifetime();
|
|
1020
|
-
} catch (err) {
|
|
1021
|
-
checkLatest();
|
|
1022
|
-
handleRedirectAndNotFound(match, err);
|
|
1078
|
+
const { loaderPromise, loadPromise } = this.getMatch(matchId);
|
|
1079
|
+
loaderPromise == null ? void 0 : loaderPromise.resolve();
|
|
1080
|
+
loadPromise == null ? void 0 : loadPromise.resolve();
|
|
1023
1081
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
}
|
|
1032
|
-
})();
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
if (match.status !== "success") {
|
|
1036
|
-
await fetchWithRedirectAndNotFound();
|
|
1037
|
-
}
|
|
1038
|
-
return;
|
|
1039
|
-
};
|
|
1040
|
-
matchPromises.push(createValidateResolvedMatchPromise());
|
|
1082
|
+
updateMatch(matchId, (prev) => ({
|
|
1083
|
+
...prev,
|
|
1084
|
+
isFetching: false,
|
|
1085
|
+
loaderPromise: void 0
|
|
1086
|
+
}));
|
|
1087
|
+
})()
|
|
1088
|
+
);
|
|
1041
1089
|
});
|
|
1042
1090
|
await Promise.all(matchPromises);
|
|
1043
|
-
checkLatest();
|
|
1044
1091
|
resolveAll();
|
|
1045
1092
|
} catch (err) {
|
|
1046
1093
|
rejectAll(err);
|
|
@@ -1062,7 +1109,7 @@ class Router {
|
|
|
1062
1109
|
const invalidate = (d) => ({
|
|
1063
1110
|
...d,
|
|
1064
1111
|
invalid: true,
|
|
1065
|
-
...d.status === "error" ? { status: "pending" } : {}
|
|
1112
|
+
...d.status === "error" ? { status: "pending", error: void 0 } : {}
|
|
1066
1113
|
});
|
|
1067
1114
|
this.__store.setState((s) => {
|
|
1068
1115
|
var _a;
|
|
@@ -1120,18 +1167,23 @@ class Router {
|
|
|
1120
1167
|
}
|
|
1121
1168
|
});
|
|
1122
1169
|
});
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
}
|
|
1170
|
+
const activeMatchIds = new Set(
|
|
1171
|
+
[...this.state.matches, ...this.state.pendingMatches ?? []].map(
|
|
1172
|
+
(d) => d.id
|
|
1173
|
+
)
|
|
1174
|
+
);
|
|
1129
1175
|
try {
|
|
1130
1176
|
matches = await this.loadMatches({
|
|
1131
1177
|
matches,
|
|
1132
1178
|
location: next,
|
|
1133
1179
|
preload: true,
|
|
1134
|
-
|
|
1180
|
+
updateMatch: (id, updater) => {
|
|
1181
|
+
if (activeMatchIds.has(id)) {
|
|
1182
|
+
matches = matches.map((d) => d.id === id ? updater(d) : d);
|
|
1183
|
+
} else {
|
|
1184
|
+
this.updateMatch(id, updater);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1135
1187
|
});
|
|
1136
1188
|
return matches;
|
|
1137
1189
|
} catch (err) {
|
|
@@ -1199,7 +1251,7 @@ class Router {
|
|
|
1199
1251
|
manifest: this.manifest
|
|
1200
1252
|
};
|
|
1201
1253
|
};
|
|
1202
|
-
this.hydrate =
|
|
1254
|
+
this.hydrate = () => {
|
|
1203
1255
|
var _a, _b, _c;
|
|
1204
1256
|
let ctx;
|
|
1205
1257
|
if (typeof document !== "undefined") {
|
|
@@ -1272,7 +1324,9 @@ class Router {
|
|
|
1272
1324
|
${children}\`)` : ""}; __TSR__.cleanScripts()<\/script>`
|
|
1273
1325
|
);
|
|
1274
1326
|
};
|
|
1275
|
-
this.
|
|
1327
|
+
this._handleNotFound = (matches, err, {
|
|
1328
|
+
updateMatch = this.updateMatch
|
|
1329
|
+
} = {}) => {
|
|
1276
1330
|
const matchesByRouteId = Object.fromEntries(
|
|
1277
1331
|
matches.map((match2) => [match2.routeId, match2])
|
|
1278
1332
|
);
|
|
@@ -1286,11 +1340,18 @@ class Router {
|
|
|
1286
1340
|
}
|
|
1287
1341
|
const match = matchesByRouteId[routeCursor.id];
|
|
1288
1342
|
invariant(match, "Could not find match for route: " + routeCursor.id);
|
|
1289
|
-
|
|
1343
|
+
updateMatch(match.id, (prev) => ({
|
|
1344
|
+
...prev,
|
|
1290
1345
|
status: "notFound",
|
|
1291
1346
|
error: err,
|
|
1292
1347
|
isFetching: false
|
|
1293
|
-
});
|
|
1348
|
+
}));
|
|
1349
|
+
if (err.routerCode === "BEFORE_LOAD" && routeCursor.parentRoute) {
|
|
1350
|
+
err.routeId = routeCursor.parentRoute.id;
|
|
1351
|
+
this._handleNotFound(matches, err, {
|
|
1352
|
+
updateMatch
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1294
1355
|
};
|
|
1295
1356
|
this.hasNotFoundMatch = () => {
|
|
1296
1357
|
return this.__store.state.matches.some(
|
|
@@ -1316,11 +1377,6 @@ class Router {
|
|
|
1316
1377
|
get looseRoutesById() {
|
|
1317
1378
|
return this.routesById;
|
|
1318
1379
|
}
|
|
1319
|
-
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
1320
|
-
// state.matches
|
|
1321
|
-
// .find((d) => d.id === matchId)
|
|
1322
|
-
// ?.__promisesByKey[key]?.resolve(value)
|
|
1323
|
-
// }
|
|
1324
1380
|
}
|
|
1325
1381
|
function lazyFn(fn, key) {
|
|
1326
1382
|
return async (...args) => {
|
|
@@ -1334,6 +1390,7 @@ class PathParamError extends Error {
|
|
|
1334
1390
|
}
|
|
1335
1391
|
function getInitialRouterState(location) {
|
|
1336
1392
|
return {
|
|
1393
|
+
loadedAt: 0,
|
|
1337
1394
|
isLoading: false,
|
|
1338
1395
|
isTransitioning: false,
|
|
1339
1396
|
status: "idle",
|