@jsarc/cp-request 0.0.0
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 +726 -0
- package/index.ts +1064 -0
- package/js/index.js +665 -0
- package/package.json +22 -0
- package/tsconfig.json +27 -0
- package/web/cp-request.js +6716 -0
- package/web/cp-request.min.js +1 -0
package/js/index.js
ADDED
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
import JON from '@jsarc/jon';
|
|
2
|
+
import { Pajo } from '@jsarc/pajo';
|
|
3
|
+
import { qust } from '@jsarc/qust';
|
|
4
|
+
const globalFunct = (function (global) {
|
|
5
|
+
'use strict';
|
|
6
|
+
const NODEENV = 'development';
|
|
7
|
+
const langs = ['en', 'fr'];
|
|
8
|
+
const langCodes = {
|
|
9
|
+
'fr': 'fr_FR',
|
|
10
|
+
'en': 'en_US',
|
|
11
|
+
};
|
|
12
|
+
const dateTimeFormatInitial = '%Y-%m-%dT%H:%M:%S.%fZ';
|
|
13
|
+
const dateFormatInitial = '%Y-%m-%d';
|
|
14
|
+
const timeFormatInitial = '%H:%M:%S.%fZ';
|
|
15
|
+
const dateFormatForFile = '%Y%m%d%H%M%S';
|
|
16
|
+
const dateFormat1 = '%Y/%m/%d %H:%M:%S.%fZ';
|
|
17
|
+
const dateFormat2 = '%Y/%m/%d %H:%M:%S';
|
|
18
|
+
const dateFormat3 = '%Y/%m/%d %H:%M';
|
|
19
|
+
const dateFormat4 = '%d/%m/%Y %H:%M:%S GMT%z';
|
|
20
|
+
const dateFormat5 = '%Y/%m/%d';
|
|
21
|
+
const timeFormat1 = '%H:%M:%S.%fZ';
|
|
22
|
+
const timeFormat2 = '%H:%M:%S';
|
|
23
|
+
const timeFormat3 = '%H:%M:%S.%f';
|
|
24
|
+
const pagesPossibles = [5, 10, 15, 25, 50, 100, -1];
|
|
25
|
+
const regExpForAlphanumeric = /^[\w\s]{1,}/;
|
|
26
|
+
const tabNumerique = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
27
|
+
const tabAlphabetique = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
|
|
28
|
+
const tabAlphabetiqueInsensitive = [...tabAlphabetique, ...tabAlphabetique.map(x => x.toUpperCase())];
|
|
29
|
+
const tabAlphanumerique = [...tabNumerique, ...tabAlphabetique];
|
|
30
|
+
const tabAlphanumeriqueInsensitive = [...tabNumerique, ...tabAlphabetiqueInsensitive];
|
|
31
|
+
function defaultMapAction(code, type, message, data, cleanedData, error, errors) {
|
|
32
|
+
return ({
|
|
33
|
+
response: {
|
|
34
|
+
code,
|
|
35
|
+
type,
|
|
36
|
+
message,
|
|
37
|
+
},
|
|
38
|
+
data: cleanedData,
|
|
39
|
+
error,
|
|
40
|
+
errors,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
;
|
|
44
|
+
function defaultErrMapAction(code, type, message, data, cleanedData, error, errors) {
|
|
45
|
+
return ({
|
|
46
|
+
response: {
|
|
47
|
+
code,
|
|
48
|
+
type,
|
|
49
|
+
message,
|
|
50
|
+
},
|
|
51
|
+
data: cleanedData,
|
|
52
|
+
error,
|
|
53
|
+
errors,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function defaultSuccessAction(response) {
|
|
57
|
+
if (NODEENV === 'development') {
|
|
58
|
+
console.log('HttpRequest - actionRequest | successActionF - response:: ', response);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function defaultErrorAction(response) {
|
|
62
|
+
if (NODEENV === 'development') {
|
|
63
|
+
console.log('HttpRequest - actionRequest | errorActionF - response:: ', response, ' && (typeof response):: ', (typeof response));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function getNotifRequestType(status = undefined) {
|
|
67
|
+
let type = "success";
|
|
68
|
+
if ([200].includes(status) || !status) {
|
|
69
|
+
status = 200;
|
|
70
|
+
type = "success";
|
|
71
|
+
}
|
|
72
|
+
else if ([422].includes(status)) {
|
|
73
|
+
type = "warning";
|
|
74
|
+
}
|
|
75
|
+
else if ([403, 409].includes(status)) {
|
|
76
|
+
type = "error_auth";
|
|
77
|
+
}
|
|
78
|
+
else if ([419, 401].includes(status)) {
|
|
79
|
+
type = "error_auth_required";
|
|
80
|
+
}
|
|
81
|
+
else if ([404, 405, 500, 400].includes(status)) {
|
|
82
|
+
type = "error";
|
|
83
|
+
}
|
|
84
|
+
else if ([501].includes(status)) {
|
|
85
|
+
type = "info";
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
type = "error";
|
|
89
|
+
}
|
|
90
|
+
return type;
|
|
91
|
+
}
|
|
92
|
+
class HttpRequest {
|
|
93
|
+
host;
|
|
94
|
+
lang = 'fr';
|
|
95
|
+
constructor() {
|
|
96
|
+
}
|
|
97
|
+
initConfig(host, lang) {
|
|
98
|
+
if (typeof host === 'string' && host.length > 0) {
|
|
99
|
+
this.host = host;
|
|
100
|
+
}
|
|
101
|
+
if (['fr', 'en'].includes(lang)) {
|
|
102
|
+
this.lang = lang;
|
|
103
|
+
}
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
getDefaultError() {
|
|
107
|
+
const message = {
|
|
108
|
+
fr: 'Error lors de la recuperation de la reponse',
|
|
109
|
+
en: 'Error lors de la recuperation de la reponse',
|
|
110
|
+
}[this.lang];
|
|
111
|
+
return {
|
|
112
|
+
response: {
|
|
113
|
+
code: 404,
|
|
114
|
+
type: 'error',
|
|
115
|
+
message: message
|
|
116
|
+
},
|
|
117
|
+
data: undefined,
|
|
118
|
+
error: new Error(message),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async actionRequest(urlParams = {
|
|
122
|
+
path: "",
|
|
123
|
+
method: "GET",
|
|
124
|
+
}, otherParams = {}, schema = undefined, mapAction, errMapAction, successAction, errorAction) {
|
|
125
|
+
if (NODEENV === 'development') {
|
|
126
|
+
console.log('HttpRequest - actionRequest | urlParams:: ', urlParams);
|
|
127
|
+
console.log('HttpRequest - actionRequest | otherParams:: ', otherParams);
|
|
128
|
+
console.log('HttpRequest - actionRequest | schema:: ', schema);
|
|
129
|
+
}
|
|
130
|
+
const FetchClass = this.getFetchClass();
|
|
131
|
+
urlParams = (typeof urlParams === "object" &&
|
|
132
|
+
Array.isArray(urlParams) === false) ? urlParams : {
|
|
133
|
+
path: "",
|
|
134
|
+
method: "GET",
|
|
135
|
+
};
|
|
136
|
+
const responseType = (!!urlParams?.responseType &&
|
|
137
|
+
["json", "arraybuffer", "blob", "text"].includes(urlParams?.responseType)) ? urlParams?.responseType : 'json';
|
|
138
|
+
const method = [
|
|
139
|
+
"GET",
|
|
140
|
+
"POST",
|
|
141
|
+
"PUT",
|
|
142
|
+
"DELETE",
|
|
143
|
+
].includes(urlParams?.method) ? urlParams?.method : "GET";
|
|
144
|
+
let path = (typeof urlParams?.path === "string") ? urlParams?.path : "";
|
|
145
|
+
let headers = (typeof urlParams?.headers === "object" &&
|
|
146
|
+
Array.isArray(urlParams?.headers) === false &&
|
|
147
|
+
Object.keys(urlParams?.headers).length > 0) ? urlParams?.headers : undefined;
|
|
148
|
+
let params = (typeof urlParams?.params === "object" &&
|
|
149
|
+
Array.isArray(urlParams?.params) === false &&
|
|
150
|
+
Object.keys(urlParams?.params).length > 0) ? urlParams?.params : undefined;
|
|
151
|
+
let body = ((typeof urlParams?.body === "object" &&
|
|
152
|
+
Array.isArray(urlParams?.body) === false) || urlParams?.body instanceof FormData) ? urlParams?.body : undefined;
|
|
153
|
+
if (typeof body === "object" &&
|
|
154
|
+
Array.isArray(body) === false) {
|
|
155
|
+
body = JSON.stringify(urlParams?.body);
|
|
156
|
+
}
|
|
157
|
+
otherParams = (typeof otherParams === "object" &&
|
|
158
|
+
Array.isArray(otherParams) == false) ? otherParams : {};
|
|
159
|
+
if (!!urlParams?.auth) {
|
|
160
|
+
headers = {
|
|
161
|
+
...headers,
|
|
162
|
+
Authorization: `Basic ${btoa(`${urlParams?.auth?.username}:${urlParams?.auth?.password}`)}`,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const mapActionF = (!!mapAction) ? mapAction : defaultMapAction;
|
|
166
|
+
const errMapActionF = (!!errMapAction) ? errMapAction : defaultErrMapAction;
|
|
167
|
+
const successActionF = !!successAction ? successAction : defaultSuccessAction;
|
|
168
|
+
const errorActionF = (!!errorAction) ? errorAction : defaultErrorAction;
|
|
169
|
+
if (!(schema instanceof JON.Object)) {
|
|
170
|
+
schema = new JON.Object(this.lang);
|
|
171
|
+
}
|
|
172
|
+
schema = schema.required();
|
|
173
|
+
try {
|
|
174
|
+
const newPath = (typeof this.host === 'string' &&
|
|
175
|
+
this.host.length > 0) ? Pajo.joinWithHost(this.host, path) : Pajo.join(path);
|
|
176
|
+
if (!!newPath) {
|
|
177
|
+
path = newPath;
|
|
178
|
+
}
|
|
179
|
+
if (!!params) {
|
|
180
|
+
path = `${path}${qust.stringify(params)}`;
|
|
181
|
+
}
|
|
182
|
+
let resConfig = {
|
|
183
|
+
method,
|
|
184
|
+
headers,
|
|
185
|
+
...otherParams,
|
|
186
|
+
};
|
|
187
|
+
if (!!body) {
|
|
188
|
+
resConfig.body = body;
|
|
189
|
+
}
|
|
190
|
+
if (NODEENV === 'development') {
|
|
191
|
+
console.log('HttpRequest - actionRequest | path (final):: ', path);
|
|
192
|
+
console.log('HttpRequest - actionRequest | resConfig:: ', resConfig);
|
|
193
|
+
}
|
|
194
|
+
const res = await FetchClass(path, {
|
|
195
|
+
...resConfig,
|
|
196
|
+
});
|
|
197
|
+
const hasContentType = !!res.headers.get("content-type");
|
|
198
|
+
const isJson = res.headers.get("content-type")?.includes("application/json");
|
|
199
|
+
if (NODEENV === 'development') {
|
|
200
|
+
console.log('HttpRequest - actionRequest | res:: ', res);
|
|
201
|
+
}
|
|
202
|
+
const statusResponse = res.status;
|
|
203
|
+
const typeResponse = getNotifRequestType(statusResponse);
|
|
204
|
+
let httpRes = undefined;
|
|
205
|
+
if (responseType === 'text' && hasContentType) {
|
|
206
|
+
httpRes = await res.text();
|
|
207
|
+
}
|
|
208
|
+
else if (responseType === 'json' && !!isJson) {
|
|
209
|
+
httpRes = await res.json();
|
|
210
|
+
}
|
|
211
|
+
else if (responseType === 'arraybuffer' && hasContentType) {
|
|
212
|
+
httpRes = await res.arrayBuffer();
|
|
213
|
+
}
|
|
214
|
+
let errors = undefined;
|
|
215
|
+
if (typeof httpRes === 'object' &&
|
|
216
|
+
!Array.isArray(httpRes)) {
|
|
217
|
+
errors = httpRes?.errors;
|
|
218
|
+
}
|
|
219
|
+
else if (typeof httpRes === 'string' &&
|
|
220
|
+
!(['info', 'success'].includes(typeResponse))) {
|
|
221
|
+
errors = httpRes;
|
|
222
|
+
}
|
|
223
|
+
if (NODEENV === 'development') {
|
|
224
|
+
console.log('HttpRequest - actionRequest | httpRes:: ', httpRes);
|
|
225
|
+
}
|
|
226
|
+
let messageNotif = undefined;
|
|
227
|
+
if (!res.ok) {
|
|
228
|
+
if (typeof errors === 'object' &&
|
|
229
|
+
!Array.isArray(errors) &&
|
|
230
|
+
Object.keys(errors).length > 0) {
|
|
231
|
+
messageNotif = errors[Object.keys(errors)[Object.keys(errors).length - 1]];
|
|
232
|
+
}
|
|
233
|
+
else if (!!httpRes?.message) {
|
|
234
|
+
messageNotif = httpRes?.message;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
messageNotif = {
|
|
238
|
+
en: "unknown error",
|
|
239
|
+
fr: "erreur inconnue",
|
|
240
|
+
}[this.lang];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (NODEENV === 'development') {
|
|
244
|
+
console.log("HttpRequest - actionRequest | messageNotif:: ", messageNotif);
|
|
245
|
+
}
|
|
246
|
+
let codeF = statusResponse || (!!res.ok ? 200 : 404);
|
|
247
|
+
let typeF = (!!statusResponse ? typeResponse : (!!res.ok ? "success" : "error"));
|
|
248
|
+
let messageF = messageNotif;
|
|
249
|
+
let correctDataF = schema.isValid(httpRes);
|
|
250
|
+
let dataF = ((!!res.ok) ? httpRes : undefined);
|
|
251
|
+
let cleanedDataF = !!correctDataF ? dataF : this.getDefaultError();
|
|
252
|
+
let errorsF = undefined;
|
|
253
|
+
if (typeof errors === 'object' && !Array.isArray(errors)) {
|
|
254
|
+
errorsF = Object.values(errors);
|
|
255
|
+
}
|
|
256
|
+
else if (typeof errors === 'object' && !!Array.isArray(errors)) {
|
|
257
|
+
errorsF = errorsF;
|
|
258
|
+
}
|
|
259
|
+
else if (typeof errors === 'string' && errors.length > 0) {
|
|
260
|
+
errorsF = [errorsF];
|
|
261
|
+
}
|
|
262
|
+
let errorF = errorsF?.[0];
|
|
263
|
+
errorF = (!(errorF instanceof Error || typeof errorF === 'undefined' || errorF === null)) ? new Error(`${errorF}`) : errorF;
|
|
264
|
+
if (!errorF && !!messageNotif) {
|
|
265
|
+
errorF = new Error(`${messageNotif}`);
|
|
266
|
+
errorsF = [messageNotif];
|
|
267
|
+
}
|
|
268
|
+
const cleanedData = (['success', 'info'].includes(typeF)) ? mapActionF(codeF, typeF, messageF, dataF, cleanedDataF, errorF, errorsF) : errMapActionF(codeF, typeF, messageF, dataF, cleanedDataF, errorF, errorsF);
|
|
269
|
+
if (NODEENV === 'development') {
|
|
270
|
+
console.log("HttpRequest - actionRequest | cleanedData (OLD):: ", cleanedData);
|
|
271
|
+
}
|
|
272
|
+
if (cleanedData.response.type === "success") {
|
|
273
|
+
await successActionF(cleanedData);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
await errorActionF(cleanedData);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
let message = 'erreur inconnue';
|
|
281
|
+
if (typeof error?.message === 'string') {
|
|
282
|
+
message = error?.message;
|
|
283
|
+
}
|
|
284
|
+
else if (typeof error === 'string') {
|
|
285
|
+
message = error;
|
|
286
|
+
}
|
|
287
|
+
if (message.toLowerCase() === 'failed to fetch') {
|
|
288
|
+
message = {
|
|
289
|
+
en: "Service unavailable. Please try again later.",
|
|
290
|
+
fr: "Service indisponible. Veuillez réessayer plus tard.",
|
|
291
|
+
}[this.lang];
|
|
292
|
+
}
|
|
293
|
+
if (NODEENV === 'development') {
|
|
294
|
+
console.log("[ERROR] HttpRequest - actionRequest | error:: ", error);
|
|
295
|
+
console.log("[ERROR] HttpRequest - actionRequest | message:: ", message);
|
|
296
|
+
}
|
|
297
|
+
let codeF = error?.status || 404;
|
|
298
|
+
let typeF = !!error?.status ? getNotifRequestType(error?.status) : "error";
|
|
299
|
+
let messageF = message;
|
|
300
|
+
let dataF = error;
|
|
301
|
+
let correctDataF = schema.isValid(dataF);
|
|
302
|
+
let cleanedDataF = !!correctDataF ? dataF : this.getDefaultError();
|
|
303
|
+
let errorsF = [message];
|
|
304
|
+
if (typeof errorsF === 'object' && !Array.isArray(errorsF)) {
|
|
305
|
+
errorsF = Object.values(errorsF);
|
|
306
|
+
}
|
|
307
|
+
else if (typeof errorsF === 'object' && !!Array.isArray(errorsF)) {
|
|
308
|
+
errorsF = errorsF;
|
|
309
|
+
}
|
|
310
|
+
else if (typeof errorsF === 'string' && errorsF.length > 0) {
|
|
311
|
+
errorsF = [errorsF];
|
|
312
|
+
}
|
|
313
|
+
let errorF = errorsF?.[0];
|
|
314
|
+
errorF = (!(errorF instanceof Error || typeof errorF === 'undefined' || errorF === null)) ? new Error(`${errorF}`) : errorF;
|
|
315
|
+
if (!errorF && !!message) {
|
|
316
|
+
errorF = new Error(`${message}`);
|
|
317
|
+
errorsF = [message];
|
|
318
|
+
}
|
|
319
|
+
if (NODEENV === 'development') {
|
|
320
|
+
console.log("[ERROR] HttpRequest - actionRequest | codeF:: ", codeF);
|
|
321
|
+
console.log("[ERROR] HttpRequest - actionRequest | typeF:: ", typeF);
|
|
322
|
+
console.log("[ERROR] HttpRequest - actionRequest | dataF:: ", dataF);
|
|
323
|
+
console.log("[ERROR] HttpRequest - actionRequest | correctDataF:: ", correctDataF);
|
|
324
|
+
console.log("[ERROR] HttpRequest - actionRequest | cleanedDataF:: ", cleanedDataF);
|
|
325
|
+
console.log("[ERROR] HttpRequest - actionRequest | errorsF:: ", errorsF);
|
|
326
|
+
console.log("[ERROR] HttpRequest - actionRequest | errorsF:: ", errorsF);
|
|
327
|
+
}
|
|
328
|
+
const errorDatas = errMapActionF(codeF, typeF, messageF, dataF, cleanedDataF, errorF, errorsF);
|
|
329
|
+
if (NODEENV === 'development') {
|
|
330
|
+
console.log("[ERROR] HttpRequest - actionRequest | errorDatas:: ", errorDatas);
|
|
331
|
+
}
|
|
332
|
+
await errorActionF(errorDatas);
|
|
333
|
+
return errorDatas;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
async findAllRequests(urlParams = {
|
|
337
|
+
path: "",
|
|
338
|
+
method: "GET",
|
|
339
|
+
}, otherParams = {}, successAction = defaultSuccessAction, errorAction = defaultErrorAction) {
|
|
340
|
+
const schema = new JON.Object(this.lang).struct({
|
|
341
|
+
response: new JON.Object(this.lang).struct({
|
|
342
|
+
type: new JON.Enum(this.lang).choices('warning', 'success', 'danger', 'info').required(),
|
|
343
|
+
code: new JON.Number(this.lang).required(),
|
|
344
|
+
message: new JON.String(this.lang),
|
|
345
|
+
}),
|
|
346
|
+
datas: new JON.Array(this.lang).types(new JON.Object(this.lang).min(1).required()).required().default([]),
|
|
347
|
+
});
|
|
348
|
+
const mapAction = (code, type, message, data, cleanedData, error, errors) => {
|
|
349
|
+
return ({
|
|
350
|
+
response: {
|
|
351
|
+
code,
|
|
352
|
+
type,
|
|
353
|
+
message,
|
|
354
|
+
},
|
|
355
|
+
data: cleanedData?.datas,
|
|
356
|
+
error,
|
|
357
|
+
errors,
|
|
358
|
+
});
|
|
359
|
+
};
|
|
360
|
+
const errMapAction = (code, type, message, data, cleanedData, error, errors) => {
|
|
361
|
+
return ({
|
|
362
|
+
response: {
|
|
363
|
+
code,
|
|
364
|
+
type,
|
|
365
|
+
message,
|
|
366
|
+
},
|
|
367
|
+
data: cleanedData?.datas,
|
|
368
|
+
error,
|
|
369
|
+
errors,
|
|
370
|
+
});
|
|
371
|
+
};
|
|
372
|
+
await this.actionRequest(urlParams, otherParams, schema, mapAction, errMapAction, successAction, errorAction);
|
|
373
|
+
}
|
|
374
|
+
async findOneRequest(urlParams = {
|
|
375
|
+
path: "",
|
|
376
|
+
method: "GET",
|
|
377
|
+
}, otherParams = {}, successAction = defaultSuccessAction, errorAction = defaultErrorAction) {
|
|
378
|
+
const schema = new JON.Object(this.lang).struct({
|
|
379
|
+
response: new JON.Object(this.lang).struct({
|
|
380
|
+
type: new JON.Enum(this.lang).choices('warning', 'success', 'danger', 'info').required(),
|
|
381
|
+
code: new JON.Number(this.lang).required(),
|
|
382
|
+
message: new JON.String(this.lang),
|
|
383
|
+
}),
|
|
384
|
+
data: new JON.Object(this.lang).min(1),
|
|
385
|
+
});
|
|
386
|
+
const mapAction = (code, type, message, data, cleanedData, error, errors) => {
|
|
387
|
+
return ({
|
|
388
|
+
response: {
|
|
389
|
+
code,
|
|
390
|
+
type,
|
|
391
|
+
message,
|
|
392
|
+
},
|
|
393
|
+
data: cleanedData?.data,
|
|
394
|
+
error,
|
|
395
|
+
errors,
|
|
396
|
+
});
|
|
397
|
+
};
|
|
398
|
+
const errMapAction = (code, type, message, data, cleanedData, error, errors) => {
|
|
399
|
+
return ({
|
|
400
|
+
response: {
|
|
401
|
+
code,
|
|
402
|
+
type,
|
|
403
|
+
message,
|
|
404
|
+
},
|
|
405
|
+
data: cleanedData?.data,
|
|
406
|
+
error,
|
|
407
|
+
errors,
|
|
408
|
+
});
|
|
409
|
+
};
|
|
410
|
+
await this.actionRequest(urlParams, otherParams, schema, mapAction, errMapAction, successAction, errorAction);
|
|
411
|
+
}
|
|
412
|
+
getFetchClass() {
|
|
413
|
+
return (typeof window !== "undefined") ? window.fetch : fetch;
|
|
414
|
+
}
|
|
415
|
+
static exposeToGlobal() {
|
|
416
|
+
if (typeof window !== "undefined") {
|
|
417
|
+
window.HttpRequest = HttpRequest;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (typeof window !== "undefined") {
|
|
422
|
+
window.HttpRequest = HttpRequest;
|
|
423
|
+
}
|
|
424
|
+
function defaultMapActionWS(code, type, message, data, cleanedData, error, errors) {
|
|
425
|
+
return {
|
|
426
|
+
response: { code, type, message },
|
|
427
|
+
data: cleanedData,
|
|
428
|
+
error,
|
|
429
|
+
errors,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
function defaultErrMapActionWS(code, type, message, data, cleanedData, error, errors) {
|
|
433
|
+
return {
|
|
434
|
+
response: { code, type, message },
|
|
435
|
+
data: cleanedData,
|
|
436
|
+
error,
|
|
437
|
+
errors,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
function defaultSuccessActionWS(res) {
|
|
441
|
+
if (NODEENV === "development") {
|
|
442
|
+
console.log("WsRequest | success :: ", res);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function defaultErrorActionWS(res) {
|
|
446
|
+
if (NODEENV === "development") {
|
|
447
|
+
console.log("WsRequest | error :: ", res);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
class WsRequest {
|
|
451
|
+
host;
|
|
452
|
+
lang = "fr";
|
|
453
|
+
socket = null;
|
|
454
|
+
connected = false;
|
|
455
|
+
autoReconnect = true;
|
|
456
|
+
reconnectDelay = 2000;
|
|
457
|
+
maxReconnectAttempts = 10;
|
|
458
|
+
reconnectAttempts = 0;
|
|
459
|
+
messageQueue = [];
|
|
460
|
+
constructor() { }
|
|
461
|
+
initConfig(host, lang) {
|
|
462
|
+
if (host && typeof host === "string") {
|
|
463
|
+
this.host = host;
|
|
464
|
+
}
|
|
465
|
+
if (["fr", "en"].includes(lang)) {
|
|
466
|
+
this.lang = lang;
|
|
467
|
+
}
|
|
468
|
+
return this;
|
|
469
|
+
}
|
|
470
|
+
connect(params) {
|
|
471
|
+
const { path, auth, headers = {}, autoReconnect = true, reconnectDelay = 2000, maxReconnectAttempts = 10, } = params;
|
|
472
|
+
let urlParams = (typeof params?.params === "object" &&
|
|
473
|
+
!Array.isArray(params?.params) &&
|
|
474
|
+
Object.keys(params?.params).length > 0) ? params?.params : undefined;
|
|
475
|
+
this.autoReconnect = autoReconnect;
|
|
476
|
+
this.reconnectDelay = reconnectDelay;
|
|
477
|
+
this.maxReconnectAttempts = maxReconnectAttempts;
|
|
478
|
+
let url = (typeof this.host === 'string' &&
|
|
479
|
+
this.host.length > 0) ? Pajo.joinWithHost(this.host, path) : Pajo.join(path);
|
|
480
|
+
if (!!urlParams) {
|
|
481
|
+
url = `${url}${qust.stringify(urlParams)}`;
|
|
482
|
+
}
|
|
483
|
+
if (auth) {
|
|
484
|
+
headers["Authorization"] =
|
|
485
|
+
"Basic " + btoa(`${auth.username}:${auth.password}`);
|
|
486
|
+
}
|
|
487
|
+
if (NODEENV === "development") {
|
|
488
|
+
console.log("WsRequest | connecting to:", url);
|
|
489
|
+
}
|
|
490
|
+
this.socket = new (this.getWsClass())(url || '');
|
|
491
|
+
if (!!this.socket) {
|
|
492
|
+
this.socket.onopen = () => {
|
|
493
|
+
this.connected = true;
|
|
494
|
+
this.reconnectAttempts = 0;
|
|
495
|
+
if (NODEENV === "development") {
|
|
496
|
+
console.log("WsRequest | WebSocket connected");
|
|
497
|
+
}
|
|
498
|
+
while (this.messageQueue.length > 0) {
|
|
499
|
+
this.socket?.send(this.messageQueue.shift());
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
this.socket.onerror = (err) => {
|
|
503
|
+
if (NODEENV === "development") {
|
|
504
|
+
console.log("WsRequest | error:", err);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
this.socket.onclose = () => {
|
|
508
|
+
this.connected = false;
|
|
509
|
+
if (NODEENV === "development") {
|
|
510
|
+
console.log("WsRequest | closed");
|
|
511
|
+
}
|
|
512
|
+
if (this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
513
|
+
setTimeout(() => {
|
|
514
|
+
this.reconnectAttempts++;
|
|
515
|
+
if (NODEENV === "development") {
|
|
516
|
+
console.log("WsRequest | reconnect attempt:", this.reconnectAttempts);
|
|
517
|
+
}
|
|
518
|
+
this.connect(params);
|
|
519
|
+
}, this.reconnectDelay);
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async actionMessage(message, schema = undefined, mapAction = defaultMapActionWS, errMapAction = defaultErrMapActionWS, successAction = defaultSuccessActionWS, errorAction = defaultErrorActionWS) {
|
|
525
|
+
if (!this.connected || !this.socket) {
|
|
526
|
+
this.messageQueue.push(JSON.stringify(message));
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (!(schema instanceof JON.Object)) {
|
|
530
|
+
schema = new JON.Object(this.lang);
|
|
531
|
+
}
|
|
532
|
+
schema = schema.required();
|
|
533
|
+
const payload = JSON.stringify(message);
|
|
534
|
+
return new Promise((resolve) => {
|
|
535
|
+
this.socket.onmessage = async (e) => {
|
|
536
|
+
let resJson = undefined;
|
|
537
|
+
try {
|
|
538
|
+
resJson = JSON.parse(e.data);
|
|
539
|
+
}
|
|
540
|
+
catch (err) {
|
|
541
|
+
resJson = e.data;
|
|
542
|
+
}
|
|
543
|
+
let isValid = schema.isValid(resJson);
|
|
544
|
+
let cleaned = isValid ? resJson : undefined;
|
|
545
|
+
let codeF = resJson?.response?.code ?? 200;
|
|
546
|
+
let typeF = resJson?.response?.type ?? "success";
|
|
547
|
+
let messageF = resJson?.response?.message ?? undefined;
|
|
548
|
+
let errorsF = [];
|
|
549
|
+
if (resJson?.errors) {
|
|
550
|
+
errorsF = Array.isArray(resJson.errors)
|
|
551
|
+
? resJson.errors
|
|
552
|
+
: Object.values(resJson.errors);
|
|
553
|
+
}
|
|
554
|
+
let errorF = errorsF?.[0];
|
|
555
|
+
if (!(errorF instanceof Error)) {
|
|
556
|
+
if (typeof errorF !== "undefined")
|
|
557
|
+
errorF = new Error(`${errorF}`);
|
|
558
|
+
}
|
|
559
|
+
const responseCleaned = typeF === "success" || typeF === "info"
|
|
560
|
+
? mapAction(codeF, typeF, messageF, resJson, cleaned, errorF, errorsF)
|
|
561
|
+
: errMapAction(codeF, typeF, messageF, resJson, cleaned, errorF, errorsF);
|
|
562
|
+
if (responseCleaned.response.type === "success") {
|
|
563
|
+
await successAction(responseCleaned);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
await errorAction(responseCleaned);
|
|
567
|
+
}
|
|
568
|
+
resolve(responseCleaned);
|
|
569
|
+
};
|
|
570
|
+
this.socket.send(payload);
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
async findAllMessages(message, successAction = defaultSuccessActionWS, errorAction = defaultErrorActionWS) {
|
|
574
|
+
const schema = new JON.Object(this.lang).struct({
|
|
575
|
+
response: new JON.Object(this.lang).struct({
|
|
576
|
+
type: new JON.Enum(this.lang)
|
|
577
|
+
.choices("warning", "success", "danger", "info")
|
|
578
|
+
.required(),
|
|
579
|
+
code: new JON.Number(this.lang).required(),
|
|
580
|
+
message: new JON.String(this.lang),
|
|
581
|
+
}),
|
|
582
|
+
datas: new JON.Array(this.lang)
|
|
583
|
+
.types(new JON.Object(this.lang).min(1).required())
|
|
584
|
+
.default([]),
|
|
585
|
+
});
|
|
586
|
+
const mapAction = (code, type, message, data, cleaned, error, errors) => {
|
|
587
|
+
return {
|
|
588
|
+
response: { code, type, message },
|
|
589
|
+
data: cleaned?.datas || [],
|
|
590
|
+
error,
|
|
591
|
+
errors,
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
return await this.actionMessage(message, schema, mapAction, mapAction, successAction, errorAction);
|
|
595
|
+
}
|
|
596
|
+
async findOneMessage(message, successAction = defaultSuccessActionWS, errorAction = defaultErrorActionWS) {
|
|
597
|
+
const schema = new JON.Object(this.lang).struct({
|
|
598
|
+
response: new JON.Object(this.lang).struct({
|
|
599
|
+
type: new JON.Enum(this.lang)
|
|
600
|
+
.choices("warning", "success", "danger", "info")
|
|
601
|
+
.required(),
|
|
602
|
+
code: new JON.Number(this.lang).required(),
|
|
603
|
+
message: new JON.String(this.lang),
|
|
604
|
+
}),
|
|
605
|
+
data: new JON.Object(this.lang).min(1),
|
|
606
|
+
});
|
|
607
|
+
const mapAction = (code, type, message, data, cleaned, error, errors) => {
|
|
608
|
+
return {
|
|
609
|
+
response: { code, type, message },
|
|
610
|
+
data: cleaned?.data || null,
|
|
611
|
+
error,
|
|
612
|
+
errors,
|
|
613
|
+
};
|
|
614
|
+
};
|
|
615
|
+
return await this.actionMessage(message, schema, mapAction, mapAction, successAction, errorAction);
|
|
616
|
+
}
|
|
617
|
+
getWsClass() {
|
|
618
|
+
return (typeof window !== "undefined") ? window.WebSocket : WebSocket;
|
|
619
|
+
}
|
|
620
|
+
static exposeToGlobal() {
|
|
621
|
+
if (typeof window !== "undefined") {
|
|
622
|
+
window.WsRequest = WsRequest;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (typeof window !== "undefined") {
|
|
627
|
+
window.WsRequest = WsRequest;
|
|
628
|
+
}
|
|
629
|
+
const defaultExport = {
|
|
630
|
+
HttpRequest,
|
|
631
|
+
WsRequest,
|
|
632
|
+
};
|
|
633
|
+
const globalFunctModule = {
|
|
634
|
+
default: defaultExport,
|
|
635
|
+
HttpRequest: HttpRequest,
|
|
636
|
+
WsRequest: WsRequest,
|
|
637
|
+
};
|
|
638
|
+
const __bundledModules = globalFunctModule;
|
|
639
|
+
if (typeof global !== 'undefined') {
|
|
640
|
+
global.default = defaultExport;
|
|
641
|
+
global.HttpRequest = HttpRequest;
|
|
642
|
+
global.WsRequest = WsRequest;
|
|
643
|
+
global.__bundledModules = __bundledModules;
|
|
644
|
+
}
|
|
645
|
+
if (typeof window !== "undefined") {
|
|
646
|
+
window.default = defaultExport;
|
|
647
|
+
window.HttpRequest = HttpRequest;
|
|
648
|
+
window.WsRequest = WsRequest;
|
|
649
|
+
window.__bundledModules = __bundledModules;
|
|
650
|
+
}
|
|
651
|
+
if (typeof exports !== 'undefined') {
|
|
652
|
+
exports.default = defaultExport;
|
|
653
|
+
exports.HttpRequest = HttpRequest;
|
|
654
|
+
exports.WsRequest = WsRequest;
|
|
655
|
+
}
|
|
656
|
+
return globalFunctModule;
|
|
657
|
+
})(typeof global !== 'undefined' ? global :
|
|
658
|
+
typeof window !== 'undefined' ? window :
|
|
659
|
+
typeof self !== 'undefined' ? self :
|
|
660
|
+
typeof globalThis !== 'undefined' ? globalThis :
|
|
661
|
+
{});
|
|
662
|
+
const HttpRequestElementGF = globalFunct.HttpRequest;
|
|
663
|
+
const WsRequestElementGF = globalFunct.WsRequest;
|
|
664
|
+
const defaultElementGF = globalFunct.default;
|
|
665
|
+
export { defaultElementGF as default, HttpRequestElementGF as HttpRequest, WsRequestElementGF as WsRequest, };
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jsarc/cp-request",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "0.0.0",
|
|
7
|
+
"description": "CP-REQUEST est une bibliothèque TypeScript complète pour gérer les requêtes HTTP et WebSocket avec une API unifiée et type-safe. Elle offre une solution robuste pour les communications client-serveur avec gestion automatique des erreurs, validation des schémas et support multi-langue.",
|
|
8
|
+
"main": "index.ts",
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "INICODE <contact.inicode@gmail.com>",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"init": "npm init --scope=@jsarc/cp-request",
|
|
14
|
+
"login": "npm login"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@jsarc/jon": "^0.0.1",
|
|
19
|
+
"@jsarc/pajo": "^0.0.1-beta.0.1",
|
|
20
|
+
"@jsarc/qust": "^0.0.1-beta.0.1"
|
|
21
|
+
}
|
|
22
|
+
}
|