@uploadcare/upload-client 3.0.0-alpha.0 → 3.1.1

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.
@@ -120,31 +120,97 @@ function identity(obj) {
120
120
  const transformFile = identity;
121
121
  var getFormData = () => new FormData();
122
122
 
123
- const isFileTuple = (tuple) => tuple[0] === 'file';
124
- function buildFormData(body) {
125
- const formData = getFormData();
126
- for (const tuple of body) {
127
- if (Array.isArray(tuple[1])) {
128
- // refactor this
129
- tuple[1].forEach((val) => val && formData.append(tuple[0] + '[]', `${val}`));
130
- }
131
- else if (isFileTuple(tuple)) {
132
- const name = tuple[2];
133
- const file = transformFile(tuple[1]); // lgtm[js/superfluous-trailing-arguments]
134
- formData.append(tuple[0], file, name);
135
- }
136
- else if (tuple[1] != null) {
137
- formData.append(tuple[0], `${tuple[1]}`);
123
+ /**
124
+ * FileData type guard.
125
+ */
126
+ const isFileData = (data) => {
127
+ return (data !== undefined &&
128
+ ((typeof Blob !== 'undefined' && data instanceof Blob) ||
129
+ (typeof File !== 'undefined' && data instanceof File) ||
130
+ (typeof Buffer !== 'undefined' && data instanceof Buffer)));
131
+ };
132
+ /**
133
+ * Uuid type guard.
134
+ */
135
+ const isUuid = (data) => {
136
+ const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
137
+ const regExp = new RegExp(UUID_REGEX);
138
+ return !isFileData(data) && regExp.test(data);
139
+ };
140
+ /**
141
+ * Url type guard.
142
+ *
143
+ * @param {NodeFile | BrowserFile | Url | Uuid} data
144
+ */
145
+ const isUrl = (data) => {
146
+ const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
147
+ const regExp = new RegExp(URL_REGEX);
148
+ return !isFileData(data) && regExp.test(data);
149
+ };
150
+
151
+ const isSimpleValue = (value) => {
152
+ return (typeof value === 'string' ||
153
+ typeof value === 'number' ||
154
+ typeof value === 'undefined');
155
+ };
156
+ const isObjectValue = (value) => {
157
+ return !!value && typeof value === 'object' && !Array.isArray(value);
158
+ };
159
+ const isFileValue = (value) => !!value &&
160
+ typeof value === 'object' &&
161
+ 'data' in value &&
162
+ isFileData(value.data);
163
+ function collectParams(params, inputKey, inputValue) {
164
+ if (isFileValue(inputValue)) {
165
+ const name = inputValue.name;
166
+ const file = transformFile(inputValue.data); // lgtm [js/superfluous-trailing-arguments]
167
+ params.push(name ? [inputKey, file, name] : [inputKey, file]);
168
+ }
169
+ else if (isObjectValue(inputValue)) {
170
+ for (const [key, value] of Object.entries(inputValue)) {
171
+ if (typeof value !== 'undefined') {
172
+ params.push([`${inputKey}[${key}]`, String(value)]);
173
+ }
138
174
  }
139
175
  }
176
+ else if (isSimpleValue(inputValue) && inputValue) {
177
+ params.push([inputKey, inputValue.toString()]);
178
+ }
179
+ }
180
+ function getFormDataParams(options) {
181
+ const params = [];
182
+ for (const [key, value] of Object.entries(options)) {
183
+ collectParams(params, key, value);
184
+ }
185
+ return params;
186
+ }
187
+ function buildFormData(options) {
188
+ const formData = getFormData();
189
+ const params = getFormDataParams(options);
190
+ for (const param of params) {
191
+ formData.append(...param);
192
+ }
140
193
  return formData;
141
194
  }
142
195
 
143
196
  const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
197
+ // TODO: generalize value transforming logic and use it here and inside `buildFormData`
144
198
  const createQuery = (query) => Object.entries(query)
145
- .reduce((params, [key, value]) => params.concat(Array.isArray(value)
146
- ? value.map((value) => serializePair(`${key}[]`, value))
147
- : serializePair(key, value)), [])
199
+ .reduce((params, [key, value]) => {
200
+ let param;
201
+ if (typeof value === 'object' && !Array.isArray(value)) {
202
+ param = Object.entries(value)
203
+ .filter((entry) => typeof entry[1] !== 'undefined')
204
+ .map((entry) => serializePair(`${key}[${entry[0]}]`, String(entry[1])));
205
+ }
206
+ else if (Array.isArray(value)) {
207
+ param = value.map((val) => serializePair(`${key}[]`, val));
208
+ }
209
+ else {
210
+ param = serializePair(key, value);
211
+ }
212
+ return params.concat(param);
213
+ }, [])
148
214
  .filter((x) => !!x)
149
215
  .join('&');
150
216
  const getUrl = (base, path, query) => [
@@ -176,7 +242,7 @@ const defaultSettings = {
176
242
  const defaultContentType = 'application/octet-stream';
177
243
  const defaultFilename = 'original';
178
244
 
179
- var version = '3.0.0-alpha.0';
245
+ var version = '3.1.1';
180
246
 
181
247
  /**
182
248
  * Returns User Agent based on version and settings.
@@ -276,11 +342,15 @@ function retryIfThrottled(fn, retryThrottledMaxTimes) {
276
342
  }));
277
343
  }
278
344
 
345
+ function getStoreValue(store) {
346
+ return typeof store === 'undefined' ? 'auto' : store ? '1' : '0';
347
+ }
348
+
279
349
  /**
280
350
  * Performs file uploading request to Uploadcare Upload API.
281
351
  * Can be canceled and has progress.
282
352
  */
283
- function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
353
+ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
284
354
  return retryIfThrottled(() => {
285
355
  var _a;
286
356
  return request({
@@ -291,17 +361,18 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
291
361
  headers: {
292
362
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
293
363
  },
294
- data: buildFormData([
295
- ['file', file, (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename],
296
- ['UPLOADCARE_PUB_KEY', publicKey],
297
- [
298
- 'UPLOADCARE_STORE',
299
- typeof store === 'undefined' ? 'auto' : store ? 1 : 0
300
- ],
301
- ['signature', secureSignature],
302
- ['expire', secureExpire],
303
- ['source', source]
304
- ]),
364
+ data: buildFormData({
365
+ file: {
366
+ data: file,
367
+ name: (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename
368
+ },
369
+ UPLOADCARE_PUB_KEY: publicKey,
370
+ UPLOADCARE_STORE: getStoreValue(store),
371
+ signature: secureSignature,
372
+ expire: secureExpire,
373
+ source: source,
374
+ metadata
375
+ }),
305
376
  signal,
306
377
  onProgress
307
378
  }).then(({ data, headers, request }) => {
@@ -324,7 +395,7 @@ var TypeEnum;
324
395
  /**
325
396
  * Uploading files from URL.
326
397
  */
327
- function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
398
+ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
328
399
  return retryIfThrottled(() => request({
329
400
  method: 'POST',
330
401
  headers: {
@@ -334,13 +405,14 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
334
405
  jsonerrors: 1,
335
406
  pub_key: publicKey,
336
407
  source_url: sourceUrl,
337
- store: typeof store === 'undefined' ? 'auto' : store ? 1 : undefined,
408
+ store: getStoreValue(store),
338
409
  filename: fileName,
339
410
  check_URL_duplicates: checkForUrlDuplicates ? 1 : undefined,
340
411
  save_URL_duplicates: saveUrlForRecurrentUploads ? 1 : undefined,
341
412
  signature: secureSignature,
342
413
  expire: secureExpire,
343
- source: source
414
+ source: source,
415
+ metadata
344
416
  }),
345
417
  signal
346
418
  }).then(({ data, headers, request }) => {
@@ -483,24 +555,25 @@ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, sour
483
555
  /**
484
556
  * Start multipart uploading.
485
557
  */
486
- function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
558
+ function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
487
559
  return retryIfThrottled(() => request({
488
560
  method: 'POST',
489
561
  url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
490
562
  headers: {
491
563
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
492
564
  },
493
- data: buildFormData([
494
- ['filename', fileName !== null && fileName !== void 0 ? fileName : defaultFilename],
495
- ['size', size],
496
- ['content_type', contentType !== null && contentType !== void 0 ? contentType : defaultContentType],
497
- ['part_size', multipartChunkSize],
498
- ['UPLOADCARE_STORE', store ? '' : 'auto'],
499
- ['UPLOADCARE_PUB_KEY', publicKey],
500
- ['signature', secureSignature],
501
- ['expire', secureExpire],
502
- ['source', source]
503
- ]),
565
+ data: buildFormData({
566
+ filename: fileName !== null && fileName !== void 0 ? fileName : defaultFilename,
567
+ size: size,
568
+ content_type: contentType !== null && contentType !== void 0 ? contentType : defaultContentType,
569
+ part_size: multipartChunkSize,
570
+ UPLOADCARE_STORE: getStoreValue(store),
571
+ UPLOADCARE_PUB_KEY: publicKey,
572
+ signature: secureSignature,
573
+ expire: secureExpire,
574
+ source: source,
575
+ metadata
576
+ }),
504
577
  signal
505
578
  }).then(({ data, headers, request }) => {
506
579
  const response = camelizeKeys(JSON.parse(data));
@@ -549,11 +622,11 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
549
622
  headers: {
550
623
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
551
624
  },
552
- data: buildFormData([
553
- ['uuid', uuid],
554
- ['UPLOADCARE_PUB_KEY', publicKey],
555
- ['source', source]
556
- ]),
625
+ data: buildFormData({
626
+ uuid: uuid,
627
+ UPLOADCARE_PUB_KEY: publicKey,
628
+ source: source
629
+ }),
557
630
  signal
558
631
  }).then(({ data, headers, request }) => {
559
632
  const response = camelizeKeys(JSON.parse(data));
@@ -579,6 +652,8 @@ class UploadcareFile {
579
652
  this.originalFilename = null;
580
653
  this.imageInfo = null;
581
654
  this.videoInfo = null;
655
+ this.contentInfo = null;
656
+ this.metadata = null;
582
657
  const { uuid, s3Bucket } = fileInfo;
583
658
  const urlBase = s3Bucket
584
659
  ? `https://${s3Bucket}.s3.amazonaws.com/${uuid}/${fileInfo.filename}`
@@ -598,6 +673,8 @@ class UploadcareFile {
598
673
  this.originalFilename = fileInfo.originalFilename;
599
674
  this.imageInfo = camelizeKeys(fileInfo.imageInfo);
600
675
  this.videoInfo = camelizeKeys(fileInfo.videoInfo);
676
+ this.contentInfo = camelizeKeys(fileInfo.contentInfo);
677
+ this.metadata = fileInfo.metadata || null;
601
678
  }
602
679
  }
603
680
 
@@ -649,7 +726,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent,
649
726
  });
650
727
  }
651
728
 
652
- const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
729
+ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN, metadata }) => {
653
730
  return base(file, {
654
731
  publicKey,
655
732
  fileName,
@@ -662,7 +739,8 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
662
739
  source,
663
740
  integration,
664
741
  userAgent,
665
- retryThrottledRequestMaxTimes
742
+ retryThrottledRequestMaxTimes,
743
+ metadata
666
744
  })
667
745
  .then(({ file }) => {
668
746
  return isReadyPoll({
@@ -965,7 +1043,7 @@ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((
965
1043
  }
966
1044
  });
967
1045
  });
968
- 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))
1046
+ 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))
969
1047
  .then(() => fromUrl(sourceUrl, {
970
1048
  publicKey,
971
1049
  fileName,
@@ -979,7 +1057,8 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
979
1057
  source,
980
1058
  integration,
981
1059
  userAgent,
982
- retryThrottledRequestMaxTimes
1060
+ retryThrottledRequestMaxTimes,
1061
+ metadata
983
1062
  }))
984
1063
  .catch((error) => {
985
1064
  const pusher = getPusher(pusherKey);
@@ -1050,34 +1129,6 @@ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProg
1050
1129
  });
1051
1130
  };
1052
1131
 
1053
- /**
1054
- * FileData type guard.
1055
- */
1056
- const isFileData = (data) => {
1057
- return (data !== undefined &&
1058
- ((typeof Blob !== 'undefined' && data instanceof Blob) ||
1059
- (typeof File !== 'undefined' && data instanceof File) ||
1060
- (typeof Buffer !== 'undefined' && data instanceof Buffer)));
1061
- };
1062
- /**
1063
- * Uuid type guard.
1064
- */
1065
- const isUuid = (data) => {
1066
- const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
1067
- const regExp = new RegExp(UUID_REGEX);
1068
- return !isFileData(data) && regExp.test(data);
1069
- };
1070
- /**
1071
- * Url type guard.
1072
- *
1073
- * @param {NodeFile | BrowserFile | Url | Uuid} data
1074
- */
1075
- const isUrl = (data) => {
1076
- const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
1077
- const regExp = new RegExp(URL_REGEX);
1078
- return !isFileData(data) && regExp.test(data);
1079
- };
1080
-
1081
1132
  /**
1082
1133
  * Get file size.
1083
1134
  */
@@ -1147,7 +1198,7 @@ const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integr
1147
1198
  }
1148
1199
  throw error;
1149
1200
  }));
1150
- 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 }) => {
1201
+ 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 }) => {
1151
1202
  const size = fileSize || getFileSize(file);
1152
1203
  let progressValues;
1153
1204
  const createProgressHandler = (totalChunks, chunkIdx) => {
@@ -1180,7 +1231,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1180
1231
  source,
1181
1232
  integration,
1182
1233
  userAgent,
1183
- retryThrottledRequestMaxTimes
1234
+ retryThrottledRequestMaxTimes,
1235
+ metadata
1184
1236
  })
1185
1237
  .then(({ uuid, parts }) => {
1186
1238
  const getChunk = prepareChunks(file, size, multipartChunkSize);
@@ -1227,10 +1279,10 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1227
1279
  /**
1228
1280
  * Uploads file from provided data.
1229
1281
  */
1230
- 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 }) {
1282
+ 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 }) {
1231
1283
  if (isFileData(data)) {
1232
1284
  const fileSize = getFileSize(data);
1233
- if (isMultipart(fileSize)) {
1285
+ if (isMultipart(fileSize, multipartMinFileSize)) {
1234
1286
  return uploadMultipart(data, {
1235
1287
  publicKey,
1236
1288
  contentType,
@@ -1248,7 +1300,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1248
1300
  userAgent,
1249
1301
  maxConcurrentRequests,
1250
1302
  retryThrottledRequestMaxTimes,
1251
- baseCDN
1303
+ baseCDN,
1304
+ metadata
1252
1305
  });
1253
1306
  }
1254
1307
  return uploadFromObject(data, {
@@ -1264,7 +1317,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1264
1317
  integration,
1265
1318
  userAgent,
1266
1319
  retryThrottledRequestMaxTimes,
1267
- baseCDN
1320
+ baseCDN,
1321
+ metadata
1268
1322
  });
1269
1323
  }
1270
1324
  if (isUrl(data)) {
@@ -1284,7 +1338,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
1284
1338
  integration,
1285
1339
  userAgent,
1286
1340
  retryThrottledRequestMaxTimes,
1287
- pusherKey
1341
+ pusherKey,
1342
+ metadata
1288
1343
  });
1289
1344
  }
1290
1345
  if (isUuid(data)) {