@uploadcare/upload-client 4.3.1-alpha.0 → 5.1.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,14 +27,116 @@ 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
135
  /**
35
136
  * Force synchronous flag to be off
36
- * Some users get `InvalidAccessError` error when we set `responseType`
137
+ * Some chrome versions gets `InvalidAccessError` error when we set `responseType`
37
138
  * See https://xhr.spec.whatwg.org/#synchronous-flag
139
+ * and https://bugs.chromium.org/p/chromium/issues/detail?id=1346628
38
140
  */
39
141
  xhr.open(requestMethod, url, true);
40
142
  if (headers) {
@@ -91,11 +193,11 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
91
193
  });
92
194
  }
93
195
  };
94
- xhr.onerror = () => {
196
+ xhr.onerror = (progressEvent) => {
95
197
  if (aborted)
96
198
  return;
97
199
  // only triggers if the request couldn't be made at all
98
- reject(new Error('Network error'));
200
+ reject(new UploadcareNetworkError(progressEvent));
99
201
  };
100
202
  if (onProgress && typeof onProgress === 'function') {
101
203
  xhr.upload.onprogress = (event) => {
@@ -229,7 +331,7 @@ const buildSearchParams = (query) => {
229
331
  };
230
332
  const getUrl = (base, path, query) => {
231
333
  const url = new URL(base);
232
- url.pathname = path;
334
+ url.pathname = (url.pathname + path).replace('//', '/');
233
335
  if (query) {
234
336
  url.search = buildSearchParams(query);
235
337
  }
@@ -245,109 +347,18 @@ const defaultSettings = {
245
347
  baseURL: 'https://upload.uploadcare.com',
246
348
  maxContentLength: 50 * 1024 * 1024,
247
349
  retryThrottledRequestMaxTimes: 1,
350
+ retryNetworkErrorMaxTimes: 3,
248
351
  multipartMinFileSize: 25 * 1024 * 1024,
249
352
  multipartChunkSize: 5 * 1024 * 1024,
250
353
  multipartMinLastPartSize: 1024 * 1024,
251
354
  maxConcurrentRequests: 4,
252
- multipartMaxAttempts: 3,
253
355
  pollingTimeoutMilliseconds: 10000,
254
356
  pusherKey: '79ae88bd931ea68464d9'
255
357
  };
256
358
  const defaultContentType = 'application/octet-stream';
257
359
  const defaultFilename = 'original';
258
360
 
259
- var version = '4.3.1-alpha.0';
260
-
261
- function isObject(o) {
262
- return Object.prototype.toString.call(o) === '[object Object]';
263
- }
264
-
265
- const SEPARATOR = /\W|_/g;
266
- function camelizeString(text) {
267
- return text
268
- .split(SEPARATOR)
269
- .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
270
- word.slice(1))
271
- .join('');
272
- }
273
- function camelizeArrayItems(array, { ignoreKeys } = { ignoreKeys: [] }) {
274
- if (!Array.isArray(array)) {
275
- return array;
276
- }
277
- return array.map((item) => camelizeKeys(item, { ignoreKeys }));
278
- }
279
- function camelizeKeys(source, { ignoreKeys } = { ignoreKeys: [] }) {
280
- if (Array.isArray(source)) {
281
- return camelizeArrayItems(source, { ignoreKeys });
282
- }
283
- if (!isObject(source)) {
284
- return source;
285
- }
286
- const result = {};
287
- for (const key of Object.keys(source)) {
288
- let value = source[key];
289
- if (ignoreKeys.includes(key)) {
290
- result[key] = value;
291
- continue;
292
- }
293
- if (isObject(value)) {
294
- value = camelizeKeys(value, { ignoreKeys });
295
- }
296
- else if (Array.isArray(value)) {
297
- value = camelizeArrayItems(value, { ignoreKeys });
298
- }
299
- result[camelizeString(key)] = value;
300
- }
301
- return result;
302
- }
303
-
304
- /**
305
- * setTimeout as Promise.
306
- *
307
- * @param {number} ms Timeout in milliseconds.
308
- */
309
- const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
310
-
311
- function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
312
- const languageName = 'JavaScript';
313
- if (typeof userAgent === 'string') {
314
- return userAgent;
315
- }
316
- if (typeof userAgent === 'function') {
317
- return userAgent({
318
- publicKey,
319
- libraryName,
320
- libraryVersion,
321
- languageName,
322
- integration
323
- });
324
- }
325
- const mainInfo = [libraryName, libraryVersion, publicKey]
326
- .filter(Boolean)
327
- .join('/');
328
- const additionInfo = [languageName, integration].filter(Boolean).join('; ');
329
- return `${mainInfo} (${additionInfo})`;
330
- }
331
-
332
- const defaultOptions = {
333
- factor: 2,
334
- time: 100
335
- };
336
- function retrier(fn, options = defaultOptions) {
337
- let attempts = 0;
338
- function runAttempt(fn) {
339
- const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
340
- const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
341
- attempts += 1;
342
- return runAttempt(fn);
343
- });
344
- return fn({
345
- attempt: attempts,
346
- retry
347
- });
348
- }
349
- return runAttempt(fn);
350
- }
361
+ var version = '5.1.0';
351
362
 
352
363
  const LIBRARY_NAME = 'UploadcareUploadClient';
353
364
  const LIBRARY_VERSION = version;
@@ -360,20 +371,26 @@ function getUserAgent(options) {
360
371
  }
361
372
 
362
373
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
363
- const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
374
+ const DEFAULT_THROTTLED_TIMEOUT = 15000;
375
+ const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
364
376
  function getTimeoutFromThrottledRequest(error) {
365
377
  const { headers } = error || {};
366
378
  return ((headers &&
367
379
  Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
368
- DEFAULT_RETRY_AFTER_TIMEOUT);
380
+ DEFAULT_THROTTLED_TIMEOUT);
369
381
  }
370
- function retryIfThrottled(fn, retryThrottledMaxTimes) {
382
+ function retryIfFailed(fn, options) {
383
+ const { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes } = options;
371
384
  return retrier(({ attempt, retry }) => fn().catch((error) => {
372
385
  if ('response' in error &&
373
386
  error?.code === REQUEST_WAS_THROTTLED_CODE &&
374
- attempt < retryThrottledMaxTimes) {
387
+ attempt < retryThrottledRequestMaxTimes) {
375
388
  return retry(getTimeoutFromThrottledRequest(error));
376
389
  }
390
+ if (error instanceof UploadcareNetworkError &&
391
+ attempt < retryNetworkErrorMaxTimes) {
392
+ return retry((attempt + 1) * DEFAULT_NETWORK_ERROR_TIMEOUT);
393
+ }
377
394
  throw error;
378
395
  }));
379
396
  }
@@ -386,8 +403,8 @@ function getStoreValue(store) {
386
403
  * Performs file uploading request to Uploadcare Upload API.
387
404
  * Can be canceled and has progress.
388
405
  */
389
- function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
390
- 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({
391
408
  method: 'POST',
392
409
  url: getUrl(baseURL, '/base/', {
393
410
  jsonerrors: 1
@@ -418,7 +435,7 @@ function base(file, { publicKey, fileName, contentType, baseURL = defaultSetting
418
435
  else {
419
436
  return response;
420
437
  }
421
- }), retryThrottledRequestMaxTimes);
438
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
422
439
  }
423
440
 
424
441
  var TypeEnum;
@@ -429,8 +446,8 @@ var TypeEnum;
429
446
  /**
430
447
  * Uploading files from URL.
431
448
  */
432
- function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
433
- 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({
434
451
  method: 'POST',
435
452
  headers: {
436
453
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -457,7 +474,7 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
457
474
  else {
458
475
  return response;
459
476
  }
460
- }), retryThrottledRequestMaxTimes);
477
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
461
478
  }
462
479
 
463
480
  var Status;
@@ -474,8 +491,8 @@ const isErrorResponse = (response) => {
474
491
  /**
475
492
  * Checking upload status and working with file tokens.
476
493
  */
477
- function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
478
- return retryIfThrottled(() => request({
494
+ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes } = {}) {
495
+ return retryIfFailed(() => request({
479
496
  method: 'GET',
480
497
  headers: publicKey
481
498
  ? {
@@ -499,14 +516,14 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
499
516
  else {
500
517
  return response;
501
518
  }
502
- }), retryThrottledRequestMaxTimes);
519
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
503
520
  }
504
521
 
505
522
  /**
506
523
  * Create files group.
507
524
  */
508
- function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
509
- 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({
510
527
  method: 'POST',
511
528
  headers: {
512
529
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -529,14 +546,14 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
529
546
  else {
530
547
  return response;
531
548
  }
532
- }), retryThrottledRequestMaxTimes);
549
+ }), { retryNetworkErrorMaxTimes, retryThrottledRequestMaxTimes });
533
550
  }
534
551
 
535
552
  /**
536
553
  * Get info about group.
537
554
  */
538
- function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
539
- 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({
540
557
  method: 'GET',
541
558
  headers: {
542
559
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -556,14 +573,14 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
556
573
  else {
557
574
  return response;
558
575
  }
559
- }), retryThrottledRequestMaxTimes);
576
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
560
577
  }
561
578
 
562
579
  /**
563
580
  * Returns a JSON dictionary holding file info.
564
581
  */
565
- function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
566
- 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({
567
584
  method: 'GET',
568
585
  headers: {
569
586
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
@@ -583,14 +600,14 @@ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, sour
583
600
  else {
584
601
  return response;
585
602
  }
586
- }), retryThrottledRequestMaxTimes);
603
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
587
604
  }
588
605
 
589
606
  /**
590
607
  * Start multipart uploading.
591
608
  */
592
- function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
593
- 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({
594
611
  method: 'POST',
595
612
  url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
596
613
  headers: {
@@ -619,14 +636,14 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
619
636
  response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
620
637
  return response;
621
638
  }
622
- }), retryThrottledRequestMaxTimes);
639
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
623
640
  }
624
641
 
625
642
  /**
626
643
  * Complete multipart uploading.
627
644
  */
628
- function multipartUpload(part, url, { signal, onProgress }) {
629
- return request({
645
+ function multipartUpload(part, url, { signal, onProgress, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes = defaultSettings.retryNetworkErrorMaxTimes }) {
646
+ return retryIfFailed(() => request({
630
647
  method: 'PUT',
631
648
  url,
632
649
  data: part,
@@ -643,14 +660,17 @@ function multipartUpload(part, url, { signal, onProgress }) {
643
660
  });
644
661
  return result;
645
662
  })
646
- .then(({ status }) => ({ code: status }));
663
+ .then(({ status }) => ({ code: status })), {
664
+ retryThrottledRequestMaxTimes,
665
+ retryNetworkErrorMaxTimes
666
+ });
647
667
  }
648
668
 
649
669
  /**
650
670
  * Complete multipart uploading.
651
671
  */
652
- function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
653
- 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({
654
674
  method: 'POST',
655
675
  url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
656
676
  headers: {
@@ -670,7 +690,7 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
670
690
  else {
671
691
  return response;
672
692
  }
673
- }), retryThrottledRequestMaxTimes);
693
+ }), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
674
694
  }
675
695
 
676
696
  class UploadcareFile {
@@ -737,7 +757,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
737
757
  timeoutId = setTimeout(tick, 0);
738
758
  });
739
759
 
740
- function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
760
+ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
741
761
  return poll({
742
762
  check: (signal) => info(file, {
743
763
  publicKey,
@@ -746,7 +766,8 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
746
766
  source,
747
767
  integration,
748
768
  userAgent,
749
- retryThrottledRequestMaxTimes
769
+ retryThrottledRequestMaxTimes,
770
+ retryNetworkErrorMaxTimes
750
771
  }).then((response) => {
751
772
  if (response.isReady) {
752
773
  return response;
@@ -758,7 +779,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
758
779
  });
759
780
  }
760
781
 
761
- 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 }) => {
762
783
  return base(file, {
763
784
  publicKey,
764
785
  fileName,
@@ -773,6 +794,7 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
773
794
  integration,
774
795
  userAgent,
775
796
  retryThrottledRequestMaxTimes,
797
+ retryNetworkErrorMaxTimes,
776
798
  metadata
777
799
  })
778
800
  .then(({ file }) => {
@@ -784,6 +806,7 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
784
806
  integration,
785
807
  userAgent,
786
808
  retryThrottledRequestMaxTimes,
809
+ retryNetworkErrorMaxTimes,
787
810
  onProgress,
788
811
  signal
789
812
  });
@@ -971,7 +994,7 @@ const preconnect = (key) => {
971
994
  getPusher(key).connect();
972
995
  };
973
996
 
974
- function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
997
+ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, onProgress, signal }) {
975
998
  return poll({
976
999
  check: (signal) => fromUrlStatus(token, {
977
1000
  publicKey,
@@ -979,6 +1002,7 @@ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retry
979
1002
  integration,
980
1003
  userAgent,
981
1004
  retryThrottledRequestMaxTimes,
1005
+ retryNetworkErrorMaxTimes,
982
1006
  signal
983
1007
  }).then((response) => {
984
1008
  switch (response.status) {
@@ -1129,7 +1153,7 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
1129
1153
  }))
1130
1154
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
1131
1155
 
1132
- 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 }) => {
1133
1157
  return info(uuid, {
1134
1158
  publicKey,
1135
1159
  baseURL,
@@ -1137,7 +1161,8 @@ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProg
1137
1161
  source,
1138
1162
  integration,
1139
1163
  userAgent,
1140
- retryThrottledRequestMaxTimes
1164
+ retryThrottledRequestMaxTimes,
1165
+ retryNetworkErrorMaxTimes
1141
1166
  })
1142
1167
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
1143
1168
  .then((result) => {
@@ -1222,18 +1247,15 @@ const runWithConcurrency = (concurrency, tasks) => {
1222
1247
  });
1223
1248
  };
1224
1249
 
1225
- 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, {
1226
1251
  publicKey,
1227
1252
  onProgress,
1228
1253
  signal,
1229
- integration
1230
- }).catch((error) => {
1231
- if (attempt < multipartMaxAttempts) {
1232
- return retry();
1233
- }
1234
- throw error;
1235
- }));
1236
- 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 }) => {
1237
1259
  const size = fileSize || getFileSize(file);
1238
1260
  let progressValues;
1239
1261
  const createProgressHandler = (totalChunks, chunkIdx) => {
@@ -1267,18 +1289,20 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1267
1289
  integration,
1268
1290
  userAgent,
1269
1291
  retryThrottledRequestMaxTimes,
1292
+ retryNetworkErrorMaxTimes,
1270
1293
  metadata
1271
1294
  })
1272
1295
  .then(({ uuid, parts }) => {
1273
1296
  const getChunk = prepareChunks(file, size, multipartChunkSize);
1274
1297
  return Promise.all([
1275
1298
  uuid,
1276
- runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
1299
+ runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPart(getChunk(index), url, {
1277
1300
  publicKey,
1278
1301
  onProgress: createProgressHandler(parts.length, index),
1279
1302
  signal,
1280
1303
  integration,
1281
- multipartMaxAttempts
1304
+ retryThrottledRequestMaxTimes,
1305
+ retryNetworkErrorMaxTimes
1282
1306
  })))
1283
1307
  ]);
1284
1308
  })
@@ -1288,7 +1312,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1288
1312
  source,
1289
1313
  integration,
1290
1314
  userAgent,
1291
- retryThrottledRequestMaxTimes
1315
+ retryThrottledRequestMaxTimes,
1316
+ retryNetworkErrorMaxTimes
1292
1317
  }))
1293
1318
  .then((fileInfo) => {
1294
1319
  if (fileInfo.isReady) {
@@ -1303,6 +1328,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1303
1328
  integration,
1304
1329
  userAgent,
1305
1330
  retryThrottledRequestMaxTimes,
1331
+ retryNetworkErrorMaxTimes,
1306
1332
  onProgress,
1307
1333
  signal
1308
1334
  });
@@ -1314,7 +1340,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1314
1340
  /**
1315
1341
  * Uploads file from provided data.
1316
1342
  */
1317
- 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 }) {
1318
1344
  if (isFileData(data)) {
1319
1345
  const fileSize = getFileSize(data);
1320
1346
  if (isMultipart(fileSize, multipartMinFileSize)) {
@@ -1322,7 +1348,6 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1322
1348
  publicKey,
1323
1349
  contentType,
1324
1350
  multipartChunkSize,
1325
- multipartMaxAttempts,
1326
1351
  fileName,
1327
1352
  baseURL,
1328
1353
  secureSignature,
@@ -1335,6 +1360,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1335
1360
  userAgent,
1336
1361
  maxConcurrentRequests,
1337
1362
  retryThrottledRequestMaxTimes,
1363
+ retryNetworkErrorMaxTimes,
1338
1364
  baseCDN,
1339
1365
  metadata
1340
1366
  });
@@ -1353,6 +1379,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1353
1379
  integration,
1354
1380
  userAgent,
1355
1381
  retryThrottledRequestMaxTimes,
1382
+ retryNetworkErrorMaxTimes,
1356
1383
  baseCDN,
1357
1384
  metadata
1358
1385
  });
@@ -1374,6 +1401,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1374
1401
  integration,
1375
1402
  userAgent,
1376
1403
  retryThrottledRequestMaxTimes,
1404
+ retryNetworkErrorMaxTimes,
1377
1405
  pusherKey,
1378
1406
  metadata
1379
1407
  });
@@ -1389,6 +1417,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1389
1417
  integration,
1390
1418
  userAgent,
1391
1419
  retryThrottledRequestMaxTimes,
1420
+ retryNetworkErrorMaxTimes,
1392
1421
  baseCDN
1393
1422
  });
1394
1423
  }
@@ -1444,7 +1473,7 @@ const isUrlArray = (data) => {
1444
1473
  return true;
1445
1474
  };
1446
1475
 
1447
- 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 }) {
1448
1477
  if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
1449
1478
  throw new TypeError(`Group uploading from "${data}" is not supported`);
1450
1479
  }
@@ -1481,6 +1510,7 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1481
1510
  integration,
1482
1511
  userAgent,
1483
1512
  retryThrottledRequestMaxTimes,
1513
+ retryNetworkErrorMaxTimes,
1484
1514
  contentType,
1485
1515
  multipartChunkSize,
1486
1516
  baseCDN
@@ -1496,7 +1526,8 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1496
1526
  source,
1497
1527
  integration,
1498
1528
  userAgent,
1499
- retryThrottledRequestMaxTimes
1529
+ retryThrottledRequestMaxTimes,
1530
+ retryNetworkErrorMaxTimes
1500
1531
  })
1501
1532
  .then((groupInfo) => new UploadcareGroup(groupInfo, files))
1502
1533
  .then((group) => {
@@ -1569,4 +1600,4 @@ class UploadClient {
1569
1600
  }
1570
1601
  }
1571
1602
 
1572
- 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 };