@arc-js/cp-request 0.0.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 +700 -0
- package/cp-request.all.js +6594 -0
- package/cp-request.all.min.js +2 -0
- package/cp-request.all.min.js.map +1 -0
- package/index.d.ts +116 -0
- package/index.js +642 -0
- package/index.min.d.ts +116 -0
- package/index.min.js +2 -0
- package/index.min.js.map +1 -0
- package/package.json +22 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
# @arc-js/cp-request
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
**@arc-js/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.
|
|
9
|
+
|
|
10
|
+
## ✨ Fonctionnalités Principales
|
|
11
|
+
|
|
12
|
+
### 🌐 HTTP Request (HttpRequest)
|
|
13
|
+
- **Méthodes HTTP complètes** : GET, POST, PUT, DELETE
|
|
14
|
+
- **Gestion intelligente des erreurs** : mapping automatique des codes HTTP vers des types de notification
|
|
15
|
+
- **Validation de schéma** : intégration avec JON pour la validation des données
|
|
16
|
+
- **Support multi-langue** : messages d'erreur en français et anglais
|
|
17
|
+
- **Authentification** : support Basic Auth
|
|
18
|
+
- **Types de réponse** : JSON, text, arraybuffer, blob
|
|
19
|
+
- **Intercepteurs** : actions personnalisées pour succès/erreur
|
|
20
|
+
|
|
21
|
+
### 🔌 WebSocket Request (WsRequest)
|
|
22
|
+
- **Connexion WebSocket managée** : avec reconnexion automatique
|
|
23
|
+
- **File d'attente de messages** : messages stockés si non connecté
|
|
24
|
+
- **API unifiée** : même interface que HttpRequest pour la cohérence
|
|
25
|
+
- **Gestion d'état** : suivi de la connexion et tentatives de reconnexion
|
|
26
|
+
- **Validation des messages** : schémas JON pour les données entrantes
|
|
27
|
+
|
|
28
|
+
### 🛡️ Sécurité & Fiabilité
|
|
29
|
+
- **Validation stricte** : des paramètres d'entrée
|
|
30
|
+
- **Gestion des timeouts** : configuration flexible
|
|
31
|
+
- **Protection contre les erreurs** : fallbacks et valeurs par défaut
|
|
32
|
+
- **Logs détaillés** : en mode développement seulement
|
|
33
|
+
|
|
34
|
+
## 📦 Installation
|
|
35
|
+
|
|
36
|
+
### Via npm/yarn/pnpm
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install @arc-js/cp-request
|
|
40
|
+
# ou
|
|
41
|
+
yarn add @arc-js/cp-request
|
|
42
|
+
# ou
|
|
43
|
+
pnpm add @arc-js/cp-request
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Importation directe (CDN)
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<script src="@arc-js/cp-request/cp-request.all.js"></script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 🚀 Démarrage Rapide
|
|
53
|
+
|
|
54
|
+
### TypeScript/ES Modules
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { HttpRequest, WsRequest } from '@arc-js/cp-request';
|
|
58
|
+
// ou
|
|
59
|
+
import CPRequest from '@arc-js/cp-request';
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### CommonJS
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const { HttpRequest, WsRequest } = require('@arc-js/cp-request');
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Navigateur (global)
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<script src="@arc-js/cp-request/cp-request.all.js"></script>
|
|
72
|
+
<script>
|
|
73
|
+
// Disponible globalement
|
|
74
|
+
const httpRequest = new HttpRequest();
|
|
75
|
+
const wsRequest = new WsRequest();
|
|
76
|
+
</script>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 📚 Documentation API
|
|
80
|
+
|
|
81
|
+
### Configuration Initiale
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// Configuration de base
|
|
85
|
+
const httpRequest = new HttpRequest()
|
|
86
|
+
.initConfig('http://api.example.com', 'fr');
|
|
87
|
+
|
|
88
|
+
const wsRequest = new WsRequest()
|
|
89
|
+
.initConfig('wss://ws.example.com', 'en');
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Interface HTTPRequestParams
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
interface HTTPRequestParams {
|
|
96
|
+
method: "GET" | "POST" | "PUT" | "DELETE";
|
|
97
|
+
path: string;
|
|
98
|
+
headers?: Record<string, string>;
|
|
99
|
+
params?: Record<string, any>;
|
|
100
|
+
body?: any;
|
|
101
|
+
responseType?: "json" | "arraybuffer" | "blob" | "text";
|
|
102
|
+
auth?: {
|
|
103
|
+
username: string;
|
|
104
|
+
password: string;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Interface WSRequestParams
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface WSRequestParams {
|
|
113
|
+
path: string;
|
|
114
|
+
headers?: Record<string, string>;
|
|
115
|
+
auth?: {
|
|
116
|
+
username: string;
|
|
117
|
+
password: string;
|
|
118
|
+
};
|
|
119
|
+
autoReconnect?: boolean;
|
|
120
|
+
reconnectDelay?: number;
|
|
121
|
+
maxReconnectAttempts?: number;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Réponse Standardisée
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface HTTPRequestResponse {
|
|
129
|
+
response: {
|
|
130
|
+
code: number;
|
|
131
|
+
type: string; // "success", "error", "warning", "info", "error_auth", "error_auth_required"
|
|
132
|
+
message: any;
|
|
133
|
+
};
|
|
134
|
+
data: any;
|
|
135
|
+
error?: any;
|
|
136
|
+
errors?: any[];
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 🔧 Utilisation Détaillée
|
|
141
|
+
|
|
142
|
+
### Requêtes HTTP
|
|
143
|
+
|
|
144
|
+
#### Récupérer plusieurs éléments (findAllRequests)
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const httpRequest = new HttpRequest()
|
|
148
|
+
.initConfig('http://api.example.com', 'fr');
|
|
149
|
+
|
|
150
|
+
httpRequest.findAllRequests(
|
|
151
|
+
{
|
|
152
|
+
method: 'GET',
|
|
153
|
+
path: '/users',
|
|
154
|
+
headers: {
|
|
155
|
+
'Content-Type': 'application/json',
|
|
156
|
+
'Authorization': 'Bearer token'
|
|
157
|
+
},
|
|
158
|
+
params: {
|
|
159
|
+
page: 1,
|
|
160
|
+
limit: 20,
|
|
161
|
+
sort: 'name'
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{}, // otherParams
|
|
165
|
+
(response) => {
|
|
166
|
+
console.log('Succès:', response.data); // Tableau d'utilisateurs
|
|
167
|
+
},
|
|
168
|
+
(response) => {
|
|
169
|
+
console.error('Erreur:', response.error);
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Récupérer un seul élément (findOneRequest)
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
httpRequest.findOneRequest(
|
|
178
|
+
{
|
|
179
|
+
method: 'GET',
|
|
180
|
+
path: '/users/123'
|
|
181
|
+
},
|
|
182
|
+
{},
|
|
183
|
+
(response) => {
|
|
184
|
+
console.log('Utilisateur:', response.data);
|
|
185
|
+
},
|
|
186
|
+
(response) => {
|
|
187
|
+
console.error('Erreur:', response.errors);
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Créer une ressource (POST)
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
httpRequest.findOneRequest(
|
|
196
|
+
{
|
|
197
|
+
method: 'POST',
|
|
198
|
+
path: '/users',
|
|
199
|
+
body: {
|
|
200
|
+
name: 'John Doe',
|
|
201
|
+
email: 'john@example.com'
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{},
|
|
205
|
+
(response) => {
|
|
206
|
+
console.log('Créé avec succès:', response.data);
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Authentification Basic
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
httpRequest.findAllRequests(
|
|
215
|
+
{
|
|
216
|
+
method: 'GET',
|
|
217
|
+
path: '/secure-data',
|
|
218
|
+
auth: {
|
|
219
|
+
username: 'admin',
|
|
220
|
+
password: 'secret123'
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### WebSocket
|
|
227
|
+
|
|
228
|
+
#### Connexion WebSocket
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
const wsRequest = new WsRequest()
|
|
232
|
+
.initConfig('wss://ws.example.com', 'fr');
|
|
233
|
+
|
|
234
|
+
wsRequest.connect({
|
|
235
|
+
path: '/socket',
|
|
236
|
+
autoReconnect: true,
|
|
237
|
+
reconnectDelay: 3000,
|
|
238
|
+
maxReconnectAttempts: 5
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Envoyer et recevoir des messages
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// Récupérer plusieurs éléments via WebSocket
|
|
246
|
+
wsRequest.findAllMessages(
|
|
247
|
+
{
|
|
248
|
+
action: 'GET_USERS',
|
|
249
|
+
filters: { active: true }
|
|
250
|
+
},
|
|
251
|
+
(response) => {
|
|
252
|
+
console.log('Utilisateurs actifs:', response.data);
|
|
253
|
+
},
|
|
254
|
+
(response) => {
|
|
255
|
+
console.error('Erreur WebSocket:', response.error);
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
// Récupérer un élément spécifique
|
|
260
|
+
wsRequest.findOneMessage(
|
|
261
|
+
{
|
|
262
|
+
action: 'GET_USER',
|
|
263
|
+
id: 456
|
|
264
|
+
},
|
|
265
|
+
(response) => {
|
|
266
|
+
console.log('Utilisateur:', response.data);
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Gestion de la file d'attente
|
|
272
|
+
|
|
273
|
+
Les messages sont automatiquement mis en file d'attente si la connexion WebSocket n'est pas encore établie et envoyés une fois la connexion rétablie.
|
|
274
|
+
|
|
275
|
+
### Actions Personnalisées
|
|
276
|
+
|
|
277
|
+
#### Custom Map Actions
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
const customMapAction: HttpRequestMapAction = (
|
|
281
|
+
code,
|
|
282
|
+
type,
|
|
283
|
+
message,
|
|
284
|
+
data,
|
|
285
|
+
cleanedData,
|
|
286
|
+
error,
|
|
287
|
+
errors
|
|
288
|
+
) => {
|
|
289
|
+
// Logique personnalisée de transformation
|
|
290
|
+
return {
|
|
291
|
+
response: { code, type, message },
|
|
292
|
+
data: cleanedData ? cleanedData.processed : null,
|
|
293
|
+
metadata: { timestamp: new Date().toISOString() },
|
|
294
|
+
error,
|
|
295
|
+
errors
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
httpRequest.findAllRequests(
|
|
300
|
+
{ method: 'GET', path: '/data' },
|
|
301
|
+
{},
|
|
302
|
+
new JON.Object('fr'), // schéma
|
|
303
|
+
customMapAction, // mapAction personnalisée
|
|
304
|
+
undefined, // errMapAction (par défaut)
|
|
305
|
+
undefined, // successAction (par défaut)
|
|
306
|
+
undefined // errorAction (par défaut)
|
|
307
|
+
);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### Custom Success/Error Actions
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
const successAction: HttpRequestReponseAction = async (response) => {
|
|
314
|
+
// Enregistrer dans l'historique
|
|
315
|
+
await logToDatabase({
|
|
316
|
+
type: 'request_success',
|
|
317
|
+
code: response.response.code,
|
|
318
|
+
data: response.data
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Afficher une notification
|
|
322
|
+
showNotification('Succès', response.response.message);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const errorAction: HttpRequestReponseAction = (response) => {
|
|
326
|
+
// Journaliser l'erreur
|
|
327
|
+
console.error('Request failed:', response);
|
|
328
|
+
|
|
329
|
+
// Afficher un message d'erreur
|
|
330
|
+
alert(`Erreur \${response.response.code}: \${response.response.message}`);
|
|
331
|
+
};
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## 🎯 Exemples Complets
|
|
335
|
+
|
|
336
|
+
### Exemple 1 : Application avec Authentification
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
class ApiService {
|
|
340
|
+
private http: HttpRequest;
|
|
341
|
+
|
|
342
|
+
constructor(baseUrl: string, lang: 'fr' | 'en' = 'fr') {
|
|
343
|
+
this.http = new HttpRequest().initConfig(baseUrl, lang);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async login(email: string, password: string) {
|
|
347
|
+
return this.http.findOneRequest(
|
|
348
|
+
{
|
|
349
|
+
method: 'POST',
|
|
350
|
+
path: '/auth/login',
|
|
351
|
+
body: { email, password }
|
|
352
|
+
},
|
|
353
|
+
{},
|
|
354
|
+
(response) => {
|
|
355
|
+
// Stocker le token
|
|
356
|
+
localStorage.setItem('token', response.data.token);
|
|
357
|
+
|
|
358
|
+
// Rediriger
|
|
359
|
+
window.location.href = '/dashboard';
|
|
360
|
+
},
|
|
361
|
+
(response) => {
|
|
362
|
+
// Afficher l'erreur
|
|
363
|
+
alert(`Échec de connexion: \${response.response.message}`);
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async getProfile() {
|
|
369
|
+
const token = localStorage.getItem('token');
|
|
370
|
+
|
|
371
|
+
return this.http.findOneRequest(
|
|
372
|
+
{
|
|
373
|
+
method: 'GET',
|
|
374
|
+
path: '/profile',
|
|
375
|
+
headers: {
|
|
376
|
+
'Authorization': `Bearer \${token}`
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Exemple 2 : Chat en Temps Réel
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
class ChatService {
|
|
388
|
+
private ws: WsRequest;
|
|
389
|
+
private messageHandlers: ((message: any) => void)[] = [];
|
|
390
|
+
|
|
391
|
+
constructor(wsUrl: string) {
|
|
392
|
+
this.ws = new WsRequest().initConfig(wsUrl, 'fr');
|
|
393
|
+
|
|
394
|
+
this.ws.connect({
|
|
395
|
+
path: '/chat',
|
|
396
|
+
autoReconnect: true,
|
|
397
|
+
reconnectDelay: 2000
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
async sendMessage(roomId: string, content: string) {
|
|
402
|
+
return this.ws.findOneMessage(
|
|
403
|
+
{
|
|
404
|
+
action: 'SEND_MESSAGE',
|
|
405
|
+
roomId,
|
|
406
|
+
content,
|
|
407
|
+
timestamp: Date.now()
|
|
408
|
+
},
|
|
409
|
+
(response) => {
|
|
410
|
+
console.log('Message envoyé:', response.data);
|
|
411
|
+
},
|
|
412
|
+
(response) => {
|
|
413
|
+
console.error('Erreur d\'envoi:', response.error);
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async getMessages(roomId: string, limit = 50) {
|
|
419
|
+
return this.ws.findAllMessages(
|
|
420
|
+
{
|
|
421
|
+
action: 'GET_MESSAGES',
|
|
422
|
+
roomId,
|
|
423
|
+
limit
|
|
424
|
+
},
|
|
425
|
+
(response) => {
|
|
426
|
+
// Traiter les messages
|
|
427
|
+
response.data.forEach(message => {
|
|
428
|
+
this.messageHandlers.forEach(handler => handler(message));
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
onMessage(handler: (message: any) => void) {
|
|
435
|
+
this.messageHandlers.push(handler);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Exemple 3 : Upload de Fichiers
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
async uploadFile(file: File, onProgress?: (progress: number) => void) {
|
|
444
|
+
const formData = new FormData();
|
|
445
|
+
formData.append('file', file);
|
|
446
|
+
formData.append('metadata', JSON.stringify({
|
|
447
|
+
name: file.name,
|
|
448
|
+
type: file.type,
|
|
449
|
+
size: file.size
|
|
450
|
+
}));
|
|
451
|
+
|
|
452
|
+
return this.http.findOneRequest(
|
|
453
|
+
{
|
|
454
|
+
method: 'POST',
|
|
455
|
+
path: '/upload',
|
|
456
|
+
body: formData,
|
|
457
|
+
// Pas de Content-Type pour FormData, le navigateur le définit automatiquement
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
// Configuration fetch supplémentaire
|
|
461
|
+
onUploadProgress: (progressEvent) => {
|
|
462
|
+
if (onProgress) {
|
|
463
|
+
const percent = (progressEvent.loaded / progressEvent.total) * 100;
|
|
464
|
+
onProgress(percent);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
(response) => {
|
|
469
|
+
console.log('Fichier uploadé:', response.data);
|
|
470
|
+
showNotification('Succès', 'Fichier uploadé avec succès');
|
|
471
|
+
},
|
|
472
|
+
(response) => {
|
|
473
|
+
console.error('Échec upload:', response.error);
|
|
474
|
+
showNotification('Erreur', 'Échec de l\'upload du fichier');
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## 🔧 Configuration Avancée
|
|
481
|
+
|
|
482
|
+
### Types de Notification Personnalisés
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
import { getNotifRequestType } from '@arc-js/cp-request';
|
|
486
|
+
|
|
487
|
+
// Étendre les types de notification
|
|
488
|
+
function customGetNotifRequestType(status: number): string {
|
|
489
|
+
const baseType = getNotifRequestType(status);
|
|
490
|
+
|
|
491
|
+
// Ajouter des types personnalisés
|
|
492
|
+
if (status === 429) {
|
|
493
|
+
return 'rate_limit';
|
|
494
|
+
}
|
|
495
|
+
if (status === 503) {
|
|
496
|
+
return 'maintenance';
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return baseType;
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Schémas de Validation Personnalisés
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
import JON from '@arc-js/jon';
|
|
507
|
+
|
|
508
|
+
// Créer un schéma de validation personnalisé
|
|
509
|
+
const userSchema = new JON.Object('fr').struct({
|
|
510
|
+
id: new JON.Number('fr').required(),
|
|
511
|
+
name: new JON.String('fr').min(2).max(100).required(),
|
|
512
|
+
email: new JON.String('fr').email().required(),
|
|
513
|
+
age: new JON.Number('fr').min(0).max(150),
|
|
514
|
+
roles: new JON.Array('fr').types(
|
|
515
|
+
new JON.Enum('fr').choices('admin', 'user', 'guest')
|
|
516
|
+
).default(['user'])
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
// Utiliser le schéma dans une requête
|
|
520
|
+
httpRequest.findOneRequest(
|
|
521
|
+
{ method: 'GET', path: '/user/123' },
|
|
522
|
+
{},
|
|
523
|
+
userSchema, // Schéma personnalisé
|
|
524
|
+
// ... autres paramètres
|
|
525
|
+
);
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### Middleware et Intercepteurs
|
|
529
|
+
|
|
530
|
+
```typescript
|
|
531
|
+
class RequestLogger {
|
|
532
|
+
static async logRequest(urlParams: HTTPRequestParams) {
|
|
533
|
+
console.log('[REQUEST]', {
|
|
534
|
+
timestamp: new Date().toISOString(),
|
|
535
|
+
method: urlParams.method,
|
|
536
|
+
path: urlParams.path,
|
|
537
|
+
hasBody: !!urlParams.body
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
static async logResponse(response: HTTPRequestResponse) {
|
|
542
|
+
console.log('[RESPONSE]', {
|
|
543
|
+
timestamp: new Date().toISOString(),
|
|
544
|
+
code: response.response.code,
|
|
545
|
+
type: response.response.type,
|
|
546
|
+
hasData: !!response.data
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Envelopper les méthodes existantes
|
|
552
|
+
const originalFindAllRequests = HttpRequest.prototype.findAllRequests;
|
|
553
|
+
HttpRequest.prototype.findAllRequests = async function(...args) {
|
|
554
|
+
await RequestLogger.logRequest(args[0]);
|
|
555
|
+
const result = await originalFindAllRequests.apply(this, args);
|
|
556
|
+
await RequestLogger.logResponse(result);
|
|
557
|
+
return result;
|
|
558
|
+
};
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## 📋 Table des Codes de Notification
|
|
562
|
+
|
|
563
|
+
| Code HTTP | Type | Description | Action Recommandée |
|
|
564
|
+
|-----------|------|-------------|-------------------|
|
|
565
|
+
| 200 | success | Requête réussie | Traiter les données |
|
|
566
|
+
| 201 | success | Ressource créée | Mettre à jour l'UI |
|
|
567
|
+
| 204 | success | Pas de contenu | Rafraîchir si nécessaire |
|
|
568
|
+
| 400 | error | Mauvaise requête | Corriger les données envoyées |
|
|
569
|
+
| 401 | error_auth_required | Non authentifié | Rediriger vers login |
|
|
570
|
+
| 403 | error_auth | Non autorisé | Vérifier les permissions |
|
|
571
|
+
| 404 | error | Non trouvé | Afficher message d'erreur |
|
|
572
|
+
| 409 | error_auth | Conflit | Résoudre le conflit de données |
|
|
573
|
+
| 419 | error_auth_required | Session expirée | Renouveler la session |
|
|
574
|
+
| 422 | warning | Données invalides | Corriger la validation |
|
|
575
|
+
| 429 | warning | Trop de requêtes | Attendre avant de réessayer |
|
|
576
|
+
| 500 | error | Erreur serveur | Signaler l'administrateur |
|
|
577
|
+
| 503 | error | Service indisponible | Réessayer plus tard |
|
|
578
|
+
|
|
579
|
+
## 🚨 Gestion des Erreurs
|
|
580
|
+
|
|
581
|
+
### Erreurs de Réseau
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
try {
|
|
585
|
+
await httpRequest.findAllRequests({
|
|
586
|
+
method: 'GET',
|
|
587
|
+
path: '/data'
|
|
588
|
+
});
|
|
589
|
+
} catch (error) {
|
|
590
|
+
if (error.message.includes('Failed to fetch')) {
|
|
591
|
+
// Pas de connexion internet
|
|
592
|
+
showOfflineMessage();
|
|
593
|
+
} else if (error.response?.code === 500) {
|
|
594
|
+
// Erreur serveur
|
|
595
|
+
showServerError();
|
|
596
|
+
} else {
|
|
597
|
+
// Erreur inconnue
|
|
598
|
+
console.error('Erreur inattendue:', error);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### Retry Automatique
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
async function fetchWithRetry(urlParams, maxRetries = 3) {
|
|
607
|
+
let lastError;
|
|
608
|
+
|
|
609
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
610
|
+
try {
|
|
611
|
+
return await httpRequest.findOneRequest(urlParams);
|
|
612
|
+
} catch (error) {
|
|
613
|
+
lastError = error;
|
|
614
|
+
|
|
615
|
+
// Attendre avant de réessayer (backoff exponentiel)
|
|
616
|
+
await new Promise(resolve =>
|
|
617
|
+
setTimeout(resolve, 1000 * Math.pow(2, i))
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
throw lastError;
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
## 🔧 Build et Développement
|
|
627
|
+
|
|
628
|
+
### Structure du Projet
|
|
629
|
+
|
|
630
|
+
```
|
|
631
|
+
@arc-js/cp-request/
|
|
632
|
+
├── cp-request.all.js
|
|
633
|
+
├── cp-request.all.min.js
|
|
634
|
+
├── index.d.ts
|
|
635
|
+
├── index.js
|
|
636
|
+
├── index.min.d.ts
|
|
637
|
+
├── index.min.js
|
|
638
|
+
├── package.json
|
|
639
|
+
├── tsconfig.json
|
|
640
|
+
└── README.md
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## 📋 Compatibilité
|
|
644
|
+
|
|
645
|
+
### Navigateurs Supportés
|
|
646
|
+
- Chrome 60+
|
|
647
|
+
- Firefox 55+
|
|
648
|
+
- Safari 12+
|
|
649
|
+
- Edge 79+
|
|
650
|
+
- Opera 47+
|
|
651
|
+
|
|
652
|
+
### Environnements
|
|
653
|
+
- Node.js 18+
|
|
654
|
+
- Deno 1.30+
|
|
655
|
+
- Bun 1.0+
|
|
656
|
+
- React Native (avec polyfill fetch)
|
|
657
|
+
- Electron
|
|
658
|
+
|
|
659
|
+
### Dépendances
|
|
660
|
+
- @arc-js/jon (pour la validation)
|
|
661
|
+
- @arc-js/pajo (pour la manipulation de chemins)
|
|
662
|
+
- @arc-js/qust (pour la manipulation de query strings)
|
|
663
|
+
- @arc-js/timez (pour la gestion du temps)
|
|
664
|
+
|
|
665
|
+
## 🛡️ Meilleures Pratiques
|
|
666
|
+
|
|
667
|
+
### Sécurité
|
|
668
|
+
1. **Toujours valider les entrées** : utiliser les schémas JON
|
|
669
|
+
2. **Ne pas exposer les tokens** : dans les logs de développement
|
|
670
|
+
3. **Utiliser HTTPS/SSL** : toujours en production
|
|
671
|
+
4. **Sanitizer les headers** : éviter l'injection de headers
|
|
672
|
+
|
|
673
|
+
### Performance
|
|
674
|
+
1. **Réutiliser les instances** : créer une instance par base URL
|
|
675
|
+
2. **Limiter les requêtes parallèles** : utiliser une file d'attente si nécessaire
|
|
676
|
+
3. **Mettre en cache** : les réponses statiques
|
|
677
|
+
4. **Compresser les données** : gzip/brotli pour les bodies volumineux
|
|
678
|
+
|
|
679
|
+
### Maintenance
|
|
680
|
+
1. **Centraliser la configuration** : dans un service dédié
|
|
681
|
+
2. **Logger proprement** : différents niveaux selon l'environnement
|
|
682
|
+
3. **Versionner les APIs** : dans le path (/api/v1/)
|
|
683
|
+
4. **Documenter les endpoints** : avec des exemples
|
|
684
|
+
|
|
685
|
+
## 📄 Licence
|
|
686
|
+
|
|
687
|
+
MIT License - Voir le fichier [LICENSE](LICENSE) pour plus de détails.
|
|
688
|
+
|
|
689
|
+
## 🐛 Signaler un Bug
|
|
690
|
+
|
|
691
|
+
Envoyez nous un mail à l'adresse `contact.inicode@gmail.com` pour :
|
|
692
|
+
- Signaler un bug
|
|
693
|
+
- Proposer une amélioration
|
|
694
|
+
- Poser une question
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
**@arc-js/cp-request** - Une solution complète pour les communications client-serveur.
|
|
699
|
+
|
|
700
|
+
*Développé par l'équipe INICODE*
|