@scirexs/fetchy 0.2.2 → 0.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 +114 -71
- package/esm/main.js +74 -66
- package/package.json +1 -1
- package/types/main.d.ts +45 -36
- package/types/main.d.ts.map +1 -1
- package/types/types.d.ts +12 -12
- package/types/types.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -15,9 +15,10 @@ A lightweight, type-safe fetch wrapper with built-in retry logic, timeout handli
|
|
|
15
15
|
- **Type-Safe** - Full TypeScript support with generic type inference
|
|
16
16
|
- **Bearer Token Helper** - Built-in Authorization header management
|
|
17
17
|
- **Jitter Support** - Prevent thundering herd with randomized delays
|
|
18
|
-
- **
|
|
18
|
+
- **Automatic Body Parsing** - Automatic JSON serialization and Content-Type detection
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
|
+
|
|
21
22
|
```bash
|
|
22
23
|
# npm
|
|
23
24
|
npm install @scirexs/fetchy
|
|
@@ -27,6 +28,7 @@ deno add jsr:@scirexs/fetchy
|
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
## Quick Start
|
|
31
|
+
|
|
30
32
|
```ts
|
|
31
33
|
import { fetchy, fetchyb } from "@scirexs/fetchy";
|
|
32
34
|
|
|
@@ -52,20 +54,23 @@ console.log(user?.name);
|
|
|
52
54
|
Performs an HTTP request and returns the raw Response object.
|
|
53
55
|
|
|
54
56
|
#### Parameters
|
|
55
|
-
|
|
57
|
+
|
|
58
|
+
- `url`: `string | URL | Request | null` - The request URL
|
|
56
59
|
- `options`: `FetchyOptions` (optional) - Configuration options
|
|
57
60
|
|
|
58
61
|
#### Returns
|
|
59
|
-
|
|
62
|
+
|
|
63
|
+
`Promise<Response>`; If `onError.onNative` is configured as `false`, returns `Promise<Response | null>`
|
|
60
64
|
|
|
61
65
|
#### Example
|
|
66
|
+
|
|
62
67
|
```ts
|
|
63
68
|
const response = await fetchy("https://api.example.com/data", {
|
|
64
69
|
method: "POST",
|
|
65
70
|
body: { key: "value" },
|
|
66
71
|
timeout: 10,
|
|
67
|
-
retry: {
|
|
68
|
-
|
|
72
|
+
retry: { maxAttempts: 3, interval: 2 },
|
|
73
|
+
bearer: "your-token-here"
|
|
69
74
|
});
|
|
70
75
|
|
|
71
76
|
if (response?.ok) {
|
|
@@ -78,14 +83,17 @@ if (response?.ok) {
|
|
|
78
83
|
Performs an HTTP request and automatically parses the response body.
|
|
79
84
|
|
|
80
85
|
#### Parameters
|
|
81
|
-
|
|
86
|
+
|
|
87
|
+
- `url`: `string | URL | Request | null` - The request URL
|
|
82
88
|
- `type`: `"text" | "json" | "bytes" | "auto"` (default: `"auto"`) - Response parsing type
|
|
83
89
|
- `options`: `FetchyOptions` (optional) - Configuration options
|
|
84
90
|
|
|
85
91
|
#### Returns
|
|
86
|
-
|
|
92
|
+
|
|
93
|
+
`Promise<T | string | Uint8Array>`; If `onError.onNative` is configured as `false`, returns `Promise<T | string | Uint8Array | null>`
|
|
87
94
|
|
|
88
95
|
#### Example
|
|
96
|
+
|
|
89
97
|
```ts
|
|
90
98
|
// Automatic type detection from Content-Type header
|
|
91
99
|
const data = await fetchyb("https://api.example.com/data");
|
|
@@ -105,50 +113,47 @@ const html = await fetchyb("https://example.com", "text");
|
|
|
105
113
|
const image = await fetchyb("https://example.com/image.png", "bytes");
|
|
106
114
|
```
|
|
107
115
|
|
|
108
|
-
##
|
|
116
|
+
## Configuration
|
|
109
117
|
|
|
110
118
|
### API Options
|
|
111
119
|
|
|
112
120
|
#### `FetchyOptions`
|
|
113
121
|
|
|
114
122
|
```ts
|
|
115
|
-
interface FetchyOptions {
|
|
123
|
+
interface FetchyOptions extends RequestInit {
|
|
116
124
|
// Standard fetch options (method, headers, etc.)
|
|
117
125
|
method?: string;
|
|
118
126
|
headers?: HeadersInit;
|
|
119
127
|
|
|
120
|
-
// Request body (auto-serializes JSON
|
|
128
|
+
// Request body (auto-serializes JSON; ReadableStream is NOT supported)
|
|
121
129
|
// type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
|
|
122
130
|
body?: JSONValue | FormData | URLSearchParams | Blob | ArrayBuffer | string;
|
|
123
131
|
|
|
124
132
|
// Timeout in seconds (default: 15)
|
|
125
|
-
timeout?: number;
|
|
133
|
+
timeout?: number; // Set to 0 to disable timeout
|
|
126
134
|
|
|
127
135
|
// Retry configuration
|
|
128
136
|
retry?: {
|
|
129
|
-
|
|
130
|
-
interval?: number;
|
|
131
|
-
maxInterval?: number;
|
|
132
|
-
|
|
137
|
+
maxAttempts?: number; // Maximum retry attempts (default: 3)
|
|
138
|
+
interval?: number; // Base interval in seconds (default: 3)
|
|
139
|
+
maxInterval?: number; // Maximum interval cap in seconds (default: 30)
|
|
140
|
+
retryAfter?: boolean; // Respect Retry-After header (default: true)
|
|
133
141
|
} | false; // Set to false to disable retry
|
|
134
142
|
|
|
135
|
-
// Bearer token (
|
|
136
|
-
|
|
143
|
+
// Bearer token (automatically adds "Bearer " prefix)
|
|
144
|
+
bearer?: string;
|
|
137
145
|
|
|
138
146
|
// Error throwing behavior
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
} | boolean; // Set to true to throw all errors
|
|
147
|
+
onError?: {
|
|
148
|
+
onNative?: boolean; // Throw on native errors (default: true)
|
|
149
|
+
onStatus?: boolean; // Throw on 4xx/5xx status (default: false)
|
|
150
|
+
} | boolean; // Set to true to throw on all errors
|
|
143
151
|
|
|
144
152
|
// Initial jitter delay in seconds
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// Redirect behavior
|
|
151
|
-
redirect?: "follow" | "error" | "manual";
|
|
153
|
+
delay?: number;
|
|
154
|
+
|
|
155
|
+
// URL for fetch (allows reusing FetchyOptions as preset configuration)
|
|
156
|
+
url?: string | URL;
|
|
152
157
|
}
|
|
153
158
|
```
|
|
154
159
|
|
|
@@ -156,63 +161,65 @@ interface FetchyOptions {
|
|
|
156
161
|
|
|
157
162
|
```ts
|
|
158
163
|
{
|
|
159
|
-
timeout: 15,
|
|
160
|
-
|
|
164
|
+
timeout: 15, // 15 seconds
|
|
165
|
+
delay: 0, // No jitter delay
|
|
161
166
|
retry: {
|
|
162
|
-
|
|
163
|
-
interval: 3,
|
|
164
|
-
maxInterval: 30,
|
|
165
|
-
|
|
167
|
+
maxAttempts: 3, // 3 retry attempts
|
|
168
|
+
interval: 3, // 3 seconds base interval
|
|
169
|
+
maxInterval: 30, // 30 seconds maximum interval
|
|
170
|
+
retryAfter: true // Respect Retry-After header
|
|
166
171
|
},
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
onError: {
|
|
173
|
+
onNative: true, // Throw native errors
|
|
174
|
+
onStatus: false // Don't throw on HTTP errors
|
|
170
175
|
},
|
|
171
|
-
redirect: "follow" // Follow redirects
|
|
172
176
|
}
|
|
173
177
|
```
|
|
174
178
|
|
|
175
|
-
###
|
|
179
|
+
### Automatic Configuration
|
|
176
180
|
|
|
177
181
|
#### Method
|
|
178
182
|
|
|
179
|
-
If a body is
|
|
183
|
+
If a body is provided without specifying a method, the method defaults to `"POST"`. When a Request object is passed as the `url` argument, its method is used.
|
|
180
184
|
|
|
181
185
|
#### Headers
|
|
182
186
|
|
|
183
|
-
|
|
187
|
+
The following headers are automatically set if not specified:
|
|
184
188
|
|
|
185
|
-
- Accept
|
|
186
|
-
- Content-Type
|
|
189
|
+
- **Accept**: `application/json, text/plain`
|
|
190
|
+
- **Content-Type**: Automatically determined based on the body type:
|
|
187
191
|
- `string`, `URLSearchParams`, `FormData`, `Blob` with type: Not set by this package; [`fetch` will set it automatically](https://fetch.spec.whatwg.org/#concept-bodyinit-extract).
|
|
188
192
|
- `JSONValue`: `application/json`
|
|
189
193
|
- `Blob` without type: `application/octet-stream`
|
|
190
194
|
- `ArrayBuffer`: `application/octet-stream`
|
|
191
|
-
- Authorization
|
|
195
|
+
- **Authorization**: Set to `Bearer ${options.bearer}` if `options.bearer` is provided.
|
|
196
|
+
|
|
197
|
+
**Note 1:** If you pass serialized JSON as the body (i.e., a string), Content-Type will be set to `text/plain;charset=UTF-8`. To ensure Content-Type is set to `application/json`, pass the JSON object directly instead of a serialized string.
|
|
192
198
|
|
|
193
|
-
**Note:** If you pass
|
|
199
|
+
**Note 2:** If you pass a body through a Request object, Content-Type will NOT be set automatically by this package.
|
|
194
200
|
|
|
195
|
-
## Error
|
|
201
|
+
## Error Handling
|
|
196
202
|
|
|
197
203
|
### Timeout
|
|
198
204
|
|
|
199
|
-
If the timeout duration specified in the `timeout` option is exceeded,
|
|
205
|
+
If the timeout duration specified in the `timeout` option is exceeded, the request is aborted using the standard `AbortSignal.timeout()` method. Note that there is no specific error class for timeout errors; they will be thrown as standard `AbortError`s.
|
|
200
206
|
|
|
201
207
|
### HTTPStatusError
|
|
202
208
|
|
|
203
|
-
If `
|
|
209
|
+
If `onStatus` is set to `true`, an `HTTPStatusError` will be thrown when the response status is outside the 2xx range. You can access the status and body through this error object. The error message format is: `404 Not Found: (no response body)`.
|
|
204
210
|
|
|
205
211
|
### RedirectError
|
|
206
212
|
|
|
207
|
-
If `redirect` is set to `"error"`, a `RedirectError` will be thrown when the response status is in the
|
|
213
|
+
If `redirect` is set to `"error"`, a `RedirectError` will be thrown when the response status is in the 3xx range. You can access the status through this error object. The error message format is: `301 Moved Permanently`.
|
|
208
214
|
|
|
209
|
-
###
|
|
215
|
+
### Other Errors
|
|
210
216
|
|
|
211
|
-
If the `
|
|
217
|
+
If the `onNative` option is set to `true`, any other errors that occur will be thrown directly.
|
|
212
218
|
|
|
213
219
|
## Usage Examples
|
|
214
220
|
|
|
215
221
|
### Basic Requests
|
|
222
|
+
|
|
216
223
|
```ts
|
|
217
224
|
import { fetchy, fetchyb } from "@scirexs/fetchy";
|
|
218
225
|
|
|
@@ -230,13 +237,19 @@ const response = await fetchy("https://api.example.com/data", {
|
|
|
230
237
|
"X-Custom-Header": "value"
|
|
231
238
|
}
|
|
232
239
|
});
|
|
240
|
+
|
|
241
|
+
// Reuse options as preset configuration (avoids Request object limitations)
|
|
242
|
+
const options = { url: "https://api.example.com/data", retry: false };
|
|
243
|
+
await fetchy(null, options);
|
|
244
|
+
await fetchy(null, options);
|
|
233
245
|
```
|
|
234
246
|
|
|
235
247
|
### Authentication
|
|
248
|
+
|
|
236
249
|
```ts
|
|
237
250
|
// Bearer token authentication
|
|
238
251
|
const user = await fetchyb<User>("https://api.example.com/me", "json", {
|
|
239
|
-
|
|
252
|
+
bearer: "your-access-token"
|
|
240
253
|
});
|
|
241
254
|
|
|
242
255
|
// Custom authorization
|
|
@@ -248,6 +261,7 @@ const data = await fetchyb("https://api.example.com/data", "json", {
|
|
|
248
261
|
```
|
|
249
262
|
|
|
250
263
|
### Timeout and Retry
|
|
264
|
+
|
|
251
265
|
```ts
|
|
252
266
|
// Custom timeout
|
|
253
267
|
const response = await fetchy("https://slow-api.example.com", {
|
|
@@ -255,12 +269,13 @@ const response = await fetchy("https://slow-api.example.com", {
|
|
|
255
269
|
});
|
|
256
270
|
|
|
257
271
|
// Retry with exponential backoff
|
|
272
|
+
// Retry intervals: 1s, 3s (3^1), 9s (3^2), 27s (3^3), 60s (capped at maxInterval)
|
|
258
273
|
const data = await fetchyb("https://api.example.com/data", "json", {
|
|
259
274
|
retry: {
|
|
260
|
-
|
|
261
|
-
interval:
|
|
275
|
+
maxAttempts: 5, // Retry up to 5 times
|
|
276
|
+
interval: 3, // Base interval for exponential backoff (interval^n)
|
|
262
277
|
maxInterval: 60, // Cap at 60 seconds
|
|
263
|
-
|
|
278
|
+
retryAfter: true // Respect Retry-After header
|
|
264
279
|
}
|
|
265
280
|
});
|
|
266
281
|
|
|
@@ -271,10 +286,11 @@ const response = await fetchy("https://api.example.com/data", {
|
|
|
271
286
|
```
|
|
272
287
|
|
|
273
288
|
### Error Handling
|
|
289
|
+
|
|
274
290
|
```ts
|
|
275
291
|
import { fetchy, HTTPStatusError, RedirectError } from "@scirexs/fetchy";
|
|
276
292
|
|
|
277
|
-
// Throw on error (default
|
|
293
|
+
// Throw on error (default behavior, same as native fetch)
|
|
278
294
|
try {
|
|
279
295
|
const response = await fetchy("https://api.example.com/data");
|
|
280
296
|
} catch (error) {
|
|
@@ -283,7 +299,7 @@ try {
|
|
|
283
299
|
|
|
284
300
|
// Return null on error
|
|
285
301
|
const response = await fetchy("https://api.example.com/data", {
|
|
286
|
-
|
|
302
|
+
onError: false,
|
|
287
303
|
});
|
|
288
304
|
if (response === null) {
|
|
289
305
|
console.log("Request failed");
|
|
@@ -292,12 +308,13 @@ if (response === null) {
|
|
|
292
308
|
// Throw only on HTTP errors
|
|
293
309
|
try {
|
|
294
310
|
const response = await fetchy("https://api.example.com/data", {
|
|
295
|
-
|
|
311
|
+
onError: { onNative: false, onStatus: true }
|
|
296
312
|
});
|
|
297
313
|
} catch (error) {
|
|
298
314
|
if (error instanceof HTTPStatusError) {
|
|
299
|
-
// You can also use error.status and error.body.
|
|
300
315
|
console.error("HTTP error:", error.message); // e.g., "404 Not Found: (no response body)"
|
|
316
|
+
console.error("Status:", error.status);
|
|
317
|
+
console.error("Body:", error.body);
|
|
301
318
|
}
|
|
302
319
|
}
|
|
303
320
|
|
|
@@ -309,28 +326,34 @@ try {
|
|
|
309
326
|
} catch (error) {
|
|
310
327
|
if (error instanceof RedirectError) {
|
|
311
328
|
console.error("Unexpected redirect:", error.message);
|
|
329
|
+
console.error("Status:", error.status);
|
|
312
330
|
}
|
|
313
331
|
}
|
|
314
332
|
```
|
|
315
333
|
|
|
316
334
|
### Advanced Usage
|
|
335
|
+
|
|
317
336
|
```ts
|
|
318
337
|
// Jitter to prevent thundering herd
|
|
319
338
|
const response = await fetchy("https://api.example.com/data", {
|
|
320
|
-
|
|
321
|
-
retry: {
|
|
339
|
+
delay: 2, // Random delay up to 2 seconds before request
|
|
340
|
+
retry: { maxAttempts: 3 }
|
|
322
341
|
});
|
|
323
342
|
|
|
324
|
-
//
|
|
325
|
-
const
|
|
343
|
+
// Combined abort signals
|
|
344
|
+
const controller1 = new AbortController();
|
|
345
|
+
const controller2 = new AbortController();
|
|
346
|
+
const request = new Request("https://api.example.com/data", {
|
|
347
|
+
signal: controller1.signal
|
|
348
|
+
});
|
|
326
349
|
|
|
327
|
-
setTimeout(() =>
|
|
350
|
+
setTimeout(() => controller1.abort(), 5000); // Abort after 5 seconds
|
|
328
351
|
|
|
329
|
-
const response = await fetchy(
|
|
330
|
-
|
|
352
|
+
const response = await fetchy(request, {
|
|
353
|
+
signal: controller2.signal
|
|
331
354
|
});
|
|
332
355
|
|
|
333
|
-
// Form data
|
|
356
|
+
// Form data upload
|
|
334
357
|
const formData = new FormData();
|
|
335
358
|
formData.append("file", blob);
|
|
336
359
|
formData.append("name", "example");
|
|
@@ -349,12 +372,14 @@ const response = await fetchy("https://api.example.com/form", {
|
|
|
349
372
|
```
|
|
350
373
|
|
|
351
374
|
### Type-Safe API Responses
|
|
375
|
+
|
|
352
376
|
```ts
|
|
353
377
|
interface ApiResponse<T> {
|
|
354
378
|
success: boolean;
|
|
355
379
|
data: T;
|
|
356
380
|
error?: string;
|
|
357
381
|
}
|
|
382
|
+
|
|
358
383
|
interface Todo {
|
|
359
384
|
id: number;
|
|
360
385
|
title: string;
|
|
@@ -371,19 +396,37 @@ if (response.success) {
|
|
|
371
396
|
}
|
|
372
397
|
```
|
|
373
398
|
|
|
374
|
-
|
|
399
|
+
## Limitations
|
|
400
|
+
|
|
401
|
+
### Return Type Inference
|
|
402
|
+
|
|
403
|
+
When setting the `onError` property in `FetchyOptions`, the return type will include `null` even if you set it to `true` or `{ onNative: true }`. To prevent this and ensure a non-nullable return type, add `as const` to the `onError` property value:
|
|
375
404
|
|
|
376
|
-
When setting the `throwError` property in `FetchyOptions`, the return type will include `null` even if you set it to `true` or `{ onError: true }`. To prevent this and ensure a non-nullable return type, add `as const` to the `throwError` property value:
|
|
377
405
|
```ts
|
|
378
406
|
interface User {
|
|
379
407
|
id: number;
|
|
380
408
|
name: string;
|
|
381
409
|
}
|
|
382
410
|
|
|
383
|
-
const options = { timeout: 5,
|
|
384
|
-
const response = await fetchy("https://api.example.com/todos/1", "json", options);
|
|
411
|
+
const options = { timeout: 5, onError: true as const }; // Add `as const`
|
|
412
|
+
const response = await fetchy("https://api.example.com/todos/1", "json", options);
|
|
413
|
+
// `response` is User (not User | null)
|
|
385
414
|
```
|
|
386
415
|
|
|
416
|
+
### Content-Type Header with Request Objects
|
|
417
|
+
|
|
418
|
+
When a body is set in a Request object, the Content-Type header is NOT set automatically by this package. Therefore, when using Request objects, you must explicitly set the Content-Type header for any body types other than those automatically handled by the native `fetch` API.
|
|
419
|
+
|
|
420
|
+
This limitation can be avoided by using the `url` property in `FetchyOptions` instead of Request objects. This approach allows you to benefit from all automatic header configuration features while still maintaining reusable preset configurations. See the "Reuse options as preset configuration" example in the [Basic Requests](#basic-requests) section.
|
|
421
|
+
|
|
422
|
+
### ReadableStream as Body
|
|
423
|
+
|
|
424
|
+
`FetchyOptions` does not accept ReadableStream as a body. If you need to use ReadableStream, create a Request object with the stream and pass it to `fetchy()`.
|
|
425
|
+
|
|
426
|
+
### Redirect Error Handling
|
|
427
|
+
|
|
428
|
+
When `redirect` is set to `"error"`, this package throws a custom `RedirectError` (instead of the native TypeError) to enable proper retry handling for redirect responses.
|
|
429
|
+
|
|
387
430
|
## License
|
|
388
431
|
|
|
389
432
|
MIT
|
package/esm/main.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
export { _correctNumber, _fetchWithJitter, _fetchWithRetry,
|
|
1
|
+
export { _cloneInput, _combineSignal, _correctNumber, _DEFAULT, _fetchWithJitter, _fetchWithRetry, _getBody, _getContentType, _getHeaders, _getNextInterval, _getOptions, _getRequestInit, _getRetryOption, _handleRedirectResponse, _isBool, _isJSONObject, _isNumber, _isPlainObject, _isString, _parseRetryAfter, _shouldNotRetry, _shouldRedirect, _throwError, _wait, fetchy, fetchyb, HTTPStatusError, RedirectError, };
|
|
2
2
|
/*=============== Constant Values ===============*/
|
|
3
3
|
/**
|
|
4
4
|
* Default configuration values for fetchy.
|
|
5
5
|
* These values are used when corresponding options are not specified.
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
7
|
+
const _DEFAULT = {
|
|
8
8
|
timeout: 15,
|
|
9
|
-
|
|
9
|
+
delay: 0,
|
|
10
10
|
interval: 3,
|
|
11
11
|
maxInterval: 30,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
maxAttempts: 3,
|
|
13
|
+
retryAfter: true,
|
|
14
|
+
onNative: true,
|
|
15
|
+
onStatus: false,
|
|
16
|
+
redirect: "follow",
|
|
17
17
|
};
|
|
18
18
|
/*=============== Main Code =====================*/
|
|
19
19
|
/**
|
|
@@ -93,22 +93,24 @@ async function fetchyb(url, type = "auto", options) {
|
|
|
93
93
|
return await resp.bytes();
|
|
94
94
|
}
|
|
95
95
|
catch (e) {
|
|
96
|
-
if (_throwError("
|
|
96
|
+
if (_throwError("onNative", options?.onError))
|
|
97
97
|
throw e;
|
|
98
98
|
return null;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
async function fetchy(url, options) {
|
|
102
102
|
try {
|
|
103
|
+
if (!url)
|
|
104
|
+
url = options?.url ?? new URL("");
|
|
103
105
|
const opts = _getOptions(options);
|
|
104
|
-
const init = _getRequestInit(
|
|
106
|
+
const init = _getRequestInit(url, opts, options);
|
|
105
107
|
const resp = await _fetchWithRetry(url, init, opts);
|
|
106
|
-
if (!resp.ok && opts.
|
|
108
|
+
if (!resp.ok && opts.onStatus)
|
|
107
109
|
throw await HTTPStatusError.fromResponse(resp);
|
|
108
110
|
return resp;
|
|
109
111
|
}
|
|
110
112
|
catch (e) {
|
|
111
|
-
if (_throwError("
|
|
113
|
+
if (_throwError("onNative", options?.onError))
|
|
112
114
|
throw e;
|
|
113
115
|
return null;
|
|
114
116
|
}
|
|
@@ -161,9 +163,9 @@ function _isPlainObject(v) {
|
|
|
161
163
|
* @returns True if error should be thrown.
|
|
162
164
|
*/
|
|
163
165
|
function _throwError(prop, options) {
|
|
164
|
-
return Boolean((options === void 0 &&
|
|
166
|
+
return Boolean((options === void 0 && _DEFAULT[prop]) ||
|
|
165
167
|
(typeof options === "boolean" && options) ||
|
|
166
|
-
(typeof options === "object" && (options[prop] ??
|
|
168
|
+
(typeof options === "object" && (options[prop] ?? _DEFAULT[prop])));
|
|
167
169
|
}
|
|
168
170
|
/**
|
|
169
171
|
* Corrects a number to be non-negative, using default if invalid.
|
|
@@ -182,9 +184,9 @@ function _getRetryOption(prop, off, options) {
|
|
|
182
184
|
if (_isBool(options))
|
|
183
185
|
return off;
|
|
184
186
|
if (options === void 0 || options[prop] === void 0)
|
|
185
|
-
return
|
|
187
|
+
return _DEFAULT[prop];
|
|
186
188
|
if (_isNumber(options[prop]))
|
|
187
|
-
return _correctNumber(
|
|
189
|
+
return _correctNumber(_DEFAULT[prop], options[prop], prop === "maxAttempts");
|
|
188
190
|
return options[prop];
|
|
189
191
|
}
|
|
190
192
|
/**
|
|
@@ -194,33 +196,32 @@ function _getRetryOption(prop, off, options) {
|
|
|
194
196
|
* @returns Normalized internal options.
|
|
195
197
|
*/
|
|
196
198
|
function _getOptions(options) {
|
|
197
|
-
const timeout = _correctNumber(DEFAULT.timeout, options?.timeout);
|
|
198
199
|
return {
|
|
199
|
-
timeout,
|
|
200
|
-
|
|
200
|
+
timeout: _correctNumber(_DEFAULT.timeout, options?.timeout),
|
|
201
|
+
delay: _correctNumber(_DEFAULT.delay, options?.delay),
|
|
201
202
|
interval: _getRetryOption("interval", 0, options?.retry),
|
|
202
203
|
maxInterval: _getRetryOption("maxInterval", 0, options?.retry),
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
userRedirect: options?.redirect ?? DEFAULT.userRedirect,
|
|
204
|
+
maxAttempts: _getRetryOption("maxAttempts", 0, options?.retry),
|
|
205
|
+
retryAfter: _getRetryOption("retryAfter", false, options?.retry),
|
|
206
|
+
onStatus: _throwError("onStatus", options?.onError),
|
|
207
|
+
redirect: options?.redirect ?? _DEFAULT.redirect,
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
210
|
/**
|
|
211
211
|
* Converts FetchyOptions to standard RequestInit format.
|
|
212
212
|
* @internal
|
|
213
|
+
* @param url - Original request URL.
|
|
214
|
+
* @param opts - Internal options.
|
|
213
215
|
* @param options - User-provided options.
|
|
214
|
-
* @param optsAbort - AbortController for timeout handling.
|
|
215
216
|
* @returns Standard RequestInit object.
|
|
216
217
|
*/
|
|
217
|
-
function _getRequestInit(
|
|
218
|
-
const { body, timeout, retry,
|
|
218
|
+
function _getRequestInit(url, opts, options) {
|
|
219
|
+
const { method, body, timeout, retry, bearer, onError, delay, redirect, signal, ...rest } = options ?? {};
|
|
219
220
|
return {
|
|
220
|
-
method: body === void 0 ? "GET" : "POST",
|
|
221
221
|
headers: _getHeaders(options),
|
|
222
|
+
method: method ? method : url instanceof Request ? url.method : body === void 0 ? "GET" : "POST",
|
|
223
|
+
signal: _combineSignal(url, opts.timeout, options?.signal),
|
|
222
224
|
...(redirect && { redirect: redirect === "error" ? "manual" : redirect }),
|
|
223
|
-
...(optsAbort && { signal: optsAbort.signal }),
|
|
224
225
|
...(body && { body: _getBody(body) }),
|
|
225
226
|
...rest,
|
|
226
227
|
};
|
|
@@ -254,7 +255,7 @@ function _getHeaders(options) {
|
|
|
254
255
|
return {
|
|
255
256
|
"Accept": "application/json, text/plain",
|
|
256
257
|
...(type && { "Content-Type": type }),
|
|
257
|
-
...(options?.
|
|
258
|
+
...(options?.bearer && { "Authorization": `Bearer ${options.bearer}` }),
|
|
258
259
|
...options?.headers,
|
|
259
260
|
};
|
|
260
261
|
}
|
|
@@ -273,6 +274,24 @@ function _getContentType(body) {
|
|
|
273
274
|
return "application/json";
|
|
274
275
|
return "application/octet-stream";
|
|
275
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Combine abort signals.
|
|
279
|
+
* @internal
|
|
280
|
+
* @param url - Original request URL.
|
|
281
|
+
* @param timeout - Request timeout in seconds.
|
|
282
|
+
* @param signal - AbortSignal in User-provided options.
|
|
283
|
+
* @returns Combined AbortSignal or undefined.
|
|
284
|
+
*/
|
|
285
|
+
function _combineSignal(url, timeout, signal) {
|
|
286
|
+
const signals = [];
|
|
287
|
+
if (url instanceof Request && url.signal)
|
|
288
|
+
signals.push(url.signal);
|
|
289
|
+
if (signal)
|
|
290
|
+
signals.push(signal);
|
|
291
|
+
if (timeout > 0)
|
|
292
|
+
signals.push(AbortSignal.timeout(timeout * 1000 + 1));
|
|
293
|
+
return signals.length ? AbortSignal.any(signals) : undefined;
|
|
294
|
+
}
|
|
276
295
|
/**
|
|
277
296
|
* Waits for specified seconds with optional randomization.
|
|
278
297
|
* @internal
|
|
@@ -298,18 +317,19 @@ function _shouldRedirect(resp) {
|
|
|
298
317
|
* Determines if retry should stop based on conditions and waits if continuing.
|
|
299
318
|
* @internal
|
|
300
319
|
* @param count - Current retry attempt number.
|
|
320
|
+
* @param init - Request initialization object.
|
|
301
321
|
* @param opts - Internal options.
|
|
302
322
|
* @param resp - Response from previous attempt.
|
|
303
323
|
* @returns True if retry should stop.
|
|
304
324
|
*/
|
|
305
|
-
async function _shouldNotRetry(count, opts, resp) {
|
|
306
|
-
if (count >= opts.
|
|
325
|
+
async function _shouldNotRetry(count, init, opts, resp) {
|
|
326
|
+
if (count >= opts.maxAttempts - 1 || init.signal?.aborted || resp?.ok)
|
|
307
327
|
return true;
|
|
308
328
|
if (resp && _shouldRedirect(resp)) {
|
|
309
|
-
if (opts.
|
|
329
|
+
if (opts.redirect === "manual")
|
|
310
330
|
return true;
|
|
311
|
-
if (opts.
|
|
312
|
-
opts.
|
|
331
|
+
if (opts.redirect === "error") {
|
|
332
|
+
opts.maxAttempts = 0;
|
|
313
333
|
throw RedirectError.fromResponse(resp);
|
|
314
334
|
}
|
|
315
335
|
}
|
|
@@ -328,7 +348,7 @@ async function _shouldNotRetry(count, opts, resp) {
|
|
|
328
348
|
* @returns Next retry interval in seconds.
|
|
329
349
|
*/
|
|
330
350
|
function _getNextInterval(count, opts, resp) {
|
|
331
|
-
return opts.
|
|
351
|
+
return opts.retryAfter && resp
|
|
332
352
|
? Math.max(_parseRetryAfter(resp.headers.get("Retry-After")?.trim() ?? ""), opts.interval)
|
|
333
353
|
: Math.min(Math.pow(Math.max(1, opts.interval), count), opts.maxInterval);
|
|
334
354
|
}
|
|
@@ -364,6 +384,16 @@ function _handleRedirectResponse(url, init, resp) {
|
|
|
364
384
|
init.method = "GET";
|
|
365
385
|
return url instanceof Request ? new Request(resp.url, url) : resp.url;
|
|
366
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Clone input if required.
|
|
389
|
+
* @internal
|
|
390
|
+
* @param url - Original request URL.
|
|
391
|
+
* @param required - Switch to clone or not.
|
|
392
|
+
* @returns Cloned input for fetch.
|
|
393
|
+
*/
|
|
394
|
+
function _cloneInput(url, required) {
|
|
395
|
+
return url instanceof Request && required ? url.clone() : url;
|
|
396
|
+
}
|
|
367
397
|
/**
|
|
368
398
|
* Executes fetch with retry logic and exponential backoff.
|
|
369
399
|
* @internal
|
|
@@ -373,23 +403,22 @@ function _handleRedirectResponse(url, init, resp) {
|
|
|
373
403
|
* @returns Response from successful request.
|
|
374
404
|
*/
|
|
375
405
|
async function _fetchWithRetry(url, init, opts) {
|
|
376
|
-
|
|
377
|
-
return await _fetchWithTimeout(url, init, opts);
|
|
378
|
-
for (let i = 1; i <= opts.max; i++) {
|
|
406
|
+
for (let i = 0; i < opts.maxAttempts; i++) {
|
|
379
407
|
try {
|
|
380
|
-
const
|
|
381
|
-
|
|
408
|
+
const input = _cloneInput(url, i < opts.maxAttempts - 1); // no clone if end of retry
|
|
409
|
+
const resp = await _fetchWithJitter(input, init, opts);
|
|
410
|
+
if (await _shouldNotRetry(i, init, opts, resp))
|
|
382
411
|
return resp;
|
|
383
412
|
url = _handleRedirectResponse(url, init, resp);
|
|
384
413
|
continue;
|
|
385
414
|
}
|
|
386
415
|
catch (e) {
|
|
387
|
-
if (await _shouldNotRetry(i, opts))
|
|
416
|
+
if (await _shouldNotRetry(i, init, opts))
|
|
388
417
|
throw e;
|
|
389
418
|
continue;
|
|
390
419
|
}
|
|
391
420
|
}
|
|
392
|
-
|
|
421
|
+
return await _fetchWithJitter(url, init, opts);
|
|
393
422
|
}
|
|
394
423
|
/**
|
|
395
424
|
* Executes fetch with initial jitter delay.
|
|
@@ -400,27 +429,6 @@ async function _fetchWithRetry(url, init, opts) {
|
|
|
400
429
|
* @returns Response from request.
|
|
401
430
|
*/
|
|
402
431
|
async function _fetchWithJitter(url, init, opts) {
|
|
403
|
-
await _wait(opts.
|
|
404
|
-
return await
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* Executes fetch with timeout handling.
|
|
408
|
-
* @internal
|
|
409
|
-
* @param url - Request URL.
|
|
410
|
-
* @param init - Request initialization object.
|
|
411
|
-
* @param opts - Internal options.
|
|
412
|
-
* @returns Response from request.
|
|
413
|
-
*/
|
|
414
|
-
async function _fetchWithTimeout(url, init, opts) {
|
|
415
|
-
const req = url instanceof Request ? url.clone() : url;
|
|
416
|
-
const id = opts.abort ? setTimeout(() => opts.abort?.abort("timeout"), opts.timeout * 1000) : 0;
|
|
417
|
-
try {
|
|
418
|
-
return await fetch(req, init);
|
|
419
|
-
}
|
|
420
|
-
catch (e) {
|
|
421
|
-
throw e;
|
|
422
|
-
}
|
|
423
|
-
finally {
|
|
424
|
-
clearTimeout(id);
|
|
425
|
-
}
|
|
432
|
+
await _wait(opts.delay);
|
|
433
|
+
return await fetch(url, init);
|
|
426
434
|
}
|
package/package.json
CHANGED
package/types/main.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { _correctNumber, _fetchWithJitter, _fetchWithRetry,
|
|
1
|
+
export { _cloneInput, _combineSignal, _correctNumber, _DEFAULT, _fetchWithJitter, _fetchWithRetry, _getBody, _getContentType, _getHeaders, _getNextInterval, _getOptions, _getRequestInit, _getRetryOption, _handleRedirectResponse, _isBool, _isJSONObject, _isNumber, _isPlainObject, _isString, _parseRetryAfter, _shouldNotRetry, _shouldRedirect, _throwError, _wait, fetchy, fetchyb, HTTPStatusError, RedirectError, };
|
|
2
2
|
import type { ErrorOptions, FetchyBody, FetchyOptions, RetryOptions } from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Default configuration values for fetchy.
|
|
5
5
|
* These values are used when corresponding options are not specified.
|
|
6
6
|
*/
|
|
7
|
-
declare const
|
|
7
|
+
declare const _DEFAULT: Options;
|
|
8
8
|
/**
|
|
9
9
|
* Valid input types for fetch requests.
|
|
10
10
|
* @internal
|
|
@@ -16,15 +16,14 @@ type Input = string | URL | Request;
|
|
|
16
16
|
*/
|
|
17
17
|
interface Options {
|
|
18
18
|
timeout: number;
|
|
19
|
-
|
|
19
|
+
delay: number;
|
|
20
20
|
interval: number;
|
|
21
21
|
maxInterval: number;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
userRedirect: "follow" | "error" | "manual";
|
|
22
|
+
maxAttempts: number;
|
|
23
|
+
retryAfter: boolean;
|
|
24
|
+
onNative?: boolean;
|
|
25
|
+
onStatus: boolean;
|
|
26
|
+
redirect: "follow" | "error" | "manual";
|
|
28
27
|
}
|
|
29
28
|
/**
|
|
30
29
|
* Infer helper type for response type overload.
|
|
@@ -109,18 +108,18 @@ declare class RedirectError extends Error {
|
|
|
109
108
|
* const bytes = await fetchyb("https://example.com/image.png", "bytes");
|
|
110
109
|
* ```
|
|
111
110
|
*/
|
|
112
|
-
declare function fetchyb(url: Input, type: "text", options?: undefined): Promise<string>;
|
|
113
|
-
declare function fetchyb(url: Input, type: "text", options: FetchyOptions & ThrowError): Promise<string>;
|
|
114
|
-
declare function fetchyb(url: Input, type: "text", options?: FetchyOptions): Promise<string | null>;
|
|
115
|
-
declare function fetchyb<T>(url: Input, type: "json", options?: undefined): Promise<T>;
|
|
116
|
-
declare function fetchyb<T>(url: Input, type: "json", options: FetchyOptions & ThrowError): Promise<T>;
|
|
117
|
-
declare function fetchyb<T>(url: Input, type: "json", options?: FetchyOptions): Promise<T | null>;
|
|
118
|
-
declare function fetchyb(url: Input, type: "bytes", options?: undefined): Promise<Uint8Array>;
|
|
119
|
-
declare function fetchyb(url: Input, type: "bytes", options: FetchyOptions & ThrowError): Promise<Uint8Array>;
|
|
120
|
-
declare function fetchyb(url: Input, type: "bytes", options?: FetchyOptions): Promise<Uint8Array | null>;
|
|
121
|
-
declare function fetchyb<T>(url: Input, type?: "auto", options?: undefined): Promise<T | string | Uint8Array>;
|
|
122
|
-
declare function fetchyb<T>(url: Input, type?: "auto", options?: FetchyOptions & ThrowError): Promise<T | string | Uint8Array>;
|
|
123
|
-
declare function fetchyb<T>(url: Input, type?: "auto", options?: FetchyOptions): Promise<T | string | Uint8Array | null>;
|
|
111
|
+
declare function fetchyb(url: Input | null, type: "text", options?: undefined): Promise<string>;
|
|
112
|
+
declare function fetchyb(url: Input | null, type: "text", options: FetchyOptions & ThrowError): Promise<string>;
|
|
113
|
+
declare function fetchyb(url: Input | null, type: "text", options?: FetchyOptions): Promise<string | null>;
|
|
114
|
+
declare function fetchyb<T>(url: Input | null, type: "json", options?: undefined): Promise<T>;
|
|
115
|
+
declare function fetchyb<T>(url: Input | null, type: "json", options: FetchyOptions & ThrowError): Promise<T>;
|
|
116
|
+
declare function fetchyb<T>(url: Input | null, type: "json", options?: FetchyOptions): Promise<T | null>;
|
|
117
|
+
declare function fetchyb(url: Input | null, type: "bytes", options?: undefined): Promise<Uint8Array>;
|
|
118
|
+
declare function fetchyb(url: Input | null, type: "bytes", options: FetchyOptions & ThrowError): Promise<Uint8Array>;
|
|
119
|
+
declare function fetchyb(url: Input | null, type: "bytes", options?: FetchyOptions): Promise<Uint8Array | null>;
|
|
120
|
+
declare function fetchyb<T>(url: Input | null, type?: "auto", options?: undefined): Promise<T | string | Uint8Array>;
|
|
121
|
+
declare function fetchyb<T>(url: Input | null, type?: "auto", options?: FetchyOptions & ThrowError): Promise<T | string | Uint8Array>;
|
|
122
|
+
declare function fetchyb<T>(url: Input | null, type?: "auto", options?: FetchyOptions): Promise<T | string | Uint8Array | null>;
|
|
124
123
|
/**
|
|
125
124
|
* Performs an HTTP request with enhanced features like timeout, retry, and automatic header management.
|
|
126
125
|
* Returns the raw Response object or null on failure, unless throwError is configured.
|
|
@@ -153,9 +152,9 @@ declare function fetchyb<T>(url: Input, type?: "auto", options?: FetchyOptions):
|
|
|
153
152
|
* });
|
|
154
153
|
* ```
|
|
155
154
|
*/
|
|
156
|
-
declare function fetchy(url: Input, options?: undefined): Promise<Response>;
|
|
157
|
-
declare function fetchy(url: Input, options: FetchyOptions & ThrowError): Promise<Response>;
|
|
158
|
-
declare function fetchy(url: Input, options?: FetchyOptions): Promise<Response | null>;
|
|
155
|
+
declare function fetchy(url: Input | null, options?: undefined): Promise<Response>;
|
|
156
|
+
declare function fetchy(url: Input | null, options: FetchyOptions & ThrowError): Promise<Response>;
|
|
157
|
+
declare function fetchy(url: Input | null, options?: FetchyOptions): Promise<Response | null>;
|
|
159
158
|
/**
|
|
160
159
|
* Checks if a value is a string.
|
|
161
160
|
* @internal
|
|
@@ -221,11 +220,12 @@ declare function _getOptions(options?: FetchyOptions): Options;
|
|
|
221
220
|
/**
|
|
222
221
|
* Converts FetchyOptions to standard RequestInit format.
|
|
223
222
|
* @internal
|
|
223
|
+
* @param url - Original request URL.
|
|
224
|
+
* @param opts - Internal options.
|
|
224
225
|
* @param options - User-provided options.
|
|
225
|
-
* @param optsAbort - AbortController for timeout handling.
|
|
226
226
|
* @returns Standard RequestInit object.
|
|
227
227
|
*/
|
|
228
|
-
declare function _getRequestInit(
|
|
228
|
+
declare function _getRequestInit(url: Input, opts: Options, options?: FetchyOptions): RequestInit;
|
|
229
229
|
/**
|
|
230
230
|
* Converts FetchyBody to standard BodyInit format.
|
|
231
231
|
* @internal
|
|
@@ -254,6 +254,15 @@ declare function _getHeaders(options?: FetchyOptions): HeadersInit;
|
|
|
254
254
|
* @returns Content-Type string or undefined.
|
|
255
255
|
*/
|
|
256
256
|
declare function _getContentType(body?: FetchyBody): string | undefined;
|
|
257
|
+
/**
|
|
258
|
+
* Combine abort signals.
|
|
259
|
+
* @internal
|
|
260
|
+
* @param url - Original request URL.
|
|
261
|
+
* @param timeout - Request timeout in seconds.
|
|
262
|
+
* @param signal - AbortSignal in User-provided options.
|
|
263
|
+
* @returns Combined AbortSignal or undefined.
|
|
264
|
+
*/
|
|
265
|
+
declare function _combineSignal(url: Input, timeout: number, signal?: AbortSignal | null): AbortSignal | undefined;
|
|
257
266
|
/**
|
|
258
267
|
* Waits for specified seconds with optional randomization.
|
|
259
268
|
* @internal
|
|
@@ -272,11 +281,12 @@ declare function _shouldRedirect(resp: Response): boolean;
|
|
|
272
281
|
* Determines if retry should stop based on conditions and waits if continuing.
|
|
273
282
|
* @internal
|
|
274
283
|
* @param count - Current retry attempt number.
|
|
284
|
+
* @param init - Request initialization object.
|
|
275
285
|
* @param opts - Internal options.
|
|
276
286
|
* @param resp - Response from previous attempt.
|
|
277
287
|
* @returns True if retry should stop.
|
|
278
288
|
*/
|
|
279
|
-
declare function _shouldNotRetry(count: number, opts: Options, resp?: Response): Promise<boolean>;
|
|
289
|
+
declare function _shouldNotRetry(count: number, init: RequestInit, opts: Options, resp?: Response): Promise<boolean>;
|
|
280
290
|
/**
|
|
281
291
|
* Calculates next retry interval using exponential backoff or Retry-After header.
|
|
282
292
|
* @internal
|
|
@@ -302,6 +312,14 @@ declare function _parseRetryAfter(value: string): number;
|
|
|
302
312
|
* @returns Updated URL for next request.
|
|
303
313
|
*/
|
|
304
314
|
declare function _handleRedirectResponse(url: Input, init: RequestInit, resp: Response): Input;
|
|
315
|
+
/**
|
|
316
|
+
* Clone input if required.
|
|
317
|
+
* @internal
|
|
318
|
+
* @param url - Original request URL.
|
|
319
|
+
* @param required - Switch to clone or not.
|
|
320
|
+
* @returns Cloned input for fetch.
|
|
321
|
+
*/
|
|
322
|
+
declare function _cloneInput(url: Input, required: boolean): Input;
|
|
305
323
|
/**
|
|
306
324
|
* Executes fetch with retry logic and exponential backoff.
|
|
307
325
|
* @internal
|
|
@@ -320,13 +338,4 @@ declare function _fetchWithRetry(url: Input, init: RequestInit, opts: Options):
|
|
|
320
338
|
* @returns Response from request.
|
|
321
339
|
*/
|
|
322
340
|
declare function _fetchWithJitter(url: Input, init: RequestInit, opts: Options): Promise<Response>;
|
|
323
|
-
/**
|
|
324
|
-
* Executes fetch with timeout handling.
|
|
325
|
-
* @internal
|
|
326
|
-
* @param url - Request URL.
|
|
327
|
-
* @param init - Request initialization object.
|
|
328
|
-
* @param opts - Internal options.
|
|
329
|
-
* @returns Response from request.
|
|
330
|
-
*/
|
|
331
|
-
declare function _fetchWithTimeout(url: Input, init: RequestInit, opts: Options): Promise<Response>;
|
|
332
341
|
//# sourceMappingURL=main.d.ts.map
|
package/types/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
package/types/types.d.ts
CHANGED
|
@@ -27,7 +27,9 @@ export type FetchyBody = JSONValue | Exclude<BodyInit, ReadableStream>;
|
|
|
27
27
|
* });
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export interface FetchyOptions extends Omit<RequestInit, "body"
|
|
30
|
+
export interface FetchyOptions extends Omit<RequestInit, "body"> {
|
|
31
|
+
/** Request URL. Used if call fetchy with null. */
|
|
32
|
+
url?: string | URL;
|
|
31
33
|
/** Request body content. Automatically serializes JSON objects. */
|
|
32
34
|
body?: FetchyBody;
|
|
33
35
|
/** Request timeout in seconds. Default is 15 seconds. */
|
|
@@ -35,13 +37,11 @@ export interface FetchyOptions extends Omit<RequestInit, "body" | "signal"> {
|
|
|
35
37
|
/** Retry configuration. Set to false to disable retry functionality. */
|
|
36
38
|
retry?: RetryOptions | false;
|
|
37
39
|
/** Bearer token for Authorization header. Automatically adds "Bearer " prefix. */
|
|
38
|
-
|
|
40
|
+
bearer?: string;
|
|
39
41
|
/** Error throwing behavior configuration. Set to true to throw all errors. */
|
|
40
|
-
|
|
42
|
+
onError?: ErrorOptions | boolean;
|
|
41
43
|
/** Initial jitter delay in seconds before sending the request. Adds randomness to prevent thundering herd. */
|
|
42
|
-
|
|
43
|
-
/** AbortController for manual request cancellation. If not provided, an internal controller is created for timeout. */
|
|
44
|
-
abort?: AbortController;
|
|
44
|
+
delay?: number;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* Configuration options for retry behavior.
|
|
@@ -63,18 +63,18 @@ export interface RetryOptions {
|
|
|
63
63
|
/** Maximum interval in seconds between retries. Caps the exponential backoff. Default is 30 seconds. */
|
|
64
64
|
maxInterval?: number;
|
|
65
65
|
/** Maximum number of retry attempts. Default is 3. */
|
|
66
|
-
|
|
66
|
+
maxAttempts?: number;
|
|
67
67
|
/** Whether to respect Retry-After header from response. Default is true. */
|
|
68
|
-
|
|
68
|
+
retryAfter?: boolean;
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
71
|
* Configuration options for error throwing behavior.
|
|
72
72
|
* Allows fine-grained control over which errors should be thrown vs. returned as null.
|
|
73
73
|
*/
|
|
74
74
|
export interface ErrorOptions {
|
|
75
|
-
/** Whether to throw errors
|
|
76
|
-
|
|
77
|
-
/** Whether to throw HTTPStatusError for non-OK status codes (4xx, 5xx). Default is false. */
|
|
78
|
-
|
|
75
|
+
/** Whether to throw native errors (network errors, parsing errors, etc.). If false, returns null instead. Default is true. */
|
|
76
|
+
onNative?: boolean;
|
|
77
|
+
/** Whether to throw HTTPStatusError for non-OK status codes (4xx, 5xx, ...). Default is false. */
|
|
78
|
+
onStatus?: boolean;
|
|
79
79
|
}
|
|
80
80
|
//# sourceMappingURL=types.d.ts.map
|
package/types/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9D,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IACnB,mEAAmE;IACnE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IACjC,8GAA8G;IAC9G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,gHAAgH;IAChH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,8HAA8H;IAC9H,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
|