klaim 1.7.0-alpha.2 → 1.7.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/README.md CHANGED
@@ -3,14 +3,19 @@
3
3
  ## 📚 Table of Contents
4
4
 
5
5
  - [Features](#-features)
6
+ - [Next features](#-next-features)
6
7
  - [Installation](#-installation)
7
8
  - [Usage](#-usage)
8
9
  - [Basic API Configuration](#basic-api-configuration)
9
10
  - [Route Definition](#route-definition)
10
11
  - [Request Handling](#request-handling)
12
+ - [Groups](#groups)
13
+ - [API Groups](#api-groups)
14
+ - [Route Groups](#route-groups)
15
+ - [Nested Groups](#nested-groups)
16
+ - [Group Configuration](#group-configuration)
11
17
  - [Middleware Usage](#middleware-usage)
12
18
  - [Hook Subscription](#hook-subscription)
13
- - [Group Usage](#group-usage)
14
19
  - [Caching Requests](#caching-requests)
15
20
  - [Retry Mechanism](#retry-mechanism)
16
21
  - [Response Validation](#response-validation)
@@ -21,17 +26,26 @@
21
26
  ## 🚀 Features
22
27
 
23
28
  - **Efficient API Management**: Easily manage multiple APIs with streamlined integration and interaction capabilities.
29
+ - **API Grouping**: Organize related APIs into logical groups with shared settings and configuration.
30
+ - **Route Grouping**: Organize related routes into logical groups with inherited settings.
24
31
  - **Request Recording**: Seamlessly track requests for debugging and monitoring.
25
32
  - **User Experience Optimization**: Focused on performance and usability for a smooth user experience.
26
33
  - **Lightweight**: Minimal footprint for fast load times and minimal performance impact.
27
34
  - **Middleware Support**: Easily add middleware to modify requests and responses (`before` and `after`).
28
35
  - **Hook System**: Subscribe to hooks to monitor and react to specific events.
29
- - **Group Organization**: Organize related routes into logical groups with inherited settings.
30
36
  - **Caching**: Enable caching on requests to reduce network load and improve performance.
31
37
  - **Retry Mechanism**: Automatically retry failed requests to enhance reliability.
32
38
  - **TypeScript Support**: Fully typed for enhanced code quality and developer experience.
33
39
  - **Response Validation**: Validate responses using schemas for increased reliability and consistency.
34
40
 
41
+ ## ⌛ Next features
42
+
43
+ - [ ] Pagination (Version: 1.8)
44
+ - [ ] Rate Limiting (Version: 1.9)
45
+ - [ ] Login (Version: 1.10)
46
+ - [ ] Time Out (Version: 1.11)
47
+ - [ ] Error Handling (Version: 1.12)
48
+
35
49
  ## 📥 Installation
36
50
 
37
51
  Install Klaim via npm:
@@ -76,19 +90,147 @@ Api.create("hello", "https://jsonplaceholder.typicode.com/", () => {
76
90
 
77
91
  ### Route Definition
78
92
 
79
- Define various routes within the API callback:
93
+ Routes represent endpoints in your API and can be defined with different HTTP methods. Routes can include parameters and custom configurations:
80
94
 
81
95
  ```typescript
82
- Api.create("hello", "https://jsonplaceholder.typicode.com/", () => {
83
- // Get a list of todos
84
- Route.get<Todo[]>("listTodos", "todos");
96
+ Api.create("api", "https://api.example.com", () => {
97
+ // Basic GET route
98
+ Route.get("listUsers", "/users");
99
+
100
+ // GET route with URL parameter
101
+ Route.get("getUser", "/users/[id]");
102
+
103
+ // POST route with custom headers and body
104
+ Route.post("createUser", "/users", {
105
+ "Content-Type": "application/json"
106
+ }, { userId: 1, name: "John Doe" });
107
+
108
+ // PUT route with parameter
109
+ Route.put("updateUser", "/users/[id]");
110
+
111
+ // DELETE route
112
+ Route.delete("deleteUser", "/users/[id]");
113
+
114
+ // PATCH route
115
+ Route.patch("updateUserStatus", "/users/[id]/status");
116
+
117
+ // OPTIONS route
118
+ Route.options("userOptions", "/users");
119
+ });
120
+ ```
85
121
 
86
- // Get a specific todo by id
87
- Route.get<Todo>("getTodo", "todos/[id]");
122
+ ### Groups
88
123
 
89
- // Add a new todo
90
- Route.post<Todo>("addTodo", "todos");
124
+ Klaim provides powerful grouping capabilities for both APIs and routes. Groups can be used to organize related elements, share configuration, and maintain a clean structure in your application.
125
+
126
+ #### API Groups
127
+
128
+ Organize multiple APIs that serve related purposes:
129
+
130
+ ```typescript
131
+ import {Group, Api, Route} from 'klaim';
132
+
133
+ // Create a group for user-related services
134
+ Group.create("userServices", () => {
135
+ // Authentication API
136
+ Api.create("auth", "https://auth.example.com", () => {
137
+ Route.post("login", "/login");
138
+ Route.post("register", "/register");
139
+ });
140
+
141
+ // User Management API
142
+ Api.create("users", "https://users.example.com", () => {
143
+ Route.get("list", "/users");
144
+ Route.get("getOne", "/users/[id]");
145
+ });
146
+ }).withRetry(3); // Apply retry mechanism to all APIs in the group
147
+
148
+ // Access grouped APIs
149
+ await Klaim.userServices.auth.login({}, { username: "user", password: "pass" });
150
+ await Klaim.userServices.users.list();
151
+ ```
152
+
153
+ #### Route Groups
154
+
155
+ Organize routes within an API into logical groups:
156
+
157
+ ```typescript
158
+ Api.create("hello", "https://api.example.com/", () => {
159
+ // Group user-related routes
160
+ Group.create("users", () => {
161
+ Route.get<User[]>("list", "/users");
162
+ Route.get<User>("getOne", "/users/[id]");
163
+ Route.post<User>("create", "/users");
164
+ }).withCache(60); // Cache all user routes for 60 seconds
165
+
166
+ // Group product-related routes
167
+ Group.create("products", () => {
168
+ Route.get("list", "/products");
169
+ Route.get("getOne", "/products/[id]");
170
+ });
91
171
  });
172
+
173
+ // Use grouped routes
174
+ const users = await Klaim.hello.users.list();
175
+ const product = await Klaim.hello.products.getOne({ id: 1 });
176
+ ```
177
+
178
+ #### Nested Groups
179
+
180
+ Create complex hierarchies with nested groups:
181
+
182
+ ```typescript
183
+ Group.create("services", () => {
184
+ // Internal services group
185
+ Group.create("internal", () => {
186
+ Api.create("logs", "https://logs.internal.example.com", () => {
187
+ Route.post("write", "/logs");
188
+ });
189
+
190
+ Api.create("metrics", "https://metrics.internal.example.com", () => {
191
+ Route.post("track", "/metrics");
192
+ });
193
+ }).withRetry(5); // More retries for internal services
194
+
195
+ // External services group
196
+ Group.create("external", () => {
197
+ Api.create("weather", "https://api.weather.com", () => {
198
+ Route.get("forecast", "/forecast/[city]");
199
+ });
200
+
201
+ Api.create("geocoding", "https://api.geocoding.com", () => {
202
+ Route.get("search", "/search/[query]");
203
+ });
204
+ }).withCache(300); // Cache external services longer
205
+ });
206
+
207
+ // Access nested groups
208
+ await Klaim.services.internal.logs.write({}, { message: "Log entry" });
209
+ await Klaim.services.external.weather.forecast({ city: "Paris" });
210
+ ```
211
+
212
+ #### Group Configuration
213
+
214
+ Groups can share configuration among all their members:
215
+
216
+ ```typescript
217
+ Group.create("apis", () => {
218
+ Api.create("service1", "https://api1.example.com", () => {
219
+ Route.get("test", "/test");
220
+ });
221
+
222
+ Api.create("service2", "https://api2.example.com", () => {
223
+ Route.get("test", "/test");
224
+ });
225
+ })
226
+ .withCache(60) // Enable caching for all APIs
227
+ .withRetry(3) // Enable retries for all APIs
228
+ .before(({ config }) => { // Add authentication for all APIs
229
+ config.headers.Authorization = `Bearer ${getToken()}`;
230
+ })
231
+ .after(({ data }) => { // Process all responses
232
+ logResponse(data);
233
+ });
92
234
  ```
93
235
 
94
236
  ### Request Handling
@@ -143,32 +285,6 @@ Hook.subscribe("hello.getFirstTodo", ({url}) => {
143
285
  });
144
286
  ```
145
287
 
146
- ### Group Usage
147
-
148
- Use groups to organize related routes and share common settings:
149
-
150
- ```typescript
151
- import {Api, Group, Route} from 'klaim';
152
-
153
- Api.create("hello", "https://jsonplaceholder.typicode.com/", () => {
154
- // Create a group for user-related routes
155
- Group.create("users", () => {
156
- Route.get("list", "/users");
157
- Route.get("getOne", "/users/[id]");
158
-
159
- // Nested group for user posts
160
- Group.create("posts", () => {
161
- Route.get("list", "/users/[userId]/posts");
162
- }).withCache(); // Cache enabled for all routes in this group
163
- });
164
- });
165
-
166
- // Use the grouped routes
167
- const users = await Klaim.hello.users.list();
168
- const user = await Klaim.hello.users.getOne({id: 1});
169
- const userPosts = await Klaim.hello.users.posts.list({userId: 1});
170
- ```
171
-
172
288
  ### Caching Requests
173
289
 
174
290
  Enable caching on requests to reduce network load and improve performance. By default, the cache duration is 20 seconds,
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antharuu/klaim",
3
- "version": "1.6.34",
3
+ "version": "1.7.1",
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 F=Object.defineProperty;var S=(s,t,e)=>t in s?F(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var o=(s,t,e)=>S(s,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function y(s){return s.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}function v(s){return s.trim().replace(/^\/|\/$/g,"")}class P{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,"callbacks",{before:null,after:null,call:null});o(this,"cache",!1);o(this,"retry",!1);this.type=t,this.name=y(e),this.name!==e&&console.warn(`Name "${e}" has been camelCased to "${this.name}"`),this.url=v(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}withCache(t=20){return this.cache=t,this}withRetry(t=2){return this.retry=t,this}}const f=class f{constructor(){o(this,"cache");this.cache=new Map}static get i(){return f._instance||(f._instance=new f),f._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(f,"_instance");let g=f;function T(s){let a=2166136261;for(let n=0;n<s.length;n++)a^=s.charCodeAt(n),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 K(s,t,e){const a=`${s.toString()}${JSON.stringify(t)}`,r=T(a);if(g.i.has(r))return g.i.get(r);const c=await(await fetch(s,t)).json();return g.i.set(r,c,e),c}class C{static subscribe(t,e){this._callbacks.set(t,e)}static run(t){const e=this._callbacks.get(t);e&&e()}}o(C,"_callbacks",new Map);const m={};async function R(s,t,e={},a={}){const r=i.i.getApi(s.split(".")[0]);if(!t||!r||t.type!=="route"||r.type!=="api")throw new Error(`Invalid path: ${s}.${t.name}`);let n=j(`${r.url}/${t.url}`,t,e),c={};a&&t.method!=="GET"&&(c.body=JSON.stringify(a)),c.headers={"Content-Type":"application/json",...r.headers,...t.headers},c.method=t.method;const{beforeRoute:u,beforeApi:h,beforeUrl:d,beforeConfig:w}=x({route:t,api:r,url:n,config:c});n=d,c=w,i.updateElement(h),i.updateElement(u);let p=await O(r,t,n,c);t.schema&&"validate"in t.schema&&(p=await t.schema.validate(p));const{afterRoute:k,afterApi:A,afterData:_}=D({route:t,api:r,response:p,data:p});return i.updateElement(A),i.updateElement(k),C.run(`${r.name}.${t.name}`),_}async function N(s,t,e,a){return s?await K(t,e,a.cache):await(await fetch(t,e)).json()}async function O(s,t,e,a){var d,w;const r=s.cache||t.cache,n=t.retry||s.retry||0;let c,u=!1,h=0;for(;h<=n&&!u;)try{(d=t.callbacks)!=null&&d.call?t.callbacks.call({}):(w=s.callbacks)!=null&&w.call&&s.callbacks.call({}),c=await N(!!r,e,a,s),u=!0}catch(p){if(h++,h>n)throw p.message=`Failed to fetch ${e} after ${n} attempts`,p}return c}function j(s,t,e){let a=s;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:s,api:t,url:e,config:a}){var n,c;const r=(c=(n=s.callbacks).before)==null?void 0:c.call(n,{route:s,api:t,url:e,config:a});return{beforeRoute:(r==null?void 0:r.route)||s,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 D({route:s,api:t,response:e,data:a}){var n,c;const r=(c=(n=s.callbacks).after)==null?void 0:c.call(n,{route:s,api:t,response:e,data:a});return{afterRoute:(r==null?void 0:r.route)||s,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 l=class l{constructor(){o(this,"_elements",new Map);o(this,"_currentParent",null)}static get i(){return l._instance||(l._instance=new l),l._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=m;e&&(r=this.getOrCreateKlaimBranch(e)),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");const e=this.getFullPath(this._currentParent);if(!this._elements.has(e))throw new Error(`Parent element ${e} not found`);t.parent=e;const a=this.getElementKey(t);this._elements.set(a,t),this.addToKlaimRoute(t)}getOrCreateKlaimBranch(t){let e=m;const r=this.getFullPath(t).split(".");for(const n of r)e[n]||(e[n]={}),e=e[n];return e}addToKlaimRoute(t){if(!t.parent)return;const e=t.parent.split(".");let a=m;for(const r of e)a[r]||(a[r]={}),a=a[r];a[t.name]=function(n={},c={}){return R(t.parent,t,n,c)}}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 l.i._elements.get(l.i.getElementKey(t))||t}getApi(t){const e=this._elements.get(t);if(e)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("."),n=this._elements.get(r);if((n==null?void 0:n.type)==="api")return n}}};o(l,"_instance");let i=l;class b extends P{static create(t,e,a,r={}){const n=y(t);n!==t&&console.warn(`API name "${t}" has been camelCased to "${n}"`);const c=new b(n,e,r);return i.i.registerElement(c),i.i.setCurrentParent(n),a(),i.i.clearCurrentParent(),c}constructor(t,e,a={}){super("api",t,e,a)}}class E extends P{static create(t,e){const a=y(t),r=i.i.getCurrentParent(),n=r?i.i.getFullPath(r):"",c=n?`${n}.${a}`:a,u=new E(a,"");a!==t&&console.warn(`Group name "${t}" has been camelCased to "${a}"`),i.i.registerElement(u);const h=i.i.getCurrentParent();return i.i.setCurrentParent(c),e(),h?i.i.setCurrentParent(i.i.getFullPath(h)):i.i.clearCurrentParent(),u}constructor(t,e,a={}){super("group",t,e,a)}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}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 $ extends P{constructor(t,e,a={},r="GET"){super("route",t,e,a),this.method=r,this.detectArguments()}static createRoute(t,e,a={},r){const n=new $(t,e,a,r);return i.i.registerRoute(n),n}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=b;exports.Group=E;exports.Hook=C;exports.Klaim=m;exports.Registry=i;exports.Route=$;
1
+ "use strict";var T=Object.defineProperty;var R=(s,t,e)=>t in s?T(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var o=(s,t,e)=>R(s,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function b(s){return s.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}function K(s){return s.trim().replace(/^\/|\/$/g,"")}class C{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,"callbacks",{before:null,after:null,call:null});o(this,"cache",!1);o(this,"retry",!1);this.type=t,this.name=b(e),this.name!==e&&console.warn(`Name "${e}" has been camelCased to "${this.name}"`),this.url=K(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}withCache(t=20){return this.cache=t,this}withRetry(t=2){return this.retry=t,this}}const p=class p{constructor(){o(this,"cache");this.cache=new Map}static get i(){return p._instance||(p._instance=new p),p._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(p,"_instance");let g=p;function N(s){let a=2166136261;for(let n=0;n<s.length;n++)a^=s.charCodeAt(n),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(s,t,e){const a=`${s.toString()}${JSON.stringify(t)}`,r=N(a);if(g.i.has(r))return g.i.get(r);const c=await(await fetch(s,t)).json();return g.i.set(r,c,e),c}class E{static subscribe(t,e){this._callbacks.set(t,e)}static run(t){const e=this._callbacks.get(t);e&&e()}}o(E,"_callbacks",new Map);const m={};async function x(s,t,e={},a={}){const r=s.split(".");let n;for(let y=0;y<r.length;y++){const v=r[y];if(n=i.i.getApi(v),n)break}if(!t||!n||t.type!=="route"||n.type!=="api")throw new Error(`Invalid path: ${s}.${t.name}`);let c=O(`${n.url}/${t.url}`,t,e),l={};a&&t.method!=="GET"&&(l.body=JSON.stringify(a)),l.headers={"Content-Type":"application/json",...n.headers,...t.headers},l.method=t.method;const{beforeRoute:h,beforeApi:f,beforeUrl:d,beforeConfig:P}=U({route:t,api:n,url:c,config:l});c=d,l=P,i.updateElement(f),i.updateElement(h);let w=await G(n,t,c,l);t.schema&&"validate"in t.schema&&(w=await t.schema.validate(w));const{afterRoute:_,afterApi:F,afterData:S}=H({route:t,api:n,response:w,data:w});return i.updateElement(F),i.updateElement(_),E.run(`${n.name}.${t.name}`),S}async function D(s,t,e,a){return s?await j(t,e,a.cache):await(await fetch(t,e)).json()}async function G(s,t,e,a){var f,d;const r=s.cache||t.cache,n=t.retry||s.retry||0;let c,l=!1,h=0;for(;h<=n&&!l;)try{(f=t.callbacks)!=null&&f.call?t.callbacks.call({}):(d=s.callbacks)!=null&&d.call&&s.callbacks.call({}),c=await D(!!r,e,a,s),l=!0}catch(P){if(h++,h>n)throw P.message=`Failed to fetch ${e} after ${n} attempts`,P}return c}function O(s,t,e){let a=s;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 U({route:s,api:t,url:e,config:a}){var n,c;const r=(c=(n=s.callbacks).before)==null?void 0:c.call(n,{route:s,api:t,url:e,config:a});return{beforeRoute:(r==null?void 0:r.route)||s,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 H({route:s,api:t,response:e,data:a}){var n,c;const r=(c=(n=s.callbacks).after)==null?void 0:c.call(n,{route:s,api:t,response:e,data:a});return{afterRoute:(r==null?void 0:r.route)||s,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 u=class u{constructor(){o(this,"_elements",new Map);o(this,"_currentParent",null)}static get i(){return u._instance||(u._instance=new u),u._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=m;if(e){const n=this.getFullPath(e).split(".");for(const c of n)r[c]||(r[c]={}),r=r[c]}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=m;const a=t.parent.split(".");for(const r of a)e[r]||(e[r]={}),e=e[r];e[t.name]=function(r={},n={}){return x(t.parent,t,r,n)}}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 u.i._elements.get(u.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("."),n=this._elements.get(r);if((n==null?void 0:n.type)==="api")return n}}};o(u,"_instance");let i=u;class $ extends C{static create(t,e,a,r={}){const n=b(t);n!==t&&console.warn(`API name "${t}" has been camelCased to "${n}"`);const c=new $(n,e,r),l=i.i.getCurrentParent();i.i.registerElement(c);const h=l?i.i.getFullPath(l):"",f=h?`${h}.${n}`:n;return i.i.setCurrentParent(f),a(),l?i.i.setCurrentParent(i.i.getFullPath(l)):i.i.clearCurrentParent(),c}constructor(t,e,a={}){super("api",t,e,a)}}class k extends C{static create(t,e){const a=b(t),r=i.i.getCurrentParent(),n=r?i.i.getFullPath(r):"",c=n?`${n}.${a}`:a,l=new k(a,"");a!==t&&console.warn(`Group name "${t}" has been camelCased to "${a}"`),i.i.registerElement(l);const h=i.i.getCurrentParent();return i.i.setCurrentParent(c),e(),h?i.i.setCurrentParent(i.i.getFullPath(h)):i.i.clearCurrentParent(),l}constructor(t,e,a={}){super("group",t,e,a)}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}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 A extends C{constructor(t,e,a={},r="GET"){super("route",t,e,a),this.method=r,this.detectArguments()}static createRoute(t,e,a={},r){const n=new A(t,e,a,r);return i.i.registerRoute(n),n}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=$;exports.Group=k;exports.Hook=E;exports.Klaim=m;exports.Registry=i;exports.Route=A;