@uploadcare/upload-client 2.2.1-alpha.0 → 3.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.
- package/README.md +21 -3
- package/dist/index.browser.cjs +222 -115
- package/dist/index.browser.js +219 -109
- package/dist/index.cjs +217 -115
- package/dist/index.js +214 -109
- package/dist/types.d.ts +43 -13
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -48,7 +48,10 @@ class ProgressEmitter extends Transform {
|
|
|
48
48
|
}
|
|
49
49
|
_transform(chunk, encoding, callback) {
|
|
50
50
|
this._position += chunk.length;
|
|
51
|
-
this._onprogress({
|
|
51
|
+
this._onprogress({
|
|
52
|
+
isComputable: true,
|
|
53
|
+
value: this._position / this.size
|
|
54
|
+
});
|
|
52
55
|
callback(null, chunk);
|
|
53
56
|
}
|
|
54
57
|
}
|
|
@@ -144,31 +147,97 @@ function identity(obj) {
|
|
|
144
147
|
const transformFile = identity;
|
|
145
148
|
var getFormData = () => new NodeFormData();
|
|
146
149
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
150
|
+
/**
|
|
151
|
+
* FileData type guard.
|
|
152
|
+
*/
|
|
153
|
+
const isFileData = (data) => {
|
|
154
|
+
return (data !== undefined &&
|
|
155
|
+
((typeof Blob !== 'undefined' && data instanceof Blob) ||
|
|
156
|
+
(typeof File !== 'undefined' && data instanceof File) ||
|
|
157
|
+
(typeof Buffer !== 'undefined' && data instanceof Buffer)));
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Uuid type guard.
|
|
161
|
+
*/
|
|
162
|
+
const isUuid = (data) => {
|
|
163
|
+
const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
|
|
164
|
+
const regExp = new RegExp(UUID_REGEX);
|
|
165
|
+
return !isFileData(data) && regExp.test(data);
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Url type guard.
|
|
169
|
+
*
|
|
170
|
+
* @param {NodeFile | BrowserFile | Url | Uuid} data
|
|
171
|
+
*/
|
|
172
|
+
const isUrl = (data) => {
|
|
173
|
+
const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
|
|
174
|
+
const regExp = new RegExp(URL_REGEX);
|
|
175
|
+
return !isFileData(data) && regExp.test(data);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const isSimpleValue = (value) => {
|
|
179
|
+
return (typeof value === 'string' ||
|
|
180
|
+
typeof value === 'number' ||
|
|
181
|
+
typeof value === 'undefined');
|
|
182
|
+
};
|
|
183
|
+
const isObjectValue = (value) => {
|
|
184
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
185
|
+
};
|
|
186
|
+
const isFileValue = (value) => !!value &&
|
|
187
|
+
typeof value === 'object' &&
|
|
188
|
+
'data' in value &&
|
|
189
|
+
isFileData(value.data);
|
|
190
|
+
function collectParams(params, inputKey, inputValue) {
|
|
191
|
+
if (isFileValue(inputValue)) {
|
|
192
|
+
const name = inputValue.name;
|
|
193
|
+
const file = transformFile(inputValue.data); // lgtm [js/superfluous-trailing-arguments]
|
|
194
|
+
params.push(name ? [inputKey, file, name] : [inputKey, file]);
|
|
195
|
+
}
|
|
196
|
+
else if (isObjectValue(inputValue)) {
|
|
197
|
+
for (const [key, value] of Object.entries(inputValue)) {
|
|
198
|
+
if (typeof value !== 'undefined') {
|
|
199
|
+
params.push([`${inputKey}[${key}]`, String(value)]);
|
|
200
|
+
}
|
|
162
201
|
}
|
|
163
202
|
}
|
|
203
|
+
else if (isSimpleValue(inputValue) && inputValue) {
|
|
204
|
+
params.push([inputKey, inputValue.toString()]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function getFormDataParams(options) {
|
|
208
|
+
const params = [];
|
|
209
|
+
for (const [key, value] of Object.entries(options)) {
|
|
210
|
+
collectParams(params, key, value);
|
|
211
|
+
}
|
|
212
|
+
return params;
|
|
213
|
+
}
|
|
214
|
+
function buildFormData(options) {
|
|
215
|
+
const formData = getFormData();
|
|
216
|
+
const params = getFormDataParams(options);
|
|
217
|
+
for (const param of params) {
|
|
218
|
+
formData.append(...param);
|
|
219
|
+
}
|
|
164
220
|
return formData;
|
|
165
221
|
}
|
|
166
222
|
|
|
167
223
|
const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
|
|
224
|
+
// TODO: generalize value transforming logic and use it here and inside `buildFormData`
|
|
168
225
|
const createQuery = (query) => Object.entries(query)
|
|
169
|
-
.reduce((params, [key, value]) =>
|
|
170
|
-
|
|
171
|
-
|
|
226
|
+
.reduce((params, [key, value]) => {
|
|
227
|
+
let param;
|
|
228
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
229
|
+
param = Object.entries(value)
|
|
230
|
+
.filter((entry) => typeof entry[1] !== 'undefined')
|
|
231
|
+
.map((entry) => serializePair(`${key}[${entry[0]}]`, String(entry[1])));
|
|
232
|
+
}
|
|
233
|
+
else if (Array.isArray(value)) {
|
|
234
|
+
param = value.map((val) => serializePair(`${key}[]`, val));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
param = serializePair(key, value);
|
|
238
|
+
}
|
|
239
|
+
return params.concat(param);
|
|
240
|
+
}, [])
|
|
172
241
|
.filter((x) => !!x)
|
|
173
242
|
.join('&');
|
|
174
243
|
const getUrl = (base, path, query) => [
|
|
@@ -200,7 +269,7 @@ const defaultSettings = {
|
|
|
200
269
|
const defaultContentType = 'application/octet-stream';
|
|
201
270
|
const defaultFilename = 'original';
|
|
202
271
|
|
|
203
|
-
var version = '
|
|
272
|
+
var version = '3.1.0';
|
|
204
273
|
|
|
205
274
|
/**
|
|
206
275
|
* Returns User Agent based on version and settings.
|
|
@@ -300,11 +369,15 @@ function retryIfThrottled(fn, retryThrottledMaxTimes) {
|
|
|
300
369
|
}));
|
|
301
370
|
}
|
|
302
371
|
|
|
372
|
+
function getStoreValue(store) {
|
|
373
|
+
return typeof store === 'undefined' ? 'auto' : store ? '1' : '0';
|
|
374
|
+
}
|
|
375
|
+
|
|
303
376
|
/**
|
|
304
377
|
* Performs file uploading request to Uploadcare Upload API.
|
|
305
378
|
* Can be canceled and has progress.
|
|
306
379
|
*/
|
|
307
|
-
function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
380
|
+
function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
|
|
308
381
|
return retryIfThrottled(() => {
|
|
309
382
|
var _a;
|
|
310
383
|
return request({
|
|
@@ -315,17 +388,18 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
315
388
|
headers: {
|
|
316
389
|
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
317
390
|
},
|
|
318
|
-
data: buildFormData(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
391
|
+
data: buildFormData({
|
|
392
|
+
file: {
|
|
393
|
+
data: file,
|
|
394
|
+
name: (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename
|
|
395
|
+
},
|
|
396
|
+
UPLOADCARE_PUB_KEY: publicKey,
|
|
397
|
+
UPLOADCARE_STORE: getStoreValue(store),
|
|
398
|
+
signature: secureSignature,
|
|
399
|
+
expire: secureExpire,
|
|
400
|
+
source: source,
|
|
401
|
+
metadata
|
|
402
|
+
}),
|
|
329
403
|
signal,
|
|
330
404
|
onProgress
|
|
331
405
|
}).then(({ data, headers, request }) => {
|
|
@@ -348,7 +422,7 @@ var TypeEnum;
|
|
|
348
422
|
/**
|
|
349
423
|
* Uploading files from URL.
|
|
350
424
|
*/
|
|
351
|
-
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
425
|
+
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
|
|
352
426
|
return retryIfThrottled(() => request({
|
|
353
427
|
method: 'POST',
|
|
354
428
|
headers: {
|
|
@@ -358,13 +432,14 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
|
|
|
358
432
|
jsonerrors: 1,
|
|
359
433
|
pub_key: publicKey,
|
|
360
434
|
source_url: sourceUrl,
|
|
361
|
-
store:
|
|
435
|
+
store: getStoreValue(store),
|
|
362
436
|
filename: fileName,
|
|
363
437
|
check_URL_duplicates: checkForUrlDuplicates ? 1 : undefined,
|
|
364
438
|
save_URL_duplicates: saveUrlForRecurrentUploads ? 1 : undefined,
|
|
365
439
|
signature: secureSignature,
|
|
366
440
|
expire: secureExpire,
|
|
367
|
-
source: source
|
|
441
|
+
source: source,
|
|
442
|
+
metadata
|
|
368
443
|
}),
|
|
369
444
|
signal
|
|
370
445
|
}).then(({ data, headers, request }) => {
|
|
@@ -507,24 +582,25 @@ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, sour
|
|
|
507
582
|
/**
|
|
508
583
|
* Start multipart uploading.
|
|
509
584
|
*/
|
|
510
|
-
function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
585
|
+
function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
|
|
511
586
|
return retryIfThrottled(() => request({
|
|
512
587
|
method: 'POST',
|
|
513
588
|
url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
|
|
514
589
|
headers: {
|
|
515
590
|
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
516
591
|
},
|
|
517
|
-
data: buildFormData(
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
592
|
+
data: buildFormData({
|
|
593
|
+
filename: fileName !== null && fileName !== void 0 ? fileName : defaultFilename,
|
|
594
|
+
size: size,
|
|
595
|
+
content_type: contentType !== null && contentType !== void 0 ? contentType : defaultContentType,
|
|
596
|
+
part_size: multipartChunkSize,
|
|
597
|
+
UPLOADCARE_STORE: getStoreValue(store),
|
|
598
|
+
UPLOADCARE_PUB_KEY: publicKey,
|
|
599
|
+
signature: secureSignature,
|
|
600
|
+
expire: secureExpire,
|
|
601
|
+
source: source,
|
|
602
|
+
metadata
|
|
603
|
+
}),
|
|
528
604
|
signal
|
|
529
605
|
}).then(({ data, headers, request }) => {
|
|
530
606
|
const response = camelizeKeys(JSON.parse(data));
|
|
@@ -547,13 +623,17 @@ function multipartUpload(part, url, { signal, onProgress }) {
|
|
|
547
623
|
method: 'PUT',
|
|
548
624
|
url,
|
|
549
625
|
data: part,
|
|
550
|
-
|
|
626
|
+
// Upload request can't be non-computable because we always know exact size
|
|
627
|
+
onProgress: onProgress,
|
|
551
628
|
signal
|
|
552
629
|
})
|
|
553
630
|
.then((result) => {
|
|
554
631
|
// hack for node ¯\_(ツ)_/¯
|
|
555
632
|
if (onProgress)
|
|
556
|
-
onProgress({
|
|
633
|
+
onProgress({
|
|
634
|
+
isComputable: true,
|
|
635
|
+
value: 1
|
|
636
|
+
});
|
|
557
637
|
return result;
|
|
558
638
|
})
|
|
559
639
|
.then(({ status }) => ({ code: status }));
|
|
@@ -569,11 +649,11 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
|
|
|
569
649
|
headers: {
|
|
570
650
|
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
571
651
|
},
|
|
572
|
-
data: buildFormData(
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
652
|
+
data: buildFormData({
|
|
653
|
+
uuid: uuid,
|
|
654
|
+
UPLOADCARE_PUB_KEY: publicKey,
|
|
655
|
+
source: source
|
|
656
|
+
}),
|
|
577
657
|
signal
|
|
578
658
|
}).then(({ data, headers, request }) => {
|
|
579
659
|
const response = camelizeKeys(JSON.parse(data));
|
|
@@ -599,6 +679,8 @@ class UploadcareFile {
|
|
|
599
679
|
this.originalFilename = null;
|
|
600
680
|
this.imageInfo = null;
|
|
601
681
|
this.videoInfo = null;
|
|
682
|
+
this.contentInfo = null;
|
|
683
|
+
this.metadata = null;
|
|
602
684
|
const { uuid, s3Bucket } = fileInfo;
|
|
603
685
|
const urlBase = s3Bucket
|
|
604
686
|
? `https://${s3Bucket}.s3.amazonaws.com/${uuid}/${fileInfo.filename}`
|
|
@@ -618,6 +700,8 @@ class UploadcareFile {
|
|
|
618
700
|
this.originalFilename = fileInfo.originalFilename;
|
|
619
701
|
this.imageInfo = camelizeKeys(fileInfo.imageInfo);
|
|
620
702
|
this.videoInfo = camelizeKeys(fileInfo.videoInfo);
|
|
703
|
+
this.contentInfo = camelizeKeys(fileInfo.contentInfo);
|
|
704
|
+
this.metadata = fileInfo.metadata || null;
|
|
621
705
|
}
|
|
622
706
|
}
|
|
623
707
|
|
|
@@ -662,14 +746,14 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
|
|
|
662
746
|
if (response.isReady) {
|
|
663
747
|
return response;
|
|
664
748
|
}
|
|
665
|
-
onProgress && onProgress({ value: 1 });
|
|
749
|
+
onProgress && onProgress({ isComputable: true, value: 1 });
|
|
666
750
|
return false;
|
|
667
751
|
}),
|
|
668
752
|
signal
|
|
669
753
|
});
|
|
670
754
|
}
|
|
671
755
|
|
|
672
|
-
const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
756
|
+
const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN, metadata }) => {
|
|
673
757
|
return base(file, {
|
|
674
758
|
publicKey,
|
|
675
759
|
fileName,
|
|
@@ -682,7 +766,8 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
|
|
|
682
766
|
source,
|
|
683
767
|
integration,
|
|
684
768
|
userAgent,
|
|
685
|
-
retryThrottledRequestMaxTimes
|
|
769
|
+
retryThrottledRequestMaxTimes,
|
|
770
|
+
metadata
|
|
686
771
|
})
|
|
687
772
|
.then(({ file }) => {
|
|
688
773
|
return isReadyPoll({
|
|
@@ -902,13 +987,25 @@ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retry
|
|
|
902
987
|
return new UploadClientError(`Token "${token}" was not found.`);
|
|
903
988
|
}
|
|
904
989
|
case Status.Progress: {
|
|
905
|
-
if (onProgress)
|
|
906
|
-
|
|
990
|
+
if (onProgress) {
|
|
991
|
+
if (response.total === 'unknown') {
|
|
992
|
+
onProgress({ isComputable: false });
|
|
993
|
+
}
|
|
994
|
+
else {
|
|
995
|
+
onProgress({
|
|
996
|
+
isComputable: true,
|
|
997
|
+
value: response.done / response.total
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
907
1001
|
return false;
|
|
908
1002
|
}
|
|
909
1003
|
case Status.Success: {
|
|
910
1004
|
if (onProgress)
|
|
911
|
-
onProgress({
|
|
1005
|
+
onProgress({
|
|
1006
|
+
isComputable: true,
|
|
1007
|
+
value: response.done / response.total
|
|
1008
|
+
});
|
|
912
1009
|
return response;
|
|
913
1010
|
}
|
|
914
1011
|
default: {
|
|
@@ -934,14 +1031,25 @@ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((
|
|
|
934
1031
|
switch (result.status) {
|
|
935
1032
|
case Status.Progress: {
|
|
936
1033
|
if (onProgress) {
|
|
937
|
-
|
|
1034
|
+
if (result.total === 'unknown') {
|
|
1035
|
+
onProgress({ isComputable: false });
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
onProgress({
|
|
1039
|
+
isComputable: true,
|
|
1040
|
+
value: result.done / result.total
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
938
1043
|
}
|
|
939
1044
|
break;
|
|
940
1045
|
}
|
|
941
1046
|
case Status.Success: {
|
|
942
1047
|
destroy();
|
|
943
1048
|
if (onProgress)
|
|
944
|
-
onProgress({
|
|
1049
|
+
onProgress({
|
|
1050
|
+
isComputable: true,
|
|
1051
|
+
value: result.done / result.total
|
|
1052
|
+
});
|
|
945
1053
|
resolve(result);
|
|
946
1054
|
break;
|
|
947
1055
|
}
|
|
@@ -952,7 +1060,7 @@ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((
|
|
|
952
1060
|
}
|
|
953
1061
|
});
|
|
954
1062
|
});
|
|
955
|
-
const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey }) => Promise.resolve(preconnect(pusherKey))
|
|
1063
|
+
const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey, metadata }) => Promise.resolve(preconnect(pusherKey))
|
|
956
1064
|
.then(() => fromUrl(sourceUrl, {
|
|
957
1065
|
publicKey,
|
|
958
1066
|
fileName,
|
|
@@ -966,7 +1074,8 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
966
1074
|
source,
|
|
967
1075
|
integration,
|
|
968
1076
|
userAgent,
|
|
969
|
-
retryThrottledRequestMaxTimes
|
|
1077
|
+
retryThrottledRequestMaxTimes,
|
|
1078
|
+
metadata
|
|
970
1079
|
}))
|
|
971
1080
|
.catch((error) => {
|
|
972
1081
|
const pusher = getPusher(pusherKey);
|
|
@@ -1029,39 +1138,14 @@ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProg
|
|
|
1029
1138
|
.then((result) => {
|
|
1030
1139
|
// hack for node ¯\_(ツ)_/¯
|
|
1031
1140
|
if (onProgress)
|
|
1032
|
-
onProgress({
|
|
1141
|
+
onProgress({
|
|
1142
|
+
isComputable: true,
|
|
1143
|
+
value: 1
|
|
1144
|
+
});
|
|
1033
1145
|
return result;
|
|
1034
1146
|
});
|
|
1035
1147
|
};
|
|
1036
1148
|
|
|
1037
|
-
/**
|
|
1038
|
-
* FileData type guard.
|
|
1039
|
-
*/
|
|
1040
|
-
const isFileData = (data) => {
|
|
1041
|
-
return (data !== undefined &&
|
|
1042
|
-
((typeof Blob !== 'undefined' && data instanceof Blob) ||
|
|
1043
|
-
(typeof File !== 'undefined' && data instanceof File) ||
|
|
1044
|
-
(typeof Buffer !== 'undefined' && data instanceof Buffer)));
|
|
1045
|
-
};
|
|
1046
|
-
/**
|
|
1047
|
-
* Uuid type guard.
|
|
1048
|
-
*/
|
|
1049
|
-
const isUuid = (data) => {
|
|
1050
|
-
const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
|
|
1051
|
-
const regExp = new RegExp(UUID_REGEX);
|
|
1052
|
-
return !isFileData(data) && regExp.test(data);
|
|
1053
|
-
};
|
|
1054
|
-
/**
|
|
1055
|
-
* Url type guard.
|
|
1056
|
-
*
|
|
1057
|
-
* @param {NodeFile | BrowserFile | Url | Uuid} data
|
|
1058
|
-
*/
|
|
1059
|
-
const isUrl = (data) => {
|
|
1060
|
-
const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
|
|
1061
|
-
const regExp = new RegExp(URL_REGEX);
|
|
1062
|
-
return !isFileData(data) && regExp.test(data);
|
|
1063
|
-
};
|
|
1064
|
-
|
|
1065
1149
|
/**
|
|
1066
1150
|
* Get file size.
|
|
1067
1151
|
*/
|
|
@@ -1131,19 +1215,25 @@ const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integr
|
|
|
1131
1215
|
}
|
|
1132
1216
|
throw error;
|
|
1133
1217
|
}));
|
|
1134
|
-
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 }) => {
|
|
1218
|
+
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 }) => {
|
|
1135
1219
|
const size = fileSize || getFileSize(file);
|
|
1136
1220
|
let progressValues;
|
|
1137
|
-
const createProgressHandler = (
|
|
1221
|
+
const createProgressHandler = (totalChunks, chunkIdx) => {
|
|
1138
1222
|
if (!onProgress)
|
|
1139
1223
|
return;
|
|
1140
1224
|
if (!progressValues) {
|
|
1141
|
-
progressValues = Array(
|
|
1225
|
+
progressValues = Array(totalChunks).fill(0);
|
|
1142
1226
|
}
|
|
1143
1227
|
const sum = (values) => values.reduce((sum, next) => sum + next, 0);
|
|
1144
|
-
return (
|
|
1145
|
-
|
|
1146
|
-
|
|
1228
|
+
return (info) => {
|
|
1229
|
+
if (!info.isComputable) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
progressValues[chunkIdx] = info.value;
|
|
1233
|
+
onProgress({
|
|
1234
|
+
isComputable: true,
|
|
1235
|
+
value: sum(progressValues) / totalChunks
|
|
1236
|
+
});
|
|
1147
1237
|
};
|
|
1148
1238
|
};
|
|
1149
1239
|
return multipartStart(size, {
|
|
@@ -1158,7 +1248,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1158
1248
|
source,
|
|
1159
1249
|
integration,
|
|
1160
1250
|
userAgent,
|
|
1161
|
-
retryThrottledRequestMaxTimes
|
|
1251
|
+
retryThrottledRequestMaxTimes,
|
|
1252
|
+
metadata
|
|
1162
1253
|
})
|
|
1163
1254
|
.then(({ uuid, parts }) => {
|
|
1164
1255
|
const getChunk = prepareChunks(file, size, multipartChunkSize);
|
|
@@ -1205,10 +1296,10 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1205
1296
|
/**
|
|
1206
1297
|
* Uploads file from provided data.
|
|
1207
1298
|
*/
|
|
1208
|
-
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 }) {
|
|
1299
|
+
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 }) {
|
|
1209
1300
|
if (isFileData(data)) {
|
|
1210
1301
|
const fileSize = getFileSize(data);
|
|
1211
|
-
if (isMultipart(fileSize)) {
|
|
1302
|
+
if (isMultipart(fileSize, multipartMinFileSize)) {
|
|
1212
1303
|
return uploadMultipart(data, {
|
|
1213
1304
|
publicKey,
|
|
1214
1305
|
contentType,
|
|
@@ -1226,7 +1317,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1226
1317
|
userAgent,
|
|
1227
1318
|
maxConcurrentRequests,
|
|
1228
1319
|
retryThrottledRequestMaxTimes,
|
|
1229
|
-
baseCDN
|
|
1320
|
+
baseCDN,
|
|
1321
|
+
metadata
|
|
1230
1322
|
});
|
|
1231
1323
|
}
|
|
1232
1324
|
return uploadFromObject(data, {
|
|
@@ -1242,7 +1334,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1242
1334
|
integration,
|
|
1243
1335
|
userAgent,
|
|
1244
1336
|
retryThrottledRequestMaxTimes,
|
|
1245
|
-
baseCDN
|
|
1337
|
+
baseCDN,
|
|
1338
|
+
metadata
|
|
1246
1339
|
});
|
|
1247
1340
|
}
|
|
1248
1341
|
if (isUrl(data)) {
|
|
@@ -1262,7 +1355,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1262
1355
|
integration,
|
|
1263
1356
|
userAgent,
|
|
1264
1357
|
retryThrottledRequestMaxTimes,
|
|
1265
|
-
pusherKey
|
|
1358
|
+
pusherKey,
|
|
1359
|
+
metadata
|
|
1266
1360
|
});
|
|
1267
1361
|
}
|
|
1268
1362
|
if (isUuid(data)) {
|
|
@@ -1336,6 +1430,7 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1336
1430
|
throw new TypeError(`Group uploading from "${data}" is not supported`);
|
|
1337
1431
|
}
|
|
1338
1432
|
let progressValues;
|
|
1433
|
+
let isStillComputable = true;
|
|
1339
1434
|
const filesCount = data.length;
|
|
1340
1435
|
const createProgressHandler = (size, index) => {
|
|
1341
1436
|
if (!onProgress)
|
|
@@ -1344,9 +1439,14 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1344
1439
|
progressValues = Array(size).fill(0);
|
|
1345
1440
|
}
|
|
1346
1441
|
const normalize = (values) => values.reduce((sum, next) => sum + next) / size;
|
|
1347
|
-
return (
|
|
1348
|
-
|
|
1349
|
-
|
|
1442
|
+
return (info) => {
|
|
1443
|
+
if (!info.isComputable || !isStillComputable) {
|
|
1444
|
+
isStillComputable = false;
|
|
1445
|
+
onProgress({ isComputable: false });
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
progressValues[index] = info.value;
|
|
1449
|
+
onProgress({ isComputable: true, value: normalize(progressValues) });
|
|
1350
1450
|
};
|
|
1351
1451
|
};
|
|
1352
1452
|
return Promise.all(data.map((file, index) => uploadFile(file, {
|
|
@@ -1385,7 +1485,12 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1385
1485
|
integration,
|
|
1386
1486
|
userAgent,
|
|
1387
1487
|
retryThrottledRequestMaxTimes
|
|
1388
|
-
})
|
|
1488
|
+
})
|
|
1489
|
+
.then((groupInfo) => new UploadcareGroup(groupInfo, filesInGroup))
|
|
1490
|
+
.then((group) => {
|
|
1491
|
+
onProgress && onProgress({ isComputable: true, value: 1 });
|
|
1492
|
+
return group;
|
|
1493
|
+
});
|
|
1389
1494
|
});
|
|
1390
1495
|
}
|
|
1391
1496
|
|