@uploadcare/upload-client 5.1.2 → 6.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.
@@ -1,32 +1,3 @@
1
- class UploadClientError extends Error {
2
- constructor(message, code, request, response, headers) {
3
- super();
4
- this.name = 'UploadClientError';
5
- this.message = message;
6
- this.code = code;
7
- this.request = request;
8
- this.response = response;
9
- this.headers = headers;
10
- Object.setPrototypeOf(this, UploadClientError.prototype);
11
- }
12
- }
13
- const cancelError = (message = 'Request canceled') => {
14
- const error = new UploadClientError(message);
15
- error.isCancel = true;
16
- return error;
17
- };
18
-
19
- const onCancel = (signal, callback) => {
20
- if (signal) {
21
- if (signal.aborted) {
22
- Promise.resolve().then(callback);
23
- }
24
- else {
25
- signal.addEventListener('abort', () => callback(), { once: true });
26
- }
27
- }
28
- };
29
-
30
1
  function isObject(o) {
31
2
  return Object.prototype.toString.call(o) === '[object Object]';
32
3
  }
@@ -128,6 +99,64 @@ class UploadcareNetworkError extends Error {
128
99
  }
129
100
  }
130
101
 
102
+ const onCancel = (signal, callback) => {
103
+ if (signal) {
104
+ if (signal.aborted) {
105
+ Promise.resolve().then(callback);
106
+ }
107
+ else {
108
+ signal.addEventListener('abort', () => callback(), { once: true });
109
+ }
110
+ }
111
+ };
112
+
113
+ class CancelError extends Error {
114
+ constructor(message = 'Request canceled') {
115
+ super(message);
116
+ this.isCancel = true;
117
+ Object.setPrototypeOf(this, CancelError.prototype);
118
+ }
119
+ }
120
+
121
+ const DEFAULT_INTERVAL = 500;
122
+ const poll = ({ check, interval = DEFAULT_INTERVAL, timeout, signal }) => new Promise((resolve, reject) => {
123
+ let tickTimeoutId;
124
+ let timeoutId;
125
+ onCancel(signal, () => {
126
+ tickTimeoutId && clearTimeout(tickTimeoutId);
127
+ reject(new CancelError('Poll cancelled'));
128
+ });
129
+ if (timeout) {
130
+ timeoutId = setTimeout(() => {
131
+ tickTimeoutId && clearTimeout(tickTimeoutId);
132
+ reject(new CancelError('Timed out'));
133
+ }, timeout);
134
+ }
135
+ const tick = () => {
136
+ try {
137
+ Promise.resolve(check(signal))
138
+ .then((result) => {
139
+ if (result) {
140
+ timeoutId && clearTimeout(timeoutId);
141
+ resolve(result);
142
+ }
143
+ else {
144
+ tickTimeoutId = setTimeout(tick, interval);
145
+ }
146
+ })
147
+ .catch((error) => {
148
+ timeoutId && clearTimeout(timeoutId);
149
+ reject(error);
150
+ });
151
+ }
152
+ catch (error) {
153
+ timeoutId && clearTimeout(timeoutId);
154
+ reject(error);
155
+ }
156
+ };
157
+ tickTimeoutId = setTimeout(tick, 0);
158
+ });
159
+
131
160
  const request = ({ method, url, data, headers = {}, signal, onProgress }) => new Promise((resolve, reject) => {
132
161
  const xhr = new XMLHttpRequest();
133
162
  const requestMethod = method?.toUpperCase() || 'GET';
@@ -151,7 +180,7 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
151
180
  onCancel(signal, () => {
152
181
  aborted = true;
153
182
  xhr.abort();
154
- reject(cancelError());
183
+ reject(new CancelError());
155
184
  });
156
185
  xhr.onload = () => {
157
186
  if (xhr.status != 200) {
@@ -355,7 +384,7 @@ const defaultSettings = {
355
384
  const defaultContentType = 'application/octet-stream';
356
385
  const defaultFilename = 'original';
357
386
 
358
- var version = '5.1.2';
387
+ var version = '6.0.0';
359
388
 
360
389
  const LIBRARY_NAME = 'UploadcareUploadClient';
361
390
  const LIBRARY_VERSION = version;
@@ -367,14 +396,32 @@ function getUserAgent(options) {
367
396
  });
368
397
  }
369
398
 
399
+ class UploadClientError extends Error {
400
+ constructor(message, code, request, response, headers) {
401
+ super();
402
+ this.name = 'UploadClientError';
403
+ this.message = message;
404
+ this.code = code;
405
+ this.request = request;
406
+ this.response = response;
407
+ this.headers = headers;
408
+ Object.setPrototypeOf(this, UploadClientError.prototype);
409
+ }
410
+ }
411
+
370
412
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
371
- const DEFAULT_THROTTLED_TIMEOUT = 15000;
413
+ const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
372
414
  const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
373
415
  function getTimeoutFromThrottledRequest(error) {
374
416
  const { headers } = error || {};
375
- return ((headers &&
376
- Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
377
- DEFAULT_THROTTLED_TIMEOUT);
417
+ if (!headers || typeof headers['retry-after'] !== 'string') {
418
+ return DEFAULT_RETRY_AFTER_TIMEOUT;
419
+ }
420
+ const seconds = parseInt(headers['retry-after'], 10);
421
+ if (!Number.isFinite(seconds)) {
422
+ return DEFAULT_RETRY_AFTER_TIMEOUT;
423
+ }
424
+ return seconds * 1000;
378
425
  }
379
426
  function retryIfFailed(fn, options) {
380
427
  const { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes } = options;
@@ -727,33 +774,6 @@ class UploadcareFile {
727
774
  }
728
775
  }
729
776
 
730
- const DEFAULT_INTERVAL = 500;
731
- const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((resolve, reject) => {
732
- let timeoutId;
733
- onCancel(signal, () => {
734
- timeoutId && clearTimeout(timeoutId);
735
- reject(cancelError('Poll cancelled'));
736
- });
737
- const tick = () => {
738
- try {
739
- Promise.resolve(check(signal))
740
- .then((result) => {
741
- if (result) {
742
- resolve(result);
743
- }
744
- else {
745
- timeoutId = setTimeout(tick, interval);
746
- }
747
- })
748
- .catch((error) => reject(error));
749
- }
750
- catch (error) {
751
- reject(error);
752
- }
753
- };
754
- timeoutId = setTimeout(tick, 0);
755
- });
756
-
757
777
  function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
758
778
  return poll({
759
779
  check: (signal) => info(file, {
@@ -1051,7 +1071,7 @@ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((
1051
1071
  };
1052
1072
  onCancel(signal, () => {
1053
1073
  destroy();
1054
- reject(cancelError('pusher cancelled'));
1074
+ reject(new CancelError('pusher cancelled'));
1055
1075
  });
1056
1076
  pusher.subscribe(token, (result) => {
1057
1077
  switch (result.status) {
@@ -5,23 +5,106 @@ import { Transform, Readable } from 'stream';
5
5
  import NodeFormData from 'form-data';
6
6
  import WebSocket from 'ws';
7
7
 
8
- class UploadClientError extends Error {
9
- constructor(message, code, request, response, headers) {
10
- super();
11
- this.name = 'UploadClientError';
12
- this.message = message;
13
- this.code = code;
14
- this.request = request;
15
- this.response = response;
16
- this.headers = headers;
17
- Object.setPrototypeOf(this, UploadClientError.prototype);
8
+ function isObject(o) {
9
+ return Object.prototype.toString.call(o) === '[object Object]';
10
+ }
11
+
12
+ const SEPARATOR = /\W|_/g;
13
+ function camelizeString(text) {
14
+ return text
15
+ .split(SEPARATOR)
16
+ .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
17
+ word.slice(1))
18
+ .join('');
19
+ }
20
+ function camelizeArrayItems(array, { ignoreKeys } = { ignoreKeys: [] }) {
21
+ if (!Array.isArray(array)) {
22
+ return array;
23
+ }
24
+ return array.map((item) => camelizeKeys(item, { ignoreKeys }));
25
+ }
26
+ function camelizeKeys(source, { ignoreKeys } = { ignoreKeys: [] }) {
27
+ if (Array.isArray(source)) {
28
+ return camelizeArrayItems(source, { ignoreKeys });
29
+ }
30
+ if (!isObject(source)) {
31
+ return source;
18
32
  }
33
+ const result = {};
34
+ for (const key of Object.keys(source)) {
35
+ let value = source[key];
36
+ if (ignoreKeys.includes(key)) {
37
+ result[key] = value;
38
+ continue;
39
+ }
40
+ if (isObject(value)) {
41
+ value = camelizeKeys(value, { ignoreKeys });
42
+ }
43
+ else if (Array.isArray(value)) {
44
+ value = camelizeArrayItems(value, { ignoreKeys });
45
+ }
46
+ result[camelizeString(key)] = value;
47
+ }
48
+ return result;
19
49
  }
20
- const cancelError = (message = 'Request canceled') => {
21
- const error = new UploadClientError(message);
22
- error.isCancel = true;
23
- return error;
50
+
51
+ /**
52
+ * setTimeout as Promise.
53
+ *
54
+ * @param {number} ms Timeout in milliseconds.
55
+ */
56
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
57
+
58
+ function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
59
+ const languageName = 'JavaScript';
60
+ if (typeof userAgent === 'string') {
61
+ return userAgent;
62
+ }
63
+ if (typeof userAgent === 'function') {
64
+ return userAgent({
65
+ publicKey,
66
+ libraryName,
67
+ libraryVersion,
68
+ languageName,
69
+ integration
70
+ });
71
+ }
72
+ const mainInfo = [libraryName, libraryVersion, publicKey]
73
+ .filter(Boolean)
74
+ .join('/');
75
+ const additionInfo = [languageName, integration].filter(Boolean).join('; ');
76
+ return `${mainInfo} (${additionInfo})`;
77
+ }
78
+
79
+ const defaultOptions = {
80
+ factor: 2,
81
+ time: 100
24
82
  };
83
+ function retrier(fn, options = defaultOptions) {
84
+ let attempts = 0;
85
+ function runAttempt(fn) {
86
+ const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
87
+ const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
88
+ attempts += 1;
89
+ return runAttempt(fn);
90
+ });
91
+ return fn({
92
+ attempt: attempts,
93
+ retry
94
+ });
95
+ }
96
+ return runAttempt(fn);
97
+ }
98
+
99
+ class UploadcareNetworkError extends Error {
100
+ constructor(progressEvent) {
101
+ super();
102
+ this.name = 'UploadcareNetworkError';
103
+ this.message = 'Network error';
104
+ Object.setPrototypeOf(this, UploadcareNetworkError.prototype);
105
+ this.originalProgressEvent = progressEvent;
106
+ }
107
+ }
25
108
 
26
109
  const onCancel = (signal, callback) => {
27
110
  if (signal) {
@@ -34,6 +117,53 @@ const onCancel = (signal, callback) => {
34
117
  }
35
118
  };
36
119
 
120
+ class CancelError extends Error {
121
+ constructor(message = 'Request canceled') {
122
+ super(message);
123
+ this.isCancel = true;
124
+ Object.setPrototypeOf(this, CancelError.prototype);
125
+ }
126
+ }
127
+
128
+ const DEFAULT_INTERVAL = 500;
129
+ const poll = ({ check, interval = DEFAULT_INTERVAL, timeout, signal }) => new Promise((resolve, reject) => {
130
+ let tickTimeoutId;
131
+ let timeoutId;
132
+ onCancel(signal, () => {
133
+ tickTimeoutId && clearTimeout(tickTimeoutId);
134
+ reject(new CancelError('Poll cancelled'));
135
+ });
136
+ if (timeout) {
137
+ timeoutId = setTimeout(() => {
138
+ tickTimeoutId && clearTimeout(tickTimeoutId);
139
+ reject(new CancelError('Timed out'));
140
+ }, timeout);
141
+ }
142
+ const tick = () => {
143
+ try {
144
+ Promise.resolve(check(signal))
145
+ .then((result) => {
146
+ if (result) {
147
+ timeoutId && clearTimeout(timeoutId);
148
+ resolve(result);
149
+ }
150
+ else {
151
+ tickTimeoutId = setTimeout(tick, interval);
152
+ }
153
+ })
154
+ .catch((error) => {
155
+ timeoutId && clearTimeout(timeoutId);
156
+ reject(error);
157
+ });
158
+ }
159
+ catch (error) {
160
+ timeoutId && clearTimeout(timeoutId);
161
+ reject(error);
162
+ }
163
+ };
164
+ tickTimeoutId = setTimeout(tick, 0);
165
+ });
166
+
37
167
  // ProgressEmitter is a simple PassThrough-style transform stream which keeps
38
168
  // track of the number of bytes which have been piped through it and will
39
169
  // invoke the `onprogress` function whenever new number are available.
@@ -102,7 +232,7 @@ const request = (params) => {
102
232
  onCancel(signal, () => {
103
233
  aborted = true;
104
234
  req.abort();
105
- reject(cancelError());
235
+ reject(new CancelError());
106
236
  });
107
237
  req.on('response', (res) => {
108
238
  if (aborted)
@@ -282,108 +412,7 @@ const defaultSettings = {
282
412
  const defaultContentType = 'application/octet-stream';
283
413
  const defaultFilename = 'original';
284
414
 
285
- var version = '5.1.2';
286
-
287
- function isObject(o) {
288
- return Object.prototype.toString.call(o) === '[object Object]';
289
- }
290
-
291
- const SEPARATOR = /\W|_/g;
292
- function camelizeString(text) {
293
- return text
294
- .split(SEPARATOR)
295
- .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
296
- word.slice(1))
297
- .join('');
298
- }
299
- function camelizeArrayItems(array, { ignoreKeys } = { ignoreKeys: [] }) {
300
- if (!Array.isArray(array)) {
301
- return array;
302
- }
303
- return array.map((item) => camelizeKeys(item, { ignoreKeys }));
304
- }
305
- function camelizeKeys(source, { ignoreKeys } = { ignoreKeys: [] }) {
306
- if (Array.isArray(source)) {
307
- return camelizeArrayItems(source, { ignoreKeys });
308
- }
309
- if (!isObject(source)) {
310
- return source;
311
- }
312
- const result = {};
313
- for (const key of Object.keys(source)) {
314
- let value = source[key];
315
- if (ignoreKeys.includes(key)) {
316
- result[key] = value;
317
- continue;
318
- }
319
- if (isObject(value)) {
320
- value = camelizeKeys(value, { ignoreKeys });
321
- }
322
- else if (Array.isArray(value)) {
323
- value = camelizeArrayItems(value, { ignoreKeys });
324
- }
325
- result[camelizeString(key)] = value;
326
- }
327
- return result;
328
- }
329
-
330
- /**
331
- * setTimeout as Promise.
332
- *
333
- * @param {number} ms Timeout in milliseconds.
334
- */
335
- const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
336
-
337
- function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
338
- const languageName = 'JavaScript';
339
- if (typeof userAgent === 'string') {
340
- return userAgent;
341
- }
342
- if (typeof userAgent === 'function') {
343
- return userAgent({
344
- publicKey,
345
- libraryName,
346
- libraryVersion,
347
- languageName,
348
- integration
349
- });
350
- }
351
- const mainInfo = [libraryName, libraryVersion, publicKey]
352
- .filter(Boolean)
353
- .join('/');
354
- const additionInfo = [languageName, integration].filter(Boolean).join('; ');
355
- return `${mainInfo} (${additionInfo})`;
356
- }
357
-
358
- const defaultOptions = {
359
- factor: 2,
360
- time: 100
361
- };
362
- function retrier(fn, options = defaultOptions) {
363
- let attempts = 0;
364
- function runAttempt(fn) {
365
- const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
366
- const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
367
- attempts += 1;
368
- return runAttempt(fn);
369
- });
370
- return fn({
371
- attempt: attempts,
372
- retry
373
- });
374
- }
375
- return runAttempt(fn);
376
- }
377
-
378
- class UploadcareNetworkError extends Error {
379
- constructor(progressEvent) {
380
- super();
381
- this.name = 'UploadcareNetworkError';
382
- this.message = 'Network error';
383
- Object.setPrototypeOf(this, UploadcareNetworkError.prototype);
384
- this.originalProgressEvent = progressEvent;
385
- }
386
- }
415
+ var version = '6.0.0';
387
416
 
388
417
  const LIBRARY_NAME = 'UploadcareUploadClient';
389
418
  const LIBRARY_VERSION = version;
@@ -395,14 +424,32 @@ function getUserAgent(options) {
395
424
  });
396
425
  }
397
426
 
427
+ class UploadClientError extends Error {
428
+ constructor(message, code, request, response, headers) {
429
+ super();
430
+ this.name = 'UploadClientError';
431
+ this.message = message;
432
+ this.code = code;
433
+ this.request = request;
434
+ this.response = response;
435
+ this.headers = headers;
436
+ Object.setPrototypeOf(this, UploadClientError.prototype);
437
+ }
438
+ }
439
+
398
440
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
399
- const DEFAULT_THROTTLED_TIMEOUT = 15000;
441
+ const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
400
442
  const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
401
443
  function getTimeoutFromThrottledRequest(error) {
402
444
  const { headers } = error || {};
403
- return ((headers &&
404
- Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
405
- DEFAULT_THROTTLED_TIMEOUT);
445
+ if (!headers || typeof headers['retry-after'] !== 'string') {
446
+ return DEFAULT_RETRY_AFTER_TIMEOUT;
447
+ }
448
+ const seconds = parseInt(headers['retry-after'], 10);
449
+ if (!Number.isFinite(seconds)) {
450
+ return DEFAULT_RETRY_AFTER_TIMEOUT;
451
+ }
452
+ return seconds * 1000;
406
453
  }
407
454
  function retryIfFailed(fn, options) {
408
455
  const { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes } = options;
@@ -755,33 +802,6 @@ class UploadcareFile {
755
802
  }
756
803
  }
757
804
 
758
- const DEFAULT_INTERVAL = 500;
759
- const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((resolve, reject) => {
760
- let timeoutId;
761
- onCancel(signal, () => {
762
- timeoutId && clearTimeout(timeoutId);
763
- reject(cancelError('Poll cancelled'));
764
- });
765
- const tick = () => {
766
- try {
767
- Promise.resolve(check(signal))
768
- .then((result) => {
769
- if (result) {
770
- resolve(result);
771
- }
772
- else {
773
- timeoutId = setTimeout(tick, interval);
774
- }
775
- })
776
- .catch((error) => reject(error));
777
- }
778
- catch (error) {
779
- reject(error);
780
- }
781
- };
782
- timeoutId = setTimeout(tick, 0);
783
- });
784
-
785
805
  function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
786
806
  return poll({
787
807
  check: (signal) => info(file, {
@@ -1077,7 +1097,7 @@ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((
1077
1097
  };
1078
1098
  onCancel(signal, () => {
1079
1099
  destroy();
1080
- reject(cancelError('pusher cancelled'));
1100
+ reject(new CancelError('pusher cancelled'));
1081
1101
  });
1082
1102
  pusher.subscribe(token, (result) => {
1083
1103
  switch (result.status) {
@@ -1,32 +1,3 @@
1
- class UploadClientError extends Error {
2
- constructor(message, code, request, response, headers) {
3
- super();
4
- this.name = 'UploadClientError';
5
- this.message = message;
6
- this.code = code;
7
- this.request = request;
8
- this.response = response;
9
- this.headers = headers;
10
- Object.setPrototypeOf(this, UploadClientError.prototype);
11
- }
12
- }
13
- const cancelError = (message = 'Request canceled') => {
14
- const error = new UploadClientError(message);
15
- error.isCancel = true;
16
- return error;
17
- };
18
-
19
- const onCancel = (signal, callback) => {
20
- if (signal) {
21
- if (signal.aborted) {
22
- Promise.resolve().then(callback);
23
- }
24
- else {
25
- signal.addEventListener('abort', () => callback(), { once: true });
26
- }
27
- }
28
- };
29
-
30
1
  function isObject(o) {
31
2
  return Object.prototype.toString.call(o) === '[object Object]';
32
3
  }
@@ -128,6 +99,64 @@ class UploadcareNetworkError extends Error {
128
99
  }
129
100
  }
130
101
 
102
+ const onCancel = (signal, callback) => {
103
+ if (signal) {
104
+ if (signal.aborted) {
105
+ Promise.resolve().then(callback);
106
+ }
107
+ else {
108
+ signal.addEventListener('abort', () => callback(), { once: true });
109
+ }
110
+ }
111
+ };
112
+
113
+ class CancelError extends Error {
114
+ constructor(message = 'Request canceled') {
115
+ super(message);
116
+ this.isCancel = true;
117
+ Object.setPrototypeOf(this, CancelError.prototype);
118
+ }
119
+ }
120
+
121
+ const DEFAULT_INTERVAL = 500;
122
+ const poll = ({ check, interval = DEFAULT_INTERVAL, timeout, signal }) => new Promise((resolve, reject) => {
123
+ let tickTimeoutId;
124
+ let timeoutId;
125
+ onCancel(signal, () => {
126
+ tickTimeoutId && clearTimeout(tickTimeoutId);
127
+ reject(new CancelError('Poll cancelled'));
128
+ });
129
+ if (timeout) {
130
+ timeoutId = setTimeout(() => {
131
+ tickTimeoutId && clearTimeout(tickTimeoutId);
132
+ reject(new CancelError('Timed out'));
133
+ }, timeout);
134
+ }
135
+ const tick = () => {
136
+ try {
137
+ Promise.resolve(check(signal))
138
+ .then((result) => {
139
+ if (result) {
140
+ timeoutId && clearTimeout(timeoutId);
141
+ resolve(result);
142
+ }
143
+ else {
144
+ tickTimeoutId = setTimeout(tick, interval);
145
+ }
146
+ })
147
+ .catch((error) => {
148
+ timeoutId && clearTimeout(timeoutId);
149
+ reject(error);
150
+ });
151
+ }
152
+ catch (error) {
153
+ timeoutId && clearTimeout(timeoutId);
154
+ reject(error);
155
+ }
156
+ };
157
+ tickTimeoutId = setTimeout(tick, 0);
158
+ });
159
+
131
160
  const request = ({ method, url, data, headers = {}, signal, onProgress }) => new Promise((resolve, reject) => {
132
161
  const xhr = new XMLHttpRequest();
133
162
  const requestMethod = method?.toUpperCase() || 'GET';
@@ -151,7 +180,7 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
151
180
  onCancel(signal, () => {
152
181
  aborted = true;
153
182
  xhr.abort();
154
- reject(cancelError());
183
+ reject(new CancelError());
155
184
  });
156
185
  xhr.onload = () => {
157
186
  if (xhr.status != 200) {
@@ -358,7 +387,7 @@ const defaultSettings = {
358
387
  const defaultContentType = 'application/octet-stream';
359
388
  const defaultFilename = 'original';
360
389
 
361
- var version = '5.1.2';
390
+ var version = '6.0.0';
362
391
 
363
392
  const LIBRARY_NAME = 'UploadcareUploadClient';
364
393
  const LIBRARY_VERSION = version;
@@ -370,14 +399,32 @@ function getUserAgent(options) {
370
399
  });
371
400
  }
372
401
 
402
+ class UploadClientError extends Error {
403
+ constructor(message, code, request, response, headers) {
404
+ super();
405
+ this.name = 'UploadClientError';
406
+ this.message = message;
407
+ this.code = code;
408
+ this.request = request;
409
+ this.response = response;
410
+ this.headers = headers;
411
+ Object.setPrototypeOf(this, UploadClientError.prototype);
412
+ }
413
+ }
414
+
373
415
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
374
- const DEFAULT_THROTTLED_TIMEOUT = 15000;
416
+ const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
375
417
  const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
376
418
  function getTimeoutFromThrottledRequest(error) {
377
419
  const { headers } = error || {};
378
- return ((headers &&
379
- Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
380
- DEFAULT_THROTTLED_TIMEOUT);
420
+ if (!headers || typeof headers['retry-after'] !== 'string') {
421
+ return DEFAULT_RETRY_AFTER_TIMEOUT;
422
+ }
423
+ const seconds = parseInt(headers['retry-after'], 10);
424
+ if (!Number.isFinite(seconds)) {
425
+ return DEFAULT_RETRY_AFTER_TIMEOUT;
426
+ }
427
+ return seconds * 1000;
381
428
  }
382
429
  function retryIfFailed(fn, options) {
383
430
  const { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes } = options;
@@ -730,33 +777,6 @@ class UploadcareFile {
730
777
  }
731
778
  }
732
779
 
733
- const DEFAULT_INTERVAL = 500;
734
- const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((resolve, reject) => {
735
- let timeoutId;
736
- onCancel(signal, () => {
737
- timeoutId && clearTimeout(timeoutId);
738
- reject(cancelError('Poll cancelled'));
739
- });
740
- const tick = () => {
741
- try {
742
- Promise.resolve(check(signal))
743
- .then((result) => {
744
- if (result) {
745
- resolve(result);
746
- }
747
- else {
748
- timeoutId = setTimeout(tick, interval);
749
- }
750
- })
751
- .catch((error) => reject(error));
752
- }
753
- catch (error) {
754
- reject(error);
755
- }
756
- };
757
- timeoutId = setTimeout(tick, 0);
758
- });
759
-
760
780
  function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
761
781
  return poll({
762
782
  check: (signal) => info(file, {
@@ -1054,7 +1074,7 @@ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((
1054
1074
  };
1055
1075
  onCancel(signal, () => {
1056
1076
  destroy();
1057
- reject(cancelError('pusher cancelled'));
1077
+ reject(new CancelError('pusher cancelled'));
1058
1078
  });
1059
1079
  pusher.subscribe(token, (result) => {
1060
1080
  switch (result.status) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uploadcare/upload-client",
3
- "version": "5.1.2",
3
+ "version": "6.0.0",
4
4
  "description": "Library for work with Uploadcare Upload API",
5
5
  "type": "module",
6
6
  "module": "./dist/index.node.js",
@@ -78,7 +78,7 @@
78
78
  "koa-body": "5.0.0",
79
79
  "mock-socket": "9.0.3",
80
80
  "start-server-and-test": "1.14.0",
81
- "@uploadcare/api-client-utils": "^5.1.2",
81
+ "@uploadcare/api-client-utils": "^6.0.0",
82
82
  "chalk": "^4.1.2"
83
83
  },
84
84
  "dependencies": {