Skip to content

Commit c9b1f82

Browse files
committed
added new js lib
1 parent 4772f7e commit c9b1f82

File tree

2 files changed

+220
-0
lines changed

2 files changed

+220
-0
lines changed

example/js api_caller lib/api_caller.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
<config>{
2+
"out": ".",
3+
"css": false,
4+
"jsMinify": true,
5+
"jsObfuscate": false,
6+
"jsScope": false,
7+
"jsIIFE": false,
8+
"prefix": null
9+
}</config>
10+
<script>
11+
class APICaller {
12+
static #desc = [
13+
'OK',
14+
'Invalid request',
15+
'Authorization failed',
16+
'Request failed',
17+
'Server error',
18+
'Invalid server response (JSON error)',
19+
];
20+
static #isObj(value) {
21+
return (typeof value === 'object' && value !== null);
22+
}
23+
#config;
24+
logging = {};
25+
26+
constructor({
27+
url,
28+
headers = null,
29+
logging = {
30+
master: true,
31+
collapsed: true,
32+
full: false,
33+
34+
params: false,
35+
debug: true,
36+
meta: false,
37+
}
38+
} = {}) {
39+
try {
40+
url = (new URL(url)).href;
41+
} catch (error) {
42+
throw new Error(`Invaild API url`);
43+
}
44+
if(!url.endsWith('/')) {
45+
url = `${url}/`;
46+
}
47+
headers ??= {};
48+
if(!APICaller.#isObj(headers)) {
49+
throw new Error('Invalid API headers; Expected an object;');
50+
}
51+
this.logging = Object.assign({}, this.logging, logging);
52+
this.#config = {
53+
url,
54+
headers
55+
}
56+
}
57+
async coreFetch({
58+
func = '',
59+
params = null,
60+
headers = null,
61+
logging = {}
62+
} = {}) {
63+
logging = Object.assign({}, this.logging, logging);
64+
headers ??= {};
65+
if(!APICaller.#isObj(headers)) {
66+
throw new Error('Invalid API headers; Expected an object;');
67+
}
68+
69+
let fetched;
70+
let ret = {
71+
status: 0,
72+
value: null,
73+
statusDesc: null,
74+
headers: null,
75+
meta: null,
76+
debug: null
77+
};
78+
79+
// Create fetch config
80+
const config = {
81+
method: 'POST',
82+
mode: 'cors'
83+
};
84+
// Combine default headers with current headers
85+
config.headers = Object.assign({}, this.#config.headers, headers);
86+
87+
// Add params if present
88+
if(APICaller.#isObj(params)) {
89+
config.headers['Content-Type'] = 'application/json';
90+
config.body = JSON.stringify(params);
91+
} else {
92+
config.method = 'GET';
93+
}
94+
95+
const url = `${this.#config.url}${func}`;
96+
97+
// Fetch data
98+
try {
99+
// console.log('API CALL', { url, params });
100+
fetched = await window.fetch(url, config);
101+
ret.headers = fetched.headers;
102+
} catch (error) {
103+
ret.status = -1;
104+
ret.statusDesc = 'Network failed';
105+
ret.value ??= error.message;
106+
return Promise.resolve(ret);
107+
}
108+
if(!fetched.ok) {
109+
ret.status = fetched.status;
110+
ret.statusDesc = APICaller.#desc[3];
111+
ret.value = fetched.statusText;
112+
return Promise.resolve(ret);
113+
}
114+
fetched = await fetched.text().catch(e => e.message);
115+
try {
116+
const json = JSON.parse(fetched);
117+
if(!APICaller.#isObj(json)) {
118+
throw new Error('Not object');
119+
}
120+
fetched = json;
121+
} catch (error) {
122+
ret.status = 5;
123+
ret.value = fetched;
124+
ret.statusDesc = APICaller.#desc[5];
125+
return Promise.resolve(ret);
126+
}
127+
ret = {...ret, ...fetched};
128+
129+
ret.statusDesc = APICaller.#desc[ret.status] ?? 'Unknown';
130+
131+
if(logging.master) {
132+
if(logging.full) {
133+
logging.collapsed ? console.groupCollapsed('API Call:', url) : console.group('API Call:', url);
134+
console.log('Request :', { url, params, headers });
135+
console.log('Response:', ret);
136+
console.groupEnd();
137+
} else {
138+
logging.collapsed ? console.groupCollapsed('API Call:', url) : console.group('API Call:', url);
139+
if(logging.params) {
140+
console.group('Request Params:', params);
141+
}
142+
if(logging.meta) {
143+
console.log('Response Meta:', ret.meta);
144+
}
145+
146+
console.log('Response Desc:', ret.statusDesc);
147+
console.log('Response Value:', ret.value);
148+
149+
if(logging.debug && ret.debug !== null) {
150+
console.log('Debug messages:');
151+
if(!Array.isArray(ret.debug)) {
152+
ret.debug = [ret.debug];
153+
}
154+
for(const msg of ret.debug) {
155+
console.log(msg);
156+
}
157+
}
158+
console.groupEnd();
159+
}
160+
}
161+
162+
return Promise.resolve(ret);
163+
}
164+
165+
#proxy() {
166+
/*
167+
syntax:
168+
this.proxy().funcGroup.funcName(params = null, {
169+
headers = null,
170+
logging = {},
171+
onerror = null
172+
} = {});
173+
*/
174+
const list = [];
175+
return new Proxy(function() {}, {
176+
get: (dummy, name, pxy) => {
177+
list.push(name);
178+
return pxy;
179+
},
180+
apply: async (dummy, pxy, args) => {
181+
const params = args[0] ?? null;
182+
let opts = {
183+
headers: null,
184+
logging: {},
185+
onerror: null
186+
};
187+
if(APICaller.#isObj(args[1])) {
188+
opts = Object.assign({}, opts, args[1]);
189+
}
190+
const resp = await this.coreFetch({
191+
func: list.join('.'),
192+
params: params,
193+
headers: opts.headers,
194+
logging: opts.logging
195+
});
196+
if(resp.status === 0) {
197+
return resp.value;
198+
} else {
199+
if(typeof opts.onerror === 'function') {
200+
opts.onerror(resp);
201+
} else {
202+
alert(`${resp.statusDesc}:\n${resp.value}`);
203+
// App.popupbox({
204+
// content: resp.value,
205+
// title: resp.statusDesc
206+
// });
207+
}
208+
}
209+
return null;
210+
}
211+
});
212+
}
213+
get fetch() {
214+
return this.#proxy();
215+
}
216+
}
217+
218+
export default APICaller;
219+
</script>

0 commit comments

Comments
 (0)