react-router 7.15.1 → 8.0.0-pre.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 +18 -2
- package/dist/development/dom-export.d.ts +6 -172
- package/dist/development/dom-export.js +12 -1007
- package/dist/development/index-react-server-client.d.ts +7 -4
- package/dist/development/index-react-server-client.js +8 -52
- package/dist/development/index-react-server.d.ts +1645 -1635
- package/dist/development/index-react-server.js +2880 -3642
- package/dist/development/index.d.ts +43 -1469
- package/dist/development/index.js +37 -2621
- package/dist/development/lib/actions.js +62 -0
- package/dist/development/lib/components.d.ts +1022 -0
- package/dist/development/lib/components.js +835 -0
- package/dist/development/lib/context.d.ts +83 -0
- package/dist/development/lib/context.js +41 -0
- package/dist/development/lib/dom/dom.d.ts +119 -0
- package/dist/development/lib/dom/dom.js +143 -0
- package/dist/development/lib/dom/lib.d.ts +2042 -0
- package/dist/development/lib/dom/lib.js +1259 -0
- package/dist/development/lib/dom/server.d.ts +138 -0
- package/dist/development/lib/dom/server.js +301 -0
- package/dist/development/lib/dom/ssr/components.d.ts +196 -0
- package/dist/development/lib/dom/ssr/components.js +579 -0
- package/dist/development/lib/dom/ssr/data.js +29 -0
- package/dist/development/lib/dom/ssr/entry.d.ts +59 -0
- package/dist/development/lib/dom/ssr/errorBoundaries.d.ts +27 -0
- package/dist/development/lib/dom/ssr/errorBoundaries.js +83 -0
- package/dist/development/lib/dom/ssr/errors.d.ts +7 -0
- package/dist/development/lib/dom/ssr/errors.js +36 -0
- package/dist/development/lib/dom/ssr/fallback.js +28 -0
- package/dist/development/lib/dom/ssr/fog-of-war.d.ts +12 -0
- package/dist/development/lib/dom/ssr/fog-of-war.js +170 -0
- package/dist/development/lib/dom/ssr/hydration.d.ts +32 -0
- package/dist/development/lib/dom/ssr/hydration.js +29 -0
- package/dist/development/lib/dom/ssr/invariant.js +16 -0
- package/dist/development/lib/dom/ssr/links.js +170 -0
- package/dist/development/lib/dom/ssr/markup.js +24 -0
- package/dist/development/lib/dom/ssr/routeModules.d.ts +206 -0
- package/dist/development/lib/dom/ssr/routeModules.js +31 -0
- package/dist/development/lib/dom/ssr/routes-test-stub.d.ts +62 -0
- package/dist/development/lib/dom/ssr/routes-test-stub.js +108 -0
- package/dist/development/lib/dom/ssr/routes.d.ts +33 -0
- package/dist/development/lib/dom/ssr/routes.js +303 -0
- package/dist/development/lib/dom/ssr/server.d.ts +45 -0
- package/dist/development/lib/dom/ssr/server.js +68 -0
- package/dist/development/lib/dom/ssr/single-fetch.d.ts +14 -0
- package/dist/development/lib/dom/ssr/single-fetch.js +346 -0
- package/dist/development/lib/dom-export/dom-router-provider.d.ts +9 -0
- package/dist/development/lib/dom-export/dom-router-provider.js +22 -0
- package/dist/development/lib/dom-export/hydrated-router.d.ts +125 -0
- package/dist/development/lib/dom-export/hydrated-router.js +153 -0
- package/dist/development/lib/errors.js +29 -0
- package/dist/development/lib/hooks.d.ts +947 -0
- package/dist/development/lib/hooks.js +1386 -0
- package/dist/development/lib/href.d.ts +20 -0
- package/dist/development/lib/href.js +50 -0
- package/dist/development/lib/router/history.d.ts +258 -0
- package/dist/development/lib/router/history.js +371 -0
- package/dist/development/lib/router/instrumentation.d.ts +86 -0
- package/dist/development/lib/router/instrumentation.js +213 -0
- package/dist/development/lib/router/links.d.ts +113 -0
- package/dist/development/lib/router/router.d.ts +663 -0
- package/dist/development/lib/router/router.js +2981 -0
- package/dist/development/lib/router/utils.d.ts +942 -0
- package/dist/development/lib/router/utils.js +791 -0
- package/dist/development/lib/rsc/browser.d.ts +137 -0
- package/dist/development/lib/rsc/browser.js +599 -0
- package/dist/development/lib/rsc/errorBoundaries.d.ts +11 -0
- package/dist/development/lib/rsc/errorBoundaries.js +90 -0
- package/dist/development/lib/rsc/html-stream/browser.d.ts +48 -0
- package/dist/development/lib/rsc/html-stream/browser.js +74 -0
- package/dist/development/lib/rsc/html-stream/server.js +78 -0
- package/dist/development/lib/rsc/route-modules.js +27 -0
- package/dist/development/lib/rsc/server.rsc.d.ts +219 -0
- package/dist/development/lib/rsc/server.ssr.d.ts +129 -0
- package/dist/development/lib/rsc/server.ssr.js +388 -0
- package/dist/development/lib/server-runtime/build.d.ts +66 -0
- package/dist/development/lib/server-runtime/cookies.d.ts +66 -0
- package/dist/development/lib/server-runtime/cookies.js +139 -0
- package/dist/development/lib/server-runtime/crypto.js +43 -0
- package/dist/development/lib/server-runtime/data.d.ts +13 -0
- package/dist/development/lib/server-runtime/data.js +25 -0
- package/dist/development/lib/server-runtime/dev.d.ts +9 -0
- package/dist/development/lib/server-runtime/dev.js +26 -0
- package/dist/development/lib/server-runtime/entry.js +20 -0
- package/dist/development/lib/server-runtime/errors.js +95 -0
- package/dist/development/lib/server-runtime/headers.js +73 -0
- package/dist/development/lib/server-runtime/invariant.js +19 -0
- package/dist/development/lib/server-runtime/mode.d.ts +12 -0
- package/dist/development/lib/server-runtime/mode.js +25 -0
- package/dist/development/lib/server-runtime/routeMatching.js +28 -0
- package/dist/development/lib/server-runtime/routes.d.ts +13 -0
- package/dist/development/lib/server-runtime/routes.js +74 -0
- package/dist/development/lib/server-runtime/server.d.ts +10 -0
- package/dist/development/lib/server-runtime/server.js +351 -0
- package/dist/development/lib/server-runtime/serverHandoff.js +17 -0
- package/dist/development/lib/server-runtime/sessions/cookieStorage.d.ts +25 -0
- package/dist/development/lib/server-runtime/sessions/cookieStorage.js +45 -0
- package/dist/development/lib/server-runtime/sessions/memoryStorage.d.ts +23 -0
- package/dist/development/lib/server-runtime/sessions/memoryStorage.js +52 -0
- package/dist/development/lib/server-runtime/sessions.d.ts +145 -0
- package/dist/development/lib/server-runtime/sessions.js +98 -0
- package/dist/development/lib/server-runtime/single-fetch.d.ts +7 -0
- package/dist/development/lib/server-runtime/single-fetch.js +215 -0
- package/dist/development/lib/server-runtime/urls.js +31 -0
- package/dist/development/lib/server-runtime/warnings.js +20 -0
- package/dist/development/lib/types/future.d.ts +9 -0
- package/dist/development/lib/types/internal.d.ts +26 -177
- package/dist/development/lib/types/internal.js +3 -2
- package/dist/{production/register-Bsscfj79.d.ts → development/lib/types/register.d.ts} +9 -15
- package/dist/development/lib/types/route-data.d.ts +113 -0
- package/dist/development/lib/types/route-module-annotations.d.ts +149 -0
- package/dist/development/lib/types/route-module.d.ts +19 -0
- package/dist/development/lib/types/serializes-to.d.ts +13 -0
- package/dist/development/lib/types/utils.d.ts +11 -0
- package/dist/development/vendor/turbo-stream-v2/flatten.js +159 -0
- package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +178 -0
- package/dist/development/vendor/turbo-stream-v2/unflatten.js +198 -0
- package/dist/development/vendor/turbo-stream-v2/utils.js +47 -0
- package/dist/production/dom-export.d.ts +6 -172
- package/dist/production/dom-export.js +12 -1007
- package/dist/production/index-react-server-client.d.ts +7 -4
- package/dist/production/index-react-server-client.js +8 -52
- package/dist/production/index-react-server.d.ts +1645 -1635
- package/dist/production/index-react-server.js +2871 -3642
- package/dist/production/index.d.ts +43 -1469
- package/dist/production/index.js +37 -2621
- package/dist/production/lib/actions.js +62 -0
- package/dist/production/lib/components.d.ts +1022 -0
- package/dist/production/lib/components.js +835 -0
- package/dist/production/lib/context.d.ts +83 -0
- package/dist/production/lib/context.js +41 -0
- package/dist/production/lib/dom/dom.d.ts +119 -0
- package/dist/production/lib/dom/dom.js +143 -0
- package/dist/production/lib/dom/lib.d.ts +2042 -0
- package/dist/production/lib/dom/lib.js +1259 -0
- package/dist/production/lib/dom/server.d.ts +138 -0
- package/dist/production/lib/dom/server.js +301 -0
- package/dist/production/lib/dom/ssr/components.d.ts +196 -0
- package/dist/production/lib/dom/ssr/components.js +579 -0
- package/dist/production/lib/dom/ssr/data.js +29 -0
- package/dist/production/lib/dom/ssr/entry.d.ts +59 -0
- package/dist/production/lib/dom/ssr/errorBoundaries.d.ts +27 -0
- package/dist/production/lib/dom/ssr/errorBoundaries.js +83 -0
- package/dist/production/lib/dom/ssr/errors.d.ts +7 -0
- package/dist/production/lib/dom/ssr/errors.js +36 -0
- package/dist/production/lib/dom/ssr/fallback.js +21 -0
- package/dist/production/lib/dom/ssr/fog-of-war.d.ts +12 -0
- package/dist/production/lib/dom/ssr/fog-of-war.js +170 -0
- package/dist/production/lib/dom/ssr/hydration.d.ts +32 -0
- package/dist/production/lib/dom/ssr/hydration.js +29 -0
- package/dist/production/lib/dom/ssr/invariant.js +16 -0
- package/dist/production/lib/dom/ssr/links.js +170 -0
- package/dist/production/lib/dom/ssr/markup.js +24 -0
- package/dist/production/lib/dom/ssr/routeModules.d.ts +206 -0
- package/dist/production/lib/dom/ssr/routeModules.js +31 -0
- package/dist/production/lib/dom/ssr/routes-test-stub.d.ts +62 -0
- package/dist/production/lib/dom/ssr/routes-test-stub.js +108 -0
- package/dist/production/lib/dom/ssr/routes.d.ts +33 -0
- package/dist/production/lib/dom/ssr/routes.js +303 -0
- package/dist/production/lib/dom/ssr/server.d.ts +45 -0
- package/dist/production/lib/dom/ssr/server.js +68 -0
- package/dist/production/lib/dom/ssr/single-fetch.d.ts +14 -0
- package/dist/production/lib/dom/ssr/single-fetch.js +346 -0
- package/dist/production/lib/dom-export/dom-router-provider.d.ts +9 -0
- package/dist/production/lib/dom-export/dom-router-provider.js +22 -0
- package/dist/production/lib/dom-export/hydrated-router.d.ts +125 -0
- package/dist/production/lib/dom-export/hydrated-router.js +153 -0
- package/dist/production/lib/errors.js +29 -0
- package/dist/production/lib/hooks.d.ts +947 -0
- package/dist/production/lib/hooks.js +1371 -0
- package/dist/production/lib/href.d.ts +20 -0
- package/dist/production/lib/href.js +50 -0
- package/dist/production/lib/router/history.d.ts +258 -0
- package/dist/production/lib/router/history.js +371 -0
- package/dist/production/lib/router/instrumentation.d.ts +86 -0
- package/dist/production/lib/router/instrumentation.js +213 -0
- package/dist/production/lib/router/links.d.ts +113 -0
- package/dist/production/lib/router/router.d.ts +663 -0
- package/dist/production/lib/router/router.js +2981 -0
- package/dist/production/lib/router/utils.d.ts +942 -0
- package/dist/production/lib/router/utils.js +782 -0
- package/dist/production/lib/rsc/browser.d.ts +137 -0
- package/dist/production/lib/rsc/browser.js +599 -0
- package/dist/production/lib/rsc/errorBoundaries.d.ts +11 -0
- package/dist/production/lib/rsc/errorBoundaries.js +90 -0
- package/dist/production/lib/rsc/html-stream/browser.d.ts +48 -0
- package/dist/production/lib/rsc/html-stream/browser.js +74 -0
- package/dist/production/lib/rsc/html-stream/server.js +78 -0
- package/dist/production/lib/rsc/route-modules.js +27 -0
- package/dist/production/lib/rsc/server.rsc.d.ts +219 -0
- package/dist/production/lib/rsc/server.ssr.d.ts +129 -0
- package/dist/production/lib/rsc/server.ssr.js +388 -0
- package/dist/production/lib/server-runtime/build.d.ts +66 -0
- package/dist/production/lib/server-runtime/cookies.d.ts +66 -0
- package/dist/production/lib/server-runtime/cookies.js +139 -0
- package/dist/production/lib/server-runtime/crypto.js +43 -0
- package/dist/production/lib/server-runtime/data.d.ts +13 -0
- package/dist/production/lib/server-runtime/data.js +25 -0
- package/dist/production/lib/server-runtime/dev.d.ts +9 -0
- package/dist/production/lib/server-runtime/dev.js +26 -0
- package/dist/production/lib/server-runtime/entry.js +20 -0
- package/dist/production/lib/server-runtime/errors.js +95 -0
- package/dist/production/lib/server-runtime/headers.js +73 -0
- package/dist/production/lib/server-runtime/invariant.js +19 -0
- package/dist/production/lib/server-runtime/mode.d.ts +12 -0
- package/dist/production/lib/server-runtime/mode.js +25 -0
- package/dist/production/lib/server-runtime/routeMatching.js +28 -0
- package/dist/production/lib/server-runtime/routes.d.ts +13 -0
- package/dist/production/lib/server-runtime/routes.js +74 -0
- package/dist/production/lib/server-runtime/server.d.ts +10 -0
- package/dist/production/lib/server-runtime/server.js +351 -0
- package/dist/production/lib/server-runtime/serverHandoff.js +17 -0
- package/dist/production/lib/server-runtime/sessions/cookieStorage.d.ts +25 -0
- package/dist/production/lib/server-runtime/sessions/cookieStorage.js +45 -0
- package/dist/production/lib/server-runtime/sessions/memoryStorage.d.ts +23 -0
- package/dist/production/lib/server-runtime/sessions/memoryStorage.js +52 -0
- package/dist/production/lib/server-runtime/sessions.d.ts +145 -0
- package/dist/production/lib/server-runtime/sessions.js +98 -0
- package/dist/production/lib/server-runtime/single-fetch.d.ts +7 -0
- package/dist/production/lib/server-runtime/single-fetch.js +215 -0
- package/dist/production/lib/server-runtime/urls.js +31 -0
- package/dist/production/lib/server-runtime/warnings.js +20 -0
- package/dist/production/lib/types/future.d.ts +9 -0
- package/dist/production/lib/types/internal.d.ts +26 -177
- package/dist/production/lib/types/internal.js +3 -2
- package/dist/{development/register-Bsscfj79.d.ts → production/lib/types/register.d.ts} +9 -15
- package/dist/production/lib/types/route-data.d.ts +113 -0
- package/dist/production/lib/types/route-module-annotations.d.ts +149 -0
- package/dist/production/lib/types/route-module.d.ts +19 -0
- package/dist/production/lib/types/serializes-to.d.ts +13 -0
- package/dist/production/lib/types/utils.d.ts +11 -0
- package/dist/production/vendor/turbo-stream-v2/flatten.js +159 -0
- package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +178 -0
- package/dist/production/vendor/turbo-stream-v2/unflatten.js +198 -0
- package/dist/production/vendor/turbo-stream-v2/utils.js +47 -0
- package/docs/explanation/backend-for-frontend.md +50 -0
- package/docs/explanation/code-splitting.md +77 -0
- package/docs/explanation/concurrency.md +135 -0
- package/docs/explanation/form-vs-fetcher.md +292 -0
- package/docs/explanation/hot-module-replacement.md +137 -0
- package/docs/explanation/hydration.md +14 -0
- package/docs/explanation/index-query-param.md +86 -0
- package/docs/explanation/index.md +4 -0
- package/docs/explanation/lazy-route-discovery.md +78 -0
- package/docs/explanation/location.md +6 -0
- package/docs/explanation/progressive-enhancement.md +150 -0
- package/docs/explanation/race-conditions.md +88 -0
- package/docs/explanation/react-transitions.md +160 -0
- package/docs/explanation/route-matching.md +7 -0
- package/docs/explanation/server-client-execution.md +4 -0
- package/docs/explanation/sessions-and-cookies.md +465 -0
- package/docs/explanation/special-files.md +16 -0
- package/docs/explanation/state-management.md +524 -0
- package/docs/explanation/styling.md +87 -0
- package/docs/explanation/type-safety.md +82 -0
- package/docs/how-to/accessibility.md +44 -0
- package/docs/how-to/client-data.md +199 -0
- package/docs/how-to/data-strategy.md +317 -0
- package/docs/how-to/error-boundary.md +231 -0
- package/docs/how-to/error-reporting.md +134 -0
- package/docs/how-to/fetchers.md +307 -0
- package/docs/how-to/file-route-conventions.md +410 -0
- package/docs/how-to/file-uploads.md +217 -0
- package/docs/how-to/form-validation.md +120 -0
- package/docs/how-to/headers.md +164 -0
- package/docs/how-to/index.md +4 -0
- package/docs/how-to/instrumentation.md +556 -0
- package/docs/how-to/meta.md +40 -0
- package/docs/how-to/middleware.md +728 -0
- package/docs/how-to/navigation-blocking.md +233 -0
- package/docs/how-to/optimize-revalidation.md +12 -0
- package/docs/how-to/pre-rendering.md +225 -0
- package/docs/how-to/presets.md +103 -0
- package/docs/how-to/react-server-components.md +899 -0
- package/docs/how-to/resource-routes.md +126 -0
- package/docs/how-to/route-module-type-safety.md +100 -0
- package/docs/how-to/search-params.md +4 -0
- package/docs/how-to/security.md +30 -0
- package/docs/how-to/server-bundles.md +66 -0
- package/docs/how-to/spa.md +120 -0
- package/docs/how-to/status.md +63 -0
- package/docs/how-to/suspense.md +132 -0
- package/docs/how-to/using-handle.md +117 -0
- package/docs/how-to/view-transitions.md +237 -0
- package/docs/how-to/webhook.md +50 -0
- package/docs/index.md +39 -0
- package/docs/start/data/actions.md +138 -0
- package/docs/start/data/custom.md +198 -0
- package/docs/start/data/data-loading.md +44 -0
- package/docs/start/data/index.md +4 -0
- package/docs/start/data/installation.md +52 -0
- package/docs/start/data/navigating.md +12 -0
- package/docs/start/data/pending-ui.md +12 -0
- package/docs/start/data/route-object.md +248 -0
- package/docs/start/data/routing.md +281 -0
- package/docs/start/data/testing.md +8 -0
- package/docs/start/declarative/index.md +4 -0
- package/docs/start/declarative/installation.md +43 -0
- package/docs/start/declarative/navigating.md +133 -0
- package/docs/start/declarative/routing.md +237 -0
- package/docs/start/declarative/url-values.md +65 -0
- package/docs/start/framework/actions.md +175 -0
- package/docs/start/framework/data-loading.md +201 -0
- package/docs/start/framework/deploying.md +96 -0
- package/docs/start/framework/index.md +4 -0
- package/docs/start/framework/installation.md +42 -0
- package/docs/start/framework/navigating.md +182 -0
- package/docs/start/framework/pending-ui.md +142 -0
- package/docs/start/framework/rendering.md +59 -0
- package/docs/start/framework/route-module.md +527 -0
- package/docs/start/framework/routing.md +362 -0
- package/docs/start/framework/testing.md +133 -0
- package/docs/start/index.md +4 -0
- package/docs/start/modes.md +201 -0
- package/docs/upgrading/component-routes.md +363 -0
- package/docs/upgrading/future.md +31 -0
- package/docs/upgrading/index.md +4 -0
- package/docs/upgrading/remix.md +403 -0
- package/docs/upgrading/router-provider.md +442 -0
- package/docs/upgrading/v6.md +379 -0
- package/package.json +44 -87
- package/dist/development/browser-3AnU12UI.d.mts +0 -318
- package/dist/development/browser-BOdXz9dK.d.ts +0 -318
- package/dist/development/chunk-4N6VE7H7.mjs +0 -11528
- package/dist/development/chunk-4YRVXM2U.js +0 -188
- package/dist/development/chunk-66UKHEGQ.js +0 -1362
- package/dist/development/chunk-D6LUOGOQ.js +0 -10229
- package/dist/development/chunk-RJYABSBD.mjs +0 -2585
- package/dist/development/context-ByvtofY2.d.mts +0 -1771
- package/dist/development/data-BVUf681J.d.mts +0 -1732
- package/dist/development/data-BqZ2x964.d.ts +0 -1732
- package/dist/development/dom-export.d.mts +0 -172
- package/dist/development/dom-export.mjs +0 -1008
- package/dist/development/index-react-server-client-BS5F89FR.d.ts +0 -3655
- package/dist/development/index-react-server-client-DY04-103.d.mts +0 -2600
- package/dist/development/index-react-server-client.d.mts +0 -4
- package/dist/development/index-react-server-client.mjs +0 -59
- package/dist/development/index-react-server.d.mts +0 -2703
- package/dist/development/index-react-server.mjs +0 -3780
- package/dist/development/index.d.mts +0 -1472
- package/dist/development/index.mjs +0 -277
- package/dist/development/instrumentation-cRWWLfsU.d.ts +0 -715
- package/dist/development/lib/types/internal.d.mts +0 -184
- package/dist/development/lib/types/internal.mjs +0 -10
- package/dist/development/register-Df8okEea.d.mts +0 -30
- package/dist/production/browser-3AnU12UI.d.mts +0 -318
- package/dist/production/browser-BOdXz9dK.d.ts +0 -318
- package/dist/production/chunk-6S4627ZB.mjs +0 -2585
- package/dist/production/chunk-HUBUW7R3.js +0 -10229
- package/dist/production/chunk-JAKZPQZC.mjs +0 -11528
- package/dist/production/chunk-PNZCCTKT.js +0 -1362
- package/dist/production/chunk-Y6IFXO7V.js +0 -188
- package/dist/production/context-ByvtofY2.d.mts +0 -1771
- package/dist/production/data-BVUf681J.d.mts +0 -1732
- package/dist/production/data-BqZ2x964.d.ts +0 -1732
- package/dist/production/dom-export.d.mts +0 -172
- package/dist/production/dom-export.mjs +0 -1008
- package/dist/production/index-react-server-client-BS5F89FR.d.ts +0 -3655
- package/dist/production/index-react-server-client-DY04-103.d.mts +0 -2600
- package/dist/production/index-react-server-client.d.mts +0 -4
- package/dist/production/index-react-server-client.mjs +0 -59
- package/dist/production/index-react-server.d.mts +0 -2703
- package/dist/production/index-react-server.mjs +0 -3780
- package/dist/production/index.d.mts +0 -1472
- package/dist/production/index.mjs +0 -277
- package/dist/production/instrumentation-cRWWLfsU.d.ts +0 -715
- package/dist/production/lib/types/internal.d.mts +0 -184
- package/dist/production/lib/types/internal.mjs +0 -10
- package/dist/production/register-Df8okEea.d.mts +0 -30
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router v8.0.0-pre.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
|
+
import { invariant, parsePath, warning } from "./history.js";
|
|
12
|
+
import * as React$1 from "react";
|
|
13
|
+
//#region lib/router/utils.ts
|
|
14
|
+
/**
|
|
15
|
+
* Creates a type-safe {@link RouterContext} object that can be used to
|
|
16
|
+
* store and retrieve arbitrary values in [`action`](../../start/framework/route-module#action)s,
|
|
17
|
+
* [`loader`](../../start/framework/route-module#loader)s, and [middleware](../../how-to/middleware).
|
|
18
|
+
* Similar to React's [`createContext`](https://react.dev/reference/react/createContext),
|
|
19
|
+
* but specifically designed for React Router's request/response lifecycle.
|
|
20
|
+
*
|
|
21
|
+
* If a `defaultValue` is provided, it will be returned from `context.get()`
|
|
22
|
+
* when no value has been set for the context. Otherwise, reading this context
|
|
23
|
+
* when no value has been set will throw an error.
|
|
24
|
+
*
|
|
25
|
+
* ```tsx filename=app/context.ts
|
|
26
|
+
* import { createContext } from "react-router";
|
|
27
|
+
*
|
|
28
|
+
* // Create a context for user data
|
|
29
|
+
* export const userContext =
|
|
30
|
+
* createContext<User | null>(null);
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* ```tsx filename=app/middleware/auth.ts
|
|
34
|
+
* import { getUserFromSession } from "~/auth.server";
|
|
35
|
+
* import { userContext } from "~/context";
|
|
36
|
+
*
|
|
37
|
+
* export const authMiddleware = async ({
|
|
38
|
+
* context,
|
|
39
|
+
* request,
|
|
40
|
+
* }) => {
|
|
41
|
+
* const user = await getUserFromSession(request);
|
|
42
|
+
* context.set(userContext, user);
|
|
43
|
+
* };
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* ```tsx filename=app/routes/profile.tsx
|
|
47
|
+
* import { userContext } from "~/context";
|
|
48
|
+
*
|
|
49
|
+
* export async function loader({
|
|
50
|
+
* context,
|
|
51
|
+
* }: Route.LoaderArgs) {
|
|
52
|
+
* const user = context.get(userContext);
|
|
53
|
+
*
|
|
54
|
+
* if (!user) {
|
|
55
|
+
* throw new Response("Unauthorized", { status: 401 });
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* return { user };
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
* @category Utils
|
|
64
|
+
* @mode framework
|
|
65
|
+
* @mode data
|
|
66
|
+
* @param defaultValue An optional default value for the context. This value
|
|
67
|
+
* will be returned if no value has been set for this context.
|
|
68
|
+
* @returns A {@link RouterContext} object that can be used with
|
|
69
|
+
* `context.get()` and `context.set()` in [`action`](../../start/framework/route-module#action)s,
|
|
70
|
+
* [`loader`](../../start/framework/route-module#loader)s, and [middleware](../../how-to/middleware).
|
|
71
|
+
*/
|
|
72
|
+
function createContext(defaultValue) {
|
|
73
|
+
return { defaultValue };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Provides methods for writing/reading values in application context in a
|
|
77
|
+
* type-safe way. Primarily for usage with [middleware](../../how-to/middleware).
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* import {
|
|
81
|
+
* createContext,
|
|
82
|
+
* RouterContextProvider
|
|
83
|
+
* } from "react-router";
|
|
84
|
+
*
|
|
85
|
+
* const userContext = createContext<User | null>(null);
|
|
86
|
+
* const contextProvider = new RouterContextProvider();
|
|
87
|
+
* contextProvider.set(userContext, getUser());
|
|
88
|
+
* // ^ Type-safe
|
|
89
|
+
* const user = contextProvider.get(userContext);
|
|
90
|
+
* // ^ User
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
* @category Utils
|
|
94
|
+
* @mode framework
|
|
95
|
+
* @mode data
|
|
96
|
+
*/
|
|
97
|
+
var RouterContextProvider = class {
|
|
98
|
+
#map = /* @__PURE__ */ new Map();
|
|
99
|
+
/**
|
|
100
|
+
* Create a new `RouterContextProvider` instance
|
|
101
|
+
* @param init An optional initial context map to populate the provider with
|
|
102
|
+
*/
|
|
103
|
+
constructor(init) {
|
|
104
|
+
if (init) for (let [context, value] of init) this.set(context, value);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Access a value from the context. If no value has been set for the context,
|
|
108
|
+
* it will return the context's `defaultValue` if provided, or throw an error
|
|
109
|
+
* if no `defaultValue` was set.
|
|
110
|
+
* @param context The context to get the value for
|
|
111
|
+
* @returns The value for the context, or the context's `defaultValue` if no
|
|
112
|
+
* value was set
|
|
113
|
+
*/
|
|
114
|
+
get(context) {
|
|
115
|
+
if (this.#map.has(context)) return this.#map.get(context);
|
|
116
|
+
if (context.defaultValue !== void 0) return context.defaultValue;
|
|
117
|
+
throw new Error("No value found for context");
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Set a value for the context. If the context already has a value set, this
|
|
121
|
+
* will overwrite it.
|
|
122
|
+
*
|
|
123
|
+
* @param context The context to set the value for
|
|
124
|
+
* @param value The value to set for the context
|
|
125
|
+
* @returns {void}
|
|
126
|
+
*/
|
|
127
|
+
set(context, value) {
|
|
128
|
+
this.#map.set(context, value);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const unsupportedLazyRouteObjectKeys = new Set([
|
|
132
|
+
"lazy",
|
|
133
|
+
"caseSensitive",
|
|
134
|
+
"path",
|
|
135
|
+
"id",
|
|
136
|
+
"index",
|
|
137
|
+
"children"
|
|
138
|
+
]);
|
|
139
|
+
function isUnsupportedLazyRouteObjectKey(key) {
|
|
140
|
+
return unsupportedLazyRouteObjectKeys.has(key);
|
|
141
|
+
}
|
|
142
|
+
const unsupportedLazyRouteFunctionKeys = new Set([
|
|
143
|
+
"lazy",
|
|
144
|
+
"caseSensitive",
|
|
145
|
+
"path",
|
|
146
|
+
"id",
|
|
147
|
+
"index",
|
|
148
|
+
"middleware",
|
|
149
|
+
"children"
|
|
150
|
+
]);
|
|
151
|
+
function isUnsupportedLazyRouteFunctionKey(key) {
|
|
152
|
+
return unsupportedLazyRouteFunctionKeys.has(key);
|
|
153
|
+
}
|
|
154
|
+
function isIndexRoute(route) {
|
|
155
|
+
return route.index === true;
|
|
156
|
+
}
|
|
157
|
+
function defaultMapRouteProperties(route) {
|
|
158
|
+
let updates = {};
|
|
159
|
+
if (route.Component) Object.assign(updates, {
|
|
160
|
+
element: React$1.createElement(route.Component),
|
|
161
|
+
Component: void 0
|
|
162
|
+
});
|
|
163
|
+
if (route.HydrateFallback) Object.assign(updates, {
|
|
164
|
+
hydrateFallbackElement: React$1.createElement(route.HydrateFallback),
|
|
165
|
+
HydrateFallback: void 0
|
|
166
|
+
});
|
|
167
|
+
if (route.ErrorBoundary) Object.assign(updates, {
|
|
168
|
+
errorElement: React$1.createElement(route.ErrorBoundary),
|
|
169
|
+
ErrorBoundary: void 0
|
|
170
|
+
});
|
|
171
|
+
return updates;
|
|
172
|
+
}
|
|
173
|
+
function convertRoutesToDataRoutes(routes, mapRouteProperties = defaultMapRouteProperties, parentPath = [], manifest = {}, allowInPlaceMutations = false) {
|
|
174
|
+
return routes.map((route, index) => {
|
|
175
|
+
let treePath = [...parentPath, String(index)];
|
|
176
|
+
let id = typeof route.id === "string" ? route.id : treePath.join("-");
|
|
177
|
+
invariant(route.index !== true || !route.children, `Cannot specify children on an index route`);
|
|
178
|
+
invariant(allowInPlaceMutations || !manifest[id], `Found a route id collision on id "${id}". Route id's must be globally unique within Data Router usages`);
|
|
179
|
+
if (isIndexRoute(route)) {
|
|
180
|
+
let indexRoute = {
|
|
181
|
+
...route,
|
|
182
|
+
id
|
|
183
|
+
};
|
|
184
|
+
manifest[id] = mergeRouteUpdates(indexRoute, mapRouteProperties(indexRoute));
|
|
185
|
+
return indexRoute;
|
|
186
|
+
} else {
|
|
187
|
+
let pathOrLayoutRoute = {
|
|
188
|
+
...route,
|
|
189
|
+
id,
|
|
190
|
+
children: void 0
|
|
191
|
+
};
|
|
192
|
+
manifest[id] = mergeRouteUpdates(pathOrLayoutRoute, mapRouteProperties(pathOrLayoutRoute));
|
|
193
|
+
if (route.children) pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, mapRouteProperties, treePath, manifest, allowInPlaceMutations);
|
|
194
|
+
return pathOrLayoutRoute;
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function mergeRouteUpdates(route, updates) {
|
|
199
|
+
return Object.assign(route, {
|
|
200
|
+
...updates,
|
|
201
|
+
...typeof updates.lazy === "object" && updates.lazy != null ? { lazy: {
|
|
202
|
+
...route.lazy,
|
|
203
|
+
...updates.lazy
|
|
204
|
+
} } : {}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Matches the given routes to a location and returns the match data.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* import { matchRoutes } from "react-router";
|
|
212
|
+
*
|
|
213
|
+
* let routes = [{
|
|
214
|
+
* path: "/",
|
|
215
|
+
* Component: Root,
|
|
216
|
+
* children: [{
|
|
217
|
+
* path: "dashboard",
|
|
218
|
+
* Component: Dashboard,
|
|
219
|
+
* }]
|
|
220
|
+
* }];
|
|
221
|
+
*
|
|
222
|
+
* matchRoutes(routes, "/dashboard"); // [rootMatch, dashboardMatch]
|
|
223
|
+
*
|
|
224
|
+
* @public
|
|
225
|
+
* @category Utils
|
|
226
|
+
* @param routes The array of route objects to match against.
|
|
227
|
+
* @param locationArg The location to match against, either a string path or a
|
|
228
|
+
* partial {@link Location} object
|
|
229
|
+
* @param basename Optional base path to strip from the location before matching.
|
|
230
|
+
* Defaults to `/`.
|
|
231
|
+
* @returns An array of matched routes, or `null` if no matches were found.
|
|
232
|
+
*/
|
|
233
|
+
function matchRoutes(routes, locationArg, basename = "/") {
|
|
234
|
+
return matchRoutesImpl(routes, locationArg, basename, false);
|
|
235
|
+
}
|
|
236
|
+
function matchRoutesImpl(routes, locationArg, basename, allowPartial, precomputedBranches) {
|
|
237
|
+
let pathname = stripBasename((typeof locationArg === "string" ? parsePath(locationArg) : locationArg).pathname || "/", basename);
|
|
238
|
+
if (pathname == null) return null;
|
|
239
|
+
let branches = precomputedBranches ?? flattenAndRankRoutes(routes);
|
|
240
|
+
let matches = null;
|
|
241
|
+
let decoded = decodePath(pathname);
|
|
242
|
+
for (let i = 0; matches == null && i < branches.length; ++i) matches = matchRouteBranch(branches[i], decoded, allowPartial);
|
|
243
|
+
return matches;
|
|
244
|
+
}
|
|
245
|
+
function convertRouteMatchToUiMatch(match, loaderData) {
|
|
246
|
+
let { route, pathname, params } = match;
|
|
247
|
+
return {
|
|
248
|
+
id: route.id,
|
|
249
|
+
pathname,
|
|
250
|
+
params,
|
|
251
|
+
loaderData: loaderData[route.id],
|
|
252
|
+
handle: route.handle
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function flattenAndRankRoutes(routes) {
|
|
256
|
+
let branches = flattenRoutes(routes);
|
|
257
|
+
rankRouteBranches(branches);
|
|
258
|
+
return branches;
|
|
259
|
+
}
|
|
260
|
+
function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) {
|
|
261
|
+
let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath) => {
|
|
262
|
+
let meta = {
|
|
263
|
+
relativePath: relativePath === void 0 ? route.path || "" : relativePath,
|
|
264
|
+
caseSensitive: route.caseSensitive === true,
|
|
265
|
+
childrenIndex: index,
|
|
266
|
+
route
|
|
267
|
+
};
|
|
268
|
+
if (meta.relativePath.startsWith("/")) {
|
|
269
|
+
if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) return;
|
|
270
|
+
invariant(meta.relativePath.startsWith(parentPath), `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`);
|
|
271
|
+
meta.relativePath = meta.relativePath.slice(parentPath.length);
|
|
272
|
+
}
|
|
273
|
+
let path = joinPaths([parentPath, meta.relativePath]);
|
|
274
|
+
let routesMeta = parentsMeta.concat(meta);
|
|
275
|
+
if (route.children && route.children.length > 0) {
|
|
276
|
+
invariant(route.index !== true, `Index routes must not have child routes. Please remove all child routes from route path "${path}".`);
|
|
277
|
+
flattenRoutes(route.children, branches, routesMeta, path, hasParentOptionalSegments);
|
|
278
|
+
}
|
|
279
|
+
if (route.path == null && !route.index) return;
|
|
280
|
+
branches.push({
|
|
281
|
+
path,
|
|
282
|
+
score: computeScore(path, route.index),
|
|
283
|
+
routesMeta
|
|
284
|
+
});
|
|
285
|
+
};
|
|
286
|
+
routes.forEach((route, index) => {
|
|
287
|
+
if (route.path === "" || !route.path?.includes("?")) flattenRoute(route, index);
|
|
288
|
+
else for (let exploded of explodeOptionalSegments(route.path)) flattenRoute(route, index, true, exploded);
|
|
289
|
+
});
|
|
290
|
+
return branches;
|
|
291
|
+
}
|
|
292
|
+
function explodeOptionalSegments(path) {
|
|
293
|
+
let segments = path.split("/");
|
|
294
|
+
if (segments.length === 0) return [];
|
|
295
|
+
let [first, ...rest] = segments;
|
|
296
|
+
let isOptional = first.endsWith("?");
|
|
297
|
+
let required = first.replace(/\?$/, "");
|
|
298
|
+
if (rest.length === 0) return isOptional ? [required, ""] : [required];
|
|
299
|
+
let restExploded = explodeOptionalSegments(rest.join("/"));
|
|
300
|
+
let result = [];
|
|
301
|
+
result.push(...restExploded.map((subpath) => subpath === "" ? required : [required, subpath].join("/")));
|
|
302
|
+
if (isOptional) result.push(...restExploded);
|
|
303
|
+
return result.map((exploded) => path.startsWith("/") && exploded === "" ? "/" : exploded);
|
|
304
|
+
}
|
|
305
|
+
function rankRouteBranches(branches) {
|
|
306
|
+
branches.sort((a, b) => a.score !== b.score ? b.score - a.score : compareIndexes(a.routesMeta.map((meta) => meta.childrenIndex), b.routesMeta.map((meta) => meta.childrenIndex)));
|
|
307
|
+
}
|
|
308
|
+
const paramRe = /^:[\w-]+$/;
|
|
309
|
+
const dynamicSegmentValue = 3;
|
|
310
|
+
const indexRouteValue = 2;
|
|
311
|
+
const emptySegmentValue = 1;
|
|
312
|
+
const staticSegmentValue = 10;
|
|
313
|
+
const splatPenalty = -2;
|
|
314
|
+
const isSplat = (s) => s === "*";
|
|
315
|
+
function computeScore(path, index) {
|
|
316
|
+
let segments = path.split("/");
|
|
317
|
+
let initialScore = segments.length;
|
|
318
|
+
if (segments.some(isSplat)) initialScore += splatPenalty;
|
|
319
|
+
if (index) initialScore += indexRouteValue;
|
|
320
|
+
return segments.filter((s) => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
|
|
321
|
+
}
|
|
322
|
+
function compareIndexes(a, b) {
|
|
323
|
+
return a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]) ? a[a.length - 1] - b[b.length - 1] : 0;
|
|
324
|
+
}
|
|
325
|
+
function matchRouteBranch(branch, pathname, allowPartial = false) {
|
|
326
|
+
let { routesMeta } = branch;
|
|
327
|
+
let matchedParams = {};
|
|
328
|
+
let matchedPathname = "/";
|
|
329
|
+
let matches = [];
|
|
330
|
+
for (let i = 0; i < routesMeta.length; ++i) {
|
|
331
|
+
let meta = routesMeta[i];
|
|
332
|
+
let end = i === routesMeta.length - 1;
|
|
333
|
+
let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
|
|
334
|
+
let match = matchPath({
|
|
335
|
+
path: meta.relativePath,
|
|
336
|
+
caseSensitive: meta.caseSensitive,
|
|
337
|
+
end
|
|
338
|
+
}, remainingPathname);
|
|
339
|
+
let route = meta.route;
|
|
340
|
+
if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) match = matchPath({
|
|
341
|
+
path: meta.relativePath,
|
|
342
|
+
caseSensitive: meta.caseSensitive,
|
|
343
|
+
end: false
|
|
344
|
+
}, remainingPathname);
|
|
345
|
+
if (!match) return null;
|
|
346
|
+
Object.assign(matchedParams, match.params);
|
|
347
|
+
matches.push({
|
|
348
|
+
params: matchedParams,
|
|
349
|
+
pathname: joinPaths([matchedPathname, match.pathname]),
|
|
350
|
+
pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
|
|
351
|
+
route
|
|
352
|
+
});
|
|
353
|
+
if (match.pathnameBase !== "/") matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
|
|
354
|
+
}
|
|
355
|
+
return matches;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Returns a path with params interpolated.
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* import { generatePath } from "react-router";
|
|
362
|
+
*
|
|
363
|
+
* generatePath("/users/:id", { id: "123" }); // "/users/123"
|
|
364
|
+
*
|
|
365
|
+
* @public
|
|
366
|
+
* @category Utils
|
|
367
|
+
* @param originalPath The original path to generate.
|
|
368
|
+
* @param params The parameters to interpolate into the path.
|
|
369
|
+
* @returns The generated path with parameters interpolated.
|
|
370
|
+
*/
|
|
371
|
+
function generatePath(originalPath, params = {}) {
|
|
372
|
+
let path = originalPath;
|
|
373
|
+
if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {
|
|
374
|
+
warning(false, `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".`);
|
|
375
|
+
path = path.replace(/\*$/, "/*");
|
|
376
|
+
}
|
|
377
|
+
const prefix = path.startsWith("/") ? "/" : "";
|
|
378
|
+
const stringify = (p) => p == null ? "" : typeof p === "string" ? p : String(p);
|
|
379
|
+
return prefix + path.split(/\/+/).map((segment, index, array) => {
|
|
380
|
+
if (index === array.length - 1 && segment === "*") return stringify(params["*"]);
|
|
381
|
+
const keyMatch = segment.match(/^:([\w-]+)(\??)(.*)/);
|
|
382
|
+
if (keyMatch) {
|
|
383
|
+
const [, key, optional, suffix] = keyMatch;
|
|
384
|
+
let param = params[key];
|
|
385
|
+
invariant(optional === "?" || param != null, `Missing ":${key}" param`);
|
|
386
|
+
return encodeURIComponent(stringify(param)) + suffix;
|
|
387
|
+
}
|
|
388
|
+
return segment.replace(/\?$/g, "");
|
|
389
|
+
}).filter((segment) => !!segment).join("/");
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Performs pattern matching on a URL pathname and returns information about
|
|
393
|
+
* the match.
|
|
394
|
+
*
|
|
395
|
+
* @public
|
|
396
|
+
* @category Utils
|
|
397
|
+
* @param pattern The pattern to match against the URL pathname. This can be a
|
|
398
|
+
* string or a {@link PathPattern} object. If a string is provided, it will be
|
|
399
|
+
* treated as a pattern with `caseSensitive` set to `false` and `end` set to
|
|
400
|
+
* `true`.
|
|
401
|
+
* @param pathname The URL pathname to match against the pattern.
|
|
402
|
+
* @returns A path match object if the pattern matches the pathname,
|
|
403
|
+
* or `null` if it does not match.
|
|
404
|
+
*/
|
|
405
|
+
function matchPath(pattern, pathname) {
|
|
406
|
+
if (typeof pattern === "string") pattern = {
|
|
407
|
+
path: pattern,
|
|
408
|
+
caseSensitive: false,
|
|
409
|
+
end: true
|
|
410
|
+
};
|
|
411
|
+
let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
|
412
|
+
let match = pathname.match(matcher);
|
|
413
|
+
if (!match) return null;
|
|
414
|
+
let matchedPathname = match[0];
|
|
415
|
+
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
|
416
|
+
let captureGroups = match.slice(1);
|
|
417
|
+
return {
|
|
418
|
+
params: compiledParams.reduce((memo, { paramName, isOptional }, index) => {
|
|
419
|
+
if (paramName === "*") {
|
|
420
|
+
let splatValue = captureGroups[index] || "";
|
|
421
|
+
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
|
422
|
+
}
|
|
423
|
+
const value = captureGroups[index];
|
|
424
|
+
if (isOptional && !value) memo[paramName] = void 0;
|
|
425
|
+
else memo[paramName] = (value || "").replace(/%2F/g, "/");
|
|
426
|
+
return memo;
|
|
427
|
+
}, {}),
|
|
428
|
+
pathname: matchedPathname,
|
|
429
|
+
pathnameBase,
|
|
430
|
+
pattern
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function compilePath(path, caseSensitive = false, end = true) {
|
|
434
|
+
warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".`);
|
|
435
|
+
let params = [];
|
|
436
|
+
let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(/\/:([\w-]+)(\?)?/g, (match, paramName, isOptional, index, str) => {
|
|
437
|
+
params.push({
|
|
438
|
+
paramName,
|
|
439
|
+
isOptional: isOptional != null
|
|
440
|
+
});
|
|
441
|
+
if (isOptional) {
|
|
442
|
+
let nextChar = str.charAt(index + match.length);
|
|
443
|
+
if (nextChar && nextChar !== "/") return "/([^\\/]*)";
|
|
444
|
+
return "(?:/([^\\/]*))?";
|
|
445
|
+
}
|
|
446
|
+
return "/([^\\/]+)";
|
|
447
|
+
}).replace(/\/([\w-]+)\?(\/|$)/g, "(/$1)?$2");
|
|
448
|
+
if (path.endsWith("*")) {
|
|
449
|
+
params.push({ paramName: "*" });
|
|
450
|
+
regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
|
|
451
|
+
} else if (end) regexpSource += "\\/*$";
|
|
452
|
+
else if (path !== "" && path !== "/") regexpSource += "(?:(?=\\/|$))";
|
|
453
|
+
return [new RegExp(regexpSource, caseSensitive ? void 0 : "i"), params];
|
|
454
|
+
}
|
|
455
|
+
function decodePath(value) {
|
|
456
|
+
try {
|
|
457
|
+
return value.split("/").map((v) => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
|
|
458
|
+
} catch (error) {
|
|
459
|
+
warning(false, `The URL path "${value}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${error}).`);
|
|
460
|
+
return value;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function stripBasename(pathname, basename) {
|
|
464
|
+
if (basename === "/") return pathname;
|
|
465
|
+
if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) return null;
|
|
466
|
+
let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
|
|
467
|
+
let nextChar = pathname.charAt(startIndex);
|
|
468
|
+
if (nextChar && nextChar !== "/") return null;
|
|
469
|
+
return pathname.slice(startIndex) || "/";
|
|
470
|
+
}
|
|
471
|
+
function prependBasename({ basename, pathname }) {
|
|
472
|
+
return pathname === "/" ? basename : joinPaths([basename, pathname]);
|
|
473
|
+
}
|
|
474
|
+
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
475
|
+
const isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url);
|
|
476
|
+
/**
|
|
477
|
+
* Returns a resolved {@link Path} object relative to the given pathname.
|
|
478
|
+
*
|
|
479
|
+
* @public
|
|
480
|
+
* @category Utils
|
|
481
|
+
* @param to The path to resolve, either a string or a partial {@link Path}
|
|
482
|
+
* object.
|
|
483
|
+
* @param fromPathname The pathname to resolve the path from. Defaults to `/`.
|
|
484
|
+
* @returns A {@link Path} object with the resolved pathname, search, and hash.
|
|
485
|
+
*/
|
|
486
|
+
function resolvePath(to, fromPathname = "/") {
|
|
487
|
+
let { pathname: toPathname, search = "", hash = "" } = typeof to === "string" ? parsePath(to) : to;
|
|
488
|
+
let pathname;
|
|
489
|
+
if (toPathname) {
|
|
490
|
+
toPathname = removeDoubleSlashes(toPathname);
|
|
491
|
+
if (toPathname.startsWith("/")) pathname = resolvePathname(toPathname.substring(1), "/");
|
|
492
|
+
else pathname = resolvePathname(toPathname, fromPathname);
|
|
493
|
+
} else pathname = fromPathname;
|
|
494
|
+
return {
|
|
495
|
+
pathname,
|
|
496
|
+
search: normalizeSearch(search),
|
|
497
|
+
hash: normalizeHash(hash)
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function resolvePathname(relativePath, fromPathname) {
|
|
501
|
+
let segments = removeTrailingSlash(fromPathname).split("/");
|
|
502
|
+
relativePath.split("/").forEach((segment) => {
|
|
503
|
+
if (segment === "..") {
|
|
504
|
+
if (segments.length > 1) segments.pop();
|
|
505
|
+
} else if (segment !== ".") segments.push(segment);
|
|
506
|
+
});
|
|
507
|
+
return segments.length > 1 ? segments.join("/") : "/";
|
|
508
|
+
}
|
|
509
|
+
function getInvalidPathError(char, field, dest, path) {
|
|
510
|
+
return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify(path)}]. Please separate it out to the \`to.${dest}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`;
|
|
511
|
+
}
|
|
512
|
+
function getPathContributingMatches(matches) {
|
|
513
|
+
return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
|
|
514
|
+
}
|
|
515
|
+
function getResolveToMatches(matches) {
|
|
516
|
+
let pathMatches = getPathContributingMatches(matches);
|
|
517
|
+
return pathMatches.map((match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase);
|
|
518
|
+
}
|
|
519
|
+
function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) {
|
|
520
|
+
let to;
|
|
521
|
+
if (typeof toArg === "string") to = parsePath(toArg);
|
|
522
|
+
else {
|
|
523
|
+
to = { ...toArg };
|
|
524
|
+
invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
|
|
525
|
+
invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
|
|
526
|
+
invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
|
|
527
|
+
}
|
|
528
|
+
let isEmptyPath = toArg === "" || to.pathname === "";
|
|
529
|
+
let toPathname = isEmptyPath ? "/" : to.pathname;
|
|
530
|
+
let from;
|
|
531
|
+
if (toPathname == null) from = locationPathname;
|
|
532
|
+
else {
|
|
533
|
+
let routePathnameIndex = routePathnames.length - 1;
|
|
534
|
+
if (!isPathRelative && toPathname.startsWith("..")) {
|
|
535
|
+
let toSegments = toPathname.split("/");
|
|
536
|
+
while (toSegments[0] === "..") {
|
|
537
|
+
toSegments.shift();
|
|
538
|
+
routePathnameIndex -= 1;
|
|
539
|
+
}
|
|
540
|
+
to.pathname = toSegments.join("/");
|
|
541
|
+
}
|
|
542
|
+
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
|
|
543
|
+
}
|
|
544
|
+
let path = resolvePath(to, from);
|
|
545
|
+
let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
|
|
546
|
+
let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
|
|
547
|
+
if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) path.pathname += "/";
|
|
548
|
+
return path;
|
|
549
|
+
}
|
|
550
|
+
const removeDoubleSlashes = (path) => path.replace(/\/\/+/g, "/");
|
|
551
|
+
const joinPaths = (paths) => removeDoubleSlashes(paths.join("/"));
|
|
552
|
+
const removeTrailingSlash = (path) => path.replace(/\/+$/, "");
|
|
553
|
+
const normalizePathname = (pathname) => removeTrailingSlash(pathname).replace(/^\/*/, "/");
|
|
554
|
+
const normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
|
|
555
|
+
const normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
|
|
556
|
+
var DataWithResponseInit = class {
|
|
557
|
+
type = "DataWithResponseInit";
|
|
558
|
+
data;
|
|
559
|
+
init;
|
|
560
|
+
constructor(data, init) {
|
|
561
|
+
this.data = data;
|
|
562
|
+
this.init = init || null;
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* Create "responses" that contain `headers`/`status` without forcing
|
|
567
|
+
* serialization into an actual [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* import { data } from "react-router";
|
|
571
|
+
*
|
|
572
|
+
* export async function action({ request }: Route.ActionArgs) {
|
|
573
|
+
* let formData = await request.formData();
|
|
574
|
+
* let item = await createItem(formData);
|
|
575
|
+
* return data(item, {
|
|
576
|
+
* headers: { "X-Custom-Header": "value" }
|
|
577
|
+
* status: 201,
|
|
578
|
+
* });
|
|
579
|
+
* }
|
|
580
|
+
*
|
|
581
|
+
* @public
|
|
582
|
+
* @category Utils
|
|
583
|
+
* @mode framework
|
|
584
|
+
* @mode data
|
|
585
|
+
* @param data The data to be included in the response.
|
|
586
|
+
* @param init The status code or a `ResponseInit` object to be included in the
|
|
587
|
+
* response.
|
|
588
|
+
* @returns A {@link DataWithResponseInit} instance containing the data and
|
|
589
|
+
* response init.
|
|
590
|
+
*/
|
|
591
|
+
function data(data, init) {
|
|
592
|
+
return new DataWithResponseInit(data, typeof init === "number" ? { status: init } : init);
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* A redirect [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
|
|
596
|
+
* Sets the status code and the [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
|
|
597
|
+
* header. Defaults to [`302 Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302).
|
|
598
|
+
*
|
|
599
|
+
* This utility accepts absolute URLs and can navigate to external domains, so
|
|
600
|
+
* the application should validate any user-supplied inputs to redirects.
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* import { redirect } from "react-router";
|
|
604
|
+
*
|
|
605
|
+
* export async function loader({ request }: Route.LoaderArgs) {
|
|
606
|
+
* if (!isLoggedIn(request))
|
|
607
|
+
* throw redirect("/login");
|
|
608
|
+
* }
|
|
609
|
+
*
|
|
610
|
+
* // ...
|
|
611
|
+
* }
|
|
612
|
+
*
|
|
613
|
+
* @public
|
|
614
|
+
* @category Utils
|
|
615
|
+
* @mode framework
|
|
616
|
+
* @mode data
|
|
617
|
+
* @param url The URL to redirect to.
|
|
618
|
+
* @param init The status code or a `ResponseInit` object to be included in the
|
|
619
|
+
* response.
|
|
620
|
+
* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
621
|
+
* object with the redirect status and [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
|
|
622
|
+
* header.
|
|
623
|
+
*/
|
|
624
|
+
const redirect = (url, init = 302) => {
|
|
625
|
+
let responseInit = init;
|
|
626
|
+
if (typeof responseInit === "number") responseInit = { status: responseInit };
|
|
627
|
+
else if (typeof responseInit.status === "undefined") responseInit.status = 302;
|
|
628
|
+
let headers = new Headers(responseInit.headers);
|
|
629
|
+
headers.set("Location", url);
|
|
630
|
+
return new Response(null, {
|
|
631
|
+
...responseInit,
|
|
632
|
+
headers
|
|
633
|
+
});
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* A redirect [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
637
|
+
* that will force a document reload to the new location. Sets the status code
|
|
638
|
+
* and the [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
|
|
639
|
+
* header. Defaults to [`302 Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302).
|
|
640
|
+
*
|
|
641
|
+
* This utility accepts absolute URLs and can navigate to external domains, so
|
|
642
|
+
* the application should validate any user-supplied inputs to redirects.
|
|
643
|
+
*
|
|
644
|
+
* ```tsx filename=routes/logout.tsx
|
|
645
|
+
* import { redirectDocument } from "react-router";
|
|
646
|
+
*
|
|
647
|
+
* import { destroySession } from "../sessions.server";
|
|
648
|
+
*
|
|
649
|
+
* export async function action({ request }: Route.ActionArgs) {
|
|
650
|
+
* let session = await getSession(request.headers.get("Cookie"));
|
|
651
|
+
* return redirectDocument("/", {
|
|
652
|
+
* headers: { "Set-Cookie": await destroySession(session) }
|
|
653
|
+
* });
|
|
654
|
+
* }
|
|
655
|
+
* ```
|
|
656
|
+
*
|
|
657
|
+
* @public
|
|
658
|
+
* @category Utils
|
|
659
|
+
* @mode framework
|
|
660
|
+
* @mode data
|
|
661
|
+
* @param url The URL to redirect to.
|
|
662
|
+
* @param init The status code or a `ResponseInit` object to be included in the
|
|
663
|
+
* response.
|
|
664
|
+
* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
665
|
+
* object with the redirect status and [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
|
|
666
|
+
* header.
|
|
667
|
+
*/
|
|
668
|
+
const redirectDocument = (url, init) => {
|
|
669
|
+
let response = redirect(url, init);
|
|
670
|
+
response.headers.set("X-Remix-Reload-Document", "true");
|
|
671
|
+
return response;
|
|
672
|
+
};
|
|
673
|
+
/**
|
|
674
|
+
* A redirect [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
675
|
+
* that will perform a [`history.replaceState`](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState)
|
|
676
|
+
* instead of a [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)
|
|
677
|
+
* for client-side navigation redirects. Sets the status code and the [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
|
|
678
|
+
* header. Defaults to [`302 Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302).
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* import { replace } from "react-router";
|
|
682
|
+
*
|
|
683
|
+
* export async function loader() {
|
|
684
|
+
* return replace("/new-location");
|
|
685
|
+
* }
|
|
686
|
+
*
|
|
687
|
+
* @public
|
|
688
|
+
* @category Utils
|
|
689
|
+
* @mode framework
|
|
690
|
+
* @mode data
|
|
691
|
+
* @param url The URL to redirect to.
|
|
692
|
+
* @param init The status code or a `ResponseInit` object to be included in the
|
|
693
|
+
* response.
|
|
694
|
+
* @returns A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
695
|
+
* object with the redirect status and [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
|
|
696
|
+
* header.
|
|
697
|
+
*/
|
|
698
|
+
const replace = (url, init) => {
|
|
699
|
+
let response = redirect(url, init);
|
|
700
|
+
response.headers.set("X-Remix-Replace", "true");
|
|
701
|
+
return response;
|
|
702
|
+
};
|
|
703
|
+
var ErrorResponseImpl = class {
|
|
704
|
+
status;
|
|
705
|
+
statusText;
|
|
706
|
+
data;
|
|
707
|
+
error;
|
|
708
|
+
internal;
|
|
709
|
+
constructor(status, statusText, data, internal = false) {
|
|
710
|
+
this.status = status;
|
|
711
|
+
this.statusText = statusText || "";
|
|
712
|
+
this.internal = internal;
|
|
713
|
+
if (data instanceof Error) {
|
|
714
|
+
this.data = data.toString();
|
|
715
|
+
this.error = data;
|
|
716
|
+
} else this.data = data;
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
/**
|
|
720
|
+
* Check if the given error is an {@link ErrorResponse} generated from a 4xx/5xx
|
|
721
|
+
* [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
722
|
+
* thrown from an [`action`](../../start/framework/route-module#action) or
|
|
723
|
+
* [`loader`](../../start/framework/route-module#loader) function.
|
|
724
|
+
*
|
|
725
|
+
* @example
|
|
726
|
+
* import { isRouteErrorResponse } from "react-router";
|
|
727
|
+
*
|
|
728
|
+
* export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
|
729
|
+
* if (isRouteErrorResponse(error)) {
|
|
730
|
+
* return (
|
|
731
|
+
* <>
|
|
732
|
+
* <p>Error: `${error.status}: ${error.statusText}`</p>
|
|
733
|
+
* <p>{error.data}</p>
|
|
734
|
+
* </>
|
|
735
|
+
* );
|
|
736
|
+
* }
|
|
737
|
+
*
|
|
738
|
+
* return (
|
|
739
|
+
* <p>Error: {error instanceof Error ? error.message : "Unknown Error"}</p>
|
|
740
|
+
* );
|
|
741
|
+
* }
|
|
742
|
+
*
|
|
743
|
+
* @public
|
|
744
|
+
* @category Utils
|
|
745
|
+
* @mode framework
|
|
746
|
+
* @mode data
|
|
747
|
+
* @param error The error to check.
|
|
748
|
+
* @returns `true` if the error is an {@link ErrorResponse}, `false` otherwise.
|
|
749
|
+
*/
|
|
750
|
+
function isRouteErrorResponse(error) {
|
|
751
|
+
return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
|
|
752
|
+
}
|
|
753
|
+
function getRoutePattern(matches) {
|
|
754
|
+
return joinPaths(matches.map((m) => m.route.path).filter(Boolean)) || "/";
|
|
755
|
+
}
|
|
756
|
+
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
757
|
+
function parseToInfo(_to, basename) {
|
|
758
|
+
let to = _to;
|
|
759
|
+
if (typeof to !== "string" || !ABSOLUTE_URL_REGEX.test(to)) return {
|
|
760
|
+
absoluteURL: void 0,
|
|
761
|
+
isExternal: false,
|
|
762
|
+
to
|
|
763
|
+
};
|
|
764
|
+
let absoluteURL = to;
|
|
765
|
+
let isExternal = false;
|
|
766
|
+
if (isBrowser) try {
|
|
767
|
+
let currentUrl = new URL(window.location.href);
|
|
768
|
+
let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
|
|
769
|
+
let path = stripBasename(targetUrl.pathname, basename);
|
|
770
|
+
if (targetUrl.origin === currentUrl.origin && path != null) to = path + targetUrl.search + targetUrl.hash;
|
|
771
|
+
else isExternal = true;
|
|
772
|
+
} catch (e) {
|
|
773
|
+
warning(false, `<Link to="${to}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`);
|
|
774
|
+
}
|
|
775
|
+
return {
|
|
776
|
+
absoluteURL,
|
|
777
|
+
isExternal,
|
|
778
|
+
to
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
//#endregion
|
|
782
|
+
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 };
|