@emmvish/stable-request 1.0.9 โ 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 +521 -180
- package/dist/constants/index.d.ts +3 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +16 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/core/stable-api-gateway.d.ts.map +1 -1
- package/dist/core/stable-api-gateway.js +2 -1
- package/dist/core/stable-api-gateway.js.map +1 -1
- package/dist/types/index.d.ts +14 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utilities/execute-concurrently.d.ts.map +1 -1
- package/dist/utilities/execute-concurrently.js +4 -2
- package/dist/utilities/execute-concurrently.js.map +1 -1
- package/dist/utilities/execute-sequentially.d.ts.map +1 -1
- package/dist/utilities/execute-sequentially.js +4 -2
- package/dist/utilities/execute-sequentially.js.map +1 -1
- package/dist/utilities/prepare-api-request-data.d.ts.map +1 -1
- package/dist/utilities/prepare-api-request-data.js +3 -1
- package/dist/utilities/prepare-api-request-data.js.map +1 -1
- package/dist/utilities/prepare-api-request-options.d.ts.map +1 -1
- package/dist/utilities/prepare-api-request-options.js +6 -16
- package/dist/utilities/prepare-api-request-options.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
## stable-request
|
|
2
2
|
|
|
3
|
-
`stable-request` is a TypeScript-first HTTP reliability
|
|
3
|
+
`stable-request` is a TypeScript-first HTTP reliability toolkit for workflow-driven API integrations, that goes beyond status-code retries by validating response content, handling eventual consistency, coordinating batch workflows with intelligent grouping, and providing deep observability into every request attempt. It is designed for real-world distributed systems where HTTP success does not guarantee business success.
|
|
4
4
|
|
|
5
5
|
## Why stable-request?
|
|
6
6
|
|
|
7
7
|
Most HTTP client libraries only retry on network failures or specific HTTP status codes. **stable-request** goes further by providing:
|
|
8
8
|
|
|
9
9
|
- โ
**Content-aware retries** - Validate response content and retry even on successful HTTP responses
|
|
10
|
-
- ๐ **Batch processing** - Execute multiple requests
|
|
10
|
+
- ๐ **Batch processing with groups** - Execute multiple requests with hierarchical configuration (global โ group โ request)
|
|
11
|
+
- ๐ฏ **Request grouping** - Organize related requests with shared settings and logical boundaries
|
|
11
12
|
- ๐งช **Trial mode** - Simulate failures to test your retry logic without depending on real network instability
|
|
12
13
|
- ๐ **Granular observability** - Monitor every attempt with detailed hooks
|
|
13
14
|
- โก **Multiple retry strategies** - Fixed, linear, or exponential backoff
|
|
14
|
-
-
|
|
15
|
+
- ๐ง **Flexible error handling** - Custom error analysis and graceful degradation
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
@@ -70,6 +71,56 @@ const results = await stableApiGateway(requests, {
|
|
|
70
71
|
});
|
|
71
72
|
```
|
|
72
73
|
|
|
74
|
+
### Grouped Requests
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { stableApiGateway, RETRY_STRATEGIES } from '@emmvish/stable-request';
|
|
78
|
+
|
|
79
|
+
const results = await stableApiGateway(
|
|
80
|
+
[
|
|
81
|
+
{
|
|
82
|
+
id: 'auth-check',
|
|
83
|
+
groupId: 'critical-services',
|
|
84
|
+
requestOptions: {
|
|
85
|
+
reqData: { path: '/auth/verify' },
|
|
86
|
+
resReq: true
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'analytics-track',
|
|
91
|
+
groupId: 'optional-services',
|
|
92
|
+
requestOptions: {
|
|
93
|
+
reqData: { path: '/analytics/event' },
|
|
94
|
+
resReq: true
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
{
|
|
99
|
+
// Global defaults
|
|
100
|
+
commonAttempts: 2,
|
|
101
|
+
commonRequestData: { hostname: 'api.example.com' },
|
|
102
|
+
|
|
103
|
+
// Define groups with their own configurations
|
|
104
|
+
requestGroups: [
|
|
105
|
+
{
|
|
106
|
+
id: 'critical-services',
|
|
107
|
+
commonConfig: {
|
|
108
|
+
commonAttempts: 10,
|
|
109
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'optional-services',
|
|
114
|
+
commonConfig: {
|
|
115
|
+
commonAttempts: 1,
|
|
116
|
+
commonFinalErrorAnalyzer: async () => true // Don't throw on failure
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
```
|
|
123
|
+
|
|
73
124
|
## Core Features
|
|
74
125
|
|
|
75
126
|
### 1. Content-Aware Retries with `stableRequest`
|
|
@@ -142,9 +193,9 @@ const results = await stableApiGateway(requests, {
|
|
|
142
193
|
// Process results
|
|
143
194
|
results.forEach(result => {
|
|
144
195
|
if (result.success) {
|
|
145
|
-
console.log(`${result.
|
|
196
|
+
console.log(`${result.requestId} succeeded:`, result.data);
|
|
146
197
|
} else {
|
|
147
|
-
console.error(`${result.
|
|
198
|
+
console.error(`${result.requestId} failed:`, result.error);
|
|
148
199
|
}
|
|
149
200
|
});
|
|
150
201
|
```
|
|
@@ -159,7 +210,98 @@ const results = await stableApiGateway(requests, {
|
|
|
159
210
|
});
|
|
160
211
|
```
|
|
161
212
|
|
|
162
|
-
### 3.
|
|
213
|
+
### 3. Request Grouping - Hierarchical Configuration
|
|
214
|
+
|
|
215
|
+
Organize requests into logical groups with their own configuration. The configuration priority is:
|
|
216
|
+
|
|
217
|
+
**Individual Request Options** (highest) โ **Group Common Options** (middle) โ **Global Common Options** (lowest)
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const results = await stableApiGateway(
|
|
221
|
+
[
|
|
222
|
+
{
|
|
223
|
+
id: 'payment-stripe',
|
|
224
|
+
groupId: 'payment-providers',
|
|
225
|
+
requestOptions: {
|
|
226
|
+
reqData: { path: '/stripe/charge' },
|
|
227
|
+
resReq: true,
|
|
228
|
+
// Individual override: even more attempts for Stripe
|
|
229
|
+
attempts: 15
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: 'payment-paypal',
|
|
234
|
+
groupId: 'payment-providers',
|
|
235
|
+
requestOptions: {
|
|
236
|
+
reqData: { path: '/paypal/charge' },
|
|
237
|
+
resReq: true
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: 'analytics-event',
|
|
242
|
+
groupId: 'analytics',
|
|
243
|
+
requestOptions: {
|
|
244
|
+
reqData: { path: '/track' },
|
|
245
|
+
resReq: true
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
{
|
|
250
|
+
// Global configuration - applies to all ungrouped requests
|
|
251
|
+
commonAttempts: 2,
|
|
252
|
+
commonWait: 500,
|
|
253
|
+
commonRequestData: {
|
|
254
|
+
hostname: 'api.example.com',
|
|
255
|
+
method: REQUEST_METHODS.POST
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
// Group-specific configurations
|
|
259
|
+
requestGroups: [
|
|
260
|
+
{
|
|
261
|
+
id: 'payment-providers',
|
|
262
|
+
commonConfig: {
|
|
263
|
+
// Payment group: aggressive retries
|
|
264
|
+
commonAttempts: 10,
|
|
265
|
+
commonWait: 2000,
|
|
266
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL,
|
|
267
|
+
commonRequestData: {
|
|
268
|
+
headers: { 'X-Idempotency-Key': crypto.randomUUID() }
|
|
269
|
+
},
|
|
270
|
+
commonHandleErrors: async (reqData, error) => {
|
|
271
|
+
await alertPagerDuty('Payment failure', error);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: 'analytics',
|
|
277
|
+
commonConfig: {
|
|
278
|
+
// Analytics group: minimal retries, failures acceptable
|
|
279
|
+
commonAttempts: 1,
|
|
280
|
+
commonFinalErrorAnalyzer: async () => true // Don't throw
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
// Filter results by group
|
|
288
|
+
const paymentResults = results.filter(r => r.groupId === 'payment-providers');
|
|
289
|
+
const analyticsResults = results.filter(r => r.groupId === 'analytics');
|
|
290
|
+
|
|
291
|
+
console.log('Payment success rate:',
|
|
292
|
+
paymentResults.filter(r => r.success).length / paymentResults.length);
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Key Benefits of Request Grouping:**
|
|
296
|
+
|
|
297
|
+
1. **Service Tiering** - Different retry strategies for critical vs. optional services
|
|
298
|
+
2. **Regional Configuration** - Customize timeouts and retries per geographic region
|
|
299
|
+
3. **Priority Management** - Handle high-priority requests more aggressively
|
|
300
|
+
4. **Organized Configuration** - Group related requests with shared settings
|
|
301
|
+
5. **Simplified Maintenance** - Update group config instead of individual requests
|
|
302
|
+
6. **Better Monitoring** - Track metrics and failures by logical groups
|
|
303
|
+
|
|
304
|
+
### 4. Trial Mode - Test Your Retry Logic
|
|
163
305
|
|
|
164
306
|
Simulate request and retry failures with configurable probabilities.
|
|
165
307
|
|
|
@@ -186,7 +328,7 @@ await stableRequest({
|
|
|
186
328
|
- Validating monitoring and alerting
|
|
187
329
|
- Testing circuit breaker patterns
|
|
188
330
|
|
|
189
|
-
###
|
|
331
|
+
### 5. Multiple Retry Strategies
|
|
190
332
|
|
|
191
333
|
Choose the backoff strategy that fits your use case.
|
|
192
334
|
|
|
@@ -221,7 +363,7 @@ await stableRequest({
|
|
|
221
363
|
});
|
|
222
364
|
```
|
|
223
365
|
|
|
224
|
-
###
|
|
366
|
+
### 6. Comprehensive Observability
|
|
225
367
|
|
|
226
368
|
Monitor every request attempt with detailed logging hooks.
|
|
227
369
|
|
|
@@ -260,7 +402,7 @@ await stableRequest({
|
|
|
260
402
|
});
|
|
261
403
|
```
|
|
262
404
|
|
|
263
|
-
###
|
|
405
|
+
### 7. Smart Retry Logic
|
|
264
406
|
|
|
265
407
|
Automatically retries on common transient errors:
|
|
266
408
|
|
|
@@ -284,7 +426,7 @@ await stableRequest({
|
|
|
284
426
|
});
|
|
285
427
|
```
|
|
286
428
|
|
|
287
|
-
###
|
|
429
|
+
### 8. Final Error Analysis
|
|
288
430
|
|
|
289
431
|
Decide whether to throw or return false based on error analysis.
|
|
290
432
|
|
|
@@ -312,7 +454,7 @@ if (result === false) {
|
|
|
312
454
|
}
|
|
313
455
|
```
|
|
314
456
|
|
|
315
|
-
###
|
|
457
|
+
### 9. Request Cancellation Support
|
|
316
458
|
|
|
317
459
|
Support for AbortController to cancel requests.
|
|
318
460
|
|
|
@@ -336,7 +478,7 @@ try {
|
|
|
336
478
|
}
|
|
337
479
|
```
|
|
338
480
|
|
|
339
|
-
###
|
|
481
|
+
### 10. Perform All Attempts Mode
|
|
340
482
|
|
|
341
483
|
Execute all retry attempts regardless of success, useful for warm-up scenarios.
|
|
342
484
|
|
|
@@ -396,7 +538,7 @@ interface REQUEST_DATA<RequestDataType = any> {
|
|
|
396
538
|
|
|
397
539
|
### `stableApiGateway<RequestDataType, ResponseDataType>(requests, options)`
|
|
398
540
|
|
|
399
|
-
Execute multiple HTTP requests with shared configuration.
|
|
541
|
+
Execute multiple HTTP requests with shared configuration and optional grouping.
|
|
400
542
|
|
|
401
543
|
#### Gateway Configuration Options
|
|
402
544
|
|
|
@@ -404,6 +546,7 @@ Execute multiple HTTP requests with shared configuration.
|
|
|
404
546
|
|--------|------|---------|-------------|
|
|
405
547
|
| `concurrentExecution` | `boolean` | `true` | Execute requests concurrently or sequentially |
|
|
406
548
|
| `stopOnFirstError` | `boolean` | `false` | Stop execution on first error (sequential only) |
|
|
549
|
+
| `requestGroups` | `RequestGroup[]` | `[]` | Define groups with their own common configurations |
|
|
407
550
|
| `commonAttempts` | `number` | `1` | Default attempts for all requests |
|
|
408
551
|
| `commonPerformAllAttempts` | `boolean` | `false` | Default performAllAttempts for all requests |
|
|
409
552
|
| `commonWait` | `number` | `1000` | Default wait time for all requests |
|
|
@@ -417,25 +560,44 @@ Execute multiple HTTP requests with shared configuration.
|
|
|
417
560
|
| `commonFinalErrorAnalyzer` | `function` | `() => false` | Default final error analyzer for all requests |
|
|
418
561
|
| `commonHandleErrors` | `function` | console.log | Default error handler for all requests |
|
|
419
562
|
| `commonHandleSuccessfulAttemptData` | `function` | console.log | Default success handler for all requests |
|
|
420
|
-
| `commonRequestData` | `Partial
|
|
563
|
+
| `commonRequestData` | `Partial<REQUEST_DATA>` | `{ hostname: '' }` | Common set of request options for each request |
|
|
421
564
|
|
|
565
|
+
#### Request Group Configuration
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
interface RequestGroup {
|
|
569
|
+
id: string; // Unique group identifier
|
|
570
|
+
commonConfig?: {
|
|
571
|
+
// Any common* option can be specified here
|
|
572
|
+
commonAttempts?: number;
|
|
573
|
+
commonWait?: number;
|
|
574
|
+
commonRetryStrategy?: RETRY_STRATEGY_TYPES;
|
|
575
|
+
commonRequestData?: Partial<REQUEST_DATA>;
|
|
576
|
+
commonResponseAnalyzer?: function;
|
|
577
|
+
commonHandleErrors?: function;
|
|
578
|
+
// ... all other common* options
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
```
|
|
422
582
|
|
|
423
583
|
#### Request Format
|
|
424
584
|
|
|
425
585
|
```typescript
|
|
426
586
|
interface API_GATEWAY_REQUEST<RequestDataType, ResponseDataType> {
|
|
427
587
|
id: string; // Unique identifier for the request
|
|
588
|
+
groupId?: string; // Optional group identifier
|
|
428
589
|
requestOptions: API_GATEWAY_REQUEST_OPTIONS_TYPE<RequestDataType, ResponseDataType>;
|
|
429
590
|
}
|
|
430
591
|
```
|
|
431
592
|
|
|
432
|
-
**
|
|
593
|
+
**Configuration Priority:** Individual request options override group options, which override global common options.
|
|
433
594
|
|
|
434
595
|
#### Response Format
|
|
435
596
|
|
|
436
597
|
```typescript
|
|
437
598
|
interface API_GATEWAY_RESPONSE<ResponseDataType> {
|
|
438
|
-
|
|
599
|
+
requestId: string; // Request identifier
|
|
600
|
+
groupId?: string; // Group identifier (if request was grouped)
|
|
439
601
|
success: boolean; // Whether the request succeeded
|
|
440
602
|
data?: ResponseDataType; // Response data (if success is true)
|
|
441
603
|
error?: string; // Error message (if success is false)
|
|
@@ -444,7 +606,224 @@ interface API_GATEWAY_RESPONSE<ResponseDataType> {
|
|
|
444
606
|
|
|
445
607
|
## Real-World Use Cases
|
|
446
608
|
|
|
447
|
-
### 1.
|
|
609
|
+
### 1. Environment-Based Service Tiers with Groups
|
|
610
|
+
|
|
611
|
+
Organize API calls by criticality with different retry strategies per tier.
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
const results = await stableApiGateway(
|
|
615
|
+
[
|
|
616
|
+
// Critical services
|
|
617
|
+
{ id: 'auth-validate', groupId: 'critical', requestOptions: { reqData: { path: '/auth/validate' }, resReq: true } },
|
|
618
|
+
{ id: 'db-primary', groupId: 'critical', requestOptions: { reqData: { path: '/db/health' }, resReq: true } },
|
|
619
|
+
|
|
620
|
+
// Payment services
|
|
621
|
+
{ id: 'stripe-charge', groupId: 'payments', requestOptions: { reqData: { path: '/stripe/charge', body: { amount: 1000 } }, resReq: true } },
|
|
622
|
+
{ id: 'paypal-charge', groupId: 'payments', requestOptions: { reqData: { path: '/paypal/charge', body: { amount: 1000 } }, resReq: true } },
|
|
623
|
+
|
|
624
|
+
// Analytics services
|
|
625
|
+
{ id: 'track-event', groupId: 'analytics', requestOptions: { reqData: { path: '/track' }, resReq: true } }
|
|
626
|
+
],
|
|
627
|
+
{
|
|
628
|
+
// Global defaults
|
|
629
|
+
commonAttempts: 2,
|
|
630
|
+
commonWait: 500,
|
|
631
|
+
commonRequestData: { hostname: 'api.example.com', method: REQUEST_METHODS.POST },
|
|
632
|
+
|
|
633
|
+
requestGroups: [
|
|
634
|
+
{
|
|
635
|
+
id: 'critical',
|
|
636
|
+
commonConfig: {
|
|
637
|
+
commonAttempts: 10,
|
|
638
|
+
commonWait: 2000,
|
|
639
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL,
|
|
640
|
+
commonHandleErrors: async (reqData, error) => {
|
|
641
|
+
await pagerDuty.alert('CRITICAL', error);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
id: 'payments',
|
|
647
|
+
commonConfig: {
|
|
648
|
+
commonAttempts: 5,
|
|
649
|
+
commonWait: 1500,
|
|
650
|
+
commonRetryStrategy: RETRY_STRATEGIES.LINEAR,
|
|
651
|
+
commonRequestData: {
|
|
652
|
+
headers: { 'X-Idempotency-Key': crypto.randomUUID() }
|
|
653
|
+
},
|
|
654
|
+
commonResponseAnalyzer: async (reqData, data) => {
|
|
655
|
+
return data?.status === 'succeeded' && data?.transactionId;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
id: 'analytics',
|
|
661
|
+
commonConfig: {
|
|
662
|
+
commonAttempts: 1,
|
|
663
|
+
commonFinalErrorAnalyzer: async () => true // Don't throw
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
]
|
|
667
|
+
}
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
// Analyze results by group
|
|
671
|
+
const criticalHealth = results.filter(r => r.groupId === 'critical').every(r => r.success);
|
|
672
|
+
const paymentSuccess = results.filter(r => r.groupId === 'payments').filter(r => r.success).length;
|
|
673
|
+
|
|
674
|
+
if (!criticalHealth) {
|
|
675
|
+
console.error('CRITICAL SERVICES DEGRADED');
|
|
676
|
+
}
|
|
677
|
+
console.log(`Payments: ${paymentSuccess} successful`);
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### 2. Multi-Region API Deployment with Groups
|
|
681
|
+
|
|
682
|
+
Handle requests to different geographic regions with region-specific configurations.
|
|
683
|
+
|
|
684
|
+
```typescript
|
|
685
|
+
const results = await stableApiGateway(
|
|
686
|
+
[
|
|
687
|
+
{ id: 'us-user-profile', groupId: 'us-east', requestOptions: { reqData: { path: '/users/profile' }, resReq: true } },
|
|
688
|
+
{ id: 'us-orders', groupId: 'us-east', requestOptions: { reqData: { path: '/orders' }, resReq: true } },
|
|
689
|
+
|
|
690
|
+
{ id: 'eu-user-profile', groupId: 'eu-west', requestOptions: { reqData: { path: '/users/profile' }, resReq: true } },
|
|
691
|
+
{ id: 'eu-orders', groupId: 'eu-west', requestOptions: { reqData: { path: '/orders' }, resReq: true } },
|
|
692
|
+
|
|
693
|
+
{ id: 'ap-user-profile', groupId: 'ap-southeast', requestOptions: { reqData: { path: '/users/profile' }, resReq: true } },
|
|
694
|
+
{ id: 'ap-orders', groupId: 'ap-southeast', requestOptions: { reqData: { path: '/orders' }, resReq: true } }
|
|
695
|
+
],
|
|
696
|
+
{
|
|
697
|
+
commonAttempts: 3,
|
|
698
|
+
commonWait: 1000,
|
|
699
|
+
|
|
700
|
+
requestGroups: [
|
|
701
|
+
{
|
|
702
|
+
id: 'us-east',
|
|
703
|
+
commonConfig: {
|
|
704
|
+
commonRequestData: {
|
|
705
|
+
hostname: 'api-us-east.example.com',
|
|
706
|
+
headers: { 'X-Region': 'us-east-1' },
|
|
707
|
+
timeout: 5000 // Lower latency expected
|
|
708
|
+
},
|
|
709
|
+
commonAttempts: 3,
|
|
710
|
+
commonRetryStrategy: RETRY_STRATEGIES.LINEAR
|
|
711
|
+
}
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
id: 'eu-west',
|
|
715
|
+
commonConfig: {
|
|
716
|
+
commonRequestData: {
|
|
717
|
+
hostname: 'api-eu-west.example.com',
|
|
718
|
+
headers: { 'X-Region': 'eu-west-1' },
|
|
719
|
+
timeout: 8000
|
|
720
|
+
},
|
|
721
|
+
commonAttempts: 5,
|
|
722
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
id: 'ap-southeast',
|
|
727
|
+
commonConfig: {
|
|
728
|
+
commonRequestData: {
|
|
729
|
+
hostname: 'api-ap-southeast.example.com',
|
|
730
|
+
headers: { 'X-Region': 'ap-southeast-1' },
|
|
731
|
+
timeout: 10000 // Higher latency expected
|
|
732
|
+
},
|
|
733
|
+
commonAttempts: 7,
|
|
734
|
+
commonWait: 1500,
|
|
735
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
]
|
|
739
|
+
}
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
// Regional performance analysis
|
|
743
|
+
const regionPerformance = results.reduce((acc, result) => {
|
|
744
|
+
if (!acc[result.groupId!]) acc[result.groupId!] = { success: 0, failed: 0 };
|
|
745
|
+
result.success ? acc[result.groupId!].success++ : acc[result.groupId!].failed++;
|
|
746
|
+
return acc;
|
|
747
|
+
}, {} as Record<string, { success: number; failed: number }>);
|
|
748
|
+
|
|
749
|
+
console.log('Regional performance:', regionPerformance);
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### 3. Microservices Health Monitoring with Groups
|
|
753
|
+
|
|
754
|
+
Monitor different microservices with service-specific health check configurations.
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
const healthChecks = await stableApiGateway(
|
|
758
|
+
[
|
|
759
|
+
// Core services
|
|
760
|
+
{ id: 'auth-health', groupId: 'core', requestOptions: { reqData: { hostname: 'auth.internal.example.com', path: '/health' } } },
|
|
761
|
+
{ id: 'user-health', groupId: 'core', requestOptions: { reqData: { hostname: 'users.internal.example.com', path: '/health' } } },
|
|
762
|
+
{ id: 'order-health', groupId: 'core', requestOptions: { reqData: { hostname: 'orders.internal.example.com', path: '/health' } } },
|
|
763
|
+
|
|
764
|
+
// Auxiliary services
|
|
765
|
+
{ id: 'cache-health', groupId: 'auxiliary', requestOptions: { reqData: { hostname: 'cache.internal.example.com', path: '/health' } } },
|
|
766
|
+
{ id: 'search-health', groupId: 'auxiliary', requestOptions: { reqData: { hostname: 'search.internal.example.com', path: '/health' } } },
|
|
767
|
+
|
|
768
|
+
// Third-party
|
|
769
|
+
{ id: 'stripe-health', groupId: 'third-party', requestOptions: { reqData: { hostname: 'api.stripe.com', path: '/v1/health' } } }
|
|
770
|
+
],
|
|
771
|
+
{
|
|
772
|
+
commonResReq: true,
|
|
773
|
+
concurrentExecution: true,
|
|
774
|
+
|
|
775
|
+
requestGroups: [
|
|
776
|
+
{
|
|
777
|
+
id: 'core',
|
|
778
|
+
commonConfig: {
|
|
779
|
+
commonAttempts: 5,
|
|
780
|
+
commonWait: 2000,
|
|
781
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL,
|
|
782
|
+
commonResponseAnalyzer: async (reqData, data) => {
|
|
783
|
+
return data?.status === 'healthy' &&
|
|
784
|
+
data?.dependencies?.every(d => d.status === 'healthy');
|
|
785
|
+
},
|
|
786
|
+
commonHandleErrors: async (reqData, error) => {
|
|
787
|
+
await pagerDuty.trigger({ severity: 'critical', message: `Core service down: ${error.error}` });
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
id: 'auxiliary',
|
|
793
|
+
commonConfig: {
|
|
794
|
+
commonAttempts: 2,
|
|
795
|
+
commonResponseAnalyzer: async (reqData, data) => data?.status === 'ok',
|
|
796
|
+
commonFinalErrorAnalyzer: async () => true // Don't fail on auxiliary issues
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
id: 'third-party',
|
|
801
|
+
commonConfig: {
|
|
802
|
+
commonAttempts: 3,
|
|
803
|
+
commonWait: 3000,
|
|
804
|
+
commonRequestData: { timeout: 15000 },
|
|
805
|
+
commonHandleErrors: async (reqData, error) => {
|
|
806
|
+
logger.warn('Third-party health check failed', { error });
|
|
807
|
+
},
|
|
808
|
+
commonFinalErrorAnalyzer: async () => true
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
]
|
|
812
|
+
}
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
const healthReport = {
|
|
816
|
+
timestamp: new Date().toISOString(),
|
|
817
|
+
core: healthChecks.filter(r => r.groupId === 'core').every(r => r.success),
|
|
818
|
+
auxiliary: healthChecks.filter(r => r.groupId === 'auxiliary').every(r => r.success),
|
|
819
|
+
thirdParty: healthChecks.filter(r => r.groupId === 'third-party').every(r => r.success),
|
|
820
|
+
overall: healthChecks.every(r => r.success) ? 'HEALTHY' : 'DEGRADED'
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
console.log('Health Report:', healthReport);
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### 4. Polling for Async Job Completion
|
|
448
827
|
|
|
449
828
|
```typescript
|
|
450
829
|
const jobResult = await stableRequest({
|
|
@@ -465,7 +844,7 @@ const jobResult = await stableRequest({
|
|
|
465
844
|
});
|
|
466
845
|
```
|
|
467
846
|
|
|
468
|
-
###
|
|
847
|
+
### 5. Resilient External API Integration
|
|
469
848
|
|
|
470
849
|
```typescript
|
|
471
850
|
const weatherData = await stableRequest({
|
|
@@ -489,7 +868,7 @@ const weatherData = await stableRequest({
|
|
|
489
868
|
});
|
|
490
869
|
```
|
|
491
870
|
|
|
492
|
-
###
|
|
871
|
+
### 6. Database Replication Consistency Check
|
|
493
872
|
|
|
494
873
|
```typescript
|
|
495
874
|
const consistentData = await stableRequest({
|
|
@@ -508,7 +887,7 @@ const consistentData = await stableRequest({
|
|
|
508
887
|
});
|
|
509
888
|
```
|
|
510
889
|
|
|
511
|
-
###
|
|
890
|
+
### 7. Batch User Creation
|
|
512
891
|
|
|
513
892
|
```typescript
|
|
514
893
|
const users = [
|
|
@@ -537,9 +916,9 @@ const results = await stableApiGateway(requests, {
|
|
|
537
916
|
console.log(`Failed to create user: ${error.error}`);
|
|
538
917
|
},
|
|
539
918
|
commonRequestData: {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
919
|
+
hostname: 'api.example.com',
|
|
920
|
+
path: '/users',
|
|
921
|
+
method: REQUEST_METHODS.POST
|
|
543
922
|
}
|
|
544
923
|
});
|
|
545
924
|
|
|
@@ -550,156 +929,97 @@ console.log(`Created ${successful.length} users`);
|
|
|
550
929
|
console.log(`Failed to create ${failed.length} users`);
|
|
551
930
|
```
|
|
552
931
|
|
|
553
|
-
###
|
|
554
|
-
|
|
555
|
-
```typescript
|
|
556
|
-
const searchResults = await stableRequest({
|
|
557
|
-
reqData: {
|
|
558
|
-
hostname: 'api.ratelimited-service.com',
|
|
559
|
-
path: '/search',
|
|
560
|
-
query: { q: 'nodejs' }
|
|
561
|
-
},
|
|
562
|
-
resReq: true,
|
|
563
|
-
attempts: 10,
|
|
564
|
-
wait: 1000,
|
|
565
|
-
retryStrategy: RETRY_STRATEGIES.EXPONENTIAL, // Exponential backoff for rate limits
|
|
566
|
-
handleErrors: async (reqConfig, error) => {
|
|
567
|
-
if (error.type === 'HTTP_ERROR' && error.error.includes('429')) {
|
|
568
|
-
console.log('Rate limited, backing off...');
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
### 6. Microservices Health Check
|
|
932
|
+
### 8. Batch Data Processing with Tiered Priority Groups
|
|
575
933
|
|
|
576
934
|
```typescript
|
|
577
|
-
const
|
|
935
|
+
const dataItems = [
|
|
936
|
+
{ id: 1, data: 'critical-transaction', priority: 'high' },
|
|
937
|
+
{ id: 2, data: 'user-action', priority: 'medium' },
|
|
938
|
+
{ id: 3, data: 'analytics-event', priority: 'low' }
|
|
939
|
+
];
|
|
578
940
|
|
|
579
|
-
const
|
|
580
|
-
id: `
|
|
941
|
+
const requests = dataItems.map(item => ({
|
|
942
|
+
id: `item-${item.id}`,
|
|
943
|
+
groupId: item.priority === 'high' ? 'high-priority' :
|
|
944
|
+
item.priority === 'medium' ? 'medium-priority' : 'low-priority',
|
|
581
945
|
requestOptions: {
|
|
582
|
-
reqData: {
|
|
583
|
-
|
|
584
|
-
},
|
|
585
|
-
resReq: true,
|
|
586
|
-
attempts: 3,
|
|
587
|
-
wait: 500
|
|
946
|
+
reqData: { body: item },
|
|
947
|
+
resReq: true
|
|
588
948
|
}
|
|
589
949
|
}));
|
|
590
950
|
|
|
591
|
-
const results = await stableApiGateway(
|
|
951
|
+
const results = await stableApiGateway(requests, {
|
|
592
952
|
concurrentExecution: true,
|
|
593
953
|
commonRequestData: {
|
|
594
|
-
|
|
954
|
+
hostname: 'processing.example.com',
|
|
955
|
+
path: '/process',
|
|
956
|
+
method: REQUEST_METHODS.POST
|
|
595
957
|
},
|
|
596
|
-
|
|
958
|
+
|
|
959
|
+
requestGroups: [
|
|
960
|
+
{
|
|
961
|
+
id: 'high-priority',
|
|
962
|
+
commonConfig: {
|
|
963
|
+
commonAttempts: 10,
|
|
964
|
+
commonWait: 2000,
|
|
965
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL,
|
|
966
|
+
commonRequestData: { headers: { 'X-Priority': 'high' } },
|
|
967
|
+
commonResponseAnalyzer: async (reqData, data) => {
|
|
968
|
+
return data?.processed && !data?.errors?.length && data?.validationStatus === 'passed';
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
id: 'medium-priority',
|
|
974
|
+
commonConfig: {
|
|
975
|
+
commonAttempts: 5,
|
|
976
|
+
commonWait: 1000,
|
|
977
|
+
commonRetryStrategy: RETRY_STRATEGIES.LINEAR,
|
|
978
|
+
commonRequestData: { headers: { 'X-Priority': 'medium' } }
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
{
|
|
982
|
+
id: 'low-priority',
|
|
983
|
+
commonConfig: {
|
|
984
|
+
commonAttempts: 2,
|
|
985
|
+
commonRequestData: { headers: { 'X-Priority': 'low' } },
|
|
986
|
+
commonFinalErrorAnalyzer: async () => true // Accept failures
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
]
|
|
597
990
|
});
|
|
598
991
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
992
|
+
// Report by priority
|
|
993
|
+
const report = {
|
|
994
|
+
high: results.filter(r => r.groupId === 'high-priority'),
|
|
995
|
+
medium: results.filter(r => r.groupId === 'medium-priority'),
|
|
996
|
+
low: results.filter(r => r.groupId === 'low-priority')
|
|
997
|
+
};
|
|
604
998
|
|
|
605
|
-
console.log(
|
|
999
|
+
console.log(`High: ${report.high.filter(r => r.success).length}/${report.high.length}`);
|
|
1000
|
+
console.log(`Medium: ${report.medium.filter(r => r.success).length}/${report.medium.length}`);
|
|
1001
|
+
console.log(`Low: ${report.low.filter(r => r.success).length}/${report.low.length}`);
|
|
606
1002
|
```
|
|
607
1003
|
|
|
608
|
-
###
|
|
1004
|
+
### 9. Rate-Limited API with Backoff
|
|
609
1005
|
|
|
610
1006
|
```typescript
|
|
611
|
-
const
|
|
1007
|
+
const searchResults = await stableRequest({
|
|
612
1008
|
reqData: {
|
|
613
|
-
hostname: '
|
|
614
|
-
path: '/
|
|
615
|
-
|
|
616
|
-
headers: { 'Idempotency-Key': uniqueId },
|
|
617
|
-
body: { amount: 1000, currency: 'USD' }
|
|
1009
|
+
hostname: 'api.ratelimited-service.com',
|
|
1010
|
+
path: '/search',
|
|
1011
|
+
query: { q: 'nodejs' }
|
|
618
1012
|
},
|
|
619
1013
|
resReq: true,
|
|
620
|
-
attempts:
|
|
1014
|
+
attempts: 10,
|
|
621
1015
|
wait: 1000,
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const status = await checkPaymentStatus(uniqueId);
|
|
628
|
-
return status === 'succeeded';
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
### 8. Bulk Data Migration
|
|
634
|
-
|
|
635
|
-
```typescript
|
|
636
|
-
const records = await fetchLegacyRecords();
|
|
637
|
-
|
|
638
|
-
const migrationRequests = records.map((record, index) => ({
|
|
639
|
-
id: `migrate-${record.id}`,
|
|
640
|
-
requestOptions: {
|
|
641
|
-
reqData: {
|
|
642
|
-
body: record
|
|
643
|
-
},
|
|
644
|
-
resReq: true,
|
|
645
|
-
// Individual retry config for critical records
|
|
646
|
-
...(record.critical && {
|
|
647
|
-
attempts: 5,
|
|
648
|
-
wait: 2000,
|
|
649
|
-
retryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
650
|
-
})
|
|
651
|
-
}
|
|
652
|
-
}));
|
|
653
|
-
|
|
654
|
-
const results = await stableApiGateway(migrationRequests, {
|
|
655
|
-
concurrentExecution: true,
|
|
656
|
-
commonRequestData: {
|
|
657
|
-
hostname: 'new-system.example.com',
|
|
658
|
-
path: '/import',
|
|
659
|
-
method: REQUEST_METHODS.POST,
|
|
660
|
-
}
|
|
661
|
-
commonAttempts: 3,
|
|
662
|
-
commonWait: 1000,
|
|
663
|
-
commonRetryStrategy: RETRY_STRATEGIES.LINEAR,
|
|
664
|
-
commonHandleErrors: async (reqConfig, error) => {
|
|
665
|
-
await logMigrationError(reqConfig.data.id, error);
|
|
666
|
-
}
|
|
667
|
-
});
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
### 9. Multi-Source Data Aggregation
|
|
671
|
-
|
|
672
|
-
```typescript
|
|
673
|
-
const sources = [
|
|
674
|
-
{ id: 'source-1', hostname: 'api1.example.com', path: '/data' },
|
|
675
|
-
{ id: 'source-2', hostname: 'api2.example.com', path: '/info' },
|
|
676
|
-
{ id: 'source-3', hostname: 'api3.example.com', path: '/stats' }
|
|
677
|
-
];
|
|
678
|
-
|
|
679
|
-
const requests = sources.map(source => ({
|
|
680
|
-
id: source.id,
|
|
681
|
-
requestOptions: {
|
|
682
|
-
reqData: {
|
|
683
|
-
hostname: source.hostname,
|
|
684
|
-
path: source.path
|
|
685
|
-
},
|
|
686
|
-
resReq: true,
|
|
687
|
-
attempts: 3,
|
|
688
|
-
finalErrorAnalyzer: async () => true // Don't fail if one source is down
|
|
1016
|
+
retryStrategy: RETRY_STRATEGIES.EXPONENTIAL,
|
|
1017
|
+
handleErrors: async (reqConfig, error) => {
|
|
1018
|
+
if (error.type === 'HTTP_ERROR' && error.error.includes('429')) {
|
|
1019
|
+
console.log('Rate limited, backing off...');
|
|
1020
|
+
}
|
|
689
1021
|
}
|
|
690
|
-
}));
|
|
691
|
-
|
|
692
|
-
const results = await stableApiGateway(requests, {
|
|
693
|
-
concurrentExecution: true,
|
|
694
|
-
commonWait: 1000,
|
|
695
|
-
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
696
1022
|
});
|
|
697
|
-
|
|
698
|
-
const aggregatedData = results
|
|
699
|
-
.filter(r => r.success)
|
|
700
|
-
.map(r => r.data);
|
|
701
|
-
|
|
702
|
-
console.log(`Collected data from ${aggregatedData.length}/${sources.length} sources`);
|
|
703
1023
|
```
|
|
704
1024
|
|
|
705
1025
|
### 10. Sequential Workflow with Dependencies
|
|
@@ -709,18 +1029,14 @@ const workflowSteps = [
|
|
|
709
1029
|
{
|
|
710
1030
|
id: 'step-1-init',
|
|
711
1031
|
requestOptions: {
|
|
712
|
-
reqData: {
|
|
713
|
-
path: '/init',
|
|
714
|
-
},
|
|
1032
|
+
reqData: { path: '/init' },
|
|
715
1033
|
resReq: true
|
|
716
1034
|
}
|
|
717
1035
|
},
|
|
718
1036
|
{
|
|
719
1037
|
id: 'step-2-process',
|
|
720
1038
|
requestOptions: {
|
|
721
|
-
reqData: {
|
|
722
|
-
path: '/process',
|
|
723
|
-
},
|
|
1039
|
+
reqData: { path: '/process' },
|
|
724
1040
|
resReq: true,
|
|
725
1041
|
responseAnalyzer: async (reqConfig, data) => {
|
|
726
1042
|
return data.status === 'completed';
|
|
@@ -730,22 +1046,20 @@ const workflowSteps = [
|
|
|
730
1046
|
{
|
|
731
1047
|
id: 'step-3-finalize',
|
|
732
1048
|
requestOptions: {
|
|
733
|
-
reqData: {
|
|
734
|
-
path: '/finalize',
|
|
735
|
-
},
|
|
1049
|
+
reqData: { path: '/finalize' },
|
|
736
1050
|
resReq: true
|
|
737
1051
|
}
|
|
738
1052
|
}
|
|
739
1053
|
];
|
|
740
1054
|
|
|
741
1055
|
const results = await stableApiGateway(workflowSteps, {
|
|
742
|
-
concurrentExecution: false,
|
|
743
|
-
stopOnFirstError: true,
|
|
1056
|
+
concurrentExecution: false,
|
|
1057
|
+
stopOnFirstError: true,
|
|
744
1058
|
commonRequestData: {
|
|
745
1059
|
hostname: 'workflow.example.com',
|
|
746
1060
|
method: REQUEST_METHODS.POST,
|
|
747
1061
|
body: { workflowId: 'wf-123' }
|
|
748
|
-
}
|
|
1062
|
+
},
|
|
749
1063
|
commonAttempts: 5,
|
|
750
1064
|
commonWait: 2000,
|
|
751
1065
|
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
@@ -780,25 +1094,26 @@ async function resilientRequest(endpoint: string) {
|
|
|
780
1094
|
failureCount++;
|
|
781
1095
|
}
|
|
782
1096
|
});
|
|
783
|
-
failureCount = 0;
|
|
1097
|
+
failureCount = 0;
|
|
784
1098
|
return result;
|
|
785
1099
|
} catch (error) {
|
|
786
1100
|
if (failureCount >= CIRCUIT_THRESHOLD) {
|
|
787
1101
|
console.log('Circuit breaker activated');
|
|
788
|
-
setTimeout(() => { failureCount = 0; }, 60000);
|
|
1102
|
+
setTimeout(() => { failureCount = 0; }, 60000);
|
|
789
1103
|
}
|
|
790
1104
|
throw error;
|
|
791
1105
|
}
|
|
792
1106
|
}
|
|
793
1107
|
```
|
|
794
1108
|
|
|
795
|
-
### Dynamic Request Configuration
|
|
1109
|
+
### Dynamic Request Configuration with Groups
|
|
796
1110
|
|
|
797
1111
|
```typescript
|
|
798
1112
|
const endpoints = await getEndpointsFromConfig();
|
|
799
1113
|
|
|
800
1114
|
const requests = endpoints.map(endpoint => ({
|
|
801
1115
|
id: endpoint.id,
|
|
1116
|
+
groupId: endpoint.tier, // 'critical', 'standard', or 'optional'
|
|
802
1117
|
requestOptions: {
|
|
803
1118
|
reqData: {
|
|
804
1119
|
hostname: endpoint.hostname,
|
|
@@ -808,15 +1123,37 @@ const requests = endpoints.map(endpoint => ({
|
|
|
808
1123
|
headers: { Authorization: `Bearer ${endpoint.auth}` }
|
|
809
1124
|
})
|
|
810
1125
|
},
|
|
811
|
-
resReq: true
|
|
812
|
-
attempts: endpoint.critical ? 5 : 3,
|
|
813
|
-
retryStrategy: endpoint.critical ? RETRY_STRATEGIES.EXPONENTIAL : RETRY_STRATEGIES.FIXED
|
|
1126
|
+
resReq: true
|
|
814
1127
|
}
|
|
815
1128
|
}));
|
|
816
1129
|
|
|
817
1130
|
const results = await stableApiGateway(requests, {
|
|
818
1131
|
concurrentExecution: true,
|
|
819
|
-
commonWait: 1000
|
|
1132
|
+
commonWait: 1000,
|
|
1133
|
+
|
|
1134
|
+
requestGroups: [
|
|
1135
|
+
{
|
|
1136
|
+
id: 'critical',
|
|
1137
|
+
commonConfig: {
|
|
1138
|
+
commonAttempts: 10,
|
|
1139
|
+
commonRetryStrategy: RETRY_STRATEGIES.EXPONENTIAL
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
id: 'standard',
|
|
1144
|
+
commonConfig: {
|
|
1145
|
+
commonAttempts: 5,
|
|
1146
|
+
commonRetryStrategy: RETRY_STRATEGIES.LINEAR
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
id: 'optional',
|
|
1151
|
+
commonConfig: {
|
|
1152
|
+
commonAttempts: 2,
|
|
1153
|
+
commonFinalErrorAnalyzer: async () => true
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
]
|
|
820
1157
|
});
|
|
821
1158
|
```
|
|
822
1159
|
|
|
@@ -831,13 +1168,11 @@ await stableRequest({
|
|
|
831
1168
|
resReq: true,
|
|
832
1169
|
attempts: 5,
|
|
833
1170
|
responseAnalyzer: async (reqConfig, data) => {
|
|
834
|
-
// Only retry if data is incomplete
|
|
835
1171
|
if (!data.complete) {
|
|
836
1172
|
console.log('Data incomplete, retrying...');
|
|
837
1173
|
return false;
|
|
838
1174
|
}
|
|
839
1175
|
|
|
840
|
-
// Don't retry if data is invalid (different from incomplete)
|
|
841
1176
|
if (data.error) {
|
|
842
1177
|
throw new Error('Invalid data, cannot retry');
|
|
843
1178
|
}
|
|
@@ -890,6 +1225,7 @@ console.log(user.id);
|
|
|
890
1225
|
|---------|----------------|-------------|
|
|
891
1226
|
| **Content validation** | โ
Full support with `responseAnalyzer` | โ Only HTTP status codes |
|
|
892
1227
|
| **Batch processing** | โ
Built-in `stableApiGateway` | โ Manual implementation needed |
|
|
1228
|
+
| **Request grouping** | โ
Hierarchical configuration | โ No grouping support |
|
|
893
1229
|
| **Trial mode** | โ
Built-in failure simulation | โ No testing utilities |
|
|
894
1230
|
| **Retry strategies** | โ
Fixed, Linear, Exponential | โ
Exponential only |
|
|
895
1231
|
| **Observability** | โ
Granular hooks for every attempt | โ ๏ธ Limited |
|
|
@@ -901,7 +1237,8 @@ console.log(user.id);
|
|
|
901
1237
|
|---------|----------------|-----|
|
|
902
1238
|
| **Built on Axios** | โ
Leverages Axios ecosystem | โ Standalone client |
|
|
903
1239
|
| **Content validation** | โ
Response analyzer | โ Only HTTP errors |
|
|
904
|
-
| **Batch processing** | โ
Built-in gateway | โ Manual implementation |
|
|
1240
|
+
| **Batch processing** | โ
Built-in gateway with grouping | โ Manual implementation |
|
|
1241
|
+
| **Request grouping** | โ
Multi-tier configuration | โ No grouping |
|
|
905
1242
|
| **Trial mode** | โ
Simulation for testing | โ No |
|
|
906
1243
|
| **Retry strategies** | โ
3 configurable strategies | โ
Exponential with jitter |
|
|
907
1244
|
|
|
@@ -912,19 +1249,23 @@ console.log(user.id);
|
|
|
912
1249
|
| **All-in-one** | โ
Single package | โ Requires multiple packages |
|
|
913
1250
|
| **HTTP-aware** | โ
Built for HTTP | โ Generic retry wrapper |
|
|
914
1251
|
| **Content validation** | โ
Built-in | โ Manual implementation |
|
|
915
|
-
| **Batch processing** | โ
Built-in | โ Manual implementation |
|
|
1252
|
+
| **Batch processing** | โ
Built-in with groups | โ Manual implementation |
|
|
1253
|
+
| **Request grouping** | โ
Native support | โ No grouping |
|
|
916
1254
|
| **Observability** | โ
Request-specific hooks | โ ๏ธ Generic callbacks |
|
|
917
1255
|
|
|
918
1256
|
## Best Practices
|
|
919
1257
|
|
|
920
1258
|
1. **Use exponential backoff for rate-limited APIs** to avoid overwhelming the server
|
|
921
|
-
2. **
|
|
922
|
-
3. **
|
|
923
|
-
4. **
|
|
924
|
-
5. **Use
|
|
925
|
-
6. **
|
|
926
|
-
7. **
|
|
927
|
-
8. **Use
|
|
1259
|
+
2. **Organize related requests into groups** for easier configuration management
|
|
1260
|
+
3. **Set reasonable timeout values** in `reqData.timeout` to prevent hanging requests
|
|
1261
|
+
4. **Implement responseAnalyzer** for APIs that return 200 OK with error details in the body
|
|
1262
|
+
5. **Use concurrent execution** in `stableApiGateway` for independent requests
|
|
1263
|
+
6. **Use sequential execution** when requests have dependencies or need to maintain order
|
|
1264
|
+
7. **Leverage request groups** to differentiate between critical and optional services
|
|
1265
|
+
8. **Use finalErrorAnalyzer** for graceful degradation in non-critical paths
|
|
1266
|
+
9. **Enable logging in development** with `logAllErrors` and `logAllSuccessfulAttempts`
|
|
1267
|
+
10. **Use Trial Mode** to test your error handling without relying on actual failures
|
|
1268
|
+
11. **Group requests by region or service tier** for better monitoring and configuration
|
|
928
1269
|
|
|
929
1270
|
## License
|
|
930
1271
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,eAAO,MAAM,+BAA+B,EAAE,wBAAwB,EAcrE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const PrepareApiRequestOptionsMapping = [
|
|
2
|
+
{ localKey: 'resReq', commonKey: 'commonResReq', groupCommonKey: 'commonResReq', targetKey: 'resReq' },
|
|
3
|
+
{ localKey: 'attempts', commonKey: 'commonAttempts', groupCommonKey: 'commonAttempts', targetKey: 'attempts' },
|
|
4
|
+
{ localKey: 'performAllAttempts', commonKey: 'commonPerformAllAttempts', groupCommonKey: 'commonPerformAllAttempts', targetKey: 'performAllAttempts' },
|
|
5
|
+
{ localKey: 'wait', commonKey: 'commonWait', groupCommonKey: 'commonWait', targetKey: 'wait' },
|
|
6
|
+
{ localKey: 'retryStrategy', commonKey: 'commonRetryStrategy', groupCommonKey: 'commonRetryStrategy', targetKey: 'retryStrategy' },
|
|
7
|
+
{ localKey: 'logAllErrors', commonKey: 'commonLogAllErrors', groupCommonKey: 'commonLogAllErrors', targetKey: 'logAllErrors' },
|
|
8
|
+
{ localKey: 'logAllSuccessfulAttempts', commonKey: 'commonLogAllSuccessfulAttempts', groupCommonKey: 'commonLogAllSuccessfulAttempts', targetKey: 'logAllSuccessfulAttempts' },
|
|
9
|
+
{ localKey: 'maxSerializableChars', commonKey: 'commonMaxSerializableChars', groupCommonKey: 'commonMaxSerializableChars', targetKey: 'maxSerializableChars' },
|
|
10
|
+
{ localKey: 'trialMode', commonKey: 'commonTrialMode', groupCommonKey: 'commonTrialMode', targetKey: 'trialMode' },
|
|
11
|
+
{ localKey: 'responseAnalyzer', commonKey: 'commonResponseAnalyzer', groupCommonKey: 'commonResponseAnalyzer', targetKey: 'responseAnalyzer' },
|
|
12
|
+
{ localKey: 'handleErrors', commonKey: 'commonHandleErrors', groupCommonKey: 'commonHandleErrors', targetKey: 'handleErrors' },
|
|
13
|
+
{ localKey: 'handleSuccessfulAttemptData', commonKey: 'commonHandleSuccessfulAttemptData', groupCommonKey: 'commonHandleSuccessfulAttemptData', targetKey: 'handleSuccessfulAttemptData' },
|
|
14
|
+
{ localKey: 'finalErrorAnalyzer', commonKey: 'commonFinalErrorAnalyzer', groupCommonKey: 'commonFinalErrorAnalyzer', targetKey: 'finalErrorAnalyzer' },
|
|
15
|
+
];
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,+BAA+B,GAA+B;IACvE,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE;IACtG,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE;IAC9G,EAAE,QAAQ,EAAE,oBAAoB,EAAE,SAAS,EAAE,0BAA0B,EAAE,cAAc,EAAE,0BAA0B,EAAE,SAAS,EAAE,oBAAoB,EAAE;IACtJ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE;IAC9F,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,qBAAqB,EAAE,cAAc,EAAE,qBAAqB,EAAE,SAAS,EAAE,eAAe,EAAE;IAClI,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,oBAAoB,EAAE,cAAc,EAAE,oBAAoB,EAAE,SAAS,EAAE,cAAc,EAAE;IAC9H,EAAE,QAAQ,EAAE,0BAA0B,EAAE,SAAS,EAAE,gCAAgC,EAAE,cAAc,EAAE,gCAAgC,EAAE,SAAS,EAAE,0BAA0B,EAAE;IAC9K,EAAE,QAAQ,EAAE,sBAAsB,EAAE,SAAS,EAAE,4BAA4B,EAAE,cAAc,EAAE,4BAA4B,EAAE,SAAS,EAAE,sBAAsB,EAAE;IAC9J,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE;IAClH,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,EAAE,wBAAwB,EAAE,cAAc,EAAE,wBAAwB,EAAE,SAAS,EAAE,kBAAkB,EAAE;IAC9I,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,oBAAoB,EAAE,cAAc,EAAE,oBAAoB,EAAE,SAAS,EAAE,cAAc,EAAE;IAC9H,EAAE,QAAQ,EAAE,6BAA6B,EAAE,SAAS,EAAE,mCAAmC,EAAE,cAAc,EAAE,mCAAmC,EAAE,SAAS,EAAE,6BAA6B,EAAE;IAC1L,EAAE,QAAQ,EAAE,oBAAoB,EAAE,SAAS,EAAE,0BAA0B,EAAE,cAAc,EAAE,0BAA0B,EAAE,SAAS,EAAE,oBAAoB,EAAE;CACzJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stable-api-gateway.d.ts","sourceRoot":"","sources":["../../src/core/stable-api-gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,mBAAmB,EAGtB,MAAM,mBAAmB,CAAC;AAO3B,wBAAsB,gBAAgB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EAChF,QAAQ,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAO,EACvE,OAAO,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAM,
|
|
1
|
+
{"version":3,"file":"stable-api-gateway.d.ts","sourceRoot":"","sources":["../../src/core/stable-api-gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,mBAAmB,EAGtB,MAAM,mBAAmB,CAAC;AAO3B,wBAAsB,gBAAgB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EAChF,QAAQ,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAO,EACvE,OAAO,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAM,iFAuBvE"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { executeConcurrently, executeSequentially, extractCommonRequestConfigOptions as extractCommonOptions } from '../utilities/index.js';
|
|
2
2
|
export async function stableApiGateway(requests = [], options = {}) {
|
|
3
|
-
const { concurrentExecution = true, stopOnFirstError = false, } = options;
|
|
3
|
+
const { concurrentExecution = true, stopOnFirstError = false, requestGroups = [] } = options;
|
|
4
4
|
if (!Array.isArray(requests) || requests.length === 0) {
|
|
5
5
|
return [];
|
|
6
6
|
}
|
|
7
7
|
const requestExecutionOptions = {
|
|
8
8
|
stopOnFirstError,
|
|
9
|
+
requestGroups,
|
|
9
10
|
...extractCommonOptions(options)
|
|
10
11
|
};
|
|
11
12
|
if (concurrentExecution) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stable-api-gateway.js","sourceRoot":"","sources":["../../src/core/stable-api-gateway.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,mBAAmB,EACnB,mBAAmB,EACnB,iCAAiC,IAAI,oBAAoB,EAC5D,MAAM,uBAAuB,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,WAAqE,EAAE,EACvE,UAAkE,EAAE;IAEpE,MAAM,EACF,mBAAmB,GAAG,IAAI,EAC1B,gBAAgB,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"stable-api-gateway.js","sourceRoot":"","sources":["../../src/core/stable-api-gateway.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,mBAAmB,EACnB,mBAAmB,EACnB,iCAAiC,IAAI,oBAAoB,EAC5D,MAAM,uBAAuB,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,WAAqE,EAAE,EACvE,UAAkE,EAAE;IAEpE,MAAM,EACF,mBAAmB,GAAG,IAAI,EAC1B,gBAAgB,GAAG,KAAK,EACxB,aAAa,GAAG,EAAE,EACrB,GAAG,OAAO,CAAC;IAEZ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,uBAAuB,GAAgF;QACzG,gBAAgB;QAChB,aAAa;QACb,GAAG,oBAAoB,CAAoC,OAAO,CAAC;KACtE,CAAA;IAED,IAAI,mBAAmB,EAAE,CAAC;QACtB,OAAO,mBAAmB,CAAoC,QAAQ,EAAG,EAAE,GAAG,uBAAuB,EAAE,gBAAgB,EAAE,SAAS,EAA6E,CAAC,CAAC;IACrN,CAAC;SAAM,CAAC;QACJ,OAAO,mBAAmB,CAAoC,QAAQ,EAAE,uBAAkG,CAAC,CAAC;IAChL,CAAC;AACL,CAAC"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -16,19 +16,28 @@ export interface API_GATEWAY_OPTIONS<RequestDataType = any, ResponseDataType = a
|
|
|
16
16
|
commonHandleErrors?: (reqData: AxiosRequestConfig<RequestDataType>, error: ERROR_LOG, maxSerializableChars?: number) => any | Promise<any>;
|
|
17
17
|
commonHandleSuccessfulAttemptData?: (reqData: AxiosRequestConfig<RequestDataType>, successfulAttemptData: SUCCESSFUL_ATTEMPT_DATA<ResponseDataType>, maxSerializableChars?: number) => any | Promise<any>;
|
|
18
18
|
concurrentExecution?: boolean;
|
|
19
|
+
requestGroups?: RequestGroup[];
|
|
19
20
|
stopOnFirstError?: boolean;
|
|
20
21
|
}
|
|
21
22
|
export type API_GATEWAY_REQUEST_OPTIONS_TYPE<RequestDataType, ResponseDataType> = Omit<STABLE_REQUEST<RequestDataType, ResponseDataType>, 'reqData'> & Partial<Pick<STABLE_REQUEST<RequestDataType, ResponseDataType>, 'reqData'>>;
|
|
22
23
|
export interface API_GATEWAY_REQUEST<RequestDataType = any, ResponseDataType = any> {
|
|
23
24
|
id: string;
|
|
25
|
+
groupId?: string;
|
|
24
26
|
requestOptions: API_GATEWAY_REQUEST_OPTIONS_TYPE<RequestDataType, ResponseDataType>;
|
|
25
27
|
}
|
|
26
28
|
export interface API_GATEWAY_RESPONSE<ResponseDataType = any> {
|
|
27
|
-
|
|
29
|
+
requestId: string;
|
|
30
|
+
groupId?: string;
|
|
28
31
|
success: boolean;
|
|
29
32
|
data?: ResponseDataType;
|
|
30
33
|
error?: string;
|
|
31
34
|
}
|
|
35
|
+
export type ApiRequestOptionsMapping = {
|
|
36
|
+
localKey: string;
|
|
37
|
+
commonKey: string;
|
|
38
|
+
groupCommonKey: string;
|
|
39
|
+
targetKey: string;
|
|
40
|
+
};
|
|
32
41
|
export type CONCURRENT_REQUEST_EXECUTION_OPTIONS<RequestDataType = any, ResponseDataType = any> = Omit<API_GATEWAY_OPTIONS<RequestDataType, ResponseDataType>, "concurrentExecution" | "stopOnFirstError">;
|
|
33
42
|
export interface ERROR_LOG {
|
|
34
43
|
timestamp: string;
|
|
@@ -39,6 +48,10 @@ export interface ERROR_LOG {
|
|
|
39
48
|
type: RESPONSE_ERROR_TYPES;
|
|
40
49
|
isRetryable: boolean;
|
|
41
50
|
}
|
|
51
|
+
export interface RequestGroup {
|
|
52
|
+
id: string;
|
|
53
|
+
commonConfig?: Omit<API_GATEWAY_OPTIONS, "concurrentExecution" | "stopOnFirstError">;
|
|
54
|
+
}
|
|
42
55
|
export interface ReqFnResponse<ResponseDataType = any> {
|
|
43
56
|
ok: boolean;
|
|
44
57
|
isRetryable: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,mBAAmB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG;IAChF,iBAAiB,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;IAC3C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9J,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpJ,kBAAkB,CAAC,EAAE,CACnB,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAC5C,KAAK,EAAE,SAAS,EAChB,oBAAoB,CAAC,EAAE,MAAM,KAC1B,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,iCAAiC,CAAC,EAAE,CAClC,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAC5C,qBAAqB,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,EAChE,oBAAoB,CAAC,EAAE,MAAM,KAC1B,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,gCAAgC,CAAC,eAAe,EAAE,gBAAgB,IAAI,IAAI,CAAC,cAAc,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AAEnO,MAAM,WAAW,mBAAmB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG;IAChF,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,gCAAgC,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;CACrF;AAED,MAAM,WAAW,oBAAoB,CAAC,gBAAgB,GAAG,GAAG;IAC1D,EAAE,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-concurrently.d.ts","sourceRoot":"","sources":["../../src/utilities/execute-concurrently.ts"],"names":[],"mappings":"AACA,OAAO,EACH,mBAAmB,EACnB,oBAAoB,EACpB,oCAAoC,EACvC,MAAM,mBAAmB,CAAC;AAI3B,wBAAsB,mBAAmB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EACnF,QAAQ,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAO,EACvE,uBAAuB,GAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAM,GACtG,OAAO,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"execute-concurrently.d.ts","sourceRoot":"","sources":["../../src/utilities/execute-concurrently.ts"],"names":[],"mappings":"AACA,OAAO,EACH,mBAAmB,EACnB,oBAAoB,EACpB,oCAAoC,EACvC,MAAM,mBAAmB,CAAC;AAI3B,wBAAsB,mBAAmB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EACnF,QAAQ,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAO,EACvE,uBAAuB,GAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAM,GACtG,OAAO,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAiCnD"}
|
|
@@ -18,7 +18,8 @@ export async function executeConcurrently(requests = [], requestExecutionOptions
|
|
|
18
18
|
if (res.status === 'fulfilled') {
|
|
19
19
|
const value = res.value;
|
|
20
20
|
responses.push({
|
|
21
|
-
|
|
21
|
+
requestId: req.id,
|
|
22
|
+
...(req.groupId && { groupId: req.groupId }),
|
|
22
23
|
success: value ? true : false,
|
|
23
24
|
...(value && { data: value }),
|
|
24
25
|
...(!value && { error: 'Request was unsuccessful, but the error was analyzed successfully!' })
|
|
@@ -26,7 +27,8 @@ export async function executeConcurrently(requests = [], requestExecutionOptions
|
|
|
26
27
|
}
|
|
27
28
|
else {
|
|
28
29
|
responses.push({
|
|
29
|
-
|
|
30
|
+
requestId: req.id,
|
|
31
|
+
...(req.groupId && { groupId: req.groupId }),
|
|
30
32
|
success: false,
|
|
31
33
|
error: res.reason?.message || 'An error occurred! Error description is unavailable.'
|
|
32
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-concurrently.js","sourceRoot":"","sources":["../../src/utilities/execute-concurrently.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,WAAqE,EAAE,EACvE,0BAAmG,EAAE;IAErG,MAAM,SAAS,GAA6C,EAAE,CAAC;IAC/D,MAAM,cAAc,GAA0C,EAAE,CAAC;IACjE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,mBAAmB,GAAG;YACxB,OAAO,EAAE,qBAAqB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;YAC/F,GAAG,wBAAwB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;SAC/F,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,aAAa,CAAoC,mBAAmB,CAAC,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxB,IAAG,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACxB,SAAS,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"execute-concurrently.js","sourceRoot":"","sources":["../../src/utilities/execute-concurrently.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,WAAqE,EAAE,EACvE,0BAAmG,EAAE;IAErG,MAAM,SAAS,GAA6C,EAAE,CAAC;IAC/D,MAAM,cAAc,GAA0C,EAAE,CAAC;IACjE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,mBAAmB,GAAG;YACxB,OAAO,EAAE,qBAAqB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;YAC/F,GAAG,wBAAwB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;SAC/F,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,aAAa,CAAoC,mBAAmB,CAAC,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxB,IAAG,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACxB,SAAS,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC5C,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;gBAC7B,GAAG,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,KAAyB,EAAE,CAAC;gBACjD,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,oEAAoE,EAAE,CAAC;aACjG,CAAC,CAAC;QACP,CAAC;aAAM,CAAC;YACJ,SAAS,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC5C,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,sDAAsD;aACvF,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-sequentially.d.ts","sourceRoot":"","sources":["../../src/utilities/execute-sequentially.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,mBAAmB,EACnB,oBAAoB,EACpB,oCAAoC,EACvC,MAAM,mBAAmB,CAAC;AAE3B,wBAAsB,mBAAmB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EACnF,QAAQ,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAO,EACvE,uBAAuB,GAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAM,GACtG,OAAO,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"execute-sequentially.d.ts","sourceRoot":"","sources":["../../src/utilities/execute-sequentially.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,mBAAmB,EACnB,oBAAoB,EACpB,oCAAoC,EACvC,MAAM,mBAAmB,CAAC;AAE3B,wBAAsB,mBAAmB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EACnF,QAAQ,GAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAO,EACvE,uBAAuB,GAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAM,GACtG,OAAO,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,CAAC,CA6BnD"}
|
|
@@ -11,7 +11,8 @@ export async function executeSequentially(requests = [], requestExecutionOptions
|
|
|
11
11
|
};
|
|
12
12
|
const res = await stableRequest(finalRequestOptions);
|
|
13
13
|
responses.push({
|
|
14
|
-
|
|
14
|
+
requestId: req.id,
|
|
15
|
+
...(req.groupId && { groupId: req.groupId }),
|
|
15
16
|
success: res ? true : false,
|
|
16
17
|
...(res && { data: res }),
|
|
17
18
|
...(!res && { error: 'Request was unsuccessful, but analyzed successfully!' })
|
|
@@ -19,7 +20,8 @@ export async function executeSequentially(requests = [], requestExecutionOptions
|
|
|
19
20
|
}
|
|
20
21
|
catch (e) {
|
|
21
22
|
responses.push({
|
|
22
|
-
|
|
23
|
+
requestId: req.id,
|
|
24
|
+
...(req.groupId && { groupId: req.groupId }),
|
|
23
25
|
success: false,
|
|
24
26
|
error: e?.message || 'An error occurred! Error description is unavailable.'
|
|
25
27
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-sequentially.js","sourceRoot":"","sources":["../../src/utilities/execute-sequentially.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAO5E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,WAAqE,EAAE,EACvE,0BAAmG,EAAE;IAErG,MAAM,SAAS,GAA6C,EAAE,CAAC;IAC/D,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC;YACD,MAAM,mBAAmB,GAAG;gBACxB,OAAO,EAAE,qBAAqB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;gBAC/F,GAAG,wBAAwB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;aAC/F,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,aAAa,CAAoC,mBAAmB,CAAC,CAAC;YACxF,SAAS,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"execute-sequentially.js","sourceRoot":"","sources":["../../src/utilities/execute-sequentially.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAO5E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,WAAqE,EAAE,EACvE,0BAAmG,EAAE;IAErG,MAAM,SAAS,GAA6C,EAAE,CAAC;IAC/D,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC;YACD,MAAM,mBAAmB,GAAG;gBACxB,OAAO,EAAE,qBAAqB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;gBAC/F,GAAG,wBAAwB,CAAoC,GAAG,EAAE,uBAAuB,CAAC;aAC/F,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,aAAa,CAAoC,mBAAmB,CAAC,CAAC;YACxF,SAAS,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC5C,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;gBAC3B,GAAG,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,GAAuB,EAAE,CAAC;gBAC7C,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,sDAAsD,EAAE,CAAC;aACjF,CAAC,CAAA;QACN,CAAC;QAAC,OAAM,CAAM,EAAE,CAAC;YACb,SAAS,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC5C,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,CAAC,EAAE,OAAO,IAAI,sDAAsD;aAC9E,CAAC,CAAC;YACH,IAAG,uBAAuB,CAAC,gBAAgB,EAAE,CAAC;gBAC1C,MAAM;YACV,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-api-request-data.d.ts","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-data.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,oCAAoC,EACpC,YAAY,EACZ,oCAAoC,EACvC,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,qBAAqB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EAC/E,OAAO,EAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAC/D,6BAA6B,EAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAC,GAC1E,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAC,GACpG,YAAY,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"prepare-api-request-data.d.ts","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-data.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,oCAAoC,EACpC,YAAY,EACZ,oCAAoC,EACvC,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,qBAAqB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EAC/E,OAAO,EAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAC/D,6BAA6B,EAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAC,GAC1E,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAC,GACpG,YAAY,CAAC,eAAe,CAAC,CAe/B"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export function prepareApiRequestData(request, commonRequestExecutionOptions) {
|
|
2
2
|
const { requestOptions: localOptions } = request;
|
|
3
|
+
const reqGroup = request.groupId ? commonRequestExecutionOptions.requestGroups?.find(group => group.id === request.groupId) : undefined;
|
|
3
4
|
const result = {
|
|
4
5
|
...(commonRequestExecutionOptions.hasOwnProperty('commonRequestData') ? commonRequestExecutionOptions.commonRequestData : {}),
|
|
6
|
+
...(reqGroup && reqGroup?.commonConfig?.hasOwnProperty('commonRequestData') ? reqGroup?.commonConfig?.commonRequestData : {}),
|
|
5
7
|
...localOptions.reqData
|
|
6
8
|
};
|
|
7
9
|
if (!result.hasOwnProperty('hostname')) {
|
|
8
|
-
console.log('stable-request: Hostname is missing in gateway request data. Setting it to an empty string to avoid
|
|
10
|
+
console.log('stable-request: Hostname is missing in gateway request data. Setting it to an empty string to avoid errors.');
|
|
9
11
|
result.hostname = '';
|
|
10
12
|
}
|
|
11
13
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-api-request-data.js","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-data.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,qBAAqB,CACjC,OAA+D,EAC/D,6BACmG;IAEnG,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"prepare-api-request-data.js","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-data.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,qBAAqB,CACjC,OAA+D,EAC/D,6BACmG;IAEnG,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAExI,MAAM,MAAM,GAAG;QACX,GAAG,CAAC,6BAA6B,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,6BAA6B,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7H,GAAG,CAAC,QAAQ,IAAI,QAAQ,EAAE,YAAY,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7H,GAAG,YAAY,CAAC,OAAO;KAC1B,CAAC;IAEF,IAAG,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,6GAA6G,CAAC,CAAC;QAC3H,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,MAAuC,CAAC;AACnD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-api-request-options.d.ts","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-options.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prepare-api-request-options.d.ts","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-options.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,mBAAmB,EACnB,oCAAoC,EACpC,oCAAoC,EACpC,cAAc,EACjB,MAAM,mBAAmB,CAAC;AAG3B,wBAAgB,wBAAwB,CAAC,eAAe,GAAG,GAAG,EAAE,gBAAgB,GAAG,GAAG,EAClF,OAAO,EAAE,mBAAmB,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAC/D,6BAA6B,EAAE,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAC,GAC1E,oCAAoC,CAAC,eAAe,EAAE,gBAAgB,CAAC,GACpG,IAAI,CAAC,cAAc,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAE,SAAS,CAAC,CAgBpE"}
|
|
@@ -1,25 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
{ localKey: 'resReq', commonKey: 'commonResReq', targetKey: 'resReq' },
|
|
3
|
-
{ localKey: 'attempts', commonKey: 'commonAttempts', targetKey: 'attempts' },
|
|
4
|
-
{ localKey: 'performAllAttempts', commonKey: 'commonPerformAllAttempts', targetKey: 'performAllAttempts' },
|
|
5
|
-
{ localKey: 'wait', commonKey: 'commonWait', targetKey: 'wait' },
|
|
6
|
-
{ localKey: 'retryStrategy', commonKey: 'commonRetryStrategy', targetKey: 'retryStrategy' },
|
|
7
|
-
{ localKey: 'logAllErrors', commonKey: 'commonLogAllErrors', targetKey: 'logAllErrors' },
|
|
8
|
-
{ localKey: 'logAllSuccessfulAttempts', commonKey: 'commonLogAllSuccessfulAttempts', targetKey: 'logAllSuccessfulAttempts' },
|
|
9
|
-
{ localKey: 'maxSerializableChars', commonKey: 'commonMaxSerializableChars', targetKey: 'maxSerializableChars' },
|
|
10
|
-
{ localKey: 'trialMode', commonKey: 'commonTrialMode', targetKey: 'trialMode' },
|
|
11
|
-
{ localKey: 'responseAnalyzer', commonKey: 'commonResponseAnalyzer', targetKey: 'responseAnalyzer' },
|
|
12
|
-
{ localKey: 'handleErrors', commonKey: 'commonHandleErrors', targetKey: 'handleErrors' },
|
|
13
|
-
{ localKey: 'handleSuccessfulAttemptData', commonKey: 'commonHandleSuccessfulAttemptData', targetKey: 'handleSuccessfulAttemptData' },
|
|
14
|
-
{ localKey: 'finalErrorAnalyzer', commonKey: 'commonFinalErrorAnalyzer', targetKey: 'finalErrorAnalyzer' },
|
|
15
|
-
];
|
|
1
|
+
import { PrepareApiRequestOptionsMapping } from "../constants/index.js";
|
|
16
2
|
export function prepareApiRequestOptions(request, commonRequestExecutionOptions) {
|
|
17
3
|
const { requestOptions: localOptions } = request;
|
|
4
|
+
const reqGroup = request.groupId ? commonRequestExecutionOptions.requestGroups?.find(group => group.id === request.groupId) : undefined;
|
|
18
5
|
const result = {};
|
|
19
|
-
for (const mapping of
|
|
6
|
+
for (const mapping of PrepareApiRequestOptionsMapping) {
|
|
20
7
|
if (localOptions.hasOwnProperty(mapping.localKey)) {
|
|
21
8
|
result[mapping.targetKey] = localOptions[mapping.localKey];
|
|
22
9
|
}
|
|
10
|
+
else if (reqGroup && (reqGroup).hasOwnProperty(mapping.groupCommonKey)) {
|
|
11
|
+
result[mapping.targetKey] = (reqGroup?.commonConfig)[mapping.groupCommonKey];
|
|
12
|
+
}
|
|
23
13
|
else if (commonRequestExecutionOptions.hasOwnProperty(mapping.commonKey)) {
|
|
24
14
|
result[mapping.targetKey] = commonRequestExecutionOptions[mapping.commonKey];
|
|
25
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-api-request-options.js","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-options.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prepare-api-request-options.js","sourceRoot":"","sources":["../../src/utilities/prepare-api-request-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AAUxE,MAAM,UAAU,wBAAwB,CACpC,OAA+D,EAC/D,6BACmG;IAEnG,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxI,MAAM,MAAM,GAAuF,EAAE,CAAC;IAEtG,KAAK,MAAM,OAAO,IAAI,+BAA+B,EAAE,CAAC;QACpD,IAAI,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAI,YAAoB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxE,CAAC;aAAM,IAAG,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACtE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAoB,CAAA,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACxF,CAAC;aAAM,IAAI,6BAA6B,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACzE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAI,6BAAqC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1F,CAAC;IACL,CAAC;IAED,OAAO,MAA4E,CAAC;AACxF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emmvish/stable-request",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "stable-request is a TypeScript-first HTTP reliability
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "stable-request is a TypeScript-first HTTP reliability toolkit for workflow-driven API integrations, that goes beyond status-code retries by validating response content, handling eventual consistency, coordinating batch workflows with intelligent grouping, and providing deep observability into every request attempt. It is designed for real-world distributed systems where HTTP success does not guarantee business success. It also provides extensive support for managing multiple requests so as to achieve workflow automation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"circuit-breaker",
|
|
32
32
|
"api-gateway",
|
|
33
33
|
"workflows",
|
|
34
|
+
"request-groups",
|
|
34
35
|
"stable",
|
|
35
36
|
"reliable",
|
|
36
37
|
"axios",
|