@fetchkit/ffetch 5.2.1 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -17
- package/dist/chunk-X64PXWPN.min.js +2 -0
- package/dist/chunk-X64PXWPN.min.js.map +1 -0
- package/dist/{chunk-RV6LC73N.js → chunk-ZIJ2DZYZ.js} +7 -1
- package/dist/chunk-ZIJ2DZYZ.js.map +1 -0
- package/dist/{error-XBHPSMAQ.js → error-H4GGJSCM.js} +4 -2
- package/dist/error-HT5UPPWM.min.js +2 -0
- package/dist/index.cjs +53 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +49 -39
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/plugins/bulkhead.cjs +137 -0
- package/dist/plugins/bulkhead.cjs.map +1 -0
- package/dist/plugins/bulkhead.d.cts +15 -0
- package/dist/plugins/bulkhead.d.ts +15 -0
- package/dist/plugins/bulkhead.js +96 -0
- package/dist/plugins/bulkhead.js.map +1 -0
- package/dist/plugins/circuit.cjs +14 -8
- package/dist/plugins/circuit.cjs.map +1 -1
- package/dist/plugins/circuit.d.cts +16 -3
- package/dist/plugins/circuit.d.ts +16 -3
- package/dist/plugins/circuit.js +15 -9
- package/dist/plugins/circuit.js.map +1 -1
- package/dist/plugins/context-id.cjs +74 -0
- package/dist/plugins/context-id.cjs.map +1 -0
- package/dist/plugins/context-id.d.cts +10 -0
- package/dist/plugins/context-id.d.ts +10 -0
- package/dist/plugins/context-id.js +49 -0
- package/dist/plugins/context-id.js.map +1 -0
- package/dist/plugins/hedge.cjs +127 -0
- package/dist/plugins/hedge.cjs.map +1 -0
- package/dist/plugins/hedge.d.cts +12 -0
- package/dist/plugins/hedge.d.ts +12 -0
- package/dist/plugins/hedge.js +102 -0
- package/dist/plugins/hedge.js.map +1 -0
- package/package.json +17 -2
- package/dist/chunk-RV6LC73N.js.map +0 -1
- package/dist/chunk-UP35S5ZH.min.js +0 -2
- package/dist/chunk-UP35S5ZH.min.js.map +0 -1
- package/dist/error-7EEQP46E.min.js +0 -2
- /package/dist/{error-7EEQP46E.min.js.map → error-H4GGJSCM.js.map} +0 -0
- /package/dist/{error-XBHPSMAQ.js.map → error-HT5UPPWM.min.js.map} +0 -0
package/README.md
CHANGED
|
@@ -63,20 +63,26 @@ ffetch uses a plugin architecture for optional features, so you only include wha
|
|
|
63
63
|
- **Universal** – Node.js, Browser, Cloudflare Workers, React Native
|
|
64
64
|
- **Zero runtime deps** – ships as dual ESM/CJS
|
|
65
65
|
- **Configurable error handling** – custom error types and `throwOnHttpError` flag to throw on HTTP errors
|
|
66
|
+
- **Bulkhead plugin (optional, prebuilt)** – cap concurrency and queue depth per client instance
|
|
66
67
|
- **Circuit breaker plugin (optional, prebuilt)** – automatic failure protection
|
|
68
|
+
- **Hedge plugin (optional, prebuilt)** – race parallel attempts to reduce tail latency
|
|
69
|
+
- **Context ID plugin (optional, prebuilt)** – inject a stable context ID header across retries/hedges for correlation
|
|
67
70
|
- **Deduplication plugin (optional, prebuilt)** – automatic deduping of in-flight identical requests
|
|
68
71
|
- **Request shortcuts plugin (optional, prebuilt)** – call `client.get(url)` / `.post()` / `.put()` / `.patch()` / `.delete()` directly on the client
|
|
69
72
|
- **Response shortcuts plugin (optional, prebuilt)** – call `client(url).json()` / `.text()` / `.blob()` directly on the request promise
|
|
70
73
|
- **Download progress plugin (optional, prebuilt)** – stream download progress callbacks with bytes transferred and percentage
|
|
71
74
|
|
|
72
|
-
**Built-in error classes:** `TimeoutError`, `RetryLimitError`, `CircuitOpenError`, `HttpError`, `NetworkError`, `AbortError`
|
|
75
|
+
**Built-in error classes:** `TimeoutError`, `RetryLimitError`, `CircuitOpenError`, `BulkheadFullError`, `HttpError`, `NetworkError`, `AbortError`
|
|
73
76
|
|
|
74
77
|
### Built-in Plugins at a Glance
|
|
75
78
|
|
|
76
79
|
All plugins are tree-shakeable — import only what you use.
|
|
77
80
|
|
|
78
81
|
- **dedupePlugin (optional)**: dedupe in-flight identical requests.
|
|
82
|
+
- **bulkheadPlugin (optional)**: cap in-flight concurrency with optional queue backpressure.
|
|
83
|
+
- **hedgePlugin (optional)**: race multiple attempts and cancel losers when a winner is found.
|
|
79
84
|
- **circuitPlugin (optional)**: fail fast after repeated failures.
|
|
85
|
+
- **contextIdPlugin (optional)**: inject a stable request context ID (for example in `x-context-id`) across retries and hedges.
|
|
80
86
|
- **requestShortcutsPlugin (optional)**: HTTP method shortcuts on the client (`.get()` / `.post()` / `.put()` / `.patch()` / `.delete()` / `.head()` / `.options()`).
|
|
81
87
|
- **responseShortcutsPlugin (optional)**: use `client(url).json()` / `.text()` / `.blob()` style parsing.
|
|
82
88
|
- **downloadProgressPlugin (optional)**: stream download progress via `onProgress(progress, chunk)` callback.
|
|
@@ -92,6 +98,8 @@ ffetch is ideal for:
|
|
|
92
98
|
|
|
93
99
|
## Quick Start
|
|
94
100
|
|
|
101
|
+
Migrating from v4? Start with the [migration guide](./docs/migration.md) before applying the examples below.
|
|
102
|
+
|
|
95
103
|
### Install
|
|
96
104
|
|
|
97
105
|
```bash
|
|
@@ -131,6 +139,7 @@ const users = (await response.json()) as User[]
|
|
|
131
139
|
import { createClient } from '@fetchkit/ffetch'
|
|
132
140
|
import { dedupePlugin } from '@fetchkit/ffetch/plugins/dedupe'
|
|
133
141
|
import { circuitPlugin } from '@fetchkit/ffetch/plugins/circuit'
|
|
142
|
+
import { contextIdPlugin } from '@fetchkit/ffetch/plugins/context-id'
|
|
134
143
|
import { requestShortcutsPlugin } from '@fetchkit/ffetch/plugins/request-shortcuts'
|
|
135
144
|
import { responseShortcutsPlugin } from '@fetchkit/ffetch/plugins/response-shortcuts'
|
|
136
145
|
|
|
@@ -142,9 +151,11 @@ const api = createClient({
|
|
|
142
151
|
dedupePlugin({ ttl: 30_000, sweepInterval: 5_000 }),
|
|
143
152
|
// 2) Optional: open the circuit after repeated failures
|
|
144
153
|
circuitPlugin({ threshold: 5, reset: 30_000 }),
|
|
145
|
-
// 3) Optional:
|
|
154
|
+
// 3) Optional: inject stable correlation context IDs
|
|
155
|
+
contextIdPlugin(),
|
|
156
|
+
// 4) Optional: enable request-promise parsing shortcuts
|
|
146
157
|
responseShortcutsPlugin(),
|
|
147
|
-
//
|
|
158
|
+
// 5) Optional: enable client HTTP method shortcuts
|
|
148
159
|
requestShortcutsPlugin(),
|
|
149
160
|
],
|
|
150
161
|
})
|
|
@@ -163,6 +174,7 @@ What this setup gives you:
|
|
|
163
174
|
- **Operational safety**: retries with timeout defaults.
|
|
164
175
|
- **Lower duplicate traffic (optional)**: concurrent identical requests share one in-flight call.
|
|
165
176
|
- **Faster failure recovery (optional)**: circuit breaker blocks repeated failing calls.
|
|
177
|
+
- **Better observability correlation (optional)**: stable request context IDs across retries and hedges.
|
|
166
178
|
- **Cleaner request ergonomics (optional)**: `client.get(url)` / `.post(url, init)` style shortcuts.
|
|
167
179
|
- **Cleaner parsing (optional)**: `client(url).json()` style shortcuts.
|
|
168
180
|
|
|
@@ -244,8 +256,10 @@ const client = createClient({
|
|
|
244
256
|
circuitPlugin({
|
|
245
257
|
threshold: 5,
|
|
246
258
|
reset: 30_000,
|
|
247
|
-
onCircuitOpen: (
|
|
248
|
-
|
|
259
|
+
onCircuitOpen: ({ request, reason }) =>
|
|
260
|
+
console.warn('Circuit opened due to:', request.url, reason.type),
|
|
261
|
+
onCircuitClose: ({ request, response }) =>
|
|
262
|
+
console.info('Circuit closed after:', request.url, response.status),
|
|
249
263
|
}),
|
|
250
264
|
],
|
|
251
265
|
hooks: {
|
|
@@ -281,17 +295,18 @@ Native `fetch`'s controversial behavior of not throwing errors for HTTP error st
|
|
|
281
295
|
|
|
282
296
|
## Documentation
|
|
283
297
|
|
|
284
|
-
| Topic
|
|
285
|
-
|
|
|
286
|
-
| **[Complete Documentation](./docs/index.md)**
|
|
287
|
-
| **[API Reference](./docs/api.md)**
|
|
288
|
-
| **[Plugin Architecture](./docs/plugins.md)**
|
|
289
|
-
| **[Deduplication](./docs/deduplication.md)**
|
|
290
|
-
| **[Error Handling](./docs/errorhandling.md)**
|
|
291
|
-
| **[Advanced Features](./docs/advanced.md)**
|
|
292
|
-
| **[
|
|
293
|
-
| **[
|
|
294
|
-
| **[
|
|
298
|
+
| Topic | Description |
|
|
299
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------------- |
|
|
300
|
+
| **[Complete Documentation](./docs/index.md)** | **Start here** - Documentation index and overview |
|
|
301
|
+
| **[API Reference](./docs/api.md)** | Complete API documentation and configuration options |
|
|
302
|
+
| **[Plugin Architecture](./docs/plugins.md)** | Plugin lifecycle, custom plugin authoring, and integration patterns |
|
|
303
|
+
| **[Deduplication](./docs/deduplication.md)** | How deduplication works, hash config, optional TTL cleanup, limitations |
|
|
304
|
+
| **[Error Handling](./docs/errorhandling.md)** | Strategies for managing errors, including `throwOnHttpError` |
|
|
305
|
+
| **[Advanced Features](./docs/advanced.md)** | Per-request overrides, pending requests, circuit breakers, custom errors |
|
|
306
|
+
| **[Production Operations](./docs/production-operations.md)** | Pre-deploy checklist, alerting baseline, and incident playbook |
|
|
307
|
+
| **[Hooks & Transformation](./docs/hooks.md)** | Lifecycle hooks, authentication, logging, request/response transformation |
|
|
308
|
+
| **[Usage Examples](./docs/examples.md)** | Real-world patterns: REST clients, GraphQL, file uploads, microservices |
|
|
309
|
+
| **[Compatibility](./docs/compatibility.md)** | Browser/Node.js support, polyfills, framework integration |
|
|
295
310
|
|
|
296
311
|
## Environment Requirements
|
|
297
312
|
|
|
@@ -345,6 +360,8 @@ See [deduplication.md](./docs/deduplication.md) for full details.
|
|
|
345
360
|
| Plugin Architecture | ❌ Not available | ⚠️ Interceptors only | ⚠️ Hook-based extensions | ✅ First-class plugin pipeline (optional built-in + custom plugins) |
|
|
346
361
|
| Circuit Breaker | ❌ Not available | ❌ Manual or plugins | ❌ Manual | ✅ Automatic failure protection |
|
|
347
362
|
| Deduplication | ❌ Not available | ❌ Not available | ❌ Not available | ✅ Optional via `dedupePlugin()` |
|
|
363
|
+
| Bulkheading | ❌ Not available | ❌ Not available | ❌ Not available | ✅ Optional via `bulkheadPlugin()` |
|
|
364
|
+
| Request Hedging | ❌ Not available | ❌ Not available | ❌ Not available | ✅ Optional via `hedgePlugin()` (tail latency reduction) |
|
|
348
365
|
| Request Monitoring | ❌ Manual tracking | ❌ Manual tracking | ❌ Manual tracking | ✅ Built-in pending requests |
|
|
349
366
|
| Error Types | ❌ Generic errors | ⚠️ HTTP errors only | ✅ Specific error classes | ✅ Specific error classes |
|
|
350
367
|
| TypeScript | ⚠️ Basic types | ⚠️ Basic types | ✅ Strong types | ✅ Full type safety |
|
|
@@ -354,7 +371,7 @@ See [deduplication.md](./docs/deduplication.md) for full details.
|
|
|
354
371
|
| Download Progress | ❌ Manual ReadableStream | ❌ Manual | ✅ `onDownloadProgress` callback | ✅ Optional via `downloadProgressPlugin()` |
|
|
355
372
|
| Custom Fetch Support | ❌ No (global only) | ❌ No | ❌ No | ✅ Yes (wrap any fetch-compatible implementation, including framework or custom fetch) |
|
|
356
373
|
|
|
357
|
-
Note: built-in plugins in ffetch are opt-in. Use `dedupePlugin()` for deduplication, `circuitPlugin()` for circuit breaking, `requestShortcutsPlugin()` for client HTTP method shortcuts, `responseShortcutsPlugin()` for request-promise parsing shortcuts, and `downloadProgressPlugin()` for streaming download progress. Bundle size: ~3kb core, additional optional plugin imports are tree-shakeable.
|
|
374
|
+
Note: built-in plugins in ffetch are opt-in. Use `bulkheadPlugin()` for concurrency isolation and backpressure, `dedupePlugin()` for deduplication, `circuitPlugin()` for circuit breaking, `hedgePlugin()` for tail-latency racing, `requestShortcutsPlugin()` for client HTTP method shortcuts, `responseShortcutsPlugin()` for request-promise parsing shortcuts, and `downloadProgressPlugin()` for streaming download progress. Bundle size: ~3kb core, additional optional plugin imports are tree-shakeable.
|
|
358
375
|
|
|
359
376
|
### Try ffetch in Action
|
|
360
377
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var s=class extends Error{constructor(e,n,t){super(n),this.name=e,t!==void 0&&(this.cause=t)}},o=class extends s{constructor(e="Request timed out",n){super("TimeoutError",e,n)}},u=class extends s{constructor(e="Circuit is open",n){super("CircuitOpenError",e,n)}},c=class extends s{constructor(e="Bulkhead queue is full",n){super("BulkheadFullError",e,n)}},p=class extends s{constructor(e="Request was aborted",n){super("AbortError",e,n)}},d=class extends s{constructor(e="Retry limit reached",n){super("RetryLimitError",e,n)}},x=class extends s{constructor(e="Network error occurred",n){super("NetworkError",e,n)}},i=class extends s{constructor(e="HTTP error occurred",n){super("HttpError",e,n)}};export{o as a,u as b,c,p as d,d as e,x as f,i as g};
|
|
2
|
+
//# sourceMappingURL=chunk-X64PXWPN.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error.ts"],"sourcesContent":["// Base error class to reduce duplication\nclass BaseError extends Error {\n public cause?: unknown\n constructor(name: string, message: string, cause?: unknown) {\n super(message)\n this.name = name\n if (cause !== undefined) this.cause = cause\n }\n}\n\nexport class TimeoutError extends BaseError {\n constructor(message = 'Request timed out', cause?: unknown) {\n super('TimeoutError', message, cause)\n }\n}\n\nexport class CircuitOpenError extends BaseError {\n constructor(message = 'Circuit is open', cause?: unknown) {\n super('CircuitOpenError', message, cause)\n }\n}\n\nexport class BulkheadFullError extends BaseError {\n constructor(message = 'Bulkhead queue is full', cause?: unknown) {\n super('BulkheadFullError', message, cause)\n }\n}\n\nexport class AbortError extends BaseError {\n constructor(message = 'Request was aborted', cause?: unknown) {\n super('AbortError', message, cause)\n }\n}\n\nexport class RetryLimitError extends BaseError {\n constructor(message = 'Retry limit reached', cause?: unknown) {\n super('RetryLimitError', message, cause)\n }\n}\n\nexport class NetworkError extends BaseError {\n constructor(message = 'Network error occurred', cause?: unknown) {\n super('NetworkError', message, cause)\n }\n}\n\nexport class HttpError extends BaseError {\n constructor(message = 'HTTP error occurred', cause?: unknown) {\n super('HttpError', message, cause)\n }\n}\n"],"mappings":"AACA,IAAMA,EAAN,cAAwB,KAAM,CAE5B,YAAYC,EAAcC,EAAiBC,EAAiB,CAC1D,MAAMD,CAAO,EACb,KAAK,KAAOD,EACRE,IAAU,SAAW,KAAK,MAAQA,EACxC,CACF,EAEaC,EAAN,cAA2BJ,CAAU,CAC1C,YAAYE,EAAU,oBAAqBC,EAAiB,CAC1D,MAAM,eAAgBD,EAASC,CAAK,CACtC,CACF,EAEaE,EAAN,cAA+BL,CAAU,CAC9C,YAAYE,EAAU,kBAAmBC,EAAiB,CACxD,MAAM,mBAAoBD,EAASC,CAAK,CAC1C,CACF,EAEaG,EAAN,cAAgCN,CAAU,CAC/C,YAAYE,EAAU,yBAA0BC,EAAiB,CAC/D,MAAM,oBAAqBD,EAASC,CAAK,CAC3C,CACF,EAEaI,EAAN,cAAyBP,CAAU,CACxC,YAAYE,EAAU,sBAAuBC,EAAiB,CAC5D,MAAM,aAAcD,EAASC,CAAK,CACpC,CACF,EAEaK,EAAN,cAA8BR,CAAU,CAC7C,YAAYE,EAAU,sBAAuBC,EAAiB,CAC5D,MAAM,kBAAmBD,EAASC,CAAK,CACzC,CACF,EAEaM,EAAN,cAA2BT,CAAU,CAC1C,YAAYE,EAAU,yBAA0BC,EAAiB,CAC/D,MAAM,eAAgBD,EAASC,CAAK,CACtC,CACF,EAEaO,EAAN,cAAwBV,CAAU,CACvC,YAAYE,EAAU,sBAAuBC,EAAiB,CAC5D,MAAM,YAAaD,EAASC,CAAK,CACnC,CACF","names":["BaseError","name","message","cause","TimeoutError","CircuitOpenError","BulkheadFullError","AbortError","RetryLimitError","NetworkError","HttpError"]}
|
|
@@ -16,6 +16,11 @@ var CircuitOpenError = class extends BaseError {
|
|
|
16
16
|
super("CircuitOpenError", message, cause);
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
+
var BulkheadFullError = class extends BaseError {
|
|
20
|
+
constructor(message = "Bulkhead queue is full", cause) {
|
|
21
|
+
super("BulkheadFullError", message, cause);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
19
24
|
var AbortError = class extends BaseError {
|
|
20
25
|
constructor(message = "Request was aborted", cause) {
|
|
21
26
|
super("AbortError", message, cause);
|
|
@@ -40,9 +45,10 @@ var HttpError = class extends BaseError {
|
|
|
40
45
|
export {
|
|
41
46
|
TimeoutError,
|
|
42
47
|
CircuitOpenError,
|
|
48
|
+
BulkheadFullError,
|
|
43
49
|
AbortError,
|
|
44
50
|
RetryLimitError,
|
|
45
51
|
NetworkError,
|
|
46
52
|
HttpError
|
|
47
53
|
};
|
|
48
|
-
//# sourceMappingURL=chunk-
|
|
54
|
+
//# sourceMappingURL=chunk-ZIJ2DZYZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error.ts"],"sourcesContent":["// Base error class to reduce duplication\nclass BaseError extends Error {\n public cause?: unknown\n constructor(name: string, message: string, cause?: unknown) {\n super(message)\n this.name = name\n if (cause !== undefined) this.cause = cause\n }\n}\n\nexport class TimeoutError extends BaseError {\n constructor(message = 'Request timed out', cause?: unknown) {\n super('TimeoutError', message, cause)\n }\n}\n\nexport class CircuitOpenError extends BaseError {\n constructor(message = 'Circuit is open', cause?: unknown) {\n super('CircuitOpenError', message, cause)\n }\n}\n\nexport class BulkheadFullError extends BaseError {\n constructor(message = 'Bulkhead queue is full', cause?: unknown) {\n super('BulkheadFullError', message, cause)\n }\n}\n\nexport class AbortError extends BaseError {\n constructor(message = 'Request was aborted', cause?: unknown) {\n super('AbortError', message, cause)\n }\n}\n\nexport class RetryLimitError extends BaseError {\n constructor(message = 'Retry limit reached', cause?: unknown) {\n super('RetryLimitError', message, cause)\n }\n}\n\nexport class NetworkError extends BaseError {\n constructor(message = 'Network error occurred', cause?: unknown) {\n super('NetworkError', message, cause)\n }\n}\n\nexport class HttpError extends BaseError {\n constructor(message = 'HTTP error occurred', cause?: unknown) {\n super('HttpError', message, cause)\n }\n}\n"],"mappings":";AACA,IAAM,YAAN,cAAwB,MAAM;AAAA,EAE5B,YAAY,MAAc,SAAiB,OAAiB;AAC1D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,QAAI,UAAU,OAAW,MAAK,QAAQ;AAAA,EACxC;AACF;AAEO,IAAM,eAAN,cAA2B,UAAU;AAAA,EAC1C,YAAY,UAAU,qBAAqB,OAAiB;AAC1D,UAAM,gBAAgB,SAAS,KAAK;AAAA,EACtC;AACF;AAEO,IAAM,mBAAN,cAA+B,UAAU;AAAA,EAC9C,YAAY,UAAU,mBAAmB,OAAiB;AACxD,UAAM,oBAAoB,SAAS,KAAK;AAAA,EAC1C;AACF;AAEO,IAAM,oBAAN,cAAgC,UAAU;AAAA,EAC/C,YAAY,UAAU,0BAA0B,OAAiB;AAC/D,UAAM,qBAAqB,SAAS,KAAK;AAAA,EAC3C;AACF;AAEO,IAAM,aAAN,cAAyB,UAAU;AAAA,EACxC,YAAY,UAAU,uBAAuB,OAAiB;AAC5D,UAAM,cAAc,SAAS,KAAK;AAAA,EACpC;AACF;AAEO,IAAM,kBAAN,cAA8B,UAAU;AAAA,EAC7C,YAAY,UAAU,uBAAuB,OAAiB;AAC5D,UAAM,mBAAmB,SAAS,KAAK;AAAA,EACzC;AACF;AAEO,IAAM,eAAN,cAA2B,UAAU;AAAA,EAC1C,YAAY,UAAU,0BAA0B,OAAiB;AAC/D,UAAM,gBAAgB,SAAS,KAAK;AAAA,EACtC;AACF;AAEO,IAAM,YAAN,cAAwB,UAAU;AAAA,EACvC,YAAY,UAAU,uBAAuB,OAAiB;AAC5D,UAAM,aAAa,SAAS,KAAK;AAAA,EACnC;AACF;","names":[]}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AbortError,
|
|
3
|
+
BulkheadFullError,
|
|
3
4
|
CircuitOpenError,
|
|
4
5
|
HttpError,
|
|
5
6
|
NetworkError,
|
|
6
7
|
RetryLimitError,
|
|
7
8
|
TimeoutError
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZIJ2DZYZ.js";
|
|
9
10
|
export {
|
|
10
11
|
AbortError,
|
|
12
|
+
BulkheadFullError,
|
|
11
13
|
CircuitOpenError,
|
|
12
14
|
HttpError,
|
|
13
15
|
NetworkError,
|
|
14
16
|
RetryLimitError,
|
|
15
17
|
TimeoutError
|
|
16
18
|
};
|
|
17
|
-
//# sourceMappingURL=error-
|
|
19
|
+
//# sourceMappingURL=error-H4GGJSCM.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -24,13 +24,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
24
24
|
var error_exports = {};
|
|
25
25
|
__export(error_exports, {
|
|
26
26
|
AbortError: () => AbortError,
|
|
27
|
+
BulkheadFullError: () => BulkheadFullError,
|
|
27
28
|
CircuitOpenError: () => CircuitOpenError,
|
|
28
29
|
HttpError: () => HttpError,
|
|
29
30
|
NetworkError: () => NetworkError,
|
|
30
31
|
RetryLimitError: () => RetryLimitError,
|
|
31
32
|
TimeoutError: () => TimeoutError
|
|
32
33
|
});
|
|
33
|
-
var BaseError, TimeoutError, CircuitOpenError, AbortError, RetryLimitError, NetworkError, HttpError;
|
|
34
|
+
var BaseError, TimeoutError, CircuitOpenError, BulkheadFullError, AbortError, RetryLimitError, NetworkError, HttpError;
|
|
34
35
|
var init_error = __esm({
|
|
35
36
|
"src/error.ts"() {
|
|
36
37
|
"use strict";
|
|
@@ -51,6 +52,11 @@ var init_error = __esm({
|
|
|
51
52
|
super("CircuitOpenError", message, cause);
|
|
52
53
|
}
|
|
53
54
|
};
|
|
55
|
+
BulkheadFullError = class extends BaseError {
|
|
56
|
+
constructor(message = "Bulkhead queue is full", cause) {
|
|
57
|
+
super("BulkheadFullError", message, cause);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
54
60
|
AbortError = class extends BaseError {
|
|
55
61
|
constructor(message = "Request was aborted", cause) {
|
|
56
62
|
super("AbortError", message, cause);
|
|
@@ -78,6 +84,7 @@ var init_error = __esm({
|
|
|
78
84
|
var index_exports = {};
|
|
79
85
|
__export(index_exports, {
|
|
80
86
|
AbortError: () => AbortError,
|
|
87
|
+
BulkheadFullError: () => BulkheadFullError,
|
|
81
88
|
CircuitOpenError: () => CircuitOpenError,
|
|
82
89
|
HttpError: () => HttpError,
|
|
83
90
|
NetworkError: () => NetworkError,
|
|
@@ -287,18 +294,19 @@ function createClient(opts = {}) {
|
|
|
287
294
|
controller = new AbortController();
|
|
288
295
|
}
|
|
289
296
|
pluginContext.metadata.signals.combined = combinedSignal;
|
|
290
|
-
const retryWithHooks = async () => {
|
|
297
|
+
const retryWithHooks = async (dispatchCtx, dispatchSignal) => {
|
|
298
|
+
const requestForAttempt = dispatchCtx.request;
|
|
291
299
|
let attempt = 0;
|
|
292
300
|
const shouldRetryWithHook = (ctx) => {
|
|
293
301
|
attempt = ctx.attempt;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
302
|
+
dispatchCtx.metadata.retry.attempt = attempt;
|
|
303
|
+
dispatchCtx.metadata.retry.lastError = ctx.error;
|
|
304
|
+
dispatchCtx.metadata.retry.lastResponse = ctx.response;
|
|
297
305
|
const retrying = effectiveShouldRetry(ctx);
|
|
298
|
-
|
|
306
|
+
dispatchCtx.metadata.retry.shouldRetryResult = retrying;
|
|
299
307
|
if (retrying && attempt <= effectiveRetries) {
|
|
300
308
|
effectiveHooks.onRetry?.(
|
|
301
|
-
|
|
309
|
+
requestForAttempt,
|
|
302
310
|
attempt - 1,
|
|
303
311
|
ctx.error,
|
|
304
312
|
ctx.response
|
|
@@ -311,21 +319,21 @@ function createClient(opts = {}) {
|
|
|
311
319
|
let res = await retry(
|
|
312
320
|
async () => {
|
|
313
321
|
if (userSignal?.aborted) {
|
|
314
|
-
effectiveHooks.onAbort?.(
|
|
322
|
+
effectiveHooks.onAbort?.(requestForAttempt);
|
|
315
323
|
throw new AbortError("Request was aborted by user");
|
|
316
324
|
}
|
|
317
325
|
if (timeoutSignal?.aborted) {
|
|
318
|
-
effectiveHooks.onTimeout?.(
|
|
326
|
+
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
319
327
|
throw new TimeoutError("signal timed out");
|
|
320
328
|
}
|
|
321
|
-
if (typeof
|
|
322
|
-
|
|
323
|
-
} else if (
|
|
329
|
+
if (typeof dispatchSignal?.throwIfAborted === "function") {
|
|
330
|
+
dispatchSignal.throwIfAborted();
|
|
331
|
+
} else if (dispatchSignal?.aborted) {
|
|
324
332
|
if (userSignal?.aborted) {
|
|
325
|
-
effectiveHooks.onAbort?.(
|
|
333
|
+
effectiveHooks.onAbort?.(requestForAttempt);
|
|
326
334
|
throw new AbortError("Request was aborted by user");
|
|
327
335
|
} else if (timeoutSignal?.aborted) {
|
|
328
|
-
effectiveHooks.onTimeout?.(
|
|
336
|
+
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
329
337
|
throw new TimeoutError("signal timed out");
|
|
330
338
|
} else {
|
|
331
339
|
throw new AbortError(
|
|
@@ -334,23 +342,23 @@ function createClient(opts = {}) {
|
|
|
334
342
|
);
|
|
335
343
|
}
|
|
336
344
|
}
|
|
337
|
-
const reqWithSignal = new Request(
|
|
338
|
-
signal:
|
|
345
|
+
const reqWithSignal = new Request(requestForAttempt, {
|
|
346
|
+
signal: dispatchSignal
|
|
339
347
|
});
|
|
340
348
|
try {
|
|
341
349
|
const handler = init.fetchHandler ?? fetchHandler ?? fetch;
|
|
342
350
|
const response = await handler(reqWithSignal);
|
|
343
351
|
lastResponse = response;
|
|
344
|
-
|
|
352
|
+
dispatchCtx.metadata.retry.lastResponse = response;
|
|
345
353
|
return response;
|
|
346
354
|
} catch (err) {
|
|
347
|
-
|
|
355
|
+
dispatchCtx.metadata.retry.lastError = err;
|
|
348
356
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
349
357
|
if (timeoutSignal?.aborted && (!userSignal || !userSignal.aborted)) {
|
|
350
|
-
effectiveHooks.onTimeout?.(
|
|
358
|
+
effectiveHooks.onTimeout?.(requestForAttempt);
|
|
351
359
|
throw new TimeoutError("signal timed out", err);
|
|
352
360
|
} else if (userSignal?.aborted) {
|
|
353
|
-
effectiveHooks.onAbort?.(
|
|
361
|
+
effectiveHooks.onAbort?.(requestForAttempt);
|
|
354
362
|
throw new AbortError("Request was aborted by user");
|
|
355
363
|
} else {
|
|
356
364
|
throw new AbortError(
|
|
@@ -369,14 +377,14 @@ function createClient(opts = {}) {
|
|
|
369
377
|
effectiveRetries,
|
|
370
378
|
effectiveRetryDelay,
|
|
371
379
|
shouldRetryWithHook,
|
|
372
|
-
|
|
373
|
-
|
|
380
|
+
requestForAttempt,
|
|
381
|
+
dispatchSignal
|
|
374
382
|
);
|
|
375
383
|
if (effectiveHooks.transformResponse) {
|
|
376
|
-
res = await effectiveHooks.transformResponse(res,
|
|
384
|
+
res = await effectiveHooks.transformResponse(res, requestForAttempt);
|
|
377
385
|
}
|
|
378
|
-
await effectiveHooks.after?.(
|
|
379
|
-
await effectiveHooks.onComplete?.(
|
|
386
|
+
await effectiveHooks.after?.(requestForAttempt, res);
|
|
387
|
+
await effectiveHooks.onComplete?.(requestForAttempt, res, void 0);
|
|
380
388
|
if (effectiveThrowOnHttpError && (res.status >= 400 && res.status < 500 && res.status !== 429 || res.status >= 500 || res.status === 429)) {
|
|
381
389
|
const { HttpError: HttpError2 } = await Promise.resolve().then(() => (init_error(), error_exports));
|
|
382
390
|
throw new HttpError2(
|
|
@@ -386,7 +394,7 @@ function createClient(opts = {}) {
|
|
|
386
394
|
}
|
|
387
395
|
return res;
|
|
388
396
|
} catch (err) {
|
|
389
|
-
|
|
397
|
+
dispatchCtx.metadata.retry.lastError = err;
|
|
390
398
|
if (lastResponse) {
|
|
391
399
|
const resp = lastResponse;
|
|
392
400
|
if (effectiveThrowOnHttpError && (resp.status >= 400 && resp.status < 500 && resp.status !== 429 || resp.status >= 500 || resp.status === 429)) {
|
|
@@ -399,32 +407,39 @@ function createClient(opts = {}) {
|
|
|
399
407
|
return resp;
|
|
400
408
|
}
|
|
401
409
|
if (err instanceof TimeoutError) {
|
|
402
|
-
await effectiveHooks.onTimeout?.(
|
|
403
|
-
await effectiveHooks.onError?.(
|
|
404
|
-
await effectiveHooks.onComplete?.(
|
|
410
|
+
await effectiveHooks.onTimeout?.(requestForAttempt);
|
|
411
|
+
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
412
|
+
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
405
413
|
throw err;
|
|
406
414
|
}
|
|
407
415
|
if (err instanceof AbortError) {
|
|
408
|
-
await effectiveHooks.onAbort?.(
|
|
409
|
-
await effectiveHooks.onError?.(
|
|
410
|
-
await effectiveHooks.onComplete?.(
|
|
416
|
+
await effectiveHooks.onAbort?.(requestForAttempt);
|
|
417
|
+
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
418
|
+
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
411
419
|
throw err;
|
|
412
420
|
}
|
|
413
421
|
if (err instanceof NetworkError) {
|
|
414
|
-
await effectiveHooks.onError?.(
|
|
415
|
-
await effectiveHooks.onComplete?.(
|
|
422
|
+
await effectiveHooks.onError?.(requestForAttempt, err);
|
|
423
|
+
await effectiveHooks.onComplete?.(requestForAttempt, void 0, err);
|
|
416
424
|
throw err;
|
|
417
425
|
}
|
|
418
426
|
const retryErr = new RetryLimitError(
|
|
419
427
|
typeof err === "object" && err && "message" in err && typeof err.message === "string" ? err.message : "Retry limit reached",
|
|
420
428
|
err
|
|
421
429
|
);
|
|
422
|
-
await effectiveHooks.onError?.(
|
|
423
|
-
await effectiveHooks.onComplete?.(
|
|
430
|
+
await effectiveHooks.onError?.(requestForAttempt, retryErr);
|
|
431
|
+
await effectiveHooks.onComplete?.(
|
|
432
|
+
requestForAttempt,
|
|
433
|
+
void 0,
|
|
434
|
+
retryErr
|
|
435
|
+
);
|
|
424
436
|
throw retryErr;
|
|
425
437
|
}
|
|
426
438
|
};
|
|
427
|
-
const baseDispatch = async () =>
|
|
439
|
+
const baseDispatch = async (ctx) => {
|
|
440
|
+
const dispatchSignal = ctx === pluginContext ? combinedSignal : ctx.request.signal;
|
|
441
|
+
return retryWithHooks(ctx, dispatchSignal);
|
|
442
|
+
};
|
|
428
443
|
let dispatch = baseDispatch;
|
|
429
444
|
for (let i = plugins.length - 1; i >= 0; i--) {
|
|
430
445
|
const plugin = plugins[i];
|
|
@@ -489,6 +504,7 @@ init_error();
|
|
|
489
504
|
// Annotate the CommonJS export names for ESM import in node:
|
|
490
505
|
0 && (module.exports = {
|
|
491
506
|
AbortError,
|
|
507
|
+
BulkheadFullError,
|
|
492
508
|
CircuitOpenError,
|
|
493
509
|
HttpError,
|
|
494
510
|
NetworkError,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/error.ts","../src/index.ts","../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["// Base error class to reduce duplication\nclass BaseError extends Error {\n public cause?: unknown\n constructor(name: string, message: string, cause?: unknown) {\n super(message)\n this.name = name\n if (cause !== undefined) this.cause = cause\n }\n}\n\nexport class TimeoutError extends BaseError {\n constructor(message = 'Request timed out', cause?: unknown) {\n super('TimeoutError', message, cause)\n }\n}\n\nexport class CircuitOpenError extends BaseError {\n constructor(message = 'Circuit is open', cause?: unknown) {\n super('CircuitOpenError', message, cause)\n }\n}\n\nexport class AbortError extends BaseError {\n constructor(message = 'Request was aborted', cause?: unknown) {\n super('AbortError', message, cause)\n }\n}\n\nexport class RetryLimitError extends BaseError {\n constructor(message = 'Retry limit reached', cause?: unknown) {\n super('RetryLimitError', message, cause)\n }\n}\n\nexport class NetworkError extends BaseError {\n constructor(message = 'Network error occurred', cause?: unknown) {\n super('NetworkError', message, cause)\n }\n}\n\nexport class HttpError extends BaseError {\n constructor(message = 'HTTP error occurred', cause?: unknown) {\n super('HttpError', message, cause)\n }\n}\n","export type { FFetch, FFetchOptions } from './types'\r\nexport type { Hooks } from './hooks'\r\nexport type {\r\n ClientPlugin,\r\n PluginRequestContext,\r\n PluginDispatch,\r\n PluginSetupContext,\r\n} from './plugins'\r\n\r\nexport { createClient } from './client'\r\n\r\nexport {\r\n TimeoutError,\r\n CircuitOpenError,\r\n AbortError,\r\n RetryLimitError,\r\n NetworkError,\r\n HttpError,\r\n} from './error'\r\n","import type { RetryContext } from './types.js'\n\nexport type RetryDelay = number | ((ctx: RetryContext) => number)\n\nexport const defaultDelay: RetryDelay = (ctx) => {\n const retryAfter = ctx.response?.headers.get('Retry-After')\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10)\n if (!isNaN(seconds)) return seconds * 1000\n const date = Date.parse(retryAfter)\n if (!isNaN(date)) return Math.max(0, date - Date.now())\n }\n return 2 ** ctx.attempt * 200 + Math.random() * 100\n}\n\nfunction waitForRetryDelay(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n if (!signal) {\n setTimeout(resolve, ms)\n return\n }\n\n if (signal.aborted) {\n resolve()\n return\n }\n\n const onAbort = () => {\n clearTimeout(timer)\n resolve()\n }\n\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport async function retry(\n fn: () => Promise<Response>,\n retries: number,\n delay: RetryDelay,\n shouldRetry: (ctx: RetryContext) => boolean = () => true,\n request: Request,\n signal?: AbortSignal\n): Promise<Response> {\n let lastErr: unknown\n let lastRes: Response | undefined\n\n for (let i = 0; i <= retries; i++) {\n const ctx: RetryContext = {\n attempt: i + 1,\n request,\n response: lastRes,\n error: lastErr,\n }\n try {\n lastRes = await fn()\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && shouldRetry(ctx)) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\n } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !shouldRetry(ctx)) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n }\n }\n throw lastErr\n}\n","import { AbortError, CircuitOpenError, TimeoutError } from './error.js'\nimport type { RetryContext } from './types.js'\n\nexport function shouldRetry(ctx: RetryContext): boolean {\n const { error, response } = ctx\n if (\n error instanceof AbortError ||\n error instanceof CircuitOpenError ||\n error instanceof TimeoutError\n )\n return false\n if (!response) return true // network error\n return response.status >= 500 || response.status === 429\n}\n","import type {\r\n FFetchOptions,\r\n FFetch,\r\n FFetchRequestInit,\r\n PendingRequest,\r\n} from './types.js'\r\nimport { retry, defaultDelay } from './retry.js'\r\nimport { shouldRetry as defaultShouldRetry } from './should-retry.js'\r\nimport {\r\n type PluginDispatch,\r\n type PluginRequestContext,\r\n type PluginExtensions,\r\n type PluginRequestPromiseExtensions,\r\n type ClientPlugin,\r\n type PluginExtensionBase,\r\n type PluginRequestPromiseExtensionBase,\r\n} from './plugins.js'\r\nimport {\r\n TimeoutError,\r\n AbortError,\r\n RetryLimitError,\r\n NetworkError,\r\n} from './error.js'\r\n\r\nexport function createClient<\r\n TPlugins extends readonly ClientPlugin<\r\n PluginExtensionBase,\r\n PluginRequestPromiseExtensionBase\r\n >[] = readonly ClientPlugin<\r\n PluginExtensionBase,\r\n PluginRequestPromiseExtensionBase\r\n >[],\r\n>(\r\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\r\n): FFetch<\r\n PluginExtensions<TPlugins>,\r\n PluginRequestPromiseExtensions<TPlugins>\r\n> {\r\n const {\r\n timeout: clientDefaultTimeout = 5_000,\r\n retries: clientDefaultRetries = 0,\r\n retryDelay: clientDefaultRetryDelay = defaultDelay,\r\n shouldRetry: clientDefaultShouldRetry = defaultShouldRetry,\r\n hooks: clientDefaultHooks = {},\r\n fetchHandler,\r\n plugins: inputPlugins = [] as unknown as TPlugins,\r\n } = opts\r\n\r\n const extensionDescriptors: PropertyDescriptorMap = Object.create(null)\r\n\r\n const plugins = inputPlugins\r\n .map((plugin, index) => ({ plugin, index }))\r\n .sort((a, b) => {\r\n const aOrder = a.plugin.order ?? 0\r\n const bOrder = b.plugin.order ?? 0\r\n if (aOrder !== bOrder) return aOrder - bOrder\r\n return a.index - b.index\r\n })\r\n .map((entry) => entry.plugin)\r\n\r\n for (const plugin of plugins) {\r\n plugin.setup?.({\r\n defineExtension: (key, descriptor) => {\r\n const propertyKey = key as PropertyKey\r\n if (propertyKey in extensionDescriptors) {\r\n throw new Error(\r\n `Plugin extension collision for property \"${String(propertyKey)}\"`\r\n )\r\n }\r\n if ('get' in descriptor) {\r\n extensionDescriptors[propertyKey] = {\r\n get: descriptor.get,\r\n enumerable: descriptor.enumerable ?? true,\r\n configurable: false,\r\n }\r\n return\r\n }\r\n extensionDescriptors[propertyKey] = {\r\n value: descriptor.value,\r\n writable: false,\r\n enumerable: descriptor.enumerable ?? true,\r\n configurable: false,\r\n }\r\n },\r\n })\r\n }\r\n\r\n const pendingRequests: PendingRequest[] = []\r\n\r\n // Helper to abort all pending requests\r\n function abortAll() {\r\n for (const entry of pendingRequests) {\r\n entry.controller?.abort()\r\n }\r\n }\r\n\r\n const client = (input: RequestInfo | URL, init: FFetchRequestInit = {}) => {\r\n const execute = async () => {\r\n let request = new Request(input, init)\r\n\r\n // Merge hooks: per-request hooks override client hooks, but fallback to client hooks\r\n const effectiveHooks = { ...clientDefaultHooks, ...(init.hooks || {}) }\r\n if (effectiveHooks.transformRequest) {\r\n request = await effectiveHooks.transformRequest(request)\r\n }\r\n await effectiveHooks.before?.(request)\r\n\r\n // Determine retry config (per-request overrides client default)\r\n const effectiveRetries = init.retries ?? clientDefaultRetries\r\n const effectiveRetryDelay =\r\n typeof init.retryDelay !== 'undefined'\r\n ? init.retryDelay\r\n : clientDefaultRetryDelay\r\n const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry\r\n\r\n // AbortSignal.timeout/any logic\r\n const effectiveTimeout = init.timeout ?? clientDefaultTimeout\r\n const userSignal = init.signal\r\n const transformedSignal = request.signal\r\n\r\n const pluginContext: PluginRequestContext = {\r\n request,\r\n init,\r\n state: Object.create(null),\r\n metadata: {\r\n startedAt: Date.now(),\r\n timeoutMs: effectiveTimeout,\r\n signals: {\r\n user:\r\n userSignal === undefined || userSignal === null\r\n ? undefined\r\n : userSignal,\r\n transformed: transformedSignal,\r\n },\r\n retry: {\r\n configuredRetries: effectiveRetries,\r\n configuredDelay: effectiveRetryDelay,\r\n attempt: 0,\r\n },\r\n },\r\n }\r\n\r\n for (const plugin of plugins) {\r\n await plugin.preRequest?.(pluginContext)\r\n }\r\n\r\n // Determine throwOnHttpError (per-request overrides client default)\r\n const effectiveThrowOnHttpError =\r\n typeof init.throwOnHttpError !== 'undefined'\r\n ? init.throwOnHttpError\r\n : (opts.throwOnHttpError ?? false)\r\n\r\n // Create timeout signal (manual implementation if AbortSignal.timeout not available)\r\n function createTimeoutSignal(timeout: number): AbortSignal {\r\n if (typeof AbortSignal?.timeout === 'function') {\r\n return AbortSignal.timeout(timeout)\r\n }\r\n const controller = new AbortController()\r\n const timeoutId = setTimeout(() => controller.abort(), timeout)\r\n controller.signal.addEventListener(\r\n 'abort',\r\n () => clearTimeout(timeoutId),\r\n { once: true }\r\n )\r\n return controller.signal\r\n }\r\n\r\n let timeoutSignal: AbortSignal | undefined = undefined\r\n let combinedSignal: AbortSignal | undefined = undefined\r\n let controller: AbortController | undefined = undefined\r\n\r\n if (effectiveTimeout > 0) {\r\n timeoutSignal = createTimeoutSignal(effectiveTimeout)\r\n pluginContext.metadata.signals.timeout = timeoutSignal\r\n }\r\n\r\n const signals: AbortSignal[] = []\r\n if (userSignal) signals.push(userSignal)\r\n if (transformedSignal && transformedSignal !== userSignal) {\r\n signals.push(transformedSignal)\r\n }\r\n if (timeoutSignal) signals.push(timeoutSignal)\r\n\r\n if (signals.length === 1) {\r\n combinedSignal = signals[0]\r\n controller = new AbortController()\r\n } else {\r\n if (typeof AbortSignal.any !== 'function') {\r\n throw new Error(\r\n 'AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.'\r\n )\r\n }\r\n combinedSignal = AbortSignal.any(signals)\r\n controller = new AbortController()\r\n }\r\n pluginContext.metadata.signals.combined = combinedSignal\r\n\r\n const retryWithHooks = async () => {\r\n let attempt = 0\r\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\r\n attempt = ctx.attempt\r\n pluginContext.metadata.retry.attempt = attempt\r\n pluginContext.metadata.retry.lastError = ctx.error\r\n pluginContext.metadata.retry.lastResponse = ctx.response\r\n const retrying = effectiveShouldRetry(ctx)\r\n pluginContext.metadata.retry.shouldRetryResult = retrying\r\n if (retrying && attempt <= effectiveRetries) {\r\n effectiveHooks.onRetry?.(\r\n request,\r\n attempt - 1,\r\n ctx.error,\r\n ctx.response\r\n )\r\n }\r\n return retrying\r\n }\r\n\r\n let lastResponse: Response | undefined = undefined\r\n try {\r\n let res = await retry(\r\n async () => {\r\n if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n }\r\n if (timeoutSignal?.aborted) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out')\r\n }\r\n if (typeof combinedSignal?.throwIfAborted === 'function') {\r\n combinedSignal.throwIfAborted()\r\n } else if (combinedSignal?.aborted) {\r\n if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n } else if (timeoutSignal?.aborted) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out')\r\n } else {\r\n throw new AbortError(\r\n 'Request was aborted',\r\n new DOMException('Aborted', 'AbortError')\r\n )\r\n }\r\n }\r\n const reqWithSignal = new Request(request, {\r\n signal: combinedSignal,\r\n })\r\n try {\r\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\r\n const response = await handler(reqWithSignal)\r\n lastResponse = response\r\n pluginContext.metadata.retry.lastResponse = response\r\n return response\r\n } catch (err) {\r\n pluginContext.metadata.retry.lastError = err\r\n if (err instanceof DOMException && err.name === 'AbortError') {\r\n if (\r\n timeoutSignal?.aborted &&\r\n (!userSignal || !userSignal.aborted)\r\n ) {\r\n effectiveHooks.onTimeout?.(request)\r\n throw new TimeoutError('signal timed out', err)\r\n } else if (userSignal?.aborted) {\r\n effectiveHooks.onAbort?.(request)\r\n throw new AbortError('Request was aborted by user')\r\n } else {\r\n throw new AbortError(\r\n 'Request was aborted',\r\n new DOMException('Aborted', 'AbortError')\r\n )\r\n }\r\n } else if (\r\n err instanceof TypeError &&\r\n /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(\r\n err.message\r\n )\r\n ) {\r\n throw new NetworkError(err.message, err)\r\n }\r\n throw err\r\n }\r\n },\r\n effectiveRetries,\r\n effectiveRetryDelay,\r\n shouldRetryWithHook,\r\n request,\r\n combinedSignal\r\n )\r\n if (effectiveHooks.transformResponse) {\r\n res = await effectiveHooks.transformResponse(res, request)\r\n }\r\n await effectiveHooks.after?.(request, res)\r\n await effectiveHooks.onComplete?.(request, res, undefined)\r\n if (\r\n effectiveThrowOnHttpError &&\r\n ((res.status >= 400 && res.status < 500 && res.status !== 429) ||\r\n res.status >= 500 ||\r\n res.status === 429)\r\n ) {\r\n const { HttpError } = await import('./error.js')\r\n throw new HttpError(\r\n `HTTP error: ${res.status} ${res.statusText}`,\r\n res\r\n )\r\n }\r\n return res\r\n } catch (err: unknown) {\r\n pluginContext.metadata.retry.lastError = err\r\n if (lastResponse) {\r\n const resp = lastResponse as Response\r\n if (\r\n effectiveThrowOnHttpError &&\r\n ((resp.status >= 400 &&\r\n resp.status < 500 &&\r\n resp.status !== 429) ||\r\n resp.status >= 500 ||\r\n resp.status === 429)\r\n ) {\r\n const { HttpError } = await import('./error.js')\r\n throw new HttpError(\r\n `HTTP error: ${resp.status} ${resp.statusText}`,\r\n resp\r\n )\r\n }\r\n return resp\r\n }\r\n if (err instanceof TimeoutError) {\r\n await effectiveHooks.onTimeout?.(request)\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n if (err instanceof AbortError) {\r\n await effectiveHooks.onAbort?.(request)\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n if (err instanceof NetworkError) {\r\n await effectiveHooks.onError?.(request, err)\r\n await effectiveHooks.onComplete?.(request, undefined, err)\r\n throw err\r\n }\r\n const retryErr = new RetryLimitError(\r\n typeof err === 'object' &&\r\n err &&\r\n 'message' in err &&\r\n typeof (err as { message?: unknown }).message === 'string'\r\n ? (err as { message: string }).message\r\n : 'Retry limit reached',\r\n err\r\n )\r\n await effectiveHooks.onError?.(request, retryErr)\r\n await effectiveHooks.onComplete?.(request, undefined, retryErr)\r\n throw retryErr\r\n }\r\n }\r\n\r\n const baseDispatch: PluginDispatch = async () => retryWithHooks()\r\n\r\n let dispatch = baseDispatch\r\n for (let i = plugins.length - 1; i >= 0; i--) {\r\n const plugin = plugins[i]\r\n if (plugin.wrapDispatch) {\r\n dispatch = plugin.wrapDispatch(dispatch)\r\n }\r\n }\r\n\r\n const actualPromise = dispatch(pluginContext)\r\n .then(async (response) => {\r\n for (const plugin of plugins) {\r\n await plugin.onSuccess?.(pluginContext, response)\r\n }\r\n return response\r\n })\r\n .catch(async (err: unknown) => {\r\n for (const plugin of plugins) {\r\n await plugin.onError?.(pluginContext, err)\r\n }\r\n throw err\r\n })\r\n\r\n const pendingEntry: PendingRequest = {\r\n promise: actualPromise,\r\n request,\r\n controller,\r\n }\r\n pendingRequests.push(pendingEntry)\r\n\r\n return actualPromise.finally(async () => {\r\n for (const plugin of plugins) {\r\n await plugin.onFinally?.(pluginContext)\r\n }\r\n\r\n const index = pendingRequests.indexOf(pendingEntry)\r\n if (index > -1) {\r\n pendingRequests.splice(index, 1)\r\n }\r\n })\r\n }\r\n\r\n let promise = execute() as Promise<Response>\r\n for (const plugin of plugins) {\r\n if (plugin.decoratePromise) {\r\n promise = plugin.decoratePromise(promise)\r\n }\r\n }\r\n return promise as Promise<Response> &\r\n PluginRequestPromiseExtensions<TPlugins>\r\n }\r\n\r\n Object.defineProperty(client, 'pendingRequests', {\r\n get() {\r\n return pendingRequests\r\n },\r\n enumerable: false,\r\n configurable: false,\r\n })\r\n\r\n Object.defineProperty(client, 'abortAll', {\r\n value: abortAll,\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n })\r\n\r\n Object.defineProperties(client, extensionDescriptors)\r\n\r\n return client as FFetch<\r\n PluginExtensions<TPlugins>,\r\n PluginRequestPromiseExtensions<TPlugins>\r\n >\r\n}\r\n"],"mappings":"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","names":["shouldRetry","controller","HttpError"]}
|
|
1
|
+
{"version":3,"sources":["../src/error.ts","../src/index.ts","../src/retry.ts","../src/should-retry.ts","../src/client.ts"],"sourcesContent":["// Base error class to reduce duplication\nclass BaseError extends Error {\n public cause?: unknown\n constructor(name: string, message: string, cause?: unknown) {\n super(message)\n this.name = name\n if (cause !== undefined) this.cause = cause\n }\n}\n\nexport class TimeoutError extends BaseError {\n constructor(message = 'Request timed out', cause?: unknown) {\n super('TimeoutError', message, cause)\n }\n}\n\nexport class CircuitOpenError extends BaseError {\n constructor(message = 'Circuit is open', cause?: unknown) {\n super('CircuitOpenError', message, cause)\n }\n}\n\nexport class BulkheadFullError extends BaseError {\n constructor(message = 'Bulkhead queue is full', cause?: unknown) {\n super('BulkheadFullError', message, cause)\n }\n}\n\nexport class AbortError extends BaseError {\n constructor(message = 'Request was aborted', cause?: unknown) {\n super('AbortError', message, cause)\n }\n}\n\nexport class RetryLimitError extends BaseError {\n constructor(message = 'Retry limit reached', cause?: unknown) {\n super('RetryLimitError', message, cause)\n }\n}\n\nexport class NetworkError extends BaseError {\n constructor(message = 'Network error occurred', cause?: unknown) {\n super('NetworkError', message, cause)\n }\n}\n\nexport class HttpError extends BaseError {\n constructor(message = 'HTTP error occurred', cause?: unknown) {\n super('HttpError', message, cause)\n }\n}\n","export type { FFetch, FFetchOptions } from './types'\nexport type { Hooks } from './hooks'\nexport type {\n ClientPlugin,\n PluginRequestContext,\n PluginDispatch,\n PluginSetupContext,\n} from './plugins'\n\nexport { createClient } from './client'\n\nexport {\n TimeoutError,\n CircuitOpenError,\n BulkheadFullError,\n AbortError,\n RetryLimitError,\n NetworkError,\n HttpError,\n} from './error'\n","import type { RetryContext } from './types.js'\n\nexport type RetryDelay = number | ((ctx: RetryContext) => number)\n\nexport const defaultDelay: RetryDelay = (ctx) => {\n const retryAfter = ctx.response?.headers.get('Retry-After')\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10)\n if (!isNaN(seconds)) return seconds * 1000\n const date = Date.parse(retryAfter)\n if (!isNaN(date)) return Math.max(0, date - Date.now())\n }\n return 2 ** ctx.attempt * 200 + Math.random() * 100\n}\n\nfunction waitForRetryDelay(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n if (!signal) {\n setTimeout(resolve, ms)\n return\n }\n\n if (signal.aborted) {\n resolve()\n return\n }\n\n const onAbort = () => {\n clearTimeout(timer)\n resolve()\n }\n\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport async function retry(\n fn: () => Promise<Response>,\n retries: number,\n delay: RetryDelay,\n shouldRetry: (ctx: RetryContext) => boolean = () => true,\n request: Request,\n signal?: AbortSignal\n): Promise<Response> {\n let lastErr: unknown\n let lastRes: Response | undefined\n\n for (let i = 0; i <= retries; i++) {\n const ctx: RetryContext = {\n attempt: i + 1,\n request,\n response: lastRes,\n error: lastErr,\n }\n try {\n lastRes = await fn()\n ctx.response = lastRes\n ctx.error = undefined\n if (i < retries && shouldRetry(ctx)) {\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n continue\n }\n return lastRes\n } catch (err) {\n lastErr = err\n ctx.error = err\n if (i === retries || !shouldRetry(ctx)) throw err\n const wait = typeof delay === 'function' ? delay(ctx) : delay\n await waitForRetryDelay(wait, signal)\n }\n }\n throw lastErr\n}\n","import { AbortError, CircuitOpenError, TimeoutError } from './error.js'\nimport type { RetryContext } from './types.js'\n\nexport function shouldRetry(ctx: RetryContext): boolean {\n const { error, response } = ctx\n if (\n error instanceof AbortError ||\n error instanceof CircuitOpenError ||\n error instanceof TimeoutError\n )\n return false\n if (!response) return true // network error\n return response.status >= 500 || response.status === 429\n}\n","import type {\n FFetchOptions,\n FFetch,\n FFetchRequestInit,\n PendingRequest,\n} from './types.js'\nimport { retry, defaultDelay } from './retry.js'\nimport { shouldRetry as defaultShouldRetry } from './should-retry.js'\nimport {\n type PluginDispatch,\n type PluginRequestContext,\n type PluginExtensions,\n type PluginRequestPromiseExtensions,\n type ClientPlugin,\n type PluginExtensionBase,\n type PluginRequestPromiseExtensionBase,\n} from './plugins.js'\nimport {\n TimeoutError,\n AbortError,\n RetryLimitError,\n NetworkError,\n} from './error.js'\n\nexport function createClient<\n TPlugins extends readonly ClientPlugin<\n PluginExtensionBase,\n PluginRequestPromiseExtensionBase\n >[] = readonly ClientPlugin<\n PluginExtensionBase,\n PluginRequestPromiseExtensionBase\n >[],\n>(\n opts: FFetchOptions<TPlugins> = {} as FFetchOptions<TPlugins>\n): FFetch<\n PluginExtensions<TPlugins>,\n PluginRequestPromiseExtensions<TPlugins>\n> {\n const {\n timeout: clientDefaultTimeout = 5_000,\n retries: clientDefaultRetries = 0,\n retryDelay: clientDefaultRetryDelay = defaultDelay,\n shouldRetry: clientDefaultShouldRetry = defaultShouldRetry,\n hooks: clientDefaultHooks = {},\n fetchHandler,\n plugins: inputPlugins = [] as unknown as TPlugins,\n } = opts\n\n const extensionDescriptors: PropertyDescriptorMap = Object.create(null)\n\n const plugins = inputPlugins\n .map((plugin, index) => ({ plugin, index }))\n .sort((a, b) => {\n const aOrder = a.plugin.order ?? 0\n const bOrder = b.plugin.order ?? 0\n if (aOrder !== bOrder) return aOrder - bOrder\n return a.index - b.index\n })\n .map((entry) => entry.plugin)\n\n for (const plugin of plugins) {\n plugin.setup?.({\n defineExtension: (key, descriptor) => {\n const propertyKey = key as PropertyKey\n if (propertyKey in extensionDescriptors) {\n throw new Error(\n `Plugin extension collision for property \"${String(propertyKey)}\"`\n )\n }\n if ('get' in descriptor) {\n extensionDescriptors[propertyKey] = {\n get: descriptor.get,\n enumerable: descriptor.enumerable ?? true,\n configurable: false,\n }\n return\n }\n extensionDescriptors[propertyKey] = {\n value: descriptor.value,\n writable: false,\n enumerable: descriptor.enumerable ?? true,\n configurable: false,\n }\n },\n })\n }\n\n const pendingRequests: PendingRequest[] = []\n\n // Helper to abort all pending requests\n function abortAll() {\n for (const entry of pendingRequests) {\n entry.controller?.abort()\n }\n }\n\n const client = (input: RequestInfo | URL, init: FFetchRequestInit = {}) => {\n const execute = async () => {\n let request = new Request(input, init)\n\n // Merge hooks: per-request hooks override client hooks, but fallback to client hooks\n const effectiveHooks = { ...clientDefaultHooks, ...(init.hooks || {}) }\n if (effectiveHooks.transformRequest) {\n request = await effectiveHooks.transformRequest(request)\n }\n await effectiveHooks.before?.(request)\n\n // Determine retry config (per-request overrides client default)\n const effectiveRetries = init.retries ?? clientDefaultRetries\n const effectiveRetryDelay =\n typeof init.retryDelay !== 'undefined'\n ? init.retryDelay\n : clientDefaultRetryDelay\n const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry\n\n // AbortSignal.timeout/any logic\n const effectiveTimeout = init.timeout ?? clientDefaultTimeout\n const userSignal = init.signal\n const transformedSignal = request.signal\n\n const pluginContext: PluginRequestContext = {\n request,\n init,\n state: Object.create(null),\n metadata: {\n startedAt: Date.now(),\n timeoutMs: effectiveTimeout,\n signals: {\n user:\n userSignal === undefined || userSignal === null\n ? undefined\n : userSignal,\n transformed: transformedSignal,\n },\n retry: {\n configuredRetries: effectiveRetries,\n configuredDelay: effectiveRetryDelay,\n attempt: 0,\n },\n },\n }\n\n for (const plugin of plugins) {\n await plugin.preRequest?.(pluginContext)\n }\n\n // Determine throwOnHttpError (per-request overrides client default)\n const effectiveThrowOnHttpError =\n typeof init.throwOnHttpError !== 'undefined'\n ? init.throwOnHttpError\n : (opts.throwOnHttpError ?? false)\n\n // Create timeout signal (manual implementation if AbortSignal.timeout not available)\n function createTimeoutSignal(timeout: number): AbortSignal {\n if (typeof AbortSignal?.timeout === 'function') {\n return AbortSignal.timeout(timeout)\n }\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n controller.signal.addEventListener(\n 'abort',\n () => clearTimeout(timeoutId),\n { once: true }\n )\n return controller.signal\n }\n\n let timeoutSignal: AbortSignal | undefined = undefined\n let combinedSignal: AbortSignal | undefined = undefined\n let controller: AbortController | undefined = undefined\n\n if (effectiveTimeout > 0) {\n timeoutSignal = createTimeoutSignal(effectiveTimeout)\n pluginContext.metadata.signals.timeout = timeoutSignal\n }\n\n const signals: AbortSignal[] = []\n if (userSignal) signals.push(userSignal)\n if (transformedSignal && transformedSignal !== userSignal) {\n signals.push(transformedSignal)\n }\n if (timeoutSignal) signals.push(timeoutSignal)\n\n if (signals.length === 1) {\n combinedSignal = signals[0]\n controller = new AbortController()\n } else {\n if (typeof AbortSignal.any !== 'function') {\n throw new Error(\n 'AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it.'\n )\n }\n combinedSignal = AbortSignal.any(signals)\n controller = new AbortController()\n }\n pluginContext.metadata.signals.combined = combinedSignal\n\n const retryWithHooks = async (\n dispatchCtx: PluginRequestContext,\n dispatchSignal: AbortSignal | undefined\n ) => {\n const requestForAttempt = dispatchCtx.request\n let attempt = 0\n const shouldRetryWithHook = (ctx: import('./types').RetryContext) => {\n attempt = ctx.attempt\n dispatchCtx.metadata.retry.attempt = attempt\n dispatchCtx.metadata.retry.lastError = ctx.error\n dispatchCtx.metadata.retry.lastResponse = ctx.response\n const retrying = effectiveShouldRetry(ctx)\n dispatchCtx.metadata.retry.shouldRetryResult = retrying\n if (retrying && attempt <= effectiveRetries) {\n effectiveHooks.onRetry?.(\n requestForAttempt,\n attempt - 1,\n ctx.error,\n ctx.response\n )\n }\n return retrying\n }\n\n let lastResponse: Response | undefined = undefined\n try {\n let res = await retry(\n async () => {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n }\n if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out')\n }\n if (typeof dispatchSignal?.throwIfAborted === 'function') {\n dispatchSignal.throwIfAborted()\n } else if (dispatchSignal?.aborted) {\n if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n } else if (timeoutSignal?.aborted) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out')\n } else {\n throw new AbortError(\n 'Request was aborted',\n new DOMException('Aborted', 'AbortError')\n )\n }\n }\n const reqWithSignal = new Request(requestForAttempt, {\n signal: dispatchSignal,\n })\n try {\n const handler = init.fetchHandler ?? fetchHandler ?? fetch\n const response = await handler(reqWithSignal)\n lastResponse = response\n dispatchCtx.metadata.retry.lastResponse = response\n return response\n } catch (err) {\n dispatchCtx.metadata.retry.lastError = err\n if (err instanceof DOMException && err.name === 'AbortError') {\n if (\n timeoutSignal?.aborted &&\n (!userSignal || !userSignal.aborted)\n ) {\n effectiveHooks.onTimeout?.(requestForAttempt)\n throw new TimeoutError('signal timed out', err)\n } else if (userSignal?.aborted) {\n effectiveHooks.onAbort?.(requestForAttempt)\n throw new AbortError('Request was aborted by user')\n } else {\n throw new AbortError(\n 'Request was aborted',\n new DOMException('Aborted', 'AbortError')\n )\n }\n } else if (\n err instanceof TypeError &&\n /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(\n err.message\n )\n ) {\n throw new NetworkError(err.message, err)\n }\n throw err\n }\n },\n effectiveRetries,\n effectiveRetryDelay,\n shouldRetryWithHook,\n requestForAttempt,\n dispatchSignal\n )\n if (effectiveHooks.transformResponse) {\n res = await effectiveHooks.transformResponse(res, requestForAttempt)\n }\n await effectiveHooks.after?.(requestForAttempt, res)\n await effectiveHooks.onComplete?.(requestForAttempt, res, undefined)\n if (\n effectiveThrowOnHttpError &&\n ((res.status >= 400 && res.status < 500 && res.status !== 429) ||\n res.status >= 500 ||\n res.status === 429)\n ) {\n const { HttpError } = await import('./error.js')\n throw new HttpError(\n `HTTP error: ${res.status} ${res.statusText}`,\n res\n )\n }\n return res\n } catch (err: unknown) {\n dispatchCtx.metadata.retry.lastError = err\n if (lastResponse) {\n const resp = lastResponse as Response\n if (\n effectiveThrowOnHttpError &&\n ((resp.status >= 400 &&\n resp.status < 500 &&\n resp.status !== 429) ||\n resp.status >= 500 ||\n resp.status === 429)\n ) {\n const { HttpError } = await import('./error.js')\n throw new HttpError(\n `HTTP error: ${resp.status} ${resp.statusText}`,\n resp\n )\n }\n return resp\n }\n if (err instanceof TimeoutError) {\n await effectiveHooks.onTimeout?.(requestForAttempt)\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n if (err instanceof AbortError) {\n await effectiveHooks.onAbort?.(requestForAttempt)\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n if (err instanceof NetworkError) {\n await effectiveHooks.onError?.(requestForAttempt, err)\n await effectiveHooks.onComplete?.(requestForAttempt, undefined, err)\n throw err\n }\n const retryErr = new RetryLimitError(\n typeof err === 'object' &&\n err &&\n 'message' in err &&\n typeof (err as { message?: unknown }).message === 'string'\n ? (err as { message: string }).message\n : 'Retry limit reached',\n err\n )\n await effectiveHooks.onError?.(requestForAttempt, retryErr)\n await effectiveHooks.onComplete?.(\n requestForAttempt,\n undefined,\n retryErr\n )\n throw retryErr\n }\n }\n\n const baseDispatch: PluginDispatch = async (ctx) => {\n const dispatchSignal =\n ctx === pluginContext ? combinedSignal : ctx.request.signal\n return retryWithHooks(ctx, dispatchSignal)\n }\n\n let dispatch = baseDispatch\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i]\n if (plugin.wrapDispatch) {\n dispatch = plugin.wrapDispatch(dispatch)\n }\n }\n\n const actualPromise = dispatch(pluginContext)\n .then(async (response) => {\n for (const plugin of plugins) {\n await plugin.onSuccess?.(pluginContext, response)\n }\n return response\n })\n .catch(async (err: unknown) => {\n for (const plugin of plugins) {\n await plugin.onError?.(pluginContext, err)\n }\n throw err\n })\n\n const pendingEntry: PendingRequest = {\n promise: actualPromise,\n request,\n controller,\n }\n pendingRequests.push(pendingEntry)\n\n return actualPromise.finally(async () => {\n for (const plugin of plugins) {\n await plugin.onFinally?.(pluginContext)\n }\n\n const index = pendingRequests.indexOf(pendingEntry)\n if (index > -1) {\n pendingRequests.splice(index, 1)\n }\n })\n }\n\n let promise = execute() as Promise<Response>\n for (const plugin of plugins) {\n if (plugin.decoratePromise) {\n promise = plugin.decoratePromise(promise)\n }\n }\n return promise as Promise<Response> &\n PluginRequestPromiseExtensions<TPlugins>\n }\n\n Object.defineProperty(client, 'pendingRequests', {\n get() {\n return pendingRequests\n },\n enumerable: false,\n configurable: false,\n })\n\n Object.defineProperty(client, 'abortAll', {\n value: abortAll,\n writable: false,\n enumerable: false,\n configurable: false,\n })\n\n Object.defineProperties(client, extensionDescriptors)\n\n return client as FFetch<\n PluginExtensions<TPlugins>,\n PluginRequestPromiseExtensions<TPlugins>\n >\n}\n"],"mappings":"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","names":["shouldRetry","controller","HttpError"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -15,6 +15,9 @@ declare class TimeoutError extends BaseError {
|
|
|
15
15
|
declare class CircuitOpenError extends BaseError {
|
|
16
16
|
constructor(message?: string, cause?: unknown);
|
|
17
17
|
}
|
|
18
|
+
declare class BulkheadFullError extends BaseError {
|
|
19
|
+
constructor(message?: string, cause?: unknown);
|
|
20
|
+
}
|
|
18
21
|
declare class AbortError extends BaseError {
|
|
19
22
|
constructor(message?: string, cause?: unknown);
|
|
20
23
|
}
|
|
@@ -28,4 +31,4 @@ declare class HttpError extends BaseError {
|
|
|
28
31
|
constructor(message?: string, cause?: unknown);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
export { AbortError, CircuitOpenError, ClientPlugin, FFetch, FFetchOptions, HttpError, NetworkError, RetryLimitError, TimeoutError, createClient };
|
|
34
|
+
export { AbortError, BulkheadFullError, CircuitOpenError, ClientPlugin, FFetch, FFetchOptions, HttpError, NetworkError, RetryLimitError, TimeoutError, createClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ declare class TimeoutError extends BaseError {
|
|
|
15
15
|
declare class CircuitOpenError extends BaseError {
|
|
16
16
|
constructor(message?: string, cause?: unknown);
|
|
17
17
|
}
|
|
18
|
+
declare class BulkheadFullError extends BaseError {
|
|
19
|
+
constructor(message?: string, cause?: unknown);
|
|
20
|
+
}
|
|
18
21
|
declare class AbortError extends BaseError {
|
|
19
22
|
constructor(message?: string, cause?: unknown);
|
|
20
23
|
}
|
|
@@ -28,4 +31,4 @@ declare class HttpError extends BaseError {
|
|
|
28
31
|
constructor(message?: string, cause?: unknown);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
export { AbortError, CircuitOpenError, ClientPlugin, FFetch, FFetchOptions, HttpError, NetworkError, RetryLimitError, TimeoutError, createClient };
|
|
34
|
+
export { AbortError, BulkheadFullError, CircuitOpenError, ClientPlugin, FFetch, FFetchOptions, HttpError, NetworkError, RetryLimitError, TimeoutError, createClient };
|