@uploadcare/upload-client 6.5.1 → 6.6.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 CHANGED
@@ -23,6 +23,7 @@ Node.js and browser.
23
23
  - [High-Level API](#high-level-api)
24
24
  - [Low-Level API](#low-level-api)
25
25
  - [Settings](#settings)
26
+ - [Uploading queue](#uploading-queue)
26
27
  - [React Native](#react-native)
27
28
  - [Testing](#testing)
28
29
  - [Security issues](#security-issues)
@@ -54,9 +55,7 @@ Once the UploadClient instance is created, you can start using the wrapper to
54
55
  upload files from binary data:
55
56
 
56
57
  ```javascript
57
- client
58
- .uploadFile(fileData)
59
- .then(file => console.log(file.uuid))
58
+ client.uploadFile(fileData).then((file) => console.log(file.uuid))
60
59
  ```
61
60
 
62
61
  Another option is uploading files from URL, via the `uploadFile` method:
@@ -64,9 +63,7 @@ Another option is uploading files from URL, via the `uploadFile` method:
64
63
  ```javascript
65
64
  const fileURL = 'https://example.com/file.jpg'
66
65
 
67
- client
68
- .uploadFile(fileURL)
69
- .then(file => console.log(file.uuid))
66
+ client.uploadFile(fileURL).then((file) => console.log(file.uuid))
70
67
  ```
71
68
 
72
69
  You can also use the `uploadFile` method to get previously uploaded files via
@@ -75,9 +72,7 @@ their UUIDs:
75
72
  ```javascript
76
73
  const fileUUID = 'edfdf045-34c0-4087-bbdd-e3834921f890'
77
74
 
78
- client
79
- .uploadFile(fileUUID)
80
- .then(file => console.log(file.uuid))
75
+ client.uploadFile(fileUUID).then((file) => console.log(file.uuid))
81
76
  ```
82
77
 
83
78
  You can track uploading progress:
@@ -90,7 +85,7 @@ const onProgress = ({ isComputable, value }) => {
90
85
 
91
86
  client
92
87
  .uploadFile(fileUUID, { onProgress })
93
- .then(file => console.log(file.uuid))
88
+ .then((file) => console.log(file.uuid))
94
89
  ```
95
90
 
96
91
  Note that `isComputable` flag can be `false` is some cases of uploading from the URL.
@@ -105,8 +100,8 @@ const abortController = new AbortController()
105
100
 
106
101
  client
107
102
  .uploadFile(fileUUID, { signal: abortController.signal })
108
- .then(file => console.log(file.uuid))
109
- .catch(error => {
103
+ .then((file) => console.log(file.uuid))
104
+ .catch((error) => {
110
105
  if (error.isCancel) {
111
106
  console.log(`File uploading was canceled.`)
112
107
  }
@@ -194,8 +189,8 @@ const onProgress = ({ isComputable, value }) => console.log(isComputable, value)
194
189
  const abortController = new AbortController()
195
190
 
196
191
  base(fileData, { onProgress, signal: abortController.signal }) // fileData must be `Blob` or `File` or `Buffer`
197
- .then(data => console.log(data.file))
198
- .catch(error => {
192
+ .then((data) => console.log(data.file))
193
+ .catch((error) => {
199
194
  if (error.isCancel) {
200
195
  console.log(`File uploading was canceled.`)
201
196
  }
@@ -421,6 +416,55 @@ Non-string values will be converted to `string`. `undefined` values will be igno
421
416
 
422
417
  See [docs][uc-file-metadata] and [REST API][uc-docs-metadata] for details.
423
418
 
419
+ ### Uploading queue
420
+
421
+ If you're going to upload a lot of files at once, it's useful to do it in a queue. Otherwise, a large number of simultaneous requests can clog the internet channel and slow down the process.
422
+
423
+ To solve this problem, we provide a simple helper called `Queue`.
424
+
425
+ Here is an example of how to use it:
426
+
427
+ ```typescript
428
+ import { Queue, uploadFile } from '@uploadcare/upload-client'
429
+
430
+ // Create a queue with a limit of 10 concurrent requests.
431
+ const queue = new Queue(10)
432
+
433
+ // Create an array containing 50 files.
434
+ const files = [
435
+ ...Array(50)
436
+ .fill(0)
437
+ .map((_, idx) => Buffer.from(`content-${idx}`))
438
+ ]
439
+ const promises = files.map((file, idx) => {
440
+ const fileName = `file-${idx}.txt`
441
+ return queue
442
+ .add(() =>
443
+ uploadFile(file, {
444
+ publicKey: 'YOUR_PUBLIC_KEY',
445
+ contentType: 'plain/text',
446
+ fileName
447
+ })
448
+ )
449
+ .then((fileInfo) =>
450
+ console.log(
451
+ `"File "${fileName}" has been successfully uploaded! You can access it at the following URL: "${fileInfo.cdnUrl}"`
452
+ )
453
+ )
454
+ })
455
+
456
+ await Promise.all(promises)
457
+
458
+ console.log('Files have been successfully uploaded')
459
+ ```
460
+
461
+ You can pass any function that returns a promise to `queue.add`, and it will be executed concurrently.
462
+
463
+ `queue.add` returns a promise that mimics the one passed in, meaning it will resolve or reject with the corresponding values.
464
+
465
+ If the functionality of the built-in `Queue` is not sufficient for you, you can use any other third-party, more functional solution.
466
+
467
+
424
468
  ## React Native
425
469
 
426
470
  ### Prepare
@@ -398,7 +398,7 @@ const getUrl = (base, path, query) => {
398
398
  return url.toString();
399
399
  };
400
400
 
401
- var version = '6.5.1';
401
+ var version = '6.6.0';
402
402
 
403
403
  const LIBRARY_NAME = 'UploadcareUploadClient';
404
404
  const LIBRARY_VERSION = version;
@@ -1656,6 +1656,62 @@ class UploadClient {
1656
1656
  }
1657
1657
  }
1658
1658
 
1659
+ class Queue {
1660
+ #concurrency = 1;
1661
+ #pending = [];
1662
+ #running = 0;
1663
+ #resolvers = new WeakMap();
1664
+ #rejectors = new WeakMap();
1665
+ constructor(concurrency) {
1666
+ this.#concurrency = concurrency;
1667
+ }
1668
+ #run() {
1669
+ const tasksLeft = this.#concurrency - this.#running;
1670
+ for (let i = 0; i < tasksLeft; i++) {
1671
+ const task = this.#pending.shift();
1672
+ if (!task) {
1673
+ return;
1674
+ }
1675
+ const resolver = this.#resolvers.get(task);
1676
+ const rejector = this.#rejectors.get(task);
1677
+ if (!resolver || !rejector)
1678
+ throw new Error('Unexpected behavior: resolver or rejector is undefined');
1679
+ this.#running += 1;
1680
+ task()
1681
+ .finally(() => {
1682
+ this.#resolvers.delete(task);
1683
+ this.#rejectors.delete(task);
1684
+ this.#running -= 1;
1685
+ this.#run();
1686
+ })
1687
+ .then((value) => resolver(value))
1688
+ .catch((error) => rejector(error));
1689
+ }
1690
+ }
1691
+ add(task) {
1692
+ return new Promise((resolve, reject) => {
1693
+ this.#resolvers.set(task, resolve);
1694
+ this.#rejectors.set(task, reject);
1695
+ this.#pending.push(task);
1696
+ this.#run();
1697
+ });
1698
+ }
1699
+ get pending() {
1700
+ return this.#pending.length;
1701
+ }
1702
+ get running() {
1703
+ return this.#running;
1704
+ }
1705
+ set concurrency(value) {
1706
+ this.#concurrency = value;
1707
+ this.#run();
1708
+ }
1709
+ get concurrency() {
1710
+ return this.#concurrency;
1711
+ }
1712
+ }
1713
+
1714
+ exports.Queue = Queue;
1659
1715
  exports.UploadClient = UploadClient;
1660
1716
  exports.UploadClientError = UploadClientError;
1661
1717
  exports.UploadcareFile = UploadcareFile;
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
@@ -429,7 +429,7 @@ const getUrl = (base, path, query) => {
429
429
  return url.toString();
430
430
  };
431
431
 
432
- var version = '6.5.1';
432
+ var version = '6.6.0';
433
433
 
434
434
  const LIBRARY_NAME = 'UploadcareUploadClient';
435
435
  const LIBRARY_VERSION = version;
@@ -1685,6 +1685,62 @@ class UploadClient {
1685
1685
  }
1686
1686
  }
1687
1687
 
1688
+ class Queue {
1689
+ #concurrency = 1;
1690
+ #pending = [];
1691
+ #running = 0;
1692
+ #resolvers = new WeakMap();
1693
+ #rejectors = new WeakMap();
1694
+ constructor(concurrency) {
1695
+ this.#concurrency = concurrency;
1696
+ }
1697
+ #run() {
1698
+ const tasksLeft = this.#concurrency - this.#running;
1699
+ for (let i = 0; i < tasksLeft; i++) {
1700
+ const task = this.#pending.shift();
1701
+ if (!task) {
1702
+ return;
1703
+ }
1704
+ const resolver = this.#resolvers.get(task);
1705
+ const rejector = this.#rejectors.get(task);
1706
+ if (!resolver || !rejector)
1707
+ throw new Error('Unexpected behavior: resolver or rejector is undefined');
1708
+ this.#running += 1;
1709
+ task()
1710
+ .finally(() => {
1711
+ this.#resolvers.delete(task);
1712
+ this.#rejectors.delete(task);
1713
+ this.#running -= 1;
1714
+ this.#run();
1715
+ })
1716
+ .then((value) => resolver(value))
1717
+ .catch((error) => rejector(error));
1718
+ }
1719
+ }
1720
+ add(task) {
1721
+ return new Promise((resolve, reject) => {
1722
+ this.#resolvers.set(task, resolve);
1723
+ this.#rejectors.set(task, reject);
1724
+ this.#pending.push(task);
1725
+ this.#run();
1726
+ });
1727
+ }
1728
+ get pending() {
1729
+ return this.#pending.length;
1730
+ }
1731
+ get running() {
1732
+ return this.#running;
1733
+ }
1734
+ set concurrency(value) {
1735
+ this.#concurrency = value;
1736
+ this.#run();
1737
+ }
1738
+ get concurrency() {
1739
+ return this.#concurrency;
1740
+ }
1741
+ }
1742
+
1743
+ exports.Queue = Queue;
1688
1744
  exports.UploadClient = UploadClient;
1689
1745
  exports.UploadClientError = UploadClientError;
1690
1746
  exports.UploadcareFile = UploadcareFile;
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
@@ -406,7 +406,7 @@ const getUrl = (base, path, query) => {
406
406
  return url.toString();
407
407
  };
408
408
 
409
- var version = '6.5.1';
409
+ var version = '6.6.0';
410
410
 
411
411
  const LIBRARY_NAME = 'UploadcareUploadClient';
412
412
  const LIBRARY_VERSION = version;
@@ -1684,6 +1684,62 @@ class UploadClient {
1684
1684
  }
1685
1685
  }
1686
1686
 
1687
+ class Queue {
1688
+ #concurrency = 1;
1689
+ #pending = [];
1690
+ #running = 0;
1691
+ #resolvers = new WeakMap();
1692
+ #rejectors = new WeakMap();
1693
+ constructor(concurrency) {
1694
+ this.#concurrency = concurrency;
1695
+ }
1696
+ #run() {
1697
+ const tasksLeft = this.#concurrency - this.#running;
1698
+ for (let i = 0; i < tasksLeft; i++) {
1699
+ const task = this.#pending.shift();
1700
+ if (!task) {
1701
+ return;
1702
+ }
1703
+ const resolver = this.#resolvers.get(task);
1704
+ const rejector = this.#rejectors.get(task);
1705
+ if (!resolver || !rejector)
1706
+ throw new Error('Unexpected behavior: resolver or rejector is undefined');
1707
+ this.#running += 1;
1708
+ task()
1709
+ .finally(() => {
1710
+ this.#resolvers.delete(task);
1711
+ this.#rejectors.delete(task);
1712
+ this.#running -= 1;
1713
+ this.#run();
1714
+ })
1715
+ .then((value) => resolver(value))
1716
+ .catch((error) => rejector(error));
1717
+ }
1718
+ }
1719
+ add(task) {
1720
+ return new Promise((resolve, reject) => {
1721
+ this.#resolvers.set(task, resolve);
1722
+ this.#rejectors.set(task, reject);
1723
+ this.#pending.push(task);
1724
+ this.#run();
1725
+ });
1726
+ }
1727
+ get pending() {
1728
+ return this.#pending.length;
1729
+ }
1730
+ get running() {
1731
+ return this.#running;
1732
+ }
1733
+ set concurrency(value) {
1734
+ this.#concurrency = value;
1735
+ this.#run();
1736
+ }
1737
+ get concurrency() {
1738
+ return this.#concurrency;
1739
+ }
1740
+ }
1741
+
1742
+ exports.Queue = Queue;
1687
1743
  exports.UploadClient = UploadClient;
1688
1744
  exports.UploadClientError = UploadClientError;
1689
1745
  exports.UploadcareFile = UploadcareFile;
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
@@ -396,7 +396,7 @@ const getUrl = (base, path, query) => {
396
396
  return url.toString();
397
397
  };
398
398
 
399
- var version = '6.5.1';
399
+ var version = '6.6.0';
400
400
 
401
401
  const LIBRARY_NAME = 'UploadcareUploadClient';
402
402
  const LIBRARY_VERSION = version;
@@ -1654,4 +1654,59 @@ class UploadClient {
1654
1654
  }
1655
1655
  }
1656
1656
 
1657
- export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
1657
+ class Queue {
1658
+ #concurrency = 1;
1659
+ #pending = [];
1660
+ #running = 0;
1661
+ #resolvers = new WeakMap();
1662
+ #rejectors = new WeakMap();
1663
+ constructor(concurrency) {
1664
+ this.#concurrency = concurrency;
1665
+ }
1666
+ #run() {
1667
+ const tasksLeft = this.#concurrency - this.#running;
1668
+ for (let i = 0; i < tasksLeft; i++) {
1669
+ const task = this.#pending.shift();
1670
+ if (!task) {
1671
+ return;
1672
+ }
1673
+ const resolver = this.#resolvers.get(task);
1674
+ const rejector = this.#rejectors.get(task);
1675
+ if (!resolver || !rejector)
1676
+ throw new Error('Unexpected behavior: resolver or rejector is undefined');
1677
+ this.#running += 1;
1678
+ task()
1679
+ .finally(() => {
1680
+ this.#resolvers.delete(task);
1681
+ this.#rejectors.delete(task);
1682
+ this.#running -= 1;
1683
+ this.#run();
1684
+ })
1685
+ .then((value) => resolver(value))
1686
+ .catch((error) => rejector(error));
1687
+ }
1688
+ }
1689
+ add(task) {
1690
+ return new Promise((resolve, reject) => {
1691
+ this.#resolvers.set(task, resolve);
1692
+ this.#rejectors.set(task, reject);
1693
+ this.#pending.push(task);
1694
+ this.#run();
1695
+ });
1696
+ }
1697
+ get pending() {
1698
+ return this.#pending.length;
1699
+ }
1700
+ get running() {
1701
+ return this.#running;
1702
+ }
1703
+ set concurrency(value) {
1704
+ this.#concurrency = value;
1705
+ this.#run();
1706
+ }
1707
+ get concurrency() {
1708
+ return this.#concurrency;
1709
+ }
1710
+ }
1711
+
1712
+ export { Queue, UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
@@ -427,7 +427,7 @@ const getUrl = (base, path, query) => {
427
427
  return url.toString();
428
428
  };
429
429
 
430
- var version = '6.5.1';
430
+ var version = '6.6.0';
431
431
 
432
432
  const LIBRARY_NAME = 'UploadcareUploadClient';
433
433
  const LIBRARY_VERSION = version;
@@ -1683,4 +1683,59 @@ class UploadClient {
1683
1683
  }
1684
1684
  }
1685
1685
 
1686
- export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
1686
+ class Queue {
1687
+ #concurrency = 1;
1688
+ #pending = [];
1689
+ #running = 0;
1690
+ #resolvers = new WeakMap();
1691
+ #rejectors = new WeakMap();
1692
+ constructor(concurrency) {
1693
+ this.#concurrency = concurrency;
1694
+ }
1695
+ #run() {
1696
+ const tasksLeft = this.#concurrency - this.#running;
1697
+ for (let i = 0; i < tasksLeft; i++) {
1698
+ const task = this.#pending.shift();
1699
+ if (!task) {
1700
+ return;
1701
+ }
1702
+ const resolver = this.#resolvers.get(task);
1703
+ const rejector = this.#rejectors.get(task);
1704
+ if (!resolver || !rejector)
1705
+ throw new Error('Unexpected behavior: resolver or rejector is undefined');
1706
+ this.#running += 1;
1707
+ task()
1708
+ .finally(() => {
1709
+ this.#resolvers.delete(task);
1710
+ this.#rejectors.delete(task);
1711
+ this.#running -= 1;
1712
+ this.#run();
1713
+ })
1714
+ .then((value) => resolver(value))
1715
+ .catch((error) => rejector(error));
1716
+ }
1717
+ }
1718
+ add(task) {
1719
+ return new Promise((resolve, reject) => {
1720
+ this.#resolvers.set(task, resolve);
1721
+ this.#rejectors.set(task, reject);
1722
+ this.#pending.push(task);
1723
+ this.#run();
1724
+ });
1725
+ }
1726
+ get pending() {
1727
+ return this.#pending.length;
1728
+ }
1729
+ get running() {
1730
+ return this.#running;
1731
+ }
1732
+ set concurrency(value) {
1733
+ this.#concurrency = value;
1734
+ this.#run();
1735
+ }
1736
+ get concurrency() {
1737
+ return this.#concurrency;
1738
+ }
1739
+ }
1740
+
1741
+ export { Queue, UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
@@ -404,7 +404,7 @@ const getUrl = (base, path, query) => {
404
404
  return url.toString();
405
405
  };
406
406
 
407
- var version = '6.5.1';
407
+ var version = '6.6.0';
408
408
 
409
409
  const LIBRARY_NAME = 'UploadcareUploadClient';
410
410
  const LIBRARY_VERSION = version;
@@ -1682,4 +1682,59 @@ class UploadClient {
1682
1682
  }
1683
1683
  }
1684
1684
 
1685
- export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
1685
+ class Queue {
1686
+ #concurrency = 1;
1687
+ #pending = [];
1688
+ #running = 0;
1689
+ #resolvers = new WeakMap();
1690
+ #rejectors = new WeakMap();
1691
+ constructor(concurrency) {
1692
+ this.#concurrency = concurrency;
1693
+ }
1694
+ #run() {
1695
+ const tasksLeft = this.#concurrency - this.#running;
1696
+ for (let i = 0; i < tasksLeft; i++) {
1697
+ const task = this.#pending.shift();
1698
+ if (!task) {
1699
+ return;
1700
+ }
1701
+ const resolver = this.#resolvers.get(task);
1702
+ const rejector = this.#rejectors.get(task);
1703
+ if (!resolver || !rejector)
1704
+ throw new Error('Unexpected behavior: resolver or rejector is undefined');
1705
+ this.#running += 1;
1706
+ task()
1707
+ .finally(() => {
1708
+ this.#resolvers.delete(task);
1709
+ this.#rejectors.delete(task);
1710
+ this.#running -= 1;
1711
+ this.#run();
1712
+ })
1713
+ .then((value) => resolver(value))
1714
+ .catch((error) => rejector(error));
1715
+ }
1716
+ }
1717
+ add(task) {
1718
+ return new Promise((resolve, reject) => {
1719
+ this.#resolvers.set(task, resolve);
1720
+ this.#rejectors.set(task, reject);
1721
+ this.#pending.push(task);
1722
+ this.#run();
1723
+ });
1724
+ }
1725
+ get pending() {
1726
+ return this.#pending.length;
1727
+ }
1728
+ get running() {
1729
+ return this.#running;
1730
+ }
1731
+ set concurrency(value) {
1732
+ this.#concurrency = value;
1733
+ this.#run();
1734
+ }
1735
+ get concurrency() {
1736
+ return this.#concurrency;
1737
+ }
1738
+ }
1739
+
1740
+ export { Queue, UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, UploadcareNetworkError, base, fromUrl, fromUrlStatus, getUserAgent$1 as getUserAgent, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
package/dist/index.d.ts CHANGED
@@ -472,6 +472,16 @@ export declare class UploadClient {
472
472
  uploadFile(data: SupportedFileInput | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
473
473
  uploadFileGroup(data: SupportedFileInput[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
474
474
  }
475
+ export type Task<T = unknown> = () => Promise<T>;
476
+ export declare class Queue {
477
+ #private;
478
+ constructor(concurrency: number);
479
+ add<T>(task: Task<T>): Promise<T>;
480
+ get pending(): number;
481
+ get running(): number;
482
+ set concurrency(value: number);
483
+ get concurrency(): number;
484
+ }
475
485
  export type Headers = {
476
486
  [key: string]: string | string[] | undefined;
477
487
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uploadcare/upload-client",
3
- "version": "6.5.1",
3
+ "version": "6.6.0",
4
4
  "description": "Library for work with Uploadcare Upload API",
5
5
  "type": "module",
6
6
  "module": "./dist/esm/index.node.mjs",
@@ -90,7 +90,7 @@
90
90
  "koa-body": "5.0.0",
91
91
  "mock-socket": "9.0.3",
92
92
  "start-server-and-test": "1.14.0",
93
- "@uploadcare/api-client-utils": "^6.5.1",
93
+ "@uploadcare/api-client-utils": "^6.6.0",
94
94
  "chalk": "^4.1.2"
95
95
  },
96
96
  "dependencies": {