@catbee/utils 2.0.0-next.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -16
- package/array/index.cjs +180 -71
- package/array/index.d.ts +293 -1
- package/array/index.mjs +171 -72
- package/async/index.cjs +92 -36
- package/async/index.d.ts +275 -1
- package/async/index.mjs +92 -36
- package/cache/index.cjs +1 -1
- package/cache/index.d.ts +155 -1
- package/cache/index.mjs +2 -2
- package/config/index.cjs +78 -64
- package/config/index.d.ts +64 -2
- package/config/index.mjs +76 -64
- package/context-store/index.d.ts +192 -1
- package/crypto/index.d.ts +163 -1
- package/date/index.cjs +46 -1
- package/date/index.d.ts +190 -1
- package/date/index.mjs +45 -2
- package/decorators/index.cjs +1156 -18
- package/decorators/index.d.ts +684 -1
- package/decorators/index.mjs +1156 -18
- package/dir/index.cjs +4 -3
- package/dir/index.d.ts +195 -1
- package/dir/index.mjs +4 -3
- package/env/index.cjs +10 -26
- package/env/index.d.ts +379 -1
- package/env/index.mjs +10 -26
- package/exception/index.d.ts +232 -1
- package/fs/index.cjs +70 -36
- package/fs/index.d.ts +205 -1
- package/fs/index.mjs +64 -34
- package/http-status-codes/index.d.ts +267 -1
- package/id/index.d.ts +37 -1
- package/index.cjs +3 -3
- package/index.d.ts +1 -1
- package/index.mjs +1 -1
- package/logger/index.cjs +11 -11
- package/logger/index.d.ts +189 -1
- package/logger/index.mjs +12 -12
- package/middleware/index.d.ts +103 -1
- package/obj/index.cjs +150 -162
- package/obj/index.d.ts +136 -1
- package/obj/index.mjs +150 -162
- package/package.json +11 -11
- package/performance/index.cjs +2 -2
- package/performance/index.d.ts +138 -1
- package/performance/index.mjs +2 -2
- package/request/index.cjs +1 -1
- package/request/index.d.ts +241 -2
- package/request/index.mjs +1 -1
- package/response/index.d.ts +318 -2
- package/server/index.cjs +27 -23
- package/server/index.d.ts +785 -4
- package/server/index.mjs +28 -23
- package/stream/index.d.ts +90 -1
- package/string/index.d.ts +102 -1
- package/type/index.cjs +1 -1
- package/type/index.d.ts +107 -1
- package/type/index.mjs +1 -1
- package/types/index.d.ts +774 -4
- package/url/index.cjs +2 -4
- package/url/index.d.ts +142 -1
- package/url/index.mjs +2 -4
- package/{validate → validation}/index.cjs +89 -42
- package/{validate/validate.utils.d.ts → validation/index.d.ts} +32 -23
- package/{validate → validation}/index.mjs +85 -42
- 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/decorators.utils.d.ts +0 -705
- package/dir/dir.utils.d.ts +0 -216
- 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/obj.utils.d.ts +0 -156
- 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.d.ts
CHANGED
|
@@ -22,4 +22,296 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Splits an array into chunks of the specified size.
|
|
27
|
+
*
|
|
28
|
+
* @template T The type of array elements.
|
|
29
|
+
* @param {T[]} array - The array to split into chunks.
|
|
30
|
+
* @param {number} size - The number of elements per chunk.
|
|
31
|
+
* @returns {T[][]} A new array containing chunked arrays.
|
|
32
|
+
* @throws {TypeError} If array is not an array.
|
|
33
|
+
* @throws {Error} If chunk size is not a positive integer.
|
|
34
|
+
*/
|
|
35
|
+
declare function chunk<T>(array: readonly T[], size: number): T[][];
|
|
36
|
+
/**
|
|
37
|
+
* Removes duplicate values from an array.
|
|
38
|
+
* Optionally enforces uniqueness by a key function.
|
|
39
|
+
*
|
|
40
|
+
* @template T The type of array elements.
|
|
41
|
+
* @param {T[]} array - The input array.
|
|
42
|
+
* @param {(item: T) => unknown} [keyFn] - Optional function to determine uniqueness by key.
|
|
43
|
+
* @returns {T[]} A new array with unique values.
|
|
44
|
+
*/
|
|
45
|
+
declare function unique<T>(array: readonly T[], keyFn?: (item: T) => unknown): T[];
|
|
46
|
+
/**
|
|
47
|
+
* Deeply flattens a nested array to a single-level array (iterative, stack-based).
|
|
48
|
+
*
|
|
49
|
+
* @template T The leaf type of array elements.
|
|
50
|
+
* @param {readonly unknown[]} array - The (possibly deeply nested) input array.
|
|
51
|
+
* @returns {T[]} A deeply flattened array.
|
|
52
|
+
*/
|
|
53
|
+
declare function flattenDeep<T>(array: readonly unknown[]): T[];
|
|
54
|
+
/**
|
|
55
|
+
* Returns a random element from an array, or undefined if empty. Uses crypto-secure randomness
|
|
56
|
+
*
|
|
57
|
+
* @template T The type of array elements.
|
|
58
|
+
* @param {T[]} array - The input array.
|
|
59
|
+
* @returns {T | undefined} A randomly selected item, or undefined if array is empty or not an array.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* securePick(['a','b','c']); // -> 'b'
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function random<T>(array: readonly T[]): T | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Groups items in an array by a nested key or key function.
|
|
69
|
+
*
|
|
70
|
+
* @template T The type of array elements.
|
|
71
|
+
* @overload
|
|
72
|
+
* @param {T[]} array - The array to group.
|
|
73
|
+
* @param {keyof T} key - Property key to group by.
|
|
74
|
+
* @returns {Record<string, readonly T[]>}
|
|
75
|
+
* @overload
|
|
76
|
+
* @param {T[]} array - The array to group.
|
|
77
|
+
* @param {(item: T) => string | number | symbol} keyFn - Function to generate group key from item.
|
|
78
|
+
* @returns {Record<K, readonly T[]>}
|
|
79
|
+
* @param {T[]} array - The array to group.
|
|
80
|
+
* @param {keyof T | ((item: T) => string | number | symbol)} keyOrFn - Nested property key or key selector.
|
|
81
|
+
* @returns {Record<string | number | symbol, readonly T[]>} Grouped result object.
|
|
82
|
+
*/
|
|
83
|
+
declare function groupBy<T>(array: T[], key: keyof T): Record<string, readonly T[]>;
|
|
84
|
+
declare function groupBy<T, K extends string | number | symbol>(array: T[], keyFn: (item: T) => K): Record<K, readonly T[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Shuffles an array using the Fisher-Yates algorithm. Uses crypto-secure randomness.
|
|
87
|
+
*
|
|
88
|
+
* @template T The type of array elements.
|
|
89
|
+
* @param {T[]} array - The input array.
|
|
90
|
+
* @returns {T[]} A new shuffled array.
|
|
91
|
+
* @throws {TypeError} If array is not an array.
|
|
92
|
+
*/
|
|
93
|
+
declare function shuffle<T>(array: readonly T[]): T[];
|
|
94
|
+
/**
|
|
95
|
+
* Returns an array of property values from an array of objects. Returns undefined for missing properties.
|
|
96
|
+
*
|
|
97
|
+
* @template T The type of array elements.
|
|
98
|
+
* @template K The object property to pluck.
|
|
99
|
+
* @param {T[]} array - The input array.
|
|
100
|
+
* @param {K} key - The property name to pluck.
|
|
101
|
+
* @returns {T[K][]} Array of property values.
|
|
102
|
+
*/
|
|
103
|
+
declare function pluck<T, K extends keyof T>(array: readonly T[], key: K): T[K][];
|
|
104
|
+
/**
|
|
105
|
+
* Returns values in array A that are not in array B.
|
|
106
|
+
*
|
|
107
|
+
* @template T The type of array elements.
|
|
108
|
+
* @param {T[]} a - First array.
|
|
109
|
+
* @param {T[]} b - Second array.
|
|
110
|
+
* @returns {T[]} Elements in A that are not in B.
|
|
111
|
+
*/
|
|
112
|
+
declare function difference<T>(a: readonly T[], b: readonly T[]): T[];
|
|
113
|
+
/**
|
|
114
|
+
* Returns common values between arrays A and B.
|
|
115
|
+
*
|
|
116
|
+
* @template T The type of array elements.
|
|
117
|
+
* @param {T[]} a - First array.
|
|
118
|
+
* @param {T[]} b - Second array.
|
|
119
|
+
* @returns {T[]} Elements that exist in both arrays.
|
|
120
|
+
*/
|
|
121
|
+
declare function intersect<T>(a: readonly T[], b: readonly T[]): T[];
|
|
122
|
+
/**
|
|
123
|
+
* Sorts an array of objects by a nested key using Merge Sort (O(n log n)).
|
|
124
|
+
* Missing/undefined keys are sorted to the "end" (asc) or "start" (desc").
|
|
125
|
+
* Optionally accepts a custom compare function or collator.
|
|
126
|
+
*
|
|
127
|
+
* @template T The type of array elements (objects).
|
|
128
|
+
* @param {T[]} array - Array of objects to sort.
|
|
129
|
+
* @param {string | ((item: T) => any)} key - Dot-notated key (e.g., "profile.age") or function.
|
|
130
|
+
* @param {"asc" | "desc"} [direction="asc"] - Sort direction: 'asc' or 'desc'.
|
|
131
|
+
* @param {(a: T, b: T) => number} [compareFn] - Optional custom compare function.
|
|
132
|
+
* @returns {T[]} A new sorted array.
|
|
133
|
+
* @throws {TypeError} If array is not an array.
|
|
134
|
+
*/
|
|
135
|
+
declare function mergeSort<T>(array: readonly T[], key: string | ((item: T) => unknown), direction?: 'asc' | 'desc', compareFn?: (a: T, b: T) => number): T[];
|
|
136
|
+
/**
|
|
137
|
+
* Combines multiple arrays into a single array of grouped elements.
|
|
138
|
+
* Output length equals the length of the shortest input array.
|
|
139
|
+
*
|
|
140
|
+
* This implementation ensures type safety and avoids holes in output.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* zip([1, 2], ['a', 'b']) => [[1, 'a'], [2, 'b']]
|
|
145
|
+
* ```
|
|
146
|
+
* @param {...Array<T>[]} arrays - Two or more arrays to zip together.
|
|
147
|
+
* @returns {Array<T[]>} Array of grouped elements.
|
|
148
|
+
*/
|
|
149
|
+
declare function zip<T>(...arrays: ReadonlyArray<T>[]): T[][];
|
|
150
|
+
/**
|
|
151
|
+
* Splits an array into two arrays based on a predicate function.
|
|
152
|
+
* Supports type-guard narrowing via overload.
|
|
153
|
+
*
|
|
154
|
+
* @template T The type of array elements.
|
|
155
|
+
* @overload
|
|
156
|
+
* @param {readonly T[]} array - The input array.
|
|
157
|
+
* @param {(item: T, index: number, array: readonly T[]) => item is U} predicate - Type guard predicate.
|
|
158
|
+
* @returns {[U[], Exclude<T, U>[]]} A tuple of two arrays: [matched, unmatched].
|
|
159
|
+
* @overload
|
|
160
|
+
* @param {readonly T[]} array - The input array.
|
|
161
|
+
* @param {(item: T, index: number, array: readonly T[]) => boolean} predicate - Boolean predicate.
|
|
162
|
+
* @returns {[T[], T[]]} A tuple of two arrays: [matched, unmatched].
|
|
163
|
+
*/
|
|
164
|
+
declare function partition<T, U extends T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => item is U): [U[], Exclude<T, U>[]];
|
|
165
|
+
declare function partition<T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => boolean): [T[], T[]];
|
|
166
|
+
/**
|
|
167
|
+
* Generates an array of numbers within a specified range.
|
|
168
|
+
*
|
|
169
|
+
* @param {number} start - Start of range (inclusive).
|
|
170
|
+
* @param {number} end - End of range (exclusive).
|
|
171
|
+
* @param {number} [step=1] - Step between numbers.
|
|
172
|
+
* @returns {number[]} Array of numbers in range.
|
|
173
|
+
*/
|
|
174
|
+
declare function range(start: number, end: number, step?: number): number[];
|
|
175
|
+
/**
|
|
176
|
+
* Returns the first `n` elements from an array.
|
|
177
|
+
*
|
|
178
|
+
* @template T The type of array elements.
|
|
179
|
+
* @param {T[]} array - The input array.
|
|
180
|
+
* @param {number} [n=1] - Number of elements to take.
|
|
181
|
+
* @returns {T[]} New array with first n elements.
|
|
182
|
+
*/
|
|
183
|
+
declare function take<T>(array: readonly T[], n?: number): T[];
|
|
184
|
+
/**
|
|
185
|
+
* Takes elements from an array while predicate returns true.
|
|
186
|
+
*
|
|
187
|
+
* @template T The type of array elements.
|
|
188
|
+
* @param {readonly T[]} array - Input array.
|
|
189
|
+
* @param {(item: T, index: number) => boolean} predicate - Condition function.
|
|
190
|
+
* @returns {T[]} New array with taken elements.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* takeWhile([1,2,3,4], (n) => n < 3); // -> [1,2]
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
declare function takeWhile<T>(array: readonly T[], predicate: (item: T, index: number) => boolean): T[];
|
|
198
|
+
/**
|
|
199
|
+
* Removes all falsy values from an array.
|
|
200
|
+
* `false`, `null`, `0`, `""`, `undefined`, and `NaN` are falsy.
|
|
201
|
+
*
|
|
202
|
+
* @template T The type of array elements.
|
|
203
|
+
* @param {T[]} array - The input array.
|
|
204
|
+
* @returns {NonNullable<T>[]} New array with falsy values removed.
|
|
205
|
+
*/
|
|
206
|
+
declare function compact<T>(array: readonly T[]): NonNullable<T>[];
|
|
207
|
+
/**
|
|
208
|
+
* Counts array elements by a key function.
|
|
209
|
+
*
|
|
210
|
+
* @template T The type of array elements.
|
|
211
|
+
* @param {T[]} array - The input array.
|
|
212
|
+
* @param {(item: T) => string | number | symbol} keyFn - Function to generate count key.
|
|
213
|
+
* @returns {Record<string, number>} Object with counts by key.
|
|
214
|
+
*/
|
|
215
|
+
declare function countBy<T>(array: readonly T[], keyFn: (item: T) => string | number | symbol): Record<string, number>;
|
|
216
|
+
/**
|
|
217
|
+
* Toggles an item in array (adds if not present, removes if present).
|
|
218
|
+
*
|
|
219
|
+
* @template T
|
|
220
|
+
* @param {readonly T[]} array
|
|
221
|
+
* @param {T} item
|
|
222
|
+
* @returns {T[]} New array with item toggled.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* toggle([1,2,3], 2); // -> [1,3]
|
|
227
|
+
* toggle([1,3], 2); // -> [1,3,2]
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
declare function toggle<T>(array: readonly T[], item: T): T[];
|
|
231
|
+
/**
|
|
232
|
+
* Returns a cryptographically secure random index for an array.
|
|
233
|
+
* Used internally for secure pick/shuffle operations.
|
|
234
|
+
*
|
|
235
|
+
* @param {number} max Upper bound (exclusive).
|
|
236
|
+
* @returns {number} A secure random integer in range `[0, max)`.
|
|
237
|
+
* @throws {RangeError} If `max` is not a positive number.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* secureIndex(10); // -> 3 (unpredictable)
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
declare function secureIndex(max: number): number;
|
|
245
|
+
/**
|
|
246
|
+
* Returns a secure random element from an array using Node crypto.
|
|
247
|
+
*
|
|
248
|
+
* @template T
|
|
249
|
+
* @param {readonly T[]} array
|
|
250
|
+
* @returns {T | undefined}
|
|
251
|
+
*/
|
|
252
|
+
declare const secureRandom: <T>(array: readonly T[]) => T | undefined;
|
|
253
|
+
/**
|
|
254
|
+
* Returns the last element in the array that satisfies the provided testing function.
|
|
255
|
+
*
|
|
256
|
+
* @template T
|
|
257
|
+
* @param {readonly T[]} array - The input array.
|
|
258
|
+
* @param {(item: T, index: number, array: readonly T[]) => boolean} predicate - Function to test each element.
|
|
259
|
+
* @returns {T | undefined} The found element, or undefined if not found.
|
|
260
|
+
*/
|
|
261
|
+
declare function findLast<T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => boolean): T | undefined;
|
|
262
|
+
/**
|
|
263
|
+
* Returns the index of the last element in the array that satisfies the provided testing function.
|
|
264
|
+
*
|
|
265
|
+
* @template T
|
|
266
|
+
* @param {readonly T[]} array - The input array.
|
|
267
|
+
* @param {(item: T, index: number, array: readonly T[]) => boolean} predicate - Function to test each element.
|
|
268
|
+
* @returns {number} The index, or -1 if not found.
|
|
269
|
+
*/
|
|
270
|
+
declare function findLastIndex<T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => boolean): number;
|
|
271
|
+
/**
|
|
272
|
+
* Splits an array into chunks based on a predicate function.
|
|
273
|
+
* Each chunk starts when predicate returns true.
|
|
274
|
+
*
|
|
275
|
+
* @template T
|
|
276
|
+
* @param {readonly T[]} array - The input array.
|
|
277
|
+
* @param {(item: T, index: number, array: readonly T[]) => boolean} predicate - Function to determine chunk boundaries.
|
|
278
|
+
* @returns {T[][]} Array of chunked arrays.
|
|
279
|
+
*/
|
|
280
|
+
declare function chunkBy<T>(array: readonly T[], predicate: (item: T, index: number, array: readonly T[]) => boolean): T[][];
|
|
281
|
+
/**
|
|
282
|
+
* Removes all occurrences of a value from an array.
|
|
283
|
+
*
|
|
284
|
+
* @template T
|
|
285
|
+
* @param {readonly T[]} array - The input array.
|
|
286
|
+
* @param {T} value - Value to remove.
|
|
287
|
+
* @returns {T[]} New array with value removed.
|
|
288
|
+
*/
|
|
289
|
+
declare function remove<T>(array: readonly T[], value: T): T[];
|
|
290
|
+
/**
|
|
291
|
+
* Checks if an array is sorted in ascending or descending order.
|
|
292
|
+
*
|
|
293
|
+
* @template T
|
|
294
|
+
* @param {readonly T[]} array - The input array.
|
|
295
|
+
* @param {'asc' | 'desc'} [direction='asc'] - Sort direction.
|
|
296
|
+
* @param {(a: T, b: T) => number} [compareFn] - Optional compare function.
|
|
297
|
+
* @returns {boolean} True if sorted, false otherwise.
|
|
298
|
+
*/
|
|
299
|
+
declare function isSorted<T>(array: readonly T[], direction?: 'asc' | 'desc', compareFn?: (a: T, b: T) => number): boolean;
|
|
300
|
+
/**
|
|
301
|
+
* Returns the first element of an array, or undefined if empty.
|
|
302
|
+
*
|
|
303
|
+
* @template T
|
|
304
|
+
* @param {readonly T[]} array
|
|
305
|
+
* @returns {T | undefined}
|
|
306
|
+
*/
|
|
307
|
+
declare function headOfArr<T>(array: readonly T[]): T | undefined;
|
|
308
|
+
/**
|
|
309
|
+
* Returns the last element of an array, or undefined if empty.
|
|
310
|
+
*
|
|
311
|
+
* @template T
|
|
312
|
+
* @param {readonly T[]} array
|
|
313
|
+
* @returns {T | undefined}
|
|
314
|
+
*/
|
|
315
|
+
declare function lastOfArr<T>(array: readonly T[]): T | undefined;
|
|
316
|
+
|
|
317
|
+
export { chunk, chunkBy, compact, countBy, difference, findLast, findLastIndex, flattenDeep, groupBy, headOfArr, intersect, isSorted, lastOfArr, mergeSort, partition, pluck, random, range, remove, secureIndex, secureRandom, shuffle, take, takeWhile, toggle, unique, zip };
|
package/array/index.mjs
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import { getValueByPath } from '@catbee/utils/obj';
|
|
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) ?? Object.prototype.hasOwnProperty.call(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,131 @@ 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");
|
|
227
326
|
|
|
228
|
-
export { chunk, compact, countBy, difference, flattenDeep, groupBy, intersect, mergeSort, partition, pluck, random, range, shuffle, take, takeWhile, unique, zip };
|
|
327
|
+
export { chunk, chunkBy, compact, countBy, difference, findLast, findLastIndex, flattenDeep, groupBy, headOfArr, intersect, isSorted, lastOfArr, mergeSort, partition, pluck, random, range, remove, secureIndex, secureRandom, shuffle, take, takeWhile, toggle, unique, zip };
|