toolbox-x 2.2.4 → 2.3.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +23 -4
  2. package/dist/{guards-Dc9MB9on.mjs → basics-B7Sqf33u.mjs} +233 -233
  3. package/dist/{guards-BSwFQX1M.cjs → basics-Cif013VV.cjs} +233 -233
  4. package/dist/{colors.cjs → colors/index.cjs} +6 -6
  5. package/dist/{colors.d.mts → colors/index.d.cts} +2 -2
  6. package/dist/{colors.d.cts → colors/index.d.mts} +2 -2
  7. package/dist/{colors.mjs → colors/index.mjs} +6 -6
  8. package/dist/constants.cjs +13 -13
  9. package/dist/constants.mjs +3 -3
  10. package/dist/{converter.cjs → converter/index.cjs} +1 -1
  11. package/dist/{converter.d.cts → converter/index.d.cts} +2 -2
  12. package/dist/{converter.d.mts → converter/index.d.mts} +2 -2
  13. package/dist/{converter.mjs → converter/index.mjs} +1 -1
  14. package/dist/{date.cjs → date/index.cjs} +7 -7
  15. package/dist/{date.d.cts → date/index.d.cts} +1 -1
  16. package/dist/{date.d.mts → date/index.d.mts} +1 -1
  17. package/dist/{date.mjs → date/index.mjs} +7 -7
  18. package/dist/{dom.cjs → dom/index.cjs} +8 -8
  19. package/dist/{dom.d.cts → dom/index.d.cts} +3 -3
  20. package/dist/{dom.d.mts → dom/index.d.mts} +3 -3
  21. package/dist/{dom.mjs → dom/index.mjs} +5 -5
  22. package/dist/{guards.cjs → guards/index.cjs} +38 -38
  23. package/dist/{guards.d.mts → guards/index.d.cts} +4 -4
  24. package/dist/{guards.d.cts → guards/index.d.mts} +4 -4
  25. package/dist/{guards.mjs → guards/index.mjs} +6 -6
  26. package/dist/{guards-CqbVT4L5.cjs → guards-BD2Fkugj.cjs} +2 -2
  27. package/dist/{guards-DKGBsd6x.mjs → guards-DBunDnng.mjs} +2 -2
  28. package/dist/{hash.cjs → hash/index.cjs} +69 -66
  29. package/dist/{hash.d.cts → hash/index.d.cts} +77 -5
  30. package/dist/{hash.d.mts → hash/index.d.mts} +77 -5
  31. package/dist/{hash.mjs → hash/index.mjs} +5 -5
  32. package/dist/{http-status.cjs → http-status/index.cjs} +1 -1
  33. package/dist/{http-status.d.mts → http-status/index.d.cts} +2 -2
  34. package/dist/{http-status.d.cts → http-status/index.d.mts} +2 -2
  35. package/dist/{http-status.mjs → http-status/index.mjs} +1 -1
  36. package/dist/index.cjs +84 -84
  37. package/dist/index.mjs +5 -5
  38. package/dist/{parse-TuFyLeVH.mjs → parse-CILDG7TG.mjs} +3 -3
  39. package/dist/{parse-jh637S25.cjs → parse-CffWYCuy.cjs} +3 -3
  40. package/dist/{query-sWSi-d7u.cjs → query-Blm7AiEZ.cjs} +9 -9
  41. package/dist/{query-BomnyWh3.mjs → query-PGFEup3p.mjs} +2 -2
  42. package/dist/{stylog.cjs → stylog/index.cjs} +5 -5
  43. package/dist/{stylog.d.cts → stylog/index.d.cts} +2 -2
  44. package/dist/{stylog.d.mts → stylog/index.d.mts} +2 -2
  45. package/dist/{stylog.mjs → stylog/index.mjs} +5 -5
  46. package/dist/types/pluralizer.d.cts +25 -1
  47. package/dist/types/pluralizer.d.mts +25 -1
  48. package/dist/{utilities-BSv8VbnM.mjs → utilities-CmPwOkdy.mjs} +1 -1
  49. package/dist/{utilities-BVpk3LKy.cjs → utilities-_COSGq1U.cjs} +1 -1
  50. package/dist/{basics-20lm69yy.mjs → utils-BO5CcsjK.mjs} +631 -548
  51. package/dist/{basics-byj0VH1c.cjs → utils-DR9g0Sef.cjs} +580 -479
  52. package/dist/{verbalizer.cjs → verbalizer/index.cjs} +1 -1
  53. package/dist/{verbalizer.mjs → verbalizer/index.mjs} +1 -1
  54. package/package.json +22 -25
  55. package/dist/pluralizer-DXMuPUAK.d.mts +0 -42
  56. package/dist/pluralizer-DYsDqq9c.d.cts +0 -42
  57. package/dist/pluralizer.cjs +0 -678
  58. package/dist/pluralizer.d.cts +0 -152
  59. package/dist/pluralizer.d.mts +0 -152
  60. package/dist/pluralizer.mjs +0 -676
  61. /package/dist/{verbalizer.d.cts → verbalizer/index.d.cts} +0 -0
  62. /package/dist/{verbalizer.d.mts → verbalizer/index.d.mts} +0 -0
@@ -16,458 +16,215 @@
16
16
 
17
17
  const require_primitives = require('./primitives-CBGICrDR.cjs');
18
18
  const require_specials = require('./specials-DU8u108m.cjs');
19
- const require_utilities = require('./utilities-BVpk3LKy.cjs');
20
- const require_guards = require('./guards-CqbVT4L5.cjs');
19
+ const require_utilities = require('./utilities-_COSGq1U.cjs');
20
+ const require_guards = require('./guards-BD2Fkugj.cjs');
21
21
 
22
- //#region src/array/helpers.ts
23
- /**
24
- * Safely resolves value of nested key (dot-notation key like `"user.city"`).
25
- *
26
- * @param obj - The source object
27
- * @param path - The nested path string (e.g. `"user.city"`)
28
- * @returns The resolved value or `undefined`
29
- */
30
- function _resolveNestedKey(obj, path) {
31
- if (require_specials.isNotEmptyObject(obj)) return path?.split(".").reduce((acc, key) => {
32
- if (require_specials.isNotEmptyObject(acc)) return acc[key];
33
- }, obj);
34
- }
35
- /**
36
- * Retrieves a numeric value from a nested property (dot-notation key like 'user.income.tax').
37
- * Falls back to 0 if value is not a number or numeric string.
38
- *
39
- * @param obj - The source object to read from.
40
- * @param path - The dot-notation path string like 'user.income.tax'.
41
- * @returns The numeric value at that path, or 0 if not valid.
42
- */
43
- function _getNumericProp(obj, path) {
44
- return require_utilities.normalizeNumber(_resolveNestedKey(obj, path)) ?? 0;
45
- }
46
-
47
- //#endregion
48
- //#region src/array/sort.ts
49
- /**
50
- * Compare two strings using natural sorting (e.g., `"file2"` < `"file10"`).
51
- * - Optionally supports case-insensitive and locale-aware string chunk comparisons.
52
- *
53
- * @param a - The first string to compare.
54
- * @param b - The second string to compare.
55
- * @param options - Optional settings to configure comparison behavior.
56
- * @returns A negative number if `a` comes before `b`, a positive number if `a` comes after `b`, or 0 if equal.
57
- */
58
- function naturalSort(a, b, options) {
59
- const { caseInsensitive = true, localeAware = false } = options || {};
60
- /**
61
- * * Splits a string into an array of number and non-number chunks.
62
- * @param str - The string to split.
63
- * @returns An array of string and number parts.
64
- */
65
- const _createChunks = (str) => {
66
- const chunks = [];
67
- let current = "";
68
- let isNumeric = false;
69
- for (const char of str) {
70
- const charIsNum = !Number.isNaN(Number(char));
71
- if (current?.length === 0) {
72
- current = char;
73
- isNumeric = charIsNum;
74
- continue;
75
- }
76
- if (charIsNum === isNumeric) current += char;
77
- else {
78
- chunks?.push(isNumeric ? Number(current) : current);
79
- current = char;
80
- isNumeric = charIsNum;
81
- }
82
- }
83
- if (current?.length > 0) chunks?.push(isNumeric ? Number(current) : current);
84
- return chunks;
85
- };
86
- const aChunks = _createChunks(a);
87
- const bChunks = _createChunks(b);
88
- for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
89
- let aChunk = aChunks[i];
90
- let bChunk = bChunks[i];
91
- if (caseInsensitive && require_primitives.isString(aChunk) && require_primitives.isString(bChunk)) {
92
- aChunk = aChunk?.toLowerCase();
93
- bChunk = bChunk?.toLowerCase();
94
- }
95
- if (typeof aChunk !== typeof bChunk) return require_primitives.isString(aChunk) ? 1 : -1;
96
- if (aChunk !== bChunk) {
97
- if (require_primitives.isNumber(aChunk) && require_primitives.isNumber(bChunk)) return aChunk - bChunk;
98
- if (require_primitives.isString(aChunk) && require_primitives.isString(bChunk)) {
99
- if (localeAware) {
100
- const cmp = aChunk.localeCompare(bChunk, void 0, { sensitivity: caseInsensitive ? "accent" : "variant" });
101
- if (cmp !== 0) return cmp;
102
- }
103
- return aChunk < bChunk ? -1 : 1;
104
- }
105
- }
106
- }
107
- return aChunks?.length - bChunks?.length;
108
- }
22
+ //#region src/string/basics.ts
109
23
  /**
110
- * * Sorts an array of strings, numbers, booleans, or objects based on the provided options.
24
+ * * Utility to truncate a string to a specified length.
111
25
  *
112
- * @param array - The array to sort.
113
- * @param options - Sorting options.
114
- * @returns The sorted array.
26
+ * @param str The string to truncate.
27
+ * @param maxLength The maximum length of the truncated string.
28
+ * @returns Truncated string with ellipsis (`...`) (only if it has more length than `maxLength`).
115
29
  */
116
- function sortAnArray(array, options) {
117
- if (!require_specials.isValidArray(array)) return array;
118
- if (require_specials.isArrayOfType(array, require_primitives.isString)) return [...array].sort((a, b) => options?.sortOrder === "desc" ? naturalSort(b, a) : naturalSort(a, b));
119
- if (require_specials.isArrayOfType(array, require_primitives.isNumber)) return [...array].sort((a, b) => options?.sortOrder === "desc" ? b - a : a - b);
120
- if (require_specials.isArrayOfType(array, require_primitives.isBoolean)) return [...array].sort((a, b) => options?.sortOrder === "desc" ? Number(b) - Number(a) : Number(a) - Number(b));
121
- if (require_specials.isArrayOfType(array, require_specials.isObject) && options && "sortByField" in options) return [...array].sort((a, b) => {
122
- const _getKeyValue = (obj, path) => {
123
- return path.split(".").reduce((acc, key) => acc?.[key], obj);
124
- };
125
- const keyA = _getKeyValue(a, options?.sortByField);
126
- const keyB = _getKeyValue(b, options?.sortByField);
127
- if (keyA == null || keyB == null) return keyA == null ? 1 : -1;
128
- if (require_primitives.isString(keyA) && require_primitives.isString(keyB)) return options?.sortOrder === "desc" ? naturalSort(keyB, keyA) : naturalSort(keyA, keyB);
129
- if (require_primitives.isNumber(keyA) && require_primitives.isNumber(keyB)) return options?.sortOrder === "desc" ? keyB - keyA : keyA - keyB;
130
- if (require_primitives.isBoolean(keyA) && require_primitives.isBoolean(keyB)) return options?.sortOrder === "desc" ? Number(keyB) - Number(keyA) : Number(keyA) - Number(keyB);
131
- return 0;
132
- });
133
- return [...array];
30
+ function truncateString(str, maxLength) {
31
+ if (!require_primitives.isNonEmptyString(str)) return "";
32
+ const trimmedString = str.trim();
33
+ if (!trimmedString) return "";
34
+ if (trimmedString.length <= maxLength) return trimmedString;
35
+ return trimmedString.slice(0, maxLength).concat("...");
134
36
  }
135
-
136
- //#endregion
137
- //#region src/utils/index.ts
138
- /**
139
- * * Deeply compare two values (arrays, objects, or primitive values).
140
- *
141
- * @param a First value to compare.
142
- * @param b Second value to compare.
143
- * @returns Whether the values are deeply equal.
144
- */
145
- const isDeepEqual = (a, b) => {
146
- if (a === b) return true;
147
- if (typeof a !== typeof b) return false;
148
- if (a === null || b === null) return a === b;
149
- if (require_specials.isArray(a) && require_specials.isArray(b)) {
150
- if (a?.length !== b?.length) return false;
151
- return a?.every((element, index) => isDeepEqual(element, b?.[index]));
152
- }
153
- if (require_specials.isObject(a) && require_specials.isObject(b)) {
154
- const aKeys = Object.keys(a);
155
- const bKeys = Object.keys(b);
156
- if (aKeys?.length !== bKeys?.length) return false;
157
- return aKeys?.every((key) => isDeepEqual(a?.[key], b?.[key]));
158
- }
159
- return false;
160
- };
161
37
  /**
162
- * * Converts an array of primitive values or objects to a string using a separator or target key.
38
+ * * Generates a random alphanumeric (16 characters long, this length is customizable in the options) ID string composed of an optional `prefix`, `suffix`, a `timestamp`, `caseOption` and a customizable `separator`.
163
39
  *
164
- * @param array Array to convert.
165
- * @param options Options for separator or key extraction from objects.
166
- * @returns String representation of array values.
167
- */
168
- function convertArrayToString(array, options) {
169
- if (!require_specials.isValidArray(array)) return "";
170
- const { separator = ", " } = options ?? {};
171
- if (require_specials.isArrayOfType(array, require_primitives.isPrimitive)) return array?.join(separator);
172
- else if (require_specials.isArrayOfType(array, require_specials.isNotEmptyObject)) if (options && "target" in options) return array?.map((el) => _resolveNestedKey(el, options?.target))?.join(separator);
173
- else return "";
174
- return "";
175
- }
176
- /**
177
- * * A generic debounce function that delays the execution of a callback.
40
+ * @param options Configuration options for random ID generation.
41
+ * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
178
42
  *
179
- * @param callback - The function to debounce.
180
- * @param delay - The delay in milliseconds. Default is `300ms`.
181
- * @returns A debounced version of the callback function.
43
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/uuid uuid} for `uuid` generation
44
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/random-hex randomHex} for random hexadecimal string generation
182
45
  *
183
46
  * @example
184
- * const debouncedSearch = debounceAction((query: string) => {
185
- * console.log(`Searching for: ${query}`);
186
- * }, 300);
47
+ * // Generate an ID with all default options
48
+ * const id = generateRandomID();
49
+ * // Example output: "swo8ckxwsc13w7xw"
187
50
  *
188
- * debouncedSearch('laptop'); // Executes after 300ms of inactivity.
189
- */
190
- function debounceAction(callback, delay = 300) {
191
- let timeoutId;
192
- return (...args) => {
193
- clearTimeout(timeoutId);
194
- timeoutId = setTimeout(() => {
195
- callback(...args);
196
- }, delay);
197
- };
198
- }
199
- /**
200
- * * A generic throttle function that ensures a callback is executed at most once per specified interval.
51
+ * @example
52
+ * // Generate an ID with a custom prefix and separator
53
+ * const id = generateRandomID({ prefix: 'ID', separator: '-' });
54
+ * // Example output: "ID-eh1ymwfxzwas9jte"
201
55
  *
202
- * @param callback - The function to throttle.
203
- * @param delay - The delay in milliseconds. Default is `150ms`.
204
- * @returns A throttled version of the callback function.
56
+ * @example
57
+ * // Generate an ID with a timestamp
58
+ * const id = generateRandomID({ timeStamp: false });
59
+ * // Example output: "1764610287501pd3r4w85qwkuulgf"
205
60
  *
206
61
  * @example
207
- * const throttledResize = throttleAction(() => {
208
- * console.log('Resized');
209
- * }, 300);
62
+ * // Generate an ID with a custom length for the random string
63
+ * const id = generateRandomID({ length: 8 });
64
+ * // Example output: "i623uiev"
210
65
  *
211
- * window.addEventListener('resize', throttledResize);
212
- */
213
- function throttleAction(callback, delay = 150) {
214
- let lastCall = 0;
215
- return (...args) => {
216
- const now = Date.now();
217
- if (now - lastCall >= delay) {
218
- lastCall = now;
219
- callback(...args);
220
- }
221
- };
222
- }
223
- /**
224
- * * Retrieves the names of all instance methods defined directly on a class prototype.
66
+ * @example
67
+ * // Generate an ID with a custom suffix
68
+ * const id = generateRandomID({ suffix: 'END' });
69
+ * // Example output: "3csf27a4800rbli9END"
225
70
  *
226
- * @param cls - The class constructor (not an instance).
227
- * @returns A sorted array of instance method names.
228
- */
229
- function getInstanceMethodNames(cls) {
230
- const prototype = cls.prototype;
231
- return sortAnArray(Object.getOwnPropertyNames(prototype).filter((method) => {
232
- if (method === "constructor") return false;
233
- return require_specials.isMethodDescriptor(Object.getOwnPropertyDescriptor(prototype, method));
234
- }));
235
- }
236
- /**
237
- * * Retrieves the names of all static methods defined directly on a class constructor.
71
+ * @example
72
+ * // Generate an ID with a uppercase random string
73
+ * const id = generateRandomID({ caseOption: "upper" });
74
+ * // Example output: "H0VNU6O8XV1Y30HG"
238
75
  *
239
- * @param cls - The class constructor (not an instance).
240
- * @returns A sorted array of static method names.
76
+ * @example
77
+ * // Generate an ID with all options customized
78
+ * const id = generateRandomID({
79
+ * prefix: 'ID',
80
+ * suffix: 'END',
81
+ * timeStamp: true,
82
+ * length: 10,
83
+ * separator: '-',
84
+ * caseOption: "upper"
85
+ * });
86
+ * // Example output: "ID-1764610471474-4KSL51IB91-END"
241
87
  */
242
- function getStaticMethodNames(cls) {
243
- return sortAnArray(Object.getOwnPropertyNames(cls).filter((method) => {
244
- return method !== "prototype" && method !== "name" && method !== "length";
245
- }));
88
+ function generateRandomID(options) {
89
+ const { prefix = "", suffix = "", timeStamp = false, length = 16, separator = "", caseOption = null } = options || {};
90
+ const date = timeStamp ? Date.now() : "";
91
+ const randomString = Array.from({ length }, () => Math.random().toString(36).slice(2, 3)).join("");
92
+ const ID = [
93
+ prefix?.trim(),
94
+ date,
95
+ randomString,
96
+ suffix?.trim()
97
+ ].filter(Boolean).join(separator);
98
+ switch (caseOption) {
99
+ case "upper": return ID.toUpperCase();
100
+ case "lower": return ID.toLowerCase();
101
+ default: return ID;
102
+ }
246
103
  }
247
104
  /**
248
- * * Counts the number of instance methods defined directly on a class prototype.
105
+ * * Trims all whitespaces in a string or an array of strings.
249
106
  *
250
- * @param cls - The class constructor (not an instance).
251
- * @returns The number of instance methods defined on the class prototype.
107
+ * @param input String or array of strings.
108
+ * @returns Trimmed string or array of strings.
252
109
  */
253
- function countInstanceMethods(cls) {
254
- return getInstanceMethodNames(cls)?.length;
110
+ function trimString(input) {
111
+ if (!input) return "";
112
+ if (require_primitives.isNonEmptyString(input)) return input.trim().replace(/\s+/g, " ");
113
+ if (Array.isArray(input)) return input.map((str) => require_primitives.isNonEmptyString(str) ? str.trim().replace(/\s+/g, " ") : str);
114
+ throw new TypeError("Expected string or array of strings!", { cause: "Invalid Input Type" });
255
115
  }
116
+
117
+ //#endregion
118
+ //#region src/hash/utils.ts
256
119
  /**
257
- * * Counts the number of static methods defined directly on a class constructor.
120
+ * * Generates random bytes in the {@link Uint8Array} format.
258
121
  *
259
- * @param cls - The class constructor (not an instance).
260
- * @returns The number of static methods defined on the class constructor.
261
- */
262
- function countStaticMethods(cls) {
263
- return getStaticMethodNames(cls)?.length;
264
- }
265
- /**
266
- * * Retrieves the names of all instance getters defined directly on a class prototype.
122
+ * @param size - The length of the byte array to generate. Defaults to `8`.
123
+ * @returns A random array of bytes.
267
124
  *
268
- * @param cls - The class constructor (not an instance).
269
- * @returns A sorted array of instance getter names.
270
- */
271
- function getInstanceGetterNames(cls) {
272
- const descriptors = Object.getOwnPropertyDescriptors(cls.prototype);
273
- return sortAnArray(Object.entries(descriptors).filter(([key, desc]) => require_specials.isFunction(desc.get) && key !== "constructor").map(([key]) => key));
274
- }
275
- /**
276
- * * Retrieves the names of all static getters defined directly on a class constructor.
125
+ * @example
126
+ * ```typescript
127
+ * const bytes = randomBytes(16);
128
+ * // Returns something like: Uint8Array(16) [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 224, 166, 170, 224, 167, 131]
277
129
  *
278
- * @param cls - The class constructor (not an instance).
279
- * @returns A sorted array of static getter names.
280
- */
281
- function getStaticGetterNames(cls) {
282
- return sortAnArray(Object.entries(Object.getOwnPropertyDescriptors(cls)).filter(([key, desc]) => typeof desc.get === "function" && key !== "prototype").map(([key]) => key));
283
- }
284
- /**
285
- * * Gathers detailed information about the instance and static methods of a class.
130
+ * // Empty array
131
+ * const empty = randomBytes(0);
132
+ * // Returns: Uint8Array(0) []
286
133
  *
287
- * @param cls - The class constructor (not an instance).
288
- * @returns An object containing names and counts of instance and static methods.
289
- */
290
- function getClassDetails(cls) {
291
- const instanceNames = getInstanceMethodNames(cls);
292
- const staticNames = getStaticMethodNames(cls);
293
- const instanceGetters = getInstanceGetterNames(cls);
294
- const staticGetters = getStaticGetterNames(cls);
295
- return {
296
- instanceMethods: instanceNames,
297
- staticMethods: staticNames,
298
- instanceGetters,
299
- staticGetters,
300
- instanceCount: instanceNames?.length,
301
- staticCount: staticNames?.length,
302
- totalGetters: instanceGetters?.length + staticGetters?.length,
303
- totalMethods: instanceNames?.length + staticNames?.length
304
- };
305
- }
306
- /**
307
- * * Create a deterministic JSON string representation of any value.
308
- * - The output format matches standard JSON but with guaranteed sorted keys.
134
+ * // Zero or negative values are treated as 0
135
+ * const zero = randomBytes(-5);
136
+ * // Returns: Uint8Array(0) []
137
+ * ```
309
138
  *
310
139
  * @remarks
311
- * - This function guarantees **stable, repeatable output** by:
312
- * - Sorting all object keys alphabetically.
313
- * - Recursively stabilizing nested objects and arrays.
314
- * - Converting all `undefined` values into `null` so the output remains valid JSON.
315
- * - Converting date-like objects (`Date`, `Chronos`, `Moment.js`, `Day.js`, `Luxon`, `JS-Joda`, `Temporal`) **in the same way that {@link JSON.stringify} would serialize them**, ensuring predictable and JSON-compliant output.
316
- * - Falling back to native JSON serialization for primitives.
317
- *
318
- * - **Useful for:**
319
- * - Hash generation (e.g., signatures, cache keys)
320
- * - Deep equality checks
321
- * - Producing predictable output across environments
322
- *
323
- * @param obj - The value to stringify into a deterministic JSON string.
324
- * @returns A stable, deterministic string representation of the input.
140
+ * - It uses {@link crypto.getRandomValues} when available for secure randomness, and falls back to {@link Math.random} if not.
141
+ * - If {@link crypto.getRandomValues} is available (supported environments include browser and Node.js), it is used for cryptographically secure random number generation.
142
+ * - In environments where {@link crypto.getRandomValues} is not available, the function falls back to {@link Math.random}, which is **not** cryptographically secure.
143
+ * - {@link crypto.getRandomValues} fills the array with random values in the range [0, 255] (inclusive).
144
+ * - {@link Math.random} returns values in the range [0, 1) (exclusive of 1), so the values are scaled to [0, 255].
145
+ * - If `size` is 0 or negative, an empty `Uint8Array` is returned.
325
146
  */
326
- function stableStringify(obj) {
327
- const _replacer = (_, v) => v === void 0 ? null : v;
328
- if (require_specials.isNotEmptyObject(obj)) return "{" + Object.keys(obj).sort().map((k) => JSON.stringify(k, _replacer) + ":" + (require_guards.isDateLike(obj[k]) ? JSON.stringify(obj[k]) : stableStringify(obj[k]))).join(",") + "}";
329
- if (require_specials.isValidArray(obj)) return "[" + obj.map((v) => stableStringify(v)).join(",") + "]";
330
- return JSON.stringify(obj, _replacer);
147
+ function randomBytes(size = 8) {
148
+ if (size <= 0) return new Uint8Array(0);
149
+ return _fillWithRandomValues(new Uint8Array(size));
331
150
  }
332
151
  /**
333
- * * Remove trailing or leading garbage characters **after/before JSON object or array**.
334
- * @param str String to sanitize/strip.
335
- * @returns Sanitized/stripped JSON string.
336
- */
337
- function stripJsonEdgeGarbage(str) {
338
- if (!require_primitives.isNonEmptyString(str)) return "";
339
- const lastIdx = Math.max(str.lastIndexOf("}"), str.lastIndexOf("]"));
340
- const _idxOf = (sym) => str.indexOf(sym) !== -1 ? str.indexOf(sym) : Infinity;
341
- const firstIdx = Math.min(_idxOf("{"), _idxOf("["));
342
- if (lastIdx === -1 || firstIdx === Infinity) return str;
343
- return str.slice(firstIdx, lastIdx + 1);
344
- }
345
- /**
346
- * * Parses any valid JSON string, optionally converting stringified primitives inside (nested) arrays or objects.
152
+ * * Generates a random hexadecimal string of the specified length.
347
153
  *
348
- * @typeParam T - Expected return type (default is unknown).
349
- * @param value - The JSON string to parse.
350
- * @param parsePrimitives - Whether to convert stringified primitives (default: `true`).
351
- * @returns The parsed JSON value typed as `T`, or the original parsed value with optional primitive conversion.
352
- * - Returns `{}` if parsing fails, such as when the input is malformed or invalid JSON or passing single quoted string.
154
+ * @param length - Number of hex characters to generate.
155
+ * @param uppercase - Whether to return uppercase `A–F` characters. Defaults to `false` (lowercase).
353
156
  *
354
- * - *Unlike {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/object/parse-json-to-object parseJsonToObject}, which ensures the root value is an object,
355
- * this function returns any valid JSON structure such as arrays, strings, numbers, or objects.*
157
+ * @returns A randomly generated hexadecimal string.
356
158
  *
357
- * This is useful when you're not sure of the root structure of the JSON, or when you expect something other than an object.
159
+ * @remarks
160
+ * - This function generates a random hexadecimal string of the specified length.
161
+ * - It uses {@link crypto.getRandomValues} when available for secure randomness, and falls back to {@link Math.random} if not.
162
+ * - The output is a string of hex characters (`0–9`, `a–f` or `A–F`) with no prefixes or separators.
163
+ * - If `length` is `0` or negative, an empty string is returned.
358
164
  *
359
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/object/parse-json-to-object parseJsonToObject} for strict object-only parsing.
360
- */
361
- const parseJSON = (value, parsePrimitives = true) => {
362
- try {
363
- const parsed = JSON.parse(value);
364
- return parsePrimitives ? deepParsePrimitives(parsed) : parsed;
365
- } catch {
366
- return {};
367
- }
368
- };
369
- /**
370
- * * Recursively parses primitive values inside objects and arrays.
165
+ * @example
166
+ * // 16-character lowercase hex
167
+ * const id = randomHex(16);
371
168
  *
372
- * @typeParam T - Expected return type after parsing (default is unknown).
373
- * @param input - Any input value to parse recursively.
374
- * @returns Input with primitives (strings like "true", "123") converted, typed as `T`.
169
+ * @example
170
+ * // 8-character uppercase hex
171
+ * const token = randomHex(8, true);
375
172
  */
376
- function deepParsePrimitives(input) {
377
- if (Array.isArray(input)) return input?.map(deepParsePrimitives);
378
- if (require_specials.isObject(input)) {
379
- const result = {};
380
- for (const [key, value] of Object.entries(input)) result[key] = deepParsePrimitives(value);
381
- return result;
382
- }
383
- if (require_primitives.isString(input)) {
384
- if (/^(true|false)$/i.test(input)) return input?.toLowerCase() === "true";
385
- if (require_specials.isNumericString(input)) return Number(input);
386
- if (input === "null") return null;
387
- if (input === "undefined") return;
388
- return input;
389
- }
390
- return input;
173
+ function randomHex(length, uppercase = false) {
174
+ if (length <= 0) return "";
175
+ const expected = _bytesToRandomHex(new Uint8Array(Math.ceil(length / 2))).slice(0, length);
176
+ return uppercase ? expected.toUpperCase() : expected;
391
177
  }
392
178
  /**
393
- * * Defines a method on any prototype including built-in prototypes — in a safe, idempotent manner.
394
- * - The method is non-enumerable by default and will not overwrite an existing method unless explicitly allowed.
179
+ * * Generates a random numeric string of the specified length.
395
180
  *
396
- * @param proto The target prototype object (e.g., String.prototype).
397
- * @param name The method name to define on the prototype.
398
- * @param impl The function implementation for the method.
399
- * @param options Optional property-descriptor settings and overwrite rules.
181
+ * @param length - Length of the numeric string. Defaults to `6`.
182
+ * @returns A randomly generated numeric string.
400
183
  *
401
184
  * @example
402
- * // Safely augment prototype methods by extending the global interface:
403
- * declare global {
404
- * interface String {
405
- * toBang(): string;
406
- * }
407
- * }
408
- *
409
- * // Define a custom method on String.prototype
410
- * definePrototypeMethod(String.prototype, 'toBang', function (this: String) {
411
- * return this.toString().concat('!');
412
- * // or
413
- * // return this.concat('!');
414
- * });
415
- *
416
- * "Hi".toBang(); // "Hi!"
417
- *
418
- * // Attempting to redefine without overwrite option is ignored
419
- * definePrototypeMethod(String.prototype, 'toBang', () => 'x'); // ignored
420
- *
421
- * // Overwrite intentionally using the overwrite option
422
- * definePrototypeMethod(
423
- * String.prototype,
424
- * 'toBang',
425
- * function (this: String) { return this.concat('!!!'); },
426
- * { overwrite: true }
427
- * );
185
+ * ```typescript
186
+ * const otp = randomNumeric(6);
187
+ * // Returns something like: '123456'
188
+ * ```
428
189
  *
429
- * "Hi".toBang(); // "Hi!!!"
190
+ * @remarks
191
+ * - If `length` is `0` or negative, an empty string is returned.
430
192
  */
431
- function definePrototypeMethod(proto, name, impl, options) {
432
- if (Object.hasOwn(proto, name) && !options?.overwrite) return;
433
- Object.defineProperty(proto, name, {
434
- value: function(...args) {
435
- return impl.apply(this, args);
436
- },
437
- enumerable: options?.enumerable ?? false,
438
- configurable: options?.configurable ?? false,
439
- writable: options?.writable ?? true
440
- });
193
+ function randomNumeric(length = 6) {
194
+ return randomBytes(length).map((byte) => byte & 10).join("");
441
195
  }
442
-
443
- //#endregion
444
- //#region src/hash/utils.ts
445
196
  /**
446
- * * Generates a random hexadecimal string of the specified length.
197
+ * * Generates a random alphanumeric string (letters and numbers) of the specified length.
447
198
  *
448
- * @param length - Number of hex characters to generate.
449
- * @param uppercase - Whether to return uppercase `A–F` characters. Defaults to `false` (lowercase).
199
+ * @param length - The desired length of the random string. Defaults to `8`.
200
+ * @param uppercase - If `true`, the string will contain uppercase letters (A-Z). Defaults to `false` (lowercase).
450
201
  *
451
- * @returns A randomly generated hexadecimal string.
452
- *
453
- * @remarks
454
- * - This function generates a random hexadecimal string of the specified length.
455
- * - It uses {@link crypto.getRandomValues} when available for secure randomness, and falls back to {@link Math.random} if not.
456
- * - The output is a string of hex characters (`0–9`, `a–f` or `A–F`) with no prefixes or separators.
457
- * - If `length` is `0` or negative, an empty string is returned.
202
+ * @returns A random string composed of alphanumeric characters.
458
203
  *
459
204
  * @example
460
- * // 16-character lowercase hex
461
- * const id = randomHex(16);
205
+ * ```typescript
206
+ * // Generate a random 8-character alphanumeric string (default: lowercase)
207
+ * const randomStr = randomAlphaNumeric(8);
208
+ * // Example output: "a7b2f9d1"
462
209
  *
463
- * @example
464
- * // 8-character uppercase hex
465
- * const token = randomHex(8, true);
210
+ * // Generate a 12-character uppercase alphanumeric string
211
+ * const randomUpper = randomAlphaNumeric(12, true);
212
+ * // Example output: "X5K9P2M7H4L3"
213
+ *
214
+ * // Generate a 6-character string
215
+ * const shortStr = randomAlphaNumeric(6);
216
+ * ```
217
+ *
218
+ * @remarks
219
+ * - The function generates random bytes and converts them to base-36 (0-9, a-z) characters.
220
+ * - If `length` is `0` or negative, an empty string is returned.
466
221
  */
467
- function randomHex(length, uppercase = false) {
468
- if (length <= 0) return "";
469
- const expected = _bytesToRandomHex(new Uint8Array(Math.ceil(length / 2))).slice(0, length);
470
- return uppercase ? expected.toUpperCase() : expected;
222
+ function randomAlphaNumeric(length = 8, uppercase = false) {
223
+ const bytes = randomBytes(Math.ceil(length / 2));
224
+ let ran = "";
225
+ for (const byte of bytes) ran += byte.toString(36).padStart(2, "0");
226
+ const result = ran.slice(0, length);
227
+ return uppercase ? result.toUpperCase() : result;
471
228
  }
472
229
  /**
473
230
  * * Converts a UTF-8 string to a byte array (`Uint8Array`).
@@ -1644,109 +1401,435 @@ function isUUIDv5(value) {
1644
1401
  function isUUIDv6(value) {
1645
1402
  return _checkUUIDVersion(value, "6");
1646
1403
  }
1647
- /** Check if a value is UUID version 7 */
1648
- function isUUIDv7(value) {
1649
- return _checkUUIDVersion(value, "7");
1404
+ /** Check if a value is UUID version 7 */
1405
+ function isUUIDv7(value) {
1406
+ return _checkUUIDVersion(value, "7");
1407
+ }
1408
+ /** Check if a value is UUID version 8 */
1409
+ function isUUIDv8(value) {
1410
+ return _checkUUIDVersion(value, "8");
1411
+ }
1412
+
1413
+ //#endregion
1414
+ //#region src/array/helpers.ts
1415
+ /**
1416
+ * Safely resolves value of nested key (dot-notation key like `"user.city"`).
1417
+ *
1418
+ * @param obj - The source object
1419
+ * @param path - The nested path string (e.g. `"user.city"`)
1420
+ * @returns The resolved value or `undefined`
1421
+ */
1422
+ function _resolveNestedKey(obj, path) {
1423
+ if (require_specials.isNotEmptyObject(obj)) return path?.split(".").reduce((acc, key) => {
1424
+ if (require_specials.isNotEmptyObject(acc)) return acc[key];
1425
+ }, obj);
1426
+ }
1427
+ /**
1428
+ * Retrieves a numeric value from a nested property (dot-notation key like 'user.income.tax').
1429
+ * Falls back to 0 if value is not a number or numeric string.
1430
+ *
1431
+ * @param obj - The source object to read from.
1432
+ * @param path - The dot-notation path string like 'user.income.tax'.
1433
+ * @returns The numeric value at that path, or 0 if not valid.
1434
+ */
1435
+ function _getNumericProp(obj, path) {
1436
+ return require_utilities.normalizeNumber(_resolveNestedKey(obj, path)) ?? 0;
1437
+ }
1438
+
1439
+ //#endregion
1440
+ //#region src/array/sort.ts
1441
+ /**
1442
+ * Compare two strings using natural sorting (e.g., `"file2"` < `"file10"`).
1443
+ * - Optionally supports case-insensitive and locale-aware string chunk comparisons.
1444
+ *
1445
+ * @param a - The first string to compare.
1446
+ * @param b - The second string to compare.
1447
+ * @param options - Optional settings to configure comparison behavior.
1448
+ * @returns A negative number if `a` comes before `b`, a positive number if `a` comes after `b`, or 0 if equal.
1449
+ */
1450
+ function naturalSort(a, b, options) {
1451
+ const { caseInsensitive = true, localeAware = false } = options || {};
1452
+ /**
1453
+ * * Splits a string into an array of number and non-number chunks.
1454
+ * @param str - The string to split.
1455
+ * @returns An array of string and number parts.
1456
+ */
1457
+ const _createChunks = (str) => {
1458
+ const chunks = [];
1459
+ let current = "";
1460
+ let isNumeric = false;
1461
+ for (const char of str) {
1462
+ const charIsNum = !Number.isNaN(Number(char));
1463
+ if (current?.length === 0) {
1464
+ current = char;
1465
+ isNumeric = charIsNum;
1466
+ continue;
1467
+ }
1468
+ if (charIsNum === isNumeric) current += char;
1469
+ else {
1470
+ chunks?.push(isNumeric ? Number(current) : current);
1471
+ current = char;
1472
+ isNumeric = charIsNum;
1473
+ }
1474
+ }
1475
+ if (current?.length > 0) chunks?.push(isNumeric ? Number(current) : current);
1476
+ return chunks;
1477
+ };
1478
+ const aChunks = _createChunks(a);
1479
+ const bChunks = _createChunks(b);
1480
+ for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
1481
+ let aChunk = aChunks[i];
1482
+ let bChunk = bChunks[i];
1483
+ if (caseInsensitive && require_primitives.isString(aChunk) && require_primitives.isString(bChunk)) {
1484
+ aChunk = aChunk?.toLowerCase();
1485
+ bChunk = bChunk?.toLowerCase();
1486
+ }
1487
+ if (typeof aChunk !== typeof bChunk) return require_primitives.isString(aChunk) ? 1 : -1;
1488
+ if (aChunk !== bChunk) {
1489
+ if (require_primitives.isNumber(aChunk) && require_primitives.isNumber(bChunk)) return aChunk - bChunk;
1490
+ if (require_primitives.isString(aChunk) && require_primitives.isString(bChunk)) {
1491
+ if (localeAware) {
1492
+ const cmp = aChunk.localeCompare(bChunk, void 0, { sensitivity: caseInsensitive ? "accent" : "variant" });
1493
+ if (cmp !== 0) return cmp;
1494
+ }
1495
+ return aChunk < bChunk ? -1 : 1;
1496
+ }
1497
+ }
1498
+ }
1499
+ return aChunks?.length - bChunks?.length;
1500
+ }
1501
+ /**
1502
+ * * Sorts an array of strings, numbers, booleans, or objects based on the provided options.
1503
+ *
1504
+ * @param array - The array to sort.
1505
+ * @param options - Sorting options.
1506
+ * @returns The sorted array.
1507
+ */
1508
+ function sortAnArray(array, options) {
1509
+ if (!require_specials.isValidArray(array)) return array;
1510
+ if (require_specials.isArrayOfType(array, require_primitives.isString)) return [...array].sort((a, b) => options?.sortOrder === "desc" ? naturalSort(b, a) : naturalSort(a, b));
1511
+ if (require_specials.isArrayOfType(array, require_primitives.isNumber)) return [...array].sort((a, b) => options?.sortOrder === "desc" ? b - a : a - b);
1512
+ if (require_specials.isArrayOfType(array, require_primitives.isBoolean)) return [...array].sort((a, b) => options?.sortOrder === "desc" ? Number(b) - Number(a) : Number(a) - Number(b));
1513
+ if (require_specials.isArrayOfType(array, require_specials.isObject) && options && "sortByField" in options) return [...array].sort((a, b) => {
1514
+ const _getKeyValue = (obj, path) => {
1515
+ return path.split(".").reduce((acc, key) => acc?.[key], obj);
1516
+ };
1517
+ const keyA = _getKeyValue(a, options?.sortByField);
1518
+ const keyB = _getKeyValue(b, options?.sortByField);
1519
+ if (keyA == null || keyB == null) return keyA == null ? 1 : -1;
1520
+ if (require_primitives.isString(keyA) && require_primitives.isString(keyB)) return options?.sortOrder === "desc" ? naturalSort(keyB, keyA) : naturalSort(keyA, keyB);
1521
+ if (require_primitives.isNumber(keyA) && require_primitives.isNumber(keyB)) return options?.sortOrder === "desc" ? keyB - keyA : keyA - keyB;
1522
+ if (require_primitives.isBoolean(keyA) && require_primitives.isBoolean(keyB)) return options?.sortOrder === "desc" ? Number(keyB) - Number(keyA) : Number(keyA) - Number(keyB);
1523
+ return 0;
1524
+ });
1525
+ return [...array];
1526
+ }
1527
+
1528
+ //#endregion
1529
+ //#region src/utils/index.ts
1530
+ /**
1531
+ * * Deeply compare two values (arrays, objects, or primitive values).
1532
+ *
1533
+ * @param a First value to compare.
1534
+ * @param b Second value to compare.
1535
+ * @returns Whether the values are deeply equal.
1536
+ */
1537
+ const isDeepEqual = (a, b) => {
1538
+ if (a === b) return true;
1539
+ if (typeof a !== typeof b) return false;
1540
+ if (a === null || b === null) return a === b;
1541
+ if (require_specials.isArray(a) && require_specials.isArray(b)) {
1542
+ if (a?.length !== b?.length) return false;
1543
+ return a?.every((element, index) => isDeepEqual(element, b?.[index]));
1544
+ }
1545
+ if (require_specials.isObject(a) && require_specials.isObject(b)) {
1546
+ const aKeys = Object.keys(a);
1547
+ const bKeys = Object.keys(b);
1548
+ if (aKeys?.length !== bKeys?.length) return false;
1549
+ return aKeys?.every((key) => isDeepEqual(a?.[key], b?.[key]));
1550
+ }
1551
+ return false;
1552
+ };
1553
+ /**
1554
+ * * Converts an array of primitive values or objects to a string using a separator or target key.
1555
+ *
1556
+ * @param array Array to convert.
1557
+ * @param options Options for separator or key extraction from objects.
1558
+ * @returns String representation of array values.
1559
+ */
1560
+ function convertArrayToString(array, options) {
1561
+ if (!require_specials.isValidArray(array)) return "";
1562
+ const { separator = ", " } = options ?? {};
1563
+ if (require_specials.isArrayOfType(array, require_primitives.isPrimitive)) return array?.join(separator);
1564
+ else if (require_specials.isArrayOfType(array, require_specials.isNotEmptyObject)) if (options && "target" in options) return array?.map((el) => _resolveNestedKey(el, options?.target))?.join(separator);
1565
+ else return "";
1566
+ return "";
1567
+ }
1568
+ /**
1569
+ * * A generic debounce function that delays the execution of a callback.
1570
+ *
1571
+ * @param callback - The function to debounce.
1572
+ * @param delay - The delay in milliseconds. Default is `300ms`.
1573
+ * @returns A debounced version of the callback function.
1574
+ *
1575
+ * @example
1576
+ * const debouncedSearch = debounceAction((query: string) => {
1577
+ * console.log(`Searching for: ${query}`);
1578
+ * }, 300);
1579
+ *
1580
+ * debouncedSearch('laptop'); // Executes after 300ms of inactivity.
1581
+ */
1582
+ function debounceAction(callback, delay = 300) {
1583
+ let timeoutId;
1584
+ return (...args) => {
1585
+ clearTimeout(timeoutId);
1586
+ timeoutId = setTimeout(() => {
1587
+ callback(...args);
1588
+ }, delay);
1589
+ };
1590
+ }
1591
+ /**
1592
+ * * A generic throttle function that ensures a callback is executed at most once per specified interval.
1593
+ *
1594
+ * @param callback - The function to throttle.
1595
+ * @param delay - The delay in milliseconds. Default is `150ms`.
1596
+ * @returns A throttled version of the callback function.
1597
+ *
1598
+ * @example
1599
+ * const throttledResize = throttleAction(() => {
1600
+ * console.log('Resized');
1601
+ * }, 300);
1602
+ *
1603
+ * window.addEventListener('resize', throttledResize);
1604
+ */
1605
+ function throttleAction(callback, delay = 150) {
1606
+ let lastCall = 0;
1607
+ return (...args) => {
1608
+ const now = Date.now();
1609
+ if (now - lastCall >= delay) {
1610
+ lastCall = now;
1611
+ callback(...args);
1612
+ }
1613
+ };
1614
+ }
1615
+ /**
1616
+ * * Retrieves the names of all instance methods defined directly on a class prototype.
1617
+ *
1618
+ * @param cls - The class constructor (not an instance).
1619
+ * @returns A sorted array of instance method names.
1620
+ */
1621
+ function getInstanceMethodNames(cls) {
1622
+ const prototype = cls.prototype;
1623
+ return sortAnArray(Object.getOwnPropertyNames(prototype).filter((method) => {
1624
+ if (method === "constructor") return false;
1625
+ return require_specials.isMethodDescriptor(Object.getOwnPropertyDescriptor(prototype, method));
1626
+ }));
1627
+ }
1628
+ /**
1629
+ * * Retrieves the names of all static methods defined directly on a class constructor.
1630
+ *
1631
+ * @param cls - The class constructor (not an instance).
1632
+ * @returns A sorted array of static method names.
1633
+ */
1634
+ function getStaticMethodNames(cls) {
1635
+ return sortAnArray(Object.getOwnPropertyNames(cls).filter((method) => {
1636
+ return method !== "prototype" && method !== "name" && method !== "length";
1637
+ }));
1638
+ }
1639
+ /**
1640
+ * * Counts the number of instance methods defined directly on a class prototype.
1641
+ *
1642
+ * @param cls - The class constructor (not an instance).
1643
+ * @returns The number of instance methods defined on the class prototype.
1644
+ */
1645
+ function countInstanceMethods(cls) {
1646
+ return getInstanceMethodNames(cls)?.length;
1647
+ }
1648
+ /**
1649
+ * * Counts the number of static methods defined directly on a class constructor.
1650
+ *
1651
+ * @param cls - The class constructor (not an instance).
1652
+ * @returns The number of static methods defined on the class constructor.
1653
+ */
1654
+ function countStaticMethods(cls) {
1655
+ return getStaticMethodNames(cls)?.length;
1650
1656
  }
1651
- /** Check if a value is UUID version 8 */
1652
- function isUUIDv8(value) {
1653
- return _checkUUIDVersion(value, "8");
1657
+ /**
1658
+ * * Retrieves the names of all instance getters defined directly on a class prototype.
1659
+ *
1660
+ * @param cls - The class constructor (not an instance).
1661
+ * @returns A sorted array of instance getter names.
1662
+ */
1663
+ function getInstanceGetterNames(cls) {
1664
+ const descriptors = Object.getOwnPropertyDescriptors(cls.prototype);
1665
+ return sortAnArray(Object.entries(descriptors).filter(([key, desc]) => require_specials.isFunction(desc.get) && key !== "constructor").map(([key]) => key));
1654
1666
  }
1655
-
1656
- //#endregion
1657
- //#region src/string/basics.ts
1658
1667
  /**
1659
- * * Utility to truncate a string to a specified length.
1668
+ * * Retrieves the names of all static getters defined directly on a class constructor.
1660
1669
  *
1661
- * @param str The string to truncate.
1662
- * @param maxLength The maximum length of the truncated string.
1663
- * @returns Truncated string with ellipsis (`...`) (only if it has more length than `maxLength`).
1670
+ * @param cls - The class constructor (not an instance).
1671
+ * @returns A sorted array of static getter names.
1664
1672
  */
1665
- function truncateString(str, maxLength) {
1666
- if (!require_primitives.isNonEmptyString(str)) return "";
1667
- const trimmedString = str.trim();
1668
- if (!trimmedString) return "";
1669
- if (trimmedString.length <= maxLength) return trimmedString;
1670
- return trimmedString.slice(0, maxLength).concat("...");
1673
+ function getStaticGetterNames(cls) {
1674
+ return sortAnArray(Object.entries(Object.getOwnPropertyDescriptors(cls)).filter(([key, desc]) => typeof desc.get === "function" && key !== "prototype").map(([key]) => key));
1671
1675
  }
1672
1676
  /**
1673
- * * Generates a random alphanumeric (16 characters long, this length is customizable in the options) ID string composed of an optional `prefix`, `suffix`, a `timestamp`, `caseOption` and a customizable `separator`.
1677
+ * * Gathers detailed information about the instance and static methods of a class.
1674
1678
  *
1675
- * @param options Configuration options for random ID generation.
1676
- * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
1679
+ * @param cls - The class constructor (not an instance).
1680
+ * @returns An object containing names and counts of instance and static methods.
1681
+ */
1682
+ function getClassDetails(cls) {
1683
+ const instanceNames = getInstanceMethodNames(cls);
1684
+ const staticNames = getStaticMethodNames(cls);
1685
+ const instanceGetters = getInstanceGetterNames(cls);
1686
+ const staticGetters = getStaticGetterNames(cls);
1687
+ return {
1688
+ instanceMethods: instanceNames,
1689
+ staticMethods: staticNames,
1690
+ instanceGetters,
1691
+ staticGetters,
1692
+ instanceCount: instanceNames?.length,
1693
+ staticCount: staticNames?.length,
1694
+ totalGetters: instanceGetters?.length + staticGetters?.length,
1695
+ totalMethods: instanceNames?.length + staticNames?.length
1696
+ };
1697
+ }
1698
+ /**
1699
+ * * Create a deterministic JSON string representation of any value.
1700
+ * - The output format matches standard JSON but with guaranteed sorted keys.
1677
1701
  *
1678
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/uuid uuid} for `uuid` generation
1679
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/random-hex randomHex} for random hexadecimal string generation
1702
+ * @remarks
1703
+ * - This function guarantees **stable, repeatable output** by:
1704
+ * - Sorting all object keys alphabetically.
1705
+ * - Recursively stabilizing nested objects and arrays.
1706
+ * - Converting all `undefined` values into `null` so the output remains valid JSON.
1707
+ * - Converting date-like objects (`Date`, `Chronos`, `Moment.js`, `Day.js`, `Luxon`, `JS-Joda`, `Temporal`) **in the same way that {@link JSON.stringify} would serialize them**, ensuring predictable and JSON-compliant output.
1708
+ * - Falling back to native JSON serialization for primitives.
1680
1709
  *
1681
- * @example
1682
- * // Generate an ID with all default options
1683
- * const id = generateRandomID();
1684
- * // Example output: "swo8ckxwsc13w7xw"
1710
+ * - **Useful for:**
1711
+ * - Hash generation (e.g., signatures, cache keys)
1712
+ * - Deep equality checks
1713
+ * - Producing predictable output across environments
1685
1714
  *
1686
- * @example
1687
- * // Generate an ID with a custom prefix and separator
1688
- * const id = generateRandomID({ prefix: 'ID', separator: '-' });
1689
- * // Example output: "ID-eh1ymwfxzwas9jte"
1715
+ * @param obj - The value to stringify into a deterministic JSON string.
1716
+ * @returns A stable, deterministic string representation of the input.
1717
+ */
1718
+ function stableStringify(obj) {
1719
+ const _replacer = (_, v) => v === void 0 ? null : v;
1720
+ if (require_specials.isNotEmptyObject(obj)) return "{" + Object.keys(obj).sort().map((k) => JSON.stringify(k, _replacer) + ":" + (require_guards.isDateLike(obj[k]) ? JSON.stringify(obj[k]) : stableStringify(obj[k]))).join(",") + "}";
1721
+ if (require_specials.isValidArray(obj)) return "[" + obj.map((v) => stableStringify(v)).join(",") + "]";
1722
+ return JSON.stringify(obj, _replacer);
1723
+ }
1724
+ /**
1725
+ * * Remove trailing or leading garbage characters **after/before JSON object or array**.
1726
+ * @param str String to sanitize/strip.
1727
+ * @returns Sanitized/stripped JSON string.
1728
+ */
1729
+ function stripJsonEdgeGarbage(str) {
1730
+ if (!require_primitives.isNonEmptyString(str)) return "";
1731
+ const lastIdx = Math.max(str.lastIndexOf("}"), str.lastIndexOf("]"));
1732
+ const _idxOf = (sym) => str.indexOf(sym) !== -1 ? str.indexOf(sym) : Infinity;
1733
+ const firstIdx = Math.min(_idxOf("{"), _idxOf("["));
1734
+ if (lastIdx === -1 || firstIdx === Infinity) return str;
1735
+ return str.slice(firstIdx, lastIdx + 1);
1736
+ }
1737
+ /**
1738
+ * * Parses any valid JSON string, optionally converting stringified primitives inside (nested) arrays or objects.
1690
1739
  *
1691
- * @example
1692
- * // Generate an ID with a timestamp
1693
- * const id = generateRandomID({ timeStamp: false });
1694
- * // Example output: "1764610287501pd3r4w85qwkuulgf"
1740
+ * @typeParam T - Expected return type (default is unknown).
1741
+ * @param value - The JSON string to parse.
1742
+ * @param parsePrimitives - Whether to convert stringified primitives (default: `true`).
1743
+ * @returns The parsed JSON value typed as `T`, or the original parsed value with optional primitive conversion.
1744
+ * - Returns `{}` if parsing fails, such as when the input is malformed or invalid JSON or passing single quoted string.
1695
1745
  *
1696
- * @example
1697
- * // Generate an ID with a custom length for the random string
1698
- * const id = generateRandomID({ length: 8 });
1699
- * // Example output: "i623uiev"
1746
+ * - *Unlike {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/object/parse-json-to-object parseJsonToObject}, which ensures the root value is an object,
1747
+ * this function returns any valid JSON structure such as arrays, strings, numbers, or objects.*
1700
1748
  *
1701
- * @example
1702
- * // Generate an ID with a custom suffix
1703
- * const id = generateRandomID({ suffix: 'END' });
1704
- * // Example output: "3csf27a4800rbli9END"
1749
+ * This is useful when you're not sure of the root structure of the JSON, or when you expect something other than an object.
1705
1750
  *
1706
- * @example
1707
- * // Generate an ID with a uppercase random string
1708
- * const id = generateRandomID({ caseOption: "upper" });
1709
- * // Example output: "H0VNU6O8XV1Y30HG"
1751
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/object/parse-json-to-object parseJsonToObject} for strict object-only parsing.
1752
+ */
1753
+ const parseJSON = (value, parsePrimitives = true) => {
1754
+ try {
1755
+ const parsed = JSON.parse(value);
1756
+ return parsePrimitives ? deepParsePrimitives(parsed) : parsed;
1757
+ } catch {
1758
+ return {};
1759
+ }
1760
+ };
1761
+ /**
1762
+ * * Recursively parses primitive values inside objects and arrays.
1710
1763
  *
1711
- * @example
1712
- * // Generate an ID with all options customized
1713
- * const id = generateRandomID({
1714
- * prefix: 'ID',
1715
- * suffix: 'END',
1716
- * timeStamp: true,
1717
- * length: 10,
1718
- * separator: '-',
1719
- * caseOption: "upper"
1720
- * });
1721
- * // Example output: "ID-1764610471474-4KSL51IB91-END"
1764
+ * @typeParam T - Expected return type after parsing (default is unknown).
1765
+ * @param input - Any input value to parse recursively.
1766
+ * @returns Input with primitives (strings like "true", "123") converted, typed as `T`.
1722
1767
  */
1723
- function generateRandomID(options) {
1724
- const { prefix = "", suffix = "", timeStamp = false, length = 16, separator = "", caseOption = null } = options || {};
1725
- const date = timeStamp ? Date.now() : "";
1726
- const randomString = Array.from({ length }, () => Math.random().toString(36).slice(2, 3)).join("");
1727
- const ID = [
1728
- prefix?.trim(),
1729
- date,
1730
- randomString,
1731
- suffix?.trim()
1732
- ].filter(Boolean).join(separator);
1733
- switch (caseOption) {
1734
- case "upper": return ID.toUpperCase();
1735
- case "lower": return ID.toLowerCase();
1736
- default: return ID;
1768
+ function deepParsePrimitives(input) {
1769
+ if (Array.isArray(input)) return input?.map(deepParsePrimitives);
1770
+ if (require_specials.isObject(input)) {
1771
+ const result = {};
1772
+ for (const [key, value] of Object.entries(input)) result[key] = deepParsePrimitives(value);
1773
+ return result;
1774
+ }
1775
+ if (require_primitives.isString(input)) {
1776
+ if (/^(true|false)$/i.test(input)) return input?.toLowerCase() === "true";
1777
+ if (require_specials.isNumericString(input)) return Number(input);
1778
+ if (input === "null") return null;
1779
+ if (input === "undefined") return;
1780
+ return input;
1737
1781
  }
1782
+ return input;
1738
1783
  }
1739
1784
  /**
1740
- * * Trims all whitespaces in a string or an array of strings.
1785
+ * * Defines a method on any prototype — including built-in prototypes in a safe, idempotent manner.
1786
+ * - The method is non-enumerable by default and will not overwrite an existing method unless explicitly allowed.
1741
1787
  *
1742
- * @param input String or array of strings.
1743
- * @returns Trimmed string or array of strings.
1788
+ * @param proto The target prototype object (e.g., String.prototype).
1789
+ * @param name The method name to define on the prototype.
1790
+ * @param impl The function implementation for the method.
1791
+ * @param options Optional property-descriptor settings and overwrite rules.
1792
+ *
1793
+ * @example
1794
+ * // Safely augment prototype methods by extending the global interface:
1795
+ * declare global {
1796
+ * interface String {
1797
+ * toBang(): string;
1798
+ * }
1799
+ * }
1800
+ *
1801
+ * // Define a custom method on String.prototype
1802
+ * definePrototypeMethod(String.prototype, 'toBang', function (this: String) {
1803
+ * return this.toString().concat('!');
1804
+ * // or
1805
+ * // return this.concat('!');
1806
+ * });
1807
+ *
1808
+ * "Hi".toBang(); // "Hi!"
1809
+ *
1810
+ * // Attempting to redefine without overwrite option is ignored
1811
+ * definePrototypeMethod(String.prototype, 'toBang', () => 'x'); // ignored
1812
+ *
1813
+ * // Overwrite intentionally using the overwrite option
1814
+ * definePrototypeMethod(
1815
+ * String.prototype,
1816
+ * 'toBang',
1817
+ * function (this: String) { return this.concat('!!!'); },
1818
+ * { overwrite: true }
1819
+ * );
1820
+ *
1821
+ * "Hi".toBang(); // "Hi!!!"
1744
1822
  */
1745
- function trimString(input) {
1746
- if (!input) return "";
1747
- if (require_primitives.isNonEmptyString(input)) return input.trim().replace(/\s+/g, " ");
1748
- if (Array.isArray(input)) return input.map((str) => require_primitives.isNonEmptyString(str) ? str.trim().replace(/\s+/g, " ") : str);
1749
- throw new TypeError("Expected string or array of strings!", { cause: "Invalid Input Type" });
1823
+ function definePrototypeMethod(proto, name, impl, options) {
1824
+ if (Object.hasOwn(proto, name) && !options?.overwrite) return;
1825
+ Object.defineProperty(proto, name, {
1826
+ value: function(...args) {
1827
+ return impl.apply(this, args);
1828
+ },
1829
+ enumerable: options?.enumerable ?? false,
1830
+ configurable: options?.configurable ?? false,
1831
+ writable: options?.writable ?? true
1832
+ });
1750
1833
  }
1751
1834
 
1752
1835
  //#endregion
@@ -1978,12 +2061,30 @@ Object.defineProperty(exports, 'parseJSON', {
1978
2061
  return parseJSON;
1979
2062
  }
1980
2063
  });
2064
+ Object.defineProperty(exports, 'randomAlphaNumeric', {
2065
+ enumerable: true,
2066
+ get: function () {
2067
+ return randomAlphaNumeric;
2068
+ }
2069
+ });
2070
+ Object.defineProperty(exports, 'randomBytes', {
2071
+ enumerable: true,
2072
+ get: function () {
2073
+ return randomBytes;
2074
+ }
2075
+ });
1981
2076
  Object.defineProperty(exports, 'randomHex', {
1982
2077
  enumerable: true,
1983
2078
  get: function () {
1984
2079
  return randomHex;
1985
2080
  }
1986
2081
  });
2082
+ Object.defineProperty(exports, 'randomNumeric', {
2083
+ enumerable: true,
2084
+ get: function () {
2085
+ return randomNumeric;
2086
+ }
2087
+ });
1987
2088
  Object.defineProperty(exports, 'sha1', {
1988
2089
  enumerable: true,
1989
2090
  get: function () {