@superutils/fetch 1.5.0 → 1.5.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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _superutils_promise from '@superutils/promise';
2
2
  import { RetryOptions, RetryIfFunc, TimeoutOptions, IPromisE_Timeout, DeferredAsyncOptions } from '@superutils/promise';
3
- export { DeferredAsyncOptions, ResolveError, ResolveIgnored, TIMEOUT_FALLBACK, TIMEOUT_MAX, TimeoutPromise } from '@superutils/promise';
3
+ export { DeferredAsyncOptions, OnEarlyFinalize, OnFinalize, ResolveError, ResolveIgnored, RetryIfFunc, RetryOptions, TIMEOUT_FALLBACK, TIMEOUT_MAX, TimeoutOptions, TimeoutPromise } from '@superutils/promise';
4
4
  import { ValueOrPromise, DropFirst } from '@superutils/core';
5
5
 
6
6
  /** Commonly used content types for easier access */
@@ -44,34 +44,36 @@ type Interceptor<T, TArgs extends unknown[]> = (...args: [value: T, ...TArgs]) =
44
44
  *
45
45
  * @returns returning undefined or not returning anything will not override the error
46
46
  *
47
- * @example intercept fetch errors to log errors
48
- * ```typescript
49
- * import PromisE from '@superutils/promise'
47
+ * @example
48
+ * #### Intercept fetch errors to log errors
49
+ * ```javascript
50
+ * import fetch from '@superutils/fetch'
50
51
  *
51
52
  * // not returning anything or returning undefined will avoid transforming the error.
52
53
  * const logError = fetchErr => console.log(fetchErr)
53
- * const result = await PromisE.fetch('https://my.domain.com/api/that/fails', {
54
- * interceptors: {
55
- * error: [logError]
56
- * }
54
+ * const result = await fetch.get('https://dummyjson.com/http/400', {
55
+ * interceptors: {
56
+ * error: [logError]
57
+ * }
57
58
  * })
58
59
  * ```
59
60
  *
60
- * @example intercept & transform fetch errors
61
- * ```typescript
62
- * import PromisE from '@superutils/promise'
61
+ * @example
62
+ * #### Intercept & transform fetch errors
63
+ * ```javascript
64
+ * import fetch from '@superutils/fetch'
63
65
  *
64
66
  * // Interceptors can be async functions or just return a promise that resolves to the error.
65
67
  * // If the execution of the interceptor fails or promise rejects, it will be ignored.
66
68
  * // To transform the error it must directly return an error or a Promise that `resolves` with an error.
67
69
  * const transformError = async (fetchErr, url, options) => {
68
- * fetchErr.message = 'Custom errormessage'
69
- * return Promise.resolve(fetchErr)
70
+ * fetchErr.message = 'Custom errormessage'
71
+ * return Promise.resolve(fetchErr)
70
72
  * }
71
- * const result = await PromisE.fetch('https://my.domain.com/api/that/fails', {
72
- * interceptors: {
73
- * error: [transformError]
74
- * }
73
+ * const result = await fetch.get('https://dummyjson.com/http/400', {
74
+ * interceptors: {
75
+ * error: [transformError]
76
+ * }
75
77
  * })
76
78
  * ```
77
79
  */
@@ -82,19 +84,21 @@ type FetchInterceptorError = Interceptor<FetchError, FetchArgsInterceptor>;
82
84
  * 1. by returning an API URL (string/URL)
83
85
  * 2. by modifying the properties of the options parameter to be used before making the fetch request
84
86
  *
85
- * @example intercept and transform fetch request
87
+ * @example
88
+ * #### Intercept and transform fetch request
86
89
  * ```typescript
87
- * import PromisE from '@superutils/promise'
90
+ * import fetch from '@superutils/fetch'
88
91
  *
89
92
  * // update API version number
90
93
  * const apiV1ToV2 = url => `${url}`.replace('api/v1', 'api/v2')
91
94
  * const includeAuthToken = (url, options) => {
92
- * options.headers.set('x-auth-token', 'my-auth-token')
95
+ * options.headers.set('x-auth-token', 'my-auth-token')
93
96
  * }
94
- * const data = await PromisE.fetch('https://my.domain.com/api', {
95
- * interceptors: {
96
- * result: [apiV1ToV2, includeAuthToken]
97
- * }
97
+ * const result = await fetch.get('https://dummyjson.com/products', {
98
+ * method: 'post',
99
+ * interceptors: {
100
+ * result: [apiV1ToV2, includeAuthToken]
101
+ * }
98
102
  * })
99
103
  * ```
100
104
  */
@@ -106,24 +110,29 @@ type FetchInterceptorRequest = Interceptor<FetchArgs[0], [
106
110
  *
107
111
  * This interceptor can also be used as a transformer by return a different/modified {@link Response}.
108
112
  *
109
- * @example intercept and transform response:
110
- * ```typescript
111
- * import PromisE from '@superutils/promise'
113
+ * @example
114
+ * #### Intercept and transform response:
115
+ * ```javascript
116
+ * import fetch from '@superutils/fetch'
112
117
  *
113
- * // After successful login, retrieve user balance.
118
+ * // After successful login, retrieve full user details.
114
119
  * // This is probably better suited as a result transformer but play along as this is
115
120
  * // just a hypothetical scenario ;)
116
- * const includeBalance = async response => {
117
- * const balance = await PromisE.fetch('https://my.domain.com/api/user/12325345/balance')
118
- * const user = await response.json()
119
- * user.balance = balance
120
- * return new Response(JSON.stringify(user))
121
+ * const getUser = async response => {
122
+ * const authResult = await response.json()
123
+ * const userDetails = await fetch.get('https://dummyjson.com/users/1')
124
+ * const userAuth = { ...userDetails, ...authResult }
125
+ * return new Response(JSON.stringify(userAuth))
121
126
  * }
122
- * const user = await PromisE.fetch('https://my.domain.com/api/login', {
123
- * interceptors: {
124
- * response: [includeBalance]
125
- * }
126
- * })
127
+ * const user = await fetch.post(
128
+ * 'https://dummyjson.com/user/login',
129
+ * { // data/request body
130
+ * username: 'emilys',
131
+ * password: 'emilyspass',
132
+ * expiresInMins: 30,
133
+ * },
134
+ * { interceptors: { response: [getUser] } }
135
+ * )
127
136
  * ```
128
137
  */
129
138
  type FetchInterceptorResponse = Interceptor<Response, FetchArgsInterceptor>;
@@ -140,32 +149,45 @@ type FetchInterceptorResponse = Interceptor<Response, FetchArgsInterceptor>;
140
149
  * This interceptor can also be used as a transformer by returns a different/modified result.
141
150
  *
142
151
  *
143
- * @example intercept and transform fetch result
144
- * ```typescript
145
- * import PromisE from '@superutils/promise'
152
+ * @example
153
+ * #### Intercept and transform fetch result
154
+ * ```javascript
155
+ * import fetch from '@superutils/fetch'
146
156
  *
147
- * // first transform result by extracting result.data
148
- * const extractData = result => result?.data ?? result
157
+ * // first transform result (user object) and ensure user result alwasy contain a hexadecimal crypto balance
158
+ * const ensureBalanceHex = (user = {}) => {
159
+ * user.crypto ??= {}
160
+ * user.crypto.balance ??= '0x0'
161
+ * return user
162
+ * }
149
163
  * // then check convert hexadecimal number to BigInt
150
- * const hexToBigInt = data => {
151
- * if (data.hasOwnProperty('balance') && `${data.balance}`.startsWith('0x')) {
152
- * data.balance = BigInt(data.balance)
153
- * }
154
- * return data
164
+ * const hexToBigInt = user => {
165
+ * user.crypto.balance = BigInt(user.crypto.balance)
166
+ * return user
155
167
  * }
156
168
  * // then log balance (no transformation)
157
- * const logBalance = data => {
158
- * data?.hasOwnProperty('balance') && console.log(data.balance)
169
+ * const logBalance = (result, url) => {
170
+ * // only log balance for single user requests
171
+ * const shouldLog = result?.hasOwnProperty('crypto') && /^[0-9]+$/.test(
172
+ * url?.split('/users/')[1].replace('/', '')
173
+ * )
174
+ * shouldLog && console.log(
175
+ * new Date().toISOString(),
176
+ * '[UserBalance] UserID:', result.id,
177
+ * result.crypto.balance
178
+ * )
159
179
  * }
160
- * const data = await PromisE.fetch('https://my.domain.com/api', {
161
- * interceptors: {
162
- * result: [
163
- * extractData,
164
- * hexToBigInt,
165
- * logBalance
166
- * ]
167
- * }
180
+ * // now we make the actaul fetch request
181
+ * const result = await fetch.get('https://dummyjson.com/users/1', {
182
+ * interceptors: {
183
+ * result: [
184
+ * ensureBalanceHex,
185
+ * hexToBigInt,
186
+ * logBalance
187
+ * ]
188
+ * }
168
189
  * })
190
+ * console.log({result})
169
191
  * ```
170
192
  */
171
193
  type FetchInterceptorResult<Args extends unknown[] = FetchArgsInterceptor> = Interceptor<unknown, Args>;
@@ -277,7 +299,7 @@ type FetchCustomOptions = {
277
299
  * See {@link FetchInterceptors} for more details.
278
300
  */
279
301
  interceptors?: FetchInterceptors;
280
- /** Whether to validate URL before making the request. Default: `true` */
302
+ /** Whether to validate URL before making the request. Default: `false` */
281
303
  validateUrl?: boolean;
282
304
  } & FetchRetryOptions & TimeoutOptions<[]>;
283
305
  /** Default args */
@@ -303,8 +325,24 @@ type FetchFunc = (...args: FetchArgs) => Promise<Response>;
303
325
  */
304
326
  type FetchOptions = Omit<RequestInit, 'body'> & FetchCustomOptions;
305
327
  /** Default fetch options */
306
- type FetchOptionsDefault = Omit<FetchOptionsInterceptor, 'abortCtrl' | 'as' | 'method' | 'signal' | 'timeout'> & {
307
- /** Request timeout duration in milliseconds. Default: `30_000` (30 seconds) */
328
+ type FetchOptionsDefault = Omit<FetchOptionsInterceptor, 'abortCtrl' | 'as' | 'method' | 'signal' | 'timeout' | 'headers'> & {
329
+ /**
330
+ * Request headers.
331
+ *
332
+ * Deafult:
333
+ * - No default content type set when `fetch()` is directly invoked.
334
+ * - `"content-type": "application/json"`: for `createPostClient()`, `fetch.post()`,
335
+ * `fetch.post.deferred()` and other method specific functions
336
+ */
337
+ headers: HeadersInit;
338
+ /**
339
+ * Request timeout duration in milliseconds.
340
+ *
341
+ * Default:
342
+ * - `30_000` for `createClient()`, `createPostClient()` and
343
+ * all method specific functions (`fetch.METHOD` & `fetch.METHOD.deferred()`
344
+ * - `2147483647` when `fetch()` invoked directly
345
+ */
308
346
  timeout: number;
309
347
  };
310
348
  /**
@@ -360,30 +398,10 @@ type PostArgs = [
360
398
  * ```typescript
361
399
  * import fetch, { type PostDeferredCbArgs } from '@superutils/fetch'
362
400
  *
363
- * // test with types
364
401
  * type T1 = PostDeferredCbArgs<string | URL, undefined> // expected: [data, options]
365
- * type T2 = PostDeferredCbArgs<undefined, string> // expected: [url, options]
402
+ * type T2 = PostDeferredCbArgs<string | undefined, string> // expected: [url, options]
366
403
  * type T3 = PostDeferredCbArgs // expected: [url, data, options]
367
404
  * type T4 = PostDeferredCbArgs<string, string> // expected: [options]
368
- *
369
- * const data = { name: 'test' }
370
- * const url = 'https://domain.com'
371
- * // test with fetch.post.deferred()
372
- * const f1 = fetch.post.deferred({}, 'https://domain.com')
373
- * // expected: [data, options]
374
- * f1({data: 1}).then(console.log, console.warn)
375
- *
376
- * const f2 = fetch.post.deferred({}, undefined, 'dome data')
377
- * // expected: [url, options]
378
- * f2('https').then(console.log, console.warn)
379
- *
380
- * const f3 = fetch.post.deferred({})
381
- * // expected: [url, data, options]
382
- * f3('https://domain.com').then(console.log, console.warn)
383
- *
384
- * const f4 = fetch.post.deferred({}, 'url', 'data')
385
- * // expected: [options]
386
- * f4().then(console.log, console.warn)
387
405
  * ```
388
406
  */
389
407
  type PostDeferredCbArgs<DefaultUrl = undefined, DefaultData = undefined, Options = PostArgs[2], PostArgsReq extends unknown[] = Required<PostArgs>, _url = undefined extends DefaultUrl ? undefined : DefaultUrl, _data = undefined extends DefaultData ? undefined : DefaultData> = [_url, _data] extends [PostArgsReq[0], undefined] ? [
@@ -440,45 +458,41 @@ type ClientData<FixedOptions> = ExtractAs<[FixedOptions]> extends FetchAs.json ?
440
458
  * The returned client also includes a `.deferred()` method, providing the same debounce, throttle, and sequential
441
459
  * execution capabilities found in functions like `fetch.get.deferred()`.
442
460
  *
443
- * @example create reusable clients
461
+ * @example
462
+ * #### Create reusable clients
444
463
  * ```javascript
445
464
  * import { createClient } from '@superutils/fetch'
446
465
  *
447
466
  * // Create a "GET" client with default headers and a 5-second timeout
448
467
  * const apiClient = createClient(
449
- * {
450
- * // fixed options cannot be overridden
451
- * method: 'get',
452
- * },
453
- * {
454
- * // default options can be overridden
455
- * headers: {
456
- * Authorization: 'Bearer my-secret-token',
457
- * 'Content-Type': 'application/json',
458
- * },
459
- * timeout: 5000,
460
- * },
461
- * {
462
- * // default defer options (can be overridden)
463
- * delay: 300,
464
- * retry: 2, // If request fails, retry up to two more times
465
- * },
468
+ * { method: 'get' }, // fixed options cannot be overridden
469
+ * { // default options can be overridden
470
+ * headers: {
471
+ * Authorization: 'Bearer my-secret-token',
472
+ * 'Content-Type': 'application/json',
473
+ * },
474
+ * timeout: 5000,
475
+ * },
476
+ * {// default defer options (can be overridden)
477
+ * delay: 300,
478
+ * retry: 2, // If request fails, retry up to two more times
479
+ * },
466
480
  * )
467
481
  *
468
482
  * // Use it just like the standard fetch
469
483
  * apiClient('https://dummyjson.com/products/1', {
470
- * // The 'method' property cannot be overridden as it is used in the fixed options when creating the client.
471
- * // In TypeScript, the compiler will not allow this property.
472
- * // In Javascript, it will simply be ignored.
473
- * // method: 'post',
474
- * timeout: 3000, // The 'timeout' property can be overridden
484
+ * // The 'method' property cannot be overridden as it is used in the fixed options when creating the client.
485
+ * // In TypeScript, the compiler will not allow this property.
486
+ * // In Javascript, it will simply be ignored.
487
+ * // method: 'post',
488
+ * timeout: 3000, // The 'timeout' property can be overridden
475
489
  * }).then(console.log, console.warn)
476
490
  *
477
491
  * // create a deferred client using "apiClient"
478
492
  * const deferredClient = apiClient.deferred(
479
- * { retry: 0 }, // disable retrying by overriding the `retry` defer option
480
- * 'https://dummyjson.com/products/1',
481
- * { timeout: 3000 },
493
+ * { retry: 0 }, // disable retrying by overriding the `retry` defer option
494
+ * 'https://dummyjson.com/products/1',
495
+ * { timeout: 3000 },
482
496
  * )
483
497
  * deferredClient({ timeout: 10000 }) // timeout is overridden by individual request
484
498
  * .then(console.log, console.warn)
@@ -503,24 +517,25 @@ commonOptions?: FetchOptions & CommonOptions, commonDeferOptions?: DeferredAsync
503
517
  * Similar to `createClient`, the returned function comes equipped with a `.deferred()` method, enabling debounced,
504
518
  * throttled, or sequential execution.
505
519
  *
506
- * @example create reusable clients
520
+ * @example
521
+ * #### Create reusable clients
507
522
  * ```javascript
508
523
  * import { createPostClient, FetchAs } from '@superutils/fetch'
509
524
  *
510
525
  * // Create a POST client with 10-second as the default timeout
511
526
  * const postClient = createPostClient(
512
- * {
513
- * method: 'post',
514
- * headers: { 'content-type': 'application/json' },
527
+ * { // fixed options cannot be overrided by client calls
528
+ * method: 'post',
529
+ * headers: { 'content-type': 'application/json' },
515
530
  * },
516
- * { timeout: 10000 },
531
+ * { timeout: 10000 }, // common options that can be overriden by client calls
517
532
  * )
518
533
  *
519
534
  * // Invoking `postClient()` automatically applies the pre-configured options
520
535
  * postClient(
521
- * 'https://dummyjson.com/products/add',
522
- * { title: 'New Product' }, // data/body
523
- * {}, // other options
536
+ * 'https://dummyjson.com/products/add',
537
+ * { title: 'New Product' }, // data/body
538
+ * {}, // other options
524
539
  * ).then(console.log)
525
540
  *
526
541
  * // create a deferred client using "postClient"
@@ -530,10 +545,7 @@ commonOptions?: FetchOptions & CommonOptions, commonDeferOptions?: DeferredAsync
530
545
  * onResult: console.log, // prints only successful results
531
546
  * },
532
547
  * 'https://dummyjson.com/products/add',
533
- * {
534
- * method: 'patch',
535
- * timeout: 3000,
536
- * },
548
+ * { method: 'patch', timeout: 3000 },
537
549
  * )
538
550
  * updateProduct({ title: 'New title 1' }) // ignored by debounce
539
551
  * updateProduct({ title: 'New title 2' }) // executed
@@ -574,12 +586,13 @@ declare const executeInterceptors: <T, TArgs extends unknown[]>(value: T, signal
574
586
  * @param options.as (optional) determines how to parse the result. Default: {@link FetchAs.json}
575
587
  * @param options.method (optional) fetch method. Default: `'get'`
576
588
  *
577
- * @example Make a simple HTTP requests
578
- * ```typescript
589
+ * @example
590
+ * #### Make a simple HTTP requests
591
+ * ```javascript
579
592
  * import { fetch } from '@superutils/fetch'
580
593
  *
581
594
  * // no need for `response.json()` or `result.data.data` drilling
582
- * fetch('https://dummyjson.com/products/1')
595
+ * fetch.get('https://dummyjson.com/products/1')
583
596
  * .then(product => console.log(product))
584
597
  * ```
585
598
  */
@@ -594,10 +607,10 @@ declare const fetch$1: {
594
607
  *
595
608
  * Notes:
596
609
  * - item properties will be prioritized in the order of sequence they were passed in
597
- * - the following properties will be merged
598
- * * `errMsgs`
599
- * * `headers`
600
- * * `interceptors`
610
+ * - the following properties will be merged:
611
+ * * `errMsgs`
612
+ * * `headers`
613
+ * * `interceptors`
601
614
  * - all other properties will simply override previous values
602
615
  *
603
616
  * @returns combined
@@ -856,8 +869,8 @@ declare const methods: {
856
869
  * import fetch from '@superutils/fetch'
857
870
  *
858
871
  * fetch('https://dummyjson.com/products/1')
859
- * .then(response => response.json())
860
- * .then(console.log, console.error)
872
+ * .then(response => response.json())
873
+ * .then(console.log, console.error)
861
874
  * ```
862
875
  *
863
876
  * @example
@@ -867,13 +880,9 @@ declare const methods: {
867
880
  *
868
881
  * // no need for `response.json()` or `result.data.data` drilling
869
882
  * fetch.get('https://dummyjson.com/products/1')
870
- * .then(product => console.log(product))
871
- * fetch.get('https://dummyjson.com/products/1')
872
- * .then(product => console.log(product))
873
- *
874
- *
883
+ * .then(product => console.log(product))
875
884
  * fetch.post('https://dummyjson.com/products/add', { title: 'Product title' })
876
- * .then(product => console.log(product))
885
+ * .then(product => console.log(product))
877
886
  * ```
878
887
  *
879
888
  *
@@ -903,10 +912,10 @@ declare const methods: {
903
912
  *
904
913
  * // add an interceptor to conditionally include header before making requests
905
914
  * interceptors.request.push((url, options) => {
906
- * // ignore login requests
907
- * if (`${url}`.includes('/login')) return
915
+ * // ignore login requests
916
+ * if (`${url}`.includes('/login')) return
908
917
  *
909
- * options.headers.set('x-auth-token', 'my-auth-token')
918
+ * options.headers.set('x-auth-token', 'my-auth-token')
910
919
  * })
911
920
  * ```
912
921
  */
package/dist/index.js CHANGED
@@ -1,3 +1,12 @@
1
+ // src/index.ts
2
+ import {
3
+ ResolveError,
4
+ ResolveIgnored,
5
+ TIMEOUT_FALLBACK,
6
+ TIMEOUT_MAX as TIMEOUT_MAX2,
7
+ TimeoutPromise
8
+ } from "@superutils/promise";
9
+
1
10
  // src/createClient.ts
2
11
  import { deferredCallback } from "@superutils/promise";
3
12
 
@@ -6,10 +15,11 @@ import {
6
15
  fallbackIfFails as fallbackIfFails3,
7
16
  isError,
8
17
  isFn as isFn4,
18
+ isObj as isObj2,
9
19
  isPromise,
10
20
  isUrlValid
11
21
  } from "@superutils/core";
12
- import { timeout as PromisE_timeout } from "@superutils/promise";
22
+ import { timeout as PromisE_timeout, TIMEOUT_MAX } from "@superutils/promise";
13
23
 
14
24
  // src/executeInterceptors.ts
15
25
  import { fallbackIfFails, isFn } from "@superutils/core";
@@ -166,20 +176,25 @@ var FetchError = class _FetchError extends Error {
166
176
  }
167
177
  };
168
178
 
169
- // src/types/index.ts
170
- import {
171
- ResolveError,
172
- ResolveIgnored,
173
- TIMEOUT_FALLBACK,
174
- TIMEOUT_MAX,
175
- TimeoutPromise
176
- } from "@superutils/promise";
177
-
178
179
  // src/fetch.ts
179
180
  var fetch = (url, options = {}) => {
180
181
  var _a, _b, _c;
182
+ if (!isObj2(options)) options = {};
183
+ let fromPostClient = false;
184
+ if (options.fromPostClient) {
185
+ delete options.fromPostClient;
186
+ fromPostClient = true;
187
+ }
181
188
  let response;
182
- const opts = mergeOptions_default(fetch.defaults, options);
189
+ const opts = mergeOptions_default(
190
+ {
191
+ abortOnEarlyFinalize: fetch.defaults.abortOnEarlyFinalize,
192
+ errMsgs: fetch.defaults.errMsgs,
193
+ timeout: TIMEOUT_MAX,
194
+ validateUrl: false
195
+ },
196
+ options
197
+ );
183
198
  opts.abortCtrl = opts.abortCtrl instanceof AbortController ? opts.abortCtrl : new AbortController();
184
199
  (_a = opts.as) != null ? _a : opts.as = "response" /* response */;
185
200
  (_b = opts.method) != null ? _b : opts.method = "get";
@@ -210,29 +225,31 @@ var fetch = (url, options = {}) => {
210
225
  return PromisE_timeout(opts, async () => {
211
226
  var _a2, _b2, _c2, _d, _e;
212
227
  try {
213
- let contentType = headers.get("content-type");
214
- if (!contentType) {
215
- headers.set("content-type", ContentType.APPLICATION_JSON);
216
- contentType = ContentType.APPLICATION_JSON;
217
- }
218
228
  url = await executeInterceptors_default(
219
229
  url,
220
230
  abortCtrl.signal,
221
231
  (_a2 = opts.interceptors) == null ? void 0 : _a2.request,
222
232
  opts
223
233
  );
224
- const { body, errMsgs, validateUrl = true } = opts;
234
+ const { body, errMsgs, validateUrl = false } = opts;
225
235
  (_b2 = opts.signal) != null ? _b2 : opts.signal = abortCtrl.signal;
226
236
  if (validateUrl && !isUrlValid(url, false))
227
237
  throw new Error(errMsgs.invalidUrl);
228
- const shouldStringifyBody = [
229
- ContentType.APPLICATION_JSON,
230
- ContentType.APPLICATION_X_WWW_FORM_URLENCODED
231
- ].find((x) => contentType.includes(x)) && !["undefined", "string"].includes(typeof body);
232
- if (shouldStringifyBody)
233
- opts.body = JSON.stringify(
234
- isFn4(body) ? fallbackIfFails3(body, [], void 0) : body
235
- );
238
+ if (fromPostClient) {
239
+ let contentType = headers.get("content-type");
240
+ if (!contentType) {
241
+ headers.set("content-type", ContentType.APPLICATION_JSON);
242
+ contentType = ContentType.APPLICATION_JSON;
243
+ }
244
+ const shouldStringifyBody = ["delete", "patch", "post", "put"].includes(
245
+ `${opts.method}`.toLowerCase()
246
+ ) && !["undefined", "string"].includes(typeof body) && isObj2(body, true) && contentType === ContentType.APPLICATION_JSON;
247
+ if (shouldStringifyBody) {
248
+ opts.body = JSON.stringify(
249
+ isFn4(body) ? fallbackIfFails3(body, [], void 0) : body
250
+ );
251
+ }
252
+ }
236
253
  response = await getResponse_default(url, opts);
237
254
  response = await executeInterceptors_default(
238
255
  response,
@@ -298,8 +315,8 @@ fetch.defaults = {
298
315
  response: [],
299
316
  result: []
300
317
  },
301
- timeout: 3e4,
302
- validateUrl: true
318
+ timeout: 6e4,
319
+ validateUrl: false
303
320
  };
304
321
  var interceptErr = async (err, url, options, response) => {
305
322
  var _a, _b, _c;
@@ -325,6 +342,7 @@ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
325
342
  function client(url, options) {
326
343
  var _a;
327
344
  const mergedOptions = mergeOptions_default(
345
+ fetch_default.defaults,
328
346
  commonOptions,
329
347
  options,
330
348
  fixedOptions
@@ -338,6 +356,7 @@ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
338
356
  const fetchCb = (...args) => {
339
357
  var _a, _b, _c;
340
358
  const mergedOptions = (_a = mergeOptions_default(
359
+ fetch_default.defaults,
341
360
  commonOptions,
342
361
  defaultOptions,
343
362
  defaultUrl === void 0 ? args[1] : args[0],
@@ -367,6 +386,7 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
367
386
  function client(url, data, options) {
368
387
  var _a, _b;
369
388
  const mergedOptions = mergeOptions_default(
389
+ fetch_default.defaults,
370
390
  commonOptions,
371
391
  options,
372
392
  fixedOptions
@@ -375,6 +395,7 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
375
395
  (_a = mergedOptions.as) != null ? _a : mergedOptions.as = "json" /* json */;
376
396
  mergedOptions.body = data;
377
397
  (_b = mergedOptions.method) != null ? _b : mergedOptions.method = "post";
398
+ mergedOptions.fromPostClient = true;
378
399
  return fetch_default(url, mergedOptions);
379
400
  }
380
401
  client.deferred = (deferOptions, defaultUrl, defaultData, defaultOptions) => {
@@ -384,6 +405,7 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
384
405
  if (defaultUrl !== void 0) args.splice(0, 0, defaultUrl);
385
406
  if (defaultData !== void 0) args.splice(1, 0, defaultData);
386
407
  const mergedOptions = (_a = mergeOptions_default(
408
+ fetch_default.defaults,
387
409
  commonOptions,
388
410
  defaultOptions,
389
411
  args[2],
@@ -395,6 +417,7 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
395
417
  _abortCtrl = new AbortController();
396
418
  mergedOptions.body = (_d = args[1]) != null ? _d : mergedOptions.body;
397
419
  (_e = mergedOptions.method) != null ? _e : mergedOptions.method = "post";
420
+ mergedOptions.fromPostClient = true;
398
421
  return fetch_default(args[0], mergedOptions);
399
422
  };
400
423
  return deferredCallback2(postCb, {
@@ -439,7 +462,7 @@ export {
439
462
  ResolveError,
440
463
  ResolveIgnored,
441
464
  TIMEOUT_FALLBACK,
442
- TIMEOUT_MAX,
465
+ TIMEOUT_MAX2 as TIMEOUT_MAX,
443
466
  TimeoutPromise,
444
467
  createClient,
445
468
  createPostClient,
package/package.json CHANGED
@@ -5,8 +5,8 @@
5
5
  },
6
6
  "description": "A lightweight `fetch` wrapper for browsers and Node.js, designed to simplify data fetching and reduce boilerplate.",
7
7
  "dependencies": {
8
- "@superutils/core": "^1.2.2",
9
- "@superutils/promise": "^1.3.0"
8
+ "@superutils/core": "^1.2.4",
9
+ "@superutils/promise": "^1.3.2"
10
10
  },
11
11
  "files": [
12
12
  "dist",
@@ -53,6 +53,6 @@
53
53
  "module": "./dist/index.js",
54
54
  "type": "module",
55
55
  "types": "./dist/index.d.ts",
56
- "version": "1.5.0",
57
- "gitHead": "382c9c3b6be8e7aad67ef7f89a0b43a4c6c2fb90"
56
+ "version": "1.5.2",
57
+ "gitHead": "bdecb6b7e72557ac91be0b4e2b2cf47dc8dc15eb"
58
58
  }