@superutils/fetch 1.1.7 → 1.2.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 +179 -10
- package/dist/index.d.ts +220 -148
- package/dist/index.js +104 -81
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,10 @@ This package enhances the native `fetch` API by providing a streamlined interfac
|
|
|
13
13
|
- [`Method Specific Functions`](#methods)
|
|
14
14
|
- [`fetch.get.deferred()`](#fetch-deferred): cancellable and debounced or throttled `fetch()`
|
|
15
15
|
- [`fetch.post()`](#post): make post requests
|
|
16
|
-
- [`fetch.post.deferred()`](#post-deferred) cancellable and debounced or throttled `post()`
|
|
16
|
+
- [`fetch.post.deferred()`](#post-deferred): cancellable and debounced or throttled `post()`
|
|
17
|
+
- [`Retry`](#retry) Retry on request failure
|
|
18
|
+
- [`Timeout`](#timeout) Abort request on timeout
|
|
19
|
+
- [`Interceptors/Transformers`](#interceptors)
|
|
17
20
|
|
|
18
21
|
## Features
|
|
19
22
|
|
|
@@ -37,18 +40,14 @@ npm install @superutils/fetch
|
|
|
37
40
|
|
|
38
41
|
### `fetch(url, options)`
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
Use as a drop-in replacement to the built-in `fetch()`.
|
|
41
44
|
|
|
42
|
-
```
|
|
45
|
+
```javascript
|
|
43
46
|
import fetch from '@superutils/fetch'
|
|
44
47
|
|
|
45
|
-
fetch('https://dummyjson.com/products/1'
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Alternative:
|
|
49
|
-
fetch
|
|
50
|
-
.get('https://dummyjson.com/products/1')
|
|
51
|
-
.then(theActualData => console.log(theActualData))
|
|
48
|
+
fetch('https://dummyjson.com/products/1')
|
|
49
|
+
.then(response => response.json())
|
|
50
|
+
.then(console.log)
|
|
52
51
|
```
|
|
53
52
|
|
|
54
53
|
<div id="methods"></div>
|
|
@@ -75,6 +74,16 @@ While `fetch()` provides access to all HTTP request methods by specifying it in
|
|
|
75
74
|
- `fetch.post.deferred(...)`
|
|
76
75
|
- `fetch.put.deferred(...)`
|
|
77
76
|
|
|
77
|
+
All method specific functions by default return result parsed as JSON. No need for `response.json()` or `result.data.data` drilling.
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
import fetch from '@superutils/fetch'
|
|
81
|
+
|
|
82
|
+
fetch
|
|
83
|
+
.get('https://dummyjson.com/products/1')
|
|
84
|
+
.then(product => console.log({ product }))
|
|
85
|
+
```
|
|
86
|
+
|
|
78
87
|
<div id="fetch-deferred"></div>
|
|
79
88
|
|
|
80
89
|
### `fetch.get.deferred(deferOptions, defaultUrl, defaultOptions)`
|
|
@@ -268,3 +277,163 @@ fetch
|
|
|
268
277
|
// Only the final call executes, 300ms after it was made (at the 400ms mark).
|
|
269
278
|
// The token is refreshed only once, preventing redundant network requests.
|
|
270
279
|
```
|
|
280
|
+
|
|
281
|
+
<div id="interceptors"></div>
|
|
282
|
+
|
|
283
|
+
### Interceptors: intercept and/or transform request & result
|
|
284
|
+
|
|
285
|
+
The following interceptor callbacks allow intercepting and/or transforming at different stages of the request.
|
|
286
|
+
|
|
287
|
+
#### Interceptor types (executed in sequence):
|
|
288
|
+
|
|
289
|
+
1. `request`: Request interceptors are executed before a HTTP request is made.
|
|
290
|
+
- To transform the URL simply return a new or modified URL.
|
|
291
|
+
- To transform `fetch` options simply modify the options parameter
|
|
292
|
+
2. `response`: Response interceptors are executed after receiving a `fetch` Response regardless of the HTTP status code.
|
|
293
|
+
3. `result`: Result interceptors are executed before returning the result. To transform the result simply return a new value.
|
|
294
|
+
PS: if the value of `options.as` is `FetchAs.response` (`"response"`), the value received in result will be a `Response` object.
|
|
295
|
+
4. `error`: Error interceptors are executed when the request fails. Error can be transformed by returning a modified/new `FetchError`.
|
|
296
|
+
|
|
297
|
+
#### Notes:
|
|
298
|
+
|
|
299
|
+
- All interceptors can be either asynchronous or synchronous functions.
|
|
300
|
+
- If an exception is raised while executing the interceptors, it will be gracefully ignored.
|
|
301
|
+
- Value returned (transformed) by an interceptor will be carried over to the subsequent interceptor of the same type.
|
|
302
|
+
- There are 2 category of interceptors:
|
|
303
|
+
- Local: interceptors provided when making a request.
|
|
304
|
+
- Global: intereptors that are executed application-wide on every request. Global interceptors can be added/accessed at `fetch.defaults.interceptors`. Global interceptors are always executed before local interceptors.
|
|
305
|
+
|
|
306
|
+
**Example: Add global request and error interceptors**
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
import fetch from '@superutils/fetch'
|
|
310
|
+
|
|
311
|
+
const { interceptors } = fetch.defaults
|
|
312
|
+
interceptors.request.push((url, options) => {
|
|
313
|
+
// a headers to all requests make by the application
|
|
314
|
+
options.headers.append('x-auth', 'token')
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
interceptors.error.push((err, url, options) => {
|
|
318
|
+
// log whenever a request fails
|
|
319
|
+
console.log('Error interceptor', err)
|
|
320
|
+
})
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
```javascript
|
|
324
|
+
import fetch, { FetchError } from '@superutils/fetch'
|
|
325
|
+
|
|
326
|
+
const interceptors = {
|
|
327
|
+
error: [
|
|
328
|
+
(err, url, options) => {
|
|
329
|
+
console.log('Request failed', err, url, options)
|
|
330
|
+
// return nothing/undefined to keep the error unchanged
|
|
331
|
+
// or return modified/new error
|
|
332
|
+
err.message = 'My custom error message!'
|
|
333
|
+
// or create a new FetchError by cloning it (make sure all the required properties are set correctly)
|
|
334
|
+
return err.clone('My custom error message!')
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
request: [
|
|
338
|
+
(url, options) => {
|
|
339
|
+
// add extra headers or modify request options here
|
|
340
|
+
options.headers.append('x-custom-header', 'some value')
|
|
341
|
+
|
|
342
|
+
// transform the URL by returning a modified URL
|
|
343
|
+
return url + '?param=value'
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
response: [
|
|
347
|
+
(response, url, options) => {
|
|
348
|
+
if (response.ok) return
|
|
349
|
+
console.log('request was successful', { url, options })
|
|
350
|
+
|
|
351
|
+
// You can transform the response by returning different `Response` object or even make a completely new HTTP reuqest.
|
|
352
|
+
// The subsequent response interceptors will receive the returned response
|
|
353
|
+
return fetch('https://dummyjson.com/products/1') // promise will be resolved automatically
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
result: [
|
|
357
|
+
(result, url, options) => {
|
|
358
|
+
const productId = Number(
|
|
359
|
+
new URL(url).pathname.split('/products/')[1],
|
|
360
|
+
)
|
|
361
|
+
if (options.method === 'get' && !Number.isNaN(productId)) {
|
|
362
|
+
result.title ??= 'Unknown title'
|
|
363
|
+
}
|
|
364
|
+
return result
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
}
|
|
368
|
+
fetch
|
|
369
|
+
.get('https://dummyjson.com/products/1', { interceptors })
|
|
370
|
+
.then(product => console.log({ product }))
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
<div id="retry"></div>
|
|
374
|
+
|
|
375
|
+
### Retry
|
|
376
|
+
|
|
377
|
+
The `retry` option provides a robust mechanism to automatically re-attempt failed requests, with support for both linear and exponential backoff strategies to gracefully handle transient network issues.
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
import fetch from '@superutils/fetch'
|
|
381
|
+
|
|
382
|
+
fetch.get('https://dummyjson.com/products/1', {
|
|
383
|
+
retry: 3, // Max number of retries.
|
|
384
|
+
retryBackOff: 'linear', // Backoff strategy: 'linear' or 'exponential'.
|
|
385
|
+
// Delay in milliseconds.
|
|
386
|
+
// - 'linear': Constant delay between each attempt.
|
|
387
|
+
// - 'exponential': Initial delay that doubles with each retry.
|
|
388
|
+
retryDelay: 300,
|
|
389
|
+
retryDelayJitter: true, // Add random delay to avoid thundering herd.
|
|
390
|
+
retryDelayJitterMax: 100, // Max jitter delay (ms).
|
|
391
|
+
retryIf: (response, retryCount, error) => {
|
|
392
|
+
console.log('Attempt #', retryCount + 1)
|
|
393
|
+
// re-attempt if status code not 200
|
|
394
|
+
return response.status !== 200
|
|
395
|
+
},
|
|
396
|
+
})
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
<div id="timeout"></div>
|
|
400
|
+
|
|
401
|
+
### Request Timeout
|
|
402
|
+
|
|
403
|
+
A request can be automatically cancelled by simply providing a `timeout` duration in milliseconds. Internally, `fetch` uses an `AbortController` to cancel the request if it does not complete within the specified time.
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
import fetch from '@superutils/fetch'
|
|
407
|
+
|
|
408
|
+
fetch.get('https://dummyjson.com/products/1', {
|
|
409
|
+
timeout: 5000,
|
|
410
|
+
})
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
<div id="fetch-as"></div>
|
|
414
|
+
|
|
415
|
+
### Response Parsing
|
|
416
|
+
|
|
417
|
+
By default, `fetch()` returns a `Response` object, making it a drop-in replacement for the built-in `fetch`.
|
|
418
|
+
|
|
419
|
+
However, all method-specific functions (e.g., `fetch.get`, `fetch.post`, `fetch.get.deferred`) automatically parse and return the result as JSON.
|
|
420
|
+
|
|
421
|
+
To retrieve the response in a different format (e.g., as text, a blob, or the raw `Response` object), set the `as` option to one of the following `FetchAs` values:
|
|
422
|
+
|
|
423
|
+
- `FetchAs.json`
|
|
424
|
+
- `FetchAs.text`
|
|
425
|
+
- `FetchAs.blob`
|
|
426
|
+
- `FetchAs.arrayBuffer`
|
|
427
|
+
- `FetchAs.formData`
|
|
428
|
+
- `FetchAs.bytes`
|
|
429
|
+
- `FetchAs.response`
|
|
430
|
+
|
|
431
|
+
> **Note:** When not using TypeScript, you can simply pass the string value (e.g., `'text'`, `'blob'`, `'response'`).
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
import fetch, { FetchAs } from '@superutils/fetch'
|
|
435
|
+
|
|
436
|
+
fetch.get('https://dummyjson.com/products/1', {
|
|
437
|
+
as: FetchAs.text,
|
|
438
|
+
})
|
|
439
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ValueOrPromise } from '@superutils/core';
|
|
2
1
|
import * as _superutils_promise from '@superutils/promise';
|
|
3
2
|
import { RetryOptions, IPromisE, DeferredAsyncOptions } from '@superutils/promise';
|
|
4
3
|
export { DeferredAsyncOptions, ResolveError, ResolveIgnored } from '@superutils/promise';
|
|
4
|
+
import { ValueOrPromise } from '@superutils/core';
|
|
5
5
|
|
|
6
6
|
type FetchArgs<OmitMethod extends boolean = false> = [
|
|
7
7
|
url: string | URL,
|
|
@@ -46,7 +46,7 @@ type FetchErrMsgs = {
|
|
|
46
46
|
};
|
|
47
47
|
/** Custom error message for fetch requests with more detailed info about the request URL, fetch options and response */
|
|
48
48
|
declare class FetchError extends Error {
|
|
49
|
-
options
|
|
49
|
+
options: FetchOptions;
|
|
50
50
|
response?: Response;
|
|
51
51
|
url: string | URL;
|
|
52
52
|
constructor(message: string, options: {
|
|
@@ -55,6 +55,7 @@ declare class FetchError extends Error {
|
|
|
55
55
|
response?: Response;
|
|
56
56
|
url: string | URL;
|
|
57
57
|
});
|
|
58
|
+
clone: (newMessage: string) => FetchError;
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* Fetch error interceptor to be invoked whenever an exception occurs.
|
|
@@ -97,11 +98,10 @@ declare class FetchError extends Error {
|
|
|
97
98
|
*/
|
|
98
99
|
type FetchInterceptorError = Interceptor<FetchError, FetchArgsInterceptor>;
|
|
99
100
|
/**
|
|
100
|
-
*
|
|
101
101
|
* Fetch request interceptor to be invoked before making a fetch request.
|
|
102
102
|
* This interceptor can also be used as a transformer:
|
|
103
103
|
* 1. by returning an API URL (string/URL)
|
|
104
|
-
* 2. by modifying the properties of the options
|
|
104
|
+
* 2. by modifying the properties of the options parameter to be used before making the fetch request
|
|
105
105
|
*
|
|
106
106
|
* @example intercept and transform fetch request
|
|
107
107
|
* ```typescript
|
|
@@ -119,7 +119,9 @@ type FetchInterceptorError = Interceptor<FetchError, FetchArgsInterceptor>;
|
|
|
119
119
|
* })
|
|
120
120
|
* ```
|
|
121
121
|
*/
|
|
122
|
-
type FetchInterceptorRequest = Interceptor<FetchArgs[0],
|
|
122
|
+
type FetchInterceptorRequest = Interceptor<FetchArgs[0], [
|
|
123
|
+
FetchArgsInterceptor[1]
|
|
124
|
+
]>;
|
|
123
125
|
/**
|
|
124
126
|
* Fetch response interceptor to be invoked before making a fetch request.
|
|
125
127
|
*
|
|
@@ -187,7 +189,7 @@ type FetchInterceptorResponse = Interceptor<Response, FetchArgsInterceptor>;
|
|
|
187
189
|
* })
|
|
188
190
|
* ```
|
|
189
191
|
*/
|
|
190
|
-
type FetchInterceptorResult = Interceptor<unknown,
|
|
192
|
+
type FetchInterceptorResult<Args extends unknown[] = FetchArgsInterceptor> = Interceptor<unknown, Args>;
|
|
191
193
|
/**
|
|
192
194
|
* All valid interceptors for fetch requests are:
|
|
193
195
|
* ---
|
|
@@ -235,7 +237,7 @@ type FetchInterceptors = {
|
|
|
235
237
|
* Fetch request options
|
|
236
238
|
*/
|
|
237
239
|
type FetchOptions = RequestInit & FetchCustomOptions;
|
|
238
|
-
type FetchOptionsDefaults = Omit<FetchOptionsInterceptor, 'method' | 'retryIf'>;
|
|
240
|
+
type FetchOptionsDefaults = Omit<FetchOptionsInterceptor, 'as' | 'method' | 'retryIf'>;
|
|
239
241
|
/**
|
|
240
242
|
* Fetch options available to interceptors
|
|
241
243
|
*/
|
|
@@ -248,7 +250,7 @@ type FetchOptionsInterceptor = Omit<FetchOptions, 'as' | 'errMsgs' | 'intercepto
|
|
|
248
250
|
/**
|
|
249
251
|
* Result types for specific parsers ("as": FetchAs)
|
|
250
252
|
*/
|
|
251
|
-
|
|
253
|
+
type FetchResult<T> = {
|
|
252
254
|
arrayBuffer: ArrayBuffer;
|
|
253
255
|
blob: Blob;
|
|
254
256
|
bytes: Uint8Array<ArrayBuffer>;
|
|
@@ -256,7 +258,7 @@ interface FetchResult<T> {
|
|
|
256
258
|
json: T;
|
|
257
259
|
text: string;
|
|
258
260
|
response: Response;
|
|
259
|
-
}
|
|
261
|
+
};
|
|
260
262
|
/**
|
|
261
263
|
* Fetch retry options
|
|
262
264
|
*/
|
|
@@ -318,12 +320,218 @@ type PostOptions = Omit<FetchOptions, 'method'> & {
|
|
|
318
320
|
method?: 'post' | 'put' | 'patch' | 'delete' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
319
321
|
};
|
|
320
322
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
+
/** Create a method-specific fetch function attached with a `.deferred()` function */
|
|
324
|
+
declare const createFetchMethodFunc: (method?: Pick<FetchOptions, "method">["method"]) => {
|
|
325
|
+
<T, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
|
|
326
|
+
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Create a method-specific function for POST-like methods that automatically stringifies `data`
|
|
331
|
+
* and attached with a `.deferred()` function
|
|
332
|
+
*/
|
|
333
|
+
declare const createPostMethodFunc: (method?: Pick<PostOptions, "method">["method"]) => {
|
|
334
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
335
|
+
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Extended `fetch` with timeout, retry, and other options. Automatically parses as JSON by default on success.
|
|
340
|
+
*
|
|
341
|
+
* @param url request URL
|
|
342
|
+
* @param options (optional) Standard `fetch` options extended with {@link FetchCustomOptions}.
|
|
343
|
+
* Default content type is 'application/json'
|
|
344
|
+
* @param options.as (optional) determines who to parse the result. Default: {@link FetchAs.json}
|
|
345
|
+
* @param options.method (optional) fetch method. Default: `'get'`
|
|
346
|
+
*
|
|
347
|
+
* @example Make a simple HTTP requests
|
|
348
|
+
* ```typescript
|
|
349
|
+
* import { fetch } from '@superutils/fetch'
|
|
350
|
+
*
|
|
351
|
+
* // no need for `response.json()` or `result.data.data` drilling
|
|
352
|
+
* fetch('https://dummyjson.com/products/1')
|
|
353
|
+
* .then(product => console.log(product))
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
declare const fetch: {
|
|
357
|
+
<T, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions): IPromisE<TReturn>;
|
|
323
358
|
/** Default fetch options */
|
|
324
359
|
defaults: FetchOptionsDefaults;
|
|
325
360
|
};
|
|
326
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Drop-in replacement for built-in `fetch()` with with timeout, retry etc options and Response as default return type.
|
|
364
|
+
*
|
|
365
|
+
* @param url request URL
|
|
366
|
+
* @param options (optional) Standard `fetch` options extended with {@link FetchCustomOptions}
|
|
367
|
+
* @param options.as (optional) determines who to parse the result. Default: {@link FetchAs.response}
|
|
368
|
+
* @param options.method (optional) fetch method. Default: `'get'`
|
|
369
|
+
*
|
|
370
|
+
* @example Make a simple HTTP requests
|
|
371
|
+
* ```typescript
|
|
372
|
+
* import { fetchResponse } from '@superutils/fetch'
|
|
373
|
+
*
|
|
374
|
+
* fetchResponse('https://dummyjson.com/products/1')
|
|
375
|
+
* .then(response => response.json())
|
|
376
|
+
* .then(console.log, console.error)
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
declare const fetchResponse: <T = Response, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.response, TReturn = FetchResult<T>[TAs]>(...args: Parameters<typeof fetch<T, TOptions, TAs, TReturn>>) => IPromisE<TReturn>;
|
|
380
|
+
|
|
381
|
+
declare const _get: {
|
|
382
|
+
<T, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
|
|
383
|
+
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
384
|
+
};
|
|
385
|
+
declare const _head: {
|
|
386
|
+
<T, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
|
|
387
|
+
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
388
|
+
};
|
|
389
|
+
declare const _options: {
|
|
390
|
+
<T, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
|
|
391
|
+
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
392
|
+
};
|
|
393
|
+
declare const _delete: {
|
|
394
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
395
|
+
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
396
|
+
};
|
|
397
|
+
declare const _patch: {
|
|
398
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
399
|
+
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
400
|
+
};
|
|
401
|
+
declare const _post: {
|
|
402
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
403
|
+
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
404
|
+
};
|
|
405
|
+
declare const _put: {
|
|
406
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
407
|
+
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
408
|
+
};
|
|
409
|
+
type FetchWithMethods = typeof fetchResponse & {
|
|
410
|
+
/** Default options */
|
|
411
|
+
defaults: typeof fetch.defaults;
|
|
412
|
+
/** Make HTTP `DELETE` request, result automatically parsed as JSON */
|
|
413
|
+
delete: typeof _delete;
|
|
414
|
+
/** Make HTTP `GET` request, result automatically parsed as JSON */
|
|
415
|
+
get: typeof _get;
|
|
416
|
+
/** Make HTTP `HEAD` request, result automatically parsed as JSON */
|
|
417
|
+
head: typeof _head;
|
|
418
|
+
/** Make HTTP `OPTIONS` request, result automatically parsed as JSON */
|
|
419
|
+
options: typeof _options;
|
|
420
|
+
/** Make HTTP `PATCH` request, result automatically parsed as JSON */
|
|
421
|
+
patch: typeof _patch;
|
|
422
|
+
/** Make HTTP `POST` request, result automatically parsed as JSON */
|
|
423
|
+
post: typeof _post;
|
|
424
|
+
/** Make HTTP `PUT` request, result automatically parsed as JSON */
|
|
425
|
+
put: typeof _put;
|
|
426
|
+
};
|
|
427
|
+
/**
|
|
428
|
+
* A `fetch()` replacement that simplifies data fetching with automatic JSON parsing, request timeouts, retries,
|
|
429
|
+
* and handy interceptors that also work as transformers. It also includes deferred and throttled request
|
|
430
|
+
* capabilities for complex asynchronous control flows.
|
|
431
|
+
*
|
|
432
|
+
* Will reject promise if response status code is not 2xx (200 <= status < 300).
|
|
433
|
+
*
|
|
434
|
+
* ## Method Specific Functions
|
|
435
|
+
*
|
|
436
|
+
* While `fetch()` provides access to all HTTP request methods by specifying it in options (eg: `{ method: 'get' }`),
|
|
437
|
+
* for ease of use you can also use the following:
|
|
438
|
+
*
|
|
439
|
+
* - `fetch.delete(...)`
|
|
440
|
+
* - `fetch.get(...)`
|
|
441
|
+
* - `fetch.head(...)`
|
|
442
|
+
* - `fetch.options(...)`
|
|
443
|
+
* - `fetch.patch(...)`
|
|
444
|
+
* - `fetch.post(...)`
|
|
445
|
+
* - `fetch.put(...)`
|
|
446
|
+
*
|
|
447
|
+
* **Deferred variants:** To debounce/throttle requests.
|
|
448
|
+
*
|
|
449
|
+
* - `fetch.delete.deferred(...)`
|
|
450
|
+
* - `fetch.get.deferred(...)`
|
|
451
|
+
* - `fetch.head.deferred(...)`
|
|
452
|
+
* - `fetch.options.deferred(...)`
|
|
453
|
+
* - `fetch.patch.deferred(...)`
|
|
454
|
+
* - `fetch.post.deferred(...)`
|
|
455
|
+
* - `fetch.put.deferred(...)`
|
|
456
|
+
*
|
|
457
|
+
* @template T The type of the value that the `fetch` resolves to.
|
|
458
|
+
* @template TReturn Return value type.
|
|
459
|
+
*
|
|
460
|
+
* If `T` is not specified defaults to the following based on the value of `options.as`:
|
|
461
|
+
* - FetchAs.arrayBuffer: `ArrayBuffer`
|
|
462
|
+
* - FetchAs.blob: `Blob`
|
|
463
|
+
* - FetchAs.bytes: `Uint8Array<ArrayBuffer>`
|
|
464
|
+
* - FetchAs.formData: `FormData`
|
|
465
|
+
* - FetchAs.json: `unknown`
|
|
466
|
+
* - FetchAs.text: `string`
|
|
467
|
+
* - FetchAs.response: `Response`
|
|
468
|
+
* @param url
|
|
469
|
+
* @param options (optional) Standard `fetch` options extended with {@link FetchCustomOptions}
|
|
470
|
+
* @param options.as (optional) determines who to parse the result. Default: {@link FetchAs.response}
|
|
471
|
+
* @param options.headers (optional) request headers
|
|
472
|
+
* Default: `{ 'content-type': `'application/json' }` (unless changed in the fetch.defaults).
|
|
473
|
+
* @param options.method (optional) fetch method. Default: `'get'`
|
|
474
|
+
*
|
|
475
|
+
* Options' default values (excluding `as`, `method` and `retryIf`) can be configured to be EFFECTIVE GLOBALLY.
|
|
476
|
+
*
|
|
477
|
+
* ```typescript
|
|
478
|
+
* import fetch from '@superutils/fetch'
|
|
479
|
+
*
|
|
480
|
+
* fetch.defaults = {
|
|
481
|
+
* errMsgs: {
|
|
482
|
+
* invalidUrl: 'Invalid URL',
|
|
483
|
+
* parseFailed: 'Failed to parse response as',
|
|
484
|
+
* reqTimedout: 'Request timed out',
|
|
485
|
+
* requestFailed: 'Request failed with status code:',
|
|
486
|
+
* },
|
|
487
|
+
* headers: new Headers([['content-type', 'application/json']]),
|
|
488
|
+
* // Global/application-wide Interceptor & Transfermers
|
|
489
|
+
* interceptors: {
|
|
490
|
+
* error: [],
|
|
491
|
+
* request: [],
|
|
492
|
+
* response: [],
|
|
493
|
+
* result: [],
|
|
494
|
+
* },
|
|
495
|
+
* timeout: 0,
|
|
496
|
+
* //........
|
|
497
|
+
* }
|
|
498
|
+
* ```
|
|
499
|
+
*
|
|
500
|
+
* @property options.abortCtrl (optional) if not provided `AbortController` will be instantiated when `timeout` used.
|
|
501
|
+
* @property options.headers (optional) request headers. Default: `{ 'content-type' : 'application/json'}`
|
|
502
|
+
* @property options.interceptors (optional) request interceptor callbacks. See {@link FetchInterceptors} for details.
|
|
503
|
+
* @property options.method (optional) Default: `"get"`
|
|
504
|
+
* @property options.timeout (optional) duration in milliseconds to abort the request if it takes longer.
|
|
505
|
+
* @property options.parse (optional) specify how to parse the result.
|
|
506
|
+
* Default: {@link FetchAs.json}
|
|
507
|
+
* For raw `Response` use {@link FetchAs.response}
|
|
508
|
+
*
|
|
509
|
+
* @example Drop-in replacement for built-in `fetch`
|
|
510
|
+
* ```typescript
|
|
511
|
+
* import fetch from '@superutils/fetch'
|
|
512
|
+
*
|
|
513
|
+
* fetch('https://dummyjson.com/products/1')
|
|
514
|
+
* .then(response => response.json())
|
|
515
|
+
* .then(console.log, console.error)
|
|
516
|
+
* ```
|
|
517
|
+
*
|
|
518
|
+
* @example Method specific function with JSON parsing by default
|
|
519
|
+
* ```typescript
|
|
520
|
+
* import fetch from '@superutils/fetch'
|
|
521
|
+
*
|
|
522
|
+
* // no need for `response.json()` or `result.data.data` drilling
|
|
523
|
+
* fetch.get('https://dummyjson.com/products/1')
|
|
524
|
+
* .then(product => console.log(product))
|
|
525
|
+
* fetch.get('https://dummyjson.com/products/1')
|
|
526
|
+
* .then(product => console.log(product))
|
|
527
|
+
*
|
|
528
|
+
*
|
|
529
|
+
* fetch.post('https://dummyjson.com/products/add', { title: 'Product title' })
|
|
530
|
+
* .then(product => console.log(product))
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
declare const fetchDefault: FetchWithMethods;
|
|
534
|
+
|
|
327
535
|
/**
|
|
328
536
|
* Creates a deferred/throttled version of {@link fetch}, powered by {@link PromisE.deferred}.
|
|
329
537
|
* This is ideal for scenarios requiring advanced control over HTTP requests, such as debouncing search inputs,
|
|
@@ -521,140 +729,4 @@ declare function postDeferred<ThisArg, Delay = unknown, DefaultUrl extends PostA
|
|
|
521
729
|
*/
|
|
522
730
|
declare const mergeFetchOptions: (...allOptions: FetchOptions[]) => FetchOptionsInterceptor;
|
|
523
731
|
|
|
524
|
-
|
|
525
|
-
declare const createFetchMethodFunc: (method?: string) => {
|
|
526
|
-
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
527
|
-
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
528
|
-
};
|
|
529
|
-
/** Create a method-specific function for POST-like methods and with a `.deferred()` function */
|
|
530
|
-
declare const createPostMethodFunc: (method?: Pick<PostOptions, "method">["method"]) => {
|
|
531
|
-
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
532
|
-
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
533
|
-
};
|
|
534
|
-
declare const _get: {
|
|
535
|
-
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
536
|
-
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
537
|
-
};
|
|
538
|
-
declare const _head: {
|
|
539
|
-
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
540
|
-
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
541
|
-
};
|
|
542
|
-
declare const _options: {
|
|
543
|
-
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
544
|
-
deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
545
|
-
};
|
|
546
|
-
declare const _delete: {
|
|
547
|
-
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
548
|
-
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
549
|
-
};
|
|
550
|
-
declare const _patch: {
|
|
551
|
-
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
552
|
-
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
553
|
-
};
|
|
554
|
-
declare const _post: {
|
|
555
|
-
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
556
|
-
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
557
|
-
};
|
|
558
|
-
declare const _put: {
|
|
559
|
-
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
560
|
-
deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
|
|
561
|
-
};
|
|
562
|
-
/**
|
|
563
|
-
* @function fetch
|
|
564
|
-
*
|
|
565
|
-
* A `fetch()` replacement that simplifies data fetching with automatic JSON parsing, request timeouts, retries,
|
|
566
|
-
* and handy interceptors that also work as transformers. It also includes deferred and throttled request
|
|
567
|
-
* capabilities for complex asynchronous control flows.
|
|
568
|
-
*
|
|
569
|
-
* Will reject promise if response status code is not 2xx (200 <= status < 300).
|
|
570
|
-
*
|
|
571
|
-
* ## Method Specific Functions
|
|
572
|
-
*
|
|
573
|
-
* While `fetch()` provides access to all HTTP request methods by specifying it in options (eg: `{ method: 'get' }`),
|
|
574
|
-
* for ease of use you can also use the following:
|
|
575
|
-
*
|
|
576
|
-
* - `fetch.delete(...)`
|
|
577
|
-
* - `fetch.get(...)`
|
|
578
|
-
* - `fetch.head(...)`
|
|
579
|
-
* - `fetch.options(...)`
|
|
580
|
-
* - `fetch.patch(...)`
|
|
581
|
-
* - `fetch.post(...)`
|
|
582
|
-
* - `fetch.put(...)`
|
|
583
|
-
*
|
|
584
|
-
* **Deferred variants:** To debounce/throttle requests.
|
|
585
|
-
*
|
|
586
|
-
* - `fetch.delete.deferred(...)`
|
|
587
|
-
* - `fetch.get.deferred(...)`
|
|
588
|
-
* - `fetch.head.deferred(...)`
|
|
589
|
-
* - `fetch.options.deferred(...)`
|
|
590
|
-
* - `fetch.patch.deferred(...)`
|
|
591
|
-
* - `fetch.post.deferred(...)`
|
|
592
|
-
* - `fetch.put.deferred(...)`
|
|
593
|
-
*
|
|
594
|
-
* @template T The type of the value that the `fetch` resolves to.
|
|
595
|
-
* @template TReturn Return value type.
|
|
596
|
-
*
|
|
597
|
-
* If `T` is not specified defaults to the following based on the value of `options.as`:
|
|
598
|
-
* - FetchAs.arrayBuffer: `ArrayBuffer`
|
|
599
|
-
* - FetchAs.blob: `Blob`
|
|
600
|
-
* - FetchAs.bytes: `Uint8Array<ArrayBuffer>`
|
|
601
|
-
* - FetchAs.formData: `FormData`
|
|
602
|
-
* - FetchAs.json: `unknown`
|
|
603
|
-
* - FetchAs.text: `string`
|
|
604
|
-
* - FetchAs.response: `Response`
|
|
605
|
-
* @param url
|
|
606
|
-
* @param options (optional) all built-in `fetch()` options such as "method", "headers" and the additionals below.
|
|
607
|
-
*
|
|
608
|
-
* Options' default values (excluding `method` and `retryIf`) can be configured to be EFFECTIVE GLOBALLY.
|
|
609
|
-
*
|
|
610
|
-
* ```typescript
|
|
611
|
-
* import fetch from '@superutils/fetch'
|
|
612
|
-
*
|
|
613
|
-
* fetch.defaults = {
|
|
614
|
-
* as: FetchAs.json,
|
|
615
|
-
* errMsgs: {
|
|
616
|
-
* invalidUrl: 'Invalid URL',
|
|
617
|
-
* parseFailed: 'Failed to parse response as',
|
|
618
|
-
* reqTimedout: 'Request timed out',
|
|
619
|
-
* requestFailed: 'Request failed with status code:',
|
|
620
|
-
* },
|
|
621
|
-
* headers: new Headers([['content-type', 'application/json']]),
|
|
622
|
-
* interceptors: {
|
|
623
|
-
* error: [],
|
|
624
|
-
* request: [],
|
|
625
|
-
* response: [],
|
|
626
|
-
* result: [],
|
|
627
|
-
* },
|
|
628
|
-
* timeout: 0,
|
|
629
|
-
* //........
|
|
630
|
-
* }
|
|
631
|
-
* ```
|
|
632
|
-
*
|
|
633
|
-
* @property options.abortCtrl (optional) if not provided `AbortController` will be instantiated when `timeout` used.
|
|
634
|
-
* @property options.headers (optional) request headers. Default: `{ 'content-type' : 'application/json'}`
|
|
635
|
-
* @property options.interceptors (optional) request interceptor callbacks. See {@link FetchInterceptors} for details.
|
|
636
|
-
* @property options.method (optional) Default: `"get"`
|
|
637
|
-
* @property options.timeout (optional) duration in milliseconds to abort the request if it takes longer.
|
|
638
|
-
* @property options.parse (optional) specify how to parse the result.
|
|
639
|
-
* Default: {@link FetchAs.json}
|
|
640
|
-
* For raw `Response` use {@link FetchAs.response}
|
|
641
|
-
*
|
|
642
|
-
* @example Make a simple HTTP requests
|
|
643
|
-
* ```typescript
|
|
644
|
-
* import { fetch } from '@superutils/fetch'
|
|
645
|
-
*
|
|
646
|
-
* // no need for `response.json()` or `result.data.theActualData` drilling
|
|
647
|
-
* fetch('https://dummyjson.com/products/1').then(theActualData => console.log(theActualData))
|
|
648
|
-
* ```
|
|
649
|
-
*/
|
|
650
|
-
declare const fetch: typeof fetch$1 & {
|
|
651
|
-
delete: typeof _delete;
|
|
652
|
-
get: typeof _get;
|
|
653
|
-
head: typeof _head;
|
|
654
|
-
options: typeof _options;
|
|
655
|
-
patch: typeof _patch;
|
|
656
|
-
post: typeof _post;
|
|
657
|
-
put: typeof _put;
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
export { type FetchArgs, type FetchArgsInterceptor, FetchAs, type FetchCustomOptions, type FetchDeferredArgs, type FetchErrMsgs, FetchError, type FetchInterceptorError, type FetchInterceptorRequest, type FetchInterceptorResponse, type FetchInterceptorResult, type FetchInterceptors, type FetchOptions, type FetchOptionsDefaults, type FetchOptionsInterceptor, type FetchResult, type FetchRetryOptions, type Interceptor, type PostArgs, type PostBody, type PostDeferredCbArgs, type PostOptions, createFetchMethodFunc, createPostMethodFunc, fetch as default, fetch, fetchDeferred, mergeFetchOptions, postDeferred };
|
|
732
|
+
export { type FetchArgs, type FetchArgsInterceptor, FetchAs, type FetchCustomOptions, type FetchDeferredArgs, type FetchErrMsgs, FetchError, type FetchInterceptorError, type FetchInterceptorRequest, type FetchInterceptorResponse, type FetchInterceptorResult, type FetchInterceptors, type FetchOptions, type FetchOptionsDefaults, type FetchOptionsInterceptor, type FetchResult, type FetchRetryOptions, type FetchWithMethods, type Interceptor, type PostArgs, type PostBody, type PostDeferredCbArgs, type PostOptions, createFetchMethodFunc, createPostMethodFunc, fetchDefault as default, fetch, fetchDeferred, fetchResponse, mergeFetchOptions, postDeferred };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/fetch.ts
|
|
2
2
|
import {
|
|
3
3
|
fallbackIfFails as fallbackIfFails2,
|
|
4
|
-
isEmpty as isEmpty2,
|
|
5
4
|
isFn as isFn2,
|
|
6
5
|
isPositiveNumber,
|
|
7
6
|
isPromise,
|
|
@@ -28,27 +27,22 @@ var executeInterceptors_default = executeInterceptors;
|
|
|
28
27
|
import PromisE from "@superutils/promise";
|
|
29
28
|
import { isPositiveInteger } from "@superutils/core";
|
|
30
29
|
var getResponse = async (...[url, options = {}]) => {
|
|
30
|
+
const fetchFunc = globalThis.fetch;
|
|
31
|
+
if (!isPositiveInteger(options.retry)) return fetchFunc(url, options);
|
|
31
32
|
let attemptCount = 0;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
};
|
|
44
|
-
if (!isPositiveInteger(options.retry)) return doFetch();
|
|
45
|
-
const response = PromisE.retry(doFetch, {
|
|
46
|
-
...options,
|
|
47
|
-
retryIf: async (res, count) => {
|
|
48
|
-
var _a;
|
|
49
|
-
return (res == null ? void 0 : res.ok) === false || await ((_a = options == null ? void 0 : options.retryIf) == null ? void 0 : _a.call(options, res, count)) === true;
|
|
33
|
+
const response = PromisE.retry(
|
|
34
|
+
() => {
|
|
35
|
+
attemptCount++;
|
|
36
|
+
return fetchFunc(url, options);
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
...options,
|
|
40
|
+
retryIf: async (res, count) => {
|
|
41
|
+
var _a;
|
|
42
|
+
return (res == null ? void 0 : res.ok) === false || await ((_a = options == null ? void 0 : options.retryIf) == null ? void 0 : _a.call(options, res, count)) === true;
|
|
43
|
+
}
|
|
50
44
|
}
|
|
51
|
-
|
|
45
|
+
).catch(
|
|
52
46
|
(err) => Promise.reject(
|
|
53
47
|
new Error(`Request failed after attempt #${attemptCount}`, {
|
|
54
48
|
cause: err
|
|
@@ -114,9 +108,15 @@ var FetchAs = /* @__PURE__ */ ((FetchAs2) => {
|
|
|
114
108
|
FetchAs2["text"] = "text";
|
|
115
109
|
return FetchAs2;
|
|
116
110
|
})(FetchAs || {});
|
|
117
|
-
var FetchError = class extends Error {
|
|
111
|
+
var FetchError = class _FetchError extends Error {
|
|
118
112
|
constructor(message, options) {
|
|
119
113
|
super(message, { cause: options.cause });
|
|
114
|
+
this.clone = (newMessage) => new _FetchError(newMessage, {
|
|
115
|
+
cause: this.cause,
|
|
116
|
+
options: this.options,
|
|
117
|
+
response: this.response,
|
|
118
|
+
url: this.url
|
|
119
|
+
});
|
|
120
120
|
this.name = "FetchError";
|
|
121
121
|
this.options = options.options;
|
|
122
122
|
this.response = options.response;
|
|
@@ -129,17 +129,18 @@ var fetch = (url, options = {}) => {
|
|
|
129
129
|
let abortCtrl;
|
|
130
130
|
let timeoutId;
|
|
131
131
|
const promise = new PromisE2(async (resolve, reject) => {
|
|
132
|
-
var _a, _b;
|
|
132
|
+
var _a, _b, _c, _d;
|
|
133
133
|
const _options2 = mergeFetchOptions_default(fetch.defaults, options);
|
|
134
|
-
|
|
134
|
+
(_a = _options2.as) != null ? _a : _options2.as = "json" /* json */;
|
|
135
|
+
(_b = _options2.method) != null ? _b : _options2.method = "get";
|
|
135
136
|
const errorInterceptors = [..._options2.interceptors.error];
|
|
136
137
|
const requestInterceptors = [..._options2.interceptors.request];
|
|
137
138
|
const responseInterceptors = [..._options2.interceptors.response];
|
|
138
139
|
const resultInterceptors = [..._options2.interceptors.result];
|
|
139
|
-
url = await executeInterceptors_default(url, requestInterceptors,
|
|
140
|
+
url = await executeInterceptors_default(url, requestInterceptors, _options2);
|
|
140
141
|
const { as: parseAs, errMsgs, timeout } = _options2;
|
|
141
142
|
if (isPositiveNumber(timeout)) {
|
|
142
|
-
(
|
|
143
|
+
(_c = _options2.abortCtrl) != null ? _c : _options2.abortCtrl = new AbortController();
|
|
143
144
|
timeoutId = setTimeout(() => {
|
|
144
145
|
var _a2;
|
|
145
146
|
return (_a2 = _options2.abortCtrl) == null ? void 0 : _a2.abort();
|
|
@@ -161,14 +162,14 @@ var fetch = (url, options = {}) => {
|
|
|
161
162
|
const { status = 0 } = response;
|
|
162
163
|
const isSuccess = status >= 200 && status < 300;
|
|
163
164
|
if (!isSuccess) {
|
|
165
|
+
const fallbackMsg = `${errMsgs.requestFailed} ${status}`;
|
|
164
166
|
const jsonError = await fallbackIfFails2(
|
|
165
167
|
// try to parse error response as json first
|
|
166
168
|
() => response.json(),
|
|
167
169
|
[],
|
|
168
|
-
|
|
169
|
-
`Request failed with status code: ${status}`
|
|
170
|
+
void 0
|
|
170
171
|
);
|
|
171
|
-
const message = (jsonError == null ? void 0 : jsonError.message) ||
|
|
172
|
+
const message = (jsonError == null ? void 0 : jsonError.message) || fallbackMsg;
|
|
172
173
|
throw new Error(`${message}`.replace("Error: ", ""), {
|
|
173
174
|
cause: jsonError
|
|
174
175
|
});
|
|
@@ -181,23 +182,23 @@ var fetch = (url, options = {}) => {
|
|
|
181
182
|
`${errMsgs.parseFailed} ${parseAs}. ${err == null ? void 0 : err.message}`,
|
|
182
183
|
{ cause: err }
|
|
183
184
|
);
|
|
184
|
-
return
|
|
185
|
+
return Promise.reject(err);
|
|
185
186
|
};
|
|
186
187
|
result = parseFunc.bind(response)();
|
|
187
188
|
if (isPromise(result)) result = result.catch(handleErr);
|
|
188
|
-
result = await executeInterceptors_default(
|
|
189
|
-
result,
|
|
190
|
-
resultInterceptors,
|
|
191
|
-
url,
|
|
192
|
-
_options2
|
|
193
|
-
);
|
|
194
189
|
}
|
|
190
|
+
result = await executeInterceptors_default(
|
|
191
|
+
result,
|
|
192
|
+
resultInterceptors,
|
|
193
|
+
url,
|
|
194
|
+
_options2
|
|
195
|
+
);
|
|
195
196
|
resolve(result);
|
|
196
197
|
} catch (err) {
|
|
197
198
|
const errX = err;
|
|
198
199
|
const msg = (errX == null ? void 0 : errX.name) === "AbortError" ? errMsgs.reqTimedout : err == null ? void 0 : err.message;
|
|
199
200
|
let error = new FetchError(msg, {
|
|
200
|
-
cause: (
|
|
201
|
+
cause: (_d = errX == null ? void 0 : errX.cause) != null ? _d : err,
|
|
201
202
|
response: errResponse,
|
|
202
203
|
options: _options2,
|
|
203
204
|
url
|
|
@@ -216,7 +217,6 @@ var fetch = (url, options = {}) => {
|
|
|
216
217
|
return promise;
|
|
217
218
|
};
|
|
218
219
|
fetch.defaults = {
|
|
219
|
-
as: "json" /* json */,
|
|
220
220
|
errMsgs: {
|
|
221
221
|
invalidUrl: "Invalid URL",
|
|
222
222
|
parseFailed: "Failed to parse response as",
|
|
@@ -237,6 +237,7 @@ fetch.defaults = {
|
|
|
237
237
|
response: [],
|
|
238
238
|
result: []
|
|
239
239
|
},
|
|
240
|
+
/** Request timeout duration in milliseconds. Default: `0` */
|
|
240
241
|
timeout: 0
|
|
241
242
|
};
|
|
242
243
|
var fetch_default = fetch;
|
|
@@ -263,25 +264,37 @@ function fetchDeferred(deferOptions = {}, defaultUrl, defaultOptions) {
|
|
|
263
264
|
}
|
|
264
265
|
var fetchDeferred_default = fetchDeferred;
|
|
265
266
|
|
|
266
|
-
// src/
|
|
267
|
-
|
|
267
|
+
// src/createFetchMethodFunc.ts
|
|
268
|
+
var createFetchMethodFunc = (method = "get") => {
|
|
269
|
+
const methodFunc = (...args) => {
|
|
270
|
+
var _a;
|
|
271
|
+
(_a = args[1]) != null ? _a : args[1] = {};
|
|
272
|
+
args[1].method = method;
|
|
273
|
+
return fetch_default(...args);
|
|
274
|
+
};
|
|
275
|
+
methodFunc.deferred = (...args) => {
|
|
276
|
+
var _a;
|
|
277
|
+
(_a = args[2]) != null ? _a : args[2] = {};
|
|
278
|
+
args[2].method = method;
|
|
279
|
+
return fetchDeferred_default(...args);
|
|
280
|
+
};
|
|
281
|
+
return methodFunc;
|
|
282
|
+
};
|
|
283
|
+
var createFetchMethodFunc_default = createFetchMethodFunc;
|
|
268
284
|
|
|
269
285
|
// src/post.ts
|
|
270
286
|
import { isFn as isFn3, isStr } from "@superutils/core";
|
|
271
287
|
function post(...[url = "", data, options = {}]) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
},
|
|
279
|
-
options
|
|
280
|
-
)
|
|
281
|
-
);
|
|
288
|
+
var _a;
|
|
289
|
+
(_a = options.method) != null ? _a : options.method = "post";
|
|
290
|
+
return fetch_default(url, {
|
|
291
|
+
...options,
|
|
292
|
+
body: isStr(data) ? data : JSON.stringify(isFn3(data) ? data() : data)
|
|
293
|
+
});
|
|
282
294
|
}
|
|
283
295
|
|
|
284
296
|
// src/postDeferred.ts
|
|
297
|
+
import PromisE4 from "@superutils/promise";
|
|
285
298
|
function postDeferred(deferOptions = {}, defaultUrl, defaultData, defaultOptions) {
|
|
286
299
|
let _abortCtrl;
|
|
287
300
|
const doPost = (...args) => {
|
|
@@ -304,21 +317,7 @@ function postDeferred(deferOptions = {}, defaultUrl, defaultData, defaultOptions
|
|
|
304
317
|
}
|
|
305
318
|
var postDeferred_default = postDeferred;
|
|
306
319
|
|
|
307
|
-
// src/
|
|
308
|
-
var createFetchMethodFunc = (method = "get") => {
|
|
309
|
-
const methodFunc = (url, options) => {
|
|
310
|
-
options != null ? options : options = {};
|
|
311
|
-
options.method = method;
|
|
312
|
-
return fetch_default(url, options);
|
|
313
|
-
};
|
|
314
|
-
methodFunc.deferred = (...args) => {
|
|
315
|
-
var _a;
|
|
316
|
-
(_a = args[2]) != null ? _a : args[2] = {};
|
|
317
|
-
args[2].method = method;
|
|
318
|
-
return fetchDeferred_default(...args);
|
|
319
|
-
};
|
|
320
|
-
return methodFunc;
|
|
321
|
-
};
|
|
320
|
+
// src/createPostMethodFunc.ts
|
|
322
321
|
var createPostMethodFunc = (method = "post") => {
|
|
323
322
|
const methodFunc = (url, data, options) => {
|
|
324
323
|
options != null ? options : options = {};
|
|
@@ -333,22 +332,45 @@ var createPostMethodFunc = (method = "post") => {
|
|
|
333
332
|
};
|
|
334
333
|
return methodFunc;
|
|
335
334
|
};
|
|
336
|
-
var
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
var
|
|
340
|
-
var
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
var
|
|
335
|
+
var createPostMethodFunc_default = createPostMethodFunc;
|
|
336
|
+
|
|
337
|
+
// src/fetchResponse.ts
|
|
338
|
+
var fetchResponse = (...args) => {
|
|
339
|
+
var _a, _b, _c;
|
|
340
|
+
(_a = args[1]) != null ? _a : args[1] = {};
|
|
341
|
+
(_c = (_b = args[1]).as) != null ? _c : _b.as = "response" /* response */;
|
|
342
|
+
return fetch_default(...args);
|
|
343
|
+
};
|
|
344
|
+
var fetchResponse_default = fetchResponse;
|
|
345
|
+
|
|
346
|
+
// src/fetchDefault.ts
|
|
347
|
+
var _get = createFetchMethodFunc_default("get");
|
|
348
|
+
var _head = createFetchMethodFunc_default("head");
|
|
349
|
+
var _options = createFetchMethodFunc_default("options");
|
|
350
|
+
var _delete = createPostMethodFunc_default("delete");
|
|
351
|
+
var _patch = createPostMethodFunc_default("patch");
|
|
352
|
+
var _post = createPostMethodFunc_default("post");
|
|
353
|
+
var _put = createPostMethodFunc_default("put");
|
|
354
|
+
var fetchDefault = fetchResponse_default;
|
|
355
|
+
Object.defineProperty(fetchDefault, "defaults", {
|
|
356
|
+
get() {
|
|
357
|
+
return fetch_default.defaults;
|
|
358
|
+
},
|
|
359
|
+
set(newDefaults) {
|
|
360
|
+
fetch_default.defaults = newDefaults;
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
fetchDefault.delete = _delete;
|
|
364
|
+
fetchDefault.get = _get;
|
|
365
|
+
fetchDefault.head = _head;
|
|
366
|
+
fetchDefault.options = _options;
|
|
367
|
+
fetchDefault.patch = _patch;
|
|
368
|
+
fetchDefault.post = _post;
|
|
369
|
+
fetchDefault.put = _put;
|
|
370
|
+
var fetchDefault_default = fetchDefault;
|
|
371
|
+
|
|
372
|
+
// src/index.ts
|
|
373
|
+
var index_default = fetchDefault_default;
|
|
352
374
|
export {
|
|
353
375
|
FetchAs,
|
|
354
376
|
FetchError,
|
|
@@ -357,8 +379,9 @@ export {
|
|
|
357
379
|
createFetchMethodFunc,
|
|
358
380
|
createPostMethodFunc,
|
|
359
381
|
index_default as default,
|
|
360
|
-
|
|
382
|
+
fetch,
|
|
361
383
|
fetchDeferred,
|
|
384
|
+
fetchResponse,
|
|
362
385
|
mergeFetchOptions,
|
|
363
386
|
postDeferred
|
|
364
387
|
};
|
package/package.json
CHANGED