react-router 8.0.0-pre.0 → 8.0.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 (177) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/development/dom-export.js +1 -1
  3. package/dist/development/index-react-server-client.js +1 -1
  4. package/dist/development/index-react-server.d.ts +9 -2
  5. package/dist/development/index-react-server.js +91 -88
  6. package/dist/development/index.d.ts +1 -2
  7. package/dist/development/index.js +2 -3
  8. package/dist/development/lib/actions.js +6 -18
  9. package/dist/development/lib/components.d.ts +11 -3
  10. package/dist/development/lib/components.js +8 -2
  11. package/dist/development/lib/context.js +1 -1
  12. package/dist/development/lib/dom/dom.js +1 -1
  13. package/dist/development/lib/dom/lib.d.ts +12 -1
  14. package/dist/development/lib/dom/lib.js +18 -6
  15. package/dist/development/lib/dom/server.js +2 -2
  16. package/dist/development/lib/dom/ssr/components.d.ts +4 -2
  17. package/dist/development/lib/dom/ssr/components.js +13 -3
  18. package/dist/development/lib/dom/ssr/data.js +1 -1
  19. package/dist/development/lib/dom/ssr/entry.d.ts +1 -0
  20. package/dist/development/lib/dom/ssr/errorBoundaries.js +7 -3
  21. package/dist/development/lib/dom/ssr/fallback.js +8 -3
  22. package/dist/development/lib/dom/ssr/fog-of-war.js +12 -2
  23. package/dist/development/lib/dom/ssr/hydration.js +1 -1
  24. package/dist/development/lib/dom/ssr/invariant.js +1 -1
  25. package/dist/development/lib/dom/ssr/links.js +1 -1
  26. package/dist/development/lib/dom/ssr/markup.js +1 -1
  27. package/dist/development/lib/dom/ssr/routeModules.js +1 -1
  28. package/dist/development/lib/dom/ssr/routes-test-stub.js +1 -1
  29. package/dist/development/lib/dom/ssr/routes.js +1 -1
  30. package/dist/development/lib/dom/ssr/server.d.ts +4 -1
  31. package/dist/development/lib/dom/ssr/server.js +2 -1
  32. package/dist/development/lib/dom/ssr/single-fetch.js +2 -3
  33. package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
  34. package/dist/development/lib/dom-export/hydrated-router.d.ts +1 -1
  35. package/dist/development/lib/dom-export/hydrated-router.js +14 -17
  36. package/dist/development/lib/errors.js +1 -1
  37. package/dist/development/lib/hooks.js +6 -4
  38. package/dist/development/lib/href.js +1 -1
  39. package/dist/development/lib/router/history.js +3 -2
  40. package/dist/development/lib/router/instrumentation.js +1 -1
  41. package/dist/development/lib/router/links.d.ts +3 -2
  42. package/dist/development/lib/router/router.js +13 -6
  43. package/dist/development/lib/router/url.js +18 -0
  44. package/dist/development/lib/router/utils.d.ts +6 -0
  45. package/dist/development/lib/router/utils.js +27 -8
  46. package/dist/development/lib/rsc/browser.js +21 -17
  47. package/dist/development/lib/rsc/errorBoundaries.js +1 -1
  48. package/dist/development/lib/rsc/html-stream/browser.js +1 -1
  49. package/dist/development/lib/rsc/html-stream/server.js +1 -1
  50. package/dist/development/lib/rsc/route-modules.js +1 -1
  51. package/dist/development/lib/rsc/server.ssr.js +27 -11
  52. package/dist/development/lib/server-runtime/cookies.js +1 -1
  53. package/dist/development/lib/server-runtime/crypto.js +1 -1
  54. package/dist/development/lib/server-runtime/data.js +1 -1
  55. package/dist/development/lib/server-runtime/dev.js +1 -1
  56. package/dist/development/lib/server-runtime/entry.js +1 -1
  57. package/dist/development/lib/server-runtime/errors.js +2 -22
  58. package/dist/development/lib/server-runtime/headers.js +1 -1
  59. package/dist/development/lib/server-runtime/invariant.js +1 -1
  60. package/dist/development/lib/server-runtime/mode.js +1 -1
  61. package/dist/development/lib/server-runtime/routeMatching.js +1 -1
  62. package/dist/development/lib/server-runtime/routes.js +1 -1
  63. package/dist/development/lib/server-runtime/server.js +17 -23
  64. package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
  65. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
  66. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
  67. package/dist/development/lib/server-runtime/sessions.js +1 -1
  68. package/dist/development/lib/server-runtime/single-fetch.js +4 -4
  69. package/dist/development/lib/server-runtime/urls.js +2 -5
  70. package/dist/development/lib/server-runtime/warnings.js +1 -1
  71. package/dist/development/lib/types/internal.js +1 -1
  72. package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
  73. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +2 -1
  74. package/dist/development/vendor/turbo-stream-v2/unflatten.js +3 -2
  75. package/dist/development/vendor/turbo-stream-v2/utils.js +2 -10
  76. package/dist/production/dom-export.js +1 -1
  77. package/dist/production/index-react-server-client.js +1 -1
  78. package/dist/production/index-react-server.d.ts +9 -2
  79. package/dist/production/index-react-server.js +91 -88
  80. package/dist/production/index.d.ts +1 -2
  81. package/dist/production/index.js +2 -3
  82. package/dist/production/lib/actions.js +6 -18
  83. package/dist/production/lib/components.d.ts +11 -3
  84. package/dist/production/lib/components.js +8 -2
  85. package/dist/production/lib/context.js +1 -1
  86. package/dist/production/lib/dom/dom.js +1 -1
  87. package/dist/production/lib/dom/lib.d.ts +12 -1
  88. package/dist/production/lib/dom/lib.js +18 -6
  89. package/dist/production/lib/dom/server.js +2 -2
  90. package/dist/production/lib/dom/ssr/components.d.ts +4 -2
  91. package/dist/production/lib/dom/ssr/components.js +13 -3
  92. package/dist/production/lib/dom/ssr/data.js +1 -1
  93. package/dist/production/lib/dom/ssr/entry.d.ts +1 -0
  94. package/dist/production/lib/dom/ssr/errorBoundaries.js +7 -3
  95. package/dist/production/lib/dom/ssr/fallback.js +3 -1
  96. package/dist/production/lib/dom/ssr/fog-of-war.js +12 -2
  97. package/dist/production/lib/dom/ssr/hydration.js +1 -1
  98. package/dist/production/lib/dom/ssr/invariant.js +1 -1
  99. package/dist/production/lib/dom/ssr/links.js +1 -1
  100. package/dist/production/lib/dom/ssr/markup.js +1 -1
  101. package/dist/production/lib/dom/ssr/routeModules.js +1 -1
  102. package/dist/production/lib/dom/ssr/routes-test-stub.js +1 -1
  103. package/dist/production/lib/dom/ssr/routes.js +1 -1
  104. package/dist/production/lib/dom/ssr/server.d.ts +4 -1
  105. package/dist/production/lib/dom/ssr/server.js +2 -1
  106. package/dist/production/lib/dom/ssr/single-fetch.js +2 -3
  107. package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
  108. package/dist/production/lib/dom-export/hydrated-router.d.ts +1 -1
  109. package/dist/production/lib/dom-export/hydrated-router.js +14 -17
  110. package/dist/production/lib/errors.js +1 -1
  111. package/dist/production/lib/hooks.js +6 -4
  112. package/dist/production/lib/href.js +1 -1
  113. package/dist/production/lib/router/history.js +3 -2
  114. package/dist/production/lib/router/instrumentation.js +1 -1
  115. package/dist/production/lib/router/links.d.ts +3 -2
  116. package/dist/production/lib/router/router.js +13 -6
  117. package/dist/production/lib/router/url.js +18 -0
  118. package/dist/production/lib/router/utils.d.ts +6 -0
  119. package/dist/production/lib/router/utils.js +27 -8
  120. package/dist/production/lib/rsc/browser.js +21 -17
  121. package/dist/production/lib/rsc/errorBoundaries.js +1 -1
  122. package/dist/production/lib/rsc/html-stream/browser.js +1 -1
  123. package/dist/production/lib/rsc/html-stream/server.js +1 -1
  124. package/dist/production/lib/rsc/route-modules.js +1 -1
  125. package/dist/production/lib/rsc/server.ssr.js +27 -11
  126. package/dist/production/lib/server-runtime/cookies.js +1 -1
  127. package/dist/production/lib/server-runtime/crypto.js +1 -1
  128. package/dist/production/lib/server-runtime/data.js +1 -1
  129. package/dist/production/lib/server-runtime/dev.js +1 -1
  130. package/dist/production/lib/server-runtime/entry.js +1 -1
  131. package/dist/production/lib/server-runtime/errors.js +2 -22
  132. package/dist/production/lib/server-runtime/headers.js +1 -1
  133. package/dist/production/lib/server-runtime/invariant.js +1 -1
  134. package/dist/production/lib/server-runtime/mode.js +1 -1
  135. package/dist/production/lib/server-runtime/routeMatching.js +1 -1
  136. package/dist/production/lib/server-runtime/routes.js +1 -1
  137. package/dist/production/lib/server-runtime/server.js +17 -23
  138. package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
  139. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
  140. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
  141. package/dist/production/lib/server-runtime/sessions.js +1 -1
  142. package/dist/production/lib/server-runtime/single-fetch.js +4 -4
  143. package/dist/production/lib/server-runtime/urls.js +2 -5
  144. package/dist/production/lib/server-runtime/warnings.js +1 -1
  145. package/dist/production/lib/types/internal.js +1 -1
  146. package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
  147. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +2 -1
  148. package/dist/production/vendor/turbo-stream-v2/unflatten.js +3 -2
  149. package/dist/production/vendor/turbo-stream-v2/utils.js +2 -10
  150. package/docs/explanation/code-splitting.md +1 -1
  151. package/docs/explanation/index-query-param.md +2 -2
  152. package/docs/explanation/type-safety.md +1 -1
  153. package/docs/how-to/data-strategy.md +5 -5
  154. package/docs/how-to/error-reporting.md +10 -2
  155. package/docs/how-to/headers.md +2 -1
  156. package/docs/how-to/middleware.md +8 -89
  157. package/docs/how-to/security.md +9 -7
  158. package/docs/how-to/status.md +1 -1
  159. package/docs/index.md +3 -6
  160. package/docs/start/data/installation.md +4 -0
  161. package/docs/start/data/route-object.md +20 -0
  162. package/docs/start/framework/actions.md +0 -1
  163. package/docs/start/framework/data-loading.md +1 -1
  164. package/docs/start/framework/deploying.md +4 -0
  165. package/docs/start/framework/installation.md +0 -1
  166. package/docs/start/modes.md +1 -2
  167. package/docs/upgrading/component-routes.md +2 -2
  168. package/docs/upgrading/future.md +58 -11
  169. package/docs/upgrading/router-provider.md +6 -3
  170. package/docs/upgrading/v7.md +443 -0
  171. package/package.json +7 -7
  172. package/dist/development/lib/dom/ssr/errors.d.ts +0 -7
  173. package/dist/development/lib/dom/ssr/errors.js +0 -36
  174. package/dist/production/lib/dom/ssr/errors.d.ts +0 -7
  175. package/dist/production/lib/dom/ssr/errors.js +0 -36
  176. package/docs/upgrading/remix.md +0 -403
  177. package/docs/upgrading/v6.md +0 -379
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,13 +8,13 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, stripBasename } from "../router/utils.js";
11
+ import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, removeTrailingSlash, stripBasename } from "../router/utils.js";
12
12
  import { instrumentHandler } from "../router/instrumentation.js";
13
13
  import { createStaticHandler, getStaticContextFromError, isMutationMethod, isRedirectResponse, isResponse } from "../router/router.js";
14
14
  import { getManifestPath } from "../dom/ssr/fog-of-war.js";
15
15
  import { createEntryRouteModules } from "./entry.js";
16
16
  import { isServerMode } from "./mode.js";
17
- import { sanitizeErrors, serializeError, serializeErrors } from "./errors.js";
17
+ import { sanitizeErrors, serializeError } from "./errors.js";
18
18
  import { matchServerRoutes } from "./routeMatching.js";
19
19
  import { getBuildTimeHeader, getDevServerHooks } from "./dev.js";
20
20
  import { createStaticHandlerDataRoutes } from "./routes.js";
@@ -54,7 +54,7 @@ function derive(build, mode) {
54
54
  }
55
55
  loadContext = initialContext || new RouterContextProvider();
56
56
  let requestUrl = new URL(request.url);
57
- let normalizedPathname = getNormalizedPath(request, build.basename).pathname;
57
+ let normalizedPathname = getNormalizedPath(request).pathname;
58
58
  let isSpaMode = getBuildTimeHeader(request, "X-React-Router-SPA-Mode") === "yes";
59
59
  if (!build.ssr) {
60
60
  let decodedPath = decodeURI(normalizedPathname);
@@ -74,7 +74,7 @@ function derive(build, mode) {
74
74
  decodedPath = strippedPath;
75
75
  }
76
76
  if (build.prerender.length === 0) isSpaMode = true;
77
- else if (!build.prerender.includes(decodedPath) && !build.prerender.includes(decodedPath + "/")) if (requestUrl.pathname.endsWith(".data")) {
77
+ else if (!build.prerender.some((p) => removeTrailingSlash(p) === removeTrailingSlash(decodedPath))) if (requestUrl.pathname.endsWith(".data")) {
78
78
  errorHandler(new ErrorResponseImpl(404, "Not Found", `Refusing to SSR the path \`${decodedPath}\` because \`ssr:false\` is set and the path is not included in the \`prerender\` config, so in production the path will be a 404.`), {
79
79
  context: loadContext,
80
80
  params,
@@ -155,26 +155,20 @@ const createRequestHandler = (build, mode) => {
155
155
  };
156
156
  };
157
157
  async function handleManifestRequest(build, dataRoutes, branches, url) {
158
- if (build.assets.version !== url.searchParams.get("version")) return new Response(null, {
159
- status: 204,
160
- headers: { "X-Remix-Reload-Document": "true" }
161
- });
162
158
  if (url.toString().length > 7680) return new Response(null, {
163
159
  statusText: "Bad Request",
164
160
  status: 400
165
161
  });
162
+ if (build.assets.version !== url.searchParams.get("version")) return new Response(null, {
163
+ status: 204,
164
+ headers: { "X-Remix-Reload-Document": "true" }
165
+ });
166
166
  let patches = {};
167
167
  if (url.searchParams.has("paths")) {
168
- let paths = /* @__PURE__ */ new Set();
169
- (url.searchParams.get("paths") || "").split(",").filter(Boolean).forEach((path) => {
170
- if (!path.startsWith("/")) path = `/${path}`;
171
- let segments = path.split("/").slice(1);
172
- segments.forEach((_, i) => {
173
- let partialPath = segments.slice(0, i + 1).join("/");
174
- paths.add(`/${partialPath}`);
175
- });
176
- });
168
+ let pathParam = url.searchParams.get("paths") || "";
169
+ let paths = new Set(pathParam.split(",").filter(Boolean));
177
170
  for (let path of paths) {
171
+ if (!path.startsWith("/")) path = `/${path}`;
178
172
  let matches = matchServerRoutes(build.routes, dataRoutes, branches, path, build.basename);
179
173
  if (matches) for (let match of matches) {
180
174
  let routeId = match.route.id;
@@ -192,7 +186,7 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
192
186
  async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, isSpaMode, criticalCss) {
193
187
  try {
194
188
  if (isMutationMethod(request.method)) try {
195
- throwIfPotentialCSRFAttack(request.headers, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
189
+ throwIfPotentialCSRFAttack(request, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
196
190
  } catch (e) {
197
191
  handleError(e);
198
192
  return new Response("Bad Request", { status: 400 });
@@ -209,7 +203,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
209
203
  return new Response(null, { status: 500 });
210
204
  }
211
205
  },
212
- normalizePath: (r) => getNormalizedPath(r, build.basename)
206
+ normalizePath: (r) => getNormalizedPath(r)
213
207
  });
214
208
  if (!isResponse(result)) result = await renderHtml(result, isSpaMode);
215
209
  return result;
@@ -232,7 +226,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
232
226
  let state = {
233
227
  loaderData: context.loaderData,
234
228
  actionData: context.actionData,
235
- errors: serializeErrors(context.errors, serverMode)
229
+ errors: context.errors
236
230
  };
237
231
  let baseServerHandoff = {
238
232
  basename: build.basename,
@@ -274,7 +268,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
274
268
  let state = {
275
269
  loaderData: context.loaderData,
276
270
  actionData: context.actionData,
277
- errors: serializeErrors(context.errors, serverMode)
271
+ errors: context.errors
278
272
  };
279
273
  entryContext = {
280
274
  ...entryContext,
@@ -304,7 +298,7 @@ async function handleResourceRequest(serverMode, build, staticHandler, routeId,
304
298
  return handleQueryRouteError(error);
305
299
  }
306
300
  },
307
- normalizePath: (r) => getNormalizedPath(r, build.basename)
301
+ normalizePath: (r) => getNormalizedPath(r)
308
302
  }));
309
303
  } catch (error) {
310
304
  return handleQueryRouteError(error);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -22,7 +22,7 @@ const SERVER_NO_BODY_STATUS_CODES = new Set([...NO_BODY_STATUS_CODES, 304]);
22
22
  async function singleFetchAction(build, serverMode, staticHandler, request, loadContext, handleError) {
23
23
  try {
24
24
  try {
25
- throwIfPotentialCSRFAttack(request.headers, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
25
+ throwIfPotentialCSRFAttack(request, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
26
26
  } catch (e) {
27
27
  return handleQueryError(/* @__PURE__ */ new Error("Bad Request"), 400);
28
28
  }
@@ -37,7 +37,7 @@ async function singleFetchAction(build, serverMode, staticHandler, request, load
37
37
  return handleQueryError(error);
38
38
  }
39
39
  },
40
- normalizePath: (r) => getNormalizedPath(r, build.basename)
40
+ normalizePath: (r) => getNormalizedPath(r)
41
41
  }));
42
42
  } catch (error) {
43
43
  return handleQueryError(error);
@@ -90,7 +90,7 @@ async function singleFetchLoaders(build, serverMode, staticHandler, request, loa
90
90
  return handleQueryError(error);
91
91
  }
92
92
  },
93
- normalizePath: (r) => getNormalizedPath(r, build.basename)
93
+ normalizePath: (r) => getNormalizedPath(r)
94
94
  }));
95
95
  } catch (error) {
96
96
  return handleQueryError(error);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,15 +8,12 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { stripBasename } from "../router/utils.js";
12
11
  //#region lib/server-runtime/urls.ts
13
- function getNormalizedPath(request, basename) {
14
- basename = basename || "/";
12
+ function getNormalizedPath(request) {
15
13
  let url = new URL(request.url);
16
14
  let pathname = url.pathname;
17
15
  if (pathname.endsWith("/_.data")) pathname = pathname.replace(/_\.data$/, "");
18
16
  else pathname = pathname.replace(/\.data$/, "");
19
- if (stripBasename(pathname, basename) !== "/" && pathname.endsWith("/")) pathname = pathname.slice(0, -1);
20
17
  let searchParams = new URLSearchParams(url.search);
21
18
  searchParams.delete("_routes");
22
19
  let search = searchParams.toString();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
+ import "../../lib/router/utils.js";
11
12
  import { Deferred, createLineSplittingTransform } from "./utils.js";
12
13
  import { flatten } from "./flatten.js";
13
14
  import { unflatten } from "./unflatten.js";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,7 +8,8 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { Deferred, SUPPORTED_ERROR_TYPES } from "./utils.js";
11
+ import { SUPPORTED_ERROR_TYPES } from "../../lib/router/utils.js";
12
+ import { Deferred } from "./utils.js";
12
13
  //#region vendor/turbo-stream-v2/unflatten.ts
13
14
  const globalObj = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : void 0;
14
15
  function unflatten(parsed) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -9,14 +9,6 @@
9
9
  * @license MIT
10
10
  */
11
11
  //#region vendor/turbo-stream-v2/utils.ts
12
- const SUPPORTED_ERROR_TYPES = [
13
- "EvalError",
14
- "RangeError",
15
- "ReferenceError",
16
- "SyntaxError",
17
- "TypeError",
18
- "URIError"
19
- ];
20
12
  var Deferred = class {
21
13
  promise;
22
14
  resolve;
@@ -44,4 +36,4 @@ function createLineSplittingTransform() {
44
36
  });
45
37
  }
46
38
  //#endregion
47
- export { Deferred, SUPPORTED_ERROR_TYPES, createLineSplittingTransform };
39
+ export { Deferred, createLineSplittingTransform };
@@ -74,4 +74,4 @@ export default function Component({ loaderData }) {
74
74
 
75
75
  After building for the browser, only the `Component` will still be in the bundle, so you can use server-only code in the other module exports.
76
76
 
77
- [route-module]: ../../start/framework/route-module
77
+ [route-module]: ../start/framework/route-module
@@ -80,7 +80,7 @@ function Component() {
80
80
  }
81
81
  ```
82
82
 
83
- [loader]: ../api/data-routers/loader
83
+ [loader]: ../start/data/route-object#loader
84
84
  [form_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
85
85
  [form_component]: ../api/components/Form
86
- [action]: ../api/data-routers/action
86
+ [action]: ../start/data/route-object#action
@@ -50,7 +50,7 @@ React Router's type generation executes your route config (`app/routes.ts` by de
50
50
  It then generates a `+types/<route file>.d.ts` for each route within a special `.react-router/types/` directory.
51
51
  With [`rootDirs` configured][route-module-type-safety], TypeScript can import these generated files as if they were right next to their corresponding route modules.
52
52
 
53
- For a deeper dive into some of the design decisions, check out our [type inference decision doc](https://github.com/remix-run/react-router/blob/dev/decisions/0012-type-inference.md).
53
+ For a deeper dive into some of the design decisions, check out our [type inference decision doc](https://github.com/remix-run/react-router/blob/main/decisions/0012-type-inference.md).
54
54
 
55
55
  [route-module-type-safety]: ../how-to/route-module-type-safety
56
56
 
@@ -158,11 +158,11 @@ const matchesToLoad = matches.filter((match) => {
158
158
 
159
159
  ## Migrating away from `shouldLoad`
160
160
 
161
- Now that we have stabilized the new `match.shouldCallHandler()`/`match.shouldRevalidateArgs` fields, it's recommended to move away from the now-deprecated `match.shouldLoad` API. The prior boolean approach did not allow for custom `dataStrategy`functions to alter the default revalidation behavior, so the new function-based APIs were created to allow that.
161
+ Now that we have stabilized the new `match.shouldCallHandler()`/`match.shouldRevalidateArgs` fields, it's recommended to move away from the now-deprecated `match.shouldLoad` API. The prior boolean approach did not allow for custom `dataStrategy` functions to alter the default revalidation behavior, so the new function-based APIs were created to allow that.
162
162
 
163
163
  The major difference between these two APIs is that when using `shouldLoad`, calling `resolve()` would _only_ call the handler if `shouldLoad` was `true`. You could safely call it for all matches even if only a subset needed to have their handlers executed.
164
164
 
165
- With `shouldCallHandler`, you are in charge of which handlers should be called so calling resolve will automatically call the handler. You should only call resolve on a the set of matches you wish to run handlers for.
165
+ With `shouldCallHandler`, you are in charge of which handlers should be called so calling resolve will automatically call the handler. You should only call resolve on the set of matches you wish to run handlers for.
166
166
 
167
167
  Here's an example change from the prior API to the new API. Note that we pre-filter the `matchesToLoad` before calling `resolve()`:
168
168
 
@@ -184,9 +184,9 @@ return results;
184
184
 
185
185
  <docs-info>This is an unlikely use-case now that React Router has built-in middleware, but if you wish to use a custom middleware you can do so with a `dataStrategy`.</docs-info>
186
186
 
187
- Let's define a middleware on each route via [`handle`](../../start/data/route-object#handle)
187
+ Let's define a middleware on each route via [`handle`](../start/data/route-object#handle)
188
188
  and call middleware sequentially first, then call all
189
- [`loader`](../../start/data/route-object#loader)s in parallel - providing
189
+ [`loader`](../start/data/route-object#loader)s in parallel - providing
190
190
  any data made available via the middleware:
191
191
 
192
192
  ```ts
@@ -258,7 +258,7 @@ let router = createBrowserRouter(routes, {
258
258
 
259
259
  ### Custom Handler
260
260
 
261
- It's also possible you don't even want to define a [`loader`](../../start/daoute-object#loader)
261
+ It's also possible you don't even want to define a [`loader`](../start/data/route-object#loader)
262
262
  implementation at the route level. Maybe you want to just determine the
263
263
  routes and issue a single GraphQL request for all of your data. You can do
264
264
  that by setting your `route.loader=true` so it qualifies as "having a
@@ -104,7 +104,11 @@ See also:
104
104
  This function is called whenever React Router catches an error in your application on the client.
105
105
 
106
106
  ```tsx
107
- import { type ClientOnErrorFunction } from "react-router";
107
+ import {
108
+ createBrowserRouter,
109
+ type ClientOnErrorFunction,
110
+ } from "react-router";
111
+ import { RouterProvider } from "react-router/dom";
108
112
 
109
113
  const onError: ClientOnErrorFunction = (
110
114
  error,
@@ -116,8 +120,12 @@ const onError: ClientOnErrorFunction = (
116
120
  console.error(error, errorInfo);
117
121
  };
118
122
 
123
+ const router = createBrowserRouter(routes);
124
+
119
125
  function App() {
120
- return <RouterProvider onError={onError} />;
126
+ return (
127
+ <RouterProvider router={router} onError={onError} />
128
+ );
121
129
  }
122
130
  ```
123
131
 
@@ -110,7 +110,8 @@ The easiest way is to simply append to the parent headers. This avoids overwriti
110
110
  ```tsx
111
111
  export function headers({ parentHeaders }: HeadersArgs) {
112
112
  parentHeaders.append(
113
- "Permissions-Policy: geolocation=()",
113
+ "Permissions-Policy",
114
+ "geolocation=()",
114
115
  );
115
116
  return parentHeaders;
116
117
  }
@@ -91,24 +91,18 @@ export default function Dashboard({
91
91
  }
92
92
  ```
93
93
 
94
- ### 3. Update your `getLoadContext` function (if applicable)
94
+ ### 3. Add a `getLoadContext` function (if applicable)
95
95
 
96
- If you're using a custom server and a `getLoadContext` function, you will need to update your implementation to return an instance of [`RouterContextProvider`][RouterContextProvider], instead of a JavaScript object:
96
+ If you're using a custom server, you can use a `getLoadContext` function to pass information to into the react router handlers:
97
97
 
98
- ```diff
99
- +import {
100
- + createContext,
101
- + RouterContextProvider,
102
- +} from "react-router";
103
- import { createDb } from "./db";
104
-
105
- +const dbContext = createContext<Database>();
98
+ ```tsx
99
+ import { RouterContextProvider } from "react-router";
100
+ import { dbContext, createDb } from "./db";
106
101
 
107
102
  function getLoadContext(req, res) {
108
- - return { db: createDb() };
109
- + const context = new RouterContextProvider();
110
- + context.set(dbContext, createDb());
111
- + return context;
103
+ const context = new RouterContextProvider();
104
+ context.set(dbContext, createDb());
105
+ return context;
112
106
  }
113
107
  ```
114
108
 
@@ -474,72 +468,6 @@ export const middleware: Route.MiddlewareFunction[] = [
474
468
 
475
469
  Which `ErrorBoundary` is rendered will differ based on whether your middleware threw _before_ or _after_ calling then `next()` function. If it throws _after_ then it will bubble up from the throwing route just like a normal loader error because we've already run the loaders and have the appropriate `loaderData` to render in the route components. However, if an error is thrown _before_ calling `next()`, then we haven't called any loaders yet and there is no `loaderData` available. When this happens, we must bubble up to the highest route with a `loader` and start looking for an `ErrorBoundary` there. We cannot render any route components at that level or below without any `loaderData`.
476
470
 
477
- ## Changes to `getLoadContext`/`AppLoadContext`
478
-
479
- <docs-info>This only applies if you are using a custom server and a custom `getLoadContext` function</docs-info>
480
-
481
- Middleware introduces a breaking change to the `context` parameter generated by `getLoadContext` and passed to your `action`s and `loader`s. The current approach of a module-augmented `AppLoadContext` isn't really type-safe and instead just sort of tells TypeScript to "trust me".
482
-
483
- Middleware needs an equivalent `context` on the client for `clientMiddleware`, but we didn't want to duplicate this pattern from the server that we already weren't thrilled with, so we decided to introduce a new API where we could tackle type-safety.
484
-
485
- When opting into middleware, the `context` parameter changes to an instance of [`RouterContextProvider`][RouterContextProvider]:
486
-
487
- ```ts
488
- let dbContext = createContext<Database>();
489
- let context = new RouterContextProvider();
490
- context.set(dbContext, getDb());
491
- // ^ type-safe
492
- let db = context.get(dbContext);
493
- // ^ Database
494
- ```
495
-
496
- If you're using a custom server and a `getLoadContext` function, you will need to update your implementation to return an instance of [`RouterContextProvider`][RouterContextProvider], instead of a plain JavaScript object:
497
-
498
- ```diff
499
- +import {
500
- + createContext,
501
- + RouterContextProvider,
502
- +} from "react-router";
503
- import { createDb } from "./db";
504
-
505
- +const dbContext = createContext<Database>();
506
-
507
- function getLoadContext(req, res) {
508
- - return { db: createDb() };
509
- + const context = new RouterContextProvider();
510
- + context.set(dbContext, createDb());
511
- + return context;
512
- }
513
- ```
514
-
515
- ### Migration from `AppLoadContext`
516
-
517
- If you're currently using `AppLoadContext`, you can migrate incrementally by using your existing module augmentation to augment [`RouterContextProvider`][RouterContextProvider] instead of `AppLoadContext`. Then, update your `getLoadContext` function to return an instance of [`RouterContextProvider`][RouterContextProvider]:
518
-
519
- ```diff
520
- declare module "react-router" {
521
- - interface AppLoadContext {
522
- + interface RouterContextProvider {
523
- db: Database;
524
- user: User;
525
- }
526
- }
527
-
528
- function getLoadContext() {
529
- const loadContext = {...};
530
- - return loadContext;
531
- + let context = new RouterContextProvider();
532
- + Object.assign(context, loadContext);
533
- + return context;
534
- }
535
- ```
536
-
537
- This allows you to leave your `action`s/`loader`s untouched during initial adoption of middleware, since they can still read values directly (i.e., `context.db`).
538
-
539
- <docs-warning>This approach is only intended to be used as a migration strategy when adopting middleware in React Router v7, allowing you to incrementally migrate to `context.set`/`context.get`. It is not safe to assume this approach will work in the next major version of React Router.</docs-warning>
540
-
541
- <docs-warning>The [`RouterContextProvider`][RouterContextProvider] class is also used for the client-side `context` parameter via `<HydratedRouter getContext>` and `<RouterProvider getContext>`. Since `AppLoadContext` is primarily intended as a hand-off from your HTTP server into the React Router handlers, you need to be aware that these augmented fields will not be available in `clientMiddleware`, `clientLoader`, or `clientAction` functions even thought TypeScript will tell you they are (unless, of course, you provide the fields via `getContext` on the client).</docs-warning>
542
-
543
471
  ## Common Patterns
544
472
 
545
473
  ### Authentication
@@ -700,24 +628,15 @@ export async function loader({
700
628
  }
701
629
  ```
702
630
 
703
- [future-flags]: ../upgrading/future
704
631
  [Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response
705
632
  [common-patterns]: #common-patterns
706
633
  [server-client]: #server-vs-client-middleware
707
- [create-browser-router]: ../api/data-routers/createBrowserRouter
708
- [create-hash-router]: ../api/data-routers/createHashRouter
709
- [create-memory-router]: ../api/data-routers/createMemoryRouter
710
- [create-static-handler]: ../api/data-routers/createStaticHandler
711
634
  [framework-action]: ../start/framework/route-module#action
712
635
  [framework-loader]: ../start/framework/route-module#loader
713
- [getloadcontext]: #changes-to-getloadcontextapploadcontext
714
636
  [datastrategy]: ../api/data-routers/createBrowserRouter#optsdatastrategy
715
637
  [cms-redirect]: #cms-redirect-on-404
716
638
  [createContext]: ../api/utils/createContext
717
- [RouterContextProvider]: ../api/utils/RouterContextProvider
718
639
  [getContext]: ../api/data-routers/createBrowserRouter#optsgetContext
719
- [window]: https://developer.mozilla.org/en-US/docs/Web/API/Window
720
- [document]: https://developer.mozilla.org/en-US/docs/Web/API/Document
721
640
  [request]: https://developer.mozilla.org/en-US/docs/Web/API/Request
722
641
  [data-action]: ../start/data/route-object#action
723
642
  [data-loader]: ../start/data/route-object#loader
@@ -13,18 +13,20 @@ This is by no means a comprehensive guide, but React Router provides features to
13
13
 
14
14
  ## `Content-Security-Policy`
15
15
 
16
- If you are implementing a [Content-Security-Policy (CSP)][csp] in your application, specifically one using the `unsafe-inline` directive, you will need to specify a [`nonce`][nonce] attribute on the inline `<script>` elements rendered in your HTML. This must be specified on any API that generates inline scripts, including:
16
+ If you are implementing a [Content-Security-Policy (CSP)][csp] in your application, specifically one using the `unsafe-inline` directive, you will need to specify a [`nonce`][nonce] attribute on the inline `<script>` elements rendered in your HTML.
17
17
 
18
- - [`<Scripts nonce>`][scripts] (`root.tsx`)
19
- - [`<ScrollRestoration nonce>`][scrollrestoration] (`root.tsx`)
20
- - [`<ServerRouter nonce>`][serverrouter] (`entry.server.tsx`)
21
- - [`renderToPipeableStream(..., { nonce })`][renderToPipeableStream] (`entry.server.tsx`)
22
- - [`renderToReadableStream(..., { nonce })`][renderToReadableStream] (`entry.server.tsx`)
18
+ Add a nonce to these two spots in [`entry.server.tsx`][entryserver]:
19
+
20
+ - The [`<ServerRouter nonce>`][serverrouter] prop
21
+ - This will be proxied along through React Context and used for other Framework Mode components that output `nonce`-aware elements, including [`<Scripts>`][scripts], [`<ScrollRestoration>`][scrollrestoration]
22
+ - If those components specify their own `nonce` prop, it will override the `ServerRouter` value
23
+ - The `nonce` options of [`renderToPipeableStream`][renderToPipeableStream]/[`renderToReadableStream`][renderToReadableStream]
23
24
 
24
25
  [csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
26
+ [entryserver]: ../api/framework-conventions/entry.server.tsx
25
27
  [nonce]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce
26
28
  [renderToPipeableStream]: https://react.dev/reference/react-dom/server/renderToPipeableStream
27
29
  [renderToReadableStream]: https://react.dev/reference/react-dom/server/renderToReadableStream
28
30
  [scripts]: ../api/components/Scripts
29
31
  [scrollrestoration]: ../api/components/ScrollRestoration
30
- [serverrouter]: ../api/components/ServerRouter
32
+ [serverrouter]: ../api/framework-routers/ServerRouter
@@ -54,7 +54,7 @@ export async function loader({ params }: Route.ActionArgs) {
54
54
  let project = await fakeDb.getProject(params.id);
55
55
  if (!project) {
56
56
  // throw to ErrorBoundary
57
- throw data(null, { status: 404 });
57
+ throw data("Not Found", { status: 404 });
58
58
  }
59
59
  return project;
60
60
  }
package/docs/index.md CHANGED
@@ -5,7 +5,7 @@ order: 1
5
5
 
6
6
  # React Router Home
7
7
 
8
- React Router is a multi-strategy router for React bridging the gap from React 18 to React 19. You can use it maximally as a React framework or as minimally as you want.
8
+ React Router is a multi-strategy router for React. You can use it maximally as a React framework or as minimally as you want.
9
9
 
10
10
  ## Getting Started
11
11
 
@@ -29,11 +29,8 @@ These icons indicate which mode the content is relevant to.
29
29
 
30
30
  Additional auto-generated reference documentation is available:
31
31
 
32
- [Autogenerated Reference Docs ↗](https://api.reactrouter.com/v7/)
32
+ [Autogenerated Reference Docs ↗](https://api.reactrouter.com/v8/)
33
33
 
34
34
  ## Upgrading
35
35
 
36
- If you are caught up on future flags, upgrading from React Router v6 or Remix v2 is generally non-breaking. Remix v2 apps are encouraged to upgrade to React Router v7.
37
-
38
- - [Upgrade from v6](./upgrading/v6)
39
- - [Upgrade from Remix](./upgrading/remix)
36
+ If you are caught up on future flags, [upgrading from React Router v7](./upgrading/v7) is generally non-breaking.
@@ -47,6 +47,10 @@ ReactDOM.createRoot(root).render(
47
47
  );
48
48
  ```
49
49
 
50
+ <docs-info>Data Routers should not be held in React state. You should create your router
51
+ once outside of the React tree and pass it to `<RouterProvider>`. You can use
52
+ `patchRoutesOnNavigation` to add additional routes programmatically.</docs-info>
53
+
50
54
  ---
51
55
 
52
56
  Next: [Routing](./routing)
@@ -240,9 +240,29 @@ createBrowserRouter([
240
240
  ]);
241
241
  ```
242
242
 
243
+ ## `handle`
244
+
245
+ Route handle allows apps to add anything to a route match in `useMatches` to create abstractions (like breadcrumbs, etc.).
246
+
247
+ ```tsx
248
+ createBrowserRouter([
249
+ {
250
+ path: "/app",
251
+ handle: {
252
+ breadcrumb: "App",
253
+ },
254
+ },
255
+ ]);
256
+ ```
257
+
258
+ See also:
259
+
260
+ - [`useMatches`][use-matches]
261
+
243
262
  ---
244
263
 
245
264
  Next: [Data Loading](./data-loading)
246
265
 
247
266
  [loader-params]: https://api.reactrouter.com/v7/interfaces/react-router.LoaderFunctionArgs
248
267
  [middleware]: ../../how-to/middleware
268
+ [use-matches]: ../../api/hooks/useMatches
@@ -172,4 +172,3 @@ See the [Using Fetchers][fetchers] guide for more information.
172
172
  Next: [Navigating](./navigating)
173
173
 
174
174
  [fetchers]: ../../how-to/fetchers
175
- [data]: ../../api/react-router/data
@@ -142,7 +142,7 @@ export async function clientLoader({
142
142
  }: Route.ClientLoaderArgs) {
143
143
  const res = await fetch(`/api/products/${params.pid}`);
144
144
  const serverData = await serverLoader();
145
- return { ...serverData, ...res.json() };
145
+ return { ...serverData, ...(await res.json()) };
146
146
  }
147
147
 
148
148
  export default function Product({