@superutils/fetch 1.5.1 → 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/README.md +49 -0
- package/dist/browser/index.min.js +1 -1123
- package/dist/browser/index.min.js.map +1 -1
- package/dist/index.cjs +51 -31
- package/dist/index.d.cts +147 -138
- package/dist/index.d.ts +147 -138
- package/dist/index.js +51 -28
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -23,11 +23,11 @@ __export(index_exports, {
|
|
|
23
23
|
ContentType: () => ContentType,
|
|
24
24
|
FetchAs: () => FetchAs,
|
|
25
25
|
FetchError: () => FetchError,
|
|
26
|
-
ResolveError: () =>
|
|
27
|
-
ResolveIgnored: () =>
|
|
28
|
-
TIMEOUT_FALLBACK: () =>
|
|
29
|
-
TIMEOUT_MAX: () =>
|
|
30
|
-
TimeoutPromise: () =>
|
|
26
|
+
ResolveError: () => import_promise5.ResolveError,
|
|
27
|
+
ResolveIgnored: () => import_promise5.ResolveIgnored,
|
|
28
|
+
TIMEOUT_FALLBACK: () => import_promise5.TIMEOUT_FALLBACK,
|
|
29
|
+
TIMEOUT_MAX: () => import_promise5.TIMEOUT_MAX,
|
|
30
|
+
TimeoutPromise: () => import_promise5.TimeoutPromise,
|
|
31
31
|
createClient: () => createClient,
|
|
32
32
|
createPostClient: () => createPostClient,
|
|
33
33
|
default: () => index_default,
|
|
@@ -36,13 +36,14 @@ __export(index_exports, {
|
|
|
36
36
|
mergeOptions: () => mergeOptions
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
var import_promise5 = require("@superutils/promise");
|
|
39
40
|
|
|
40
41
|
// src/createClient.ts
|
|
41
|
-
var
|
|
42
|
+
var import_promise3 = require("@superutils/promise");
|
|
42
43
|
|
|
43
44
|
// src/fetch.ts
|
|
44
45
|
var import_core4 = require("@superutils/core");
|
|
45
|
-
var
|
|
46
|
+
var import_promise2 = require("@superutils/promise");
|
|
46
47
|
|
|
47
48
|
// src/executeInterceptors.ts
|
|
48
49
|
var import_core = require("@superutils/core");
|
|
@@ -199,14 +200,25 @@ var FetchError = class _FetchError extends Error {
|
|
|
199
200
|
}
|
|
200
201
|
};
|
|
201
202
|
|
|
202
|
-
// src/types/index.ts
|
|
203
|
-
var import_promise2 = require("@superutils/promise");
|
|
204
|
-
|
|
205
203
|
// src/fetch.ts
|
|
206
204
|
var fetch = (url, options = {}) => {
|
|
207
205
|
var _a, _b, _c;
|
|
206
|
+
if (!(0, import_core4.isObj)(options)) options = {};
|
|
207
|
+
let fromPostClient = false;
|
|
208
|
+
if (options.fromPostClient) {
|
|
209
|
+
delete options.fromPostClient;
|
|
210
|
+
fromPostClient = true;
|
|
211
|
+
}
|
|
208
212
|
let response;
|
|
209
|
-
const opts = mergeOptions_default(
|
|
213
|
+
const opts = mergeOptions_default(
|
|
214
|
+
{
|
|
215
|
+
abortOnEarlyFinalize: fetch.defaults.abortOnEarlyFinalize,
|
|
216
|
+
errMsgs: fetch.defaults.errMsgs,
|
|
217
|
+
timeout: import_promise2.TIMEOUT_MAX,
|
|
218
|
+
validateUrl: false
|
|
219
|
+
},
|
|
220
|
+
options
|
|
221
|
+
);
|
|
210
222
|
opts.abortCtrl = opts.abortCtrl instanceof AbortController ? opts.abortCtrl : new AbortController();
|
|
211
223
|
(_a = opts.as) != null ? _a : opts.as = "response" /* response */;
|
|
212
224
|
(_b = opts.method) != null ? _b : opts.method = "get";
|
|
@@ -234,32 +246,34 @@ var fetch = (url, options = {}) => {
|
|
|
234
246
|
response
|
|
235
247
|
);
|
|
236
248
|
};
|
|
237
|
-
return (0,
|
|
249
|
+
return (0, import_promise2.timeout)(opts, async () => {
|
|
238
250
|
var _a2, _b2, _c2, _d, _e;
|
|
239
251
|
try {
|
|
240
|
-
let contentType = headers.get("content-type");
|
|
241
|
-
if (!contentType) {
|
|
242
|
-
headers.set("content-type", ContentType.APPLICATION_JSON);
|
|
243
|
-
contentType = ContentType.APPLICATION_JSON;
|
|
244
|
-
}
|
|
245
252
|
url = await executeInterceptors_default(
|
|
246
253
|
url,
|
|
247
254
|
abortCtrl.signal,
|
|
248
255
|
(_a2 = opts.interceptors) == null ? void 0 : _a2.request,
|
|
249
256
|
opts
|
|
250
257
|
);
|
|
251
|
-
const { body, errMsgs, validateUrl =
|
|
258
|
+
const { body, errMsgs, validateUrl = false } = opts;
|
|
252
259
|
(_b2 = opts.signal) != null ? _b2 : opts.signal = abortCtrl.signal;
|
|
253
260
|
if (validateUrl && !(0, import_core4.isUrlValid)(url, false))
|
|
254
261
|
throw new Error(errMsgs.invalidUrl);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
262
|
+
if (fromPostClient) {
|
|
263
|
+
let contentType = headers.get("content-type");
|
|
264
|
+
if (!contentType) {
|
|
265
|
+
headers.set("content-type", ContentType.APPLICATION_JSON);
|
|
266
|
+
contentType = ContentType.APPLICATION_JSON;
|
|
267
|
+
}
|
|
268
|
+
const shouldStringifyBody = ["delete", "patch", "post", "put"].includes(
|
|
269
|
+
`${opts.method}`.toLowerCase()
|
|
270
|
+
) && !["undefined", "string"].includes(typeof body) && (0, import_core4.isObj)(body, true) && contentType === ContentType.APPLICATION_JSON;
|
|
271
|
+
if (shouldStringifyBody) {
|
|
272
|
+
opts.body = JSON.stringify(
|
|
273
|
+
(0, import_core4.isFn)(body) ? (0, import_core4.fallbackIfFails)(body, [], void 0) : body
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
263
277
|
response = await getResponse_default(url, opts);
|
|
264
278
|
response = await executeInterceptors_default(
|
|
265
279
|
response,
|
|
@@ -325,8 +339,8 @@ fetch.defaults = {
|
|
|
325
339
|
response: [],
|
|
326
340
|
result: []
|
|
327
341
|
},
|
|
328
|
-
timeout:
|
|
329
|
-
validateUrl:
|
|
342
|
+
timeout: 6e4,
|
|
343
|
+
validateUrl: false
|
|
330
344
|
};
|
|
331
345
|
var interceptErr = async (err, url, options, response) => {
|
|
332
346
|
var _a, _b, _c;
|
|
@@ -352,6 +366,7 @@ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
352
366
|
function client(url, options) {
|
|
353
367
|
var _a;
|
|
354
368
|
const mergedOptions = mergeOptions_default(
|
|
369
|
+
fetch_default.defaults,
|
|
355
370
|
commonOptions,
|
|
356
371
|
options,
|
|
357
372
|
fixedOptions
|
|
@@ -365,6 +380,7 @@ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
365
380
|
const fetchCb = (...args) => {
|
|
366
381
|
var _a, _b, _c;
|
|
367
382
|
const mergedOptions = (_a = mergeOptions_default(
|
|
383
|
+
fetch_default.defaults,
|
|
368
384
|
commonOptions,
|
|
369
385
|
defaultOptions,
|
|
370
386
|
defaultUrl === void 0 ? args[1] : args[0],
|
|
@@ -379,7 +395,7 @@ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
379
395
|
mergedOptions
|
|
380
396
|
);
|
|
381
397
|
};
|
|
382
|
-
return (0,
|
|
398
|
+
return (0, import_promise3.deferredCallback)(fetchCb, {
|
|
383
399
|
...commonDeferOptions,
|
|
384
400
|
...deferOptions
|
|
385
401
|
});
|
|
@@ -389,11 +405,12 @@ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
389
405
|
var createClient_default = createClient;
|
|
390
406
|
|
|
391
407
|
// src/createPostClient.ts
|
|
392
|
-
var
|
|
408
|
+
var import_promise4 = require("@superutils/promise");
|
|
393
409
|
var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
394
410
|
function client(url, data, options) {
|
|
395
411
|
var _a, _b;
|
|
396
412
|
const mergedOptions = mergeOptions_default(
|
|
413
|
+
fetch_default.defaults,
|
|
397
414
|
commonOptions,
|
|
398
415
|
options,
|
|
399
416
|
fixedOptions
|
|
@@ -402,6 +419,7 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
402
419
|
(_a = mergedOptions.as) != null ? _a : mergedOptions.as = "json" /* json */;
|
|
403
420
|
mergedOptions.body = data;
|
|
404
421
|
(_b = mergedOptions.method) != null ? _b : mergedOptions.method = "post";
|
|
422
|
+
mergedOptions.fromPostClient = true;
|
|
405
423
|
return fetch_default(url, mergedOptions);
|
|
406
424
|
}
|
|
407
425
|
client.deferred = (deferOptions, defaultUrl, defaultData, defaultOptions) => {
|
|
@@ -411,6 +429,7 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
411
429
|
if (defaultUrl !== void 0) args.splice(0, 0, defaultUrl);
|
|
412
430
|
if (defaultData !== void 0) args.splice(1, 0, defaultData);
|
|
413
431
|
const mergedOptions = (_a = mergeOptions_default(
|
|
432
|
+
fetch_default.defaults,
|
|
414
433
|
commonOptions,
|
|
415
434
|
defaultOptions,
|
|
416
435
|
args[2],
|
|
@@ -422,9 +441,10 @@ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
|
|
|
422
441
|
_abortCtrl = new AbortController();
|
|
423
442
|
mergedOptions.body = (_d = args[1]) != null ? _d : mergedOptions.body;
|
|
424
443
|
(_e = mergedOptions.method) != null ? _e : mergedOptions.method = "post";
|
|
444
|
+
mergedOptions.fromPostClient = true;
|
|
425
445
|
return fetch_default(args[0], mergedOptions);
|
|
426
446
|
};
|
|
427
|
-
return (0,
|
|
447
|
+
return (0, import_promise4.deferredCallback)(postCb, {
|
|
428
448
|
...commonDeferOptions,
|
|
429
449
|
...deferOptions
|
|
430
450
|
});
|
package/dist/index.d.cts
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
|
|
48
|
-
*
|
|
49
|
-
*
|
|
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
|
|
54
|
-
*
|
|
55
|
-
*
|
|
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
|
|
61
|
-
*
|
|
62
|
-
*
|
|
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
|
-
*
|
|
69
|
-
*
|
|
70
|
+
* fetchErr.message = 'Custom errormessage'
|
|
71
|
+
* return Promise.resolve(fetchErr)
|
|
70
72
|
* }
|
|
71
|
-
* const result = await
|
|
72
|
-
*
|
|
73
|
-
*
|
|
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
|
|
87
|
+
* @example
|
|
88
|
+
* #### Intercept and transform fetch request
|
|
86
89
|
* ```typescript
|
|
87
|
-
* import
|
|
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
|
-
*
|
|
95
|
+
* options.headers.set('x-auth-token', 'my-auth-token')
|
|
93
96
|
* }
|
|
94
|
-
* const
|
|
95
|
-
*
|
|
96
|
-
*
|
|
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
|
|
110
|
-
*
|
|
111
|
-
*
|
|
113
|
+
* @example
|
|
114
|
+
* #### Intercept and transform response:
|
|
115
|
+
* ```javascript
|
|
116
|
+
* import fetch from '@superutils/fetch'
|
|
112
117
|
*
|
|
113
|
-
* // After successful login, retrieve user
|
|
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
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
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
|
|
123
|
-
*
|
|
124
|
-
*
|
|
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
|
|
144
|
-
*
|
|
145
|
-
*
|
|
152
|
+
* @example
|
|
153
|
+
* #### Intercept and transform fetch result
|
|
154
|
+
* ```javascript
|
|
155
|
+
* import fetch from '@superutils/fetch'
|
|
146
156
|
*
|
|
147
|
-
* // first transform result
|
|
148
|
-
* const
|
|
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 =
|
|
151
|
-
*
|
|
152
|
-
*
|
|
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 =
|
|
158
|
-
*
|
|
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
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
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: `
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
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
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
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
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
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
|
|
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
|
-
*
|
|
514
|
-
*
|
|
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
|
-
*
|
|
522
|
-
*
|
|
523
|
-
*
|
|
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
|
|
578
|
-
*
|
|
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
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
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
|
-
*
|
|
860
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
907
|
-
*
|
|
915
|
+
* // ignore login requests
|
|
916
|
+
* if (`${url}`.includes('/login')) return
|
|
908
917
|
*
|
|
909
|
-
*
|
|
918
|
+
* options.headers.set('x-auth-token', 'my-auth-token')
|
|
910
919
|
* })
|
|
911
920
|
* ```
|
|
912
921
|
*/
|