@tanstack/react-router 1.28.1 → 1.28.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/Matches.cjs +45 -23
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +5 -6
- package/dist/cjs/RouterProvider.cjs +2 -2
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/fileRoute.d.cts +4 -4
- 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/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +2 -0
- package/dist/cjs/redirects.cjs.map +1 -1
- package/dist/cjs/redirects.d.cts +3 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +2 -2
- package/dist/cjs/router.cjs +374 -327
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +2 -2
- package/dist/cjs/utils.cjs +20 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +6 -1
- package/dist/esm/Matches.d.ts +5 -6
- package/dist/esm/Matches.js +46 -24
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.js +2 -2
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/fileRoute.d.ts +4 -4
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/link.d.ts +2 -0
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/redirects.d.ts +3 -1
- package/dist/esm/redirects.js.map +1 -1
- package/dist/esm/route.d.ts +2 -2
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +2 -2
- package/dist/esm/router.js +375 -328
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/utils.d.ts +6 -1
- package/dist/esm/utils.js +20 -2
- package/dist/esm/utils.js.map +1 -1
- package/package.json +4 -2
- package/src/Matches.tsx +73 -35
- package/src/RouterProvider.tsx +2 -0
- package/src/index.tsx +0 -1
- package/src/link.tsx +2 -0
- package/src/redirects.ts +4 -2
- package/src/route.ts +2 -7
- package/src/router.ts +498 -426
- package/src/utils.ts +31 -2
package/dist/cjs/router.cjs
CHANGED
|
@@ -33,6 +33,7 @@ class Router {
|
|
|
33
33
|
this.latestLoadPromise = Promise.resolve();
|
|
34
34
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
35
35
|
this.injectedHtml = [];
|
|
36
|
+
this.isServer = typeof document === "undefined";
|
|
36
37
|
this.startReactTransition = (fn) => fn();
|
|
37
38
|
this.update = (newOptions) => {
|
|
38
39
|
if (newOptions.notFoundRoute) {
|
|
@@ -288,7 +289,7 @@ class Router {
|
|
|
288
289
|
});
|
|
289
290
|
const matches = [];
|
|
290
291
|
matchedRoutes.forEach((route2, index) => {
|
|
291
|
-
var _a, _b, _c, _d, _e, _f;
|
|
292
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
292
293
|
const parentMatch = matches[index - 1];
|
|
293
294
|
const [preMatchSearch, searchError] = (() => {
|
|
294
295
|
const parentSearch = (parentMatch == null ? void 0 : parentMatch.search) ?? locationSearch;
|
|
@@ -327,36 +328,55 @@ class Router {
|
|
|
327
328
|
}) + loaderDepsHash;
|
|
328
329
|
const existingMatch = RouterProvider.getRouteMatch(this.state, matchId);
|
|
329
330
|
const cause = this.state.matches.find((d) => d.id === matchId) ? "stay" : "enter";
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
331
|
+
let match;
|
|
332
|
+
if (existingMatch) {
|
|
333
|
+
match = {
|
|
334
|
+
...existingMatch,
|
|
335
|
+
cause,
|
|
336
|
+
params: routeParams
|
|
337
|
+
};
|
|
338
|
+
} else {
|
|
339
|
+
const status = route2.options.loader || route2.options.beforeLoad ? "pending" : "success";
|
|
340
|
+
const loadPromise = utils.createControlledPromise();
|
|
341
|
+
if (status === "success") {
|
|
342
|
+
loadPromise.resolve();
|
|
343
|
+
}
|
|
344
|
+
match = {
|
|
345
|
+
id: matchId,
|
|
346
|
+
routeId: route2.id,
|
|
347
|
+
params: routeParams,
|
|
348
|
+
pathname: path.joinPaths([this.basepath, interpolatedPath]),
|
|
349
|
+
updatedAt: Date.now(),
|
|
350
|
+
search: {},
|
|
351
|
+
searchError: void 0,
|
|
352
|
+
status: "pending",
|
|
353
|
+
isFetching: false,
|
|
354
|
+
error: void 0,
|
|
355
|
+
paramsError: parseErrors[index],
|
|
356
|
+
loaderPromise: Promise.resolve(),
|
|
357
|
+
loadPromise,
|
|
358
|
+
routeContext: void 0,
|
|
359
|
+
context: void 0,
|
|
360
|
+
abortController: new AbortController(),
|
|
361
|
+
fetchCount: 0,
|
|
362
|
+
cause,
|
|
363
|
+
loaderDeps,
|
|
364
|
+
invalid: false,
|
|
365
|
+
preload: false,
|
|
366
|
+
links: (_d = (_c = route2.options).links) == null ? void 0 : _d.call(_c),
|
|
367
|
+
scripts: (_f = (_e = route2.options).scripts) == null ? void 0 : _f.call(_e),
|
|
368
|
+
staticData: route2.options.staticData || {}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
if (match.status === "success") {
|
|
372
|
+
match.meta = (_h = (_g = route2.options).meta) == null ? void 0 : _h.call(_g, {
|
|
373
|
+
params: match.params,
|
|
374
|
+
loaderData: match.loaderData
|
|
375
|
+
});
|
|
376
|
+
match.headers = (_j = (_i = route2.options).headers) == null ? void 0 : _j.call(_i, {
|
|
377
|
+
loaderData: match.loaderData
|
|
378
|
+
});
|
|
379
|
+
}
|
|
360
380
|
if (!(opts == null ? void 0 : opts.preload)) {
|
|
361
381
|
match.globalNotFound = globalNotFoundRouteId === route2.id;
|
|
362
382
|
}
|
|
@@ -378,25 +398,20 @@ class Router {
|
|
|
378
398
|
};
|
|
379
399
|
this.buildLocation = (opts) => {
|
|
380
400
|
const build = (dest = {}, matches) => {
|
|
381
|
-
var _a, _b, _c;
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
);
|
|
387
|
-
const fromMatches = this.matchRoutes(
|
|
388
|
-
this.latestLocation.pathname,
|
|
389
|
-
fromSearch
|
|
390
|
-
);
|
|
401
|
+
var _a, _b, _c, _d;
|
|
402
|
+
const fromPath = dest.from || this.latestLocation.pathname;
|
|
403
|
+
let fromSearch = ((_a = dest._fromLocation) == null ? void 0 : _a.search) || this.latestLocation.search;
|
|
404
|
+
const fromMatches = this.matchRoutes(fromPath, fromSearch);
|
|
405
|
+
fromSearch = ((_b = utils.last(fromMatches)) == null ? void 0 : _b.search) || this.latestLocation.search;
|
|
391
406
|
const stayingMatches = matches == null ? void 0 : matches.filter(
|
|
392
407
|
(d) => fromMatches.find((e) => e.routeId === d.routeId)
|
|
393
408
|
);
|
|
394
|
-
const fromRoute = this.looseRoutesById[(
|
|
409
|
+
const fromRoute = this.looseRoutesById[(_c = utils.last(fromMatches)) == null ? void 0 : _c.routeId];
|
|
395
410
|
let pathname = dest.to ? this.resolvePathWithBase(
|
|
396
411
|
dest.from ?? this.latestLocation.pathname,
|
|
397
412
|
`${dest.to}`
|
|
398
413
|
) : this.resolvePathWithBase(fromRoute == null ? void 0 : fromRoute.fullPath, fromRoute == null ? void 0 : fromRoute.fullPath);
|
|
399
|
-
const prevParams = { ...(
|
|
414
|
+
const prevParams = { ...(_d = utils.last(fromMatches)) == null ? void 0 : _d.params };
|
|
400
415
|
let nextParams = (dest.params ?? true) === true ? prevParams : { ...prevParams, ...utils.functionalUpdate(dest.params, prevParams) };
|
|
401
416
|
if (Object.keys(nextParams).length > 0) {
|
|
402
417
|
matches == null ? void 0 : matches.map((d) => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach((fn) => {
|
|
@@ -563,275 +578,302 @@ class Router {
|
|
|
563
578
|
matches,
|
|
564
579
|
preload
|
|
565
580
|
}) => {
|
|
566
|
-
var _a, _b;
|
|
567
581
|
let latestPromise;
|
|
568
582
|
let firstBadMatchIndex;
|
|
569
|
-
const updateMatch = (
|
|
570
|
-
var
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
);
|
|
574
|
-
const isMatched = this.state.matches.find((d) => d.id === match.id);
|
|
583
|
+
const updateMatch = (id, updater, opts) => {
|
|
584
|
+
var _a;
|
|
585
|
+
let updated;
|
|
586
|
+
const isPending = (_a = this.state.pendingMatches) == null ? void 0 : _a.find((d) => d.id === id);
|
|
587
|
+
const isMatched = this.state.matches.find((d) => d.id === id);
|
|
575
588
|
const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : "cachedMatches";
|
|
576
589
|
this.__store.setState((s) => {
|
|
577
|
-
var
|
|
590
|
+
var _a2, _b;
|
|
578
591
|
return {
|
|
579
592
|
...s,
|
|
580
|
-
[matchesKey]: (opts == null ? void 0 : opts.remove) ? (
|
|
593
|
+
[matchesKey]: (opts == null ? void 0 : opts.remove) ? (_a2 = s[matchesKey]) == null ? void 0 : _a2.filter((d) => d.id !== id) : (_b = s[matchesKey]) == null ? void 0 : _b.map(
|
|
594
|
+
(d) => d.id === id ? updated = updater(d) : d
|
|
595
|
+
)
|
|
581
596
|
};
|
|
582
597
|
});
|
|
598
|
+
return updated;
|
|
583
599
|
};
|
|
584
600
|
const handleMatchSpecialError = (match, err) => {
|
|
585
|
-
match
|
|
586
|
-
...
|
|
601
|
+
updateMatch(match.id, (prev) => ({
|
|
602
|
+
...prev,
|
|
587
603
|
status: redirects.isRedirect(err) ? "redirected" : notFound.isNotFound(err) ? "notFound" : "error",
|
|
588
604
|
isFetching: false,
|
|
589
605
|
error: err
|
|
590
|
-
};
|
|
591
|
-
updateMatch(match);
|
|
606
|
+
}));
|
|
592
607
|
if (!err.routeId) {
|
|
593
608
|
err.routeId = match.routeId;
|
|
594
609
|
}
|
|
595
610
|
throw err;
|
|
596
611
|
};
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
};
|
|
623
|
-
};
|
|
624
|
-
if (match.paramsError) {
|
|
625
|
-
handleSerialError(match.paramsError, "PARSE_PARAMS");
|
|
626
|
-
}
|
|
627
|
-
if (match.searchError) {
|
|
628
|
-
handleSerialError(match.searchError, "VALIDATE_SEARCH");
|
|
629
|
-
}
|
|
630
|
-
try {
|
|
631
|
-
const parentContext = (parentMatch == null ? void 0 : parentMatch.context) ?? this.options.context ?? {};
|
|
632
|
-
const pendingMs = route2.options.pendingMs ?? this.options.defaultPendingMs;
|
|
633
|
-
const pendingPromise = typeof pendingMs === "number" && pendingMs <= 0 ? Promise.resolve() : new Promise((r) => setTimeout(r, pendingMs));
|
|
634
|
-
const beforeLoadContext = await ((_b = (_a = route2.options).beforeLoad) == null ? void 0 : _b.call(_a, {
|
|
635
|
-
search: match.search,
|
|
636
|
-
abortController,
|
|
637
|
-
params: match.params,
|
|
638
|
-
preload: !!preload,
|
|
639
|
-
context: parentContext,
|
|
640
|
-
location,
|
|
641
|
-
navigate: (opts) => this.navigate({ ...opts, from: match.pathname }),
|
|
642
|
-
buildLocation: this.buildLocation,
|
|
643
|
-
cause: preload ? "preload" : match.cause
|
|
644
|
-
})) ?? {};
|
|
645
|
-
if (redirects.isRedirect(beforeLoadContext) || notFound.isNotFound(beforeLoadContext)) {
|
|
646
|
-
handleSerialError(beforeLoadContext, "BEFORE_LOAD");
|
|
647
|
-
}
|
|
648
|
-
const context = {
|
|
649
|
-
...parentContext,
|
|
650
|
-
...beforeLoadContext
|
|
651
|
-
};
|
|
652
|
-
matches[index] = match = {
|
|
653
|
-
...match,
|
|
654
|
-
routeContext: utils.replaceEqualDeep(match.routeContext, beforeLoadContext),
|
|
655
|
-
context: utils.replaceEqualDeep(match.context, context),
|
|
656
|
-
abortController,
|
|
657
|
-
pendingPromise
|
|
658
|
-
};
|
|
659
|
-
} catch (err) {
|
|
660
|
-
handleSerialError(err, "BEFORE_LOAD");
|
|
661
|
-
break;
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
665
|
-
const matchPromises = [];
|
|
666
|
-
validResolvedMatches.forEach((match, index) => {
|
|
667
|
-
matchPromises.push(
|
|
668
|
-
// eslint-disable-next-line no-async-promise-executor
|
|
669
|
-
new Promise(async (resolve, reject) => {
|
|
670
|
-
var _a2;
|
|
671
|
-
const parentMatchPromise = matchPromises[index - 1];
|
|
672
|
-
const route2 = this.looseRoutesById[match.routeId];
|
|
673
|
-
const handleError = (err) => {
|
|
674
|
-
if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
|
|
675
|
-
handleMatchSpecialError(match, err);
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
|
-
let loadPromise;
|
|
679
|
-
matches[index] = match = {
|
|
680
|
-
...match,
|
|
681
|
-
showPending: false
|
|
682
|
-
};
|
|
683
|
-
let didShowPending = false;
|
|
684
|
-
const pendingMs = route2.options.pendingMs ?? this.options.defaultPendingMs;
|
|
685
|
-
const pendingMinMs = route2.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
686
|
-
const loaderContext = {
|
|
687
|
-
params: match.params,
|
|
688
|
-
deps: match.loaderDeps,
|
|
689
|
-
preload: !!preload,
|
|
690
|
-
parentMatchPromise,
|
|
691
|
-
abortController: match.abortController,
|
|
692
|
-
context: match.context,
|
|
693
|
-
location,
|
|
694
|
-
navigate: (opts) => this.navigate({ ...opts, from: match.pathname }),
|
|
695
|
-
cause: preload ? "preload" : match.cause,
|
|
696
|
-
route: route2
|
|
697
|
-
};
|
|
698
|
-
const fetch = async () => {
|
|
699
|
-
var _a3, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
700
|
-
try {
|
|
701
|
-
if (match.isFetching) {
|
|
702
|
-
loadPromise = (_a3 = RouterProvider.getRouteMatch(this.state, match.id)) == null ? void 0 : _a3.loadPromise;
|
|
703
|
-
} else {
|
|
612
|
+
try {
|
|
613
|
+
await new Promise((resolveAll, rejectAll) => {
|
|
614
|
+
;
|
|
615
|
+
(async () => {
|
|
616
|
+
var _a, _b;
|
|
617
|
+
try {
|
|
618
|
+
for (let [index, match] of matches.entries()) {
|
|
619
|
+
const parentMatch = matches[index - 1];
|
|
620
|
+
const route2 = this.looseRoutesById[match.routeId];
|
|
621
|
+
const abortController = new AbortController();
|
|
622
|
+
const handleSerialError = (err, code) => {
|
|
623
|
+
var _a2, _b2;
|
|
624
|
+
err.routerCode = code;
|
|
625
|
+
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
626
|
+
if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
|
|
627
|
+
handleMatchSpecialError(match, err);
|
|
628
|
+
}
|
|
629
|
+
try {
|
|
630
|
+
(_b2 = (_a2 = route2.options).onError) == null ? void 0 : _b2.call(_a2, err);
|
|
631
|
+
} catch (errorHandlerErr) {
|
|
632
|
+
err = errorHandlerErr;
|
|
633
|
+
if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
|
|
634
|
+
handleMatchSpecialError(match, errorHandlerErr);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
704
637
|
matches[index] = match = {
|
|
705
638
|
...match,
|
|
706
|
-
|
|
707
|
-
|
|
639
|
+
error: err,
|
|
640
|
+
status: "error",
|
|
641
|
+
updatedAt: Date.now(),
|
|
642
|
+
abortController: new AbortController()
|
|
708
643
|
};
|
|
709
|
-
const lazyPromise = ((_b2 = route2.lazyFn) == null ? void 0 : _b2.call(route2).then((lazyRoute) => {
|
|
710
|
-
Object.assign(route2.options, lazyRoute.options);
|
|
711
|
-
})) || Promise.resolve();
|
|
712
|
-
const componentsPromise = lazyPromise.then(
|
|
713
|
-
() => Promise.all(
|
|
714
|
-
componentTypes.map(async (type) => {
|
|
715
|
-
const component = route2.options[type];
|
|
716
|
-
if (component == null ? void 0 : component.preload) {
|
|
717
|
-
await component.preload();
|
|
718
|
-
}
|
|
719
|
-
})
|
|
720
|
-
)
|
|
721
|
-
);
|
|
722
|
-
const loaderPromise = (_d = (_c = route2.options).loader) == null ? void 0 : _d.call(_c, loaderContext);
|
|
723
|
-
loadPromise = Promise.all([
|
|
724
|
-
componentsPromise,
|
|
725
|
-
loaderPromise,
|
|
726
|
-
lazyPromise
|
|
727
|
-
]).then((d) => d[1]);
|
|
728
|
-
}
|
|
729
|
-
matches[index] = match = {
|
|
730
|
-
...match,
|
|
731
|
-
loadPromise
|
|
732
644
|
};
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (latestPromise = checkLatest())
|
|
736
|
-
return await latestPromise;
|
|
737
|
-
handleError(loaderData);
|
|
738
|
-
if (didShowPending && pendingMinMs) {
|
|
739
|
-
await new Promise((r) => setTimeout(r, pendingMinMs));
|
|
645
|
+
if (match.paramsError) {
|
|
646
|
+
handleSerialError(match.paramsError, "PARSE_PARAMS");
|
|
740
647
|
}
|
|
741
|
-
if (
|
|
742
|
-
|
|
743
|
-
const [meta, headers] = await Promise.all([
|
|
744
|
-
(_f = (_e = route2.options).meta) == null ? void 0 : _f.call(_e, {
|
|
745
|
-
params: match.params,
|
|
746
|
-
loaderData
|
|
747
|
-
}),
|
|
748
|
-
(_h = (_g = route2.options).headers) == null ? void 0 : _h.call(_g, {
|
|
749
|
-
loaderData
|
|
750
|
-
})
|
|
751
|
-
]);
|
|
752
|
-
matches[index] = match = {
|
|
753
|
-
...match,
|
|
754
|
-
error: void 0,
|
|
755
|
-
status: "success",
|
|
756
|
-
isFetching: false,
|
|
757
|
-
updatedAt: Date.now(),
|
|
758
|
-
loaderData,
|
|
759
|
-
loadPromise: void 0,
|
|
760
|
-
meta,
|
|
761
|
-
headers
|
|
762
|
-
};
|
|
763
|
-
} catch (e) {
|
|
764
|
-
let error = e;
|
|
765
|
-
if (latestPromise = checkLatest())
|
|
766
|
-
return await latestPromise;
|
|
767
|
-
handleError(e);
|
|
768
|
-
try {
|
|
769
|
-
(_j = (_i = route2.options).onError) == null ? void 0 : _j.call(_i, e);
|
|
770
|
-
} catch (onErrorError) {
|
|
771
|
-
error = onErrorError;
|
|
772
|
-
handleError(onErrorError);
|
|
648
|
+
if (match.searchError) {
|
|
649
|
+
handleSerialError(match.searchError, "VALIDATE_SEARCH");
|
|
773
650
|
}
|
|
774
|
-
matches[index] = match = {
|
|
775
|
-
...match,
|
|
776
|
-
error,
|
|
777
|
-
status: "error",
|
|
778
|
-
isFetching: false
|
|
779
|
-
};
|
|
780
|
-
}
|
|
781
|
-
updateMatch(match);
|
|
782
|
-
};
|
|
783
|
-
const age = Date.now() - match.updatedAt;
|
|
784
|
-
const staleAge = preload ? route2.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route2.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
785
|
-
const shouldReloadOption = route2.options.shouldReload;
|
|
786
|
-
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(loaderContext) : shouldReloadOption;
|
|
787
|
-
matches[index] = match = {
|
|
788
|
-
...match,
|
|
789
|
-
preload: !!preload && !this.state.matches.find((d) => d.id === match.id)
|
|
790
|
-
};
|
|
791
|
-
if (match.status === "success" && (match.invalid || (shouldReload ?? age > staleAge))) {
|
|
792
|
-
(async () => {
|
|
793
651
|
try {
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
handleError(err);
|
|
800
|
-
invariant(
|
|
801
|
-
false,
|
|
802
|
-
"You need to redirect from a background fetch? This is not supported yet. File an issue."
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
})();
|
|
807
|
-
return resolve();
|
|
808
|
-
}
|
|
809
|
-
const shouldPending = !preload && route2.options.loader && typeof pendingMs === "number" && (route2.options.pendingComponent ?? this.options.defaultPendingComponent);
|
|
810
|
-
if (match.status !== "success") {
|
|
811
|
-
try {
|
|
812
|
-
if (shouldPending) {
|
|
813
|
-
(_a2 = match.pendingPromise) == null ? void 0 : _a2.then(async () => {
|
|
814
|
-
if (latestPromise = checkLatest())
|
|
815
|
-
return latestPromise;
|
|
816
|
-
didShowPending = true;
|
|
817
|
-
matches[index] = match = {
|
|
818
|
-
...match,
|
|
819
|
-
showPending: true
|
|
820
|
-
};
|
|
821
|
-
updateMatch(match);
|
|
822
|
-
resolve();
|
|
652
|
+
const parentContext = (parentMatch == null ? void 0 : parentMatch.context) ?? this.options.context ?? {};
|
|
653
|
+
const pendingMs = route2.options.pendingMs ?? this.options.defaultPendingMs;
|
|
654
|
+
const pendingPromise = typeof pendingMs !== "number" || pendingMs <= 0 ? Promise.resolve() : new Promise((r) => {
|
|
655
|
+
if (pendingMs !== Infinity)
|
|
656
|
+
setTimeout(r, pendingMs);
|
|
823
657
|
});
|
|
658
|
+
const shouldPending = !this.isServer && !preload && (route2.options.loader || route2.options.beforeLoad) && typeof pendingMs === "number" && (route2.options.pendingComponent ?? this.options.defaultPendingComponent);
|
|
659
|
+
if (shouldPending) {
|
|
660
|
+
pendingPromise.then(async () => {
|
|
661
|
+
if (latestPromise = checkLatest())
|
|
662
|
+
return latestPromise;
|
|
663
|
+
resolveAll();
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
const beforeLoadContext = await ((_b = (_a = route2.options).beforeLoad) == null ? void 0 : _b.call(_a, {
|
|
667
|
+
search: match.search,
|
|
668
|
+
abortController,
|
|
669
|
+
params: match.params,
|
|
670
|
+
preload: !!preload,
|
|
671
|
+
context: parentContext,
|
|
672
|
+
location,
|
|
673
|
+
navigate: (opts) => this.navigate({ ...opts, from: match.pathname }),
|
|
674
|
+
buildLocation: this.buildLocation,
|
|
675
|
+
cause: preload ? "preload" : match.cause
|
|
676
|
+
})) ?? {};
|
|
677
|
+
if (redirects.isRedirect(beforeLoadContext) || notFound.isNotFound(beforeLoadContext)) {
|
|
678
|
+
handleSerialError(beforeLoadContext, "BEFORE_LOAD");
|
|
679
|
+
}
|
|
680
|
+
const context = {
|
|
681
|
+
...parentContext,
|
|
682
|
+
...beforeLoadContext
|
|
683
|
+
};
|
|
684
|
+
matches[index] = match = {
|
|
685
|
+
...match,
|
|
686
|
+
routeContext: utils.replaceEqualDeep(
|
|
687
|
+
match.routeContext,
|
|
688
|
+
beforeLoadContext
|
|
689
|
+
),
|
|
690
|
+
context: utils.replaceEqualDeep(match.context, context),
|
|
691
|
+
abortController
|
|
692
|
+
};
|
|
693
|
+
} catch (err) {
|
|
694
|
+
handleSerialError(err, "BEFORE_LOAD");
|
|
695
|
+
break;
|
|
824
696
|
}
|
|
825
|
-
await fetch();
|
|
826
|
-
} catch (err) {
|
|
827
|
-
reject(err);
|
|
828
697
|
}
|
|
698
|
+
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
699
|
+
const matchPromises = [];
|
|
700
|
+
await Promise.all(
|
|
701
|
+
validResolvedMatches.map(async (match, index) => {
|
|
702
|
+
const parentMatchPromise = matchPromises[index - 1];
|
|
703
|
+
const route2 = this.looseRoutesById[match.routeId];
|
|
704
|
+
const handleError = (err) => {
|
|
705
|
+
if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
|
|
706
|
+
handleMatchSpecialError(match, err);
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
const loaderContext = {
|
|
710
|
+
params: match.params,
|
|
711
|
+
deps: match.loaderDeps,
|
|
712
|
+
preload: !!preload,
|
|
713
|
+
parentMatchPromise,
|
|
714
|
+
abortController: match.abortController,
|
|
715
|
+
context: match.context,
|
|
716
|
+
location,
|
|
717
|
+
navigate: (opts) => this.navigate({ ...opts, from: match.pathname }),
|
|
718
|
+
cause: preload ? "preload" : match.cause,
|
|
719
|
+
route: route2
|
|
720
|
+
};
|
|
721
|
+
const fetch = async () => {
|
|
722
|
+
var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
|
|
723
|
+
const existing = RouterProvider.getRouteMatch(this.state, match.id);
|
|
724
|
+
let lazyPromise = Promise.resolve();
|
|
725
|
+
let componentsPromise = Promise.resolve();
|
|
726
|
+
let loaderPromise = existing.loaderPromise;
|
|
727
|
+
let loadPromise = existing.loadPromise;
|
|
728
|
+
const potentialPendingMinPromise = async () => {
|
|
729
|
+
const latestMatch = RouterProvider.getRouteMatch(this.state, match.id);
|
|
730
|
+
if (latestMatch == null ? void 0 : latestMatch.minPendingPromise) {
|
|
731
|
+
await latestMatch.minPendingPromise;
|
|
732
|
+
if (latestPromise = checkLatest())
|
|
733
|
+
return await latestPromise;
|
|
734
|
+
updateMatch(latestMatch.id, (prev) => ({
|
|
735
|
+
...prev,
|
|
736
|
+
minPendingPromise: void 0
|
|
737
|
+
}));
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
try {
|
|
741
|
+
if (!match.isFetching) {
|
|
742
|
+
matches[index] = match = {
|
|
743
|
+
...match,
|
|
744
|
+
isFetching: true,
|
|
745
|
+
fetchCount: match.fetchCount + 1
|
|
746
|
+
};
|
|
747
|
+
lazyPromise = ((_a2 = route2.lazyFn) == null ? void 0 : _a2.call(route2).then((lazyRoute) => {
|
|
748
|
+
Object.assign(route2.options, lazyRoute.options);
|
|
749
|
+
})) || Promise.resolve();
|
|
750
|
+
componentsPromise = lazyPromise.then(
|
|
751
|
+
() => Promise.all(
|
|
752
|
+
componentTypes.map(async (type) => {
|
|
753
|
+
const component = route2.options[type];
|
|
754
|
+
if (component == null ? void 0 : component.preload) {
|
|
755
|
+
await component.preload();
|
|
756
|
+
}
|
|
757
|
+
})
|
|
758
|
+
)
|
|
759
|
+
);
|
|
760
|
+
await lazyPromise;
|
|
761
|
+
if (latestPromise = checkLatest())
|
|
762
|
+
return await latestPromise;
|
|
763
|
+
loaderPromise = (_c = (_b2 = route2.options).loader) == null ? void 0 : _c.call(_b2, loaderContext);
|
|
764
|
+
const previousResolve = loadPromise.resolve;
|
|
765
|
+
loadPromise = utils.createControlledPromise(
|
|
766
|
+
// Resolve the old when we we resolve the new one
|
|
767
|
+
previousResolve
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
matches[index] = match = updateMatch(match.id, (prev) => ({
|
|
771
|
+
...prev,
|
|
772
|
+
loaderPromise,
|
|
773
|
+
loadPromise
|
|
774
|
+
}));
|
|
775
|
+
const loaderData = await loaderPromise;
|
|
776
|
+
if (latestPromise = checkLatest())
|
|
777
|
+
return await latestPromise;
|
|
778
|
+
handleError(loaderData);
|
|
779
|
+
if (latestPromise = checkLatest())
|
|
780
|
+
return await latestPromise;
|
|
781
|
+
await potentialPendingMinPromise();
|
|
782
|
+
if (latestPromise = checkLatest())
|
|
783
|
+
return await latestPromise;
|
|
784
|
+
const meta = (_e = (_d = route2.options).meta) == null ? void 0 : _e.call(_d, {
|
|
785
|
+
params: match.params,
|
|
786
|
+
loaderData
|
|
787
|
+
});
|
|
788
|
+
const headers = (_g = (_f = route2.options).headers) == null ? void 0 : _g.call(_f, {
|
|
789
|
+
loaderData
|
|
790
|
+
});
|
|
791
|
+
matches[index] = match = updateMatch(match.id, (prev) => ({
|
|
792
|
+
...prev,
|
|
793
|
+
error: void 0,
|
|
794
|
+
status: "success",
|
|
795
|
+
isFetching: false,
|
|
796
|
+
updatedAt: Date.now(),
|
|
797
|
+
loaderData,
|
|
798
|
+
meta,
|
|
799
|
+
headers
|
|
800
|
+
}));
|
|
801
|
+
} catch (e) {
|
|
802
|
+
let error = e;
|
|
803
|
+
if (latestPromise = checkLatest())
|
|
804
|
+
return await latestPromise;
|
|
805
|
+
await potentialPendingMinPromise();
|
|
806
|
+
if (latestPromise = checkLatest())
|
|
807
|
+
return await latestPromise;
|
|
808
|
+
handleError(e);
|
|
809
|
+
try {
|
|
810
|
+
(_i = (_h = route2.options).onError) == null ? void 0 : _i.call(_h, e);
|
|
811
|
+
} catch (onErrorError) {
|
|
812
|
+
error = onErrorError;
|
|
813
|
+
handleError(onErrorError);
|
|
814
|
+
}
|
|
815
|
+
matches[index] = match = updateMatch(match.id, (prev) => ({
|
|
816
|
+
...prev,
|
|
817
|
+
error,
|
|
818
|
+
status: "error",
|
|
819
|
+
isFetching: false
|
|
820
|
+
}));
|
|
821
|
+
}
|
|
822
|
+
await componentsPromise;
|
|
823
|
+
if (latestPromise = checkLatest())
|
|
824
|
+
return await latestPromise;
|
|
825
|
+
loadPromise.resolve();
|
|
826
|
+
};
|
|
827
|
+
const age = Date.now() - match.updatedAt;
|
|
828
|
+
const staleAge = preload ? route2.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 3e4 : route2.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
829
|
+
const shouldReloadOption = route2.options.shouldReload;
|
|
830
|
+
const shouldReload = typeof shouldReloadOption === "function" ? shouldReloadOption(loaderContext) : shouldReloadOption;
|
|
831
|
+
matches[index] = match = {
|
|
832
|
+
...match,
|
|
833
|
+
preload: !!preload && !this.state.matches.find((d) => d.id === match.id)
|
|
834
|
+
};
|
|
835
|
+
const fetchWithRedirect = async () => {
|
|
836
|
+
try {
|
|
837
|
+
await fetch();
|
|
838
|
+
} catch (err) {
|
|
839
|
+
if (latestPromise = checkLatest())
|
|
840
|
+
return await latestPromise;
|
|
841
|
+
if (redirects.isRedirect(err)) {
|
|
842
|
+
const redirect = this.resolveRedirect(err);
|
|
843
|
+
if (!preload && !this.isServer) {
|
|
844
|
+
this.navigate({ ...redirect, replace: true });
|
|
845
|
+
}
|
|
846
|
+
throw redirect;
|
|
847
|
+
} else if (notFound.isNotFound(err)) {
|
|
848
|
+
if (!preload)
|
|
849
|
+
this.handleNotFound(matches, err);
|
|
850
|
+
throw err;
|
|
851
|
+
}
|
|
852
|
+
handleError(err);
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
if (match.status === "success" && (match.invalid || (shouldReload ?? age > staleAge))) {
|
|
856
|
+
fetchWithRedirect();
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
if (match.status !== "success") {
|
|
860
|
+
await fetchWithRedirect();
|
|
861
|
+
}
|
|
862
|
+
})
|
|
863
|
+
);
|
|
864
|
+
if (latestPromise = checkLatest())
|
|
865
|
+
return await latestPromise;
|
|
866
|
+
resolveAll();
|
|
867
|
+
} catch (err) {
|
|
868
|
+
rejectAll(err);
|
|
829
869
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
870
|
+
})();
|
|
871
|
+
});
|
|
872
|
+
} catch (err) {
|
|
873
|
+
if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
|
|
874
|
+
throw err;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
835
877
|
return matches;
|
|
836
878
|
};
|
|
837
879
|
this.invalidate = () => {
|
|
@@ -852,53 +894,57 @@ class Router {
|
|
|
852
894
|
return this.load();
|
|
853
895
|
};
|
|
854
896
|
this.load = async () => {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
toLocation: next,
|
|
865
|
-
pathChanged: pathDidChange
|
|
866
|
-
});
|
|
867
|
-
let pendingMatches;
|
|
868
|
-
const previousMatches = this.state.matches;
|
|
869
|
-
this.__store.batch(() => {
|
|
870
|
-
this.cleanCache();
|
|
871
|
-
pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
872
|
-
debug: true
|
|
873
|
-
});
|
|
874
|
-
this.__store.setState((s) => ({
|
|
875
|
-
...s,
|
|
876
|
-
isLoading: true,
|
|
877
|
-
location: next,
|
|
878
|
-
pendingMatches,
|
|
879
|
-
cachedMatches: s.cachedMatches.filter((d) => {
|
|
880
|
-
return !pendingMatches.find((e) => e.id === d.id);
|
|
881
|
-
})
|
|
882
|
-
}));
|
|
883
|
-
});
|
|
897
|
+
let resolveLoad;
|
|
898
|
+
let rejectLoad;
|
|
899
|
+
const promise = new Promise((resolve, reject) => {
|
|
900
|
+
resolveLoad = resolve;
|
|
901
|
+
rejectLoad = reject;
|
|
902
|
+
});
|
|
903
|
+
this.latestLoadPromise = promise;
|
|
904
|
+
let latestPromise;
|
|
905
|
+
(async () => {
|
|
884
906
|
try {
|
|
907
|
+
const next = this.latestLocation;
|
|
908
|
+
const prevLocation = this.state.resolvedLocation;
|
|
909
|
+
const pathDidChange = prevLocation.href !== next.href;
|
|
910
|
+
this.cancelMatches();
|
|
911
|
+
this.emit({
|
|
912
|
+
type: "onBeforeLoad",
|
|
913
|
+
fromLocation: prevLocation,
|
|
914
|
+
toLocation: next,
|
|
915
|
+
pathChanged: pathDidChange
|
|
916
|
+
});
|
|
917
|
+
let pendingMatches;
|
|
918
|
+
const previousMatches = this.state.matches;
|
|
919
|
+
this.__store.batch(() => {
|
|
920
|
+
this.cleanCache();
|
|
921
|
+
pendingMatches = this.matchRoutes(next.pathname, next.search);
|
|
922
|
+
this.__store.setState((s) => ({
|
|
923
|
+
...s,
|
|
924
|
+
isLoading: true,
|
|
925
|
+
location: next,
|
|
926
|
+
pendingMatches,
|
|
927
|
+
cachedMatches: s.cachedMatches.filter((d) => {
|
|
928
|
+
return !pendingMatches.find((e) => e.id === d.id);
|
|
929
|
+
})
|
|
930
|
+
}));
|
|
931
|
+
});
|
|
885
932
|
let redirect;
|
|
886
933
|
let notFound$1;
|
|
887
934
|
try {
|
|
888
|
-
|
|
935
|
+
const loadMatchesPromise = this.loadMatches({
|
|
889
936
|
matches: pendingMatches,
|
|
890
937
|
location: next,
|
|
891
938
|
checkLatest: () => this.checkLatest(promise)
|
|
892
939
|
});
|
|
940
|
+
if (previousMatches.length || this.isServer) {
|
|
941
|
+
await loadMatchesPromise;
|
|
942
|
+
}
|
|
893
943
|
} catch (err) {
|
|
894
944
|
if (redirects.isRedirect(err)) {
|
|
895
|
-
redirect =
|
|
896
|
-
if (!utils.isServer) {
|
|
897
|
-
this.navigate({ ...redirect, replace: true });
|
|
898
|
-
}
|
|
945
|
+
redirect = err;
|
|
899
946
|
} else if (notFound.isNotFound(err)) {
|
|
900
947
|
notFound$1 = err;
|
|
901
|
-
this.handleNotFound(pendingMatches, err);
|
|
902
948
|
}
|
|
903
949
|
}
|
|
904
950
|
if (latestPromise = this.checkLatest(promise)) {
|
|
@@ -944,16 +990,15 @@ class Router {
|
|
|
944
990
|
toLocation: next,
|
|
945
991
|
pathChanged: pathDidChange
|
|
946
992
|
});
|
|
947
|
-
|
|
993
|
+
resolveLoad();
|
|
948
994
|
} catch (err) {
|
|
949
995
|
if (latestPromise = this.checkLatest(promise)) {
|
|
950
996
|
return latestPromise;
|
|
951
997
|
}
|
|
952
|
-
console.
|
|
953
|
-
|
|
998
|
+
console.error("Load Error", err);
|
|
999
|
+
rejectLoad(err);
|
|
954
1000
|
}
|
|
955
|
-
});
|
|
956
|
-
this.latestLoadPromise = promise;
|
|
1001
|
+
})();
|
|
957
1002
|
return this.latestLoadPromise;
|
|
958
1003
|
};
|
|
959
1004
|
this.resolveRedirect = (err) => {
|
|
@@ -1017,7 +1062,11 @@ class Router {
|
|
|
1017
1062
|
return matches;
|
|
1018
1063
|
} catch (err) {
|
|
1019
1064
|
if (redirects.isRedirect(err)) {
|
|
1020
|
-
return await this.preloadRoute(
|
|
1065
|
+
return await this.preloadRoute({
|
|
1066
|
+
_fromDest: next,
|
|
1067
|
+
from: next.pathname,
|
|
1068
|
+
...err
|
|
1069
|
+
});
|
|
1021
1070
|
}
|
|
1022
1071
|
console.error(err);
|
|
1023
1072
|
return void 0;
|
|
@@ -1158,8 +1207,7 @@ class Router {
|
|
|
1158
1207
|
this.__store.setState((s) => {
|
|
1159
1208
|
return {
|
|
1160
1209
|
...s,
|
|
1161
|
-
matches
|
|
1162
|
-
lastUpdated: Date.now()
|
|
1210
|
+
matches
|
|
1163
1211
|
};
|
|
1164
1212
|
});
|
|
1165
1213
|
};
|
|
@@ -1234,7 +1282,6 @@ function getInitialRouterState(location) {
|
|
|
1234
1282
|
matches: [],
|
|
1235
1283
|
pendingMatches: [],
|
|
1236
1284
|
cachedMatches: [],
|
|
1237
|
-
lastUpdated: 0,
|
|
1238
1285
|
statusCode: 200
|
|
1239
1286
|
};
|
|
1240
1287
|
}
|