@scirexs/fetchy 0.2.1 → 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 +123 -68
- package/esm/main.js +74 -98
- package/package.json +1 -1
- package/types/main.d.ts +56 -26
- 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,6 +372,7 @@ 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;
|
|
@@ -367,11 +391,42 @@ const response = await fetchyb<ApiResponse<Todo>>(
|
|
|
367
391
|
"json"
|
|
368
392
|
);
|
|
369
393
|
|
|
370
|
-
if (response
|
|
394
|
+
if (response.success) {
|
|
371
395
|
console.log(response.data.title); // Fully typed
|
|
372
396
|
}
|
|
373
397
|
```
|
|
374
398
|
|
|
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:
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
interface User {
|
|
407
|
+
id: number;
|
|
408
|
+
name: string;
|
|
409
|
+
}
|
|
410
|
+
|
|
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)
|
|
414
|
+
```
|
|
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
|
+
|
|
375
430
|
## License
|
|
376
431
|
|
|
377
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,54 +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
|
-
/**
|
|
102
|
-
* Performs an HTTP request with enhanced features like timeout, retry, and automatic header management.
|
|
103
|
-
* Returns the raw Response object or null on failure, unless throwError is configured.
|
|
104
|
-
*
|
|
105
|
-
* @param url - The URL to fetch. Can be a string, URL object, or Request object.
|
|
106
|
-
* @param options - Configuration options for the request.
|
|
107
|
-
* @returns Response object or null on failure.
|
|
108
|
-
*
|
|
109
|
-
* @example
|
|
110
|
-
* ```ts
|
|
111
|
-
* import { fetchy } from "@scirexs/fetchy";
|
|
112
|
-
*
|
|
113
|
-
* // Simple GET request
|
|
114
|
-
* const response = await fetchy("https://api.example.com/data");
|
|
115
|
-
* if (response?.ok) {
|
|
116
|
-
* const data = await response.json();
|
|
117
|
-
* }
|
|
118
|
-
*
|
|
119
|
-
* // POST request with JSON body
|
|
120
|
-
* const response = await fetchy("https://api.example.com/create", {
|
|
121
|
-
* body: { name: "John", age: 30 },
|
|
122
|
-
* bearerToken: "your-token"
|
|
123
|
-
* });
|
|
124
|
-
*
|
|
125
|
-
* // With retry and timeout
|
|
126
|
-
* const response = await fetchy("https://api.example.com/data", {
|
|
127
|
-
* timeout: 10,
|
|
128
|
-
* retry: { max: 5, interval: 2 },
|
|
129
|
-
* throwError: { onErrorStatus: true }
|
|
130
|
-
* });
|
|
131
|
-
* ```
|
|
132
|
-
*/
|
|
133
101
|
async function fetchy(url, options) {
|
|
134
102
|
try {
|
|
103
|
+
if (!url)
|
|
104
|
+
url = options?.url ?? new URL("");
|
|
135
105
|
const opts = _getOptions(options);
|
|
136
|
-
const init = _getRequestInit(
|
|
106
|
+
const init = _getRequestInit(url, opts, options);
|
|
137
107
|
const resp = await _fetchWithRetry(url, init, opts);
|
|
138
|
-
if (!resp.ok && opts.
|
|
108
|
+
if (!resp.ok && opts.onStatus)
|
|
139
109
|
throw await HTTPStatusError.fromResponse(resp);
|
|
140
110
|
return resp;
|
|
141
111
|
}
|
|
142
112
|
catch (e) {
|
|
143
|
-
if (_throwError("
|
|
113
|
+
if (_throwError("onNative", options?.onError))
|
|
144
114
|
throw e;
|
|
145
115
|
return null;
|
|
146
116
|
}
|
|
@@ -193,9 +163,9 @@ function _isPlainObject(v) {
|
|
|
193
163
|
* @returns True if error should be thrown.
|
|
194
164
|
*/
|
|
195
165
|
function _throwError(prop, options) {
|
|
196
|
-
return Boolean((options === void 0 &&
|
|
166
|
+
return Boolean((options === void 0 && _DEFAULT[prop]) ||
|
|
197
167
|
(typeof options === "boolean" && options) ||
|
|
198
|
-
(typeof options === "object" && (options[prop] ??
|
|
168
|
+
(typeof options === "object" && (options[prop] ?? _DEFAULT[prop])));
|
|
199
169
|
}
|
|
200
170
|
/**
|
|
201
171
|
* Corrects a number to be non-negative, using default if invalid.
|
|
@@ -214,9 +184,9 @@ function _getRetryOption(prop, off, options) {
|
|
|
214
184
|
if (_isBool(options))
|
|
215
185
|
return off;
|
|
216
186
|
if (options === void 0 || options[prop] === void 0)
|
|
217
|
-
return
|
|
187
|
+
return _DEFAULT[prop];
|
|
218
188
|
if (_isNumber(options[prop]))
|
|
219
|
-
return _correctNumber(
|
|
189
|
+
return _correctNumber(_DEFAULT[prop], options[prop], prop === "maxAttempts");
|
|
220
190
|
return options[prop];
|
|
221
191
|
}
|
|
222
192
|
/**
|
|
@@ -226,33 +196,32 @@ function _getRetryOption(prop, off, options) {
|
|
|
226
196
|
* @returns Normalized internal options.
|
|
227
197
|
*/
|
|
228
198
|
function _getOptions(options) {
|
|
229
|
-
const timeout = _correctNumber(DEFAULT.timeout, options?.timeout);
|
|
230
199
|
return {
|
|
231
|
-
timeout,
|
|
232
|
-
|
|
200
|
+
timeout: _correctNumber(_DEFAULT.timeout, options?.timeout),
|
|
201
|
+
delay: _correctNumber(_DEFAULT.delay, options?.delay),
|
|
233
202
|
interval: _getRetryOption("interval", 0, options?.retry),
|
|
234
203
|
maxInterval: _getRetryOption("maxInterval", 0, options?.retry),
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
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,
|
|
240
208
|
};
|
|
241
209
|
}
|
|
242
210
|
/**
|
|
243
211
|
* Converts FetchyOptions to standard RequestInit format.
|
|
244
212
|
* @internal
|
|
213
|
+
* @param url - Original request URL.
|
|
214
|
+
* @param opts - Internal options.
|
|
245
215
|
* @param options - User-provided options.
|
|
246
|
-
* @param optsAbort - AbortController for timeout handling.
|
|
247
216
|
* @returns Standard RequestInit object.
|
|
248
217
|
*/
|
|
249
|
-
function _getRequestInit(
|
|
250
|
-
const { body, timeout, retry,
|
|
218
|
+
function _getRequestInit(url, opts, options) {
|
|
219
|
+
const { method, body, timeout, retry, bearer, onError, delay, redirect, signal, ...rest } = options ?? {};
|
|
251
220
|
return {
|
|
252
|
-
method: body === void 0 ? "GET" : "POST",
|
|
253
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),
|
|
254
224
|
...(redirect && { redirect: redirect === "error" ? "manual" : redirect }),
|
|
255
|
-
...(optsAbort && { signal: optsAbort.signal }),
|
|
256
225
|
...(body && { body: _getBody(body) }),
|
|
257
226
|
...rest,
|
|
258
227
|
};
|
|
@@ -286,7 +255,7 @@ function _getHeaders(options) {
|
|
|
286
255
|
return {
|
|
287
256
|
"Accept": "application/json, text/plain",
|
|
288
257
|
...(type && { "Content-Type": type }),
|
|
289
|
-
...(options?.
|
|
258
|
+
...(options?.bearer && { "Authorization": `Bearer ${options.bearer}` }),
|
|
290
259
|
...options?.headers,
|
|
291
260
|
};
|
|
292
261
|
}
|
|
@@ -305,6 +274,24 @@ function _getContentType(body) {
|
|
|
305
274
|
return "application/json";
|
|
306
275
|
return "application/octet-stream";
|
|
307
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
|
+
}
|
|
308
295
|
/**
|
|
309
296
|
* Waits for specified seconds with optional randomization.
|
|
310
297
|
* @internal
|
|
@@ -330,18 +317,19 @@ function _shouldRedirect(resp) {
|
|
|
330
317
|
* Determines if retry should stop based on conditions and waits if continuing.
|
|
331
318
|
* @internal
|
|
332
319
|
* @param count - Current retry attempt number.
|
|
320
|
+
* @param init - Request initialization object.
|
|
333
321
|
* @param opts - Internal options.
|
|
334
322
|
* @param resp - Response from previous attempt.
|
|
335
323
|
* @returns True if retry should stop.
|
|
336
324
|
*/
|
|
337
|
-
async function _shouldNotRetry(count, opts, resp) {
|
|
338
|
-
if (count >= opts.
|
|
325
|
+
async function _shouldNotRetry(count, init, opts, resp) {
|
|
326
|
+
if (count >= opts.maxAttempts - 1 || init.signal?.aborted || resp?.ok)
|
|
339
327
|
return true;
|
|
340
328
|
if (resp && _shouldRedirect(resp)) {
|
|
341
|
-
if (opts.
|
|
329
|
+
if (opts.redirect === "manual")
|
|
342
330
|
return true;
|
|
343
|
-
if (opts.
|
|
344
|
-
opts.
|
|
331
|
+
if (opts.redirect === "error") {
|
|
332
|
+
opts.maxAttempts = 0;
|
|
345
333
|
throw RedirectError.fromResponse(resp);
|
|
346
334
|
}
|
|
347
335
|
}
|
|
@@ -360,7 +348,7 @@ async function _shouldNotRetry(count, opts, resp) {
|
|
|
360
348
|
* @returns Next retry interval in seconds.
|
|
361
349
|
*/
|
|
362
350
|
function _getNextInterval(count, opts, resp) {
|
|
363
|
-
return opts.
|
|
351
|
+
return opts.retryAfter && resp
|
|
364
352
|
? Math.max(_parseRetryAfter(resp.headers.get("Retry-After")?.trim() ?? ""), opts.interval)
|
|
365
353
|
: Math.min(Math.pow(Math.max(1, opts.interval), count), opts.maxInterval);
|
|
366
354
|
}
|
|
@@ -396,6 +384,16 @@ function _handleRedirectResponse(url, init, resp) {
|
|
|
396
384
|
init.method = "GET";
|
|
397
385
|
return url instanceof Request ? new Request(resp.url, url) : resp.url;
|
|
398
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
|
+
}
|
|
399
397
|
/**
|
|
400
398
|
* Executes fetch with retry logic and exponential backoff.
|
|
401
399
|
* @internal
|
|
@@ -405,23 +403,22 @@ function _handleRedirectResponse(url, init, resp) {
|
|
|
405
403
|
* @returns Response from successful request.
|
|
406
404
|
*/
|
|
407
405
|
async function _fetchWithRetry(url, init, opts) {
|
|
408
|
-
|
|
409
|
-
return await _fetchWithTimeout(url, init, opts);
|
|
410
|
-
for (let i = 1; i <= opts.max; i++) {
|
|
406
|
+
for (let i = 0; i < opts.maxAttempts; i++) {
|
|
411
407
|
try {
|
|
412
|
-
const
|
|
413
|
-
|
|
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))
|
|
414
411
|
return resp;
|
|
415
412
|
url = _handleRedirectResponse(url, init, resp);
|
|
416
413
|
continue;
|
|
417
414
|
}
|
|
418
415
|
catch (e) {
|
|
419
|
-
if (await _shouldNotRetry(i, opts))
|
|
416
|
+
if (await _shouldNotRetry(i, init, opts))
|
|
420
417
|
throw e;
|
|
421
418
|
continue;
|
|
422
419
|
}
|
|
423
420
|
}
|
|
424
|
-
|
|
421
|
+
return await _fetchWithJitter(url, init, opts);
|
|
425
422
|
}
|
|
426
423
|
/**
|
|
427
424
|
* Executes fetch with initial jitter delay.
|
|
@@ -432,27 +429,6 @@ async function _fetchWithRetry(url, init, opts) {
|
|
|
432
429
|
* @returns Response from request.
|
|
433
430
|
*/
|
|
434
431
|
async function _fetchWithJitter(url, init, opts) {
|
|
435
|
-
await _wait(opts.
|
|
436
|
-
return await
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Executes fetch with timeout handling.
|
|
440
|
-
* @internal
|
|
441
|
-
* @param url - Request URL.
|
|
442
|
-
* @param init - Request initialization object.
|
|
443
|
-
* @param opts - Internal options.
|
|
444
|
-
* @returns Response from request.
|
|
445
|
-
*/
|
|
446
|
-
async function _fetchWithTimeout(url, init, opts) {
|
|
447
|
-
const req = url instanceof Request ? url.clone() : url;
|
|
448
|
-
const id = opts.abort ? setTimeout(() => opts.abort?.abort("timeout"), opts.timeout * 1000) : 0;
|
|
449
|
-
try {
|
|
450
|
-
return await fetch(req, init);
|
|
451
|
-
}
|
|
452
|
-
catch (e) {
|
|
453
|
-
throw e;
|
|
454
|
-
}
|
|
455
|
-
finally {
|
|
456
|
-
clearTimeout(id);
|
|
457
|
-
}
|
|
432
|
+
await _wait(opts.delay);
|
|
433
|
+
return await fetch(url, init);
|
|
458
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,16 +16,26 @@ 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
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Infer helper type for response type overload.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
type ThrowError = FetchyOptions & Partial<{
|
|
33
|
+
throwError: true;
|
|
34
|
+
}> | FetchyOptions & Partial<{
|
|
35
|
+
throwError: {
|
|
36
|
+
onError: true;
|
|
37
|
+
};
|
|
38
|
+
}>;
|
|
29
39
|
/**
|
|
30
40
|
* Error thrown when HTTP response has a non-OK status code (4xx, 5xx, ...).
|
|
31
41
|
* Only thrown when throwError.onErrorStatus is set to true.
|
|
@@ -98,10 +108,18 @@ declare class RedirectError extends Error {
|
|
|
98
108
|
* const bytes = await fetchyb("https://example.com/image.png", "bytes");
|
|
99
109
|
* ```
|
|
100
110
|
*/
|
|
101
|
-
declare function fetchyb(url: Input, type: "text", options?:
|
|
102
|
-
declare function fetchyb
|
|
103
|
-
declare function fetchyb(url: Input, type: "
|
|
104
|
-
declare function fetchyb<T>(url: Input, type
|
|
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>;
|
|
105
123
|
/**
|
|
106
124
|
* Performs an HTTP request with enhanced features like timeout, retry, and automatic header management.
|
|
107
125
|
* Returns the raw Response object or null on failure, unless throwError is configured.
|
|
@@ -134,7 +152,9 @@ declare function fetchyb<T>(url: Input, type?: "auto", options?: FetchyOptions):
|
|
|
134
152
|
* });
|
|
135
153
|
* ```
|
|
136
154
|
*/
|
|
137
|
-
declare function fetchy(url: Input, options?:
|
|
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>;
|
|
138
158
|
/**
|
|
139
159
|
* Checks if a value is a string.
|
|
140
160
|
* @internal
|
|
@@ -200,11 +220,12 @@ declare function _getOptions(options?: FetchyOptions): Options;
|
|
|
200
220
|
/**
|
|
201
221
|
* Converts FetchyOptions to standard RequestInit format.
|
|
202
222
|
* @internal
|
|
223
|
+
* @param url - Original request URL.
|
|
224
|
+
* @param opts - Internal options.
|
|
203
225
|
* @param options - User-provided options.
|
|
204
|
-
* @param optsAbort - AbortController for timeout handling.
|
|
205
226
|
* @returns Standard RequestInit object.
|
|
206
227
|
*/
|
|
207
|
-
declare function _getRequestInit(
|
|
228
|
+
declare function _getRequestInit(url: Input, opts: Options, options?: FetchyOptions): RequestInit;
|
|
208
229
|
/**
|
|
209
230
|
* Converts FetchyBody to standard BodyInit format.
|
|
210
231
|
* @internal
|
|
@@ -233,6 +254,15 @@ declare function _getHeaders(options?: FetchyOptions): HeadersInit;
|
|
|
233
254
|
* @returns Content-Type string or undefined.
|
|
234
255
|
*/
|
|
235
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;
|
|
236
266
|
/**
|
|
237
267
|
* Waits for specified seconds with optional randomization.
|
|
238
268
|
* @internal
|
|
@@ -251,11 +281,12 @@ declare function _shouldRedirect(resp: Response): boolean;
|
|
|
251
281
|
* Determines if retry should stop based on conditions and waits if continuing.
|
|
252
282
|
* @internal
|
|
253
283
|
* @param count - Current retry attempt number.
|
|
284
|
+
* @param init - Request initialization object.
|
|
254
285
|
* @param opts - Internal options.
|
|
255
286
|
* @param resp - Response from previous attempt.
|
|
256
287
|
* @returns True if retry should stop.
|
|
257
288
|
*/
|
|
258
|
-
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>;
|
|
259
290
|
/**
|
|
260
291
|
* Calculates next retry interval using exponential backoff or Retry-After header.
|
|
261
292
|
* @internal
|
|
@@ -281,6 +312,14 @@ declare function _parseRetryAfter(value: string): number;
|
|
|
281
312
|
* @returns Updated URL for next request.
|
|
282
313
|
*/
|
|
283
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;
|
|
284
323
|
/**
|
|
285
324
|
* Executes fetch with retry logic and exponential backoff.
|
|
286
325
|
* @internal
|
|
@@ -299,13 +338,4 @@ declare function _fetchWithRetry(url: Input, init: RequestInit, opts: Options):
|
|
|
299
338
|
* @returns Response from request.
|
|
300
339
|
*/
|
|
301
340
|
declare function _fetchWithJitter(url: Input, init: RequestInit, opts: Options): Promise<Response>;
|
|
302
|
-
/**
|
|
303
|
-
* Executes fetch with timeout handling.
|
|
304
|
-
* @internal
|
|
305
|
-
* @param url - Request URL.
|
|
306
|
-
* @param init - Request initialization object.
|
|
307
|
-
* @param opts - Internal options.
|
|
308
|
-
* @returns Response from request.
|
|
309
|
-
*/
|
|
310
|
-
declare function _fetchWithTimeout(url: Input, init: RequestInit, opts: Options): Promise<Response>;
|
|
311
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"}
|