@benjavicente/router-core 1.168.9
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/LICENSE +21 -0
- package/README.md +5 -0
- package/bin/intent.js +25 -0
- package/dist/cjs/Matches.cjs +17 -0
- package/dist/cjs/Matches.cjs.map +1 -0
- package/dist/cjs/Matches.d.cts +139 -0
- package/dist/cjs/RouterProvider.d.cts +27 -0
- package/dist/cjs/config.cjs +11 -0
- package/dist/cjs/config.cjs.map +1 -0
- package/dist/cjs/config.d.cts +17 -0
- package/dist/cjs/defer.cjs +41 -0
- package/dist/cjs/defer.cjs.map +1 -0
- package/dist/cjs/defer.d.cts +37 -0
- package/dist/cjs/fileRoute.d.cts +24 -0
- package/dist/cjs/global.d.cts +7 -0
- package/dist/cjs/hash-scroll.cjs +20 -0
- package/dist/cjs/hash-scroll.cjs.map +1 -0
- package/dist/cjs/hash-scroll.d.cts +7 -0
- package/dist/cjs/history.d.cts +8 -0
- package/dist/cjs/index.cjs +96 -0
- package/dist/cjs/index.d.cts +53 -0
- package/dist/cjs/invariant.cjs +8 -0
- package/dist/cjs/invariant.cjs.map +1 -0
- package/dist/cjs/invariant.d.cts +1 -0
- package/dist/cjs/isServer/client.cjs +7 -0
- package/dist/cjs/isServer/client.cjs.map +1 -0
- package/dist/cjs/isServer/client.d.cts +1 -0
- package/dist/cjs/isServer/development.cjs +7 -0
- package/dist/cjs/isServer/development.cjs.map +1 -0
- package/dist/cjs/isServer/development.d.cts +1 -0
- package/dist/cjs/isServer/server.cjs +7 -0
- package/dist/cjs/isServer/server.cjs.map +1 -0
- package/dist/cjs/isServer/server.d.cts +1 -0
- package/dist/cjs/link.cjs +6 -0
- package/dist/cjs/link.cjs.map +1 -0
- package/dist/cjs/link.d.cts +221 -0
- package/dist/cjs/load-matches.cjs +659 -0
- package/dist/cjs/load-matches.cjs.map +1 -0
- package/dist/cjs/load-matches.d.cts +18 -0
- package/dist/cjs/location.d.cts +50 -0
- package/dist/cjs/lru-cache.cjs +70 -0
- package/dist/cjs/lru-cache.cjs.map +1 -0
- package/dist/cjs/lru-cache.d.cts +6 -0
- package/dist/cjs/manifest.cjs +18 -0
- package/dist/cjs/manifest.cjs.map +1 -0
- package/dist/cjs/manifest.d.cts +35 -0
- package/dist/cjs/new-process-route-tree.cjs +754 -0
- package/dist/cjs/new-process-route-tree.cjs.map +1 -0
- package/dist/cjs/new-process-route-tree.d.cts +236 -0
- package/dist/cjs/not-found.cjs +26 -0
- package/dist/cjs/not-found.cjs.map +1 -0
- package/dist/cjs/not-found.d.cts +32 -0
- package/dist/cjs/path.cjs +252 -0
- package/dist/cjs/path.cjs.map +1 -0
- package/dist/cjs/path.d.cts +56 -0
- package/dist/cjs/qss.cjs +70 -0
- package/dist/cjs/qss.cjs.map +1 -0
- package/dist/cjs/qss.d.cts +33 -0
- package/dist/cjs/redirect.cjs +56 -0
- package/dist/cjs/redirect.cjs.map +1 -0
- package/dist/cjs/redirect.d.cts +77 -0
- package/dist/cjs/rewrite.cjs +68 -0
- package/dist/cjs/rewrite.cjs.map +1 -0
- package/dist/cjs/rewrite.d.cts +30 -0
- package/dist/cjs/root.cjs +7 -0
- package/dist/cjs/root.cjs.map +1 -0
- package/dist/cjs/root.d.cts +3 -0
- package/dist/cjs/route.cjs +100 -0
- package/dist/cjs/route.cjs.map +1 -0
- package/dist/cjs/route.d.cts +552 -0
- package/dist/cjs/routeInfo.d.cts +54 -0
- package/dist/cjs/router.cjs +1173 -0
- package/dist/cjs/router.cjs.map +1 -0
- package/dist/cjs/router.d.cts +734 -0
- package/dist/cjs/scroll-restoration-inline.cjs +6 -0
- package/dist/cjs/scroll-restoration-inline.cjs.map +1 -0
- package/dist/cjs/scroll-restoration-inline.d.cts +6 -0
- package/dist/cjs/scroll-restoration-script/client.cjs +9 -0
- package/dist/cjs/scroll-restoration-script/client.cjs.map +1 -0
- package/dist/cjs/scroll-restoration-script/client.d.cts +2 -0
- package/dist/cjs/scroll-restoration-script/server.cjs +30 -0
- package/dist/cjs/scroll-restoration-script/server.cjs.map +1 -0
- package/dist/cjs/scroll-restoration-script/server.d.cts +2 -0
- package/dist/cjs/scroll-restoration.cjs +191 -0
- package/dist/cjs/scroll-restoration.cjs.map +1 -0
- package/dist/cjs/scroll-restoration.d.cts +38 -0
- package/dist/cjs/searchMiddleware.cjs +55 -0
- package/dist/cjs/searchMiddleware.cjs.map +1 -0
- package/dist/cjs/searchMiddleware.d.cts +25 -0
- package/dist/cjs/searchParams.cjs +65 -0
- package/dist/cjs/searchParams.cjs.map +1 -0
- package/dist/cjs/searchParams.d.cts +31 -0
- package/dist/cjs/ssr/client.cjs +7 -0
- package/dist/cjs/ssr/client.d.cts +6 -0
- package/dist/cjs/ssr/constants.cjs +8 -0
- package/dist/cjs/ssr/constants.cjs.map +1 -0
- package/dist/cjs/ssr/constants.d.cts +3 -0
- package/dist/cjs/ssr/createRequestHandler.cjs +44 -0
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -0
- package/dist/cjs/ssr/createRequestHandler.d.cts +9 -0
- package/dist/cjs/ssr/handlerCallback.cjs +8 -0
- package/dist/cjs/ssr/handlerCallback.cjs.map +1 -0
- package/dist/cjs/ssr/handlerCallback.d.cts +9 -0
- package/dist/cjs/ssr/headers.cjs +21 -0
- package/dist/cjs/ssr/headers.cjs.map +1 -0
- package/dist/cjs/ssr/headers.d.cts +3 -0
- package/dist/cjs/ssr/json.cjs +11 -0
- package/dist/cjs/ssr/json.cjs.map +1 -0
- package/dist/cjs/ssr/json.d.cts +10 -0
- package/dist/cjs/ssr/serializer/RawStream.cjs +287 -0
- package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -0
- package/dist/cjs/ssr/serializer/RawStream.d.cts +64 -0
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs +32 -0
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -0
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.d.cts +9 -0
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs +13 -0
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -0
- package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -0
- package/dist/cjs/ssr/serializer/transformer.cjs +53 -0
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -0
- package/dist/cjs/ssr/serializer/transformer.d.cts +91 -0
- package/dist/cjs/ssr/server.cjs +13 -0
- package/dist/cjs/ssr/server.d.cts +6 -0
- package/dist/cjs/ssr/ssr-client.cjs +183 -0
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -0
- package/dist/cjs/ssr/ssr-client.d.cts +10 -0
- package/dist/cjs/ssr/ssr-match-id.cjs +12 -0
- package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -0
- package/dist/cjs/ssr/ssr-match-id.d.cts +2 -0
- package/dist/cjs/ssr/ssr-server.cjs +279 -0
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -0
- package/dist/cjs/ssr/ssr-server.d.cts +42 -0
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +327 -0
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -0
- package/dist/cjs/ssr/transformStreamWithRouter.d.cts +11 -0
- package/dist/cjs/ssr/tsrScript.cjs +6 -0
- package/dist/cjs/ssr/tsrScript.cjs.map +1 -0
- package/dist/cjs/ssr/tsrScript.d.cts +1 -0
- package/dist/cjs/ssr/types.d.cts +30 -0
- package/dist/cjs/stores.cjs +148 -0
- package/dist/cjs/stores.cjs.map +1 -0
- package/dist/cjs/stores.d.cts +70 -0
- package/dist/cjs/structuralSharing.d.cts +4 -0
- package/dist/cjs/typePrimitives.d.cts +65 -0
- package/dist/cjs/useLoaderData.d.cts +5 -0
- package/dist/cjs/useLoaderDeps.d.cts +5 -0
- package/dist/cjs/useNavigate.d.cts +3 -0
- package/dist/cjs/useParams.d.cts +5 -0
- package/dist/cjs/useRouteContext.d.cts +9 -0
- package/dist/cjs/useSearch.d.cts +5 -0
- package/dist/cjs/utils.cjs +339 -0
- package/dist/cjs/utils.cjs.map +1 -0
- package/dist/cjs/utils.d.cts +178 -0
- package/dist/cjs/validators.d.cts +51 -0
- package/dist/esm/Matches.d.ts +139 -0
- package/dist/esm/Matches.js +17 -0
- package/dist/esm/Matches.js.map +1 -0
- package/dist/esm/RouterProvider.d.ts +27 -0
- package/dist/esm/config.d.ts +17 -0
- package/dist/esm/config.js +11 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/defer.d.ts +37 -0
- package/dist/esm/defer.js +40 -0
- package/dist/esm/defer.js.map +1 -0
- package/dist/esm/fileRoute.d.ts +24 -0
- package/dist/esm/global.d.ts +7 -0
- package/dist/esm/hash-scroll.d.ts +7 -0
- package/dist/esm/hash-scroll.js +20 -0
- package/dist/esm/hash-scroll.js.map +1 -0
- package/dist/esm/history.d.ts +8 -0
- package/dist/esm/index.d.ts +53 -0
- package/dist/esm/index.js +24 -0
- package/dist/esm/invariant.d.ts +1 -0
- package/dist/esm/invariant.js +8 -0
- package/dist/esm/invariant.js.map +1 -0
- package/dist/esm/isServer/client.d.ts +1 -0
- package/dist/esm/isServer/client.js +6 -0
- package/dist/esm/isServer/client.js.map +1 -0
- package/dist/esm/isServer/development.d.ts +1 -0
- package/dist/esm/isServer/development.js +6 -0
- package/dist/esm/isServer/development.js.map +1 -0
- package/dist/esm/isServer/server.d.ts +1 -0
- package/dist/esm/isServer/server.js +6 -0
- package/dist/esm/isServer/server.js.map +1 -0
- package/dist/esm/link.d.ts +221 -0
- package/dist/esm/link.js +6 -0
- package/dist/esm/link.js.map +1 -0
- package/dist/esm/load-matches.d.ts +18 -0
- package/dist/esm/load-matches.js +657 -0
- package/dist/esm/load-matches.js.map +1 -0
- package/dist/esm/location.d.ts +50 -0
- package/dist/esm/lru-cache.d.ts +6 -0
- package/dist/esm/lru-cache.js +70 -0
- package/dist/esm/lru-cache.js.map +1 -0
- package/dist/esm/manifest.d.ts +35 -0
- package/dist/esm/manifest.js +17 -0
- package/dist/esm/manifest.js.map +1 -0
- package/dist/esm/new-process-route-tree.d.ts +236 -0
- package/dist/esm/new-process-route-tree.js +749 -0
- package/dist/esm/new-process-route-tree.js.map +1 -0
- package/dist/esm/not-found.d.ts +32 -0
- package/dist/esm/not-found.js +25 -0
- package/dist/esm/not-found.js.map +1 -0
- package/dist/esm/path.d.ts +56 -0
- package/dist/esm/path.js +243 -0
- package/dist/esm/path.js.map +1 -0
- package/dist/esm/qss.d.ts +33 -0
- package/dist/esm/qss.js +69 -0
- package/dist/esm/qss.js.map +1 -0
- package/dist/esm/redirect.d.ts +77 -0
- package/dist/esm/redirect.js +53 -0
- package/dist/esm/redirect.js.map +1 -0
- package/dist/esm/rewrite.d.ts +30 -0
- package/dist/esm/rewrite.js +65 -0
- package/dist/esm/rewrite.js.map +1 -0
- package/dist/esm/root.d.ts +3 -0
- package/dist/esm/root.js +7 -0
- package/dist/esm/root.js.map +1 -0
- package/dist/esm/route.d.ts +552 -0
- package/dist/esm/route.js +98 -0
- package/dist/esm/route.js.map +1 -0
- package/dist/esm/routeInfo.d.ts +54 -0
- package/dist/esm/router.d.ts +734 -0
- package/dist/esm/router.js +1165 -0
- package/dist/esm/router.js.map +1 -0
- package/dist/esm/scroll-restoration-inline.d.ts +6 -0
- package/dist/esm/scroll-restoration-inline.js +6 -0
- package/dist/esm/scroll-restoration-inline.js.map +1 -0
- package/dist/esm/scroll-restoration-script/client.d.ts +2 -0
- package/dist/esm/scroll-restoration-script/client.js +8 -0
- package/dist/esm/scroll-restoration-script/client.js.map +1 -0
- package/dist/esm/scroll-restoration-script/server.d.ts +2 -0
- package/dist/esm/scroll-restoration-script/server.js +29 -0
- package/dist/esm/scroll-restoration-script/server.js.map +1 -0
- package/dist/esm/scroll-restoration.d.ts +38 -0
- package/dist/esm/scroll-restoration.js +187 -0
- package/dist/esm/scroll-restoration.js.map +1 -0
- package/dist/esm/searchMiddleware.d.ts +25 -0
- package/dist/esm/searchMiddleware.js +54 -0
- package/dist/esm/searchMiddleware.js.map +1 -0
- package/dist/esm/searchParams.d.ts +31 -0
- package/dist/esm/searchParams.js +62 -0
- package/dist/esm/searchParams.js.map +1 -0
- package/dist/esm/ssr/client.d.ts +6 -0
- package/dist/esm/ssr/client.js +4 -0
- package/dist/esm/ssr/constants.d.ts +3 -0
- package/dist/esm/ssr/constants.js +7 -0
- package/dist/esm/ssr/constants.js.map +1 -0
- package/dist/esm/ssr/createRequestHandler.d.ts +9 -0
- package/dist/esm/ssr/createRequestHandler.js +44 -0
- package/dist/esm/ssr/createRequestHandler.js.map +1 -0
- package/dist/esm/ssr/handlerCallback.d.ts +9 -0
- package/dist/esm/ssr/handlerCallback.js +8 -0
- package/dist/esm/ssr/handlerCallback.js.map +1 -0
- package/dist/esm/ssr/headers.d.ts +3 -0
- package/dist/esm/ssr/headers.js +21 -0
- package/dist/esm/ssr/headers.js.map +1 -0
- package/dist/esm/ssr/json.d.ts +10 -0
- package/dist/esm/ssr/json.js +11 -0
- package/dist/esm/ssr/json.js.map +1 -0
- package/dist/esm/ssr/serializer/RawStream.d.ts +64 -0
- package/dist/esm/ssr/serializer/RawStream.js +282 -0
- package/dist/esm/ssr/serializer/RawStream.js.map +1 -0
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.d.ts +9 -0
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js +33 -0
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -0
- package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -0
- package/dist/esm/ssr/serializer/seroval-plugins.js +13 -0
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -0
- package/dist/esm/ssr/serializer/transformer.d.ts +91 -0
- package/dist/esm/ssr/serializer/transformer.js +51 -0
- package/dist/esm/ssr/serializer/transformer.js.map +1 -0
- package/dist/esm/ssr/server.d.ts +6 -0
- package/dist/esm/ssr/server.js +5 -0
- package/dist/esm/ssr/ssr-client.d.ts +10 -0
- package/dist/esm/ssr/ssr-client.js +183 -0
- package/dist/esm/ssr/ssr-client.js.map +1 -0
- package/dist/esm/ssr/ssr-match-id.d.ts +2 -0
- package/dist/esm/ssr/ssr-match-id.js +11 -0
- package/dist/esm/ssr/ssr-match-id.js.map +1 -0
- package/dist/esm/ssr/ssr-server.d.ts +42 -0
- package/dist/esm/ssr/ssr-server.js +277 -0
- package/dist/esm/ssr/ssr-server.js.map +1 -0
- package/dist/esm/ssr/transformStreamWithRouter.d.ts +11 -0
- package/dist/esm/ssr/transformStreamWithRouter.js +325 -0
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -0
- package/dist/esm/ssr/tsrScript.d.ts +0 -0
- package/dist/esm/ssr/tsrScript.js +6 -0
- package/dist/esm/ssr/tsrScript.js.map +1 -0
- package/dist/esm/ssr/types.d.ts +30 -0
- package/dist/esm/stores.d.ts +70 -0
- package/dist/esm/stores.js +146 -0
- package/dist/esm/stores.js.map +1 -0
- package/dist/esm/structuralSharing.d.ts +4 -0
- package/dist/esm/typePrimitives.d.ts +65 -0
- package/dist/esm/useLoaderData.d.ts +5 -0
- package/dist/esm/useLoaderDeps.d.ts +5 -0
- package/dist/esm/useNavigate.d.ts +3 -0
- package/dist/esm/useParams.d.ts +5 -0
- package/dist/esm/useRouteContext.d.ts +9 -0
- package/dist/esm/useSearch.d.ts +5 -0
- package/dist/esm/utils.d.ts +178 -0
- package/dist/esm/utils.js +322 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/validators.d.ts +51 -0
- package/package.json +200 -0
- package/skills/router-core/SKILL.md +139 -0
- package/skills/router-core/auth-and-guards/SKILL.md +458 -0
- package/skills/router-core/code-splitting/SKILL.md +322 -0
- package/skills/router-core/data-loading/SKILL.md +485 -0
- package/skills/router-core/navigation/SKILL.md +448 -0
- package/skills/router-core/not-found-and-errors/SKILL.md +435 -0
- package/skills/router-core/path-params/SKILL.md +382 -0
- package/skills/router-core/search-params/SKILL.md +349 -0
- package/skills/router-core/search-params/references/validation-patterns.md +379 -0
- package/skills/router-core/ssr/SKILL.md +437 -0
- package/skills/router-core/type-safety/SKILL.md +497 -0
- package/src/Matches.ts +291 -0
- package/src/RouterProvider.ts +47 -0
- package/src/config.ts +42 -0
- package/src/defer.ts +69 -0
- package/src/fileRoute.ts +164 -0
- package/src/global.ts +9 -0
- package/src/hash-scroll.ts +21 -0
- package/src/history.ts +9 -0
- package/src/index.ts +471 -0
- package/src/invariant.ts +3 -0
- package/src/isServer/client.ts +1 -0
- package/src/isServer/development.ts +2 -0
- package/src/isServer/server.ts +1 -0
- package/src/link.ts +704 -0
- package/src/load-matches.ts +1281 -0
- package/src/location.ts +51 -0
- package/src/lru-cache.ts +74 -0
- package/src/manifest.ts +68 -0
- package/src/new-process-route-tree.ts +1387 -0
- package/src/not-found.ts +41 -0
- package/src/path.ts +436 -0
- package/src/qss.ts +81 -0
- package/src/redirect.ts +179 -0
- package/src/rewrite.ts +93 -0
- package/src/root.ts +3 -0
- package/src/route.ts +2235 -0
- package/src/routeInfo.ts +235 -0
- package/src/router.ts +3207 -0
- package/src/scroll-restoration-inline.ts +81 -0
- package/src/scroll-restoration-script/client.ts +5 -0
- package/src/scroll-restoration-script/server.ts +64 -0
- package/src/scroll-restoration.ts +357 -0
- package/src/searchMiddleware.ts +76 -0
- package/src/searchParams.ts +90 -0
- package/src/ssr/client.ts +6 -0
- package/src/ssr/constants.ts +3 -0
- package/src/ssr/createRequestHandler.ts +98 -0
- package/src/ssr/handlerCallback.ts +15 -0
- package/src/ssr/headers.ts +40 -0
- package/src/ssr/json.ts +16 -0
- package/src/ssr/serializer/RawStream.ts +464 -0
- package/src/ssr/serializer/ShallowErrorPlugin.ts +43 -0
- package/src/ssr/serializer/seroval-plugins.ts +12 -0
- package/src/ssr/serializer/transformer.ts +312 -0
- package/src/ssr/server.ts +14 -0
- package/src/ssr/ssr-client.ts +313 -0
- package/src/ssr/ssr-match-id.ts +7 -0
- package/src/ssr/ssr-server.ts +425 -0
- package/src/ssr/transformStreamWithRouter.ts +493 -0
- package/src/ssr/tsrScript.ts +20 -0
- package/src/ssr/types.ts +41 -0
- package/src/stores.ts +342 -0
- package/src/structuralSharing.ts +7 -0
- package/src/typePrimitives.ts +181 -0
- package/src/useLoaderData.ts +20 -0
- package/src/useLoaderDeps.ts +13 -0
- package/src/useNavigate.ts +13 -0
- package/src/useParams.ts +20 -0
- package/src/useRouteContext.ts +39 -0
- package/src/useSearch.ts +20 -0
- package/src/utils.ts +708 -0
- package/src/validators.ts +121 -0
- package/src/vite-env.d.ts +4 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
const require_utils = require("./utils.cjs");
|
|
2
|
+
const require_new_process_route_tree = require("./new-process-route-tree.cjs");
|
|
3
|
+
let _benjavicente_router_core_isServer = require("@benjavicente/router-core/isServer");
|
|
4
|
+
//#region src/path.ts
|
|
5
|
+
/** Join path segments, cleaning duplicate slashes between parts. */
|
|
6
|
+
function joinPaths(paths) {
|
|
7
|
+
return cleanPath(paths.filter((val) => {
|
|
8
|
+
return val !== void 0;
|
|
9
|
+
}).join("/"));
|
|
10
|
+
}
|
|
11
|
+
/** Remove repeated slashes from a path string. */
|
|
12
|
+
function cleanPath(path) {
|
|
13
|
+
return path.replace(/\/{2,}/g, "/");
|
|
14
|
+
}
|
|
15
|
+
/** Trim leading slashes (except preserving root '/'). */
|
|
16
|
+
function trimPathLeft(path) {
|
|
17
|
+
return path === "/" ? path : path.replace(/^\/{1,}/, "");
|
|
18
|
+
}
|
|
19
|
+
/** Trim trailing slashes (except preserving root '/'). */
|
|
20
|
+
function trimPathRight(path) {
|
|
21
|
+
const len = path.length;
|
|
22
|
+
return len > 1 && path[len - 1] === "/" ? path.replace(/\/{1,}$/, "") : path;
|
|
23
|
+
}
|
|
24
|
+
/** Trim both leading and trailing slashes. */
|
|
25
|
+
function trimPath(path) {
|
|
26
|
+
return trimPathRight(trimPathLeft(path));
|
|
27
|
+
}
|
|
28
|
+
/** Remove a trailing slash from value when appropriate for comparisons. */
|
|
29
|
+
function removeTrailingSlash(value, basepath) {
|
|
30
|
+
if (value?.endsWith("/") && value !== "/" && value !== `${basepath}/`) return value.slice(0, -1);
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compare two pathnames for exact equality after normalizing trailing slashes
|
|
35
|
+
* relative to the provided `basepath`.
|
|
36
|
+
*/
|
|
37
|
+
function exactPathTest(pathName1, pathName2, basepath) {
|
|
38
|
+
return removeTrailingSlash(pathName1, basepath) === removeTrailingSlash(pathName2, basepath);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a destination path against a base, honoring trailing-slash policy
|
|
42
|
+
* and supporting relative segments (`.`/`..`) and absolute `to` values.
|
|
43
|
+
*/
|
|
44
|
+
function resolvePath({ base, to, trailingSlash = "never", cache }) {
|
|
45
|
+
const isAbsolute = to.startsWith("/");
|
|
46
|
+
const isBase = !isAbsolute && to === ".";
|
|
47
|
+
let key;
|
|
48
|
+
if (cache) {
|
|
49
|
+
key = isAbsolute ? to : isBase ? base : base + "\0" + to;
|
|
50
|
+
const cached = cache.get(key);
|
|
51
|
+
if (cached) return cached;
|
|
52
|
+
}
|
|
53
|
+
let baseSegments;
|
|
54
|
+
if (isBase) baseSegments = base.split("/");
|
|
55
|
+
else if (isAbsolute) baseSegments = to.split("/");
|
|
56
|
+
else {
|
|
57
|
+
baseSegments = base.split("/");
|
|
58
|
+
while (baseSegments.length > 1 && require_utils.last(baseSegments) === "") baseSegments.pop();
|
|
59
|
+
const toSegments = to.split("/");
|
|
60
|
+
for (let index = 0, length = toSegments.length; index < length; index++) {
|
|
61
|
+
const value = toSegments[index];
|
|
62
|
+
if (value === "") {
|
|
63
|
+
if (!index) baseSegments = [value];
|
|
64
|
+
else if (index === length - 1) baseSegments.push(value);
|
|
65
|
+
} else if (value === "..") baseSegments.pop();
|
|
66
|
+
else if (value === ".") {} else baseSegments.push(value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (baseSegments.length > 1) {
|
|
70
|
+
if (require_utils.last(baseSegments) === "") {
|
|
71
|
+
if (trailingSlash === "never") baseSegments.pop();
|
|
72
|
+
} else if (trailingSlash === "always") baseSegments.push("");
|
|
73
|
+
}
|
|
74
|
+
let segment;
|
|
75
|
+
let joined = "";
|
|
76
|
+
for (let i = 0; i < baseSegments.length; i++) {
|
|
77
|
+
if (i > 0) joined += "/";
|
|
78
|
+
const part = baseSegments[i];
|
|
79
|
+
if (!part) continue;
|
|
80
|
+
segment = require_new_process_route_tree.parseSegment(part, 0, segment);
|
|
81
|
+
const kind = segment[0];
|
|
82
|
+
if (kind === 0) {
|
|
83
|
+
joined += part;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const end = segment[5];
|
|
87
|
+
const prefix = part.substring(0, segment[1]);
|
|
88
|
+
const suffix = part.substring(segment[4], end);
|
|
89
|
+
const value = part.substring(segment[2], segment[3]);
|
|
90
|
+
if (kind === 1) joined += prefix || suffix ? `${prefix}{$${value}}${suffix}` : `$${value}`;
|
|
91
|
+
else if (kind === 2) joined += prefix || suffix ? `${prefix}{$}${suffix}` : "$";
|
|
92
|
+
else joined += `${prefix}{-$${value}}${suffix}`;
|
|
93
|
+
}
|
|
94
|
+
joined = cleanPath(joined);
|
|
95
|
+
const result = joined || "/";
|
|
96
|
+
if (key && cache) cache.set(key, result);
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Create a pre-compiled decode config from allowed characters.
|
|
101
|
+
* This should be called once at router initialization.
|
|
102
|
+
*/
|
|
103
|
+
function compileDecodeCharMap(pathParamsAllowedCharacters) {
|
|
104
|
+
const charMap = new Map(pathParamsAllowedCharacters.map((char) => [encodeURIComponent(char), char]));
|
|
105
|
+
const pattern = Array.from(charMap.keys()).map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
106
|
+
const regex = new RegExp(pattern, "g");
|
|
107
|
+
return (encoded) => encoded.replace(regex, (match) => charMap.get(match) ?? match);
|
|
108
|
+
}
|
|
109
|
+
function encodeParam(key, params, decoder) {
|
|
110
|
+
const value = params[key];
|
|
111
|
+
if (typeof value !== "string") return value;
|
|
112
|
+
if (key === "_splat") {
|
|
113
|
+
if (/^[a-zA-Z0-9\-._~!/]*$/.test(value)) return value;
|
|
114
|
+
return value.split("/").map((segment) => encodePathParam(segment, decoder)).join("/");
|
|
115
|
+
} else return encodePathParam(value, decoder);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Interpolate params and wildcards into a route path template.
|
|
119
|
+
*
|
|
120
|
+
* - Encodes params safely (configurable allowed characters)
|
|
121
|
+
* - Supports `{-$optional}` segments, `{prefix{$id}suffix}` and `{$}` wildcards
|
|
122
|
+
*/
|
|
123
|
+
function interpolatePath({ path, params, decoder, ...rest }) {
|
|
124
|
+
let isMissingParams = false;
|
|
125
|
+
const usedParams = Object.create(null);
|
|
126
|
+
if (!path || path === "/") return {
|
|
127
|
+
interpolatedPath: "/",
|
|
128
|
+
usedParams,
|
|
129
|
+
isMissingParams
|
|
130
|
+
};
|
|
131
|
+
if (!path.includes("$")) return {
|
|
132
|
+
interpolatedPath: path,
|
|
133
|
+
usedParams,
|
|
134
|
+
isMissingParams
|
|
135
|
+
};
|
|
136
|
+
if (_benjavicente_router_core_isServer.isServer ?? rest.server) {
|
|
137
|
+
if (path.indexOf("{") === -1) {
|
|
138
|
+
const length = path.length;
|
|
139
|
+
let cursor = 0;
|
|
140
|
+
let joined = "";
|
|
141
|
+
while (cursor < length) {
|
|
142
|
+
while (cursor < length && path.charCodeAt(cursor) === 47) cursor++;
|
|
143
|
+
if (cursor >= length) break;
|
|
144
|
+
const start = cursor;
|
|
145
|
+
let end = path.indexOf("/", cursor);
|
|
146
|
+
if (end === -1) end = length;
|
|
147
|
+
cursor = end;
|
|
148
|
+
const part = path.substring(start, end);
|
|
149
|
+
if (!part) continue;
|
|
150
|
+
if (part.charCodeAt(0) === 36) if (part.length === 1) {
|
|
151
|
+
const splat = params._splat;
|
|
152
|
+
usedParams._splat = splat;
|
|
153
|
+
usedParams["*"] = splat;
|
|
154
|
+
if (!splat) {
|
|
155
|
+
isMissingParams = true;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const value = encodeParam("_splat", params, decoder);
|
|
159
|
+
joined += "/" + value;
|
|
160
|
+
} else {
|
|
161
|
+
const key = part.substring(1);
|
|
162
|
+
if (!isMissingParams && !(key in params)) isMissingParams = true;
|
|
163
|
+
usedParams[key] = params[key];
|
|
164
|
+
const value = encodeParam(key, params, decoder) ?? "undefined";
|
|
165
|
+
joined += "/" + value;
|
|
166
|
+
}
|
|
167
|
+
else joined += "/" + part;
|
|
168
|
+
}
|
|
169
|
+
if (path.endsWith("/")) joined += "/";
|
|
170
|
+
return {
|
|
171
|
+
usedParams,
|
|
172
|
+
interpolatedPath: joined || "/",
|
|
173
|
+
isMissingParams
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const length = path.length;
|
|
178
|
+
let cursor = 0;
|
|
179
|
+
let segment;
|
|
180
|
+
let joined = "";
|
|
181
|
+
while (cursor < length) {
|
|
182
|
+
const start = cursor;
|
|
183
|
+
segment = require_new_process_route_tree.parseSegment(path, start, segment);
|
|
184
|
+
const end = segment[5];
|
|
185
|
+
cursor = end + 1;
|
|
186
|
+
if (start === end) continue;
|
|
187
|
+
const kind = segment[0];
|
|
188
|
+
if (kind === 0) {
|
|
189
|
+
joined += "/" + path.substring(start, end);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (kind === 2) {
|
|
193
|
+
const splat = params._splat;
|
|
194
|
+
usedParams._splat = splat;
|
|
195
|
+
usedParams["*"] = splat;
|
|
196
|
+
const prefix = path.substring(start, segment[1]);
|
|
197
|
+
const suffix = path.substring(segment[4], end);
|
|
198
|
+
if (!splat) {
|
|
199
|
+
isMissingParams = true;
|
|
200
|
+
if (prefix || suffix) joined += "/" + prefix + suffix;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const value = encodeParam("_splat", params, decoder);
|
|
204
|
+
joined += "/" + prefix + value + suffix;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (kind === 1) {
|
|
208
|
+
const key = path.substring(segment[2], segment[3]);
|
|
209
|
+
if (!isMissingParams && !(key in params)) isMissingParams = true;
|
|
210
|
+
usedParams[key] = params[key];
|
|
211
|
+
const prefix = path.substring(start, segment[1]);
|
|
212
|
+
const suffix = path.substring(segment[4], end);
|
|
213
|
+
const value = encodeParam(key, params, decoder) ?? "undefined";
|
|
214
|
+
joined += "/" + prefix + value + suffix;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (kind === 3) {
|
|
218
|
+
const key = path.substring(segment[2], segment[3]);
|
|
219
|
+
const valueRaw = params[key];
|
|
220
|
+
if (valueRaw == null) continue;
|
|
221
|
+
usedParams[key] = valueRaw;
|
|
222
|
+
const prefix = path.substring(start, segment[1]);
|
|
223
|
+
const suffix = path.substring(segment[4], end);
|
|
224
|
+
const value = encodeParam(key, params, decoder) ?? "";
|
|
225
|
+
joined += "/" + prefix + value + suffix;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (path.endsWith("/")) joined += "/";
|
|
230
|
+
return {
|
|
231
|
+
usedParams,
|
|
232
|
+
interpolatedPath: joined || "/",
|
|
233
|
+
isMissingParams
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function encodePathParam(value, decoder) {
|
|
237
|
+
const encoded = encodeURIComponent(value);
|
|
238
|
+
return decoder?.(encoded) ?? encoded;
|
|
239
|
+
}
|
|
240
|
+
//#endregion
|
|
241
|
+
exports.cleanPath = cleanPath;
|
|
242
|
+
exports.compileDecodeCharMap = compileDecodeCharMap;
|
|
243
|
+
exports.exactPathTest = exactPathTest;
|
|
244
|
+
exports.interpolatePath = interpolatePath;
|
|
245
|
+
exports.joinPaths = joinPaths;
|
|
246
|
+
exports.removeTrailingSlash = removeTrailingSlash;
|
|
247
|
+
exports.resolvePath = resolvePath;
|
|
248
|
+
exports.trimPath = trimPath;
|
|
249
|
+
exports.trimPathLeft = trimPathLeft;
|
|
250
|
+
exports.trimPathRight = trimPathRight;
|
|
251
|
+
|
|
252
|
+
//# sourceMappingURL=path.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.cjs","names":[],"sources":["../../src/path.ts"],"sourcesContent":["import { isServer } from '@benjavicente/router-core/isServer'\nimport { last } from './utils'\nimport {\n SEGMENT_TYPE_OPTIONAL_PARAM,\n SEGMENT_TYPE_PARAM,\n SEGMENT_TYPE_PATHNAME,\n SEGMENT_TYPE_WILDCARD,\n parseSegment,\n} from './new-process-route-tree'\nimport type { LRUCache } from './lru-cache'\n\n/** Join path segments, cleaning duplicate slashes between parts. */\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\n/** Remove repeated slashes from a path string. */\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\n/** Trim leading slashes (except preserving root '/'). */\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\n/** Trim trailing slashes (except preserving root '/'). */\nexport function trimPathRight(path: string) {\n const len = path.length\n return len > 1 && path[len - 1] === '/' ? path.replace(/\\/{1,}$/, '') : path\n}\n\n/** Trim both leading and trailing slashes. */\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\n/** Remove a trailing slash from value when appropriate for comparisons. */\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\n/**\n * Compare two pathnames for exact equality after normalizing trailing slashes\n * relative to the provided `basepath`.\n */\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n cache?: LRUCache<string, string>\n}\n\n/**\n * Resolve a destination path against a base, honoring trailing-slash policy\n * and supporting relative segments (`.`/`..`) and absolute `to` values.\n */\nexport function resolvePath({\n base,\n to,\n trailingSlash = 'never',\n cache,\n}: ResolvePathOptions) {\n const isAbsolute = to.startsWith('/')\n const isBase = !isAbsolute && to === '.'\n\n let key\n if (cache) {\n // `trailingSlash` is static per router, so it doesn't need to be part of the cache key\n key = isAbsolute ? to : isBase ? base : base + '\\0' + to\n const cached = cache.get(key)\n if (cached) return cached\n }\n\n let baseSegments: Array<string>\n if (isBase) {\n baseSegments = base.split('/')\n } else if (isAbsolute) {\n baseSegments = to.split('/')\n } else {\n baseSegments = base.split('/')\n while (baseSegments.length > 1 && last(baseSegments) === '') {\n baseSegments.pop()\n }\n\n const toSegments = to.split('/')\n for (let index = 0, length = toSegments.length; index < length; index++) {\n const value = toSegments[index]!\n if (value === '') {\n if (!index) {\n // Leading slash\n baseSegments = [value]\n } else if (index === length - 1) {\n // Trailing Slash\n baseSegments.push(value)\n } else {\n // ignore inter-slashes\n }\n } else if (value === '..') {\n baseSegments.pop()\n } else if (value === '.') {\n // ignore\n } else {\n baseSegments.push(value)\n }\n }\n }\n\n if (baseSegments.length > 1) {\n if (last(baseSegments) === '') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push('')\n }\n }\n\n let segment\n let joined = ''\n for (let i = 0; i < baseSegments.length; i++) {\n if (i > 0) joined += '/'\n const part = baseSegments[i]!\n if (!part) continue\n segment = parseSegment(part, 0, segment)\n const kind = segment[0]\n if (kind === SEGMENT_TYPE_PATHNAME) {\n joined += part\n continue\n }\n const end = segment[5]\n const prefix = part.substring(0, segment[1])\n const suffix = part.substring(segment[4], end)\n const value = part.substring(segment[2], segment[3])\n if (kind === SEGMENT_TYPE_PARAM) {\n joined += prefix || suffix ? `${prefix}{$${value}}${suffix}` : `$${value}`\n } else if (kind === SEGMENT_TYPE_WILDCARD) {\n joined += prefix || suffix ? `${prefix}{$}${suffix}` : '$'\n } else {\n // SEGMENT_TYPE_OPTIONAL_PARAM\n joined += `${prefix}{-$${value}}${suffix}`\n }\n }\n joined = cleanPath(joined)\n const result = joined || '/'\n if (key && cache) cache.set(key, result)\n return result\n}\n\n/**\n * Create a pre-compiled decode config from allowed characters.\n * This should be called once at router initialization.\n */\nexport function compileDecodeCharMap(\n pathParamsAllowedCharacters: ReadonlyArray<string>,\n) {\n const charMap = new Map(\n pathParamsAllowedCharacters.map((char) => [encodeURIComponent(char), char]),\n )\n // Escape special regex characters and join with |\n const pattern = Array.from(charMap.keys())\n .map((key) => key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n .join('|')\n const regex = new RegExp(pattern, 'g')\n return (encoded: string) =>\n encoded.replace(regex, (match) => charMap.get(match) ?? match)\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n /**\n * A function that decodes a path parameter value.\n * Obtained from `compileDecodeCharMap(pathParamsAllowedCharacters)`.\n */\n decoder?: (encoded: string) => string\n /**\n * @internal\n * For testing only, in development mode we use the router.isServer value\n */\n server?: boolean\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\n\nfunction encodeParam(\n key: string,\n params: InterpolatePathOptions['params'],\n decoder: InterpolatePathOptions['decoder'],\n): any {\n const value = params[key]\n if (typeof value !== 'string') return value\n\n if (key === '_splat') {\n // Early return if value only contains URL-safe characters (performance optimization)\n if (/^[a-zA-Z0-9\\-._~!/]*$/.test(value)) return value\n // the splat/catch-all routes shouldn't have the '/' encoded out\n // Use encodeURIComponent for each segment to properly encode spaces,\n // plus signs, and other special characters that encodeURI leaves unencoded\n return value\n .split('/')\n .map((segment) => encodePathParam(segment, decoder))\n .join('/')\n } else {\n return encodePathParam(value, decoder)\n }\n}\n\n/**\n * Interpolate params and wildcards into a route path template.\n *\n * - Encodes params safely (configurable allowed characters)\n * - Supports `{-$optional}` segments, `{prefix{$id}suffix}` and `{$}` wildcards\n */\nexport function interpolatePath({\n path,\n params,\n decoder,\n // `server` is marked @internal and stripped from .d.ts by `stripInternal`.\n // We avoid destructuring it in the function signature so the emitted\n // declaration doesn't reference a property that no longer exists.\n ...rest\n}: InterpolatePathOptions): InterPolatePathResult {\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n const usedParams: Record<string, unknown> = Object.create(null)\n\n if (!path || path === '/')\n return { interpolatedPath: '/', usedParams, isMissingParams }\n if (!path.includes('$'))\n return { interpolatedPath: path, usedParams, isMissingParams }\n\n if (isServer ?? rest.server) {\n // Fast path for common templates like `/posts/$id` or `/files/$`.\n // Braced segments (`{...}`) are more complex (prefix/suffix/optional) and are\n // handled by the general parser below.\n if (path.indexOf('{') === -1) {\n const length = path.length\n let cursor = 0\n let joined = ''\n\n while (cursor < length) {\n // Skip slashes between segments. '/' code is 47\n while (cursor < length && path.charCodeAt(cursor) === 47) cursor++\n if (cursor >= length) break\n\n const start = cursor\n let end = path.indexOf('/', cursor)\n if (end === -1) end = length\n cursor = end\n\n const part = path.substring(start, end)\n if (!part) continue\n\n // `$id` or `$` (splat). '$' code is 36\n if (part.charCodeAt(0) === 36) {\n if (part.length === 1) {\n const splat = params._splat\n usedParams._splat = splat\n // TODO: Deprecate *\n usedParams['*'] = splat\n\n if (!splat) {\n isMissingParams = true\n continue\n }\n\n const value = encodeParam('_splat', params, decoder)\n joined += '/' + value\n } else {\n const key = part.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n\n const value = encodeParam(key, params, decoder) ?? 'undefined'\n joined += '/' + value\n }\n } else {\n joined += '/' + part\n }\n }\n\n if (path.endsWith('/')) joined += '/'\n\n const interpolatedPath = joined || '/'\n return { usedParams, interpolatedPath, isMissingParams }\n }\n }\n\n const length = path.length\n let cursor = 0\n let segment\n let joined = ''\n while (cursor < length) {\n const start = cursor\n segment = parseSegment(path, start, segment)\n const end = segment[5]\n cursor = end + 1\n\n if (start === end) continue\n\n const kind = segment[0]\n\n if (kind === SEGMENT_TYPE_PATHNAME) {\n joined += '/' + path.substring(start, end)\n continue\n }\n\n if (kind === SEGMENT_TYPE_WILDCARD) {\n const splat = params._splat\n usedParams._splat = splat\n // TODO: Deprecate *\n usedParams['*'] = splat\n\n const prefix = path.substring(start, segment[1])\n const suffix = path.substring(segment[4], end)\n\n // Check if _splat parameter is missing. _splat could be missing if undefined or an empty string or some other falsy value.\n if (!splat) {\n isMissingParams = true\n // For missing splat parameters, just return the prefix and suffix without the wildcard\n // If there is a prefix or suffix, return them joined, otherwise omit the segment\n if (prefix || suffix) {\n joined += '/' + prefix + suffix\n }\n continue\n }\n\n const value = encodeParam('_splat', params, decoder)\n joined += '/' + prefix + value + suffix\n continue\n }\n\n if (kind === SEGMENT_TYPE_PARAM) {\n const key = path.substring(segment[2], segment[3])\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n\n const prefix = path.substring(start, segment[1])\n const suffix = path.substring(segment[4], end)\n const value = encodeParam(key, params, decoder) ?? 'undefined'\n joined += '/' + prefix + value + suffix\n continue\n }\n\n if (kind === SEGMENT_TYPE_OPTIONAL_PARAM) {\n const key = path.substring(segment[2], segment[3])\n const valueRaw = params[key]\n\n // Check if optional parameter is missing or undefined\n if (valueRaw == null) continue\n\n usedParams[key] = valueRaw\n\n const prefix = path.substring(start, segment[1])\n const suffix = path.substring(segment[4], end)\n const value = encodeParam(key, params, decoder) ?? ''\n joined += '/' + prefix + value + suffix\n continue\n }\n }\n\n if (path.endsWith('/')) joined += '/'\n\n const interpolatedPath = joined || '/'\n\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(\n value: string,\n decoder?: InterpolatePathOptions['decoder'],\n) {\n const encoded = encodeURIComponent(value)\n return decoder?.(encoded) ?? encoded\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { LRUCache } from './lru-cache.cjs';
|
|
2
|
+
/** Join path segments, cleaning duplicate slashes between parts. */
|
|
3
|
+
export declare function joinPaths(paths: Array<string | undefined>): string;
|
|
4
|
+
/** Remove repeated slashes from a path string. */
|
|
5
|
+
export declare function cleanPath(path: string): string;
|
|
6
|
+
/** Trim leading slashes (except preserving root '/'). */
|
|
7
|
+
export declare function trimPathLeft(path: string): string;
|
|
8
|
+
/** Trim trailing slashes (except preserving root '/'). */
|
|
9
|
+
export declare function trimPathRight(path: string): string;
|
|
10
|
+
/** Trim both leading and trailing slashes. */
|
|
11
|
+
export declare function trimPath(path: string): string;
|
|
12
|
+
/** Remove a trailing slash from value when appropriate for comparisons. */
|
|
13
|
+
export declare function removeTrailingSlash(value: string, basepath: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Compare two pathnames for exact equality after normalizing trailing slashes
|
|
16
|
+
* relative to the provided `basepath`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function exactPathTest(pathName1: string, pathName2: string, basepath: string): boolean;
|
|
19
|
+
interface ResolvePathOptions {
|
|
20
|
+
base: string;
|
|
21
|
+
to: string;
|
|
22
|
+
trailingSlash?: 'always' | 'never' | 'preserve';
|
|
23
|
+
cache?: LRUCache<string, string>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve a destination path against a base, honoring trailing-slash policy
|
|
27
|
+
* and supporting relative segments (`.`/`..`) and absolute `to` values.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolvePath({ base, to, trailingSlash, cache, }: ResolvePathOptions): string;
|
|
30
|
+
/**
|
|
31
|
+
* Create a pre-compiled decode config from allowed characters.
|
|
32
|
+
* This should be called once at router initialization.
|
|
33
|
+
*/
|
|
34
|
+
export declare function compileDecodeCharMap(pathParamsAllowedCharacters: ReadonlyArray<string>): (encoded: string) => string;
|
|
35
|
+
interface InterpolatePathOptions {
|
|
36
|
+
path?: string;
|
|
37
|
+
params: Record<string, unknown>;
|
|
38
|
+
/**
|
|
39
|
+
* A function that decodes a path parameter value.
|
|
40
|
+
* Obtained from `compileDecodeCharMap(pathParamsAllowedCharacters)`.
|
|
41
|
+
*/
|
|
42
|
+
decoder?: (encoded: string) => string;
|
|
43
|
+
}
|
|
44
|
+
type InterPolatePathResult = {
|
|
45
|
+
interpolatedPath: string;
|
|
46
|
+
usedParams: Record<string, unknown>;
|
|
47
|
+
isMissingParams: boolean;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Interpolate params and wildcards into a route path template.
|
|
51
|
+
*
|
|
52
|
+
* - Encodes params safely (configurable allowed characters)
|
|
53
|
+
* - Supports `{-$optional}` segments, `{prefix{$id}suffix}` and `{$}` wildcards
|
|
54
|
+
*/
|
|
55
|
+
export declare function interpolatePath({ path, params, decoder, ...rest }: InterpolatePathOptions): InterPolatePathResult;
|
|
56
|
+
export {};
|
package/dist/cjs/qss.cjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//#region src/qss.ts
|
|
2
|
+
/**
|
|
3
|
+
* Program is a reimplementation of the `qss` package:
|
|
4
|
+
* Copyright (c) Luke Edwards luke.edwards05@gmail.com, MIT License
|
|
5
|
+
* https://github.com/lukeed/qss/blob/master/license.md
|
|
6
|
+
*
|
|
7
|
+
* This reimplementation uses modern browser APIs
|
|
8
|
+
* (namely URLSearchParams) and TypeScript while still
|
|
9
|
+
* maintaining the original functionality and interface.
|
|
10
|
+
*
|
|
11
|
+
* Update: this implementation has also been mangled to
|
|
12
|
+
* fit exactly our use-case (single value per key in encoding).
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Encodes an object into a query string.
|
|
16
|
+
* @param obj - The object to encode into a query string.
|
|
17
|
+
* @param stringify - An optional custom stringify function.
|
|
18
|
+
* @returns The encoded query string.
|
|
19
|
+
* @example
|
|
20
|
+
* ```
|
|
21
|
+
* // Example input: encode({ token: 'foo', key: 'value' })
|
|
22
|
+
* // Expected output: "token=foo&key=value"
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function encode(obj, stringify = String) {
|
|
26
|
+
const result = new URLSearchParams();
|
|
27
|
+
for (const key in obj) {
|
|
28
|
+
const val = obj[key];
|
|
29
|
+
if (val !== void 0) result.set(key, stringify(val));
|
|
30
|
+
}
|
|
31
|
+
return result.toString();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Converts a string value to its appropriate type (string, number, boolean).
|
|
35
|
+
* @param mix - The string value to convert.
|
|
36
|
+
* @returns The converted value.
|
|
37
|
+
* @example
|
|
38
|
+
* // Example input: toValue("123")
|
|
39
|
+
* // Expected output: 123
|
|
40
|
+
*/
|
|
41
|
+
function toValue(str) {
|
|
42
|
+
if (!str) return "";
|
|
43
|
+
if (str === "false") return false;
|
|
44
|
+
if (str === "true") return true;
|
|
45
|
+
return +str * 0 === 0 && +str + "" === str ? +str : str;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Decodes a query string into an object.
|
|
49
|
+
* @param str - The query string to decode.
|
|
50
|
+
* @returns The decoded key-value pairs in an object format.
|
|
51
|
+
* @example
|
|
52
|
+
* // Example input: decode("token=foo&key=value")
|
|
53
|
+
* // Expected output: { "token": "foo", "key": "value" }
|
|
54
|
+
*/
|
|
55
|
+
function decode(str) {
|
|
56
|
+
const searchParams = new URLSearchParams(str);
|
|
57
|
+
const result = Object.create(null);
|
|
58
|
+
for (const [key, value] of searchParams.entries()) {
|
|
59
|
+
const previousValue = result[key];
|
|
60
|
+
if (previousValue == null) result[key] = toValue(value);
|
|
61
|
+
else if (Array.isArray(previousValue)) previousValue.push(toValue(value));
|
|
62
|
+
else result[key] = [previousValue, toValue(value)];
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
exports.decode = decode;
|
|
68
|
+
exports.encode = encode;
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=qss.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qss.cjs","names":[],"sources":["../../src/qss.ts"],"sourcesContent":["/**\n * Program is a reimplementation of the `qss` package:\n * Copyright (c) Luke Edwards luke.edwards05@gmail.com, MIT License\n * https://github.com/lukeed/qss/blob/master/license.md\n *\n * This reimplementation uses modern browser APIs\n * (namely URLSearchParams) and TypeScript while still\n * maintaining the original functionality and interface.\n *\n * Update: this implementation has also been mangled to\n * fit exactly our use-case (single value per key in encoding).\n */\n\n/**\n * Encodes an object into a query string.\n * @param obj - The object to encode into a query string.\n * @param stringify - An optional custom stringify function.\n * @returns The encoded query string.\n * @example\n * ```\n * // Example input: encode({ token: 'foo', key: 'value' })\n * // Expected output: \"token=foo&key=value\"\n * ```\n */\nexport function encode(\n obj: Record<string, any>,\n stringify: (value: any) => string = String,\n): string {\n const result = new URLSearchParams()\n\n for (const key in obj) {\n const val = obj[key]\n if (val !== undefined) {\n result.set(key, stringify(val))\n }\n }\n\n return result.toString()\n}\n\n/**\n * Converts a string value to its appropriate type (string, number, boolean).\n * @param mix - The string value to convert.\n * @returns The converted value.\n * @example\n * // Example input: toValue(\"123\")\n * // Expected output: 123\n */\nfunction toValue(str: unknown) {\n if (!str) return ''\n\n if (str === 'false') return false\n if (str === 'true') return true\n return +str * 0 === 0 && +str + '' === str ? +str : str\n}\n/**\n * Decodes a query string into an object.\n * @param str - The query string to decode.\n * @returns The decoded key-value pairs in an object format.\n * @example\n * // Example input: decode(\"token=foo&key=value\")\n * // Expected output: { \"token\": \"foo\", \"key\": \"value\" }\n */\nexport function decode(str: any): any {\n const searchParams = new URLSearchParams(str)\n\n const result: Record<string, unknown> = Object.create(null)\n\n for (const [key, value] of searchParams.entries()) {\n const previousValue = result[key]\n if (previousValue == null) {\n result[key] = toValue(value)\n } else if (Array.isArray(previousValue)) {\n previousValue.push(toValue(value))\n } else {\n result[key] = [previousValue, toValue(value)]\n }\n }\n\n return result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,OACd,KACA,YAAoC,QAC5B;CACR,MAAM,SAAS,IAAI,iBAAiB;AAEpC,MAAK,MAAM,OAAO,KAAK;EACrB,MAAM,MAAM,IAAI;AAChB,MAAI,QAAQ,KAAA,EACV,QAAO,IAAI,KAAK,UAAU,IAAI,CAAC;;AAInC,QAAO,OAAO,UAAU;;;;;;;;;;AAW1B,SAAS,QAAQ,KAAc;AAC7B,KAAI,CAAC,IAAK,QAAO;AAEjB,KAAI,QAAQ,QAAS,QAAO;AAC5B,KAAI,QAAQ,OAAQ,QAAO;AAC3B,QAAO,CAAC,MAAM,MAAM,KAAK,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM;;;;;;;;;;AAUtD,SAAgB,OAAO,KAAe;CACpC,MAAM,eAAe,IAAI,gBAAgB,IAAI;CAE7C,MAAM,SAAkC,OAAO,OAAO,KAAK;AAE3D,MAAK,MAAM,CAAC,KAAK,UAAU,aAAa,SAAS,EAAE;EACjD,MAAM,gBAAgB,OAAO;AAC7B,MAAI,iBAAiB,KACnB,QAAO,OAAO,QAAQ,MAAM;WACnB,MAAM,QAAQ,cAAc,CACrC,eAAc,KAAK,QAAQ,MAAM,CAAC;MAElC,QAAO,OAAO,CAAC,eAAe,QAAQ,MAAM,CAAC;;AAIjD,QAAO"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program is a reimplementation of the `qss` package:
|
|
3
|
+
* Copyright (c) Luke Edwards luke.edwards05@gmail.com, MIT License
|
|
4
|
+
* https://github.com/lukeed/qss/blob/master/license.md
|
|
5
|
+
*
|
|
6
|
+
* This reimplementation uses modern browser APIs
|
|
7
|
+
* (namely URLSearchParams) and TypeScript while still
|
|
8
|
+
* maintaining the original functionality and interface.
|
|
9
|
+
*
|
|
10
|
+
* Update: this implementation has also been mangled to
|
|
11
|
+
* fit exactly our use-case (single value per key in encoding).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Encodes an object into a query string.
|
|
15
|
+
* @param obj - The object to encode into a query string.
|
|
16
|
+
* @param stringify - An optional custom stringify function.
|
|
17
|
+
* @returns The encoded query string.
|
|
18
|
+
* @example
|
|
19
|
+
* ```
|
|
20
|
+
* // Example input: encode({ token: 'foo', key: 'value' })
|
|
21
|
+
* // Expected output: "token=foo&key=value"
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function encode(obj: Record<string, any>, stringify?: (value: any) => string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Decodes a query string into an object.
|
|
27
|
+
* @param str - The query string to decode.
|
|
28
|
+
* @returns The decoded key-value pairs in an object format.
|
|
29
|
+
* @example
|
|
30
|
+
* // Example input: decode("token=foo&key=value")
|
|
31
|
+
* // Expected output: { "token": "foo", "key": "value" }
|
|
32
|
+
*/
|
|
33
|
+
export declare function decode(str: any): any;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/redirect.ts
|
|
2
|
+
/**
|
|
3
|
+
* Create a redirect Response understood by TanStack Router.
|
|
4
|
+
*
|
|
5
|
+
* Use from route `loader`/`beforeLoad` or server functions to trigger a
|
|
6
|
+
* navigation. If `throw: true` is set, the redirect is thrown instead of
|
|
7
|
+
* returned. When an absolute `href` is supplied and `reloadDocument` is not
|
|
8
|
+
* set, a full-document navigation is inferred.
|
|
9
|
+
*
|
|
10
|
+
* @param opts Options for the redirect. Common fields:
|
|
11
|
+
* - `href`: absolute URL for external redirects; infers `reloadDocument`.
|
|
12
|
+
* - `statusCode`: HTTP status code to use (defaults to 307).
|
|
13
|
+
* - `headers`: additional headers to include on the Response.
|
|
14
|
+
* - Standard navigation options like `to`, `params`, `search`, `replace`,
|
|
15
|
+
* and `reloadDocument` for internal redirects.
|
|
16
|
+
* @returns A Response augmented with router navigation options.
|
|
17
|
+
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction
|
|
18
|
+
*/
|
|
19
|
+
function redirect(opts) {
|
|
20
|
+
opts.statusCode = opts.statusCode || opts.code || 307;
|
|
21
|
+
if (!opts._builtLocation && !opts.reloadDocument && typeof opts.href === "string") try {
|
|
22
|
+
new URL(opts.href);
|
|
23
|
+
opts.reloadDocument = true;
|
|
24
|
+
} catch {}
|
|
25
|
+
const headers = new Headers(opts.headers);
|
|
26
|
+
if (opts.href && headers.get("Location") === null) headers.set("Location", opts.href);
|
|
27
|
+
const response = new Response(null, {
|
|
28
|
+
status: opts.statusCode,
|
|
29
|
+
headers
|
|
30
|
+
});
|
|
31
|
+
response.options = opts;
|
|
32
|
+
if (opts.throw) throw response;
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
/** Check whether a value is a TanStack Router redirect Response. */
|
|
36
|
+
/** Check whether a value is a TanStack Router redirect Response. */
|
|
37
|
+
function isRedirect(obj) {
|
|
38
|
+
return obj instanceof Response && !!obj.options;
|
|
39
|
+
}
|
|
40
|
+
/** True if value is a redirect with a resolved `href` location. */
|
|
41
|
+
/** True if value is a redirect with a resolved `href` location. */
|
|
42
|
+
function isResolvedRedirect(obj) {
|
|
43
|
+
return isRedirect(obj) && !!obj.options.href;
|
|
44
|
+
}
|
|
45
|
+
/** Parse a serialized redirect object back into a redirect Response. */
|
|
46
|
+
/** Parse a serialized redirect object back into a redirect Response. */
|
|
47
|
+
function parseRedirect(obj) {
|
|
48
|
+
if (obj !== null && typeof obj === "object" && obj.isSerializedRedirect) return redirect(obj);
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
exports.isRedirect = isRedirect;
|
|
52
|
+
exports.isResolvedRedirect = isResolvedRedirect;
|
|
53
|
+
exports.parseRedirect = parseRedirect;
|
|
54
|
+
exports.redirect = redirect;
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=redirect.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.cjs","names":[],"sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { ParsedLocation } from './location'\n\nexport type AnyRedirect = Redirect<any, any, any, any, any>\n\n/**\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type Redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = Response & {\n options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\n /**\n * @internal\n * A **trusted** built location that can be used to redirect to.\n */\n _builtLocation?: ParsedLocation\n }\n redirectHandled?: boolean\n}\n\nexport type RedirectOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = {\n href?: string\n /**\n * @deprecated Use `statusCode` instead\n **/\n code?: number\n /**\n * The HTTP status code to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#statuscode-property)\n */\n statusCode?: number\n /**\n * If provided, will throw the redirect object instead of returning it. This can be useful in places where `throwing` in a function might cause it to have a return type of `never`. In that case, you can use `redirect({ throw: true })` to throw the redirect object instead of returning it.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#throw-property)\n */\n throw?: any\n /**\n * The HTTP headers to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#headers-property)\n */\n headers?: HeadersInit\n /**\n * @internal\n * A **trusted** built location that can be used to redirect to.\n */\n _builtLocation?: ParsedLocation\n} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type ResolvedRedirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\n/**\n * Options for route-bound redirect, where 'from' is automatically set.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type RedirectOptionsRoute<\n TDefaultFrom extends string = string,\n TRouter extends AnyRouter = RegisteredRouter,\n TTo extends string | undefined = undefined,\n TMaskTo extends string = '',\n> = Omit<\n RedirectOptions<TRouter, TDefaultFrom, TTo, TDefaultFrom, TMaskTo>,\n 'from'\n>\n\n/**\n * A redirect function bound to a specific route, with 'from' pre-set to the route's fullPath.\n * This enables relative redirects like `Route.redirect({ to: './overview' })`.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport interface RedirectFnRoute<in out TDefaultFrom extends string = string> {\n <\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = undefined,\n const TMaskTo extends string = '',\n >(\n opts: RedirectOptionsRoute<TDefaultFrom, TRouter, TTo, TMaskTo>,\n ): Redirect<TRouter, TDefaultFrom, TTo, TDefaultFrom, TMaskTo>\n}\n\n/**\n * Create a redirect Response understood by TanStack Router.\n *\n * Use from route `loader`/`beforeLoad` or server functions to trigger a\n * navigation. If `throw: true` is set, the redirect is thrown instead of\n * returned. When an absolute `href` is supplied and `reloadDocument` is not\n * set, a full-document navigation is inferred.\n *\n * @param opts Options for the redirect. Common fields:\n * - `href`: absolute URL for external redirects; infers `reloadDocument`.\n * - `statusCode`: HTTP status code to use (defaults to 307).\n * - `headers`: additional headers to include on the Response.\n * - Standard navigation options like `to`, `params`, `search`, `replace`,\n * and `reloadDocument` for internal redirects.\n * @returns A Response augmented with router navigation options.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction\n */\nexport function redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = '.',\n const TFrom extends string = string,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {\n opts.statusCode = opts.statusCode || opts.code || 307\n\n if (\n !opts._builtLocation &&\n !opts.reloadDocument &&\n typeof opts.href === 'string'\n ) {\n try {\n new URL(opts.href)\n opts.reloadDocument = true\n } catch {}\n }\n\n const headers = new Headers(opts.headers)\n if (opts.href && headers.get('Location') === null) {\n headers.set('Location', opts.href)\n }\n\n const response = new Response(null, {\n status: opts.statusCode,\n headers,\n })\n\n ;(response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>).options =\n opts\n\n if (opts.throw) {\n throw response\n }\n\n return response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n}\n\n/** Check whether a value is a TanStack Router redirect Response. */\n/** Check whether a value is a TanStack Router redirect Response. */\nexport function isRedirect(obj: any): obj is AnyRedirect {\n return obj instanceof Response && !!(obj as any).options\n}\n\n/** True if value is a redirect with a resolved `href` location. */\n/** True if value is a redirect with a resolved `href` location. */\nexport function isResolvedRedirect(\n obj: any,\n): obj is AnyRedirect & { options: { href: string } } {\n return isRedirect(obj) && !!obj.options.href\n}\n\n/** Parse a serialized redirect object back into a redirect Response. */\n/** Parse a serialized redirect object back into a redirect Response. */\nexport function parseRedirect(obj: any) {\n if (obj !== null && typeof obj === 'object' && obj.isSerializedRedirect) {\n return redirect(obj)\n }\n\n return undefined\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkHA,SAAgB,SAOd,MACmD;AACnD,MAAK,aAAa,KAAK,cAAc,KAAK,QAAQ;AAElD,KACE,CAAC,KAAK,kBACN,CAAC,KAAK,kBACN,OAAO,KAAK,SAAS,SAErB,KAAI;AACF,MAAI,IAAI,KAAK,KAAK;AAClB,OAAK,iBAAiB;SAChB;CAGV,MAAM,UAAU,IAAI,QAAQ,KAAK,QAAQ;AACzC,KAAI,KAAK,QAAQ,QAAQ,IAAI,WAAW,KAAK,KAC3C,SAAQ,IAAI,YAAY,KAAK,KAAK;CAGpC,MAAM,WAAW,IAAI,SAAS,MAAM;EAClC,QAAQ,KAAK;EACb;EACD,CAAC;AAEA,UAA+D,UAC/D;AAEF,KAAI,KAAK,MACP,OAAM;AAGR,QAAO;;;;AAKT,SAAgB,WAAW,KAA8B;AACvD,QAAO,eAAe,YAAY,CAAC,CAAE,IAAY;;;;AAKnD,SAAgB,mBACd,KACoD;AACpD,QAAO,WAAW,IAAI,IAAI,CAAC,CAAC,IAAI,QAAQ;;;;AAK1C,SAAgB,cAAc,KAAU;AACtC,KAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,IAAI,qBACjD,QAAO,SAAS,IAAI"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { NavigateOptions } from './link.cjs';
|
|
2
|
+
import { AnyRouter, RegisteredRouter } from './router.cjs';
|
|
3
|
+
export type AnyRedirect = Redirect<any, any, any, any, any>;
|
|
4
|
+
/**
|
|
5
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)
|
|
6
|
+
*/
|
|
7
|
+
export type Redirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = Response & {
|
|
8
|
+
options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {};
|
|
9
|
+
redirectHandled?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type RedirectOptions<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = {
|
|
12
|
+
href?: string;
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated Use `statusCode` instead
|
|
15
|
+
**/
|
|
16
|
+
code?: number;
|
|
17
|
+
/**
|
|
18
|
+
* The HTTP status code to use when redirecting.
|
|
19
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#statuscode-property)
|
|
20
|
+
*/
|
|
21
|
+
statusCode?: number;
|
|
22
|
+
/**
|
|
23
|
+
* If provided, will throw the redirect object instead of returning it. This can be useful in places where `throwing` in a function might cause it to have a return type of `never`. In that case, you can use `redirect({ throw: true })` to throw the redirect object instead of returning it.
|
|
24
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#throw-property)
|
|
25
|
+
*/
|
|
26
|
+
throw?: any;
|
|
27
|
+
/**
|
|
28
|
+
* The HTTP headers to use when redirecting.
|
|
29
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#headers-property)
|
|
30
|
+
*/
|
|
31
|
+
headers?: HeadersInit;
|
|
32
|
+
} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
33
|
+
export type ResolvedRedirect<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string = '', TMaskFrom extends string = TFrom, TMaskTo extends string = ''> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
34
|
+
/**
|
|
35
|
+
* Options for route-bound redirect, where 'from' is automatically set.
|
|
36
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)
|
|
37
|
+
*/
|
|
38
|
+
export type RedirectOptionsRoute<TDefaultFrom extends string = string, TRouter extends AnyRouter = RegisteredRouter, TTo extends string | undefined = undefined, TMaskTo extends string = ''> = Omit<RedirectOptions<TRouter, TDefaultFrom, TTo, TDefaultFrom, TMaskTo>, 'from'>;
|
|
39
|
+
/**
|
|
40
|
+
* A redirect function bound to a specific route, with 'from' pre-set to the route's fullPath.
|
|
41
|
+
* This enables relative redirects like `Route.redirect({ to: './overview' })`.
|
|
42
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)
|
|
43
|
+
*/
|
|
44
|
+
export interface RedirectFnRoute<in out TDefaultFrom extends string = string> {
|
|
45
|
+
<TRouter extends AnyRouter = RegisteredRouter, const TTo extends string | undefined = undefined, const TMaskTo extends string = ''>(opts: RedirectOptionsRoute<TDefaultFrom, TRouter, TTo, TMaskTo>): Redirect<TRouter, TDefaultFrom, TTo, TDefaultFrom, TMaskTo>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create a redirect Response understood by TanStack Router.
|
|
49
|
+
*
|
|
50
|
+
* Use from route `loader`/`beforeLoad` or server functions to trigger a
|
|
51
|
+
* navigation. If `throw: true` is set, the redirect is thrown instead of
|
|
52
|
+
* returned. When an absolute `href` is supplied and `reloadDocument` is not
|
|
53
|
+
* set, a full-document navigation is inferred.
|
|
54
|
+
*
|
|
55
|
+
* @param opts Options for the redirect. Common fields:
|
|
56
|
+
* - `href`: absolute URL for external redirects; infers `reloadDocument`.
|
|
57
|
+
* - `statusCode`: HTTP status code to use (defaults to 307).
|
|
58
|
+
* - `headers`: additional headers to include on the Response.
|
|
59
|
+
* - Standard navigation options like `to`, `params`, `search`, `replace`,
|
|
60
|
+
* and `reloadDocument` for internal redirects.
|
|
61
|
+
* @returns A Response augmented with router navigation options.
|
|
62
|
+
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction
|
|
63
|
+
*/
|
|
64
|
+
export declare function redirect<TRouter extends AnyRouter = RegisteredRouter, const TTo extends string | undefined = '.', const TFrom extends string = string, const TMaskFrom extends string = TFrom, const TMaskTo extends string = ''>(opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>;
|
|
65
|
+
/** Check whether a value is a TanStack Router redirect Response. */
|
|
66
|
+
/** Check whether a value is a TanStack Router redirect Response. */
|
|
67
|
+
export declare function isRedirect(obj: any): obj is AnyRedirect;
|
|
68
|
+
/** True if value is a redirect with a resolved `href` location. */
|
|
69
|
+
/** True if value is a redirect with a resolved `href` location. */
|
|
70
|
+
export declare function isResolvedRedirect(obj: any): obj is AnyRedirect & {
|
|
71
|
+
options: {
|
|
72
|
+
href: string;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
/** Parse a serialized redirect object back into a redirect Response. */
|
|
76
|
+
/** Parse a serialized redirect object back into a redirect Response. */
|
|
77
|
+
export declare function parseRedirect(obj: any): Redirect<AnyRouter, string, ".", string, ""> | undefined;
|