@uploadcare/upload-client 4.0.1 → 4.2.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.
@@ -150,7 +150,7 @@ const getFileOptions = ({ name, contentType }) => [
150
150
  contentType
151
151
  })
152
152
  .filter(([, value]) => !!value)
153
- .reduce((acc, [key, value]) => (Object.assign(Object.assign({}, acc), { [key]: value })), {})
153
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
154
154
  ].filter((value) => !!value);
155
155
  const transformFile = identity;
156
156
  var getFormData = () => new NodeFormData();
@@ -231,34 +231,36 @@ function buildFormData(options) {
231
231
  return formData;
232
232
  }
233
233
 
234
- const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
235
- // TODO: generalize value transforming logic and use it here and inside `buildFormData`
236
- const createQuery = (query) => Object.entries(query)
237
- .reduce((params, [key, value]) => {
238
- let param;
239
- if (typeof value === 'object' && !Array.isArray(value)) {
240
- param = Object.entries(value)
241
- .filter((entry) => typeof entry[1] !== 'undefined')
242
- .map((entry) => serializePair(`${key}[${entry[0]}]`, String(entry[1])));
243
- }
244
- else if (Array.isArray(value)) {
245
- param = value.map((val) => serializePair(`${key}[]`, val));
234
+ const buildSearchParams = (query) => {
235
+ const searchParams = new URLSearchParams();
236
+ for (const [key, value] of Object.entries(query)) {
237
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
238
+ Object.entries(value)
239
+ .filter((entry) => entry[1] ?? false)
240
+ .forEach((entry) => searchParams.set(`${key}[${entry[0]}]`, String(entry[1])));
241
+ }
242
+ else if (Array.isArray(value)) {
243
+ value.forEach((val) => {
244
+ searchParams.append(`${key}[]`, val);
245
+ });
246
+ }
247
+ else if (typeof value === 'string' && value) {
248
+ searchParams.set(key, value);
249
+ }
250
+ else if (typeof value === 'number') {
251
+ searchParams.set(key, value.toString());
252
+ }
246
253
  }
247
- else {
248
- param = serializePair(key, value);
254
+ return searchParams.toString();
255
+ };
256
+ const getUrl = (base, path, query) => {
257
+ const url = new URL(base);
258
+ url.pathname = path;
259
+ if (query) {
260
+ url.search = buildSearchParams(query);
249
261
  }
250
- return params.concat(param);
251
- }, [])
252
- .filter((x) => !!x)
253
- .join('&');
254
- const getUrl = (base, path, query) => [
255
- base,
256
- path,
257
- query && Object.keys(query).length > 0 ? '?' : '',
258
- query && createQuery(query)
259
- ]
260
- .filter(Boolean)
261
- .join('');
262
+ return url.toString();
263
+ };
262
264
 
263
265
  /*
264
266
  Settings for future support:
@@ -280,14 +282,59 @@ const defaultSettings = {
280
282
  const defaultContentType = 'application/octet-stream';
281
283
  const defaultFilename = 'original';
282
284
 
283
- var version = '4.0.1';
285
+ var version = '4.2.1';
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
+ }
284
329
 
285
330
  /**
286
- * Returns User Agent based on version and settings.
331
+ * setTimeout as Promise.
332
+ *
333
+ * @param {number} ms Timeout in milliseconds.
287
334
  */
288
- function getUserAgent({ userAgent, publicKey = '', integration = '' } = {}) {
289
- const libraryName = 'UploadcareUploadClient';
290
- const libraryVersion = version;
335
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
336
+
337
+ function getUserAgent$1({ libraryName, libraryVersion, userAgent, publicKey = '', integration = '' }) {
291
338
  const languageName = 'JavaScript';
292
339
  if (typeof userAgent === 'string') {
293
340
  return userAgent;
@@ -308,39 +355,6 @@ function getUserAgent({ userAgent, publicKey = '', integration = '' } = {}) {
308
355
  return `${mainInfo} (${additionInfo})`;
309
356
  }
310
357
 
311
- const SEPARATOR = /\W|_/g;
312
- /**
313
- * Transforms a string to camelCased.
314
- */
315
- function camelize(text) {
316
- return text
317
- .split(SEPARATOR)
318
- .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
319
- word.slice(1))
320
- .join('');
321
- }
322
- /**
323
- * Transforms keys of an object to camelCased recursively.
324
- */
325
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
326
- function camelizeKeys(source) {
327
- if (!source || typeof source !== 'object') {
328
- return source;
329
- }
330
- return Object.keys(source).reduce((accumulator, key) => {
331
- accumulator[camelize(key)] =
332
- typeof source[key] === 'object' ? camelizeKeys(source[key]) : source[key];
333
- return accumulator;
334
- }, {});
335
- }
336
-
337
- /**
338
- * setTimeout as Promise.
339
- *
340
- * @param {number} ms Timeout in milliseconds.
341
- */
342
- const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
343
-
344
358
  const defaultOptions = {
345
359
  factor: 2,
346
360
  time: 100
@@ -348,8 +362,8 @@ const defaultOptions = {
348
362
  function retrier(fn, options = defaultOptions) {
349
363
  let attempts = 0;
350
364
  function runAttempt(fn) {
351
- const defaultDelayTime = Math.round(options.time * Math.pow(options.factor, attempts));
352
- const retry = (ms) => delay(ms !== null && ms !== void 0 ? ms : defaultDelayTime).then(() => {
365
+ const defaultDelayTime = Math.round(options.time * options.factor ** attempts);
366
+ const retry = (ms) => delay(ms ?? defaultDelayTime).then(() => {
353
367
  attempts += 1;
354
368
  return runAttempt(fn);
355
369
  });
@@ -361,6 +375,16 @@ function retrier(fn, options = defaultOptions) {
361
375
  return runAttempt(fn);
362
376
  }
363
377
 
378
+ const LIBRARY_NAME = 'UploadcareUploadClient';
379
+ const LIBRARY_VERSION = version;
380
+ function getUserAgent(options) {
381
+ return getUserAgent$1({
382
+ libraryName: LIBRARY_NAME,
383
+ libraryVersion: LIBRARY_VERSION,
384
+ ...options
385
+ });
386
+ }
387
+
364
388
  const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
365
389
  const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
366
390
  function getTimeoutFromThrottledRequest(error) {
@@ -372,7 +396,7 @@ function getTimeoutFromThrottledRequest(error) {
372
396
  function retryIfThrottled(fn, retryThrottledMaxTimes) {
373
397
  return retrier(({ attempt, retry }) => fn().catch((error) => {
374
398
  if ('response' in error &&
375
- (error === null || error === void 0 ? void 0 : error.code) === REQUEST_WAS_THROTTLED_CODE &&
399
+ error?.code === REQUEST_WAS_THROTTLED_CODE &&
376
400
  attempt < retryThrottledMaxTimes) {
377
401
  return retry(getTimeoutFromThrottledRequest(error));
378
402
  }
@@ -389,41 +413,38 @@ function getStoreValue(store) {
389
413
  * Can be canceled and has progress.
390
414
  */
391
415
  function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
392
- return retryIfThrottled(() => {
393
- var _a;
394
- return request({
395
- method: 'POST',
396
- url: getUrl(baseURL, '/base/', {
397
- jsonerrors: 1
398
- }),
399
- headers: {
400
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
416
+ return retryIfThrottled(() => request({
417
+ method: 'POST',
418
+ url: getUrl(baseURL, '/base/', {
419
+ jsonerrors: 1
420
+ }),
421
+ headers: {
422
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
423
+ },
424
+ data: buildFormData({
425
+ file: {
426
+ data: file,
427
+ name: fileName ?? file.name ?? defaultFilename,
428
+ contentType
401
429
  },
402
- data: buildFormData({
403
- file: {
404
- data: file,
405
- name: (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename,
406
- contentType
407
- },
408
- UPLOADCARE_PUB_KEY: publicKey,
409
- UPLOADCARE_STORE: getStoreValue(store),
410
- signature: secureSignature,
411
- expire: secureExpire,
412
- source: source,
413
- metadata
414
- }),
415
- signal,
416
- onProgress
417
- }).then(({ data, headers, request }) => {
418
- const response = camelizeKeys(JSON.parse(data));
419
- if ('error' in response) {
420
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
421
- }
422
- else {
423
- return response;
424
- }
425
- });
426
- }, retryThrottledRequestMaxTimes);
430
+ UPLOADCARE_PUB_KEY: publicKey,
431
+ UPLOADCARE_STORE: getStoreValue(store),
432
+ signature: secureSignature,
433
+ expire: secureExpire,
434
+ source: source,
435
+ metadata
436
+ }),
437
+ signal,
438
+ onProgress
439
+ }).then(({ data, headers, request }) => {
440
+ const response = camelizeKeys(JSON.parse(data));
441
+ if ('error' in response) {
442
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
443
+ }
444
+ else {
445
+ return response;
446
+ }
447
+ }), retryThrottledRequestMaxTimes);
427
448
  }
428
449
 
429
450
  var TypeEnum;
@@ -602,9 +623,9 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
602
623
  'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
603
624
  },
604
625
  data: buildFormData({
605
- filename: fileName !== null && fileName !== void 0 ? fileName : defaultFilename,
626
+ filename: fileName ?? defaultFilename,
606
627
  size: size,
607
- content_type: contentType !== null && contentType !== void 0 ? contentType : defaultContentType,
628
+ content_type: contentType ?? defaultContentType,
608
629
  part_size: multipartChunkSize,
609
630
  UPLOADCARE_STORE: getStoreValue(store),
610
631
  UPLOADCARE_PUB_KEY: publicKey,
@@ -706,9 +727,9 @@ class UploadcareFile {
706
727
  this.mimeType = fileInfo.mimeType;
707
728
  this.cdnUrl = cdnUrl;
708
729
  this.originalFilename = fileInfo.originalFilename;
709
- this.imageInfo = camelizeKeys(fileInfo.imageInfo);
710
- this.videoInfo = camelizeKeys(fileInfo.videoInfo);
711
- this.contentInfo = camelizeKeys(fileInfo.contentInfo);
730
+ this.imageInfo = fileInfo.imageInfo;
731
+ this.videoInfo = fileInfo.videoInfo;
732
+ this.contentInfo = fileInfo.contentInfo;
712
733
  this.metadata = fileInfo.metadata || null;
713
734
  this.s3Bucket = s3Bucket || null;
714
735
  this.s3Url = s3Url;
@@ -834,8 +855,7 @@ class Events {
834
855
  this.events = Object.create({});
835
856
  }
836
857
  emit(event, data) {
837
- var _a;
838
- (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(data));
858
+ this.events[event]?.forEach((fn) => fn(data));
839
859
  }
840
860
  on(event, callback) {
841
861
  this.events[event] = this.events[event] || [];
@@ -853,12 +873,12 @@ class Events {
853
873
 
854
874
  const response = (type, data) => {
855
875
  if (type === 'success') {
856
- return Object.assign({ status: Status.Success }, data);
876
+ return { status: Status.Success, ...data };
857
877
  }
858
878
  if (type === 'progress') {
859
- return Object.assign({ status: Status.Progress }, data);
879
+ return { status: Status.Progress, ...data };
860
880
  }
861
- return Object.assign({ status: Status.Error }, data);
881
+ return { status: Status.Error, ...data };
862
882
  };
863
883
  class Pusher {
864
884
  constructor(pusherKey, disconnectTime = 30000) {
@@ -906,8 +926,7 @@ class Pusher {
906
926
  }
907
927
  disconnect() {
908
928
  const actualDisconect = () => {
909
- var _a;
910
- (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
929
+ this.ws?.close();
911
930
  this.ws = undefined;
912
931
  this.isConnected = false;
913
932
  };
@@ -921,9 +940,8 @@ class Pusher {
921
940
  }
922
941
  }
923
942
  send(event, data) {
924
- var _a;
925
943
  const str = JSON.stringify({ event, data });
926
- (_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(str);
944
+ this.ws?.send(str);
927
945
  }
928
946
  subscribe(token, handler) {
929
947
  this.subscribers += 1;
@@ -1090,7 +1108,7 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
1090
1108
  }))
1091
1109
  .catch((error) => {
1092
1110
  const pusher = getPusher(pusherKey);
1093
- pusher === null || pusher === void 0 ? void 0 : pusher.disconnect();
1111
+ pusher?.disconnect();
1094
1112
  return Promise.reject(error);
1095
1113
  })
1096
1114
  .then((urlResponse) => {
@@ -1250,7 +1268,7 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
1250
1268
  return multipartStart(size, {
1251
1269
  publicKey,
1252
1270
  contentType,
1253
- fileName: fileName !== null && fileName !== void 0 ? fileName : file.name,
1271
+ fileName: fileName ?? file.name,
1254
1272
  baseURL,
1255
1273
  secureSignature,
1256
1274
  secureExpire,
@@ -1502,7 +1520,10 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
1502
1520
  /**
1503
1521
  * Populate options with settings.
1504
1522
  */
1505
- const populateOptionsWithSettings = (options, settings) => (Object.assign(Object.assign({}, settings), options));
1523
+ const populateOptionsWithSettings = (options, settings) => ({
1524
+ ...settings,
1525
+ ...options
1526
+ });
1506
1527
  class UploadClient {
1507
1528
  constructor(settings) {
1508
1529
  this.settings = Object.assign({}, defaultSettings, settings);