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