react-router 8.0.0-pre.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/dist/development/dom-export.js +1 -1
- package/dist/development/index-react-server-client.js +1 -1
- package/dist/development/index-react-server.d.ts +9 -2
- package/dist/development/index-react-server.js +91 -88
- package/dist/development/index.d.ts +1 -2
- package/dist/development/index.js +2 -3
- package/dist/development/lib/actions.js +6 -18
- package/dist/development/lib/components.d.ts +11 -3
- package/dist/development/lib/components.js +8 -2
- package/dist/development/lib/context.js +1 -1
- package/dist/development/lib/dom/dom.js +1 -1
- package/dist/development/lib/dom/lib.d.ts +12 -1
- package/dist/development/lib/dom/lib.js +18 -6
- package/dist/development/lib/dom/server.js +2 -2
- package/dist/development/lib/dom/ssr/components.d.ts +4 -2
- package/dist/development/lib/dom/ssr/components.js +13 -3
- package/dist/development/lib/dom/ssr/data.js +1 -1
- package/dist/development/lib/dom/ssr/entry.d.ts +1 -0
- package/dist/development/lib/dom/ssr/errorBoundaries.js +7 -3
- package/dist/development/lib/dom/ssr/fallback.js +8 -3
- package/dist/development/lib/dom/ssr/fog-of-war.js +12 -2
- package/dist/development/lib/dom/ssr/hydration.js +1 -1
- 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 +1 -1
- package/dist/development/lib/dom/ssr/routeModules.js +1 -1
- package/dist/development/lib/dom/ssr/routes-test-stub.js +1 -1
- package/dist/development/lib/dom/ssr/routes.js +1 -1
- package/dist/development/lib/dom/ssr/server.d.ts +4 -1
- package/dist/development/lib/dom/ssr/server.js +2 -1
- package/dist/development/lib/dom/ssr/single-fetch.js +2 -3
- package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/development/lib/dom-export/hydrated-router.d.ts +1 -1
- package/dist/development/lib/dom-export/hydrated-router.js +14 -17
- package/dist/development/lib/errors.js +1 -1
- package/dist/development/lib/hooks.js +6 -4
- package/dist/development/lib/href.js +1 -1
- package/dist/development/lib/router/history.js +3 -2
- package/dist/development/lib/router/instrumentation.js +1 -1
- package/dist/development/lib/router/links.d.ts +3 -2
- package/dist/development/lib/router/router.js +13 -6
- package/dist/development/lib/router/url.js +18 -0
- package/dist/development/lib/router/utils.d.ts +6 -0
- package/dist/development/lib/router/utils.js +27 -8
- package/dist/development/lib/rsc/browser.js +21 -17
- 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 +1 -1
- package/dist/development/lib/rsc/route-modules.js +1 -1
- package/dist/development/lib/rsc/server.ssr.js +27 -11
- 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 +2 -22
- 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 +1 -1
- package/dist/development/lib/server-runtime/routes.js +1 -1
- package/dist/development/lib/server-runtime/server.js +17 -23
- 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 +4 -4
- package/dist/development/lib/server-runtime/urls.js +2 -5
- package/dist/development/lib/server-runtime/warnings.js +1 -1
- package/dist/development/lib/types/internal.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +2 -1
- package/dist/development/vendor/turbo-stream-v2/unflatten.js +3 -2
- package/dist/development/vendor/turbo-stream-v2/utils.js +2 -10
- package/dist/production/dom-export.js +1 -1
- package/dist/production/index-react-server-client.js +1 -1
- package/dist/production/index-react-server.d.ts +9 -2
- package/dist/production/index-react-server.js +91 -88
- package/dist/production/index.d.ts +1 -2
- package/dist/production/index.js +2 -3
- package/dist/production/lib/actions.js +6 -18
- package/dist/production/lib/components.d.ts +11 -3
- package/dist/production/lib/components.js +8 -2
- package/dist/production/lib/context.js +1 -1
- package/dist/production/lib/dom/dom.js +1 -1
- package/dist/production/lib/dom/lib.d.ts +12 -1
- package/dist/production/lib/dom/lib.js +18 -6
- package/dist/production/lib/dom/server.js +2 -2
- package/dist/production/lib/dom/ssr/components.d.ts +4 -2
- package/dist/production/lib/dom/ssr/components.js +13 -3
- package/dist/production/lib/dom/ssr/data.js +1 -1
- package/dist/production/lib/dom/ssr/entry.d.ts +1 -0
- package/dist/production/lib/dom/ssr/errorBoundaries.js +7 -3
- package/dist/production/lib/dom/ssr/fallback.js +3 -1
- package/dist/production/lib/dom/ssr/fog-of-war.js +12 -2
- package/dist/production/lib/dom/ssr/hydration.js +1 -1
- 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 +1 -1
- package/dist/production/lib/dom/ssr/routeModules.js +1 -1
- package/dist/production/lib/dom/ssr/routes-test-stub.js +1 -1
- package/dist/production/lib/dom/ssr/routes.js +1 -1
- package/dist/production/lib/dom/ssr/server.d.ts +4 -1
- package/dist/production/lib/dom/ssr/server.js +2 -1
- package/dist/production/lib/dom/ssr/single-fetch.js +2 -3
- package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/production/lib/dom-export/hydrated-router.d.ts +1 -1
- package/dist/production/lib/dom-export/hydrated-router.js +14 -17
- package/dist/production/lib/errors.js +1 -1
- package/dist/production/lib/hooks.js +6 -4
- package/dist/production/lib/href.js +1 -1
- package/dist/production/lib/router/history.js +3 -2
- package/dist/production/lib/router/instrumentation.js +1 -1
- package/dist/production/lib/router/links.d.ts +3 -2
- package/dist/production/lib/router/router.js +13 -6
- package/dist/production/lib/router/url.js +18 -0
- package/dist/production/lib/router/utils.d.ts +6 -0
- package/dist/production/lib/router/utils.js +27 -8
- package/dist/production/lib/rsc/browser.js +21 -17
- 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 +1 -1
- package/dist/production/lib/rsc/route-modules.js +1 -1
- package/dist/production/lib/rsc/server.ssr.js +27 -11
- 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 +2 -22
- 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 +1 -1
- package/dist/production/lib/server-runtime/routes.js +1 -1
- package/dist/production/lib/server-runtime/server.js +17 -23
- 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 +4 -4
- package/dist/production/lib/server-runtime/urls.js +2 -5
- package/dist/production/lib/server-runtime/warnings.js +1 -1
- package/dist/production/lib/types/internal.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +2 -1
- package/dist/production/vendor/turbo-stream-v2/unflatten.js +3 -2
- package/dist/production/vendor/turbo-stream-v2/utils.js +2 -10
- package/docs/explanation/code-splitting.md +1 -1
- package/docs/explanation/index-query-param.md +2 -2
- package/docs/explanation/type-safety.md +1 -1
- package/docs/how-to/data-strategy.md +5 -5
- package/docs/how-to/error-reporting.md +10 -2
- package/docs/how-to/headers.md +2 -1
- package/docs/how-to/middleware.md +8 -89
- package/docs/how-to/security.md +9 -7
- package/docs/how-to/status.md +1 -1
- package/docs/index.md +3 -6
- package/docs/start/data/installation.md +4 -0
- package/docs/start/data/route-object.md +20 -0
- package/docs/start/framework/actions.md +0 -1
- package/docs/start/framework/data-loading.md +1 -1
- package/docs/start/framework/deploying.md +4 -0
- package/docs/start/framework/installation.md +0 -1
- package/docs/start/modes.md +1 -2
- package/docs/upgrading/component-routes.md +2 -2
- package/docs/upgrading/future.md +58 -11
- package/docs/upgrading/router-provider.md +6 -3
- package/docs/upgrading/v7.md +443 -0
- package/package.json +7 -7
- package/dist/development/lib/dom/ssr/errors.d.ts +0 -7
- package/dist/development/lib/dom/ssr/errors.js +0 -36
- package/dist/production/lib/dom/ssr/errors.d.ts +0 -7
- package/dist/production/lib/dom/ssr/errors.js +0 -36
- package/docs/upgrading/remix.md +0 -403
- package/docs/upgrading/v6.md +0 -379
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0
|
|
2
|
+
* react-router v8.0.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
+
import { PROTOCOL_RELATIVE_URL_REGEX, normalizeProtocolRelativeUrl } from "./url.js";
|
|
11
12
|
import { createBrowserURLImpl, createLocation, createPath, invariant, parsePath, warning } from "./history.js";
|
|
12
13
|
import { ErrorResponseImpl, RouterContextProvider, convertRouteMatchToUiMatch, convertRoutesToDataRoutes, flattenAndRankRoutes, getPathContributingMatches, getResolveToMatches, getRoutePattern, isAbsoluteUrl, isRouteErrorResponse, isUnsupportedLazyRouteFunctionKey, isUnsupportedLazyRouteObjectKey, matchRoutesImpl, prependBasename, removeDoubleSlashes, resolveTo, stripBasename } from "./utils.js";
|
|
13
14
|
import { getRouteInstrumentationUpdates, instrumentClientSideRouter } from "./instrumentation.js";
|
|
@@ -2572,17 +2573,23 @@ const invalidProtocols = [
|
|
|
2572
2573
|
"filesystem:",
|
|
2573
2574
|
"javascript:"
|
|
2574
2575
|
];
|
|
2576
|
+
function hasInvalidProtocol(location) {
|
|
2577
|
+
try {
|
|
2578
|
+
return invalidProtocols.includes(new URL(location).protocol);
|
|
2579
|
+
} catch {
|
|
2580
|
+
return false;
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2575
2583
|
function normalizeRedirectLocation(location, currentUrl, basename, historyInstance) {
|
|
2576
2584
|
if (isAbsoluteUrl(location)) {
|
|
2577
2585
|
let normalizedLocation = location;
|
|
2578
|
-
let url =
|
|
2579
|
-
if (
|
|
2586
|
+
let url = PROTOCOL_RELATIVE_URL_REGEX.test(normalizedLocation) ? new URL(normalizeProtocolRelativeUrl(normalizedLocation, currentUrl.protocol)) : new URL(normalizedLocation);
|
|
2587
|
+
if (hasInvalidProtocol(url.toString())) throw new Error("Invalid redirect location");
|
|
2580
2588
|
let isSameBasename = stripBasename(url.pathname, basename) != null;
|
|
2581
2589
|
if (url.origin === currentUrl.origin && isSameBasename) return removeDoubleSlashes(url.pathname) + url.search + url.hash;
|
|
2582
2590
|
}
|
|
2583
2591
|
try {
|
|
2584
|
-
|
|
2585
|
-
if (invalidProtocols.includes(url.protocol)) throw new Error("Invalid redirect location");
|
|
2592
|
+
if (hasInvalidProtocol(historyInstance.createURL(location).toString())) throw new Error("Invalid redirect location");
|
|
2586
2593
|
} catch (e) {}
|
|
2587
2594
|
return location;
|
|
2588
2595
|
}
|
|
@@ -2978,4 +2985,4 @@ function createDeferred() {
|
|
|
2978
2985
|
};
|
|
2979
2986
|
}
|
|
2980
2987
|
//#endregion
|
|
2981
|
-
export { IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, createRouter, createStaticHandler, getStaticContextFromError,
|
|
2988
|
+
export { IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, createRouter, createStaticHandler, getStaticContextFromError, hasInvalidProtocol, isDataWithResponseInit, isMutationMethod, isRedirectResponse, isRedirectStatusCode, isResponse };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router v8.0.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
//#region lib/router/url.ts
|
|
12
|
+
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i;
|
|
13
|
+
const PROTOCOL_RELATIVE_URL_REGEX = /^[\\/]{2}/;
|
|
14
|
+
function normalizeProtocolRelativeUrl(url, protocol) {
|
|
15
|
+
return protocol + url.replace(/\\/g, "/");
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { ABSOLUTE_URL_REGEX, PROTOCOL_RELATIVE_URL_REGEX, normalizeProtocolRelativeUrl };
|
|
@@ -668,6 +668,8 @@ interface RouteMeta<RouteObjectType extends RouteObject = RouteObject> {
|
|
|
668
668
|
caseSensitive: boolean;
|
|
669
669
|
childrenIndex: number;
|
|
670
670
|
route: RouteObjectType;
|
|
671
|
+
matcher?: RegExp;
|
|
672
|
+
compiledParams?: CompiledPathParam[];
|
|
671
673
|
}
|
|
672
674
|
/**
|
|
673
675
|
* @private
|
|
@@ -752,6 +754,10 @@ interface PathMatch<ParamKey extends string = string> {
|
|
|
752
754
|
* or `null` if it does not match.
|
|
753
755
|
*/
|
|
754
756
|
declare function matchPath<Path extends string>(pattern: PathPattern<Path> | Path, pathname: string): PathMatch<ParamParseKey<Path>> | null;
|
|
757
|
+
type CompiledPathParam = {
|
|
758
|
+
paramName: string;
|
|
759
|
+
isOptional?: boolean;
|
|
760
|
+
};
|
|
755
761
|
/**
|
|
756
762
|
* Returns a resolved {@link Path} object relative to the given pathname.
|
|
757
763
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0
|
|
2
|
+
* react-router v8.0.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
+
import { ABSOLUTE_URL_REGEX, PROTOCOL_RELATIVE_URL_REGEX, normalizeProtocolRelativeUrl } from "./url.js";
|
|
11
12
|
import { invariant, parsePath, warning } from "./history.js";
|
|
12
13
|
import * as React$1 from "react";
|
|
13
14
|
//#region lib/router/utils.ts
|
|
@@ -289,7 +290,14 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "",
|
|
|
289
290
|
branches.push({
|
|
290
291
|
path,
|
|
291
292
|
score: computeScore(path, route.index),
|
|
292
|
-
routesMeta
|
|
293
|
+
routesMeta: routesMeta.map((meta, i) => {
|
|
294
|
+
let [matcher, params] = compilePath(meta.relativePath, meta.caseSensitive, i === routesMeta.length - 1);
|
|
295
|
+
return {
|
|
296
|
+
...meta,
|
|
297
|
+
matcher,
|
|
298
|
+
compiledParams: params
|
|
299
|
+
};
|
|
300
|
+
})
|
|
293
301
|
});
|
|
294
302
|
};
|
|
295
303
|
routes.forEach((route, index) => {
|
|
@@ -340,11 +348,12 @@ function matchRouteBranch(branch, pathname, allowPartial = false) {
|
|
|
340
348
|
let meta = routesMeta[i];
|
|
341
349
|
let end = i === routesMeta.length - 1;
|
|
342
350
|
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
|
343
|
-
let
|
|
351
|
+
let pattern = {
|
|
344
352
|
path: meta.relativePath,
|
|
345
353
|
caseSensitive: meta.caseSensitive,
|
|
346
354
|
end
|
|
347
|
-
}
|
|
355
|
+
};
|
|
356
|
+
let match = meta.matcher && meta.compiledParams ? matchPathImpl(pattern, remainingPathname, meta.matcher, meta.compiledParams) : matchPath(pattern, remainingPathname);
|
|
348
357
|
let route = meta.route;
|
|
349
358
|
if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) match = matchPath({
|
|
350
359
|
path: meta.relativePath,
|
|
@@ -418,6 +427,9 @@ function matchPath(pattern, pathname) {
|
|
|
418
427
|
end: true
|
|
419
428
|
};
|
|
420
429
|
let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
|
430
|
+
return matchPathImpl(pattern, pathname, matcher, compiledParams);
|
|
431
|
+
}
|
|
432
|
+
function matchPathImpl(pattern, pathname, matcher, compiledParams) {
|
|
421
433
|
let match = pathname.match(matcher);
|
|
422
434
|
if (!match) return null;
|
|
423
435
|
let matchedPathname = match[0];
|
|
@@ -480,7 +492,6 @@ function stripBasename(pathname, basename) {
|
|
|
480
492
|
function prependBasename({ basename, pathname }) {
|
|
481
493
|
return pathname === "/" ? basename : joinPaths([basename, pathname]);
|
|
482
494
|
}
|
|
483
|
-
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
484
495
|
const isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url);
|
|
485
496
|
/**
|
|
486
497
|
* Returns a resolved {@link Path} object relative to the given pathname.
|
|
@@ -556,7 +567,7 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = fal
|
|
|
556
567
|
if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) path.pathname += "/";
|
|
557
568
|
return path;
|
|
558
569
|
}
|
|
559
|
-
const removeDoubleSlashes = (path) => path.replace(
|
|
570
|
+
const removeDoubleSlashes = (path) => path.replace(/[\\/]{2,}/g, "/");
|
|
560
571
|
const joinPaths = (paths) => removeDoubleSlashes(paths.join("/"));
|
|
561
572
|
const removeTrailingSlash = (path) => path.replace(/\/+$/, "");
|
|
562
573
|
const normalizePathname = (pathname) => removeTrailingSlash(pathname).replace(/^\/*/, "/");
|
|
@@ -709,6 +720,14 @@ const replace = (url, init) => {
|
|
|
709
720
|
response.headers.set("X-Remix-Replace", "true");
|
|
710
721
|
return response;
|
|
711
722
|
};
|
|
723
|
+
const SUPPORTED_ERROR_TYPES = [
|
|
724
|
+
"EvalError",
|
|
725
|
+
"RangeError",
|
|
726
|
+
"ReferenceError",
|
|
727
|
+
"SyntaxError",
|
|
728
|
+
"TypeError",
|
|
729
|
+
"URIError"
|
|
730
|
+
];
|
|
712
731
|
var ErrorResponseImpl = class {
|
|
713
732
|
status;
|
|
714
733
|
statusText;
|
|
@@ -774,7 +793,7 @@ function parseToInfo(_to, basename) {
|
|
|
774
793
|
let isExternal = false;
|
|
775
794
|
if (isBrowser) try {
|
|
776
795
|
let currentUrl = new URL(window.location.href);
|
|
777
|
-
let targetUrl =
|
|
796
|
+
let targetUrl = PROTOCOL_RELATIVE_URL_REGEX.test(to) ? new URL(normalizeProtocolRelativeUrl(to, currentUrl.protocol)) : new URL(to);
|
|
778
797
|
let path = stripBasename(targetUrl.pathname, basename);
|
|
779
798
|
if (targetUrl.origin === currentUrl.origin && path != null) to = path + targetUrl.search + targetUrl.hash;
|
|
780
799
|
else isExternal = true;
|
|
@@ -788,4 +807,4 @@ function parseToInfo(_to, basename) {
|
|
|
788
807
|
};
|
|
789
808
|
}
|
|
790
809
|
//#endregion
|
|
791
|
-
export { ErrorResponseImpl, RouterContextProvider, compilePath, convertRouteMatchToUiMatch, convertRoutesToDataRoutes, createContext, data, decodePath, defaultMapRouteProperties, flattenAndRankRoutes, generatePath, getPathContributingMatches, getResolveToMatches, getRoutePattern, isAbsoluteUrl, isBrowser, isRouteErrorResponse, isUnsupportedLazyRouteFunctionKey, isUnsupportedLazyRouteObjectKey, joinPaths, matchPath, matchRoutes, matchRoutesImpl, parseToInfo, prependBasename, redirect, redirectDocument, removeDoubleSlashes, replace, resolvePath, resolveTo, stripBasename };
|
|
810
|
+
export { ErrorResponseImpl, RouterContextProvider, SUPPORTED_ERROR_TYPES, compilePath, convertRouteMatchToUiMatch, convertRoutesToDataRoutes, createContext, data, decodePath, defaultMapRouteProperties, flattenAndRankRoutes, generatePath, getPathContributingMatches, getResolveToMatches, getRoutePattern, isAbsoluteUrl, isBrowser, isRouteErrorResponse, isUnsupportedLazyRouteFunctionKey, isUnsupportedLazyRouteObjectKey, joinPaths, matchPath, matchRoutes, matchRoutesImpl, parseToInfo, prependBasename, redirect, redirectDocument, removeDoubleSlashes, removeTrailingSlash, replace, resolvePath, resolveTo, stripBasename };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0
|
|
2
|
+
* react-router v8.0.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
+
import { PROTOCOL_RELATIVE_URL_REGEX } from "../router/url.js";
|
|
11
12
|
import { createBrowserHistory, invariant } from "../router/history.js";
|
|
12
|
-
import { ErrorResponseImpl, createContext } from "../router/utils.js";
|
|
13
|
-
import { createRouter,
|
|
13
|
+
import { ErrorResponseImpl, createContext, resolvePath } from "../router/utils.js";
|
|
14
|
+
import { createRouter, hasInvalidProtocol, isMutationMethod } from "../router/router.js";
|
|
14
15
|
import { RSCRouterContext } from "../context.js";
|
|
15
16
|
import { RouterProvider } from "../components.js";
|
|
16
17
|
import { createRequestInit } from "../dom/ssr/data.js";
|
|
17
18
|
import { getSingleFetchDataStrategyImpl, singleFetchUrl, stripIndexParam } from "../dom/ssr/single-fetch.js";
|
|
18
19
|
import { noActionDefinedError, shouldHydrateRouteLoader } from "../dom/ssr/routes.js";
|
|
19
|
-
import "../dom/ssr/fog-of-war.js";
|
|
20
|
+
import { getPathsWithAncestors } from "../dom/ssr/fog-of-war.js";
|
|
20
21
|
import { FrameworkContext, setIsHydrated } from "../dom/ssr/components.js";
|
|
21
22
|
import { RSCRouterGlobalErrorBoundary } from "./errorBoundaries.js";
|
|
22
23
|
import { populateRSCRouteModules } from "./route-modules.js";
|
|
@@ -80,13 +81,14 @@ function createCallServer({ createFromReadableStream, createTemporaryReferenceSe
|
|
|
80
81
|
});
|
|
81
82
|
React$1.startTransition(() => Promise.resolve(payloadPromise).then(async (payload) => {
|
|
82
83
|
if (payload.type === "redirect") {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
let location = normalizeRedirectLocation(payload.location);
|
|
85
|
+
if (payload.reload || isExternalLocation(location)) {
|
|
86
|
+
if (hasInvalidProtocol(location)) throw new Error("Invalid redirect location");
|
|
87
|
+
window.location.href = location;
|
|
86
88
|
return;
|
|
87
89
|
}
|
|
88
90
|
React$1.startTransition(() => {
|
|
89
|
-
globalVar.__reactRouterDataRouter.navigate(
|
|
91
|
+
globalVar.__reactRouterDataRouter.navigate(location, { replace: payload.replace });
|
|
90
92
|
});
|
|
91
93
|
return;
|
|
92
94
|
}
|
|
@@ -94,13 +96,14 @@ function createCallServer({ createFromReadableStream, createTemporaryReferenceSe
|
|
|
94
96
|
const rerender = await payload.rerender;
|
|
95
97
|
if (rerender && landedActionId < actionId && globalVar.__routerActionID <= actionId) {
|
|
96
98
|
if (rerender.type === "redirect") {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
let location = normalizeRedirectLocation(rerender.location);
|
|
100
|
+
if (rerender.reload || isExternalLocation(location)) {
|
|
101
|
+
if (hasInvalidProtocol(location)) throw new Error("Invalid redirect location");
|
|
102
|
+
window.location.href = location;
|
|
100
103
|
return;
|
|
101
104
|
}
|
|
102
105
|
React$1.startTransition(() => {
|
|
103
|
-
globalVar.__reactRouterDataRouter.navigate(
|
|
106
|
+
globalVar.__reactRouterDataRouter.navigate(location, { replace: rerender.replace });
|
|
104
107
|
});
|
|
105
108
|
return;
|
|
106
109
|
}
|
|
@@ -533,6 +536,7 @@ function getManifestUrl(paths) {
|
|
|
533
536
|
return url;
|
|
534
537
|
}
|
|
535
538
|
async function fetchAndApplyManifestPatches(paths, createFromReadableStream, fetchImplementation, signal) {
|
|
539
|
+
paths = getPathsWithAncestors(paths);
|
|
536
540
|
let url = getManifestUrl(paths);
|
|
537
541
|
if (url == null) return;
|
|
538
542
|
if (url.toString().length > 7680) {
|
|
@@ -568,12 +572,12 @@ function debounce(callback, wait) {
|
|
|
568
572
|
function isExternalLocation(location) {
|
|
569
573
|
return new URL(location, window.location.href).origin !== window.location.origin;
|
|
570
574
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
return false;
|
|
575
|
+
function normalizeRedirectLocation(location) {
|
|
576
|
+
if (PROTOCOL_RELATIVE_URL_REGEX.test(location)) {
|
|
577
|
+
let path = resolvePath(location);
|
|
578
|
+
return path.pathname + path.search + path.hash;
|
|
576
579
|
}
|
|
580
|
+
return location;
|
|
577
581
|
}
|
|
578
582
|
function cloneRoutes(routes) {
|
|
579
583
|
if (!routes) return void 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0
|
|
2
|
+
* react-router v8.0.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
11
|
import { isRouteErrorResponse } from "../router/utils.js";
|
|
12
|
+
import { hasInvalidProtocol } from "../router/router.js";
|
|
12
13
|
import { RSCRouterContext } from "../context.js";
|
|
13
14
|
import { decodeRedirectErrorDigest, decodeRouteErrorResponseDigest } from "../errors.js";
|
|
14
15
|
import { escapeHtml } from "../dom/ssr/markup.js";
|
|
@@ -122,6 +123,7 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
122
123
|
if (!detectRedirectResponse.body) throw new Error("Failed to clone server response");
|
|
123
124
|
const payload = await createFromReadableStream(detectRedirectResponse.body);
|
|
124
125
|
if (serverResponse.status === 202 && payload.type === "redirect") {
|
|
126
|
+
if (hasInvalidProtocol(payload.location)) throw new Error("Invalid redirect location");
|
|
125
127
|
const headers = new Headers(serverResponse.headers);
|
|
126
128
|
headers.delete("Content-Encoding");
|
|
127
129
|
headers.delete("Content-Length");
|
|
@@ -159,6 +161,7 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
159
161
|
for (const [key, value] of serverResponse.headers) headers.append(key, value);
|
|
160
162
|
headers.set("Content-Type", "text/html; charset=utf-8");
|
|
161
163
|
if (renderRedirect) {
|
|
164
|
+
if (hasInvalidProtocol(renderRedirect.location)) throw new Error("Invalid redirect location");
|
|
162
165
|
headers.set("Location", renderRedirect.location);
|
|
163
166
|
return new Response(html, {
|
|
164
167
|
status: renderRedirect.status,
|
|
@@ -166,7 +169,10 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
166
169
|
});
|
|
167
170
|
}
|
|
168
171
|
const redirectTransform = new TransformStream({ flush(controller) {
|
|
169
|
-
if (renderRedirect)
|
|
172
|
+
if (renderRedirect) {
|
|
173
|
+
if (hasInvalidProtocol(renderRedirect.location)) return;
|
|
174
|
+
controller.enqueue(new TextEncoder().encode(`<meta http-equiv="refresh" content="0;url=${escapeHtml(renderRedirect.location)}"/>`));
|
|
175
|
+
}
|
|
170
176
|
} });
|
|
171
177
|
if (!hydrate) return new Response(html.pipeThrough(redirectTransform), {
|
|
172
178
|
status,
|
|
@@ -182,10 +188,13 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
182
188
|
});
|
|
183
189
|
} catch (error) {
|
|
184
190
|
if (error instanceof Response) return error;
|
|
185
|
-
if (renderRedirect)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
191
|
+
if (renderRedirect) {
|
|
192
|
+
if (hasInvalidProtocol(renderRedirect.location)) throw new Error("Invalid redirect location");
|
|
193
|
+
return new Response(`Redirect: ${renderRedirect.location}`, {
|
|
194
|
+
status: renderRedirect.status,
|
|
195
|
+
headers: { Location: renderRedirect.location }
|
|
196
|
+
});
|
|
197
|
+
}
|
|
189
198
|
try {
|
|
190
199
|
let normalizedError = renderError ?? error;
|
|
191
200
|
let [status, statusText] = isRouteErrorResponse(normalizedError) ? [normalizedError.status, normalizedError.statusText] : [500, ""];
|
|
@@ -230,6 +239,7 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
230
239
|
for (const [key, value] of serverResponse.headers) headers.append(key, value);
|
|
231
240
|
headers.set("Content-Type", "text/html; charset=utf-8");
|
|
232
241
|
if (retryRedirect) {
|
|
242
|
+
if (hasInvalidProtocol(retryRedirect.location)) throw new Error("Invalid redirect location");
|
|
233
243
|
headers.set("Location", retryRedirect.location);
|
|
234
244
|
return new Response(html, {
|
|
235
245
|
status: retryRedirect.status,
|
|
@@ -237,7 +247,10 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
237
247
|
});
|
|
238
248
|
}
|
|
239
249
|
const retryRedirectTransform = new TransformStream({ flush(controller) {
|
|
240
|
-
if (retryRedirect)
|
|
250
|
+
if (retryRedirect) {
|
|
251
|
+
if (hasInvalidProtocol(retryRedirect.location)) return;
|
|
252
|
+
controller.enqueue(new TextEncoder().encode(`<meta http-equiv="refresh" content="0;url=${escapeHtml(retryRedirect.location)}"/>`));
|
|
253
|
+
}
|
|
241
254
|
} });
|
|
242
255
|
if (!hydrate) return new Response(html.pipeThrough(retryRedirectTransform), {
|
|
243
256
|
status,
|
|
@@ -295,10 +308,13 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
|
|
|
295
308
|
function RSCStaticRouter({ getPayload }) {
|
|
296
309
|
const decoded = getPayload();
|
|
297
310
|
const payload = React$1.use(decoded);
|
|
298
|
-
if (payload.type === "redirect")
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
311
|
+
if (payload.type === "redirect") {
|
|
312
|
+
if (hasInvalidProtocol(payload.location)) throw new Error("Invalid redirect location");
|
|
313
|
+
throw new Response(null, {
|
|
314
|
+
status: payload.status,
|
|
315
|
+
headers: { Location: payload.location }
|
|
316
|
+
});
|
|
317
|
+
}
|
|
302
318
|
if (payload.type !== "render") return null;
|
|
303
319
|
let patchedLoaderData = { ...payload.loaderData };
|
|
304
320
|
for (const match of payload.matches) if (shouldHydrateRouteLoader(match.id, match.clientLoader, match.hasLoader, false) && (match.hydrateFallbackElement || !match.hasLoader)) delete patchedLoaderData[match.id];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0
|
|
2
|
+
* react-router v8.0.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { isRouteErrorResponse } from "../router/utils.js";
|
|
12
11
|
import "./mode.js";
|
|
13
12
|
//#region lib/server-runtime/errors.ts
|
|
14
13
|
/**
|
|
@@ -72,24 +71,5 @@ function serializeError(error, serverMode) {
|
|
|
72
71
|
stack: sanitized.stack
|
|
73
72
|
};
|
|
74
73
|
}
|
|
75
|
-
function serializeErrors(errors, serverMode) {
|
|
76
|
-
if (!errors) return null;
|
|
77
|
-
let entries = Object.entries(errors);
|
|
78
|
-
let serialized = {};
|
|
79
|
-
for (let [key, val] of entries) if (isRouteErrorResponse(val)) serialized[key] = {
|
|
80
|
-
...val,
|
|
81
|
-
__type: "RouteErrorResponse"
|
|
82
|
-
};
|
|
83
|
-
else if (val instanceof Error) {
|
|
84
|
-
let sanitized = sanitizeError(val, serverMode);
|
|
85
|
-
serialized[key] = {
|
|
86
|
-
message: sanitized.message,
|
|
87
|
-
stack: sanitized.stack,
|
|
88
|
-
__type: "Error",
|
|
89
|
-
...sanitized.name !== "Error" ? { __subType: sanitized.name } : {}
|
|
90
|
-
};
|
|
91
|
-
} else serialized[key] = val;
|
|
92
|
-
return serialized;
|
|
93
|
-
}
|
|
94
74
|
//#endregion
|
|
95
|
-
export { sanitizeError, sanitizeErrors, serializeError
|
|
75
|
+
export { sanitizeError, sanitizeErrors, serializeError };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0
|
|
2
|
+
* react-router v8.0.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, stripBasename } from "../router/utils.js";
|
|
11
|
+
import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, removeTrailingSlash, stripBasename } from "../router/utils.js";
|
|
12
12
|
import { instrumentHandler } from "../router/instrumentation.js";
|
|
13
13
|
import { createStaticHandler, getStaticContextFromError, isMutationMethod, isRedirectResponse, isResponse } from "../router/router.js";
|
|
14
14
|
import { getManifestPath } from "../dom/ssr/fog-of-war.js";
|
|
15
15
|
import { createEntryRouteModules } from "./entry.js";
|
|
16
16
|
import { isServerMode } from "./mode.js";
|
|
17
|
-
import { sanitizeErrors, serializeError
|
|
17
|
+
import { sanitizeErrors, serializeError } from "./errors.js";
|
|
18
18
|
import { matchServerRoutes } from "./routeMatching.js";
|
|
19
19
|
import { getBuildTimeHeader, getDevServerHooks } from "./dev.js";
|
|
20
20
|
import { createStaticHandlerDataRoutes } from "./routes.js";
|
|
@@ -54,7 +54,7 @@ function derive(build, mode) {
|
|
|
54
54
|
}
|
|
55
55
|
loadContext = initialContext || new RouterContextProvider();
|
|
56
56
|
let requestUrl = new URL(request.url);
|
|
57
|
-
let normalizedPathname = getNormalizedPath(request
|
|
57
|
+
let normalizedPathname = getNormalizedPath(request).pathname;
|
|
58
58
|
let isSpaMode = getBuildTimeHeader(request, "X-React-Router-SPA-Mode") === "yes";
|
|
59
59
|
if (!build.ssr) {
|
|
60
60
|
let decodedPath = decodeURI(normalizedPathname);
|
|
@@ -74,7 +74,7 @@ function derive(build, mode) {
|
|
|
74
74
|
decodedPath = strippedPath;
|
|
75
75
|
}
|
|
76
76
|
if (build.prerender.length === 0) isSpaMode = true;
|
|
77
|
-
else if (!build.prerender.
|
|
77
|
+
else if (!build.prerender.some((p) => removeTrailingSlash(p) === removeTrailingSlash(decodedPath))) if (requestUrl.pathname.endsWith(".data")) {
|
|
78
78
|
errorHandler(new ErrorResponseImpl(404, "Not Found", `Refusing to SSR the path \`${decodedPath}\` because \`ssr:false\` is set and the path is not included in the \`prerender\` config, so in production the path will be a 404.`), {
|
|
79
79
|
context: loadContext,
|
|
80
80
|
params,
|
|
@@ -155,26 +155,20 @@ const createRequestHandler = (build, mode) => {
|
|
|
155
155
|
};
|
|
156
156
|
};
|
|
157
157
|
async function handleManifestRequest(build, dataRoutes, branches, url) {
|
|
158
|
-
if (build.assets.version !== url.searchParams.get("version")) return new Response(null, {
|
|
159
|
-
status: 204,
|
|
160
|
-
headers: { "X-Remix-Reload-Document": "true" }
|
|
161
|
-
});
|
|
162
158
|
if (url.toString().length > 7680) return new Response(null, {
|
|
163
159
|
statusText: "Bad Request",
|
|
164
160
|
status: 400
|
|
165
161
|
});
|
|
162
|
+
if (build.assets.version !== url.searchParams.get("version")) return new Response(null, {
|
|
163
|
+
status: 204,
|
|
164
|
+
headers: { "X-Remix-Reload-Document": "true" }
|
|
165
|
+
});
|
|
166
166
|
let patches = {};
|
|
167
167
|
if (url.searchParams.has("paths")) {
|
|
168
|
-
let
|
|
169
|
-
|
|
170
|
-
if (!path.startsWith("/")) path = `/${path}`;
|
|
171
|
-
let segments = path.split("/").slice(1);
|
|
172
|
-
segments.forEach((_, i) => {
|
|
173
|
-
let partialPath = segments.slice(0, i + 1).join("/");
|
|
174
|
-
paths.add(`/${partialPath}`);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
168
|
+
let pathParam = url.searchParams.get("paths") || "";
|
|
169
|
+
let paths = new Set(pathParam.split(",").filter(Boolean));
|
|
177
170
|
for (let path of paths) {
|
|
171
|
+
if (!path.startsWith("/")) path = `/${path}`;
|
|
178
172
|
let matches = matchServerRoutes(build.routes, dataRoutes, branches, path, build.basename);
|
|
179
173
|
if (matches) for (let match of matches) {
|
|
180
174
|
let routeId = match.route.id;
|
|
@@ -192,7 +186,7 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
|
|
|
192
186
|
async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, isSpaMode, criticalCss) {
|
|
193
187
|
try {
|
|
194
188
|
if (isMutationMethod(request.method)) try {
|
|
195
|
-
throwIfPotentialCSRFAttack(request
|
|
189
|
+
throwIfPotentialCSRFAttack(request, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
|
|
196
190
|
} catch (e) {
|
|
197
191
|
handleError(e);
|
|
198
192
|
return new Response("Bad Request", { status: 400 });
|
|
@@ -209,7 +203,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
|
|
|
209
203
|
return new Response(null, { status: 500 });
|
|
210
204
|
}
|
|
211
205
|
},
|
|
212
|
-
normalizePath: (r) => getNormalizedPath(r
|
|
206
|
+
normalizePath: (r) => getNormalizedPath(r)
|
|
213
207
|
});
|
|
214
208
|
if (!isResponse(result)) result = await renderHtml(result, isSpaMode);
|
|
215
209
|
return result;
|
|
@@ -232,7 +226,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
|
|
|
232
226
|
let state = {
|
|
233
227
|
loaderData: context.loaderData,
|
|
234
228
|
actionData: context.actionData,
|
|
235
|
-
errors:
|
|
229
|
+
errors: context.errors
|
|
236
230
|
};
|
|
237
231
|
let baseServerHandoff = {
|
|
238
232
|
basename: build.basename,
|
|
@@ -274,7 +268,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
|
|
|
274
268
|
let state = {
|
|
275
269
|
loaderData: context.loaderData,
|
|
276
270
|
actionData: context.actionData,
|
|
277
|
-
errors:
|
|
271
|
+
errors: context.errors
|
|
278
272
|
};
|
|
279
273
|
entryContext = {
|
|
280
274
|
...entryContext,
|
|
@@ -304,7 +298,7 @@ async function handleResourceRequest(serverMode, build, staticHandler, routeId,
|
|
|
304
298
|
return handleQueryRouteError(error);
|
|
305
299
|
}
|
|
306
300
|
},
|
|
307
|
-
normalizePath: (r) => getNormalizedPath(r
|
|
301
|
+
normalizePath: (r) => getNormalizedPath(r)
|
|
308
302
|
}));
|
|
309
303
|
} catch (error) {
|
|
310
304
|
return handleQueryRouteError(error);
|