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