react-router 7.2.0 → 7.3.0-pre.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 +266 -0
  2. package/dist/development/{chunk-HA7DTUK3.mjs → chunk-3XNZT7XE.mjs} +782 -340
  3. package/dist/development/dom-export.d.mts +13 -3
  4. package/dist/development/dom-export.d.ts +13 -3
  5. package/dist/development/dom-export.js +306 -83
  6. package/dist/development/dom-export.mjs +14 -5
  7. package/dist/development/{fog-of-war-Cm1iXIp7.d.ts → fog-of-war-CvttGpNz.d.ts} +93 -9
  8. package/dist/{production/fog-of-war-Cm1iXIp7.d.ts → development/fog-of-war-Da8gpnoZ.d.mts} +93 -9
  9. package/dist/{production/data-CQbyyGzl.d.mts → development/future-ldDp5FKH.d.mts} +11 -1
  10. package/dist/development/{data-CQbyyGzl.d.mts → future-ldDp5FKH.d.ts} +11 -1
  11. package/dist/development/index.d.mts +16 -14
  12. package/dist/development/index.d.ts +16 -14
  13. package/dist/development/index.js +784 -340
  14. package/dist/development/index.mjs +6 -2
  15. package/dist/development/lib/types/route-module.d.mts +25 -6
  16. package/dist/development/lib/types/route-module.d.ts +25 -6
  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/{production/route-data-BmvbmBej.d.mts → development/route-data-H2S3hwhf.d.mts} +66 -13
  20. package/dist/development/{route-data-BmvbmBej.d.mts → route-data-H2S3hwhf.d.ts} +66 -13
  21. package/dist/production/{chunk-Z4EF7MSU.mjs → chunk-ZGBK665M.mjs} +782 -340
  22. package/dist/production/dom-export.d.mts +13 -3
  23. package/dist/production/dom-export.d.ts +13 -3
  24. package/dist/production/dom-export.js +306 -83
  25. package/dist/production/dom-export.mjs +14 -5
  26. package/dist/production/{fog-of-war-BALYJxf_.d.mts → fog-of-war-CvttGpNz.d.ts} +93 -9
  27. package/dist/{development/fog-of-war-BALYJxf_.d.mts → production/fog-of-war-Da8gpnoZ.d.mts} +93 -9
  28. package/dist/{development/data-CQbyyGzl.d.ts → production/future-ldDp5FKH.d.mts} +11 -1
  29. package/dist/production/{data-CQbyyGzl.d.ts → future-ldDp5FKH.d.ts} +11 -1
  30. package/dist/production/index.d.mts +16 -14
  31. package/dist/production/index.d.ts +16 -14
  32. package/dist/production/index.js +784 -340
  33. package/dist/production/index.mjs +6 -2
  34. package/dist/production/lib/types/route-module.d.mts +25 -6
  35. package/dist/production/lib/types/route-module.d.ts +25 -6
  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/{development/route-data-BmvbmBej.d.ts → production/route-data-H2S3hwhf.d.mts} +66 -13
  39. package/dist/production/{route-data-BmvbmBej.d.ts → route-data-H2S3hwhf.d.ts} +66 -13
  40. package/package.json +3 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v7.2.0
2
+ * react-router v7.3.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -15,6 +15,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
15
15
  var __getOwnPropNames = Object.getOwnPropertyNames;
16
16
  var __getProtoOf = Object.getPrototypeOf;
17
17
  var __hasOwnProp = Object.prototype.hasOwnProperty;
18
+ var __typeError = (msg) => {
19
+ throw TypeError(msg);
20
+ };
18
21
  var __export = (target, all) => {
19
22
  for (var name in all)
20
23
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -36,6 +39,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
39
  mod
37
40
  ));
38
41
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
42
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
43
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
44
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
39
45
 
40
46
  // index.ts
41
47
  var react_router_exports = {};
@@ -121,6 +127,8 @@ __export(react_router_exports, {
121
127
  replace: () => replace,
122
128
  resolvePath: () => resolvePath,
123
129
  unstable_HistoryRouter: () => HistoryRouter,
130
+ unstable_RouterContextProvider: () => unstable_RouterContextProvider,
131
+ unstable_createContext: () => unstable_createContext,
124
132
  unstable_setDevServerHooks: () => setDevServerHooks,
125
133
  unstable_usePrompt: () => usePrompt,
126
134
  useActionData: () => useActionData,
@@ -496,6 +504,33 @@ function getUrlBasedHistory(getLocation, createHref2, validateLocation, options
496
504
  }
497
505
 
498
506
  // lib/router/utils.ts
507
+ function unstable_createContext(defaultValue) {
508
+ return { defaultValue };
509
+ }
510
+ var _map;
511
+ var unstable_RouterContextProvider = class {
512
+ constructor(init) {
513
+ __privateAdd(this, _map, /* @__PURE__ */ new Map());
514
+ if (init) {
515
+ for (let [context, value] of init) {
516
+ this.set(context, value);
517
+ }
518
+ }
519
+ }
520
+ get(context) {
521
+ if (__privateGet(this, _map).has(context)) {
522
+ return __privateGet(this, _map).get(context);
523
+ }
524
+ if (context.defaultValue !== void 0) {
525
+ return context.defaultValue;
526
+ }
527
+ throw new Error("No value found for context");
528
+ }
529
+ set(context, value) {
530
+ __privateGet(this, _map).set(context, value);
531
+ }
532
+ };
533
+ _map = new WeakMap();
499
534
  var immutableRouteKeys = /* @__PURE__ */ new Set([
500
535
  "lazy",
501
536
  "caseSensitive",
@@ -1053,9 +1088,9 @@ function createRouter(init) {
1053
1088
  );
1054
1089
  let inFlightDataRoutes;
1055
1090
  let basename = init.basename || "/";
1056
- let dataStrategyImpl = init.dataStrategy || defaultDataStrategy;
1057
- let patchRoutesOnNavigationImpl = init.patchRoutesOnNavigation;
1091
+ let dataStrategyImpl = init.dataStrategy || defaultDataStrategyWithMiddleware;
1058
1092
  let future = {
1093
+ unstable_middleware: false,
1059
1094
  ...init.future
1060
1095
  };
1061
1096
  let unlistenHistory = null;
@@ -1067,7 +1102,7 @@ function createRouter(init) {
1067
1102
  let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
1068
1103
  let initialMatchesIsFOW = false;
1069
1104
  let initialErrors = null;
1070
- if (initialMatches == null && !patchRoutesOnNavigationImpl) {
1105
+ if (initialMatches == null && !init.patchRoutesOnNavigation) {
1071
1106
  let error = getInternalRouterError(404, {
1072
1107
  pathname: init.history.location.pathname
1073
1108
  });
@@ -1498,6 +1533,9 @@ function createRouter(init) {
1498
1533
  pendingNavigationController.signal,
1499
1534
  opts && opts.submission
1500
1535
  );
1536
+ let scopedContext = new unstable_RouterContextProvider(
1537
+ init.unstable_getContext ? await init.unstable_getContext() : void 0
1538
+ );
1501
1539
  let pendingActionResult;
1502
1540
  if (opts && opts.pendingError) {
1503
1541
  pendingActionResult = [
@@ -1510,6 +1548,7 @@ function createRouter(init) {
1510
1548
  location,
1511
1549
  opts.submission,
1512
1550
  matches,
1551
+ scopedContext,
1513
1552
  fogOfWar.active,
1514
1553
  { replace: opts.replace, flushSync }
1515
1554
  );
@@ -1550,6 +1589,7 @@ function createRouter(init) {
1550
1589
  request,
1551
1590
  location,
1552
1591
  matches,
1592
+ scopedContext,
1553
1593
  fogOfWar.active,
1554
1594
  loadingNavigation,
1555
1595
  opts && opts.submission,
@@ -1570,7 +1610,7 @@ function createRouter(init) {
1570
1610
  errors
1571
1611
  });
1572
1612
  }
1573
- async function handleAction(request, location, submission, matches, isFogOfWar, opts = {}) {
1613
+ async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, opts = {}) {
1574
1614
  interruptActiveLoads();
1575
1615
  let navigation = getSubmittingNavigation(location, submission);
1576
1616
  updateState({ navigation }, { flushSync: opts.flushSync === true });
@@ -1626,13 +1666,21 @@ function createRouter(init) {
1626
1666
  } else {
1627
1667
  let results = await callDataStrategy(
1628
1668
  "action",
1629
- state,
1630
1669
  request,
1631
1670
  [actionMatch],
1632
1671
  matches,
1672
+ scopedContext,
1633
1673
  null
1634
1674
  );
1635
1675
  result = results[actionMatch.route.id];
1676
+ if (!result) {
1677
+ for (let match of matches) {
1678
+ if (results[match.route.id]) {
1679
+ result = results[match.route.id];
1680
+ break;
1681
+ }
1682
+ }
1683
+ }
1636
1684
  if (request.signal.aborted) {
1637
1685
  return { shortCircuited: true };
1638
1686
  }
@@ -1670,7 +1718,7 @@ function createRouter(init) {
1670
1718
  pendingActionResult: [actionMatch.route.id, result]
1671
1719
  };
1672
1720
  }
1673
- async function handleLoaders(request, location, matches, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult) {
1721
+ async function handleLoaders(request, location, matches, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult) {
1674
1722
  let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
1675
1723
  let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
1676
1724
  let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration;
@@ -1780,11 +1828,11 @@ function createRouter(init) {
1780
1828
  );
1781
1829
  }
1782
1830
  let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
1783
- state,
1784
1831
  matches,
1785
1832
  matchesToLoad,
1786
1833
  revalidatingFetchers,
1787
- request
1834
+ request,
1835
+ scopedContext
1788
1836
  );
1789
1837
  if (request.signal.aborted) {
1790
1838
  return { shortCircuited: true };
@@ -1892,6 +1940,9 @@ function createRouter(init) {
1892
1940
  return;
1893
1941
  }
1894
1942
  let match = getTargetMatch(matches, path);
1943
+ let scopedContext = new unstable_RouterContextProvider(
1944
+ init.unstable_getContext ? await init.unstable_getContext() : void 0
1945
+ );
1895
1946
  let preventScrollReset = (opts && opts.preventScrollReset) === true;
1896
1947
  if (submission && isMutationMethod(submission.formMethod)) {
1897
1948
  await handleFetcherAction(
@@ -1900,6 +1951,7 @@ function createRouter(init) {
1900
1951
  path,
1901
1952
  match,
1902
1953
  matches,
1954
+ scopedContext,
1903
1955
  fogOfWar.active,
1904
1956
  flushSync,
1905
1957
  preventScrollReset,
@@ -1914,13 +1966,14 @@ function createRouter(init) {
1914
1966
  path,
1915
1967
  match,
1916
1968
  matches,
1969
+ scopedContext,
1917
1970
  fogOfWar.active,
1918
1971
  flushSync,
1919
1972
  preventScrollReset,
1920
1973
  submission
1921
1974
  );
1922
1975
  }
1923
- async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, preventScrollReset, submission) {
1976
+ async function handleFetcherAction(key, routeId, path, match, requestMatches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) {
1924
1977
  interruptActiveLoads();
1925
1978
  fetchLoadMatches.delete(key);
1926
1979
  function detectAndHandle405Error(m) {
@@ -1953,7 +2006,8 @@ function createRouter(init) {
1953
2006
  let discoverResult = await discoverRoutes(
1954
2007
  requestMatches,
1955
2008
  path,
1956
- fetchRequest.signal
2009
+ fetchRequest.signal,
2010
+ key
1957
2011
  );
1958
2012
  if (discoverResult.type === "aborted") {
1959
2013
  return;
@@ -1980,10 +2034,10 @@ function createRouter(init) {
1980
2034
  let originatingLoadId = incrementingLoadId;
1981
2035
  let actionResults = await callDataStrategy(
1982
2036
  "action",
1983
- state,
1984
2037
  fetchRequest,
1985
2038
  [match],
1986
2039
  requestMatches,
2040
+ scopedContext,
1987
2041
  key
1988
2042
  );
1989
2043
  let actionResult = actionResults[match.route.id];
@@ -2067,11 +2121,11 @@ function createRouter(init) {
2067
2121
  abortPendingFetchRevalidations
2068
2122
  );
2069
2123
  let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
2070
- state,
2071
2124
  matches,
2072
2125
  matchesToLoad,
2073
2126
  revalidatingFetchers,
2074
- revalidationRequest
2127
+ revalidationRequest,
2128
+ scopedContext
2075
2129
  );
2076
2130
  if (abortController.signal.aborted) {
2077
2131
  return;
@@ -2138,7 +2192,7 @@ function createRouter(init) {
2138
2192
  isRevalidationRequired = false;
2139
2193
  }
2140
2194
  }
2141
- async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, preventScrollReset, submission) {
2195
+ async function handleFetcherLoader(key, routeId, path, match, matches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) {
2142
2196
  let existingFetcher = state.fetchers.get(key);
2143
2197
  updateFetcherState(
2144
2198
  key,
@@ -2158,7 +2212,8 @@ function createRouter(init) {
2158
2212
  let discoverResult = await discoverRoutes(
2159
2213
  matches,
2160
2214
  path,
2161
- fetchRequest.signal
2215
+ fetchRequest.signal,
2216
+ key
2162
2217
  );
2163
2218
  if (discoverResult.type === "aborted") {
2164
2219
  return;
@@ -2182,10 +2237,10 @@ function createRouter(init) {
2182
2237
  let originatingLoadId = incrementingLoadId;
2183
2238
  let results = await callDataStrategy(
2184
2239
  "loader",
2185
- state,
2186
2240
  fetchRequest,
2187
2241
  [match],
2188
2242
  matches,
2243
+ scopedContext,
2189
2244
  key
2190
2245
  );
2191
2246
  let result = results[match.route.id];
@@ -2287,20 +2342,21 @@ function createRouter(init) {
2287
2342
  });
2288
2343
  }
2289
2344
  }
2290
- async function callDataStrategy(type, state2, request, matchesToLoad, matches, fetcherKey) {
2345
+ async function callDataStrategy(type, request, matchesToLoad, matches, scopedContext, fetcherKey) {
2291
2346
  let results;
2292
2347
  let dataResults = {};
2293
2348
  try {
2294
2349
  results = await callDataStrategyImpl(
2295
2350
  dataStrategyImpl,
2296
2351
  type,
2297
- state2,
2298
2352
  request,
2299
2353
  matchesToLoad,
2300
2354
  matches,
2301
2355
  fetcherKey,
2302
2356
  manifest,
2303
- mapRouteProperties2
2357
+ mapRouteProperties2,
2358
+ scopedContext,
2359
+ future.unstable_middleware
2304
2360
  );
2305
2361
  } catch (e) {
2306
2362
  matchesToLoad.forEach((m) => {
@@ -2332,13 +2388,13 @@ function createRouter(init) {
2332
2388
  }
2333
2389
  return dataResults;
2334
2390
  }
2335
- async function callLoadersAndMaybeResolveData(state2, matches, matchesToLoad, fetchersToLoad, request) {
2391
+ async function callLoadersAndMaybeResolveData(matches, matchesToLoad, fetchersToLoad, request, scopedContext) {
2336
2392
  let loaderResultsPromise = callDataStrategy(
2337
2393
  "loader",
2338
- state2,
2339
2394
  request,
2340
2395
  matchesToLoad,
2341
2396
  matches,
2397
+ scopedContext,
2342
2398
  null
2343
2399
  );
2344
2400
  let fetcherResultsPromise = Promise.all(
@@ -2346,10 +2402,10 @@ function createRouter(init) {
2346
2402
  if (f.matches && f.match && f.controller) {
2347
2403
  let results = await callDataStrategy(
2348
2404
  "loader",
2349
- state2,
2350
2405
  createClientSideRequest(init.history, f.path, f.controller.signal),
2351
2406
  [f.match],
2352
2407
  f.matches,
2408
+ scopedContext,
2353
2409
  f.key
2354
2410
  );
2355
2411
  let result = results[f.match.route.id];
@@ -2571,7 +2627,7 @@ function createRouter(init) {
2571
2627
  return null;
2572
2628
  }
2573
2629
  function checkFogOfWar(matches, routesToUse, pathname) {
2574
- if (patchRoutesOnNavigationImpl) {
2630
+ if (init.patchRoutesOnNavigation) {
2575
2631
  if (!matches) {
2576
2632
  let fogMatches = matchRoutesImpl(
2577
2633
  routesToUse,
@@ -2594,8 +2650,8 @@ function createRouter(init) {
2594
2650
  }
2595
2651
  return { active: false, matches: null };
2596
2652
  }
2597
- async function discoverRoutes(matches, pathname, signal) {
2598
- if (!patchRoutesOnNavigationImpl) {
2653
+ async function discoverRoutes(matches, pathname, signal, fetcherKey) {
2654
+ if (!init.patchRoutesOnNavigation) {
2599
2655
  return { type: "success", matches };
2600
2656
  }
2601
2657
  let partialMatches = matches;
@@ -2604,10 +2660,11 @@ function createRouter(init) {
2604
2660
  let routesToUse = inFlightDataRoutes || dataRoutes;
2605
2661
  let localManifest = manifest;
2606
2662
  try {
2607
- await patchRoutesOnNavigationImpl({
2663
+ await init.patchRoutesOnNavigation({
2608
2664
  signal,
2609
2665
  path: pathname,
2610
2666
  matches: partialMatches,
2667
+ fetcherKey,
2611
2668
  patch: (routeId, children) => {
2612
2669
  if (signal.aborted) return;
2613
2670
  patchRoutesImpl(
@@ -2726,17 +2783,21 @@ function createStaticHandler(routes, opts) {
2726
2783
  );
2727
2784
  async function query(request, {
2728
2785
  requestContext,
2786
+ filterMatchesToLoad,
2729
2787
  skipLoaderErrorBubbling,
2730
- dataStrategy
2788
+ skipRevalidation,
2789
+ dataStrategy,
2790
+ unstable_respond: respond
2731
2791
  } = {}) {
2732
2792
  let url = new URL(request.url);
2733
2793
  let method = request.method;
2734
2794
  let location = createLocation("", createPath(url), null, "default");
2735
2795
  let matches = matchRoutes(dataRoutes, location, basename);
2796
+ requestContext = requestContext != null ? requestContext : new unstable_RouterContextProvider();
2736
2797
  if (!isValidMethod(method) && method !== "HEAD") {
2737
2798
  let error = getInternalRouterError(405, { method });
2738
2799
  let { matches: methodNotAllowedMatches, route } = getShortCircuitMatches(dataRoutes);
2739
- return {
2800
+ let staticContext = {
2740
2801
  basename,
2741
2802
  location,
2742
2803
  matches: methodNotAllowedMatches,
@@ -2749,10 +2810,11 @@ function createStaticHandler(routes, opts) {
2749
2810
  loaderHeaders: {},
2750
2811
  actionHeaders: {}
2751
2812
  };
2813
+ return respond ? respond(staticContext) : staticContext;
2752
2814
  } else if (!matches) {
2753
2815
  let error = getInternalRouterError(404, { pathname: location.pathname });
2754
2816
  let { matches: notFoundMatches, route } = getShortCircuitMatches(dataRoutes);
2755
- return {
2817
+ let staticContext = {
2756
2818
  basename,
2757
2819
  location,
2758
2820
  matches: notFoundMatches,
@@ -2765,6 +2827,87 @@ function createStaticHandler(routes, opts) {
2765
2827
  loaderHeaders: {},
2766
2828
  actionHeaders: {}
2767
2829
  };
2830
+ return respond ? respond(staticContext) : staticContext;
2831
+ }
2832
+ if (respond && matches.some((m) => m.route.unstable_middleware)) {
2833
+ invariant(
2834
+ requestContext instanceof unstable_RouterContextProvider,
2835
+ "When using middleware in `staticHandler.query()`, any provided `requestContext` must bean instance of `unstable_RouterContextProvider`"
2836
+ );
2837
+ try {
2838
+ let renderedStaticContext;
2839
+ let response = await runMiddlewarePipeline(
2840
+ {
2841
+ request,
2842
+ matches,
2843
+ params: matches[0].params,
2844
+ // If we're calling middleware then it must be enabled so we can cast
2845
+ // this to the proper type knowing it's not an `AppLoadContext`
2846
+ context: requestContext
2847
+ },
2848
+ true,
2849
+ async () => {
2850
+ let result2 = await queryImpl(
2851
+ request,
2852
+ location,
2853
+ matches,
2854
+ requestContext,
2855
+ dataStrategy || null,
2856
+ skipLoaderErrorBubbling === true,
2857
+ null,
2858
+ filterMatchesToLoad || null,
2859
+ skipRevalidation === true
2860
+ );
2861
+ if (isResponse(result2)) {
2862
+ return result2;
2863
+ }
2864
+ renderedStaticContext = { location, basename, ...result2 };
2865
+ let res = await respond(renderedStaticContext);
2866
+ return res;
2867
+ },
2868
+ async (e) => {
2869
+ if (isResponse(e.error)) {
2870
+ return e.error;
2871
+ }
2872
+ if (renderedStaticContext) {
2873
+ if (e.routeId in renderedStaticContext.loaderData) {
2874
+ renderedStaticContext.loaderData[e.routeId] = void 0;
2875
+ }
2876
+ return respond(
2877
+ getStaticContextFromError(
2878
+ dataRoutes,
2879
+ renderedStaticContext,
2880
+ e.error,
2881
+ findNearestBoundary(matches, e.routeId).route.id
2882
+ )
2883
+ );
2884
+ } else {
2885
+ let loaderIdx = matches.findIndex((m) => m.route.loader);
2886
+ let boundary = loaderIdx >= 0 ? findNearestBoundary(matches, matches[loaderIdx].route.id) : findNearestBoundary(matches);
2887
+ return respond({
2888
+ matches,
2889
+ location,
2890
+ basename,
2891
+ loaderData: {},
2892
+ actionData: null,
2893
+ errors: {
2894
+ [boundary.route.id]: e.error
2895
+ },
2896
+ statusCode: isRouteErrorResponse(e.error) ? e.error.status : 500,
2897
+ actionHeaders: {},
2898
+ loaderHeaders: {}
2899
+ });
2900
+ }
2901
+ }
2902
+ );
2903
+ invariant(isResponse(response), "Expected a response in query()");
2904
+ return response;
2905
+ } catch (e) {
2906
+ if (isResponse(e)) {
2907
+ return e;
2908
+ }
2909
+ throw e;
2910
+ }
2768
2911
  }
2769
2912
  let result = await queryImpl(
2770
2913
  request,
@@ -2773,7 +2916,9 @@ function createStaticHandler(routes, opts) {
2773
2916
  requestContext,
2774
2917
  dataStrategy || null,
2775
2918
  skipLoaderErrorBubbling === true,
2776
- null
2919
+ null,
2920
+ filterMatchesToLoad || null,
2921
+ skipRevalidation === true
2777
2922
  );
2778
2923
  if (isResponse(result)) {
2779
2924
  return result;
@@ -2783,12 +2928,14 @@ function createStaticHandler(routes, opts) {
2783
2928
  async function queryRoute(request, {
2784
2929
  routeId,
2785
2930
  requestContext,
2786
- dataStrategy
2931
+ dataStrategy,
2932
+ unstable_respond: respond
2787
2933
  } = {}) {
2788
2934
  let url = new URL(request.url);
2789
2935
  let method = request.method;
2790
2936
  let location = createLocation("", createPath(url), null, "default");
2791
2937
  let matches = matchRoutes(dataRoutes, location, basename);
2938
+ requestContext = requestContext != null ? requestContext : new unstable_RouterContextProvider();
2792
2939
  if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") {
2793
2940
  throw getInternalRouterError(405, { method });
2794
2941
  } else if (!matches) {
@@ -2803,6 +2950,55 @@ function createStaticHandler(routes, opts) {
2803
2950
  } else if (!match) {
2804
2951
  throw getInternalRouterError(404, { pathname: location.pathname });
2805
2952
  }
2953
+ if (respond && matches.some((m) => m.route.unstable_middleware)) {
2954
+ invariant(
2955
+ requestContext instanceof unstable_RouterContextProvider,
2956
+ "When using middleware in `staticHandler.queryRoute()`, any provided `requestContext` must bean instance of `unstable_RouterContextProvider`"
2957
+ );
2958
+ let response = await runMiddlewarePipeline(
2959
+ {
2960
+ request,
2961
+ matches,
2962
+ params: matches[0].params,
2963
+ // If we're calling middleware then it must be enabled so we can cast
2964
+ // this to the proper type knowing it's not an `AppLoadContext`
2965
+ context: requestContext
2966
+ },
2967
+ true,
2968
+ async () => {
2969
+ let result2 = await queryImpl(
2970
+ request,
2971
+ location,
2972
+ matches,
2973
+ requestContext,
2974
+ dataStrategy || null,
2975
+ false,
2976
+ match,
2977
+ null,
2978
+ false
2979
+ );
2980
+ if (isResponse(result2)) {
2981
+ return respond(result2);
2982
+ }
2983
+ let error2 = result2.errors ? Object.values(result2.errors)[0] : void 0;
2984
+ if (error2 !== void 0) {
2985
+ throw error2;
2986
+ }
2987
+ let value = result2.actionData ? Object.values(result2.actionData)[0] : Object.values(result2.loaderData)[0];
2988
+ return typeof value === "string" ? new Response(value) : Response.json(value);
2989
+ },
2990
+ (e) => {
2991
+ if (isResponse(e.error)) {
2992
+ return respond(e.error);
2993
+ }
2994
+ return new Response(String(e.error), {
2995
+ status: 500,
2996
+ statusText: "Unexpected Server Error"
2997
+ });
2998
+ }
2999
+ );
3000
+ return response;
3001
+ }
2806
3002
  let result = await queryImpl(
2807
3003
  request,
2808
3004
  location,
@@ -2810,7 +3006,9 @@ function createStaticHandler(routes, opts) {
2810
3006
  requestContext,
2811
3007
  dataStrategy || null,
2812
3008
  false,
2813
- match
3009
+ match,
3010
+ null,
3011
+ false
2814
3012
  );
2815
3013
  if (isResponse(result)) {
2816
3014
  return result;
@@ -2827,7 +3025,7 @@ function createStaticHandler(routes, opts) {
2827
3025
  }
2828
3026
  return void 0;
2829
3027
  }
2830
- async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch) {
3028
+ async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, skipRevalidation) {
2831
3029
  invariant(
2832
3030
  request.signal,
2833
3031
  "query()/queryRoute() requests must contain an AbortController signal"
@@ -2841,7 +3039,9 @@ function createStaticHandler(routes, opts) {
2841
3039
  requestContext,
2842
3040
  dataStrategy,
2843
3041
  skipLoaderErrorBubbling,
2844
- routeMatch != null
3042
+ routeMatch != null,
3043
+ filterMatchesToLoad,
3044
+ skipRevalidation
2845
3045
  );
2846
3046
  return result2;
2847
3047
  }
@@ -2851,7 +3051,8 @@ function createStaticHandler(routes, opts) {
2851
3051
  requestContext,
2852
3052
  dataStrategy,
2853
3053
  skipLoaderErrorBubbling,
2854
- routeMatch
3054
+ routeMatch,
3055
+ filterMatchesToLoad
2855
3056
  );
2856
3057
  return isResponse(result) ? result : {
2857
3058
  ...result,
@@ -2871,7 +3072,7 @@ function createStaticHandler(routes, opts) {
2871
3072
  throw e;
2872
3073
  }
2873
3074
  }
2874
- async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest) {
3075
+ async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest, filterMatchesToLoad, skipRevalidation) {
2875
3076
  let result;
2876
3077
  if (!actionMatch.route.action && !actionMatch.route.lazy) {
2877
3078
  let error = getInternalRouterError(405, {
@@ -2925,6 +3126,36 @@ function createStaticHandler(routes, opts) {
2925
3126
  actionHeaders: {}
2926
3127
  };
2927
3128
  }
3129
+ if (skipRevalidation) {
3130
+ if (isErrorResult(result)) {
3131
+ let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
3132
+ return {
3133
+ statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
3134
+ actionData: null,
3135
+ actionHeaders: {
3136
+ ...result.headers ? { [actionMatch.route.id]: result.headers } : {}
3137
+ },
3138
+ matches,
3139
+ loaderData: {},
3140
+ errors: {
3141
+ [boundaryMatch.route.id]: result.error
3142
+ },
3143
+ loaderHeaders: {}
3144
+ };
3145
+ } else {
3146
+ return {
3147
+ actionData: {
3148
+ [actionMatch.route.id]: result.data
3149
+ },
3150
+ actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {},
3151
+ matches,
3152
+ loaderData: {},
3153
+ errors: null,
3154
+ statusCode: result.statusCode || 200,
3155
+ loaderHeaders: {}
3156
+ };
3157
+ }
3158
+ }
2928
3159
  let loaderRequest = new Request(request.url, {
2929
3160
  headers: request.headers,
2930
3161
  redirect: request.redirect,
@@ -2932,17 +3163,18 @@ function createStaticHandler(routes, opts) {
2932
3163
  });
2933
3164
  if (isErrorResult(result)) {
2934
3165
  let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
2935
- let context2 = await loadRouteData(
3166
+ let handlerContext2 = await loadRouteData(
2936
3167
  loaderRequest,
2937
3168
  matches,
2938
3169
  requestContext,
2939
3170
  dataStrategy,
2940
3171
  skipLoaderErrorBubbling,
2941
3172
  null,
3173
+ filterMatchesToLoad,
2942
3174
  [boundaryMatch.route.id, result]
2943
3175
  );
2944
3176
  return {
2945
- ...context2,
3177
+ ...handlerContext2,
2946
3178
  statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,
2947
3179
  actionData: null,
2948
3180
  actionHeaders: {
@@ -2950,16 +3182,17 @@ function createStaticHandler(routes, opts) {
2950
3182
  }
2951
3183
  };
2952
3184
  }
2953
- let context = await loadRouteData(
3185
+ let handlerContext = await loadRouteData(
2954
3186
  loaderRequest,
2955
3187
  matches,
2956
3188
  requestContext,
2957
3189
  dataStrategy,
2958
3190
  skipLoaderErrorBubbling,
2959
- null
3191
+ null,
3192
+ filterMatchesToLoad
2960
3193
  );
2961
3194
  return {
2962
- ...context,
3195
+ ...handlerContext,
2963
3196
  actionData: {
2964
3197
  [actionMatch.route.id]: result.data
2965
3198
  },
@@ -2968,7 +3201,7 @@ function createStaticHandler(routes, opts) {
2968
3201
  actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {}
2969
3202
  };
2970
3203
  }
2971
- async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, pendingActionResult) {
3204
+ async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, pendingActionResult) {
2972
3205
  let isRouteRequest = routeMatch != null;
2973
3206
  if (isRouteRequest && !routeMatch?.route.loader && !routeMatch?.route.lazy) {
2974
3207
  throw getInternalRouterError(400, {
@@ -2979,7 +3212,7 @@ function createStaticHandler(routes, opts) {
2979
3212
  }
2980
3213
  let requestMatches = routeMatch ? [routeMatch] : pendingActionResult && isErrorResult(pendingActionResult[1]) ? getLoaderMatchesUntilBoundary(matches, pendingActionResult[0]) : matches;
2981
3214
  let matchesToLoad = requestMatches.filter(
2982
- (m) => m.route.loader || m.route.lazy
3215
+ (m) => (m.route.loader || m.route.lazy) && (!filterMatchesToLoad || filterMatchesToLoad(m))
2983
3216
  );
2984
3217
  if (matchesToLoad.length === 0) {
2985
3218
  return {
@@ -3008,7 +3241,7 @@ function createStaticHandler(routes, opts) {
3008
3241
  if (request.signal.aborted) {
3009
3242
  throwStaticHandlerAbortedError(request, isRouteRequest);
3010
3243
  }
3011
- let context = processRouteLoaderData(
3244
+ let handlerContext = processRouteLoaderData(
3012
3245
  matches,
3013
3246
  results,
3014
3247
  pendingActionResult,
@@ -3020,11 +3253,11 @@ function createStaticHandler(routes, opts) {
3020
3253
  );
3021
3254
  matches.forEach((match) => {
3022
3255
  if (!executedLoaders.has(match.route.id)) {
3023
- context.loaderData[match.route.id] = null;
3256
+ handlerContext.loaderData[match.route.id] = null;
3024
3257
  }
3025
3258
  });
3026
3259
  return {
3027
- ...context,
3260
+ ...handlerContext,
3028
3261
  matches
3029
3262
  };
3030
3263
  }
@@ -3032,14 +3265,15 @@ function createStaticHandler(routes, opts) {
3032
3265
  let results = await callDataStrategyImpl(
3033
3266
  dataStrategy || defaultDataStrategy,
3034
3267
  type,
3035
- null,
3036
3268
  request,
3037
3269
  matchesToLoad,
3038
3270
  matches,
3039
3271
  null,
3040
3272
  manifest,
3041
3273
  mapRouteProperties2,
3042
- requestContext
3274
+ requestContext,
3275
+ false
3276
+ // middleware not done via dataStrategy in the static handler
3043
3277
  );
3044
3278
  let dataResults = {};
3045
3279
  await Promise.all(
@@ -3072,15 +3306,15 @@ function createStaticHandler(routes, opts) {
3072
3306
  queryRoute
3073
3307
  };
3074
3308
  }
3075
- function getStaticContextFromError(routes, context, error) {
3076
- let newContext = {
3077
- ...context,
3309
+ function getStaticContextFromError(routes, handlerContext, error, boundaryId) {
3310
+ let errorBoundaryId = boundaryId || handlerContext._deepestRenderedBoundaryId || routes[0].id;
3311
+ return {
3312
+ ...handlerContext,
3078
3313
  statusCode: isRouteErrorResponse(error) ? error.status : 500,
3079
3314
  errors: {
3080
- [context._deepestRenderedBoundaryId || routes[0].id]: error
3315
+ [errorBoundaryId]: error
3081
3316
  }
3082
3317
  };
3083
- return newContext;
3084
3318
  }
3085
3319
  function throwStaticHandlerAbortedError(request, isRouteRequest) {
3086
3320
  if (request.signal.reason !== void 0) {
@@ -3473,20 +3707,127 @@ async function loadLazyRouteModule(route, mapRouteProperties2, manifest) {
3473
3707
  lazy: void 0
3474
3708
  });
3475
3709
  }
3476
- async function defaultDataStrategy({
3477
- matches
3478
- }) {
3479
- let matchesToLoad = matches.filter((m) => m.shouldLoad);
3710
+ async function defaultDataStrategy(args) {
3711
+ let matchesToLoad = args.matches.filter((m) => m.shouldLoad);
3712
+ let keyedResults = {};
3480
3713
  let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
3481
- return results.reduce(
3482
- (acc, result, i) => Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
3483
- {}
3714
+ results.forEach((result, i) => {
3715
+ keyedResults[matchesToLoad[i].route.id] = result;
3716
+ });
3717
+ return keyedResults;
3718
+ }
3719
+ async function defaultDataStrategyWithMiddleware(args) {
3720
+ if (!args.matches.some((m) => m.route.unstable_middleware)) {
3721
+ return defaultDataStrategy(args);
3722
+ }
3723
+ return runMiddlewarePipeline(
3724
+ args,
3725
+ false,
3726
+ () => defaultDataStrategy(args),
3727
+ (e) => ({ [e.routeId]: { type: "error", result: e.error } })
3484
3728
  );
3485
3729
  }
3486
- async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, requestContext) {
3730
+ async function runMiddlewarePipeline(args, propagateResult, handler, errorHandler) {
3731
+ let { matches, request, params, context } = args;
3732
+ let middlewareState = {
3733
+ handlerResult: void 0,
3734
+ propagateResult
3735
+ };
3736
+ try {
3737
+ let tuples = matches.flatMap(
3738
+ (m) => m.route.unstable_middleware ? m.route.unstable_middleware.map((fn) => [m.route.id, fn]) : []
3739
+ );
3740
+ let result = await callRouteMiddleware(
3741
+ { request, params, context },
3742
+ tuples,
3743
+ middlewareState,
3744
+ handler
3745
+ );
3746
+ return middlewareState.propagateResult ? result : middlewareState.handlerResult;
3747
+ } catch (e) {
3748
+ if (!(e instanceof MiddlewareError)) {
3749
+ throw e;
3750
+ }
3751
+ let result = await errorHandler(e);
3752
+ if (propagateResult || !middlewareState.handlerResult) {
3753
+ return result;
3754
+ }
3755
+ return Object.assign(middlewareState.handlerResult, result);
3756
+ }
3757
+ }
3758
+ var MiddlewareError = class {
3759
+ constructor(routeId, error) {
3760
+ this.routeId = routeId;
3761
+ this.error = error;
3762
+ }
3763
+ };
3764
+ async function callRouteMiddleware(args, middlewares, middlewareState, handler, idx = 0) {
3765
+ let { request } = args;
3766
+ if (request.signal.aborted) {
3767
+ if (request.signal.reason) {
3768
+ throw request.signal.reason;
3769
+ }
3770
+ throw new Error(
3771
+ `Request aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`
3772
+ );
3773
+ }
3774
+ let tuple = middlewares[idx];
3775
+ if (!tuple) {
3776
+ middlewareState.handlerResult = await handler();
3777
+ return middlewareState.handlerResult;
3778
+ }
3779
+ let [routeId, middleware] = tuple;
3780
+ let nextCalled = false;
3781
+ let nextResult = void 0;
3782
+ let next = async () => {
3783
+ if (nextCalled) {
3784
+ throw new Error("You may only call `next()` once per middleware");
3785
+ }
3786
+ nextCalled = true;
3787
+ let result = await callRouteMiddleware(
3788
+ args,
3789
+ middlewares,
3790
+ middlewareState,
3791
+ handler,
3792
+ idx + 1
3793
+ );
3794
+ if (middlewareState.propagateResult) {
3795
+ nextResult = result;
3796
+ return nextResult;
3797
+ }
3798
+ };
3799
+ try {
3800
+ let result = await middleware(
3801
+ {
3802
+ request: args.request,
3803
+ params: args.params,
3804
+ context: args.context
3805
+ },
3806
+ next
3807
+ );
3808
+ if (nextCalled) {
3809
+ if (result === void 0) {
3810
+ return nextResult;
3811
+ } else {
3812
+ return result;
3813
+ }
3814
+ } else {
3815
+ return next();
3816
+ }
3817
+ } catch (e) {
3818
+ if (e instanceof MiddlewareError) {
3819
+ throw e;
3820
+ }
3821
+ throw new MiddlewareError(routeId, e);
3822
+ }
3823
+ }
3824
+ async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, scopedContext, enableMiddleware) {
3487
3825
  let loadRouteDefinitionsPromises = matches.map(
3488
3826
  (m) => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties2, manifest) : void 0
3489
3827
  );
3828
+ if (enableMiddleware) {
3829
+ await Promise.all(loadRouteDefinitionsPromises);
3830
+ }
3490
3831
  let dsMatches = matches.map((match, i) => {
3491
3832
  let loadRoutePromise = loadRouteDefinitionsPromises[i];
3492
3833
  let shouldLoad = matchesToLoad.some((m) => m.route.id === match.route.id);
@@ -3500,7 +3841,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matc
3500
3841
  match,
3501
3842
  loadRoutePromise,
3502
3843
  handlerOverride,
3503
- requestContext
3844
+ scopedContext
3504
3845
  ) : Promise.resolve({ type: "data" /* data */, result: void 0 });
3505
3846
  };
3506
3847
  return {
@@ -3514,7 +3855,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matc
3514
3855
  request,
3515
3856
  params: matches[0].params,
3516
3857
  fetcherKey,
3517
- context: requestContext
3858
+ context: scopedContext
3518
3859
  });
3519
3860
  try {
3520
3861
  await Promise.all(loadRouteDefinitionsPromises);
@@ -3522,7 +3863,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matc
3522
3863
  }
3523
3864
  return results;
3524
3865
  }
3525
- async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, staticContext) {
3866
+ async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, scopedContext) {
3526
3867
  let result;
3527
3868
  let onReject;
3528
3869
  let runHandler = (handler) => {
@@ -3542,7 +3883,7 @@ async function callLoaderOrAction(type, request, match, loadRoutePromise, handle
3542
3883
  {
3543
3884
  request,
3544
3885
  params: match.params,
3545
- context: staticContext
3886
+ context: scopedContext
3546
3887
  },
3547
3888
  ...ctx !== void 0 ? [ctx] : []
3548
3889
  );
@@ -4855,6 +5196,7 @@ function mapRouteProperties(route) {
4855
5196
  function createMemoryRouter(routes, opts) {
4856
5197
  return createRouter({
4857
5198
  basename: opts?.basename,
5199
+ unstable_getContext: opts?.unstable_getContext,
4858
5200
  future: opts?.future,
4859
5201
  history: createMemoryHistory({
4860
5202
  initialEntries: opts?.initialEntries,
@@ -5810,55 +6152,61 @@ function StreamTransfer({
5810
6152
  )));
5811
6153
  }
5812
6154
  }
5813
- function getSingleFetchDataStrategy(manifest, routeModules, ssr, getRouter) {
5814
- return async ({ request, matches, fetcherKey }) => {
6155
+ function getSingleFetchDataStrategy(manifest, routeModules, ssr, basename, getRouter) {
6156
+ return async (args) => {
6157
+ let { request, matches, fetcherKey } = args;
5815
6158
  if (request.method !== "GET") {
5816
- return singleFetchActionStrategy(request, matches);
6159
+ return runMiddlewarePipeline(
6160
+ args,
6161
+ false,
6162
+ () => singleFetchActionStrategy(request, matches, basename),
6163
+ (e) => ({ [e.routeId]: { type: "error", result: e.error } })
6164
+ );
5817
6165
  }
5818
6166
  if (!ssr) {
5819
6167
  let foundRevalidatingServerLoader = matches.some(
5820
6168
  (m) => m.shouldLoad && manifest.routes[m.route.id]?.hasLoader && !manifest.routes[m.route.id]?.hasClientLoader
5821
6169
  );
5822
6170
  if (!foundRevalidatingServerLoader) {
5823
- let matchesToLoad = matches.filter((m) => m.shouldLoad);
5824
- let url = stripIndexParam(singleFetchUrl(request.url));
5825
- let init = await createRequestInit(request);
5826
- let results = {};
5827
- await Promise.all(
5828
- matchesToLoad.map(
5829
- (m) => m.resolve(async (handler) => {
5830
- try {
5831
- let result = manifest.routes[m.route.id]?.hasClientLoader ? await fetchSingleLoader(handler, url, init, m.route.id) : await handler();
5832
- results[m.route.id] = { type: "data", result };
5833
- } catch (e) {
5834
- results[m.route.id] = { type: "error", result: e };
5835
- }
5836
- })
5837
- )
6171
+ return runMiddlewarePipeline(
6172
+ args,
6173
+ false,
6174
+ () => nonSsrStrategy(manifest, request, matches, basename),
6175
+ (e) => ({ [e.routeId]: { type: "error", result: e.error } })
5838
6176
  );
5839
- return results;
5840
6177
  }
5841
6178
  }
5842
6179
  if (fetcherKey) {
5843
- return singleFetchLoaderFetcherStrategy(request, matches);
6180
+ return runMiddlewarePipeline(
6181
+ args,
6182
+ false,
6183
+ () => singleFetchLoaderFetcherStrategy(request, matches, basename),
6184
+ (e) => ({ [e.routeId]: { type: "error", result: e.error } })
6185
+ );
5844
6186
  }
5845
- return singleFetchLoaderNavigationStrategy(
5846
- manifest,
5847
- routeModules,
5848
- ssr,
5849
- getRouter(),
5850
- request,
5851
- matches
6187
+ return runMiddlewarePipeline(
6188
+ args,
6189
+ false,
6190
+ () => singleFetchLoaderNavigationStrategy(
6191
+ manifest,
6192
+ routeModules,
6193
+ ssr,
6194
+ getRouter(),
6195
+ request,
6196
+ matches,
6197
+ basename
6198
+ ),
6199
+ (e) => ({ [e.routeId]: { type: "error", result: e.error } })
5852
6200
  );
5853
6201
  };
5854
6202
  }
5855
- async function singleFetchActionStrategy(request, matches) {
6203
+ async function singleFetchActionStrategy(request, matches, basename) {
5856
6204
  let actionMatch = matches.find((m) => m.shouldLoad);
5857
6205
  invariant2(actionMatch, "No action match found");
5858
6206
  let actionStatus = void 0;
5859
6207
  let result = await actionMatch.resolve(async (handler) => {
5860
6208
  let result2 = await handler(async () => {
5861
- let url = singleFetchUrl(request.url);
6209
+ let url = singleFetchUrl(request.url, basename);
5862
6210
  let init = await createRequestInit(request);
5863
6211
  let { data: data2, status } = await fetchAndDecode(url, init);
5864
6212
  actionStatus = status;
@@ -5879,13 +6227,35 @@ async function singleFetchActionStrategy(request, matches) {
5879
6227
  }
5880
6228
  };
5881
6229
  }
5882
- async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr, router, request, matches) {
6230
+ async function nonSsrStrategy(manifest, request, matches, basename) {
6231
+ let matchesToLoad = matches.filter((m) => m.shouldLoad);
6232
+ let url = stripIndexParam(singleFetchUrl(request.url, basename));
6233
+ let init = await createRequestInit(request);
6234
+ let results = {};
6235
+ await Promise.all(
6236
+ matchesToLoad.map(
6237
+ (m) => m.resolve(async (handler) => {
6238
+ try {
6239
+ let result = manifest.routes[m.route.id]?.hasClientLoader ? await fetchSingleLoader(handler, url, init, m.route.id) : await handler();
6240
+ results[m.route.id] = { type: "data", result };
6241
+ } catch (e) {
6242
+ results[m.route.id] = { type: "error", result: e };
6243
+ }
6244
+ })
6245
+ )
6246
+ );
6247
+ return results;
6248
+ }
6249
+ function isOptedOut(manifestRoute, routeModule, match, router) {
6250
+ return match.route.id in router.state.loaderData && manifestRoute && manifestRoute.hasLoader && routeModule && routeModule.shouldRevalidate;
6251
+ }
6252
+ async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr, router, request, matches, basename) {
5883
6253
  let routesParams = /* @__PURE__ */ new Set();
5884
6254
  let foundOptOutRoute = false;
5885
6255
  let routeDfds = matches.map(() => createDeferred2());
5886
6256
  let routesLoadedPromise = Promise.all(routeDfds.map((d) => d.promise));
5887
6257
  let singleFetchDfd = createDeferred2();
5888
- let url = stripIndexParam(singleFetchUrl(request.url));
6258
+ let url = stripIndexParam(singleFetchUrl(request.url, basename));
5889
6259
  let init = await createRequestInit(request);
5890
6260
  let results = {};
5891
6261
  let resolvePromise = Promise.all(
@@ -5897,7 +6267,7 @@ async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr,
5897
6267
  if (!router.state.initialized) {
5898
6268
  return;
5899
6269
  }
5900
- if (m.route.id in router.state.loaderData && manifestRoute && manifestRoute.hasLoader && routeModules[m.route.id]?.shouldRevalidate) {
6270
+ if (isOptedOut(manifestRoute, routeModules[m.route.id], m, router)) {
5901
6271
  foundOptOutRoute = true;
5902
6272
  return;
5903
6273
  }
@@ -5960,11 +6330,11 @@ async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr,
5960
6330
  await resolvePromise;
5961
6331
  return results;
5962
6332
  }
5963
- async function singleFetchLoaderFetcherStrategy(request, matches) {
6333
+ async function singleFetchLoaderFetcherStrategy(request, matches, basename) {
5964
6334
  let fetcherMatch = matches.find((m) => m.shouldLoad);
5965
6335
  invariant2(fetcherMatch, "No fetcher match found");
5966
6336
  let result = await fetcherMatch.resolve(async (handler) => {
5967
- let url = stripIndexParam(singleFetchUrl(request.url));
6337
+ let url = stripIndexParam(singleFetchUrl(request.url, basename));
5968
6338
  let init = await createRequestInit(request);
5969
6339
  return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
5970
6340
  });
@@ -5992,7 +6362,7 @@ function stripIndexParam(url) {
5992
6362
  }
5993
6363
  return url;
5994
6364
  }
5995
- function singleFetchUrl(reqUrl) {
6365
+ function singleFetchUrl(reqUrl, basename) {
5996
6366
  let url = typeof reqUrl === "string" ? new URL(
5997
6367
  reqUrl,
5998
6368
  // This can be called during the SSR flow via PrefetchPageLinksImpl so
@@ -6001,6 +6371,8 @@ function singleFetchUrl(reqUrl) {
6001
6371
  ) : reqUrl;
6002
6372
  if (url.pathname === "/") {
6003
6373
  url.pathname = "_root.data";
6374
+ } else if (basename && stripBasename(url.pathname, basename) === "/") {
6375
+ url.pathname = `${basename.replace(/\/$/, "")}/_root.data`;
6004
6376
  } else {
6005
6377
  url.pathname = `${url.pathname.replace(/\/$/, "")}.data`;
6006
6378
  }
@@ -6297,8 +6669,8 @@ function createServerRoutes(manifest, routeModules, future, isSpaMode, parentId
6297
6669
  // render, so just give it a no-op function so we can render down to the
6298
6670
  // proper fallback
6299
6671
  loader: route.hasLoader || route.hasClientLoader ? () => null : void 0
6300
- // We don't need action/shouldRevalidate on these routes since they're
6301
- // for a static render
6672
+ // We don't need middleware/action/shouldRevalidate on these routes since
6673
+ // they're for a static render
6302
6674
  };
6303
6675
  let children = createServerRoutes(
6304
6676
  manifest,
@@ -6392,6 +6764,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6392
6764
  Object.assign(dataRoute, {
6393
6765
  ...dataRoute,
6394
6766
  ...getRouteComponents(route, routeModule, isSpaMode),
6767
+ unstable_middleware: routeModule.unstable_clientMiddleware,
6395
6768
  handle: routeModule.handle,
6396
6769
  shouldRevalidate: getShouldRevalidateFunction(
6397
6770
  routeModule,
@@ -6405,7 +6778,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6405
6778
  let hasInitialError = initialState && initialState.errors && route.id in initialState.errors;
6406
6779
  let initialError = hasInitialError ? initialState?.errors?.[route.id] : void 0;
6407
6780
  let isHydrationRequest = needsRevalidation == null && (routeModule.clientLoader?.hydrate === true || !route.hasLoader);
6408
- dataRoute.loader = async ({ request, params }, singleFetch) => {
6781
+ dataRoute.loader = async ({ request, params, context }, singleFetch) => {
6409
6782
  try {
6410
6783
  let result = await prefetchStylesAndCallHandler(async () => {
6411
6784
  invariant2(
@@ -6418,6 +6791,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6418
6791
  return routeModule.clientLoader({
6419
6792
  request,
6420
6793
  params,
6794
+ context,
6421
6795
  async serverLoader() {
6422
6796
  preventInvalidServerHandlerCall("loader", route);
6423
6797
  if (isHydrationRequest) {
@@ -6442,7 +6816,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6442
6816
  routeModule,
6443
6817
  isSpaMode
6444
6818
  );
6445
- dataRoute.action = ({ request, params }, singleFetch) => {
6819
+ dataRoute.action = ({ request, params, context }, singleFetch) => {
6446
6820
  return prefetchStylesAndCallHandler(async () => {
6447
6821
  invariant2(
6448
6822
  routeModule,
@@ -6457,6 +6831,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6457
6831
  return routeModule.clientAction({
6458
6832
  request,
6459
6833
  params,
6834
+ context,
6460
6835
  async serverAction() {
6461
6836
  preventInvalidServerHandlerCall("action", route);
6462
6837
  return fetchServerAction(singleFetch);
@@ -6466,7 +6841,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6466
6841
  };
6467
6842
  } else {
6468
6843
  if (!route.hasClientLoader) {
6469
- dataRoute.loader = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
6844
+ dataRoute.loader = (_, singleFetch) => prefetchStylesAndCallHandler(() => {
6470
6845
  return fetchServerLoader(singleFetch);
6471
6846
  });
6472
6847
  } else if (route.clientLoaderModule) {
@@ -6487,7 +6862,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6487
6862
  };
6488
6863
  }
6489
6864
  if (!route.hasClientAction) {
6490
- dataRoute.action = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
6865
+ dataRoute.action = (_, singleFetch) => prefetchStylesAndCallHandler(() => {
6491
6866
  if (isSpaMode) {
6492
6867
  throw noActionDefinedError("clientAction", route.id);
6493
6868
  }
@@ -6545,6 +6920,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSp
6545
6920
  return {
6546
6921
  ...lazyRoute.loader ? { loader: lazyRoute.loader } : {},
6547
6922
  ...lazyRoute.action ? { action: lazyRoute.action } : {},
6923
+ unstable_middleware: mod.unstable_clientMiddleware,
6548
6924
  hasErrorBoundary: lazyRoute.hasErrorBoundary,
6549
6925
  shouldRevalidate: getShouldRevalidateFunction(
6550
6926
  lazyRoute,
@@ -6617,6 +6993,7 @@ async function loadRouteModuleWithBlockingLinks(route, routeModules) {
6617
6993
  return {
6618
6994
  Component: getRouteModuleComponent(routeModule),
6619
6995
  ErrorBoundary: routeModule.ErrorBoundary,
6996
+ unstable_clientMiddleware: routeModule.unstable_clientMiddleware,
6620
6997
  clientAction: routeModule.clientAction,
6621
6998
  clientLoader: routeModule.clientLoader,
6622
6999
  handle: routeModule.handle,
@@ -6672,12 +7049,13 @@ function getPatchRoutesOnNavigationFunction(manifest, routeModules, ssr, isSpaMo
6672
7049
  if (!isFogOfWarEnabled(ssr)) {
6673
7050
  return void 0;
6674
7051
  }
6675
- return async ({ path, patch, signal }) => {
7052
+ return async ({ path, patch, signal, fetcherKey }) => {
6676
7053
  if (discoveredPaths.has(path)) {
6677
7054
  return;
6678
7055
  }
6679
7056
  await fetchAndApplyManifestPatches(
6680
7057
  [path],
7058
+ fetcherKey ? window.location.href : path,
6681
7059
  manifest,
6682
7060
  routeModules,
6683
7061
  ssr,
@@ -6718,6 +7096,7 @@ function useFogOFWarDiscovery(router, manifest, routeModules, ssr, isSpaMode) {
6718
7096
  try {
6719
7097
  await fetchAndApplyManifestPatches(
6720
7098
  lazyPaths,
7099
+ null,
6721
7100
  manifest,
6722
7101
  routeModules,
6723
7102
  ssr,
@@ -6741,7 +7120,8 @@ function useFogOFWarDiscovery(router, manifest, routeModules, ssr, isSpaMode) {
6741
7120
  return () => observer.disconnect();
6742
7121
  }, [ssr, isSpaMode, manifest, routeModules, router]);
6743
7122
  }
6744
- async function fetchAndApplyManifestPatches(paths, manifest, routeModules, ssr, isSpaMode, basename, patchRoutes, signal) {
7123
+ var MANIFEST_VERSION_STORAGE_KEY = "react-router-manifest-version";
7124
+ async function fetchAndApplyManifestPatches(paths, errorReloadPath, manifest, routeModules, ssr, isSpaMode, basename, patchRoutes, signal) {
6745
7125
  let manifestPath = `${basename != null ? basename : "/"}/__manifest`.replace(
6746
7126
  /\/+/g,
6747
7127
  "/"
@@ -6758,9 +7138,26 @@ async function fetchAndApplyManifestPatches(paths, manifest, routeModules, ssr,
6758
7138
  let res = await fetch(url, { signal });
6759
7139
  if (!res.ok) {
6760
7140
  throw new Error(`${res.status} ${res.statusText}`);
7141
+ } else if (res.status === 204 && res.headers.has("X-Remix-Reload-Document")) {
7142
+ if (!errorReloadPath) {
7143
+ console.warn(
7144
+ "Detected a manifest version mismatch during eager route discovery. The next navigation/fetch to an undiscovered route will result in a new document navigation to sync up with the latest manifest."
7145
+ );
7146
+ return;
7147
+ }
7148
+ if (sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === manifest.version) {
7149
+ console.error(
7150
+ "Unable to discover routes due to manifest version mismatch."
7151
+ );
7152
+ return;
7153
+ }
7154
+ sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, manifest.version);
7155
+ window.location.href = errorReloadPath;
7156
+ throw new Error("Detected manifest version mismatch, reloading...");
6761
7157
  } else if (res.status >= 400) {
6762
7158
  throw new Error(await res.text());
6763
7159
  }
7160
+ sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);
6764
7161
  serverPatches = await res.json();
6765
7162
  } catch (e) {
6766
7163
  if (signal?.aborted) return;
@@ -6914,7 +7311,7 @@ function Links() {
6914
7311
  () => getKeyedLinksForMatches(matches, routeModules, manifest),
6915
7312
  [matches, routeModules, manifest]
6916
7313
  );
6917
- return /* @__PURE__ */ React9.createElement(React9.Fragment, null, criticalCss ? /* @__PURE__ */ React9.createElement("style", { dangerouslySetInnerHTML: { __html: criticalCss } }) : null, keyedLinks.map(
7314
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, typeof criticalCss === "string" ? /* @__PURE__ */ React9.createElement("style", { dangerouslySetInnerHTML: { __html: criticalCss } }) : null, typeof criticalCss === "object" ? /* @__PURE__ */ React9.createElement("link", { rel: "stylesheet", href: criticalCss.href }) : null, keyedLinks.map(
6918
7315
  ({ key, link }) => isPageLinkDescriptor(link) ? /* @__PURE__ */ React9.createElement(PrefetchPageLinks, { key, ...link }) : /* @__PURE__ */ React9.createElement("link", { key, ...link })
6919
7316
  ));
6920
7317
  }
@@ -6957,6 +7354,7 @@ function PrefetchPageLinksImpl({
6957
7354
  }) {
6958
7355
  let location = useLocation();
6959
7356
  let { manifest, routeModules } = useFrameworkContext();
7357
+ let { basename } = useDataRouterContext2();
6960
7358
  let { loaderData, matches } = useDataRouterStateContext();
6961
7359
  let newMatchesForData = React9.useMemo(
6962
7360
  () => getNewMatchesForLinks(
@@ -7002,7 +7400,7 @@ function PrefetchPageLinksImpl({
7002
7400
  if (routesParams.size === 0) {
7003
7401
  return [];
7004
7402
  }
7005
- let url = singleFetchUrl(page);
7403
+ let url = singleFetchUrl(page, basename);
7006
7404
  if (foundOptOutRoute && routesParams.size > 0) {
7007
7405
  url.searchParams.set(
7008
7406
  "_routes",
@@ -7011,6 +7409,7 @@ function PrefetchPageLinksImpl({
7011
7409
  }
7012
7410
  return [url.pathname + url.search];
7013
7411
  }, [
7412
+ basename,
7014
7413
  loaderData,
7015
7414
  location,
7016
7415
  manifest,
@@ -7264,13 +7663,14 @@ function mergeRefs(...refs) {
7264
7663
  var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
7265
7664
  try {
7266
7665
  if (isBrowser) {
7267
- window.__reactRouterVersion = "7.2.0";
7666
+ window.__reactRouterVersion = "7.3.0-pre.1";
7268
7667
  }
7269
7668
  } catch (e) {
7270
7669
  }
7271
7670
  function createBrowserRouter(routes, opts) {
7272
7671
  return createRouter({
7273
7672
  basename: opts?.basename,
7673
+ unstable_getContext: opts?.unstable_getContext,
7274
7674
  future: opts?.future,
7275
7675
  history: createBrowserHistory({ window: opts?.window }),
7276
7676
  hydrationData: opts?.hydrationData || parseHydrationData(),
@@ -7284,6 +7684,7 @@ function createBrowserRouter(routes, opts) {
7284
7684
  function createHashRouter(routes, opts) {
7285
7685
  return createRouter({
7286
7686
  basename: opts?.basename,
7687
+ unstable_getContext: opts?.unstable_getContext,
7287
7688
  future: opts?.future,
7288
7689
  history: createHashHistory({ window: opts?.window }),
7289
7690
  hydrationData: opts?.hydrationData || parseHydrationData(),
@@ -8242,6 +8643,7 @@ function createStaticRouter(routes, context, opts = {}) {
8242
8643
  },
8243
8644
  get future() {
8244
8645
  return {
8646
+ unstable_middleware: false,
8245
8647
  ...opts?.future
8246
8648
  };
8247
8649
  },
@@ -8404,7 +8806,7 @@ function ServerRouter({
8404
8806
 
8405
8807
  // lib/dom/ssr/routes-test-stub.tsx
8406
8808
  var React13 = __toESM(require("react"));
8407
- function createRoutesStub(routes, context = {}) {
8809
+ function createRoutesStub(routes, unstable_getContext) {
8408
8810
  return function RoutesTestStub({
8409
8811
  initialEntries,
8410
8812
  initialIndex,
@@ -8415,7 +8817,9 @@ function createRoutesStub(routes, context = {}) {
8415
8817
  let remixContextRef = React13.useRef();
8416
8818
  if (routerRef.current == null) {
8417
8819
  remixContextRef.current = {
8418
- future: {},
8820
+ future: {
8821
+ unstable_middleware: future?.unstable_middleware === true
8822
+ },
8419
8823
  manifest: {
8420
8824
  routes: {},
8421
8825
  entry: { imports: [], module: "" },
@@ -8427,13 +8831,14 @@ function createRoutesStub(routes, context = {}) {
8427
8831
  isSpaMode: false
8428
8832
  };
8429
8833
  let patched = processRoutes(
8430
- // @ts-expect-error loader/action context types don't match :/
8834
+ // @ts-expect-error `StubRouteObject` is stricter about `loader`/`action`
8835
+ // types compared to `AgnosticRouteObject`
8431
8836
  convertRoutesToDataRoutes(routes, (r) => r),
8432
- context,
8433
8837
  remixContextRef.current.manifest,
8434
8838
  remixContextRef.current.routeModules
8435
8839
  );
8436
8840
  routerRef.current = createMemoryRouter(patched, {
8841
+ unstable_getContext,
8437
8842
  initialEntries,
8438
8843
  initialIndex,
8439
8844
  hydrationData
@@ -8442,14 +8847,13 @@ function createRoutesStub(routes, context = {}) {
8442
8847
  return /* @__PURE__ */ React13.createElement(FrameworkContext.Provider, { value: remixContextRef.current }, /* @__PURE__ */ React13.createElement(RouterProvider, { router: routerRef.current }));
8443
8848
  };
8444
8849
  }
8445
- function processRoutes(routes, context, manifest, routeModules, parentId) {
8850
+ function processRoutes(routes, manifest, routeModules, parentId) {
8446
8851
  return routes.map((route) => {
8447
8852
  if (!route.id) {
8448
8853
  throw new Error(
8449
8854
  "Expected a route.id in @remix-run/testing processRoutes() function"
8450
8855
  );
8451
8856
  }
8452
- let { loader, action } = route;
8453
8857
  let newRoute = {
8454
8858
  id: route.id,
8455
8859
  path: route.path,
@@ -8457,8 +8861,8 @@ function processRoutes(routes, context, manifest, routeModules, parentId) {
8457
8861
  Component: route.Component,
8458
8862
  HydrateFallback: route.HydrateFallback,
8459
8863
  ErrorBoundary: route.ErrorBoundary,
8460
- action: action ? (args) => action({ ...args, context }) : void 0,
8461
- loader: loader ? (args) => loader({ ...args, context }) : void 0,
8864
+ action: route.action,
8865
+ loader: route.loader,
8462
8866
  handle: route.handle,
8463
8867
  shouldRevalidate: route.shouldRevalidate
8464
8868
  };
@@ -8493,7 +8897,6 @@ function processRoutes(routes, context, manifest, routeModules, parentId) {
8493
8897
  if (route.children) {
8494
8898
  newRoute.children = processRoutes(
8495
8899
  route.children,
8496
- context,
8497
8900
  manifest,
8498
8901
  routeModules,
8499
8902
  newRoute.id
@@ -8854,6 +9257,7 @@ function createStaticHandlerDataRoutes(manifest, future, parentId = "", routesBy
8854
9257
  hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
8855
9258
  id: route.id,
8856
9259
  path: route.path,
9260
+ unstable_middleware: route.module.unstable_middleware,
8857
9261
  // Need to use RR's version in the param typed here to permit the optional
8858
9262
  // context even though we know it'll always be provided in remix
8859
9263
  loader: route.module.loader ? async (args) => {
@@ -8999,27 +9403,46 @@ function prependCookies(parentHeaders, childHeaders) {
8999
9403
  }
9000
9404
 
9001
9405
  // lib/server-runtime/single-fetch.ts
9406
+ var NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205, 304]);
9002
9407
  var SINGLE_FETCH_REDIRECT_STATUS = 202;
9003
- function getSingleFetchDataStrategy2({
9004
- isActionDataRequest,
9005
- loadRouteIds
9006
- } = {}) {
9007
- return async ({ request, matches }) => {
9008
- if (isActionDataRequest && request.method === "GET") {
9009
- return {};
9010
- }
9011
- let matchesToLoad = loadRouteIds ? matches.filter((m) => loadRouteIds.includes(m.route.id)) : matches;
9012
- let results = await Promise.all(
9013
- matchesToLoad.map((match) => match.resolve())
9014
- );
9015
- return results.reduce(
9016
- (acc, result, i) => Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
9017
- {}
9018
- );
9019
- };
9020
- }
9021
9408
  async function singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
9022
9409
  try {
9410
+ let respond2 = function(context) {
9411
+ let headers = getDocumentHeaders(build, context);
9412
+ if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
9413
+ return generateSingleFetchResponse(request, build, serverMode, {
9414
+ result: getSingleFetchRedirect(
9415
+ context.statusCode,
9416
+ headers,
9417
+ build.basename
9418
+ ),
9419
+ headers,
9420
+ status: SINGLE_FETCH_REDIRECT_STATUS
9421
+ });
9422
+ }
9423
+ if (context.errors) {
9424
+ Object.values(context.errors).forEach((err) => {
9425
+ if (!isRouteErrorResponse(err) || err.error) {
9426
+ handleError(err);
9427
+ }
9428
+ });
9429
+ context.errors = sanitizeErrors(context.errors, serverMode);
9430
+ }
9431
+ let singleFetchResult;
9432
+ if (context.errors) {
9433
+ singleFetchResult = { error: Object.values(context.errors)[0] };
9434
+ } else {
9435
+ singleFetchResult = {
9436
+ data: Object.values(context.actionData || {})[0]
9437
+ };
9438
+ }
9439
+ return generateSingleFetchResponse(request, build, serverMode, {
9440
+ result: singleFetchResult,
9441
+ headers,
9442
+ status: context.statusCode
9443
+ });
9444
+ };
9445
+ var respond = respond2;
9023
9446
  let handlerRequest = new Request(handlerUrl, {
9024
9447
  method: request.method,
9025
9448
  body: request.body,
@@ -9030,12 +9453,14 @@ async function singleFetchAction(build, serverMode, staticHandler, request, hand
9030
9453
  let result = await staticHandler.query(handlerRequest, {
9031
9454
  requestContext: loadContext,
9032
9455
  skipLoaderErrorBubbling: true,
9033
- dataStrategy: getSingleFetchDataStrategy2({
9034
- isActionDataRequest: true
9035
- })
9456
+ skipRevalidation: true,
9457
+ unstable_respond: respond2
9036
9458
  });
9037
- if (isResponse(result)) {
9038
- return {
9459
+ if (!isResponse(result)) {
9460
+ result = respond2(result);
9461
+ }
9462
+ if (isRedirectResponse(result)) {
9463
+ return generateSingleFetchResponse(request, build, serverMode, {
9039
9464
  result: getSingleFetchRedirect(
9040
9465
  result.status,
9041
9466
  result.headers,
@@ -9043,65 +9468,83 @@ async function singleFetchAction(build, serverMode, staticHandler, request, hand
9043
9468
  ),
9044
9469
  headers: result.headers,
9045
9470
  status: SINGLE_FETCH_REDIRECT_STATUS
9046
- };
9047
- }
9048
- let context = result;
9049
- let headers = getDocumentHeaders(build, context);
9050
- if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
9051
- return {
9052
- result: getSingleFetchRedirect(
9053
- context.statusCode,
9054
- headers,
9055
- build.basename
9056
- ),
9057
- headers,
9058
- status: SINGLE_FETCH_REDIRECT_STATUS
9059
- };
9060
- }
9061
- if (context.errors) {
9062
- Object.values(context.errors).forEach((err) => {
9063
- if (!isRouteErrorResponse(err) || err.error) {
9064
- handleError(err);
9065
- }
9066
9471
  });
9067
- context.errors = sanitizeErrors(context.errors, serverMode);
9068
- }
9069
- let singleFetchResult;
9070
- if (context.errors) {
9071
- singleFetchResult = { error: Object.values(context.errors)[0] };
9072
- } else {
9073
- singleFetchResult = { data: Object.values(context.actionData || {})[0] };
9074
9472
  }
9075
- return {
9076
- result: singleFetchResult,
9077
- headers,
9078
- status: context.statusCode
9079
- };
9473
+ return result;
9080
9474
  } catch (error) {
9081
9475
  handleError(error);
9082
- return {
9476
+ return generateSingleFetchResponse(request, build, serverMode, {
9083
9477
  result: { error },
9084
9478
  headers: new Headers(),
9085
9479
  status: 500
9086
- };
9480
+ });
9087
9481
  }
9088
9482
  }
9089
9483
  async function singleFetchLoaders(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
9090
9484
  try {
9485
+ let respond2 = function(context) {
9486
+ let headers = getDocumentHeaders(build, context);
9487
+ if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
9488
+ return generateSingleFetchResponse(request, build, serverMode, {
9489
+ result: {
9490
+ [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
9491
+ context.statusCode,
9492
+ headers,
9493
+ build.basename
9494
+ )
9495
+ },
9496
+ headers,
9497
+ status: SINGLE_FETCH_REDIRECT_STATUS
9498
+ });
9499
+ }
9500
+ if (context.errors) {
9501
+ Object.values(context.errors).forEach((err) => {
9502
+ if (!isRouteErrorResponse(err) || err.error) {
9503
+ handleError(err);
9504
+ }
9505
+ });
9506
+ context.errors = sanitizeErrors(context.errors, serverMode);
9507
+ }
9508
+ let results = {};
9509
+ let loadedMatches = new Set(
9510
+ context.matches.filter(
9511
+ (m) => loadRouteIds ? loadRouteIds.has(m.route.id) : m.route.loader != null
9512
+ ).map((m) => m.route.id)
9513
+ );
9514
+ if (context.errors) {
9515
+ for (let [id, error] of Object.entries(context.errors)) {
9516
+ results[id] = { error };
9517
+ }
9518
+ }
9519
+ for (let [id, data2] of Object.entries(context.loaderData)) {
9520
+ if (!(id in results) && loadedMatches.has(id)) {
9521
+ results[id] = { data: data2 };
9522
+ }
9523
+ }
9524
+ return generateSingleFetchResponse(request, build, serverMode, {
9525
+ result: results,
9526
+ headers,
9527
+ status: context.statusCode
9528
+ });
9529
+ };
9530
+ var respond = respond2;
9091
9531
  let handlerRequest = new Request(handlerUrl, {
9092
9532
  headers: request.headers,
9093
9533
  signal: request.signal
9094
9534
  });
9095
- let loadRouteIds = new URL(request.url).searchParams.get("_routes")?.split(",") || void 0;
9535
+ let routesParam = new URL(request.url).searchParams.get("_routes");
9536
+ let loadRouteIds = routesParam ? new Set(routesParam.split(",")) : null;
9096
9537
  let result = await staticHandler.query(handlerRequest, {
9097
9538
  requestContext: loadContext,
9539
+ filterMatchesToLoad: (m) => !loadRouteIds || loadRouteIds.has(m.route.id),
9098
9540
  skipLoaderErrorBubbling: true,
9099
- dataStrategy: getSingleFetchDataStrategy2({
9100
- loadRouteIds
9101
- })
9541
+ unstable_respond: respond2
9102
9542
  });
9103
- if (isResponse(result)) {
9104
- return {
9543
+ if (!isResponse(result)) {
9544
+ result = respond2(result);
9545
+ }
9546
+ if (isRedirectResponse(result)) {
9547
+ return generateSingleFetchResponse(request, build, serverMode, {
9105
9548
  result: {
9106
9549
  [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
9107
9550
  result.status,
@@ -9111,56 +9554,41 @@ async function singleFetchLoaders(build, serverMode, staticHandler, request, han
9111
9554
  },
9112
9555
  headers: result.headers,
9113
9556
  status: SINGLE_FETCH_REDIRECT_STATUS
9114
- };
9115
- }
9116
- let context = result;
9117
- let headers = getDocumentHeaders(build, context);
9118
- if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
9119
- return {
9120
- result: {
9121
- [SingleFetchRedirectSymbol]: getSingleFetchRedirect(
9122
- context.statusCode,
9123
- headers,
9124
- build.basename
9125
- )
9126
- },
9127
- headers,
9128
- status: SINGLE_FETCH_REDIRECT_STATUS
9129
- };
9130
- }
9131
- if (context.errors) {
9132
- Object.values(context.errors).forEach((err) => {
9133
- if (!isRouteErrorResponse(err) || err.error) {
9134
- handleError(err);
9135
- }
9136
9557
  });
9137
- context.errors = sanitizeErrors(context.errors, serverMode);
9138
9558
  }
9139
- let results = {};
9140
- let loadedMatches = loadRouteIds ? context.matches.filter(
9141
- (m) => m.route.loader && loadRouteIds.includes(m.route.id)
9142
- ) : context.matches;
9143
- loadedMatches.forEach((m) => {
9144
- let { id } = m.route;
9145
- if (context.errors && context.errors.hasOwnProperty(id)) {
9146
- results[id] = { error: context.errors[id] };
9147
- } else if (context.loaderData.hasOwnProperty(id)) {
9148
- results[id] = { data: context.loaderData[id] };
9149
- }
9150
- });
9151
- return {
9152
- result: results,
9153
- headers,
9154
- status: context.statusCode
9155
- };
9559
+ return result;
9156
9560
  } catch (error) {
9157
9561
  handleError(error);
9158
- return {
9562
+ return generateSingleFetchResponse(request, build, serverMode, {
9159
9563
  result: { root: { error } },
9160
9564
  headers: new Headers(),
9161
9565
  status: 500
9162
- };
9566
+ });
9567
+ }
9568
+ }
9569
+ function generateSingleFetchResponse(request, build, serverMode, {
9570
+ result,
9571
+ headers,
9572
+ status
9573
+ }) {
9574
+ let resultHeaders = new Headers(headers);
9575
+ resultHeaders.set("X-Remix-Response", "yes");
9576
+ if (NO_BODY_STATUS_CODES.has(status)) {
9577
+ return new Response(null, { status, headers: resultHeaders });
9163
9578
  }
9579
+ resultHeaders.set("Content-Type", "text/x-script");
9580
+ return new Response(
9581
+ encodeViaTurboStream(
9582
+ result,
9583
+ request.signal,
9584
+ build.entry.module.streamTimeout,
9585
+ serverMode
9586
+ ),
9587
+ {
9588
+ status: status || 200,
9589
+ headers: resultHeaders
9590
+ }
9591
+ );
9164
9592
  }
9165
9593
  function getSingleFetchRedirect(status, headers, basename) {
9166
9594
  let redirect2 = headers.get("Location");
@@ -9223,7 +9651,6 @@ function encodeViaTurboStream(data2, requestSignal, streamTimeout, serverMode) {
9223
9651
  }
9224
9652
 
9225
9653
  // lib/server-runtime/server.ts
9226
- var NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([100, 101, 204, 205, 304]);
9227
9654
  function derive(build, mode) {
9228
9655
  let routes = createRoutes(build.routes);
9229
9656
  let dataRoutes = createStaticHandlerDataRoutes(build.routes, build.future);
@@ -9253,8 +9680,11 @@ var createRequestHandler = (build, mode) => {
9253
9680
  let serverMode;
9254
9681
  let staticHandler;
9255
9682
  let errorHandler;
9256
- return async function requestHandler(request, loadContext = {}) {
9683
+ return async function requestHandler(request, initialContext) {
9257
9684
  _build = typeof build === "function" ? await build() : build;
9685
+ let loadContext = _build.future.unstable_middleware ? new unstable_RouterContextProvider(
9686
+ initialContext
9687
+ ) : initialContext || {};
9258
9688
  if (typeof build === "function") {
9259
9689
  let derived = derive(_build, mode);
9260
9690
  routes = derived.routes;
@@ -9269,8 +9699,14 @@ var createRequestHandler = (build, mode) => {
9269
9699
  errorHandler = derived.errorHandler;
9270
9700
  }
9271
9701
  let url = new URL(request.url);
9272
- let normalizedPath = url.pathname.replace(/\.data$/, "").replace(/^\/_root$/, "/");
9273
- if (normalizedPath !== "/" && normalizedPath.endsWith("/")) {
9702
+ let normalizedBasename = _build.basename || "/";
9703
+ let normalizedPath = url.pathname;
9704
+ if (stripBasename(normalizedPath, normalizedBasename) === "/_root.data") {
9705
+ normalizedPath = normalizedBasename;
9706
+ } else if (normalizedPath.endsWith(".data")) {
9707
+ normalizedPath = normalizedPath.replace(/\.data$/, "");
9708
+ }
9709
+ if (stripBasename(normalizedPath, normalizedBasename) !== "/" && normalizedPath.endsWith("/")) {
9274
9710
  normalizedPath = normalizedPath.slice(0, -1);
9275
9711
  }
9276
9712
  let params = {};
@@ -9310,10 +9746,7 @@ var createRequestHandler = (build, mode) => {
9310
9746
  }
9311
9747
  }
9312
9748
  }
9313
- let manifestUrl = `${_build.basename ?? "/"}/__manifest`.replace(
9314
- /\/+/g,
9315
- "/"
9316
- );
9749
+ let manifestUrl = `${normalizedBasename}/__manifest`.replace(/\/+/g, "/");
9317
9750
  if (url.pathname === manifestUrl) {
9318
9751
  try {
9319
9752
  let res = await handleManifestRequest(_build, routes, url);
@@ -9378,9 +9811,10 @@ var createRequestHandler = (build, mode) => {
9378
9811
  );
9379
9812
  }
9380
9813
  }
9381
- } else if (matches && matches[matches.length - 1].route.module.default == null && matches[matches.length - 1].route.module.ErrorBoundary == null) {
9814
+ } else if (!request.headers.has("X-React-Router-SPA-Mode") && matches && matches[matches.length - 1].route.module.default == null && matches[matches.length - 1].route.module.ErrorBoundary == null) {
9382
9815
  response = await handleResourceRequest(
9383
9816
  serverMode,
9817
+ _build,
9384
9818
  staticHandler,
9385
9819
  matches.slice(-1)[0].route.id,
9386
9820
  request,
@@ -9388,7 +9822,13 @@ var createRequestHandler = (build, mode) => {
9388
9822
  handleError
9389
9823
  );
9390
9824
  } else {
9391
- let criticalCss = mode === "development" /* Development */ ? await getDevServerHooks()?.getCriticalCss?.(_build, url.pathname) : void 0;
9825
+ let { pathname } = url;
9826
+ let criticalCss = void 0;
9827
+ if (_build.getCriticalCss) {
9828
+ criticalCss = await _build.getCriticalCss({ pathname });
9829
+ } else if (mode === "development" /* Development */ && getDevServerHooks()?.getCriticalCss) {
9830
+ criticalCss = await getDevServerHooks()?.getCriticalCss?.(pathname);
9831
+ }
9392
9832
  response = await handleDocumentRequest(
9393
9833
  serverMode,
9394
9834
  _build,
@@ -9410,6 +9850,14 @@ var createRequestHandler = (build, mode) => {
9410
9850
  };
9411
9851
  };
9412
9852
  async function handleManifestRequest(build, routes, url) {
9853
+ if (build.assets.version !== url.searchParams.get("version")) {
9854
+ return new Response(null, {
9855
+ status: 204,
9856
+ headers: {
9857
+ "X-Remix-Reload-Document": "true"
9858
+ }
9859
+ });
9860
+ }
9413
9861
  let patches = {};
9414
9862
  if (url.searchParams.has("p")) {
9415
9863
  for (let path of url.searchParams.getAll("p")) {
@@ -9433,7 +9881,7 @@ async function handleManifestRequest(build, routes, url) {
9433
9881
  return new Response("Invalid Request", { status: 400 });
9434
9882
  }
9435
9883
  async function handleSingleFetchRequest(serverMode, build, staticHandler, request, handlerUrl, loadContext, handleError) {
9436
- let { result, headers, status } = request.method !== "GET" ? await singleFetchAction(
9884
+ let response = request.method !== "GET" ? await singleFetchAction(
9437
9885
  build,
9438
9886
  serverMode,
9439
9887
  staticHandler,
@@ -9450,133 +9898,66 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
9450
9898
  loadContext,
9451
9899
  handleError
9452
9900
  );
9453
- let resultHeaders = new Headers(headers);
9454
- resultHeaders.set("X-Remix-Response", "yes");
9455
- if (NO_BODY_STATUS_CODES.has(status)) {
9456
- return new Response(null, { status, headers: resultHeaders });
9457
- }
9458
- resultHeaders.set("Content-Type", "text/x-script");
9459
- return new Response(
9460
- encodeViaTurboStream(
9461
- result,
9462
- request.signal,
9463
- build.entry.module.streamTimeout,
9464
- serverMode
9465
- ),
9466
- {
9467
- status: status || 200,
9468
- headers: resultHeaders
9469
- }
9470
- );
9901
+ return response;
9471
9902
  }
9472
9903
  async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, criticalCss) {
9473
9904
  let isSpaMode = request.headers.has("X-React-Router-SPA-Mode");
9474
- let context;
9475
9905
  try {
9476
- context = await staticHandler.query(request, {
9477
- requestContext: loadContext
9906
+ let response = await staticHandler.query(request, {
9907
+ requestContext: loadContext,
9908
+ unstable_respond: build.future.unstable_middleware ? (ctx) => renderHtml(ctx, isSpaMode) : void 0
9478
9909
  });
9910
+ return isResponse(response) ? response : renderHtml(response, isSpaMode);
9479
9911
  } catch (error) {
9480
9912
  handleError(error);
9481
9913
  return new Response(null, { status: 500 });
9482
9914
  }
9483
- if (isResponse(context)) {
9484
- return context;
9485
- }
9486
- let headers = getDocumentHeaders(build, context);
9487
- if (NO_BODY_STATUS_CODES.has(context.statusCode)) {
9488
- return new Response(null, { status: context.statusCode, headers });
9489
- }
9490
- if (context.errors) {
9491
- Object.values(context.errors).forEach((err) => {
9492
- if (!isRouteErrorResponse(err) || err.error) {
9493
- handleError(err);
9494
- }
9495
- });
9496
- context.errors = sanitizeErrors(context.errors, serverMode);
9497
- }
9498
- let state = {
9499
- loaderData: context.loaderData,
9500
- actionData: context.actionData,
9501
- errors: serializeErrors2(context.errors, serverMode)
9502
- };
9503
- let entryContext = {
9504
- manifest: build.assets,
9505
- routeModules: createEntryRouteModules(build.routes),
9506
- staticHandlerContext: context,
9507
- criticalCss,
9508
- serverHandoffString: createServerHandoffString({
9509
- basename: build.basename,
9510
- criticalCss,
9511
- future: build.future,
9512
- ssr: build.ssr,
9513
- isSpaMode
9514
- }),
9515
- serverHandoffStream: encodeViaTurboStream(
9516
- state,
9517
- request.signal,
9518
- build.entry.module.streamTimeout,
9519
- serverMode
9520
- ),
9521
- renderMeta: {},
9522
- future: build.future,
9523
- ssr: build.ssr,
9524
- isSpaMode,
9525
- serializeError: (err) => serializeError(err, serverMode)
9526
- };
9527
- let handleDocumentRequestFunction = build.entry.module.default;
9528
- try {
9529
- return await handleDocumentRequestFunction(
9530
- request,
9531
- context.statusCode,
9532
- headers,
9533
- entryContext,
9534
- loadContext
9535
- );
9536
- } catch (error) {
9537
- handleError(error);
9538
- let errorForSecondRender = error;
9539
- if (isResponse(error)) {
9540
- try {
9541
- let data2 = await unwrapResponse(error);
9542
- errorForSecondRender = new ErrorResponseImpl(
9543
- error.status,
9544
- error.statusText,
9545
- data2
9546
- );
9547
- } catch (e) {
9548
- }
9915
+ async function renderHtml(context, isSpaMode2) {
9916
+ if (isResponse(context)) {
9917
+ return context;
9918
+ }
9919
+ let headers = getDocumentHeaders(build, context);
9920
+ if (NO_BODY_STATUS_CODES.has(context.statusCode)) {
9921
+ return new Response(null, { status: context.statusCode, headers });
9549
9922
  }
9550
- context = getStaticContextFromError(
9551
- staticHandler.dataRoutes,
9552
- context,
9553
- errorForSecondRender
9554
- );
9555
9923
  if (context.errors) {
9924
+ Object.values(context.errors).forEach((err) => {
9925
+ if (!isRouteErrorResponse(err) || err.error) {
9926
+ handleError(err);
9927
+ }
9928
+ });
9556
9929
  context.errors = sanitizeErrors(context.errors, serverMode);
9557
9930
  }
9558
- let state2 = {
9931
+ let state = {
9559
9932
  loaderData: context.loaderData,
9560
9933
  actionData: context.actionData,
9561
9934
  errors: serializeErrors2(context.errors, serverMode)
9562
9935
  };
9563
- entryContext = {
9564
- ...entryContext,
9936
+ let entryContext = {
9937
+ manifest: build.assets,
9938
+ routeModules: createEntryRouteModules(build.routes),
9565
9939
  staticHandlerContext: context,
9940
+ criticalCss,
9566
9941
  serverHandoffString: createServerHandoffString({
9567
9942
  basename: build.basename,
9943
+ criticalCss,
9568
9944
  future: build.future,
9569
9945
  ssr: build.ssr,
9570
- isSpaMode
9946
+ isSpaMode: isSpaMode2
9571
9947
  }),
9572
9948
  serverHandoffStream: encodeViaTurboStream(
9573
- state2,
9949
+ state,
9574
9950
  request.signal,
9575
9951
  build.entry.module.streamTimeout,
9576
9952
  serverMode
9577
9953
  ),
9578
- renderMeta: {}
9954
+ renderMeta: {},
9955
+ future: build.future,
9956
+ ssr: build.ssr,
9957
+ isSpaMode: isSpaMode2,
9958
+ serializeError: (err) => serializeError(err, serverMode)
9579
9959
  };
9960
+ let handleDocumentRequestFunction = build.entry.module.default;
9580
9961
  try {
9581
9962
  return await handleDocumentRequestFunction(
9582
9963
  request,
@@ -9585,17 +9966,71 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
9585
9966
  entryContext,
9586
9967
  loadContext
9587
9968
  );
9588
- } catch (error2) {
9589
- handleError(error2);
9590
- return returnLastResortErrorResponse(error2, serverMode);
9969
+ } catch (error) {
9970
+ handleError(error);
9971
+ let errorForSecondRender = error;
9972
+ if (isResponse(error)) {
9973
+ try {
9974
+ let data2 = await unwrapResponse(error);
9975
+ errorForSecondRender = new ErrorResponseImpl(
9976
+ error.status,
9977
+ error.statusText,
9978
+ data2
9979
+ );
9980
+ } catch (e) {
9981
+ }
9982
+ }
9983
+ context = getStaticContextFromError(
9984
+ staticHandler.dataRoutes,
9985
+ context,
9986
+ errorForSecondRender
9987
+ );
9988
+ if (context.errors) {
9989
+ context.errors = sanitizeErrors(context.errors, serverMode);
9990
+ }
9991
+ let state2 = {
9992
+ loaderData: context.loaderData,
9993
+ actionData: context.actionData,
9994
+ errors: serializeErrors2(context.errors, serverMode)
9995
+ };
9996
+ entryContext = {
9997
+ ...entryContext,
9998
+ staticHandlerContext: context,
9999
+ serverHandoffString: createServerHandoffString({
10000
+ basename: build.basename,
10001
+ future: build.future,
10002
+ ssr: build.ssr,
10003
+ isSpaMode: isSpaMode2
10004
+ }),
10005
+ serverHandoffStream: encodeViaTurboStream(
10006
+ state2,
10007
+ request.signal,
10008
+ build.entry.module.streamTimeout,
10009
+ serverMode
10010
+ ),
10011
+ renderMeta: {}
10012
+ };
10013
+ try {
10014
+ return await handleDocumentRequestFunction(
10015
+ request,
10016
+ context.statusCode,
10017
+ headers,
10018
+ entryContext,
10019
+ loadContext
10020
+ );
10021
+ } catch (error2) {
10022
+ handleError(error2);
10023
+ return returnLastResortErrorResponse(error2, serverMode);
10024
+ }
9591
10025
  }
9592
10026
  }
9593
10027
  }
9594
- async function handleResourceRequest(serverMode, staticHandler, routeId, request, loadContext, handleError) {
10028
+ async function handleResourceRequest(serverMode, build, staticHandler, routeId, request, loadContext, handleError) {
9595
10029
  try {
9596
10030
  let response = await staticHandler.queryRoute(request, {
9597
10031
  routeId,
9598
- requestContext: loadContext
10032
+ requestContext: loadContext,
10033
+ unstable_respond: build.future.unstable_middleware ? (ctx) => ctx : void 0
9599
10034
  });
9600
10035
  if (isResponse(response)) {
9601
10036
  return response;
@@ -9615,6 +10050,13 @@ async function handleResourceRequest(serverMode, staticHandler, routeId, request
9615
10050
  }
9616
10051
  return errorResponseToJson(error, serverMode);
9617
10052
  }
10053
+ if (error instanceof Error && error.message === "Expected a response from queryRoute") {
10054
+ let newError = new Error(
10055
+ "Expected a Response to be returned from resource route handler"
10056
+ );
10057
+ handleError(newError);
10058
+ return returnLastResortErrorResponse(newError, serverMode);
10059
+ }
9618
10060
  handleError(error);
9619
10061
  return returnLastResortErrorResponse(error, serverMode);
9620
10062
  }
@@ -9931,6 +10373,8 @@ function deserializeErrors2(errors) {
9931
10373
  replace,
9932
10374
  resolvePath,
9933
10375
  unstable_HistoryRouter,
10376
+ unstable_RouterContextProvider,
10377
+ unstable_createContext,
9934
10378
  unstable_setDevServerHooks,
9935
10379
  unstable_usePrompt,
9936
10380
  useActionData,