what-router 0.12.4 → 0.13.1

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/dist/index.min.js CHANGED
@@ -1,4 +1,4 @@
1
- import{signal as R,effect as $,computed as b,batch as M,h as c,ErrorBoundary as X}from"what-core";function O(e){let n=e.replace(/\([\w-]+\)\//g,"").replace(/\[\.\.\.(\w+)\]/g,(i,l)=>`*:${l}`).replace(/\[(\w+)\]/g,":$1"),t=[],r=null,o=n.split("/").map(i=>i.startsWith("*:")?(r=i.slice(2),t.push(r),"(.+)"):i==="*"?(r="rest",t.push("rest"),"(.+)"):i.startsWith(":")?(t.push(i.slice(1)),"([^/]+)"):i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("/");return{regex:new RegExp(`^${o}$`),paramNames:t,catchAll:r}}var S=new Map,z=1e3;function H(e){let n=S.get(e);return n||(n=O(e),S.size>=z&&S.clear(),S.set(e,n)),n}function K(e,n){let t;try{t=decodeURIComponent(e)}catch{return null}let r=t.split(/[/\\]/);return!n&&r.length>1||r.includes("..")?null:t}function _(e,n){let t=n.filter(r=>r.path);t.sort((r,o)=>{let a=(r.path.match(/:/g)||[]).length+(r.path.includes("*")?100:0),i=(o.path.match(/:/g)||[]).length+(o.path.includes("*")?100:0);return a-i});for(let r of t){let{regex:o,paramNames:a,catchAll:i}=H(r.path),l=e.match(o);if(l){let p={},u=!1;if(a.forEach((s,d)=>{let m=K(l[d+1],s===i);if(m===null){u=!0;return}p[s]=m}),u)continue;return{route:r,params:p}}}return null}function A(e){let n=Object.create(null);if(!e)return n;let t=e.startsWith("?")?e.slice(1):e;for(let r of t.split("&")){let[o,a]=r.split("=");if(!o)continue;let i=decodeURIComponent(o),l=a?decodeURIComponent(a):"";Object.prototype.hasOwnProperty.call(n,i)?Array.isArray(n[i])?n[i].push(l):n[i]=[n[i],l]:n[i]=l}return n}var Q=new Set(["http:","https:","mailto:","tel:"]);function C(e){if(typeof e!="string")return!1;let t=e.trim().replace(/[\s\x00-\x1f]/g,"").toLowerCase();if(t.startsWith("javascript:")||t.startsWith("data:")||t.startsWith("vbscript:")||/^[/\\]{2}/.test(t))return!1;let r=t.match(/^([a-z][a-z0-9+.-]*:)/);return r?Q.has(r[1]):!t.includes("\\")}var h=R(typeof location<"u"?location.pathname+location.search+location.hash:"/"),G=R({}),F=R({}),y=R(!1),x=R(null),B=R(null),g={get url(){return h()},get path(){return h().split("?")[0].split("#")[0]},get params(){return G()},get query(){return F()},get hash(){let e=h().split("#")[1];return e?"#"+e:""},get isNavigating(){return y()},get error(){return B()}},T=[],q=[];function D(e,n){return e.push(n),()=>{let t=e.indexOf(n);t!==-1&&e.splice(t,1)}}function le(e){return D(T,e)}function fe(e){return D(q,e)}async function v(e,n={}){let{replace:t=!1,state:r=null,transition:o=!0,_fromPopstate:a=!1,_redirectChain:i=!1}=n;if(i||(w.length=0),!C(e)){typeof console<"u"&&console.warn("[what-router] Blocked navigation to unsafe URL:",e);return}if(typeof window<"u"&&e.startsWith("#")){let d=h().split("#")[0]+e;history.replaceState(r,"",d),h.set(d);let m=document.querySelector(e);m&&m.scrollIntoView({behavior:"smooth"});return}if(e===h()||y.peek())return;y.set(!0),x.set(e);let l=h();if(T.length){let u=!1;try{for(let s of T.slice())if(await s(e,l)===!1){u=!0;break}}catch(s){throw y.set(!1),x.set(null),s}if(u){y.set(!1),x.set(null),a&&typeof history<"u"&&history.pushState(null,"",l);return}}B.set(null);let p=()=>{a||(typeof window<"u"&&k.set(h(),{x:window.scrollX,y:window.scrollY}),t?history.replaceState(r,"",e):history.pushState(r,"",e)),h.set(e),y.set(!1),x.set(null)};if(o&&typeof document<"u"&&document.startViewTransition)try{let u=document.startViewTransition(p);u.ready&&typeof u.ready.catch=="function"&&u.ready.catch(()=>{}),await u.finished}catch{}else p();if(q.length)for(let u of q.slice())u(e,l)}var V=Symbol.for("what.router.redirect"),Y=Symbol.for("what.navigation.signal");function de(e,n={}){if(!C(e)){let r=typeof e=="string"?e:Object.prototype.toString.call(e),o=new Error(`[what-router] redirect() refused an unsafe target: ${r}`);throw o.code="ERR_UNSAFE_REDIRECT",o.suggestion='redirect() accepts same-origin paths and http:, https:, mailto: or tel: URLs only. Protocol-relative ("//host"), backslash-smuggled and javascript:/data: targets are open-redirect vectors. Check a user-supplied target against an allowlist first.',o.codeExample=`// Bad - a user-controlled target can leave your origin:
1
+ import{signal as R,effect as $,computed as b,batch as M,h as c,ErrorBoundary as X}from"what-core";function O(e){let n=e.replace(/\([\w-]+\)\//g,"").replace(/\[\.\.\.(\w+)\]/g,(i,u)=>`*:${u}`).replace(/\[(\w+)\]/g,":$1"),t=[],r=null,o=n.split("/").map(i=>i.startsWith("*:")?(r=i.slice(2),t.push(r),"(.+)"):i==="*"?(r="rest",t.push("rest"),"(.+)"):i.startsWith(":")?(t.push(i.slice(1)),"([^/]+)"):i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("/");return{regex:new RegExp(`^${o}$`),paramNames:t,catchAll:r}}var S=new Map,z=1e3;function H(e){let n=S.get(e);return n||(n=O(e),S.size>=z&&S.clear(),S.set(e,n)),n}function K(e,n){let t;try{t=decodeURIComponent(e)}catch{return null}let r=t.split(/[/\\]/);return!n&&r.length>1||r.includes("..")?null:t}function _(e,n){let t=n.filter(r=>r.path);t.sort((r,o)=>{let s=(r.path.match(/:/g)||[]).length+(r.path.includes("*")?100:0),i=(o.path.match(/:/g)||[]).length+(o.path.includes("*")?100:0);return s-i});for(let r of t){let{regex:o,paramNames:s,catchAll:i}=H(r.path),u=e.match(o);if(u){let p={},l=!1;if(s.forEach((a,d)=>{let m=K(u[d+1],a===i);if(m===null){l=!0;return}p[a]=m}),l)continue;return{route:r,params:p}}}return null}function A(e){let n=Object.create(null);if(!e)return n;let t=e.startsWith("?")?e.slice(1):e;for(let r of t.split("&")){let[o,s]=r.split("=");if(!o)continue;let i=decodeURIComponent(o),u=s?decodeURIComponent(s):"";Object.prototype.hasOwnProperty.call(n,i)?Array.isArray(n[i])?n[i].push(u):n[i]=[n[i],u]:n[i]=u}return n}var Q=new Set(["http:","https:","mailto:","tel:"]);function C(e){if(typeof e!="string")return!1;let t=e.trim().replace(/[\s\x00-\x1f]/g,"").toLowerCase();if(t.startsWith("javascript:")||t.startsWith("data:")||t.startsWith("vbscript:")||/^[/\\]{2}/.test(t))return!1;let r=t.match(/^([a-z][a-z0-9+.-]*:)/);return r?Q.has(r[1]):!t.includes("\\")}var h=R(typeof location<"u"?location.pathname+location.search+location.hash:"/"),G=R({}),F=R({}),y=R(!1),x=R(null),B=R(null),g={get url(){return h()},get path(){return h().split("?")[0].split("#")[0]},get params(){return G()},get query(){return F()},get hash(){let e=h().split("#")[1];return e?"#"+e:""},get isNavigating(){return y()},get error(){return B()}},q=[],P=[];function D(e,n){return e.push(n),()=>{let t=e.indexOf(n);t!==-1&&e.splice(t,1)}}function ue(e){return D(q,e)}function le(e){return D(P,e)}async function v(e,n={}){let{replace:t=!1,state:r=null,transition:o=!0,_fromPopstate:s=!1,_redirectChain:i=!1}=n;if(i||(w.length=0),!C(e)){typeof console<"u"&&console.warn("[what-router] Blocked navigation to unsafe URL:",e);return}if(typeof window<"u"&&e.startsWith("#")){let d=h().split("#")[0]+e;history.replaceState(r,"",d),h.set(d);let m=document.querySelector(e);m&&m.scrollIntoView({behavior:"smooth"});return}if(e===h()||y.peek())return;y.set(!0),x.set(e);let u=h();if(q.length){let l=!1;try{for(let a of q.slice())if(await a(e,u)===!1){l=!0;break}}catch(a){throw y.set(!1),x.set(null),a}if(l){y.set(!1),x.set(null),s&&typeof history<"u"&&history.pushState(null,"",u);return}}B.set(null);let p=()=>{s||(typeof window<"u"&&k.set(h(),{x:window.scrollX,y:window.scrollY}),t?history.replaceState(r,"",e):history.pushState(r,"",e)),h.set(e),y.set(!1),x.set(null)};if(o&&typeof document<"u"&&document.startViewTransition)try{let l=document.startViewTransition(p);l.ready&&typeof l.ready.catch=="function"&&l.ready.catch(()=>{}),await l.finished}catch{}else p();if(P.length)for(let l of P.slice())l(e,u)}var V=Symbol.for("what.router.redirect"),Y=Symbol.for("what.navigation.signal");function fe(e,n={}){if(!C(e)){let r=typeof e=="string"?e:Object.prototype.toString.call(e),o=new Error(`[what-router] redirect() refused an unsafe target: ${r}`);throw o.code="ERR_UNSAFE_REDIRECT",o.suggestion='redirect() accepts same-origin paths and http:, https:, mailto: or tel: URLs only. Protocol-relative ("//host"), backslash-smuggled and javascript:/data: targets are open-redirect vectors. Check a user-supplied target against an allowlist first.',o.codeExample=`// Bad - a user-controlled target can leave your origin:
2
2
  redirect(query.next);
3
3
 
4
4
  // Good - allowlist the target first:
@@ -12,4 +12,4 @@ redirect(ALLOWED.has(query.next) ? query.next : '/');`,o}let t=new Error(`[what-
12
12
  function Private() {
13
13
  if (!user()) redirect('/login');
14
14
  return <Secret />;
15
- }`,t[V]=!0,t[Y]=()=>{L(e,n)},t.to=e,t.options=n,t}typeof window<"u"&&window.addEventListener("popstate",()=>{k.set(h(),{x:window.scrollX,y:window.scrollY});let e=location.pathname+location.search+location.hash;v(e,{replace:!0,_fromPopstate:!0,transition:!1}).then(()=>{let n=k.get(e);n&&requestAnimationFrame(()=>window.scrollTo(n.x,n.y))})});function J(e,n){let t=[];if(!e.path)return t;let r=e.path.split("/").filter(Boolean),o="";for(let a of r){o+="/"+a;let i=n.find(l=>l.layout&&l.path===o+"/_layout");i&&t.push(i.layout)}return e.layout&&t.push(e.layout),t}var w=[],Z=10;function I(e){return c("div",{class:"what-redirect-loop"},c("h1",null,"Redirect Loop"),c("p",null,e))}function L(e,n){if(x.peek()===e)return null;if(w.push(e),w.length>Z){let o=w.slice(-5).join(" \u2192 ");return w.length=0,console.error(`[what-router] Redirect loop detected: ${o}`),y.set(!1),x.set(null),I("Too many redirects. Check your middleware configuration.")}let t=new Set,r=!1;for(let o of w){if(t.has(o)){r=!0;break}t.add(o)}if(r){let o=w.join(" \u2192 ");return w.length=0,console.error(`[what-router] Redirect cycle detected: ${o}`),y.set(!1),x.set(null),I("Circular redirect detected. Check your middleware configuration.")}return v(e,{replace:!0,...n,_redirectChain:!0}),null}function ee(e,n,t){if(!e)return null;let r=e.split("?")[0].split("#")[0],o=_(r,n);return!o||o.route===t?null:o.route.loading||null}function te({routes:e,fallback:n,globalLayout:t}){let r=()=>{let a=h(),i=a.split("?")[0].split("#")[0],l=a.split("?")[1]?.split("#")[0]||"",p=y(),u=_(i,e);if(u){M(()=>{G.set(u.params),F.set(A(l))});let{route:s,params:d}=u,m=A(l);if(s.middleware&&s.middleware.length>0)for(let N of s.middleware){let P=N({path:i,params:d,query:m,route:s});if(P===!1)return n?c(n,{}):c("div",{class:"what-403"},c("h1",null,"403"),c("p",null,"Access denied"));if(typeof P=="string")return L(P)}let f,E=p?ee(x(),e,s):null;E?f=c(E,{}):s.loading&&p?f=c(s.loading,{}):f=c(s.component,{params:d,query:m,route:s}),s.error&&(f=c(X,{fallback:s.error},f));let j=J(s,e);for(let N of j.reverse())f=c(N,{params:d,query:m},f);return f}return n?c(n,{}):c("div",{class:"what-404"},c("h1",null,"404"),c("p",null,"Page not found"))},o=()=>{let a=null;try{return r()}catch(i){if(!i||!i[V])throw i;a=i}return L(a.to,a.options)};return t?c(t,{},o):o}function ne({href:e,class:n,className:t,children:r,replace:o,prefetch:a=!0,activeClass:i="active",exactActiveClass:l="exact-active",transition:p=!0,...u}){let s=C(e)?e:"about:blank";!C(e)&&typeof console<"u"&&console.warn("[what-router] Link blocked unsafe href:",e);let d=s.split("?")[0].split("#")[0];return c("a",{href:s,class:()=>{let f=g.path,E=d==="/"?f==="/":f===d||f.startsWith(d+"/");return[n||t,E&&i,f===d&&l].filter(Boolean).join(" ")||void 0},onclick:f=>{f.ctrlKey||f.metaKey||f.shiftKey||f.altKey||f.button!==0||(f.preventDefault(),v(s,{replace:o,transition:p}))},onmouseenter:a?()=>U(s):void 0,...u},...Array.isArray(r)?r:[r])}function pe(e){return ne(e)}function he(e){return Object.entries(e).map(([n,t])=>typeof t=="function"?{path:n,component:t}:{path:n,...t})}function re(e,n){let t=e.endsWith("/")?e.slice(0,-1):e,r=!n||n==="/"?"/":n.startsWith("/")?n:`/${n}`;return r==="/"?t||"/":t+r}function me(e,n,t={}){let{layout:r,loading:o,error:a}=t;return n.map(i=>({...i,path:re(e,i.path),layout:i.layout||r,loading:i.loading||o,error:i.error||a}))}function ge(e,n,t={}){let{layout:r,middleware:o}=t;return n.map(a=>({...a,_group:e,layout:a.layout||r,middleware:[...a.middleware||[],...o||[]]}))}function ye({to:e}){return v(e,{replace:!0}),null}function we(e,n){return t=>function(o){let a=e(o);return a instanceof Promise?c("div",{class:"what-guard-loading"},"Loading..."):a?c(t,o):typeof n=="string"?(v(n,{replace:!0}),null):c(n,o)}}function xe(e,n={}){let{fallback:t="/login",loading:r=null}=n;return o=>function(i){let l=R("pending"),p=R(null),u=!1;return $(()=>(u=!1,Promise.resolve(e(i)).then(s=>{u||(p.set(s),l.set(s?"allowed":"denied"))}).catch(()=>{u||l.set("denied")}),()=>{u=!0})),()=>{let s=l();return s==="pending"?r?c(r,{}):null:s==="allowed"?c(o,i):typeof t=="string"?(v(t,{replace:!0}),null):c(t,i)}}}var W=new Set;function U(e){if(typeof document>"u"||W.has(e))return;W.add(e);let n=document.createElement("link");n.rel="prefetch",n.href=e,document.head.appendChild(n)}var k=new Map;function Re(){if(typeof window>"u")return;let e=!0;$(()=>{let n=g.url,t=k.get(n),r=g.hash,o=e;e=!1,requestAnimationFrame(()=>{r?oe(r)?.scrollIntoView():t?window.scrollTo(t.x,t.y):o||window.scrollTo(0,0)})})}function oe(e){try{return document.querySelector(e)}catch{return document.getElementById(e.slice(1))}}function ve(e){return{style:{viewTransitionName:e}}}function be(e){typeof document>"u"||(document.documentElement.dataset.transition=e)}function Ee(){return{path:b(()=>g.path),params:b(()=>g.params),query:b(()=>g.query),hash:b(()=>g.hash),isNavigating:b(()=>g.isNavigating),navigate:v,prefetch:U}}function Se(){return g.params}function _e(){return g.query}function Ae(){return v}function Ce(e){U(e)}function ke({children:e}){return e||null}function Ne({routes:e,layout:n,fallback:t,error:r}){let o=e.map(a=>({path:a.path,component:a.component,layout:a.layout||void 0,loading:a.loading||void 0,error:a.error||r||void 0,_mode:a.mode||"client"}));return te({routes:o,globalLayout:n,fallback:t||ie})}function ie(){return c("div",{style:"text-align:center;padding:60px 20px"},c("h1",{style:"font-size:48px;margin-bottom:8px"},"404"),c("p",{style:"color:#64748b"},"Page not found"))}export{Ne as FileRouter,ne as Link,pe as NavLink,ke as Outlet,ye as Redirect,te as Router,fe as afterNavigate,xe as asyncGuard,le as beforeNavigate,O as compilePath,he as defineRoutes,Re as enableScrollRestoration,we as guard,C as isSafeUrl,_ as matchRoute,v as navigate,me as nestedRoutes,A as parseQuery,U as prefetch,Ce as prefetchRoute,de as redirect,g as route,ge as routeGroup,be as setViewTransition,Ae as useNavigate,Se as useParams,Ee as useRoute,_e as useSearch,ve as viewTransitionName};
15
+ }`,t[V]=!0,t[Y]=()=>{L(e,n)},t.to=e,t.options=n,t}typeof window<"u"&&window.addEventListener("popstate",()=>{k.set(h(),{x:window.scrollX,y:window.scrollY});let e=location.pathname+location.search+location.hash;v(e,{replace:!0,_fromPopstate:!0,transition:!1}).then(()=>{let n=k.get(e);n&&requestAnimationFrame(()=>window.scrollTo(n.x,n.y))})});function J(e,n){let t=[];if(!e.path)return t;let r=e.path.split("/").filter(Boolean),o="";for(let s of r){o+="/"+s;let i=n.find(u=>u.layout&&u.path===o+"/_layout");i&&t.push(i.layout)}return e.layout&&t.push(e.layout),t}var w=[],Z=10;function I(e){return c("div",{class:"what-redirect-loop"},c("h1",null,"Redirect Loop"),c("p",null,e))}function L(e,n){if(x.peek()===e)return null;if(w.push(e),w.length>Z){let o=w.slice(-5).join(" \u2192 ");return w.length=0,console.error(`[what-router] Redirect loop detected: ${o}`),y.set(!1),x.set(null),I("Too many redirects. Check your middleware configuration.")}let t=new Set,r=!1;for(let o of w){if(t.has(o)){r=!0;break}t.add(o)}if(r){let o=w.join(" \u2192 ");return w.length=0,console.error(`[what-router] Redirect cycle detected: ${o}`),y.set(!1),x.set(null),I("Circular redirect detected. Check your middleware configuration.")}return v(e,{replace:!0,...n,_redirectChain:!0}),null}function ee(e,n,t){if(!e)return null;let r=e.split("?")[0].split("#")[0],o=_(r,n);return!o||o.route===t?null:o.route.loading||null}function te({routes:e,fallback:n,globalLayout:t}){let r=()=>{let s=h(),i=s.split("?")[0].split("#")[0],u=s.split("?")[1]?.split("#")[0]||"",p=y(),l=_(i,e);if(l){M(()=>{G.set(l.params),F.set(A(u))});let{route:a,params:d}=l,m=A(u);if(a.middleware&&a.middleware.length>0)for(let N of a.middleware){let T=N({path:i,params:d,query:m,route:a});if(T===!1)return n?c(n,{}):c("div",{class:"what-403"},c("h1",null,"403"),c("p",null,"Access denied"));if(typeof T=="string")return L(T)}let f,E=p?ee(x(),e,a):null;E?f=c(E,{}):a.loading&&p?f=c(a.loading,{}):f=c(a.component,{params:d,query:m,route:a}),a.error&&(f=c(X,{fallback:a.error},f));let j=J(a,e);for(let N of j.reverse())f=c(N,{params:d,query:m},f);return f}return n?c(n,{}):c("div",{class:"what-404"},c("h1",null,"404"),c("p",null,"Page not found"))},o=()=>{let s=null;try{return r()}catch(i){if(!i||!i[V])throw i;s=i}return L(s.to,s.options)};return t?c(t,{},o):o}function ne({href:e,class:n,className:t,children:r,replace:o,prefetch:s=!0,activeClass:i="active",exactActiveClass:u="exact-active",transition:p=!0,...l}){let a=C(e)?e:"about:blank";!C(e)&&typeof console<"u"&&console.warn("[what-router] Link blocked unsafe href:",e);let d=a.split("?")[0].split("#")[0];return c("a",{href:a,class:()=>{let f=g.path,E=d==="/"?f==="/":f===d||f.startsWith(d+"/");return[n||t,E&&i,f===d&&u].filter(Boolean).join(" ")||void 0},onclick:f=>{f.ctrlKey||f.metaKey||f.shiftKey||f.altKey||f.button!==0||(f.preventDefault(),v(a,{replace:o,transition:p}))},onmouseenter:s?()=>U(a):void 0,...l},...Array.isArray(r)?r:[r])}function de(e){return ne(e)}function pe(e){return Object.entries(e).map(([n,t])=>typeof t=="function"?{path:n,component:t}:{path:n,...t})}function re(e,n){let t=e.endsWith("/")?e.slice(0,-1):e,r=!n||n==="/"?"/":n.startsWith("/")?n:`/${n}`;return r==="/"?t||"/":t+r}function he(e,n,t={}){let{layout:r,loading:o,error:s}=t;return n.map(i=>({...i,path:re(e,i.path),layout:i.layout||r,loading:i.loading||o,error:i.error||s}))}function me(e,n,t={}){let{layout:r,middleware:o}=t;return n.map(s=>({...s,_group:e,layout:s.layout||r,middleware:[...s.middleware||[],...o||[]]}))}function ge({to:e}){return v(e,{replace:!0}),null}function ye(e,n){return t=>function(o){let s=e(o);return s instanceof Promise?c("div",{class:"what-guard-loading"},"Loading..."):s?c(t,o):typeof n=="string"?(v(n,{replace:!0}),null):c(n,o)}}function we(e,n={}){let{fallback:t="/login",loading:r=null}=n;return o=>function(i){let u=R("pending"),p=R(null),l=!1;return $(()=>(l=!1,Promise.resolve(e(i)).then(a=>{l||(p.set(a),u.set(a?"allowed":"denied"))}).catch(()=>{l||u.set("denied")}),()=>{l=!0})),()=>{let a=u();return a==="pending"?r?c(r,{}):null:a==="allowed"?c(o,i):typeof t=="string"?(v(t,{replace:!0}),null):c(t,i)}}}var W=new Set;function U(e){if(typeof document>"u"||W.has(e))return;W.add(e);let n=document.createElement("link");n.rel="prefetch",n.href=e,document.head.appendChild(n)}var k=new Map;function xe(){if(typeof window>"u")return;let e=!0;$(()=>{let n=g.url,t=k.get(n),r=g.hash,o=e;e=!1,requestAnimationFrame(()=>{r?oe(r)?.scrollIntoView():t?window.scrollTo(t.x,t.y):o||window.scrollTo(0,0)})})}function oe(e){try{return document.querySelector(e)}catch{return document.getElementById(e.slice(1))}}function Re(e){return{style:{viewTransitionName:e}}}function ve(e){typeof document>"u"||(document.documentElement.dataset.transition=e)}function be(){return{path:b(()=>g.path),params:b(()=>g.params),query:b(()=>g.query),hash:b(()=>g.hash),isNavigating:b(()=>g.isNavigating),navigate:v,prefetch:U}}function Ee(){return g.params}function Se(){return g.query}function _e(){return v}function Ae(e){U(e)}function Ce({children:e}){return e||null}function ke({routes:e,layout:n,fallback:t,error:r}){let o=e.map(s=>({path:s.path,component:s.component,layout:s.layout||void 0,loading:s.loading||void 0,error:s.error||r||void 0,_mode:s.mode||"client"}));return te({routes:o,globalLayout:n,fallback:t||ie})}function ie(){return c("div",{style:"text-align:center;padding:60px 20px"},c("h1",{style:"font-size:48px;margin-bottom:8px"},"404"),c("p",{style:"color:#64748b"},"Page not found"))}export{ke as FileRouter,ne as Link,de as NavLink,Ce as Outlet,ge as Redirect,te as Router,le as afterNavigate,we as asyncGuard,ue as beforeNavigate,O as compilePath,pe as defineRoutes,xe as enableScrollRestoration,ye as guard,C as isSafeUrl,_ as matchRoute,v as navigate,he as nestedRoutes,A as parseQuery,U as prefetch,Ae as prefetchRoute,fe as redirect,g as route,me as routeGroup,ve as setViewTransition,_e as useNavigate,Ee as useParams,be as useRoute,Se as useSearch,Re as viewTransitionName};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "what-router",
3
- "version": "0.12.4",
3
+ "version": "0.13.1",
4
4
  "description": "What Framework - File-based & programmatic router with View Transitions",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -35,7 +35,7 @@
35
35
  "license": "MIT",
36
36
  "dependencies": {},
37
37
  "peerDependencies": {
38
- "what-core": "^0.12.4"
38
+ "what-core": "^0.13.1"
39
39
  },
40
40
  "repository": {
41
41
  "type": "git",
package/src/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // route groups, view transitions, and middleware.
4
4
 
5
5
  import { signal, effect, computed, batch, h, ErrorBoundary } from 'what-core';
6
- import { compilePath, matchRoute, parseQuery } from './match.js';
6
+ import { matchRoute, parseQuery } from './match.js';
7
7
 
8
8
  // --- URL Sanitization ---
9
9
  // Rejects javascript:, data:, vbscript: protocols (case-insensitive, trimmed),
@@ -196,7 +196,7 @@ export async function navigate(to, opts = {}) {
196
196
  viewTransition.ready.catch(() => {});
197
197
  }
198
198
  await viewTransition.finished;
199
- } catch (e) {
199
+ } catch {
200
200
  // Transition failed, navigation still happened
201
201
  }
202
202
  } else {
@@ -229,6 +229,7 @@ const NAV_SIGNAL = Symbol.for('what.navigation.signal');
229
229
  export function redirect(to, options = {}) {
230
230
  if (!isSafeUrl(to)) {
231
231
  const target = typeof to === 'string' ? to : Object.prototype.toString.call(to);
232
+ /** @type {Error & { code?: string, suggestion?: string, codeExample?: string }} */
232
233
  const err = new Error(`[what-router] redirect() refused an unsafe target: ${target}`);
233
234
  err.code = 'ERR_UNSAFE_REDIRECT';
234
235
  err.suggestion = 'redirect() accepts same-origin paths and http:, https:, mailto: or tel: URLs only. Protocol-relative ("//host"), backslash-smuggled and javascript:/data: targets are open-redirect vectors. Check a user-supplied target against an allowlist first.';
@@ -240,6 +241,7 @@ redirect(ALLOWED.has(query.next) ? query.next : '/');`;
240
241
  throw err;
241
242
  }
242
243
 
244
+ /** @type {Error & { code?: string, suggestion?: string, codeExample?: string, to?: any, options?: any }} */
243
245
  const sig = new Error(`[what-router] redirect to ${to}`);
244
246
  sig.name = 'RouterRedirect';
245
247
  sig.code = 'ERR_REDIRECT_NOT_CAUGHT';