@superutils/fetch 1.4.2 → 1.5.1

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.cjs ADDED
@@ -0,0 +1,477 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ContentType: () => ContentType,
24
+ FetchAs: () => FetchAs,
25
+ FetchError: () => FetchError,
26
+ ResolveError: () => import_promise2.ResolveError,
27
+ ResolveIgnored: () => import_promise2.ResolveIgnored,
28
+ TIMEOUT_FALLBACK: () => import_promise2.TIMEOUT_FALLBACK,
29
+ TIMEOUT_MAX: () => import_promise2.TIMEOUT_MAX,
30
+ TimeoutPromise: () => import_promise2.TimeoutPromise,
31
+ createClient: () => createClient,
32
+ createPostClient: () => createPostClient,
33
+ default: () => index_default,
34
+ executeInterceptors: () => executeInterceptors,
35
+ fetch: () => fetch2,
36
+ mergeOptions: () => mergeOptions
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+
40
+ // src/createClient.ts
41
+ var import_promise4 = require("@superutils/promise");
42
+
43
+ // src/fetch.ts
44
+ var import_core4 = require("@superutils/core");
45
+ var import_promise3 = require("@superutils/promise");
46
+
47
+ // src/executeInterceptors.ts
48
+ var import_core = require("@superutils/core");
49
+ var executeInterceptors = async (value, signal, interceptors, ...args) => {
50
+ var _a;
51
+ for (const interceptor of [...interceptors != null ? interceptors : []].filter(import_core.isFn)) {
52
+ if (signal == null ? void 0 : signal.aborted) break;
53
+ value = (_a = await (0, import_core.fallbackIfFails)(
54
+ interceptor,
55
+ [value, ...args],
56
+ void 0
57
+ )) != null ? _a : value;
58
+ }
59
+ return value;
60
+ };
61
+ var executeInterceptors_default = executeInterceptors;
62
+
63
+ // src/getResponse.ts
64
+ var import_core2 = require("@superutils/core");
65
+ var import_promise = require("@superutils/promise");
66
+ var getResponse = (url, options = {}) => {
67
+ const fetchFunc = (0, import_core2.isFn)(options.fetchFunc) ? options.fetchFunc : globalThis.fetch;
68
+ if (!(0, import_core2.isPositiveInteger)(options.retry)) return fetchFunc(url, options);
69
+ let attemptCount = 0;
70
+ const response = (0, import_promise.retry)(
71
+ () => {
72
+ attemptCount++;
73
+ return fetchFunc(url, options);
74
+ },
75
+ {
76
+ ...options,
77
+ retryIf: async (res, count, error) => {
78
+ var _a;
79
+ const { abortCtrl, retryIf, signal } = options;
80
+ if ((abortCtrl == null ? void 0 : abortCtrl.signal.aborted) || (signal == null ? void 0 : signal.aborted)) return false;
81
+ return !!((_a = await (0, import_core2.fallbackIfFails)(
82
+ retryIf,
83
+ [res, count, error],
84
+ void 0
85
+ )) != null ? _a : !!error || !(res == null ? void 0 : res.ok));
86
+ }
87
+ }
88
+ ).catch(
89
+ (err) => Promise.reject(
90
+ new Error(`Request failed after attempt #${attemptCount}`, {
91
+ cause: err
92
+ })
93
+ )
94
+ );
95
+ return response;
96
+ };
97
+ var getResponse_default = getResponse;
98
+
99
+ // src/mergeOptions.ts
100
+ var import_core3 = require("@superutils/core");
101
+ var mergeOptions = (...allOptions) => allOptions.reduce(
102
+ (merged, options) => {
103
+ var _a;
104
+ options = (0, import_core3.isObj)(options) ? options : {};
105
+ const { headers, interceptors: ints1 = {} } = merged;
106
+ const { interceptors: ints2 = {} } = options;
107
+ options.headers && new Headers(options.headers).forEach(
108
+ (value, key) => headers.set(key, value)
109
+ );
110
+ return {
111
+ ...merged,
112
+ ...options,
113
+ errMsgs: (0, import_core3.objCopy)(
114
+ options.errMsgs,
115
+ merged.errMsgs,
116
+ [],
117
+ "empty"
118
+ ),
119
+ headers,
120
+ interceptors: {
121
+ error: [...toArr(ints1 == null ? void 0 : ints1.error), ...toArr(ints2 == null ? void 0 : ints2.error)],
122
+ request: [
123
+ ...toArr(ints1 == null ? void 0 : ints1.request),
124
+ ...toArr(ints2 == null ? void 0 : ints2.request)
125
+ ],
126
+ response: [
127
+ ...toArr(ints1 == null ? void 0 : ints1.response),
128
+ ...toArr(ints2 == null ? void 0 : ints2.response)
129
+ ],
130
+ result: [...toArr(ints1 == null ? void 0 : ints1.result), ...toArr(ints2 == null ? void 0 : ints2.result)]
131
+ },
132
+ timeout: (_a = options.timeout) != null ? _a : merged.timeout
133
+ };
134
+ },
135
+ { headers: new Headers() }
136
+ );
137
+ var mergeOptions_default = mergeOptions;
138
+ var toArr = (x) => (0, import_core3.isArr)(x) ? x : (0, import_core3.isFn)(x) ? [x] : [];
139
+
140
+ // src/types/constants.ts
141
+ var ContentType = {
142
+ APPLICATION_JAVASCRIPT: "application/javascript",
143
+ APPLICATION_JSON: "application/json",
144
+ APPLICATION_OCTET_STREAM: "application/octet-stream",
145
+ APPLICATION_PDF: "application/pdf",
146
+ APPLICATION_X_WWW_FORM_URLENCODED: "application/x-www-form-urlencoded",
147
+ APPLICATION_XML: "application/xml",
148
+ APPLICATION_ZIP: "application/zip",
149
+ AUDIO_MPEG: "audio/mpeg",
150
+ MULTIPART_FORM_DATA: "multipart/form-data",
151
+ TEXT_CSS: "text/css",
152
+ TEXT_HTML: "text/html",
153
+ TEXT_PLAIN: "text/plain",
154
+ VIDEO_MP4: "video/mp4"
155
+ };
156
+ var FetchAs = /* @__PURE__ */ ((FetchAs2) => {
157
+ FetchAs2["arrayBuffer"] = "arrayBuffer";
158
+ FetchAs2["blob"] = "blob";
159
+ FetchAs2["bytes"] = "bytes";
160
+ FetchAs2["formData"] = "formData";
161
+ FetchAs2["json"] = "json";
162
+ FetchAs2["response"] = "response";
163
+ FetchAs2["text"] = "text";
164
+ return FetchAs2;
165
+ })(FetchAs || {});
166
+
167
+ // src/types/FetchError.ts
168
+ var FetchError = class _FetchError extends Error {
169
+ constructor(message, options) {
170
+ super(message, { cause: options.cause });
171
+ this.name = "FetchError";
172
+ Object.defineProperties(this, {
173
+ clone: {
174
+ get() {
175
+ return (newMessage) => new _FetchError(newMessage, {
176
+ cause: options.cause,
177
+ options: options.options,
178
+ response: options.response,
179
+ url: options.url
180
+ });
181
+ }
182
+ },
183
+ options: {
184
+ get() {
185
+ return options.options;
186
+ }
187
+ },
188
+ response: {
189
+ get() {
190
+ return options.response;
191
+ }
192
+ },
193
+ url: {
194
+ get() {
195
+ return options.url;
196
+ }
197
+ }
198
+ });
199
+ }
200
+ };
201
+
202
+ // src/types/index.ts
203
+ var import_promise2 = require("@superutils/promise");
204
+
205
+ // src/fetch.ts
206
+ var fetch = (url, options = {}) => {
207
+ var _a, _b, _c;
208
+ let response;
209
+ const opts = mergeOptions_default(fetch.defaults, options);
210
+ opts.abortCtrl = opts.abortCtrl instanceof AbortController ? opts.abortCtrl : new AbortController();
211
+ (_a = opts.as) != null ? _a : opts.as = "response" /* response */;
212
+ (_b = opts.method) != null ? _b : opts.method = "get";
213
+ (_c = opts.signal) != null ? _c : opts.signal = opts.abortCtrl.signal;
214
+ const { abortCtrl, as: parseAs, headers, onAbort, onTimeout } = opts;
215
+ opts.onAbort = async () => {
216
+ var _a2, _b2, _c2, _d, _e, _f;
217
+ const err = (_f = (_e = (_c2 = await (0, import_core4.fallbackIfFails)(onAbort, [], void 0)) != null ? _c2 : (_b2 = (_a2 = opts.abortCtrl) == null ? void 0 : _a2.signal) == null ? void 0 : _b2.reason) != null ? _e : (_d = opts.signal) == null ? void 0 : _d.reason) != null ? _f : opts.errMsgs.aborted;
218
+ if ((0, import_core4.isError)(err) && err.name === "AbortError") {
219
+ err.message = ["This operation was aborted"].includes(err.message) ? opts.errMsgs.aborted : err.message;
220
+ }
221
+ return await interceptErr(
222
+ (0, import_core4.isError)(err) ? err : new Error(err),
223
+ url,
224
+ opts,
225
+ response
226
+ );
227
+ };
228
+ opts.onTimeout = async () => {
229
+ const err = await (0, import_core4.fallbackIfFails)(onTimeout, [], void 0);
230
+ return await interceptErr(
231
+ err != null ? err : new Error(opts.errMsgs.timedout),
232
+ url,
233
+ opts,
234
+ response
235
+ );
236
+ };
237
+ return (0, import_promise3.timeout)(opts, async () => {
238
+ var _a2, _b2, _c2, _d, _e;
239
+ 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
+ url = await executeInterceptors_default(
246
+ url,
247
+ abortCtrl.signal,
248
+ (_a2 = opts.interceptors) == null ? void 0 : _a2.request,
249
+ opts
250
+ );
251
+ const { body, errMsgs, validateUrl = true } = opts;
252
+ (_b2 = opts.signal) != null ? _b2 : opts.signal = abortCtrl.signal;
253
+ if (validateUrl && !(0, import_core4.isUrlValid)(url, false))
254
+ throw new Error(errMsgs.invalidUrl);
255
+ const shouldStringifyBody = [
256
+ ContentType.APPLICATION_JSON,
257
+ ContentType.APPLICATION_X_WWW_FORM_URLENCODED
258
+ ].find((x) => contentType.includes(x)) && !["undefined", "string"].includes(typeof body);
259
+ if (shouldStringifyBody)
260
+ opts.body = JSON.stringify(
261
+ (0, import_core4.isFn)(body) ? (0, import_core4.fallbackIfFails)(body, [], void 0) : body
262
+ );
263
+ response = await getResponse_default(url, opts);
264
+ response = await executeInterceptors_default(
265
+ response,
266
+ abortCtrl.signal,
267
+ (_c2 = opts.interceptors) == null ? void 0 : _c2.response,
268
+ url,
269
+ opts
270
+ );
271
+ const status = (_d = response == null ? void 0 : response.status) != null ? _d : 0;
272
+ const isSuccess = status >= 200 && status < 300;
273
+ if (!isSuccess) {
274
+ const jsonError = await (0, import_core4.fallbackIfFails)(
275
+ // try to parse error response as json first
276
+ () => response.json(),
277
+ [],
278
+ void 0
279
+ );
280
+ throw new Error(
281
+ (jsonError == null ? void 0 : jsonError.message) || `${errMsgs.requestFailed} ${status}`,
282
+ { cause: jsonError }
283
+ );
284
+ }
285
+ const parseFunc = response[parseAs];
286
+ let result = !(0, import_core4.isFn)(parseFunc) ? response : parseFunc.bind(response)();
287
+ if ((0, import_core4.isPromise)(result))
288
+ result = await result.catch(
289
+ (err) => Promise.reject(
290
+ new Error(
291
+ `${errMsgs.parseFailed} ${parseAs}. ${err == null ? void 0 : err.message}`,
292
+ { cause: err }
293
+ )
294
+ )
295
+ );
296
+ result = await executeInterceptors_default(
297
+ result,
298
+ abortCtrl.signal,
299
+ (_e = opts.interceptors) == null ? void 0 : _e.result,
300
+ url,
301
+ opts
302
+ );
303
+ return result;
304
+ } catch (_err) {
305
+ let err = _err;
306
+ err = await interceptErr(_err, url, opts, response);
307
+ return Promise.reject(err);
308
+ }
309
+ });
310
+ };
311
+ fetch.defaults = {
312
+ abortOnEarlyFinalize: true,
313
+ errMsgs: {
314
+ aborted: "Request aborted",
315
+ invalidUrl: "Invalid URL",
316
+ parseFailed: "Failed to parse response as",
317
+ timedout: "Request timed out",
318
+ requestFailed: "Request failed with status code:"
319
+ },
320
+ // all error messages must be defined here
321
+ headers: new Headers(),
322
+ interceptors: {
323
+ error: [],
324
+ request: [],
325
+ response: [],
326
+ result: []
327
+ },
328
+ timeout: 3e4,
329
+ validateUrl: true
330
+ };
331
+ var interceptErr = async (err, url, options, response) => {
332
+ var _a, _b, _c;
333
+ const fErr = await executeInterceptors_default(
334
+ new FetchError((_a = err == null ? void 0 : err.message) != null ? _a : err, {
335
+ cause: (_b = err == null ? void 0 : err.cause) != null ? _b : err,
336
+ response,
337
+ options,
338
+ url
339
+ }),
340
+ void 0,
341
+ // should execute regardless of abort status
342
+ (_c = options.interceptors) == null ? void 0 : _c.error,
343
+ url,
344
+ options
345
+ );
346
+ return fErr;
347
+ };
348
+ var fetch_default = fetch;
349
+
350
+ // src/createClient.ts
351
+ var createClient = (fixedOptions, commonOptions, commonDeferOptions) => {
352
+ function client(url, options) {
353
+ var _a;
354
+ const mergedOptions = mergeOptions_default(
355
+ commonOptions,
356
+ options,
357
+ fixedOptions
358
+ // fixed options will always override other options
359
+ );
360
+ (_a = mergedOptions.as) != null ? _a : mergedOptions.as = "json" /* json */;
361
+ return fetch_default(url, mergedOptions);
362
+ }
363
+ client.deferred = (deferOptions, defaultUrl, defaultOptions) => {
364
+ let _abortCtrl;
365
+ const fetchCb = (...args) => {
366
+ var _a, _b, _c;
367
+ const mergedOptions = (_a = mergeOptions_default(
368
+ commonOptions,
369
+ defaultOptions,
370
+ defaultUrl === void 0 ? args[1] : args[0],
371
+ fixedOptions
372
+ // fixed options will always override other options
373
+ )) != null ? _a : {};
374
+ (_b = mergedOptions.as) != null ? _b : mergedOptions.as = "json" /* json */;
375
+ (_c = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _c.call(_abortCtrl);
376
+ _abortCtrl = new AbortController();
377
+ return fetch_default(
378
+ defaultUrl != null ? defaultUrl : args[0],
379
+ mergedOptions
380
+ );
381
+ };
382
+ return (0, import_promise4.deferredCallback)(fetchCb, {
383
+ ...commonDeferOptions,
384
+ ...deferOptions
385
+ });
386
+ };
387
+ return client;
388
+ };
389
+ var createClient_default = createClient;
390
+
391
+ // src/createPostClient.ts
392
+ var import_promise5 = require("@superutils/promise");
393
+ var createPostClient = (fixedOptions, commonOptions, commonDeferOptions) => {
394
+ function client(url, data, options) {
395
+ var _a, _b;
396
+ const mergedOptions = mergeOptions_default(
397
+ commonOptions,
398
+ options,
399
+ fixedOptions
400
+ // fixed options will always override other options
401
+ );
402
+ (_a = mergedOptions.as) != null ? _a : mergedOptions.as = "json" /* json */;
403
+ mergedOptions.body = data;
404
+ (_b = mergedOptions.method) != null ? _b : mergedOptions.method = "post";
405
+ return fetch_default(url, mergedOptions);
406
+ }
407
+ client.deferred = (deferOptions, defaultUrl, defaultData, defaultOptions) => {
408
+ let _abortCtrl;
409
+ const postCb = (...args) => {
410
+ var _a, _b, _c, _d, _e;
411
+ if (defaultUrl !== void 0) args.splice(0, 0, defaultUrl);
412
+ if (defaultData !== void 0) args.splice(1, 0, defaultData);
413
+ const mergedOptions = (_a = mergeOptions_default(
414
+ commonOptions,
415
+ defaultOptions,
416
+ args[2],
417
+ fixedOptions
418
+ // fixed options will always override other options
419
+ )) != null ? _a : {};
420
+ (_b = mergedOptions.as) != null ? _b : mergedOptions.as = "json" /* json */;
421
+ (_c = _abortCtrl == null ? void 0 : _abortCtrl.abort) == null ? void 0 : _c.call(_abortCtrl);
422
+ _abortCtrl = new AbortController();
423
+ mergedOptions.body = (_d = args[1]) != null ? _d : mergedOptions.body;
424
+ (_e = mergedOptions.method) != null ? _e : mergedOptions.method = "post";
425
+ return fetch_default(args[0], mergedOptions);
426
+ };
427
+ return (0, import_promise5.deferredCallback)(postCb, {
428
+ ...commonDeferOptions,
429
+ ...deferOptions
430
+ });
431
+ };
432
+ return client;
433
+ };
434
+ var createPostClient_default = createPostClient;
435
+
436
+ // src/index.ts
437
+ var methods = {
438
+ /** Make HTTP requests with method GET */
439
+ get: createClient_default({ method: "get" }),
440
+ /** Make HTTP requests with method HEAD */
441
+ head: createClient_default({ method: "head" }),
442
+ /** Make HTTP requests with method OPTIONS */
443
+ options: createClient_default({ method: "options" }),
444
+ /** Make HTTP requests with method DELETE */
445
+ delete: createPostClient_default({ method: "delete" }),
446
+ /** Make HTTP requests with method PATCH */
447
+ patch: createPostClient_default({ method: "patch" }),
448
+ /** Make HTTP requests with method POST */
449
+ post: createPostClient_default({ method: "post" }),
450
+ /** Make HTTP requests with method PUT */
451
+ put: createPostClient_default({ method: "put" })
452
+ };
453
+ var fetch2 = fetch_default;
454
+ fetch2.delete = methods.delete;
455
+ fetch2.get = methods.get;
456
+ fetch2.head = methods.head;
457
+ fetch2.options = methods.options;
458
+ fetch2.patch = methods.patch;
459
+ fetch2.post = methods.post;
460
+ fetch2.put = methods.put;
461
+ var index_default = fetch2;
462
+ // Annotate the CommonJS export names for ESM import in node:
463
+ 0 && (module.exports = {
464
+ ContentType,
465
+ FetchAs,
466
+ FetchError,
467
+ ResolveError,
468
+ ResolveIgnored,
469
+ TIMEOUT_FALLBACK,
470
+ TIMEOUT_MAX,
471
+ TimeoutPromise,
472
+ createClient,
473
+ createPostClient,
474
+ executeInterceptors,
475
+ fetch,
476
+ mergeOptions
477
+ });