react-router 0.0.0-experimental-afe1c2609 → 0.0.0-experimental-e2130f538

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 (30) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/development/{chunk-LUBA2YEY.mjs → chunk-KLLSQY3I.mjs} +67 -66
  3. package/dist/development/{chunk-V6EJ2E6X.mjs → chunk-KNNCBCIS.mjs} +122 -5
  4. package/dist/{production/chunk-V6TY6CUE.js → development/chunk-LMUBLF7X.js} +270 -156
  5. package/dist/development/{chunk-WHZBURKX.js → chunk-VU2GHDHY.js} +7 -4
  6. package/dist/development/dom-export.js +3 -3
  7. package/dist/development/dom-export.mjs +3 -3
  8. package/dist/development/index-react-server-client.js +4 -4
  9. package/dist/development/index-react-server-client.mjs +2 -2
  10. package/dist/development/index-react-server.js +7 -3
  11. package/dist/development/index-react-server.mjs +7 -3
  12. package/dist/development/index.js +160 -159
  13. package/dist/development/index.mjs +3 -3
  14. package/dist/development/lib/types/internal.js +1 -1
  15. package/dist/development/lib/types/internal.mjs +1 -1
  16. package/dist/production/{chunk-AJPSYVLM.js → chunk-4OVLJFUE.js} +7 -4
  17. package/dist/{development/chunk-VMNIQCPL.js → production/chunk-D5G4H67X.js} +270 -156
  18. package/dist/production/{chunk-I6TNFXM2.mjs → chunk-KBACS3E4.mjs} +67 -66
  19. package/dist/production/{chunk-V5GOVMXP.mjs → chunk-PXZXGDXW.mjs} +122 -5
  20. package/dist/production/dom-export.js +3 -3
  21. package/dist/production/dom-export.mjs +3 -3
  22. package/dist/production/index-react-server-client.js +4 -4
  23. package/dist/production/index-react-server-client.mjs +2 -2
  24. package/dist/production/index-react-server.js +7 -3
  25. package/dist/production/index-react-server.mjs +7 -3
  26. package/dist/production/index.js +160 -159
  27. package/dist/production/index.mjs +3 -3
  28. package/dist/production/lib/types/internal.js +1 -1
  29. package/dist/production/lib/types/internal.mjs +1 -1
  30. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # `react-router`
2
2
 
3
+ ## 7.9.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Do not try to use `turbo-stream` to decode CDN errors that never reached the server ([#14385](https://github.com/remix-run/react-router/pull/14385))
8
+ - We used to do this but lost this check with the adoption of single fetch
9
+
10
+ - Fix Data Mode regression causing a 404 during initial load in when `middleware` exists without any `loader` functions ([#14393](https://github.com/remix-run/react-router/pull/14393))
11
+
12
+ ## 7.9.2
13
+
14
+ ### Patch Changes
15
+
16
+ - - Update client-side router to run client `middleware` on initial load even if no loaders exist ([#14348](https://github.com/remix-run/react-router/pull/14348))
17
+ - Update `createRoutesStub` to run route middleware
18
+ - You will need to set the `<RoutesStub future={{ v8_middleware: true }} />` flag to enable the proper `context` type
19
+
20
+ - Update Lazy Route Discovery manifest requests to use a singular comma-separated `paths` query param instead of repeated `p` query params ([#14321](https://github.com/remix-run/react-router/pull/14321))
21
+ - This is because Cloudflare has a hard limit of 100 URL search param key/value pairs when used as a key for caching purposes
22
+ - If more that 100 paths were included, the cache key would be incomplete and could produce false-positive cache hits
23
+
24
+ - \[UNSTABLE] Add `fetcher.unstable_reset()` API ([#14206](https://github.com/remix-run/react-router/pull/14206))
25
+
26
+ - Made useOutlet element reference have stable identity in-between route chages ([#13382](https://github.com/remix-run/react-router/pull/13382))
27
+
28
+ - feat: enable full transition support for the rsc router ([#14362](https://github.com/remix-run/react-router/pull/14362))
29
+
30
+ - In RSC Data Mode, handle SSR'd client errors and re-try in the browser ([#14342](https://github.com/remix-run/react-router/pull/14342))
31
+
32
+ - Support `middleware` prop on `<Route>` for usage with a data router via `createRoutesFromElements` ([#14357](https://github.com/remix-run/react-router/pull/14357))
33
+
34
+ - Handle encoded question mark and hash characters in ancestor splat routes ([#14249](https://github.com/remix-run/react-router/pull/14249))
35
+
36
+ - Fail gracefully on manifest version mismatch logic if `sessionStorage` access is blocked ([#14335](https://github.com/remix-run/react-router/pull/14335))
37
+
3
38
  ## 7.9.1
4
39
 
5
40
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-afe1c2609
2
+ * react-router v0.0.0-experimental-e2130f538
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -22,6 +22,7 @@ import {
22
22
  SingleFetchRedirectSymbol,
23
23
  StaticRouterProvider,
24
24
  StreamTransfer,
25
+ UNSTABLE_TransitionEnabledRouterProvider,
25
26
  convertRoutesToDataRoutes,
26
27
  createBrowserHistory,
27
28
  createContext,
@@ -59,7 +60,7 @@ import {
59
60
  withComponentProps,
60
61
  withErrorBoundaryProps,
61
62
  withHydrateFallbackProps
62
- } from "./chunk-V6EJ2E6X.mjs";
63
+ } from "./chunk-KNNCBCIS.mjs";
63
64
 
64
65
  // lib/dom/ssr/server.tsx
65
66
  import * as React from "react";
@@ -1458,7 +1459,6 @@ async function handleResourceRequest(serverMode, build, staticHandler, routeId,
1458
1459
  }
1459
1460
  function handleQueryRouteError(error) {
1460
1461
  if (isResponse(error)) {
1461
- error.headers.set("X-Remix-Catch", "yes");
1462
1462
  return error;
1463
1463
  }
1464
1464
  if (isRouteErrorResponse(error)) {
@@ -1485,10 +1485,7 @@ function errorResponseToJson(errorResponse, serverMode) {
1485
1485
  ),
1486
1486
  {
1487
1487
  status: errorResponse.status,
1488
- statusText: errorResponse.statusText,
1489
- headers: {
1490
- "X-Remix-Error": "yes"
1491
- }
1488
+ statusText: errorResponse.statusText
1492
1489
  }
1493
1490
  );
1494
1491
  }
@@ -1856,7 +1853,7 @@ function createCallServer({
1856
1853
  return async (id, args) => {
1857
1854
  let actionId = globalVar.__routerActionID = (globalVar.__routerActionID ?? (globalVar.__routerActionID = 0)) + 1;
1858
1855
  const temporaryReferences = createTemporaryReferenceSet();
1859
- const response = await fetchImplementation(
1856
+ const payloadPromise = fetchImplementation(
1860
1857
  new Request(location.href, {
1861
1858
  body: await encodeReply(args, { temporaryReferences }),
1862
1859
  method: "POST",
@@ -1865,44 +1862,45 @@ function createCallServer({
1865
1862
  "rsc-action-id": id
1866
1863
  }
1867
1864
  })
1868
- );
1869
- if (!response.body) {
1870
- throw new Error("No response body");
1871
- }
1872
- const payload = await createFromReadableStream(response.body, {
1873
- temporaryReferences
1874
- });
1875
- if (payload.type === "redirect") {
1876
- if (payload.reload) {
1877
- window.location.href = payload.location;
1878
- return;
1865
+ ).then((response) => {
1866
+ if (!response.body) {
1867
+ throw new Error("No response body");
1879
1868
  }
1880
- globalVar.__reactRouterDataRouter.navigate(payload.location, {
1881
- replace: payload.replace
1869
+ return createFromReadableStream(response.body, {
1870
+ temporaryReferences
1882
1871
  });
1883
- return payload.actionResult;
1884
- }
1885
- if (payload.type !== "action") {
1886
- throw new Error("Unexpected payload type");
1887
- }
1888
- if (payload.rerender) {
1889
- React4.startTransition(
1890
- // @ts-expect-error - We have old react types that don't know this can be async
1891
- async () => {
1892
- const rerender = await payload.rerender;
1893
- if (!rerender) return;
1894
- if (landedActionId < actionId && globalVar.__routerActionID <= actionId) {
1895
- landedActionId = actionId;
1896
- if (rerender.type === "redirect") {
1897
- if (rerender.reload) {
1898
- window.location.href = rerender.location;
1899
- return;
1900
- }
1872
+ });
1873
+ globalVar.__reactRouterDataRouter.__setPendingRerender(
1874
+ Promise.resolve(payloadPromise).then(async (payload) => {
1875
+ if (payload.type === "redirect") {
1876
+ if (payload.reload) {
1877
+ window.location.href = payload.location;
1878
+ return () => {
1879
+ };
1880
+ }
1881
+ return () => {
1882
+ globalVar.__reactRouterDataRouter.navigate(payload.location, {
1883
+ replace: payload.replace
1884
+ });
1885
+ };
1886
+ }
1887
+ if (payload.type !== "action") {
1888
+ throw new Error("Unexpected payload type");
1889
+ }
1890
+ const rerender = await payload.rerender;
1891
+ if (rerender && landedActionId < actionId && globalVar.__routerActionID <= actionId) {
1892
+ if (rerender.type === "redirect") {
1893
+ if (rerender.reload) {
1894
+ window.location.href = rerender.location;
1895
+ return;
1896
+ }
1897
+ return () => {
1901
1898
  globalVar.__reactRouterDataRouter.navigate(rerender.location, {
1902
1899
  replace: rerender.replace
1903
1900
  });
1904
- return;
1905
- }
1901
+ };
1902
+ }
1903
+ return () => {
1906
1904
  let lastMatch;
1907
1905
  for (const match of rerender.matches) {
1908
1906
  globalVar.__reactRouterDataRouter.patchRoutes(
@@ -1913,29 +1911,32 @@ function createCallServer({
1913
1911
  lastMatch = match;
1914
1912
  }
1915
1913
  window.__reactRouterDataRouter._internalSetStateDoNotUseOrYouWillBreakYourApp(
1916
- {}
1914
+ {
1915
+ loaderData: Object.assign(
1916
+ {},
1917
+ globalVar.__reactRouterDataRouter.state.loaderData,
1918
+ rerender.loaderData
1919
+ ),
1920
+ errors: rerender.errors ? Object.assign(
1921
+ {},
1922
+ globalVar.__reactRouterDataRouter.state.errors,
1923
+ rerender.errors
1924
+ ) : null
1925
+ }
1917
1926
  );
1918
- React4.startTransition(() => {
1919
- window.__reactRouterDataRouter._internalSetStateDoNotUseOrYouWillBreakYourApp(
1920
- {
1921
- loaderData: Object.assign(
1922
- {},
1923
- globalVar.__reactRouterDataRouter.state.loaderData,
1924
- rerender.loaderData
1925
- ),
1926
- errors: rerender.errors ? Object.assign(
1927
- {},
1928
- globalVar.__reactRouterDataRouter.state.errors,
1929
- rerender.errors
1930
- ) : null
1931
- }
1932
- );
1933
- });
1934
- }
1927
+ };
1935
1928
  }
1936
- );
1937
- }
1938
- return payload.actionResult;
1929
+ return () => {
1930
+ };
1931
+ }).catch(() => {
1932
+ })
1933
+ );
1934
+ return payloadPromise.then((payload) => {
1935
+ if (payload.type !== "action" && payload.type !== "redirect") {
1936
+ throw new Error("Unexpected payload type");
1937
+ }
1938
+ return payload.actionResult;
1939
+ });
1939
1940
  };
1940
1941
  }
1941
1942
  function createRouterFromPayload({
@@ -2155,8 +2156,8 @@ function getFetchAndDecodeViaRSC(createFromReadableStream, fetchImplementation)
2155
2156
  let res = await fetchImplementation(
2156
2157
  new Request(url, await createRequestInit(request))
2157
2158
  );
2158
- if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
2159
- throw new ErrorResponseImpl(404, "Not Found", true);
2159
+ if (res.status >= 400 && !res.headers.has("X-Remix-Response")) {
2160
+ throw new ErrorResponseImpl(res.status, res.statusText, await res.text());
2160
2161
  }
2161
2162
  invariant(res.body, "No response body to decode");
2162
2163
  try {
@@ -2302,7 +2303,7 @@ function RSCHydratedRouter({
2302
2303
  routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" },
2303
2304
  routeModules
2304
2305
  };
2305
- return /* @__PURE__ */ React4.createElement(RSCRouterContext.Provider, { value: true }, /* @__PURE__ */ React4.createElement(RSCRouterGlobalErrorBoundary, { location: location2 }, /* @__PURE__ */ React4.createElement(FrameworkContext.Provider, { value: frameworkContext }, /* @__PURE__ */ React4.createElement(RouterProvider, { router, flushSync: ReactDOM.flushSync }))));
2306
+ return /* @__PURE__ */ React4.createElement(RSCRouterContext.Provider, { value: true }, /* @__PURE__ */ React4.createElement(RSCRouterGlobalErrorBoundary, { location: location2 }, /* @__PURE__ */ React4.createElement(FrameworkContext.Provider, { value: frameworkContext }, /* @__PURE__ */ React4.createElement(UNSTABLE_TransitionEnabledRouterProvider, { router, flushSync: ReactDOM.flushSync }))));
2306
2307
  }
2307
2308
  function createRouteFromServerManifest(match, payload) {
2308
2309
  let hasInitialData = payload && match.id in payload.loaderData;
@@ -2644,7 +2645,7 @@ async function routeRSCServerRequest({
2644
2645
  headers2.delete("Content-Encoding");
2645
2646
  headers2.delete("Content-Length");
2646
2647
  headers2.delete("Content-Type");
2647
- headers2.delete("x-remix-response");
2648
+ headers2.delete("X-Remix-Response");
2648
2649
  headers2.set("Location", payload.location);
2649
2650
  return new Response(serverResponseB?.body || "", {
2650
2651
  headers: headers2,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v0.0.0-experimental-afe1c2609
2
+ * react-router v0.0.0-experimental-e2130f538
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -4148,7 +4148,10 @@ function getDataStrategyMatch(mapRouteProperties2, manifest, request, match, laz
4148
4148
  return shouldRevalidateLoader(match, unstable_shouldRevalidateArgs);
4149
4149
  },
4150
4150
  resolve(handlerOverride) {
4151
- if (isUsingNewApi || shouldLoad || handlerOverride && !isMutationMethod(request.method) && (match.route.lazy || match.route.loader)) {
4151
+ let { lazy, loader, middleware } = match.route;
4152
+ let callHandler = isUsingNewApi || shouldLoad || handlerOverride && !isMutationMethod(request.method) && (lazy || loader);
4153
+ let isMiddlewareOnlyRoute = middleware && middleware.length > 0 && !loader && !lazy;
4154
+ if (callHandler && !isMiddlewareOnlyRoute) {
4152
4155
  return callLoaderOrAction({
4153
4156
  request,
4154
4157
  match,
@@ -5653,6 +5656,119 @@ var Deferred = class {
5653
5656
  });
5654
5657
  }
5655
5658
  };
5659
+ function shallowDiff(a, b) {
5660
+ if (a === b) {
5661
+ return false;
5662
+ }
5663
+ let aKeys = Object.keys(a);
5664
+ let bKeys = Object.keys(b);
5665
+ if (aKeys.length !== bKeys.length) {
5666
+ return true;
5667
+ }
5668
+ for (let key of aKeys) {
5669
+ if (a[key] !== b[key]) {
5670
+ return true;
5671
+ }
5672
+ }
5673
+ return false;
5674
+ }
5675
+ function UNSTABLE_TransitionEnabledRouterProvider({
5676
+ router,
5677
+ flushSync: reactDomFlushSyncImpl,
5678
+ unstable_onError
5679
+ }) {
5680
+ let fetcherData = React3.useRef(/* @__PURE__ */ new Map());
5681
+ let [revalidating, startRevalidation] = React3.useTransition();
5682
+ let [state, setState] = React3.useState(router.state);
5683
+ router.__setPendingRerender = (promise) => startRevalidation(
5684
+ // @ts-expect-error - need react 19 types for this to be async
5685
+ async () => {
5686
+ const rerender = await promise;
5687
+ startRevalidation(() => {
5688
+ rerender();
5689
+ });
5690
+ }
5691
+ );
5692
+ let navigator = React3.useMemo(() => {
5693
+ return {
5694
+ createHref: router.createHref,
5695
+ encodeLocation: router.encodeLocation,
5696
+ go: (n) => router.navigate(n),
5697
+ push: (to, state2, opts) => router.navigate(to, {
5698
+ state: state2,
5699
+ preventScrollReset: opts?.preventScrollReset
5700
+ }),
5701
+ replace: (to, state2, opts) => router.navigate(to, {
5702
+ replace: true,
5703
+ state: state2,
5704
+ preventScrollReset: opts?.preventScrollReset
5705
+ })
5706
+ };
5707
+ }, [router]);
5708
+ let basename = router.basename || "/";
5709
+ let dataRouterContext = React3.useMemo(
5710
+ () => ({
5711
+ router,
5712
+ navigator,
5713
+ static: false,
5714
+ basename,
5715
+ unstable_onError
5716
+ }),
5717
+ [router, navigator, basename, unstable_onError]
5718
+ );
5719
+ React3.useLayoutEffect(() => {
5720
+ return router.subscribe(
5721
+ (newState, { deletedFetchers, flushSync, viewTransitionOpts }) => {
5722
+ newState.fetchers.forEach((fetcher, key) => {
5723
+ if (fetcher.data !== void 0) {
5724
+ fetcherData.current.set(key, fetcher.data);
5725
+ }
5726
+ });
5727
+ deletedFetchers.forEach((key) => fetcherData.current.delete(key));
5728
+ const diff = shallowDiff(state, newState);
5729
+ if (!diff) return;
5730
+ if (flushSync) {
5731
+ if (reactDomFlushSyncImpl) {
5732
+ reactDomFlushSyncImpl(() => setState(newState));
5733
+ } else {
5734
+ setState(newState);
5735
+ }
5736
+ } else {
5737
+ React3.startTransition(() => {
5738
+ setState(newState);
5739
+ });
5740
+ }
5741
+ }
5742
+ );
5743
+ }, [router, reactDomFlushSyncImpl, state]);
5744
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React3.createElement(
5745
+ DataRouterStateContext.Provider,
5746
+ {
5747
+ value: {
5748
+ ...state,
5749
+ revalidation: revalidating ? "loading" : state.revalidation
5750
+ }
5751
+ },
5752
+ /* @__PURE__ */ React3.createElement(FetchersContext.Provider, { value: fetcherData.current }, /* @__PURE__ */ React3.createElement(
5753
+ Router,
5754
+ {
5755
+ basename,
5756
+ location: state.location,
5757
+ navigationType: state.historyAction,
5758
+ navigator
5759
+ },
5760
+ /* @__PURE__ */ React3.createElement(
5761
+ MemoizedDataRoutes,
5762
+ {
5763
+ routes: router.routes,
5764
+ future: router.future,
5765
+ state,
5766
+ unstable_onError
5767
+ }
5768
+ )
5769
+ ))
5770
+ )), null);
5771
+ }
5656
5772
  function RouterProvider({
5657
5773
  router,
5658
5774
  flushSync: reactDomFlushSyncImpl,
@@ -7355,8 +7471,8 @@ async function fetchAndDecodeViaTurboStream(args, basename, targetRoutes) {
7355
7471
  }
7356
7472
  }
7357
7473
  let res = await fetch(url, await createRequestInit(request));
7358
- if (res.status === 404 && !res.headers.has("X-Remix-Response")) {
7359
- throw new ErrorResponseImpl(404, "Not Found", true);
7474
+ if (res.status >= 400 && !res.headers.has("X-Remix-Response")) {
7475
+ throw new ErrorResponseImpl(res.status, res.statusText, await res.text());
7360
7476
  }
7361
7477
  if (res.status === 204 && res.headers.has("X-Remix-Redirect")) {
7362
7478
  return {
@@ -8997,7 +9113,7 @@ var isBrowser = typeof window !== "undefined" && typeof window.document !== "und
8997
9113
  try {
8998
9114
  if (isBrowser) {
8999
9115
  window.__reactRouterVersion = // @ts-expect-error
9000
- "0.0.0-experimental-afe1c2609";
9116
+ "0.0.0-experimental-e2130f538";
9001
9117
  }
9002
9118
  } catch (e) {
9003
9119
  }
@@ -10159,6 +10275,7 @@ export {
10159
10275
  mapRouteProperties,
10160
10276
  hydrationRouteProperties,
10161
10277
  createMemoryRouter,
10278
+ UNSTABLE_TransitionEnabledRouterProvider,
10162
10279
  RouterProvider,
10163
10280
  MemoryRouter,
10164
10281
  Navigate,