react-router 7.5.0 → 7.5.1

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 (40) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/development/{chunk-KNED5TY2.mjs → chunk-LSOULM7L.mjs} +586 -346
  3. package/dist/development/{future-ldDp5FKH.d.ts → data-CQbyyGzl.d.mts} +1 -11
  4. package/dist/{production/future-ldDp5FKH.d.mts → development/data-CQbyyGzl.d.ts} +1 -11
  5. package/dist/development/dom-export.d.mts +2 -2
  6. package/dist/development/dom-export.d.ts +2 -2
  7. package/dist/development/dom-export.js +479 -311
  8. package/dist/development/dom-export.mjs +18 -6
  9. package/dist/{production/fog-of-war-1hWhK5ey.d.mts → development/fog-of-war-CyHis97d.d.mts} +3 -2
  10. package/dist/development/{fog-of-war-oa9CGk10.d.ts → fog-of-war-D4x86-Xc.d.ts} +3 -2
  11. package/dist/development/index.d.mts +12 -8
  12. package/dist/development/index.d.ts +12 -8
  13. package/dist/development/index.js +587 -346
  14. package/dist/development/index.mjs +4 -2
  15. package/dist/development/lib/types/route-module.d.mts +2 -2
  16. package/dist/development/lib/types/route-module.d.ts +2 -2
  17. package/dist/development/lib/types/route-module.js +1 -1
  18. package/dist/development/lib/types/route-module.mjs +1 -1
  19. package/dist/development/{route-data-5OzAzQtT.d.mts → route-data-OcOrqK13.d.mts} +30 -7
  20. package/dist/{production/route-data-5OzAzQtT.d.mts → development/route-data-OcOrqK13.d.ts} +30 -7
  21. package/dist/production/{chunk-ZIM7OIE3.mjs → chunk-SAWFLE7G.mjs} +586 -346
  22. package/dist/production/{future-ldDp5FKH.d.ts → data-CQbyyGzl.d.mts} +1 -11
  23. package/dist/{development/future-ldDp5FKH.d.mts → production/data-CQbyyGzl.d.ts} +1 -11
  24. package/dist/production/dom-export.d.mts +2 -2
  25. package/dist/production/dom-export.d.ts +2 -2
  26. package/dist/production/dom-export.js +479 -311
  27. package/dist/production/dom-export.mjs +18 -6
  28. package/dist/{development/fog-of-war-1hWhK5ey.d.mts → production/fog-of-war-CyHis97d.d.mts} +3 -2
  29. package/dist/production/{fog-of-war-oa9CGk10.d.ts → fog-of-war-D4x86-Xc.d.ts} +3 -2
  30. package/dist/production/index.d.mts +12 -8
  31. package/dist/production/index.d.ts +12 -8
  32. package/dist/production/index.js +587 -346
  33. package/dist/production/index.mjs +4 -2
  34. package/dist/production/lib/types/route-module.d.mts +2 -2
  35. package/dist/production/lib/types/route-module.d.ts +2 -2
  36. package/dist/production/lib/types/route-module.js +1 -1
  37. package/dist/production/lib/types/route-module.mjs +1 -1
  38. package/dist/production/{route-data-5OzAzQtT.d.ts → route-data-OcOrqK13.d.mts} +30 -7
  39. package/dist/{development/route-data-5OzAzQtT.d.ts → production/route-data-OcOrqK13.d.ts} +30 -7
  40. package/package.json +1 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v7.5.0
2
+ * react-router v7.5.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -803,6 +803,7 @@ function createRouter(init) {
803
803
  init.routes.length > 0,
804
804
  "You must provide a non-empty routes array to createRouter"
805
805
  );
806
+ let hydrationRouteProperties2 = init.hydrationRouteProperties || [];
806
807
  let mapRouteProperties2 = init.mapRouteProperties || defaultMapRouteProperties;
807
808
  let manifest = {};
808
809
  let dataRoutes = convertRoutesToDataRoutes(
@@ -1275,6 +1276,7 @@ function createRouter(init) {
1275
1276
  matches,
1276
1277
  scopedContext,
1277
1278
  fogOfWar.active,
1279
+ opts && opts.initialHydration === true,
1278
1280
  { replace: opts.replace, flushSync: flushSync2 }
1279
1281
  );
1280
1282
  if (actionResult.shortCircuited) {
@@ -1335,7 +1337,7 @@ function createRouter(init) {
1335
1337
  errors
1336
1338
  });
1337
1339
  }
1338
- async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, opts = {}) {
1340
+ async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, initialHydration, opts = {}) {
1339
1341
  interruptActiveLoads();
1340
1342
  let navigation = getSubmittingNavigation(location, submission);
1341
1343
  updateState({ navigation }, { flushSync: opts.flushSync === true });
@@ -1389,11 +1391,18 @@ function createRouter(init) {
1389
1391
  })
1390
1392
  };
1391
1393
  } else {
1392
- let results = await callDataStrategy(
1393
- "action",
1394
+ let dsMatches = getTargetedDataStrategyMatches(
1395
+ mapRouteProperties2,
1396
+ manifest,
1394
1397
  request,
1395
- [actionMatch],
1396
1398
  matches,
1399
+ actionMatch,
1400
+ initialHydration ? [] : hydrationRouteProperties2,
1401
+ scopedContext
1402
+ );
1403
+ let results = await callDataStrategy(
1404
+ request,
1405
+ dsMatches,
1397
1406
  scopedContext,
1398
1407
  null
1399
1408
  );
@@ -1492,12 +1501,17 @@ function createRouter(init) {
1492
1501
  }
1493
1502
  }
1494
1503
  let routesToUse = inFlightDataRoutes || dataRoutes;
1495
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(
1504
+ let { dsMatches, revalidatingFetchers } = getMatchesToLoad(
1505
+ request,
1506
+ scopedContext,
1507
+ mapRouteProperties2,
1508
+ manifest,
1496
1509
  init.history,
1497
1510
  state,
1498
1511
  matches,
1499
1512
  activeSubmission,
1500
1513
  location,
1514
+ initialHydration ? [] : hydrationRouteProperties2,
1501
1515
  initialHydration === true,
1502
1516
  isRevalidationRequired,
1503
1517
  cancelledFetcherLoads,
@@ -1509,7 +1523,7 @@ function createRouter(init) {
1509
1523
  pendingActionResult
1510
1524
  );
1511
1525
  pendingNavigationLoadId = ++incrementingLoadId;
1512
- if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
1526
+ if (!init.dataStrategy && !dsMatches.some((m) => m.shouldLoad) && revalidatingFetchers.length === 0) {
1513
1527
  let updatedFetchers2 = markFetchRedirectsDone();
1514
1528
  completeNavigation(
1515
1529
  location,
@@ -1553,8 +1567,7 @@ function createRouter(init) {
1553
1567
  );
1554
1568
  }
1555
1569
  let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1556
- matches,
1557
- matchesToLoad,
1570
+ dsMatches,
1558
1571
  revalidatingFetchers,
1559
1572
  request,
1560
1573
  scopedContext
@@ -1757,11 +1770,18 @@ function createRouter(init) {
1757
1770
  }
1758
1771
  fetchControllers.set(key, abortController);
1759
1772
  let originatingLoadId = incrementingLoadId;
1760
- let actionResults = await callDataStrategy(
1761
- "action",
1773
+ let fetchMatches = getTargetedDataStrategyMatches(
1774
+ mapRouteProperties2,
1775
+ manifest,
1762
1776
  fetchRequest,
1763
- [match],
1764
1777
  requestMatches,
1778
+ match,
1779
+ hydrationRouteProperties2,
1780
+ scopedContext
1781
+ );
1782
+ let actionResults = await callDataStrategy(
1783
+ fetchRequest,
1784
+ fetchMatches,
1765
1785
  scopedContext,
1766
1786
  key
1767
1787
  );
@@ -1810,12 +1830,17 @@ function createRouter(init) {
1810
1830
  fetchReloadIds.set(key, loadId);
1811
1831
  let loadFetcher = getLoadingFetcher(submission, actionResult.data);
1812
1832
  state.fetchers.set(key, loadFetcher);
1813
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(
1833
+ let { dsMatches, revalidatingFetchers } = getMatchesToLoad(
1834
+ revalidationRequest,
1835
+ scopedContext,
1836
+ mapRouteProperties2,
1837
+ manifest,
1814
1838
  init.history,
1815
1839
  state,
1816
1840
  matches,
1817
1841
  submission,
1818
1842
  nextLocation,
1843
+ hydrationRouteProperties2,
1819
1844
  false,
1820
1845
  isRevalidationRequired,
1821
1846
  cancelledFetcherLoads,
@@ -1846,8 +1871,7 @@ function createRouter(init) {
1846
1871
  abortPendingFetchRevalidations
1847
1872
  );
1848
1873
  let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1849
- matches,
1850
- matchesToLoad,
1874
+ dsMatches,
1851
1875
  revalidatingFetchers,
1852
1876
  revalidationRequest,
1853
1877
  scopedContext
@@ -1960,11 +1984,18 @@ function createRouter(init) {
1960
1984
  }
1961
1985
  fetchControllers.set(key, abortController);
1962
1986
  let originatingLoadId = incrementingLoadId;
1963
- let results = await callDataStrategy(
1964
- "loader",
1987
+ let dsMatches = getTargetedDataStrategyMatches(
1988
+ mapRouteProperties2,
1989
+ manifest,
1965
1990
  fetchRequest,
1966
- [match],
1967
1991
  matches,
1992
+ match,
1993
+ hydrationRouteProperties2,
1994
+ scopedContext
1995
+ );
1996
+ let results = await callDataStrategy(
1997
+ fetchRequest,
1998
+ dsMatches,
1968
1999
  scopedContext,
1969
2000
  key
1970
2001
  );
@@ -2067,23 +2098,20 @@ function createRouter(init) {
2067
2098
  });
2068
2099
  }
2069
2100
  }
2070
- async function callDataStrategy(type, request, matchesToLoad, matches, scopedContext, fetcherKey) {
2101
+ async function callDataStrategy(request, matches, scopedContext, fetcherKey) {
2071
2102
  let results;
2072
2103
  let dataResults = {};
2073
2104
  try {
2074
2105
  results = await callDataStrategyImpl(
2075
2106
  dataStrategyImpl,
2076
- type,
2077
2107
  request,
2078
- matchesToLoad,
2079
2108
  matches,
2080
2109
  fetcherKey,
2081
- manifest,
2082
- mapRouteProperties2,
2083
- scopedContext
2110
+ scopedContext,
2111
+ false
2084
2112
  );
2085
2113
  } catch (e) {
2086
- matchesToLoad.forEach((m) => {
2114
+ matches.filter((m) => m.shouldLoad).forEach((m) => {
2087
2115
  dataResults[m.route.id] = {
2088
2116
  type: "error" /* error */,
2089
2117
  error: e
@@ -2112,22 +2140,18 @@ function createRouter(init) {
2112
2140
  }
2113
2141
  return dataResults;
2114
2142
  }
2115
- async function callLoadersAndMaybeResolveData(matches, matchesToLoad, fetchersToLoad, request, scopedContext) {
2143
+ async function callLoadersAndMaybeResolveData(matches, fetchersToLoad, request, scopedContext) {
2116
2144
  let loaderResultsPromise = callDataStrategy(
2117
- "loader",
2118
2145
  request,
2119
- matchesToLoad,
2120
2146
  matches,
2121
2147
  scopedContext,
2122
2148
  null
2123
2149
  );
2124
2150
  let fetcherResultsPromise = Promise.all(
2125
2151
  fetchersToLoad.map(async (f) => {
2126
- if (f.matches && f.match && f.controller) {
2152
+ if (f.matches && f.match && f.request && f.controller) {
2127
2153
  let results = await callDataStrategy(
2128
- "loader",
2129
- createClientSideRequest(init.history, f.path, f.controller.signal),
2130
- [f.match],
2154
+ f.request,
2131
2155
  f.matches,
2132
2156
  scopedContext,
2133
2157
  f.key
@@ -2645,62 +2669,78 @@ function normalizeNavigateOptions(isFetcher, path, opts) {
2645
2669
  parsedPath.search = `?${searchParams}`;
2646
2670
  return { path: createPath(parsedPath), submission };
2647
2671
  }
2648
- function getLoaderMatchesUntilBoundary(matches, boundaryId, includeBoundary = false) {
2649
- let index = matches.findIndex((m) => m.route.id === boundaryId);
2650
- if (index >= 0) {
2651
- return matches.slice(0, includeBoundary ? index + 1 : index);
2652
- }
2653
- return matches;
2654
- }
2655
- function getMatchesToLoad(history, state, matches, submission, location, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
2672
+ function getMatchesToLoad(request, scopedContext, mapRouteProperties2, manifest, history, state, matches, submission, location, lazyRoutePropertiesToSkip, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
2656
2673
  let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : void 0;
2657
2674
  let currentUrl = history.createURL(state.location);
2658
2675
  let nextUrl = history.createURL(location);
2659
- let boundaryMatches = matches;
2676
+ let maxIdx;
2660
2677
  if (initialHydration && state.errors) {
2661
- boundaryMatches = getLoaderMatchesUntilBoundary(
2662
- matches,
2663
- Object.keys(state.errors)[0],
2664
- true
2665
- );
2678
+ let boundaryId = Object.keys(state.errors)[0];
2679
+ maxIdx = matches.findIndex((m) => m.route.id === boundaryId);
2666
2680
  } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) {
2667
- boundaryMatches = getLoaderMatchesUntilBoundary(
2668
- matches,
2669
- pendingActionResult[0]
2670
- );
2681
+ let boundaryId = pendingActionResult[0];
2682
+ maxIdx = matches.findIndex((m) => m.route.id === boundaryId) - 1;
2671
2683
  }
2672
2684
  let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : void 0;
2673
2685
  let shouldSkipRevalidation = actionStatus && actionStatus >= 400;
2674
- let navigationMatches = boundaryMatches.filter((match, index) => {
2686
+ let baseShouldRevalidateArgs = {
2687
+ currentUrl,
2688
+ currentParams: state.matches[0]?.params || {},
2689
+ nextUrl,
2690
+ nextParams: matches[0].params,
2691
+ ...submission,
2692
+ actionResult,
2693
+ actionStatus
2694
+ };
2695
+ let dsMatches = matches.map((match, index) => {
2675
2696
  let { route } = match;
2676
- if (route.lazy) {
2677
- return true;
2697
+ let forceShouldLoad = null;
2698
+ if (maxIdx != null && index > maxIdx) {
2699
+ forceShouldLoad = false;
2700
+ } else if (route.lazy) {
2701
+ forceShouldLoad = true;
2702
+ } else if (route.loader == null) {
2703
+ forceShouldLoad = false;
2704
+ } else if (initialHydration) {
2705
+ forceShouldLoad = shouldLoadRouteOnHydration(
2706
+ route,
2707
+ state.loaderData,
2708
+ state.errors
2709
+ );
2710
+ } else if (isNewLoader(state.loaderData, state.matches[index], match)) {
2711
+ forceShouldLoad = true;
2678
2712
  }
2679
- if (route.loader == null) {
2680
- return false;
2713
+ if (forceShouldLoad !== null) {
2714
+ return getDataStrategyMatch(
2715
+ mapRouteProperties2,
2716
+ manifest,
2717
+ request,
2718
+ match,
2719
+ lazyRoutePropertiesToSkip,
2720
+ scopedContext,
2721
+ forceShouldLoad
2722
+ );
2681
2723
  }
2682
- if (initialHydration) {
2683
- return shouldLoadRouteOnHydration(route, state.loaderData, state.errors);
2684
- }
2685
- if (isNewLoader(state.loaderData, state.matches[index], match)) {
2686
- return true;
2687
- }
2688
- let currentRouteMatch = state.matches[index];
2689
- let nextRouteMatch = match;
2690
- return shouldRevalidateLoader(match, {
2691
- currentUrl,
2692
- currentParams: currentRouteMatch.params,
2693
- nextUrl,
2694
- nextParams: nextRouteMatch.params,
2695
- ...submission,
2696
- actionResult,
2697
- actionStatus,
2698
- defaultShouldRevalidate: shouldSkipRevalidation ? false : (
2699
- // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
2700
- isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders
2701
- currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch)
2702
- )
2703
- });
2724
+ let defaultShouldRevalidate = shouldSkipRevalidation ? false : (
2725
+ // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
2726
+ isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders
2727
+ currentUrl.search !== nextUrl.search || isNewRouteInstance(state.matches[index], match)
2728
+ );
2729
+ let shouldRevalidateArgs = {
2730
+ ...baseShouldRevalidateArgs,
2731
+ defaultShouldRevalidate
2732
+ };
2733
+ let shouldLoad = shouldRevalidateLoader(match, shouldRevalidateArgs);
2734
+ return getDataStrategyMatch(
2735
+ mapRouteProperties2,
2736
+ manifest,
2737
+ request,
2738
+ match,
2739
+ lazyRoutePropertiesToSkip,
2740
+ scopedContext,
2741
+ shouldLoad,
2742
+ shouldRevalidateArgs
2743
+ );
2704
2744
  });
2705
2745
  let revalidatingFetchers = [];
2706
2746
  fetchLoadMatches.forEach((f, key) => {
@@ -2715,44 +2755,77 @@ function getMatchesToLoad(history, state, matches, submission, location, initial
2715
2755
  path: f.path,
2716
2756
  matches: null,
2717
2757
  match: null,
2758
+ request: null,
2718
2759
  controller: null
2719
2760
  });
2720
2761
  return;
2721
2762
  }
2763
+ if (fetchRedirectIds.has(key)) {
2764
+ return;
2765
+ }
2722
2766
  let fetcher = state.fetchers.get(key);
2723
2767
  let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
2724
- let shouldRevalidate = false;
2725
- if (fetchRedirectIds.has(key)) {
2726
- shouldRevalidate = false;
2727
- } else if (cancelledFetcherLoads.has(key)) {
2768
+ let fetchController = new AbortController();
2769
+ let fetchRequest = createClientSideRequest(
2770
+ history,
2771
+ f.path,
2772
+ fetchController.signal
2773
+ );
2774
+ let fetcherDsMatches = null;
2775
+ if (cancelledFetcherLoads.has(key)) {
2728
2776
  cancelledFetcherLoads.delete(key);
2729
- shouldRevalidate = true;
2777
+ fetcherDsMatches = getTargetedDataStrategyMatches(
2778
+ mapRouteProperties2,
2779
+ manifest,
2780
+ fetchRequest,
2781
+ fetcherMatches,
2782
+ fetcherMatch,
2783
+ lazyRoutePropertiesToSkip,
2784
+ scopedContext
2785
+ );
2730
2786
  } else if (fetcher && fetcher.state !== "idle" && fetcher.data === void 0) {
2731
- shouldRevalidate = isRevalidationRequired;
2787
+ if (isRevalidationRequired) {
2788
+ fetcherDsMatches = getTargetedDataStrategyMatches(
2789
+ mapRouteProperties2,
2790
+ manifest,
2791
+ fetchRequest,
2792
+ fetcherMatches,
2793
+ fetcherMatch,
2794
+ lazyRoutePropertiesToSkip,
2795
+ scopedContext
2796
+ );
2797
+ }
2732
2798
  } else {
2733
- shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {
2734
- currentUrl,
2735
- currentParams: state.matches[state.matches.length - 1].params,
2736
- nextUrl,
2737
- nextParams: matches[matches.length - 1].params,
2738
- ...submission,
2739
- actionResult,
2740
- actionStatus,
2799
+ let shouldRevalidateArgs = {
2800
+ ...baseShouldRevalidateArgs,
2741
2801
  defaultShouldRevalidate: shouldSkipRevalidation ? false : isRevalidationRequired
2742
- });
2802
+ };
2803
+ if (shouldRevalidateLoader(fetcherMatch, shouldRevalidateArgs)) {
2804
+ fetcherDsMatches = getTargetedDataStrategyMatches(
2805
+ mapRouteProperties2,
2806
+ manifest,
2807
+ fetchRequest,
2808
+ fetcherMatches,
2809
+ fetcherMatch,
2810
+ lazyRoutePropertiesToSkip,
2811
+ scopedContext,
2812
+ shouldRevalidateArgs
2813
+ );
2814
+ }
2743
2815
  }
2744
- if (shouldRevalidate) {
2816
+ if (fetcherDsMatches) {
2745
2817
  revalidatingFetchers.push({
2746
2818
  key,
2747
2819
  routeId: f.routeId,
2748
2820
  path: f.path,
2749
- matches: fetcherMatches,
2821
+ matches: fetcherDsMatches,
2750
2822
  match: fetcherMatch,
2751
- controller: new AbortController()
2823
+ request: fetchRequest,
2824
+ controller: fetchController
2752
2825
  });
2753
2826
  }
2754
2827
  });
2755
- return [navigationMatches, revalidatingFetchers];
2828
+ return { dsMatches, revalidatingFetchers };
2756
2829
  }
2757
2830
  function shouldLoadRouteOnHydration(route, loaderData, errors) {
2758
2831
  if (route.lazy) {
@@ -2898,7 +2971,7 @@ var loadLazyRouteProperty = ({
2898
2971
  return propertyPromise;
2899
2972
  };
2900
2973
  var lazyRouteFunctionCache = /* @__PURE__ */ new WeakMap();
2901
- function loadLazyRoute(route, type, manifest, mapRouteProperties2) {
2974
+ function loadLazyRoute(route, type, manifest, mapRouteProperties2, lazyRoutePropertiesToSkip) {
2902
2975
  let routeToUpdate = manifest[route.id];
2903
2976
  invariant(routeToUpdate, "No route found in manifest");
2904
2977
  if (!route.lazy) {
@@ -2956,6 +3029,8 @@ function loadLazyRoute(route, type, manifest, mapRouteProperties2) {
2956
3029
  });
2957
3030
  })();
2958
3031
  lazyRouteFunctionCache.set(routeToUpdate, lazyRoutePromise2);
3032
+ lazyRoutePromise2.catch(() => {
3033
+ });
2959
3034
  return {
2960
3035
  lazyRoutePromise: lazyRoutePromise2,
2961
3036
  lazyHandlerPromise: lazyRoutePromise2
@@ -2965,6 +3040,9 @@ function loadLazyRoute(route, type, manifest, mapRouteProperties2) {
2965
3040
  let lazyPropertyPromises = [];
2966
3041
  let lazyHandlerPromise = void 0;
2967
3042
  for (let key of lazyKeys) {
3043
+ if (lazyRoutePropertiesToSkip && lazyRoutePropertiesToSkip.includes(key)) {
3044
+ continue;
3045
+ }
2968
3046
  let promise = loadLazyRouteProperty({
2969
3047
  key,
2970
3048
  route,
@@ -2978,30 +3056,17 @@ function loadLazyRoute(route, type, manifest, mapRouteProperties2) {
2978
3056
  }
2979
3057
  }
2980
3058
  }
2981
- let lazyRoutePromise = Promise.all(lazyPropertyPromises).then(() => {
3059
+ let lazyRoutePromise = lazyPropertyPromises.length > 0 ? Promise.all(lazyPropertyPromises).then(() => {
3060
+ }) : void 0;
3061
+ lazyRoutePromise?.catch(() => {
3062
+ });
3063
+ lazyHandlerPromise?.catch(() => {
2982
3064
  });
2983
3065
  return {
2984
3066
  lazyRoutePromise,
2985
3067
  lazyHandlerPromise
2986
3068
  };
2987
3069
  }
2988
- function isNonNullable(value) {
2989
- return value !== void 0;
2990
- }
2991
- function loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties2) {
2992
- let promises = matches.map(({ route }) => {
2993
- if (typeof route.lazy !== "object" || !route.lazy.unstable_middleware) {
2994
- return void 0;
2995
- }
2996
- return loadLazyRouteProperty({
2997
- key: "unstable_middleware",
2998
- route,
2999
- manifest,
3000
- mapRouteProperties: mapRouteProperties2
3001
- });
3002
- }).filter(isNonNullable);
3003
- return promises.length > 0 ? Promise.all(promises) : void 0;
3004
- }
3005
3070
  async function defaultDataStrategy(args) {
3006
3071
  let matchesToLoad = args.matches.filter((m) => m.shouldLoad);
3007
3072
  let keyedResults = {};
@@ -3116,59 +3181,145 @@ async function callRouteMiddleware(args, middlewares, propagateResult, middlewar
3116
3181
  throw error;
3117
3182
  }
3118
3183
  }
3119
- async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, scopedContext) {
3120
- let loadMiddlewarePromise = loadLazyMiddlewareForMatches(
3121
- matches,
3184
+ function getDataStrategyMatchLazyPromises(mapRouteProperties2, manifest, request, match, lazyRoutePropertiesToSkip) {
3185
+ let lazyMiddlewarePromise = loadLazyRouteProperty({
3186
+ key: "unstable_middleware",
3187
+ route: match.route,
3122
3188
  manifest,
3123
- mapRouteProperties2
3189
+ mapRouteProperties: mapRouteProperties2
3190
+ });
3191
+ let lazyRoutePromises = loadLazyRoute(
3192
+ match.route,
3193
+ isMutationMethod(request.method) ? "action" : "loader",
3194
+ manifest,
3195
+ mapRouteProperties2,
3196
+ lazyRoutePropertiesToSkip
3124
3197
  );
3125
- let lazyRoutePromises = matches.map(
3126
- (m) => loadLazyRoute(m.route, type, manifest, mapRouteProperties2)
3198
+ return {
3199
+ middleware: lazyMiddlewarePromise,
3200
+ route: lazyRoutePromises.lazyRoutePromise,
3201
+ handler: lazyRoutePromises.lazyHandlerPromise
3202
+ };
3203
+ }
3204
+ function getDataStrategyMatch(mapRouteProperties2, manifest, request, match, lazyRoutePropertiesToSkip, scopedContext, shouldLoad, unstable_shouldRevalidateArgs = null) {
3205
+ let isUsingNewApi = false;
3206
+ let _lazyPromises = getDataStrategyMatchLazyPromises(
3207
+ mapRouteProperties2,
3208
+ manifest,
3209
+ request,
3210
+ match,
3211
+ lazyRoutePropertiesToSkip
3127
3212
  );
3128
- if (loadMiddlewarePromise) {
3129
- await loadMiddlewarePromise;
3130
- }
3131
- let dsMatches = matches.map((match, i) => {
3132
- let { lazyRoutePromise, lazyHandlerPromise } = lazyRoutePromises[i];
3133
- let shouldLoad = matchesToLoad.some((m) => m.route.id === match.route.id);
3134
- let resolve = async (handlerOverride) => {
3135
- if (handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) {
3136
- shouldLoad = true;
3137
- }
3138
- return shouldLoad ? callLoaderOrAction({
3139
- type,
3140
- request,
3141
- match,
3142
- lazyHandlerPromise,
3143
- lazyRoutePromise,
3144
- handlerOverride,
3145
- scopedContext
3146
- }) : Promise.resolve({ type: "data" /* data */, result: void 0 });
3147
- };
3148
- return {
3149
- ...match,
3150
- shouldLoad,
3151
- resolve
3152
- };
3213
+ return {
3214
+ ...match,
3215
+ _lazyPromises,
3216
+ shouldLoad,
3217
+ unstable_shouldRevalidateArgs,
3218
+ unstable_shouldCallHandler(defaultShouldRevalidate) {
3219
+ isUsingNewApi = true;
3220
+ if (!unstable_shouldRevalidateArgs) {
3221
+ return shouldLoad;
3222
+ }
3223
+ if (typeof defaultShouldRevalidate === "boolean") {
3224
+ return shouldRevalidateLoader(match, {
3225
+ ...unstable_shouldRevalidateArgs,
3226
+ defaultShouldRevalidate
3227
+ });
3228
+ }
3229
+ return shouldRevalidateLoader(match, unstable_shouldRevalidateArgs);
3230
+ },
3231
+ resolve(handlerOverride) {
3232
+ if (isUsingNewApi || shouldLoad || handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) {
3233
+ return callLoaderOrAction({
3234
+ request,
3235
+ match,
3236
+ lazyHandlerPromise: _lazyPromises?.handler,
3237
+ lazyRoutePromise: _lazyPromises?.route,
3238
+ handlerOverride,
3239
+ scopedContext
3240
+ });
3241
+ }
3242
+ return Promise.resolve({ type: "data" /* data */, result: void 0 });
3243
+ }
3244
+ };
3245
+ }
3246
+ function getTargetedDataStrategyMatches(mapRouteProperties2, manifest, request, matches, targetMatch, lazyRoutePropertiesToSkip, scopedContext, shouldRevalidateArgs = null) {
3247
+ return matches.map((match) => {
3248
+ if (match.route.id !== targetMatch.route.id) {
3249
+ return {
3250
+ ...match,
3251
+ shouldLoad: false,
3252
+ unstable_shouldRevalidateArgs: shouldRevalidateArgs,
3253
+ unstable_shouldCallHandler: () => false,
3254
+ _lazyPromises: getDataStrategyMatchLazyPromises(
3255
+ mapRouteProperties2,
3256
+ manifest,
3257
+ request,
3258
+ match,
3259
+ lazyRoutePropertiesToSkip
3260
+ ),
3261
+ resolve: () => Promise.resolve({ type: "data", result: void 0 })
3262
+ };
3263
+ }
3264
+ return getDataStrategyMatch(
3265
+ mapRouteProperties2,
3266
+ manifest,
3267
+ request,
3268
+ match,
3269
+ lazyRoutePropertiesToSkip,
3270
+ scopedContext,
3271
+ true,
3272
+ shouldRevalidateArgs
3273
+ );
3153
3274
  });
3154
- let results = await dataStrategyImpl({
3155
- matches: dsMatches,
3275
+ }
3276
+ async function callDataStrategyImpl(dataStrategyImpl, request, matches, fetcherKey, scopedContext, isStaticHandler) {
3277
+ if (matches.some((m) => m._lazyPromises?.middleware)) {
3278
+ await Promise.all(matches.map((m) => m._lazyPromises?.middleware));
3279
+ }
3280
+ let dataStrategyArgs = {
3156
3281
  request,
3157
3282
  params: matches[0].params,
3283
+ context: scopedContext,
3284
+ matches
3285
+ };
3286
+ let unstable_runClientMiddleware = isStaticHandler ? () => {
3287
+ throw new Error(
3288
+ "You cannot call `unstable_runClientMiddleware()` from a static handler `dataStrategy`. Middleware is run outside of `dataStrategy` during SSR in order to bubble up the Response. You can enable middleware via the `respond` API in `query`/`queryRoute`"
3289
+ );
3290
+ } : (cb) => {
3291
+ let typedDataStrategyArgs = dataStrategyArgs;
3292
+ return runMiddlewarePipeline(
3293
+ typedDataStrategyArgs,
3294
+ false,
3295
+ () => cb({
3296
+ ...typedDataStrategyArgs,
3297
+ fetcherKey,
3298
+ unstable_runClientMiddleware: () => {
3299
+ throw new Error(
3300
+ "Cannot call `unstable_runClientMiddleware()` from within an `unstable_runClientMiddleware` handler"
3301
+ );
3302
+ }
3303
+ }),
3304
+ (error, routeId) => ({
3305
+ [routeId]: { type: "error", result: error }
3306
+ })
3307
+ );
3308
+ };
3309
+ let results = await dataStrategyImpl({
3310
+ ...dataStrategyArgs,
3158
3311
  fetcherKey,
3159
- context: scopedContext
3312
+ unstable_runClientMiddleware
3160
3313
  });
3161
- let allLazyRoutePromises = lazyRoutePromises.flatMap(
3162
- (promiseMap) => Object.values(promiseMap).filter(isNonNullable)
3163
- );
3164
3314
  try {
3165
- await Promise.all(allLazyRoutePromises);
3315
+ await Promise.all(
3316
+ matches.flatMap((m) => [m._lazyPromises?.handler, m._lazyPromises?.route])
3317
+ );
3166
3318
  } catch (e) {
3167
3319
  }
3168
3320
  return results;
3169
3321
  }
3170
3322
  async function callLoaderOrAction({
3171
- type,
3172
3323
  request,
3173
3324
  match,
3174
3325
  lazyHandlerPromise,
@@ -3178,6 +3329,8 @@ async function callLoaderOrAction({
3178
3329
  }) {
3179
3330
  let result;
3180
3331
  let onReject;
3332
+ let isAction = isMutationMethod(request.method);
3333
+ let type = isAction ? "action" : "loader";
3181
3334
  let runHandler = (handler) => {
3182
3335
  let reject;
3183
3336
  let abortPromise = new Promise((_, r) => reject = r);
@@ -3211,7 +3364,7 @@ async function callLoaderOrAction({
3211
3364
  return Promise.race([handlerPromise, abortPromise]);
3212
3365
  };
3213
3366
  try {
3214
- let handler = match.route[type];
3367
+ let handler = isAction ? match.route.action : match.route.loader;
3215
3368
  if (lazyHandlerPromise || lazyRoutePromise) {
3216
3369
  if (handler) {
3217
3370
  let handlerError;
@@ -3232,9 +3385,9 @@ async function callLoaderOrAction({
3232
3385
  result = value;
3233
3386
  } else {
3234
3387
  await lazyHandlerPromise;
3235
- handler = match.route[type];
3236
- if (handler) {
3237
- [result] = await Promise.all([runHandler(handler), lazyRoutePromise]);
3388
+ let handler2 = isAction ? match.route.action : match.route.loader;
3389
+ if (handler2) {
3390
+ [result] = await Promise.all([runHandler(handler2), lazyRoutePromise]);
3238
3391
  } else if (type === "action") {
3239
3392
  let url = new URL(request.url);
3240
3393
  let pathname = url.pathname + url.search;
@@ -3469,7 +3622,7 @@ function processLoaderData(state, matches, results, pendingActionResult, revalid
3469
3622
  results,
3470
3623
  pendingActionResult
3471
3624
  );
3472
- revalidatingFetchers.forEach((rf) => {
3625
+ revalidatingFetchers.filter((f) => !f.matches || f.matches.some((m) => m.shouldLoad)).forEach((rf) => {
3473
3626
  let { key, match, controller } = rf;
3474
3627
  let result = fetcherResults[key];
3475
3628
  invariant(result, "Did not find corresponding fetcher result");
@@ -4258,6 +4411,10 @@ function mapRouteProperties(route) {
4258
4411
  }
4259
4412
  return updates;
4260
4413
  }
4414
+ var hydrationRouteProperties = [
4415
+ "HydrateFallback",
4416
+ "hydrateFallbackElement"
4417
+ ];
4261
4418
  var Deferred = class {
4262
4419
  constructor() {
4263
4420
  this.status = "pending";
@@ -4678,71 +4835,55 @@ async function createRequestInit(request) {
4678
4835
 
4679
4836
  // lib/dom/ssr/single-fetch.tsx
4680
4837
  var SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
4681
- function handleMiddlewareError(error, routeId) {
4682
- return { [routeId]: { type: "error", result: error } };
4838
+ var NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205]);
4839
+ function getSingleFetchDataStrategy(getRouter, getRouteInfo, ssr, basename) {
4840
+ let dataStrategy = getSingleFetchDataStrategyImpl(
4841
+ getRouter,
4842
+ getRouteInfo,
4843
+ fetchAndDecodeViaTurboStream,
4844
+ ssr,
4845
+ basename
4846
+ );
4847
+ return async (args) => args.unstable_runClientMiddleware(dataStrategy);
4683
4848
  }
4684
- function getSingleFetchDataStrategy(manifest, routeModules, ssr, basename, getRouter) {
4849
+ function getSingleFetchDataStrategyImpl(getRouter, getRouteInfo, fetchAndDecode, ssr, basename) {
4685
4850
  return async (args) => {
4686
4851
  let { request, matches, fetcherKey } = args;
4852
+ let router2 = getRouter();
4687
4853
  if (request.method !== "GET") {
4688
- return runMiddlewarePipeline(
4689
- args,
4690
- false,
4691
- () => singleFetchActionStrategy(request, matches, basename),
4692
- handleMiddlewareError
4693
- );
4854
+ return singleFetchActionStrategy(args, fetchAndDecode, basename);
4694
4855
  }
4695
- if (!ssr) {
4696
- let foundRevalidatingServerLoader = matches.some(
4697
- (m) => m.shouldLoad && manifest.routes[m.route.id]?.hasLoader && !manifest.routes[m.route.id]?.hasClientLoader
4698
- );
4699
- if (!foundRevalidatingServerLoader) {
4700
- return runMiddlewarePipeline(
4701
- args,
4702
- false,
4703
- () => nonSsrStrategy(manifest, request, matches, basename),
4704
- handleMiddlewareError
4705
- );
4706
- }
4856
+ let foundRevalidatingServerLoader = matches.some((m) => {
4857
+ let { hasLoader, hasClientLoader } = getRouteInfo(m.route.id);
4858
+ return m.unstable_shouldCallHandler() && hasLoader && !hasClientLoader;
4859
+ });
4860
+ if (!ssr && !foundRevalidatingServerLoader) {
4861
+ return nonSsrStrategy(args, getRouteInfo, fetchAndDecode, basename);
4707
4862
  }
4708
4863
  if (fetcherKey) {
4709
- return runMiddlewarePipeline(
4710
- args,
4711
- false,
4712
- () => singleFetchLoaderFetcherStrategy(request, matches, basename),
4713
- handleMiddlewareError
4714
- );
4864
+ return singleFetchLoaderFetcherStrategy(args, fetchAndDecode, basename);
4715
4865
  }
4716
- return runMiddlewarePipeline(
4866
+ return singleFetchLoaderNavigationStrategy(
4717
4867
  args,
4718
- false,
4719
- () => singleFetchLoaderNavigationStrategy(
4720
- manifest,
4721
- routeModules,
4722
- ssr,
4723
- getRouter(),
4724
- request,
4725
- matches,
4726
- basename
4727
- ),
4728
- handleMiddlewareError
4868
+ router2,
4869
+ getRouteInfo,
4870
+ fetchAndDecode,
4871
+ ssr,
4872
+ basename
4729
4873
  );
4730
4874
  };
4731
4875
  }
4732
- async function singleFetchActionStrategy(request, matches, basename) {
4733
- let actionMatch = matches.find((m) => m.shouldLoad);
4876
+ async function singleFetchActionStrategy(args, fetchAndDecode, basename) {
4877
+ let actionMatch = args.matches.find((m) => m.unstable_shouldCallHandler());
4734
4878
  invariant2(actionMatch, "No action match found");
4735
4879
  let actionStatus = void 0;
4736
4880
  let result = await actionMatch.resolve(async (handler) => {
4737
4881
  let result2 = await handler(async () => {
4738
- let url = singleFetchUrl(request.url, basename);
4739
- let init = await createRequestInit(request);
4740
- let { data: data2, status } = await fetchAndDecode(url, init);
4741
- actionStatus = status;
4742
- return unwrapSingleFetchResult(
4743
- data2,
4882
+ let { data: data2, status } = await fetchAndDecode(args, basename, [
4744
4883
  actionMatch.route.id
4745
- );
4884
+ ]);
4885
+ actionStatus = status;
4886
+ return unwrapSingleFetchResult(data2, actionMatch.route.id);
4746
4887
  });
4747
4888
  return result2;
4748
4889
  });
@@ -4756,16 +4897,21 @@ async function singleFetchActionStrategy(request, matches, basename) {
4756
4897
  }
4757
4898
  };
4758
4899
  }
4759
- async function nonSsrStrategy(manifest, request, matches, basename) {
4760
- let matchesToLoad = matches.filter((m) => m.shouldLoad);
4761
- let url = stripIndexParam(singleFetchUrl(request.url, basename));
4762
- let init = await createRequestInit(request);
4900
+ async function nonSsrStrategy(args, getRouteInfo, fetchAndDecode, basename) {
4901
+ let matchesToLoad = args.matches.filter(
4902
+ (m) => m.unstable_shouldCallHandler()
4903
+ );
4763
4904
  let results = {};
4764
4905
  await Promise.all(
4765
4906
  matchesToLoad.map(
4766
4907
  (m) => m.resolve(async (handler) => {
4767
4908
  try {
4768
- let result = manifest.routes[m.route.id]?.hasClientLoader ? await fetchSingleLoader(handler, url, init, m.route.id) : await handler();
4909
+ let { hasClientLoader } = getRouteInfo(m.route.id);
4910
+ let routeId = m.route.id;
4911
+ let result = hasClientLoader ? await handler(async () => {
4912
+ let { data: data2 } = await fetchAndDecode(args, basename, [routeId]);
4913
+ return unwrapSingleFetchResult(data2, routeId);
4914
+ }) : await handler();
4769
4915
  results[m.route.id] = { type: "data", result };
4770
4916
  } catch (e) {
4771
4917
  results[m.route.id] = { type: "error", result: e };
@@ -4775,81 +4921,63 @@ async function nonSsrStrategy(manifest, request, matches, basename) {
4775
4921
  );
4776
4922
  return results;
4777
4923
  }
4778
- async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr, router2, request, matches, basename) {
4924
+ async function singleFetchLoaderNavigationStrategy(args, router2, getRouteInfo, fetchAndDecode, ssr, basename) {
4779
4925
  let routesParams = /* @__PURE__ */ new Set();
4780
4926
  let foundOptOutRoute = false;
4781
- let routeDfds = matches.map(() => createDeferred2());
4782
- let routesLoadedPromise = Promise.all(routeDfds.map((d) => d.promise));
4927
+ let routeDfds = args.matches.map(() => createDeferred2());
4783
4928
  let singleFetchDfd = createDeferred2();
4784
- let url = stripIndexParam(singleFetchUrl(request.url, basename));
4785
- let init = await createRequestInit(request);
4786
4929
  let results = {};
4787
4930
  let resolvePromise = Promise.all(
4788
- matches.map(
4931
+ args.matches.map(
4789
4932
  async (m, i) => m.resolve(async (handler) => {
4790
4933
  routeDfds[i].resolve();
4791
- let manifestRoute = manifest.routes[m.route.id];
4792
- if (!m.shouldLoad) {
4793
- if (!router2.state.initialized) {
4794
- return;
4795
- }
4796
- if (m.route.id in router2.state.loaderData && manifestRoute && m.route.shouldRevalidate) {
4797
- if (manifestRoute.hasLoader) {
4798
- foundOptOutRoute = true;
4799
- }
4800
- return;
4801
- }
4934
+ let routeId = m.route.id;
4935
+ let { hasLoader, hasClientLoader, hasShouldRevalidate } = getRouteInfo(routeId);
4936
+ let defaultShouldRevalidate = !m.unstable_shouldRevalidateArgs || m.unstable_shouldRevalidateArgs.actionStatus == null || m.unstable_shouldRevalidateArgs.actionStatus < 400;
4937
+ let shouldCall = m.unstable_shouldCallHandler(defaultShouldRevalidate);
4938
+ if (!shouldCall) {
4939
+ foundOptOutRoute || (foundOptOutRoute = m.unstable_shouldRevalidateArgs != null && // This is a revalidation,
4940
+ hasLoader && // for a route with a server loader,
4941
+ hasShouldRevalidate === true);
4942
+ return;
4802
4943
  }
4803
- if (manifestRoute && manifestRoute.hasClientLoader) {
4804
- if (manifestRoute.hasLoader) {
4944
+ if (hasClientLoader) {
4945
+ if (hasLoader) {
4805
4946
  foundOptOutRoute = true;
4806
4947
  }
4807
4948
  try {
4808
- let result = await fetchSingleLoader(
4809
- handler,
4810
- url,
4811
- init,
4812
- m.route.id
4813
- );
4814
- results[m.route.id] = { type: "data", result };
4949
+ let result = await handler(async () => {
4950
+ let { data: data2 } = await fetchAndDecode(args, basename, [routeId]);
4951
+ return unwrapSingleFetchResult(data2, routeId);
4952
+ });
4953
+ results[routeId] = { type: "data", result };
4815
4954
  } catch (e) {
4816
- results[m.route.id] = { type: "error", result: e };
4955
+ results[routeId] = { type: "error", result: e };
4817
4956
  }
4818
4957
  return;
4819
4958
  }
4820
- if (manifestRoute && manifestRoute.hasLoader) {
4821
- routesParams.add(m.route.id);
4959
+ if (hasLoader) {
4960
+ routesParams.add(routeId);
4822
4961
  }
4823
4962
  try {
4824
4963
  let result = await handler(async () => {
4825
4964
  let data2 = await singleFetchDfd.promise;
4826
- return unwrapSingleFetchResults(data2, m.route.id);
4965
+ return unwrapSingleFetchResult(data2, routeId);
4827
4966
  });
4828
- results[m.route.id] = {
4829
- type: "data",
4830
- result
4831
- };
4967
+ results[routeId] = { type: "data", result };
4832
4968
  } catch (e) {
4833
- results[m.route.id] = {
4834
- type: "error",
4835
- result: e
4836
- };
4969
+ results[routeId] = { type: "error", result: e };
4837
4970
  }
4838
4971
  })
4839
4972
  )
4840
4973
  );
4841
- await routesLoadedPromise;
4974
+ await Promise.all(routeDfds.map((d) => d.promise));
4842
4975
  if ((!router2.state.initialized || routesParams.size === 0) && !window.__reactRouterHdrActive) {
4843
4976
  singleFetchDfd.resolve({});
4844
4977
  } else {
4978
+ let targetRoutes = ssr && foundOptOutRoute && routesParams.size > 0 ? [...routesParams.keys()] : void 0;
4845
4979
  try {
4846
- if (ssr && foundOptOutRoute && routesParams.size > 0) {
4847
- url.searchParams.set(
4848
- "_routes",
4849
- matches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
4850
- );
4851
- }
4852
- let data2 = await fetchAndDecode(url, init);
4980
+ let data2 = await fetchAndDecode(args, basename, targetRoutes);
4853
4981
  singleFetchDfd.resolve(data2.data);
4854
4982
  } catch (e) {
4855
4983
  singleFetchDfd.reject(e);
@@ -4858,24 +4986,18 @@ async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr,
4858
4986
  await resolvePromise;
4859
4987
  return results;
4860
4988
  }
4861
- async function singleFetchLoaderFetcherStrategy(request, matches, basename) {
4862
- let fetcherMatch = matches.find((m) => m.shouldLoad);
4989
+ async function singleFetchLoaderFetcherStrategy(args, fetchAndDecode, basename) {
4990
+ let fetcherMatch = args.matches.find((m) => m.unstable_shouldCallHandler());
4863
4991
  invariant2(fetcherMatch, "No fetcher match found");
4864
- let result = await fetcherMatch.resolve(async (handler) => {
4865
- let url = stripIndexParam(singleFetchUrl(request.url, basename));
4866
- let init = await createRequestInit(request);
4867
- return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
4868
- });
4992
+ let routeId = fetcherMatch.route.id;
4993
+ let result = await fetcherMatch.resolve(
4994
+ async (handler) => handler(async () => {
4995
+ let { data: data2 } = await fetchAndDecode(args, basename, [routeId]);
4996
+ return unwrapSingleFetchResult(data2, routeId);
4997
+ })
4998
+ );
4869
4999
  return { [fetcherMatch.route.id]: result };
4870
5000
  }
4871
- function fetchSingleLoader(handler, url, init, routeId) {
4872
- return handler(async () => {
4873
- let singleLoaderUrl = new URL(url);
4874
- singleLoaderUrl.searchParams.set("_routes", routeId);
4875
- let { data: data2 } = await fetchAndDecode(singleLoaderUrl, init);
4876
- return unwrapSingleFetchResults(data2, routeId);
4877
- });
4878
- }
4879
5001
  function stripIndexParam(url) {
4880
5002
  let indexValues = url.searchParams.getAll("index");
4881
5003
  url.searchParams.delete("index");
@@ -4906,23 +5028,51 @@ function singleFetchUrl(reqUrl, basename) {
4906
5028
  }
4907
5029
  return url;
4908
5030
  }
4909
- async function fetchAndDecode(url, init) {
4910
- let res = await fetch(url, init);
5031
+ async function fetchAndDecodeViaTurboStream(args, basename, targetRoutes) {
5032
+ let { request } = args;
5033
+ let url = singleFetchUrl(request.url, basename);
5034
+ if (request.method === "GET") {
5035
+ url = stripIndexParam(url);
5036
+ if (targetRoutes) {
5037
+ url.searchParams.set("_routes", targetRoutes.join(","));
5038
+ }
5039
+ }
5040
+ let res = await fetch(url, await createRequestInit(request));
4911
5041
  if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
4912
5042
  throw new ErrorResponseImpl(404, "Not Found", true);
4913
5043
  }
4914
- const NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205]);
4915
5044
  if (NO_BODY_STATUS_CODES.has(res.status)) {
4916
- if (!init.method || init.method === "GET") {
4917
- return { status: res.status, data: {} };
4918
- } else {
4919
- return { status: res.status, data: { data: void 0 } };
5045
+ let routes = {};
5046
+ if (targetRoutes && request.method !== "GET") {
5047
+ routes[targetRoutes[0]] = { data: void 0 };
4920
5048
  }
5049
+ return {
5050
+ status: res.status,
5051
+ data: { routes }
5052
+ };
4921
5053
  }
4922
5054
  invariant2(res.body, "No response body to decode");
4923
5055
  try {
4924
5056
  let decoded = await decodeViaTurboStream(res.body, window);
4925
- return { status: res.status, data: decoded.value };
5057
+ let data2;
5058
+ if (request.method === "GET") {
5059
+ let typed = decoded.value;
5060
+ if (SingleFetchRedirectSymbol in typed) {
5061
+ data2 = { redirect: typed[SingleFetchRedirectSymbol] };
5062
+ } else {
5063
+ data2 = { routes: typed };
5064
+ }
5065
+ } else {
5066
+ let typed = decoded.value;
5067
+ let routeId = targetRoutes?.[0];
5068
+ invariant2(routeId, "No routeId found for single fetch call decoding");
5069
+ if ("redirect" in typed) {
5070
+ data2 = { redirect: typed };
5071
+ } else {
5072
+ data2 = { routes: { [routeId]: typed } };
5073
+ }
5074
+ }
5075
+ return { status: res.status, data: data2 };
4926
5076
  } catch (e) {
4927
5077
  throw new Error("Unable to decode turbo-stream response");
4928
5078
  }
@@ -4960,30 +5110,30 @@ function decodeViaTurboStream(body, global) {
4960
5110
  ]
4961
5111
  });
4962
5112
  }
4963
- function unwrapSingleFetchResults(results, routeId) {
4964
- let redirect2 = results[SingleFetchRedirectSymbol];
4965
- if (redirect2) {
4966
- return unwrapSingleFetchResult(redirect2, routeId);
4967
- }
4968
- return results[routeId] !== void 0 ? unwrapSingleFetchResult(results[routeId], routeId) : null;
4969
- }
4970
5113
  function unwrapSingleFetchResult(result, routeId) {
4971
- if ("error" in result) {
4972
- throw result.error;
4973
- } else if ("redirect" in result) {
4974
- let headers = {};
4975
- if (result.revalidate) {
4976
- headers["X-Remix-Revalidate"] = "yes";
4977
- }
4978
- if (result.reload) {
4979
- headers["X-Remix-Reload-Document"] = "yes";
4980
- }
4981
- if (result.replace) {
4982
- headers["X-Remix-Replace"] = "yes";
4983
- }
4984
- throw redirect(result.redirect, { status: result.status, headers });
4985
- } else if ("data" in result) {
4986
- return result.data;
5114
+ if ("redirect" in result) {
5115
+ let {
5116
+ redirect: location,
5117
+ revalidate,
5118
+ reload,
5119
+ replace: replace2,
5120
+ status
5121
+ } = result.redirect;
5122
+ throw redirect(location, {
5123
+ status,
5124
+ headers: {
5125
+ // Three R's of redirecting (lol Veep)
5126
+ ...revalidate ? { "X-Remix-Revalidate": "yes" } : null,
5127
+ ...reload ? { "X-Remix-Reload-Document": "yes" } : null,
5128
+ ...replace2 ? { "X-Remix-Replace": "yes" } : null
5129
+ }
5130
+ });
5131
+ }
5132
+ let routeResult = result.routes[routeId];
5133
+ if ("error" in routeResult) {
5134
+ throw routeResult.error;
5135
+ } else if ("data" in routeResult) {
5136
+ return routeResult.data;
4987
5137
  } else {
4988
5138
  throw new Error(`No response found for routeId "${routeId}"`);
4989
5139
  }
@@ -5255,6 +5405,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
5255
5405
  unstable_middleware: routeModule.unstable_clientMiddleware,
5256
5406
  handle: routeModule.handle,
5257
5407
  shouldRevalidate: getShouldRevalidateFunction(
5408
+ dataRoute.path,
5258
5409
  routeModule,
5259
5410
  route,
5260
5411
  ssr,
@@ -5407,6 +5558,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
5407
5558
  shouldRevalidate: async () => {
5408
5559
  let lazyRoute = await getLazyRoute();
5409
5560
  return getShouldRevalidateFunction(
5561
+ dataRoute.path,
5410
5562
  lazyRoute,
5411
5563
  route,
5412
5564
  ssr,
@@ -5434,7 +5586,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
5434
5586
  return dataRoute;
5435
5587
  });
5436
5588
  }
5437
- function getShouldRevalidateFunction(route, manifestRoute, ssr, needsRevalidation) {
5589
+ function getShouldRevalidateFunction(path, route, manifestRoute, ssr, needsRevalidation) {
5438
5590
  if (needsRevalidation) {
5439
5591
  return wrapShouldRevalidateForHdr(
5440
5592
  manifestRoute.id,
@@ -5443,11 +5595,16 @@ function getShouldRevalidateFunction(route, manifestRoute, ssr, needsRevalidatio
5443
5595
  );
5444
5596
  }
5445
5597
  if (!ssr && manifestRoute.hasLoader && !manifestRoute.hasClientLoader) {
5598
+ let myParams = path ? compilePath(path)[1].map((p) => p.paramName) : [];
5599
+ const didParamsChange = (opts) => myParams.some((p) => opts.currentParams[p] !== opts.nextParams[p]);
5446
5600
  if (route.shouldRevalidate) {
5447
5601
  let fn = route.shouldRevalidate;
5448
- return (opts) => fn({ ...opts, defaultShouldRevalidate: false });
5602
+ return (opts) => fn({
5603
+ ...opts,
5604
+ defaultShouldRevalidate: didParamsChange(opts)
5605
+ });
5449
5606
  } else {
5450
- return () => false;
5607
+ return (opts) => didParamsChange(opts);
5451
5608
  }
5452
5609
  }
5453
5610
  if (ssr && route.shouldRevalidate) {
@@ -6018,16 +6175,27 @@ function createHydratedRouter({
6018
6175
  basename: ssrInfo.context.basename,
6019
6176
  unstable_getContext,
6020
6177
  hydrationData,
6178
+ hydrationRouteProperties,
6021
6179
  mapRouteProperties,
6022
6180
  future: {
6023
6181
  unstable_middleware: ssrInfo.context.future.unstable_middleware
6024
6182
  },
6025
6183
  dataStrategy: getSingleFetchDataStrategy(
6026
- ssrInfo.manifest,
6027
- ssrInfo.routeModules,
6184
+ () => router2,
6185
+ (routeId) => {
6186
+ let manifestRoute = ssrInfo.manifest.routes[routeId];
6187
+ invariant(manifestRoute, "Route not found in manifest/routeModules");
6188
+ let routeModule = ssrInfo.routeModules[routeId];
6189
+ return {
6190
+ hasLoader: manifestRoute.hasLoader,
6191
+ hasClientLoader: manifestRoute.hasClientLoader,
6192
+ // In some cases the module may not be loaded yet and we don't care
6193
+ // if it's got shouldRevalidate or not
6194
+ hasShouldRevalidate: routeModule ? routeModule.shouldRevalidate != null : void 0
6195
+ };
6196
+ },
6028
6197
  ssrInfo.context.ssr,
6029
- ssrInfo.context.basename,
6030
- () => router2
6198
+ ssrInfo.context.basename
6031
6199
  ),
6032
6200
  patchRoutesOnNavigation: getPatchRoutesOnNavigationFunction(
6033
6201
  ssrInfo.manifest,