@tanstack/react-router 1.18.2 → 1.18.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.
Files changed (52) hide show
  1. package/dist/cjs/Matches.cjs +75 -24
  2. package/dist/cjs/Matches.cjs.map +1 -1
  3. package/dist/cjs/Matches.d.cts +2 -3
  4. package/dist/cjs/RouterProvider.cjs +1 -10
  5. package/dist/cjs/RouterProvider.cjs.map +1 -1
  6. package/dist/cjs/awaited.cjs +2 -4
  7. package/dist/cjs/awaited.cjs.map +1 -1
  8. package/dist/cjs/fileRoute.cjs +6 -1
  9. package/dist/cjs/fileRoute.cjs.map +1 -1
  10. package/dist/cjs/fileRoute.d.cts +7 -6
  11. package/dist/cjs/link.cjs.map +1 -1
  12. package/dist/cjs/not-found.cjs.map +1 -1
  13. package/dist/cjs/not-found.d.cts +11 -1
  14. package/dist/cjs/redirects.cjs +1 -1
  15. package/dist/cjs/redirects.cjs.map +1 -1
  16. package/dist/cjs/route.cjs +3 -2
  17. package/dist/cjs/route.cjs.map +1 -1
  18. package/dist/cjs/route.d.cts +25 -24
  19. package/dist/cjs/router.cjs +172 -143
  20. package/dist/cjs/router.cjs.map +1 -1
  21. package/dist/cjs/router.d.cts +12 -8
  22. package/dist/esm/Matches.d.ts +2 -3
  23. package/dist/esm/Matches.js +67 -16
  24. package/dist/esm/Matches.js.map +1 -1
  25. package/dist/esm/RouterProvider.js +1 -10
  26. package/dist/esm/RouterProvider.js.map +1 -1
  27. package/dist/esm/awaited.js +2 -4
  28. package/dist/esm/awaited.js.map +1 -1
  29. package/dist/esm/fileRoute.d.ts +7 -6
  30. package/dist/esm/fileRoute.js +6 -1
  31. package/dist/esm/fileRoute.js.map +1 -1
  32. package/dist/esm/link.js.map +1 -1
  33. package/dist/esm/not-found.d.ts +11 -1
  34. package/dist/esm/not-found.js.map +1 -1
  35. package/dist/esm/redirects.js +1 -1
  36. package/dist/esm/redirects.js.map +1 -1
  37. package/dist/esm/route.d.ts +25 -24
  38. package/dist/esm/route.js +3 -2
  39. package/dist/esm/route.js.map +1 -1
  40. package/dist/esm/router.d.ts +12 -8
  41. package/dist/esm/router.js +163 -134
  42. package/dist/esm/router.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/Matches.tsx +100 -27
  45. package/src/RouterProvider.tsx +1 -12
  46. package/src/awaited.tsx +3 -5
  47. package/src/fileRoute.ts +16 -4
  48. package/src/link.tsx +0 -2
  49. package/src/not-found.tsx +11 -1
  50. package/src/redirects.ts +2 -1
  51. package/src/route.ts +55 -114
  52. package/src/router.ts +267 -175
@@ -67,7 +67,10 @@ class Router {
67
67
  onUpdate: () => {
68
68
  this.__store.state = {
69
69
  ...this.state,
70
- status: this.state.isTransitioning || this.state.isLoading ? "pending" : "idle"
70
+ status: this.state.isTransitioning || this.state.isLoading ? "pending" : "idle",
71
+ cachedMatches: this.state.cachedMatches.filter(
72
+ (d) => !["redirected"].includes(d.status)
73
+ )
71
74
  };
72
75
  }
73
76
  });
@@ -221,7 +224,7 @@ class Router {
221
224
  }
222
225
  return false;
223
226
  });
224
- let routeCursor = foundRoute || this.routesById["__root__"];
227
+ let routeCursor = foundRoute || this.routesById[route.rootRouteId];
225
228
  let matchedRoutes = [routeCursor];
226
229
  let isGlobalNotFound = false;
227
230
  if (
@@ -242,6 +245,20 @@ class Router {
242
245
  if (routeCursor)
243
246
  matchedRoutes.unshift(routeCursor);
244
247
  }
248
+ const globalNotFoundRouteId = (() => {
249
+ if (!isGlobalNotFound) {
250
+ return void 0;
251
+ }
252
+ if (this.options.notFoundMode !== "root") {
253
+ for (let i = matchedRoutes.length - 1; i >= 0; i--) {
254
+ const route2 = matchedRoutes[i];
255
+ if (route2.children) {
256
+ return route2.id;
257
+ }
258
+ }
259
+ }
260
+ return route.rootRouteId;
261
+ })();
245
262
  const parseErrors = matchedRoutes.map((route2) => {
246
263
  let parsedParamsError;
247
264
  if (route2.options.parseParams) {
@@ -261,13 +278,13 @@ class Router {
261
278
  return;
262
279
  });
263
280
  const matches = [];
264
- matchedRoutes.forEach((route$1, index) => {
281
+ matchedRoutes.forEach((route2, index) => {
265
282
  var _a, _b, _c, _d, _e, _f;
266
283
  const parentMatch = matches[index - 1];
267
284
  const [preMatchSearch, searchError] = (() => {
268
285
  const parentSearch = (parentMatch == null ? void 0 : parentMatch.search) ?? locationSearch;
269
286
  try {
270
- const validator = typeof route$1.options.validateSearch === "object" ? route$1.options.validateSearch.parse : route$1.options.validateSearch;
287
+ const validator = typeof route2.options.validateSearch === "object" ? route2.options.validateSearch.parse : route2.options.validateSearch;
271
288
  let search = (validator == null ? void 0 : validator(parentSearch)) ?? {};
272
289
  return [
273
290
  {
@@ -286,29 +303,28 @@ class Router {
286
303
  return [parentSearch, searchError2];
287
304
  }
288
305
  })();
289
- const loaderDeps = ((_b = (_a = route$1.options).loaderDeps) == null ? void 0 : _b.call(_a, {
306
+ const loaderDeps = ((_b = (_a = route2.options).loaderDeps) == null ? void 0 : _b.call(_a, {
290
307
  search: preMatchSearch
291
308
  })) ?? "";
292
309
  const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : "";
293
310
  const interpolatedPath = path.interpolatePath({
294
- path: route$1.fullPath,
311
+ path: route2.fullPath,
295
312
  params: routeParams
296
313
  });
297
314
  const matchId = path.interpolatePath({
298
- path: route$1.id,
315
+ path: route2.id,
299
316
  params: routeParams,
300
317
  leaveWildcards: true
301
318
  }) + loaderDepsHash;
302
- const existingMatch = RouterProvider.getRouteMatch(this.state, matchId);
319
+ let existingMatch = RouterProvider.getRouteMatch(this.state, matchId);
303
320
  const cause = this.state.matches.find((d) => d.id === matchId) ? "stay" : "enter";
304
321
  const match = existingMatch ? {
305
322
  ...existingMatch,
306
323
  cause,
307
- notFoundError: isGlobalNotFound && route$1.id === route.rootRouteId ? { global: true } : void 0,
308
324
  params: routeParams
309
325
  } : {
310
326
  id: matchId,
311
- routeId: route$1.id,
327
+ routeId: route2.id,
312
328
  params: routeParams,
313
329
  pathname: path.joinPaths([this.basepath, interpolatedPath]),
314
330
  updatedAt: Date.now(),
@@ -328,11 +344,13 @@ class Router {
328
344
  loaderDeps,
329
345
  invalid: false,
330
346
  preload: false,
331
- notFoundError: isGlobalNotFound && route$1.id === route.rootRouteId ? { global: true } : void 0,
332
- links: (_d = (_c = route$1.options).links) == null ? void 0 : _d.call(_c),
333
- scripts: (_f = (_e = route$1.options).scripts) == null ? void 0 : _f.call(_e),
334
- staticData: route$1.options.staticData || {}
347
+ links: (_d = (_c = route2.options).links) == null ? void 0 : _d.call(_c),
348
+ scripts: (_f = (_e = route2.options).scripts) == null ? void 0 : _f.call(_e),
349
+ staticData: route2.options.staticData || {}
335
350
  };
351
+ if (!(opts == null ? void 0 : opts.preload)) {
352
+ match.globalNotFound = globalNotFoundRouteId === route2.id;
353
+ }
336
354
  match.search = utils.replaceEqualDeep(match.search, preMatchSearch);
337
355
  match.searchError = searchError;
338
356
  matches.push(match);
@@ -340,8 +358,6 @@ class Router {
340
358
  return matches;
341
359
  };
342
360
  this.cancelMatch = (id) => {
343
- var _a, _b;
344
- (_b = (_a = RouterProvider.getRouteMatch(this.state, id)) == null ? void 0 : _a.abortController) == null ? void 0 : _b.abort();
345
361
  };
346
362
  this.cancelMatches = () => {
347
363
  var _a;
@@ -351,13 +367,9 @@ class Router {
351
367
  };
352
368
  this.buildLocation = (opts) => {
353
369
  const build = (dest = {}, matches) => {
354
- var _a, _b;
370
+ var _a, _b, _c;
355
371
  const relevantMatches = this.state.pendingMatches || this.state.matches;
356
372
  const fromSearch = ((_a = relevantMatches[relevantMatches.length - 1]) == null ? void 0 : _a.search) || this.latestLocation.search;
357
- let pathname = this.resolvePathWithBase(
358
- dest.from ?? this.latestLocation.pathname,
359
- `${dest.to ?? ""}`
360
- );
361
373
  const fromMatches = this.matchRoutes(
362
374
  this.latestLocation.pathname,
363
375
  fromSearch
@@ -365,7 +377,12 @@ class Router {
365
377
  const stayingMatches = matches == null ? void 0 : matches.filter(
366
378
  (d) => fromMatches == null ? void 0 : fromMatches.find((e) => e.routeId === d.routeId)
367
379
  );
368
- const prevParams = { ...(_b = utils.last(fromMatches)) == null ? void 0 : _b.params };
380
+ const fromRoute = this.looseRoutesById[(_b = utils.last(fromMatches)) == null ? void 0 : _b.routeId];
381
+ let pathname = dest.to ? this.resolvePathWithBase(
382
+ dest.from ?? this.latestLocation.pathname,
383
+ `${dest.to}`
384
+ ) : fromRoute == null ? void 0 : fromRoute.fullPath;
385
+ const prevParams = { ...(_c = utils.last(fromMatches)) == null ? void 0 : _c.params };
369
386
  let nextParams = (dest.params ?? true) === true ? prevParams : { ...prevParams, ...utils.functionalUpdate(dest.params, prevParams) };
370
387
  if (nextParams) {
371
388
  matches == null ? void 0 : matches.map((d) => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach((fn) => {
@@ -457,7 +474,7 @@ class Router {
457
474
  if (this.navigateTimeout)
458
475
  clearTimeout(this.navigateTimeout);
459
476
  const isSameUrl = this.latestLocation.href === next.href;
460
- if (!isSameUrl || !next.replace) {
477
+ if (!isSameUrl) {
461
478
  let { maskedLocation, ...nextHistory } = next;
462
479
  if (maskedLocation) {
463
480
  nextHistory = {
@@ -531,13 +548,14 @@ class Router {
531
548
  };
532
549
  this.loadMatches = async ({
533
550
  checkLatest,
551
+ location,
534
552
  matches,
535
553
  preload
536
554
  }) => {
537
555
  var _a, _b;
538
556
  let latestPromise;
539
557
  let firstBadMatchIndex;
540
- const updateMatch = (match) => {
558
+ const updateMatch = (match, opts) => {
541
559
  var _a2;
542
560
  const isPending = (_a2 = this.state.pendingMatches) == null ? void 0 : _a2.find(
543
561
  (d) => d.id === match.id
@@ -545,36 +563,43 @@ class Router {
545
563
  const isMatched = this.state.matches.find((d) => d.id === match.id);
546
564
  const matchesKey = isPending ? "pendingMatches" : isMatched ? "matches" : "cachedMatches";
547
565
  this.__store.setState((s) => {
548
- var _a3;
566
+ var _a3, _b2;
549
567
  return {
550
568
  ...s,
551
- [matchesKey]: (_a3 = s[matchesKey]) == null ? void 0 : _a3.map(
552
- (d) => d.id === match.id ? match : d
553
- )
569
+ [matchesKey]: (opts == null ? void 0 : opts.remove) ? (_a3 = s[matchesKey]) == null ? void 0 : _a3.filter((d) => d.id !== match.id) : (_b2 = s[matchesKey]) == null ? void 0 : _b2.map((d) => d.id === match.id ? match : d)
554
570
  };
555
571
  });
556
572
  };
573
+ const handleMatchSpecialError = (match, err) => {
574
+ match = {
575
+ ...match,
576
+ status: redirects.isRedirect(err) ? "redirected" : notFound.isNotFound(err) ? "notFound" : "error",
577
+ isFetching: false,
578
+ error: err
579
+ };
580
+ updateMatch(match);
581
+ if (!err.routeId) {
582
+ err.routeId = match.routeId;
583
+ }
584
+ throw err;
585
+ };
557
586
  for (let [index, match] of matches.entries()) {
558
587
  const parentMatch = matches[index - 1];
559
588
  const route2 = this.looseRoutesById[match.routeId];
560
589
  const abortController = new AbortController();
561
- const handleError = (err, code) => {
590
+ const handleSerialError = (err, code) => {
562
591
  var _a2, _b2;
563
592
  err.routerCode = code;
564
593
  firstBadMatchIndex = firstBadMatchIndex ?? index;
565
- if (redirects.isRedirect(err)) {
566
- throw err;
567
- }
568
- if (notFound.isNotFound(err)) {
569
- err.routeId = match.routeId;
570
- throw err;
594
+ if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
595
+ handleMatchSpecialError(match, err);
571
596
  }
572
597
  try {
573
598
  (_b2 = (_a2 = route2.options).onError) == null ? void 0 : _b2.call(_a2, err);
574
599
  } catch (errorHandlerErr) {
575
600
  err = errorHandlerErr;
576
- if (redirects.isRedirect(errorHandlerErr)) {
577
- throw errorHandlerErr;
601
+ if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
602
+ handleMatchSpecialError(match, errorHandlerErr);
578
603
  }
579
604
  }
580
605
  matches[index] = match = {
@@ -585,13 +610,13 @@ class Router {
585
610
  abortController: new AbortController()
586
611
  };
587
612
  };
613
+ if (match.paramsError) {
614
+ handleSerialError(match.paramsError, "PARSE_PARAMS");
615
+ }
616
+ if (match.searchError) {
617
+ handleSerialError(match.searchError, "VALIDATE_SEARCH");
618
+ }
588
619
  try {
589
- if (match.paramsError) {
590
- handleError(match.paramsError, "PARSE_PARAMS");
591
- }
592
- if (match.searchError) {
593
- handleError(match.searchError, "VALIDATE_SEARCH");
594
- }
595
620
  const parentContext = (parentMatch == null ? void 0 : parentMatch.context) ?? this.options.context ?? {};
596
621
  const pendingMs = route2.options.pendingMs ?? this.options.defaultPendingMs;
597
622
  const pendingPromise = typeof pendingMs === "number" && pendingMs <= 0 ? Promise.resolve() : new Promise((r) => setTimeout(r, pendingMs));
@@ -601,14 +626,13 @@ class Router {
601
626
  params: match.params,
602
627
  preload: !!preload,
603
628
  context: parentContext,
604
- location: this.state.location,
605
- // TOOD: just expose state and router, etc
629
+ location,
606
630
  navigate: (opts) => this.navigate({ ...opts, from: match.pathname }),
607
631
  buildLocation: this.buildLocation,
608
632
  cause: preload ? "preload" : match.cause
609
633
  })) ?? {};
610
- if (redirects.isRedirect(beforeLoadContext)) {
611
- throw beforeLoadContext;
634
+ if (redirects.isRedirect(beforeLoadContext) || notFound.isNotFound(beforeLoadContext)) {
635
+ handleSerialError(beforeLoadContext, "BEFORE_LOAD");
612
636
  }
613
637
  const context = {
614
638
  ...parentContext,
@@ -622,7 +646,7 @@ class Router {
622
646
  pendingPromise
623
647
  };
624
648
  } catch (err) {
625
- handleError(err, "BEFORE_LOAD");
649
+ handleSerialError(err, "BEFORE_LOAD");
626
650
  break;
627
651
  }
628
652
  }
@@ -635,12 +659,8 @@ class Router {
635
659
  const parentMatchPromise = matchPromises[index - 1];
636
660
  const route2 = this.looseRoutesById[match.routeId];
637
661
  const handleError = (err) => {
638
- if (redirects.isRedirect(err)) {
639
- throw err;
640
- }
641
- if (notFound.isNotFound(err)) {
642
- err.routeId = match.routeId;
643
- throw err;
662
+ if (redirects.isRedirect(err) || notFound.isNotFound(err)) {
663
+ handleMatchSpecialError(match, err);
644
664
  }
645
665
  };
646
666
  let loadPromise;
@@ -651,7 +671,6 @@ class Router {
651
671
  let didShowPending = false;
652
672
  const pendingMs = route2.options.pendingMs ?? this.options.defaultPendingMs;
653
673
  const pendingMinMs = route2.options.pendingMinMs ?? this.options.defaultPendingMinMs;
654
- const shouldPending = !preload && typeof pendingMs === "number" && (route2.options.pendingComponent ?? this.options.defaultPendingComponent);
655
674
  const loaderContext = {
656
675
  params: match.params,
657
676
  deps: match.loaderDeps,
@@ -659,53 +678,47 @@ class Router {
659
678
  parentMatchPromise,
660
679
  abortController: match.abortController,
661
680
  context: match.context,
662
- location: this.state.location,
681
+ location,
663
682
  navigate: (opts) => this.navigate({ ...opts, from: match.pathname }),
664
- cause: preload ? "preload" : match.cause
683
+ cause: preload ? "preload" : match.cause,
684
+ route: route2
665
685
  };
666
686
  const fetch = async () => {
667
- var _a3, _b2, _c, _d, _e, _f, _g, _h;
668
- if (match.isFetching) {
669
- loadPromise = (_a3 = RouterProvider.getRouteMatch(this.state, match.id)) == null ? void 0 : _a3.loadPromise;
670
- } else {
671
- if (match.fetchCount && match.status === "success") {
672
- resolve();
687
+ var _a3, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
688
+ try {
689
+ if (match.isFetching) {
690
+ loadPromise = (_a3 = RouterProvider.getRouteMatch(this.state, match.id)) == null ? void 0 : _a3.loadPromise;
691
+ } else {
692
+ matches[index] = match = {
693
+ ...match,
694
+ isFetching: true,
695
+ fetchCount: match.fetchCount + 1
696
+ };
697
+ const lazyPromise = ((_b2 = route2.lazyFn) == null ? void 0 : _b2.call(route2).then((lazyRoute) => {
698
+ Object.assign(route2.options, lazyRoute.options);
699
+ })) || Promise.resolve();
700
+ const componentsPromise = lazyPromise.then(
701
+ () => Promise.all(
702
+ componentTypes.map(async (type) => {
703
+ const component = route2.options[type];
704
+ if (component == null ? void 0 : component.preload) {
705
+ await component.preload();
706
+ }
707
+ })
708
+ )
709
+ );
710
+ const loaderPromise = (_d = (_c = route2.options).loader) == null ? void 0 : _d.call(_c, loaderContext);
711
+ loadPromise = Promise.all([
712
+ componentsPromise,
713
+ loaderPromise,
714
+ lazyPromise
715
+ ]).then((d) => d[1]);
673
716
  }
674
717
  matches[index] = match = {
675
718
  ...match,
676
- isFetching: true,
677
- fetchCount: match.fetchCount + 1
719
+ loadPromise
678
720
  };
679
- const lazyPromise = ((_b2 = route2.lazyFn) == null ? void 0 : _b2.call(route2).then((lazyRoute) => {
680
- Object.assign(route2.options, lazyRoute.options);
681
- })) || Promise.resolve();
682
- const componentsPromise = lazyPromise.then(
683
- () => Promise.all(
684
- componentTypes.map(async (type) => {
685
- const component = route2.options[type];
686
- if (component == null ? void 0 : component.preload) {
687
- await component.preload();
688
- }
689
- })
690
- )
691
- );
692
- async function loader() {
693
- var _a4, _b3;
694
- return await ((_b3 = (_a4 = route2.options).loader) == null ? void 0 : _b3.call(_a4, loaderContext));
695
- }
696
- const loaderPromise = loader();
697
- loadPromise = Promise.all([
698
- componentsPromise,
699
- loaderPromise,
700
- lazyPromise
701
- ]).then((d) => d[1]);
702
- }
703
- matches[index] = match = {
704
- ...match,
705
- loadPromise
706
- };
707
- updateMatch(match);
708
- try {
721
+ updateMatch(match);
709
722
  const loaderData = await loadPromise;
710
723
  if (latestPromise = checkLatest())
711
724
  return await latestPromise;
@@ -716,11 +729,11 @@ class Router {
716
729
  if (latestPromise = checkLatest())
717
730
  return await latestPromise;
718
731
  const [meta, headers] = await Promise.all([
719
- (_d = (_c = route2.options).meta) == null ? void 0 : _d.call(_c, {
732
+ (_f = (_e = route2.options).meta) == null ? void 0 : _f.call(_e, {
720
733
  params: match.params,
721
734
  loaderData
722
735
  }),
723
- (_f = (_e = route2.options).headers) == null ? void 0 : _f.call(_e, {
736
+ (_h = (_g = route2.options).headers) == null ? void 0 : _h.call(_g, {
724
737
  loaderData
725
738
  })
726
739
  ]);
@@ -740,7 +753,7 @@ class Router {
740
753
  return await latestPromise;
741
754
  handleError(error);
742
755
  try {
743
- (_h = (_g = route2.options).onError) == null ? void 0 : _h.call(_g, error);
756
+ (_j = (_i = route2.options).onError) == null ? void 0 : _j.call(_i, error);
744
757
  } catch (onErrorError) {
745
758
  error = onErrorError;
746
759
  handleError(onErrorError);
@@ -763,8 +776,26 @@ class Router {
763
776
  ...match,
764
777
  preload: !!preload && !this.state.matches.find((d) => d.id === match.id)
765
778
  };
766
- try {
767
- if (match.status !== "success") {
779
+ if (match.status === "success" && (match.invalid || (shouldReload ?? age > staleAge))) {
780
+ (async () => {
781
+ try {
782
+ await fetch();
783
+ } catch (err) {
784
+ console.info("Background Fetching Error", err);
785
+ if (redirects.isRedirect(err)) {
786
+ const isActive = (this.state.pendingMatches || this.state.matches).find((d) => d.id === match.id);
787
+ handleError(err);
788
+ if (isActive) {
789
+ this.handleRedirect(err);
790
+ }
791
+ }
792
+ }
793
+ })();
794
+ return resolve();
795
+ }
796
+ const shouldPending = !preload && typeof pendingMs === "number" && (route2.options.pendingComponent ?? this.options.defaultPendingComponent);
797
+ if (match.status !== "success") {
798
+ try {
768
799
  if (shouldPending) {
769
800
  (_a2 = match.pendingPromise) == null ? void 0 : _a2.then(async () => {
770
801
  if (latestPromise = checkLatest())
@@ -779,11 +810,9 @@ class Router {
779
810
  });
780
811
  }
781
812
  await fetch();
782
- } else if (match.invalid || (shouldReload ?? age > staleAge)) {
783
- fetch();
813
+ } catch (err) {
814
+ reject(err);
784
815
  }
785
- } catch (err) {
786
- reject(err);
787
816
  }
788
817
  resolve();
789
818
  })
@@ -839,15 +868,20 @@ class Router {
839
868
  }));
840
869
  });
841
870
  try {
871
+ let redirected;
872
+ let notFound$1;
842
873
  try {
843
874
  await this.loadMatches({
844
875
  matches: pendingMatches,
876
+ location: next,
845
877
  checkLatest: () => this.checkLatest(promise)
846
878
  });
847
879
  } catch (err) {
848
880
  if (redirects.isRedirect(err)) {
881
+ redirected = err;
849
882
  this.handleRedirect(err);
850
883
  } else if (notFound.isNotFound(err)) {
884
+ notFound$1 = err;
851
885
  this.handleNotFound(pendingMatches, err);
852
886
  }
853
887
  }
@@ -872,7 +906,8 @@ class Router {
872
906
  cachedMatches: [
873
907
  ...s.cachedMatches,
874
908
  ...exitingMatches.filter((d) => d.status !== "error")
875
- ]
909
+ ],
910
+ statusCode: (redirected == null ? void 0 : redirected.code) || notFound$1 ? 404 : s.matches.some((d) => d.status === "error") ? 500 : 200
876
911
  }));
877
912
  this.cleanCache();
878
913
  });
@@ -897,6 +932,7 @@ class Router {
897
932
  if (latestPromise = this.checkLatest(promise)) {
898
933
  return latestPromise;
899
934
  }
935
+ console.log("Load Error", err);
900
936
  reject(err);
901
937
  }
902
938
  });
@@ -907,10 +943,9 @@ class Router {
907
943
  if (!err.href) {
908
944
  err.href = this.buildLocation(err).href;
909
945
  }
910
- if (utils.isServer) {
911
- throw err;
946
+ if (!utils.isServer) {
947
+ this.navigate({ ...err, replace: true });
912
948
  }
913
- this.navigate(err);
914
949
  };
915
950
  this.cleanCache = () => {
916
951
  this.__store.setState((s) => {
@@ -927,11 +962,12 @@ class Router {
927
962
  };
928
963
  });
929
964
  };
930
- this.preloadRoute = async (navigateOpts = this.state.location) => {
965
+ this.preloadRoute = async (opts) => {
931
966
  var _a;
932
- let next = this.buildLocation(navigateOpts);
967
+ let next = this.buildLocation(opts);
933
968
  let matches = this.matchRoutes(next.pathname, next.search, {
934
- throwOnError: true
969
+ throwOnError: true,
970
+ preload: true
935
971
  });
936
972
  const loadedMatchIds = Object.fromEntries(
937
973
  (_a = [
@@ -953,14 +989,16 @@ class Router {
953
989
  try {
954
990
  matches = await this.loadMatches({
955
991
  matches,
992
+ location: next,
956
993
  preload: true,
957
994
  checkLatest: () => void 0
958
995
  });
959
996
  return matches;
960
997
  } catch (err) {
961
- if (!redirects.isRedirect(err) && !notFound.isNotFound(err)) {
962
- console.error(err);
998
+ if (redirects.isRedirect(err)) {
999
+ return await this.preloadRoute(err);
963
1000
  }
1001
+ console.error(err);
964
1002
  return void 0;
965
1003
  }
966
1004
  };
@@ -1047,15 +1085,7 @@ class Router {
1047
1085
  return {
1048
1086
  state: {
1049
1087
  dehydratedMatches: this.state.matches.map((d) => ({
1050
- ...utils.pick(d, [
1051
- "id",
1052
- "status",
1053
- "updatedAt",
1054
- "loaderData",
1055
- // Not-founds that occur during SSR don't require the client to load data before
1056
- // triggering in order to prevent the flicker of the loading component
1057
- "notFoundError"
1058
- ]),
1088
+ ...utils.pick(d, ["id", "status", "updatedAt", "loaderData"]),
1059
1089
  // If an error occurs server-side during SSRing,
1060
1090
  // send a small subset of the error to the client
1061
1091
  error: d.error ? {
@@ -1117,30 +1147,28 @@ class Router {
1117
1147
  };
1118
1148
  this.handleNotFound = (matches, err) => {
1119
1149
  const matchesByRouteId = Object.fromEntries(
1120
- matches.map((match) => [match.routeId, match])
1150
+ matches.map((match2) => [match2.routeId, match2])
1121
1151
  );
1122
- if (!err.global && err.routeId) {
1123
- let currentRoute = this.looseRoutesById[err.routeId];
1124
- if (currentRoute) {
1125
- while (!currentRoute.options.notFoundComponent) {
1126
- currentRoute = currentRoute == null ? void 0 : currentRoute.parentRoute;
1127
- invariant(
1128
- currentRoute,
1129
- "Found invalid route tree while trying to find not-found handler."
1130
- );
1131
- if (currentRoute.id === route.rootRouteId)
1132
- break;
1133
- }
1134
- const match = matchesByRouteId[currentRoute.id];
1135
- invariant(match, "Could not find match for route: " + currentRoute.id);
1136
- match.notFoundError = err;
1137
- return;
1138
- }
1152
+ let routeCursor = (err.global ? this.looseRoutesById[route.rootRouteId] : this.looseRoutesById[err.routeId]) || this.looseRoutesById[route.rootRouteId];
1153
+ while (!routeCursor.options.notFoundComponent && !this.options.defaultNotFoundComponent && routeCursor.id !== route.rootRouteId) {
1154
+ routeCursor = routeCursor == null ? void 0 : routeCursor.parentRoute;
1155
+ invariant(
1156
+ routeCursor,
1157
+ "Found invalid route tree while trying to find not-found handler."
1158
+ );
1139
1159
  }
1140
- matchesByRouteId[route.rootRouteId].notFoundError = err;
1160
+ let match = matchesByRouteId[routeCursor.id];
1161
+ invariant(match, "Could not find match for route: " + routeCursor.id);
1162
+ Object.assign(match, {
1163
+ status: "notFound",
1164
+ error: err,
1165
+ isFetching: false
1166
+ });
1141
1167
  };
1142
1168
  this.hasNotFoundMatch = () => {
1143
- return this.__store.state.matches.some((d) => d.notFoundError);
1169
+ return this.__store.state.matches.some(
1170
+ (d) => d.status === "notFound" || d.globalNotFound
1171
+ );
1144
1172
  };
1145
1173
  this.update({
1146
1174
  defaultPreloadDelay: 50,
@@ -1188,7 +1216,8 @@ function getInitialRouterState(location) {
1188
1216
  matches: [],
1189
1217
  pendingMatches: [],
1190
1218
  cachedMatches: [],
1191
- lastUpdated: 0
1219
+ lastUpdated: 0,
1220
+ statusCode: 200
1192
1221
  };
1193
1222
  }
1194
1223
  function defaultSerializeError(err) {