react-routes-forge 1.5.0 → 1.6.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.
@@ -1,4 +1,5 @@
1
- import { E as ExtractParams, Q as QueryParams } from '../index-B3PDrNod.cjs';
1
+ import { useRouter } from 'next/navigation';
2
+ import { E as ExtractParams, Q as QueryParams } from '../index-_N1whVbt.cjs';
2
3
 
3
4
  /**
4
5
  * Checks if the current path matches the given template.
@@ -14,7 +15,10 @@ type NavigateOptions = {
14
15
  /**
15
16
  * Returns a function to navigate to a new path.
16
17
  */
17
- declare function useNavigateTo(): (path: string, options?: NavigateOptions) => void;
18
+ declare function useNavigateTo(): {
19
+ (path: string, options?: NavigateOptions): void;
20
+ prefetch(path: string, options?: Parameters<ReturnType<typeof useRouter>["prefetch"]>[1]): void;
21
+ };
18
22
  /**
19
23
  * Extracts route parameters. Optionally strongly typed.
20
24
  */
@@ -25,10 +29,10 @@ declare function useRouteParams<P extends string>(route: {
25
29
  /**
26
30
  * Typed search params hook.
27
31
  */
28
- declare function useTypedSearchParams(options?: {
32
+ declare function useTypedSearchParams<T extends QueryParams = QueryParams>(options?: {
29
33
  coerceBooleans?: boolean;
30
34
  coerceNumbers?: boolean;
31
- }): readonly [QueryParams, (newQuery: QueryParams, navigateOptions?: {
35
+ }): readonly [T, (newQuery: Partial<T> | QueryParams, navigateOptions?: {
32
36
  replace?: boolean;
33
37
  scroll?: boolean;
34
38
  }) => void];
@@ -1,4 +1,5 @@
1
- import { E as ExtractParams, Q as QueryParams } from '../index-B3PDrNod.js';
1
+ import { useRouter } from 'next/navigation';
2
+ import { E as ExtractParams, Q as QueryParams } from '../index-_N1whVbt.js';
2
3
 
3
4
  /**
4
5
  * Checks if the current path matches the given template.
@@ -14,7 +15,10 @@ type NavigateOptions = {
14
15
  /**
15
16
  * Returns a function to navigate to a new path.
16
17
  */
17
- declare function useNavigateTo(): (path: string, options?: NavigateOptions) => void;
18
+ declare function useNavigateTo(): {
19
+ (path: string, options?: NavigateOptions): void;
20
+ prefetch(path: string, options?: Parameters<ReturnType<typeof useRouter>["prefetch"]>[1]): void;
21
+ };
18
22
  /**
19
23
  * Extracts route parameters. Optionally strongly typed.
20
24
  */
@@ -25,10 +29,10 @@ declare function useRouteParams<P extends string>(route: {
25
29
  /**
26
30
  * Typed search params hook.
27
31
  */
28
- declare function useTypedSearchParams(options?: {
32
+ declare function useTypedSearchParams<T extends QueryParams = QueryParams>(options?: {
29
33
  coerceBooleans?: boolean;
30
34
  coerceNumbers?: boolean;
31
- }): readonly [QueryParams, (newQuery: QueryParams, navigateOptions?: {
35
+ }): readonly [T, (newQuery: Partial<T> | QueryParams, navigateOptions?: {
32
36
  replace?: boolean;
33
37
  scroll?: boolean;
34
38
  }) => void];
@@ -1,2 +1,2 @@
1
- import"../chunk-H5UZR7HM.js";import{k as m,o as f}from"../chunk-NX4N6IWV.js";import{useCallback as y,useMemo as h}from"react";import{usePathname as P,useRouter as w,useSearchParams as x,useParams as R}from"next/navigation";function N(e,r={}){if(typeof window>"u")throw new Error("useActivePath can only be used in browser environment. Call this hook only in client components.");let n=P();return h(()=>f(n||"/",e,r),[n,e,r.exact,r.caseSensitive])}function T(){if(typeof window>"u")throw new Error("useNavigateTo can only be used in browser environment. Call this hook only in client components.");let e=w();return y((r,n)=>{let o=n?.scroll!==void 0?{scroll:n.scroll}:void 0;n?.replace?e.replace(r,o):e.push(r,o)},[e])}function C(e){if(typeof window>"u")throw new Error("useRouteParams can only be used in browser environment. Call this hook only in client components.");return R()||{}}function O(e){if(typeof window>"u")throw new Error("useTypedSearchParams can only be used in browser environment. Call this hook only in client components.");let r=x(),n=w(),o=P(),b=h(()=>m(r?"?"+r.toString():"",e),[r,e]),g=y((l,s)=>{let a=new URLSearchParams;Object.entries(l).forEach(([i,t])=>{Object.prototype.hasOwnProperty.call(l,i)&&t!=null&&(Array.isArray(t)?t.forEach(c=>{c!=null&&a.append(i,String(c))}):a.append(i,String(t)))});let u=a.toString(),d=`${o}${u?"?":""}${u}`,p=s?.scroll!==void 0?{scroll:s.scroll}:void 0;s?.replace?n.replace(d,p):n.push(d,p)},[n,o]);return[b,g]}export{N as useActivePath,T as useNavigateTo,C as useRouteParams,O as useTypedSearchParams};
1
+ import"../chunk-LKDKVG2S.js";import{j as i,k as m,o as p}from"../chunk-3E7SIS7B.js";import{useCallback as x,useMemo as c}from"react";import{usePathname as P,useRouter as y,useSearchParams as h,useParams as R}from"next/navigation";function Q(e,a={}){let r=P();return c(()=>p(r||"/",e,a),[r,e,a.exact,a.caseSensitive])}function A(){let e=y();return c(()=>{let a=(r,t)=>{let s=t?.scroll!==void 0?{scroll:t.scroll}:void 0;t?.replace?e.replace(r,s):e.push(r,s)};return a.prefetch=(r,t)=>{e.prefetch(r,t)},a},[e])}function N(e){return R()||{}}function S(e){let a=h(),r=y(),t=P(),s=c(()=>m(a?"?"+a.toString():"",e),[a,e]),d=x((f,o)=>{let n=i("",f),g=n.startsWith("?")?"":n?"?":"",u=`${t}${g}${n}`,l=o?.scroll!==void 0?{scroll:o.scroll}:void 0;o?.replace?r.replace(u,l):r.push(u,l)},[r,t]);return[s,d]}export{Q as useActivePath,A as useNavigateTo,N as useRouteParams,S as useTypedSearchParams};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/index.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n usePathname,\n useRouter,\n useSearchParams,\n useParams,\n} from \"next/navigation\";\nimport { isActivePath, extractQueryFromPath } from \"../index\";\nimport type { QueryParams, ExtractParams } from \"../types\";\n\n/**\n * Checks if the current path matches the given template.\n */\nexport function useActivePath(\n template: string,\n options: { exact?: boolean; caseSensitive?: boolean } = {},\n): boolean {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"useActivePath can only be used in browser environment. \" +\n \"Call this hook only in client components.\",\n );\n }\n const pathname = usePathname();\n return useMemo(\n () => isActivePath(pathname || \"/\", template, options),\n [pathname, template, options.exact, options.caseSensitive],\n );\n}\n\nexport type NavigateOptions = {\n replace?: boolean;\n scroll?: boolean;\n};\n\n/**\n * Returns a function to navigate to a new path.\n */\nexport function useNavigateTo() {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"useNavigateTo can only be used in browser environment. \" +\n \"Call this hook only in client components.\",\n );\n }\n const router = useRouter();\n\n return useCallback(\n (path: string, options?: NavigateOptions) => {\n const navOpts = options?.scroll !== undefined ? { scroll: options.scroll } : undefined;\n if (options?.replace) {\n router.replace(path, navOpts);\n } else {\n router.push(path, navOpts);\n }\n },\n [router],\n );\n}\n\n/**\n * Extracts route parameters. Optionally strongly typed.\n */\nexport function useRouteParams<T extends string = string>(): Record<\n ExtractParams<T>,\n string\n>;\nexport function useRouteParams<P extends string>(route: {\n readonly paramNames: ReadonlyArray<P> | Array<P>;\n}): Record<P, string>;\nexport function useRouteParams<P extends string>(_route?: {\n readonly paramNames: ReadonlyArray<P> | Array<P>;\n}): Record<string, string> {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"useRouteParams can only be used in browser environment. \" +\n \"Call this hook only in client components.\",\n );\n }\n return (useParams() as Record<string, string>) || {};\n}\n\n/**\n * Typed search params hook.\n */\nexport function useTypedSearchParams(options?: {\n coerceBooleans?: boolean;\n coerceNumbers?: boolean;\n}) {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"useTypedSearchParams can only be used in browser environment. \" +\n \"Call this hook only in client components.\",\n );\n }\n const searchParams = useSearchParams();\n const router = useRouter();\n const pathname = usePathname();\n\n const queryParams = useMemo(\n () =>\n extractQueryFromPath(\n searchParams ? \"?\" + searchParams.toString() : \"\",\n options,\n ),\n [searchParams, options],\n );\n\n const setTypedQuery = useCallback(\n (\n newQuery: QueryParams,\n navigateOptions?: { replace?: boolean; scroll?: boolean },\n ) => {\n const sp = new URLSearchParams();\n Object.entries(newQuery).forEach(([key, value]) => {\n if (!Object.prototype.hasOwnProperty.call(newQuery, key)) return;\n if (value === undefined || value === null) return;\n\n if (Array.isArray(value)) {\n value.forEach((v) => {\n if (v !== undefined && v !== null) {\n sp.append(key, String(v));\n }\n });\n } else {\n sp.append(key, String(value));\n }\n });\n\n const queryString = sp.toString();\n const prefix = queryString ? \"?\" : \"\";\n\n const newPath = `${pathname}${prefix}${queryString}`;\n const navOpts = navigateOptions?.scroll !== undefined ? { scroll: navigateOptions.scroll } : undefined;\n if (navigateOptions?.replace) {\n router.replace(newPath, navOpts);\n } else {\n router.push(newPath, navOpts);\n }\n },\n [router, pathname],\n );\n\n return [queryParams, setTypedQuery] as const;\n}\n"],"mappings":"6EAAA,OAAS,eAAAA,EAAa,WAAAC,MAAe,QACrC,OACE,eAAAC,EACA,aAAAC,EACA,mBAAAC,EACA,aAAAC,MACK,kBAOA,SAASC,EACdC,EACAC,EAAwD,CAAC,EAChD,CACT,GAAI,OAAO,OAAW,IACpB,MAAM,IAAI,MACR,kGAEF,EAEF,IAAMC,EAAWC,EAAY,EAC7B,OAAOC,EACL,IAAMC,EAAaH,GAAY,IAAKF,EAAUC,CAAO,EACrD,CAACC,EAAUF,EAAUC,EAAQ,MAAOA,EAAQ,aAAa,CAC3D,CACF,CAUO,SAASK,GAAgB,CAC9B,GAAI,OAAO,OAAW,IACpB,MAAM,IAAI,MACR,kGAEF,EAEF,IAAMC,EAASC,EAAU,EAEzB,OAAOC,EACL,CAACC,EAAcT,IAA8B,CAC3C,IAAMU,EAAUV,GAAS,SAAW,OAAY,CAAE,OAAQA,EAAQ,MAAO,EAAI,OACzEA,GAAS,QACXM,EAAO,QAAQG,EAAMC,CAAO,EAE5BJ,EAAO,KAAKG,EAAMC,CAAO,CAE7B,EACA,CAACJ,CAAM,CACT,CACF,CAYO,SAASK,EAAiCC,EAEtB,CACzB,GAAI,OAAO,OAAW,IACpB,MAAM,IAAI,MACR,mGAEF,EAEF,OAAQC,EAAU,GAAgC,CAAC,CACrD,CAKO,SAASC,EAAqBd,EAGlC,CACD,GAAI,OAAO,OAAW,IACpB,MAAM,IAAI,MACR,yGAEF,EAEF,IAAMe,EAAeC,EAAgB,EAC/BV,EAASC,EAAU,EACnBN,EAAWC,EAAY,EAEvBe,EAAcd,EAClB,IACEe,EACEH,EAAe,IAAMA,EAAa,SAAS,EAAI,GAC/Cf,CACF,EACF,CAACe,EAAcf,CAAO,CACxB,EAEMmB,EAAgBX,EACpB,CACEY,EACAC,IACG,CACH,IAAMC,EAAK,IAAI,gBACf,OAAO,QAAQF,CAAQ,EAAE,QAAQ,CAAC,CAACG,EAAKC,CAAK,IAAM,CAC5C,OAAO,UAAU,eAAe,KAAKJ,EAAUG,CAAG,GAC5BC,GAAU,OAEjC,MAAM,QAAQA,CAAK,EACrBA,EAAM,QAASC,GAAM,CACIA,GAAM,MAC3BH,EAAG,OAAOC,EAAK,OAAOE,CAAC,CAAC,CAE5B,CAAC,EAEDH,EAAG,OAAOC,EAAK,OAAOC,CAAK,CAAC,EAEhC,CAAC,EAED,IAAME,EAAcJ,EAAG,SAAS,EAG1BK,EAAU,GAAG1B,CAAQ,GAFZyB,EAAc,IAAM,EAEC,GAAGA,CAAW,GAC5ChB,EAAUW,GAAiB,SAAW,OAAY,CAAE,OAAQA,EAAgB,MAAO,EAAI,OACzFA,GAAiB,QACnBf,EAAO,QAAQqB,EAASjB,CAAO,EAE/BJ,EAAO,KAAKqB,EAASjB,CAAO,CAEhC,EACA,CAACJ,EAAQL,CAAQ,CACnB,EAEA,MAAO,CAACgB,EAAaE,CAAa,CACpC","names":["useCallback","useMemo","usePathname","useRouter","useSearchParams","useParams","useActivePath","template","options","pathname","usePathname","useMemo","isActivePath","useNavigateTo","router","useRouter","useCallback","path","navOpts","useRouteParams","_route","useParams","useTypedSearchParams","searchParams","useSearchParams","queryParams","extractQueryFromPath","setTypedQuery","newQuery","navigateOptions","sp","key","value","v","queryString","newPath"]}
1
+ {"version":3,"sources":["../../src/next/index.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n usePathname,\n useRouter,\n useSearchParams,\n useParams,\n} from \"next/navigation\";\nimport { isActivePath, extractQueryFromPath, appendQuery } from \"../index\";\nimport type { QueryParams, ExtractParams } from \"../types\";\n\n/**\n * Checks if the current path matches the given template.\n */\nexport function useActivePath(\n template: string,\n options: { exact?: boolean; caseSensitive?: boolean } = {},\n): boolean {\n\n const pathname = usePathname();\n return useMemo(\n () => isActivePath(pathname || \"/\", template, options),\n [pathname, template, options.exact, options.caseSensitive],\n );\n}\n\nexport type NavigateOptions = {\n replace?: boolean;\n scroll?: boolean;\n};\n\n/**\n * Returns a function to navigate to a new path.\n */\nexport function useNavigateTo() {\n const router = useRouter();\n\n return useMemo(() => {\n const navigateTo = (path: string, options?: NavigateOptions) => {\n const navOpts = options?.scroll !== undefined ? { scroll: options.scroll } : undefined;\n if (options?.replace) {\n router.replace(path, navOpts);\n } else {\n router.push(path, navOpts);\n }\n };\n \n navigateTo.prefetch = (\n path: string,\n options?: Parameters<ReturnType<typeof useRouter>[\"prefetch\"]>[1]\n ) => {\n router.prefetch(path, options);\n };\n\n return navigateTo;\n }, [router]);\n}\n\n/**\n * Extracts route parameters. Optionally strongly typed.\n */\nexport function useRouteParams<T extends string = string>(): Record<\n ExtractParams<T>,\n string\n>;\nexport function useRouteParams<P extends string>(route: {\n readonly paramNames: ReadonlyArray<P> | Array<P>;\n}): Record<P, string>;\nexport function useRouteParams<P extends string>(_route?: {\n readonly paramNames: ReadonlyArray<P> | Array<P>;\n}): Record<string, string> {\n\n return (useParams() as Record<string, string>) || {};\n}\n\n/**\n * Typed search params hook.\n */\nexport function useTypedSearchParams<T extends QueryParams = QueryParams>(options?: {\n coerceBooleans?: boolean;\n coerceNumbers?: boolean;\n}) {\n\n const searchParams = useSearchParams();\n const router = useRouter();\n const pathname = usePathname();\n\n const queryParams = useMemo(\n () =>\n extractQueryFromPath(\n searchParams ? \"?\" + searchParams.toString() : \"\",\n options,\n ) as T,\n [searchParams, options],\n );\n\n const setTypedQuery = useCallback(\n (\n newQuery: Partial<T> | QueryParams,\n navigateOptions?: { replace?: boolean; scroll?: boolean },\n ) => {\n const queryString = appendQuery(\"\", newQuery as QueryParams);\n const prefix = queryString.startsWith(\"?\") ? \"\" : (queryString ? \"?\" : \"\");\n \n const newPath = `${pathname}${prefix}${queryString}`;\n const navOpts = navigateOptions?.scroll !== undefined ? { scroll: navigateOptions.scroll } : undefined;\n \n if (navigateOptions?.replace) {\n router.replace(newPath, navOpts);\n } else {\n router.push(newPath, navOpts);\n }\n },\n [router, pathname],\n );\n\n return [queryParams, setTypedQuery] as const;\n}\n"],"mappings":"oFAAA,OAAS,eAAAA,EAAa,WAAAC,MAAe,QACrC,OACE,eAAAC,EACA,aAAAC,EACA,mBAAAC,EACA,aAAAC,MACK,kBAOA,SAASC,EACdC,EACAC,EAAwD,CAAC,EAChD,CAET,IAAMC,EAAWC,EAAY,EAC7B,OAAOC,EACL,IAAMC,EAAaH,GAAY,IAAKF,EAAUC,CAAO,EACrD,CAACC,EAAUF,EAAUC,EAAQ,MAAOA,EAAQ,aAAa,CAC3D,CACF,CAUO,SAASK,GAAgB,CAC9B,IAAMC,EAASC,EAAU,EAEzB,OAAOJ,EAAQ,IAAM,CACnB,IAAMK,EAAa,CAACC,EAAcT,IAA8B,CAC9D,IAAMU,EAAUV,GAAS,SAAW,OAAY,CAAE,OAAQA,EAAQ,MAAO,EAAI,OACzEA,GAAS,QACXM,EAAO,QAAQG,EAAMC,CAAO,EAE5BJ,EAAO,KAAKG,EAAMC,CAAO,CAE7B,EAEA,OAAAF,EAAW,SAAW,CACpBC,EACAT,IACG,CACHM,EAAO,SAASG,EAAMT,CAAO,CAC/B,EAEOQ,CACT,EAAG,CAACF,CAAM,CAAC,CACb,CAYO,SAASK,EAAiCC,EAEtB,CAEzB,OAAQC,EAAU,GAAgC,CAAC,CACrD,CAKO,SAASC,EAA0Dd,EAGvE,CAED,IAAMe,EAAeC,EAAgB,EAC/BV,EAASC,EAAU,EACnBN,EAAWC,EAAY,EAEvBe,EAAcd,EAClB,IACEe,EACEH,EAAe,IAAMA,EAAa,SAAS,EAAI,GAC/Cf,CACF,EACF,CAACe,EAAcf,CAAO,CACxB,EAEMmB,EAAgBC,EACpB,CACEC,EACAC,IACG,CACH,IAAMC,EAAcC,EAAY,GAAIH,CAAuB,EACrDI,EAASF,EAAY,WAAW,GAAG,EAAI,GAAMA,EAAc,IAAM,GAEjEG,EAAU,GAAGzB,CAAQ,GAAGwB,CAAM,GAAGF,CAAW,GAC5Cb,EAAUY,GAAiB,SAAW,OAAY,CAAE,OAAQA,EAAgB,MAAO,EAAI,OAEzFA,GAAiB,QACnBhB,EAAO,QAAQoB,EAAShB,CAAO,EAE/BJ,EAAO,KAAKoB,EAAShB,CAAO,CAEhC,EACA,CAACJ,EAAQL,CAAQ,CACnB,EAEA,MAAO,CAACgB,EAAaE,CAAa,CACpC","names":["useCallback","useMemo","usePathname","useRouter","useSearchParams","useParams","useActivePath","template","options","pathname","usePathname","useMemo","isActivePath","useNavigateTo","router","useRouter","navigateTo","path","navOpts","useRouteParams","_route","useParams","useTypedSearchParams","searchParams","useSearchParams","queryParams","extractQueryFromPath","setTypedQuery","useCallback","newQuery","navigateOptions","queryString","appendQuery","prefix","newPath"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-routes-forge",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Type-safe route definitions, automatic path builders, query parameter handling, and active route matching for React applications with zero duplication.",
5
5
  "type": "module",
6
6
  "author": {
@@ -1,2 +0,0 @@
1
- function C(){return globalThis.process?.env?.NODE_ENV==="production"}function y(e){C()||console.warn(e)}var O=/[.*+?^${}()|[\]\\]/g,d=/(^|\/):([A-Za-z0-9_]+)(\?)?/g;function g(e){return e.replace(O,"\\$&")}function $(e){let t=e.endsWith("/*"),n=t?e.slice(0,-2):e,r="",s=0;for(let i of n.matchAll(d)){let c=i.index??0,u=i[0];r+=g(n.slice(s,c));let[,o="",,l]=i;r+=l?`(?:${g(o)}([^/]+))?`:`${g(o)}([^/]+)`,s=c+(u?.length??0)}return r+g(n.slice(s))+(t?"(?:/(.*))?":"")}function E(e,t){return new RegExp(`:${g(t)}\\?(?![A-Za-z0-9_])`).test(e)}var P=new Map,v=/^/;function b(e){if(e==="/")return v;let t=P.get(e);if(t!==void 0)return t;let n=new RegExp(`^${$(e)}(?=/|$)`);return P.set(e,n),n}function S(e){try{return decodeURIComponent(e)}catch{return e}}var R=new Map;function m(e,t){let n=t?.end??!0,r=t?.caseSensitive?"":"i",s=`${e}:${n}:${r}`,i=R.get(s);if(i!==void 0)return i;let c=$(e),u=n?`^${c}$`:`^${c}(?=/|$)`,o=new RegExp(u,r);return R.set(s,o),o}function T(){P.clear(),R.clear()}function h(e){let t=[...e.matchAll(d)].map(n=>n[2]);return e.endsWith("/*")&&t.push("*"),t}function W(e){return e.search(d)!==-1||e.endsWith("/*")}function j(e){return h(e)}function k(e,t){let n=t.split("?")[0]??"",r=h(e),s=n.match(m(e));if(!s)return{};let i={};return r.forEach((c,u)=>{let o=s[u+1];o!==void 0&&(i[c]=S(o))}),i}function w(e,t,n){let r=e.indexOf("#"),s=r===-1?e:e.slice(0,r),i=r===-1?"":e.slice(r+1),c=new URLSearchParams;if(t)for(let[l,a]of Object.entries(t))Object.prototype.hasOwnProperty.call(t,l)&&a!=null&&(Array.isArray(a)?a.forEach(f=>{f!=null&&c.append(l,String(f))}):c.append(l,String(a)));let u=s,o=c.toString();return o&&(u+=(u.includes("?")?"&":"?")+o),n?u+="#"+encodeURIComponent(n):i&&(u+="#"+i),u}function H(e,t){let n=e.indexOf("#"),r=n===-1?e:e.slice(0,n),s=r.indexOf("?");if(s===-1)return{};let i=new URLSearchParams(r.slice(s+1)),c={};for(let u of new Set(i.keys())){let l=i.getAll(u).map(a=>{if(t?.coerceBooleans){let f=String(a).toLowerCase();if(f==="true"||f==="false")return f==="true"}return t?.coerceNumbers&&a.trim()!==""&&!isNaN(Number(a))?Number(a):a});c[u]=l.length>1?l:l[0]??""}return c}function _(e,t,n,r){let s=h(e),i=s.filter(o=>(t[o]===void 0||t[o]===null)&&!E(e,o)&&o!=="*"),c=s.reduce((o,l)=>{let a=t[l],f=a==null;if(l==="*"){if(f)return o.replace(/\/\*$/,"")||"/";if(typeof a!="string"&&typeof a!="number")throw new TypeError(`Splat parameter must be string or number, got ${typeof a}`);let x=r?.encode===!1?String(a):String(a).split("/").map(p=>encodeURIComponent(p)).join("/");return o.replace(/\/\*$/,`/${x}`)}let A=new RegExp(`(^|/):${g(l)}\\??(?![A-Za-z0-9_])`,"g");return o.replace(A,(x,p)=>{if(f)return x.endsWith("?")?"":`${p}:${l}`;let N=r?.encode===!1?String(a):encodeURIComponent(String(a));return`${p}${N}`})},e);if(i.length>0){if(r?.strict)throw new RangeError(`[route-forge] Missing required param(s) ${i.map(o=>`":${o}"`).join(", ")} in template "${e}".`);y(`[route-forge] Unresolved params in path "${c}". Check that all :param segments have matching keys.`)}let u=r?.locale?Q(r.locale,c):c;return w(u,n,r?.hash)}function G(e,t,n,r){return _(e,t,n,r)}function Q(...e){return"/"+e.map(r=>r.replace(/^\/+/,"").replace(/\/+$/,"")).filter(Boolean).join("/")}function K(e,t,n={}){let r=n.exact??!0,s=n.caseSensitive??!1,i=(e.split("?")[0]??"").replace(/\/+$/,"")||"/",c=t.replace(/\/+$/,"")||"/",u=s?c:c.toLowerCase(),o=s?i:i.toLowerCase();return(r?m(u,{caseSensitive:s}):b(u)).test(o)}export{C as a,y as b,b as c,m as d,T as e,h as f,W as g,j as h,k as i,w as j,H as k,_ as l,G as m,Q as n,K as o};
2
- //# sourceMappingURL=chunk-NX4N6IWV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/environment.ts","../src/core/pattern.ts","../src/core/params.ts","../src/core/query.ts","../src/core/build.ts","../src/core/match.ts"],"sourcesContent":["/**\n * Returns `true` when running in a production bundle (suppresses dev warnings).\n */\nexport function isProduction(): boolean {\n const runtimeProcess = (\n globalThis as typeof globalThis & {\n process?: { env?: Record<string, string | undefined> };\n }\n ).process;\n return runtimeProcess?.env?.NODE_ENV === \"production\";\n}\n\n/**\n * Emits a `console.warn` in non-production environments.\n * Shared by the core utilities and `defineRoutes()` so the production check\n * lives in one place.\n */\nexport function devWarn(message: string): void {\n if (!isProduction()) {\n console.warn(message);\n }\n}\n","/** Global RegExp instances — safe since String.prototype.replace/matchAll don't bleed lastIndex. */\nconst ESCAPE_RE = /[.*+?^${}()|[\\]\\\\]/g;\n\n/**\n * Matches a `:param` token that starts a URL segment.\n *\n * A param is only recognized when its `:` sits at the very start of the\n * template or is immediately preceded by `/`, so a literal colon inside a\n * segment (e.g. `/users/foo:bar`) is not treated as a param. Param names are\n * restricted to `[A-Za-z0-9_]` (matching React Router), so any static suffix\n * (e.g. `.json` in `/files/:name.json`) stays a literal. The optional `?`\n * marker (`:param?`) is captured separately so it can be handled as a\n * whole-segment modifier.\n */\nexport const PARAM_SEGMENT_RE = /(^|\\/):([A-Za-z0-9_]+)(\\?)?/g;\n\nexport function escapeRegex(value: string): string {\n return value.replace(ESCAPE_RE, \"\\\\$&\");\n}\n\n/**\n * Convert a route template into an unanchored `RegExp` source string.\n *\n * - Required `:name` segments become a capturing group `([^/]+)`.\n * - Optional `:name?` segments become `(?:([^/]+))?` — the whole segment is\n * optional, matching React Router semantics.\n * - A trailing splat (`/*`) becomes `(?:/(.*))?`, capturing the remainder of\n * the path (including slashes) or nothing at all.\n * - Everything else is regex-escaped literally.\n */\nfunction createTemplatePattern(template: string): string {\n const splat = template.endsWith(\"/*\");\n const base = splat ? template.slice(0, -2) : template;\n let pattern = \"\";\n let cursor = 0;\n\n for (const match of base.matchAll(PARAM_SEGMENT_RE)) {\n const start = match.index ?? 0;\n const token = match[0];\n\n pattern += escapeRegex(base.slice(cursor, start));\n\n const [, boundary = \"\", , optional] = match;\n pattern += optional\n ? `(?:${escapeRegex(boundary)}([^/]+))?`\n : `${escapeRegex(boundary)}([^/]+)`;\n\n cursor = start + (token?.length ?? 0);\n }\n\n return (\n pattern + escapeRegex(base.slice(cursor)) + (splat ? \"(?:/(.*))?\" : \"\")\n );\n}\n\n/** Returns `true` when `name` is an optional (`:name?`) param in `template`. */\nexport function isOptionalParam(template: string, name: string): boolean {\n return new RegExp(`:${escapeRegex(name)}\\\\?(?![A-Za-z0-9_])`).test(template);\n}\n\n/**\n * Returns a `RegExp` that matches `template` as a path prefix, honoring\n * segment boundaries (`/users` matches `/users/42` but not `/usersettings`).\n *\n * The root template `/` is a prefix of every path.\n *\n * Compiled patterns are cached per template: the resulting `RegExp` has no\n * `/g` flag, so repeated `.test()`/`.exec()` calls are side-effect free and\n * sharing instances across callers is safe.\n */\nconst PREFIX_CACHE = new Map<string, RegExp>();\nconst ROOT_PREFIX_RE = /^/;\n\nexport function matchPrefix(template: string): RegExp {\n if (template === \"/\") return ROOT_PREFIX_RE;\n const cached = PREFIX_CACHE.get(template);\n if (cached !== undefined) return cached;\n const re = new RegExp(`^${createTemplatePattern(template)}(?=/|$)`);\n PREFIX_CACHE.set(template, re);\n return re;\n}\n\n/** Decode a URL-encoded param value, falling back to the raw value on error. */\nexport function safeDecode(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\n/**\n * Convert a route template string into an anchored `RegExp` for matching paths.\n *\n * Each `:param` segment becomes a capturing group so the returned regex\n * can be used with `.test()` or `.exec()`.\n *\n * Query strings are **not** stripped — callers should split on `\"?\"` first\n * (see {@link isActivePath} or {@link extractParamsFromPath} for higher-level\n * helpers that handle this automatically).\n *\n * @param template - A route template, e.g. `\"/users/:id\"` or `\"/users/:id/posts/:postId\"`.\n * @returns A `RegExp` anchored with `^` and `$` that captures param values.\n *\n * @example\n * ```ts\n * const re = matchPath(\"/users/:id\");\n * re.test(\"/users/42\"); // true\n * re.exec(\"/users/42\"); // [\"/users/42\", \"42\"]\n * re.test(\"/users/42/posts\"); // false (exact match)\n * re.test(\"/users/42?page=1\"); // true (query is part of captured value)\n * ```\n *\n * Compiled patterns are cached per template (the regex has no `/g` flag, so\n * sharing instances across callers is safe).\n */\nconst PATH_CACHE = new Map<string, RegExp>();\n\nexport function matchPath(\n template: string,\n options?: { end?: boolean; caseSensitive?: boolean },\n): RegExp {\n const end = options?.end ?? true;\n const flags = options?.caseSensitive ? \"\" : \"i\";\n const cacheKey = `${template}:${end}:${flags}`;\n\n const cached = PATH_CACHE.get(cacheKey);\n if (cached !== undefined) return cached;\n\n const basePattern = createTemplatePattern(template);\n const pattern = end ? `^${basePattern}$` : `^${basePattern}(?=/|$)`;\n const re = new RegExp(pattern, flags);\n PATH_CACHE.set(cacheKey, re);\n return re;\n}\n\n/**\n * Clears internal regex cache maps (PREFIX_CACHE and PATH_CACHE).\n * Useful in test suites to prevent cached patterns from leaking across test cases.\n */\nexport function clearPathCache(): void {\n PREFIX_CACHE.clear();\n PATH_CACHE.clear();\n}\n","import { PARAM_SEGMENT_RE, matchPath, safeDecode } from \"./pattern\";\n\n/**\n * Extract the `:param` names from a route template.\n *\n * A param is only recognized at the start of a segment (see\n * {@link PARAM_SEGMENT_RE}), so literal colons (`/users/foo:bar`) and static\n * suffixes after a param (`/files/:name.json`) are not treated as params.\n * A trailing splat (`/*`) is reported as the `\"*\"` name.\n */\nexport function extractParamNames(template: string): string[] {\n const names = [...template.matchAll(PARAM_SEGMENT_RE)].map(\n (match) => match[2] as string,\n );\n if (template.endsWith(\"/*\")) names.push(\"*\");\n return names;\n}\n\n/** Returns `true` when the template contains a `:param` or trailing `/*` splat. */\nexport function isDynamic(path: string): boolean {\n return path.search(PARAM_SEGMENT_RE) !== -1 || path.endsWith(\"/*\");\n}\n\n/**\n * Alias of {@link extractParamNames} — kept for backwards compatibility.\n */\nexport function getParamNames(template: string): string[] {\n return extractParamNames(template);\n}\n\n/**\n * Extract the param values matched by `template` from a resolved path.\n *\n * The query string is stripped before matching, so `/users/42?tab=profile`\n * still yields `{ id: \"42\" }`. Values are URL-decoded back to their original\n * form; a non-matching path yields an empty object.\n */\nexport function extractParamsFromPath(\n template: string,\n resolvedPath: string,\n): Record<string, string> {\n const pathWithoutSearch = resolvedPath.split(\"?\")[0] ?? \"\";\n const paramNames = extractParamNames(template);\n const match = pathWithoutSearch.match(matchPath(template));\n\n if (!match) return {};\n\n const result: Record<string, string> = {};\n paramNames.forEach((name, index) => {\n const raw = match[index + 1];\n if (raw !== undefined) result[name] = safeDecode(raw);\n });\n return result;\n}\n","import type { QueryParams } from \"../types\";\n\n/**\n * Append a query string and/or hash fragment to a path that may already\n * contain a query or hash.\n *\n * - Existing query pairs are preserved; new ones are joined with `&`.\n * - The query string is always inserted before any hash fragment, so an\n * existing `#section` on `path` is kept unless a new `hash` is given.\n *\n * @example\n * ```ts\n * appendQuery(\"/users?tab=list\", { page: 2 }); // → \"/users?tab=list&page=2\"\n * appendQuery(\"/users#top\", { tab: \"list\" }); // → \"/users?tab=list#top\"\n * ```\n */\nexport function appendQuery(\n path: string,\n query?: QueryParams,\n hash?: string,\n): string {\n const hashIdx = path.indexOf(\"#\");\n const base = hashIdx === -1 ? path : path.slice(0, hashIdx);\n const existingHash = hashIdx === -1 ? \"\" : path.slice(hashIdx + 1);\n\n const searchParams = new URLSearchParams();\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (!Object.prototype.hasOwnProperty.call(query, key)) continue;\n if (value === undefined || value === null) continue;\n if (Array.isArray(value)) {\n value.forEach((v) => {\n if (v !== undefined && v !== null)\n searchParams.append(key, String(v));\n });\n } else {\n searchParams.append(key, String(value));\n }\n }\n }\n\n let result = base;\n const queryString = searchParams.toString();\n if (queryString) {\n result += (result.includes(\"?\") ? \"&\" : \"?\") + queryString;\n }\n\n if (hash) {\n result += \"#\" + encodeURIComponent(hash);\n } else if (existingHash) {\n result += \"#\" + existingHash;\n }\n\n return result;\n}\n\n/**\n * Parse the query string out of a path (or bare query string) into a plain\n * object. Repeated keys become arrays; a single key is a scalar string.\n *\n * With `{ coerceBooleans: true }`, the strings `\"true\"`/`\"false\"` are\n * converted to actual booleans.\n *\n * @example\n * ```ts\n * extractQueryFromPath(\"/users/42?tab=profile&tag=a&tag=b\");\n * // → { tab: \"profile\", tag: [\"a\", \"b\"] }\n * extractQueryFromPath(\"/search?active=true\", { coerceBooleans: true });\n * // → { active: true }\n * ```\n */\nexport function extractQueryFromPath(\n path: string,\n options?: { coerceBooleans?: boolean; coerceNumbers?: boolean },\n): QueryParams {\n const hashIdx = path.indexOf(\"#\");\n const noHash = hashIdx === -1 ? path : path.slice(0, hashIdx);\n const queryIdx = noHash.indexOf(\"?\");\n if (queryIdx === -1) return {};\n\n const params = new URLSearchParams(noHash.slice(queryIdx + 1));\n const result: QueryParams = {};\n\n for (const key of new Set(params.keys())) {\n const values = params.getAll(key);\n const parsed = values.map((v) => {\n if (options?.coerceBooleans) {\n const lower = String(v).toLowerCase();\n if (lower === \"true\" || lower === \"false\") {\n return lower === \"true\";\n }\n }\n if (options?.coerceNumbers && v.trim() !== \"\" && !isNaN(Number(v))) {\n return Number(v);\n }\n return v;\n });\n result[key] = parsed.length > 1 ? parsed : (parsed[0] ?? \"\");\n }\n\n return result;\n}\n","import { escapeRegex, isOptionalParam } from \"./pattern\";\nimport { extractParamNames } from \"./params\";\nimport { appendQuery } from \"./query\";\nimport { devWarn } from \"./environment\";\nimport type { BuildPathOptions, QueryParams, RouteParams } from \"../types\";\n\n/**\n * Resolve a route template against a params object, appending an optional\n * query string and hash fragment.\n *\n * Missing required params are left as their `:name` placeholder and a\n * `console.warn` is emitted — pass `{ strict: true }` to throw a `RangeError`\n * instead. Optional (`:param?`) segments are dropped entirely when missing;\n * a missing splat just drops the trailing `/*`. Values are URL-encoded by\n * default (`{ encode: false }` opts out).\n */\nexport function buildPath(\n template: string,\n params: RouteParams,\n query?: QueryParams,\n options?: BuildPathOptions,\n): string {\n const paramNames = extractParamNames(template);\n const unresolved = paramNames.filter(\n (name) =>\n (params[name] === undefined || params[name] === null) &&\n !isOptionalParam(template, name) &&\n // A missing splat simply drops the `/*` suffix (matching React Router,\n // where `/files/*` also matches `/files`).\n name !== \"*\",\n );\n\n const resolved = paramNames.reduce((path, name) => {\n const value = params[name];\n const missing = value === undefined || value === null;\n\n if (name === \"*\") {\n if (missing) return path.replace(/\\/\\*$/, \"\") || \"/\";\n\n if (typeof value !== 'string' && typeof value !== 'number') {\n throw new TypeError(\n `Splat parameter must be string or number, got ${typeof value}`\n );\n }\n\n // Splat values are path-like: preserve `/` separators but still\n // encode characters that could break the URL (`?`, `#`, spaces, …).\n const encoded =\n options?.encode === false\n ? String(value)\n : String(value)\n .split(\"/\")\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n return path.replace(/\\/\\*$/, `/${encoded}`);\n }\n\n const re = new RegExp(\n `(^|/):${escapeRegex(name)}\\\\??(?![A-Za-z0-9_])`,\n \"g\",\n );\n\n return path.replace(re, (match, boundary) => {\n if (missing) {\n // Optional segment: drop the whole `/segment`. Required: keep the\n // `:name` placeholder so strict mode can report it.\n return match.endsWith(\"?\") ? \"\" : `${boundary}:${name}`;\n }\n\n const encoded =\n options?.encode === false\n ? String(value)\n : encodeURIComponent(String(value));\n return `${boundary}${encoded}`;\n });\n }, template);\n\n if (unresolved.length > 0) {\n if (options?.strict) {\n throw new RangeError(\n `[route-forge] Missing required param(s) ${unresolved.map((p) => `\":${p}\"`).join(\", \")} in template \"${template}\".`,\n );\n }\n\n devWarn(\n `[route-forge] Unresolved params in path \"${resolved}\". ` +\n `Check that all :param segments have matching keys.`,\n );\n }\n\n const finalPath = options?.locale\n ? joinPaths(options.locale, resolved)\n : resolved;\n\n return appendQuery(finalPath, query, options?.hash);\n}\n\n/**\n * Standalone alias of {@link buildPath} — resolves a template against params.\n */\nexport function build(\n template: string,\n params: RouteParams,\n query?: QueryParams,\n options?: BuildPathOptions,\n): string {\n return buildPath(template, params, query, options);\n}\n\n/**\n * Join URL path segments into a single slash-prefixed path, normalising\n * duplicate slashes.\n *\n * @example\n * joinPaths(\"/api/\", \"/v1/\", \"users\"); // → \"/api/v1/users\"\n */\nexport function joinPaths(...segments: string[]): string {\n const processed = segments.map((segment) =>\n segment.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\"),\n );\n const filtered = processed.filter(Boolean);\n return \"/\" + filtered.join(\"/\");\n}\n","import { matchPath, matchPrefix } from \"./pattern\";\n\n/**\n * Test whether `currentPath` matches `template`, mirroring React Router's\n * `NavLink` matching semantics:\n *\n * - Case-insensitive by default (pass `caseSensitive: true` to opt out).\n * - Trailing slashes are tolerated (`/users/` matches `/users`).\n * - `exact: true` (the default) requires a full match; `exact: false`\n * matches any path that starts with the template.\n */\nexport function isActivePath(\n currentPath: string,\n template: string,\n options: { exact?: boolean; caseSensitive?: boolean } = {},\n): boolean {\n // NOTE: default each property individually rather than relying on a\n // default *object* for `options` — JS default parameters only apply when\n // the whole argument is omitted, so `isActivePath(a, b, { caseSensitive: true })`\n // would otherwise silently lose the documented `exact: true` default.\n const exact = options.exact ?? true;\n const caseSensitive = options.caseSensitive ?? false;\n\n const pathname = (currentPath.split(\"?\")[0] ?? \"\").replace(/\\/+$/, \"\") || \"/\";\n const normalizedTemplate = template.replace(/\\/+$/, \"\") || \"/\";\n const target = caseSensitive\n ? normalizedTemplate\n : normalizedTemplate.toLowerCase();\n const candidate = caseSensitive ? pathname : pathname.toLowerCase();\n const regex = exact\n ? matchPath(target, { caseSensitive })\n : matchPrefix(target);\n\n return regex.test(candidate);\n}\n"],"mappings":"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","names":["isProduction","devWarn","message","ESCAPE_RE","PARAM_SEGMENT_RE","escapeRegex","value","createTemplatePattern","template","splat","base","pattern","cursor","match","start","token","boundary","optional","isOptionalParam","name","PREFIX_CACHE","ROOT_PREFIX_RE","matchPrefix","cached","re","safeDecode","PATH_CACHE","matchPath","options","end","flags","cacheKey","basePattern","clearPathCache","extractParamNames","template","names","PARAM_SEGMENT_RE","match","isDynamic","path","getParamNames","extractParamsFromPath","resolvedPath","pathWithoutSearch","paramNames","matchPath","result","name","index","raw","safeDecode","appendQuery","path","query","hash","hashIdx","base","existingHash","searchParams","key","value","v","result","queryString","extractQueryFromPath","options","noHash","queryIdx","params","parsed","lower","buildPath","template","params","query","options","paramNames","extractParamNames","unresolved","name","isOptionalParam","resolved","path","value","missing","encoded","segment","re","escapeRegex","match","boundary","p","devWarn","finalPath","joinPaths","appendQuery","build","segments","isActivePath","currentPath","template","options","exact","caseSensitive","pathname","normalizedTemplate","target","candidate","matchPath","matchPrefix"]}