@uploadcare/upload-client 2.0.0-alpha.9 → 2.2.1-alpha.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.
- package/README.md +42 -12
- package/dist/index.browser.cjs +73 -42
- package/dist/index.browser.js +110 -86
- package/dist/index.cjs +85 -49
- package/dist/index.js +119 -95
- package/dist/types.d.ts +101 -5
- package/package.json +31 -32
- package/CHANGELOG.md +0 -243
package/dist/index.browser.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
class UploadClientError extends Error {
|
|
2
|
-
constructor(message, request, response, headers) {
|
|
2
|
+
constructor(message, code, request, response, headers) {
|
|
3
3
|
super();
|
|
4
4
|
this.name = 'UploadClientError';
|
|
5
5
|
this.message = message;
|
|
6
|
+
this.code = code;
|
|
6
7
|
this.request = request;
|
|
7
8
|
this.response = response;
|
|
8
9
|
this.headers = headers;
|
|
@@ -32,7 +33,7 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
|
|
|
32
33
|
let aborted = false;
|
|
33
34
|
xhr.open(requestMethod, url);
|
|
34
35
|
if (headers) {
|
|
35
|
-
Object.entries(headers).forEach(entry => {
|
|
36
|
+
Object.entries(headers).forEach((entry) => {
|
|
36
37
|
const [key, value] = entry;
|
|
37
38
|
typeof value !== 'undefined' &&
|
|
38
39
|
!Array.isArray(value) &&
|
|
@@ -104,18 +105,25 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
|
|
|
104
105
|
}
|
|
105
106
|
});
|
|
106
107
|
|
|
108
|
+
function identity(obj) {
|
|
109
|
+
return obj;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const transformFile = identity;
|
|
107
113
|
var getFormData = () => new FormData();
|
|
108
114
|
|
|
115
|
+
const isFileTuple = (tuple) => tuple[0] === 'file';
|
|
109
116
|
function buildFormData(body) {
|
|
110
117
|
const formData = getFormData();
|
|
111
|
-
const isTriple = (tuple) => tuple[0] === 'file';
|
|
112
118
|
for (const tuple of body) {
|
|
113
119
|
if (Array.isArray(tuple[1])) {
|
|
114
120
|
// refactor this
|
|
115
|
-
tuple[1].forEach(val => val && formData.append(tuple[0] + '[]', `${val}`));
|
|
121
|
+
tuple[1].forEach((val) => val && formData.append(tuple[0] + '[]', `${val}`));
|
|
116
122
|
}
|
|
117
|
-
else if (
|
|
118
|
-
|
|
123
|
+
else if (isFileTuple(tuple)) {
|
|
124
|
+
const name = tuple[2];
|
|
125
|
+
const file = transformFile(tuple[1]); // lgtm[js/superfluous-trailing-arguments]
|
|
126
|
+
formData.append(tuple[0], file, name);
|
|
119
127
|
}
|
|
120
128
|
else if (tuple[1] != null) {
|
|
121
129
|
formData.append(tuple[0], `${tuple[1]}`);
|
|
@@ -127,9 +135,9 @@ function buildFormData(body) {
|
|
|
127
135
|
const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
|
|
128
136
|
const createQuery = (query) => Object.entries(query)
|
|
129
137
|
.reduce((params, [key, value]) => params.concat(Array.isArray(value)
|
|
130
|
-
? value.map(value => serializePair(`${key}[]`, value))
|
|
138
|
+
? value.map((value) => serializePair(`${key}[]`, value))
|
|
131
139
|
: serializePair(key, value)), [])
|
|
132
|
-
.filter(x => !!x)
|
|
140
|
+
.filter((x) => !!x)
|
|
133
141
|
.join('&');
|
|
134
142
|
const getUrl = (base, path, query) => [
|
|
135
143
|
base,
|
|
@@ -160,7 +168,7 @@ const defaultSettings = {
|
|
|
160
168
|
const defaultContentType = 'application/octet-stream';
|
|
161
169
|
const defaultFilename = 'original';
|
|
162
170
|
|
|
163
|
-
var version = '
|
|
171
|
+
var version = '2.2.0';
|
|
164
172
|
|
|
165
173
|
/**
|
|
166
174
|
* Returns User Agent based on version and settings.
|
|
@@ -219,7 +227,7 @@ function camelizeKeys(source) {
|
|
|
219
227
|
*
|
|
220
228
|
* @param {number} ms Timeout in milliseconds.
|
|
221
229
|
*/
|
|
222
|
-
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
230
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
223
231
|
|
|
224
232
|
const defaultOptions = {
|
|
225
233
|
factor: 2,
|
|
@@ -241,7 +249,7 @@ function retrier(fn, options = defaultOptions) {
|
|
|
241
249
|
return runAttempt(fn);
|
|
242
250
|
}
|
|
243
251
|
|
|
244
|
-
const REQUEST_WAS_THROTTLED_CODE =
|
|
252
|
+
const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
|
|
245
253
|
const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
|
|
246
254
|
function getTimeoutFromThrottledRequest(error) {
|
|
247
255
|
const { headers } = error || {};
|
|
@@ -251,9 +259,8 @@ function getTimeoutFromThrottledRequest(error) {
|
|
|
251
259
|
}
|
|
252
260
|
function retryIfThrottled(fn, retryThrottledMaxTimes) {
|
|
253
261
|
return retrier(({ attempt, retry }) => fn().catch((error) => {
|
|
254
|
-
var _a;
|
|
255
262
|
if ('response' in error &&
|
|
256
|
-
(
|
|
263
|
+
(error === null || error === void 0 ? void 0 : error.code) === REQUEST_WAS_THROTTLED_CODE &&
|
|
257
264
|
attempt < retryThrottledMaxTimes) {
|
|
258
265
|
return retry(getTimeoutFromThrottledRequest(error));
|
|
259
266
|
}
|
|
@@ -292,7 +299,7 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
292
299
|
}).then(({ data, headers, request }) => {
|
|
293
300
|
const response = camelizeKeys(JSON.parse(data));
|
|
294
301
|
if ('error' in response) {
|
|
295
|
-
throw new UploadClientError(
|
|
302
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
296
303
|
}
|
|
297
304
|
else {
|
|
298
305
|
return response;
|
|
@@ -309,7 +316,6 @@ var TypeEnum;
|
|
|
309
316
|
/**
|
|
310
317
|
* Uploading files from URL.
|
|
311
318
|
*/
|
|
312
|
-
/* eslint @typescript-eslint/camelcase: [2, {allow: ["pub_key", "source_url", "check_URL_duplicates", "save_URL_duplicates"]}] */
|
|
313
319
|
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
314
320
|
return retryIfThrottled(() => request({
|
|
315
321
|
method: 'POST',
|
|
@@ -332,7 +338,7 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
|
|
|
332
338
|
}).then(({ data, headers, request }) => {
|
|
333
339
|
const response = camelizeKeys(JSON.parse(data));
|
|
334
340
|
if ('error' in response) {
|
|
335
|
-
throw new UploadClientError(
|
|
341
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
336
342
|
}
|
|
337
343
|
else {
|
|
338
344
|
return response;
|
|
@@ -374,7 +380,7 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
|
|
|
374
380
|
}).then(({ data, headers, request }) => {
|
|
375
381
|
const response = camelizeKeys(JSON.parse(data));
|
|
376
382
|
if ('error' in response && !isErrorResponse(response)) {
|
|
377
|
-
throw new UploadClientError(
|
|
383
|
+
throw new UploadClientError(response.error.content, undefined, request, response, headers);
|
|
378
384
|
}
|
|
379
385
|
else {
|
|
380
386
|
return response;
|
|
@@ -385,7 +391,6 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
|
|
|
385
391
|
/**
|
|
386
392
|
* Create files group.
|
|
387
393
|
*/
|
|
388
|
-
/* eslint @typescript-eslint/camelcase: [2, {allow: ["pub_key"]}] */
|
|
389
394
|
function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
390
395
|
return retryIfThrottled(() => request({
|
|
391
396
|
method: 'POST',
|
|
@@ -405,7 +410,7 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
|
|
|
405
410
|
}).then(({ data, headers, request }) => {
|
|
406
411
|
const response = camelizeKeys(JSON.parse(data));
|
|
407
412
|
if ('error' in response) {
|
|
408
|
-
throw new UploadClientError(
|
|
413
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
409
414
|
}
|
|
410
415
|
else {
|
|
411
416
|
return response;
|
|
@@ -416,7 +421,6 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
|
|
|
416
421
|
/**
|
|
417
422
|
* Get info about group.
|
|
418
423
|
*/
|
|
419
|
-
/* eslint @typescript-eslint/camelcase: [2, {allow: ["pub_key", "group_id"]}] */
|
|
420
424
|
function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
421
425
|
return retryIfThrottled(() => request({
|
|
422
426
|
method: 'GET',
|
|
@@ -433,7 +437,7 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
|
|
|
433
437
|
}).then(({ data, headers, request }) => {
|
|
434
438
|
const response = camelizeKeys(JSON.parse(data));
|
|
435
439
|
if ('error' in response) {
|
|
436
|
-
throw new UploadClientError(
|
|
440
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
437
441
|
}
|
|
438
442
|
else {
|
|
439
443
|
return response;
|
|
@@ -444,7 +448,6 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
|
|
|
444
448
|
/**
|
|
445
449
|
* Returns a JSON dictionary holding file info.
|
|
446
450
|
*/
|
|
447
|
-
/* eslint @typescript-eslint/camelcase: [2, {allow: ["pub_key", "file_id"]}] */
|
|
448
451
|
function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
449
452
|
return retryIfThrottled(() => request({
|
|
450
453
|
method: 'GET',
|
|
@@ -461,7 +464,7 @@ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, sour
|
|
|
461
464
|
}).then(({ data, headers, request }) => {
|
|
462
465
|
const response = camelizeKeys(JSON.parse(data));
|
|
463
466
|
if ('error' in response) {
|
|
464
|
-
throw new UploadClientError(
|
|
467
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
465
468
|
}
|
|
466
469
|
else {
|
|
467
470
|
return response;
|
|
@@ -494,11 +497,11 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
|
|
|
494
497
|
}).then(({ data, headers, request }) => {
|
|
495
498
|
const response = camelizeKeys(JSON.parse(data));
|
|
496
499
|
if ('error' in response) {
|
|
497
|
-
throw new UploadClientError(
|
|
500
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
498
501
|
}
|
|
499
502
|
else {
|
|
500
503
|
// convert to array
|
|
501
|
-
response.parts = Object.keys(response.parts).map(key => response.parts[key]);
|
|
504
|
+
response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
|
|
502
505
|
return response;
|
|
503
506
|
}
|
|
504
507
|
}), retryThrottledRequestMaxTimes);
|
|
@@ -515,7 +518,7 @@ function multipartUpload(part, url, { signal, onProgress }) {
|
|
|
515
518
|
onProgress,
|
|
516
519
|
signal
|
|
517
520
|
})
|
|
518
|
-
.then(result => {
|
|
521
|
+
.then((result) => {
|
|
519
522
|
// hack for node ¯\_(ツ)_/¯
|
|
520
523
|
if (onProgress)
|
|
521
524
|
onProgress({ value: 1 });
|
|
@@ -543,7 +546,7 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
|
|
|
543
546
|
}).then(({ data, headers, request }) => {
|
|
544
547
|
const response = camelizeKeys(JSON.parse(data));
|
|
545
548
|
if ('error' in response) {
|
|
546
|
-
throw new UploadClientError(
|
|
549
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
547
550
|
}
|
|
548
551
|
else {
|
|
549
552
|
return response;
|
|
@@ -557,6 +560,7 @@ class UploadcareFile {
|
|
|
557
560
|
this.size = null;
|
|
558
561
|
this.isStored = null;
|
|
559
562
|
this.isImage = null;
|
|
563
|
+
this.mimeType = null;
|
|
560
564
|
this.cdnUrl = null;
|
|
561
565
|
this.cdnUrlModifiers = null;
|
|
562
566
|
this.originalUrl = null;
|
|
@@ -575,6 +579,7 @@ class UploadcareFile {
|
|
|
575
579
|
this.size = fileInfo.size;
|
|
576
580
|
this.isStored = fileInfo.isStored;
|
|
577
581
|
this.isImage = fileInfo.isImage;
|
|
582
|
+
this.mimeType = fileInfo.mimeType;
|
|
578
583
|
this.cdnUrl = cdnUrl;
|
|
579
584
|
this.cdnUrlModifiers = cdnUrlModifiers;
|
|
580
585
|
this.originalUrl = originalUrl;
|
|
@@ -594,7 +599,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
594
599
|
const tick = () => {
|
|
595
600
|
try {
|
|
596
601
|
Promise.resolve(check(signal))
|
|
597
|
-
.then(result => {
|
|
602
|
+
.then((result) => {
|
|
598
603
|
if (result) {
|
|
599
604
|
resolve(result);
|
|
600
605
|
}
|
|
@@ -602,7 +607,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
602
607
|
timeoutId = setTimeout(tick, interval);
|
|
603
608
|
}
|
|
604
609
|
})
|
|
605
|
-
.catch(error => reject(error));
|
|
610
|
+
.catch((error) => reject(error));
|
|
606
611
|
}
|
|
607
612
|
catch (error) {
|
|
608
613
|
reject(error);
|
|
@@ -613,7 +618,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
613
618
|
|
|
614
619
|
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
|
|
615
620
|
return poll({
|
|
616
|
-
check: signal => info(file, {
|
|
621
|
+
check: (signal) => info(file, {
|
|
617
622
|
publicKey,
|
|
618
623
|
baseURL,
|
|
619
624
|
signal,
|
|
@@ -621,7 +626,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
|
|
|
621
626
|
integration,
|
|
622
627
|
userAgent,
|
|
623
628
|
retryThrottledRequestMaxTimes
|
|
624
|
-
}).then(response => {
|
|
629
|
+
}).then((response) => {
|
|
625
630
|
if (response.isReady) {
|
|
626
631
|
return response;
|
|
627
632
|
}
|
|
@@ -660,7 +665,7 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
|
|
|
660
665
|
signal
|
|
661
666
|
});
|
|
662
667
|
})
|
|
663
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
668
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
664
669
|
};
|
|
665
670
|
|
|
666
671
|
/*globals self, window */
|
|
@@ -680,21 +685,21 @@ const race = (fns, { signal } = {}) => {
|
|
|
680
685
|
controllers.forEach((controller, index) => index !== i && controller.abort());
|
|
681
686
|
};
|
|
682
687
|
onCancel(signal, () => {
|
|
683
|
-
controllers.forEach(controller => controller.abort());
|
|
688
|
+
controllers.forEach((controller) => controller.abort());
|
|
684
689
|
});
|
|
685
690
|
return Promise.all(fns.map((fn, i) => {
|
|
686
691
|
const stopRace = createStopRaceCallback(i);
|
|
687
692
|
return Promise.resolve()
|
|
688
693
|
.then(() => fn({ stopRace, signal: controllers[i].signal }))
|
|
689
|
-
.then(result => {
|
|
694
|
+
.then((result) => {
|
|
690
695
|
stopRace();
|
|
691
696
|
return result;
|
|
692
697
|
})
|
|
693
|
-
.catch(error => {
|
|
698
|
+
.catch((error) => {
|
|
694
699
|
lastError = error;
|
|
695
700
|
return null;
|
|
696
701
|
});
|
|
697
|
-
})).then(results => {
|
|
702
|
+
})).then((results) => {
|
|
698
703
|
if (winnerIndex === null) {
|
|
699
704
|
throw lastError;
|
|
700
705
|
}
|
|
@@ -712,7 +717,7 @@ class Events {
|
|
|
712
717
|
}
|
|
713
718
|
emit(event, data) {
|
|
714
719
|
var _a;
|
|
715
|
-
(_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach(fn => fn(data));
|
|
720
|
+
(_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(data));
|
|
716
721
|
}
|
|
717
722
|
on(event, callback) {
|
|
718
723
|
this.events[event] = this.events[event] || [];
|
|
@@ -720,7 +725,7 @@ class Events {
|
|
|
720
725
|
}
|
|
721
726
|
off(event, callback) {
|
|
722
727
|
if (callback) {
|
|
723
|
-
this.events[event] = this.events[event].filter(fn => fn !== callback);
|
|
728
|
+
this.events[event] = this.events[event].filter((fn) => fn !== callback);
|
|
724
729
|
}
|
|
725
730
|
else {
|
|
726
731
|
this.events[event] = [];
|
|
@@ -753,16 +758,16 @@ class Pusher {
|
|
|
753
758
|
if (!this.isConnected && !this.ws) {
|
|
754
759
|
const pusherUrl = `wss://ws.pusherapp.com/app/${this.key}?protocol=5&client=js&version=1.12.2`;
|
|
755
760
|
this.ws = new WebSocket(pusherUrl);
|
|
756
|
-
this.ws.addEventListener('error', error => {
|
|
761
|
+
this.ws.addEventListener('error', (error) => {
|
|
757
762
|
this.emmitter.emit('error', new Error(error.message));
|
|
758
763
|
});
|
|
759
764
|
this.emmitter.on('connected', () => {
|
|
760
765
|
this.isConnected = true;
|
|
761
|
-
this.queue.forEach(message => this.send(message.event, message.data));
|
|
766
|
+
this.queue.forEach((message) => this.send(message.event, message.data));
|
|
762
767
|
this.queue = [];
|
|
763
768
|
});
|
|
764
|
-
this.ws.addEventListener('message', e => {
|
|
765
|
-
const data = JSON.parse(e.data);
|
|
769
|
+
this.ws.addEventListener('message', (e) => {
|
|
770
|
+
const data = JSON.parse(e.data.toString());
|
|
766
771
|
switch (data.event) {
|
|
767
772
|
case 'pusher:connection_established': {
|
|
768
773
|
this.emmitter.emit('connected', undefined);
|
|
@@ -830,7 +835,7 @@ class Pusher {
|
|
|
830
835
|
this.send(message.event, message.data);
|
|
831
836
|
}
|
|
832
837
|
else {
|
|
833
|
-
this.queue = this.queue.filter(msg => msg.data.channel !== channel);
|
|
838
|
+
this.queue = this.queue.filter((msg) => msg.data.channel !== channel);
|
|
834
839
|
}
|
|
835
840
|
if (this.subscribers === 0) {
|
|
836
841
|
this.disconnect();
|
|
@@ -856,17 +861,17 @@ const preconnect = (key) => {
|
|
|
856
861
|
|
|
857
862
|
function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
|
|
858
863
|
return poll({
|
|
859
|
-
check: signal => fromUrlStatus(token, {
|
|
864
|
+
check: (signal) => fromUrlStatus(token, {
|
|
860
865
|
publicKey,
|
|
861
866
|
baseURL,
|
|
862
867
|
integration,
|
|
863
868
|
userAgent,
|
|
864
869
|
retryThrottledRequestMaxTimes,
|
|
865
870
|
signal
|
|
866
|
-
}).then(response => {
|
|
871
|
+
}).then((response) => {
|
|
867
872
|
switch (response.status) {
|
|
868
873
|
case Status.Error: {
|
|
869
|
-
return new UploadClientError(response.error);
|
|
874
|
+
return new UploadClientError(response.error, response.errorCode);
|
|
870
875
|
}
|
|
871
876
|
case Status.Waiting: {
|
|
872
877
|
return false;
|
|
@@ -892,7 +897,7 @@ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retry
|
|
|
892
897
|
signal
|
|
893
898
|
});
|
|
894
899
|
}
|
|
895
|
-
const pushStrategy = ({ token, pusherKey, signal,
|
|
900
|
+
const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((resolve, reject) => {
|
|
896
901
|
const pusher = getPusher(pusherKey);
|
|
897
902
|
const unsubErrorHandler = pusher.onError(reject);
|
|
898
903
|
const destroy = () => {
|
|
@@ -901,10 +906,9 @@ const pushStrategy = ({ token, pusherKey, signal, stopRace, onProgress }) => new
|
|
|
901
906
|
};
|
|
902
907
|
onCancel(signal, () => {
|
|
903
908
|
destroy();
|
|
904
|
-
reject(cancelError('
|
|
909
|
+
reject(cancelError('pusher cancelled'));
|
|
905
910
|
});
|
|
906
|
-
pusher.subscribe(token, result => {
|
|
907
|
-
stopRace();
|
|
911
|
+
pusher.subscribe(token, (result) => {
|
|
908
912
|
switch (result.status) {
|
|
909
913
|
case Status.Progress: {
|
|
910
914
|
if (onProgress) {
|
|
@@ -921,7 +925,7 @@ const pushStrategy = ({ token, pusherKey, signal, stopRace, onProgress }) => new
|
|
|
921
925
|
}
|
|
922
926
|
case Status.Error: {
|
|
923
927
|
destroy();
|
|
924
|
-
reject(new UploadClientError(result.msg));
|
|
928
|
+
reject(new UploadClientError(result.msg, result.error_code));
|
|
925
929
|
}
|
|
926
930
|
}
|
|
927
931
|
});
|
|
@@ -942,7 +946,12 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
942
946
|
userAgent,
|
|
943
947
|
retryThrottledRequestMaxTimes
|
|
944
948
|
}))
|
|
945
|
-
.
|
|
949
|
+
.catch((error) => {
|
|
950
|
+
const pusher = getPusher(pusherKey);
|
|
951
|
+
pusher === null || pusher === void 0 ? void 0 : pusher.disconnect();
|
|
952
|
+
return Promise.reject(error);
|
|
953
|
+
})
|
|
954
|
+
.then((urlResponse) => {
|
|
946
955
|
if (urlResponse.type === TypeEnum.FileInfo) {
|
|
947
956
|
return urlResponse;
|
|
948
957
|
}
|
|
@@ -958,22 +967,21 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
958
967
|
onProgress,
|
|
959
968
|
signal
|
|
960
969
|
}),
|
|
961
|
-
({
|
|
970
|
+
({ signal }) => pushStrategy({
|
|
962
971
|
token: urlResponse.token,
|
|
963
972
|
pusherKey,
|
|
964
|
-
stopRace,
|
|
965
973
|
signal,
|
|
966
974
|
onProgress
|
|
967
975
|
})
|
|
968
976
|
], { signal });
|
|
969
977
|
}
|
|
970
978
|
})
|
|
971
|
-
.then(result => {
|
|
979
|
+
.then((result) => {
|
|
972
980
|
if (result instanceof UploadClientError)
|
|
973
981
|
throw result;
|
|
974
982
|
return result;
|
|
975
983
|
})
|
|
976
|
-
.then(result => isReadyPoll({
|
|
984
|
+
.then((result) => isReadyPoll({
|
|
977
985
|
file: result.uuid,
|
|
978
986
|
publicKey,
|
|
979
987
|
baseURL,
|
|
@@ -983,7 +991,7 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
983
991
|
onProgress,
|
|
984
992
|
signal
|
|
985
993
|
}))
|
|
986
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
994
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
987
995
|
|
|
988
996
|
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
989
997
|
return info(uuid, {
|
|
@@ -995,8 +1003,8 @@ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProg
|
|
|
995
1003
|
userAgent,
|
|
996
1004
|
retryThrottledRequestMaxTimes
|
|
997
1005
|
})
|
|
998
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
999
|
-
.then(result => {
|
|
1006
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
1007
|
+
.then((result) => {
|
|
1000
1008
|
// hack for node ¯\_(ツ)_/¯
|
|
1001
1009
|
if (onProgress)
|
|
1002
1010
|
onProgress({ value: 1 });
|
|
@@ -1045,6 +1053,16 @@ const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartM
|
|
|
1045
1053
|
return fileSize >= multipartMinFileSize;
|
|
1046
1054
|
};
|
|
1047
1055
|
|
|
1056
|
+
const sliceChunk = (file, index, fileSize, chunkSize) => {
|
|
1057
|
+
const start = chunkSize * index;
|
|
1058
|
+
const end = Math.min(start + chunkSize, fileSize);
|
|
1059
|
+
return file.slice(start, end);
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
function prepareChunks(file, fileSize, chunkSize) {
|
|
1063
|
+
return (index) => sliceChunk(file, index, fileSize, chunkSize);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1048
1066
|
const runWithConcurrency = (concurrency, tasks) => {
|
|
1049
1067
|
return new Promise((resolve, reject) => {
|
|
1050
1068
|
const results = [];
|
|
@@ -1068,7 +1086,7 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1068
1086
|
resolve(results);
|
|
1069
1087
|
}
|
|
1070
1088
|
})
|
|
1071
|
-
.catch(error => {
|
|
1089
|
+
.catch((error) => {
|
|
1072
1090
|
rejected = true;
|
|
1073
1091
|
reject(error);
|
|
1074
1092
|
});
|
|
@@ -1080,15 +1098,12 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1080
1098
|
});
|
|
1081
1099
|
};
|
|
1082
1100
|
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1085
|
-
const end = Math.min(start + chunkSize, fileSize);
|
|
1086
|
-
return file.slice(start, end);
|
|
1087
|
-
};
|
|
1088
|
-
const uploadPartWithRetry = (chunk, url, { onProgress, signal, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
|
|
1101
|
+
const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
|
|
1102
|
+
publicKey,
|
|
1089
1103
|
onProgress,
|
|
1090
|
-
signal
|
|
1091
|
-
|
|
1104
|
+
signal,
|
|
1105
|
+
integration
|
|
1106
|
+
}).catch((error) => {
|
|
1092
1107
|
if (attempt < multipartMaxAttempts) {
|
|
1093
1108
|
return retry();
|
|
1094
1109
|
}
|
|
@@ -1123,14 +1138,19 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1123
1138
|
userAgent,
|
|
1124
1139
|
retryThrottledRequestMaxTimes
|
|
1125
1140
|
})
|
|
1126
|
-
.then(({ uuid, parts }) =>
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1141
|
+
.then(({ uuid, parts }) => {
|
|
1142
|
+
const getChunk = prepareChunks(file, size, multipartChunkSize);
|
|
1143
|
+
return Promise.all([
|
|
1144
|
+
uuid,
|
|
1145
|
+
runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
|
|
1146
|
+
publicKey,
|
|
1147
|
+
onProgress: createProgressHandler(parts.length, index),
|
|
1148
|
+
signal,
|
|
1149
|
+
integration,
|
|
1150
|
+
multipartMaxAttempts
|
|
1151
|
+
})))
|
|
1152
|
+
]);
|
|
1153
|
+
})
|
|
1134
1154
|
.then(([uuid]) => multipartComplete(uuid, {
|
|
1135
1155
|
publicKey,
|
|
1136
1156
|
baseURL,
|
|
@@ -1139,7 +1159,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1139
1159
|
userAgent,
|
|
1140
1160
|
retryThrottledRequestMaxTimes
|
|
1141
1161
|
}))
|
|
1142
|
-
.then(fileInfo => {
|
|
1162
|
+
.then((fileInfo) => {
|
|
1143
1163
|
if (fileInfo.isReady) {
|
|
1144
1164
|
return fileInfo;
|
|
1145
1165
|
}
|
|
@@ -1157,13 +1177,13 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1157
1177
|
});
|
|
1158
1178
|
}
|
|
1159
1179
|
})
|
|
1160
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1180
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1161
1181
|
};
|
|
1162
1182
|
|
|
1163
1183
|
/**
|
|
1164
1184
|
* Uploads file from provided data.
|
|
1165
1185
|
*/
|
|
1166
|
-
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize
|
|
1186
|
+
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize, multipartMaxAttempts, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey }) {
|
|
1167
1187
|
if (isFileData(data)) {
|
|
1168
1188
|
const fileSize = getFileSize(data);
|
|
1169
1189
|
if (isMultipart(fileSize)) {
|
|
@@ -1171,6 +1191,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1171
1191
|
publicKey,
|
|
1172
1192
|
contentType,
|
|
1173
1193
|
multipartChunkSize,
|
|
1194
|
+
multipartMaxAttempts,
|
|
1174
1195
|
fileName,
|
|
1175
1196
|
baseURL,
|
|
1176
1197
|
secureSignature,
|
|
@@ -1181,6 +1202,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1181
1202
|
source,
|
|
1182
1203
|
integration,
|
|
1183
1204
|
userAgent,
|
|
1205
|
+
maxConcurrentRequests,
|
|
1184
1206
|
retryThrottledRequestMaxTimes,
|
|
1185
1207
|
baseCDN
|
|
1186
1208
|
});
|
|
@@ -1206,6 +1228,9 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1206
1228
|
publicKey,
|
|
1207
1229
|
fileName,
|
|
1208
1230
|
baseURL,
|
|
1231
|
+
baseCDN,
|
|
1232
|
+
checkForUrlDuplicates,
|
|
1233
|
+
saveUrlForRecurrentUploads,
|
|
1209
1234
|
secureSignature,
|
|
1210
1235
|
secureExpire,
|
|
1211
1236
|
store,
|
|
@@ -1215,7 +1240,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1215
1240
|
integration,
|
|
1216
1241
|
userAgent,
|
|
1217
1242
|
retryThrottledRequestMaxTimes,
|
|
1218
|
-
|
|
1243
|
+
pusherKey
|
|
1219
1244
|
});
|
|
1220
1245
|
}
|
|
1221
1246
|
if (isUuid(data)) {
|
|
@@ -1242,8 +1267,7 @@ class UploadcareGroup {
|
|
|
1242
1267
|
this.filesCount = groupInfo.filesCount;
|
|
1243
1268
|
this.totalSize = Object.values(groupInfo.files).reduce((acc, file) => acc + file.size, 0);
|
|
1244
1269
|
this.isStored = !!groupInfo.datetimeStored;
|
|
1245
|
-
this.isImage = !!Object.values(groupInfo.files).filter(file => file.isImage)
|
|
1246
|
-
.length;
|
|
1270
|
+
this.isImage = !!Object.values(groupInfo.files).filter((file) => file.isImage).length;
|
|
1247
1271
|
this.cdnUrl = groupInfo.cdnUrl;
|
|
1248
1272
|
this.files = files;
|
|
1249
1273
|
this.createdAt = groupInfo.datetimeCreated;
|
|
@@ -1319,8 +1343,8 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1319
1343
|
contentType,
|
|
1320
1344
|
multipartChunkSize,
|
|
1321
1345
|
baseCDN
|
|
1322
|
-
}))).then(files => {
|
|
1323
|
-
const uuids = files.map(file => file.uuid);
|
|
1346
|
+
}))).then((files) => {
|
|
1347
|
+
const uuids = files.map((file) => file.uuid);
|
|
1324
1348
|
const addDefaultEffects = (file) => {
|
|
1325
1349
|
const cdnUrlModifiers = defaultEffects ? `-/${defaultEffects}` : null;
|
|
1326
1350
|
const cdnUrl = `${file.urlBase}${cdnUrlModifiers || ''}`;
|
|
@@ -1339,7 +1363,7 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1339
1363
|
integration,
|
|
1340
1364
|
userAgent,
|
|
1341
1365
|
retryThrottledRequestMaxTimes
|
|
1342
|
-
}).then(groupInfo => new UploadcareGroup(groupInfo, filesInGroup));
|
|
1366
|
+
}).then((groupInfo) => new UploadcareGroup(groupInfo, filesInGroup));
|
|
1343
1367
|
});
|
|
1344
1368
|
}
|
|
1345
1369
|
|
|
@@ -1403,4 +1427,4 @@ class UploadClient {
|
|
|
1403
1427
|
}
|
|
1404
1428
|
}
|
|
1405
1429
|
|
|
1406
|
-
export { AbortController, UploadClient, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFile, uploadFileGroup };
|
|
1430
|
+
export { AbortController, UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFromObject as uploadBase, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
|