klaim 1.0.6 → 1.1.2

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,12 +3,18 @@
3
3
  Klaim is a lightweight TypeScript library designed to manage APIs and record requests, optimized for an optimal user
4
4
  experience.
5
5
 
6
+ ## Links
7
+
8
+ - [NPM](https://www.npmjs.com/package/klaim)
9
+ - [GitHub](https://github.com/antharuu/klaim)
10
+
6
11
  ## 🚀 Features
7
12
 
8
13
  - **Efficient API Management**: Easily manage multiple APIs with streamlined integration and interaction capabilities.
9
14
  - **Request Recording**: Seamlessly track requests for debugging and monitoring.
10
15
  - **User Experience Optimization**: Focused on performance and usability for a smooth user experience.
11
16
  - **Lightweight**: Minimal footprint for fast load times and minimal performance impact.
17
+ - **Middleware Support**: Easily add middleware to modify requests and responses (`before` and `after`).
12
18
  - **TypeScript Support**: Fully typed for enhanced code quality and developer experience.
13
19
 
14
20
  ## 📥 Installation
@@ -49,6 +55,17 @@ Api.create("hello", "https://jsonplaceholder.typicode.com/", () => {
49
55
 
50
56
  // You can also define routes in post, (put, delete, etc)
51
57
  Route.post<Todo>("addTodo", "todos");
58
+
59
+ // With before middleware
60
+ Route.get<Todo>("getRandomTodo", "todos")
61
+ .before(({url}) => {
62
+ const random = Math.floor(Math.random() * 10) + 1;
63
+ return ({url: `${url}/${random}`});
64
+ });
65
+
66
+ // With after middleware
67
+ Route.get<Todo>("getFirstTodo", "todos")
68
+ .after(({data: [first]}) => ({data: first}));
52
69
  });
53
70
 
54
71
  // --- Usage
package/dist/klaim.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";var C=Object.defineProperty;var $=(a,t,e)=>t in a?C(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var s=(a,t,e)=>$(a,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function d(a){return a.trim().replace(/^\/|\/$/g,"")}function m(a){return a.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}var A=(a=>(a.GET="GET",a.POST="POST",a.PUT="PUT",a.DELETE="DELETE",a.PATCH="PATCH",a.OPTIONS="OPTIONS",a))(A||{});class p{constructor(t,e,n,r="GET"){s(this,"api","undefined");s(this,"name");s(this,"url");s(this,"method");s(this,"headers");s(this,"arguments",new Set);s(this,"callbacks",{before:null,after:null});this.name=m(t),this.name!==t&&console.warn(`Route name "${t}" has been camelCased to "${this.name}"`),this.url=d(e),this.headers=n||{},this.method=r,this.detectArguments()}static createRoute(t,e,n,r){const i=new p(t,e,n,r);return o.i.registerRoute(i),i}static get(t,e,n={}){return this.createRoute(t,e,n,"GET")}static post(t,e,n){return this.createRoute(t,e,n,"POST")}static put(t,e,n){return this.createRoute(t,e,n,"PUT")}static delete(t,e,n){return this.createRoute(t,e,n,"DELETE")}static patch(t,e,n){return this.createRoute(t,e,n,"PATCH")}static options(t,e,n){return this.createRoute(t,e,n,"OPTIONS")}before(t){return this.callbacks.before=t,this}after(t){return this.callbacks.after=t,this}detectArguments(){const t=this.url.match(/\[([^\]]+)]/g);t&&t.forEach(e=>{const n=e.replace(/\[|]/g,"");this.arguments.add(n)})}}const l={};async function O(a,t,e={},n={}){let r=y(`${a.url}/${t.url}`,t,e),i={};n&&t.method!==A.GET&&(i.body=JSON.stringify(n)),i.headers={"Content-Type":"application/json",...a.headers,...t.headers},i.method=t.method;const{beforeRoute:u,beforeApi:g,beforeUrl:w,beforeConfig:T}=S({route:t,api:a,url:r,config:i});r=w,i=T,a=o.updateApi(g),t=o.updateRoute(u);const f=await fetch(r,i),{afterRoute:E,afterApi:P,afterData:b}=I({route:t,api:a,response:f,data:await f.json()});return o.updateApi(P),o.updateRoute(E),b}function y(a,t,e){let n=a;return t.arguments.forEach(r=>{if(e[r]===void 0)throw new Error(`Argument ${r} is missing`);n=n.replace(`[${r}]`,e[r])}),n}function S({route:a,api:t,url:e,config:n}){var i,u;const r=(u=(i=a.callbacks).before)==null?void 0:u.call(i,{route:a,api:t,url:e,config:n});return{beforeRoute:(r==null?void 0:r.route)||a,beforeApi:(r==null?void 0:r.api)||t,beforeUrl:(r==null?void 0:r.url)||e,beforeConfig:(r==null?void 0:r.config)||n}}function I({route:a,api:t,response:e,data:n}){var i,u;const r=(u=(i=a.callbacks).after)==null?void 0:u.call(i,{route:a,api:t,response:e,data:n});return{afterRoute:(r==null?void 0:r.route)||a,afterApi:(r==null?void 0:r.api)||t,afterResponse:(r==null?void 0:r.response)||e,afterData:(r==null?void 0:r.data)||n}}const c=class c{constructor(){s(this,"_apis",new Map);s(this,"_currentApi",null)}static get i(){return c._instance||(c._instance=new c),c._instance}registerApi(t){this._apis.set(t.name,t),l[t.name]={}}setCurrent(t){const e=this._apis.get(t);if(!e)throw new Error(`API ${t} not found`);this._currentApi=e}clearCurrent(){this._currentApi=null}registerRoute(t){if(!this._currentApi)throw new Error("No current API set, use Route only inside Api.create callback");t.api=this._currentApi.name,this._currentApi.routes.set(t.name,t),this.addToKlaimRoute(t.api,t)}getApi(t){return this._apis.get(t)}getRoute(t,e){const n=this._apis.get(t);if(!n)throw new Error(`API ${t} not found`);return n.routes.get(e)}static updateApi(t){return c.i._apis.has(t.name)||c.i.registerApi(t),c.i._apis.set(t.name,t),t}static updateRoute(t){const e=c.i._apis.get(t.api);if(!e)throw new Error(`API ${t.api} not found`);return e.routes.set(t.name,t),t}addToKlaimRoute(t,e){l[t][e.name]=async(n={},r={})=>{const i=c.i._apis.get(t);if(!i)throw new Error(`API ${e.api} not found`);return O(i,e,n,r)}}};s(c,"_instance");let o=c;class h{constructor(t,e,n){s(this,"name");s(this,"url");s(this,"headers");s(this,"routes",new Map);this.name=t,this.url=d(e),this.headers=n||{}}static create(t,e,n,r={}){const i=m(t);i!==t&&console.warn(`API name "${t}" has been camelCased to "${i}"`);const u=new h(i,e,r);return o.i.registerApi(u),o.i.setCurrent(i),n(),o.i.clearCurrent(),u}}exports.Api=h;exports.Klaim=l;exports.Registry=o;exports.Route=p;
package/dist/klaim.es.js CHANGED
@@ -1,14 +1,14 @@
1
- var f = Object.defineProperty;
2
- var A = (n, t, e) => t in n ? f(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
3
- var i = (n, t, e) => A(n, typeof t != "symbol" ? t + "" : t, e);
4
- function l(n) {
5
- return n.trim().replace(/^\/|\/$/g, "");
1
+ var b = Object.defineProperty;
2
+ var $ = (a, t, e) => t in a ? b(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
3
+ var s = (a, t, e) => $(a, typeof t != "symbol" ? t + "" : t, e);
4
+ function h(a) {
5
+ return a.trim().replace(/^\/|\/$/g, "");
6
6
  }
7
- function p(n) {
8
- return n.replace(/([-_][a-z])/gi, (t) => t.toUpperCase().replace("-", "").replace("_", "")).replace(/(^\w)/, (t) => t.toLowerCase());
7
+ function f(a) {
8
+ return a.replace(/([-_][a-z])/gi, (t) => t.toUpperCase().replace("-", "").replace("_", "")).replace(/(^\w)/, (t) => t.toLowerCase());
9
9
  }
10
- var m = /* @__PURE__ */ ((n) => (n.GET = "GET", n.POST = "POST", n.PUT = "PUT", n.DELETE = "DELETE", n.PATCH = "PATCH", n.OPTIONS = "OPTIONS", n))(m || {});
11
- class d {
10
+ var d = /* @__PURE__ */ ((a) => (a.GET = "GET", a.POST = "POST", a.PUT = "PUT", a.DELETE = "DELETE", a.PATCH = "PATCH", a.OPTIONS = "OPTIONS", a))(d || {});
11
+ class A {
12
12
  /**
13
13
  * Constructor
14
14
  *
@@ -17,14 +17,24 @@ class d {
17
17
  * @param headers - The headers to be sent with the request
18
18
  * @param method - The HTTP method of the route
19
19
  */
20
- constructor(t, e, r, a = "GET") {
21
- i(this, "api", "undefined");
22
- i(this, "name");
23
- i(this, "url");
24
- i(this, "method");
25
- i(this, "headers");
26
- i(this, "arguments", /* @__PURE__ */ new Set());
27
- this.name = p(t), this.name !== t && console.warn(`Route name "${t}" has been camelCased to "${this.name}"`), this.url = l(e), this.headers = r || {}, this.method = a, this.detectArguments();
20
+ constructor(t, e, n, r = "GET") {
21
+ s(this, "api", "undefined");
22
+ s(this, "name");
23
+ s(this, "url");
24
+ s(this, "method");
25
+ s(this, "headers");
26
+ s(this, "arguments", /* @__PURE__ */ new Set());
27
+ s(this, "callbacks", {
28
+ /**
29
+ * Called before the request is sent
30
+ */
31
+ before: null,
32
+ /**
33
+ * Called after the request is sent and before the data is returned
34
+ */
35
+ after: null
36
+ });
37
+ this.name = f(t), this.name !== t && console.warn(`Route name "${t}" has been camelCased to "${this.name}"`), this.url = h(e), this.headers = n || {}, this.method = r, this.detectArguments();
28
38
  }
29
39
  /**
30
40
  * Creates a new route
@@ -35,9 +45,9 @@ class d {
35
45
  * @param method - The HTTP method of the route
36
46
  * @returns The new route
37
47
  */
38
- static createRoute(t, e, r, a) {
39
- const s = new d(t, e, r, a);
40
- return o.i.registerRoute(s), s;
48
+ static createRoute(t, e, n, r) {
49
+ const i = new A(t, e, n, r);
50
+ return u.i.registerRoute(i), i;
41
51
  }
42
52
  /**
43
53
  * Creates a new route with the GET method
@@ -47,11 +57,11 @@ class d {
47
57
  * @param headers - The headers to be sent with the request
48
58
  * @returns The new route
49
59
  */
50
- static get(t, e, r = {}) {
60
+ static get(t, e, n = {}) {
51
61
  return this.createRoute(
52
62
  t,
53
63
  e,
54
- r,
64
+ n,
55
65
  "GET"
56
66
  /* GET */
57
67
  );
@@ -64,11 +74,11 @@ class d {
64
74
  * @param headers - The headers to be sent with the request
65
75
  * @returns The new route
66
76
  */
67
- static post(t, e, r) {
77
+ static post(t, e, n) {
68
78
  return this.createRoute(
69
79
  t,
70
80
  e,
71
- r,
81
+ n,
72
82
  "POST"
73
83
  /* POST */
74
84
  );
@@ -81,11 +91,11 @@ class d {
81
91
  * @param headers - The headers to be sent with the request
82
92
  * @returns The new route
83
93
  */
84
- static put(t, e, r) {
94
+ static put(t, e, n) {
85
95
  return this.createRoute(
86
96
  t,
87
97
  e,
88
- r,
98
+ n,
89
99
  "PUT"
90
100
  /* PUT */
91
101
  );
@@ -98,11 +108,11 @@ class d {
98
108
  * @param headers - The headers to be sent with the request
99
109
  * @returns The new route
100
110
  */
101
- static delete(t, e, r) {
111
+ static delete(t, e, n) {
102
112
  return this.createRoute(
103
113
  t,
104
114
  e,
105
- r,
115
+ n,
106
116
  "DELETE"
107
117
  /* DELETE */
108
118
  );
@@ -115,11 +125,11 @@ class d {
115
125
  * @param headers - The headers to be sent with the request
116
126
  * @returns The new route
117
127
  */
118
- static patch(t, e, r) {
128
+ static patch(t, e, n) {
119
129
  return this.createRoute(
120
130
  t,
121
131
  e,
122
- r,
132
+ n,
123
133
  "PATCH"
124
134
  /* PATCH */
125
135
  );
@@ -132,50 +142,101 @@ class d {
132
142
  * @param headers - The headers to be sent with the request
133
143
  * @returns The new route
134
144
  */
135
- static options(t, e, r) {
145
+ static options(t, e, n) {
136
146
  return this.createRoute(
137
147
  t,
138
148
  e,
139
- r,
149
+ n,
140
150
  "OPTIONS"
141
151
  /* OPTIONS */
142
152
  );
143
153
  }
154
+ /**
155
+ * Sets the before callback
156
+ *
157
+ * @param callback - The callback
158
+ * @returns The route
159
+ */
160
+ before(t) {
161
+ return this.callbacks.before = t, this;
162
+ }
163
+ /**
164
+ * Sets the after callback
165
+ *
166
+ * @param callback - The callback
167
+ * @returns The route
168
+ */
169
+ after(t) {
170
+ return this.callbacks.after = t, this;
171
+ }
144
172
  /**
145
173
  * Detects the arguments in the URL
146
174
  */
147
175
  detectArguments() {
148
176
  const t = this.url.match(/\[([^\]]+)]/g);
149
177
  t && t.forEach((e) => {
150
- const r = e.replace(/\[|]/g, "");
151
- this.arguments.add(r);
178
+ const n = e.replace(/\[|]/g, "");
179
+ this.arguments.add(n);
152
180
  });
153
181
  }
154
182
  }
155
- const h = {};
156
- async function T(n, t, e = {}, r = {}) {
157
- const a = g(`${n.url}/${t.url}`, t, e), s = {};
158
- return r && t.method !== m.GET && (s.body = JSON.stringify(r)), s.headers = {
183
+ const p = {};
184
+ async function O(a, t, e = {}, n = {}) {
185
+ let r = I(`${a.url}/${t.url}`, t, e), i = {};
186
+ n && t.method !== d.GET && (i.body = JSON.stringify(n)), i.headers = {
159
187
  "Content-Type": "application/json",
160
- ...n.headers,
188
+ ...a.headers,
161
189
  ...t.headers
162
- }, s.method = t.method, await (await fetch(a, s)).json();
190
+ }, i.method = t.method;
191
+ const {
192
+ beforeRoute: o,
193
+ beforeApi: w,
194
+ beforeUrl: g,
195
+ beforeConfig: T
196
+ } = _({ route: t, api: a, url: r, config: i });
197
+ r = g, i = T, a = u.updateApi(w), t = u.updateRoute(o);
198
+ const l = await fetch(r, i), {
199
+ afterRoute: E,
200
+ afterApi: P,
201
+ afterData: C
202
+ } = S({ route: t, api: a, response: l, data: await l.json() });
203
+ return u.updateApi(P), u.updateRoute(E), C;
163
204
  }
164
- function g(n, t, e) {
165
- let r = n;
166
- return t.arguments.forEach((a) => {
167
- if (e[a] === void 0)
168
- throw new Error(`Argument ${a} is missing`);
169
- r = r.replace(`[${a}]`, e[a]);
170
- }), r;
205
+ function I(a, t, e) {
206
+ let n = a;
207
+ return t.arguments.forEach((r) => {
208
+ if (e[r] === void 0)
209
+ throw new Error(`Argument ${r} is missing`);
210
+ n = n.replace(`[${r}]`, e[r]);
211
+ }), n;
212
+ }
213
+ function _({ route: a, api: t, url: e, config: n }) {
214
+ var i, o;
215
+ const r = (o = (i = a.callbacks).before) == null ? void 0 : o.call(i, { route: a, api: t, url: e, config: n });
216
+ return {
217
+ beforeRoute: (r == null ? void 0 : r.route) || a,
218
+ beforeApi: (r == null ? void 0 : r.api) || t,
219
+ beforeUrl: (r == null ? void 0 : r.url) || e,
220
+ beforeConfig: (r == null ? void 0 : r.config) || n
221
+ };
222
+ }
223
+ function S({ route: a, api: t, response: e, data: n }) {
224
+ var i, o;
225
+ const r = (o = (i = a.callbacks).after) == null ? void 0 : o.call(i, { route: a, api: t, response: e, data: n });
226
+ return {
227
+ afterRoute: (r == null ? void 0 : r.route) || a,
228
+ afterApi: (r == null ? void 0 : r.api) || t,
229
+ afterResponse: (r == null ? void 0 : r.response) || e,
230
+ afterData: (r == null ? void 0 : r.data) || n
231
+ };
171
232
  }
172
233
  const c = class c {
173
234
  /**
174
235
  * Constructor
175
236
  */
176
237
  constructor() {
177
- i(this, "_apis", /* @__PURE__ */ new Map());
178
- i(this, "_currentApi", null);
238
+ s(this, "_apis", /* @__PURE__ */ new Map());
239
+ s(this, "_currentApi", null);
179
240
  }
180
241
  /**
181
242
  * Singleton instance
@@ -191,7 +252,7 @@ const c = class c {
191
252
  * @param api - The API to register
192
253
  */
193
254
  registerApi(t) {
194
- this._apis.set(t.name, t), h[t.name] = {};
255
+ this._apis.set(t.name, t), p[t.name] = {};
195
256
  }
196
257
  /**
197
258
  * Sets the current API
@@ -237,10 +298,31 @@ const c = class c {
237
298
  * @returns The route
238
299
  */
239
300
  getRoute(t, e) {
240
- const r = this._apis.get(t);
241
- if (!r)
301
+ const n = this._apis.get(t);
302
+ if (!n)
242
303
  throw new Error(`API ${t} not found`);
243
- return r.routes.get(e);
304
+ return n.routes.get(e);
305
+ }
306
+ /**
307
+ * Updates an API
308
+ *
309
+ * @param api - The API to update
310
+ * @returns The updated API
311
+ */
312
+ static updateApi(t) {
313
+ return c.i._apis.has(t.name) || c.i.registerApi(t), c.i._apis.set(t.name, t), t;
314
+ }
315
+ /**
316
+ * Updates a route
317
+ *
318
+ * @param route - The route to update
319
+ * @returns The updated route
320
+ */
321
+ static updateRoute(t) {
322
+ const e = c.i._apis.get(t.api);
323
+ if (!e)
324
+ throw new Error(`API ${t.api} not found`);
325
+ return e.routes.set(t.name, t), t;
244
326
  }
245
327
  /**
246
328
  * Adds a route to Klaim object
@@ -249,17 +331,17 @@ const c = class c {
249
331
  * @param route - The route to add
250
332
  */
251
333
  addToKlaimRoute(t, e) {
252
- h[t][e.name] = async (r = {}, a = {}) => {
253
- const s = c.i._apis.get(t);
254
- if (!s)
334
+ p[t][e.name] = async (n = {}, r = {}) => {
335
+ const i = c.i._apis.get(t);
336
+ if (!i)
255
337
  throw new Error(`API ${e.api} not found`);
256
- return T(s, e, r, a);
338
+ return O(i, e, n, r);
257
339
  };
258
340
  }
259
341
  };
260
- i(c, "_instance");
261
- let o = c;
262
- class w {
342
+ s(c, "_instance");
343
+ let u = c;
344
+ class m {
263
345
  /**
264
346
  * Constructor
265
347
  *
@@ -267,12 +349,12 @@ class w {
267
349
  * @param url - The base URL of the API
268
350
  * @param headers - The headers to be sent with each request
269
351
  */
270
- constructor(t, e, r) {
271
- i(this, "name");
272
- i(this, "url");
273
- i(this, "headers");
274
- i(this, "routes", /* @__PURE__ */ new Map());
275
- this.name = t, this.url = l(e), this.headers = r || {};
352
+ constructor(t, e, n) {
353
+ s(this, "name");
354
+ s(this, "url");
355
+ s(this, "headers");
356
+ s(this, "routes", /* @__PURE__ */ new Map());
357
+ this.name = t, this.url = h(e), this.headers = n || {};
276
358
  }
277
359
  /**
278
360
  * Creates a new API
@@ -283,16 +365,16 @@ class w {
283
365
  * @param headers - The headers to be sent with each request
284
366
  * @returns The new API
285
367
  */
286
- static create(t, e, r, a = {}) {
287
- const s = p(t);
288
- s !== t && console.warn(`API name "${t}" has been camelCased to "${s}"`);
289
- const u = new w(s, e, a);
290
- return o.i.registerApi(u), o.i.setCurrent(s), r(), o.i.clearCurrent(), u;
368
+ static create(t, e, n, r = {}) {
369
+ const i = f(t);
370
+ i !== t && console.warn(`API name "${t}" has been camelCased to "${i}"`);
371
+ const o = new m(i, e, r);
372
+ return u.i.registerApi(o), u.i.setCurrent(i), n(), u.i.clearCurrent(), o;
291
373
  }
292
374
  }
293
375
  export {
294
- w as Api,
295
- h as Klaim,
296
- o as Registry,
297
- d as Route
376
+ m as Api,
377
+ p as Klaim,
378
+ u as Registry,
379
+ A as Route
298
380
  };
@@ -0,0 +1 @@
1
+ (function(s,o){typeof exports=="object"&&typeof module<"u"?o(exports):typeof define=="function"&&define.amd?define(["exports"],o):(s=typeof globalThis<"u"?globalThis:s||self,o(s.klaim={}))})(this,function(s){"use strict";var I=Object.defineProperty;var _=(s,o,h)=>o in s?I(s,o,{enumerable:!0,configurable:!0,writable:!0,value:h}):s[o]=h;var c=(s,o,h)=>_(s,typeof o!="symbol"?o+"":o,h);function o(i){return i.trim().replace(/^\/|\/$/g,"")}function h(i){return i.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}var A=(i=>(i.GET="GET",i.POST="POST",i.PUT="PUT",i.DELETE="DELETE",i.PATCH="PATCH",i.OPTIONS="OPTIONS",i))(A||{});class f{constructor(t,e,r,n="GET"){c(this,"api","undefined");c(this,"name");c(this,"url");c(this,"method");c(this,"headers");c(this,"arguments",new Set);c(this,"callbacks",{before:null,after:null});this.name=h(t),this.name!==t&&console.warn(`Route name "${t}" has been camelCased to "${this.name}"`),this.url=o(e),this.headers=r||{},this.method=n,this.detectArguments()}static createRoute(t,e,r,n){const a=new f(t,e,r,n);return l.i.registerRoute(a),a}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")}before(t){return this.callbacks.before=t,this}after(t){return this.callbacks.after=t,this}detectArguments(){const t=this.url.match(/\[([^\]]+)]/g);t&&t.forEach(e=>{const r=e.replace(/\[|]/g,"");this.arguments.add(r)})}}const d={};async function w(i,t,e={},r={}){let n=T(`${i.url}/${t.url}`,t,e),a={};r&&t.method!==A.GET&&(a.body=JSON.stringify(r)),a.headers={"Content-Type":"application/json",...i.headers,...t.headers},a.method=t.method;const{beforeRoute:p,beforeApi:b,beforeUrl:C,beforeConfig:$}=E({route:t,api:i,url:n,config:a});n=C,a=$,i=l.updateApi(b),t=l.updateRoute(p);const g=await fetch(n,a),{afterRoute:y,afterApi:O,afterData:S}=P({route:t,api:i,response:g,data:await g.json()});return l.updateApi(O),l.updateRoute(y),S}function T(i,t,e){let r=i;return t.arguments.forEach(n=>{if(e[n]===void 0)throw new Error(`Argument ${n} is missing`);r=r.replace(`[${n}]`,e[n])}),r}function E({route:i,api:t,url:e,config:r}){var a,p;const n=(p=(a=i.callbacks).before)==null?void 0:p.call(a,{route:i,api:t,url:e,config:r});return{beforeRoute:(n==null?void 0:n.route)||i,beforeApi:(n==null?void 0:n.api)||t,beforeUrl:(n==null?void 0:n.url)||e,beforeConfig:(n==null?void 0:n.config)||r}}function P({route:i,api:t,response:e,data:r}){var a,p;const n=(p=(a=i.callbacks).after)==null?void 0:p.call(a,{route:i,api:t,response:e,data:r});return{afterRoute:(n==null?void 0:n.route)||i,afterApi:(n==null?void 0:n.api)||t,afterResponse:(n==null?void 0:n.response)||e,afterData:(n==null?void 0:n.data)||r}}const u=class u{constructor(){c(this,"_apis",new Map);c(this,"_currentApi",null)}static get i(){return u._instance||(u._instance=new u),u._instance}registerApi(t){this._apis.set(t.name,t),d[t.name]={}}setCurrent(t){const e=this._apis.get(t);if(!e)throw new Error(`API ${t} not found`);this._currentApi=e}clearCurrent(){this._currentApi=null}registerRoute(t){if(!this._currentApi)throw new Error("No current API set, use Route only inside Api.create callback");t.api=this._currentApi.name,this._currentApi.routes.set(t.name,t),this.addToKlaimRoute(t.api,t)}getApi(t){return this._apis.get(t)}getRoute(t,e){const r=this._apis.get(t);if(!r)throw new Error(`API ${t} not found`);return r.routes.get(e)}static updateApi(t){return u.i._apis.has(t.name)||u.i.registerApi(t),u.i._apis.set(t.name,t),t}static updateRoute(t){const e=u.i._apis.get(t.api);if(!e)throw new Error(`API ${t.api} not found`);return e.routes.set(t.name,t),t}addToKlaimRoute(t,e){d[t][e.name]=async(r={},n={})=>{const a=u.i._apis.get(t);if(!a)throw new Error(`API ${e.api} not found`);return w(a,e,r,n)}}};c(u,"_instance");let l=u;class m{constructor(t,e,r){c(this,"name");c(this,"url");c(this,"headers");c(this,"routes",new Map);this.name=t,this.url=o(e),this.headers=r||{}}static create(t,e,r,n={}){const a=h(t);a!==t&&console.warn(`API name "${t}" has been camelCased to "${a}"`);const p=new m(a,e,n);return l.i.registerApi(p),l.i.setCurrent(a),r(),l.i.clearCurrent(),p}}s.Api=m,s.Klaim=d,s.Registry=l,s.Route=f,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
package/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './src';
2
+
package/package.json CHANGED
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "homepage": "https://github.com/antharuu/klaim#readme",
22
22
  "type": "module",
23
- "version": "1.0.6",
23
+ "version": "1.1.2",
24
24
  "main": "dist/klaim.cjs.js",
25
25
  "module": "dist/klaim.es.js",
26
26
  "types": "dist/index.d.ts",
package/src/core/Klaim.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Api } from "./Api";
2
- import { Route, RouteMethod } from "./Route";
2
+ import { Registry } from "./Registry";
3
+ import { ICallbackAfter, ICallbackBefore, Route, RouteMethod } from "./Route";
3
4
 
4
5
  export type IArgs = Record<string, unknown>;
5
6
 
@@ -21,9 +22,9 @@ export const Klaim: IApiReference = {};
21
22
  * @returns The response
22
23
  */
23
24
  export async function callApi<T> (api: Api, route: Route, args: IArgs = {}, body: IBody = {}): Promise<T> {
24
- const url = applyArgs(`${api.url}/${route.url}`, route, args);
25
+ let url = applyArgs(`${api.url}/${route.url}`, route, args);
25
26
 
26
- const config: Record<string, unknown> = {};
27
+ let config: Record<string, unknown> = {};
27
28
 
28
29
  if (body && route.method !== RouteMethod.GET) {
29
30
  config.body = JSON.stringify(body);
@@ -37,10 +38,28 @@ export async function callApi<T> (api: Api, route: Route, args: IArgs = {}, body
37
38
 
38
39
  config.method = route.method;
39
40
 
41
+ const {
42
+ beforeRoute,
43
+ beforeApi,
44
+ beforeUrl,
45
+ beforeConfig
46
+ } = applyBefore({ route, api, url, config });
47
+ url = beforeUrl;
48
+ config = beforeConfig;
49
+ api = Registry.updateApi(beforeApi);
50
+ route = Registry.updateRoute(beforeRoute);
51
+
40
52
  const response = await fetch(url, config);
41
53
 
42
- const data = await response.json();
43
- return data as T;
54
+ const {
55
+ afterRoute,
56
+ afterApi,
57
+ afterData
58
+ } = applyAfter({ route, api, response, data: await response.json() });
59
+ Registry.updateApi(afterApi);
60
+ Registry.updateRoute(afterRoute);
61
+
62
+ return afterData as T;
44
63
  }
45
64
 
46
65
  /**
@@ -64,3 +83,53 @@ function applyArgs (url: string, route: Route, args: IArgs): string {
64
83
 
65
84
  return newUrl;
66
85
  }
86
+
87
+ /**
88
+ * Applies the before callback
89
+ *
90
+ * @param callbackArgs - The arguments to pass to the callback
91
+ * @param callbackArgs.route - The route
92
+ * @param callbackArgs.api - The API
93
+ * @param callbackArgs.url - The URL
94
+ * @param callbackArgs.config - The config
95
+ * @returns The new args
96
+ */
97
+ function applyBefore ({ route, api, url, config }: ICallbackBefore): {
98
+ beforeRoute: Route;
99
+ beforeApi: Api;
100
+ beforeUrl: string;
101
+ beforeConfig: Record<string, unknown>;
102
+ } {
103
+ const beforeRes = route.callbacks.before?.({ route, api, url, config });
104
+ return {
105
+ beforeRoute: beforeRes?.route || route,
106
+ beforeApi: beforeRes?.api || api,
107
+ beforeUrl: beforeRes?.url || url,
108
+ beforeConfig: beforeRes?.config || config
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Applies the after callback
114
+ *
115
+ * @param callbackArgs - The arguments to pass to the callback
116
+ * @param callbackArgs.route - The route
117
+ * @param callbackArgs.api - The API
118
+ * @param callbackArgs.response - The response
119
+ * @param callbackArgs.data - The data
120
+ * @returns The new data
121
+ */
122
+ function applyAfter ({ route, api, response, data }: ICallbackAfter): {
123
+ afterRoute: Route;
124
+ afterApi: Api;
125
+ afterResponse: Response;
126
+ afterData: any;
127
+ } {
128
+ const afterRes = route.callbacks.after?.({ route, api, response, data });
129
+ return {
130
+ afterRoute: afterRes?.route || route,
131
+ afterApi: afterRes?.api || api,
132
+ afterResponse: afterRes?.response || response,
133
+ afterData: afterRes?.data || data
134
+ };
135
+ }
@@ -101,6 +101,39 @@ export class Registry {
101
101
  return apiObj.routes.get(name) as Route;
102
102
  }
103
103
 
104
+ /**
105
+ * Updates an API
106
+ *
107
+ * @param api - The API to update
108
+ * @returns The updated API
109
+ */
110
+ public static updateApi (api: Api): Api {
111
+ if (!Registry.i._apis.has(api.name)) {
112
+ Registry.i.registerApi(api);
113
+ }
114
+
115
+ Registry.i._apis.set(api.name, api);
116
+
117
+ return api;
118
+ }
119
+
120
+ /**
121
+ * Updates a route
122
+ *
123
+ * @param route - The route to update
124
+ * @returns The updated route
125
+ */
126
+ public static updateRoute (route: Route): Route {
127
+ const api = Registry.i._apis.get(route.api);
128
+ if (!api) {
129
+ throw new Error(`API ${route.api} not found`);
130
+ }
131
+
132
+ api.routes.set(route.name, route);
133
+
134
+ return route;
135
+ }
136
+
104
137
  /**
105
138
  * Adds a route to Klaim object
106
139
  *
package/src/core/Route.ts CHANGED
@@ -13,6 +13,25 @@ export enum RouteMethod {
13
13
  OPTIONS = "OPTIONS"
14
14
  }
15
15
 
16
+ export interface ICallbackBefore {
17
+ route: Route;
18
+ api: Api;
19
+ url: string;
20
+ config: Record<string, unknown>;
21
+ }
22
+
23
+ export interface ICallbackAfter {
24
+ route: Route;
25
+ api: Api;
26
+ response: Response;
27
+ data: any;
28
+ }
29
+
30
+ interface IRouteCallbacks {
31
+ before: ((args: ICallbackBefore) => (Partial<ICallbackBefore> | void)) | null;
32
+ after: ((args: ICallbackAfter) => (Partial<ICallbackAfter> | void)) | null;
33
+ }
34
+
16
35
  interface IRoute {
17
36
  api: Api["name"];
18
37
  name: string;
@@ -20,6 +39,10 @@ interface IRoute {
20
39
  method: RouteMethod;
21
40
  headers: IHeaders;
22
41
  arguments: Set<string>;
42
+ callbacks: IRouteCallbacks;
43
+
44
+ before: (callback: (args: ICallbackBefore) => (Partial<ICallbackBefore> | void)) => Route;
45
+ after: (callback: (args: ICallbackAfter) => (Partial<ICallbackAfter> | void)) => Route;
23
46
  }
24
47
 
25
48
  /**
@@ -38,6 +61,17 @@ export class Route implements IRoute {
38
61
 
39
62
  public arguments: Set<string> = new Set<string>();
40
63
 
64
+ public callbacks: IRouteCallbacks = {
65
+ /**
66
+ * Called before the request is sent
67
+ */
68
+ before: null,
69
+ /**
70
+ * Called after the request is sent and before the data is returned
71
+ */
72
+ after: null
73
+ };
74
+
41
75
  /**
42
76
  * Constructor
43
77
  *
@@ -146,6 +180,28 @@ export class Route implements IRoute {
146
180
  return this.createRoute(name, url, headers, RouteMethod.OPTIONS);
147
181
  }
148
182
 
183
+ /**
184
+ * Sets the before callback
185
+ *
186
+ * @param callback - The callback
187
+ * @returns The route
188
+ */
189
+ public before (callback: (args: ICallbackBefore) => (Partial<ICallbackBefore> | void)): this {
190
+ this.callbacks.before = callback;
191
+ return this;
192
+ }
193
+
194
+ /**
195
+ * Sets the after callback
196
+ *
197
+ * @param callback - The callback
198
+ * @returns The route
199
+ */
200
+ public after (callback: (args: ICallbackAfter) => (Partial<ICallbackAfter> | void)): this {
201
+ this.callbacks.after = callback;
202
+ return this;
203
+ }
204
+
149
205
  /**
150
206
  * Detects the arguments in the URL
151
207
  */
package/vite.config.ts CHANGED
@@ -7,8 +7,11 @@ export default defineConfig({
7
7
  lib: {
8
8
  entry: path.resolve(__dirname, 'src/index.ts'),
9
9
  name: 'klaim',
10
- fileName: format => `klaim.${format}.js`,
11
- formats: ['es', 'cjs']
10
+ fileName: format => {
11
+ if (format === 'cjs') return `klaim.${format}`;
12
+ return `klaim.${format}.js`;
13
+ },
14
+ formats: ['es', 'cjs', 'umd']
12
15
  },
13
16
  rollupOptions: {
14
17
  external: [],
package/dist/klaim.cjs.js DELETED
@@ -1 +0,0 @@
1
- "use strict";var g=Object.defineProperty;var w=(n,t,e)=>t in n?g(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var a=(n,t,e)=>w(n,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function m(n){return n.trim().replace(/^\/|\/$/g,"")}function d(n){return n.replace(/([-_][a-z])/gi,t=>t.toUpperCase().replace("-","").replace("_","")).replace(/(^\w)/,t=>t.toLowerCase())}var f=(n=>(n.GET="GET",n.POST="POST",n.PUT="PUT",n.DELETE="DELETE",n.PATCH="PATCH",n.OPTIONS="OPTIONS",n))(f||{});class h{constructor(t,e,r,i="GET"){a(this,"api","undefined");a(this,"name");a(this,"url");a(this,"method");a(this,"headers");a(this,"arguments",new Set);this.name=d(t),this.name!==t&&console.warn(`Route name "${t}" has been camelCased to "${this.name}"`),this.url=m(e),this.headers=r||{},this.method=i,this.detectArguments()}static createRoute(t,e,r,i){const s=new h(t,e,r,i);return o.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(/\[|]/g,"");this.arguments.add(r)})}}const l={};async function A(n,t,e={},r={}){const i=T(`${n.url}/${t.url}`,t,e),s={};return r&&t.method!==f.GET&&(s.body=JSON.stringify(r)),s.headers={"Content-Type":"application/json",...n.headers,...t.headers},s.method=t.method,await(await fetch(i,s)).json()}function T(n,t,e){let r=n;return t.arguments.forEach(i=>{if(e[i]===void 0)throw new Error(`Argument ${i} is missing`);r=r.replace(`[${i}]`,e[i])}),r}const c=class c{constructor(){a(this,"_apis",new Map);a(this,"_currentApi",null)}static get i(){return c._instance||(c._instance=new c),c._instance}registerApi(t){this._apis.set(t.name,t),l[t.name]={}}setCurrent(t){const e=this._apis.get(t);if(!e)throw new Error(`API ${t} not found`);this._currentApi=e}clearCurrent(){this._currentApi=null}registerRoute(t){if(!this._currentApi)throw new Error("No current API set, use Route only inside Api.create callback");t.api=this._currentApi.name,this._currentApi.routes.set(t.name,t),this.addToKlaimRoute(t.api,t)}getApi(t){return this._apis.get(t)}getRoute(t,e){const r=this._apis.get(t);if(!r)throw new Error(`API ${t} not found`);return r.routes.get(e)}addToKlaimRoute(t,e){l[t][e.name]=async(r={},i={})=>{const s=c.i._apis.get(t);if(!s)throw new Error(`API ${e.api} not found`);return A(s,e,r,i)}}};a(c,"_instance");let o=c;class p{constructor(t,e,r){a(this,"name");a(this,"url");a(this,"headers");a(this,"routes",new Map);this.name=t,this.url=m(e),this.headers=r||{}}static create(t,e,r,i={}){const s=d(t);s!==t&&console.warn(`API name "${t}" has been camelCased to "${s}"`);const u=new p(s,e,i);return o.i.registerApi(u),o.i.setCurrent(s),r(),o.i.clearCurrent(),u}}exports.Api=p;exports.Klaim=l;exports.Registry=o;exports.Route=h;