react-router 0.0.0-experimental-d5a247381 → 0.0.0-experimental-2eb7164

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 (62) hide show
  1. package/CHANGELOG.md +51 -36
  2. package/dist/development/{chunk-5CZ4IYHY.mjs → chunk-433YBOKX.mjs} +189 -60
  3. package/dist/{production/chunk-EPFW5H4E.mjs → development/chunk-CM3L6EBM.mjs} +147 -33
  4. package/dist/development/{chunk-HTLIKYA4.js → chunk-DMYOHO3D.js} +210 -169
  5. package/dist/development/{chunk-JKTJNTER.js → chunk-PFFPX2WQ.js} +149 -61
  6. package/dist/development/{context-DZWGFcKX.d.mts → context-DY_GBoQM.d.mts} +849 -13
  7. package/dist/development/dom-export.d.mts +20 -2
  8. package/dist/development/dom-export.d.ts +20 -1
  9. package/dist/development/dom-export.js +10 -4
  10. package/dist/development/dom-export.mjs +10 -4
  11. package/dist/{production/index-react-server-client-BUK-oRcG.d.mts → development/index-react-server-client-ByWQ94sU.d.mts} +20 -4
  12. package/dist/development/{index-react-server-client-DSU6bZil.d.ts → index-react-server-client-pJZFIoFI.d.ts} +24 -817
  13. package/dist/development/index-react-server-client.d.mts +3 -4
  14. package/dist/development/index-react-server-client.d.ts +2 -2
  15. package/dist/development/index-react-server-client.js +4 -4
  16. package/dist/development/index-react-server-client.mjs +2 -2
  17. package/dist/development/index-react-server.d.mts +6 -7
  18. package/dist/development/index-react-server.d.ts +6 -7
  19. package/dist/development/index-react-server.js +64 -17
  20. package/dist/development/index-react-server.mjs +64 -17
  21. package/dist/development/index.d.mts +7 -9
  22. package/dist/development/index.d.ts +5 -5
  23. package/dist/development/index.js +242 -128
  24. package/dist/development/index.mjs +3 -3
  25. package/dist/development/lib/types/internal.d.mts +2 -2
  26. package/dist/development/lib/types/internal.d.ts +1 -1
  27. package/dist/development/lib/types/internal.js +1 -1
  28. package/dist/development/lib/types/internal.mjs +1 -1
  29. package/dist/development/{route-data-UTmTa8an.d.mts → route-data-DZyLihZ0.d.mts} +1 -1
  30. package/dist/{production/routeModules-D5bppTB2.d.ts → development/routeModules-iYhSy-FD.d.ts} +849 -13
  31. package/dist/production/{chunk-G3S3XTKQ.mjs → chunk-G343FNS2.mjs} +189 -60
  32. package/dist/production/{chunk-CXNNH7ML.js → chunk-GALNUNJG.js} +210 -169
  33. package/dist/production/{chunk-4OSWJNZY.js → chunk-MFKHDFBJ.js} +149 -61
  34. package/dist/{development/chunk-WD74EEJO.mjs → production/chunk-VQTSL3FX.mjs} +147 -33
  35. package/dist/production/{context-DZWGFcKX.d.mts → context-DY_GBoQM.d.mts} +849 -13
  36. package/dist/production/dom-export.d.mts +20 -2
  37. package/dist/production/dom-export.d.ts +20 -1
  38. package/dist/production/dom-export.js +10 -4
  39. package/dist/production/dom-export.mjs +10 -4
  40. package/dist/{development/index-react-server-client-BUK-oRcG.d.mts → production/index-react-server-client-ByWQ94sU.d.mts} +20 -4
  41. package/dist/production/{index-react-server-client-DSU6bZil.d.ts → index-react-server-client-pJZFIoFI.d.ts} +24 -817
  42. package/dist/production/index-react-server-client.d.mts +3 -4
  43. package/dist/production/index-react-server-client.d.ts +2 -2
  44. package/dist/production/index-react-server-client.js +4 -4
  45. package/dist/production/index-react-server-client.mjs +2 -2
  46. package/dist/production/index-react-server.d.mts +6 -7
  47. package/dist/production/index-react-server.d.ts +6 -7
  48. package/dist/production/index-react-server.js +64 -17
  49. package/dist/production/index-react-server.mjs +64 -17
  50. package/dist/production/index.d.mts +7 -9
  51. package/dist/production/index.d.ts +5 -5
  52. package/dist/production/index.js +242 -128
  53. package/dist/production/index.mjs +3 -3
  54. package/dist/production/lib/types/internal.d.mts +2 -2
  55. package/dist/production/lib/types/internal.d.ts +1 -1
  56. package/dist/production/lib/types/internal.js +1 -1
  57. package/dist/production/lib/types/internal.mjs +1 -1
  58. package/dist/production/{route-data-UTmTa8an.d.mts → route-data-DZyLihZ0.d.mts} +1 -1
  59. package/dist/{development/routeModules-D5bppTB2.d.ts → production/routeModules-iYhSy-FD.d.ts} +849 -13
  60. package/package.json +1 -1
  61. package/dist/development/components-uUh0svuC.d.mts +0 -814
  62. package/dist/production/components-uUh0svuC.d.mts +0 -814
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # `react-router`
2
2
 
3
- ## 7.8.0-pre.0
3
+ ## 7.8.0
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -11,14 +11,50 @@
11
11
 
12
12
  ### Patch Changes
13
13
 
14
- - [UNSTABLE] Ensure resource route errors go through `handleError` w/middleware enabled ([#14078](https://github.com/remix-run/react-router/pull/14078))
15
14
  - Prevent _"Did not find corresponding fetcher result"_ console error when navigating during a `fetcher.submit` revalidation ([#14114](https://github.com/remix-run/react-router/pull/14114))
15
+
16
+ - Bubble client-side middleware errors prior to `next` to the appropriate ancestor error boundary ([#14138](https://github.com/remix-run/react-router/pull/14138))
17
+
16
18
  - Switch Lazy Route Discovery manifest URL generation to usea standalone `URLSearchParams` instance instead of `URL.searchParams` to avoid a major performance bottleneck in Chrome ([#14084](https://github.com/remix-run/react-router/pull/14084))
17
- - [UNSTABLE] Propagate returned Response from server middleware if next wasn't called ([#14093](https://github.com/remix-run/react-router/pull/14093))
18
- - [UNSTABLE] Allow server middlewares to return `data()` values which will be converted into a `Response` ([#14093](https://github.com/remix-run/react-router/pull/14093))
19
- - [UNSTABLE] Update middleware error handling so that the `next` function never throws and instead handles any middleware errors at the proper `ErrorBoundary` and returns the `Response` up through the ancestor `next` function ([#14118](https://github.com/remix-run/react-router/pull/14118))
20
- - - [UNSTABLE] When middleware is enabled, make the `context` parameter read-only (via `Readonly<unstable_RouterContextProvider>`) so that TypeScript will not allow you to write arbitrary fields to it in loaders, actions, or middleware. ([#14097](https://github.com/remix-run/react-router/pull/14097))
21
- - [UNSTABLE] Rename and alter the signature/functionality of the `unstable_respond` API in `staticHandler.query`/`staticHandler.queryRoute` ([#14103](https://github.com/remix-run/react-router/pull/14103))
19
+
20
+ - Adjust internal RSC usage of `React.use` to avoid Webpack compilation errors when using React 18 ([#14113](https://github.com/remix-run/react-router/pull/14113))
21
+
22
+ - Remove dependency on `@types/node` in TypeScript declaration files ([#14059](https://github.com/remix-run/react-router/pull/14059))
23
+
24
+ - Fix types for `UIMatch` to reflect that the `loaderData`/`data` properties may be `undefined` ([#12206](https://github.com/remix-run/react-router/pull/12206))
25
+ - When an `ErrorBoundary` is being rendered, not all active matches will have loader data available, since it may have been their `loader` that threw to trigger the boundary
26
+ - The `UIMatch.data` type was not correctly handing this and would always reflect the presence of data, leading to the unexpected runtime errors when an `ErrorBoundary` was rendered
27
+ - ⚠️ This may cause some type errors to show up in your code for unguarded `match.data` accesses - you should properly guard for `undefined` values in those scenarios.
28
+
29
+ ```tsx
30
+ // app/root.tsx
31
+ export function loader() {
32
+ someFunctionThatThrows(); // ❌ Throws an Error
33
+ return { title: "My Title" };
34
+ }
35
+
36
+ export function Layout({ children }: { children: React.ReactNode }) {
37
+ let matches = useMatches();
38
+ let rootMatch = matches[0] as UIMatch<Awaited<ReturnType<typeof loader>>>;
39
+ // ^ rootMatch.data is incorrectly typed here, so TypeScript does not
40
+ // complain if you do the following which throws an error at runtime:
41
+ let { title } = rootMatch.data; // 💥
42
+
43
+ return <html>...</html>;
44
+ }
45
+ ```
46
+
47
+ - \[UNSTABLE] Ensure resource route errors go through `handleError` w/middleware enabled ([#14078](https://github.com/remix-run/react-router/pull/14078))
48
+
49
+ - \[UNSTABLE] Propagate returned Response from server middleware if next wasn't called ([#14093](https://github.com/remix-run/react-router/pull/14093))
50
+
51
+ - \[UNSTABLE] Allow server middlewares to return `data()` values which will be converted into a `Response` ([#14093](https://github.com/remix-run/react-router/pull/14093))
52
+
53
+ - \[UNSTABLE] Update middleware error handling so that the `next` function never throws and instead handles any middleware errors at the proper `ErrorBoundary` and returns the `Response` up through the ancestor `next` function ([#14118](https://github.com/remix-run/react-router/pull/14118))
54
+
55
+ - \[UNSTABLE] When middleware is enabled, make the `context` parameter read-only (via `Readonly<unstable_RouterContextProvider>`) so that TypeScript will not allow you to write arbitrary fields to it in loaders, actions, or middleware. ([#14097](https://github.com/remix-run/react-router/pull/14097))
56
+
57
+ - \[UNSTABLE] Rename and alter the signature/functionality of the `unstable_respond` API in `staticHandler.query`/`staticHandler.queryRoute` ([#14103](https://github.com/remix-run/react-router/pull/14103))
22
58
  - The API has been renamed to `unstable_generateMiddlewareResponse` for clarity
23
59
  - The main functional change is that instead of running the loaders/actions before calling `unstable_respond` and handing you the result, we now pass a `query`/`queryRoute` function as a parameter and you execute the loaders/actions inside your callback, giving you full access to pre-processing and error handling
24
60
  - The `query` version of the API now has a signature of `(query: (r: Request) => Promise<StaticHandlerContext | Response>) => Promise<Response>`
@@ -45,41 +81,20 @@
45
81
  });
46
82
  ```
47
83
 
48
- - [UNSTABLE] Convert internal middleware implementations to use the new `unstable_generateMiddlewareResponse` API ([#14103](https://github.com/remix-run/react-router/pull/14103))
49
- - Adjust internal RSC usage of `React.use` to avoid Webpack compilation errors when using React 18 ([#14113](https://github.com/remix-run/react-router/pull/14113))
50
- - [UNSTABLE] Change `getLoadContext` signature (`type GetLoadContextFunction`) when `future.unstable_middleware` is enabled so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
84
+ - \[UNSTABLE] Convert internal middleware implementations to use the new `unstable_generateMiddlewareResponse` API ([#14103](https://github.com/remix-run/react-router/pull/14103))
85
+
86
+ - \[UNSTABLE] Change `getLoadContext` signature (`type GetLoadContextFunction`) when `future.unstable_middleware` is enabled so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
51
87
  - This also removes the `type unstable_InitialContext` export
52
88
  - ⚠️ This is a breaking change if you have adopted middleware and are using a custom server with a `getLoadContext` function
53
89
 
54
- - Remove dependency on `@types/node` in TypeScript declaration files ([#14059](https://github.com/remix-run/react-router/pull/14059))
55
- - Fix types for `UIMatch` to reflect that the `loaderData`/`data` properties may be `undefined` ([#12206](https://github.com/remix-run/react-router/pull/12206))
56
- - When an `ErrorBoundary` is being rendered, not all active matches will have loader data available, since it may have been their `loader` that threw to trigger the boundary
57
- - The `UIMatch.data` type was not correctly handing this and would always reflect the presence of data, leading to the unexpected runtime errors when an `ErrorBoundary` was rendered
58
- - ⚠️ This may cause some type errors to show up in your code for unguarded `match.data` accesses - you should properly guard for `undefined` values in those scenarios.
59
-
60
- ```tsx
61
- // app/root.tsx
62
- export function loader() {
63
- someFunctionThatThrows(); // ❌ Throws an Error
64
- return { title: "My Title" };
65
- }
66
-
67
- export function Layout({ children }: { children: React.ReactNode }) {
68
- let matches = useMatches();
69
- let rootMatch = matches[0] as UIMatch<Awaited<ReturnType<typeof loader>>>;
70
- // ^ rootMatch.data is incorrectly typed here, so TypeScript does not
71
- // complain if you do the following which throws an error at runtime:
72
- let { title } = rootMatch.data; // 💥
90
+ - \[UNSTABLE] Run client middleware on client navigations even if no loaders exist ([#14106](https://github.com/remix-run/react-router/pull/14106))
73
91
 
74
- return <html>...</html>;
75
- }
76
- ```
77
-
78
- - [UNSTABLE] Run client middleware on client navigations even if no loaders exist ([#14106](https://github.com/remix-run/react-router/pull/14106))
79
- - [UNSTABLE] Change the `unstable_getContext` signature on `RouterProvider`/`HydratedRouter`/`unstable_RSCHydratedRouter` so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
92
+ - \[UNSTABLE] Change the `unstable_getContext` signature on `RouterProvider`/`HydratedRouter`/`unstable_RSCHydratedRouter` so that it returns an `unstable_RouterContextProvider` instance instead of a `Map` used to contruct the instance internally ([#14097](https://github.com/remix-run/react-router/pull/14097))
80
93
  - ⚠️ This is a breaking change if you have adopted the `unstable_getContext` prop
81
94
 
82
- - Fix RSC Data Mode issue where routes that return `false` from `shouldRevalidate` would be replaced by an `<Outlet />` ([#14071](https://github.com/remix-run/react-router/pull/14071))
95
+ - [UNSTABLE] proxy server action side-effect redirects from actions for document and callServer requests ([#14131](https://github.com/remix-run/react-router/pull/14131))
96
+
97
+ - [UNSTABLE] Fix RSC Data Mode issue where routes that return `false` from `shouldRevalidate` would be replaced by an `<Outlet />` ([#14071](https://github.com/remix-run/react-router/pull/14071))
83
98
 
84
99
  ## 7.7.1
85
100
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-d5a247381
2
+ * react-router v0.0.0-experimental-2eb7164
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -513,8 +513,8 @@ function convertRouteMatchToUiMatch(match, loaderData) {
513
513
  handle: route.handle
514
514
  };
515
515
  }
516
- function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "") {
517
- let flattenRoute = (route, index, relativePath) => {
516
+ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) {
517
+ let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath) => {
518
518
  let meta = {
519
519
  relativePath: relativePath === void 0 ? route.path || "" : relativePath,
520
520
  caseSensitive: route.caseSensitive === true,
@@ -522,6 +522,9 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
522
522
  route
523
523
  };
524
524
  if (meta.relativePath.startsWith("/")) {
525
+ if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) {
526
+ return;
527
+ }
525
528
  invariant(
526
529
  meta.relativePath.startsWith(parentPath),
527
530
  `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`
@@ -537,7 +540,13 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
537
540
  route.index !== true,
538
541
  `Index routes must not have child routes. Please remove all child routes from route path "${path}".`
539
542
  );
540
- flattenRoutes(route.children, branches, routesMeta, path);
543
+ flattenRoutes(
544
+ route.children,
545
+ branches,
546
+ routesMeta,
547
+ path,
548
+ hasParentOptionalSegments
549
+ );
541
550
  }
542
551
  if (route.path == null && !route.index) {
543
552
  return;
@@ -553,7 +562,7 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "")
553
562
  flattenRoute(route, index);
554
563
  } else {
555
564
  for (let exploded of explodeOptionalSegments(route.path)) {
556
- flattenRoute(route, index, exploded);
565
+ flattenRoute(route, index, true, exploded);
557
566
  }
558
567
  }
559
568
  });
@@ -745,7 +754,7 @@ function compilePath(path, caseSensitive = false, end = true) {
745
754
  params.push({ paramName, isOptional: isOptional != null });
746
755
  return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
747
756
  }
748
- );
757
+ ).replace(/\/([\w-]+)\?(\/|$)/g, "(/$1)?$2");
749
758
  if (path.endsWith("*")) {
750
759
  params.push({ paramName: "*" });
751
760
  regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
@@ -2942,6 +2951,9 @@ function createStaticHandler(routes, opts) {
2942
2951
  return res;
2943
2952
  },
2944
2953
  (error) => {
2954
+ if (isRouteErrorResponse(error)) {
2955
+ return Promise.resolve(errorResponseToResponse(error));
2956
+ }
2945
2957
  if (isResponse(error)) {
2946
2958
  return Promise.resolve(error);
2947
2959
  }
@@ -3917,12 +3929,42 @@ async function defaultDataStrategyWithMiddleware(args) {
3917
3929
  if (!args.matches.some((m) => m.route.unstable_middleware)) {
3918
3930
  return defaultDataStrategy(args);
3919
3931
  }
3932
+ let didCallHandler = false;
3920
3933
  return runClientMiddlewarePipeline(
3921
3934
  args,
3922
- () => defaultDataStrategy(args),
3923
- (error, routeId) => ({ [routeId]: { type: "error", result: error } })
3935
+ () => {
3936
+ didCallHandler = true;
3937
+ return defaultDataStrategy(args);
3938
+ },
3939
+ (error, routeId) => clientMiddlewareErrorHandler(
3940
+ error,
3941
+ routeId,
3942
+ args.matches,
3943
+ didCallHandler
3944
+ )
3924
3945
  );
3925
3946
  }
3947
+ function clientMiddlewareErrorHandler(error, routeId, matches, didCallHandler) {
3948
+ if (didCallHandler) {
3949
+ return {
3950
+ [routeId]: { type: "error", result: error }
3951
+ };
3952
+ } else {
3953
+ let maxBoundaryIdx = Math.min(
3954
+ // Throwing route
3955
+ matches.findIndex((m) => m.route.id === routeId) || 0,
3956
+ // or the shallowest route that needs to load data
3957
+ matches.findIndex((m) => m.unstable_shouldCallHandler()) || 0
3958
+ );
3959
+ let boundaryRouteId = findNearestBoundary(
3960
+ matches,
3961
+ matches[maxBoundaryIdx].route.id
3962
+ ).route.id;
3963
+ return {
3964
+ [boundaryRouteId]: { type: "error", result: error }
3965
+ };
3966
+ }
3967
+ }
3926
3968
  async function runServerMiddlewarePipeline(args, handler, errorHandler) {
3927
3969
  let { matches, request, params, context } = args;
3928
3970
  let tuples = matches.flatMap(
@@ -3934,12 +3976,6 @@ async function runServerMiddlewarePipeline(args, handler, errorHandler) {
3934
3976
  handler,
3935
3977
  errorHandler
3936
3978
  );
3937
- if (isDataWithResponseInit(result)) {
3938
- return new Response(
3939
- typeof result.data === "string" ? result.data : JSON.stringify(result.data),
3940
- { ...result.init }
3941
- );
3942
- }
3943
3979
  if (isResponse(result)) {
3944
3980
  return result;
3945
3981
  }
@@ -3976,10 +4012,17 @@ async function callServerRouteMiddleware(args, middlewares, handler, errorHandle
3976
4012
  errorHandler,
3977
4013
  idx + 1
3978
4014
  );
4015
+ if (isDataWithResponseInit(result)) {
4016
+ result = dataWithResponseInitToResponse(result);
4017
+ }
3979
4018
  nextResult = result;
3980
4019
  return nextResult;
3981
4020
  } catch (e) {
3982
- nextResult = await errorHandler(e, routeId);
4021
+ nextResult = await errorHandler(
4022
+ // Convert thrown data() values to ErrorResponses
4023
+ isDataWithResponseInit(e) ? dataWithResponseInitToErrorResponse(e) : e,
4024
+ routeId
4025
+ );
3983
4026
  return nextResult;
3984
4027
  }
3985
4028
  };
@@ -3992,16 +4035,23 @@ async function callServerRouteMiddleware(args, middlewares, handler, errorHandle
3992
4035
  },
3993
4036
  next
3994
4037
  );
4038
+ if (isDataWithResponseInit(result)) {
4039
+ result = dataWithResponseInitToResponse(result);
4040
+ }
3995
4041
  if (nextCalled) {
3996
4042
  return typeof result === "undefined" ? nextResult : result;
3997
- } else if (isResponse(result) || isDataWithResponseInit(result)) {
4043
+ } else if (isResponse(result)) {
3998
4044
  return result;
3999
4045
  } else {
4000
4046
  nextResult = await next();
4001
4047
  return nextResult;
4002
4048
  }
4003
- } catch (error) {
4004
- let response = await errorHandler(error, routeId);
4049
+ } catch (e) {
4050
+ let response = await errorHandler(
4051
+ // Convert thrown data() values to ErrorResponses
4052
+ isDataWithResponseInit(e) ? dataWithResponseInitToErrorResponse(e) : e,
4053
+ routeId
4054
+ );
4005
4055
  return response;
4006
4056
  }
4007
4057
  }
@@ -4189,20 +4239,27 @@ async function callDataStrategyImpl(dataStrategyImpl, request, matches, fetcherK
4189
4239
  );
4190
4240
  } : (cb) => {
4191
4241
  let typedDataStrategyArgs = dataStrategyArgs;
4242
+ let didCallHandler = false;
4192
4243
  return runClientMiddlewarePipeline(
4193
4244
  typedDataStrategyArgs,
4194
- () => cb({
4195
- ...typedDataStrategyArgs,
4196
- fetcherKey,
4197
- unstable_runClientMiddleware: () => {
4198
- throw new Error(
4199
- "Cannot call `unstable_runClientMiddleware()` from within an `unstable_runClientMiddleware` handler"
4200
- );
4201
- }
4202
- }),
4203
- (error, routeId) => ({
4204
- [routeId]: { type: "error", result: error }
4205
- })
4245
+ () => {
4246
+ didCallHandler = true;
4247
+ return cb({
4248
+ ...typedDataStrategyArgs,
4249
+ fetcherKey,
4250
+ unstable_runClientMiddleware: () => {
4251
+ throw new Error(
4252
+ "Cannot call `unstable_runClientMiddleware()` from within an `unstable_runClientMiddleware` handler"
4253
+ );
4254
+ }
4255
+ });
4256
+ },
4257
+ (error, routeId) => clientMiddlewareErrorHandler(
4258
+ error,
4259
+ routeId,
4260
+ matches,
4261
+ didCallHandler
4262
+ )
4206
4263
  );
4207
4264
  };
4208
4265
  let results = await dataStrategyImpl({
@@ -4663,6 +4720,28 @@ function isHashChangeOnly(a, b) {
4663
4720
  }
4664
4721
  return false;
4665
4722
  }
4723
+ function dataWithResponseInitToResponse(data2) {
4724
+ return new Response(
4725
+ typeof data2.data === "string" ? data2.data : JSON.stringify(data2.data),
4726
+ data2.init || void 0
4727
+ );
4728
+ }
4729
+ function dataWithResponseInitToErrorResponse(data2) {
4730
+ return new ErrorResponseImpl(
4731
+ data2.init?.status ?? 500,
4732
+ data2.init?.statusText ?? "Internal Server Error",
4733
+ data2.data
4734
+ );
4735
+ }
4736
+ function errorResponseToResponse(error) {
4737
+ return new Response(
4738
+ typeof error.data === "string" ? error.data : JSON.stringify(error.data),
4739
+ {
4740
+ status: error.status,
4741
+ statusText: error.statusText
4742
+ }
4743
+ );
4744
+ }
4666
4745
  function isDataStrategyResult(result) {
4667
4746
  return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === "data" /* data */ || result.type === "error" /* error */);
4668
4747
  }
@@ -5070,7 +5149,7 @@ function useResolvedPath(to, { relative } = {}) {
5070
5149
  function useRoutes(routes, locationArg) {
5071
5150
  return useRoutesImpl(routes, locationArg);
5072
5151
  }
5073
- function useRoutesImpl(routes, locationArg, dataRouterState, future) {
5152
+ function useRoutesImpl(routes, locationArg, dataRouterState, unstable_handleError, future) {
5074
5153
  invariant(
5075
5154
  useInRouterContext(),
5076
5155
  // TODO: This error is probably because they somehow have 2 versions of the
@@ -5142,6 +5221,7 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
5142
5221
  ),
5143
5222
  parentMatches,
5144
5223
  dataRouterState,
5224
+ unstable_handleError,
5145
5225
  future
5146
5226
  );
5147
5227
  if (locationArg && renderedMatches) {
@@ -5210,11 +5290,14 @@ var RenderErrorBoundary = class extends React2.Component {
5210
5290
  };
5211
5291
  }
5212
5292
  componentDidCatch(error, errorInfo) {
5213
- console.error(
5214
- "React Router caught the following error during render",
5215
- error,
5216
- errorInfo
5217
- );
5293
+ if (this.props.unstable_handleError) {
5294
+ this.props.unstable_handleError(error, errorInfo);
5295
+ } else {
5296
+ console.error(
5297
+ "React Router caught the following error during render",
5298
+ error
5299
+ );
5300
+ }
5218
5301
  }
5219
5302
  render() {
5220
5303
  return this.state.error !== void 0 ? /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React2.createElement(
@@ -5233,7 +5316,7 @@ function RenderedRoute({ routeContext, match, children }) {
5233
5316
  }
5234
5317
  return /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: routeContext }, children);
5235
5318
  }
5236
- function _renderMatches(matches, parentMatches = [], dataRouterState = null, future = null) {
5319
+ function _renderMatches(matches, parentMatches = [], dataRouterState = null, unstable_handleError = null, future = null) {
5237
5320
  if (matches == null) {
5238
5321
  if (!dataRouterState) {
5239
5322
  return null;
@@ -5345,7 +5428,8 @@ function _renderMatches(matches, parentMatches = [], dataRouterState = null, fut
5345
5428
  component: errorElement,
5346
5429
  error,
5347
5430
  children: getChildren(),
5348
- routeContext: { outlet: null, matches: matches2, isDataRoute: true }
5431
+ routeContext: { outlet: null, matches: matches2, isDataRoute: true },
5432
+ unstable_handleError
5349
5433
  }
5350
5434
  ) : getChildren();
5351
5435
  },
@@ -5611,7 +5695,8 @@ var Deferred = class {
5611
5695
  };
5612
5696
  function RouterProvider({
5613
5697
  router,
5614
- flushSync: reactDomFlushSyncImpl
5698
+ flushSync: reactDomFlushSyncImpl,
5699
+ unstable_handleError
5615
5700
  }) {
5616
5701
  let [state, setStateImpl] = React3.useState(router.state);
5617
5702
  let [pendingState, setPendingState] = React3.useState();
@@ -5622,6 +5707,21 @@ function RouterProvider({
5622
5707
  let [transition, setTransition] = React3.useState();
5623
5708
  let [interruption, setInterruption] = React3.useState();
5624
5709
  let fetcherData = React3.useRef(/* @__PURE__ */ new Map());
5710
+ let logErrorsAndSetState = React3.useCallback(
5711
+ (newState) => {
5712
+ setStateImpl((prevState) => {
5713
+ if (newState.errors && unstable_handleError) {
5714
+ Object.entries(newState.errors).forEach(([routeId, error]) => {
5715
+ if (prevState.errors?.[routeId] !== error) {
5716
+ unstable_handleError(error);
5717
+ }
5718
+ });
5719
+ }
5720
+ return newState;
5721
+ });
5722
+ },
5723
+ [unstable_handleError]
5724
+ );
5625
5725
  let setState = React3.useCallback(
5626
5726
  (newState, { deletedFetchers, flushSync, viewTransitionOpts }) => {
5627
5727
  newState.fetchers.forEach((fetcher, key) => {
@@ -5641,9 +5741,9 @@ function RouterProvider({
5641
5741
  );
5642
5742
  if (!viewTransitionOpts || !isViewTransitionAvailable) {
5643
5743
  if (reactDomFlushSyncImpl && flushSync) {
5644
- reactDomFlushSyncImpl(() => setStateImpl(newState));
5744
+ reactDomFlushSyncImpl(() => logErrorsAndSetState(newState));
5645
5745
  } else {
5646
- React3.startTransition(() => setStateImpl(newState));
5746
+ React3.startTransition(() => logErrorsAndSetState(newState));
5647
5747
  }
5648
5748
  return;
5649
5749
  }
@@ -5661,7 +5761,7 @@ function RouterProvider({
5661
5761
  });
5662
5762
  });
5663
5763
  let t = router.window.document.startViewTransition(() => {
5664
- reactDomFlushSyncImpl(() => setStateImpl(newState));
5764
+ reactDomFlushSyncImpl(() => logErrorsAndSetState(newState));
5665
5765
  });
5666
5766
  t.finished.finally(() => {
5667
5767
  reactDomFlushSyncImpl(() => {
@@ -5692,7 +5792,13 @@ function RouterProvider({
5692
5792
  });
5693
5793
  }
5694
5794
  },
5695
- [router.window, reactDomFlushSyncImpl, transition, renderDfd]
5795
+ [
5796
+ router.window,
5797
+ reactDomFlushSyncImpl,
5798
+ transition,
5799
+ renderDfd,
5800
+ logErrorsAndSetState
5801
+ ]
5696
5802
  );
5697
5803
  React3.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
5698
5804
  React3.useEffect(() => {
@@ -5705,7 +5811,7 @@ function RouterProvider({
5705
5811
  let newState = pendingState;
5706
5812
  let renderPromise = renderDfd.promise;
5707
5813
  let transition2 = router.window.document.startViewTransition(async () => {
5708
- React3.startTransition(() => setStateImpl(newState));
5814
+ React3.startTransition(() => logErrorsAndSetState(newState));
5709
5815
  await renderPromise;
5710
5816
  });
5711
5817
  transition2.finished.finally(() => {
@@ -5716,7 +5822,7 @@ function RouterProvider({
5716
5822
  });
5717
5823
  setTransition(transition2);
5718
5824
  }
5719
- }, [pendingState, renderDfd, router.window]);
5825
+ }, [pendingState, renderDfd, router.window, logErrorsAndSetState]);
5720
5826
  React3.useEffect(() => {
5721
5827
  if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
5722
5828
  renderDfd.resolve();
@@ -5756,9 +5862,10 @@ function RouterProvider({
5756
5862
  router,
5757
5863
  navigator,
5758
5864
  static: false,
5759
- basename
5865
+ basename,
5866
+ unstable_handleError
5760
5867
  }),
5761
- [router, navigator, basename]
5868
+ [router, navigator, basename, unstable_handleError]
5762
5869
  );
5763
5870
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React3.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React3.createElement(FetchersContext.Provider, { value: fetcherData.current }, /* @__PURE__ */ React3.createElement(ViewTransitionContext.Provider, { value: vtContext }, /* @__PURE__ */ React3.createElement(
5764
5871
  Router,
@@ -5773,7 +5880,8 @@ function RouterProvider({
5773
5880
  {
5774
5881
  routes: router.routes,
5775
5882
  future: router.future,
5776
- state
5883
+ state,
5884
+ unstable_handleError
5777
5885
  }
5778
5886
  )
5779
5887
  ))))), null);
@@ -5782,9 +5890,10 @@ var MemoizedDataRoutes = React3.memo(DataRoutes);
5782
5890
  function DataRoutes({
5783
5891
  routes,
5784
5892
  future,
5785
- state
5893
+ state,
5894
+ unstable_handleError
5786
5895
  }) {
5787
- return useRoutesImpl(routes, void 0, state, future);
5896
+ return useRoutesImpl(routes, void 0, state, unstable_handleError, future);
5788
5897
  }
5789
5898
  function MemoryRouter({
5790
5899
  basename,
@@ -5932,7 +6041,16 @@ function Await({
5932
6041
  errorElement,
5933
6042
  resolve
5934
6043
  }) {
5935
- return /* @__PURE__ */ React3.createElement(AwaitErrorBoundary, { resolve, errorElement }, /* @__PURE__ */ React3.createElement(ResolveAwait, null, children));
6044
+ let dataRouterContext = React3.useContext(DataRouterContext);
6045
+ return /* @__PURE__ */ React3.createElement(
6046
+ AwaitErrorBoundary,
6047
+ {
6048
+ resolve,
6049
+ errorElement,
6050
+ unstable_handleError: dataRouterContext?.unstable_handleError
6051
+ },
6052
+ /* @__PURE__ */ React3.createElement(ResolveAwait, null, children)
6053
+ );
5936
6054
  }
5937
6055
  var AwaitErrorBoundary = class extends React3.Component {
5938
6056
  constructor(props) {
@@ -5943,11 +6061,15 @@ var AwaitErrorBoundary = class extends React3.Component {
5943
6061
  return { error };
5944
6062
  }
5945
6063
  componentDidCatch(error, errorInfo) {
5946
- console.error(
5947
- "<Await> caught the following error during render",
5948
- error,
5949
- errorInfo
5950
- );
6064
+ if (this.props.unstable_handleError) {
6065
+ this.props.unstable_handleError(error, errorInfo);
6066
+ } else {
6067
+ console.error(
6068
+ "<Await> caught the following error during render",
6069
+ error,
6070
+ errorInfo
6071
+ );
6072
+ }
5951
6073
  }
5952
6074
  render() {
5953
6075
  let { children, errorElement, resolve } = this.props;
@@ -5973,7 +6095,10 @@ var AwaitErrorBoundary = class extends React3.Component {
5973
6095
  Object.defineProperty(resolve, "_tracked", { get: () => true });
5974
6096
  promise = resolve.then(
5975
6097
  (data2) => Object.defineProperty(resolve, "_data", { get: () => data2 }),
5976
- (error) => Object.defineProperty(resolve, "_error", { get: () => error })
6098
+ (error) => {
6099
+ this.props.unstable_handleError?.(error);
6100
+ Object.defineProperty(resolve, "_error", { get: () => error });
6101
+ }
5977
6102
  );
5978
6103
  }
5979
6104
  if (status === 2 /* error */ && !errorElement) {
@@ -8634,6 +8759,9 @@ function isValidMetaTag(tagName) {
8634
8759
  return typeof tagName === "string" && /^(meta|link)$/.test(tagName);
8635
8760
  }
8636
8761
  var isHydrated = false;
8762
+ function setIsHydrated() {
8763
+ isHydrated = true;
8764
+ }
8637
8765
  function Scripts(scriptProps) {
8638
8766
  let {
8639
8767
  manifest,
@@ -8652,7 +8780,7 @@ function Scripts(scriptProps) {
8652
8780
  }
8653
8781
  let matches = getActiveMatches(routerMatches, null, isSpaMode);
8654
8782
  React8.useEffect(() => {
8655
- isHydrated = true;
8783
+ setIsHydrated();
8656
8784
  }, []);
8657
8785
  let initialScripts = React8.useMemo(() => {
8658
8786
  if (isRSCRouterContext) {
@@ -8908,7 +9036,7 @@ var isBrowser = typeof window !== "undefined" && typeof window.document !== "und
8908
9036
  try {
8909
9037
  if (isBrowser) {
8910
9038
  window.__reactRouterVersion = // @ts-expect-error
8911
- "0.0.0-experimental-d5a247381";
9039
+ "0.0.0-experimental-2eb7164";
8912
9040
  }
8913
9041
  } catch (e) {
8914
9042
  }
@@ -9815,7 +9943,7 @@ function DataRoutes2({
9815
9943
  future,
9816
9944
  state
9817
9945
  }) {
9818
- return useRoutesImpl(routes, void 0, state, future);
9946
+ return useRoutesImpl(routes, void 0, state, void 0, future);
9819
9947
  }
9820
9948
  function serializeErrors(errors) {
9821
9949
  if (!errors) return null;
@@ -10107,6 +10235,7 @@ export {
10107
10235
  Links,
10108
10236
  PrefetchPageLinks,
10109
10237
  Meta,
10238
+ setIsHydrated,
10110
10239
  Scripts,
10111
10240
  createBrowserRouter,
10112
10241
  createHashRouter,