@catbee/utils 1.1.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/LICENSE +1 -1
- package/README.md +79 -43
- package/array/index.cjs +355 -0
- package/array/index.d.ts +317 -0
- package/array/index.mjs +327 -0
- package/async/index.cjs +484 -0
- package/async/index.d.ts +299 -0
- package/async/index.mjs +463 -0
- package/cache/index.cjs +292 -0
- package/cache/index.d.ts +179 -0
- package/cache/index.mjs +290 -0
- package/config/index.cjs +150 -0
- package/config/index.d.ts +88 -0
- package/config/index.mjs +143 -0
- package/context-store/index.cjs +267 -0
- package/context-store/index.d.ts +216 -0
- package/context-store/index.mjs +261 -0
- package/crypto/index.cjs +182 -0
- package/crypto/index.d.ts +187 -0
- package/crypto/index.mjs +166 -0
- package/date/index.cjs +340 -0
- package/date/index.d.ts +214 -0
- package/date/index.mjs +326 -0
- package/decorators/index.cjs +2051 -0
- package/decorators/index.d.ts +708 -0
- package/decorators/index.mjs +2010 -0
- package/dir/index.cjs +417 -0
- package/dir/index.d.ts +219 -0
- package/dir/index.mjs +390 -0
- package/env/index.cjs +745 -0
- package/env/index.d.ts +403 -0
- package/env/index.mjs +742 -0
- package/exception/index.cjs +362 -0
- package/exception/index.d.ts +256 -0
- package/exception/index.mjs +338 -0
- package/fs/index.cjs +287 -0
- package/fs/index.d.ts +229 -0
- package/fs/index.mjs +258 -0
- package/http-status-codes/index.cjs +96 -0
- package/http-status-codes/index.d.ts +291 -0
- package/http-status-codes/index.mjs +94 -0
- package/id/index.cjs +62 -0
- package/id/index.d.ts +61 -0
- package/id/index.mjs +56 -0
- package/index.cjs +218 -0
- package/index.d.ts +51 -0
- package/index.mjs +51 -0
- package/logger/index.cjs +334 -0
- package/logger/index.d.ts +213 -0
- package/logger/index.mjs +313 -0
- package/middleware/index.cjs +177 -0
- package/middleware/index.d.ts +127 -0
- package/middleware/index.mjs +170 -0
- package/obj/index.cjs +305 -0
- package/obj/index.d.ts +160 -0
- package/obj/index.mjs +289 -0
- package/package.json +172 -20
- package/performance/index.cjs +231 -0
- package/performance/index.d.ts +162 -0
- package/performance/index.mjs +225 -0
- package/request/index.cjs +202 -0
- package/request/index.d.ts +265 -0
- package/request/index.mjs +194 -0
- package/response/index.cjs +234 -0
- package/response/index.d.ts +342 -0
- package/response/index.mjs +222 -0
- package/server/index.cjs +1631 -0
- package/server/index.d.ts +809 -0
- package/server/index.mjs +1622 -0
- package/stream/index.cjs +151 -0
- package/stream/index.d.ts +114 -0
- package/stream/index.mjs +144 -0
- package/string/index.cjs +109 -0
- package/string/index.d.ts +126 -0
- package/string/index.mjs +95 -0
- package/type/index.cjs +129 -0
- package/type/index.d.ts +131 -0
- package/type/index.mjs +119 -0
- package/types/index.cjs +34 -0
- package/types/index.d.ts +798 -0
- package/types/index.mjs +32 -0
- package/url/index.cjs +199 -0
- package/url/index.d.ts +166 -0
- package/url/index.mjs +187 -0
- package/validation/index.cjs +259 -0
- package/validation/index.d.ts +209 -0
- package/validation/index.mjs +231 -0
- package/build/index.cjs +0 -7694
- package/build/index.d.ts +0 -5792
- package/build/index.mjs +0 -7386
package/array/index.d.ts
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025 Catbee Technologies. https://catbee.in/license
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
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
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025 Catbee Technologies. https://catbee.in/license
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { getValueByPath } from '@catbee/utils/obj';
|
|
26
|
+
import { randomBytes } from 'crypto';
|
|
27
|
+
|
|
28
|
+
var __defProp = Object.defineProperty;
|
|
29
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
30
|
+
function chunk(array, size) {
|
|
31
|
+
if (!Array.isArray(array)) throw new TypeError("Expected an array");
|
|
32
|
+
if (array.length === 0) return [];
|
|
33
|
+
if (!Number.isInteger(size) || size <= 0) throw new Error("Chunk size must be a positive integer");
|
|
34
|
+
const result = [];
|
|
35
|
+
for (let i = 0; i < array.length; i += size) {
|
|
36
|
+
result.push(array.slice(i, i + size));
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
__name(chunk, "chunk");
|
|
41
|
+
function unique(array, keyFn) {
|
|
42
|
+
if (!Array.isArray(array) || array.length === 0) return [];
|
|
43
|
+
if (!keyFn) return Array.from(new Set(array));
|
|
44
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45
|
+
const result = [];
|
|
46
|
+
for (const item of array) {
|
|
47
|
+
const key = keyFn(item);
|
|
48
|
+
if (!seen.has(key)) {
|
|
49
|
+
seen.add(key);
|
|
50
|
+
result.push(item);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
__name(unique, "unique");
|
|
56
|
+
function flattenDeep(array) {
|
|
57
|
+
if (!Array.isArray(array)) return [];
|
|
58
|
+
const result = [];
|
|
59
|
+
const stack = [
|
|
60
|
+
...array
|
|
61
|
+
];
|
|
62
|
+
while (stack.length) {
|
|
63
|
+
const val = stack.pop();
|
|
64
|
+
if (Array.isArray(val)) {
|
|
65
|
+
stack.push(...val);
|
|
66
|
+
} else {
|
|
67
|
+
result.push(val);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return result.reverse();
|
|
71
|
+
}
|
|
72
|
+
__name(flattenDeep, "flattenDeep");
|
|
73
|
+
function random(array) {
|
|
74
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
75
|
+
return array[secureIndex(array.length)];
|
|
76
|
+
}
|
|
77
|
+
__name(random, "random");
|
|
78
|
+
function groupBy(array, keyOrFn) {
|
|
79
|
+
if (!Array.isArray(array) || array.length === 0) return {};
|
|
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
|
+
]));
|
|
96
|
+
}
|
|
97
|
+
__name(groupBy, "groupBy");
|
|
98
|
+
function shuffle(array) {
|
|
99
|
+
if (!Array.isArray(array)) throw new TypeError("Expected an array");
|
|
100
|
+
const copy = array.slice();
|
|
101
|
+
for (let i = copy.length - 1; i > 0; i--) {
|
|
102
|
+
const j = secureIndex(i + 1);
|
|
103
|
+
[copy[i], copy[j]] = [
|
|
104
|
+
copy[j],
|
|
105
|
+
copy[i]
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
return copy;
|
|
109
|
+
}
|
|
110
|
+
__name(shuffle, "shuffle");
|
|
111
|
+
function pluck(array, key) {
|
|
112
|
+
if (!Array.isArray(array)) return [];
|
|
113
|
+
return array.map((item) => item?.[key]);
|
|
114
|
+
}
|
|
115
|
+
__name(pluck, "pluck");
|
|
116
|
+
function difference(a, b) {
|
|
117
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return [];
|
|
118
|
+
const setB = new Set(b);
|
|
119
|
+
return a.filter((item) => !setB.has(item));
|
|
120
|
+
}
|
|
121
|
+
__name(difference, "difference");
|
|
122
|
+
function intersect(a, b) {
|
|
123
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return [];
|
|
124
|
+
const setB = new Set(b);
|
|
125
|
+
return a.filter((item) => setB.has(item));
|
|
126
|
+
}
|
|
127
|
+
__name(intersect, "intersect");
|
|
128
|
+
function mergeSort(array, key, direction = "asc", compareFn) {
|
|
129
|
+
if (!Array.isArray(array)) throw new TypeError("Expected array");
|
|
130
|
+
const arr = array.slice();
|
|
131
|
+
if (arr.length <= 1) return arr;
|
|
132
|
+
const keyFn = typeof key === "function" ? key : (item) => getValueByPath(item, key);
|
|
133
|
+
const collator = new Intl.Collator("en", {
|
|
134
|
+
numeric: true
|
|
135
|
+
});
|
|
136
|
+
const compare = compareFn ?? function(a, b) {
|
|
137
|
+
const aVal = keyFn(a);
|
|
138
|
+
const bVal = keyFn(b);
|
|
139
|
+
if (aVal === bVal) return 0;
|
|
140
|
+
if (aVal == null) return direction === "asc" ? 1 : -1;
|
|
141
|
+
if (bVal == null) return direction === "asc" ? -1 : 1;
|
|
142
|
+
return direction === "asc" ? collator.compare(String(aVal), String(bVal)) : collator.compare(String(bVal), String(aVal));
|
|
143
|
+
};
|
|
144
|
+
const merge = /* @__PURE__ */ __name((left, right) => {
|
|
145
|
+
const result = [];
|
|
146
|
+
let i = 0, j = 0;
|
|
147
|
+
while (i < left.length && j < right.length) {
|
|
148
|
+
result.push(compare(left[i], right[j]) <= 0 ? left[i++] : right[j++]);
|
|
149
|
+
}
|
|
150
|
+
while (i < left.length) result.push(left[i++]);
|
|
151
|
+
while (j < right.length) result.push(right[j++]);
|
|
152
|
+
return result;
|
|
153
|
+
}, "merge");
|
|
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));
|
|
160
|
+
return merge(left, right);
|
|
161
|
+
}, "sort");
|
|
162
|
+
return sort(arr);
|
|
163
|
+
}
|
|
164
|
+
__name(mergeSort, "mergeSort");
|
|
165
|
+
function zip(...arrays) {
|
|
166
|
+
if (arrays.length === 0) return [];
|
|
167
|
+
if (arrays.some((arr) => !Array.isArray(arr))) {
|
|
168
|
+
throw new TypeError("All arguments must be arrays");
|
|
169
|
+
}
|
|
170
|
+
const minLength = Math.min(...arrays.map((arr) => arr.length));
|
|
171
|
+
const result = [];
|
|
172
|
+
for (let i = 0; i < minLength; i++) {
|
|
173
|
+
result.push(arrays.map((arr) => arr[i]));
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
__name(zip, "zip");
|
|
178
|
+
function partition(array, predicate) {
|
|
179
|
+
const pass = [];
|
|
180
|
+
const fail = [];
|
|
181
|
+
if (!Array.isArray(array)) return [
|
|
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
|
|
192
|
+
];
|
|
193
|
+
}
|
|
194
|
+
__name(partition, "partition");
|
|
195
|
+
function range(start, end, step = 1) {
|
|
196
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || !Number.isFinite(step)) {
|
|
197
|
+
throw new TypeError("Arguments must be finite numbers");
|
|
198
|
+
}
|
|
199
|
+
if (step === 0) throw new Error("Step cannot be zero");
|
|
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);
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
__name(range, "range");
|
|
209
|
+
function take(array, n = 1) {
|
|
210
|
+
if (!Array.isArray(array) || n <= 0) return [];
|
|
211
|
+
return n >= array.length ? array.slice() : array.slice(0, n);
|
|
212
|
+
}
|
|
213
|
+
__name(take, "take");
|
|
214
|
+
function takeWhile(array, predicate) {
|
|
215
|
+
const result = [];
|
|
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);
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
__name(takeWhile, "takeWhile");
|
|
226
|
+
function compact(array) {
|
|
227
|
+
if (!Array.isArray(array)) return [];
|
|
228
|
+
const result = [];
|
|
229
|
+
for (const v of array) {
|
|
230
|
+
if (v) result.push(v);
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
__name(compact, "compact");
|
|
235
|
+
function countBy(array, keyFn) {
|
|
236
|
+
if (!Array.isArray(array)) return {};
|
|
237
|
+
const result = {};
|
|
238
|
+
for (const item of array) {
|
|
239
|
+
const key = String(keyFn(item));
|
|
240
|
+
result[key] = (result[key] ?? 0) + 1;
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
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
|
+
|
|
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 };
|