@catbee/utils 2.0.0-next.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +102 -52
- package/array/index.cjs +215 -74
- package/array/index.d.ts +345 -2
- package/array/index.mjs +201 -74
- package/async/index.cjs +116 -39
- package/async/index.d.ts +292 -2
- package/async/index.mjs +116 -40
- package/cache/index.cjs +2 -2
- package/cache/index.d.ts +156 -2
- package/cache/index.mjs +3 -3
- package/config/index.cjs +80 -66
- package/config/index.d.ts +65 -3
- package/config/index.mjs +77 -65
- package/context-store/index.cjs +2 -3
- package/context-store/index.d.ts +193 -2
- package/context-store/index.mjs +2 -3
- package/crypto/index.cjs +55 -5
- package/crypto/index.d.ts +225 -2
- package/crypto/index.mjs +52 -7
- package/date/index.cjs +676 -2
- package/date/index.d.ts +676 -2
- package/date/index.mjs +665 -3
- package/decorator/index.cjs +2172 -0
- package/{decorators/decorators.utils.d.ts → decorator/index.d.ts} +58 -54
- package/decorator/index.mjs +2131 -0
- package/{dir → directory}/index.cjs +5 -4
- package/{dir/dir.utils.d.ts → directory/index.d.ts} +24 -21
- package/{dir → directory}/index.mjs +5 -4
- package/env/index.cjs +100 -68
- package/env/index.d.ts +391 -2
- package/env/index.mjs +100 -68
- package/exception/index.cjs +1 -1
- package/exception/index.d.ts +233 -2
- package/exception/index.mjs +1 -1
- package/fs/index.cjs +71 -37
- package/fs/index.d.ts +206 -2
- package/fs/index.mjs +65 -35
- package/http-status-codes/index.cjs +1 -1
- package/http-status-codes/index.d.ts +268 -2
- package/http-status-codes/index.mjs +1 -1
- package/id/index.cjs +1 -1
- package/id/index.d.ts +38 -2
- package/id/index.mjs +1 -1
- package/index.cjs +13 -13
- package/index.d.ts +5 -5
- package/index.mjs +5 -5
- package/logger/index.cjs +13 -15
- package/logger/index.d.ts +190 -2
- package/logger/index.mjs +14 -16
- package/middleware/index.cjs +1 -1
- package/middleware/index.d.ts +104 -2
- package/middleware/index.mjs +1 -1
- package/object/index.cjs +379 -0
- package/{obj/obj.utils.d.ts → object/index.d.ts} +73 -33
- package/object/index.mjs +360 -0
- package/package.json +41 -23
- package/performance/index.cjs +4 -4
- package/performance/index.d.ts +139 -2
- package/performance/index.mjs +4 -4
- package/request/index.cjs +37 -25
- package/request/index.d.ts +242 -3
- package/request/index.mjs +37 -25
- package/response/index.cjs +1 -1
- package/response/index.d.ts +319 -3
- package/response/index.mjs +1 -1
- package/server/index.cjs +249 -146
- package/server/index.d.ts +866 -5
- package/server/index.mjs +248 -144
- package/stream/index.cjs +1 -1
- package/stream/index.d.ts +91 -2
- package/stream/index.mjs +1 -1
- package/string/index.cjs +34 -1
- package/string/index.d.ts +146 -2
- package/string/index.mjs +31 -2
- package/type/index.cjs +19 -2
- package/type/index.d.ts +144 -2
- package/type/index.mjs +17 -3
- package/types/index.cjs +1 -1
- package/types/index.d.ts +775 -5
- package/types/index.mjs +1 -1
- package/url/index.cjs +63 -5
- package/url/index.d.ts +200 -2
- package/url/index.mjs +59 -6
- package/{validate → validation}/index.cjs +91 -44
- package/{validate/validate.utils.d.ts → validation/index.d.ts} +33 -24
- package/{validate → validation}/index.mjs +87 -44
- package/array/array.utils.d.ts +0 -191
- package/async/async.utils.d.ts +0 -296
- package/cache/cache.utils.d.ts +0 -176
- package/config/config.d.ts +0 -57
- package/context-store/context-store.utils.d.ts +0 -212
- package/crypto/crypto.utils.d.ts +0 -183
- package/date/date.utils.d.ts +0 -190
- package/decorators/index.cjs +0 -913
- package/decorators/index.d.ts +0 -25
- package/decorators/index.mjs +0 -872
- package/dir/index.d.ts +0 -25
- package/env/env.utils.d.ts +0 -400
- package/exception/exception.utils.d.ts +0 -253
- package/fs/fs.utils.d.ts +0 -196
- package/http-status-codes/http-status-codes.d.ts +0 -289
- package/id/id.utils.d.ts +0 -59
- package/logger/logger.utils.d.ts +0 -210
- package/middleware/middleware.utils.d.ts +0 -123
- package/obj/index.cjs +0 -317
- package/obj/index.d.ts +0 -25
- package/obj/index.mjs +0 -301
- package/performance/performance.utils.d.ts +0 -159
- package/request/request.utils.d.ts +0 -109
- package/response/response.utils.d.ts +0 -186
- package/server/server.builder.d.ts +0 -531
- package/server/server.d.ts +0 -303
- package/stream/stream.utils.d.ts +0 -111
- package/string/string.utils.d.ts +0 -124
- package/type/type.utils.d.ts +0 -129
- package/types/api-response.d.ts +0 -175
- package/types/common.d.ts +0 -148
- package/types/config.d.ts +0 -88
- package/types/server.d.ts +0 -291
- package/url/url.utils.d.ts +0 -164
- package/validate/index.d.ts +0 -25
package/array/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import { getValueByPath } from '@catbee/utils/
|
|
25
|
+
import { getValueByPath } from '@catbee/utils/object';
|
|
26
|
+
import { randomBytes } from 'crypto';
|
|
26
27
|
|
|
27
28
|
var __defProp = Object.defineProperty;
|
|
28
29
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -41,49 +42,64 @@ function unique(array, keyFn) {
|
|
|
41
42
|
if (!Array.isArray(array) || array.length === 0) return [];
|
|
42
43
|
if (!keyFn) return Array.from(new Set(array));
|
|
43
44
|
const seen = /* @__PURE__ */ new Set();
|
|
44
|
-
|
|
45
|
+
const result = [];
|
|
46
|
+
for (const item of array) {
|
|
45
47
|
const key = keyFn(item);
|
|
46
|
-
if (seen.has(key))
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
if (!seen.has(key)) {
|
|
49
|
+
seen.add(key);
|
|
50
|
+
result.push(item);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
50
54
|
}
|
|
51
55
|
__name(unique, "unique");
|
|
52
56
|
function flattenDeep(array) {
|
|
53
57
|
if (!Array.isArray(array)) return [];
|
|
54
58
|
const result = [];
|
|
55
|
-
|
|
59
|
+
const stack = [
|
|
60
|
+
...array
|
|
61
|
+
];
|
|
62
|
+
while (stack.length) {
|
|
63
|
+
const val = stack.pop();
|
|
56
64
|
if (Array.isArray(val)) {
|
|
57
|
-
|
|
65
|
+
stack.push(...val);
|
|
58
66
|
} else {
|
|
59
67
|
result.push(val);
|
|
60
68
|
}
|
|
61
69
|
}
|
|
62
|
-
return result;
|
|
70
|
+
return result.reverse();
|
|
63
71
|
}
|
|
64
72
|
__name(flattenDeep, "flattenDeep");
|
|
65
73
|
function random(array) {
|
|
66
74
|
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
67
|
-
|
|
68
|
-
return array[idx];
|
|
75
|
+
return array[secureIndex(array.length)];
|
|
69
76
|
}
|
|
70
77
|
__name(random, "random");
|
|
71
78
|
function groupBy(array, keyOrFn) {
|
|
72
79
|
if (!Array.isArray(array) || array.length === 0) return {};
|
|
73
|
-
const keyFn = typeof keyOrFn === "function" ? keyOrFn : (item) => item
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
const keyFn = typeof keyOrFn === "function" ? keyOrFn : (item) => String(getValueByPath(item, keyOrFn));
|
|
81
|
+
const result = {};
|
|
82
|
+
for (const item of array) {
|
|
83
|
+
const key = String(keyFn(item));
|
|
84
|
+
if (Object.hasOwn(result, key)) {
|
|
85
|
+
result[key].push(item);
|
|
86
|
+
} else {
|
|
87
|
+
result[key] = [
|
|
88
|
+
item
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return Object.fromEntries(Object.entries(result).map(([k, v]) => [
|
|
93
|
+
k,
|
|
94
|
+
v
|
|
95
|
+
]));
|
|
80
96
|
}
|
|
81
97
|
__name(groupBy, "groupBy");
|
|
82
98
|
function shuffle(array) {
|
|
83
99
|
if (!Array.isArray(array)) throw new TypeError("Expected an array");
|
|
84
100
|
const copy = array.slice();
|
|
85
101
|
for (let i = copy.length - 1; i > 0; i--) {
|
|
86
|
-
const j =
|
|
102
|
+
const j = secureIndex(i + 1);
|
|
87
103
|
[copy[i], copy[j]] = [
|
|
88
104
|
copy[j],
|
|
89
105
|
copy[i]
|
|
@@ -94,7 +110,7 @@ function shuffle(array) {
|
|
|
94
110
|
__name(shuffle, "shuffle");
|
|
95
111
|
function pluck(array, key) {
|
|
96
112
|
if (!Array.isArray(array)) return [];
|
|
97
|
-
return array.map((item) => item[key]);
|
|
113
|
+
return array.map((item) => item?.[key]);
|
|
98
114
|
}
|
|
99
115
|
__name(pluck, "pluck");
|
|
100
116
|
function difference(a, b) {
|
|
@@ -109,35 +125,41 @@ function intersect(a, b) {
|
|
|
109
125
|
return a.filter((item) => setB.has(item));
|
|
110
126
|
}
|
|
111
127
|
__name(intersect, "intersect");
|
|
112
|
-
function mergeSort(array, key, direction = "asc") {
|
|
128
|
+
function mergeSort(array, key, direction = "asc", compareFn) {
|
|
113
129
|
if (!Array.isArray(array)) throw new TypeError("Expected array");
|
|
114
|
-
|
|
130
|
+
const arr = array.slice();
|
|
131
|
+
if (arr.length <= 1) return arr;
|
|
115
132
|
const keyFn = typeof key === "function" ? key : (item) => getValueByPath(item, key);
|
|
116
|
-
const
|
|
133
|
+
const collator = new Intl.Collator("en", {
|
|
134
|
+
numeric: true
|
|
135
|
+
});
|
|
136
|
+
const compare = compareFn ?? function(a, b) {
|
|
117
137
|
const aVal = keyFn(a);
|
|
118
138
|
const bVal = keyFn(b);
|
|
119
139
|
if (aVal === bVal) return 0;
|
|
120
140
|
if (aVal == null) return direction === "asc" ? 1 : -1;
|
|
121
141
|
if (bVal == null) return direction === "asc" ? -1 : 1;
|
|
122
|
-
return direction === "asc" ? aVal
|
|
123
|
-
}
|
|
142
|
+
return direction === "asc" ? collator.compare(String(aVal), String(bVal)) : collator.compare(String(bVal), String(aVal));
|
|
143
|
+
};
|
|
124
144
|
const merge = /* @__PURE__ */ __name((left, right) => {
|
|
125
145
|
const result = [];
|
|
126
146
|
let i = 0, j = 0;
|
|
127
147
|
while (i < left.length && j < right.length) {
|
|
128
|
-
|
|
129
|
-
else result.push(right[j++]);
|
|
148
|
+
result.push(compare(left[i], right[j]) <= 0 ? left[i++] : right[j++]);
|
|
130
149
|
}
|
|
131
|
-
|
|
150
|
+
while (i < left.length) result.push(left[i++]);
|
|
151
|
+
while (j < right.length) result.push(right[j++]);
|
|
152
|
+
return result;
|
|
132
153
|
}, "merge");
|
|
133
|
-
const sort = /* @__PURE__ */ __name((
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
const
|
|
154
|
+
const sort = /* @__PURE__ */ __name((input) => {
|
|
155
|
+
const len = input.length;
|
|
156
|
+
if (len <= 1) return input;
|
|
157
|
+
const mid = len >> 1;
|
|
158
|
+
const left = sort(input.slice(0, mid));
|
|
159
|
+
const right = sort(input.slice(mid));
|
|
138
160
|
return merge(left, right);
|
|
139
161
|
}, "sort");
|
|
140
|
-
return sort(
|
|
162
|
+
return sort(arr);
|
|
141
163
|
}
|
|
142
164
|
__name(mergeSort, "mergeSort");
|
|
143
165
|
function zip(...arrays) {
|
|
@@ -154,28 +176,20 @@ function zip(...arrays) {
|
|
|
154
176
|
}
|
|
155
177
|
__name(zip, "zip");
|
|
156
178
|
function partition(array, predicate) {
|
|
179
|
+
const pass = [];
|
|
180
|
+
const fail = [];
|
|
157
181
|
if (!Array.isArray(array)) return [
|
|
158
|
-
|
|
159
|
-
|
|
182
|
+
pass,
|
|
183
|
+
fail
|
|
184
|
+
];
|
|
185
|
+
for (let i = 0; i < array.length; i++) {
|
|
186
|
+
const item = array[i];
|
|
187
|
+
(predicate(item, i, array) ? pass : fail).push(item);
|
|
188
|
+
}
|
|
189
|
+
return [
|
|
190
|
+
pass,
|
|
191
|
+
fail
|
|
160
192
|
];
|
|
161
|
-
return array.reduce(([pass, fail], item, index) => {
|
|
162
|
-
return predicate(item, index, array) ? [
|
|
163
|
-
[
|
|
164
|
-
...pass,
|
|
165
|
-
item
|
|
166
|
-
],
|
|
167
|
-
fail
|
|
168
|
-
] : [
|
|
169
|
-
pass,
|
|
170
|
-
[
|
|
171
|
-
...fail,
|
|
172
|
-
item
|
|
173
|
-
]
|
|
174
|
-
];
|
|
175
|
-
}, [
|
|
176
|
-
[],
|
|
177
|
-
[]
|
|
178
|
-
]);
|
|
179
193
|
}
|
|
180
194
|
__name(partition, "partition");
|
|
181
195
|
function range(start, end, step = 1) {
|
|
@@ -183,46 +197,159 @@ function range(start, end, step = 1) {
|
|
|
183
197
|
throw new TypeError("Arguments must be finite numbers");
|
|
184
198
|
}
|
|
185
199
|
if (step === 0) throw new Error("Step cannot be zero");
|
|
186
|
-
const
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const result = new Array(length);
|
|
192
|
-
for (let i = 0, value = start; i < length; i++, value += step) {
|
|
193
|
-
result[i] = value;
|
|
200
|
+
const result = [];
|
|
201
|
+
if (step > 0) {
|
|
202
|
+
for (let i = start; i < end; i += step) result.push(i);
|
|
203
|
+
} else {
|
|
204
|
+
for (let i = start; i > end; i += step) result.push(i);
|
|
194
205
|
}
|
|
195
206
|
return result;
|
|
196
207
|
}
|
|
197
208
|
__name(range, "range");
|
|
198
209
|
function take(array, n = 1) {
|
|
199
210
|
if (!Array.isArray(array) || n <= 0) return [];
|
|
200
|
-
return array.slice(0, n);
|
|
211
|
+
return n >= array.length ? array.slice() : array.slice(0, n);
|
|
201
212
|
}
|
|
202
213
|
__name(take, "take");
|
|
203
214
|
function takeWhile(array, predicate) {
|
|
204
|
-
if (!Array.isArray(array)) return [];
|
|
205
215
|
const result = [];
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
216
|
+
if (!Array.isArray(array)) return result;
|
|
217
|
+
const len = array.length;
|
|
218
|
+
for (let i = 0; i < len; i++) {
|
|
219
|
+
const item = array[i];
|
|
220
|
+
if (!predicate(item, i)) break;
|
|
221
|
+
result.push(item);
|
|
209
222
|
}
|
|
210
223
|
return result;
|
|
211
224
|
}
|
|
212
225
|
__name(takeWhile, "takeWhile");
|
|
213
226
|
function compact(array) {
|
|
214
227
|
if (!Array.isArray(array)) return [];
|
|
215
|
-
|
|
228
|
+
const result = [];
|
|
229
|
+
for (const v of array) {
|
|
230
|
+
if (v) result.push(v);
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
216
233
|
}
|
|
217
234
|
__name(compact, "compact");
|
|
218
235
|
function countBy(array, keyFn) {
|
|
219
236
|
if (!Array.isArray(array)) return {};
|
|
220
|
-
|
|
237
|
+
const result = {};
|
|
238
|
+
for (const item of array) {
|
|
221
239
|
const key = String(keyFn(item));
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
240
|
+
result[key] = (result[key] ?? 0) + 1;
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
225
243
|
}
|
|
226
244
|
__name(countBy, "countBy");
|
|
245
|
+
function toggle(array, item) {
|
|
246
|
+
if (!Array.isArray(array)) return [
|
|
247
|
+
item
|
|
248
|
+
];
|
|
249
|
+
const exists = array.includes(item);
|
|
250
|
+
if (exists) return array.filter((x) => x !== item);
|
|
251
|
+
return [
|
|
252
|
+
...array,
|
|
253
|
+
item
|
|
254
|
+
];
|
|
255
|
+
}
|
|
256
|
+
__name(toggle, "toggle");
|
|
257
|
+
function secureIndex(max) {
|
|
258
|
+
if (!Number.isInteger(max) || max <= 0) throw new RangeError("Max must be a positive integer");
|
|
259
|
+
const limit = 4294967295 - 4294967295 % max;
|
|
260
|
+
let rand;
|
|
261
|
+
do {
|
|
262
|
+
rand = randomBytes(4).readUInt32BE(0);
|
|
263
|
+
} while (rand >= limit);
|
|
264
|
+
return rand % max;
|
|
265
|
+
}
|
|
266
|
+
__name(secureIndex, "secureIndex");
|
|
267
|
+
var secureRandom = /* @__PURE__ */ __name((array) => {
|
|
268
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
269
|
+
const idx = secureIndex(array.length);
|
|
270
|
+
return array[idx];
|
|
271
|
+
}, "secureRandom");
|
|
272
|
+
function findLast(array, predicate) {
|
|
273
|
+
if (!Array.isArray(array)) return void 0;
|
|
274
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
275
|
+
if (predicate(array[i], i, array)) return array[i];
|
|
276
|
+
}
|
|
277
|
+
return void 0;
|
|
278
|
+
}
|
|
279
|
+
__name(findLast, "findLast");
|
|
280
|
+
function findLastIndex(array, predicate) {
|
|
281
|
+
if (!Array.isArray(array)) return -1;
|
|
282
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
283
|
+
if (predicate(array[i], i, array)) return i;
|
|
284
|
+
}
|
|
285
|
+
return -1;
|
|
286
|
+
}
|
|
287
|
+
__name(findLastIndex, "findLastIndex");
|
|
288
|
+
function chunkBy(array, predicate) {
|
|
289
|
+
if (!Array.isArray(array) || array.length === 0) return [];
|
|
290
|
+
const result = [];
|
|
291
|
+
let chunk2 = [];
|
|
292
|
+
for (let i = 0; i < array.length; i++) {
|
|
293
|
+
if (predicate(array[i], i, array) && chunk2.length) {
|
|
294
|
+
result.push(chunk2);
|
|
295
|
+
chunk2 = [];
|
|
296
|
+
}
|
|
297
|
+
chunk2.push(array[i]);
|
|
298
|
+
}
|
|
299
|
+
if (chunk2.length) result.push(chunk2);
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
__name(chunkBy, "chunkBy");
|
|
303
|
+
function remove(array, value) {
|
|
304
|
+
if (!Array.isArray(array)) return [];
|
|
305
|
+
return array.filter((item) => item !== value);
|
|
306
|
+
}
|
|
307
|
+
__name(remove, "remove");
|
|
308
|
+
function isSorted(array, direction = "asc", compareFn) {
|
|
309
|
+
if (!Array.isArray(array) || array.length <= 1) return true;
|
|
310
|
+
const cmp = compareFn || ((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
311
|
+
for (let i = 1; i < array.length; i++) {
|
|
312
|
+
const res = cmp(array[i - 1], array[i]);
|
|
313
|
+
if (direction === "asc" && res > 0 || direction === "desc" && res < 0) return false;
|
|
314
|
+
}
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
__name(isSorted, "isSorted");
|
|
318
|
+
function headOfArr(array) {
|
|
319
|
+
return Array.isArray(array) && array.length > 0 ? array[0] : void 0;
|
|
320
|
+
}
|
|
321
|
+
__name(headOfArr, "headOfArr");
|
|
322
|
+
function lastOfArr(array) {
|
|
323
|
+
return Array.isArray(array) && array.length > 0 ? array.at(-1) : void 0;
|
|
324
|
+
}
|
|
325
|
+
__name(lastOfArr, "lastOfArr");
|
|
326
|
+
function drop(array, n) {
|
|
327
|
+
if (!Array.isArray(array) || n <= 0) return [
|
|
328
|
+
...array
|
|
329
|
+
];
|
|
330
|
+
return array.slice(n);
|
|
331
|
+
}
|
|
332
|
+
__name(drop, "drop");
|
|
333
|
+
function dropWhile(array, predicate) {
|
|
334
|
+
if (!Array.isArray(array)) return [];
|
|
335
|
+
let i = 0;
|
|
336
|
+
while (i < array.length && predicate(array[i], i)) {
|
|
337
|
+
i++;
|
|
338
|
+
}
|
|
339
|
+
return array.slice(i);
|
|
340
|
+
}
|
|
341
|
+
__name(dropWhile, "dropWhile");
|
|
342
|
+
function maxBy(array, keyOrFn) {
|
|
343
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
344
|
+
const fn = typeof keyOrFn === "function" ? keyOrFn : (item) => item[keyOrFn];
|
|
345
|
+
return array.reduce((max, item) => fn(item) > fn(max) ? item : max, array[0]);
|
|
346
|
+
}
|
|
347
|
+
__name(maxBy, "maxBy");
|
|
348
|
+
function minBy(array, keyOrFn) {
|
|
349
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
350
|
+
const fn = typeof keyOrFn === "function" ? keyOrFn : (item) => item[keyOrFn];
|
|
351
|
+
return array.reduce((min, item) => fn(item) < fn(min) ? item : min, array[0]);
|
|
352
|
+
}
|
|
353
|
+
__name(minBy, "minBy");
|
|
227
354
|
|
|
228
|
-
export { chunk, compact, countBy, difference, flattenDeep, groupBy, intersect, mergeSort, partition, pluck, random, range, shuffle, take, takeWhile, unique, zip };
|
|
355
|
+
export { chunk, chunkBy, compact, countBy, difference, drop, dropWhile, findLast, findLastIndex, flattenDeep, groupBy, headOfArr, intersect, isSorted, lastOfArr, maxBy, mergeSort, minBy, partition, pluck, random, range, remove, secureIndex, secureRandom, shuffle, take, takeWhile, toggle, unique, zip };
|
package/async/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -45,7 +45,13 @@ function debounce(fn, delay) {
|
|
|
45
45
|
pendingArgs = args;
|
|
46
46
|
if (timer) clearTimeout(timer);
|
|
47
47
|
timer = setTimeout(() => {
|
|
48
|
-
|
|
48
|
+
try {
|
|
49
|
+
fn(...pendingArgs);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
logger.getLogger().error({
|
|
52
|
+
err
|
|
53
|
+
}, "Error in debounced function");
|
|
54
|
+
}
|
|
49
55
|
timer = null;
|
|
50
56
|
}, delay);
|
|
51
57
|
}
|
|
@@ -58,7 +64,13 @@ function debounce(fn, delay) {
|
|
|
58
64
|
debounced.flush = () => {
|
|
59
65
|
if (timer) {
|
|
60
66
|
clearTimeout(timer);
|
|
61
|
-
|
|
67
|
+
try {
|
|
68
|
+
fn(...pendingArgs);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
logger.getLogger().error({
|
|
71
|
+
err
|
|
72
|
+
}, "Error in debounced.flush");
|
|
73
|
+
}
|
|
62
74
|
timer = null;
|
|
63
75
|
pendingArgs = null;
|
|
64
76
|
}
|
|
@@ -66,10 +78,11 @@ function debounce(fn, delay) {
|
|
|
66
78
|
return debounced;
|
|
67
79
|
}
|
|
68
80
|
__name(debounce, "debounce");
|
|
69
|
-
|
|
81
|
+
var DEFAULT_THROTTLE_OPTS = {
|
|
70
82
|
leading: true,
|
|
71
83
|
trailing: false
|
|
72
|
-
}
|
|
84
|
+
};
|
|
85
|
+
function throttle(fn, limit, opts = DEFAULT_THROTTLE_OPTS) {
|
|
73
86
|
let lastCall = 0;
|
|
74
87
|
let timer = null;
|
|
75
88
|
let savedArgs = null;
|
|
@@ -84,14 +97,28 @@ function throttle(fn, limit, opts = {
|
|
|
84
97
|
timer = null;
|
|
85
98
|
}
|
|
86
99
|
lastCall = now;
|
|
87
|
-
|
|
100
|
+
try {
|
|
101
|
+
fn(...args);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
logger.getLogger().error({
|
|
104
|
+
err
|
|
105
|
+
}, "Error in throttled function");
|
|
106
|
+
}
|
|
88
107
|
} else if (trailing) {
|
|
89
108
|
savedArgs = args;
|
|
90
109
|
if (!timer) {
|
|
91
110
|
timer = setTimeout(() => {
|
|
92
111
|
lastCall = leading ? Date.now() : 0;
|
|
93
112
|
timer = null;
|
|
94
|
-
if (savedArgs)
|
|
113
|
+
if (savedArgs) {
|
|
114
|
+
try {
|
|
115
|
+
fn(...savedArgs);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
logger.getLogger().error({
|
|
118
|
+
err
|
|
119
|
+
}, "Error in throttled trailing call");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
95
122
|
}, remaining);
|
|
96
123
|
}
|
|
97
124
|
}
|
|
@@ -142,7 +169,7 @@ function singletonAsync(fn, drop = false) {
|
|
|
142
169
|
promise = null;
|
|
143
170
|
});
|
|
144
171
|
} else if (drop) {
|
|
145
|
-
|
|
172
|
+
throw new Error("Function is already in progress");
|
|
146
173
|
}
|
|
147
174
|
return promise;
|
|
148
175
|
};
|
|
@@ -213,11 +240,19 @@ async function runInSeries(tasks) {
|
|
|
213
240
|
__name(runInSeries, "runInSeries");
|
|
214
241
|
function memoizeAsync(fn, options = {}) {
|
|
215
242
|
const cache = /* @__PURE__ */ new Map();
|
|
216
|
-
const { ttl
|
|
217
|
-
|
|
218
|
-
|
|
243
|
+
const { ttl } = options;
|
|
244
|
+
const generateKey = /* @__PURE__ */ __name((args) => {
|
|
245
|
+
try {
|
|
246
|
+
return options.keyFn?.(args) ?? JSON.stringify(args);
|
|
247
|
+
} catch {
|
|
248
|
+
logger.getLogger().warn("memoizeAsync: key generation failed, falling back to JSON.stringify");
|
|
249
|
+
return JSON.stringify(args);
|
|
250
|
+
}
|
|
251
|
+
}, "generateKey");
|
|
252
|
+
return async (...args) => {
|
|
253
|
+
const key = generateKey(args);
|
|
219
254
|
const cached = cache.get(key);
|
|
220
|
-
if (cached &&
|
|
255
|
+
if (cached && Date.now() < cached.expires) {
|
|
221
256
|
return cached.value;
|
|
222
257
|
}
|
|
223
258
|
const result = await fn(...args);
|
|
@@ -236,7 +271,10 @@ function abortable(promise, signal, abortValue = new Error("Operation aborted"))
|
|
|
236
271
|
return Promise.race([
|
|
237
272
|
promise,
|
|
238
273
|
new Promise((_, reject) => {
|
|
239
|
-
const abort = /* @__PURE__ */ __name(() =>
|
|
274
|
+
const abort = /* @__PURE__ */ __name(() => {
|
|
275
|
+
reject(abortValue);
|
|
276
|
+
signal.removeEventListener("abort", abort);
|
|
277
|
+
}, "abort");
|
|
240
278
|
signal.addEventListener("abort", abort, {
|
|
241
279
|
once: true
|
|
242
280
|
});
|
|
@@ -305,39 +343,53 @@ var CircuitBreakerState = /* @__PURE__ */ (function(CircuitBreakerState2) {
|
|
|
305
343
|
function circuitBreaker(fn, options = {}) {
|
|
306
344
|
const { failureThreshold = 5, resetTimeout = 1e4, successThreshold = 1, onOpen, onClose, onHalfOpen } = options;
|
|
307
345
|
let state = "CLOSED";
|
|
308
|
-
let
|
|
309
|
-
let
|
|
310
|
-
let
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
346
|
+
let fails = 0;
|
|
347
|
+
let halfSuccess = 0;
|
|
348
|
+
let unlockAt = 0;
|
|
349
|
+
const reset = /* @__PURE__ */ __name(() => {
|
|
350
|
+
fails = 0;
|
|
351
|
+
halfSuccess = 0;
|
|
352
|
+
state = "CLOSED";
|
|
353
|
+
onClose?.();
|
|
354
|
+
}, "reset");
|
|
355
|
+
const open = /* @__PURE__ */ __name(() => {
|
|
356
|
+
state = "OPEN";
|
|
357
|
+
unlockAt = Date.now() + resetTimeout;
|
|
358
|
+
onOpen?.();
|
|
359
|
+
}, "open");
|
|
360
|
+
const halfOpen = /* @__PURE__ */ __name(() => {
|
|
361
|
+
state = "HALF_OPEN";
|
|
362
|
+
onHalfOpen?.();
|
|
363
|
+
}, "halfOpen");
|
|
364
|
+
return async (...args) => {
|
|
365
|
+
const now = Date.now();
|
|
366
|
+
if (state === "OPEN" && now < unlockAt) {
|
|
367
|
+
throw new CircuitBreakerOpenError();
|
|
368
|
+
}
|
|
369
|
+
if (state === "OPEN" && now >= unlockAt) {
|
|
370
|
+
halfOpen();
|
|
318
371
|
}
|
|
319
372
|
try {
|
|
320
|
-
const
|
|
373
|
+
const res = await fn(...args);
|
|
321
374
|
if (state === "HALF_OPEN") {
|
|
322
|
-
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
state = "
|
|
327
|
-
if (onClose) onClose();
|
|
375
|
+
halfSuccess++;
|
|
376
|
+
if (halfSuccess >= successThreshold) {
|
|
377
|
+
reset();
|
|
378
|
+
} else {
|
|
379
|
+
state = "HALF_OPEN";
|
|
328
380
|
}
|
|
329
381
|
} else {
|
|
330
|
-
|
|
382
|
+
fails = 0;
|
|
331
383
|
}
|
|
332
|
-
return
|
|
333
|
-
} catch (
|
|
334
|
-
|
|
335
|
-
if (
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
384
|
+
return res;
|
|
385
|
+
} catch (err) {
|
|
386
|
+
fails++;
|
|
387
|
+
if (state === "HALF_OPEN" || state === "CLOSED") {
|
|
388
|
+
if (fails >= failureThreshold) {
|
|
389
|
+
open();
|
|
390
|
+
}
|
|
339
391
|
}
|
|
340
|
-
throw
|
|
392
|
+
throw err;
|
|
341
393
|
}
|
|
342
394
|
};
|
|
343
395
|
}
|
|
@@ -353,12 +405,15 @@ async function runWithConcurrency(tasks, options = {}) {
|
|
|
353
405
|
}
|
|
354
406
|
return new Promise((resolve, reject) => {
|
|
355
407
|
let taskIndex = 0;
|
|
408
|
+
let rejected = false;
|
|
356
409
|
const processNext = /* @__PURE__ */ __name(async () => {
|
|
410
|
+
if (rejected) return;
|
|
357
411
|
const currentTaskIndex = taskIndex++;
|
|
358
412
|
if (currentTaskIndex >= totalTasks) return;
|
|
359
413
|
try {
|
|
360
414
|
const result = await tasks[currentTaskIndex]();
|
|
361
415
|
if (signal?.aborted) {
|
|
416
|
+
rejected = true;
|
|
362
417
|
reject(new Error("Aborted"));
|
|
363
418
|
return;
|
|
364
419
|
}
|
|
@@ -374,6 +429,7 @@ async function runWithConcurrency(tasks, options = {}) {
|
|
|
374
429
|
}
|
|
375
430
|
}
|
|
376
431
|
} catch (error) {
|
|
432
|
+
rejected = true;
|
|
377
433
|
reject(error);
|
|
378
434
|
return;
|
|
379
435
|
}
|
|
@@ -389,6 +445,7 @@ async function runWithConcurrency(tasks, options = {}) {
|
|
|
389
445
|
}
|
|
390
446
|
if (signal) {
|
|
391
447
|
signal.addEventListener("abort", () => {
|
|
448
|
+
rejected = true;
|
|
392
449
|
reject(new Error("Aborted"));
|
|
393
450
|
}, {
|
|
394
451
|
once: true
|
|
@@ -405,6 +462,25 @@ function optionalRequire(name) {
|
|
|
405
462
|
}
|
|
406
463
|
}
|
|
407
464
|
__name(optionalRequire, "optionalRequire");
|
|
465
|
+
async function raceWithValue(promises) {
|
|
466
|
+
return new Promise((resolve, reject) => {
|
|
467
|
+
let rejectedCount = 0;
|
|
468
|
+
let lastError;
|
|
469
|
+
promises.forEach((p, index) => {
|
|
470
|
+
p.then((value) => resolve({
|
|
471
|
+
value,
|
|
472
|
+
index
|
|
473
|
+
})).catch((err) => {
|
|
474
|
+
rejectedCount++;
|
|
475
|
+
lastError = err;
|
|
476
|
+
if (rejectedCount === promises.length) {
|
|
477
|
+
reject(lastError);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
__name(raceWithValue, "raceWithValue");
|
|
408
484
|
|
|
409
485
|
exports.CircuitBreakerOpenError = CircuitBreakerOpenError;
|
|
410
486
|
exports.CircuitBreakerState = CircuitBreakerState;
|
|
@@ -415,6 +491,7 @@ exports.createTaskQueue = createTaskQueue;
|
|
|
415
491
|
exports.debounce = debounce;
|
|
416
492
|
exports.memoizeAsync = memoizeAsync;
|
|
417
493
|
exports.optionalRequire = optionalRequire;
|
|
494
|
+
exports.raceWithValue = raceWithValue;
|
|
418
495
|
exports.rateLimit = rateLimit;
|
|
419
496
|
exports.retry = retry;
|
|
420
497
|
exports.runInBatches = runInBatches;
|