@uploadcare/upload-client 4.3.0 → 5.0.0

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.
@@ -27,11 +27,118 @@ const onCancel = (signal, callback) => {
27
27
  }
28
28
  };
29
29
 
30
+ function isObject(o) {
31
+ return Object.prototype.toString.call(o) === '[object Object]';
32
+ }
33
+
34
+ const SEPARATOR = /\W|_/g;
35
+ function camelizeString(text) {
36
+ return text
37
+ .split(SEPARATOR)
38
+ .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
39
+ word.slice(1))
40
+ .join('');
41
+ }
42
+ function camelizeArrayItems(array, { ignoreKeys } = { ignoreKeys: [] }) {
43
+ if (!Array.isArray(array)) {
44
+ return array;
45
+ }
46
+ return array.map((item) => camelizeKeys(item, { ignoreKeys }));
47
+ }
48
+ function camelizeKeys(source, { ignoreKeys } = { ignoreKeys: [] }) {
49
+ if (Array.isArray(source)) {
50
+ return camelizeArrayItems(source, { ignoreKeys });
51
+ }
52
+ if (!isObject(source)) {
53
+ return source;
54
+ }
55
+ const result = {};
56
+ for (const key of Object.keys(source)) {
57
+ let value = source[key];
58
+ if (ignoreKeys.includes(key)) {
59
+ result[key] = value;
60
+ continue;
61
+ }
62
+ if (isObject(value)) {
63
+ value = camelizeKeys(value, { ignoreKeys });
64
+ }
65
+ else if (Array.isArray(value)) {
66
+ value = camelizeArrayItems(value, { ignoreKeys });
67
+ }
68
+ result[camelizeString(key)] = value;
69
+ }
70
+ return result;
71
+ }
72
+
73
+ /**
74
+ * setTimeout as Promise.
75
+ *
76
+ * @param {number} ms Timeout in milliseconds.
77
+ */
78
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
79
+
80
+ function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
81
+ const languageName = 'JavaScript';
82
+ if (typeof userAgent === 'string') {
83
+ return userAgent;
84
+ }
85
+ if (typeof userAgent === 'function') {
86
+ return userAgent({
87
+ publicKey,
88
+ libraryName,
89
+ libraryVersion,
90
+ languageName,
91
+ integration
92
+ });
93
+ }
94
+ const mainInfo = [libraryName, libraryVersion, publicKey]
95
+ .filter(Boolean)
96
+ .join('/');
97
+ const additionInfo = [languageName, integration].filter(Boolean).join('; ');
98
+ return `${mainInfo} (${additionInfo})`;
99
+ }
100
+
101
+ const defaultOptions = {
102
+ factor: 2,
103
+ time: 100
104
+ };
105
+ function retrier(fn, options = defaultOptions) {
106
+ let attempts = 0;
107
+ function runAttempt(fn) {
108
+ const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
109
+ const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
110
+ attempts += 1;
111
+ return runAttempt(fn);
112
+ });
113
+ return fn({
114
+ attempt: attempts,
115
+ retry
116
+ });
117
+ }
118
+ return runAttempt(fn);
119
+ }
120
+
121
+ class UploadcareNetworkError extends Error {
122
+ constructor(progressEvent) {
123
+ super();
124
+ this.name = 'UploadcareNetworkError';
125
+ this.message = 'Network error';
126
+ Object.setPrototypeOf(this, UploadcareNetworkError.prototype);
127
+ this.originalProgressEvent = progressEvent;
128
+ }
129
+ }
130
+
30
131
  const request = ({ method, url, data, headers = {}, signal, onProgress }) => new Promise((resolve, reject) => {
31
132
  const xhr = new XMLHttpRequest();
32
133
  const requestMethod = method?.toUpperCase() || 'GET';
33
134
  let aborted = false;
34
- xhr.open(requestMethod, url);
135
+ /**
136
+ * Force synchronous flag to be off
137
+ * Some chrome versions gets `InvalidAccessError` error when we set `responseType`
138
+ * See https://xhr.spec.whatwg.org/#synchronous-flag
139
+ * and https://bugs.chromium.org/p/chromium/issues/detail?id=1346628
140
+ */
141
+ xhr.open(requestMethod, url, true);
35
142
  if (headers) {
36
143
  Object.entries(headers).forEach((entry) => {
37
144
  const [key, value] = entry;
@@ -86,11 +193,11 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
86
193
  });
87
194
  }
88
195
  };
89
- xhr.onerror = () => {
196
+ xhr.onerror = (progressEvent) => {
90
197
  if (aborted)
91
198
  return;
92
199
  // only triggers if the request couldn't be made at all
93
- reject(new Error('Network error'));
200
+ reject(new UploadcareNetworkError(progressEvent));
94
201
  };
95
202
  if (onProgress && typeof onProgress === 'function') {
96
203
  xhr.upload.onprogress = (event) => {
@@ -224,7 +331,7 @@ const buildSearchParams = (query) => {
224
331
  };
225
332
  const getUrl = (base, path, query) => {
226
333
  const url = new URL(base);
227
- url.pathname = path;
334
+ url.pathname = (url.pathname + path).replace('//', '/');
228
335
  if (query) {
229
336
  url.search = buildSearchParams(query);
230
337
  }
@@ -240,109 +347,18 @@ const defaultSettings = {
240
347
  baseURL: 'https://upload.uploadcare.com',
241
348
  maxContentLength: 50 * 1024 * 1024,
242
349
  retryThrottledRequestMaxTimes: 1,
350
+ retryNetworkErrorMaxTimes: 3,
243
351
  multipartMinFileSize: 25 * 1024 * 1024,
244
352
  multipartChunkSize: 5 * 1024 * 1024,
245
353
  multipartMinLastPartSize: 1024 * 1024,
246
354
  maxConcurrentRequests: 4,
247
- multipartMaxAttempts: 3,
248
355
  pollingTimeoutMilliseconds: 10000,
249
356
  pusherKey: '79ae88bd931ea68464d9'
250
357
  };
251
358
  const defaultContentType = 'application/octet-stream';
252
359
  const defaultFilename = 'original';
253
360
 
254
- var version = '4.3.0';
255
-
256
- function isObject(o) {
257
- return Object.prototype.toString.call(o) === '[object Object]';
258
- }
259
-
260
- const SEPARATOR = /\W|_/g;
261
- function camelizeString(text) {
262
- return text
263
- .split(SEPARATOR)
264
- .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
265
- word.slice(1))
266
- .join('');
267
- }
268
- function camelizeArrayItems(array, { ignoreKeys } = { ignoreKeys: [] }) {
269
- if (!Array.isArray(array)) {
270
- return array;
271
- }
272
- return array.map((item) => camelizeKeys(item, { ignoreKeys }));
273
- }
274
- function camelizeKeys(source, { ignoreKeys } = { ignoreKeys: [] }) {
275
- if (Array.isArray(source)) {
276
- return camelizeArrayItems(source, { ignoreKeys });
277
- }
278
- if (!isObject(source)) {
279
- return source;
280
- }
281
- const result = {};
282
- for (const key of Object.keys(source)) {
283
- let value = source[key];
284
- if (ignoreKeys.includes(key)) {
285
- result[key] = value;
286
- continue;
287
- }
288
- if (isObject(value)) {
289
- value = camelizeKeys(value, { ignoreKeys });
290
- }
291
- else if (Array.isArray(value)) {
292
- value = camelizeArrayItems(value, { ignoreKeys });
293
- }
294
- result[camelizeString(key)] = value;
295
- }
296
- return result;
297
- }
298
-
299
- /**
300
- * setTimeout as Promise.
301
- *
302
- * @param {number} ms Timeout in milliseconds.
303
- */
304
- const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
305
-
306
- function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
307
- const languageName = 'JavaScript';
308
- if (typeof userAgent === 'string') {
309
- return userAgent;
310
- }
311
- if (typeof userAgent === 'function') {
312
- return userAgent({
313
- publicKey,
314
- libraryName,
315
- libraryVersion,
316
- languageName,
317
- integration
318
- });
319
- }
320
- const mainInfo = [libraryName, libraryVersion, publicKey]
321
- .filter(Boolean)
322
- .join('/');
323
- const additionInfo = [languageName, integration].filter(Boolean).join('; ');
324
- return `${mainInfo} (${additionInfo})`;
325
- }
326
-
327
- const defaultOptions = {
328
- factor: 2,
329
- time: 100
330
- };
331
- function retrier(fn, options = defaultOptions) {
332
- let attempts = 0;
333
- function runAttempt(fn) {
334
- const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
335
- const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
336
- attempts += 1;
337
- return runAttempt(fn);
338
- });
339
- return fn({
340
- attempt: attempts,
341
- retry
342
- });
343
- }
344
- return runAttempt(fn);
345
- }
361
+ var version = '5.0.0';
346
362
 
347
363
  const LIBRARY_NAME = 'UploadcareUploadClient';
348
364
  const LIBRARY_VERSION = version;
@@ -355,20 +371,26 @@ function getUserAgent(options) {
355
371
  }
356
372
 
357
373
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
358
- const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
374
+ const DEFAULT_THROTTLED_TIMEOUT = 15000;
375
+ const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
359
376
  function getTimeoutFromThrottledRequest(error) {
360
377
  const { headers } = error || {};
361
378
  return ((headers &&
362
379
  Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
363
- DEFAULT_RETRY_AFTER_TIMEOUT);
380
+ DEFAULT_THROTTLED_TIMEOUT);
364
381
  }
365
- function retryIfThrottled(fn, retryThrottledMaxTimes) {
382
+ function retryIfFailed(fn, options) {
383
+ const { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes } = options;
366
384
  return retrier(({ attempt, retry }) => fn().catch((error) => {
367
385
  if ('response' in error &&
368
386
  error?.code === REQUEST_WAS_THROTTLED_CODE &&
369
- attempt < retryThrottledMaxTimes) {
387
+ attempt < retryThrottledRequestMaxTimes) {
370
388
  return retry(getTimeoutFromThrottledRequest(error));
371
389
  }
390
+ if (error instanceof UploadcareNetworkError &&
391
+ attempt < retryNetworkErrorMaxTimes) {
392
+ return retry((attempt + 1) * DEFAULT_NETWORK_ERROR_TIMEOUT);
393
+ }
372
394
  throw error;
373
395
  }));
374
396
  }
@@ -381,8 +403,8 @@ function getStoreValue(store) {
381
403
  * Performs file uploading request to Uploadcare Upload API.
382
404
  * Can be canceled and has progress.
383
405
  */
384
- function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
385
- return retryIfThrottled(() => request({
406
+ function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes, metadata }) {
407
+ return retryIfFailed(() => request({
386
408
  method: 'POST',
387
409
  url: getUrl(baseURL, '/base/', {
388
410
  jsonerrors: 1
@@ -413,7 +435,7 @@ function base(file, { publicKey, fileName, contentType, baseURL = defaultSetting
413
435
  else {
414
436
  return response;
415
437
  }
416
- }), retryThrottledRequestMaxTimes);
438
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
417
439
  }
418
440
 
419
441
  var TypeEnum;
@@ -424,8 +446,8 @@ var TypeEnum;
424
446
  /**
425
447
  * Uploading files from URL.
426
448
  */
427
- function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
428
- return retryIfThrottled(() => request({
449
+ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes, metadata }) {
450
+ return retryIfFailed(() => request({
429
451
  method: 'POST',
430
452
  headers: {
431
453
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -452,7 +474,7 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
452
474
  else {
453
475
  return response;
454
476
  }
455
- }), retryThrottledRequestMaxTimes);
477
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
456
478
  }
457
479
 
458
480
  var Status;
@@ -469,8 +491,8 @@ const isErrorResponse = (response) => {
469
491
  /**
470
492
  * Checking upload status and working with file tokens.
471
493
  */
472
- function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
473
- return retryIfThrottled(() => request({
494
+ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes } = {}) {
495
+ return retryIfFailed(() => request({
474
496
  method: 'GET',
475
497
  headers: publicKey
476
498
  ? {
@@ -494,14 +516,14 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
494
516
  else {
495
517
  return response;
496
518
  }
497
- }), retryThrottledRequestMaxTimes);
519
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
498
520
  }
499
521
 
500
522
  /**
501
523
  * Create files group.
502
524
  */
503
- function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
504
- return retryIfThrottled(() => request({
525
+ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
526
+ return retryIfFailed(() => request({
505
527
  method: 'POST',
506
528
  headers: {
507
529
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -524,14 +546,14 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
524
546
  else {
525
547
  return response;
526
548
  }
527
- }), retryThrottledRequestMaxTimes);
549
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
528
550
  }
529
551
 
530
552
  /**
531
553
  * Get info about group.
532
554
  */
533
- function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
534
- return retryIfThrottled(() => request({
555
+ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
556
+ return retryIfFailed(() => request({
535
557
  method: 'GET',
536
558
  headers: {
537
559
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -551,14 +573,14 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
551
573
  else {
552
574
  return response;
553
575
  }
554
- }), retryThrottledRequestMaxTimes);
576
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
555
577
  }
556
578
 
557
579
  /**
558
580
  * Returns a JSON dictionary holding file info.
559
581
  */
560
- function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
561
- return retryIfThrottled(() => request({
582
+ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
583
+ return retryIfFailed(() => request({
562
584
  method: 'GET',
563
585
  headers: {
564
586
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -578,14 +600,14 @@ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, sour
578
600
  else {
579
601
  return response;
580
602
  }
581
- }), retryThrottledRequestMaxTimes);
603
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
582
604
  }
583
605
 
584
606
  /**
585
607
  * Start multipart uploading.
586
608
  */
587
- function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
588
- return retryIfThrottled(() => request({
609
+ function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes, metadata }) {
610
+ return retryIfFailed(() => request({
589
611
  method: 'POST',
590
612
  url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
591
613
  headers: {
@@ -614,14 +636,14 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
614
636
  response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
615
637
  return response;
616
638
  }
617
- }), retryThrottledRequestMaxTimes);
639
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
618
640
  }
619
641
 
620
642
  /**
621
643
  * Complete multipart uploading.
622
644
  */
623
- function multipartUpload(part, url, { signal, onProgress }) {
624
- return request({
645
+ function multipartUpload(part, url, { signal, onProgress, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
646
+ return retryIfFailed(() => request({
625
647
  method: 'PUT',
626
648
  url,
627
649
  data: part,
@@ -638,14 +660,17 @@ function multipartUpload(part, url, { signal, onProgress }) {
638
660
  });
639
661
  return result;
640
662
  })
641
- .then(({ status }) => ({ code: status }));
663
+ .then(({ status }) => ({ code: status })), {
664
+ retryThrottledRequestMaxTimes,
665
+ retryNetworkErrorMaxTimes
666
+ });
642
667
  }
643
668
 
644
669
  /**
645
670
  * Complete multipart uploading.
646
671
  */
647
- function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
648
- return retryIfThrottled(() => request({
672
+ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
673
+ return retryIfFailed(() => request({
649
674
  method: 'POST',
650
675
  url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
651
676
  headers: {
@@ -665,7 +690,7 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
665
690
  else {
666
691
  return response;
667
692
  }
668
- }), retryThrottledRequestMaxTimes);
693
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
669
694
  }
670
695
 
671
696
  class UploadcareFile {
@@ -732,7 +757,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
732
757
  timeoutId = setTimeout(tick, 0);
733
758
  });
734
759
 
735
- function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
760
+ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
736
761
  return poll({
737
762
  check: (signal) => info(file, {
738
763
  publicKey,
@@ -741,7 +766,8 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
741
766
  source,
742
767
  integration,
743
768
  userAgent,
744
- retryThrottledRequestMaxTimes
769
+ retryThrottledRequestMaxTimes,
770
+ retryNetworkErrorMaxTimes
745
771
  }).then((response) => {
746
772
  if (response.isReady) {
747
773
  return response;
@@ -753,7 +779,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
753
779
  });
754
780
  }
755
781
 
756
- const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN, metadata }) => {
782
+ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN, metadata }) => {
757
783
  return base(file, {
758
784
  publicKey,
759
785
  fileName,
@@ -768,6 +794,7 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
768
794
  integration,
769
795
  userAgent,
770
796
  retryThrottledRequestMaxTimes,
797
+ retryNetworkErrorMaxTimes,
771
798
  metadata
772
799
  })
773
800
  .then(({ file }) => {
@@ -779,6 +806,7 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
779
806
  integration,
780
807
  userAgent,
781
808
  retryThrottledRequestMaxTimes,
809
+ retryNetworkErrorMaxTimes,
782
810
  onProgress,
783
811
  signal
784
812
  });
@@ -966,7 +994,7 @@ const preconnect = (key) => {
966
994
  getPusher(key).connect();
967
995
  };
968
996
 
969
- function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
997
+ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, onProgress, signal }) {
970
998
  return poll({
971
999
  check: (signal) => fromUrlStatus(token, {
972
1000
  publicKey,
@@ -974,6 +1002,7 @@ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retry
974
1002
  integration,
975
1003
  userAgent,
976
1004
  retryThrottledRequestMaxTimes,
1005
+ retryNetworkErrorMaxTimes,
977
1006
  signal
978
1007
  }).then((response) => {
979
1008
  switch (response.status) {
@@ -1124,7 +1153,7 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
1124
1153
  }))
1125
1154
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
1126
1155
 
1127
- const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
1156
+ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN }) => {
1128
1157
  return info(uuid, {
1129
1158
  publicKey,
1130
1159
  baseURL,
@@ -1132,7 +1161,8 @@ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProg
1132
1161
  source,
1133
1162
  integration,
1134
1163
  userAgent,
1135
- retryThrottledRequestMaxTimes
1164
+ retryThrottledRequestMaxTimes,
1165
+ retryNetworkErrorMaxTimes
1136
1166
  })
1137
1167
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
1138
1168
  .then((result) => {
@@ -1217,18 +1247,15 @@ const runWithConcurrency = (concurrency, tasks) => {
1217
1247
  });
1218
1248
  };
1219
1249
 
1220
- const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
1250
+ const uploadPart = (chunk, url, { publicKey, onProgress, signal, integration, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes }) => multipartUpload(chunk, url, {
1221
1251
  publicKey,
1222
1252
  onProgress,
1223
1253
  signal,
1224
- integration
1225
- }).catch((error) => {
1226
- if (attempt < multipartMaxAttempts) {
1227
- return retry();
1228
- }
1229
- throw error;
1230
- }));
1231
- const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, multipartMaxAttempts = defaultSettings.multipartMaxAttempts, baseCDN, metadata }) => {
1254
+ integration,
1255
+ retryThrottledRequestMaxTimes,
1256
+ retryNetworkErrorMaxTimes
1257
+ });
1258
+ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, baseCDN, metadata }) => {
1232
1259
  const size = fileSize || getFileSize(file);
1233
1260
  let progressValues;
1234
1261
  const createProgressHandler = (totalChunks, chunkIdx) => {
@@ -1262,18 +1289,20 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1262
1289
  integration,
1263
1290
  userAgent,
1264
1291
  retryThrottledRequestMaxTimes,
1292
+ retryNetworkErrorMaxTimes,
1265
1293
  metadata
1266
1294
  })
1267
1295
  .then(({ uuid, parts }) => {
1268
1296
  const getChunk = prepareChunks(file, size, multipartChunkSize);
1269
1297
  return Promise.all([
1270
1298
  uuid,
1271
- runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
1299
+ runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPart(getChunk(index), url, {
1272
1300
  publicKey,
1273
1301
  onProgress: createProgressHandler(parts.length, index),
1274
1302
  signal,
1275
1303
  integration,
1276
- multipartMaxAttempts
1304
+ retryThrottledRequestMaxTimes,
1305
+ retryNetworkErrorMaxTimes
1277
1306
  })))
1278
1307
  ]);
1279
1308
  })
@@ -1283,7 +1312,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1283
1312
  source,
1284
1313
  integration,
1285
1314
  userAgent,
1286
- retryThrottledRequestMaxTimes
1315
+ retryThrottledRequestMaxTimes,
1316
+ retryNetworkErrorMaxTimes
1287
1317
  }))
1288
1318
  .then((fileInfo) => {
1289
1319
  if (fileInfo.isReady) {
@@ -1298,6 +1328,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1298
1328
  integration,
1299
1329
  userAgent,
1300
1330
  retryThrottledRequestMaxTimes,
1331
+ retryNetworkErrorMaxTimes,
1301
1332
  onProgress,
1302
1333
  signal
1303
1334
  });
@@ -1309,7 +1340,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1309
1340
  /**
1310
1341
  * Uploads file from provided data.
1311
1342
  */
1312
- function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, multipartMaxAttempts, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
1343
+ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
1313
1344
  if (isFileData(data)) {
1314
1345
  const fileSize = getFileSize(data);
1315
1346
  if (isMultipart(fileSize, multipartMinFileSize)) {
@@ -1317,7 +1348,6 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1317
1348
  publicKey,
1318
1349
  contentType,
1319
1350
  multipartChunkSize,
1320
- multipartMaxAttempts,
1321
1351
  fileName,
1322
1352
  baseURL,
1323
1353
  secureSignature,
@@ -1330,6 +1360,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1330
1360
  userAgent,
1331
1361
  maxConcurrentRequests,
1332
1362
  retryThrottledRequestMaxTimes,
1363
+ retryNetworkErrorMaxTimes,
1333
1364
  baseCDN,
1334
1365
  metadata
1335
1366
  });
@@ -1348,6 +1379,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1348
1379
  integration,
1349
1380
  userAgent,
1350
1381
  retryThrottledRequestMaxTimes,
1382
+ retryNetworkErrorMaxTimes,
1351
1383
  baseCDN,
1352
1384
  metadata
1353
1385
  });
@@ -1369,6 +1401,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1369
1401
  integration,
1370
1402
  userAgent,
1371
1403
  retryThrottledRequestMaxTimes,
1404
+ retryNetworkErrorMaxTimes,
1372
1405
  pusherKey,
1373
1406
  metadata
1374
1407
  });
@@ -1384,6 +1417,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1384
1417
  integration,
1385
1418
  userAgent,
1386
1419
  retryThrottledRequestMaxTimes,
1420
+ retryNetworkErrorMaxTimes,
1387
1421
  baseCDN
1388
1422
  });
1389
1423
  }
@@ -1439,7 +1473,7 @@ const isUrlArray = (data) => {
1439
1473
  return true;
1440
1474
  };
1441
1475
 
1442
- function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, baseCDN = defaultSettings.baseCDN, jsonpCallback }) {
1476
+ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, baseCDN = defaultSettings.baseCDN, jsonpCallback }) {
1443
1477
  if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
1444
1478
  throw new TypeError(`Group uploading from "${data}" is not supported`);
1445
1479
  }
@@ -1476,6 +1510,7 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1476
1510
  integration,
1477
1511
  userAgent,
1478
1512
  retryThrottledRequestMaxTimes,
1513
+ retryNetworkErrorMaxTimes,
1479
1514
  contentType,
1480
1515
  multipartChunkSize,
1481
1516
  baseCDN
@@ -1491,7 +1526,8 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1491
1526
  source,
1492
1527
  integration,
1493
1528
  userAgent,
1494
- retryThrottledRequestMaxTimes
1529
+ retryThrottledRequestMaxTimes,
1530
+ retryNetworkErrorMaxTimes
1495
1531
  })
1496
1532
  .then((groupInfo) => new UploadcareGroup(groupInfo, files))
1497
1533
  .then((group) => {
@@ -1564,4 +1600,4 @@ class UploadClient {
1564
1600
  }
1565
1601
  }
1566
1602
 
1567
- export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
1603
+ export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };