@catbee/utils 0.0.1 → 0.0.3
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 +303 -107
- package/build/esm/config.d.ts +13 -1
- package/build/esm/config.js +16 -4
- package/build/esm/config.js.map +1 -1
- package/build/esm/index.d.ts +20 -18
- package/build/esm/index.js +20 -18
- package/build/esm/index.js.map +1 -1
- package/build/esm/types/api-response.d.ts +83 -1
- package/build/esm/types/api-response.js.map +1 -1
- package/build/esm/utils/array.utils.d.ts +65 -2
- package/build/esm/utils/array.utils.js +147 -20
- package/build/esm/utils/array.utils.js.map +1 -1
- package/build/esm/utils/async.utils.d.ts +56 -1
- package/build/esm/utils/async.utils.js +166 -11
- package/build/esm/utils/async.utils.js.map +1 -1
- package/build/esm/utils/cache.utils.d.ts +67 -4
- package/build/esm/utils/cache.utils.js +210 -28
- package/build/esm/utils/cache.utils.js.map +1 -1
- package/build/esm/utils/context-store.utils.d.ts +102 -1
- package/build/esm/utils/context-store.utils.js +185 -3
- package/build/esm/utils/context-store.utils.js.map +1 -1
- package/build/esm/utils/crypto.utils.d.ts +110 -8
- package/build/esm/utils/crypto.utils.js +298 -23
- package/build/esm/utils/crypto.utils.js.map +1 -1
- package/build/esm/utils/decorators.utils.d.ts +40 -0
- package/build/esm/utils/decorators.utils.js +312 -0
- package/build/esm/utils/decorators.utils.js.map +1 -0
- package/build/esm/utils/dir.utils.d.ts +122 -1
- package/build/esm/utils/dir.utils.js +578 -3
- package/build/esm/utils/dir.utils.js.map +1 -1
- package/build/esm/utils/env.utils.d.ts +83 -0
- package/build/esm/utils/env.utils.js +235 -6
- package/build/esm/utils/env.utils.js.map +1 -1
- package/build/esm/utils/exception.utils.d.ts +117 -1
- package/build/esm/utils/exception.utils.js +331 -12
- package/build/esm/utils/exception.utils.js.map +1 -1
- package/build/esm/utils/fs.utils.d.ts +132 -0
- package/build/esm/utils/fs.utils.js +421 -4
- package/build/esm/utils/fs.utils.js.map +1 -1
- package/build/esm/utils/http-status-codes.d.ts +87 -178
- package/build/esm/utils/http-status-codes.js +92 -178
- package/build/esm/utils/http-status-codes.js.map +1 -1
- package/build/esm/utils/id.utils.d.ts +11 -10
- package/build/esm/utils/id.utils.js +30 -21
- package/build/esm/utils/id.utils.js.map +1 -1
- package/build/esm/utils/logger.utils.d.ts +35 -2
- package/build/esm/utils/logger.utils.js +68 -14
- package/build/esm/utils/logger.utils.js.map +1 -1
- package/build/esm/utils/middleware.utils.d.ts +73 -0
- package/build/esm/utils/middleware.utils.js +158 -0
- package/build/esm/utils/middleware.utils.js.map +1 -0
- package/build/esm/utils/obj.utils.d.ts +65 -3
- package/build/esm/utils/obj.utils.js +206 -18
- package/build/esm/utils/obj.utils.js.map +1 -1
- package/build/esm/utils/response.utils.d.ts +103 -2
- package/build/esm/utils/response.utils.js +156 -3
- package/build/esm/utils/response.utils.js.map +1 -1
- package/build/esm/utils/string.utils.d.ts +61 -5
- package/build/esm/utils/string.utils.js +109 -19
- package/build/esm/utils/string.utils.js.map +1 -1
- package/build/esm/utils/url.utils.d.ts +117 -0
- package/build/esm/utils/url.utils.js +287 -2
- package/build/esm/utils/url.utils.js.map +1 -1
- package/build/esm/utils/validate.utils.d.ts +110 -0
- package/build/esm/utils/validate.utils.js +190 -8
- package/build/esm/utils/validate.utils.js.map +1 -1
- package/build/esnext/config.d.ts +13 -1
- package/build/esnext/config.js +16 -4
- package/build/esnext/config.js.map +1 -1
- package/build/esnext/index.d.ts +20 -18
- package/build/esnext/index.js +20 -18
- package/build/esnext/index.js.map +1 -1
- package/build/esnext/types/api-response.d.ts +83 -1
- package/build/esnext/types/api-response.js.map +1 -1
- package/build/esnext/utils/array.utils.d.ts +65 -2
- package/build/esnext/utils/array.utils.js +140 -21
- package/build/esnext/utils/array.utils.js.map +1 -1
- package/build/esnext/utils/async.utils.d.ts +56 -1
- package/build/esnext/utils/async.utils.js +130 -14
- package/build/esnext/utils/async.utils.js.map +1 -1
- package/build/esnext/utils/cache.utils.d.ts +67 -4
- package/build/esnext/utils/cache.utils.js +137 -9
- package/build/esnext/utils/cache.utils.js.map +1 -1
- package/build/esnext/utils/context-store.utils.d.ts +102 -1
- package/build/esnext/utils/context-store.utils.js +171 -3
- package/build/esnext/utils/context-store.utils.js.map +1 -1
- package/build/esnext/utils/crypto.utils.d.ts +110 -8
- package/build/esnext/utils/crypto.utils.js +199 -19
- package/build/esnext/utils/crypto.utils.js.map +1 -1
- package/build/esnext/utils/decorators.utils.d.ts +40 -0
- package/build/esnext/utils/decorators.utils.js +155 -0
- package/build/esnext/utils/decorators.utils.js.map +1 -0
- package/build/esnext/utils/dir.utils.d.ts +122 -1
- package/build/esnext/utils/dir.utils.js +307 -3
- package/build/esnext/utils/dir.utils.js.map +1 -1
- package/build/esnext/utils/env.utils.d.ts +83 -0
- package/build/esnext/utils/env.utils.js +191 -8
- package/build/esnext/utils/env.utils.js.map +1 -1
- package/build/esnext/utils/exception.utils.d.ts +117 -1
- package/build/esnext/utils/exception.utils.js +222 -12
- package/build/esnext/utils/exception.utils.js.map +1 -1
- package/build/esnext/utils/fs.utils.d.ts +132 -0
- package/build/esnext/utils/fs.utils.js +268 -4
- package/build/esnext/utils/fs.utils.js.map +1 -1
- package/build/esnext/utils/http-status-codes.d.ts +87 -178
- package/build/esnext/utils/http-status-codes.js +92 -178
- package/build/esnext/utils/http-status-codes.js.map +1 -1
- package/build/esnext/utils/id.utils.d.ts +11 -10
- package/build/esnext/utils/id.utils.js +28 -20
- package/build/esnext/utils/id.utils.js.map +1 -1
- package/build/esnext/utils/logger.utils.d.ts +35 -2
- package/build/esnext/utils/logger.utils.js +56 -14
- package/build/esnext/utils/logger.utils.js.map +1 -1
- package/build/esnext/utils/middleware.utils.d.ts +73 -0
- package/build/esnext/utils/middleware.utils.js +157 -0
- package/build/esnext/utils/middleware.utils.js.map +1 -0
- package/build/esnext/utils/obj.utils.d.ts +65 -3
- package/build/esnext/utils/obj.utils.js +169 -14
- package/build/esnext/utils/obj.utils.js.map +1 -1
- package/build/esnext/utils/response.utils.d.ts +103 -2
- package/build/esnext/utils/response.utils.js +141 -3
- package/build/esnext/utils/response.utils.js.map +1 -1
- package/build/esnext/utils/string.utils.d.ts +61 -5
- package/build/esnext/utils/string.utils.js +110 -14
- package/build/esnext/utils/string.utils.js.map +1 -1
- package/build/esnext/utils/url.utils.d.ts +117 -0
- package/build/esnext/utils/url.utils.js +248 -2
- package/build/esnext/utils/url.utils.js.map +1 -1
- package/build/esnext/utils/validate.utils.d.ts +110 -0
- package/build/esnext/utils/validate.utils.js +190 -8
- package/build/esnext/utils/validate.utils.js.map +1 -1
- package/build/src/config.d.ts +13 -1
- package/build/src/config.js +15 -3
- package/build/src/config.js.map +1 -1
- package/build/src/index.d.ts +20 -18
- package/build/src/index.js +2 -0
- package/build/src/index.js.map +1 -1
- package/build/src/types/api-response.d.ts +83 -1
- package/build/src/types/api-response.js.map +1 -1
- package/build/src/utils/array.utils.d.ts +65 -2
- package/build/src/utils/array.utils.js +147 -22
- package/build/src/utils/array.utils.js.map +1 -1
- package/build/src/utils/async.utils.d.ts +56 -1
- package/build/src/utils/async.utils.js +137 -17
- package/build/src/utils/async.utils.js.map +1 -1
- package/build/src/utils/cache.utils.d.ts +67 -4
- package/build/src/utils/cache.utils.js +137 -9
- package/build/src/utils/cache.utils.js.map +1 -1
- package/build/src/utils/context-store.utils.d.ts +102 -1
- package/build/src/utils/context-store.utils.js +173 -3
- package/build/src/utils/context-store.utils.js.map +1 -1
- package/build/src/utils/crypto.utils.d.ts +110 -8
- package/build/src/utils/crypto.utils.js +214 -27
- package/build/src/utils/crypto.utils.js.map +1 -1
- package/build/src/utils/decorators.utils.d.ts +40 -0
- package/build/src/utils/decorators.utils.js +165 -0
- package/build/src/utils/decorators.utils.js.map +1 -0
- package/build/src/utils/dir.utils.d.ts +122 -1
- package/build/src/utils/dir.utils.js +314 -0
- package/build/src/utils/dir.utils.js.map +1 -1
- package/build/src/utils/env.utils.d.ts +83 -0
- package/build/src/utils/env.utils.js +192 -9
- package/build/src/utils/env.utils.js.map +1 -1
- package/build/src/utils/exception.utils.d.ts +117 -1
- package/build/src/utils/exception.utils.js +233 -11
- package/build/src/utils/exception.utils.js.map +1 -1
- package/build/src/utils/fs.utils.d.ts +132 -0
- package/build/src/utils/fs.utils.js +281 -3
- package/build/src/utils/fs.utils.js.map +1 -1
- package/build/src/utils/http-status-codes.d.ts +87 -178
- package/build/src/utils/http-status-codes.js +92 -178
- package/build/src/utils/http-status-codes.js.map +1 -1
- package/build/src/utils/id.utils.d.ts +11 -10
- package/build/src/utils/id.utils.js +28 -20
- package/build/src/utils/id.utils.js.map +1 -1
- package/build/src/utils/logger.utils.d.ts +35 -2
- package/build/src/utils/logger.utils.js +56 -11
- package/build/src/utils/logger.utils.js.map +1 -1
- package/build/src/utils/middleware.utils.d.ts +73 -0
- package/build/src/utils/middleware.utils.js +163 -0
- package/build/src/utils/middleware.utils.js.map +1 -0
- package/build/src/utils/obj.utils.d.ts +65 -3
- package/build/src/utils/obj.utils.js +179 -18
- package/build/src/utils/obj.utils.js.map +1 -1
- package/build/src/utils/response.utils.d.ts +103 -2
- package/build/src/utils/response.utils.js +147 -2
- package/build/src/utils/response.utils.js.map +1 -1
- package/build/src/utils/string.utils.d.ts +61 -5
- package/build/src/utils/string.utils.js +122 -20
- package/build/src/utils/string.utils.js.map +1 -1
- package/build/src/utils/url.utils.d.ts +117 -0
- package/build/src/utils/url.utils.js +256 -1
- package/build/src/utils/url.utils.js.map +1 -1
- package/build/src/utils/validate.utils.d.ts +110 -0
- package/build/src/utils/validate.utils.js +204 -8
- package/build/src/utils/validate.utils.js.map +1 -1
- package/package.json +20 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getValueByPath } from
|
|
1
|
+
import { getValueByPath } from './obj.utils';
|
|
2
2
|
/**
|
|
3
3
|
* Splits an array into chunks of the specified size.
|
|
4
4
|
*
|
|
@@ -9,15 +9,15 @@ import { getValueByPath } from "./obj.utils";
|
|
|
9
9
|
* @throws {TypeError} If array is not an array.
|
|
10
10
|
* @throws {Error} If chunk size is not a positive integer.
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
12
|
+
export function chunk(array, size) {
|
|
13
13
|
if (!Array.isArray(array))
|
|
14
|
-
throw new TypeError(
|
|
14
|
+
throw new TypeError('Expected an array');
|
|
15
15
|
if (!array.length)
|
|
16
16
|
return [];
|
|
17
17
|
if (!Number.isInteger(size) || size <= 0)
|
|
18
|
-
throw new Error(
|
|
18
|
+
throw new Error('Chunk size must be a positive integer');
|
|
19
19
|
return Array.from({ length: Math.ceil(array.length / size) }, (_, i) => array.slice(i * size, i * size + size));
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
21
|
/**
|
|
22
22
|
* Removes duplicate values from an array.
|
|
23
23
|
* Optionally enforces uniqueness by a key function.
|
|
@@ -33,7 +33,7 @@ export function unique(array, keyFn) {
|
|
|
33
33
|
if (!keyFn)
|
|
34
34
|
return Array.from(new Set(array));
|
|
35
35
|
const seen = new Set();
|
|
36
|
-
return array.filter(
|
|
36
|
+
return array.filter(item => {
|
|
37
37
|
const key = keyFn(item);
|
|
38
38
|
if (seen.has(key))
|
|
39
39
|
return false;
|
|
@@ -76,9 +76,7 @@ export function random(array) {
|
|
|
76
76
|
export function groupBy(array, keyOrFn) {
|
|
77
77
|
if (!Array.isArray(array) || array.length === 0)
|
|
78
78
|
return {};
|
|
79
|
-
const keyFn = typeof keyOrFn ===
|
|
80
|
-
? keyOrFn
|
|
81
|
-
: (item) => item[keyOrFn];
|
|
79
|
+
const keyFn = typeof keyOrFn === 'function' ? keyOrFn : (item) => item[keyOrFn];
|
|
82
80
|
return array.reduce((acc, item) => {
|
|
83
81
|
const key = keyFn(item);
|
|
84
82
|
if (!acc[key])
|
|
@@ -98,7 +96,7 @@ export function groupBy(array, keyOrFn) {
|
|
|
98
96
|
*/
|
|
99
97
|
export function shuffle(array) {
|
|
100
98
|
if (!Array.isArray(array))
|
|
101
|
-
throw new TypeError(
|
|
99
|
+
throw new TypeError('Expected an array');
|
|
102
100
|
const copy = array.slice();
|
|
103
101
|
for (let i = copy.length - 1; i > 0; i--) {
|
|
104
102
|
const j = Math.floor(Math.random() * (i + 1));
|
|
@@ -118,7 +116,7 @@ export function shuffle(array) {
|
|
|
118
116
|
export function pluck(array, key) {
|
|
119
117
|
if (!Array.isArray(array))
|
|
120
118
|
return [];
|
|
121
|
-
return array.map(
|
|
119
|
+
return array.map(item => item[key]);
|
|
122
120
|
}
|
|
123
121
|
/**
|
|
124
122
|
* Returns values in array A that are not in array B.
|
|
@@ -132,7 +130,7 @@ export function difference(a, b) {
|
|
|
132
130
|
if (!Array.isArray(a) || !Array.isArray(b))
|
|
133
131
|
return [];
|
|
134
132
|
const setB = new Set(b);
|
|
135
|
-
return a.filter(
|
|
133
|
+
return a.filter(item => !setB.has(item));
|
|
136
134
|
}
|
|
137
135
|
/**
|
|
138
136
|
* Returns common values between arrays A and B.
|
|
@@ -146,7 +144,7 @@ export function intersect(a, b) {
|
|
|
146
144
|
if (!Array.isArray(a) || !Array.isArray(b))
|
|
147
145
|
return [];
|
|
148
146
|
const setB = new Set(b);
|
|
149
|
-
return a.filter(
|
|
147
|
+
return a.filter(item => setB.has(item));
|
|
150
148
|
}
|
|
151
149
|
/**
|
|
152
150
|
* Sorts an array of objects by a nested key using Merge Sort (O(n log n)).
|
|
@@ -159,14 +157,12 @@ export function intersect(a, b) {
|
|
|
159
157
|
* @returns {T[]} A new sorted array.
|
|
160
158
|
* @throws {TypeError} If array is not an array.
|
|
161
159
|
*/
|
|
162
|
-
export function mergeSort(array, key, direction =
|
|
160
|
+
export function mergeSort(array, key, direction = 'asc') {
|
|
163
161
|
if (!Array.isArray(array))
|
|
164
|
-
throw new TypeError(
|
|
162
|
+
throw new TypeError('Expected array');
|
|
165
163
|
if (array.length <= 1)
|
|
166
164
|
return array.slice();
|
|
167
|
-
const keyFn = typeof key ===
|
|
168
|
-
? key
|
|
169
|
-
: (item) => getValueByPath(item, key);
|
|
165
|
+
const keyFn = typeof key === 'function' ? key : (item) => getValueByPath(item, key);
|
|
170
166
|
const compare = (a, b) => {
|
|
171
167
|
const aVal = keyFn(a);
|
|
172
168
|
const bVal = keyFn(b);
|
|
@@ -174,10 +170,10 @@ export function mergeSort(array, key, direction = "asc") {
|
|
|
174
170
|
if (aVal === bVal)
|
|
175
171
|
return 0;
|
|
176
172
|
if (aVal == null)
|
|
177
|
-
return direction ===
|
|
173
|
+
return direction === 'asc' ? 1 : -1;
|
|
178
174
|
if (bVal == null)
|
|
179
|
-
return direction ===
|
|
180
|
-
return direction ===
|
|
175
|
+
return direction === 'asc' ? -1 : 1;
|
|
176
|
+
return direction === 'asc' ? (aVal < bVal ? -1 : 1) : aVal > bVal ? -1 : 1;
|
|
181
177
|
};
|
|
182
178
|
const merge = (left, right) => {
|
|
183
179
|
const result = [];
|
|
@@ -200,4 +196,127 @@ export function mergeSort(array, key, direction = "asc") {
|
|
|
200
196
|
};
|
|
201
197
|
return sort(array);
|
|
202
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Combines multiple arrays into a single array of grouped elements.
|
|
201
|
+
* Output array length equals the length of the shortest input array.
|
|
202
|
+
*
|
|
203
|
+
* @example zip([1, 2], ['a', 'b']) => [[1, 'a'], [2, 'b']]
|
|
204
|
+
* @param {...Array<T>[]} arrays - Two or more arrays to zip together.
|
|
205
|
+
* @returns {Array<T[]>} Array of grouped elements.
|
|
206
|
+
*/
|
|
207
|
+
export function zip(...arrays) {
|
|
208
|
+
if (arrays.length === 0)
|
|
209
|
+
return [];
|
|
210
|
+
if (arrays.some(arr => !Array.isArray(arr))) {
|
|
211
|
+
throw new TypeError('All arguments must be arrays');
|
|
212
|
+
}
|
|
213
|
+
const minLength = Math.min(...arrays.map(arr => arr.length));
|
|
214
|
+
const result = [];
|
|
215
|
+
for (let i = 0; i < minLength; i++) {
|
|
216
|
+
result.push(arrays.map(arr => arr[i]));
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Splits an array into two arrays based on a predicate function.
|
|
222
|
+
*
|
|
223
|
+
* @template T The type of array elements.
|
|
224
|
+
* @param {T[]} array - The input array.
|
|
225
|
+
* @param {(item: T, index: number, array: T[]) => boolean} predicate - Function to test each element.
|
|
226
|
+
* @returns {[T[], T[]]} A tuple of two arrays: [matched, unmatched].
|
|
227
|
+
*/
|
|
228
|
+
export function partition(array, predicate) {
|
|
229
|
+
if (!Array.isArray(array))
|
|
230
|
+
return [[], []];
|
|
231
|
+
return array.reduce(([pass, fail], item, index) => {
|
|
232
|
+
return predicate(item, index, array) ? [[...pass, item], fail] : [pass, [...fail, item]];
|
|
233
|
+
}, [[], []]);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Generates an array of numbers within a specified range.
|
|
237
|
+
*
|
|
238
|
+
* @param {number} start - Start of range (inclusive).
|
|
239
|
+
* @param {number} end - End of range (exclusive).
|
|
240
|
+
* @param {number} [step=1] - Step between numbers.
|
|
241
|
+
* @returns {number[]} Array of numbers in range.
|
|
242
|
+
*/
|
|
243
|
+
export function range(start, end, step = 1) {
|
|
244
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || !Number.isFinite(step)) {
|
|
245
|
+
throw new TypeError('Arguments must be finite numbers');
|
|
246
|
+
}
|
|
247
|
+
if (step === 0)
|
|
248
|
+
throw new Error('Step cannot be zero');
|
|
249
|
+
const isAscending = step > 0;
|
|
250
|
+
if ((isAscending && start >= end) || (!isAscending && start <= end)) {
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
const length = Math.max(Math.ceil((end - start) / step), 0);
|
|
254
|
+
const result = new Array(length);
|
|
255
|
+
for (let i = 0, value = start; i < length; i++, value += step) {
|
|
256
|
+
result[i] = value;
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Returns the first n elements of an array.
|
|
262
|
+
*
|
|
263
|
+
* @template T The type of array elements.
|
|
264
|
+
* @param {T[]} array - The input array.
|
|
265
|
+
* @param {number} [n=1] - Number of elements to take.
|
|
266
|
+
* @returns {T[]} New array with first n elements.
|
|
267
|
+
*/
|
|
268
|
+
export function take(array, n = 1) {
|
|
269
|
+
if (!Array.isArray(array) || n <= 0)
|
|
270
|
+
return [];
|
|
271
|
+
return array.slice(0, n);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Takes elements from the array while predicate returns true.
|
|
275
|
+
*
|
|
276
|
+
* @template T The type of array elements.
|
|
277
|
+
* @param {T[]} array - The input array.
|
|
278
|
+
* @param {(item: T, index: number) => boolean} predicate - Function to test each element.
|
|
279
|
+
* @returns {T[]} New array with taken elements.
|
|
280
|
+
*/
|
|
281
|
+
export function takeWhile(array, predicate) {
|
|
282
|
+
if (!Array.isArray(array))
|
|
283
|
+
return [];
|
|
284
|
+
const result = [];
|
|
285
|
+
for (let i = 0; i < array.length; i++) {
|
|
286
|
+
if (!predicate(array[i], i))
|
|
287
|
+
break;
|
|
288
|
+
result.push(array[i]);
|
|
289
|
+
}
|
|
290
|
+
return result;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Removes all falsy values from an array.
|
|
294
|
+
* False, null, 0, "", undefined, and NaN are falsy.
|
|
295
|
+
*
|
|
296
|
+
* @template T The type of array elements.
|
|
297
|
+
* @param {T[]} array - The input array.
|
|
298
|
+
* @returns {NonNullable<T>[]} New array with falsy values removed.
|
|
299
|
+
*/
|
|
300
|
+
export function compact(array) {
|
|
301
|
+
if (!Array.isArray(array))
|
|
302
|
+
return [];
|
|
303
|
+
return array.filter(Boolean);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Counts array elements by a key function.
|
|
307
|
+
*
|
|
308
|
+
* @template T The type of array elements.
|
|
309
|
+
* @param {T[]} array - The input array.
|
|
310
|
+
* @param {(item: T) => string | number | symbol} keyFn - Function to generate count key.
|
|
311
|
+
* @returns {Record<string, number>} Object with counts by key.
|
|
312
|
+
*/
|
|
313
|
+
export function countBy(array, keyFn) {
|
|
314
|
+
if (!Array.isArray(array))
|
|
315
|
+
return {};
|
|
316
|
+
return array.reduce((acc, item) => {
|
|
317
|
+
const key = String(keyFn(item));
|
|
318
|
+
acc[key] = (acc[key] || 0) + 1;
|
|
319
|
+
return acc;
|
|
320
|
+
}, {});
|
|
321
|
+
}
|
|
203
322
|
//# sourceMappingURL=array.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.utils.js","sourceRoot":"","sources":["../../../src/utils/array.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAI,KAAU,EAAE,IAAY,EAAS,EAAE;IAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrE,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CACvC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CAAI,KAAU,EAAE,KAA4B;IAChE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAW,CAAC;IAChC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAI,KAAY;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,MAAM,CAAM,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC,GAAG,WAAW,CAAI,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,MAAM,CAAI,KAAU;IAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AACzD,CAAC;AAwBD,MAAM,UAAU,OAAO,CACrB,KAAU,EACV,OAA0D;IAE1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3D,MAAM,KAAK,GACT,OAAO,OAAO,KAAK,UAAU;QAC3B,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,CAAC,IAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAkB,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACZ,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAA6B,CAAC;QACpD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QAC7B,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAA2C,CAC5C,CAAC;AACJ,CAAC;AACD,gCAAgC;AAEhC;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAI,KAAU;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,KAAK,CAAuB,KAAU,EAAE,GAAM;IAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAI,CAAM,EAAE,CAAM;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAI,CAAM,EAAE,CAAM;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CACvB,KAAU,EACV,GAAgC,EAChC,YAA4B,KAAK;IAEjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC;IAE5C,MAAM,KAAK,GACT,OAAO,GAAG,KAAK,UAAU;QACvB,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,CAAC,IAAO,EAAE,EAAE,CAAC,cAAc,CAAC,IAAc,EAAE,GAAG,CAAC,CAAC;IAEvD,MAAM,OAAO,GAAG,CAAC,CAAI,EAAE,CAAI,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,wDAAwD;QACxD,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;QAC5B,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,IAAS,EAAE,KAAU,EAAO,EAAE;QAC3C,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,EACP,CAAC,GAAG,CAAC,CAAC;QACR,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;gBACvD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,GAAQ,EAAO,EAAE;QAC7B,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,OAAO,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC","sourcesContent":["import { getValueByPath } from \"./obj.utils\";\n\n/**\n * Splits an array into chunks of the specified size.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The array to split into chunks.\n * @param {number} size - The number of elements per chunk.\n * @returns {T[][]} A new array containing chunked arrays.\n * @throws {TypeError} If array is not an array.\n * @throws {Error} If chunk size is not a positive integer.\n */\nexport const chunk = <T>(array: T[], size: number): T[][] => {\n if (!Array.isArray(array)) throw new TypeError(\"Expected an array\");\n if (!array.length) return [];\n if (!Number.isInteger(size) || size <= 0)\n throw new Error(\"Chunk size must be a positive integer\");\n return Array.from({ length: Math.ceil(array.length / size) }, (_, i) =>\n array.slice(i * size, i * size + size),\n );\n};\n\n/**\n * Removes duplicate values from an array.\n * Optionally enforces uniqueness by a key function.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @param {(item: T) => unknown} [keyFn] - Optional function to determine uniqueness by key.\n * @returns {T[]} A new array with unique values.\n */\nexport function unique<T>(array: T[], keyFn?: (item: T) => unknown): T[] {\n if (!Array.isArray(array) || array.length === 0) return [];\n if (!keyFn) return Array.from(new Set(array));\n const seen = new Set<unknown>();\n return array.filter((item) => {\n const key = keyFn(item);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * Deeply flattens a nested array to a single-level array.\n *\n * @template T The leaf type of array elements.\n * @param {any[]} array - The (possibly deeply nested) input array.\n * @returns {T[]} A deeply flattened array.\n */\nexport function flattenDeep<T>(array: any[]): T[] {\n if (!Array.isArray(array)) return [];\n return array.reduce<T[]>((acc, val) => {\n if (Array.isArray(val)) {\n acc.push(...flattenDeep<T>(val));\n } else {\n acc.push(val);\n }\n return acc;\n }, []);\n}\n\n/**\n * Returns a random element from an array, or undefined if empty.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @returns {T | undefined} A randomly selected item, or undefined if array is empty or not an array.\n */\nexport function random<T>(array: T[]): T | undefined {\n if (!Array.isArray(array) || array.length === 0) return undefined;\n return array[Math.floor(Math.random() * array.length)];\n}\n\n/* eslint-disable no-redeclare */\n/**\n * Groups items in an array by a key or key function.\n *\n * @template T The type of array elements.\n * @overload\n * @param {T[]} array - The array to group.\n * @param {keyof T} key - Property key to group by.\n * @returns {Record<string, T[]>}\n * @overload\n * @param {T[]} array - The array to group.\n * @param {(item: T) => string | number | symbol} keyFn - Function to generate group key from item.\n * @returns {Record<K, T[]>}\n * @param {T[]} array - The array to group.\n * @param {keyof T | ((item: T) => string | number | symbol)} keyOrFn - Property key or key-generating function.\n * @returns {Record<string | number | symbol, T[]>} An object mapping group keys to item arrays.\n */\nexport function groupBy<T>(array: T[], key: keyof T): Record<string, T[]>;\nexport function groupBy<T, K extends string | number | symbol>(\n array: T[],\n keyFn: (item: T) => K,\n): Record<K, T[]>;\nexport function groupBy<T>(\n array: T[],\n keyOrFn: keyof T | ((item: T) => string | number | symbol),\n): Record<string | number | symbol, T[]> {\n if (!Array.isArray(array) || array.length === 0) return {};\n const keyFn =\n typeof keyOrFn === \"function\"\n ? keyOrFn\n : (item: T) => item[keyOrFn as keyof T];\n return array.reduce(\n (acc, item) => {\n const key = keyFn(item) as string | number | symbol;\n if (!acc[key]) acc[key] = [];\n acc[key].push(item);\n return acc;\n },\n {} as Record<string | number | symbol, T[]>,\n );\n}\n/* eslint-enable no-redeclare */\n\n/**\n * Shuffles an array using the Fisher-Yates algorithm.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @returns {T[]} A new shuffled array.\n * @throws {TypeError} If array is not an array.\n */\nexport function shuffle<T>(array: T[]): T[] {\n if (!Array.isArray(array)) throw new TypeError(\"Expected an array\");\n const copy = array.slice();\n for (let i = copy.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [copy[i], copy[j]] = [copy[j], copy[i]];\n }\n return copy;\n}\n\n/**\n * Returns an array of property values from an array of objects.\n *\n * @template T The type of array elements.\n * @template K The object property to pluck.\n * @param {T[]} array - The input array.\n * @param {K} key - The property name to pluck.\n * @returns {T[K][]} Array of property values.\n */\nexport function pluck<T, K extends keyof T>(array: T[], key: K): T[K][] {\n if (!Array.isArray(array)) return [];\n return array.map((item) => item[key]);\n}\n\n/**\n * Returns values in array A that are not in array B.\n *\n * @template T The type of array elements.\n * @param {T[]} a - First array.\n * @param {T[]} b - Second array.\n * @returns {T[]} Elements in A that are not in B.\n */\nexport function difference<T>(a: T[], b: T[]): T[] {\n if (!Array.isArray(a) || !Array.isArray(b)) return [];\n const setB = new Set(b);\n return a.filter((item) => !setB.has(item));\n}\n\n/**\n * Returns common values between arrays A and B.\n *\n * @template T The type of array elements.\n * @param {T[]} a - First array.\n * @param {T[]} b - Second array.\n * @returns {T[]} Elements that exist in both arrays.\n */\nexport function intersect<T>(a: T[], b: T[]): T[] {\n if (!Array.isArray(a) || !Array.isArray(b)) return [];\n const setB = new Set(b);\n return a.filter((item) => setB.has(item));\n}\n\n/**\n * Sorts an array of objects by a nested key using Merge Sort (O(n log n)).\n * Missing/undefined keys are sorted to the \"end\" (asc) or \"start\" (desc).\n *\n * @template T The type of array elements (objects).\n * @param {T[]} array - Array of objects to sort.\n * @param {string | ((item: T) => any)} key - Dot-notated key (e.g., \"profile.age\") or function.\n * @param {\"asc\" | \"desc\"} [direction=\"asc\"] - Sort direction: 'asc' or 'desc'.\n * @returns {T[]} A new sorted array.\n * @throws {TypeError} If array is not an array.\n */\nexport function mergeSort<T>(\n array: T[],\n key: string | ((item: T) => any),\n direction: \"asc\" | \"desc\" = \"asc\",\n): T[] {\n if (!Array.isArray(array)) throw new TypeError(\"Expected array\");\n if (array.length <= 1) return array.slice();\n\n const keyFn =\n typeof key === \"function\"\n ? key\n : (item: T) => getValueByPath(item as object, key);\n\n const compare = (a: T, b: T) => {\n const aVal = keyFn(a);\n const bVal = keyFn(b);\n // Sorts undefined/null last for \"asc\", first for \"desc\"\n if (aVal === bVal) return 0;\n if (aVal == null) return direction === \"asc\" ? 1 : -1;\n if (bVal == null) return direction === \"asc\" ? -1 : 1;\n return direction === \"asc\" ? (aVal < bVal ? -1 : 1) : aVal > bVal ? -1 : 1;\n };\n\n const merge = (left: T[], right: T[]): T[] => {\n const result: T[] = [];\n let i = 0,\n j = 0;\n while (i < left.length && j < right.length) {\n if (compare(left[i], right[j]) <= 0) result.push(left[i++]);\n else result.push(right[j++]);\n }\n return result.concat(left.slice(i)).concat(right.slice(j));\n };\n\n const sort = (arr: T[]): T[] => {\n if (arr.length <= 1) return arr;\n const mid = Math.floor(arr.length / 2);\n const left = sort(arr.slice(0, mid));\n const right = sort(arr.slice(mid));\n return merge(left, right);\n };\n return sort(array);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"array.utils.js","sourceRoot":"","sources":["../../../src/utils/array.utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { getValueByPath } from './obj.utils';\n\n/**\n * Splits an array into chunks of the specified size.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The array to split into chunks.\n * @param {number} size - The number of elements per chunk.\n * @returns {T[][]} A new array containing chunked arrays.\n * @throws {TypeError} If array is not an array.\n * @throws {Error} If chunk size is not a positive integer.\n */\nexport function chunk<T>(array: T[], size: number): T[][] {\n if (!Array.isArray(array)) throw new TypeError('Expected an array');\n if (!array.length) return [];\n if (!Number.isInteger(size) || size <= 0) throw new Error('Chunk size must be a positive integer');\n return Array.from({ length: Math.ceil(array.length / size) }, (_, i) => array.slice(i * size, i * size + size));\n}\n\n/**\n * Removes duplicate values from an array.\n * Optionally enforces uniqueness by a key function.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @param {(item: T) => unknown} [keyFn] - Optional function to determine uniqueness by key.\n * @returns {T[]} A new array with unique values.\n */\nexport function unique<T>(array: T[], keyFn?: (item: T) => unknown): T[] {\n if (!Array.isArray(array) || array.length === 0) return [];\n if (!keyFn) return Array.from(new Set(array));\n const seen = new Set<unknown>();\n return array.filter(item => {\n const key = keyFn(item);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * Deeply flattens a nested array to a single-level array.\n *\n * @template T The leaf type of array elements.\n * @param {any[]} array - The (possibly deeply nested) input array.\n * @returns {T[]} A deeply flattened array.\n */\nexport function flattenDeep<T>(array: any[]): T[] {\n if (!Array.isArray(array)) return [];\n return array.reduce<T[]>((acc, val) => {\n if (Array.isArray(val)) {\n acc.push(...flattenDeep<T>(val));\n } else {\n acc.push(val);\n }\n return acc;\n }, []);\n}\n\n/**\n * Returns a random element from an array, or undefined if empty.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @returns {T | undefined} A randomly selected item, or undefined if array is empty or not an array.\n */\nexport function random<T>(array: T[]): T | undefined {\n if (!Array.isArray(array) || array.length === 0) return undefined;\n return array[Math.floor(Math.random() * array.length)];\n}\n\n/* eslint-disable no-redeclare */\n/**\n * Groups items in an array by a key or key function.\n *\n * @template T The type of array elements.\n * @overload\n * @param {T[]} array - The array to group.\n * @param {keyof T} key - Property key to group by.\n * @returns {Record<string, T[]>}\n * @overload\n * @param {T[]} array - The array to group.\n * @param {(item: T) => string | number | symbol} keyFn - Function to generate group key from item.\n * @returns {Record<K, T[]>}\n * @param {T[]} array - The array to group.\n * @param {keyof T | ((item: T) => string | number | symbol)} keyOrFn - Property key or key-generating function.\n * @returns {Record<string | number | symbol, T[]>} An object mapping group keys to item arrays.\n */\nexport function groupBy<T>(array: T[], key: keyof T): Record<string, T[]>;\nexport function groupBy<T, K extends string | number | symbol>(array: T[], keyFn: (item: T) => K): Record<K, T[]>;\nexport function groupBy<T>(\n array: T[],\n keyOrFn: keyof T | ((item: T) => string | number | symbol)\n): Record<string | number | symbol, T[]> {\n if (!Array.isArray(array) || array.length === 0) return {};\n const keyFn = typeof keyOrFn === 'function' ? keyOrFn : (item: T) => item[keyOrFn as keyof T];\n return array.reduce(\n (acc, item) => {\n const key = keyFn(item) as string | number | symbol;\n if (!acc[key]) acc[key] = [];\n acc[key].push(item);\n return acc;\n },\n {} as Record<string | number | symbol, T[]>\n );\n}\n/* eslint-enable no-redeclare */\n\n/**\n * Shuffles an array using the Fisher-Yates algorithm.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @returns {T[]} A new shuffled array.\n * @throws {TypeError} If array is not an array.\n */\nexport function shuffle<T>(array: T[]): T[] {\n if (!Array.isArray(array)) throw new TypeError('Expected an array');\n const copy = array.slice();\n for (let i = copy.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [copy[i], copy[j]] = [copy[j], copy[i]];\n }\n return copy;\n}\n\n/**\n * Returns an array of property values from an array of objects.\n *\n * @template T The type of array elements.\n * @template K The object property to pluck.\n * @param {T[]} array - The input array.\n * @param {K} key - The property name to pluck.\n * @returns {T[K][]} Array of property values.\n */\nexport function pluck<T, K extends keyof T>(array: T[], key: K): T[K][] {\n if (!Array.isArray(array)) return [];\n return array.map(item => item[key]);\n}\n\n/**\n * Returns values in array A that are not in array B.\n *\n * @template T The type of array elements.\n * @param {T[]} a - First array.\n * @param {T[]} b - Second array.\n * @returns {T[]} Elements in A that are not in B.\n */\nexport function difference<T>(a: T[], b: T[]): T[] {\n if (!Array.isArray(a) || !Array.isArray(b)) return [];\n const setB = new Set(b);\n return a.filter(item => !setB.has(item));\n}\n\n/**\n * Returns common values between arrays A and B.\n *\n * @template T The type of array elements.\n * @param {T[]} a - First array.\n * @param {T[]} b - Second array.\n * @returns {T[]} Elements that exist in both arrays.\n */\nexport function intersect<T>(a: T[], b: T[]): T[] {\n if (!Array.isArray(a) || !Array.isArray(b)) return [];\n const setB = new Set(b);\n return a.filter(item => setB.has(item));\n}\n\n/**\n * Sorts an array of objects by a nested key using Merge Sort (O(n log n)).\n * Missing/undefined keys are sorted to the \"end\" (asc) or \"start\" (desc).\n *\n * @template T The type of array elements (objects).\n * @param {T[]} array - Array of objects to sort.\n * @param {string | ((item: T) => any)} key - Dot-notated key (e.g., \"profile.age\") or function.\n * @param {\"asc\" | \"desc\"} [direction=\"asc\"] - Sort direction: 'asc' or 'desc'.\n * @returns {T[]} A new sorted array.\n * @throws {TypeError} If array is not an array.\n */\nexport function mergeSort<T>(array: T[], key: string | ((item: T) => any), direction: 'asc' | 'desc' = 'asc'): T[] {\n if (!Array.isArray(array)) throw new TypeError('Expected array');\n if (array.length <= 1) return array.slice();\n\n const keyFn = typeof key === 'function' ? key : (item: T) => getValueByPath(item as object, key);\n\n const compare = (a: T, b: T) => {\n const aVal = keyFn(a);\n const bVal = keyFn(b);\n // Sorts undefined/null last for \"asc\", first for \"desc\"\n if (aVal === bVal) return 0;\n if (aVal == null) return direction === 'asc' ? 1 : -1;\n if (bVal == null) return direction === 'asc' ? -1 : 1;\n return direction === 'asc' ? (aVal < bVal ? -1 : 1) : aVal > bVal ? -1 : 1;\n };\n\n const merge = (left: T[], right: T[]): T[] => {\n const result: T[] = [];\n let i = 0,\n j = 0;\n while (i < left.length && j < right.length) {\n if (compare(left[i], right[j]) <= 0) result.push(left[i++]);\n else result.push(right[j++]);\n }\n return result.concat(left.slice(i)).concat(right.slice(j));\n };\n\n const sort = (arr: T[]): T[] => {\n if (arr.length <= 1) return arr;\n const mid = Math.floor(arr.length / 2);\n const left = sort(arr.slice(0, mid));\n const right = sort(arr.slice(mid));\n return merge(left, right);\n };\n return sort(array);\n}\n\n/**\n * Combines multiple arrays into a single array of grouped elements.\n * Output array length equals the length of the shortest input array.\n *\n * @example zip([1, 2], ['a', 'b']) => [[1, 'a'], [2, 'b']]\n * @param {...Array<T>[]} arrays - Two or more arrays to zip together.\n * @returns {Array<T[]>} Array of grouped elements.\n */\nexport function zip<T>(...arrays: T[][]): T[][] {\n if (arrays.length === 0) return [];\n if (arrays.some(arr => !Array.isArray(arr))) {\n throw new TypeError('All arguments must be arrays');\n }\n\n const minLength = Math.min(...arrays.map(arr => arr.length));\n const result: T[][] = [];\n\n for (let i = 0; i < minLength; i++) {\n result.push(arrays.map(arr => arr[i]));\n }\n\n return result;\n}\n\n/**\n * Splits an array into two arrays based on a predicate function.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @param {(item: T, index: number, array: T[]) => boolean} predicate - Function to test each element.\n * @returns {[T[], T[]]} A tuple of two arrays: [matched, unmatched].\n */\nexport function partition<T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean): [T[], T[]] {\n if (!Array.isArray(array)) return [[], []];\n\n return array.reduce(\n ([pass, fail], item, index) => {\n return predicate(item, index, array) ? [[...pass, item], fail] : [pass, [...fail, item]];\n },\n [[] as T[], [] as T[]]\n );\n}\n\n/**\n * Generates an array of numbers within a specified range.\n *\n * @param {number} start - Start of range (inclusive).\n * @param {number} end - End of range (exclusive).\n * @param {number} [step=1] - Step between numbers.\n * @returns {number[]} Array of numbers in range.\n */\nexport function range(start: number, end: number, step: number = 1): number[] {\n if (!Number.isFinite(start) || !Number.isFinite(end) || !Number.isFinite(step)) {\n throw new TypeError('Arguments must be finite numbers');\n }\n if (step === 0) throw new Error('Step cannot be zero');\n\n const isAscending = step > 0;\n if ((isAscending && start >= end) || (!isAscending && start <= end)) {\n return [];\n }\n\n const length = Math.max(Math.ceil((end - start) / step), 0);\n const result = new Array(length);\n\n for (let i = 0, value = start; i < length; i++, value += step) {\n result[i] = value;\n }\n\n return result;\n}\n\n/**\n * Returns the first n elements of an array.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @param {number} [n=1] - Number of elements to take.\n * @returns {T[]} New array with first n elements.\n */\nexport function take<T>(array: T[], n: number = 1): T[] {\n if (!Array.isArray(array) || n <= 0) return [];\n return array.slice(0, n);\n}\n\n/**\n * Takes elements from the array while predicate returns true.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @param {(item: T, index: number) => boolean} predicate - Function to test each element.\n * @returns {T[]} New array with taken elements.\n */\nexport function takeWhile<T>(array: T[], predicate: (item: T, index: number) => boolean): T[] {\n if (!Array.isArray(array)) return [];\n\n const result: T[] = [];\n for (let i = 0; i < array.length; i++) {\n if (!predicate(array[i], i)) break;\n result.push(array[i]);\n }\n\n return result;\n}\n\n/**\n * Removes all falsy values from an array.\n * False, null, 0, \"\", undefined, and NaN are falsy.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @returns {NonNullable<T>[]} New array with falsy values removed.\n */\nexport function compact<T>(array: T[]): NonNullable<T>[] {\n if (!Array.isArray(array)) return [];\n return array.filter(Boolean) as NonNullable<T>[];\n}\n\n/**\n * Counts array elements by a key function.\n *\n * @template T The type of array elements.\n * @param {T[]} array - The input array.\n * @param {(item: T) => string | number | symbol} keyFn - Function to generate count key.\n * @returns {Record<string, number>} Object with counts by key.\n */\nexport function countBy<T>(array: T[], keyFn: (item: T) => string | number | symbol): Record<string, number> {\n if (!Array.isArray(array)) return {};\n\n return array.reduce(\n (acc, item) => {\n const key = String(keyFn(item));\n acc[key] = (acc[key] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n );\n}\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {number} ms - The number of milliseconds to sleep.
|
|
5
5
|
* @returns {Promise<void>} A Promise that resolves after the given time.
|
|
6
6
|
*/
|
|
7
|
-
export declare
|
|
7
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
8
8
|
/**
|
|
9
9
|
* Creates a debounced version of a function that delays its execution.
|
|
10
10
|
* Provides `.cancel()` and `.flush()` methods.
|
|
@@ -116,4 +116,59 @@ export declare function createTaskQueue(limit: number): TaskQueue;
|
|
|
116
116
|
* @returns {Promise<T[]>} Array of resolved values.
|
|
117
117
|
*/
|
|
118
118
|
export declare function runInSeries<T>(tasks: (() => Promise<T>)[]): Promise<T[]>;
|
|
119
|
+
/**
|
|
120
|
+
* Memoizes an async function, caching results for repeated calls with identical arguments.
|
|
121
|
+
* Optional TTL (time-to-live) for cached entries.
|
|
122
|
+
*
|
|
123
|
+
* @template T Function return type
|
|
124
|
+
* @template Args Function arguments types
|
|
125
|
+
* @param {(...args: Args) => Promise<T>} fn - The async function to memoize
|
|
126
|
+
* @param {object} [options] - Memoization options
|
|
127
|
+
* @param {number} [options.ttl] - Cache TTL in milliseconds (optional)
|
|
128
|
+
* @param {(args: Args) => string} [options.keyFn] - Custom key generator function
|
|
129
|
+
* @returns {(...args: Args) => Promise<T>} Memoized function
|
|
130
|
+
*/
|
|
131
|
+
export declare function memoizeAsync<T, Args extends any[]>(fn: (...args: Args) => Promise<T>, options?: {
|
|
132
|
+
ttl?: number;
|
|
133
|
+
keyFn?: (args: Args) => string;
|
|
134
|
+
}): (...args: Args) => Promise<T>;
|
|
135
|
+
/**
|
|
136
|
+
* Creates an abortable version of a promise that can be cancelled using an AbortController.
|
|
137
|
+
*
|
|
138
|
+
* @template T
|
|
139
|
+
* @param {Promise<T>} promise - The promise to make abortable
|
|
140
|
+
* @param {AbortSignal} signal - AbortSignal from AbortController
|
|
141
|
+
* @param {any} [abortValue] - Value to use when rejecting on abort
|
|
142
|
+
* @returns {Promise<T>} Promise that rejects if the signal is aborted
|
|
143
|
+
*/
|
|
144
|
+
export declare function abortable<T>(promise: Promise<T>, signal: AbortSignal, abortValue?: any): Promise<T>;
|
|
145
|
+
/**
|
|
146
|
+
* Creates a promise with external resolve/reject functions.
|
|
147
|
+
* Useful for creating promises that can be resolved or rejected from outside.
|
|
148
|
+
*
|
|
149
|
+
* @template T
|
|
150
|
+
* @returns {[Promise<T>, (value: T | PromiseLike<T>) => void, (reason?: any) => void]}
|
|
151
|
+
* Tuple of [promise, resolve, reject]
|
|
152
|
+
*/
|
|
153
|
+
export declare function createDeferred<T>(): [Promise<T>, (value: T | PromiseLike<T>) => void, (reason?: any) => void];
|
|
154
|
+
/**
|
|
155
|
+
* Chains a series of async functions, passing the result of each to the next.
|
|
156
|
+
* Similar to function composition but for async functions.
|
|
157
|
+
*
|
|
158
|
+
* @template T
|
|
159
|
+
* @param {Array<(input: any) => Promise<any>>} fns - Array of async functions to compose
|
|
160
|
+
* @returns {(input: any) => Promise<T>} Composed function
|
|
161
|
+
*/
|
|
162
|
+
export declare function waterfall<T>(fns: Array<(input: any) => Promise<any>>): (initialValue: any) => Promise<T>;
|
|
163
|
+
/**
|
|
164
|
+
* Creates a rate limiter that ensures functions aren't called more than
|
|
165
|
+
* a specified number of times per interval.
|
|
166
|
+
*
|
|
167
|
+
* @template T
|
|
168
|
+
* @param {(...args: any[]) => Promise<T>} fn - Function to rate limit
|
|
169
|
+
* @param {number} maxCalls - Maximum calls allowed per interval
|
|
170
|
+
* @param {number} interval - Time interval in milliseconds
|
|
171
|
+
* @returns {(...args: any[]) => Promise<T>} Rate limited function
|
|
172
|
+
*/
|
|
173
|
+
export declare function rateLimit<T>(fn: (...args: any[]) => Promise<T>, maxCalls: number, interval: number): (...args: any[]) => Promise<T>;
|
|
119
174
|
//# sourceMappingURL=async.utils.d.ts.map
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* @param {number} ms - The number of milliseconds to sleep.
|
|
5
5
|
* @returns {Promise<void>} A Promise that resolves after the given time.
|
|
6
6
|
*/
|
|
7
|
-
export
|
|
7
|
+
export function sleep(ms) {
|
|
8
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
9
|
+
}
|
|
8
10
|
/**
|
|
9
11
|
* Creates a debounced version of a function that delays its execution.
|
|
10
12
|
* Provides `.cancel()` and `.flush()` methods.
|
|
@@ -54,7 +56,7 @@ export function debounce(fn, delay) {
|
|
|
54
56
|
*/
|
|
55
57
|
export function throttle(fn, limit, opts = {
|
|
56
58
|
leading: true,
|
|
57
|
-
trailing: false
|
|
59
|
+
trailing: false
|
|
58
60
|
}) {
|
|
59
61
|
let lastCall = 0;
|
|
60
62
|
let timer = null;
|
|
@@ -111,7 +113,7 @@ export async function retry(fn, retries = 3, delay = 500, backoff = false, onRet
|
|
|
111
113
|
await sleep(backoff ? delay * Math.pow(2, i) : delay);
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
|
-
throw new Error(
|
|
116
|
+
throw new Error('Retry failed'); // should never reach here
|
|
115
117
|
}
|
|
116
118
|
/**
|
|
117
119
|
* Wraps a promise and rejects it if it doesn't resolve within the specified timeout.
|
|
@@ -122,15 +124,15 @@ export async function retry(fn, retries = 3, delay = 500, backoff = false, onRet
|
|
|
122
124
|
* @param {string} [message="Operation timed out"] - Optional timeout message.
|
|
123
125
|
* @returns {Promise<T>} A promise that resolves or rejects within the timeout.
|
|
124
126
|
*/
|
|
125
|
-
export function withTimeout(promise, ms, message =
|
|
127
|
+
export function withTimeout(promise, ms, message = 'Operation timed out') {
|
|
126
128
|
return new Promise((resolve, reject) => {
|
|
127
129
|
const timeoutHandle = setTimeout(() => reject(new Error(message)), ms);
|
|
128
130
|
promise
|
|
129
|
-
.then(
|
|
131
|
+
.then(result => {
|
|
130
132
|
clearTimeout(timeoutHandle);
|
|
131
133
|
resolve(result);
|
|
132
134
|
})
|
|
133
|
-
.catch(
|
|
135
|
+
.catch(err => {
|
|
134
136
|
clearTimeout(timeoutHandle);
|
|
135
137
|
reject(err);
|
|
136
138
|
});
|
|
@@ -151,7 +153,7 @@ export async function runInBatches(tasks, limit) {
|
|
|
151
153
|
const results = [];
|
|
152
154
|
for (let i = 0; i < tasks.length; i += limit) {
|
|
153
155
|
const batch = tasks.slice(i, i + limit);
|
|
154
|
-
const batchResults = await Promise.all(batch.map(
|
|
156
|
+
const batchResults = await Promise.all(batch.map(fn => fn()));
|
|
155
157
|
results.push(...batchResults);
|
|
156
158
|
}
|
|
157
159
|
return results;
|
|
@@ -176,7 +178,7 @@ export function singletonAsync(fn, drop = false) {
|
|
|
176
178
|
});
|
|
177
179
|
}
|
|
178
180
|
else if (drop) {
|
|
179
|
-
return Promise.reject(new Error(
|
|
181
|
+
return Promise.reject(new Error('Busy: function already running'));
|
|
180
182
|
}
|
|
181
183
|
return promise;
|
|
182
184
|
};
|
|
@@ -189,7 +191,7 @@ export function singletonAsync(fn, drop = false) {
|
|
|
189
191
|
* @returns {Promise<PromiseSettledResult<T>[]>} Results including status and value/reason.
|
|
190
192
|
*/
|
|
191
193
|
export async function settleAll(tasks) {
|
|
192
|
-
return Promise.allSettled(tasks.map(
|
|
194
|
+
return Promise.allSettled(tasks.map(task => task()));
|
|
193
195
|
}
|
|
194
196
|
/**
|
|
195
197
|
* A simple task queue that executes async tasks with a concurrency limit.
|
|
@@ -230,7 +232,7 @@ export function createTaskQueue(limit) {
|
|
|
230
232
|
*/
|
|
231
233
|
get isPaused() {
|
|
232
234
|
return paused;
|
|
233
|
-
}
|
|
235
|
+
}
|
|
234
236
|
};
|
|
235
237
|
const next = () => {
|
|
236
238
|
if (paused || queue.length === 0 || activeCount >= limit)
|
|
@@ -265,11 +267,11 @@ export function createTaskQueue(limit) {
|
|
|
265
267
|
};
|
|
266
268
|
enqueue.pause = state.pause;
|
|
267
269
|
enqueue.resume = state.resume;
|
|
268
|
-
Object.defineProperty(enqueue,
|
|
269
|
-
get: () => queue.length
|
|
270
|
+
Object.defineProperty(enqueue, 'length', {
|
|
271
|
+
get: () => queue.length
|
|
270
272
|
});
|
|
271
|
-
Object.defineProperty(enqueue,
|
|
272
|
-
get: () => paused
|
|
273
|
+
Object.defineProperty(enqueue, 'isPaused', {
|
|
274
|
+
get: () => paused
|
|
273
275
|
});
|
|
274
276
|
return enqueue;
|
|
275
277
|
}
|
|
@@ -288,4 +290,118 @@ export async function runInSeries(tasks) {
|
|
|
288
290
|
}
|
|
289
291
|
return results;
|
|
290
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Memoizes an async function, caching results for repeated calls with identical arguments.
|
|
295
|
+
* Optional TTL (time-to-live) for cached entries.
|
|
296
|
+
*
|
|
297
|
+
* @template T Function return type
|
|
298
|
+
* @template Args Function arguments types
|
|
299
|
+
* @param {(...args: Args) => Promise<T>} fn - The async function to memoize
|
|
300
|
+
* @param {object} [options] - Memoization options
|
|
301
|
+
* @param {number} [options.ttl] - Cache TTL in milliseconds (optional)
|
|
302
|
+
* @param {(args: Args) => string} [options.keyFn] - Custom key generator function
|
|
303
|
+
* @returns {(...args: Args) => Promise<T>} Memoized function
|
|
304
|
+
*/
|
|
305
|
+
export function memoizeAsync(fn, options = {}) {
|
|
306
|
+
const cache = new Map();
|
|
307
|
+
const { ttl, keyFn = JSON.stringify } = options;
|
|
308
|
+
return async function (...args) {
|
|
309
|
+
const key = keyFn(args);
|
|
310
|
+
const cached = cache.get(key);
|
|
311
|
+
if (cached && (!ttl || Date.now() < cached.expires)) {
|
|
312
|
+
return cached.value;
|
|
313
|
+
}
|
|
314
|
+
const result = await fn(...args);
|
|
315
|
+
cache.set(key, {
|
|
316
|
+
value: result,
|
|
317
|
+
expires: ttl ? Date.now() + ttl : Infinity
|
|
318
|
+
});
|
|
319
|
+
return result;
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Creates an abortable version of a promise that can be cancelled using an AbortController.
|
|
324
|
+
*
|
|
325
|
+
* @template T
|
|
326
|
+
* @param {Promise<T>} promise - The promise to make abortable
|
|
327
|
+
* @param {AbortSignal} signal - AbortSignal from AbortController
|
|
328
|
+
* @param {any} [abortValue] - Value to use when rejecting on abort
|
|
329
|
+
* @returns {Promise<T>} Promise that rejects if the signal is aborted
|
|
330
|
+
*/
|
|
331
|
+
export function abortable(promise, signal, abortValue = new Error('Operation aborted')) {
|
|
332
|
+
if (signal.aborted) {
|
|
333
|
+
return Promise.reject(abortValue);
|
|
334
|
+
}
|
|
335
|
+
return Promise.race([
|
|
336
|
+
promise,
|
|
337
|
+
new Promise((_, reject) => {
|
|
338
|
+
const abort = () => reject(abortValue);
|
|
339
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
340
|
+
promise.finally(() => signal.removeEventListener('abort', abort));
|
|
341
|
+
})
|
|
342
|
+
]);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Creates a promise with external resolve/reject functions.
|
|
346
|
+
* Useful for creating promises that can be resolved or rejected from outside.
|
|
347
|
+
*
|
|
348
|
+
* @template T
|
|
349
|
+
* @returns {[Promise<T>, (value: T | PromiseLike<T>) => void, (reason?: any) => void]}
|
|
350
|
+
* Tuple of [promise, resolve, reject]
|
|
351
|
+
*/
|
|
352
|
+
export function createDeferred() {
|
|
353
|
+
let resolve;
|
|
354
|
+
let reject;
|
|
355
|
+
const promise = new Promise((res, rej) => {
|
|
356
|
+
resolve = res;
|
|
357
|
+
reject = rej;
|
|
358
|
+
});
|
|
359
|
+
return [promise, resolve, reject];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Chains a series of async functions, passing the result of each to the next.
|
|
363
|
+
* Similar to function composition but for async functions.
|
|
364
|
+
*
|
|
365
|
+
* @template T
|
|
366
|
+
* @param {Array<(input: any) => Promise<any>>} fns - Array of async functions to compose
|
|
367
|
+
* @returns {(input: any) => Promise<T>} Composed function
|
|
368
|
+
*/
|
|
369
|
+
export function waterfall(fns) {
|
|
370
|
+
return async (initialValue) => {
|
|
371
|
+
return fns.reduce(async (acc, fn) => fn(await acc), Promise.resolve(initialValue));
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Creates a rate limiter that ensures functions aren't called more than
|
|
376
|
+
* a specified number of times per interval.
|
|
377
|
+
*
|
|
378
|
+
* @template T
|
|
379
|
+
* @param {(...args: any[]) => Promise<T>} fn - Function to rate limit
|
|
380
|
+
* @param {number} maxCalls - Maximum calls allowed per interval
|
|
381
|
+
* @param {number} interval - Time interval in milliseconds
|
|
382
|
+
* @returns {(...args: any[]) => Promise<T>} Rate limited function
|
|
383
|
+
*/
|
|
384
|
+
export function rateLimit(fn, maxCalls, interval) {
|
|
385
|
+
const calls = [];
|
|
386
|
+
return async function (...args) {
|
|
387
|
+
const now = Date.now();
|
|
388
|
+
calls.splice(0, calls.length, ...calls.filter(time => now - time < interval));
|
|
389
|
+
if (calls.length >= maxCalls) {
|
|
390
|
+
const oldestCall = calls[0];
|
|
391
|
+
const delay = interval - (now - oldestCall);
|
|
392
|
+
await sleep(Math.max(1, delay));
|
|
393
|
+
// Remove potentially stale entries after sleep
|
|
394
|
+
const currentTime = Date.now();
|
|
395
|
+
calls.splice(0, calls.length, ...calls.filter(time => currentTime - time < interval));
|
|
396
|
+
// If still at limit after sleep, wait for another cycle
|
|
397
|
+
if (calls.length >= maxCalls) {
|
|
398
|
+
const nextDelay = interval - (currentTime - calls[0]);
|
|
399
|
+
await sleep(Math.max(1, nextDelay));
|
|
400
|
+
calls.splice(0, calls.length, ...calls.filter(time => Date.now() - time < interval));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
calls.push(Date.now());
|
|
404
|
+
return fn(...args);
|
|
405
|
+
};
|
|
406
|
+
}
|
|
291
407
|
//# sourceMappingURL=async.utils.js.map
|