es-toolkit 1.41.0 → 1.42.0-dev.1675

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/array/filterAsync.d.mts +35 -0
  3. package/dist/array/filterAsync.d.ts +35 -0
  4. package/dist/array/filterAsync.js +15 -0
  5. package/dist/array/filterAsync.mjs +11 -0
  6. package/dist/array/flatMapAsync.d.mts +37 -0
  7. package/dist/array/flatMapAsync.d.ts +37 -0
  8. package/dist/array/flatMapAsync.js +16 -0
  9. package/dist/array/flatMapAsync.mjs +12 -0
  10. package/dist/array/forEachAsync.d.mts +35 -0
  11. package/dist/array/forEachAsync.d.ts +35 -0
  12. package/dist/array/forEachAsync.js +14 -0
  13. package/dist/array/forEachAsync.mjs +10 -0
  14. package/dist/array/index.d.mts +6 -0
  15. package/dist/array/index.d.ts +6 -0
  16. package/dist/array/index.js +12 -0
  17. package/dist/array/index.mjs +6 -0
  18. package/dist/array/limitAsync.d.mts +34 -0
  19. package/dist/array/limitAsync.d.ts +34 -0
  20. package/dist/array/limitAsync.js +20 -0
  21. package/dist/array/limitAsync.mjs +16 -0
  22. package/dist/array/mapAsync.d.mts +34 -0
  23. package/dist/array/mapAsync.d.ts +34 -0
  24. package/dist/array/mapAsync.js +14 -0
  25. package/dist/array/mapAsync.mjs +10 -0
  26. package/dist/array/reduceAsync.d.mts +71 -0
  27. package/dist/array/reduceAsync.d.ts +71 -0
  28. package/dist/array/reduceAsync.js +18 -0
  29. package/dist/array/reduceAsync.mjs +14 -0
  30. package/dist/browser.global.js +1 -1
  31. package/dist/compat/object/keys.js +5 -1
  32. package/dist/compat/object/keys.mjs +5 -1
  33. package/dist/compat/object/keysIn.js +5 -1
  34. package/dist/compat/object/keysIn.mjs +5 -1
  35. package/dist/compat/object/updateWith.js +10 -7
  36. package/dist/compat/object/updateWith.mjs +10 -7
  37. package/dist/compat/predicate/isFinite.d.mts +10 -3
  38. package/dist/compat/predicate/isFinite.d.ts +10 -3
  39. package/dist/compat/predicate/isSafeInteger.d.mts +4 -3
  40. package/dist/compat/predicate/isSafeInteger.d.ts +4 -3
  41. package/dist/function/debounce.d.mts +1 -1
  42. package/dist/function/debounce.d.ts +1 -1
  43. package/dist/function/index.d.mts +2 -2
  44. package/dist/function/index.d.ts +2 -2
  45. package/dist/function/throttle.d.mts +2 -2
  46. package/dist/function/throttle.d.ts +2 -2
  47. package/dist/index.d.mts +8 -2
  48. package/dist/index.d.ts +8 -2
  49. package/dist/index.js +12 -0
  50. package/dist/index.mjs +6 -0
  51. package/dist/object/mergeWith.js +1 -1
  52. package/dist/object/mergeWith.mjs +1 -1
  53. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # es-toolkit Changelog
2
2
 
3
+ ## Version v1.42.0
4
+
5
+ Released on November 17th, 2025.
6
+
7
+ - Added new async utilities: `filterAsync`, `flatMapAsync`, `forEachAsync`, `mapAsync`, `reduceAsync`, and `limitAsync` for handling asynchronous operations.
8
+ - Exported `ThrottleOptions` and `DebounceOptions` interfaces for better type support.
9
+ - Fixed `isFinite` to implement type predicate to narrow type to number.
10
+ - Fixed `isSafeInteger` to implement type predicate to narrow type to number.
11
+ - Fixed `omit` to prevent adding index properties to array-like objects.
12
+ - Fixed `mergeWith` to remove unnecessary nullish coalescing for 100% branch coverage.
13
+ - Fixed `compat/updateWith` to remove unreachable code and add prototype pollution test.
14
+ - Updated documentation headings for consistency.
15
+ - Improved test coverage for `compat/mergeWith`, `compat/unset`, `get`, `toMerged`, `mergeWith`, and `compat/intersectionBy` with additional edge cases and security tests.
16
+
17
+ We sincerely thank @Debbl, @wo-o29, @raon0211, @Yeom-JinHo, @sukvvon, and @D-Sketon for their contributions. We appreciate your great efforts!
18
+
3
19
  ## Version v1.41.0
4
20
 
5
21
  Released on October 24th, 2025.
@@ -0,0 +1,35 @@
1
+ interface FilterAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Filters an array asynchronously using an async predicate function.
6
+ *
7
+ * Returns a promise that resolves to a new array containing only the elements
8
+ * for which the predicate function returns a truthy value.
9
+ *
10
+ * @template T - The type of elements in the array.
11
+ * @param {readonly T[]} array The array to filter.
12
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<boolean>} predicate An async function that tests each element.
13
+ * @param {FilterAsyncOptions} [options] Optional configuration object.
14
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
15
+ * @returns {Promise<T[]>} A promise that resolves to the filtered array.
16
+ * @example
17
+ * const users = [{ id: 1, active: true }, { id: 2, active: false }, { id: 3, active: true }];
18
+ * const activeUsers = await filterAsync(users, async (user) => {
19
+ * return await checkUserStatus(user.id);
20
+ * });
21
+ * // Returns: [{ id: 1, active: true }, { id: 3, active: true }]
22
+ *
23
+ * @example
24
+ * // With concurrency limit
25
+ * const numbers = [1, 2, 3, 4, 5];
26
+ * const evenNumbers = await filterAsync(
27
+ * numbers,
28
+ * async (n) => await isEvenAsync(n),
29
+ * { concurrency: 2 }
30
+ * );
31
+ * // Processes at most 2 operations concurrently
32
+ */
33
+ declare function filterAsync<T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => Promise<boolean>, options?: FilterAsyncOptions): Promise<T[]>;
34
+
35
+ export { filterAsync };
@@ -0,0 +1,35 @@
1
+ interface FilterAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Filters an array asynchronously using an async predicate function.
6
+ *
7
+ * Returns a promise that resolves to a new array containing only the elements
8
+ * for which the predicate function returns a truthy value.
9
+ *
10
+ * @template T - The type of elements in the array.
11
+ * @param {readonly T[]} array The array to filter.
12
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<boolean>} predicate An async function that tests each element.
13
+ * @param {FilterAsyncOptions} [options] Optional configuration object.
14
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
15
+ * @returns {Promise<T[]>} A promise that resolves to the filtered array.
16
+ * @example
17
+ * const users = [{ id: 1, active: true }, { id: 2, active: false }, { id: 3, active: true }];
18
+ * const activeUsers = await filterAsync(users, async (user) => {
19
+ * return await checkUserStatus(user.id);
20
+ * });
21
+ * // Returns: [{ id: 1, active: true }, { id: 3, active: true }]
22
+ *
23
+ * @example
24
+ * // With concurrency limit
25
+ * const numbers = [1, 2, 3, 4, 5];
26
+ * const evenNumbers = await filterAsync(
27
+ * numbers,
28
+ * async (n) => await isEvenAsync(n),
29
+ * { concurrency: 2 }
30
+ * );
31
+ * // Processes at most 2 operations concurrently
32
+ */
33
+ declare function filterAsync<T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => Promise<boolean>, options?: FilterAsyncOptions): Promise<T[]>;
34
+
35
+ export { filterAsync };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const limitAsync = require('./limitAsync.js');
6
+
7
+ async function filterAsync(array, predicate, options) {
8
+ if (options?.concurrency != null) {
9
+ predicate = limitAsync.limitAsync(predicate, options.concurrency);
10
+ }
11
+ const results = await Promise.all(array.map(predicate));
12
+ return array.filter((_, index) => results[index]);
13
+ }
14
+
15
+ exports.filterAsync = filterAsync;
@@ -0,0 +1,11 @@
1
+ import { limitAsync } from './limitAsync.mjs';
2
+
3
+ async function filterAsync(array, predicate, options) {
4
+ if (options?.concurrency != null) {
5
+ predicate = limitAsync(predicate, options.concurrency);
6
+ }
7
+ const results = await Promise.all(array.map(predicate));
8
+ return array.filter((_, index) => results[index]);
9
+ }
10
+
11
+ export { filterAsync };
@@ -0,0 +1,37 @@
1
+ interface FlatMapAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Maps each element in an array using an async callback function and flattens the result by one level.
6
+ *
7
+ * This is equivalent to calling `mapAsync` followed by `flat(1)`, but more efficient.
8
+ * Each callback should return an array, and all returned arrays are concatenated into
9
+ * a single output array.
10
+ *
11
+ * @template T - The type of elements in the input array.
12
+ * @template R - The type of elements in the arrays returned by the callback.
13
+ * @param {readonly T[]} array The array to transform.
14
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<R[]>} callback An async function that transforms each element into an array.
15
+ * @param {FlatMapAsyncOptions} [options] Optional configuration object.
16
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
17
+ * @returns {Promise<R[]>} A promise that resolves to a flattened array of transformed values.
18
+ * @example
19
+ * const users = [{ id: 1 }, { id: 2 }];
20
+ * const allPosts = await flatMapAsync(users, async (user) => {
21
+ * return await fetchUserPosts(user.id);
22
+ * });
23
+ * // Returns: [post1, post2, post3, ...] (all posts from all users)
24
+ *
25
+ * @example
26
+ * // With concurrency limit
27
+ * const numbers = [1, 2, 3];
28
+ * const results = await flatMapAsync(
29
+ * numbers,
30
+ * async (n) => await fetchRelatedItems(n),
31
+ * { concurrency: 2 }
32
+ * );
33
+ * // Processes at most 2 operations concurrently
34
+ */
35
+ declare function flatMapAsync<T, R>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<R[]>, options?: FlatMapAsyncOptions): Promise<R[]>;
36
+
37
+ export { flatMapAsync };
@@ -0,0 +1,37 @@
1
+ interface FlatMapAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Maps each element in an array using an async callback function and flattens the result by one level.
6
+ *
7
+ * This is equivalent to calling `mapAsync` followed by `flat(1)`, but more efficient.
8
+ * Each callback should return an array, and all returned arrays are concatenated into
9
+ * a single output array.
10
+ *
11
+ * @template T - The type of elements in the input array.
12
+ * @template R - The type of elements in the arrays returned by the callback.
13
+ * @param {readonly T[]} array The array to transform.
14
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<R[]>} callback An async function that transforms each element into an array.
15
+ * @param {FlatMapAsyncOptions} [options] Optional configuration object.
16
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
17
+ * @returns {Promise<R[]>} A promise that resolves to a flattened array of transformed values.
18
+ * @example
19
+ * const users = [{ id: 1 }, { id: 2 }];
20
+ * const allPosts = await flatMapAsync(users, async (user) => {
21
+ * return await fetchUserPosts(user.id);
22
+ * });
23
+ * // Returns: [post1, post2, post3, ...] (all posts from all users)
24
+ *
25
+ * @example
26
+ * // With concurrency limit
27
+ * const numbers = [1, 2, 3];
28
+ * const results = await flatMapAsync(
29
+ * numbers,
30
+ * async (n) => await fetchRelatedItems(n),
31
+ * { concurrency: 2 }
32
+ * );
33
+ * // Processes at most 2 operations concurrently
34
+ */
35
+ declare function flatMapAsync<T, R>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<R[]>, options?: FlatMapAsyncOptions): Promise<R[]>;
36
+
37
+ export { flatMapAsync };
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const flatten = require('./flatten.js');
6
+ const limitAsync = require('./limitAsync.js');
7
+
8
+ async function flatMapAsync(array, callback, options) {
9
+ if (options?.concurrency != null) {
10
+ callback = limitAsync.limitAsync(callback, options.concurrency);
11
+ }
12
+ const results = await Promise.all(array.map(callback));
13
+ return flatten.flatten(results);
14
+ }
15
+
16
+ exports.flatMapAsync = flatMapAsync;
@@ -0,0 +1,12 @@
1
+ import { flatten } from './flatten.mjs';
2
+ import { limitAsync } from './limitAsync.mjs';
3
+
4
+ async function flatMapAsync(array, callback, options) {
5
+ if (options?.concurrency != null) {
6
+ callback = limitAsync(callback, options.concurrency);
7
+ }
8
+ const results = await Promise.all(array.map(callback));
9
+ return flatten(results);
10
+ }
11
+
12
+ export { flatMapAsync };
@@ -0,0 +1,35 @@
1
+ interface ForEachAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Executes an async callback function for each element in an array.
6
+ *
7
+ * Unlike the native `forEach`, this function returns a promise that resolves
8
+ * when all async operations complete. It supports optional concurrency limiting.
9
+ *
10
+ * @template T - The type of elements in the array.
11
+ * @param {readonly T[]} array The array to iterate over.
12
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<void>} callback An async function to execute for each element.
13
+ * @param {ForEachAsyncOptions} [options] Optional configuration object.
14
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
15
+ * @returns {Promise<void>} A promise that resolves when all operations complete.
16
+ * @example
17
+ * const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
18
+ * await forEachAsync(users, async (user) => {
19
+ * await updateUser(user.id);
20
+ * });
21
+ * // All users have been updated
22
+ *
23
+ * @example
24
+ * // With concurrency limit
25
+ * const items = [1, 2, 3, 4, 5];
26
+ * await forEachAsync(
27
+ * items,
28
+ * async (item) => await processItem(item),
29
+ * { concurrency: 2 }
30
+ * );
31
+ * // Processes at most 2 items concurrently
32
+ */
33
+ declare function forEachAsync<T>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<void>, options?: ForEachAsyncOptions): Promise<void>;
34
+
35
+ export { forEachAsync };
@@ -0,0 +1,35 @@
1
+ interface ForEachAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Executes an async callback function for each element in an array.
6
+ *
7
+ * Unlike the native `forEach`, this function returns a promise that resolves
8
+ * when all async operations complete. It supports optional concurrency limiting.
9
+ *
10
+ * @template T - The type of elements in the array.
11
+ * @param {readonly T[]} array The array to iterate over.
12
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<void>} callback An async function to execute for each element.
13
+ * @param {ForEachAsyncOptions} [options] Optional configuration object.
14
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
15
+ * @returns {Promise<void>} A promise that resolves when all operations complete.
16
+ * @example
17
+ * const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
18
+ * await forEachAsync(users, async (user) => {
19
+ * await updateUser(user.id);
20
+ * });
21
+ * // All users have been updated
22
+ *
23
+ * @example
24
+ * // With concurrency limit
25
+ * const items = [1, 2, 3, 4, 5];
26
+ * await forEachAsync(
27
+ * items,
28
+ * async (item) => await processItem(item),
29
+ * { concurrency: 2 }
30
+ * );
31
+ * // Processes at most 2 items concurrently
32
+ */
33
+ declare function forEachAsync<T>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<void>, options?: ForEachAsyncOptions): Promise<void>;
34
+
35
+ export { forEachAsync };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const limitAsync = require('./limitAsync.js');
6
+
7
+ async function forEachAsync(array, callback, options) {
8
+ if (options?.concurrency != null) {
9
+ callback = limitAsync.limitAsync(callback, options.concurrency);
10
+ }
11
+ await Promise.all(array.map(callback));
12
+ }
13
+
14
+ exports.forEachAsync = forEachAsync;
@@ -0,0 +1,10 @@
1
+ import { limitAsync } from './limitAsync.mjs';
2
+
3
+ async function forEachAsync(array, callback, options) {
4
+ if (options?.concurrency != null) {
5
+ callback = limitAsync(callback, options.concurrency);
6
+ }
7
+ await Promise.all(array.map(callback));
8
+ }
9
+
10
+ export { forEachAsync };
@@ -10,10 +10,13 @@ export { dropRight } from './dropRight.mjs';
10
10
  export { dropRightWhile } from './dropRightWhile.mjs';
11
11
  export { dropWhile } from './dropWhile.mjs';
12
12
  export { fill } from './fill.mjs';
13
+ export { filterAsync } from './filterAsync.mjs';
13
14
  export { flatMap } from './flatMap.mjs';
15
+ export { flatMapAsync } from './flatMapAsync.mjs';
14
16
  export { flatMapDeep } from './flatMapDeep.mjs';
15
17
  export { flatten } from './flatten.mjs';
16
18
  export { flattenDeep } from './flattenDeep.mjs';
19
+ export { forEachAsync } from './forEachAsync.mjs';
17
20
  export { forEachRight } from './forEachRight.mjs';
18
21
  export { groupBy } from './groupBy.mjs';
19
22
  export { head } from './head.mjs';
@@ -25,12 +28,15 @@ export { isSubset } from './isSubset.mjs';
25
28
  export { isSubsetWith } from './isSubsetWith.mjs';
26
29
  export { keyBy } from './keyBy.mjs';
27
30
  export { last } from './last.mjs';
31
+ export { limitAsync } from './limitAsync.mjs';
32
+ export { mapAsync } from './mapAsync.mjs';
28
33
  export { maxBy } from './maxBy.mjs';
29
34
  export { minBy } from './minBy.mjs';
30
35
  export { orderBy } from './orderBy.mjs';
31
36
  export { partition } from './partition.mjs';
32
37
  export { pull } from './pull.mjs';
33
38
  export { pullAt } from './pullAt.mjs';
39
+ export { reduceAsync } from './reduceAsync.mjs';
34
40
  export { remove } from './remove.mjs';
35
41
  export { sample } from './sample.mjs';
36
42
  export { sampleSize } from './sampleSize.mjs';
@@ -10,10 +10,13 @@ export { dropRight } from './dropRight.js';
10
10
  export { dropRightWhile } from './dropRightWhile.js';
11
11
  export { dropWhile } from './dropWhile.js';
12
12
  export { fill } from './fill.js';
13
+ export { filterAsync } from './filterAsync.js';
13
14
  export { flatMap } from './flatMap.js';
15
+ export { flatMapAsync } from './flatMapAsync.js';
14
16
  export { flatMapDeep } from './flatMapDeep.js';
15
17
  export { flatten } from './flatten.js';
16
18
  export { flattenDeep } from './flattenDeep.js';
19
+ export { forEachAsync } from './forEachAsync.js';
17
20
  export { forEachRight } from './forEachRight.js';
18
21
  export { groupBy } from './groupBy.js';
19
22
  export { head } from './head.js';
@@ -25,12 +28,15 @@ export { isSubset } from './isSubset.js';
25
28
  export { isSubsetWith } from './isSubsetWith.js';
26
29
  export { keyBy } from './keyBy.js';
27
30
  export { last } from './last.js';
31
+ export { limitAsync } from './limitAsync.js';
32
+ export { mapAsync } from './mapAsync.js';
28
33
  export { maxBy } from './maxBy.js';
29
34
  export { minBy } from './minBy.js';
30
35
  export { orderBy } from './orderBy.js';
31
36
  export { partition } from './partition.js';
32
37
  export { pull } from './pull.js';
33
38
  export { pullAt } from './pullAt.js';
39
+ export { reduceAsync } from './reduceAsync.js';
34
40
  export { remove } from './remove.js';
35
41
  export { sample } from './sample.js';
36
42
  export { sampleSize } from './sampleSize.js';
@@ -14,10 +14,13 @@ const dropRight = require('./dropRight.js');
14
14
  const dropRightWhile = require('./dropRightWhile.js');
15
15
  const dropWhile = require('./dropWhile.js');
16
16
  const fill = require('./fill.js');
17
+ const filterAsync = require('./filterAsync.js');
17
18
  const flatMap = require('./flatMap.js');
19
+ const flatMapAsync = require('./flatMapAsync.js');
18
20
  const flatMapDeep = require('./flatMapDeep.js');
19
21
  const flatten = require('./flatten.js');
20
22
  const flattenDeep = require('./flattenDeep.js');
23
+ const forEachAsync = require('./forEachAsync.js');
21
24
  const forEachRight = require('./forEachRight.js');
22
25
  const groupBy = require('./groupBy.js');
23
26
  const head = require('./head.js');
@@ -29,12 +32,15 @@ const isSubset = require('./isSubset.js');
29
32
  const isSubsetWith = require('./isSubsetWith.js');
30
33
  const keyBy = require('./keyBy.js');
31
34
  const last = require('./last.js');
35
+ const limitAsync = require('./limitAsync.js');
36
+ const mapAsync = require('./mapAsync.js');
32
37
  const maxBy = require('./maxBy.js');
33
38
  const minBy = require('./minBy.js');
34
39
  const orderBy = require('./orderBy.js');
35
40
  const partition = require('./partition.js');
36
41
  const pull = require('./pull.js');
37
42
  const pullAt = require('./pullAt.js');
43
+ const reduceAsync = require('./reduceAsync.js');
38
44
  const remove = require('./remove.js');
39
45
  const sample = require('./sample.js');
40
46
  const sampleSize = require('./sampleSize.js');
@@ -77,10 +83,13 @@ exports.dropRight = dropRight.dropRight;
77
83
  exports.dropRightWhile = dropRightWhile.dropRightWhile;
78
84
  exports.dropWhile = dropWhile.dropWhile;
79
85
  exports.fill = fill.fill;
86
+ exports.filterAsync = filterAsync.filterAsync;
80
87
  exports.flatMap = flatMap.flatMap;
88
+ exports.flatMapAsync = flatMapAsync.flatMapAsync;
81
89
  exports.flatMapDeep = flatMapDeep.flatMapDeep;
82
90
  exports.flatten = flatten.flatten;
83
91
  exports.flattenDeep = flattenDeep.flattenDeep;
92
+ exports.forEachAsync = forEachAsync.forEachAsync;
84
93
  exports.forEachRight = forEachRight.forEachRight;
85
94
  exports.groupBy = groupBy.groupBy;
86
95
  exports.head = head.head;
@@ -92,12 +101,15 @@ exports.isSubset = isSubset.isSubset;
92
101
  exports.isSubsetWith = isSubsetWith.isSubsetWith;
93
102
  exports.keyBy = keyBy.keyBy;
94
103
  exports.last = last.last;
104
+ exports.limitAsync = limitAsync.limitAsync;
105
+ exports.mapAsync = mapAsync.mapAsync;
95
106
  exports.maxBy = maxBy.maxBy;
96
107
  exports.minBy = minBy.minBy;
97
108
  exports.orderBy = orderBy.orderBy;
98
109
  exports.partition = partition.partition;
99
110
  exports.pull = pull.pull;
100
111
  exports.pullAt = pullAt.pullAt;
112
+ exports.reduceAsync = reduceAsync.reduceAsync;
101
113
  exports.remove = remove.remove;
102
114
  exports.sample = sample.sample;
103
115
  exports.sampleSize = sampleSize.sampleSize;
@@ -10,10 +10,13 @@ export { dropRight } from './dropRight.mjs';
10
10
  export { dropRightWhile } from './dropRightWhile.mjs';
11
11
  export { dropWhile } from './dropWhile.mjs';
12
12
  export { fill } from './fill.mjs';
13
+ export { filterAsync } from './filterAsync.mjs';
13
14
  export { flatMap } from './flatMap.mjs';
15
+ export { flatMapAsync } from './flatMapAsync.mjs';
14
16
  export { flatMapDeep } from './flatMapDeep.mjs';
15
17
  export { flatten } from './flatten.mjs';
16
18
  export { flattenDeep } from './flattenDeep.mjs';
19
+ export { forEachAsync } from './forEachAsync.mjs';
17
20
  export { forEachRight } from './forEachRight.mjs';
18
21
  export { groupBy } from './groupBy.mjs';
19
22
  export { head } from './head.mjs';
@@ -25,12 +28,15 @@ export { isSubset } from './isSubset.mjs';
25
28
  export { isSubsetWith } from './isSubsetWith.mjs';
26
29
  export { keyBy } from './keyBy.mjs';
27
30
  export { last } from './last.mjs';
31
+ export { limitAsync } from './limitAsync.mjs';
32
+ export { mapAsync } from './mapAsync.mjs';
28
33
  export { maxBy } from './maxBy.mjs';
29
34
  export { minBy } from './minBy.mjs';
30
35
  export { orderBy } from './orderBy.mjs';
31
36
  export { partition } from './partition.mjs';
32
37
  export { pull } from './pull.mjs';
33
38
  export { pullAt } from './pullAt.mjs';
39
+ export { reduceAsync } from './reduceAsync.mjs';
34
40
  export { remove } from './remove.mjs';
35
41
  export { sample } from './sample.mjs';
36
42
  export { sampleSize } from './sampleSize.mjs';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Wraps an async function to limit the number of concurrent executions.
3
+ *
4
+ * This function creates a wrapper around an async callback that ensures at most
5
+ * `concurrency` number of executions can run simultaneously. Additional calls will
6
+ * wait until a slot becomes available.
7
+ *
8
+ * @template F - The type of the async function to wrap.
9
+ * @param {F} callback The async function to wrap with concurrency control.
10
+ * @param {number} concurrency Maximum number of concurrent executions allowed.
11
+ * @returns {F} A wrapped version of the callback with concurrency limiting.
12
+ * @example
13
+ * const limitedFetch = limitAsync(async (url) => {
14
+ * return await fetch(url);
15
+ * }, 3);
16
+ *
17
+ * // Only 3 fetches will run concurrently
18
+ * const urls = ['url1', 'url2', 'url3', 'url4', 'url5'];
19
+ * await Promise.all(urls.map(url => limitedFetch(url)));
20
+ *
21
+ * @example
22
+ * const processItem = async (item) => {
23
+ * // Expensive async operation
24
+ * return await heavyComputation(item);
25
+ * };
26
+ *
27
+ * const limitedProcess = limitAsync(processItem, 2);
28
+ * const items = [1, 2, 3, 4, 5];
29
+ * // At most 2 items will be processed concurrently
30
+ * await Promise.all(items.map(item => limitedProcess(item)));
31
+ */
32
+ declare function limitAsync<F extends (...args: any[]) => Promise<any>>(callback: F, concurrency: number): F;
33
+
34
+ export { limitAsync };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Wraps an async function to limit the number of concurrent executions.
3
+ *
4
+ * This function creates a wrapper around an async callback that ensures at most
5
+ * `concurrency` number of executions can run simultaneously. Additional calls will
6
+ * wait until a slot becomes available.
7
+ *
8
+ * @template F - The type of the async function to wrap.
9
+ * @param {F} callback The async function to wrap with concurrency control.
10
+ * @param {number} concurrency Maximum number of concurrent executions allowed.
11
+ * @returns {F} A wrapped version of the callback with concurrency limiting.
12
+ * @example
13
+ * const limitedFetch = limitAsync(async (url) => {
14
+ * return await fetch(url);
15
+ * }, 3);
16
+ *
17
+ * // Only 3 fetches will run concurrently
18
+ * const urls = ['url1', 'url2', 'url3', 'url4', 'url5'];
19
+ * await Promise.all(urls.map(url => limitedFetch(url)));
20
+ *
21
+ * @example
22
+ * const processItem = async (item) => {
23
+ * // Expensive async operation
24
+ * return await heavyComputation(item);
25
+ * };
26
+ *
27
+ * const limitedProcess = limitAsync(processItem, 2);
28
+ * const items = [1, 2, 3, 4, 5];
29
+ * // At most 2 items will be processed concurrently
30
+ * await Promise.all(items.map(item => limitedProcess(item)));
31
+ */
32
+ declare function limitAsync<F extends (...args: any[]) => Promise<any>>(callback: F, concurrency: number): F;
33
+
34
+ export { limitAsync };
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const semaphore = require('../promise/semaphore.js');
6
+
7
+ function limitAsync(callback, concurrency) {
8
+ const semaphore$1 = new semaphore.Semaphore(concurrency);
9
+ return async function (...args) {
10
+ try {
11
+ await semaphore$1.acquire();
12
+ return await callback.apply(this, args);
13
+ }
14
+ finally {
15
+ semaphore$1.release();
16
+ }
17
+ };
18
+ }
19
+
20
+ exports.limitAsync = limitAsync;
@@ -0,0 +1,16 @@
1
+ import { Semaphore } from '../promise/semaphore.mjs';
2
+
3
+ function limitAsync(callback, concurrency) {
4
+ const semaphore = new Semaphore(concurrency);
5
+ return async function (...args) {
6
+ try {
7
+ await semaphore.acquire();
8
+ return await callback.apply(this, args);
9
+ }
10
+ finally {
11
+ semaphore.release();
12
+ }
13
+ };
14
+ }
15
+
16
+ export { limitAsync };
@@ -0,0 +1,34 @@
1
+ interface MapAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Transforms each element in an array using an async callback function and returns
6
+ * a promise that resolves to an array of transformed values.
7
+ *
8
+ * @template T - The type of elements in the input array.
9
+ * @template R - The type of elements in the output array.
10
+ * @param {readonly T[]} array The array to transform.
11
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<R>} callback An async function that transforms each element.
12
+ * @param {MapAsyncOptions} [options] Optional configuration object.
13
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
14
+ * @returns {Promise<R[]>} A promise that resolves to an array of transformed values.
15
+ * @example
16
+ * const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
17
+ * const userDetails = await mapAsync(users, async (user) => {
18
+ * return await fetchUserDetails(user.id);
19
+ * });
20
+ * // Returns: [{ id: 1, name: '...' }, { id: 2, name: '...' }, { id: 3, name: '...' }]
21
+ *
22
+ * @example
23
+ * // With concurrency limit
24
+ * const numbers = [1, 2, 3, 4, 5];
25
+ * const results = await mapAsync(
26
+ * numbers,
27
+ * async (n) => await slowOperation(n),
28
+ * { concurrency: 2 }
29
+ * );
30
+ * // Processes at most 2 operations concurrently
31
+ */
32
+ declare function mapAsync<T, R>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<R>, options?: MapAsyncOptions): Promise<R[]>;
33
+
34
+ export { mapAsync };
@@ -0,0 +1,34 @@
1
+ interface MapAsyncOptions {
2
+ concurrency?: number;
3
+ }
4
+ /**
5
+ * Transforms each element in an array using an async callback function and returns
6
+ * a promise that resolves to an array of transformed values.
7
+ *
8
+ * @template T - The type of elements in the input array.
9
+ * @template R - The type of elements in the output array.
10
+ * @param {readonly T[]} array The array to transform.
11
+ * @param {(item: T, index: number, array: readonly T[]) => Promise<R>} callback An async function that transforms each element.
12
+ * @param {MapAsyncOptions} [options] Optional configuration object.
13
+ * @param {number} [options.concurrency] Maximum number of concurrent async operations. If not specified, all operations run concurrently.
14
+ * @returns {Promise<R[]>} A promise that resolves to an array of transformed values.
15
+ * @example
16
+ * const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
17
+ * const userDetails = await mapAsync(users, async (user) => {
18
+ * return await fetchUserDetails(user.id);
19
+ * });
20
+ * // Returns: [{ id: 1, name: '...' }, { id: 2, name: '...' }, { id: 3, name: '...' }]
21
+ *
22
+ * @example
23
+ * // With concurrency limit
24
+ * const numbers = [1, 2, 3, 4, 5];
25
+ * const results = await mapAsync(
26
+ * numbers,
27
+ * async (n) => await slowOperation(n),
28
+ * { concurrency: 2 }
29
+ * );
30
+ * // Processes at most 2 operations concurrently
31
+ */
32
+ declare function mapAsync<T, R>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<R>, options?: MapAsyncOptions): Promise<R[]>;
33
+
34
+ export { mapAsync };