react-router 8.3.1 → 8.5.0

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 (218) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/development/dom-export.d.ts +2 -1
  3. package/dist/development/dom-export.js +1 -1
  4. package/dist/development/index-react-server-client.js +2 -2
  5. package/dist/development/index-react-server.d.ts +601 -189
  6. package/dist/development/index-react-server.js +100 -48
  7. package/dist/development/index.d.ts +10 -9
  8. package/dist/development/index.js +6 -5
  9. package/dist/development/lib/actions.js +1 -1
  10. package/dist/development/lib/components.js +66 -10
  11. package/dist/development/lib/context.d.ts +19 -6
  12. package/dist/development/lib/context.js +11 -3
  13. package/dist/development/lib/dom/dom.d.ts +3 -0
  14. package/dist/development/lib/dom/dom.js +1 -1
  15. package/dist/development/lib/dom/global.d.ts +35 -0
  16. package/dist/development/lib/dom/lib.d.ts +34 -9
  17. package/dist/development/lib/dom/lib.js +30 -37
  18. package/dist/development/lib/dom/server.d.ts +6 -1
  19. package/dist/development/lib/dom/server.js +41 -15
  20. package/dist/development/lib/dom/ssr/components.js +26 -31
  21. package/dist/development/lib/dom/ssr/data.js +1 -1
  22. package/dist/development/lib/dom/ssr/entry.d.ts +13 -2
  23. package/dist/development/lib/dom/ssr/errorBoundaries.js +1 -1
  24. package/dist/development/lib/dom/ssr/fallback.js +1 -1
  25. package/dist/development/lib/dom/ssr/fog-of-war.d.ts +3 -2
  26. package/dist/development/lib/dom/ssr/fog-of-war.js +46 -22
  27. package/dist/development/lib/dom/ssr/hydration.d.ts +3 -1
  28. package/dist/development/lib/dom/ssr/hydration.js +6 -4
  29. package/dist/development/lib/dom/ssr/invariant.js +1 -1
  30. package/dist/development/lib/dom/ssr/links.js +1 -1
  31. package/dist/development/lib/dom/ssr/markup.js +5 -2
  32. package/dist/development/lib/dom/ssr/route-discovery.d.ts +120 -0
  33. package/dist/development/lib/dom/ssr/route-discovery.js +415 -0
  34. package/dist/development/lib/dom/ssr/routeModules.js +1 -1
  35. package/dist/development/lib/dom/ssr/routes-test-stub.js +2 -2
  36. package/dist/development/lib/dom/ssr/routes.d.ts +2 -2
  37. package/dist/development/lib/dom/ssr/routes.js +8 -8
  38. package/dist/development/lib/dom/ssr/server.js +4 -2
  39. package/dist/development/lib/dom/ssr/single-fetch.d.ts +28 -2
  40. package/dist/development/lib/dom/ssr/single-fetch.js +80 -71
  41. package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
  42. package/dist/development/lib/dom-export/hydrated-router.d.ts +28 -0
  43. package/dist/development/lib/dom-export/hydrated-router.js +33 -12
  44. package/dist/development/lib/errors.js +1 -1
  45. package/dist/development/lib/hooks.d.ts +3 -3
  46. package/dist/development/lib/hooks.js +52 -47
  47. package/dist/development/lib/href.js +1 -1
  48. package/dist/development/lib/router/history.js +1 -1
  49. package/dist/development/lib/router/instrumentation.js +1 -1
  50. package/dist/development/lib/router/matcher-route-pattern.d.ts +2 -0
  51. package/dist/development/lib/router/matcher-route-pattern.js +216 -0
  52. package/dist/development/lib/router/matcher-route-pattern.preload.d.ts +20 -0
  53. package/dist/development/lib/router/matcher-route-pattern.preload.js +36 -0
  54. package/dist/development/lib/router/matcher.d.ts +2 -0
  55. package/dist/development/lib/router/matcher.js +29 -0
  56. package/dist/development/lib/router/navigation.js +1 -1
  57. package/dist/development/lib/router/router.d.ts +19 -7
  58. package/dist/development/lib/router/router.js +235 -128
  59. package/dist/development/lib/router/url.js +1 -1
  60. package/dist/development/lib/router/utils.d.ts +30 -5
  61. package/dist/development/lib/router/utils.js +8 -5
  62. package/dist/development/lib/rsc/browser.js +3 -2
  63. package/dist/development/lib/rsc/errorBoundaries.js +1 -1
  64. package/dist/development/lib/rsc/html-stream/browser.js +1 -1
  65. package/dist/development/lib/rsc/html-stream/server.js +25 -15
  66. package/dist/development/lib/rsc/route-modules.js +1 -1
  67. package/dist/development/lib/rsc/server.rsc.d.ts +10 -2
  68. package/dist/development/lib/rsc/server.ssr.js +25 -21
  69. package/dist/development/lib/server-runtime/build.d.ts +14 -0
  70. package/dist/development/lib/server-runtime/cookies.js +1 -1
  71. package/dist/development/lib/server-runtime/crypto.js +1 -1
  72. package/dist/development/lib/server-runtime/data.js +1 -1
  73. package/dist/development/lib/server-runtime/dev.js +1 -1
  74. package/dist/development/lib/server-runtime/entry.js +1 -1
  75. package/dist/development/lib/server-runtime/errors.js +1 -1
  76. package/dist/development/lib/server-runtime/headers.js +1 -1
  77. package/dist/development/lib/server-runtime/invariant.js +1 -1
  78. package/dist/development/lib/server-runtime/mode.js +1 -1
  79. package/dist/development/lib/server-runtime/routeMatching.js +3 -4
  80. package/dist/development/lib/server-runtime/routes.d.ts +1 -1
  81. package/dist/development/lib/server-runtime/routes.js +1 -1
  82. package/dist/development/lib/server-runtime/server.js +18 -9
  83. package/dist/development/lib/server-runtime/serverHandoff.d.ts +17 -0
  84. package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
  85. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
  86. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
  87. package/dist/development/lib/server-runtime/sessions.js +1 -1
  88. package/dist/development/lib/server-runtime/single-fetch.js +1 -1
  89. package/dist/development/lib/server-runtime/urls.js +1 -1
  90. package/dist/development/lib/server-runtime/warnings.js +1 -1
  91. package/dist/development/lib/types/internal.js +1 -1
  92. package/dist/development/lib/types/route-data.d.ts +2 -2
  93. package/dist/development/lib/types/route-module-annotations.d.ts +1 -1
  94. package/dist/development/route-pattern.d.ts +3 -0
  95. package/dist/development/route-pattern.js +12 -0
  96. package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
  97. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +1 -1
  98. package/dist/development/vendor/turbo-stream-v2/unflatten.js +1 -1
  99. package/dist/development/vendor/turbo-stream-v2/utils.js +1 -1
  100. package/dist/production/dom-export.d.ts +2 -1
  101. package/dist/production/dom-export.js +1 -1
  102. package/dist/production/index-react-server-client.js +2 -2
  103. package/dist/production/index-react-server.d.ts +601 -189
  104. package/dist/production/index-react-server.js +100 -48
  105. package/dist/production/index.d.ts +10 -9
  106. package/dist/production/index.js +6 -5
  107. package/dist/production/lib/actions.js +1 -1
  108. package/dist/production/lib/components.js +66 -10
  109. package/dist/production/lib/context.d.ts +19 -6
  110. package/dist/production/lib/context.js +11 -3
  111. package/dist/production/lib/dom/dom.d.ts +3 -0
  112. package/dist/production/lib/dom/dom.js +1 -1
  113. package/dist/production/lib/dom/global.d.ts +35 -0
  114. package/dist/production/lib/dom/lib.d.ts +34 -9
  115. package/dist/production/lib/dom/lib.js +30 -37
  116. package/dist/production/lib/dom/server.d.ts +6 -1
  117. package/dist/production/lib/dom/server.js +41 -15
  118. package/dist/production/lib/dom/ssr/components.js +26 -31
  119. package/dist/production/lib/dom/ssr/data.js +1 -1
  120. package/dist/production/lib/dom/ssr/entry.d.ts +13 -2
  121. package/dist/production/lib/dom/ssr/errorBoundaries.js +1 -1
  122. package/dist/production/lib/dom/ssr/fallback.js +1 -1
  123. package/dist/production/lib/dom/ssr/fog-of-war.d.ts +3 -2
  124. package/dist/production/lib/dom/ssr/fog-of-war.js +46 -22
  125. package/dist/production/lib/dom/ssr/hydration.d.ts +3 -1
  126. package/dist/production/lib/dom/ssr/hydration.js +6 -4
  127. package/dist/production/lib/dom/ssr/invariant.js +1 -1
  128. package/dist/production/lib/dom/ssr/links.js +1 -1
  129. package/dist/production/lib/dom/ssr/markup.js +5 -2
  130. package/dist/production/lib/dom/ssr/route-discovery.d.ts +120 -0
  131. package/dist/production/lib/dom/ssr/route-discovery.js +415 -0
  132. package/dist/production/lib/dom/ssr/routeModules.js +1 -1
  133. package/dist/production/lib/dom/ssr/routes-test-stub.js +2 -2
  134. package/dist/production/lib/dom/ssr/routes.d.ts +2 -2
  135. package/dist/production/lib/dom/ssr/routes.js +8 -8
  136. package/dist/production/lib/dom/ssr/server.js +4 -2
  137. package/dist/production/lib/dom/ssr/single-fetch.d.ts +28 -2
  138. package/dist/production/lib/dom/ssr/single-fetch.js +80 -71
  139. package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
  140. package/dist/production/lib/dom-export/hydrated-router.d.ts +28 -0
  141. package/dist/production/lib/dom-export/hydrated-router.js +33 -12
  142. package/dist/production/lib/errors.js +1 -1
  143. package/dist/production/lib/hooks.d.ts +3 -3
  144. package/dist/production/lib/hooks.js +51 -46
  145. package/dist/production/lib/href.js +1 -1
  146. package/dist/production/lib/router/history.js +1 -1
  147. package/dist/production/lib/router/instrumentation.js +1 -1
  148. package/dist/production/lib/router/matcher-route-pattern.d.ts +2 -0
  149. package/dist/production/lib/router/matcher-route-pattern.js +216 -0
  150. package/dist/production/lib/router/matcher-route-pattern.preload.d.ts +20 -0
  151. package/dist/production/lib/router/matcher-route-pattern.preload.js +36 -0
  152. package/dist/production/lib/router/matcher.d.ts +2 -0
  153. package/dist/production/lib/router/matcher.js +29 -0
  154. package/dist/production/lib/router/navigation.js +1 -1
  155. package/dist/production/lib/router/router.d.ts +19 -7
  156. package/dist/production/lib/router/router.js +235 -128
  157. package/dist/production/lib/router/url.js +1 -1
  158. package/dist/production/lib/router/utils.d.ts +30 -5
  159. package/dist/production/lib/router/utils.js +8 -5
  160. package/dist/production/lib/rsc/browser.js +3 -2
  161. package/dist/production/lib/rsc/errorBoundaries.js +1 -1
  162. package/dist/production/lib/rsc/html-stream/browser.js +1 -1
  163. package/dist/production/lib/rsc/html-stream/server.js +25 -15
  164. package/dist/production/lib/rsc/route-modules.js +1 -1
  165. package/dist/production/lib/rsc/server.rsc.d.ts +10 -2
  166. package/dist/production/lib/rsc/server.ssr.js +25 -21
  167. package/dist/production/lib/server-runtime/build.d.ts +14 -0
  168. package/dist/production/lib/server-runtime/cookies.js +1 -1
  169. package/dist/production/lib/server-runtime/crypto.js +1 -1
  170. package/dist/production/lib/server-runtime/data.js +1 -1
  171. package/dist/production/lib/server-runtime/dev.js +1 -1
  172. package/dist/production/lib/server-runtime/entry.js +1 -1
  173. package/dist/production/lib/server-runtime/errors.js +1 -1
  174. package/dist/production/lib/server-runtime/headers.js +1 -1
  175. package/dist/production/lib/server-runtime/invariant.js +1 -1
  176. package/dist/production/lib/server-runtime/mode.js +1 -1
  177. package/dist/production/lib/server-runtime/routeMatching.js +3 -4
  178. package/dist/production/lib/server-runtime/routes.d.ts +1 -1
  179. package/dist/production/lib/server-runtime/routes.js +1 -1
  180. package/dist/production/lib/server-runtime/server.js +18 -9
  181. package/dist/production/lib/server-runtime/serverHandoff.d.ts +17 -0
  182. package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
  183. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
  184. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
  185. package/dist/production/lib/server-runtime/sessions.js +1 -1
  186. package/dist/production/lib/server-runtime/single-fetch.js +1 -1
  187. package/dist/production/lib/server-runtime/urls.js +1 -1
  188. package/dist/production/lib/server-runtime/warnings.js +1 -1
  189. package/dist/production/lib/types/internal.js +1 -1
  190. package/dist/production/lib/types/route-data.d.ts +2 -2
  191. package/dist/production/lib/types/route-module-annotations.d.ts +1 -1
  192. package/dist/production/route-pattern.d.ts +3 -0
  193. package/dist/production/route-pattern.js +12 -0
  194. package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
  195. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +1 -1
  196. package/dist/production/vendor/turbo-stream-v2/unflatten.js +1 -1
  197. package/dist/production/vendor/turbo-stream-v2/utils.js +1 -1
  198. package/docs/explanation/lazy-route-discovery.md +4 -0
  199. package/docs/explanation/sessions-and-cookies.md +108 -4
  200. package/docs/how-to/custom-fetch.md +218 -0
  201. package/docs/how-to/data-strategy.md +23 -1
  202. package/docs/how-to/fetchers.md +6 -1
  203. package/docs/how-to/middleware.md +4 -1
  204. package/docs/how-to/optimize-revalidation.md +178 -5
  205. package/docs/how-to/pre-rendering.md +23 -1
  206. package/docs/how-to/react-server-components.md +26 -3
  207. package/docs/how-to/resource-routes.md +3 -0
  208. package/docs/how-to/route-discovery.md +145 -0
  209. package/docs/how-to/spa.md +2 -0
  210. package/docs/how-to/view-transitions.md +80 -13
  211. package/docs/start/data/actions.md +2 -1
  212. package/docs/start/data/route-object.md +21 -6
  213. package/docs/start/framework/actions.md +4 -2
  214. package/docs/start/framework/navigating.md +5 -9
  215. package/docs/start/framework/rendering.md +37 -0
  216. package/docs/start/framework/route-module.md +32 -5
  217. package/docs/upgrading/future.md +68 -0
  218. package/package.json +19 -1
@@ -1,14 +1,40 @@
1
1
 
2
+ import { Action } from "../../router/history.js";
2
3
  import { DataStrategyFunction } from "../../router/utils.js";
3
4
  import { Router } from "../../router/router.js";
4
5
  import { RouteModules } from "./routeModules.js";
5
6
  import { AssetsManifest } from "./entry.js";
6
7
  //#region lib/dom/ssr/single-fetch.d.ts
7
8
  declare const SingleFetchRedirectSymbol: unique symbol;
8
- declare function getTurboStreamSingleFetchDataStrategy(getRouter: () => Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean): DataStrategyFunction;
9
+ /**
10
+ * Describes the operation that initiated an internal router request.
11
+ *
12
+ * Requests that reload fetchers as part of a navigation, revalidation, or
13
+ * initialization redirect keep that initiating `type`. `fetcherKey` identifies
14
+ * the fetcher being loaded, or is `null` when the request targets route loaders
15
+ * or actions.
16
+ *
17
+ * `navigationType` is the history action (`"PUSH"`, `"REPLACE"`, or `"POP"`)
18
+ * for navigation-initiated data requests, including reloaded fetchers. It is
19
+ * `null` for initialization, fetcher, and revalidation requests. Manifest
20
+ * requests have no navigation type.
21
+ */
22
+ type RouterFetchContext = {
23
+ type: "manifest";
24
+ } | {
25
+ type: "navigation";
26
+ fetcherKey: string | null;
27
+ navigationType: Action;
28
+ } | {
29
+ type: "initialization" | "fetcher" | "revalidation";
30
+ fetcherKey: string | null;
31
+ navigationType: null;
32
+ };
33
+ type RouterFetch = (request: Request, context: RouterFetchContext) => Promise<Response>;
34
+ declare function getTurboStreamSingleFetchDataStrategy(getRouter: () => Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean, fetchImplementation?: RouterFetch, isApiOnly?: boolean, serverOrigin?: string): DataStrategyFunction;
9
35
  declare function decodeViaTurboStream(body: ReadableStream<Uint8Array>, global: Window | typeof globalThis): Promise<{
10
36
  done: Promise<void>;
11
37
  value: unknown;
12
38
  }>;
13
39
  //#endregion
14
- export { SingleFetchRedirectSymbol, decodeViaTurboStream, getTurboStreamSingleFetchDataStrategy };
40
+ export { RouterFetch, RouterFetchContext, SingleFetchRedirectSymbol, decodeViaTurboStream, getTurboStreamSingleFetchDataStrategy };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -56,7 +56,7 @@ function StreamTransfer({ context, identifier, reader, textDecoder, nonce }) {
56
56
  nonce
57
57
  })));
58
58
  }
59
- function getTurboStreamSingleFetchDataStrategy(getRouter, manifest, routeModules, ssr) {
59
+ function getTurboStreamSingleFetchDataStrategy(getRouter, manifest, routeModules, ssr, fetchImplementation = (request) => fetch(request), isApiOnly = false, serverOrigin) {
60
60
  let dataStrategy = getSingleFetchDataStrategyImpl(getRouter, (match) => {
61
61
  let manifestRoute = manifest.routes[match.route.id];
62
62
  invariant(manifestRoute, "Route not found in manifest");
@@ -64,10 +64,10 @@ function getTurboStreamSingleFetchDataStrategy(getRouter, manifest, routeModules
64
64
  hasLoader: manifestRoute.hasLoader,
65
65
  hasClientLoader: manifestRoute.hasClientLoader
66
66
  };
67
- }, fetchAndDecodeViaTurboStream, ssr);
67
+ }, fetchAndDecodeViaTurboStream(fetchImplementation, serverOrigin), ssr, void 0, isApiOnly);
68
68
  return async (args) => args.runClientMiddleware(dataStrategy);
69
69
  }
70
- function getSingleFetchDataStrategyImpl(getRouter, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut = () => true) {
70
+ function getSingleFetchDataStrategyImpl(getRouter, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut = () => true, isApiOnly = false) {
71
71
  return async (args) => {
72
72
  let { request, matches, fetcherKey } = args;
73
73
  let router = getRouter();
@@ -78,7 +78,7 @@ function getSingleFetchDataStrategyImpl(getRouter, getRouteInfo, fetchAndDecode,
78
78
  });
79
79
  if (!ssr && !foundRevalidatingServerLoader) return nonSsrStrategy(args, getRouteInfo, fetchAndDecode);
80
80
  if (fetcherKey) return singleFetchLoaderFetcherStrategy(args, fetchAndDecode);
81
- return singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut);
81
+ return singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut, isApiOnly);
82
82
  };
83
83
  }
84
84
  async function singleFetchActionStrategy(args, fetchAndDecode) {
@@ -101,28 +101,19 @@ async function singleFetchActionStrategy(args, fetchAndDecode) {
101
101
  async function nonSsrStrategy(args, getRouteInfo, fetchAndDecode) {
102
102
  let matchesToLoad = args.matches.filter((m) => m.shouldCallHandler());
103
103
  let results = {};
104
- await Promise.all(matchesToLoad.map((m) => m.resolve(async (handler) => {
105
- try {
104
+ await Promise.all(matchesToLoad.map(async (m) => {
105
+ let routeId = m.route.id;
106
+ results[routeId] = await m.resolve(async (handler) => {
106
107
  let { hasClientLoader } = getRouteInfo(m);
107
- let routeId = m.route.id;
108
- let result = hasClientLoader ? await handler(async () => {
108
+ return hasClientLoader ? handler(async () => {
109
109
  let { data } = await fetchAndDecode(args, [routeId]);
110
110
  return unwrapSingleFetchResult(data, routeId);
111
- }) : await handler();
112
- results[m.route.id] = {
113
- type: "data",
114
- result
115
- };
116
- } catch (e) {
117
- results[m.route.id] = {
118
- type: "error",
119
- result: e
120
- };
121
- }
122
- })));
111
+ }) : handler();
112
+ });
113
+ }));
123
114
  return results;
124
115
  }
125
- async function singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut = () => true) {
116
+ async function singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, fetchAndDecode, ssr, shouldAllowOptOut = () => true, isApiOnly = false) {
126
117
  let routesParams = /* @__PURE__ */ new Set();
127
118
  let foundOptOutRoute = false;
128
119
  let routeDfds = args.matches.map(() => createDeferred());
@@ -171,7 +162,7 @@ async function singleFetchLoaderNavigationStrategy(args, router, getRouteInfo, f
171
162
  }
172
163
  })));
173
164
  await Promise.all(routeDfds.map((d) => d.promise));
174
- if ((!router.state.initialized && router.state.navigation.state === "idle" || routesParams.size === 0) && !window.__reactRouterHdrActive) singleFetchDfd.resolve({ routes: {} });
165
+ if ((!router.state.initialized && router.state.navigation.state === "idle" && !isApiOnly || routesParams.size === 0) && !window.__reactRouterHdrActive) singleFetchDfd.resolve({ routes: {} });
175
166
  else {
176
167
  let targetRoutes = ssr && foundOptOutRoute && routesParams.size > 0 ? [...routesParams.keys()] : void 0;
177
168
  try {
@@ -225,61 +216,79 @@ function stripIndexParam(url) {
225
216
  for (let toKeep of indexValuesToKeep) url.searchParams.append("index", toKeep);
226
217
  return url;
227
218
  }
228
- function singleFetchUrl(reqUrl, extension) {
229
- let url = typeof reqUrl === "string" ? new URL(reqUrl, typeof window === "undefined" ? "server://singlefetch/" : window.location.origin) : reqUrl;
219
+ function singleFetchUrl(reqUrl, extension, serverOrigin) {
220
+ let url = typeof reqUrl === "string" ? new URL(reqUrl, serverOrigin ?? (typeof window === "undefined" ? "server://singlefetch/" : window.location.origin)) : new URL(reqUrl);
221
+ if (serverOrigin && url.origin !== serverOrigin) url = new URL(url.pathname + url.search + url.hash, serverOrigin);
230
222
  if (url.pathname.endsWith("/")) url.pathname = `${url.pathname}_.${extension}`;
231
223
  else url.pathname = `${url.pathname}.${extension}`;
232
224
  return url;
233
225
  }
234
- async function fetchAndDecodeViaTurboStream(args, targetRoutes) {
235
- let { request } = args;
236
- let url = singleFetchUrl(request.url, "data");
237
- if (request.method === "GET") {
238
- url = stripIndexParam(url);
239
- if (targetRoutes) url.searchParams.set("_routes", targetRoutes.join(","));
240
- }
241
- let res = await fetch(url, await createRequestInit(request));
242
- if (res.status >= 400 && !res.headers.has("X-Remix-Response")) throw new ErrorResponseImpl(res.status, res.statusText, await res.text());
243
- if (res.status === 204 && res.headers.has("X-Remix-Redirect")) return {
244
- status: 202,
245
- data: { redirect: {
246
- redirect: res.headers.get("X-Remix-Redirect"),
247
- status: Number(res.headers.get("X-Remix-Status") || "302"),
248
- revalidate: res.headers.get("X-Remix-Revalidate") === "true",
249
- reload: res.headers.get("X-Remix-Reload-Document") === "true",
250
- replace: res.headers.get("X-Remix-Replace") === "true"
251
- } }
252
- };
253
- if (NO_BODY_STATUS_CODES.has(res.status)) {
254
- let routes = {};
255
- if (targetRoutes && request.method !== "GET") routes[targetRoutes[0]] = { data: void 0 };
256
- return {
257
- status: res.status,
258
- data: { routes }
259
- };
260
- }
261
- invariant(res.body, "No response body to decode");
262
- try {
263
- let decoded = await decodeViaTurboStream(res.body, window);
264
- let data;
226
+ function fetchAndDecodeViaTurboStream(fetchImplementation, serverOrigin) {
227
+ return async (args, targetRoutes) => {
228
+ let { request } = args;
229
+ let url = singleFetchUrl(request.url, "data", serverOrigin);
265
230
  if (request.method === "GET") {
266
- let typed = decoded.value;
267
- if (SingleFetchRedirectSymbol in typed) data = { redirect: typed[SingleFetchRedirectSymbol] };
268
- else data = { routes: typed };
269
- } else {
270
- let typed = decoded.value;
271
- let routeId = targetRoutes?.[0];
272
- invariant(routeId, "No routeId found for single fetch call decoding");
273
- if ("redirect" in typed) data = { redirect: typed };
274
- else data = { routes: { [routeId]: typed } };
231
+ url = stripIndexParam(url);
232
+ if (targetRoutes) url.searchParams.set("_routes", targetRoutes.join(","));
275
233
  }
276
- return {
277
- status: res.status,
278
- data
234
+ let req = new Request(url, await createRequestInit(request));
235
+ invariant(args.unstable_initiator !== "static", "Static data strategy initiator used for a client data request");
236
+ let fetchContext;
237
+ if (args.unstable_initiator === "navigation") {
238
+ invariant(args.unstable_navigationType !== null, "Missing navigation type for a navigation data request");
239
+ fetchContext = {
240
+ type: "navigation",
241
+ fetcherKey: args.fetcherKey,
242
+ navigationType: args.unstable_navigationType
243
+ };
244
+ } else fetchContext = {
245
+ type: args.unstable_initiator,
246
+ fetcherKey: args.fetcherKey,
247
+ navigationType: null
279
248
  };
280
- } catch {
281
- throw new Error("Unable to decode turbo-stream response");
282
- }
249
+ let res = await fetchImplementation(req, fetchContext);
250
+ if (res.status >= 400 && !res.headers.has("X-Remix-Response")) throw new ErrorResponseImpl(res.status, res.statusText, await res.text());
251
+ if (res.status === 204 && res.headers.has("X-Remix-Redirect")) return {
252
+ status: 202,
253
+ data: { redirect: {
254
+ redirect: res.headers.get("X-Remix-Redirect"),
255
+ status: Number(res.headers.get("X-Remix-Status") || "302"),
256
+ revalidate: res.headers.get("X-Remix-Revalidate") === "true",
257
+ reload: res.headers.get("X-Remix-Reload-Document") === "true",
258
+ replace: res.headers.get("X-Remix-Replace") === "true"
259
+ } }
260
+ };
261
+ if (NO_BODY_STATUS_CODES.has(res.status)) {
262
+ let routes = {};
263
+ if (targetRoutes && request.method !== "GET") routes[targetRoutes[0]] = { data: void 0 };
264
+ return {
265
+ status: res.status,
266
+ data: { routes }
267
+ };
268
+ }
269
+ invariant(res.body, "No response body to decode");
270
+ try {
271
+ let decoded = await decodeViaTurboStream(res.body, window);
272
+ let data;
273
+ if (request.method === "GET") {
274
+ let typed = decoded.value;
275
+ if (SingleFetchRedirectSymbol in typed) data = { redirect: typed[SingleFetchRedirectSymbol] };
276
+ else data = { routes: typed };
277
+ } else {
278
+ let typed = decoded.value;
279
+ let routeId = targetRoutes?.[0];
280
+ invariant(routeId, "No routeId found for single fetch call decoding");
281
+ if ("redirect" in typed) data = { redirect: typed };
282
+ else data = { routes: { [routeId]: typed } };
283
+ }
284
+ return {
285
+ status: res.status,
286
+ data
287
+ };
288
+ } catch (cause) {
289
+ throw new Error("Unable to decode turbo-stream response", { cause });
290
+ }
291
+ };
283
292
  }
284
293
  function decodeViaTurboStream(body, global) {
285
294
  return decode(body, { plugins: [(type, ...rest) => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,4 +1,5 @@
1
1
 
2
+ import { RouterFetch } from "../dom/ssr/single-fetch.js";
2
3
  import { ClientInstrumentation } from "../router/instrumentation.js";
3
4
  import * as React$1 from "react";
4
5
  import { ClientOnErrorFunction, RouterInit } from "react-router";
@@ -107,6 +108,32 @@ interface HydratedRouterProps {
107
108
  * For more information, please see the [docs](../../explanation/react-transitions).
108
109
  */
109
110
  useTransitions?: boolean;
111
+ /**
112
+ * <docs-warning>This prop is experimental and subject to breaking
113
+ * changes.</docs-warning>
114
+ *
115
+ * Provide a custom implementation for `fetch`, which will be used to perform
116
+ * JavaScript-issued manifest and data requests. The context identifies the
117
+ * operation that initiated each request. Defaults to `window.fetch`.
118
+ *
119
+ * This prop is read when the singleton router is created. Changing it after
120
+ * router initialization has no effect. To use changing values such as auth
121
+ * tokens, read current application state inside the function rather than
122
+ * capturing values from a component render.
123
+ *
124
+ * See the [Custom Fetch guide](../../how-to/custom-fetch) for examples of
125
+ * authentication headers, cross-origin credentials, traversal caching, and
126
+ * retries.
127
+ *
128
+ * <docs-info>
129
+ * Browser-managed data prefetches from {@link Link}, {@link NavLink}, or
130
+ * {@link PrefetchPageLinks} use native `<link rel="prefetch">` elements
131
+ * and do not call this function. If your data requests require custom headers
132
+ * or other request transformations, use `prefetch="none"` on links and avoid
133
+ * rendering {@link PrefetchPageLinks}.
134
+ * </docs-info>
135
+ */
136
+ unstable_fetch?: RouterFetch;
110
137
  }
111
138
  /**
112
139
  * Framework-mode router component to be used to hydrate a router from a
@@ -118,6 +145,7 @@ interface HydratedRouterProps {
118
145
  * @param props Props
119
146
  * @param {dom.HydratedRouterProps.getContext} props.getContext n/a
120
147
  * @param {dom.HydratedRouterProps.onError} props.onError n/a
148
+ * @param {dom.HydratedRouterProps.unstable_fetch} props.unstable_fetch n/a
121
149
  * @returns A React element that represents the hydrated application.
122
150
  */
123
151
  declare function HydratedRouter(props: HydratedRouterProps): React$1.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -11,10 +11,11 @@
11
11
  import { CRITICAL_CSS_DATA_ATTRIBUTE } from "../dom/ssr/components.js";
12
12
  import { RouterProvider as RouterProvider$1 } from "./dom-router-provider.js";
13
13
  import * as React$1 from "react";
14
- import { UNSAFE_FrameworkContext, UNSAFE_RemixErrorBoundary, UNSAFE_createBrowserHistory, UNSAFE_createClientRoutes, UNSAFE_createClientRoutesWithHMRRevalidationOptOut, UNSAFE_createRouter, UNSAFE_decodeViaTurboStream, UNSAFE_defaultMapRouteProperties, UNSAFE_getHydrationData, UNSAFE_getPatchRoutesOnNavigationFunction, UNSAFE_getTurboStreamSingleFetchDataStrategy, UNSAFE_hydrationRouteProperties, UNSAFE_invariant, UNSAFE_useFogOFWarDiscovery } from "react-router";
14
+ import { UNSAFE_FrameworkContext, UNSAFE_RemixErrorBoundary, UNSAFE_RouteDiscoveryRuntime, UNSAFE_createBrowserHistory, UNSAFE_createClientRoutes, UNSAFE_createClientRoutesWithHMRRevalidationOptOut, UNSAFE_createRouter, UNSAFE_decodeViaTurboStream, UNSAFE_defaultMapRouteProperties, UNSAFE_getCustomPatchRoutesOnNavigationFunction, UNSAFE_getHydrationData, UNSAFE_getPatchRoutesOnNavigationFunction, UNSAFE_getTurboStreamSingleFetchDataStrategy, UNSAFE_hydrationRouteProperties, UNSAFE_invariant, UNSAFE_useCustomRouteDiscovery, UNSAFE_useFogOFWarDiscovery } from "react-router";
15
15
  //#region lib/dom-export/hydrated-router.tsx
16
16
  let ssrInfo = null;
17
17
  let router = null;
18
+ let fetchImplementation = (request) => window.fetch(request);
18
19
  function initSsrInfo() {
19
20
  if (!ssrInfo && window.__reactRouterContext && window.__reactRouterManifest && window.__reactRouterRouteModules) {
20
21
  if (window.__reactRouterManifest.sri === true) {
@@ -31,14 +32,17 @@ function initSsrInfo() {
31
32
  routeModules: window.__reactRouterRouteModules,
32
33
  stateDecodingPromise: void 0,
33
34
  router: void 0,
35
+ routeDiscoveryRuntime: void 0,
34
36
  routerInitialized: false
35
37
  };
36
38
  }
37
39
  }
38
- function createHydratedRouter({ getContext, instrumentations }) {
40
+ function createHydratedRouter({ getContext, instrumentations, fetch: fetchImplementation }) {
39
41
  initSsrInfo();
40
42
  if (!ssrInfo) throw new Error("You must be using the SSR features of React Router in order to skip passing a `router` prop to `<RouterProvider>`");
41
43
  let localSsrInfo = ssrInfo;
44
+ let isApiOnly = ssrInfo.context.unstable_apiOnly === true;
45
+ let ssr = ssrInfo.context.ssr;
42
46
  if (!ssrInfo.stateDecodingPromise) {
43
47
  let stream = ssrInfo.context.stream;
44
48
  UNSAFE_invariant(stream, "No stream found for single fetch decoding");
@@ -52,7 +56,7 @@ function createHydratedRouter({ getContext, instrumentations }) {
52
56
  }
53
57
  if (ssrInfo.stateDecodingPromise.error) throw ssrInfo.stateDecodingPromise.error;
54
58
  if (!ssrInfo.stateDecodingPromise.value) throw ssrInfo.stateDecodingPromise;
55
- let routes = UNSAFE_createClientRoutes(ssrInfo.manifest.routes, ssrInfo.routeModules, ssrInfo.context.state, ssrInfo.context.ssr, ssrInfo.context.isSpaMode);
59
+ let routes = UNSAFE_createClientRoutes(ssrInfo.manifest.routes, ssrInfo.routeModules, ssrInfo.context.state, ssr, ssrInfo.context.isSpaMode, "", void 0, void 0, isApiOnly);
56
60
  let hydrationData = void 0;
57
61
  if (ssrInfo.context.isSpaMode) {
58
62
  let { loaderData } = ssrInfo.context.state;
@@ -67,25 +71,29 @@ function createHydratedRouter({ getContext, instrumentations }) {
67
71
  }),
68
72
  location: window.location,
69
73
  basename: window.__reactRouterContext?.basename,
74
+ future: ssrInfo.context.future,
70
75
  isSpaMode: ssrInfo.context.isSpaMode
71
76
  });
72
77
  if (window.history.state && window.history.state.masked) window.history.replaceState({
73
78
  ...window.history.state,
74
79
  masked: void 0
75
80
  }, "");
81
+ let discoveryRuntime = ssrInfo.context.future.unstable_customRouteDiscovery ? new UNSAFE_RouteDiscoveryRuntime(ssrInfo, { fetch: fetchImplementation }) : void 0;
76
82
  let router = UNSAFE_createRouter({
77
83
  routes,
78
84
  history: UNSAFE_createBrowserHistory(),
85
+ future: { unstable_customRouteDiscovery: ssrInfo.context.future.unstable_customRouteDiscovery },
79
86
  basename: ssrInfo.context.basename,
80
87
  getContext,
81
88
  hydrationData,
82
89
  mapRouteProperties: UNSAFE_defaultMapRouteProperties,
83
90
  hydrationRouteProperties: UNSAFE_hydrationRouteProperties,
84
91
  instrumentations,
85
- dataStrategy: UNSAFE_getTurboStreamSingleFetchDataStrategy(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr),
86
- patchRoutesOnNavigation: UNSAFE_getPatchRoutesOnNavigationFunction(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode, ssrInfo.context.basename)
92
+ dataStrategy: UNSAFE_getTurboStreamSingleFetchDataStrategy(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssr, fetchImplementation, ssrInfo.context.unstable_apiOnly === true, ssrInfo.context.unstable_apiServerOrigin),
93
+ patchRoutesOnNavigation: discoveryRuntime ? UNSAFE_getCustomPatchRoutesOnNavigationFunction(() => router, discoveryRuntime) : UNSAFE_getPatchRoutesOnNavigationFunction(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode, ssrInfo.context.basename, fetchImplementation, ssrInfo.context.unstable_apiServerOrigin, isApiOnly)
87
94
  });
88
95
  ssrInfo.router = router;
96
+ ssrInfo.routeDiscoveryRuntime = discoveryRuntime;
89
97
  if (router.state.initialized) {
90
98
  ssrInfo.routerInitialized = true;
91
99
  router.initialize();
@@ -104,13 +112,18 @@ function createHydratedRouter({ getContext, instrumentations }) {
104
112
  * @param props Props
105
113
  * @param {dom.HydratedRouterProps.getContext} props.getContext n/a
106
114
  * @param {dom.HydratedRouterProps.onError} props.onError n/a
115
+ * @param {dom.HydratedRouterProps.unstable_fetch} props.unstable_fetch n/a
107
116
  * @returns A React element that represents the hydrated application.
108
117
  */
109
118
  function HydratedRouter(props) {
110
- if (!router) router = createHydratedRouter({
111
- getContext: props.getContext,
112
- instrumentations: props.instrumentations
113
- });
119
+ if (!router) {
120
+ router = createHydratedRouter({
121
+ getContext: props.getContext,
122
+ instrumentations: props.instrumentations,
123
+ fetch: props.unstable_fetch ?? fetchImplementation
124
+ });
125
+ if (props.unstable_fetch) fetchImplementation = props.unstable_fetch;
126
+ }
114
127
  let [criticalCss, setCriticalCss] = React$1.useState(process.env.NODE_ENV === "development" ? ssrInfo?.context.criticalCss : void 0);
115
128
  React$1.useEffect(() => {
116
129
  if (process.env.NODE_ENV === "development") setCriticalCss(void 0);
@@ -131,15 +144,23 @@ function HydratedRouter(props) {
131
144
  });
132
145
  }, [location]);
133
146
  UNSAFE_invariant(ssrInfo, "ssrInfo unavailable for HydratedRouter");
134
- UNSAFE_useFogOFWarDiscovery(router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode);
147
+ let ssr = ssrInfo.context.ssr;
148
+ let discoveryRuntime = ssrInfo.routeDiscoveryRuntime;
149
+ let discoveryState;
150
+ if (discoveryRuntime) discoveryState = UNSAFE_useCustomRouteDiscovery(discoveryRuntime, props.onError);
151
+ else UNSAFE_useFogOFWarDiscovery(router, ssrInfo.manifest, ssrInfo.routeModules, ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode, fetchImplementation, ssrInfo.context.unstable_apiServerOrigin, ssrInfo.context.unstable_apiOnly === true);
135
152
  return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(UNSAFE_FrameworkContext.Provider, { value: {
153
+ routeDiscoveryRuntime: discoveryRuntime,
154
+ routeDiscoveryState: discoveryState,
136
155
  manifest: ssrInfo.manifest,
137
156
  routeModules: ssrInfo.routeModules,
138
157
  future: ssrInfo.context.future,
139
158
  criticalCss,
140
159
  ssr: ssrInfo.context.ssr,
141
160
  isSpaMode: ssrInfo.context.isSpaMode,
142
- routeDiscovery: ssrInfo.context.routeDiscovery
161
+ unstable_apiOnly: ssrInfo.context.unstable_apiOnly,
162
+ routeDiscovery: ssrInfo.context.routeDiscovery,
163
+ unstable_apiServerOrigin: ssrInfo.context.unstable_apiServerOrigin
143
164
  } }, /* @__PURE__ */ React$1.createElement(UNSAFE_RemixErrorBoundary, { location }, /* @__PURE__ */ React$1.createElement(RouterProvider$1, {
144
165
  router,
145
166
  useTransitions: props.useTransitions,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.3.1
2
+ * react-router v8.5.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -3,8 +3,8 @@ import { Action, Location, Path, To } from "./router/history.js";
3
3
  import { ParamParseKey, Params, PathMatch, PathPattern, RouteObject, UIMatch } from "./router/utils.js";
4
4
  import { Blocker, BlockerFunction, NavigationStates, RelativeRoutingType, Router } from "./router/router.js";
5
5
  import { NavigateOptions } from "./context.js";
6
- import { RouteModules } from "./types/register.js";
7
6
  import { GetActionData, GetLoaderData, SerializeFrom } from "./types/route-data.js";
7
+ import { RouteModules } from "./types/register.js";
8
8
  import * as React$1 from "react";
9
9
 
10
10
  //#region lib/hooks.d.ts
@@ -116,7 +116,7 @@ interface NavigateFunction {
116
116
  * * These options only work in Framework and Data modes:
117
117
  * * `flushSync`: Wrap the DOM updates in [`ReactDom.flushSync`](https://react.dev/reference/react-dom/flushSync)
118
118
  * * `preventScrollReset`: Do not scroll back to the top of the page after navigation
119
- * * `viewTransition`: Enable [`document.startViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) for this navigation
119
+ * * `viewTransition`: **Deprecated.** Use React's [`<ViewTransition>`](https://react.dev/reference/react/ViewTransition) component instead. See the [migration guide](../../how-to/view-transitions).
120
120
  *
121
121
  * @example
122
122
  * import { useNavigate } from "react-router";
@@ -939,7 +939,7 @@ type unstable_RouterState = {
939
939
  * @example
940
940
  * import { unstable_useRouterState as useRouterState } from "react-router";
941
941
  *
942
- * let { active, pending } = unstable_useRouterState();
942
+ * let { active, pending } = useRouterState();
943
943
  *
944
944
  * // Active is always populated with the current location
945
945
  * active.location; // replaces `useLocation()`