@superutils/fetch 1.5.9 → 1.5.10

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.js CHANGED
@@ -12,9 +12,8 @@ import { deferredCallback } from "@superutils/promise";
12
12
 
13
13
  // src/fetch.ts
14
14
  import {
15
- fallbackIfFails as fallbackIfFails3,
15
+ fallbackIfFails as fallbackIfFails4,
16
16
  isError,
17
- isFn as isFn4,
18
17
  isObj as isObj2,
19
18
  isPromise,
20
19
  isUrlValid
@@ -74,46 +73,8 @@ var getResponse = (url, options = {}) => {
74
73
  getResponse.fetch = globalThis.fetch;
75
74
  var getResponse_default = getResponse;
76
75
 
77
- // src/mergeOptions.ts
78
- import { isArr, isFn as isFn3, isObj, objCopy } from "@superutils/core";
79
- var mergeOptions = (...allOptions) => allOptions.reduce(
80
- (merged, options) => {
81
- var _a;
82
- options = isObj(options) ? options : {};
83
- const { headers, interceptors: ints1 = {} } = merged;
84
- const { interceptors: ints2 = {} } = options;
85
- options.headers && new Headers(options.headers).forEach(
86
- (value, key) => headers.set(key, value)
87
- );
88
- return {
89
- ...merged,
90
- ...options,
91
- errMsgs: objCopy(
92
- options.errMsgs,
93
- merged.errMsgs,
94
- [],
95
- "empty"
96
- ),
97
- headers,
98
- interceptors: {
99
- error: [...toArr(ints1 == null ? void 0 : ints1.error), ...toArr(ints2 == null ? void 0 : ints2.error)],
100
- request: [
101
- ...toArr(ints1 == null ? void 0 : ints1.request),
102
- ...toArr(ints2 == null ? void 0 : ints2.request)
103
- ],
104
- response: [
105
- ...toArr(ints1 == null ? void 0 : ints1.response),
106
- ...toArr(ints2 == null ? void 0 : ints2.response)
107
- ],
108
- result: [...toArr(ints1 == null ? void 0 : ints1.result), ...toArr(ints2 == null ? void 0 : ints2.result)]
109
- },
110
- timeout: (_a = options.timeout) != null ? _a : merged.timeout
111
- };
112
- },
113
- { headers: new Headers() }
114
- );
115
- var mergeOptions_default = mergeOptions;
116
- var toArr = (x) => isArr(x) ? x : isFn3(x) ? [x] : [];
76
+ // src/getResult.ts
77
+ import { fallbackIfFails as fallbackIfFails3, isFn as isFn3 } from "@superutils/core";
117
78
 
118
79
  // src/types/constants.ts
119
80
  var ContentType = {
@@ -177,6 +138,170 @@ var FetchError = class _FetchError extends Error {
177
138
  }
178
139
  };
179
140
 
141
+ // src/getResult.ts
142
+ var getResult = async (response, as = "json" /* json */, onDownloadProgress) => {
143
+ var _a;
144
+ if (!isFn3(onDownloadProgress) || as === "response" /* response */) {
145
+ const parseFunc = response[as];
146
+ const result = !isFn3(parseFunc) ? response : parseFunc.bind(response)();
147
+ return result;
148
+ }
149
+ const reader = (_a = response == null ? void 0 : response.body) == null ? void 0 : _a.getReader();
150
+ const contentLength = response.headers.get("Content-Length");
151
+ const total = contentLength ? parseInt(contentLength, 10) : null;
152
+ const chunks = new Chunks(
153
+ [],
154
+ response.headers.get("content-type")
155
+ );
156
+ let received = 0;
157
+ while (reader) {
158
+ const { done, value } = await reader.read();
159
+ if (done) break;
160
+ chunks.value.push(value);
161
+ received += value.length;
162
+ fallbackIfFails3(
163
+ onDownloadProgress,
164
+ total ? [100 * received / total, received, total] : [null, received, null],
165
+ null
166
+ );
167
+ }
168
+ switch (as) {
169
+ case "arrayBuffer" /* arrayBuffer */:
170
+ return chunks.toArrayBuffer();
171
+ case "blob" /* blob */:
172
+ return chunks.toBlob();
173
+ case "bytes" /* bytes */:
174
+ return chunks.toBytes();
175
+ case "formData" /* formData */:
176
+ return chunks.toFormData();
177
+ case "text" /* text */:
178
+ return chunks.toText();
179
+ case "json" /* json */:
180
+ break;
181
+ }
182
+ return chunks.toJSON();
183
+ };
184
+ var getResult_default = getResult;
185
+ var Chunks = class {
186
+ /**
187
+ * @param value The initial array of chunks.
188
+ * @param contentType The MIME type of the content for Blob/FormData conversion.
189
+ * @param encoding The character encoding for text decoding. Defaults to 'utf-8'.
190
+ */
191
+ constructor(value, contentType = "", encoding = "utf-8") {
192
+ this.value = value;
193
+ this.contentType = contentType;
194
+ this.encoding = encoding;
195
+ /**
196
+ * Converts the accumulated data to an ArrayBuffer.
197
+ */
198
+ this.toArrayBuffer = () => this.concatChunks().buffer;
199
+ /**
200
+ * Converts the accumulated data to a Blob
201
+ *
202
+ * @param type content type. Default: `this.contentType`
203
+ */
204
+ this.toBlob = (type = this.contentType) => new Blob(this.value, { type });
205
+ /**
206
+ * Converts the accumulated data to a single Uint8Array.
207
+ */
208
+ this.toBytes = () => this.concatChunks();
209
+ /**
210
+ * Decodes the data as text and parses it as JSON.
211
+ *
212
+ * @template T The expected type of the JSON result.
213
+ * @param encoding Optional encoding override.
214
+ * @returns The parsed JSON object.
215
+ */
216
+ this.toJSON = (encoding = this.encoding) => JSON.parse(this.toText(encoding));
217
+ /**
218
+ * Decodes the accumulated chunks into a string.
219
+ *
220
+ * @param encoding The character encoding to use. Defaults to the instance's `encoding`.
221
+ */
222
+ this.toText = (encoding = this.encoding) => new TextDecoder(encoding).decode(this.concatChunks());
223
+ }
224
+ /**
225
+ * Concatenates all accumulated chunks into a single Uint8Array.
226
+ *
227
+ * @returns A single Uint8Array containing the merged data.
228
+ */
229
+ concatChunks() {
230
+ const total = this.value.reduce((s, c) => s + c.byteLength, 0);
231
+ const out = new Uint8Array(total);
232
+ let off = 0;
233
+ for (const u of this.value) {
234
+ out.set(u, off);
235
+ off += u.byteLength;
236
+ }
237
+ return out;
238
+ }
239
+ /**
240
+ * Attempts to convert the accumulated data to FormData.
241
+ *
242
+ * If the `contentType` is `application/x-www-form-urlencoded` or the content appears to be
243
+ * query parameters, it parses them into FormData. Otherwise, it appends the entire
244
+ * content as a Blob under the key 'file'.
245
+ *
246
+ * @param encoding Optional encoding override for text decoding.
247
+ * @returns A FormData instance containing the data.
248
+ */
249
+ toFormData(encoding = this.encoding) {
250
+ const text = this.toText(encoding);
251
+ const formData = new FormData();
252
+ if (this.contentType.includes(
253
+ ContentType.APPLICATION_X_WWW_FORM_URLENCODED
254
+ ) || text.includes("=")) {
255
+ const params = new URLSearchParams(text);
256
+ for (const [k, v] of params) formData.append(k, v);
257
+ return formData;
258
+ }
259
+ formData.append("file", new Blob([text]));
260
+ return formData;
261
+ }
262
+ };
263
+
264
+ // src/mergeOptions.ts
265
+ import { isArr, isFn as isFn4, isObj, objCopy } from "@superutils/core";
266
+ var mergeOptions = (...allOptions) => allOptions.reduce(
267
+ (merged, options) => {
268
+ var _a;
269
+ options = isObj(options) ? options : {};
270
+ const { headers, interceptors: ints1 = {} } = merged;
271
+ const { interceptors: ints2 = {} } = options;
272
+ options.headers && new Headers(options.headers).forEach(
273
+ (value, key) => headers.set(key, value)
274
+ );
275
+ return {
276
+ ...merged,
277
+ ...options,
278
+ errMsgs: objCopy(
279
+ options.errMsgs,
280
+ merged.errMsgs,
281
+ [],
282
+ "empty"
283
+ ),
284
+ headers,
285
+ interceptors: {
286
+ error: [...toArr(ints1 == null ? void 0 : ints1.error), ...toArr(ints2 == null ? void 0 : ints2.error)],
287
+ request: [
288
+ ...toArr(ints1 == null ? void 0 : ints1.request),
289
+ ...toArr(ints2 == null ? void 0 : ints2.request)
290
+ ],
291
+ response: [
292
+ ...toArr(ints1 == null ? void 0 : ints1.response),
293
+ ...toArr(ints2 == null ? void 0 : ints2.response)
294
+ ],
295
+ result: [...toArr(ints1 == null ? void 0 : ints1.result), ...toArr(ints2 == null ? void 0 : ints2.result)]
296
+ },
297
+ timeout: (_a = options.timeout) != null ? _a : merged.timeout
298
+ };
299
+ },
300
+ { headers: new Headers() }
301
+ );
302
+ var mergeOptions_default = mergeOptions;
303
+ var toArr = (x) => isArr(x) ? x : isFn4(x) ? [x] : [];
304
+
180
305
  // src/fetch.ts
181
306
  var defaultErrorMsgs = Object.freeze({
182
307
  aborted: "Request aborted",
@@ -200,7 +325,7 @@ var fetch = (url, options = {}) => {
200
325
  (_c = opts.signal) != null ? _c : opts.signal = opts.abortCtrl.signal;
201
326
  const { abortCtrl, as: parseAs, headers, onAbort, onTimeout } = opts;
202
327
  opts.onAbort = async () => {
203
- const err = await fallbackIfFails3(onAbort, [], void 0);
328
+ const err = await fallbackIfFails4(onAbort, [], void 0);
204
329
  return await interceptErr(
205
330
  isError(err) ? err : new Error(err),
206
331
  url,
@@ -209,7 +334,7 @@ var fetch = (url, options = {}) => {
209
334
  );
210
335
  };
211
336
  opts.onTimeout = async () => {
212
- const err = await fallbackIfFails3(onTimeout, [], void 0);
337
+ const err = await fallbackIfFails4(onTimeout, [], void 0);
213
338
  return await interceptErr(
214
339
  err != null ? err : new Error(opts.errMsgs.timedout),
215
340
  url,
@@ -220,7 +345,7 @@ var fetch = (url, options = {}) => {
220
345
  return PromisE_timeout(opts, async () => {
221
346
  var _a2, _b2, _c2, _d;
222
347
  try {
223
- opts.body = await fallbackIfFails3(
348
+ opts.body = await fallbackIfFails4(
224
349
  opts.body,
225
350
  [],
226
351
  (err) => Promise.reject(err)
@@ -250,7 +375,7 @@ var fetch = (url, options = {}) => {
250
375
  const status = response == null ? void 0 : response.status;
251
376
  const isSuccess = status >= 200 && status < 300;
252
377
  if (!isSuccess) {
253
- const jsonError = await fallbackIfFails3(
378
+ const jsonError = await fallbackIfFails4(
254
379
  // try to parse error response as json first
255
380
  () => {
256
381
  var _a3;
@@ -261,9 +386,12 @@ var fetch = (url, options = {}) => {
261
386
  );
262
387
  throw new Error(jsonError, { cause: jsonError });
263
388
  }
264
- const parseFunc = response[parseAs];
265
- let result = !isFn4(parseFunc) ? response : parseFunc.bind(response)();
266
- if (isPromise(result))
389
+ let result = getResult_default(
390
+ response,
391
+ parseAs,
392
+ opts.onDownloadProgress
393
+ );
394
+ if (isPromise(result)) {
267
395
  result = await result.catch(
268
396
  (err) => Promise.reject(
269
397
  new Error(
@@ -272,6 +400,7 @@ var fetch = (url, options = {}) => {
272
400
  )
273
401
  )
274
402
  );
403
+ }
275
404
  result = await executeInterceptors_default(
276
405
  result,
277
406
  abortCtrl.signal,
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.10",
9
- "@superutils/promise": "^1.3.9"
8
+ "@superutils/core": "^1.2.11",
9
+ "@superutils/promise": "^1.3.10"
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.9",
57
- "gitHead": "9b77219f98125fd231d24c6e44299de7b99b679e"
56
+ "version": "1.5.10",
57
+ "gitHead": "c97c6ce7baebd9de3a314616594e69b435d7b719"
58
58
  }