@superutils/fetch 1.2.1 → 1.2.2
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 +94 -2
- package/dist/index.d.ts +144 -226
- package/dist/index.js +122 -110
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,19 +4,28 @@ A lightweight `fetch` wrapper for browsers and Node.js, designed to simplify dat
|
|
|
4
4
|
|
|
5
5
|
This package enhances the native `fetch` API by providing a streamlined interface and integrating practical & useful features from `@superutils/promise`. It offers built-in support for automatic retries, request timeouts, interceptors, and effortless request cancellation, making complex asynchronous flows simple and manageable.
|
|
6
6
|
|
|
7
|
+
<div v-if="false">
|
|
8
|
+
|
|
9
|
+
For full API reference check out the [docs page](https://alien45.github.io/superutils/packages/@superutils/fetch/).
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
7
13
|
## Table of Contents
|
|
8
14
|
|
|
9
15
|
- Features
|
|
10
16
|
- Installation
|
|
11
17
|
- Usage
|
|
12
|
-
- [`fetch()`](#fetch):
|
|
18
|
+
- [`fetch()`](#fetch): drop-in replacement for built-in `fetch()`
|
|
19
|
+
- [`PromisE Features`](#promise-features): status, early finalization etc
|
|
13
20
|
- [`Method Specific Functions`](#methods)
|
|
21
|
+
- [`fetch.get()`](#fetch-get)
|
|
14
22
|
- [`fetch.get.deferred()`](#fetch-deferred): cancellable and debounced or throttled `fetch()`
|
|
15
23
|
- [`fetch.post()`](#post): make post requests
|
|
16
24
|
- [`fetch.post.deferred()`](#post-deferred): cancellable and debounced or throttled `post()`
|
|
17
25
|
- [`Retry`](#retry) Retry on request failure
|
|
18
26
|
- [`Timeout`](#timeout) Abort request on timeout
|
|
19
27
|
- [`Interceptors/Transformers`](#interceptors)
|
|
28
|
+
- [`Reusable Clients`](#reusable-clients)
|
|
20
29
|
|
|
21
30
|
## Features
|
|
22
31
|
|
|
@@ -40,7 +49,7 @@ npm install @superutils/fetch
|
|
|
40
49
|
|
|
41
50
|
### `fetch(url, options)`
|
|
42
51
|
|
|
43
|
-
Use as a drop-in replacement to
|
|
52
|
+
Use as a drop-in replacement to built-in `fetch()`.
|
|
44
53
|
|
|
45
54
|
```javascript
|
|
46
55
|
import fetch from '@superutils/fetch'
|
|
@@ -50,6 +59,48 @@ fetch('https://dummyjson.com/products/1')
|
|
|
50
59
|
.then(console.log)
|
|
51
60
|
```
|
|
52
61
|
|
|
62
|
+
<div id="promise-features"></div>
|
|
63
|
+
|
|
64
|
+
### PromisE Instance: status, early cancellation
|
|
65
|
+
|
|
66
|
+
All fetch calls return a `PromisE` (`@superutils/promise`) instance which means they come with additional features available in `PromisE`:
|
|
67
|
+
|
|
68
|
+
1. Status tracking: all instances come with `.pending`, `.resolved` and `.rejected` attributes that indicate the current state of the promise.
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
import fetch from '@superutils/fetch'
|
|
72
|
+
|
|
73
|
+
const request = fetch('https://dummyjson.com/products/1')
|
|
74
|
+
|
|
75
|
+
console.log(request.pending) // true
|
|
76
|
+
|
|
77
|
+
request.then(() => {
|
|
78
|
+
console.log(request.resolved) // true
|
|
79
|
+
console.log(request.pending) // false
|
|
80
|
+
console.log(request.rejected) // false
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
2. Early finalization: all `PromisE` instances expose `.resolve()` and `.reject()` methods that allow early finalization and `.onEarlyFinalize` array that allows adding callbacks to be executed when the promise is finalized externally using these methods. Fetch promises utilize this to abort the request when appropriate.
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
import fetch from '@superutils/fetch'
|
|
88
|
+
|
|
89
|
+
// Request that will take 5 seconds to resolve
|
|
90
|
+
const request = fetch('https://dummyjson.com/products?delay=5000')
|
|
91
|
+
|
|
92
|
+
request.then(result => console.log(result), console.warn)
|
|
93
|
+
|
|
94
|
+
// Add a callback to do stuff whenever request is aborted externally.
|
|
95
|
+
// This will not be invoked if fetch fails or resolves (promise finalized naturally) using the Promise executor.
|
|
96
|
+
request.onEarlyFinalize.push((resolved, valueOrReason) =>
|
|
97
|
+
console.log('Aborted externally:', { resolved, valueOrReason }),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
// resolve/reject before the promise is finalized
|
|
101
|
+
request.reject(new Error('No longer needed'))
|
|
102
|
+
```
|
|
103
|
+
|
|
53
104
|
<div id="methods"></div>
|
|
54
105
|
|
|
55
106
|
### Method Specific Functions
|
|
@@ -76,6 +127,14 @@ While `fetch()` provides access to all HTTP request methods by specifying it in
|
|
|
76
127
|
|
|
77
128
|
All method specific functions by default return result parsed as JSON. No need for `response.json()` or `result.data.data` drilling.
|
|
78
129
|
|
|
130
|
+
<div id="fetch-get"></div>
|
|
131
|
+
|
|
132
|
+
### `fetch.get(url, options)`
|
|
133
|
+
|
|
134
|
+
Performs a GET request and returns the result parsed as JSON by default.
|
|
135
|
+
|
|
136
|
+
Equivalent to `fetch(url, { method: 'get', as: 'json' })`.
|
|
137
|
+
|
|
79
138
|
```javascript
|
|
80
139
|
import fetch from '@superutils/fetch'
|
|
81
140
|
|
|
@@ -437,3 +496,36 @@ fetch.get('https://dummyjson.com/products/1', {
|
|
|
437
496
|
as: FetchAs.text,
|
|
438
497
|
})
|
|
439
498
|
```
|
|
499
|
+
|
|
500
|
+
<div id="reusable-clients"></div>
|
|
501
|
+
|
|
502
|
+
### `createClient(method, )`: Reusable Clients
|
|
503
|
+
|
|
504
|
+
The `createClient` utility allows you to generate pre-configured fetch functions with default options, such as headers, timeouts, or specific HTTP methods. This is ideal for creating dedicated API clients for specific services to avoid repetition.
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
import { createClient } from '@superutils/fetch'
|
|
508
|
+
|
|
509
|
+
// Create a client with default headers and a 5-second timeout
|
|
510
|
+
const apiClient = createClient(undefined, {
|
|
511
|
+
headers: {
|
|
512
|
+
Authorization: 'Bearer my-secret-token',
|
|
513
|
+
'Content-Type': 'application/json',
|
|
514
|
+
},
|
|
515
|
+
timeout: 5000,
|
|
516
|
+
})
|
|
517
|
+
|
|
518
|
+
// Use it just like the standard fetch
|
|
519
|
+
apiClient('https://dummyjson.com/products/1').then(console.log)
|
|
520
|
+
|
|
521
|
+
// Create a specialized POST client
|
|
522
|
+
const createProduct = createClient(
|
|
523
|
+
'get', // if provided will force all requests to be of this
|
|
524
|
+
{ timeout: 10000 },
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
// No need to specify method: 'post'
|
|
528
|
+
createProduct('https://dummyjson.com/products/add', {
|
|
529
|
+
body: JSON.stringify({ title: 'New Product' }),
|
|
530
|
+
}).then(console.log)
|
|
531
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import * as _superutils_promise from '@superutils/promise';
|
|
2
|
-
import { RetryOptions,
|
|
2
|
+
import { RetryOptions, DeferredAsyncOptions, IPromisE } from '@superutils/promise';
|
|
3
3
|
export { DeferredAsyncOptions, ResolveError, ResolveIgnored } from '@superutils/promise';
|
|
4
4
|
import { ValueOrPromise } from '@superutils/core';
|
|
5
5
|
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
type ExcludeOptions<Target, // options to exclude
|
|
7
|
+
Options extends FetchOptions = FetchOptions> = Target extends FetchOptions ? {
|
|
8
|
+
headers?: Options['headers'];
|
|
9
|
+
} & Omit<Options, 'headers' | keyof Target> & Partial<Record<Exclude<keyof Target, 'headers'>, never>> : Options;
|
|
10
|
+
type ExcludePostOptions<Target> = ExcludeOptions<Target, PostOptions>;
|
|
11
|
+
type FetchArgs = [url: string | URL, options?: FetchOptions];
|
|
10
12
|
type FetchArgsInterceptor = [
|
|
11
13
|
url: string | URL,
|
|
12
14
|
options: FetchOptionsInterceptor
|
|
@@ -20,6 +22,10 @@ declare enum FetchAs {
|
|
|
20
22
|
response = "response",
|
|
21
23
|
text = "text"
|
|
22
24
|
}
|
|
25
|
+
/** Extract `FetchAs` from `FetchOptions` */
|
|
26
|
+
type FetchAsFromOptions<TOptions, TFallback = FetchAs.json> = TOptions extends {
|
|
27
|
+
as: infer As;
|
|
28
|
+
} ? As extends FetchAs ? As : TFallback : TFallback;
|
|
23
29
|
/** Custom fetch options (not used by built-in `fetch()`*/
|
|
24
30
|
type FetchCustomOptions = {
|
|
25
31
|
/**
|
|
@@ -28,10 +34,12 @@ type FetchCustomOptions = {
|
|
|
28
34
|
*/
|
|
29
35
|
as?: FetchAs;
|
|
30
36
|
abortCtrl?: AbortController;
|
|
37
|
+
body?: PostBody | (() => PostBody);
|
|
31
38
|
errMsgs?: FetchErrMsgs;
|
|
32
39
|
interceptors?: FetchInterceptors;
|
|
33
40
|
/** Request timeout in milliseconds. */
|
|
34
41
|
timeout?: number;
|
|
42
|
+
validateUrl?: boolean;
|
|
35
43
|
} & FetchRetryOptions;
|
|
36
44
|
/** Default args */
|
|
37
45
|
type FetchDeferredArgs<OmitMethod extends boolean = false> = [
|
|
@@ -214,7 +222,7 @@ type FetchInterceptorResult<Args extends unknown[] = FetchArgsInterceptor> = Int
|
|
|
214
222
|
* ---
|
|
215
223
|
* 1. Any exception thrown by interceptors will gracefully ignored.
|
|
216
224
|
* 2. Interceptors will be executed in the sequence they're given.
|
|
217
|
-
* 3. Execution priority: global
|
|
225
|
+
* 3. Execution priority: global interceptors will always be executed before local interceptors.
|
|
218
226
|
*
|
|
219
227
|
*
|
|
220
228
|
*
|
|
@@ -236,7 +244,7 @@ type FetchInterceptors = {
|
|
|
236
244
|
/**
|
|
237
245
|
* Fetch request options
|
|
238
246
|
*/
|
|
239
|
-
type FetchOptions = RequestInit & FetchCustomOptions;
|
|
247
|
+
type FetchOptions = Omit<RequestInit, 'body'> & FetchCustomOptions;
|
|
240
248
|
type FetchOptionsDefaults = Omit<FetchOptionsInterceptor, 'as' | 'method' | 'retryIf'>;
|
|
241
249
|
/**
|
|
242
250
|
* Fetch options available to interceptors
|
|
@@ -284,55 +292,68 @@ type PostArgs<OmitMethod = false> = [
|
|
|
284
292
|
options?: OmitMethod extends true ? Omit<FetchOptions, 'method'> : PostOptions
|
|
285
293
|
];
|
|
286
294
|
/**
|
|
287
|
-
* Dynamic arguments for
|
|
295
|
+
* Dynamic arguments for deferred post-like methods.
|
|
288
296
|
*
|
|
289
297
|
* @example
|
|
290
298
|
* ```typescript
|
|
299
|
+
* import fetch, { type PostDeferredCbArgs } from '@superutils/fetch'
|
|
300
|
+
*
|
|
291
301
|
* // test with types
|
|
292
|
-
* type T1 =
|
|
293
|
-
* type T2 =
|
|
294
|
-
* type T3 =
|
|
295
|
-
* type T4 =
|
|
302
|
+
* type T1 = PostDeferredCbArgs<string | URL, undefined> // expected: [data, options]
|
|
303
|
+
* type T2 = PostDeferredCbArgs<undefined, string> // expected: [url, options]
|
|
304
|
+
* type T3 = PostDeferredCbArgs // expected: [url, data, options]
|
|
305
|
+
* type T4 = PostDeferredCbArgs<string, string> // expected: [options]
|
|
296
306
|
*
|
|
297
307
|
* const data = { name: 'test' }
|
|
298
308
|
* const url = 'https://domain.com'
|
|
299
|
-
* // test with
|
|
300
|
-
* const f1 =
|
|
309
|
+
* // test with fetch.post.deferred()
|
|
310
|
+
* const f1 = fetch.post.deferred({}, 'https://domain.com')
|
|
301
311
|
* // expected: [data, options]
|
|
302
312
|
* f1({data: 1}).then(console.log, console.warn)
|
|
303
313
|
*
|
|
304
|
-
* const f2 =
|
|
314
|
+
* const f2 = fetch.post.deferred({}, undefined, 'dome data')
|
|
305
315
|
* // expected: [url, options]
|
|
306
316
|
* f2('https').then(console.log, console.warn)
|
|
307
317
|
*
|
|
308
|
-
* const f3 =
|
|
318
|
+
* const f3 = fetch.post.deferred({})
|
|
309
319
|
* // expected: [url, data, options]
|
|
310
320
|
* f3('https://domain.com').then(console.log, console.warn)
|
|
311
321
|
*
|
|
312
|
-
* const f4 =
|
|
322
|
+
* const f4 = fetch.post.deferred({}, 'url', 'data')
|
|
313
323
|
* // expected: [options]
|
|
314
324
|
* f4().then(console.log, console.warn)
|
|
315
325
|
* ```
|
|
316
326
|
*/
|
|
317
|
-
type PostDeferredCbArgs<TUrl = undefined, TData = undefined,
|
|
318
|
-
type PostOptions =
|
|
327
|
+
type PostDeferredCbArgs<TUrl = undefined, TData = undefined, Options = PostOptions, CbArgsReq extends unknown[] = Required<PostArgs>> = [TUrl, TData] extends [CbArgsReq[0], undefined] ? [data?: PostArgs[1], options?: Options] : [TUrl, TData] extends [undefined, CbArgsReq[1]] ? [url: PostArgs[0], options?: Options] : [TUrl, TData] extends [CbArgsReq[0], CbArgsReq[1]] ? [options?: Options] : PostArgs;
|
|
328
|
+
type PostOptions = {
|
|
319
329
|
/** Default: `'post'` */
|
|
320
330
|
method?: 'post' | 'put' | 'patch' | 'delete' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
321
|
-
}
|
|
331
|
+
} & Omit<FetchOptions, 'method'>;
|
|
322
332
|
|
|
323
|
-
/**
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
333
|
+
/**
|
|
334
|
+
* Create a reusable fetch client with shared options. The returned function comes attached with a
|
|
335
|
+
* `.deferred()` function for debounced and throttled request.
|
|
336
|
+
*/
|
|
337
|
+
declare const createClient: <MandatoryOpts extends FetchOptions | undefined, CommonOpts extends ExcludeOptions<MandatoryOpts> | undefined, MandatoryAs extends FetchAs | undefined = FetchAsFromOptions<MandatoryOpts, undefined>>(
|
|
338
|
+
/** Mandatory fetch options that cannot be overriden by individual request */
|
|
339
|
+
mandatoryOptions?: MandatoryOpts,
|
|
340
|
+
/** Common fetch options that can be overriden by individual request */
|
|
341
|
+
commonOptions?: FetchOptions & CommonOpts, commonDeferOptions?: DeferredAsyncOptions<unknown, unknown>) => {
|
|
342
|
+
<T, TOptions extends ExcludeOptions<MandatoryOpts> | undefined = ExcludeOptions<MandatoryOpts> | undefined, TAs extends FetchAs = MandatoryAs extends FetchAs ? MandatoryAs : FetchAsFromOptions<TOptions, FetchAsFromOptions<CommonOpts>>, TReturn = FetchResult<T>[TAs]>(url: FetchArgs[0], options?: TOptions): IPromisE<TReturn>;
|
|
343
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends FetchArgs[0] | undefined = string | URL | undefined, DefaultOptions extends ExcludeOptions<MandatoryOpts> | undefined = ExcludeOptions<MandatoryOpts> | undefined>(deferOptions?: DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl, defaultOptions?: DefaultOptions): <TResult = unknown, TOptions_1 extends ExcludeOptions<MandatoryOpts> | undefined = ExcludeOptions<MandatoryOpts> | undefined, TAs_1 extends FetchAs = MandatoryAs extends FetchAs ? MandatoryAs : FetchAsFromOptions<TOptions_1, FetchAsFromOptions<CommonOpts>>, TReturn_1 = FetchResult<TResult>[TAs_1]>(...args: DefaultUrl extends undefined ? [url: FetchArgs[0], options?: TOptions_1] : [options?: TOptions_1]) => IPromisE<TReturn_1>;
|
|
327
344
|
};
|
|
328
345
|
|
|
329
346
|
/**
|
|
330
|
-
* Create a
|
|
331
|
-
*
|
|
347
|
+
* Create a reusable fetch client with shared options. The returned function comes attached with a
|
|
348
|
+
* `.deferred()` function for debounced and throttled request.
|
|
332
349
|
*/
|
|
333
|
-
declare const
|
|
334
|
-
|
|
335
|
-
|
|
350
|
+
declare const createPostClient: <MandatoryOpts extends PostOptions | undefined, CommonOpts extends ExcludePostOptions<MandatoryOpts> | undefined, MandatoryAs extends FetchAs | undefined = FetchAsFromOptions<MandatoryOpts, undefined>>(
|
|
351
|
+
/** Mandatory fetch options that cannot be overriden by individual request */
|
|
352
|
+
mandatoryOptions?: MandatoryOpts,
|
|
353
|
+
/** Common fetch options that can be overriden by individual request */
|
|
354
|
+
commonOptions?: PostOptions & CommonOpts, commonDeferOptions?: DeferredAsyncOptions<unknown, unknown>) => {
|
|
355
|
+
<T, TOptions extends ExcludePostOptions<MandatoryOpts> | undefined, TAs extends FetchAs = MandatoryAs extends FetchAs ? MandatoryAs : FetchAsFromOptions<TOptions, FetchAsFromOptions<CommonOpts>>, TReturn = FetchResult<T>[TAs]>(url: PostArgs[0], data?: PostArgs[1], options?: TOptions): IPromisE<TReturn>;
|
|
356
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends PostArgs[0] | undefined = string | URL | undefined, DefaultData extends PostArgs[1] = PostBody | (() => PostBody) | undefined, DefaultOptions extends ExcludePostOptions<MandatoryOpts> | undefined = ExcludePostOptions<MandatoryOpts> | undefined>(deferOptions?: DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl, defaultData?: DefaultData, defaultOptions?: DefaultOptions): <TResult = unknown, TOptions_1 extends ExcludePostOptions<MandatoryOpts> | undefined = ExcludePostOptions<MandatoryOpts> | undefined, TAs_1 extends FetchAs = MandatoryAs extends FetchAs ? MandatoryAs : FetchAsFromOptions<TOptions_1, FetchAsFromOptions<CommonOpts>>, TReturn_1 = FetchResult<TResult>[TAs_1]>(...args: PostDeferredCbArgs<DefaultUrl, DefaultData, TOptions_1>) => IPromisE<TReturn_1>;
|
|
336
357
|
};
|
|
337
358
|
|
|
338
359
|
/**
|
|
@@ -379,32 +400,108 @@ declare const fetch: {
|
|
|
379
400
|
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
401
|
|
|
381
402
|
declare const _get: {
|
|
382
|
-
<T, TOptions extends
|
|
383
|
-
|
|
403
|
+
<T, TOptions extends ({
|
|
404
|
+
headers?: HeadersInit | undefined;
|
|
405
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
406
|
+
headers?: HeadersInit | undefined;
|
|
407
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: FetchArgs[0], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
408
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends FetchArgs[0] | undefined = string | URL | undefined, DefaultOptions extends ({
|
|
409
|
+
headers?: HeadersInit | undefined;
|
|
410
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
411
|
+
headers?: HeadersInit | undefined;
|
|
412
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
413
|
+
headers?: HeadersInit | undefined;
|
|
414
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
415
|
+
headers?: HeadersInit | undefined;
|
|
416
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: DefaultUrl extends undefined ? [url: string | URL, options?: TOptions | undefined] : [options?: TOptions | undefined]) => _superutils_promise.IPromisE<TReturn>;
|
|
384
417
|
};
|
|
385
418
|
declare const _head: {
|
|
386
|
-
<T, TOptions extends
|
|
387
|
-
|
|
419
|
+
<T, TOptions extends ({
|
|
420
|
+
headers?: HeadersInit | undefined;
|
|
421
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
422
|
+
headers?: HeadersInit | undefined;
|
|
423
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: FetchArgs[0], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
424
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends FetchArgs[0] | undefined = string | URL | undefined, DefaultOptions extends ({
|
|
425
|
+
headers?: HeadersInit | undefined;
|
|
426
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
427
|
+
headers?: HeadersInit | undefined;
|
|
428
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
429
|
+
headers?: HeadersInit | undefined;
|
|
430
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
431
|
+
headers?: HeadersInit | undefined;
|
|
432
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: DefaultUrl extends undefined ? [url: string | URL, options?: TOptions | undefined] : [options?: TOptions | undefined]) => _superutils_promise.IPromisE<TReturn>;
|
|
388
433
|
};
|
|
389
434
|
declare const _options: {
|
|
390
|
-
<T, TOptions extends
|
|
391
|
-
|
|
435
|
+
<T, TOptions extends ({
|
|
436
|
+
headers?: HeadersInit | undefined;
|
|
437
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
438
|
+
headers?: HeadersInit | undefined;
|
|
439
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: FetchArgs[0], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
440
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends FetchArgs[0] | undefined = string | URL | undefined, DefaultOptions extends ({
|
|
441
|
+
headers?: HeadersInit | undefined;
|
|
442
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
443
|
+
headers?: HeadersInit | undefined;
|
|
444
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
445
|
+
headers?: HeadersInit | undefined;
|
|
446
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
447
|
+
headers?: HeadersInit | undefined;
|
|
448
|
+
} & Omit<FetchOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: DefaultUrl extends undefined ? [url: string | URL, options?: TOptions | undefined] : [options?: TOptions | undefined]) => _superutils_promise.IPromisE<TReturn>;
|
|
392
449
|
};
|
|
393
450
|
declare const _delete: {
|
|
394
|
-
<T,
|
|
395
|
-
|
|
451
|
+
<T, TOptions extends ({
|
|
452
|
+
headers?: HeadersInit | undefined;
|
|
453
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: PostArgs[0], data?: PostArgs[1], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
454
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends PostArgs[0] | undefined = string | URL | undefined, DefaultData extends PostArgs[1] = PostBody | (() => PostBody) | undefined, DefaultOptions extends ({
|
|
455
|
+
headers?: HeadersInit | undefined;
|
|
456
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
457
|
+
headers?: HeadersInit | undefined;
|
|
458
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultData?: DefaultData | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
459
|
+
headers?: HeadersInit | undefined;
|
|
460
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
461
|
+
headers?: HeadersInit | undefined;
|
|
462
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: PostDeferredCbArgs<DefaultUrl, DefaultData, TOptions, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TReturn>;
|
|
396
463
|
};
|
|
397
464
|
declare const _patch: {
|
|
398
|
-
<T,
|
|
399
|
-
|
|
465
|
+
<T, TOptions extends ({
|
|
466
|
+
headers?: HeadersInit | undefined;
|
|
467
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: PostArgs[0], data?: PostArgs[1], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
468
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends PostArgs[0] | undefined = string | URL | undefined, DefaultData extends PostArgs[1] = PostBody | (() => PostBody) | undefined, DefaultOptions extends ({
|
|
469
|
+
headers?: HeadersInit | undefined;
|
|
470
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
471
|
+
headers?: HeadersInit | undefined;
|
|
472
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultData?: DefaultData | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
473
|
+
headers?: HeadersInit | undefined;
|
|
474
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
475
|
+
headers?: HeadersInit | undefined;
|
|
476
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: PostDeferredCbArgs<DefaultUrl, DefaultData, TOptions, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TReturn>;
|
|
400
477
|
};
|
|
401
478
|
declare const _post: {
|
|
402
|
-
<T,
|
|
403
|
-
|
|
479
|
+
<T, TOptions extends ({
|
|
480
|
+
headers?: HeadersInit | undefined;
|
|
481
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: PostArgs[0], data?: PostArgs[1], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
482
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends PostArgs[0] | undefined = string | URL | undefined, DefaultData extends PostArgs[1] = PostBody | (() => PostBody) | undefined, DefaultOptions extends ({
|
|
483
|
+
headers?: HeadersInit | undefined;
|
|
484
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
485
|
+
headers?: HeadersInit | undefined;
|
|
486
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultData?: DefaultData | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
487
|
+
headers?: HeadersInit | undefined;
|
|
488
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
489
|
+
headers?: HeadersInit | undefined;
|
|
490
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: PostDeferredCbArgs<DefaultUrl, DefaultData, TOptions, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TReturn>;
|
|
404
491
|
};
|
|
405
492
|
declare const _put: {
|
|
406
|
-
<T,
|
|
407
|
-
|
|
493
|
+
<T, TOptions extends ({
|
|
494
|
+
headers?: HeadersInit | undefined;
|
|
495
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<T>[TAs]>(url: PostArgs[0], data?: PostArgs[1], options?: TOptions | undefined): _superutils_promise.IPromisE<TReturn>;
|
|
496
|
+
deferred<ThisArg = unknown, TDelay extends number = number, DefaultUrl extends PostArgs[0] | undefined = string | URL | undefined, DefaultData extends PostArgs[1] = PostBody | (() => PostBody) | undefined, DefaultOptions extends ({
|
|
497
|
+
headers?: HeadersInit | undefined;
|
|
498
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
499
|
+
headers?: HeadersInit | undefined;
|
|
500
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, TDelay>, defaultUrl?: DefaultUrl | undefined, defaultData?: DefaultData | undefined, defaultOptions?: DefaultOptions | undefined): <TResult = unknown, TOptions extends ({
|
|
501
|
+
headers?: HeadersInit | undefined;
|
|
502
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined = ({
|
|
503
|
+
headers?: HeadersInit | undefined;
|
|
504
|
+
} & Omit<PostOptions, "headers" | "method"> & Partial<Record<"method", never>>) | undefined, TAs extends FetchAs = FetchAsFromOptions<TOptions, FetchAs.json>, TReturn = FetchResult<TResult>[TAs]>(...args: PostDeferredCbArgs<DefaultUrl, DefaultData, TOptions, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TReturn>;
|
|
408
505
|
};
|
|
409
506
|
type FetchWithMethods = typeof fetchResponse & {
|
|
410
507
|
/** Default options */
|
|
@@ -532,192 +629,10 @@ type FetchWithMethods = typeof fetchResponse & {
|
|
|
532
629
|
*/
|
|
533
630
|
declare const fetchDefault: FetchWithMethods;
|
|
534
631
|
|
|
535
|
-
/**
|
|
536
|
-
* Creates a deferred/throttled version of {@link fetch}, powered by {@link PromisE.deferred}.
|
|
537
|
-
* This is ideal for scenarios requiring advanced control over HTTP requests, such as debouncing search inputs,
|
|
538
|
-
* throttling API calls, or ensuring sequential request execution.
|
|
539
|
-
*
|
|
540
|
-
* It leverages the robust capabilities of the underlying {@link fetch} function, which includes features like request timeouts and manual abortion.
|
|
541
|
-
* `fetchDeferred` uses this to automatically abort pending requests when a new one is initiated, preventing race conditions and redundant network traffic.
|
|
542
|
-
*
|
|
543
|
-
* @param deferOptions Configuration for the deferred execution behavior (e.g., `delayMs`, `throttle`).
|
|
544
|
-
* See {@link DeferredAsyncOptions} for details.
|
|
545
|
-
* @param defaultUrl (optional) If a global URL is `undefined`, returned callback will always require an URL.
|
|
546
|
-
* @param defaultOptions (optional) Default {@link FetchOptions} to be used by the returned function.
|
|
547
|
-
* Default options will be merged with the options provided in the callback.
|
|
548
|
-
* If the same property is provided in both cases, defaults will be overriden by the callback.
|
|
549
|
-
*
|
|
550
|
-
* @example Debounce/Throttle requests for an auto-complete search input
|
|
551
|
-
* ```typescript
|
|
552
|
-
* import { fetchDeferred, ResolveIgnored } from '@superutils/fetch'
|
|
553
|
-
*
|
|
554
|
-
* // Create a debounced search function with a 300ms delay.
|
|
555
|
-
* const searchProducts = fetchDeferred({
|
|
556
|
-
* delayMs: 300, // Debounce delay
|
|
557
|
-
* resolveIgnored: ResolveIgnored.WITH_UNDEFINED, // Ignored (aborted) promises will resolve with `undefined`
|
|
558
|
-
* })
|
|
559
|
-
*
|
|
560
|
-
* // User types 'iphone'
|
|
561
|
-
* searchProducts('https://dummyjson.com/products/search?q=iphone').then(result => {
|
|
562
|
-
* console.log('Result for "iphone":', result);
|
|
563
|
-
* });
|
|
564
|
-
*
|
|
565
|
-
* // Before 300ms has passed, the user continues typing 'iphone 9'
|
|
566
|
-
* setTimeout(() => {
|
|
567
|
-
* searchProducts('https://dummyjson.com/products/search?q=iphone 9').then(result => {
|
|
568
|
-
* console.log('Result for "iphone 9":', result);
|
|
569
|
-
* });
|
|
570
|
-
* }, 200);
|
|
571
|
-
*
|
|
572
|
-
* // Outcome:
|
|
573
|
-
* // The first request for "iphone" is aborted.
|
|
574
|
-
* // The first promise resolves with `undefined`.
|
|
575
|
-
* // The second request for "iphone 9" is executed after the 300ms debounce delay.
|
|
576
|
-
* ```
|
|
577
|
-
*
|
|
578
|
-
* @example Creating a reusable, pre-configured client
|
|
579
|
-
* ```typescript
|
|
580
|
-
* import { fetchDeferred, ResolveIgnored } from '@superutils/fetch'
|
|
581
|
-
*
|
|
582
|
-
* // Create a throttled function to fetch a random quote.
|
|
583
|
-
* // The URL and a 3-second timeout are set as defaults, creating a reusable client.
|
|
584
|
-
* const getRandomQuote = fetchDeferred(
|
|
585
|
-
* {
|
|
586
|
-
* delayMs: 300, // Throttle window
|
|
587
|
-
* throttle: true,
|
|
588
|
-
* // Ignored calls will resolve with the result of the last successful call.
|
|
589
|
-
* resolveIgnored: ResolveIgnored.WITH_LAST,
|
|
590
|
-
* },
|
|
591
|
-
* 'https://dummyjson.com/quotes/random', // Default URL
|
|
592
|
-
* { timeout: 3000 }, // Default fetch options
|
|
593
|
-
* )
|
|
594
|
-
*
|
|
595
|
-
* // Call the function multiple times in quick succession.
|
|
596
|
-
* getRandomQuote().then(quote => console.log('Call 1 resolved:', quote.id));
|
|
597
|
-
* getRandomQuote().then(quote => console.log('Call 2 resolved:', quote.id));
|
|
598
|
-
* getRandomQuote().then(quote => console.log('Call 3 resolved:', quote.id));
|
|
599
|
-
*
|
|
600
|
-
* // Outcome:
|
|
601
|
-
* // Due to throttling, only one network request is made.
|
|
602
|
-
* // Because `resolveIgnored` is `WITH_LAST`, all three promises resolve with the same quote.
|
|
603
|
-
* // The promises for the two ignored calls resolve as soon as the first successful call resolves.
|
|
604
|
-
* // Console output will show the same quote ID for all three calls.
|
|
605
|
-
* ```
|
|
606
|
-
*/
|
|
607
|
-
declare function fetchDeferred<ThisArg = unknown, Delay extends number = number, DefaultUrl = FetchArgs[0] | undefined, CbArgs extends unknown[] = undefined extends DefaultUrl ? FetchArgs<false> : [options?: FetchArgs<false>[1]]>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, defaultUrl?: DefaultUrl, defaultOptions?: FetchArgs[1]): <TResult = unknown>(...args: CbArgs) => _superutils_promise.IPromisE<TResult>;
|
|
608
|
-
|
|
609
|
-
/**
|
|
610
|
-
* Creates a deferred/throttled function for making `DELETE`, `POST`, `PUT`, or `PATCH` requests, powered by
|
|
611
|
-
* {@link PromisE.deferred}.
|
|
612
|
-
*
|
|
613
|
-
* This is ideal for scenarios like auto-saving form data, preventing duplicate submissions on button clicks,
|
|
614
|
-
* or throttling API updates.
|
|
615
|
-
*
|
|
616
|
-
* Like `fetchDeferred`, it automatically aborts pending requests when a new one is initiated, ensuring only
|
|
617
|
-
* the most recent or relevant action is executed.
|
|
618
|
-
*
|
|
619
|
-
* @param deferOptions Configuration for the deferred execution behavior (e.g., `delayMs`, `throttle`).
|
|
620
|
-
* See {@link DeferredAsyncOptions} for details.
|
|
621
|
-
* @param defaultUrl (optional) If default URL is `undefined`, returned callback will always require an URL.
|
|
622
|
-
* @param defaultData (optional) If default data is `undefined`, returned callback will allow a data parameter.
|
|
623
|
-
* @param defaultOptions (optional) Default {@link FetchOptions} to be used by the returned function.
|
|
624
|
-
* Default options will be merged with the options provided in the callback.
|
|
625
|
-
* If the same property is provided in both cases, defaults will be overriden by the callback.
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
* #### Example 1: Auto-saving form data with throttling
|
|
629
|
-
*
|
|
630
|
-
* ```typescript
|
|
631
|
-
* import fetch from '@superutils/fetch'
|
|
632
|
-
* import PromisE from '@superutils/promise'
|
|
633
|
-
*
|
|
634
|
-
* // Create a throttled function to auto-save product updates.
|
|
635
|
-
* const saveProductThrottled = fetch.post.deferred(
|
|
636
|
-
* {
|
|
637
|
-
* delayMs: 1000, // Throttle window of 1 second
|
|
638
|
-
* throttle: true,
|
|
639
|
-
* trailing: true, // Ensures the very last update is always saved
|
|
640
|
-
* onResult: product => console.log(`[Saved] Product: ${product.title}`),
|
|
641
|
-
* },
|
|
642
|
-
* 'https://dummyjson.com/products/add', // Default URL
|
|
643
|
-
* )
|
|
644
|
-
* // Simulate a user typing quickly, triggering multiple saves.
|
|
645
|
-
* console.log('User starts typing...')
|
|
646
|
-
*
|
|
647
|
-
* // Executed immediately (leading edge)
|
|
648
|
-
* saveProductThrottled({ title: 'iPhone' })
|
|
649
|
-
* // Ignored (within 1000ms throttle window)
|
|
650
|
-
* PromisE.delay(200, () => saveProductThrottled({ title: 'iPhone 15' }))
|
|
651
|
-
* // Ignored
|
|
652
|
-
* PromisE.delay(300, () => saveProductThrottled({ title: 'iPhone 15 Pro' }))
|
|
653
|
-
* // Queued to execute on the trailing edge
|
|
654
|
-
* PromisE.delay(400, () => saveProductThrottled({ title: 'iPhone 15 Pro Max' }))
|
|
655
|
-
* // Outcome:
|
|
656
|
-
* // The first call ('iPhone') is executed immediately.
|
|
657
|
-
* // The next two calls are ignored by the throttle.
|
|
658
|
-
* // The final call ('iPhone 15 Pro Max') is executed after the 1000ms throttle window closes,
|
|
659
|
-
* // thanks to `trailing: true`.
|
|
660
|
-
* // This results in only two network requests instead of four.
|
|
661
|
-
* ```
|
|
662
|
-
*
|
|
663
|
-
* #### Example 2: debouncing an authentication token refresh
|
|
664
|
-
*
|
|
665
|
-
* ```typescript
|
|
666
|
-
* import fetch from '@superutils/fetch'
|
|
667
|
-
* import PromisE from '@superutils/promise'
|
|
668
|
-
*
|
|
669
|
-
* // Mock a simple token store
|
|
670
|
-
* let currentRefreshToken = ''
|
|
671
|
-
* // Create a debounced function to refresh the auth token.
|
|
672
|
-
* // It waits 300ms after the last call before executing.
|
|
673
|
-
* const requestNewToken = fetch.post.deferred(
|
|
674
|
-
* {
|
|
675
|
-
* delayMs: 300, // debounce delay
|
|
676
|
-
* onResult: ({ refreshToken = '' }) => {
|
|
677
|
-
* console.log(
|
|
678
|
-
* `Auth token successfully refreshed at ${new Date().toISOString()}`,
|
|
679
|
-
* )
|
|
680
|
-
* currentRefreshToken = refreshToken
|
|
681
|
-
* },
|
|
682
|
-
* },
|
|
683
|
-
* 'https://dummyjson.com/auth/refresh', // Default URL
|
|
684
|
-
* () => ({
|
|
685
|
-
* refreshToken: currentRefreshToken,
|
|
686
|
-
* expiresInMins: 30,
|
|
687
|
-
* }),
|
|
688
|
-
* )
|
|
689
|
-
*
|
|
690
|
-
* // First authenticate user to get the initial refresh token and then request new referesh tokens
|
|
691
|
-
* fetch
|
|
692
|
-
* .post<{ refreshToken: string }>(
|
|
693
|
-
* 'https://dummyjson.com/auth/login',
|
|
694
|
-
* {
|
|
695
|
-
* username: 'emilys',
|
|
696
|
-
* password: 'emilyspass',
|
|
697
|
-
* expiresInMins: 30,
|
|
698
|
-
* },
|
|
699
|
-
* { credentials: 'include' },
|
|
700
|
-
* )
|
|
701
|
-
* .then(result => {
|
|
702
|
-
* currentRefreshToken = result?.refreshToken
|
|
703
|
-
*
|
|
704
|
-
* requestNewToken() // Called at 0ms
|
|
705
|
-
* PromisE.delay(50, requestNewToken) // Called at 50ms
|
|
706
|
-
* PromisE.delay(100, requestNewToken) // Called at 100ms
|
|
707
|
-
* }, console.error)
|
|
708
|
-
* // Outcome:
|
|
709
|
-
* // The first two calls are aborted by the debounce mechanism.
|
|
710
|
-
* // Only the final call executes, 300ms after it was made (at the 400ms mark).
|
|
711
|
-
* // The token is refreshed only once, preventing redundant network requests.
|
|
712
|
-
* ```
|
|
713
|
-
*/
|
|
714
|
-
declare function postDeferred<ThisArg, Delay = unknown, DefaultUrl extends PostArgs[0] | undefined = undefined, DefaultData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<DefaultUrl, DefaultData, false>>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, defaultUrl?: DefaultUrl, defaultData?: DefaultData, defaultOptions?: PostArgs[2]): <TResult = unknown>(...args: CbArgs) => _superutils_promise.IPromisE<TResult>;
|
|
715
|
-
|
|
716
632
|
/**
|
|
717
633
|
* Merge one or more {@link FetchOptions}
|
|
718
634
|
*
|
|
719
635
|
* Notes:
|
|
720
|
-
* - {@link config.fetchOptions} will be added as the base and not necessary to be included
|
|
721
636
|
* - item properties will be prioritized in the order of sequence they were passed in
|
|
722
637
|
* - the following properties will be merged
|
|
723
638
|
* * `errMsgs`
|
|
@@ -729,4 +644,7 @@ declare function postDeferred<ThisArg, Delay = unknown, DefaultUrl extends PostA
|
|
|
729
644
|
*/
|
|
730
645
|
declare const mergeFetchOptions: (...allOptions: FetchOptions[]) => FetchOptionsInterceptor;
|
|
731
646
|
|
|
732
|
-
|
|
647
|
+
/** Merges partial fetch options ignoring empty or undefined. Otherwise, will return the first argument. */
|
|
648
|
+
declare const mergePartialOptions: (...optionsAr: (Partial<FetchOptions> | undefined)[]) => Partial<FetchOptions> | undefined;
|
|
649
|
+
|
|
650
|
+
export { type ExcludeOptions, type ExcludePostOptions, type FetchArgs, type FetchArgsInterceptor, FetchAs, type FetchAsFromOptions, 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, createClient, createPostClient, fetchDefault as default, fetch, fetchResponse, mergeFetchOptions, mergePartialOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/createClient.ts
|
|
2
|
+
import PromisE3 from "@superutils/promise";
|
|
3
|
+
|
|
1
4
|
// src/fetch.ts
|
|
2
5
|
import {
|
|
3
6
|
fallbackIfFails as fallbackIfFails2,
|
|
@@ -10,9 +13,9 @@ import PromisE2 from "@superutils/promise";
|
|
|
10
13
|
|
|
11
14
|
// src/executeInterceptors.ts
|
|
12
15
|
import { fallbackIfFails, isFn } from "@superutils/core";
|
|
13
|
-
var executeInterceptors = async (value, interceptors, ...args) => {
|
|
16
|
+
var executeInterceptors = async (value, interceptors = [], ...args) => {
|
|
14
17
|
var _a;
|
|
15
|
-
for (const interceptor of interceptors.filter(isFn)) {
|
|
18
|
+
for (const interceptor of [...interceptors || []].filter(isFn)) {
|
|
16
19
|
value = (_a = await fallbackIfFails(
|
|
17
20
|
interceptor,
|
|
18
21
|
[value, ...args],
|
|
@@ -28,7 +31,8 @@ import PromisE from "@superutils/promise";
|
|
|
28
31
|
import { isPositiveInteger } from "@superutils/core";
|
|
29
32
|
var getResponse = async (...[url, options = {}]) => {
|
|
30
33
|
const fetchFunc = globalThis.fetch;
|
|
31
|
-
if (!isPositiveInteger(options.retry))
|
|
34
|
+
if (!isPositiveInteger(options.retry))
|
|
35
|
+
return fetchFunc(url, options);
|
|
32
36
|
let attemptCount = 0;
|
|
33
37
|
const response = PromisE.retry(
|
|
34
38
|
() => {
|
|
@@ -92,6 +96,10 @@ var mergeFetchOptions = (...allOptions) => allOptions.reduce(
|
|
|
92
96
|
{ headers: new Headers() }
|
|
93
97
|
);
|
|
94
98
|
var mergeFetchOptions_default = mergeFetchOptions;
|
|
99
|
+
var mergePartialOptions = (...optionsAr) => {
|
|
100
|
+
optionsAr = optionsAr.filter((x) => !isEmpty(x));
|
|
101
|
+
return optionsAr.length <= 1 ? optionsAr[0] : mergeFetchOptions(...optionsAr);
|
|
102
|
+
};
|
|
95
103
|
|
|
96
104
|
// src/types.ts
|
|
97
105
|
import {
|
|
@@ -129,18 +137,25 @@ var fetch = (url, options = {}) => {
|
|
|
129
137
|
let abortCtrl;
|
|
130
138
|
let timeoutId;
|
|
131
139
|
const promise = new PromisE2(async (resolve, reject) => {
|
|
132
|
-
var _a, _b, _c
|
|
140
|
+
var _a, _b, _c;
|
|
141
|
+
let errResponse;
|
|
133
142
|
const _options2 = mergeFetchOptions_default(fetch.defaults, options);
|
|
134
143
|
(_a = _options2.as) != null ? _a : _options2.as = "json" /* json */;
|
|
135
144
|
(_b = _options2.method) != null ? _b : _options2.method = "get";
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
_options2.abortCtrl = _options2.abortCtrl instanceof AbortController ? _options2.abortCtrl : new AbortController();
|
|
146
|
+
url = await executeInterceptors_default(
|
|
147
|
+
url,
|
|
148
|
+
_options2.interceptors.request,
|
|
149
|
+
_options2
|
|
150
|
+
);
|
|
151
|
+
const {
|
|
152
|
+
as: parseAs,
|
|
153
|
+
body,
|
|
154
|
+
errMsgs,
|
|
155
|
+
timeout,
|
|
156
|
+
validateUrl = true
|
|
157
|
+
} = _options2;
|
|
142
158
|
if (isPositiveNumber(timeout)) {
|
|
143
|
-
(_c = _options2.abortCtrl) != null ? _c : _options2.abortCtrl = new AbortController();
|
|
144
159
|
timeoutId = setTimeout(() => {
|
|
145
160
|
var _a2;
|
|
146
161
|
return (_a2 = _options2.abortCtrl) == null ? void 0 : _a2.abort();
|
|
@@ -148,13 +163,17 @@ var fetch = (url, options = {}) => {
|
|
|
148
163
|
}
|
|
149
164
|
abortCtrl = _options2.abortCtrl;
|
|
150
165
|
if (_options2.abortCtrl) _options2.signal = _options2.abortCtrl.signal;
|
|
151
|
-
let errResponse;
|
|
152
166
|
try {
|
|
153
|
-
if (!isUrlValid(url, false))
|
|
167
|
+
if (validateUrl && !isUrlValid(url, false))
|
|
168
|
+
throw new Error(errMsgs.invalidUrl);
|
|
169
|
+
if (!["undefined", "string"].includes(typeof body))
|
|
170
|
+
_options2.body = JSON.stringify(
|
|
171
|
+
isFn2(body) ? fallbackIfFails2(body, [], void 0) : body
|
|
172
|
+
);
|
|
154
173
|
let response = await getResponse_default(url, _options2);
|
|
155
174
|
response = await executeInterceptors_default(
|
|
156
175
|
response,
|
|
157
|
-
|
|
176
|
+
_options2.interceptors.response,
|
|
158
177
|
url,
|
|
159
178
|
_options2
|
|
160
179
|
);
|
|
@@ -189,7 +208,7 @@ var fetch = (url, options = {}) => {
|
|
|
189
208
|
}
|
|
190
209
|
result = await executeInterceptors_default(
|
|
191
210
|
result,
|
|
192
|
-
|
|
211
|
+
_options2.interceptors.result,
|
|
193
212
|
url,
|
|
194
213
|
_options2
|
|
195
214
|
);
|
|
@@ -198,14 +217,14 @@ var fetch = (url, options = {}) => {
|
|
|
198
217
|
const errX = err;
|
|
199
218
|
const msg = (errX == null ? void 0 : errX.name) === "AbortError" ? errMsgs.reqTimedout : err == null ? void 0 : err.message;
|
|
200
219
|
let error = new FetchError(msg, {
|
|
201
|
-
cause: (
|
|
220
|
+
cause: (_c = errX == null ? void 0 : errX.cause) != null ? _c : err,
|
|
202
221
|
response: errResponse,
|
|
203
222
|
options: _options2,
|
|
204
223
|
url
|
|
205
224
|
});
|
|
206
225
|
error = await executeInterceptors_default(
|
|
207
226
|
error,
|
|
208
|
-
|
|
227
|
+
_options2.interceptors.error,
|
|
209
228
|
url,
|
|
210
229
|
_options2
|
|
211
230
|
);
|
|
@@ -238,101 +257,95 @@ fetch.defaults = {
|
|
|
238
257
|
result: []
|
|
239
258
|
},
|
|
240
259
|
/** Request timeout duration in milliseconds. Default: `0` */
|
|
241
|
-
timeout: 0
|
|
260
|
+
timeout: 0,
|
|
261
|
+
validateUrl: true
|
|
242
262
|
};
|
|
243
263
|
var fetch_default = fetch;
|
|
244
264
|
|
|
245
|
-
// src/
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
_abortCtrl = options.abortCtrl;
|
|
256
|
-
const promise = fetch_default(
|
|
257
|
-
defaultUrl != null ? defaultUrl : args[0],
|
|
258
|
-
options
|
|
265
|
+
// src/createClient.ts
|
|
266
|
+
var createClient = (mandatoryOptions, commonOptions, commonDeferOptions) => {
|
|
267
|
+
const func = (url, options) => {
|
|
268
|
+
return fetch_default(
|
|
269
|
+
url,
|
|
270
|
+
mergePartialOptions(
|
|
271
|
+
commonOptions,
|
|
272
|
+
options,
|
|
273
|
+
mandatoryOptions
|
|
274
|
+
)
|
|
259
275
|
);
|
|
260
|
-
promise.onEarlyFinalize.push(() => _abortCtrl == null ? void 0 : _abortCtrl.abort());
|
|
261
|
-
return promise;
|
|
262
276
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
func.deferred = (deferOptions = {}, defaultUrl, defaultOptions) => {
|
|
278
|
+
let _abortCtrl;
|
|
279
|
+
const fetchCb = (...args) => {
|
|
280
|
+
var _a, _b;
|
|
281
|
+
const options = mergePartialOptions(
|
|
282
|
+
commonOptions,
|
|
283
|
+
defaultOptions,
|
|
284
|
+
defaultUrl === void 0 ? args[1] : args[0],
|
|
285
|
+
mandatoryOptions
|
|
286
|
+
);
|
|
287
|
+
(_a = options.abortCtrl) != null ? _a : options.abortCtrl = new AbortController();
|
|
288
|
+
(_b = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _b.call(_abortCtrl);
|
|
289
|
+
_abortCtrl = options.abortCtrl;
|
|
290
|
+
const promise = fetch_default(
|
|
291
|
+
defaultUrl != null ? defaultUrl : args[0],
|
|
292
|
+
options
|
|
293
|
+
);
|
|
294
|
+
promise.onEarlyFinalize.push(() => _abortCtrl == null ? void 0 : _abortCtrl.abort());
|
|
295
|
+
return promise;
|
|
296
|
+
};
|
|
297
|
+
return PromisE3.deferredCallback(fetchCb, {
|
|
298
|
+
...commonDeferOptions,
|
|
299
|
+
...deferOptions
|
|
300
|
+
});
|
|
280
301
|
};
|
|
281
|
-
return
|
|
302
|
+
return func;
|
|
282
303
|
};
|
|
283
|
-
var
|
|
304
|
+
var createClient_default = createClient;
|
|
284
305
|
|
|
285
|
-
// src/
|
|
286
|
-
import { isFn as isFn3, isStr } from "@superutils/core";
|
|
287
|
-
function post(...[url = "", data, options = {}]) {
|
|
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
|
-
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// src/postDeferred.ts
|
|
306
|
+
// src/createPostClient.ts
|
|
297
307
|
import PromisE4 from "@superutils/promise";
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
(_b = options.abortCtrl) != null ? _b : options.abortCtrl = new AbortController();
|
|
306
|
-
(_c = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _c.call(_abortCtrl);
|
|
307
|
-
_abortCtrl = options.abortCtrl;
|
|
308
|
-
const promise = post(
|
|
309
|
-
args[0],
|
|
310
|
-
args[1],
|
|
311
|
-
options
|
|
308
|
+
var createPostClient = (mandatoryOptions, commonOptions, commonDeferOptions) => {
|
|
309
|
+
const func = (url, data, options) => {
|
|
310
|
+
var _a;
|
|
311
|
+
const _options2 = mergePartialOptions(
|
|
312
|
+
commonOptions,
|
|
313
|
+
options,
|
|
314
|
+
mandatoryOptions
|
|
312
315
|
);
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return PromisE4.deferredCallback(doPost, deferOptions);
|
|
317
|
-
}
|
|
318
|
-
var postDeferred_default = postDeferred;
|
|
319
|
-
|
|
320
|
-
// src/createPostMethodFunc.ts
|
|
321
|
-
var createPostMethodFunc = (method = "post") => {
|
|
322
|
-
const methodFunc = (url, data, options) => {
|
|
323
|
-
options != null ? options : options = {};
|
|
324
|
-
options.method = method;
|
|
325
|
-
return post(url, data, options);
|
|
316
|
+
_options2.body = data;
|
|
317
|
+
(_a = _options2.method) != null ? _a : _options2.method = "post";
|
|
318
|
+
return fetch_default(url, _options2);
|
|
326
319
|
};
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
320
|
+
func.deferred = (deferOptions = {}, defaultUrl, defaultData, defaultOptions) => {
|
|
321
|
+
let _abortCtrl;
|
|
322
|
+
const postCb = (...args) => {
|
|
323
|
+
var _a, _b, _c, _d;
|
|
324
|
+
if (defaultUrl !== void 0) args.splice(0, 0, defaultUrl);
|
|
325
|
+
if (defaultData !== void 0) args.splice(1, 0, defaultData);
|
|
326
|
+
const options = mergePartialOptions(
|
|
327
|
+
commonOptions,
|
|
328
|
+
defaultOptions,
|
|
329
|
+
args[2],
|
|
330
|
+
mandatoryOptions
|
|
331
|
+
);
|
|
332
|
+
(_a = options.abortCtrl) != null ? _a : options.abortCtrl = new AbortController();
|
|
333
|
+
(_b = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _b.call(_abortCtrl);
|
|
334
|
+
_abortCtrl = options.abortCtrl;
|
|
335
|
+
options.body = (_c = args[1]) != null ? _c : options.body;
|
|
336
|
+
(_d = options.method) != null ? _d : options.method = "post";
|
|
337
|
+
const promise = fetch_default(args[0], options);
|
|
338
|
+
promise.onEarlyFinalize.push(() => _abortCtrl == null ? void 0 : _abortCtrl.abort());
|
|
339
|
+
return promise;
|
|
340
|
+
};
|
|
341
|
+
return PromisE4.deferredCallback(postCb, {
|
|
342
|
+
...commonDeferOptions,
|
|
343
|
+
...deferOptions
|
|
344
|
+
});
|
|
332
345
|
};
|
|
333
|
-
return
|
|
346
|
+
return func;
|
|
334
347
|
};
|
|
335
|
-
var
|
|
348
|
+
var createPostClient_default = createPostClient;
|
|
336
349
|
|
|
337
350
|
// src/fetchResponse.ts
|
|
338
351
|
var fetchResponse = (...args) => {
|
|
@@ -344,13 +357,13 @@ var fetchResponse = (...args) => {
|
|
|
344
357
|
var fetchResponse_default = fetchResponse;
|
|
345
358
|
|
|
346
359
|
// src/fetchDefault.ts
|
|
347
|
-
var _get =
|
|
348
|
-
var _head =
|
|
349
|
-
var _options =
|
|
350
|
-
var _delete =
|
|
351
|
-
var _patch =
|
|
352
|
-
var _post =
|
|
353
|
-
var _put =
|
|
360
|
+
var _get = createClient_default({ method: "get" });
|
|
361
|
+
var _head = createClient_default({ method: "head" });
|
|
362
|
+
var _options = createClient_default({ method: "options" });
|
|
363
|
+
var _delete = createPostClient_default({ method: "delete" });
|
|
364
|
+
var _patch = createPostClient_default({ method: "patch" });
|
|
365
|
+
var _post = createPostClient_default({ method: "post" });
|
|
366
|
+
var _put = createPostClient_default({ method: "put" });
|
|
354
367
|
var fetchDefault = fetchResponse_default;
|
|
355
368
|
Object.defineProperty(fetchDefault, "defaults", {
|
|
356
369
|
get() {
|
|
@@ -376,12 +389,11 @@ export {
|
|
|
376
389
|
FetchError,
|
|
377
390
|
ResolveError,
|
|
378
391
|
ResolveIgnored,
|
|
379
|
-
|
|
380
|
-
|
|
392
|
+
createClient,
|
|
393
|
+
createPostClient,
|
|
381
394
|
index_default as default,
|
|
382
395
|
fetch,
|
|
383
|
-
fetchDeferred,
|
|
384
396
|
fetchResponse,
|
|
385
397
|
mergeFetchOptions,
|
|
386
|
-
|
|
398
|
+
mergePartialOptions
|
|
387
399
|
};
|
package/package.json
CHANGED