@superutils/fetch 1.0.1 → 1.0.3
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 +111 -8
- package/dist/index.d.ts +116 -93
- package/dist/index.js +67 -60
- package/package.json +13 -5
package/README.md
CHANGED
|
@@ -11,9 +11,9 @@ This package enhances the native `fetch` API by providing a streamlined interfac
|
|
|
11
11
|
- Usage
|
|
12
12
|
- [`fetch()`](#fetch): make HTTP requests just like built-in `fetch()`
|
|
13
13
|
- [`Method Specific Functions`](#methods)
|
|
14
|
-
- [`
|
|
15
|
-
- [`post()`](#post): make post
|
|
16
|
-
- [`
|
|
14
|
+
- [`fetch.get.deferred()`](#fetch-deferred): cancellable and debounced or throttled `fetch()`
|
|
15
|
+
- [`fetch.post()`](#post): make post requests
|
|
16
|
+
- [`fetch.post.deferred()`](#post-deferred) cancellable and debounced or throttled `post()`
|
|
17
17
|
|
|
18
18
|
## Features
|
|
19
19
|
|
|
@@ -47,8 +47,8 @@ const theActualData = await fetch('https://dummyjson.com/products/1', {
|
|
|
47
47
|
})
|
|
48
48
|
console.log(theActualData)
|
|
49
49
|
// Alternative:
|
|
50
|
-
const
|
|
51
|
-
console.log(
|
|
50
|
+
const theActualData2 = await fetch.get('https://dummyjson.com/products/1')
|
|
51
|
+
console.log(theActualData2)
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
<div id="methods"></div>
|
|
@@ -124,7 +124,11 @@ setTimeout(() => {
|
|
|
124
124
|
of the final "iphone 9" request. Both promises resolve to the same value.
|
|
125
125
|
3. `ResolveIgnored.NEVER`: The promise for the aborted "iphone" request is neither resolved nor rejected.
|
|
126
126
|
It will remain pending indefinitely.
|
|
127
|
-
|
|
127
|
+
- **`resolveError`**: Controls how failed requests are handled.
|
|
128
|
+
1. `ResolveError.NEVER`: Never resolve ignored promises. Caution: make sure this doesn't cause any memory leaks.
|
|
129
|
+
2. `ResolveError.WITH_LAST`: (default) resolve with active promise result, the one that caused the current promise/callback to be ignored.
|
|
130
|
+
3. `ResolveError.WITH_UNDEFINED`: resolve failed requests with `undefined` value
|
|
131
|
+
4. `ResolveError.WITH_ERROR`: The promise for the aborted "iphone" request is rejected with a `FetchError`.
|
|
128
132
|
|
|
129
133
|
#### Using defaults to reduce redundancy
|
|
130
134
|
|
|
@@ -160,8 +164,107 @@ getRandomQuote().then(quote => console.log('Call 3 resolved:', quote.id))
|
|
|
160
164
|
|
|
161
165
|
### `fetch.post(url, options)`
|
|
162
166
|
|
|
167
|
+
Send a POST request to create a new product and receive the parsed JSON response.
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
import fetch from '@superutils/fetch'
|
|
171
|
+
|
|
172
|
+
const newProduct = { title: 'Perfume Oil' }
|
|
173
|
+
|
|
174
|
+
fetch.post('https://dummyjson.com/products/add', newProduct).then(
|
|
175
|
+
createdProduct => console.log('Product created:', createdProduct),
|
|
176
|
+
error => console.error('Failed to create product:', error),
|
|
177
|
+
)
|
|
178
|
+
```
|
|
179
|
+
|
|
163
180
|
<div id="post-deferred"></div>
|
|
164
181
|
|
|
165
|
-
### `fetch.post.deferred(deferOptions, url,
|
|
182
|
+
### `fetch.post.deferred(deferOptions, url, data, options)`
|
|
183
|
+
|
|
184
|
+
HTTP POST request with debounce/throttle.
|
|
185
|
+
|
|
186
|
+
#### Example 1: Auto-saving form data with throttling
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import fetch from '@superutils/fetch'
|
|
190
|
+
import PromisE from '@superutils/promise'
|
|
191
|
+
|
|
192
|
+
// Create a throttled function to auto-save product updates.
|
|
193
|
+
const saveProductThrottled = fetch.post.deferred(
|
|
194
|
+
{
|
|
195
|
+
delayMs: 1000, // Throttle window of 1 second
|
|
196
|
+
throttle: true,
|
|
197
|
+
trailing: true, // Ensures the very last update is always saved
|
|
198
|
+
onResult: product => console.log(`[Saved] Product: ${product.title}`),
|
|
199
|
+
},
|
|
200
|
+
'https://dummyjson.com/products/1', // Default URL
|
|
201
|
+
undefined, // No default data
|
|
202
|
+
{ method: 'put' }, // Default method
|
|
203
|
+
)
|
|
204
|
+
// Simulate a user typing quickly, triggering multiple saves.
|
|
205
|
+
console.log('User starts typing...')
|
|
206
|
+
saveProductThrottled({ title: 'iPhone' }) // Executed immediately (leading edge)
|
|
207
|
+
await PromisE.delay(200)
|
|
208
|
+
saveProductThrottled({ title: 'iPhone 15' }) // Ignored (within 1000ms throttle window)
|
|
209
|
+
await PromisE.delay(300)
|
|
210
|
+
saveProductThrottled({ title: 'iPhone 15 Pro' }) // Ignored
|
|
211
|
+
await PromisE.delay(400)
|
|
212
|
+
saveProductThrottled({ title: 'iPhone 15 Pro Max' }) // Queued to execute on the trailing edge
|
|
213
|
+
// Outcome:
|
|
214
|
+
// The first call ('iPhone') is executed immediately.
|
|
215
|
+
// The next two calls are ignored by the throttle.
|
|
216
|
+
// The final call ('iPhone 15 Pro Max') is executed after the 1000ms throttle window closes,
|
|
217
|
+
// thanks to `trailing: true`.
|
|
218
|
+
// This results in only two network requests instead of four.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Example 2: debouncing an authentication token refresh
|
|
166
222
|
|
|
167
|
-
|
|
223
|
+
```typescript
|
|
224
|
+
import fetch from '@superutils/fetch'
|
|
225
|
+
import PromisE from '@superutils/promise'
|
|
226
|
+
|
|
227
|
+
// Mock a simple token store
|
|
228
|
+
let currentRefreshToken = ''
|
|
229
|
+
// Create a debounced function to refresh the auth token.
|
|
230
|
+
// It waits 300ms after the last call before executing.
|
|
231
|
+
const requestNewToken = fetch.post.deferred(
|
|
232
|
+
{
|
|
233
|
+
delayMs: 300, // debounce delay
|
|
234
|
+
onResult: ({ token = '' }) => {
|
|
235
|
+
console.log(
|
|
236
|
+
`Auth token successfully refreshed at ${new Date().toISOString()}`,
|
|
237
|
+
)
|
|
238
|
+
currentRefreshToken = token
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
'https://dummyjson.com/auth/refresh', // Default URL
|
|
242
|
+
() => ({
|
|
243
|
+
refreshToken: currentRefreshToken,
|
|
244
|
+
expiresInMins: 30,
|
|
245
|
+
}),
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
// First authenticate user to get the initial refresh token and then request new referesh tokens
|
|
249
|
+
fetch
|
|
250
|
+
.post<{ refreshToken: string }>(
|
|
251
|
+
'https://dummyjson.com/auth/login',
|
|
252
|
+
{
|
|
253
|
+
username: 'emilys',
|
|
254
|
+
password: 'emilyspass',
|
|
255
|
+
expiresInMins: 30,
|
|
256
|
+
},
|
|
257
|
+
{ credentials: 'include' },
|
|
258
|
+
)
|
|
259
|
+
.then(result => {
|
|
260
|
+
currentRefreshToken = result?.refreshToken
|
|
261
|
+
|
|
262
|
+
requestNewToken() // Called at 0ms
|
|
263
|
+
PromisE.delay(50, requestNewToken) // Called at 50ms
|
|
264
|
+
PromisE.delay(100, requestNewToken) // Called at 100ms
|
|
265
|
+
}, console.error)
|
|
266
|
+
// Outcome:
|
|
267
|
+
// The first two calls are aborted by the debounce mechanism.
|
|
268
|
+
// Only the final call executes, 300ms after it was made (at the 400ms mark).
|
|
269
|
+
// The token is refreshed only once, preventing redundant network requests.
|
|
270
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { ValueOrPromise } from '@superutils/core';
|
|
1
2
|
import * as _superutils_promise from '@superutils/promise';
|
|
2
3
|
import { RetryOptions, IPromisE, DeferredAsyncOptions } from '@superutils/promise';
|
|
3
4
|
export { DeferredAsyncOptions, ResolveError, ResolveIgnored } from '@superutils/promise';
|
|
4
|
-
import { ValueOrPromise } from '@superutils/core';
|
|
5
5
|
|
|
6
|
-
type FetchArgs
|
|
6
|
+
type FetchArgs<OmitMethod extends boolean = false> = [
|
|
7
|
+
url: string | URL,
|
|
8
|
+
options?: OmitMethod extends true ? Omit<FetchOptions, 'method'> : FetchOptions
|
|
9
|
+
];
|
|
7
10
|
type FetchArgsInterceptor = [
|
|
8
11
|
url: string | URL,
|
|
9
12
|
options: FetchOptionsInterceptor
|
|
@@ -31,9 +34,9 @@ type FetchCustomOptions = {
|
|
|
31
34
|
timeout?: number;
|
|
32
35
|
} & FetchRetryOptions;
|
|
33
36
|
/** Default args */
|
|
34
|
-
type FetchDeferredArgs = [
|
|
37
|
+
type FetchDeferredArgs<OmitMethod extends boolean = false> = [
|
|
35
38
|
url?: string | URL,
|
|
36
|
-
options?: Omit<FetchOptions, 'abortCtrl'>
|
|
39
|
+
options?: Omit<FetchOptions, 'abortCtrl' | (OmitMethod extends true ? 'method' : never)>
|
|
37
40
|
];
|
|
38
41
|
type FetchErrMsgs = {
|
|
39
42
|
invalidUrl?: string;
|
|
@@ -273,10 +276,10 @@ type FetchRetryOptions = Omit<Partial<RetryOptions>, 'retry' | 'retryIf'> & {
|
|
|
273
276
|
*/
|
|
274
277
|
type Interceptor<T, TArgs extends unknown[], TArgsCb extends unknown[] = [value: T, ...TArgs]> = (...args: TArgsCb) => ValueOrPromise<void> | ValueOrPromise<T>;
|
|
275
278
|
type PostBody = Record<string, unknown> | BodyInit | null;
|
|
276
|
-
type PostArgs = [
|
|
279
|
+
type PostArgs<OmitMethod = false> = [
|
|
277
280
|
url: string | URL,
|
|
278
|
-
data?: PostBody,
|
|
279
|
-
options?: PostOptions
|
|
281
|
+
data?: PostBody | (() => PostBody),
|
|
282
|
+
options?: OmitMethod extends true ? Omit<FetchOptions, 'method'> : PostOptions
|
|
280
283
|
];
|
|
281
284
|
/**
|
|
282
285
|
*
|
|
@@ -308,10 +311,10 @@ type PostArgs = [
|
|
|
308
311
|
* f4().then(console.log, console.warn)
|
|
309
312
|
* ```
|
|
310
313
|
*/
|
|
311
|
-
type PostDeferredCallbackArgs<TUrl = undefined, TData = undefined, RPA extends unknown[] = Required<
|
|
314
|
+
type PostDeferredCallbackArgs<TUrl = undefined, TData = undefined, OmitMethod extends boolean = true, CbArgs extends PostArgs<OmitMethod> = PostArgs<OmitMethod>, Options = CbArgs[2], RPA extends unknown[] = Required<CbArgs>> = [TUrl, TData] extends [RPA[0], undefined] ? [data?: CbArgs[1], options?: Options] : [TUrl, TData] extends [undefined, RPA[1]] ? [url: CbArgs[0], options?: Options] : [TUrl, TData] extends [RPA[0], RPA[1]] ? [options?: Options] : CbArgs;
|
|
312
315
|
type PostOptions = Omit<FetchOptions, 'method'> & {
|
|
313
316
|
/** Default: `'post'` */
|
|
314
|
-
method?: 'post' | 'put' | 'patch' | 'delete';
|
|
317
|
+
method?: 'post' | 'put' | 'patch' | 'delete' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
315
318
|
};
|
|
316
319
|
|
|
317
320
|
declare const fetch$1: {
|
|
@@ -406,18 +409,18 @@ declare const fetch$1: {
|
|
|
406
409
|
* // Console output will show the same quote ID for all three calls.
|
|
407
410
|
* ```
|
|
408
411
|
*/
|
|
409
|
-
declare function fetchDeferred<ThisArg = unknown, Delay extends number = number, GlobalUrl
|
|
412
|
+
declare function fetchDeferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = FetchArgs[0] | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: FetchArgs<true>[1]]>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl, defaultOptions?: FetchArgs[1]): <TResult = unknown>(...args: CbArgs) => _superutils_promise.IPromisE<TResult>;
|
|
410
413
|
|
|
411
414
|
/**
|
|
412
|
-
* Creates a deferred/throttled function for making `POST`, `PUT`, or `PATCH` requests, powered by
|
|
415
|
+
* Creates a deferred/throttled function for making `DELETE`, `POST`, `PUT`, or `PATCH` requests, powered by
|
|
413
416
|
* {@link PromisE.deferred}.
|
|
417
|
+
*
|
|
414
418
|
* This is ideal for scenarios like auto-saving form data, preventing duplicate submissions on button clicks,
|
|
415
419
|
* or throttling API updates.
|
|
416
420
|
*
|
|
417
421
|
* Like `fetchDeferred`, it automatically aborts pending requests when a new one is initiated, ensuring only
|
|
418
422
|
* the most recent or relevant action is executed.
|
|
419
423
|
*
|
|
420
|
-
*
|
|
421
424
|
* @param deferOptions Configuration for the deferred execution behavior (e.g., `delayMs`, `throttle`).
|
|
422
425
|
* See {@link DeferredAsyncOptions} for details.
|
|
423
426
|
* @param globalUrl (optional) If global URL is `undefined`, returned callback will always require an URL.
|
|
@@ -427,86 +430,87 @@ declare function fetchDeferred<ThisArg = unknown, Delay extends number = number,
|
|
|
427
430
|
* If the same property is provided in both cases, defaults will be overriden by the callback.
|
|
428
431
|
*
|
|
429
432
|
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
433
|
+
*
|
|
434
|
+
* @example Auto-saving form data with throttling
|
|
435
|
+
* ```javascript
|
|
432
436
|
* import { postDeferred } from '@superutils/fetch'
|
|
433
437
|
* import PromisE from '@superutils/promise'
|
|
434
438
|
*
|
|
435
|
-
* //
|
|
436
|
-
*
|
|
439
|
+
* // Create a throttled function to auto-save product updates.
|
|
440
|
+
* const saveProductThrottled = fetch.post.deferred(
|
|
441
|
+
* {
|
|
442
|
+
* delayMs: 1000, // Throttle window of 1 second
|
|
443
|
+
* throttle: true,
|
|
444
|
+
* trailing: true, // Ensures the very last update is always saved
|
|
445
|
+
* onResult: product => console.log(`[Saved] Product: ${product.title}`),
|
|
446
|
+
* },
|
|
447
|
+
* 'https://dummyjson.com/products/1', // Default URL
|
|
448
|
+
* undefined, // No default data
|
|
449
|
+
* { method: 'put' }, // Default method
|
|
450
|
+
* )
|
|
451
|
+
* // Simulate a user typing quickly, triggering multiple saves.
|
|
452
|
+
* console.log('User starts typing...')
|
|
453
|
+
* // First call
|
|
454
|
+
* saveProductThrottled({ title: 'iPhone' }) // Executed immediately (leading edge)
|
|
455
|
+
* // Second call after 200ms => Ignored (within 1000ms throttle window)
|
|
456
|
+
* PromisE.delay(200, () => saveProductThrottled({ title: 'iPhone 15' }))
|
|
457
|
+
* // Third call 300ms after second call => Ignored
|
|
458
|
+
* PromisE.delay(500, () => saveProductThrottled({ title: 'iPhone 15 Pro' }))
|
|
459
|
+
* // Fourth call 400ms after third call => Queued to execute on the trailing edge
|
|
460
|
+
* PromisE.delay(900, () => saveProductThrottled({ title: 'iPhone 15 Pro Max' }))
|
|
461
|
+
* ```
|
|
437
462
|
*
|
|
463
|
+
* @example Advanced example: debouncing an authentication token refresh
|
|
464
|
+
* ```typescript
|
|
465
|
+
* import fetch from '@superutils/fetch'
|
|
466
|
+
* import PromisE from '@superutils/promise'
|
|
467
|
+
*
|
|
468
|
+
* // Mock a simple token store
|
|
469
|
+
* let currentRefreshToken = ''
|
|
438
470
|
* // Create a debounced function to refresh the auth token.
|
|
439
471
|
* // It waits 300ms after the last call before executing.
|
|
440
|
-
* const
|
|
472
|
+
* const requestNewToken = fetch.post.deferred(
|
|
441
473
|
* {
|
|
442
474
|
* delayMs: 300, // debounce delay
|
|
443
|
-
* onResult: (
|
|
444
|
-
* console.log(
|
|
445
|
-
*
|
|
446
|
-
*
|
|
475
|
+
* onResult: ({ token = '' }) => {
|
|
476
|
+
* console.log(
|
|
477
|
+
* `Auth token successfully refreshed at ${new Date().toISOString()}`,
|
|
478
|
+
* )
|
|
479
|
+
* currentRefreshToken = token
|
|
480
|
+
* },
|
|
447
481
|
* },
|
|
448
482
|
* 'https://dummyjson.com/auth/refresh', // Default URL
|
|
483
|
+
* () => ({
|
|
484
|
+
* refreshToken: currentRefreshToken,
|
|
485
|
+
* expiresInMins: 30,
|
|
486
|
+
* }),
|
|
449
487
|
* )
|
|
450
488
|
*
|
|
451
|
-
* //
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
489
|
+
* // First authenticate user to get the initial refresh token and then request new referesh tokens
|
|
490
|
+
* fetch
|
|
491
|
+
* .post<{ refreshToken: string }>(
|
|
492
|
+
* 'https://dummyjson.com/auth/login',
|
|
493
|
+
* {
|
|
494
|
+
* username: 'emilys',
|
|
495
|
+
* password: 'emilyspass',
|
|
496
|
+
* expiresInMins: 30,
|
|
497
|
+
* },
|
|
498
|
+
* { credentials: 'include' },
|
|
499
|
+
* )
|
|
500
|
+
* .then(result => {
|
|
501
|
+
* currentRefreshToken = result?.refreshToken
|
|
502
|
+
*
|
|
503
|
+
* requestNewToken() // Called at 0ms
|
|
504
|
+
* PromisE.delay(50, requestNewToken) // Called at 50ms
|
|
505
|
+
* PromisE.delay(100, requestNewToken) // Called at 100ms
|
|
506
|
+
* }, console.error)
|
|
465
507
|
* // Outcome:
|
|
466
508
|
* // The first two calls are aborted by the debounce mechanism.
|
|
467
509
|
* // Only the final call executes, 300ms after it was made (at the 400ms mark).
|
|
468
510
|
* // The token is refreshed only once, preventing redundant network requests.
|
|
469
511
|
* ```
|
|
470
|
-
*
|
|
471
|
-
* @example Auto-saving form data with throttling
|
|
472
|
-
* ```typescript
|
|
473
|
-
* import { postDeferred } from '@superutils/fetch'
|
|
474
|
-
* import PromisE from '@superutils/promise'
|
|
475
|
-
*
|
|
476
|
-
* // Create a throttled function to auto-save product updates.
|
|
477
|
-
* const saveProductThrottled = postDeferred(
|
|
478
|
-
* {
|
|
479
|
-
* delayMs: 1000, // Throttle window of 1 second
|
|
480
|
-
* throttle: true,
|
|
481
|
-
* trailing: true, // Ensures the very last update is always saved
|
|
482
|
-
* onResult: (product) => console.log(`[Saved] Product: ${product.title}`),
|
|
483
|
-
* },
|
|
484
|
-
* 'https://dummyjson.com/products/1', // Default URL
|
|
485
|
-
* undefined, // No default data
|
|
486
|
-
* { method: 'put' }, // Default method
|
|
487
|
-
* )
|
|
488
|
-
*
|
|
489
|
-
* // Simulate a user typing quickly, triggering multiple saves.
|
|
490
|
-
* console.log('User starts typing...');
|
|
491
|
-
* saveProductThrottled({ title: 'iPhone' }); // Executed immediately (leading edge)
|
|
492
|
-
* await PromisE.delay(200);
|
|
493
|
-
* saveProductThrottled({ title: 'iPhone 15' }); // Ignored (within 1000ms throttle window)
|
|
494
|
-
* await PromisE.delay(300);
|
|
495
|
-
* saveProductThrottled({ title: 'iPhone 15 Pro' }); // Ignored
|
|
496
|
-
* await PromisE.delay(400);
|
|
497
|
-
* saveProductThrottled({ title: 'iPhone 15 Pro Max' }); // Queued to execute on the trailing edge
|
|
498
|
-
*
|
|
499
|
-
* // Outcome:
|
|
500
|
-
* // The first call ('iPhone') is executed immediately.
|
|
501
|
-
* // The next two calls are ignored by the throttle.
|
|
502
|
-
* // The final call ('iPhone 15 Pro Max') is executed after the 1000ms throttle window closes,
|
|
503
|
-
* // thanks to `trailing: true`.
|
|
504
|
-
* // This results in only two network requests instead of four.
|
|
505
|
-
* ```
|
|
506
512
|
*/
|
|
507
|
-
declare function postDeferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, Args extends unknown[] = PostDeferredCallbackArgs<GlobalUrl, GlobalData>>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl,
|
|
508
|
-
globalData?: GlobalData, // The default data for all calls
|
|
509
|
-
defaultOptions?: PostOptions): <TResult = unknown>(...args: Args) => _superutils_promise.IPromisE<TResult>;
|
|
513
|
+
declare function postDeferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, Args extends unknown[] = PostDeferredCallbackArgs<GlobalUrl, GlobalData, true>>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl, globalData?: GlobalData, defaultOptions?: PostArgs[2]): <TResult = unknown>(...args: Args) => _superutils_promise.IPromisE<TResult>;
|
|
510
514
|
|
|
511
515
|
/**
|
|
512
516
|
* Merge one or more {@link FetchOptions}
|
|
@@ -525,29 +529,40 @@ defaultOptions?: PostOptions): <TResult = unknown>(...args: Args) => _superutils
|
|
|
525
529
|
declare const mergeFetchOptions: (...allOptions: FetchOptions[]) => FetchOptionsInterceptor;
|
|
526
530
|
|
|
527
531
|
type FetchWithoutMethods = typeof fetch$1;
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
deferred:
|
|
532
|
+
declare const _get: {
|
|
533
|
+
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
534
|
+
deferred: <ThisArg, Delay extends number, GlobalUrl extends string | URL>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay> | undefined, globalUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined) => <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
531
535
|
};
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
deferred:
|
|
536
|
+
declare const _head: {
|
|
537
|
+
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
538
|
+
deferred: <ThisArg, Delay extends number, GlobalUrl extends string | URL>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay> | undefined, globalUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined) => <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
539
|
+
};
|
|
540
|
+
declare const _options: {
|
|
541
|
+
<T>(url: string | URL, options?: Omit<FetchOptions, "method">): _superutils_promise.IPromisE<T>;
|
|
542
|
+
deferred: <ThisArg, Delay extends number, GlobalUrl extends string | URL>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay> | undefined, globalUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined) => <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]) => _superutils_promise.IPromisE<TResult>;
|
|
543
|
+
};
|
|
544
|
+
declare const _delete: {
|
|
545
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
546
|
+
deferred: <ThisArg, Delay extends number = number, Args extends PostArgs<true> = PostArgs<true>, GlobalUrl extends Args[0] | undefined = undefined, GlobalData extends Args[1] | undefined = undefined>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl, globalData?: GlobalData, defaultOptions?: Args[2]) => <TResult = unknown>(...args: PostDeferredCallbackArgs<GlobalUrl, GlobalData, true, PostArgs<true>, Omit<FetchOptions, "method"> | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: Omit<FetchOptions, "method">]>) => _superutils_promise.IPromisE<TResult>;
|
|
547
|
+
};
|
|
548
|
+
declare const _patch: {
|
|
549
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
550
|
+
deferred: <ThisArg, Delay extends number = number, Args extends PostArgs<true> = PostArgs<true>, GlobalUrl extends Args[0] | undefined = undefined, GlobalData extends Args[1] | undefined = undefined>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl, globalData?: GlobalData, defaultOptions?: Args[2]) => <TResult = unknown>(...args: PostDeferredCallbackArgs<GlobalUrl, GlobalData, true, PostArgs<true>, Omit<FetchOptions, "method"> | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: Omit<FetchOptions, "method">]>) => _superutils_promise.IPromisE<TResult>;
|
|
551
|
+
};
|
|
552
|
+
declare const _post: {
|
|
553
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
554
|
+
deferred: <ThisArg, Delay extends number = number, Args extends PostArgs<true> = PostArgs<true>, GlobalUrl extends Args[0] | undefined = undefined, GlobalData extends Args[1] | undefined = undefined>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl, globalData?: GlobalData, defaultOptions?: Args[2]) => <TResult = unknown>(...args: PostDeferredCallbackArgs<GlobalUrl, GlobalData, true, PostArgs<true>, Omit<FetchOptions, "method"> | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: Omit<FetchOptions, "method">]>) => _superutils_promise.IPromisE<TResult>;
|
|
555
|
+
};
|
|
556
|
+
declare const _put: {
|
|
557
|
+
<T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
|
|
558
|
+
deferred: <ThisArg, Delay extends number = number, Args extends PostArgs<true> = PostArgs<true>, GlobalUrl extends Args[0] | undefined = undefined, GlobalData extends Args[1] | undefined = undefined>(deferOptions?: DeferredAsyncOptions<ThisArg, Delay>, globalUrl?: GlobalUrl, globalData?: GlobalData, defaultOptions?: Args[2]) => <TResult = unknown>(...args: PostDeferredCallbackArgs<GlobalUrl, GlobalData, true, PostArgs<true>, Omit<FetchOptions, "method"> | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: Omit<FetchOptions, "method">]>) => _superutils_promise.IPromisE<TResult>;
|
|
535
559
|
};
|
|
536
|
-
interface FetchWithMethods extends FetchWithoutMethods {
|
|
537
|
-
get: FetchMethodFunc;
|
|
538
|
-
head: FetchMethodFunc;
|
|
539
|
-
options: FetchMethodFunc;
|
|
540
|
-
delete: PostMethodFunc;
|
|
541
|
-
patch: PostMethodFunc;
|
|
542
|
-
post: PostMethodFunc;
|
|
543
|
-
put: PostMethodFunc;
|
|
544
|
-
}
|
|
545
560
|
/**
|
|
546
561
|
* @function fetch
|
|
547
562
|
*
|
|
548
563
|
* A `fetch()` replacement that simplifies data fetching with automatic JSON parsing, request timeouts, retries,
|
|
549
|
-
* and
|
|
550
|
-
* control flows.
|
|
564
|
+
* and handy interceptors that also work as transformers. It also includes deferred and throttled request
|
|
565
|
+
* capabilities for complex asynchronous control flows.
|
|
551
566
|
*
|
|
552
567
|
* Will reject promise if response status code is not 2xx (200 <= status < 300).
|
|
553
568
|
*
|
|
@@ -627,6 +642,14 @@ interface FetchWithMethods extends FetchWithoutMethods {
|
|
|
627
642
|
* fetch('https://dummyjson.com/products/1').then(theActualData => console.log(theActualData))
|
|
628
643
|
* ```
|
|
629
644
|
*/
|
|
630
|
-
declare const fetch:
|
|
645
|
+
declare const fetch: typeof fetch$1 & {
|
|
646
|
+
get: typeof _get;
|
|
647
|
+
head: typeof _head;
|
|
648
|
+
options: typeof _options;
|
|
649
|
+
delete: typeof _delete;
|
|
650
|
+
patch: typeof _patch;
|
|
651
|
+
post: typeof _post;
|
|
652
|
+
put: typeof _put;
|
|
653
|
+
};
|
|
631
654
|
|
|
632
|
-
export { type FetchArgs, type FetchArgsInterceptor, FetchAs, type FetchCustomOptions, type FetchDeferredArgs, type FetchErrMsgs, FetchError, type FetchInterceptorError, type FetchInterceptorRequest, type FetchInterceptorResponse, type FetchInterceptorResult, type FetchInterceptors, type
|
|
655
|
+
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 FetchWithoutMethods, type Interceptor, type PostArgs, type PostBody, type PostDeferredCallbackArgs, type PostOptions, fetch as default, fetch, fetchDeferred, mergeFetchOptions, postDeferred };
|
package/dist/index.js
CHANGED
|
@@ -116,32 +116,32 @@ var fetch = (url, options = {}) => {
|
|
|
116
116
|
let timeoutId;
|
|
117
117
|
const promise = new PromisE2(async (resolve, reject) => {
|
|
118
118
|
var _a, _b;
|
|
119
|
-
const
|
|
120
|
-
if (isEmpty2(
|
|
121
|
-
const errorInterceptors = [...
|
|
122
|
-
const requestInterceptors = [...
|
|
123
|
-
const responseInterceptors = [...
|
|
124
|
-
const resultInterceptors = [...
|
|
125
|
-
url = await executeInterceptors_default(url, requestInterceptors, url,
|
|
126
|
-
const { as: parseAs, errMsgs, timeout } =
|
|
119
|
+
const _options2 = mergeFetchOptions_default(fetch.defaults, options);
|
|
120
|
+
if (isEmpty2(_options2.method)) _options2.method = "get";
|
|
121
|
+
const errorInterceptors = [..._options2.interceptors.error];
|
|
122
|
+
const requestInterceptors = [..._options2.interceptors.request];
|
|
123
|
+
const responseInterceptors = [..._options2.interceptors.response];
|
|
124
|
+
const resultInterceptors = [..._options2.interceptors.result];
|
|
125
|
+
url = await executeInterceptors_default(url, requestInterceptors, url, _options2);
|
|
126
|
+
const { as: parseAs, errMsgs, timeout } = _options2;
|
|
127
127
|
if (isPositiveNumber(timeout)) {
|
|
128
|
-
(_a =
|
|
128
|
+
(_a = _options2.abortCtrl) != null ? _a : _options2.abortCtrl = new AbortController();
|
|
129
129
|
timeoutId = setTimeout(() => {
|
|
130
130
|
var _a2;
|
|
131
|
-
return (_a2 =
|
|
131
|
+
return (_a2 = _options2.abortCtrl) == null ? void 0 : _a2.abort();
|
|
132
132
|
}, timeout);
|
|
133
133
|
}
|
|
134
|
-
abortCtrl =
|
|
135
|
-
if (
|
|
134
|
+
abortCtrl = _options2.abortCtrl;
|
|
135
|
+
if (_options2.abortCtrl) _options2.signal = _options2.abortCtrl.signal;
|
|
136
136
|
let errResponse;
|
|
137
137
|
try {
|
|
138
|
-
if (!isUrlValid(url, false)) throw errMsgs.invalidUrl;
|
|
139
|
-
let response = await getResponse_default(url,
|
|
138
|
+
if (!isUrlValid(url, false)) throw new Error(errMsgs.invalidUrl);
|
|
139
|
+
let response = await getResponse_default(url, _options2);
|
|
140
140
|
response = await executeInterceptors_default(
|
|
141
141
|
response,
|
|
142
142
|
responseInterceptors,
|
|
143
143
|
url,
|
|
144
|
-
|
|
144
|
+
_options2
|
|
145
145
|
);
|
|
146
146
|
errResponse = response;
|
|
147
147
|
const { status = 0 } = response;
|
|
@@ -157,43 +157,36 @@ var fetch = (url, options = {}) => {
|
|
|
157
157
|
const parseFunc = response[parseAs];
|
|
158
158
|
if (isFn2(parseFunc)) {
|
|
159
159
|
const handleErr = (err) => {
|
|
160
|
-
var _a2, _b2;
|
|
161
160
|
err = new Error(
|
|
162
|
-
|
|
163
|
-
errMsgs.parseFailed,
|
|
164
|
-
parseAs + ".",
|
|
165
|
-
(_b2 = `${(_a2 = err == null ? void 0 : err.message) != null ? _a2 : err}`) == null ? void 0 : _b2.replace("Error: ", "")
|
|
166
|
-
].join(" "),
|
|
161
|
+
`${errMsgs.parseFailed} ${parseAs}. ${err == null ? void 0 : err.message}`,
|
|
167
162
|
{ cause: err }
|
|
168
163
|
);
|
|
169
164
|
return globalThis.Promise.reject(err);
|
|
170
165
|
};
|
|
171
|
-
result = parseFunc();
|
|
166
|
+
result = parseFunc.bind(response)();
|
|
172
167
|
if (isPromise(result)) result = result.catch(handleErr);
|
|
173
168
|
result = await executeInterceptors_default(
|
|
174
169
|
result,
|
|
175
170
|
resultInterceptors,
|
|
176
171
|
url,
|
|
177
|
-
|
|
172
|
+
_options2
|
|
178
173
|
);
|
|
179
174
|
}
|
|
180
|
-
resolve(
|
|
175
|
+
resolve(result);
|
|
181
176
|
} catch (err) {
|
|
182
177
|
const errX = err;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
);
|
|
178
|
+
const msg = (errX == null ? void 0 : errX.name) === "AbortError" ? errMsgs.reqTimedout : err == null ? void 0 : err.message;
|
|
179
|
+
let error = new FetchError(msg, {
|
|
180
|
+
cause: (_b = errX == null ? void 0 : errX.cause) != null ? _b : err,
|
|
181
|
+
response: errResponse,
|
|
182
|
+
options: _options2,
|
|
183
|
+
url
|
|
184
|
+
});
|
|
192
185
|
error = await executeInterceptors_default(
|
|
193
186
|
error,
|
|
194
187
|
errorInterceptors,
|
|
195
188
|
url,
|
|
196
|
-
|
|
189
|
+
_options2
|
|
197
190
|
);
|
|
198
191
|
reject(error);
|
|
199
192
|
}
|
|
@@ -260,14 +253,14 @@ var fetchDeferred_default = fetchDeferred;
|
|
|
260
253
|
import PromisE4 from "@superutils/promise";
|
|
261
254
|
|
|
262
255
|
// src/post.ts
|
|
263
|
-
import { isStr } from "@superutils/core";
|
|
256
|
+
import { isFn as isFn3, isStr } from "@superutils/core";
|
|
264
257
|
function post(...[url = "", data, options = {}]) {
|
|
265
258
|
return fetch_default(
|
|
266
259
|
url,
|
|
267
260
|
mergeFetchOptions_default(
|
|
268
261
|
{
|
|
269
262
|
method: "post",
|
|
270
|
-
body: isStr(data) ? data : JSON.stringify(data)
|
|
263
|
+
body: isStr(data) ? data : JSON.stringify(isFn3(data) ? data() : data)
|
|
271
264
|
},
|
|
272
265
|
options
|
|
273
266
|
)
|
|
@@ -287,10 +280,7 @@ function postDeferred(deferOptions = {}, globalUrl, globalData, defaultOptions)
|
|
|
287
280
|
if (globalData !== void 0) args.splice(1, 0, globalData);
|
|
288
281
|
const url = args[0];
|
|
289
282
|
const data = args[1];
|
|
290
|
-
const options = mergeFetchOptions_default(
|
|
291
|
-
defaultOptions != null ? defaultOptions : {},
|
|
292
|
-
(_a = args[2]) != null ? _a : {}
|
|
293
|
-
);
|
|
283
|
+
const options = mergeFetchOptions_default(defaultOptions != null ? defaultOptions : {}, (_a = args[2]) != null ? _a : {});
|
|
294
284
|
(_b = options.abortCtrl) != null ? _b : options.abortCtrl = new AbortController();
|
|
295
285
|
(_c = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _c.call(_abortCtrl);
|
|
296
286
|
_abortCtrl = options.abortCtrl;
|
|
@@ -303,33 +293,50 @@ function postDeferred(deferOptions = {}, globalUrl, globalData, defaultOptions)
|
|
|
303
293
|
var postDeferred_default = postDeferred;
|
|
304
294
|
|
|
305
295
|
// src/index.ts
|
|
306
|
-
import { isObj } from "@superutils/core";
|
|
307
296
|
var createFetchMethodFunc = (method = "get") => {
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
297
|
+
const deferred = (...args) => fetchDeferred_default(...args);
|
|
298
|
+
const methodFunc = (url, options) => {
|
|
299
|
+
options != null ? options : options = {};
|
|
300
|
+
options.method = method;
|
|
301
|
+
return fetch_default(url, options);
|
|
302
|
+
};
|
|
303
|
+
methodFunc.deferred = deferred;
|
|
314
304
|
return methodFunc;
|
|
315
305
|
};
|
|
316
306
|
var createPostMethodFunc = (method = "post") => {
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return
|
|
321
|
-
|
|
322
|
-
|
|
307
|
+
const deferredFunc = (deferOptions = {}, globalUrl, globalData, defaultOptions) => {
|
|
308
|
+
defaultOptions != null ? defaultOptions : defaultOptions = {};
|
|
309
|
+
defaultOptions.method = method;
|
|
310
|
+
return postDeferred_default(
|
|
311
|
+
deferOptions,
|
|
312
|
+
globalUrl,
|
|
313
|
+
globalData,
|
|
314
|
+
defaultOptions
|
|
315
|
+
);
|
|
316
|
+
};
|
|
317
|
+
const methodFunc = (url, data, options) => {
|
|
318
|
+
options != null ? options : options = {};
|
|
319
|
+
options.method = method;
|
|
320
|
+
return post(url, data, options);
|
|
321
|
+
};
|
|
322
|
+
methodFunc.deferred = deferredFunc;
|
|
323
323
|
return methodFunc;
|
|
324
324
|
};
|
|
325
|
+
var _get = createFetchMethodFunc("get");
|
|
326
|
+
var _head = createFetchMethodFunc("head");
|
|
327
|
+
var _options = createFetchMethodFunc("options");
|
|
328
|
+
var _delete = createPostMethodFunc("delete");
|
|
329
|
+
var _patch = createPostMethodFunc("patch");
|
|
330
|
+
var _post = createPostMethodFunc("post");
|
|
331
|
+
var _put = createPostMethodFunc("put");
|
|
325
332
|
var fetch2 = fetch_default;
|
|
326
|
-
fetch2.get =
|
|
327
|
-
fetch2.head =
|
|
328
|
-
fetch2.options =
|
|
329
|
-
fetch2.delete =
|
|
330
|
-
fetch2.patch =
|
|
331
|
-
fetch2.post =
|
|
332
|
-
fetch2.put =
|
|
333
|
+
fetch2.get = _get;
|
|
334
|
+
fetch2.head = _head;
|
|
335
|
+
fetch2.options = _options;
|
|
336
|
+
fetch2.delete = _delete;
|
|
337
|
+
fetch2.patch = _patch;
|
|
338
|
+
fetch2.post = _post;
|
|
339
|
+
fetch2.put = _put;
|
|
333
340
|
var index_default = fetch2;
|
|
334
341
|
export {
|
|
335
342
|
FetchAs,
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Toufiqur Rahaman Chowdhury",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/alien45/superutils/issues"
|
|
5
|
+
},
|
|
3
6
|
"description": "A lightweight `fetch` wrapper for browsers and Node.js, designed to simplify data fetching and reduce boilerplate.",
|
|
4
7
|
"dependencies": {
|
|
5
|
-
"@superutils/core": "^1.0.
|
|
6
|
-
"@superutils/promise": "^1.0.
|
|
8
|
+
"@superutils/core": "^1.0.8",
|
|
9
|
+
"@superutils/promise": "^1.0.9"
|
|
7
10
|
},
|
|
8
11
|
"files": [
|
|
9
12
|
"dist",
|
|
10
13
|
"README.md",
|
|
11
14
|
"LICENSE"
|
|
12
15
|
],
|
|
16
|
+
"homepage": "https://alien45.github.io/superutils/packages/@superutils/fetch/",
|
|
13
17
|
"keywords": [
|
|
14
18
|
"promise",
|
|
15
19
|
"async",
|
|
@@ -20,12 +24,16 @@
|
|
|
20
24
|
"main": "dist/index.js",
|
|
21
25
|
"name": "@superutils/fetch",
|
|
22
26
|
"peerDependencies": {
|
|
23
|
-
"@superutils/core": "^1.0.
|
|
24
|
-
"@superutils/promise": "^1.0.
|
|
27
|
+
"@superutils/core": "^1.0.8",
|
|
28
|
+
"@superutils/promise": "^1.0.9"
|
|
25
29
|
},
|
|
26
30
|
"publishConfig": {
|
|
27
31
|
"access": "public"
|
|
28
32
|
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/alien45/superutils.git"
|
|
36
|
+
},
|
|
29
37
|
"scripts": {
|
|
30
38
|
"_build": "tsc -p tsconfig.json",
|
|
31
39
|
"_watch": "tsc -p tsconfig.json --watch",
|
|
@@ -37,5 +45,5 @@
|
|
|
37
45
|
"sideEffects": false,
|
|
38
46
|
"type": "module",
|
|
39
47
|
"types": "dist/index.d.ts",
|
|
40
|
-
"version": "1.0.
|
|
48
|
+
"version": "1.0.3"
|
|
41
49
|
}
|