klaim 1.0.6 → 1.1.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 +11 -0
- package/dist/klaim.cjs +1 -0
- package/dist/klaim.es.js +157 -75
- package/dist/klaim.umd.js +1 -0
- package/index.ts +1 -0
- package/package.json +1 -1
- package/src/core/Klaim.ts +74 -5
- package/src/core/Registry.ts +33 -0
- package/src/core/Route.ts +56 -0
- package/vite.config.ts +5 -2
- package/dist/klaim.cjs.js +0 -1
package/README.md
CHANGED
|
@@ -49,6 +49,17 @@ Api.create("hello", "https://jsonplaceholder.typicode.com/", () => {
|
|
|
49
49
|
|
|
50
50
|
// You can also define routes in post, (put, delete, etc)
|
|
51
51
|
Route.post<Todo>("addTodo", "todos");
|
|
52
|
+
|
|
53
|
+
// With before middleware
|
|
54
|
+
Route.get<Todo>("getRandomTodo", "todos")
|
|
55
|
+
.before(({url}) => {
|
|
56
|
+
const random = Math.floor(Math.random() * 10) + 1;
|
|
57
|
+
return ({url: `${url}/${random}`});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// With after middleware
|
|
61
|
+
Route.get<Todo>("getFirstTodo", "todos")
|
|
62
|
+
.after(({data: [first]}) => ({data: first}));
|
|
52
63
|
});
|
|
53
64
|
|
|
54
65
|
// --- 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
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
function
|
|
5
|
-
return
|
|
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
|
|
8
|
-
return
|
|
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
|
|
11
|
-
class
|
|
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,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this
|
|
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,
|
|
39
|
-
const
|
|
40
|
-
return
|
|
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,
|
|
60
|
+
static get(t, e, n = {}) {
|
|
51
61
|
return this.createRoute(
|
|
52
62
|
t,
|
|
53
63
|
e,
|
|
54
|
-
|
|
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,
|
|
77
|
+
static post(t, e, n) {
|
|
68
78
|
return this.createRoute(
|
|
69
79
|
t,
|
|
70
80
|
e,
|
|
71
|
-
|
|
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,
|
|
94
|
+
static put(t, e, n) {
|
|
85
95
|
return this.createRoute(
|
|
86
96
|
t,
|
|
87
97
|
e,
|
|
88
|
-
|
|
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,
|
|
111
|
+
static delete(t, e, n) {
|
|
102
112
|
return this.createRoute(
|
|
103
113
|
t,
|
|
104
114
|
e,
|
|
105
|
-
|
|
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,
|
|
128
|
+
static patch(t, e, n) {
|
|
119
129
|
return this.createRoute(
|
|
120
130
|
t,
|
|
121
131
|
e,
|
|
122
|
-
|
|
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,
|
|
145
|
+
static options(t, e, n) {
|
|
136
146
|
return this.createRoute(
|
|
137
147
|
t,
|
|
138
148
|
e,
|
|
139
|
-
|
|
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
|
|
151
|
-
this.arguments.add(
|
|
178
|
+
const n = e.replace(/\[|]/g, "");
|
|
179
|
+
this.arguments.add(n);
|
|
152
180
|
});
|
|
153
181
|
}
|
|
154
182
|
}
|
|
155
|
-
const
|
|
156
|
-
async function
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
...
|
|
188
|
+
...a.headers,
|
|
161
189
|
...t.headers
|
|
162
|
-
},
|
|
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
|
|
165
|
-
let
|
|
166
|
-
return t.arguments.forEach((
|
|
167
|
-
if (e[
|
|
168
|
-
throw new Error(`Argument ${
|
|
169
|
-
|
|
170
|
-
}),
|
|
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
|
-
|
|
178
|
-
|
|
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),
|
|
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
|
|
241
|
-
if (!
|
|
301
|
+
const n = this._apis.get(t);
|
|
302
|
+
if (!n)
|
|
242
303
|
throw new Error(`API ${t} not found`);
|
|
243
|
-
return
|
|
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
|
-
|
|
253
|
-
const
|
|
254
|
-
if (!
|
|
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
|
|
338
|
+
return O(i, e, n, r);
|
|
257
339
|
};
|
|
258
340
|
}
|
|
259
341
|
};
|
|
260
|
-
|
|
261
|
-
let
|
|
262
|
-
class
|
|
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,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.name = t, this.url =
|
|
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,
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
return
|
|
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
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
package/package.json
CHANGED
package/src/core/Klaim.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Api } from "./Api";
|
|
2
|
-
import {
|
|
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
|
-
|
|
25
|
+
let url = applyArgs(`${api.url}/${route.url}`, route, args);
|
|
25
26
|
|
|
26
|
-
|
|
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
|
|
43
|
-
|
|
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
|
+
}
|
package/src/core/Registry.ts
CHANGED
|
@@ -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 =>
|
|
11
|
-
|
|
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;
|