toolbox-x 1.2.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/{Color-Dsut0Bex.d.cts → Color-B8MR8Vp0.d.cts} +1 -1
  2. package/dist/{Color-DCfoQk_-.d.mts → Color-D2MfZx7L.d.mts} +1 -1
  3. package/dist/{Stylog-DXZtHAbp.d.mts → Stylog-CSbLtqrZ.d.mts} +5 -5
  4. package/dist/{Stylog-TyLCTRtT.d.cts → Stylog-DF0CWtZb.d.cts} +5 -5
  5. package/dist/{area-CvSC96va.d.mts → area-C4tDXnGC.d.mts} +3 -3
  6. package/dist/{area-CcRQ6TfR.d.cts → area-CMJZ0gVm.d.cts} +3 -3
  7. package/dist/{array-B6jWzJ4F.d.mts → array-26Vs2HCs.d.mts} +1 -1
  8. package/dist/{array-CqDu610k.d.cts → array-DJAq9Qj8.d.cts} +1 -1
  9. package/dist/{basics-K8BDSYD6.cjs → basics-CJmdhXoo.cjs} +567 -14
  10. package/dist/{basics-1_M7UvCn.mjs → basics-CebgkY-n.mjs} +449 -16
  11. package/dist/{basics-KobRNhV-.d.cts → basics-Cis9Ej6c.d.mts} +5 -5
  12. package/dist/{basics-V5M2oltn.d.mts → basics-D4yU0NQ_.d.cts} +5 -5
  13. package/dist/{case-uKFzt5TY.cjs → case-Bd7QLHYw.cjs} +3 -3
  14. package/dist/{case-KdrBKjjK.d.mts → case-ChRzRBnY.d.mts} +12 -12
  15. package/dist/{case-BQwn5N-k.mjs → case-DBC4Rj0h.mjs} +3 -3
  16. package/dist/{case--Vjea9DS.d.cts → case-DkYSKSeV.d.cts} +12 -12
  17. package/dist/change-case.cjs +1 -1
  18. package/dist/change-case.d.cts +1 -1
  19. package/dist/change-case.d.mts +1 -1
  20. package/dist/change-case.mjs +1 -1
  21. package/dist/colors.d.cts +2 -2
  22. package/dist/colors.d.mts +2 -2
  23. package/dist/constants.d.cts +1 -1
  24. package/dist/constants.d.mts +1 -1
  25. package/dist/converter.cjs +2 -2
  26. package/dist/converter.d.cts +2 -2
  27. package/dist/converter.d.mts +2 -2
  28. package/dist/converter.mjs +2 -2
  29. package/dist/date.cjs +10 -10
  30. package/dist/date.d.cts +4 -4
  31. package/dist/date.d.mts +4 -4
  32. package/dist/date.mjs +10 -10
  33. package/dist/dom.cjs +5 -6
  34. package/dist/dom.d.cts +3 -3
  35. package/dist/dom.d.mts +3 -3
  36. package/dist/dom.mjs +4 -5
  37. package/dist/{form-DoQGMTOc.d.mts → form-Cp1OyCRI.d.cts} +2 -2
  38. package/dist/{form-mP-nl8EC.d.cts → form-DPdS2AhM.d.mts} +2 -2
  39. package/dist/guards-B2s2wlVN.mjs +425 -0
  40. package/dist/{guards-C0smSAKC.mjs → guards-BK1QuvFZ.mjs} +2 -2
  41. package/dist/{guards-ClGDJrQp.cjs → guards-Bsh6Bfdq.cjs} +2 -2
  42. package/dist/{guards-0VjySrPM.cjs → guards-DMJcjPDt.cjs} +279 -3
  43. package/dist/guards.cjs +9 -8
  44. package/dist/guards.d.cts +6 -5
  45. package/dist/guards.d.mts +6 -5
  46. package/dist/guards.mjs +5 -5
  47. package/dist/{hash-BcoFHSu1.d.cts → hash-DfhOK0Fi.d.mts} +1 -1
  48. package/dist/{hash-GYRx2ee_.d.mts → hash-IdZN0mIe.d.cts} +1 -1
  49. package/dist/hash.cjs +8 -8
  50. package/dist/hash.d.cts +8 -8
  51. package/dist/hash.d.mts +8 -8
  52. package/dist/hash.mjs +4 -5
  53. package/dist/{http-status-xrlR-LlB.d.mts → http-status-B-yBZr-J.d.mts} +1 -1
  54. package/dist/{http-status-C0DOpCDf.d.cts → http-status-Dq_hoSG6.d.cts} +1 -1
  55. package/dist/http-status.cjs +4 -4
  56. package/dist/http-status.d.cts +6 -6
  57. package/dist/http-status.d.mts +6 -6
  58. package/dist/http-status.mjs +4 -4
  59. package/dist/index-C5FoCCbF.d.cts +292 -0
  60. package/dist/index-CIJWxnDS.d.mts +292 -0
  61. package/dist/index.cjs +67 -248
  62. package/dist/index.d.cts +25 -280
  63. package/dist/index.d.mts +25 -280
  64. package/dist/index.mjs +11 -194
  65. package/dist/{object-ChFVh95z.d.cts → object-X5fSMx-I.d.cts} +13 -1
  66. package/dist/{object-ChFVh95z.d.mts → object-X5fSMx-I.d.mts} +13 -1
  67. package/dist/{objectify-DEnFpPt1.mjs → objectify-CQa8gQib.mjs} +3 -4
  68. package/dist/{objectify-DewBSJP_.cjs → objectify-xQvZS3UI.cjs} +5 -6
  69. package/dist/paginator.d.cts +1 -1
  70. package/dist/paginator.d.mts +1 -1
  71. package/dist/{parse-DovagZFA.cjs → parse-DT7jbWx7.cjs} +3 -3
  72. package/dist/{parse-BhZ6-tKg.mjs → parse-erxBG2hd.mjs} +3 -3
  73. package/dist/{pluralizer-CdG-VJ6t.d.cts → pluralizer-B8vuljyy.d.cts} +1 -1
  74. package/dist/{pluralizer-D2Lh8CdU.d.mts → pluralizer-DOdDskzF.d.mts} +1 -1
  75. package/dist/pluralizer.cjs +6 -6
  76. package/dist/pluralizer.d.cts +6 -6
  77. package/dist/pluralizer.d.mts +6 -6
  78. package/dist/pluralizer.mjs +6 -6
  79. package/dist/{specials-Cye93-uo.mjs → specials-Hq5Ncd6y.mjs} +2 -2
  80. package/dist/{specials-BM6cx43o.cjs → specials-dkYP1Nh2.cjs} +2 -2
  81. package/dist/{string-CkwTVFeL.d.mts → string-C51m7T6d.d.mts} +4 -2
  82. package/dist/{string-Dq2b8rcN.d.cts → string-CO7HP50i.d.cts} +4 -2
  83. package/dist/stylog.cjs +5 -5
  84. package/dist/stylog.d.cts +2 -2
  85. package/dist/stylog.d.mts +2 -2
  86. package/dist/stylog.mjs +5 -5
  87. package/dist/types/array.d.cts +1 -1
  88. package/dist/types/array.d.mts +1 -1
  89. package/dist/types/colors.d.cts +1 -1
  90. package/dist/types/colors.d.mts +1 -1
  91. package/dist/types/converter.d.cts +1 -1
  92. package/dist/types/converter.d.mts +1 -1
  93. package/dist/types/date.d.cts +1 -1
  94. package/dist/types/date.d.mts +1 -1
  95. package/dist/types/form.d.cts +1 -1
  96. package/dist/types/form.d.mts +1 -1
  97. package/dist/types/hash.d.cts +1 -1
  98. package/dist/types/hash.d.mts +1 -1
  99. package/dist/types/http-status.d.cts +1 -1
  100. package/dist/types/http-status.d.mts +1 -1
  101. package/dist/types/index.d.cts +2 -2
  102. package/dist/types/index.d.mts +2 -2
  103. package/dist/types/number.d.cts +1 -1
  104. package/dist/types/number.d.mts +1 -1
  105. package/dist/types/object.d.cts +2 -2
  106. package/dist/types/object.d.mts +2 -2
  107. package/dist/types/pluralizer.d.cts +1 -1
  108. package/dist/types/pluralizer.d.mts +1 -1
  109. package/dist/types/string.d.cts +2 -2
  110. package/dist/types/string.d.mts +2 -2
  111. package/dist/types/stylog.d.cts +1 -1
  112. package/dist/types/stylog.d.mts +1 -1
  113. package/dist/types/utils.d.cts +1 -1
  114. package/dist/types/utils.d.mts +1 -1
  115. package/dist/{utilities-CzyXCRHM.cjs → utilities-CWV1GPGY.cjs} +1 -1
  116. package/dist/{utilities-B9axOvOX.mjs → utilities-DPscNbS1.mjs} +1 -1
  117. package/dist/{uuid-DgTBxcVu.d.cts → uuid-BUI3Jt8n.d.cts} +3 -3
  118. package/dist/{uuid-Yc3Uu8qr.d.mts → uuid-mEiy14sf.d.mts} +3 -3
  119. package/dist/verbalizer.cjs +3 -3
  120. package/dist/verbalizer.d.cts +3 -3
  121. package/dist/verbalizer.d.mts +3 -3
  122. package/dist/verbalizer.mjs +3 -3
  123. package/package.json +7 -6
  124. package/dist/guards-DeO4ukiK.mjs +0 -221
  125. package/dist/utils-BxguWSoa.cjs +0 -568
  126. package/dist/utils-DXovsTKs.mjs +0 -449
@@ -15,8 +15,432 @@
15
15
  */
16
16
 
17
17
  const require_primitives = require('./primitives-CBGICrDR.cjs');
18
- const require_specials = require('./specials-BM6cx43o.cjs');
18
+ const require_specials = require('./specials-dkYP1Nh2.cjs');
19
+ const require_utilities = require('./utilities-CWV1GPGY.cjs');
20
+ const require_guards = require('./guards-Bsh6Bfdq.cjs');
19
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
+ }
109
+ /**
110
+ * * Sorts an array of strings, numbers, booleans, or objects based on the provided options.
111
+ *
112
+ * @param array - The array to sort.
113
+ * @param options - Sorting options.
114
+ * @returns The sorted array.
115
+ */
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];
134
+ }
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
+ /**
162
+ * * Converts an array of primitive values or objects to a string using a separator or target key.
163
+ *
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.
178
+ *
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.
182
+ *
183
+ * @example
184
+ * const debouncedSearch = debounceAction((query: string) => {
185
+ * console.log(`Searching for: ${query}`);
186
+ * }, 300);
187
+ *
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.
201
+ *
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.
205
+ *
206
+ * @example
207
+ * const throttledResize = throttleAction(() => {
208
+ * console.log('Resized');
209
+ * }, 300);
210
+ *
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.
225
+ *
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.
238
+ *
239
+ * @param cls - The class constructor (not an instance).
240
+ * @returns A sorted array of static method names.
241
+ */
242
+ function getStaticMethodNames(cls) {
243
+ return sortAnArray(Object.getOwnPropertyNames(cls).filter((method) => {
244
+ return method !== "prototype" && method !== "name" && method !== "length";
245
+ }));
246
+ }
247
+ /**
248
+ * * Counts the number of instance methods defined directly on a class prototype.
249
+ *
250
+ * @param cls - The class constructor (not an instance).
251
+ * @returns The number of instance methods defined on the class prototype.
252
+ */
253
+ function countInstanceMethods(cls) {
254
+ return getInstanceMethodNames(cls)?.length;
255
+ }
256
+ /**
257
+ * * Counts the number of static methods defined directly on a class constructor.
258
+ *
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.
267
+ *
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.
277
+ *
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.
286
+ *
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.
309
+ *
310
+ * @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.
325
+ */
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);
331
+ }
332
+ /**
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.
347
+ *
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.
353
+ *
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.*
356
+ *
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.
358
+ *
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.
371
+ *
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`.
375
+ */
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;
391
+ }
392
+ /**
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.
395
+ *
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.
400
+ *
401
+ * @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
+ * );
428
+ *
429
+ * "Hi".toBang(); // "Hi!!!"
430
+ */
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
+ });
441
+ }
442
+
443
+ //#endregion
20
444
  //#region src/hash/utils.ts
21
445
  /**
22
446
  * * Generates a random hexadecimal string of the specified length.
@@ -805,13 +1229,22 @@ function _randomNode48() {
805
1229
  return (parseInt(node.slice(0, 2).join(""), 16) | 1).toString(16).padStart(2, "0") + node.slice(2).join("");
806
1230
  }
807
1231
  /**
808
- * Generates random hex string of given byte length using crypto API if available, otherwise falls back to Math.random.
1232
+ * Fills the given {@link Uint8Array} with random values using crypto API if available, otherwise falls back to {@link Math.random}.
809
1233
  * @param bytes Instance of {@link Uint8Array} to fill with random values.
810
- * @returns Hex string representation of the random bytes.
1234
+ * @returns Random bytes. It also mutates the {@link bytes} argument.
811
1235
  */
812
- function _bytesToRandomHex(bytes) {
813
- if (crypto?.getRandomValues) crypto.getRandomValues(bytes);
1236
+ function _fillWithRandomValues(bytes) {
1237
+ if (!require_primitives.isUndefined(crypto) && crypto?.getRandomValues) crypto.getRandomValues(bytes);
814
1238
  else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
1239
+ return bytes;
1240
+ }
1241
+ /**
1242
+ * Generates random hex string of given byte length using crypto API if available, otherwise falls back to {@link Math.random}.
1243
+ * @param bytes Instance of {@link Uint8Array} to fill with random values.
1244
+ * @returns Hex string representation of the random bytes. It also mutates the {@link bytes} argument.
1245
+ */
1246
+ function _bytesToRandomHex(bytes) {
1247
+ _fillWithRandomValues(bytes);
815
1248
  let hex = "";
816
1249
  for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, "0");
817
1250
  return hex;
@@ -1031,9 +1464,9 @@ function sha1(msg) {
1031
1464
  * // Returns: '7037e204b825b83553ba336a6ec35b796d505599286ae864729ed6cb33ae9fe1'
1032
1465
  * ```
1033
1466
  *
1034
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/encoding#sha256bytes sha256Bytes} for hashing raw bytes
1035
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/encoding#utf8tobytes utf8ToBytes} for converting string to bytes
1036
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/encoding#bytestohex bytesToHex} for converting bytes to a hexadecimal string
1467
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/encoding#sha256bytes sha256Bytes} for hashing raw bytes
1468
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/encoding#utf8tobytes utf8ToBytes} for converting string to bytes
1469
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/encoding#bytestohex bytesToHex} for converting bytes to a hexadecimal string
1037
1470
  */
1038
1471
  function sha256(msg) {
1039
1472
  if (!require_primitives.isString(msg)) throw new TypeError("Input must be of type string!");
@@ -1087,7 +1520,7 @@ function sha256(msg) {
1087
1520
  * - `v7`: Millisecond precision; extremely high throughput may still cause rare collisions.
1088
1521
  * - `v8`: Uses a simple timestamp + randomness layout; custom layouts are not supported here.
1089
1522
  *
1090
- * - Use {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/string/generateRandomID generateRandomID} for customized id generation or {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for hex-only random string with custom length.
1523
+ * - Use {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/string/generate-random-id generateRandomID} for customized id generation or {@link https://toolbox-x.nazmul-nhb.dev/docs/utils/hash/random-hex randomHex} for hex-only random string with custom length.
1091
1524
  */
1092
1525
  function uuid(options) {
1093
1526
  const { version = "v4", uppercase = false } = options || {};
@@ -1242,8 +1675,8 @@ function truncateString(str, maxLength) {
1242
1675
  * @param options Configuration options for random ID generation.
1243
1676
  * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
1244
1677
  *
1245
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
1246
- * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
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
1247
1680
  *
1248
1681
  * @example
1249
1682
  * // Generate an ID with all default options
@@ -1292,10 +1725,10 @@ function generateRandomID(options) {
1292
1725
  const date = timeStamp ? Date.now() : "";
1293
1726
  const randomString = Array.from({ length }, () => Math.random().toString(36).slice(2, 3)).join("");
1294
1727
  const ID = [
1295
- prefix && prefix.trim(),
1728
+ prefix?.trim(),
1296
1729
  date,
1297
1730
  randomString,
1298
- suffix && suffix.trim()
1731
+ suffix?.trim()
1299
1732
  ].filter(Boolean).join(separator);
1300
1733
  switch (caseOption) {
1301
1734
  case "upper": return ID.toUpperCase();
@@ -1304,7 +1737,7 @@ function generateRandomID(options) {
1304
1737
  }
1305
1738
  }
1306
1739
  /**
1307
- * * Trims all the words in a string or an array of strings.
1740
+ * * Trims all whitespaces in a string or an array of strings.
1308
1741
  *
1309
1742
  * @param input String or array of strings.
1310
1743
  * @returns Trimmed string or array of strings.
@@ -1323,12 +1756,24 @@ Object.defineProperty(exports, '_constantTimeEquals', {
1323
1756
  return _constantTimeEquals;
1324
1757
  }
1325
1758
  });
1759
+ Object.defineProperty(exports, '_getNumericProp', {
1760
+ enumerable: true,
1761
+ get: function () {
1762
+ return _getNumericProp;
1763
+ }
1764
+ });
1326
1765
  Object.defineProperty(exports, '_padStartWith0', {
1327
1766
  enumerable: true,
1328
1767
  get: function () {
1329
1768
  return _padStartWith0;
1330
1769
  }
1331
1770
  });
1771
+ Object.defineProperty(exports, '_resolveNestedKey', {
1772
+ enumerable: true,
1773
+ get: function () {
1774
+ return _resolveNestedKey;
1775
+ }
1776
+ });
1332
1777
  Object.defineProperty(exports, '_splitByCharLength', {
1333
1778
  enumerable: true,
1334
1779
  get: function () {
@@ -1365,18 +1810,84 @@ Object.defineProperty(exports, 'concatBytes', {
1365
1810
  return concatBytes;
1366
1811
  }
1367
1812
  });
1813
+ Object.defineProperty(exports, 'convertArrayToString', {
1814
+ enumerable: true,
1815
+ get: function () {
1816
+ return convertArrayToString;
1817
+ }
1818
+ });
1819
+ Object.defineProperty(exports, 'countInstanceMethods', {
1820
+ enumerable: true,
1821
+ get: function () {
1822
+ return countInstanceMethods;
1823
+ }
1824
+ });
1825
+ Object.defineProperty(exports, 'countStaticMethods', {
1826
+ enumerable: true,
1827
+ get: function () {
1828
+ return countStaticMethods;
1829
+ }
1830
+ });
1831
+ Object.defineProperty(exports, 'debounceAction', {
1832
+ enumerable: true,
1833
+ get: function () {
1834
+ return debounceAction;
1835
+ }
1836
+ });
1368
1837
  Object.defineProperty(exports, 'decodeUUID', {
1369
1838
  enumerable: true,
1370
1839
  get: function () {
1371
1840
  return decodeUUID;
1372
1841
  }
1373
1842
  });
1843
+ Object.defineProperty(exports, 'deepParsePrimitives', {
1844
+ enumerable: true,
1845
+ get: function () {
1846
+ return deepParsePrimitives;
1847
+ }
1848
+ });
1849
+ Object.defineProperty(exports, 'definePrototypeMethod', {
1850
+ enumerable: true,
1851
+ get: function () {
1852
+ return definePrototypeMethod;
1853
+ }
1854
+ });
1374
1855
  Object.defineProperty(exports, 'generateRandomID', {
1375
1856
  enumerable: true,
1376
1857
  get: function () {
1377
1858
  return generateRandomID;
1378
1859
  }
1379
1860
  });
1861
+ Object.defineProperty(exports, 'getClassDetails', {
1862
+ enumerable: true,
1863
+ get: function () {
1864
+ return getClassDetails;
1865
+ }
1866
+ });
1867
+ Object.defineProperty(exports, 'getInstanceGetterNames', {
1868
+ enumerable: true,
1869
+ get: function () {
1870
+ return getInstanceGetterNames;
1871
+ }
1872
+ });
1873
+ Object.defineProperty(exports, 'getInstanceMethodNames', {
1874
+ enumerable: true,
1875
+ get: function () {
1876
+ return getInstanceMethodNames;
1877
+ }
1878
+ });
1879
+ Object.defineProperty(exports, 'getStaticGetterNames', {
1880
+ enumerable: true,
1881
+ get: function () {
1882
+ return getStaticGetterNames;
1883
+ }
1884
+ });
1885
+ Object.defineProperty(exports, 'getStaticMethodNames', {
1886
+ enumerable: true,
1887
+ get: function () {
1888
+ return getStaticMethodNames;
1889
+ }
1890
+ });
1380
1891
  Object.defineProperty(exports, 'hexToBytes', {
1381
1892
  enumerable: true,
1382
1893
  get: function () {
@@ -1395,6 +1906,12 @@ Object.defineProperty(exports, 'intTo4BytesBE', {
1395
1906
  return intTo4BytesBE;
1396
1907
  }
1397
1908
  });
1909
+ Object.defineProperty(exports, 'isDeepEqual', {
1910
+ enumerable: true,
1911
+ get: function () {
1912
+ return isDeepEqual;
1913
+ }
1914
+ });
1398
1915
  Object.defineProperty(exports, 'isUUIDv1', {
1399
1916
  enumerable: true,
1400
1917
  get: function () {
@@ -1449,6 +1966,18 @@ Object.defineProperty(exports, 'md5', {
1449
1966
  return md5;
1450
1967
  }
1451
1968
  });
1969
+ Object.defineProperty(exports, 'naturalSort', {
1970
+ enumerable: true,
1971
+ get: function () {
1972
+ return naturalSort;
1973
+ }
1974
+ });
1975
+ Object.defineProperty(exports, 'parseJSON', {
1976
+ enumerable: true,
1977
+ get: function () {
1978
+ return parseJSON;
1979
+ }
1980
+ });
1452
1981
  Object.defineProperty(exports, 'randomHex', {
1453
1982
  enumerable: true,
1454
1983
  get: function () {
@@ -1473,6 +2002,30 @@ Object.defineProperty(exports, 'sha256Bytes', {
1473
2002
  return sha256Bytes;
1474
2003
  }
1475
2004
  });
2005
+ Object.defineProperty(exports, 'sortAnArray', {
2006
+ enumerable: true,
2007
+ get: function () {
2008
+ return sortAnArray;
2009
+ }
2010
+ });
2011
+ Object.defineProperty(exports, 'stableStringify', {
2012
+ enumerable: true,
2013
+ get: function () {
2014
+ return stableStringify;
2015
+ }
2016
+ });
2017
+ Object.defineProperty(exports, 'stripJsonEdgeGarbage', {
2018
+ enumerable: true,
2019
+ get: function () {
2020
+ return stripJsonEdgeGarbage;
2021
+ }
2022
+ });
2023
+ Object.defineProperty(exports, 'throttleAction', {
2024
+ enumerable: true,
2025
+ get: function () {
2026
+ return throttleAction;
2027
+ }
2028
+ });
1476
2029
  Object.defineProperty(exports, 'trimString', {
1477
2030
  enumerable: true,
1478
2031
  get: function () {