klaim 1.11.7 → 1.11.8

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/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antharuu/klaim",
3
- "version": "1.11.7",
3
+ "version": "1.11.8",
4
4
  "description": "Klaim is a lightweight TypeScript library designed to manage APIs and record requests, optimized for an optimal user experience.",
5
5
  "repository": {
6
6
  "type": "git",
package/dist/klaim.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var O=Object.defineProperty;var G=(n,t,e)=>t in n?O(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var o=(n,t,e)=>G(n,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function k(n){return n.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}function M(n){return n.trim().replace(/^\/|\/$/g,"")}const j={limit:5,duration:10},A=new Map;function U(n,t){const e=Date.now(),a=t.duration*1e3;let r=A.get(n);r||(r={timestamps:[]},A.set(n,r));const i=r.timestamps.filter(s=>e-s<a);return i.length>=t.limit?!1:(i.push(e),r.timestamps=i,!0)}function I(n,t){const e=A.get(n);if(!e||e.timestamps.length<t.limit)return 0;const a=Date.now(),r=t.duration*1e3,l=[...e.timestamps].sort((u,p)=>u-p)[0]+r-a;return Math.max(0,l)}const b={duration:5,message:"Request timed out"};async function H(n,t){const{duration:e,message:a}=t;return Promise.race([n,new Promise((r,i)=>{const s=setTimeout(()=>{clearTimeout(s),i(new Error(a))},e*1e3)})])}const q={page:1,pageParam:"page",limit:10,limitParam:"limit"};class F{constructor(t,e,a,r={}){o(this,"type");o(this,"name");o(this,"url");o(this,"headers");o(this,"parent");o(this,"method");o(this,"arguments",new Set);o(this,"schema");o(this,"pagination");o(this,"callbacks",{before:null,after:null,call:null});o(this,"cache",!1);o(this,"retry",!1);o(this,"rate",!1);o(this,"timeout",!1);o(this,"withCache",(t=20)=>(this.cache=t,this));o(this,"withRetry",(t=2)=>(this.retry=t,this));o(this,"withRate",(t={})=>(this.rate={...j,...t},this));o(this,"withTimeout",(t=b.duration,e=b.message)=>(this.timeout={duration:t,message:e},this));this.type=t,this.name=k(e),this.name!==e&&console.warn(`Name "${e}" has been camelCased to "${this.name}"`),this.url=M(a),this.headers=r||{}}before(t){return this.callbacks.before=t,this}after(t){return this.callbacks.after=t,this}onCall(t){return this.callbacks.call=t,this}withPagination(t={}){return this.pagination={...q,...t},this}}const g=class g{constructor(){o(this,"cache");this.cache=new Map}static get i(){return g._instance||(g._instance=new g),g._instance}set(t,e,a=0){const r=Date.now()+a;this.cache.set(t,{data:e,expiry:r})}has(t){const e=this.cache.get(t);return e?Date.now()>e.expiry?(this.cache.delete(t),!1):!0:!1}get(t){return this.has(t)?this.cache.get(t).data:null}};o(g,"_instance");let y=g;function W(n){let a=2166136261;for(let i=0;i<n.length;i++)a^=n.charCodeAt(i),a*=16777619;let r=(a>>>0).toString(16).padStart(8,"0");for(;r.length<32;)a^=r.charCodeAt(r.length%r.length),a*=16777619,r+=(a>>>0).toString(16).padStart(8,"0");return r.substring(0,32)}async function J(n,t,e){const a=`${n.toString()}${JSON.stringify(t)}`,r=W(a);if(y.i.has(r))return y.i.get(r);const s=await(await fetch(n,t)).json();return y.i.set(r,s,e),s}class S{static subscribe(t,e){this._callbacks.set(t,e)}static run(t){const e=this._callbacks.get(t);e&&e()}}o(S,"_callbacks",new Map);const _={};function V(n,t){return async(...e)=>{if(t.pagination){const[i=0,s={},l={}]=e;return x(n,t,i,s,l)}const[a={},r={}]=e;return x(n,t,void 0,a,r)}}async function x(n,t,e,a={},r={}){const i=n.split(".");let s;for(let P=0;P<i.length;P++){const $=i[P];if(s=c.i.getApi($),s)break}if(!t||!s||t.type!=="route"||s.type!=="api")throw new Error(`Invalid path: ${n}.${t.name}`);let l=Q(`${s.url}/${t.url}`,t,a);if(t.pagination&&typeof e<"u"){const{pageParam:P="page",limit:$=10,limitParam:K="limit"}=t.pagination,T=new URLSearchParams;T.append(P,String(e)),T.append(K,String($));const L=l.includes("?")?"&":"?";l=`${l}${L}${T.toString()}`}let u={};r&&t.method!=="GET"&&(u.body=JSON.stringify(r)),u.headers={"Content-Type":"application/json",...s.headers,...t.headers},u.method=t.method;const{beforeRoute:p,beforeApi:C,beforeUrl:E,beforeConfig:h}=X({route:t,api:s,url:l,config:u});l=E,u=h,c.updateElement(C),c.updateElement(p);let m=await B(s,t,l,u);t.schema&&"validate"in t.schema&&(m=await t.schema.validate(m));const{afterRoute:d,afterApi:w,afterData:D}=Y({route:t,api:s,response:m,data:m});return c.updateElement(w),c.updateElement(d),S.run(`${s.name}.${t.name}`),D}async function z(n,t,e,a){return n?await J(t,e,a.cache):await(await fetch(t,e)).json()}async function B(n,t,e,a){var C,E;const r=n.cache||t.cache,i=t.retry||n.retry||0,s=t.timeout||n.timeout;if(t.rate){const h=`${n.name}.${t.name}`;if(!U(h,t.rate)){const d=I(h,t.rate),w=Math.ceil(d/1e3);throw new Error(`Rate limit exceeded for ${h}. Try again in ${w} seconds.`)}}else if(n.rate){const h=`${n.name}`;if(!U(h,n.rate)){const d=I(h,n.rate),w=Math.ceil(d/1e3);throw new Error(`Rate limit exceeded for ${n.name} API. Try again in ${w} seconds.`)}}let l,u=!1,p=0;for(;p<=i&&!u;)try{(C=t.callbacks)!=null&&C.call?t.callbacks.call({}):(E=n.callbacks)!=null&&E.call&&n.callbacks.call({});const h=z(!!r,e,a,n);l=s?await H(h,s):await h,u=!0}catch(h){if(p++,p>i)throw h.message||(h.message=`Failed to fetch ${e} after ${i} attempts`),h}return l}function Q(n,t,e){let a=n;return t.arguments.forEach(r=>{if(e[r]===void 0)throw new Error(`Argument ${r} is missing`);a=a.replace(`[${r}]`,e[r])}),a}function X({route:n,api:t,url:e,config:a}){var i,s;const r=(s=(i=n.callbacks).before)==null?void 0:s.call(i,{route:n,api:t,url:e,config:a});return{beforeRoute:(r==null?void 0:r.route)||n,beforeApi:(r==null?void 0:r.api)||t,beforeUrl:(r==null?void 0:r.url)||e,beforeConfig:(r==null?void 0:r.config)||a}}function Y({route:n,api:t,response:e,data:a}){var i,s;const r=(s=(i=n.callbacks).after)==null?void 0:s.call(i,{route:n,api:t,response:e,data:a});return{afterRoute:(r==null?void 0:r.route)||n,afterApi:(r==null?void 0:r.api)||t,afterResponse:(r==null?void 0:r.response)||e,afterData:(r==null?void 0:r.data)||a}}const f=class f{constructor(){o(this,"_elements",new Map);o(this,"_currentParent",null)}static get i(){return f._instance||(f._instance=new f),f._instance}registerElement(t){const e=this._currentParent;e&&(t.parent=this.getFullPath(e));const a=this.getElementKey(t);if(this._elements.set(a,t),t.type==="api"||t.type==="group"){let r=_;if(e){const i=this.getFullPath(e).split(".");for(const s of i)r[s]||(r[s]={}),r=r[s]}r[t.name]||(r[t.name]={})}}getCurrentParent(){return this._currentParent}setCurrentParent(t){const e=this._elements.get(t);if(!e||e.type!=="api"&&e.type!=="group")throw new Error(`Element ${t} not found or not a valid parent type`);this._currentParent=e}clearCurrentParent(){this._currentParent=null}registerRoute(t){if(!this._currentParent)throw new Error("No current parent set, use Route only inside Api or Group create callback");t.parent=this.getFullPath(this._currentParent);const e=this.getElementKey(t);this._elements.set(e,t),this.addToKlaimRoute(t)}addToKlaimRoute(t){if(!t.parent)return;let e=_;const a=t.parent.split(".");for(const r of a)e[r]||(e[r]={}),e=e[r];e[t.name]=V(t.parent,t)}getElementKey(t){return t?t.parent?`${t.parent}.${t.name}`:t.name:""}getFullPath(t){if(!t)return"";if(!t.parent)return t.name;const e=[t.name];let a=t;for(;a.parent;){const r=this._elements.get(a.parent);if(!r)break;e.unshift(r.name),a=r}return e.join(".")}getRoute(t,e){return this._elements.get(`${t}.${e}`)}getChildren(t){const e=[];return this._elements.forEach(a=>{a.parent===t&&e.push(a)}),e}static updateElement(t){return f.i._elements.get(f.i.getElementKey(t))||t}getApi(t){const e=this._elements.get(t);if(!e){for(const[a,r]of this._elements.entries())if(r.type==="api"&&a.endsWith(`.${t}`))return r;return}return e.type==="api"?e:this.findApi(e)}findApi(t){if(!t||!t.parent)return;const e=t.parent.split(".");for(let a=e.length;a>=0;a--){const r=e.slice(0,a).join("."),i=this._elements.get(r);if((i==null?void 0:i.type)==="api")return i}}};o(f,"_instance");let c=f;class R extends F{static create(t,e,a,r={}){const i=k(t);i!==t&&console.warn(`API name "${t}" has been camelCased to "${i}"`);const s=new R(i,e,r),l=c.i.getCurrentParent();c.i.registerElement(s);const u=l?c.i.getFullPath(l):"",p=u?`${u}.${i}`:i;return c.i.setCurrentParent(p),a(),l?c.i.setCurrentParent(c.i.getFullPath(l)):c.i.clearCurrentParent(),s}constructor(t,e,a={}){super("api",t,e,a)}}class v extends F{static create(t,e){const a=k(t),r=c.i.getCurrentParent(),i=r?c.i.getFullPath(r):"",s=i?`${i}.${a}`:a,l=new v(a,"");a!==t&&console.warn(`Group name "${t}" has been camelCased to "${a}"`),c.i.registerElement(l);const u=c.i.getCurrentParent();return c.i.setCurrentParent(s),e(),u?c.i.setCurrentParent(c.i.getFullPath(u)):c.i.clearCurrentParent(),l}constructor(t,e,a={}){super("group",t,e,a)}withCache(t=20){return super.withCache(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.cache||(e.cache=t)}),this}withRetry(t=2){return super.withRetry(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.retry||(e.retry=t)}),this}withTimeout(t=b.duration,e=b.message){return super.withTimeout(t,e),c.i.getChildren(c.i.getFullPath(this)).forEach(a=>{a.timeout||(a.timeout={duration:t,message:e})}),this}before(t){return super.before(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.callbacks.before||(e.callbacks.before=t)}),this}after(t){return super.after(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.callbacks.after||(e.callbacks.after=t)}),this}onCall(t){return super.onCall(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.callbacks.call||(e.callbacks.call=t)}),this}}class N extends F{constructor(t,e,a={},r="GET"){super("route",t,e,a),this.method=r,this.detectArguments()}static createRoute(t,e,a={},r){const i=new N(t,e,a,r);return c.i.registerRoute(i),i}static get(t,e,a={}){return this.createRoute(t,e,a,"GET")}static post(t,e,a={}){return this.createRoute(t,e,a,"POST")}static put(t,e,a={}){return this.createRoute(t,e,a,"PUT")}static delete(t,e,a={}){return this.createRoute(t,e,a,"DELETE")}static patch(t,e,a={}){return this.createRoute(t,e,a,"PATCH")}static options(t,e,a={}){return this.createRoute(t,e,a,"OPTIONS")}detectArguments(){const t=this.url.match(/\[([^\]]+)]/g);t&&t.forEach(e=>{const a=e.replace("[","").replace("]","");this.arguments.add(a)})}validate(t){return this.schema=t,this}}exports.Api=R;exports.Group=v;exports.Hook=S;exports.Klaim=_;exports.Registry=c;exports.Route=N;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function C(n){return n.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}function D(n){return n.trim().replace(/^\/|\/$/g,"")}const K={limit:5,duration:10},b=new Map;function _(n,t){const e=Date.now(),r=t.duration*1e3;let a=b.get(n);a||(a={timestamps:[]},b.set(n,a));const i=a.timestamps.filter(c=>e-c<r);return i.length>=t.limit?!1:(i.push(e),a.timestamps=i,!0)}function k(n,t){const e=b.get(n);if(!e||e.timestamps.length<t.limit)return 0;const r=Date.now(),a=t.duration*1e3,o=[...e.timestamps].sort((l,h)=>l-h)[0]+a-r;return Math.max(0,o)}const d={duration:5,message:"Request timed out"};async function L(n,t){const{duration:e,message:r}=t;return Promise.race([n,new Promise((a,i)=>{const c=setTimeout(()=>{clearTimeout(c),i(new Error(r))},e*1e3)})])}const O={page:1,pageParam:"page",limit:10,limitParam:"limit"};class ${type;name;url;headers;parent;method;arguments=new Set;schema;pagination;callbacks={before:null,after:null,call:null};cache=!1;retry=!1;rate=!1;timeout=!1;constructor(t,e,r,a={}){this.type=t,this.name=C(e),this.name!==e&&console.warn(`Name "${e}" has been camelCased to "${this.name}"`),this.url=D(r),this.headers=a||{}}before(t){return this.callbacks.before=t,this}after(t){return this.callbacks.after=t,this}onCall(t){return this.callbacks.call=t,this}withCache=(t=20)=>(this.cache=t,this);withRetry=(t=2)=>(this.retry=t,this);withPagination(t={}){return this.pagination={...O,...t},this}withRate=(t={})=>(this.rate={...K,...t},this);withTimeout=(t=d.duration,e=d.message)=>(this.timeout={duration:t,message:e},this)}class p{static _instance;cache;constructor(){this.cache=new Map}static get i(){return p._instance||(p._instance=new p),p._instance}set(t,e,r=0){const a=Date.now()+r;this.cache.set(t,{data:e,expiry:a})}has(t){const e=this.cache.get(t);return e?Date.now()>e.expiry?(this.cache.delete(t),!1):!0:!1}get(t){return this.has(t)?this.cache.get(t).data:null}}function G(n){let r=2166136261;for(let i=0;i<n.length;i++)r^=n.charCodeAt(i),r*=16777619;let a=(r>>>0).toString(16).padStart(8,"0");for(;a.length<32;)r^=a.charCodeAt(a.length%a.length),r*=16777619,a+=(r>>>0).toString(16).padStart(8,"0");return a.substring(0,32)}async function M(n,t,e){const r=`${n.toString()}${JSON.stringify(t)}`,a=G(r);if(p.i.has(a))return p.i.get(a);const c=await(await fetch(n,t)).json();return p.i.set(a,c,e),c}class S{static _callbacks=new Map;static subscribe(t,e){this._callbacks.set(t,e)}static run(t){const e=this._callbacks.get(t);e&&e()}}const E={};function H(n,t){return async(...e)=>{if(t.pagination){const[i=0,c={},o={}]=e;return F(n,t,i,c,o)}const[r={},a={}]=e;return F(n,t,void 0,r,a)}}async function F(n,t,e,r={},a={}){const i=n.split(".");let c;for(let g=0;g<i.length;g++){const P=i[g];if(c=s.i.getApi(P),c)break}if(!t||!c||t.type!=="route"||c.type!=="api")throw new Error(`Invalid path: ${n}.${t.name}`);let o=W(`${c.url}/${t.url}`,t,r);if(t.pagination&&typeof e<"u"){const{pageParam:g="page",limit:P=10,limitParam:I="limit"}=t.pagination,y=new URLSearchParams;y.append(g,String(e)),y.append(I,String(P));const x=o.includes("?")?"&":"?";o=`${o}${x}${y.toString()}`}let l={};a&&t.method!=="GET"&&(l.body=JSON.stringify(a)),l.headers={"Content-Type":"application/json",...c.headers,...t.headers},l.method=t.method;const{beforeRoute:h,beforeApi:u,beforeUrl:w,beforeConfig:m}=J({route:t,api:c,url:o,config:l});o=w,l=m,s.updateElement(u),s.updateElement(h);let f=await q(c,t,o,l);t.schema&&"validate"in t.schema&&(f=await t.schema.validate(f));const{afterRoute:v,afterApi:N,afterData:U}=V({route:t,api:c,response:f,data:f});return s.updateElement(N),s.updateElement(v),S.run(`${c.name}.${t.name}`),U}async function j(n,t,e,r){return n?await M(t,e,r.cache):await(await fetch(t,e)).json()}async function q(n,t,e,r){const a=n.cache||t.cache,i=t.retry||n.retry||0,c=t.timeout||n.timeout;if(t.rate){const u=`${n.name}.${t.name}`;if(!_(u,t.rate)){const m=k(u,t.rate),f=Math.ceil(m/1e3);throw new Error(`Rate limit exceeded for ${u}. Try again in ${f} seconds.`)}}else if(n.rate){const u=`${n.name}`;if(!_(u,n.rate)){const m=k(u,n.rate),f=Math.ceil(m/1e3);throw new Error(`Rate limit exceeded for ${n.name} API. Try again in ${f} seconds.`)}}let o,l=!1,h=0;for(;h<=i&&!l;)try{t.callbacks?.call?t.callbacks.call({}):n.callbacks?.call&&n.callbacks.call({});const u=j(!!a,e,r,n);o=c?await L(u,c):await u,l=!0}catch(u){if(h++,h>i)throw u.message||(u.message=`Failed to fetch ${e} after ${i} attempts`),u}return o}function W(n,t,e){let r=n;return t.arguments.forEach(a=>{if(e[a]===void 0)throw new Error(`Argument ${a} is missing`);r=r.replace(`[${a}]`,e[a])}),r}function J({route:n,api:t,url:e,config:r}){const a=n.callbacks.before?.({route:n,api:t,url:e,config:r});return{beforeRoute:a?.route||n,beforeApi:a?.api||t,beforeUrl:a?.url||e,beforeConfig:a?.config||r}}function V({route:n,api:t,response:e,data:r}){const a=n.callbacks.after?.({route:n,api:t,response:e,data:r});return{afterRoute:a?.route||n,afterApi:a?.api||t,afterResponse:a?.response||e,afterData:a?.data||r}}class s{static _instance;_elements=new Map;_currentParent=null;constructor(){}static get i(){return s._instance||(s._instance=new s),s._instance}registerElement(t){const e=this._currentParent;e&&(t.parent=this.getFullPath(e));const r=this.getElementKey(t);if(this._elements.set(r,t),t.type==="api"||t.type==="group"){let a=E;if(e){const i=this.getFullPath(e).split(".");for(const c of i)a[c]||(a[c]={}),a=a[c]}a[t.name]||(a[t.name]={})}}getCurrentParent(){return this._currentParent}setCurrentParent(t){const e=this._elements.get(t);if(!e||e.type!=="api"&&e.type!=="group")throw new Error(`Element ${t} not found or not a valid parent type`);this._currentParent=e}clearCurrentParent(){this._currentParent=null}registerRoute(t){if(!this._currentParent)throw new Error("No current parent set, use Route only inside Api or Group create callback");t.parent=this.getFullPath(this._currentParent);const e=this.getElementKey(t);this._elements.set(e,t),this.addToKlaimRoute(t)}addToKlaimRoute(t){if(!t.parent)return;let e=E;const r=t.parent.split(".");for(const a of r)e[a]||(e[a]={}),e=e[a];e[t.name]=H(t.parent,t)}getElementKey(t){return t?t.parent?`${t.parent}.${t.name}`:t.name:""}getFullPath(t){if(!t)return"";if(!t.parent)return t.name;const e=[t.name];let r=t;for(;r.parent;){const a=this._elements.get(r.parent);if(!a)break;e.unshift(a.name),r=a}return e.join(".")}getRoute(t,e){return this._elements.get(`${t}.${e}`)}getChildren(t){const e=[];return this._elements.forEach(r=>{r.parent===t&&e.push(r)}),e}static updateElement(t){return s.i._elements.get(s.i.getElementKey(t))||t}getApi(t){const e=this._elements.get(t);if(!e){for(const[r,a]of this._elements.entries())if(a.type==="api"&&r.endsWith(`.${t}`))return a;return}return e.type==="api"?e:this.findApi(e)}findApi(t){if(!t||!t.parent)return;const e=t.parent.split(".");for(let r=e.length;r>=0;r--){const a=e.slice(0,r).join("."),i=this._elements.get(a);if(i?.type==="api")return i}}}class T extends ${static create(t,e,r,a={}){const i=C(t);i!==t&&console.warn(`API name "${t}" has been camelCased to "${i}"`);const c=new T(i,e,a),o=s.i.getCurrentParent();s.i.registerElement(c);const l=o?s.i.getFullPath(o):"",h=l?`${l}.${i}`:i;return s.i.setCurrentParent(h),r(),o?s.i.setCurrentParent(s.i.getFullPath(o)):s.i.clearCurrentParent(),c}constructor(t,e,r={}){super("api",t,e,r)}}class R extends ${static create(t,e){const r=C(t),a=s.i.getCurrentParent(),i=a?s.i.getFullPath(a):"",c=i?`${i}.${r}`:r,o=new R(r,"");r!==t&&console.warn(`Group name "${t}" has been camelCased to "${r}"`),s.i.registerElement(o);const l=s.i.getCurrentParent();return s.i.setCurrentParent(c),e(),l?s.i.setCurrentParent(s.i.getFullPath(l)):s.i.clearCurrentParent(),o}constructor(t,e,r={}){super("group",t,e,r)}withCache(t=20){return super.withCache(t),s.i.getChildren(s.i.getFullPath(this)).forEach(e=>{e.cache||(e.cache=t)}),this}withRetry(t=2){return super.withRetry(t),s.i.getChildren(s.i.getFullPath(this)).forEach(e=>{e.retry||(e.retry=t)}),this}withTimeout(t=d.duration,e=d.message){return super.withTimeout(t,e),s.i.getChildren(s.i.getFullPath(this)).forEach(r=>{r.timeout||(r.timeout={duration:t,message:e})}),this}before(t){return super.before(t),s.i.getChildren(s.i.getFullPath(this)).forEach(e=>{e.callbacks.before||(e.callbacks.before=t)}),this}after(t){return super.after(t),s.i.getChildren(s.i.getFullPath(this)).forEach(e=>{e.callbacks.after||(e.callbacks.after=t)}),this}onCall(t){return super.onCall(t),s.i.getChildren(s.i.getFullPath(this)).forEach(e=>{e.callbacks.call||(e.callbacks.call=t)}),this}}class A extends ${constructor(t,e,r={},a="GET"){super("route",t,e,r),this.method=a,this.detectArguments()}static createRoute(t,e,r={},a){const i=new A(t,e,r,a);return s.i.registerRoute(i),i}static get(t,e,r={}){return this.createRoute(t,e,r,"GET")}static post(t,e,r={}){return this.createRoute(t,e,r,"POST")}static put(t,e,r={}){return this.createRoute(t,e,r,"PUT")}static delete(t,e,r={}){return this.createRoute(t,e,r,"DELETE")}static patch(t,e,r={}){return this.createRoute(t,e,r,"PATCH")}static options(t,e,r={}){return this.createRoute(t,e,r,"OPTIONS")}detectArguments(){const t=this.url.match(/\[([^\]]+)]/g);t&&t.forEach(e=>{const r=e.replace("[","").replace("]","");this.arguments.add(r)})}validate(t){return this.schema=t,this}}exports.Api=T;exports.Group=R;exports.Hook=S;exports.Klaim=E;exports.Registry=s;exports.Route=A;
package/dist/klaim.es.js CHANGED
@@ -1,53 +1,68 @@
1
- var O = Object.defineProperty;
2
- var G = (n, t, e) => t in n ? O(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
3
- var o = (n, t, e) => G(n, typeof t != "symbol" ? t + "" : t, e);
4
- function _(n) {
1
+ function E(n) {
5
2
  return n.replace(/([-_][a-z])/gi, (t) => t.toUpperCase().replace("-", "").replace("_", "")).replace(/(^\w)/, (t) => t.toLowerCase());
6
3
  }
7
- function M(n) {
4
+ function I(n) {
8
5
  return n.trim().replace(/^\/|\/$/g, "");
9
6
  }
10
- const j = {
7
+ const D = {
11
8
  limit: 5,
12
9
  duration: 10
13
10
  // seconds
14
- }, A = /* @__PURE__ */ new Map();
15
- function F(n, t) {
16
- const e = Date.now(), a = t.duration * 1e3;
17
- let r = A.get(n);
18
- r || (r = { timestamps: [] }, A.set(n, r));
19
- const i = r.timestamps.filter((s) => e - s < a);
20
- return i.length >= t.limit ? !1 : (i.push(e), r.timestamps = i, !0);
11
+ }, b = /* @__PURE__ */ new Map();
12
+ function $(n, t) {
13
+ const e = Date.now(), r = t.duration * 1e3;
14
+ let a = b.get(n);
15
+ a || (a = { timestamps: [] }, b.set(n, a));
16
+ const i = a.timestamps.filter((c) => e - c < r);
17
+ return i.length >= t.limit ? !1 : (i.push(e), a.timestamps = i, !0);
21
18
  }
22
- function S(n, t) {
23
- const e = A.get(n);
19
+ function T(n, t) {
20
+ const e = b.get(n);
24
21
  if (!e || e.timestamps.length < t.limit)
25
22
  return 0;
26
- const a = Date.now(), r = t.duration * 1e3, l = [...e.timestamps].sort((u, p) => u - p)[0] + r - a;
27
- return Math.max(0, l);
23
+ const r = Date.now(), a = t.duration * 1e3, o = [...e.timestamps].sort((l, h) => l - h)[0] + a - r;
24
+ return Math.max(0, o);
28
25
  }
29
- const $ = {
26
+ const d = {
30
27
  duration: 5,
31
28
  message: "Request timed out"
32
29
  };
33
- async function q(n, t) {
34
- const { duration: e, message: a } = t;
30
+ async function L(n, t) {
31
+ const { duration: e, message: r } = t;
35
32
  return Promise.race([
36
33
  n,
37
- new Promise((r, i) => {
38
- const s = setTimeout(() => {
39
- clearTimeout(s), i(new Error(a));
34
+ new Promise((a, i) => {
35
+ const c = setTimeout(() => {
36
+ clearTimeout(c), i(new Error(r));
40
37
  }, e * 1e3);
41
38
  })
42
39
  ]);
43
40
  }
44
- const H = {
41
+ const K = {
45
42
  page: 1,
46
43
  pageParam: "page",
47
44
  limit: 10,
48
45
  limitParam: "limit"
49
46
  };
50
- class k {
47
+ class C {
48
+ type;
49
+ name;
50
+ url;
51
+ headers;
52
+ parent;
53
+ method;
54
+ arguments = /* @__PURE__ */ new Set();
55
+ schema;
56
+ pagination;
57
+ callbacks = {
58
+ before: null,
59
+ after: null,
60
+ call: null
61
+ };
62
+ cache = !1;
63
+ retry = !1;
64
+ rate = !1;
65
+ timeout = !1;
51
66
  /**
52
67
  * Creates a new element with the specified properties
53
68
  *
@@ -56,62 +71,8 @@ class k {
56
71
  * @param {string} url - Base URL or path segment
57
72
  * @param {IHeaders} [headers] - HTTP headers for the element
58
73
  */
59
- constructor(t, e, a, r = {}) {
60
- o(this, "type");
61
- o(this, "name");
62
- o(this, "url");
63
- o(this, "headers");
64
- o(this, "parent");
65
- o(this, "method");
66
- o(this, "arguments", /* @__PURE__ */ new Set());
67
- o(this, "schema");
68
- o(this, "pagination");
69
- o(this, "callbacks", {
70
- before: null,
71
- after: null,
72
- call: null
73
- });
74
- o(this, "cache", !1);
75
- o(this, "retry", !1);
76
- o(this, "rate", !1);
77
- o(this, "timeout", !1);
78
- /**
79
- * Enables response caching for this element
80
- *
81
- * @param {number} [duration] - Cache duration in seconds
82
- * @returns {this} The element instance for chaining
83
- */
84
- o(this, "withCache", (t = 20) => (this.cache = t, this));
85
- /**
86
- * Enables request retries for this element
87
- *
88
- * @param {number} [maxRetries] - Maximum number of retry attempts
89
- * @returns {this} The element instance for chaining
90
- */
91
- o(this, "withRetry", (t = 2) => (this.retry = t, this));
92
- /**
93
- * Enables rate limiting for this element
94
- *
95
- * @param {Partial<IRateLimitConfig>} [config] - Rate limiting configuration options
96
- * @returns {this} The element instance for chaining
97
- * @example
98
- * ```typescript
99
- * Route.get("getUser", "/users/[id]").withRate({ limit: 5, duration: 10 });
100
- * ```
101
- */
102
- o(this, "withRate", (t = {}) => (this.rate = {
103
- ...j,
104
- ...t
105
- }, this));
106
- /**
107
- * Enables request timeout for this element
108
- *
109
- * @param {number} [duration] - Timeout duration in seconds
110
- * @param {string} [message] - Custom error message
111
- * @returns {this} The element instance for chaining
112
- */
113
- o(this, "withTimeout", (t = $.duration, e = $.message) => (this.timeout = { duration: t, message: e }, this));
114
- this.type = t, this.name = _(e), this.name !== e && console.warn(`Name "${e}" has been camelCased to "${this.name}"`), this.url = M(a), this.headers = r || {};
74
+ constructor(t, e, r, a = {}) {
75
+ this.type = t, this.name = E(e), this.name !== e && console.warn(`Name "${e}" has been camelCased to "${this.name}"`), this.url = I(r), this.headers = a || {};
115
76
  }
116
77
  /**
117
78
  * Adds a before-request middleware callback
@@ -140,6 +101,20 @@ class k {
140
101
  onCall(t) {
141
102
  return this.callbacks.call = t, this;
142
103
  }
104
+ /**
105
+ * Enables response caching for this element
106
+ *
107
+ * @param {number} [duration] - Cache duration in seconds
108
+ * @returns {this} The element instance for chaining
109
+ */
110
+ withCache = (t = 20) => (this.cache = t, this);
111
+ /**
112
+ * Enables request retries for this element
113
+ *
114
+ * @param {number} [maxRetries] - Maximum number of retry attempts
115
+ * @returns {this} The element instance for chaining
116
+ */
117
+ withRetry = (t = 2) => (this.retry = t, this);
143
118
  /**
144
119
  * Configures pagination settings for this element
145
120
  *
@@ -157,12 +132,47 @@ class k {
157
132
  */
158
133
  withPagination(t = {}) {
159
134
  return this.pagination = {
160
- ...H,
135
+ ...K,
161
136
  ...t
162
137
  }, this;
163
138
  }
139
+ /**
140
+ * Enables rate limiting for this element
141
+ *
142
+ * @param {Partial<IRateLimitConfig>} [config] - Rate limiting configuration options
143
+ * @returns {this} The element instance for chaining
144
+ * @example
145
+ * ```typescript
146
+ * Route.get("getUser", "/users/[id]").withRate({ limit: 5, duration: 10 });
147
+ * ```
148
+ */
149
+ withRate = (t = {}) => (this.rate = {
150
+ ...D,
151
+ ...t
152
+ }, this);
153
+ /**
154
+ * Enables request timeout for this element
155
+ *
156
+ * @param {number} [duration] - Timeout duration in seconds
157
+ * @param {string} [message] - Custom error message
158
+ * @returns {this} The element instance for chaining
159
+ */
160
+ withTimeout = (t = d.duration, e = d.message) => (this.timeout = { duration: t, message: e }, this);
164
161
  }
165
- const g = class g {
162
+ class p {
163
+ /**
164
+ * The singleton instance of the Cache class.
165
+ *
166
+ * @private
167
+ */
168
+ static _instance;
169
+ /**
170
+ * Internal storage for cached items.
171
+ * Maps keys to objects containing the data and expiration timestamp.
172
+ *
173
+ * @private
174
+ */
175
+ cache;
166
176
  /**
167
177
  * Private constructor to enforce singleton pattern.
168
178
  * Initializes an empty cache storage.
@@ -170,13 +180,6 @@ const g = class g {
170
180
  * @private
171
181
  */
172
182
  constructor() {
173
- /**
174
- * Internal storage for cached items.
175
- * Maps keys to objects containing the data and expiration timestamp.
176
- *
177
- * @private
178
- */
179
- o(this, "cache");
180
183
  this.cache = /* @__PURE__ */ new Map();
181
184
  }
182
185
  /**
@@ -190,7 +193,7 @@ const g = class g {
190
193
  * ```
191
194
  */
192
195
  static get i() {
193
- return g._instance || (g._instance = new g()), g._instance;
196
+ return p._instance || (p._instance = new p()), p._instance;
194
197
  }
195
198
  /**
196
199
  * Stores a value in the cache with an optional time-to-live duration.
@@ -207,9 +210,9 @@ const g = class g {
207
210
  * Cache.i.set("appConfig", configData);
208
211
  * ```
209
212
  */
210
- set(t, e, a = 0) {
211
- const r = Date.now() + a;
212
- this.cache.set(t, { data: e, expiry: r });
213
+ set(t, e, r = 0) {
214
+ const a = Date.now() + r;
215
+ this.cache.set(t, { data: e, expiry: a });
213
216
  }
214
217
  /**
215
218
  * Checks if the cache contains a valid (non-expired) entry for the given key.
@@ -247,31 +250,31 @@ const g = class g {
247
250
  get(t) {
248
251
  return this.has(t) ? this.cache.get(t).data : null;
249
252
  }
250
- };
251
- /**
252
- * The singleton instance of the Cache class.
253
- *
254
- * @private
255
- */
256
- o(g, "_instance");
257
- let y = g;
258
- function W(n) {
259
- let a = 2166136261;
253
+ }
254
+ function O(n) {
255
+ let r = 2166136261;
260
256
  for (let i = 0; i < n.length; i++)
261
- a ^= n.charCodeAt(i), a *= 16777619;
262
- let r = (a >>> 0).toString(16).padStart(8, "0");
263
- for (; r.length < 32; )
264
- a ^= r.charCodeAt(r.length % r.length), a *= 16777619, r += (a >>> 0).toString(16).padStart(8, "0");
265
- return r.substring(0, 32);
257
+ r ^= n.charCodeAt(i), r *= 16777619;
258
+ let a = (r >>> 0).toString(16).padStart(8, "0");
259
+ for (; a.length < 32; )
260
+ r ^= a.charCodeAt(a.length % a.length), r *= 16777619, a += (r >>> 0).toString(16).padStart(8, "0");
261
+ return a.substring(0, 32);
266
262
  }
267
- async function J(n, t, e) {
268
- const a = `${n.toString()}${JSON.stringify(t)}`, r = W(a);
269
- if (y.i.has(r))
270
- return y.i.get(r);
271
- const s = await (await fetch(n, t)).json();
272
- return y.i.set(r, s, e), s;
263
+ async function G(n, t, e) {
264
+ const r = `${n.toString()}${JSON.stringify(t)}`, a = O(r);
265
+ if (p.i.has(a))
266
+ return p.i.get(a);
267
+ const c = await (await fetch(n, t)).json();
268
+ return p.i.set(a, c, e), c;
273
269
  }
274
- class v {
270
+ class M {
271
+ /**
272
+ * Internal storage for hook callbacks.
273
+ * Maps route names to their corresponding callback functions.
274
+ *
275
+ * @private
276
+ */
277
+ static _callbacks = /* @__PURE__ */ new Map();
275
278
  /**
276
279
  * Registers a callback function for a specific route.
277
280
  * If a callback already exists for the route, it will be replaced.
@@ -307,142 +310,133 @@ class v {
307
310
  e && e();
308
311
  }
309
312
  }
310
- /**
311
- * Internal storage for hook callbacks.
312
- * Maps route names to their corresponding callback functions.
313
- *
314
- * @private
315
- */
316
- o(v, "_callbacks", /* @__PURE__ */ new Map());
317
313
  const R = {};
318
- function V(n, t) {
314
+ function H(n, t) {
319
315
  return async (...e) => {
320
316
  if (t.pagination) {
321
317
  const [
322
318
  i = 0,
323
- s = {},
324
- l = {}
319
+ c = {},
320
+ o = {}
325
321
  ] = e;
326
- return N(n, t, i, s, l);
322
+ return A(n, t, i, c, o);
327
323
  }
328
- const [a = {}, r = {}] = e;
329
- return N(n, t, void 0, a, r);
324
+ const [r = {}, a = {}] = e;
325
+ return A(n, t, void 0, r, a);
330
326
  };
331
327
  }
332
- async function N(n, t, e, a = {}, r = {}) {
328
+ async function A(n, t, e, r = {}, a = {}) {
333
329
  const i = n.split(".");
334
- let s;
335
- for (let P = 0; P < i.length; P++) {
336
- const b = i[P];
337
- if (s = c.i.getApi(b), s) break;
330
+ let c;
331
+ for (let g = 0; g < i.length; g++) {
332
+ const P = i[g];
333
+ if (c = s.i.getApi(P), c) break;
338
334
  }
339
- if (!t || !s || t.type !== "route" || s.type !== "api")
335
+ if (!t || !c || t.type !== "route" || c.type !== "api")
340
336
  throw new Error(`Invalid path: ${n}.${t.name}`);
341
- let l = Q(`${s.url}/${t.url}`, t, a);
337
+ let o = W(`${c.url}/${t.url}`, t, r);
342
338
  if (t.pagination && typeof e < "u") {
343
- const { pageParam: P = "page", limit: b = 10, limitParam: L = "limit" } = t.pagination, T = new URLSearchParams();
344
- T.append(P, String(e)), T.append(L, String(b));
345
- const K = l.includes("?") ? "&" : "?";
346
- l = `${l}${K}${T.toString()}`;
339
+ const { pageParam: g = "page", limit: P = 10, limitParam: U = "limit" } = t.pagination, y = new URLSearchParams();
340
+ y.append(g, String(e)), y.append(U, String(P));
341
+ const x = o.includes("?") ? "&" : "?";
342
+ o = `${o}${x}${y.toString()}`;
347
343
  }
348
- let u = {};
349
- r && t.method !== "GET" && (u.body = JSON.stringify(r)), u.headers = {
344
+ let l = {};
345
+ a && t.method !== "GET" && (l.body = JSON.stringify(a)), l.headers = {
350
346
  "Content-Type": "application/json",
351
- ...s.headers,
347
+ ...c.headers,
352
348
  ...t.headers
353
- }, u.method = t.method;
349
+ }, l.method = t.method;
354
350
  const {
355
- beforeRoute: p,
356
- beforeApi: C,
357
- beforeUrl: E,
358
- beforeConfig: h
359
- } = X({ route: t, api: s, url: l, config: u });
360
- l = E, u = h, c.updateElement(C), c.updateElement(p);
361
- let m = await B(s, t, l, u);
362
- t.schema && "validate" in t.schema && (m = await t.schema.validate(m));
351
+ beforeRoute: h,
352
+ beforeApi: u,
353
+ beforeUrl: w,
354
+ beforeConfig: m
355
+ } = J({ route: t, api: c, url: o, config: l });
356
+ o = w, l = m, s.updateElement(u), s.updateElement(h);
357
+ let f = await q(c, t, o, l);
358
+ t.schema && "validate" in t.schema && (f = await t.schema.validate(f));
363
359
  const {
364
- afterRoute: d,
365
- afterApi: w,
366
- afterData: D
367
- } = Y({ route: t, api: s, response: m, data: m });
368
- return c.updateElement(w), c.updateElement(d), v.run(`${s.name}.${t.name}`), D;
360
+ afterRoute: S,
361
+ afterApi: N,
362
+ afterData: v
363
+ } = V({ route: t, api: c, response: f, data: f });
364
+ return s.updateElement(N), s.updateElement(S), M.run(`${c.name}.${t.name}`), v;
369
365
  }
370
- async function z(n, t, e, a) {
371
- return n ? await J(t, e, a.cache) : await (await fetch(t, e)).json();
366
+ async function j(n, t, e, r) {
367
+ return n ? await G(t, e, r.cache) : await (await fetch(t, e)).json();
372
368
  }
373
- async function B(n, t, e, a) {
374
- var C, E;
375
- const r = n.cache || t.cache, i = t.retry || n.retry || 0, s = t.timeout || n.timeout;
369
+ async function q(n, t, e, r) {
370
+ const a = n.cache || t.cache, i = t.retry || n.retry || 0, c = t.timeout || n.timeout;
376
371
  if (t.rate) {
377
- const h = `${n.name}.${t.name}`;
378
- if (!F(h, t.rate)) {
379
- const d = S(h, t.rate), w = Math.ceil(d / 1e3);
380
- throw new Error(`Rate limit exceeded for ${h}. Try again in ${w} seconds.`);
372
+ const u = `${n.name}.${t.name}`;
373
+ if (!$(u, t.rate)) {
374
+ const m = T(u, t.rate), f = Math.ceil(m / 1e3);
375
+ throw new Error(`Rate limit exceeded for ${u}. Try again in ${f} seconds.`);
381
376
  }
382
377
  } else if (n.rate) {
383
- const h = `${n.name}`;
384
- if (!F(h, n.rate)) {
385
- const d = S(h, n.rate), w = Math.ceil(d / 1e3);
386
- throw new Error(`Rate limit exceeded for ${n.name} API. Try again in ${w} seconds.`);
378
+ const u = `${n.name}`;
379
+ if (!$(u, n.rate)) {
380
+ const m = T(u, n.rate), f = Math.ceil(m / 1e3);
381
+ throw new Error(`Rate limit exceeded for ${n.name} API. Try again in ${f} seconds.`);
387
382
  }
388
383
  }
389
- let l, u = !1, p = 0;
390
- for (; p <= i && !u; )
384
+ let o, l = !1, h = 0;
385
+ for (; h <= i && !l; )
391
386
  try {
392
- (C = t.callbacks) != null && C.call ? t.callbacks.call({}) : (E = n.callbacks) != null && E.call && n.callbacks.call({});
393
- const h = z(!!r, e, a, n);
394
- l = s ? await q(h, s) : await h, u = !0;
395
- } catch (h) {
396
- if (p++, p > i)
397
- throw h.message || (h.message = `Failed to fetch ${e} after ${i} attempts`), h;
387
+ t.callbacks?.call ? t.callbacks.call({}) : n.callbacks?.call && n.callbacks.call({});
388
+ const u = j(!!a, e, r, n);
389
+ o = c ? await L(u, c) : await u, l = !0;
390
+ } catch (u) {
391
+ if (h++, h > i)
392
+ throw u.message || (u.message = `Failed to fetch ${e} after ${i} attempts`), u;
398
393
  }
399
- return l;
394
+ return o;
400
395
  }
401
- function Q(n, t, e) {
402
- let a = n;
403
- return t.arguments.forEach((r) => {
404
- if (e[r] === void 0)
405
- throw new Error(`Argument ${r} is missing`);
406
- a = a.replace(`[${r}]`, e[r]);
407
- }), a;
396
+ function W(n, t, e) {
397
+ let r = n;
398
+ return t.arguments.forEach((a) => {
399
+ if (e[a] === void 0)
400
+ throw new Error(`Argument ${a} is missing`);
401
+ r = r.replace(`[${a}]`, e[a]);
402
+ }), r;
408
403
  }
409
- function X({ route: n, api: t, url: e, config: a }) {
410
- var i, s;
411
- const r = (s = (i = n.callbacks).before) == null ? void 0 : s.call(i, { route: n, api: t, url: e, config: a });
404
+ function J({ route: n, api: t, url: e, config: r }) {
405
+ const a = n.callbacks.before?.({ route: n, api: t, url: e, config: r });
412
406
  return {
413
- beforeRoute: (r == null ? void 0 : r.route) || n,
414
- beforeApi: (r == null ? void 0 : r.api) || t,
415
- beforeUrl: (r == null ? void 0 : r.url) || e,
416
- beforeConfig: (r == null ? void 0 : r.config) || a
407
+ beforeRoute: a?.route || n,
408
+ beforeApi: a?.api || t,
409
+ beforeUrl: a?.url || e,
410
+ beforeConfig: a?.config || r
417
411
  };
418
412
  }
419
- function Y({ route: n, api: t, response: e, data: a }) {
420
- var i, s;
421
- const r = (s = (i = n.callbacks).after) == null ? void 0 : s.call(i, { route: n, api: t, response: e, data: a });
413
+ function V({ route: n, api: t, response: e, data: r }) {
414
+ const a = n.callbacks.after?.({ route: n, api: t, response: e, data: r });
422
415
  return {
423
- afterRoute: (r == null ? void 0 : r.route) || n,
424
- afterApi: (r == null ? void 0 : r.api) || t,
425
- afterResponse: (r == null ? void 0 : r.response) || e,
426
- afterData: (r == null ? void 0 : r.data) || a
416
+ afterRoute: a?.route || n,
417
+ afterApi: a?.api || t,
418
+ afterResponse: a?.response || e,
419
+ afterData: a?.data || r
427
420
  };
428
421
  }
429
- const f = class f {
422
+ class s {
423
+ static _instance;
424
+ /**
425
+ * Map storing all registered elements with their full paths as keys
426
+ *
427
+ * @private
428
+ */
429
+ _elements = /* @__PURE__ */ new Map();
430
+ /**
431
+ * Reference to the current parent element during registration
432
+ *
433
+ * @private
434
+ */
435
+ _currentParent = null;
430
436
  /**
431
437
  *
432
438
  */
433
439
  constructor() {
434
- /**
435
- * Map storing all registered elements with their full paths as keys
436
- *
437
- * @private
438
- */
439
- o(this, "_elements", /* @__PURE__ */ new Map());
440
- /**
441
- * Reference to the current parent element during registration
442
- *
443
- * @private
444
- */
445
- o(this, "_currentParent", null);
446
440
  }
447
441
  /**
448
442
  * Gets the singleton instance of the Registry
@@ -450,7 +444,7 @@ const f = class f {
450
444
  * @returns The singleton Registry instance
451
445
  */
452
446
  static get i() {
453
- return f._instance || (f._instance = new f()), f._instance;
447
+ return s._instance || (s._instance = new s()), s._instance;
454
448
  }
455
449
  /**
456
450
  * Registers a new element in the registry and updates the Klaim object structure
@@ -465,15 +459,15 @@ const f = class f {
465
459
  registerElement(t) {
466
460
  const e = this._currentParent;
467
461
  e && (t.parent = this.getFullPath(e));
468
- const a = this.getElementKey(t);
469
- if (this._elements.set(a, t), t.type === "api" || t.type === "group") {
470
- let r = R;
462
+ const r = this.getElementKey(t);
463
+ if (this._elements.set(r, t), t.type === "api" || t.type === "group") {
464
+ let a = R;
471
465
  if (e) {
472
466
  const i = this.getFullPath(e).split(".");
473
- for (const s of i)
474
- r[s] || (r[s] = {}), r = r[s];
467
+ for (const c of i)
468
+ a[c] || (a[c] = {}), a = a[c];
475
469
  }
476
- r[t.name] || (r[t.name] = {});
470
+ a[t.name] || (a[t.name] = {});
477
471
  }
478
472
  }
479
473
  /**
@@ -524,10 +518,10 @@ const f = class f {
524
518
  addToKlaimRoute(t) {
525
519
  if (!t.parent) return;
526
520
  let e = R;
527
- const a = t.parent.split(".");
528
- for (const r of a)
529
- e[r] || (e[r] = {}), e = e[r];
530
- e[t.name] = V(t.parent, t);
521
+ const r = t.parent.split(".");
522
+ for (const a of r)
523
+ e[a] || (e[a] = {}), e = e[a];
524
+ e[t.name] = H(t.parent, t);
531
525
  }
532
526
  /**
533
527
  * Generates a unique key for an element based on its path
@@ -548,11 +542,11 @@ const f = class f {
548
542
  if (!t) return "";
549
543
  if (!t.parent) return t.name;
550
544
  const e = [t.name];
551
- let a = t;
552
- for (; a.parent; ) {
553
- const r = this._elements.get(a.parent);
554
- if (!r) break;
555
- e.unshift(r.name), a = r;
545
+ let r = t;
546
+ for (; r.parent; ) {
547
+ const a = this._elements.get(r.parent);
548
+ if (!a) break;
549
+ e.unshift(a.name), r = a;
556
550
  }
557
551
  return e.join(".");
558
552
  }
@@ -574,8 +568,8 @@ const f = class f {
574
568
  */
575
569
  getChildren(t) {
576
570
  const e = [];
577
- return this._elements.forEach((a) => {
578
- a.parent === t && e.push(a);
571
+ return this._elements.forEach((r) => {
572
+ r.parent === t && e.push(r);
579
573
  }), e;
580
574
  }
581
575
  /**
@@ -585,7 +579,7 @@ const f = class f {
585
579
  * @returns The updated element
586
580
  */
587
581
  static updateElement(t) {
588
- return f.i._elements.get(f.i.getElementKey(t)) || t;
582
+ return s.i._elements.get(s.i.getElementKey(t)) || t;
589
583
  }
590
584
  /**
591
585
  * Retrieves an API element by name, searching through the entire registry if necessary
@@ -596,9 +590,9 @@ const f = class f {
596
590
  getApi(t) {
597
591
  const e = this._elements.get(t);
598
592
  if (!e) {
599
- for (const [a, r] of this._elements.entries())
600
- if (r.type === "api" && a.endsWith(`.${t}`))
601
- return r;
593
+ for (const [r, a] of this._elements.entries())
594
+ if (a.type === "api" && r.endsWith(`.${t}`))
595
+ return a;
602
596
  return;
603
597
  }
604
598
  return e.type === "api" ? e : this.findApi(e);
@@ -613,15 +607,13 @@ const f = class f {
613
607
  findApi(t) {
614
608
  if (!t || !t.parent) return;
615
609
  const e = t.parent.split(".");
616
- for (let a = e.length; a >= 0; a--) {
617
- const r = e.slice(0, a).join("."), i = this._elements.get(r);
618
- if ((i == null ? void 0 : i.type) === "api") return i;
610
+ for (let r = e.length; r >= 0; r--) {
611
+ const a = e.slice(0, r).join("."), i = this._elements.get(a);
612
+ if (i?.type === "api") return i;
619
613
  }
620
614
  }
621
- };
622
- o(f, "_instance");
623
- let c = f;
624
- class U extends k {
615
+ }
616
+ class _ extends C {
625
617
  /**
626
618
  * Creates and registers a new API instance with the given configuration
627
619
  *
@@ -640,13 +632,13 @@ class U extends k {
640
632
  * });
641
633
  * ```
642
634
  */
643
- static create(t, e, a, r = {}) {
644
- const i = _(t);
635
+ static create(t, e, r, a = {}) {
636
+ const i = E(t);
645
637
  i !== t && console.warn(`API name "${t}" has been camelCased to "${i}"`);
646
- const s = new U(i, e, r), l = c.i.getCurrentParent();
647
- c.i.registerElement(s);
648
- const u = l ? c.i.getFullPath(l) : "", p = u ? `${u}.${i}` : i;
649
- return c.i.setCurrentParent(p), a(), l ? c.i.setCurrentParent(c.i.getFullPath(l)) : c.i.clearCurrentParent(), s;
638
+ const c = new _(i, e, a), o = s.i.getCurrentParent();
639
+ s.i.registerElement(c);
640
+ const l = o ? s.i.getFullPath(o) : "", h = l ? `${l}.${i}` : i;
641
+ return s.i.setCurrentParent(h), r(), o ? s.i.setCurrentParent(s.i.getFullPath(o)) : s.i.clearCurrentParent(), c;
650
642
  }
651
643
  /**
652
644
  * Creates a new API instance
@@ -657,11 +649,11 @@ class U extends k {
657
649
  * @param headers - Optional default headers for all routes
658
650
  * @private
659
651
  */
660
- constructor(t, e, a = {}) {
661
- super("api", t, e, a);
652
+ constructor(t, e, r = {}) {
653
+ super("api", t, e, r);
662
654
  }
663
655
  }
664
- class x extends k {
656
+ class k extends C {
665
657
  /**
666
658
  * Creates a new group and registers it in the Registry.
667
659
  * Supports nested groups and inheritable configurations.
@@ -687,10 +679,10 @@ class x extends k {
687
679
  * ```
688
680
  */
689
681
  static create(t, e) {
690
- const a = _(t), r = c.i.getCurrentParent(), i = r ? c.i.getFullPath(r) : "", s = i ? `${i}.${a}` : a, l = new x(a, "");
691
- a !== t && console.warn(`Group name "${t}" has been camelCased to "${a}"`), c.i.registerElement(l);
692
- const u = c.i.getCurrentParent();
693
- return c.i.setCurrentParent(s), e(), u ? c.i.setCurrentParent(c.i.getFullPath(u)) : c.i.clearCurrentParent(), l;
682
+ const r = E(t), a = s.i.getCurrentParent(), i = a ? s.i.getFullPath(a) : "", c = i ? `${i}.${r}` : r, o = new k(r, "");
683
+ r !== t && console.warn(`Group name "${t}" has been camelCased to "${r}"`), s.i.registerElement(o);
684
+ const l = s.i.getCurrentParent();
685
+ return s.i.setCurrentParent(c), e(), l ? s.i.setCurrentParent(s.i.getFullPath(l)) : s.i.clearCurrentParent(), o;
694
686
  }
695
687
  /**
696
688
  * Creates a new Group instance.
@@ -701,8 +693,8 @@ class x extends k {
701
693
  * @param headers - Optional headers shared by all routes in the group
702
694
  * @private
703
695
  */
704
- constructor(t, e, a = {}) {
705
- super("group", t, e, a);
696
+ constructor(t, e, r = {}) {
697
+ super("group", t, e, r);
706
698
  }
707
699
  /**
708
700
  * Enables caching for the group and all its children (routes and APIs).
@@ -720,7 +712,7 @@ class x extends k {
720
712
  * ```
721
713
  */
722
714
  withCache(t = 20) {
723
- return super.withCache(t), c.i.getChildren(c.i.getFullPath(this)).forEach((e) => {
715
+ return super.withCache(t), s.i.getChildren(s.i.getFullPath(this)).forEach((e) => {
724
716
  e.cache || (e.cache = t);
725
717
  }), this;
726
718
  }
@@ -740,7 +732,7 @@ class x extends k {
740
732
  * ```
741
733
  */
742
734
  withRetry(t = 2) {
743
- return super.withRetry(t), c.i.getChildren(c.i.getFullPath(this)).forEach((e) => {
735
+ return super.withRetry(t), s.i.getChildren(s.i.getFullPath(this)).forEach((e) => {
744
736
  e.retry || (e.retry = t);
745
737
  }), this;
746
738
  }
@@ -752,9 +744,9 @@ class x extends k {
752
744
  * @param message - Error message if the timeout is reached
753
745
  * @returns The current instance for chaining
754
746
  */
755
- withTimeout(t = $.duration, e = $.message) {
756
- return super.withTimeout(t, e), c.i.getChildren(c.i.getFullPath(this)).forEach((a) => {
757
- a.timeout || (a.timeout = { duration: t, message: e });
747
+ withTimeout(t = d.duration, e = d.message) {
748
+ return super.withTimeout(t, e), s.i.getChildren(s.i.getFullPath(this)).forEach((r) => {
749
+ r.timeout || (r.timeout = { duration: t, message: e });
758
750
  }), this;
759
751
  }
760
752
  /**
@@ -775,7 +767,7 @@ class x extends k {
775
767
  * ```
776
768
  */
777
769
  before(t) {
778
- return super.before(t), c.i.getChildren(c.i.getFullPath(this)).forEach((e) => {
770
+ return super.before(t), s.i.getChildren(s.i.getFullPath(this)).forEach((e) => {
779
771
  e.callbacks.before || (e.callbacks.before = t);
780
772
  }), this;
781
773
  }
@@ -797,7 +789,7 @@ class x extends k {
797
789
  * ```
798
790
  */
799
791
  after(t) {
800
- return super.after(t), c.i.getChildren(c.i.getFullPath(this)).forEach((e) => {
792
+ return super.after(t), s.i.getChildren(s.i.getFullPath(this)).forEach((e) => {
801
793
  e.callbacks.after || (e.callbacks.after = t);
802
794
  }), this;
803
795
  }
@@ -819,12 +811,12 @@ class x extends k {
819
811
  * ```
820
812
  */
821
813
  onCall(t) {
822
- return super.onCall(t), c.i.getChildren(c.i.getFullPath(this)).forEach((e) => {
814
+ return super.onCall(t), s.i.getChildren(s.i.getFullPath(this)).forEach((e) => {
823
815
  e.callbacks.call || (e.callbacks.call = t);
824
816
  }), this;
825
817
  }
826
818
  }
827
- class I extends k {
819
+ class F extends C {
828
820
  /**
829
821
  * Creates a new Route instance.
830
822
  *
@@ -833,8 +825,8 @@ class I extends k {
833
825
  * @param headers - Optional HTTP headers specific to this route
834
826
  * @param method - HTTP method for this route
835
827
  */
836
- constructor(t, e, a = {}, r = "GET") {
837
- super("route", t, e, a), this.method = r, this.detectArguments();
828
+ constructor(t, e, r = {}, a = "GET") {
829
+ super("route", t, e, r), this.method = a, this.detectArguments();
838
830
  }
839
831
  /**
840
832
  * Internal helper to create and register a new route.
@@ -846,9 +838,9 @@ class I extends k {
846
838
  * @returns The created route element
847
839
  * @private
848
840
  */
849
- static createRoute(t, e, a = {}, r) {
850
- const i = new I(t, e, a, r);
851
- return c.i.registerRoute(i), i;
841
+ static createRoute(t, e, r = {}, a) {
842
+ const i = new F(t, e, r, a);
843
+ return s.i.registerRoute(i), i;
852
844
  }
853
845
  /**
854
846
  * Creates a GET route.
@@ -863,11 +855,11 @@ class I extends k {
863
855
  * Route.get("getUser", "/users/[id]");
864
856
  * ```
865
857
  */
866
- static get(t, e, a = {}) {
858
+ static get(t, e, r = {}) {
867
859
  return this.createRoute(
868
860
  t,
869
861
  e,
870
- a,
862
+ r,
871
863
  "GET"
872
864
  /* GET */
873
865
  );
@@ -884,11 +876,11 @@ class I extends k {
884
876
  * Route.post("createUser", "/users");
885
877
  * ```
886
878
  */
887
- static post(t, e, a = {}) {
879
+ static post(t, e, r = {}) {
888
880
  return this.createRoute(
889
881
  t,
890
882
  e,
891
- a,
883
+ r,
892
884
  "POST"
893
885
  /* POST */
894
886
  );
@@ -905,11 +897,11 @@ class I extends k {
905
897
  * Route.put("updateUser", "/users/[id]");
906
898
  * ```
907
899
  */
908
- static put(t, e, a = {}) {
900
+ static put(t, e, r = {}) {
909
901
  return this.createRoute(
910
902
  t,
911
903
  e,
912
- a,
904
+ r,
913
905
  "PUT"
914
906
  /* PUT */
915
907
  );
@@ -926,11 +918,11 @@ class I extends k {
926
918
  * Route.delete("deleteUser", "/users/[id]");
927
919
  * ```
928
920
  */
929
- static delete(t, e, a = {}) {
921
+ static delete(t, e, r = {}) {
930
922
  return this.createRoute(
931
923
  t,
932
924
  e,
933
- a,
925
+ r,
934
926
  "DELETE"
935
927
  /* DELETE */
936
928
  );
@@ -947,11 +939,11 @@ class I extends k {
947
939
  * Route.patch("updateUserStatus", "/users/[id]/status");
948
940
  * ```
949
941
  */
950
- static patch(t, e, a = {}) {
942
+ static patch(t, e, r = {}) {
951
943
  return this.createRoute(
952
944
  t,
953
945
  e,
954
- a,
946
+ r,
955
947
  "PATCH"
956
948
  /* PATCH */
957
949
  );
@@ -968,11 +960,11 @@ class I extends k {
968
960
  * Route.options("userOptions", "/users");
969
961
  * ```
970
962
  */
971
- static options(t, e, a = {}) {
963
+ static options(t, e, r = {}) {
972
964
  return this.createRoute(
973
965
  t,
974
966
  e,
975
- a,
967
+ r,
976
968
  "OPTIONS"
977
969
  /* OPTIONS */
978
970
  );
@@ -987,8 +979,8 @@ class I extends k {
987
979
  detectArguments() {
988
980
  const t = this.url.match(/\[([^\]]+)]/g);
989
981
  t && t.forEach((e) => {
990
- const a = e.replace("[", "").replace("]", "");
991
- this.arguments.add(a);
982
+ const r = e.replace("[", "").replace("]", "");
983
+ this.arguments.add(r);
992
984
  });
993
985
  }
994
986
  /**
@@ -1007,10 +999,10 @@ class I extends k {
1007
999
  }
1008
1000
  }
1009
1001
  export {
1010
- U as Api,
1011
- x as Group,
1012
- v as Hook,
1002
+ _ as Api,
1003
+ k as Group,
1004
+ M as Hook,
1013
1005
  R as Klaim,
1014
- c as Registry,
1015
- I as Route
1006
+ s as Registry,
1007
+ F as Route
1016
1008
  };
package/dist/klaim.umd.js CHANGED
@@ -1 +1 @@
1
- (function(u,p){typeof exports=="object"&&typeof module<"u"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(u=typeof globalThis<"u"?globalThis:u||self,p(u.klaim={}))})(this,function(u){"use strict";var Y=Object.defineProperty;var Z=(u,p,w)=>p in u?Y(u,p,{enumerable:!0,configurable:!0,writable:!0,value:w}):u[p]=w;var o=(u,p,w)=>Z(u,typeof p!="symbol"?p+"":p,w);function p(n){return n.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}function w(n){return n.trim().replace(/^\/|\/$/g,"")}const O={limit:5,duration:10},k=new Map;function D(n,t){const e=Date.now(),a=t.duration*1e3;let r=k.get(n);r||(r={timestamps:[]},k.set(n,r));const i=r.timestamps.filter(s=>e-s<a);return i.length>=t.limit?!1:(i.push(e),r.timestamps=i,!0)}function K(n,t){const e=k.get(n);if(!e||e.timestamps.length<t.limit)return 0;const a=Date.now(),r=t.duration*1e3,l=[...e.timestamps].sort((h,g)=>h-g)[0]+r-a;return Math.max(0,l)}const $={duration:5,message:"Request timed out"};async function G(n,t){const{duration:e,message:a}=t;return Promise.race([n,new Promise((r,i)=>{const s=setTimeout(()=>{clearTimeout(s),i(new Error(a))},e*1e3)})])}const M={page:1,pageParam:"page",limit:10,limitParam:"limit"};class _{constructor(t,e,a,r={}){o(this,"type");o(this,"name");o(this,"url");o(this,"headers");o(this,"parent");o(this,"method");o(this,"arguments",new Set);o(this,"schema");o(this,"pagination");o(this,"callbacks",{before:null,after:null,call:null});o(this,"cache",!1);o(this,"retry",!1);o(this,"rate",!1);o(this,"timeout",!1);o(this,"withCache",(t=20)=>(this.cache=t,this));o(this,"withRetry",(t=2)=>(this.retry=t,this));o(this,"withRate",(t={})=>(this.rate={...O,...t},this));o(this,"withTimeout",(t=$.duration,e=$.message)=>(this.timeout={duration:t,message:e},this));this.type=t,this.name=p(e),this.name!==e&&console.warn(`Name "${e}" has been camelCased to "${this.name}"`),this.url=w(a),this.headers=r||{}}before(t){return this.callbacks.before=t,this}after(t){return this.callbacks.after=t,this}onCall(t){return this.callbacks.call=t,this}withPagination(t={}){return this.pagination={...M,...t},this}}const d=class d{constructor(){o(this,"cache");this.cache=new Map}static get i(){return d._instance||(d._instance=new d),d._instance}set(t,e,a=0){const r=Date.now()+a;this.cache.set(t,{data:e,expiry:r})}has(t){const e=this.cache.get(t);return e?Date.now()>e.expiry?(this.cache.delete(t),!1):!0:!1}get(t){return this.has(t)?this.cache.get(t).data:null}};o(d,"_instance");let y=d;function x(n){let a=2166136261;for(let i=0;i<n.length;i++)a^=n.charCodeAt(i),a*=16777619;let r=(a>>>0).toString(16).padStart(8,"0");for(;r.length<32;)a^=r.charCodeAt(r.length%r.length),a*=16777619,r+=(a>>>0).toString(16).padStart(8,"0");return r.substring(0,32)}async function j(n,t,e){const a=`${n.toString()}${JSON.stringify(t)}`,r=x(a);if(y.i.has(r))return y.i.get(r);const s=await(await fetch(n,t)).json();return y.i.set(r,s,e),s}class F{static subscribe(t,e){this._callbacks.set(t,e)}static run(t){const e=this._callbacks.get(t);e&&e()}}o(F,"_callbacks",new Map);const S={};function H(n,t){return async(...e)=>{if(t.pagination){const[i=0,s={},l={}]=e;return L(n,t,i,s,l)}const[a={},r={}]=e;return L(n,t,void 0,a,r)}}async function L(n,t,e,a={},r={}){const i=n.split(".");let s;for(let b=0;b<i.length;b++){const U=i[b];if(s=c.i.getApi(U),s)break}if(!t||!s||t.type!=="route"||s.type!=="api")throw new Error(`Invalid path: ${n}.${t.name}`);let l=J(`${s.url}/${t.url}`,t,a);if(t.pagination&&typeof e<"u"){const{pageParam:b="page",limit:U=10,limitParam:Q="limit"}=t.pagination,I=new URLSearchParams;I.append(b,String(e)),I.append(Q,String(U));const X=l.includes("?")?"&":"?";l=`${l}${X}${I.toString()}`}let h={};r&&t.method!=="GET"&&(h.body=JSON.stringify(r)),h.headers={"Content-Type":"application/json",...s.headers,...t.headers},h.method=t.method;const{beforeRoute:g,beforeApi:T,beforeUrl:A,beforeConfig:f}=V({route:t,api:s,url:l,config:h});l=A,h=f,c.updateElement(T),c.updateElement(g);let P=await W(s,t,l,h);t.schema&&"validate"in t.schema&&(P=await t.schema.validate(P));const{afterRoute:C,afterApi:E,afterData:B}=z({route:t,api:s,response:P,data:P});return c.updateElement(E),c.updateElement(C),F.run(`${s.name}.${t.name}`),B}async function q(n,t,e,a){return n?await j(t,e,a.cache):await(await fetch(t,e)).json()}async function W(n,t,e,a){var T,A;const r=n.cache||t.cache,i=t.retry||n.retry||0,s=t.timeout||n.timeout;if(t.rate){const f=`${n.name}.${t.name}`;if(!D(f,t.rate)){const C=K(f,t.rate),E=Math.ceil(C/1e3);throw new Error(`Rate limit exceeded for ${f}. Try again in ${E} seconds.`)}}else if(n.rate){const f=`${n.name}`;if(!D(f,n.rate)){const C=K(f,n.rate),E=Math.ceil(C/1e3);throw new Error(`Rate limit exceeded for ${n.name} API. Try again in ${E} seconds.`)}}let l,h=!1,g=0;for(;g<=i&&!h;)try{(T=t.callbacks)!=null&&T.call?t.callbacks.call({}):(A=n.callbacks)!=null&&A.call&&n.callbacks.call({});const f=q(!!r,e,a,n);l=s?await G(f,s):await f,h=!0}catch(f){if(g++,g>i)throw f.message||(f.message=`Failed to fetch ${e} after ${i} attempts`),f}return l}function J(n,t,e){let a=n;return t.arguments.forEach(r=>{if(e[r]===void 0)throw new Error(`Argument ${r} is missing`);a=a.replace(`[${r}]`,e[r])}),a}function V({route:n,api:t,url:e,config:a}){var i,s;const r=(s=(i=n.callbacks).before)==null?void 0:s.call(i,{route:n,api:t,url:e,config:a});return{beforeRoute:(r==null?void 0:r.route)||n,beforeApi:(r==null?void 0:r.api)||t,beforeUrl:(r==null?void 0:r.url)||e,beforeConfig:(r==null?void 0:r.config)||a}}function z({route:n,api:t,response:e,data:a}){var i,s;const r=(s=(i=n.callbacks).after)==null?void 0:s.call(i,{route:n,api:t,response:e,data:a});return{afterRoute:(r==null?void 0:r.route)||n,afterApi:(r==null?void 0:r.api)||t,afterResponse:(r==null?void 0:r.response)||e,afterData:(r==null?void 0:r.data)||a}}const m=class m{constructor(){o(this,"_elements",new Map);o(this,"_currentParent",null)}static get i(){return m._instance||(m._instance=new m),m._instance}registerElement(t){const e=this._currentParent;e&&(t.parent=this.getFullPath(e));const a=this.getElementKey(t);if(this._elements.set(a,t),t.type==="api"||t.type==="group"){let r=S;if(e){const i=this.getFullPath(e).split(".");for(const s of i)r[s]||(r[s]={}),r=r[s]}r[t.name]||(r[t.name]={})}}getCurrentParent(){return this._currentParent}setCurrentParent(t){const e=this._elements.get(t);if(!e||e.type!=="api"&&e.type!=="group")throw new Error(`Element ${t} not found or not a valid parent type`);this._currentParent=e}clearCurrentParent(){this._currentParent=null}registerRoute(t){if(!this._currentParent)throw new Error("No current parent set, use Route only inside Api or Group create callback");t.parent=this.getFullPath(this._currentParent);const e=this.getElementKey(t);this._elements.set(e,t),this.addToKlaimRoute(t)}addToKlaimRoute(t){if(!t.parent)return;let e=S;const a=t.parent.split(".");for(const r of a)e[r]||(e[r]={}),e=e[r];e[t.name]=H(t.parent,t)}getElementKey(t){return t?t.parent?`${t.parent}.${t.name}`:t.name:""}getFullPath(t){if(!t)return"";if(!t.parent)return t.name;const e=[t.name];let a=t;for(;a.parent;){const r=this._elements.get(a.parent);if(!r)break;e.unshift(r.name),a=r}return e.join(".")}getRoute(t,e){return this._elements.get(`${t}.${e}`)}getChildren(t){const e=[];return this._elements.forEach(a=>{a.parent===t&&e.push(a)}),e}static updateElement(t){return m.i._elements.get(m.i.getElementKey(t))||t}getApi(t){const e=this._elements.get(t);if(!e){for(const[a,r]of this._elements.entries())if(r.type==="api"&&a.endsWith(`.${t}`))return r;return}return e.type==="api"?e:this.findApi(e)}findApi(t){if(!t||!t.parent)return;const e=t.parent.split(".");for(let a=e.length;a>=0;a--){const r=e.slice(0,a).join("."),i=this._elements.get(r);if((i==null?void 0:i.type)==="api")return i}}};o(m,"_instance");let c=m;class R extends _{static create(t,e,a,r={}){const i=p(t);i!==t&&console.warn(`API name "${t}" has been camelCased to "${i}"`);const s=new R(i,e,r),l=c.i.getCurrentParent();c.i.registerElement(s);const h=l?c.i.getFullPath(l):"",g=h?`${h}.${i}`:i;return c.i.setCurrentParent(g),a(),l?c.i.setCurrentParent(c.i.getFullPath(l)):c.i.clearCurrentParent(),s}constructor(t,e,a={}){super("api",t,e,a)}}class v extends _{static create(t,e){const a=p(t),r=c.i.getCurrentParent(),i=r?c.i.getFullPath(r):"",s=i?`${i}.${a}`:a,l=new v(a,"");a!==t&&console.warn(`Group name "${t}" has been camelCased to "${a}"`),c.i.registerElement(l);const h=c.i.getCurrentParent();return c.i.setCurrentParent(s),e(),h?c.i.setCurrentParent(c.i.getFullPath(h)):c.i.clearCurrentParent(),l}constructor(t,e,a={}){super("group",t,e,a)}withCache(t=20){return super.withCache(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.cache||(e.cache=t)}),this}withRetry(t=2){return super.withRetry(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.retry||(e.retry=t)}),this}withTimeout(t=$.duration,e=$.message){return super.withTimeout(t,e),c.i.getChildren(c.i.getFullPath(this)).forEach(a=>{a.timeout||(a.timeout={duration:t,message:e})}),this}before(t){return super.before(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.callbacks.before||(e.callbacks.before=t)}),this}after(t){return super.after(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.callbacks.after||(e.callbacks.after=t)}),this}onCall(t){return super.onCall(t),c.i.getChildren(c.i.getFullPath(this)).forEach(e=>{e.callbacks.call||(e.callbacks.call=t)}),this}}class N extends _{constructor(t,e,a={},r="GET"){super("route",t,e,a),this.method=r,this.detectArguments()}static createRoute(t,e,a={},r){const i=new N(t,e,a,r);return c.i.registerRoute(i),i}static get(t,e,a={}){return this.createRoute(t,e,a,"GET")}static post(t,e,a={}){return this.createRoute(t,e,a,"POST")}static put(t,e,a={}){return this.createRoute(t,e,a,"PUT")}static delete(t,e,a={}){return this.createRoute(t,e,a,"DELETE")}static patch(t,e,a={}){return this.createRoute(t,e,a,"PATCH")}static options(t,e,a={}){return this.createRoute(t,e,a,"OPTIONS")}detectArguments(){const t=this.url.match(/\[([^\]]+)]/g);t&&t.forEach(e=>{const a=e.replace("[","").replace("]","");this.arguments.add(a)})}validate(t){return this.schema=t,this}}u.Api=R,u.Group=v,u.Hook=F,u.Klaim=S,u.Registry=c,u.Route=N,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
1
+ (function(h,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(h=typeof globalThis<"u"?globalThis:h||self,g(h.klaim={}))})(this,function(h){"use strict";function g(n){return n.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}function N(n){return n.trim().replace(/^\/|\/$/g,"")}const U={limit:5,duration:10},y=new Map;function k(n,t){const e=Date.now(),r=t.duration*1e3;let a=y.get(n);a||(a={timestamps:[]},y.set(n,a));const s=a.timestamps.filter(c=>e-c<r);return s.length>=t.limit?!1:(s.push(e),a.timestamps=s,!0)}function F(n,t){const e=y.get(n);if(!e||e.timestamps.length<t.limit)return 0;const r=Date.now(),a=t.duration*1e3,o=[...e.timestamps].sort((l,f)=>l-f)[0]+a-r;return Math.max(0,o)}const P={duration:5,message:"Request timed out"};async function I(n,t){const{duration:e,message:r}=t;return Promise.race([n,new Promise((a,s)=>{const c=setTimeout(()=>{clearTimeout(c),s(new Error(r))},e*1e3)})])}const D={page:1,pageParam:"page",limit:10,limitParam:"limit"};class b{type;name;url;headers;parent;method;arguments=new Set;schema;pagination;callbacks={before:null,after:null,call:null};cache=!1;retry=!1;rate=!1;timeout=!1;constructor(t,e,r,a={}){this.type=t,this.name=g(e),this.name!==e&&console.warn(`Name "${e}" has been camelCased to "${this.name}"`),this.url=N(r),this.headers=a||{}}before(t){return this.callbacks.before=t,this}after(t){return this.callbacks.after=t,this}onCall(t){return this.callbacks.call=t,this}withCache=(t=20)=>(this.cache=t,this);withRetry=(t=2)=>(this.retry=t,this);withPagination(t={}){return this.pagination={...D,...t},this}withRate=(t={})=>(this.rate={...U,...t},this);withTimeout=(t=P.duration,e=P.message)=>(this.timeout={duration:t,message:e},this)}class p{static _instance;cache;constructor(){this.cache=new Map}static get i(){return p._instance||(p._instance=new p),p._instance}set(t,e,r=0){const a=Date.now()+r;this.cache.set(t,{data:e,expiry:a})}has(t){const e=this.cache.get(t);return e?Date.now()>e.expiry?(this.cache.delete(t),!1):!0:!1}get(t){return this.has(t)?this.cache.get(t).data:null}}function K(n){let r=2166136261;for(let s=0;s<n.length;s++)r^=n.charCodeAt(s),r*=16777619;let a=(r>>>0).toString(16).padStart(8,"0");for(;a.length<32;)r^=a.charCodeAt(a.length%a.length),r*=16777619,a+=(r>>>0).toString(16).padStart(8,"0");return a.substring(0,32)}async function L(n,t,e){const r=`${n.toString()}${JSON.stringify(t)}`,a=K(r);if(p.i.has(a))return p.i.get(a);const c=await(await fetch(n,t)).json();return p.i.set(a,c,e),c}class S{static _callbacks=new Map;static subscribe(t,e){this._callbacks.set(t,e)}static run(t){const e=this._callbacks.get(t);e&&e()}}const E={};function O(n,t){return async(...e)=>{if(t.pagination){const[s=0,c={},o={}]=e;return v(n,t,s,c,o)}const[r={},a={}]=e;return v(n,t,void 0,r,a)}}async function v(n,t,e,r={},a={}){const s=n.split(".");let c;for(let w=0;w<s.length;w++){const A=s[w];if(c=i.i.getApi(A),c)break}if(!t||!c||t.type!=="route"||c.type!=="api")throw new Error(`Invalid path: ${n}.${t.name}`);let o=x(`${c.url}/${t.url}`,t,r);if(t.pagination&&typeof e<"u"){const{pageParam:w="page",limit:A=10,limitParam:V="limit"}=t.pagination,_=new URLSearchParams;_.append(w,String(e)),_.append(V,String(A));const z=o.includes("?")?"&":"?";o=`${o}${z}${_.toString()}`}let l={};a&&t.method!=="GET"&&(l.body=JSON.stringify(a)),l.headers={"Content-Type":"application/json",...c.headers,...t.headers},l.method=t.method;const{beforeRoute:f,beforeApi:u,beforeUrl:R,beforeConfig:d}=j({route:t,api:c,url:o,config:l});o=R,l=d,i.updateElement(u),i.updateElement(f);let m=await M(c,t,o,l);t.schema&&"validate"in t.schema&&(m=await t.schema.validate(m));const{afterRoute:q,afterApi:W,afterData:J}=H({route:t,api:c,response:m,data:m});return i.updateElement(W),i.updateElement(q),S.run(`${c.name}.${t.name}`),J}async function G(n,t,e,r){return n?await L(t,e,r.cache):await(await fetch(t,e)).json()}async function M(n,t,e,r){const a=n.cache||t.cache,s=t.retry||n.retry||0,c=t.timeout||n.timeout;if(t.rate){const u=`${n.name}.${t.name}`;if(!k(u,t.rate)){const d=F(u,t.rate),m=Math.ceil(d/1e3);throw new Error(`Rate limit exceeded for ${u}. Try again in ${m} seconds.`)}}else if(n.rate){const u=`${n.name}`;if(!k(u,n.rate)){const d=F(u,n.rate),m=Math.ceil(d/1e3);throw new Error(`Rate limit exceeded for ${n.name} API. Try again in ${m} seconds.`)}}let o,l=!1,f=0;for(;f<=s&&!l;)try{t.callbacks?.call?t.callbacks.call({}):n.callbacks?.call&&n.callbacks.call({});const u=G(!!a,e,r,n);o=c?await I(u,c):await u,l=!0}catch(u){if(f++,f>s)throw u.message||(u.message=`Failed to fetch ${e} after ${s} attempts`),u}return o}function x(n,t,e){let r=n;return t.arguments.forEach(a=>{if(e[a]===void 0)throw new Error(`Argument ${a} is missing`);r=r.replace(`[${a}]`,e[a])}),r}function j({route:n,api:t,url:e,config:r}){const a=n.callbacks.before?.({route:n,api:t,url:e,config:r});return{beforeRoute:a?.route||n,beforeApi:a?.api||t,beforeUrl:a?.url||e,beforeConfig:a?.config||r}}function H({route:n,api:t,response:e,data:r}){const a=n.callbacks.after?.({route:n,api:t,response:e,data:r});return{afterRoute:a?.route||n,afterApi:a?.api||t,afterResponse:a?.response||e,afterData:a?.data||r}}class i{static _instance;_elements=new Map;_currentParent=null;constructor(){}static get i(){return i._instance||(i._instance=new i),i._instance}registerElement(t){const e=this._currentParent;e&&(t.parent=this.getFullPath(e));const r=this.getElementKey(t);if(this._elements.set(r,t),t.type==="api"||t.type==="group"){let a=E;if(e){const s=this.getFullPath(e).split(".");for(const c of s)a[c]||(a[c]={}),a=a[c]}a[t.name]||(a[t.name]={})}}getCurrentParent(){return this._currentParent}setCurrentParent(t){const e=this._elements.get(t);if(!e||e.type!=="api"&&e.type!=="group")throw new Error(`Element ${t} not found or not a valid parent type`);this._currentParent=e}clearCurrentParent(){this._currentParent=null}registerRoute(t){if(!this._currentParent)throw new Error("No current parent set, use Route only inside Api or Group create callback");t.parent=this.getFullPath(this._currentParent);const e=this.getElementKey(t);this._elements.set(e,t),this.addToKlaimRoute(t)}addToKlaimRoute(t){if(!t.parent)return;let e=E;const r=t.parent.split(".");for(const a of r)e[a]||(e[a]={}),e=e[a];e[t.name]=O(t.parent,t)}getElementKey(t){return t?t.parent?`${t.parent}.${t.name}`:t.name:""}getFullPath(t){if(!t)return"";if(!t.parent)return t.name;const e=[t.name];let r=t;for(;r.parent;){const a=this._elements.get(r.parent);if(!a)break;e.unshift(a.name),r=a}return e.join(".")}getRoute(t,e){return this._elements.get(`${t}.${e}`)}getChildren(t){const e=[];return this._elements.forEach(r=>{r.parent===t&&e.push(r)}),e}static updateElement(t){return i.i._elements.get(i.i.getElementKey(t))||t}getApi(t){const e=this._elements.get(t);if(!e){for(const[r,a]of this._elements.entries())if(a.type==="api"&&r.endsWith(`.${t}`))return a;return}return e.type==="api"?e:this.findApi(e)}findApi(t){if(!t||!t.parent)return;const e=t.parent.split(".");for(let r=e.length;r>=0;r--){const a=e.slice(0,r).join("."),s=this._elements.get(a);if(s?.type==="api")return s}}}class C extends b{static create(t,e,r,a={}){const s=g(t);s!==t&&console.warn(`API name "${t}" has been camelCased to "${s}"`);const c=new C(s,e,a),o=i.i.getCurrentParent();i.i.registerElement(c);const l=o?i.i.getFullPath(o):"",f=l?`${l}.${s}`:s;return i.i.setCurrentParent(f),r(),o?i.i.setCurrentParent(i.i.getFullPath(o)):i.i.clearCurrentParent(),c}constructor(t,e,r={}){super("api",t,e,r)}}class $ extends b{static create(t,e){const r=g(t),a=i.i.getCurrentParent(),s=a?i.i.getFullPath(a):"",c=s?`${s}.${r}`:r,o=new $(r,"");r!==t&&console.warn(`Group name "${t}" has been camelCased to "${r}"`),i.i.registerElement(o);const l=i.i.getCurrentParent();return i.i.setCurrentParent(c),e(),l?i.i.setCurrentParent(i.i.getFullPath(l)):i.i.clearCurrentParent(),o}constructor(t,e,r={}){super("group",t,e,r)}withCache(t=20){return super.withCache(t),i.i.getChildren(i.i.getFullPath(this)).forEach(e=>{e.cache||(e.cache=t)}),this}withRetry(t=2){return super.withRetry(t),i.i.getChildren(i.i.getFullPath(this)).forEach(e=>{e.retry||(e.retry=t)}),this}withTimeout(t=P.duration,e=P.message){return super.withTimeout(t,e),i.i.getChildren(i.i.getFullPath(this)).forEach(r=>{r.timeout||(r.timeout={duration:t,message:e})}),this}before(t){return super.before(t),i.i.getChildren(i.i.getFullPath(this)).forEach(e=>{e.callbacks.before||(e.callbacks.before=t)}),this}after(t){return super.after(t),i.i.getChildren(i.i.getFullPath(this)).forEach(e=>{e.callbacks.after||(e.callbacks.after=t)}),this}onCall(t){return super.onCall(t),i.i.getChildren(i.i.getFullPath(this)).forEach(e=>{e.callbacks.call||(e.callbacks.call=t)}),this}}class T extends b{constructor(t,e,r={},a="GET"){super("route",t,e,r),this.method=a,this.detectArguments()}static createRoute(t,e,r={},a){const s=new T(t,e,r,a);return i.i.registerRoute(s),s}static get(t,e,r={}){return this.createRoute(t,e,r,"GET")}static post(t,e,r={}){return this.createRoute(t,e,r,"POST")}static put(t,e,r={}){return this.createRoute(t,e,r,"PUT")}static delete(t,e,r={}){return this.createRoute(t,e,r,"DELETE")}static patch(t,e,r={}){return this.createRoute(t,e,r,"PATCH")}static options(t,e,r={}){return this.createRoute(t,e,r,"OPTIONS")}detectArguments(){const t=this.url.match(/\[([^\]]+)]/g);t&&t.forEach(e=>{const r=e.replace("[","").replace("]","");this.arguments.add(r)})}validate(t){return this.schema=t,this}}h.Api=C,h.Group=$,h.Hook=S,h.Klaim=E,h.Registry=i,h.Route=T,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klaim",
3
- "version": "1.11.7",
3
+ "version": "1.11.8",
4
4
  "author": "antharuu",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,18 +13,18 @@
13
13
  "@stylistic/eslint-plugin": "5.0.0",
14
14
  "@types/bun": "^1.2.17",
15
15
  "@types/eslint__js": "9.14.0",
16
- "@types/node": "^24.0.3",
16
+ "@types/node": "^24.0.4",
17
17
  "@vitest/coverage-v8": "^3.2.4",
18
18
  "@vitest/ui": "^3.2.4",
19
19
  "dotenv-cli": "^8.0.0",
20
20
  "eslint": "9.29.0",
21
- "eslint-plugin-jsdoc": "51.2.2",
21
+ "eslint-plugin-jsdoc": "51.2.3",
22
22
  "eslint-plugin-simple-import-sort": "12.1.1",
23
23
  "jsdom": "^26.1.0",
24
24
  "release-it": "^19.0.3",
25
25
  "typescript": "5.8",
26
26
  "typescript-eslint": "8.35",
27
- "vite": "^6.3.5",
27
+ "vite": "^7.0.0",
28
28
  "vitest": "^3.2.4",
29
29
  "yup": "^1.6.1"
30
30
  },