@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 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): make HTTP requests just like built-in `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 the built-in `fetch()`.
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, IPromisE, DeferredAsyncOptions } from '@superutils/promise';
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 FetchArgs<OmitMethod extends boolean = false> = [
7
- url: string | URL,
8
- options?: OmitMethod extends true ? Omit<FetchOptions, 'method'> : FetchOptions
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 interceprors will always be executed before local interceptors.
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 deffered post-like methods.
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 = PostDeferredCallbackArgs<string | URL, undefined> // expected: [data, options]
293
- * type T2 = PostDeferredCallbackArgs<undefined, string> // expected: [url, options]
294
- * type T3 = PostDeferredCallbackArgs // expected: [url, data, options]
295
- * type T4 = PostDeferredCallbackArgs<string, string> // expected: [options]
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 postDeferred()
300
- * const f1 = postDeferred({}, 'https://domain.com')
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 = postDeferred({}, undefined, 'dome data')
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 = postDeferred({})
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 = postDeferred({}, 'url', 'data')
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, OmitMethod extends boolean = true, CbArgs extends PostArgs<OmitMethod> = PostArgs<OmitMethod>, Options = CbArgs[2], CbArgsReq extends unknown[] = Required<CbArgs>> = [TUrl, TData] extends [CbArgsReq[0], undefined] ? [data?: CbArgs[1], options?: Options] : [TUrl, TData] extends [undefined, CbArgsReq[1]] ? [url: CbArgs[0], options?: Options] : [TUrl, TData] extends [CbArgsReq[0], CbArgsReq[1]] ? [options?: Options] : CbArgs;
318
- type PostOptions = Omit<FetchOptions, 'method'> & {
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
- /** Create a method-specific fetch function attached with a `.deferred()` function */
324
- declare const createFetchMethodFunc: (method?: Pick<FetchOptions, "method">["method"]) => {
325
- <T, TOptions extends FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
326
- deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
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 method-specific function for POST-like methods that automatically stringifies `data`
331
- * and attached with a `.deferred()` function
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 createPostMethodFunc: (method?: Pick<PostOptions, "method">["method"]) => {
334
- <T, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
335
- deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
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 FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
383
- deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
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 FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
387
- deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
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 FetchOptions = FetchOptions, TAs extends FetchAs = TOptions["as"] extends FetchAs ? TOptions["as"] : FetchAs.json, TReturn = FetchResult<T>[TAs]>(url: string | URL, options?: TOptions | undefined): _superutils_promise.IPromisE<T>;
391
- deferred<ThisArg = unknown, Delay extends number = number, GlobalUrl = string | URL | undefined, CbArgs extends unknown[] = undefined extends GlobalUrl ? FetchArgs<true> : [options?: Omit<FetchOptions, "method"> | undefined]>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultOptions?: FetchOptions | undefined): <TResult = unknown>(...args: undefined extends GlobalUrl ? FetchArgs<false> : [options?: FetchOptions | undefined]) => _superutils_promise.IPromisE<TResult>;
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, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
395
- deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
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, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
399
- deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
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, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
403
- deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
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, Args extends PostArgs<true> = PostArgs<true>>(url: Args[0], data?: Args[1], options?: Args[2]): _superutils_promise.IPromisE<T>;
407
- deferred<ThisArg, Delay extends number = number, GlobalUrl extends PostArgs[0] | undefined = undefined, GlobalData extends PostArgs[1] | undefined = undefined, CbArgs extends unknown[] = PostDeferredCbArgs<GlobalUrl, GlobalData, true>>(deferOptions?: _superutils_promise.DeferredAsyncOptions<ThisArg, Delay> | undefined, defaultUrl?: GlobalUrl | undefined, defaultData?: GlobalData | undefined, defaultOptions?: PostOptions | undefined): <TResult = unknown>(...args: PostDeferredCbArgs<GlobalUrl, GlobalData, false, PostArgs<false>, PostOptions | undefined, [url: string | URL, data: PostBody | (() => PostBody), options: PostOptions]>) => _superutils_promise.IPromisE<TResult>;
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
- export { type FetchArgs, type FetchArgsInterceptor, FetchAs, type FetchCustomOptions, type FetchDeferredArgs, type FetchErrMsgs, FetchError, type FetchInterceptorError, type FetchInterceptorRequest, type FetchInterceptorResponse, type FetchInterceptorResult, type FetchInterceptors, type FetchOptions, type FetchOptionsDefaults, type FetchOptionsInterceptor, type FetchResult, type FetchRetryOptions, type FetchWithMethods, type Interceptor, type PostArgs, type PostBody, type PostDeferredCbArgs, type PostOptions, createFetchMethodFunc, createPostMethodFunc, fetchDefault as default, fetch, fetchDeferred, fetchResponse, mergeFetchOptions, postDeferred };
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)) return fetchFunc(url, options);
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, _d;
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
- const errorInterceptors = [..._options2.interceptors.error];
137
- const requestInterceptors = [..._options2.interceptors.request];
138
- const responseInterceptors = [..._options2.interceptors.response];
139
- const resultInterceptors = [..._options2.interceptors.result];
140
- url = await executeInterceptors_default(url, requestInterceptors, _options2);
141
- const { as: parseAs, errMsgs, timeout } = _options2;
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)) throw new Error(errMsgs.invalidUrl);
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
- responseInterceptors,
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
- resultInterceptors,
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: (_d = errX == null ? void 0 : errX.cause) != null ? _d : err,
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
- errorInterceptors,
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/fetchDeferred.ts
246
- import PromisE3 from "@superutils/promise";
247
- function fetchDeferred(deferOptions = {}, defaultUrl, defaultOptions) {
248
- let _abortCtrl;
249
- const fetchCallback = (...args) => {
250
- var _a, _b, _c;
251
- let options = (_a = defaultUrl === void 0 ? args[1] : args[0]) != null ? _a : {};
252
- if (defaultOptions) options = mergeFetchOptions_default(defaultOptions, options);
253
- (_b = options.abortCtrl) != null ? _b : options.abortCtrl = new AbortController();
254
- (_c = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _c.call(_abortCtrl);
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
- return PromisE3.deferredCallback(fetchCallback, deferOptions);
264
- }
265
- var fetchDeferred_default = fetchDeferred;
266
-
267
- // src/createFetchMethodFunc.ts
268
- var createFetchMethodFunc = (method = "get") => {
269
- const methodFunc = (...args) => {
270
- var _a;
271
- (_a = args[1]) != null ? _a : args[1] = {};
272
- args[1].method = method;
273
- return fetch_default(...args);
274
- };
275
- methodFunc.deferred = (...args) => {
276
- var _a;
277
- (_a = args[2]) != null ? _a : args[2] = {};
278
- args[2].method = method;
279
- return fetchDeferred_default(...args);
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 methodFunc;
302
+ return func;
282
303
  };
283
- var createFetchMethodFunc_default = createFetchMethodFunc;
304
+ var createClient_default = createClient;
284
305
 
285
- // src/post.ts
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
- function postDeferred(deferOptions = {}, defaultUrl, defaultData, defaultOptions) {
299
- let _abortCtrl;
300
- const doPost = (...args) => {
301
- var _a, _b, _c;
302
- if (defaultUrl !== void 0) args.splice(0, 0, defaultUrl);
303
- if (defaultData !== void 0) args.splice(1, 0, defaultData);
304
- const options = mergeFetchOptions_default(defaultOptions != null ? defaultOptions : {}, (_a = args[2]) != null ? _a : {});
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
- promise.onEarlyFinalize.push(() => _abortCtrl == null ? void 0 : _abortCtrl.abort());
314
- return promise;
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
- methodFunc.deferred = (...args) => {
328
- var _a;
329
- (_a = args[3]) != null ? _a : args[3] = {};
330
- args[3].method = method;
331
- return postDeferred_default(...args);
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 methodFunc;
346
+ return func;
334
347
  };
335
- var createPostMethodFunc_default = createPostMethodFunc;
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 = createFetchMethodFunc_default("get");
348
- var _head = createFetchMethodFunc_default("head");
349
- var _options = createFetchMethodFunc_default("options");
350
- var _delete = createPostMethodFunc_default("delete");
351
- var _patch = createPostMethodFunc_default("patch");
352
- var _post = createPostMethodFunc_default("post");
353
- var _put = createPostMethodFunc_default("put");
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
- createFetchMethodFunc,
380
- createPostMethodFunc,
392
+ createClient,
393
+ createPostClient,
381
394
  index_default as default,
382
395
  fetch,
383
- fetchDeferred,
384
396
  fetchResponse,
385
397
  mergeFetchOptions,
386
- postDeferred
398
+ mergePartialOptions
387
399
  };
package/package.json CHANGED
@@ -45,5 +45,5 @@
45
45
  "sideEffects": false,
46
46
  "type": "module",
47
47
  "types": "dist/index.d.ts",
48
- "version": "1.2.1"
48
+ "version": "1.2.2"
49
49
  }