@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) => {
@@ -221,7 +328,7 @@ const buildSearchParams = (query) => {
221
328
  };
222
329
  const getUrl = (base, path, query) => {
223
330
  const url = new URL(base);
224
- url.pathname = path;
331
+ url.pathname = (url.pathname + path).replace('//', '/');
225
332
  if (query) {
226
333
  url.search = buildSearchParams(query);
227
334
  }
@@ -237,109 +344,18 @@ const defaultSettings = {
237
344
  baseURL: 'https://upload.uploadcare.com',
238
345
  maxContentLength: 50 * 1024 * 1024,
239
346
  retryThrottledRequestMaxTimes: 1,
347
+ retryNetworkErrorMaxTimes: 3,
240
348
  multipartMinFileSize: 25 * 1024 * 1024,
241
349
  multipartChunkSize: 5 * 1024 * 1024,
242
350
  multipartMinLastPartSize: 1024 * 1024,
243
351
  maxConcurrentRequests: 4,
244
- multipartMaxAttempts: 3,
245
352
  pollingTimeoutMilliseconds: 10000,
246
353
  pusherKey: '79ae88bd931ea68464d9'
247
354
  };
248
355
  const defaultContentType = 'application/octet-stream';
249
356
  const defaultFilename = 'original';
250
357
 
251
- var version = '4.3.0';
252
-
253
- function isObject(o) {
254
- return Object.prototype.toString.call(o) === '[object Object]';
255
- }
256
-
257
- const SEPARATOR = /\W|_/g;
258
- function camelizeString(text) {
259
- return text
260
- .split(SEPARATOR)
261
- .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
262
- word.slice(1))
263
- .join('');
264
- }
265
- function camelizeArrayItems(array, { ignoreKeys } = { ignoreKeys: [] }) {
266
- if (!Array.isArray(array)) {
267
- return array;
268
- }
269
- return array.map((item) => camelizeKeys(item, { ignoreKeys }));
270
- }
271
- function camelizeKeys(source, { ignoreKeys } = { ignoreKeys: [] }) {
272
- if (Array.isArray(source)) {
273
- return camelizeArrayItems(source, { ignoreKeys });
274
- }
275
- if (!isObject(source)) {
276
- return source;
277
- }
278
- const result = {};
279
- for (const key of Object.keys(source)) {
280
- let value = source[key];
281
- if (ignoreKeys.includes(key)) {
282
- result[key] = value;
283
- continue;
284
- }
285
- if (isObject(value)) {
286
- value = camelizeKeys(value, { ignoreKeys });
287
- }
288
- else if (Array.isArray(value)) {
289
- value = camelizeArrayItems(value, { ignoreKeys });
290
- }
291
- result[camelizeString(key)] = value;
292
- }
293
- return result;
294
- }
295
-
296
- /**
297
- * setTimeout as Promise.
298
- *
299
- * @param {number} ms Timeout in milliseconds.
300
- */
301
- const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
302
-
303
- function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
304
- const languageName = 'JavaScript';
305
- if (typeof userAgent === 'string') {
306
- return userAgent;
307
- }
308
- if (typeof userAgent === 'function') {
309
- return userAgent({
310
- publicKey,
311
- libraryName,
312
- libraryVersion,
313
- languageName,
314
- integration
315
- });
316
- }
317
- const mainInfo = [libraryName, libraryVersion, publicKey]
318
- .filter(Boolean)
319
- .join('/');
320
- const additionInfo = [languageName, integration].filter(Boolean).join('; ');
321
- return `${mainInfo} (${additionInfo})`;
322
- }
323
-
324
- const defaultOptions = {
325
- factor: 2,
326
- time: 100
327
- };
328
- function retrier(fn, options = defaultOptions) {
329
- let attempts = 0;
330
- function runAttempt(fn) {
331
- const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
332
- const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
333
- attempts += 1;
334
- return runAttempt(fn);
335
- });
336
- return fn({
337
- attempt: attempts,
338
- retry
339
- });
340
- }
341
- return runAttempt(fn);
342
- }
358
+ var version = '5.0.0';
343
359
 
344
360
  const LIBRARY_NAME = 'UploadcareUploadClient';
345
361
  const LIBRARY_VERSION = version;
@@ -352,20 +368,26 @@ function getUserAgent(options) {
352
368
  }
353
369
 
354
370
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
355
- const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
371
+ const DEFAULT_THROTTLED_TIMEOUT = 15000;
372
+ const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
356
373
  function getTimeoutFromThrottledRequest(error) {
357
374
  const { headers } = error || {};
358
375
  return ((headers &&
359
376
  Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
360
- DEFAULT_RETRY_AFTER_TIMEOUT);
377
+ DEFAULT_THROTTLED_TIMEOUT);
361
378
  }
362
- function retryIfThrottled(fn, retryThrottledMaxTimes) {
379
+ function retryIfFailed(fn, options) {
380
+ const { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes } = options;
363
381
  return retrier(({ attempt, retry }) => fn().catch((error) => {
364
382
  if ('response' in error &&
365
383
  error?.code === REQUEST_WAS_THROTTLED_CODE &&
366
- attempt < retryThrottledMaxTimes) {
384
+ attempt < retryThrottledRequestMaxTimes) {
367
385
  return retry(getTimeoutFromThrottledRequest(error));
368
386
  }
387
+ if (error instanceof UploadcareNetworkError &&
388
+ attempt < retryNetworkErrorMaxTimes) {
389
+ return retry((attempt + 1) * DEFAULT_NETWORK_ERROR_TIMEOUT);
390
+ }
369
391
  throw error;
370
392
  }));
371
393
  }
@@ -378,8 +400,8 @@ function getStoreValue(store) {
378
400
  * Performs file uploading request to Uploadcare Upload API.
379
401
  * Can be canceled and has progress.
380
402
  */
381
- function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
382
- return retryIfThrottled(() => request({
403
+ 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 }) {
404
+ return retryIfFailed(() => request({
383
405
  method: 'POST',
384
406
  url: getUrl(baseURL, '/base/', {
385
407
  jsonerrors: 1
@@ -410,7 +432,7 @@ function base(file, { publicKey, fileName, contentType, baseURL = defaultSetting
410
432
  else {
411
433
  return response;
412
434
  }
413
- }), retryThrottledRequestMaxTimes);
435
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
414
436
  }
415
437
 
416
438
  var TypeEnum;
@@ -421,8 +443,8 @@ var TypeEnum;
421
443
  /**
422
444
  * Uploading files from URL.
423
445
  */
424
- function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
425
- return retryIfThrottled(() => request({
446
+ 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 }) {
447
+ return retryIfFailed(() => request({
426
448
  method: 'POST',
427
449
  headers: {
428
450
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -449,7 +471,7 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
449
471
  else {
450
472
  return response;
451
473
  }
452
- }), retryThrottledRequestMaxTimes);
474
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
453
475
  }
454
476
 
455
477
  var Status;
@@ -466,8 +488,8 @@ const isErrorResponse = (response) => {
466
488
  /**
467
489
  * Checking upload status and working with file tokens.
468
490
  */
469
- function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
470
- return retryIfThrottled(() => request({
491
+ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes } = {}) {
492
+ return retryIfFailed(() => request({
471
493
  method: 'GET',
472
494
  headers: publicKey
473
495
  ? {
@@ -491,14 +513,14 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
491
513
  else {
492
514
  return response;
493
515
  }
494
- }), retryThrottledRequestMaxTimes);
516
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
495
517
  }
496
518
 
497
519
  /**
498
520
  * Create files group.
499
521
  */
500
- function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
501
- return retryIfThrottled(() => request({
522
+ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
523
+ return retryIfFailed(() => request({
502
524
  method: 'POST',
503
525
  headers: {
504
526
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -521,14 +543,14 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
521
543
  else {
522
544
  return response;
523
545
  }
524
- }), retryThrottledRequestMaxTimes);
546
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
525
547
  }
526
548
 
527
549
  /**
528
550
  * Get info about group.
529
551
  */
530
- function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
531
- return retryIfThrottled(() => request({
552
+ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
553
+ return retryIfFailed(() => request({
532
554
  method: 'GET',
533
555
  headers: {
534
556
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -548,14 +570,14 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
548
570
  else {
549
571
  return response;
550
572
  }
551
- }), retryThrottledRequestMaxTimes);
573
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
552
574
  }
553
575
 
554
576
  /**
555
577
  * Returns a JSON dictionary holding file info.
556
578
  */
557
- function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
558
- return retryIfThrottled(() => request({
579
+ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
580
+ return retryIfFailed(() => request({
559
581
  method: 'GET',
560
582
  headers: {
561
583
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -575,14 +597,14 @@ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, sour
575
597
  else {
576
598
  return response;
577
599
  }
578
- }), retryThrottledRequestMaxTimes);
600
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
579
601
  }
580
602
 
581
603
  /**
582
604
  * Start multipart uploading.
583
605
  */
584
- function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
585
- return retryIfThrottled(() => request({
606
+ 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 }) {
607
+ return retryIfFailed(() => request({
586
608
  method: 'POST',
587
609
  url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
588
610
  headers: {
@@ -611,14 +633,14 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
611
633
  response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
612
634
  return response;
613
635
  }
614
- }), retryThrottledRequestMaxTimes);
636
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
615
637
  }
616
638
 
617
639
  /**
618
640
  * Complete multipart uploading.
619
641
  */
620
- function multipartUpload(part, url, { signal, onProgress }) {
621
- return request({
642
+ function multipartUpload(part, url, { signal, onProgress, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
643
+ return retryIfFailed(() => request({
622
644
  method: 'PUT',
623
645
  url,
624
646
  data: part,
@@ -635,14 +657,17 @@ function multipartUpload(part, url, { signal, onProgress }) {
635
657
  });
636
658
  return result;
637
659
  })
638
- .then(({ status }) => ({ code: status }));
660
+ .then(({ status }) => ({ code: status })), {
661
+ retryThrottledRequestMaxTimes,
662
+ retryNetworkErrorMaxTimes
663
+ });
639
664
  }
640
665
 
641
666
  /**
642
667
  * Complete multipart uploading.
643
668
  */
644
- function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
645
- return retryIfThrottled(() => request({
669
+ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
670
+ return retryIfFailed(() => request({
646
671
  method: 'POST',
647
672
  url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
648
673
  headers: {
@@ -662,7 +687,7 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
662
687
  else {
663
688
  return response;
664
689
  }
665
- }), retryThrottledRequestMaxTimes);
690
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
666
691
  }
667
692
 
668
693
  class UploadcareFile {
@@ -729,7 +754,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
729
754
  timeoutId = setTimeout(tick, 0);
730
755
  });
731
756
 
732
- function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
757
+ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
733
758
  return poll({
734
759
  check: (signal) => info(file, {
735
760
  publicKey,
@@ -738,7 +763,8 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
738
763
  source,
739
764
  integration,
740
765
  userAgent,
741
- retryThrottledRequestMaxTimes
766
+ retryThrottledRequestMaxTimes,
767
+ retryNetworkErrorMaxTimes
742
768
  }).then((response) => {
743
769
  if (response.isReady) {
744
770
  return response;
@@ -750,7 +776,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
750
776
  });
751
777
  }
752
778
 
753
- const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN, metadata }) => {
779
+ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN, metadata }) => {
754
780
  return base(file, {
755
781
  publicKey,
756
782
  fileName,
@@ -765,6 +791,7 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
765
791
  integration,
766
792
  userAgent,
767
793
  retryThrottledRequestMaxTimes,
794
+ retryNetworkErrorMaxTimes,
768
795
  metadata
769
796
  })
770
797
  .then(({ file }) => {
@@ -776,6 +803,7 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
776
803
  integration,
777
804
  userAgent,
778
805
  retryThrottledRequestMaxTimes,
806
+ retryNetworkErrorMaxTimes,
779
807
  onProgress,
780
808
  signal
781
809
  });
@@ -963,7 +991,7 @@ const preconnect = (key) => {
963
991
  getPusher(key).connect();
964
992
  };
965
993
 
966
- function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
994
+ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, onProgress, signal }) {
967
995
  return poll({
968
996
  check: (signal) => fromUrlStatus(token, {
969
997
  publicKey,
@@ -971,6 +999,7 @@ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retry
971
999
  integration,
972
1000
  userAgent,
973
1001
  retryThrottledRequestMaxTimes,
1002
+ retryNetworkErrorMaxTimes,
974
1003
  signal
975
1004
  }).then((response) => {
976
1005
  switch (response.status) {
@@ -1121,7 +1150,7 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
1121
1150
  }))
1122
1151
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
1123
1152
 
1124
- const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
1153
+ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN }) => {
1125
1154
  return info(uuid, {
1126
1155
  publicKey,
1127
1156
  baseURL,
@@ -1129,7 +1158,8 @@ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProg
1129
1158
  source,
1130
1159
  integration,
1131
1160
  userAgent,
1132
- retryThrottledRequestMaxTimes
1161
+ retryThrottledRequestMaxTimes,
1162
+ retryNetworkErrorMaxTimes
1133
1163
  })
1134
1164
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
1135
1165
  .then((result) => {
@@ -1201,18 +1231,15 @@ const runWithConcurrency = (concurrency, tasks) => {
1201
1231
  });
1202
1232
  };
1203
1233
 
1204
- const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
1234
+ const uploadPart = (chunk, url, { publicKey, onProgress, signal, integration, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes }) => multipartUpload(chunk, url, {
1205
1235
  publicKey,
1206
1236
  onProgress,
1207
1237
  signal,
1208
- integration
1209
- }).catch((error) => {
1210
- if (attempt < multipartMaxAttempts) {
1211
- return retry();
1212
- }
1213
- throw error;
1214
- }));
1215
- 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 }) => {
1238
+ integration,
1239
+ retryThrottledRequestMaxTimes,
1240
+ retryNetworkErrorMaxTimes
1241
+ });
1242
+ 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 }) => {
1216
1243
  const size = fileSize || getFileSize(file);
1217
1244
  let progressValues;
1218
1245
  const createProgressHandler = (totalChunks, chunkIdx) => {
@@ -1246,18 +1273,20 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1246
1273
  integration,
1247
1274
  userAgent,
1248
1275
  retryThrottledRequestMaxTimes,
1276
+ retryNetworkErrorMaxTimes,
1249
1277
  metadata
1250
1278
  })
1251
1279
  .then(({ uuid, parts }) => {
1252
1280
  const getChunk = prepareChunks(file, size, multipartChunkSize);
1253
1281
  return Promise.all([
1254
1282
  uuid,
1255
- runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
1283
+ runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPart(getChunk(index), url, {
1256
1284
  publicKey,
1257
1285
  onProgress: createProgressHandler(parts.length, index),
1258
1286
  signal,
1259
1287
  integration,
1260
- multipartMaxAttempts
1288
+ retryThrottledRequestMaxTimes,
1289
+ retryNetworkErrorMaxTimes
1261
1290
  })))
1262
1291
  ]);
1263
1292
  })
@@ -1267,7 +1296,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1267
1296
  source,
1268
1297
  integration,
1269
1298
  userAgent,
1270
- retryThrottledRequestMaxTimes
1299
+ retryThrottledRequestMaxTimes,
1300
+ retryNetworkErrorMaxTimes
1271
1301
  }))
1272
1302
  .then((fileInfo) => {
1273
1303
  if (fileInfo.isReady) {
@@ -1282,6 +1312,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1282
1312
  integration,
1283
1313
  userAgent,
1284
1314
  retryThrottledRequestMaxTimes,
1315
+ retryNetworkErrorMaxTimes,
1285
1316
  onProgress,
1286
1317
  signal
1287
1318
  });
@@ -1293,7 +1324,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1293
1324
  /**
1294
1325
  * Uploads file from provided data.
1295
1326
  */
1296
- 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 }) {
1327
+ 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 }) {
1297
1328
  if (isFileData(data)) {
1298
1329
  const fileSize = getFileSize(data);
1299
1330
  if (isMultipart(fileSize, multipartMinFileSize)) {
@@ -1301,7 +1332,6 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1301
1332
  publicKey,
1302
1333
  contentType,
1303
1334
  multipartChunkSize,
1304
- multipartMaxAttempts,
1305
1335
  fileName,
1306
1336
  baseURL,
1307
1337
  secureSignature,
@@ -1314,6 +1344,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1314
1344
  userAgent,
1315
1345
  maxConcurrentRequests,
1316
1346
  retryThrottledRequestMaxTimes,
1347
+ retryNetworkErrorMaxTimes,
1317
1348
  baseCDN,
1318
1349
  metadata
1319
1350
  });
@@ -1332,6 +1363,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1332
1363
  integration,
1333
1364
  userAgent,
1334
1365
  retryThrottledRequestMaxTimes,
1366
+ retryNetworkErrorMaxTimes,
1335
1367
  baseCDN,
1336
1368
  metadata
1337
1369
  });
@@ -1353,6 +1385,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1353
1385
  integration,
1354
1386
  userAgent,
1355
1387
  retryThrottledRequestMaxTimes,
1388
+ retryNetworkErrorMaxTimes,
1356
1389
  pusherKey,
1357
1390
  metadata
1358
1391
  });
@@ -1368,6 +1401,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1368
1401
  integration,
1369
1402
  userAgent,
1370
1403
  retryThrottledRequestMaxTimes,
1404
+ retryNetworkErrorMaxTimes,
1371
1405
  baseCDN
1372
1406
  });
1373
1407
  }
@@ -1423,7 +1457,7 @@ const isUrlArray = (data) => {
1423
1457
  return true;
1424
1458
  };
1425
1459
 
1426
- 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 }) {
1460
+ 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 }) {
1427
1461
  if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
1428
1462
  throw new TypeError(`Group uploading from "${data}" is not supported`);
1429
1463
  }
@@ -1460,6 +1494,7 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1460
1494
  integration,
1461
1495
  userAgent,
1462
1496
  retryThrottledRequestMaxTimes,
1497
+ retryNetworkErrorMaxTimes,
1463
1498
  contentType,
1464
1499
  multipartChunkSize,
1465
1500
  baseCDN
@@ -1475,7 +1510,8 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1475
1510
  source,
1476
1511
  integration,
1477
1512
  userAgent,
1478
- retryThrottledRequestMaxTimes
1513
+ retryThrottledRequestMaxTimes,
1514
+ retryNetworkErrorMaxTimes
1479
1515
  })
1480
1516
  .then((groupInfo) => new UploadcareGroup(groupInfo, files))
1481
1517
  .then((group) => {
@@ -1548,4 +1584,4 @@ class UploadClient {
1548
1584
  }
1549
1585
  }
1550
1586
 
1551
- export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
1587
+ 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 };