@zairakai/js-utils 1.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 (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/dist/arrays.cjs +210 -0
  4. package/dist/arrays.d.cts +119 -0
  5. package/dist/arrays.d.ts +119 -0
  6. package/dist/arrays.js +32 -0
  7. package/dist/chunk-27YHP2CK.js +407 -0
  8. package/dist/chunk-3WNRYKPG.js +37 -0
  9. package/dist/chunk-42CHLXT7.js +214 -0
  10. package/dist/chunk-6F4PWJZI.js +0 -0
  11. package/dist/chunk-7SXRFZBB.js +173 -0
  12. package/dist/chunk-F6RSTW65.js +156 -0
  13. package/dist/chunk-G7ZJ23DW.js +253 -0
  14. package/dist/chunk-IPP7PA6H.js +136 -0
  15. package/dist/chunk-LDSWHSRX.js +96 -0
  16. package/dist/chunk-TY75OOIQ.js +700 -0
  17. package/dist/chunk-W6JEMFAF.js +54 -0
  18. package/dist/chunk-XEJLBAXE.js +164 -0
  19. package/dist/chunk-Z7G3SIQH.js +270 -0
  20. package/dist/chunk-ZJPKS2MQ.js +101 -0
  21. package/dist/collections.cjs +797 -0
  22. package/dist/collections.d.cts +353 -0
  23. package/dist/collections.d.ts +353 -0
  24. package/dist/collections.js +17 -0
  25. package/dist/datetime.cjs +80 -0
  26. package/dist/datetime.d.cts +75 -0
  27. package/dist/datetime.d.ts +75 -0
  28. package/dist/datetime.js +24 -0
  29. package/dist/equals.cjs +121 -0
  30. package/dist/equals.d.cts +24 -0
  31. package/dist/equals.d.ts +24 -0
  32. package/dist/equals.js +8 -0
  33. package/dist/formatters.cjs +201 -0
  34. package/dist/formatters.d.cts +180 -0
  35. package/dist/formatters.d.ts +180 -0
  36. package/dist/formatters.js +48 -0
  37. package/dist/index.cjs +2906 -0
  38. package/dist/index.d.cts +120 -0
  39. package/dist/index.d.ts +120 -0
  40. package/dist/index.js +348 -0
  41. package/dist/number.cjs +279 -0
  42. package/dist/number.d.cts +177 -0
  43. package/dist/number.d.ts +177 -0
  44. package/dist/number.js +10 -0
  45. package/dist/obj.cjs +427 -0
  46. package/dist/obj.d.cts +177 -0
  47. package/dist/obj.d.ts +177 -0
  48. package/dist/obj.js +12 -0
  49. package/dist/php-arrays.cjs +954 -0
  50. package/dist/php-arrays.d.cts +256 -0
  51. package/dist/php-arrays.d.ts +256 -0
  52. package/dist/php-arrays.js +70 -0
  53. package/dist/runtime.cjs +134 -0
  54. package/dist/runtime.d.cts +90 -0
  55. package/dist/runtime.d.ts +90 -0
  56. package/dist/runtime.js +24 -0
  57. package/dist/schemas.cjs +86 -0
  58. package/dist/schemas.d.cts +108 -0
  59. package/dist/schemas.d.ts +108 -0
  60. package/dist/schemas.js +22 -0
  61. package/dist/str.cjs +499 -0
  62. package/dist/str.d.cts +282 -0
  63. package/dist/str.d.ts +282 -0
  64. package/dist/str.js +11 -0
  65. package/dist/types.cjs +18 -0
  66. package/dist/types.d.cts +13 -0
  67. package/dist/types.d.ts +13 -0
  68. package/dist/types.js +1 -0
  69. package/dist/validator.cjs +251 -0
  70. package/dist/validator.d.cts +99 -0
  71. package/dist/validator.d.ts +99 -0
  72. package/dist/validator.js +11 -0
  73. package/dist/validators.cjs +217 -0
  74. package/dist/validators.d.cts +216 -0
  75. package/dist/validators.d.ts +216 -0
  76. package/dist/validators.js +64 -0
  77. package/package.json +180 -0
  78. package/src/arrays.ts +316 -0
  79. package/src/collections.ts +866 -0
  80. package/src/datetime.ts +103 -0
  81. package/src/equals.ts +134 -0
  82. package/src/formatters.ts +342 -0
  83. package/src/index.ts +36 -0
  84. package/src/number.ts +281 -0
  85. package/src/obj.ts +303 -0
  86. package/src/php-arrays.ts +445 -0
  87. package/src/pipe.ts +29 -0
  88. package/src/runtime.ts +194 -0
  89. package/src/schemas.ts +136 -0
  90. package/src/str.ts +438 -0
  91. package/src/types.ts +13 -0
  92. package/src/validator.ts +157 -0
  93. package/src/validators.ts +359 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,2906 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ ApiResponseSchema: () => ApiResponseSchema,
34
+ DateSchema: () => DateSchema,
35
+ EmailSchema: () => EmailSchema,
36
+ EnhancedArray: () => EnhancedArray,
37
+ EnhancedMap: () => EnhancedMap,
38
+ NumberHelper: () => NumberHelper,
39
+ Numberable: () => Numberable,
40
+ Obj: () => Obj,
41
+ Objectable: () => Objectable,
42
+ PaginatedResponseSchema: () => PaginatedResponseSchema,
43
+ PaginationSchema: () => PaginationSchema,
44
+ PhoneSchema: () => PhoneSchema,
45
+ Str: () => Str,
46
+ Stringable: () => Stringable,
47
+ UrlSchema: () => UrlSchema,
48
+ ValidationInstance: () => ValidationInstance,
49
+ Validator: () => Validator,
50
+ arrayAdd: () => arrayAdd,
51
+ arrayCollapse: () => arrayCollapse,
52
+ arrayDivide: () => arrayDivide,
53
+ arrayDot: () => arrayDot,
54
+ arrayExcept: () => arrayExcept,
55
+ arrayFirst: () => arrayFirst,
56
+ arrayFlatten: () => arrayFlatten,
57
+ arrayGet: () => arrayGet,
58
+ arrayGroupBy: () => arrayGroupBy,
59
+ arrayHas: () => arrayHas,
60
+ arrayOnly: () => arrayOnly,
61
+ arrayPluck: () => arrayPluck,
62
+ arrayUnique: () => arrayUnique,
63
+ arrayWhere: () => arrayWhere,
64
+ array_chunk: () => array_chunk,
65
+ array_column: () => array_column,
66
+ array_count_values: () => array_count_values,
67
+ array_diff: () => array_diff,
68
+ array_filter: () => array_filter,
69
+ array_flip: () => array_flip,
70
+ array_intersect: () => array_intersect,
71
+ array_key_exists: () => array_key_exists,
72
+ array_keys: () => array_keys,
73
+ array_map: () => array_map,
74
+ array_merge: () => array_merge,
75
+ array_pop: () => array_pop,
76
+ array_product: () => array_product,
77
+ array_push: () => array_push,
78
+ array_rand: () => array_rand,
79
+ array_reduce: () => array_reduce,
80
+ array_reverse: () => array_reverse,
81
+ array_search: () => array_search,
82
+ array_shift: () => array_shift,
83
+ array_slice: () => array_slice,
84
+ array_splice: () => array_splice,
85
+ array_sum: () => array_sum,
86
+ array_unique: () => array_unique,
87
+ array_unshift: () => array_unshift,
88
+ blank: () => blank,
89
+ camelCase: () => camelCase,
90
+ capitalize: () => capitalize,
91
+ collect: () => collect,
92
+ collectMap: () => collectMap,
93
+ data_get: () => data_get,
94
+ data_set: () => data_set,
95
+ dayjs: () => dayjs,
96
+ diff: () => diff,
97
+ filled: () => filled,
98
+ fromNow: () => fromNow,
99
+ isArray: () => isArray,
100
+ isBase64: () => isBase64,
101
+ isBetweenDates: () => isBetweenDates,
102
+ isBlank: () => isBlank,
103
+ isBoolean: () => isBoolean,
104
+ isDate: () => isDate,
105
+ isEmail: () => isEmail,
106
+ isEmpty: () => isEmpty,
107
+ isEqual: () => isEqual,
108
+ isEven: () => isEven,
109
+ isFalse: () => isFalse,
110
+ isFloat: () => isFloat,
111
+ isFunction: () => isFunction,
112
+ isFuture: () => isFuture,
113
+ isInteger: () => isInteger,
114
+ isIp: () => isIp,
115
+ isJson: () => isJson,
116
+ isMacAddress: () => isMacAddress,
117
+ isNotEmpty: () => isNotEmpty,
118
+ isNull: () => isNull,
119
+ isNumber: () => isNumber,
120
+ isNumeric: () => isNumeric,
121
+ isObject: () => isObject,
122
+ isOdd: () => isOdd,
123
+ isPast: () => isPast,
124
+ isPresent: () => isPresent,
125
+ isRecord: () => isRecord,
126
+ isSet: () => isSet,
127
+ isString: () => isString,
128
+ isToday: () => isToday,
129
+ isTrue: () => isTrue,
130
+ isUndefined: () => isUndefined,
131
+ isUrl: () => isUrl,
132
+ isUuid: () => isUuid,
133
+ kebabCase: () => kebabCase,
134
+ mapToObject: () => mapToObject,
135
+ normalizeString: () => normalizeString,
136
+ now: () => now,
137
+ num: () => num,
138
+ numberFormat: () => numberFormat,
139
+ obj: () => obj,
140
+ objectToMap: () => objectToMap,
141
+ optional: () => optional,
142
+ php_array: () => php_array,
143
+ pipe: () => pipe,
144
+ range: () => range,
145
+ retry: () => retry,
146
+ rsort: () => rsort,
147
+ safeValidateSchema: () => safeValidateSchema,
148
+ shuffle: () => shuffle,
149
+ slugify: () => slugify,
150
+ snakeCase: () => snakeCase,
151
+ sort: () => sort,
152
+ str: () => str,
153
+ strContainsAll: () => strContainsAll,
154
+ strContainsAny: () => strContainsAny,
155
+ strFinish: () => strFinish,
156
+ strLimit: () => strLimit,
157
+ strMask: () => strMask,
158
+ strPadBoth: () => strPadBoth,
159
+ strPadLeft: () => strPadLeft,
160
+ strPadRight: () => strPadRight,
161
+ strRemove: () => strRemove,
162
+ strReverse: () => strReverse,
163
+ strStart: () => strStart,
164
+ strWordCount: () => strWordCount,
165
+ strWords: () => strWords,
166
+ studlyCase: () => studlyCase,
167
+ tap: () => tap,
168
+ throw_if: () => throw_if,
169
+ throw_unless: () => throw_unless,
170
+ titleCase: () => titleCase,
171
+ today: () => today,
172
+ tomorrow: () => tomorrow,
173
+ uasort: () => uasort,
174
+ uksort: () => uksort,
175
+ usort: () => usort,
176
+ validateSchema: () => validateSchema,
177
+ validator: () => validator,
178
+ value: () => value,
179
+ when: () => when,
180
+ yesterday: () => yesterday
181
+ });
182
+ module.exports = __toCommonJS(src_exports);
183
+
184
+ // src/validators.ts
185
+ var isTrue = (value2) => true === value2;
186
+ var isFalse = (value2) => false === value2;
187
+ var isNull = (value2) => null === value2;
188
+ var isUndefined = (value2) => void 0 === value2;
189
+ var isSet = (value2) => void 0 !== value2 && null !== value2;
190
+ var isArray = (value2) => Array.isArray(value2);
191
+ var isObject = (value2) => "object" === typeof value2 && null !== value2 && !Array.isArray(value2);
192
+ var isString = (value2) => "string" === typeof value2;
193
+ var isNumber = (value2) => "number" === typeof value2 && !isNaN(value2);
194
+ var isInteger = (value2) => Number.isInteger(value2);
195
+ var isFloat = (value2) => "number" === typeof value2 && !isNaN(value2) && !Number.isInteger(value2);
196
+ var isBoolean = (value2) => "boolean" === typeof value2;
197
+ var isFunction = (value2) => "function" === typeof value2;
198
+ var isDate = (value2) => value2 instanceof Date && !isNaN(value2.getTime());
199
+ var isNumeric = (value2) => {
200
+ if ("number" === typeof value2) {
201
+ return !isNaN(value2) && isFinite(value2);
202
+ }
203
+ if ("string" === typeof value2) {
204
+ const num2 = Number(value2.trim());
205
+ return "" !== value2.trim() && !isNaN(num2) && isFinite(num2);
206
+ }
207
+ return false;
208
+ };
209
+ var isEmail = (value2) => {
210
+ if ("string" !== typeof value2) {
211
+ return false;
212
+ }
213
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
214
+ return emailRegex.test(value2);
215
+ };
216
+ var isUrl = (value2) => {
217
+ if ("string" !== typeof value2) {
218
+ return false;
219
+ }
220
+ try {
221
+ new URL(value2);
222
+ return true;
223
+ } catch {
224
+ return false;
225
+ }
226
+ };
227
+ var isEmpty = (value2) => {
228
+ if (isNull(value2) || isUndefined(value2)) {
229
+ return true;
230
+ }
231
+ if (isString(value2)) {
232
+ return 0 === value2.trim().length;
233
+ }
234
+ if (isArray(value2)) {
235
+ return 0 === value2.length;
236
+ }
237
+ if (isObject(value2)) {
238
+ return 0 === Object.keys(value2).length;
239
+ }
240
+ if (isNumber(value2)) {
241
+ return 0 === value2;
242
+ }
243
+ if (isBoolean(value2)) {
244
+ return isFalse(value2);
245
+ }
246
+ return false;
247
+ };
248
+ var isNotEmpty = (value2) => !isEmpty(value2);
249
+ var isBlank = (value2) => {
250
+ if (value2 == null) {
251
+ return true;
252
+ }
253
+ if ("string" === typeof value2) {
254
+ return "" === value2.trim();
255
+ }
256
+ return isEmpty(value2);
257
+ };
258
+ var isPresent = (value2) => !isBlank(value2);
259
+ var filled = (value2) => isPresent(value2);
260
+ var blank = (value2) => isBlank(value2);
261
+ var isEven = (value2) => {
262
+ return isNumber(value2) && 0 === value2 % 2;
263
+ };
264
+ var isOdd = (value2) => {
265
+ return isNumber(value2) && 0 !== value2 % 2;
266
+ };
267
+ var isJson = (value2) => {
268
+ if ("string" !== typeof value2) {
269
+ return false;
270
+ }
271
+ try {
272
+ JSON.parse(value2);
273
+ return true;
274
+ } catch {
275
+ return false;
276
+ }
277
+ };
278
+ var isBase64 = (value2) => {
279
+ if ("string" !== typeof value2) {
280
+ return false;
281
+ }
282
+ const base64Pattern = /^[A-Za-z0-9+/]*={0,2}$/;
283
+ if (0 !== value2.length % 4) {
284
+ return false;
285
+ }
286
+ return base64Pattern.test(value2);
287
+ };
288
+ var isMacAddress = (value2) => {
289
+ if ("string" !== typeof value2) {
290
+ return false;
291
+ }
292
+ const macPattern = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
293
+ return macPattern.test(value2);
294
+ };
295
+ var isUuid = (value2) => {
296
+ if ("string" !== typeof value2) {
297
+ return false;
298
+ }
299
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value2);
300
+ };
301
+ var isIp = (value2) => {
302
+ if ("string" !== typeof value2) {
303
+ return false;
304
+ }
305
+ const ipv4 = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
306
+ if (ipv4.test(value2)) {
307
+ return value2.split(".").every((part) => {
308
+ const n = Number(part);
309
+ return n >= 0 && n <= 255 && String(n) === part;
310
+ });
311
+ }
312
+ const ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|(([0-9a-fA-F]{1,4}:){0,7}:)|(:[0-9a-fA-F]{1,4}){1,7}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|::1)$/;
313
+ return ipv6.test(value2);
314
+ };
315
+
316
+ // src/formatters.ts
317
+ var capitalize = (value2) => {
318
+ if (value2 == null) {
319
+ return "";
320
+ }
321
+ const stringValue = String(value2);
322
+ return stringValue.charAt(0).toUpperCase() + stringValue.slice(1).toLowerCase();
323
+ };
324
+ var slugify = (text) => {
325
+ if (!text) {
326
+ return "";
327
+ }
328
+ return text.toString().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/\s+/g, "-").replace(/[^\w-]+/g, "").replace(/--+/g, "-");
329
+ };
330
+ var strLimit = (value2, size) => {
331
+ if (!value2) {
332
+ return "";
333
+ }
334
+ const stringValue = String(value2);
335
+ return stringValue.length <= size ? stringValue : `${stringValue.slice(0, size)}\u2026`;
336
+ };
337
+ var normalizeString = (value2) => {
338
+ if (!value2) {
339
+ return value2;
340
+ }
341
+ return value2.trim().toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
342
+ };
343
+ var strContainsAll = (haystack, needles) => {
344
+ if (!haystack || !Array.isArray(needles)) {
345
+ return false;
346
+ }
347
+ return needles.every((needle) => haystack.includes(needle));
348
+ };
349
+ var strContainsAny = (haystack, needles) => {
350
+ if (!haystack || !Array.isArray(needles)) {
351
+ return false;
352
+ }
353
+ return needles.some((needle) => haystack.includes(needle));
354
+ };
355
+ var strFinish = (value2, cap) => {
356
+ if (!value2) {
357
+ return cap;
358
+ }
359
+ if (!cap) {
360
+ return value2;
361
+ }
362
+ return value2.endsWith(cap) ? value2 : value2 + cap;
363
+ };
364
+ var strStart = (value2, prefix) => {
365
+ if (!value2) {
366
+ return prefix;
367
+ }
368
+ if (!prefix) {
369
+ return value2;
370
+ }
371
+ return value2.startsWith(prefix) ? value2 : prefix + value2;
372
+ };
373
+ var strPadBoth = (str2, length, pad = " ") => {
374
+ if (str2.length >= length) {
375
+ return str2;
376
+ }
377
+ const totalPad = length - str2.length;
378
+ const leftPad = Math.floor(totalPad / 2);
379
+ const rightPad = totalPad - leftPad;
380
+ return pad.repeat(leftPad) + str2 + pad.repeat(rightPad);
381
+ };
382
+ var strPadLeft = (str2, length, pad = " ") => {
383
+ return str2.padStart(length, pad);
384
+ };
385
+ var strPadRight = (str2, length, pad = " ") => {
386
+ return str2.padEnd(length, pad);
387
+ };
388
+ var strReverse = (value2) => {
389
+ return value2.split("").reverse().join("");
390
+ };
391
+ var strRemove = (search, subject, caseSensitive = true) => {
392
+ if (!search || !subject) {
393
+ return subject;
394
+ }
395
+ const flags = caseSensitive ? "g" : "gi";
396
+ return subject.replace(new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags), "");
397
+ };
398
+ var strMask = (str2, character, index, length) => {
399
+ if (!str2) {
400
+ return str2;
401
+ }
402
+ const start = Math.max(0, index);
403
+ const end = length !== void 0 ? start + length : str2.length;
404
+ return str2.substring(0, start) + character.repeat(end - start) + str2.substring(end);
405
+ };
406
+ var strWordCount = (str2, characters) => {
407
+ if (!str2) {
408
+ return 0;
409
+ }
410
+ const pattern = characters ? new RegExp(`[${characters}\\s]+`) : /\s+/;
411
+ return str2.trim().split(pattern).filter((word) => 0 < word.length).length;
412
+ };
413
+ var strWords = (value2, words = 100, end = "...") => {
414
+ if (!value2) {
415
+ return "";
416
+ }
417
+ const wordArray = value2.trim().split(/\s+/);
418
+ if (wordArray.length <= words) {
419
+ return value2;
420
+ }
421
+ return wordArray.slice(0, words).join(" ") + end;
422
+ };
423
+ var camelCase = (value2) => {
424
+ const studly = studlyCase(value2);
425
+ return studly.charAt(0).toLowerCase() + studly.slice(1);
426
+ };
427
+ var snakeCase = (value2) => {
428
+ return value2.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
429
+ };
430
+ var kebabCase = (value2) => {
431
+ return value2.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
432
+ };
433
+ var studlyCase = (value2) => {
434
+ return value2.replace(/[_-]/g, " ").replace(/\s+(.)/g, (_, c) => c.toUpperCase()).replace(/^(.)/, (_, c) => c.toUpperCase()).replace(/\s+/g, "");
435
+ };
436
+ var titleCase = (value2) => {
437
+ return value2.replace(/\w\S*/g, (txt) => {
438
+ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
439
+ });
440
+ };
441
+ var numberFormat = (value2, decimals = 2, locale = "en-US") => {
442
+ return new Intl.NumberFormat(locale, {
443
+ minimumFractionDigits: decimals,
444
+ maximumFractionDigits: decimals
445
+ }).format(value2);
446
+ };
447
+
448
+ // src/arrays.ts
449
+ var arrayAdd = (array, key, value2) => {
450
+ const result = Array.isArray(array) ? Object.fromEntries(array.map((v, i) => [i, v])) : { ...array };
451
+ result[key] = value2;
452
+ return result;
453
+ };
454
+ var arrayCollapse = (array) => {
455
+ if (!Array.isArray(array)) {
456
+ return [];
457
+ }
458
+ return array.reduce((flat, item) => {
459
+ if (Array.isArray(item)) {
460
+ return flat.concat(item);
461
+ }
462
+ return flat.concat([item]);
463
+ }, []);
464
+ };
465
+ var arrayDivide = (array) => {
466
+ if (!Array.isArray(array)) {
467
+ return [[], []];
468
+ }
469
+ const keys = array.map((_, index) => index.toString());
470
+ const values = [...array];
471
+ return [keys, values];
472
+ };
473
+ var arrayDot = (array, prepend = "") => {
474
+ const result = {};
475
+ for (const [key, value2] of Object.entries(array)) {
476
+ const newKey = prepend ? `${prepend}.${key}` : key;
477
+ if (value2 && "object" === typeof value2 && !Array.isArray(value2)) {
478
+ Object.assign(result, arrayDot(value2, newKey));
479
+ } else {
480
+ result[newKey] = value2;
481
+ }
482
+ }
483
+ return result;
484
+ };
485
+ var arrayExcept = (array, keys) => {
486
+ if (!Array.isArray(array) || !Array.isArray(keys)) {
487
+ return array;
488
+ }
489
+ return array.filter((_, index) => !keys.includes(index.toString()));
490
+ };
491
+ var arrayFirst = (array, callback, defaultValue) => {
492
+ if (!Array.isArray(array)) {
493
+ return defaultValue;
494
+ }
495
+ if (!callback) {
496
+ return 0 < array.length ? array[0] : defaultValue;
497
+ }
498
+ for (let i = 0; i < array.length; i++) {
499
+ if (callback(array[i], i)) {
500
+ return array[i];
501
+ }
502
+ }
503
+ return defaultValue;
504
+ };
505
+ var arrayFlatten = (array, depth = Infinity) => {
506
+ if (!Array.isArray(array)) {
507
+ return [];
508
+ }
509
+ const flatten = (arr, currentDepth) => {
510
+ const result = [];
511
+ for (const item of arr) {
512
+ if (Array.isArray(item) && 0 < currentDepth) {
513
+ result.push(...flatten(item, currentDepth - 1));
514
+ } else {
515
+ result.push(item);
516
+ }
517
+ }
518
+ return result;
519
+ };
520
+ return flatten(array, depth);
521
+ };
522
+ var arrayGet = (array, key, defaultValue) => {
523
+ if (!array || "object" !== typeof array) {
524
+ return defaultValue;
525
+ }
526
+ const keys = key.split(".");
527
+ let current = array;
528
+ for (const k of keys) {
529
+ if (null === current || current === void 0 || "object" !== typeof current || !(k in current)) {
530
+ return defaultValue;
531
+ }
532
+ current = current[k];
533
+ }
534
+ return current;
535
+ };
536
+ var arrayHas = (array, keys) => {
537
+ if (!array || "object" !== typeof array) {
538
+ return false;
539
+ }
540
+ const keyArray = Array.isArray(keys) ? keys : [keys];
541
+ return keyArray.every((key) => {
542
+ const keyParts = key.split(".");
543
+ let current = array;
544
+ for (const part of keyParts) {
545
+ if (null === current || current === void 0 || "object" !== typeof current || !(part in current)) {
546
+ return false;
547
+ }
548
+ current = current[part];
549
+ }
550
+ return true;
551
+ });
552
+ };
553
+ var arrayOnly = (array, keys) => {
554
+ if (!Array.isArray(array) || !Array.isArray(keys)) {
555
+ return [];
556
+ }
557
+ return array.filter((_, index) => keys.includes(index.toString()));
558
+ };
559
+ var arrayWhere = (array, callback) => {
560
+ if (!Array.isArray(array)) {
561
+ return [];
562
+ }
563
+ return array.filter(callback);
564
+ };
565
+ var arrayPluck = (array, key) => {
566
+ if (!Array.isArray(array)) {
567
+ return [];
568
+ }
569
+ return array.map((item) => item && "object" === typeof item ? item[key] : void 0).filter((value2) => value2 !== void 0);
570
+ };
571
+ var arrayGroupBy = (array, keyOrFn) => {
572
+ if (!Array.isArray(array)) {
573
+ return {};
574
+ }
575
+ return array.reduce(
576
+ (groups, item) => {
577
+ const key = "function" === typeof keyOrFn ? String(keyOrFn(item)) : String(item && "object" === typeof item ? item[keyOrFn] : item);
578
+ if (!groups[key]) {
579
+ groups[key] = [];
580
+ }
581
+ groups[key].push(item);
582
+ return groups;
583
+ },
584
+ {}
585
+ );
586
+ };
587
+ var arrayUnique = (array, key) => {
588
+ if (!Array.isArray(array)) {
589
+ return [];
590
+ }
591
+ if (!key) {
592
+ return [...new Set(array)];
593
+ }
594
+ const seen = /* @__PURE__ */ new Set();
595
+ return array.filter((item) => {
596
+ const value2 = item && "object" === typeof item ? item[key] : item;
597
+ if (seen.has(value2)) {
598
+ return false;
599
+ }
600
+ seen.add(value2);
601
+ return true;
602
+ });
603
+ };
604
+
605
+ // src/equals.ts
606
+ var isEqual = (a, b) => {
607
+ if (a === b) {
608
+ return true;
609
+ }
610
+ if (a && b && "object" === typeof a && "object" === typeof b) {
611
+ if (a.constructor !== b.constructor) {
612
+ return false;
613
+ }
614
+ if (Array.isArray(a)) {
615
+ if (a.length !== b.length) {
616
+ return false;
617
+ }
618
+ for (let i = 0; i < a.length; i++) {
619
+ if (!isEqual(a[i], b[i])) {
620
+ return false;
621
+ }
622
+ }
623
+ return true;
624
+ }
625
+ if (a instanceof Map && b instanceof Map) {
626
+ if (a.size !== b.size) {
627
+ return false;
628
+ }
629
+ for (const [key, val] of a) {
630
+ if (!b.has(key) || !isEqual(val, b.get(key))) {
631
+ return false;
632
+ }
633
+ }
634
+ return true;
635
+ }
636
+ if (a instanceof Set && b instanceof Set) {
637
+ if (a.size !== b.size) {
638
+ return false;
639
+ }
640
+ for (const val of a) {
641
+ if (!b.has(val)) {
642
+ return false;
643
+ }
644
+ }
645
+ return true;
646
+ }
647
+ if (a.constructor === RegExp) {
648
+ return a.source === b.source && a.flags === b.flags;
649
+ }
650
+ if (a.valueOf !== Object.prototype.valueOf) {
651
+ return a.valueOf() === b.valueOf();
652
+ }
653
+ if (a.toString !== Object.prototype.toString) {
654
+ return a.toString() === b.toString();
655
+ }
656
+ const keys = Object.keys(a);
657
+ if (keys.length !== Object.keys(b).length) {
658
+ return false;
659
+ }
660
+ const bObj = b;
661
+ const aObj = a;
662
+ for (const key of keys) {
663
+ if (!Object.prototype.hasOwnProperty.call(bObj, key)) {
664
+ return false;
665
+ }
666
+ if (!isEqual(aObj[key], bObj[key])) {
667
+ return false;
668
+ }
669
+ }
670
+ return true;
671
+ }
672
+ return a !== a && b !== b;
673
+ };
674
+ var diff = (original, current) => {
675
+ const result = {};
676
+ if (isEqual(original, current)) {
677
+ return result;
678
+ }
679
+ if (!original || !current || "object" !== typeof original || "object" !== typeof current) {
680
+ return current || {};
681
+ }
682
+ const originalObj = original;
683
+ const currentObj = current;
684
+ const keys = /* @__PURE__ */ new Set([...Object.keys(originalObj), ...Object.keys(currentObj)]);
685
+ for (const key of keys) {
686
+ if (!isEqual(originalObj[key], currentObj[key])) {
687
+ if (originalObj[key] && currentObj[key] && "object" === typeof originalObj[key] && "object" === typeof currentObj[key] && !Array.isArray(originalObj[key])) {
688
+ result[key] = diff(originalObj[key], currentObj[key]);
689
+ } else {
690
+ result[key] = currentObj[key];
691
+ }
692
+ }
693
+ }
694
+ return result;
695
+ };
696
+
697
+ // src/collections.ts
698
+ var EnhancedArray = class _EnhancedArray extends Array {
699
+ /**
700
+ * Create a new EnhancedArray instance.
701
+ *
702
+ * @param {...T[]} items The items to initialize the collection with
703
+ */
704
+ constructor(...items) {
705
+ super(...items);
706
+ Object.setPrototypeOf(this, _EnhancedArray.prototype);
707
+ this.originalItems = structuredClone(items);
708
+ }
709
+ /**
710
+ * Determine if the collection has been modified since initialization or last sync.
711
+ *
712
+ * @returns {boolean} True if modified, false otherwise
713
+ */
714
+ isDirty() {
715
+ return !isEqual(this.originalItems, Array.from(this));
716
+ }
717
+ /**
718
+ * Determine if the collection is clean (not modified).
719
+ *
720
+ * @returns {boolean} True if not modified, false otherwise
721
+ */
722
+ isClean() {
723
+ return !this.isDirty();
724
+ }
725
+ /**
726
+ * Sync the original items with current items to mark the collection as clean.
727
+ *
728
+ * @returns {this} The collection instance
729
+ */
730
+ syncOriginal() {
731
+ this.originalItems = structuredClone(Array.from(this));
732
+ return this;
733
+ }
734
+ /**
735
+ * Compare with another array or collection for equality.
736
+ *
737
+ * @param {T[] | EnhancedArray<T>} other The array or collection to compare with
738
+ * @returns {boolean} True if equivalent, false otherwise
739
+ */
740
+ isEquivalent(other) {
741
+ return isEqual(Array.from(this), Array.from(other));
742
+ }
743
+ /**
744
+ * Create an EnhancedArray from an iterable or array-like object.
745
+ *
746
+ * @param {Iterable<T> | ArrayLike<T>} items The items to convert
747
+ * @returns {EnhancedArray<T>} A new EnhancedArray instance
748
+ */
749
+ static from(items) {
750
+ return new _EnhancedArray(...Array.from(items));
751
+ }
752
+ /**
753
+ * Create an EnhancedArray from a variable number of arguments.
754
+ *
755
+ * @param {...T[]} items The items to include
756
+ * @returns {EnhancedArray<T>} A new EnhancedArray instance
757
+ */
758
+ static of(...items) {
759
+ return new _EnhancedArray(...items);
760
+ }
761
+ // Laravel Collection inspired methods
762
+ /**
763
+ * Create a new collection instance from the current items.
764
+ *
765
+ * @returns {EnhancedArray<T>} A new EnhancedArray instance
766
+ */
767
+ collect() {
768
+ return new _EnhancedArray(...this);
769
+ }
770
+ /**
771
+ * Pluck an array of values from an array of objects.
772
+ *
773
+ * @param {K} key The key to pluck
774
+ * @returns {EnhancedArray<T[K]>} A new collection of plucked values
775
+ */
776
+ pluck(key) {
777
+ return new _EnhancedArray(
778
+ ...this.map((item) => item && "object" === typeof item ? item[key] : void 0).filter(
779
+ (val) => val !== void 0
780
+ )
781
+ );
782
+ }
783
+ /**
784
+ * Group the collection's items by a given key or callback.
785
+ *
786
+ * @param {K | Callback<T, string | number>} key The key or callback to group by
787
+ * @returns {Record<string, EnhancedArray<T>>} A record of grouped collections
788
+ */
789
+ groupBy(key) {
790
+ const groups = {};
791
+ for (let i = 0; i < this.length; i++) {
792
+ const item = this[i];
793
+ const groupKey = "function" === typeof key ? String(key(item, i)) : String(item && "object" === typeof item ? item[key] : item);
794
+ if (!groups[groupKey]) {
795
+ groups[groupKey] = new _EnhancedArray();
796
+ }
797
+ groups[groupKey].push(item);
798
+ }
799
+ return groups;
800
+ }
801
+ /**
802
+ * Return only unique items from the collection.
803
+ *
804
+ * @param {K} [key] Optional key to determine uniqueness for objects
805
+ * @returns {EnhancedArray<T>} A new collection of unique items
806
+ */
807
+ unique(key) {
808
+ if (!key) {
809
+ return new _EnhancedArray(...new Set(this));
810
+ }
811
+ const seen = /* @__PURE__ */ new Set();
812
+ return new _EnhancedArray(
813
+ ...this.filter((item) => {
814
+ const value2 = item && "object" === typeof item ? item[key] : item;
815
+ if (seen.has(value2)) {
816
+ return false;
817
+ }
818
+ seen.add(value2);
819
+ return true;
820
+ })
821
+ );
822
+ }
823
+ /**
824
+ * Chunk the collection into smaller collections of a given size.
825
+ *
826
+ * @param {number} size The size of each chunk
827
+ * @returns {EnhancedArray<EnhancedArray<T>>} A collection of chunked collections
828
+ */
829
+ chunk(size) {
830
+ const chunks = new _EnhancedArray();
831
+ for (let i = 0; i < this.length; i += size) {
832
+ chunks.push(new _EnhancedArray(...this.slice(i, i + size)));
833
+ }
834
+ return chunks;
835
+ }
836
+ // Advanced manipulation methods
837
+ /**
838
+ * Flatten a multi-dimensional collection into a single level.
839
+ *
840
+ * @param {number} [depth=Infinity] The depth to flatten to
841
+ * @returns {EnhancedArray<unknown>} A new flattened collection
842
+ */
843
+ deepFlatten(depth = Infinity) {
844
+ const flatten = (arr, currentDepth) => {
845
+ const result = [];
846
+ for (const item of arr) {
847
+ if (Array.isArray(item) && 0 < currentDepth) {
848
+ result.push(...flatten(item, currentDepth - 1));
849
+ } else {
850
+ result.push(item);
851
+ }
852
+ }
853
+ return result;
854
+ };
855
+ return new _EnhancedArray(...flatten(this, depth));
856
+ }
857
+ /**
858
+ * Rotate the collection by a given number of positions.
859
+ *
860
+ * @param {number} [positions=1] The number of positions to rotate
861
+ * @returns {EnhancedArray<T>} A new rotated collection
862
+ */
863
+ rotate(positions = 1) {
864
+ if (0 === this.length) {
865
+ return new _EnhancedArray();
866
+ }
867
+ const count = this.length;
868
+ positions = positions % count;
869
+ if (0 === positions) {
870
+ return this.collect();
871
+ }
872
+ if (0 > positions) {
873
+ positions = count + positions;
874
+ }
875
+ return new _EnhancedArray(...this.slice(positions), ...this.slice(0, positions));
876
+ }
877
+ /**
878
+ * Chunk the collection as long as the given predicate returns true.
879
+ *
880
+ * @param {Predicate<T>} predicate The predicate to check
881
+ * @returns {EnhancedArray<EnhancedArray<T>>} A collection of chunked collections
882
+ */
883
+ chunkWhile(predicate) {
884
+ const chunks = new _EnhancedArray();
885
+ let currentChunk = new _EnhancedArray();
886
+ for (let i = 0; i < this.length; i++) {
887
+ const item = this[i];
888
+ if (0 < currentChunk.length && !predicate(item, i)) {
889
+ chunks.push(currentChunk);
890
+ currentChunk = new _EnhancedArray();
891
+ }
892
+ currentChunk.push(item);
893
+ }
894
+ if (0 < currentChunk.length) {
895
+ chunks.push(currentChunk);
896
+ }
897
+ return chunks;
898
+ }
899
+ /**
900
+ * Transpose the collection (swap rows and columns).
901
+ *
902
+ * @returns {EnhancedArray<EnhancedArray<unknown>>} A new transposed collection
903
+ */
904
+ transpose() {
905
+ if (0 === this.length) {
906
+ return new _EnhancedArray();
907
+ }
908
+ const maxLength = Math.max(...this.map((row) => Array.isArray(row) ? row.length : 1));
909
+ const result = new _EnhancedArray();
910
+ for (let i = 0; i < maxLength; i++) {
911
+ const column = new _EnhancedArray(
912
+ ...this.map((row) => {
913
+ if (Array.isArray(row)) {
914
+ return row[i] ?? null;
915
+ }
916
+ return 0 === i ? row : null;
917
+ })
918
+ );
919
+ result.push(column);
920
+ }
921
+ return result;
922
+ }
923
+ // Validation methods
924
+ /**
925
+ * Check if the collection is sorted.
926
+ *
927
+ * @param {Function} [compareFn] Optional comparison function
928
+ * @returns {boolean} True if sorted, false otherwise
929
+ */
930
+ isSorted(compareFn) {
931
+ if (1 >= this.length) {
932
+ return true;
933
+ }
934
+ for (let i = 1; i < this.length; i++) {
935
+ const prev = this[i - 1];
936
+ const current = this[i];
937
+ if (compareFn) {
938
+ if (0 < compareFn(prev, current)) {
939
+ return false;
940
+ }
941
+ } else {
942
+ if (prev > current) {
943
+ return false;
944
+ }
945
+ }
946
+ }
947
+ return true;
948
+ }
949
+ /**
950
+ * Check if the collection contains duplicate items.
951
+ *
952
+ * @param {K} [key] Optional key to check for uniqueness in objects
953
+ * @returns {boolean} True if duplicates found, false otherwise
954
+ */
955
+ hasDuplicates(key) {
956
+ if (key) {
957
+ const seen = /* @__PURE__ */ new Set();
958
+ for (const item of this) {
959
+ const value2 = item && "object" === typeof item ? item[key] : item;
960
+ if (seen.has(value2)) {
961
+ return true;
962
+ }
963
+ seen.add(value2);
964
+ }
965
+ return false;
966
+ }
967
+ return this.length !== new Set(this).size;
968
+ }
969
+ // Statistical methods
970
+ /**
971
+ * Calculate the median value of the collection.
972
+ *
973
+ * @param {Callback<T, number>} [accessor] Optional accessor for non-numeric items
974
+ * @returns {number | null} The median value or null if collection is empty
975
+ */
976
+ median(accessor) {
977
+ if (0 === this.length) {
978
+ return null;
979
+ }
980
+ const values = accessor ? this.map(accessor) : this;
981
+ const sorted = [...values].sort((a, b) => a - b);
982
+ const count = sorted.length;
983
+ if (0 === count % 2) {
984
+ return (sorted[count / 2 - 1] + sorted[count / 2]) / 2;
985
+ }
986
+ return sorted[Math.floor(count / 2)];
987
+ }
988
+ /**
989
+ * Calculate the mode (most frequent values) of the collection.
990
+ *
991
+ * @param {Callback<T, unknown>} [accessor] Optional accessor for the values
992
+ * @returns {EnhancedArray<unknown>} A collection of mode values
993
+ */
994
+ mode(accessor) {
995
+ if (0 === this.length) {
996
+ return new _EnhancedArray();
997
+ }
998
+ const frequencies = this.frequencies(accessor);
999
+ const maxFrequency = Math.max(...Object.values(frequencies));
1000
+ return new _EnhancedArray(...Object.keys(frequencies).filter((key) => frequencies[key] === maxFrequency));
1001
+ }
1002
+ /**
1003
+ * Calculate the standard deviation of the collection.
1004
+ *
1005
+ * @param {Callback<T, number>} [accessor] Optional accessor for non-numeric items
1006
+ * @returns {number} The standard deviation
1007
+ */
1008
+ standardDeviation(accessor) {
1009
+ if (0 === this.length) {
1010
+ return 0;
1011
+ }
1012
+ const values = accessor ? this.map(accessor) : this;
1013
+ const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
1014
+ const sumSquaredDifferences = values.reduce(
1015
+ (sum, val) => sum + Math.pow(val - mean, 2),
1016
+ 0
1017
+ );
1018
+ return Math.sqrt(sumSquaredDifferences / values.length);
1019
+ }
1020
+ /**
1021
+ * Calculate a specific percentile of the collection.
1022
+ *
1023
+ * @param {number} percentile The percentile to calculate (0-100)
1024
+ * @param {Callback<T, number>} [accessor] Optional accessor for non-numeric items
1025
+ * @returns {number | null} The percentile value or null if collection is empty
1026
+ */
1027
+ percentile(percentile, accessor) {
1028
+ if (0 === this.length) {
1029
+ return null;
1030
+ }
1031
+ const values = accessor ? this.map(accessor) : this;
1032
+ const sorted = [...values].sort((a, b) => a - b);
1033
+ const index = percentile / 100 * (sorted.length - 1);
1034
+ const lower = Math.floor(index);
1035
+ const upper = Math.ceil(index);
1036
+ if (lower === upper) {
1037
+ return sorted[lower];
1038
+ }
1039
+ const weight = index - lower;
1040
+ return sorted[lower] * (1 - weight) + sorted[upper] * weight;
1041
+ }
1042
+ /**
1043
+ * Calculate the frequencies of items in the collection.
1044
+ *
1045
+ * @param {Callback<T, unknown>} [accessor] Optional accessor for the values
1046
+ * @returns {Record<string, number>} A record of values and their frequencies
1047
+ */
1048
+ frequencies(accessor) {
1049
+ const frequencies = {};
1050
+ for (let i = 0; i < this.length; i++) {
1051
+ const item = this[i];
1052
+ const key = accessor ? String(accessor(item, i)) : String(item);
1053
+ frequencies[key] = (frequencies[key] || 0) + 1;
1054
+ }
1055
+ return frequencies;
1056
+ }
1057
+ // Advanced operations
1058
+ /**
1059
+ * Calculate the Cartesian product of the collection and other arrays.
1060
+ *
1061
+ * @param {...U[][]} arrays The arrays to calculate the product with
1062
+ * @returns {EnhancedArray<[T, ...U[]]>} A collection of product combinations
1063
+ */
1064
+ cartesian(...arrays) {
1065
+ const result = new _EnhancedArray();
1066
+ const allArrays = [this, ...arrays];
1067
+ function* cartesianProduct(arrays2, index = 0, current = []) {
1068
+ if (index === arrays2.length) {
1069
+ yield [...current];
1070
+ return;
1071
+ }
1072
+ for (const item of arrays2[index]) {
1073
+ yield* cartesianProduct(arrays2, index + 1, [...current, item]);
1074
+ }
1075
+ }
1076
+ for (const combination of cartesianProduct(allArrays)) {
1077
+ result.push(combination);
1078
+ }
1079
+ return result;
1080
+ }
1081
+ /**
1082
+ * Interleave the collection with other arrays.
1083
+ *
1084
+ * @param {...U[][]} arrays The arrays to interleave with
1085
+ * @returns {EnhancedArray<T | U>} A new interleaved collection
1086
+ */
1087
+ interleave(...arrays) {
1088
+ const result = new _EnhancedArray();
1089
+ const allArrays = [this, ...arrays];
1090
+ const maxLength = Math.max(...allArrays.map((arr) => arr.length));
1091
+ for (let i = 0; i < maxLength; i++) {
1092
+ for (const array of allArrays) {
1093
+ if (i < array.length) {
1094
+ result.push(array[i]);
1095
+ }
1096
+ }
1097
+ }
1098
+ return result;
1099
+ }
1100
+ /**
1101
+ * Get a sliding window of items from the collection.
1102
+ *
1103
+ * @param {number} [size=2] The size of the window
1104
+ * @param {number} [step=1] The step between windows
1105
+ * @returns {EnhancedArray<EnhancedArray<T>>} A collection of window collections
1106
+ */
1107
+ sliding(size = 2, step = 1) {
1108
+ if (0 >= size || 0 >= step) {
1109
+ return new _EnhancedArray();
1110
+ }
1111
+ const windows = new _EnhancedArray();
1112
+ for (let i = 0; i <= this.length - size; i += step) {
1113
+ windows.push(new _EnhancedArray(...this.slice(i, i + size)));
1114
+ }
1115
+ return windows;
1116
+ }
1117
+ // Navigation macros
1118
+ /**
1119
+ * Get the item at the given index.
1120
+ *
1121
+ * @param {number} index The index to retrieve
1122
+ * @returns {T | undefined} The item at the index or undefined
1123
+ */
1124
+ at(index) {
1125
+ return this[index];
1126
+ }
1127
+ /**
1128
+ * Get the item before the given item.
1129
+ *
1130
+ * @param {T} item The item to search for
1131
+ * @returns {T | undefined} The item before or undefined
1132
+ */
1133
+ before(item) {
1134
+ const index = this.indexOf(item);
1135
+ return 0 < index ? this[index - 1] : void 0;
1136
+ }
1137
+ /**
1138
+ * Get the item after the given item.
1139
+ *
1140
+ * @param {T} item The item to search for
1141
+ * @returns {T | undefined} The item after or undefined
1142
+ */
1143
+ after(item) {
1144
+ const index = this.indexOf(item);
1145
+ return 0 <= index && index < this.length - 1 ? this[index + 1] : void 0;
1146
+ }
1147
+ // Transformation macros
1148
+ /**
1149
+ * Chunk the collection by a given key or callback when its value changes.
1150
+ *
1151
+ * @param {K | Callback<T, unknown>} key The key or callback to chunk by
1152
+ * @returns {EnhancedArray<EnhancedArray<T>>} A collection of chunked collections
1153
+ */
1154
+ chunkBy(key) {
1155
+ if (0 === this.length) {
1156
+ return new _EnhancedArray();
1157
+ }
1158
+ const chunks = new _EnhancedArray();
1159
+ let currentChunk = new _EnhancedArray();
1160
+ let lastValue = null;
1161
+ for (let i = 0; i < this.length; i++) {
1162
+ const item = this[i];
1163
+ const currentValue = "function" === typeof key ? key(item, i) : item && "object" === typeof item ? item[key] : item;
1164
+ if (0 === i || currentValue === lastValue) {
1165
+ currentChunk.push(item);
1166
+ } else {
1167
+ chunks.push(currentChunk);
1168
+ currentChunk = new _EnhancedArray(item);
1169
+ }
1170
+ lastValue = currentValue;
1171
+ }
1172
+ if (0 < currentChunk.length) {
1173
+ chunks.push(currentChunk);
1174
+ }
1175
+ return chunks;
1176
+ }
1177
+ /**
1178
+ * Map and filter the collection simultaneously.
1179
+ * Items for which the callback returns null or undefined are removed.
1180
+ *
1181
+ * @param {Function} callback The callback to map items
1182
+ * @returns {EnhancedArray<U>} A new mapped and filtered collection
1183
+ */
1184
+ filterMap(callback) {
1185
+ const result = new _EnhancedArray();
1186
+ for (let i = 0; i < this.length; i++) {
1187
+ const mapped = callback(this[i], i);
1188
+ if (null !== mapped && mapped !== void 0) {
1189
+ result.push(mapped);
1190
+ }
1191
+ }
1192
+ return result;
1193
+ }
1194
+ /**
1195
+ * Extract a subset of properties from each item in the collection.
1196
+ *
1197
+ * @param {K[]} keys The keys to extract
1198
+ * @returns {EnhancedArray<Partial<T>>} A new collection of partial items
1199
+ */
1200
+ extract(keys) {
1201
+ return new _EnhancedArray(
1202
+ ...this.map((item) => {
1203
+ if (!item || "object" !== typeof item) {
1204
+ return {};
1205
+ }
1206
+ const extracted = {};
1207
+ for (const key of keys) {
1208
+ if (key in item) {
1209
+ extracted[key] = item[key];
1210
+ }
1211
+ }
1212
+ return extracted;
1213
+ })
1214
+ );
1215
+ }
1216
+ // Utility macros
1217
+ /**
1218
+ * Get the first item or push a default item if the collection is empty.
1219
+ *
1220
+ * @param {T} item The default item to push if empty
1221
+ * @returns {T} The first item or the pushed item
1222
+ */
1223
+ firstOrPush(item) {
1224
+ if (0 === this.length) {
1225
+ this.push(item);
1226
+ return item;
1227
+ }
1228
+ return this[0];
1229
+ }
1230
+ /**
1231
+ * Get every n-th item from the collection.
1232
+ *
1233
+ * @param {number} n The step size
1234
+ * @returns {EnhancedArray<T>} A new collection of every n-th item
1235
+ */
1236
+ getNth(n) {
1237
+ const result = new _EnhancedArray();
1238
+ for (let i = n - 1; i < this.length; i += n) {
1239
+ result.push(this[i]);
1240
+ }
1241
+ return result;
1242
+ }
1243
+ /**
1244
+ * Get a random item from the collection based on weights.
1245
+ *
1246
+ * @param {number[]} [weights] Optional weights for each item
1247
+ * @returns {T | undefined} A random item or undefined if collection is empty
1248
+ */
1249
+ weightedRandom(weights) {
1250
+ if (0 === this.length) {
1251
+ return void 0;
1252
+ }
1253
+ const effectiveWeights = weights ?? new Array(this.length).fill(1);
1254
+ if (effectiveWeights.length !== this.length) {
1255
+ throw new Error("Weights array must have same length as collection");
1256
+ }
1257
+ const totalWeight = effectiveWeights.reduce((sum, weight) => sum + weight, 0);
1258
+ const random = Math.random() * totalWeight;
1259
+ let currentWeight = 0;
1260
+ for (let i = 0; i < this.length; i++) {
1261
+ currentWeight += effectiveWeights[i];
1262
+ if (random <= currentWeight) {
1263
+ return this[i];
1264
+ }
1265
+ }
1266
+ return this[this.length - 1];
1267
+ }
1268
+ /**
1269
+ * Paginate the collection items.
1270
+ *
1271
+ * @param {number} perPage Items per page
1272
+ * @param {number} [page=1] Current page number
1273
+ * @returns {Object} Pagination results
1274
+ */
1275
+ paginate(perPage, page = 1) {
1276
+ const total = this.length;
1277
+ const lastPage = Math.ceil(total / perPage);
1278
+ const currentPage = Math.max(1, Math.min(page, lastPage));
1279
+ const from = (currentPage - 1) * perPage;
1280
+ const to = Math.min(from + perPage, total);
1281
+ return {
1282
+ data: new _EnhancedArray(...this.slice(from, to)),
1283
+ total,
1284
+ perPage,
1285
+ currentPage,
1286
+ lastPage,
1287
+ from: from + 1,
1288
+ to
1289
+ };
1290
+ }
1291
+ /**
1292
+ * Recursively convert all nested arrays to EnhancedArray instances.
1293
+ *
1294
+ * @returns {EnhancedArray<unknown>} A new collection with recursive EnhancedArrays
1295
+ */
1296
+ recursive() {
1297
+ const convert = (item) => {
1298
+ if (Array.isArray(item)) {
1299
+ return new _EnhancedArray(...item.map(convert));
1300
+ }
1301
+ if (item && "object" === typeof item && item.constructor === Object) {
1302
+ const converted = {};
1303
+ for (const [key, value2] of Object.entries(item)) {
1304
+ converted[key] = convert(value2);
1305
+ }
1306
+ return converted;
1307
+ }
1308
+ return item;
1309
+ };
1310
+ return new _EnhancedArray(...this.map(convert));
1311
+ }
1312
+ };
1313
+ var objectToMap = (obj2) => {
1314
+ return new Map(Object.entries(obj2));
1315
+ };
1316
+ var mapToObject = (map) => {
1317
+ return Object.fromEntries(map);
1318
+ };
1319
+ var EnhancedMap = class _EnhancedMap extends Map {
1320
+ /**
1321
+ * Create an EnhancedMap from a plain object.
1322
+ *
1323
+ * @param {Record<string, V>} obj The object to convert
1324
+ * @returns {EnhancedMap<string, V>} A new EnhancedMap instance
1325
+ */
1326
+ static fromObject(obj2) {
1327
+ return new _EnhancedMap(Object.entries(obj2));
1328
+ }
1329
+ /**
1330
+ * Pluck a property from each value in the map.
1331
+ *
1332
+ * @param {P} key The key to pluck
1333
+ * @returns {EnhancedArray<V[P]>} A new collection of plucked values
1334
+ */
1335
+ pluck(key) {
1336
+ return new EnhancedArray(
1337
+ ...Array.from(this.values()).map((value2) => value2 && "object" === typeof value2 ? value2[key] : void 0).filter((val) => val !== void 0)
1338
+ );
1339
+ }
1340
+ /**
1341
+ * Group the map's entries by a given accessor.
1342
+ *
1343
+ * @param {Function} accessor The accessor to group by
1344
+ * @returns {Record<string, EnhancedArray<[K, V]>>} A record of grouped entries
1345
+ */
1346
+ groupBy(accessor) {
1347
+ const groups = {};
1348
+ for (const [key, value2] of this) {
1349
+ const groupKey = String(accessor(value2, key));
1350
+ if (!groups[groupKey]) {
1351
+ groups[groupKey] = new EnhancedArray();
1352
+ }
1353
+ groups[groupKey].push([key, value2]);
1354
+ }
1355
+ return groups;
1356
+ }
1357
+ /**
1358
+ * Convert the map to an array of entries.
1359
+ *
1360
+ * @returns {EnhancedArray<[K, V]>} A collection of entries
1361
+ */
1362
+ toArray() {
1363
+ return new EnhancedArray(...this.entries());
1364
+ }
1365
+ /**
1366
+ * Convert the map to a plain object.
1367
+ *
1368
+ * @returns {Record<string, V>} A plain object representation of the map
1369
+ */
1370
+ toObject() {
1371
+ const obj2 = {};
1372
+ for (const [key, value2] of this) {
1373
+ obj2[String(key)] = value2;
1374
+ }
1375
+ return obj2;
1376
+ }
1377
+ };
1378
+ var collect = (items) => {
1379
+ return new EnhancedArray(...items);
1380
+ };
1381
+ var collectMap = (entries) => {
1382
+ return new EnhancedMap(entries);
1383
+ };
1384
+
1385
+ // src/php-arrays.ts
1386
+ var array_chunk = (array, size) => {
1387
+ if (0 >= size) {
1388
+ return [];
1389
+ }
1390
+ const chunks = [];
1391
+ for (let i = 0; i < array.length; i += size) {
1392
+ chunks.push(array.slice(i, i + size));
1393
+ }
1394
+ return chunks;
1395
+ };
1396
+ var array_filter = (array, callback) => {
1397
+ if (!callback) {
1398
+ return array.filter((item) => Boolean(item));
1399
+ }
1400
+ return array.filter(callback);
1401
+ };
1402
+ var array_map = (callback, array) => {
1403
+ return array.map(callback);
1404
+ };
1405
+ var array_reduce = (array, callback, initial) => {
1406
+ return array.reduce((carry, item, index) => callback(carry, item, index), initial);
1407
+ };
1408
+ var array_merge = (...arrays) => {
1409
+ return arrays.flat();
1410
+ };
1411
+ var array_unique = (array) => {
1412
+ return [...new Set(array)];
1413
+ };
1414
+ var array_reverse = (array, _preserveKeys = false) => {
1415
+ return [...array].reverse();
1416
+ };
1417
+ var array_slice = (array, offset, length) => {
1418
+ const start = 0 > offset ? Math.max(0, array.length + offset) : offset;
1419
+ const end = length !== void 0 ? start + length : void 0;
1420
+ return array.slice(start, end);
1421
+ };
1422
+ var array_splice = (array, offset, length, ...replacement) => {
1423
+ const result = [...array];
1424
+ const actualLength = length ?? result.length - offset;
1425
+ result.splice(offset, actualLength, ...replacement);
1426
+ return result;
1427
+ };
1428
+ var array_keys = (array) => {
1429
+ return array.map((_, index) => index);
1430
+ };
1431
+ var array_search = (needle, haystack) => {
1432
+ const index = haystack.indexOf(needle);
1433
+ return -1 !== index ? index : false;
1434
+ };
1435
+ var array_key_exists = (key, array) => {
1436
+ return 0 <= key && key < array.length;
1437
+ };
1438
+ var array_pop = (array) => {
1439
+ const result = [...array];
1440
+ return result.pop();
1441
+ };
1442
+ var array_push = (array, ...values) => {
1443
+ return [...array, ...values];
1444
+ };
1445
+ var array_shift = (array) => {
1446
+ const result = [...array];
1447
+ return result.shift();
1448
+ };
1449
+ var array_unshift = (array, ...values) => {
1450
+ return [...values, ...array];
1451
+ };
1452
+ var array_sum = (array) => {
1453
+ return array.reduce((sum, num2) => sum + num2, 0);
1454
+ };
1455
+ var array_product = (array) => {
1456
+ return array.reduce((product, num2) => product * num2, 1);
1457
+ };
1458
+ var array_rand = (array, num2 = 1) => {
1459
+ if (0 === array.length) {
1460
+ return 1 === num2 ? void 0 : [];
1461
+ }
1462
+ const shuffled = [...array].sort(() => Math.random() - 0.5);
1463
+ if (1 === num2) {
1464
+ return shuffled[0];
1465
+ }
1466
+ return shuffled.slice(0, Math.min(num2, array.length));
1467
+ };
1468
+ var array_flip = (array) => {
1469
+ const result = {};
1470
+ array.forEach((value2, index) => {
1471
+ result[String(value2)] = index;
1472
+ });
1473
+ return result;
1474
+ };
1475
+ var array_count_values = (array) => {
1476
+ const result = {};
1477
+ array.forEach((value2) => {
1478
+ const key = String(value2);
1479
+ result[key] = (result[key] || 0) + 1;
1480
+ });
1481
+ return result;
1482
+ };
1483
+ var array_intersect = (...arrays) => {
1484
+ if (0 === arrays.length) {
1485
+ return [];
1486
+ }
1487
+ const first = arrays[0];
1488
+ return first.filter((item) => arrays.slice(1).every((arr) => arr.includes(item)));
1489
+ };
1490
+ var array_diff = (array1, ...arrays) => {
1491
+ const otherItems = new Set(arrays.flat());
1492
+ return array1.filter((item) => !otherItems.has(item));
1493
+ };
1494
+ var array_column = (array, column) => {
1495
+ return array.map((item) => item && "object" === typeof item ? item[column] : void 0).filter((value2) => value2 !== void 0);
1496
+ };
1497
+ var sort = (array) => {
1498
+ return [...array].sort();
1499
+ };
1500
+ var rsort = (array) => {
1501
+ return [...array].sort().reverse();
1502
+ };
1503
+ var usort = (array, compareFunction) => {
1504
+ return [...array].sort(compareFunction);
1505
+ };
1506
+ var uasort = (array, compareFunction) => {
1507
+ return [...array].sort(compareFunction);
1508
+ };
1509
+ var uksort = (array, compareFunction) => {
1510
+ const indices = Array.from({ length: array.length }, (_, i) => i);
1511
+ const sortedIndices = indices.sort(compareFunction);
1512
+ return sortedIndices.map((i) => array[i]);
1513
+ };
1514
+ var shuffle = (array) => {
1515
+ const result = [...array];
1516
+ for (let i = result.length - 1; 0 < i; i--) {
1517
+ const j = Math.floor(Math.random() * (i + 1));
1518
+ [result[i], result[j]] = [result[j], result[i]];
1519
+ }
1520
+ return result;
1521
+ };
1522
+ var range = (start, end, step = 1) => {
1523
+ const result = [];
1524
+ if (0 < step) {
1525
+ for (let i = start; i <= end; i += step) {
1526
+ result.push(i);
1527
+ }
1528
+ } else if (0 > step) {
1529
+ for (let i = start; i >= end; i += step) {
1530
+ result.push(i);
1531
+ }
1532
+ }
1533
+ return result;
1534
+ };
1535
+ var php_array = (items) => {
1536
+ const enhanced = new EnhancedArray(...items);
1537
+ Object.assign(enhanced, {
1538
+ // PHP array functions as methods
1539
+ chunk: (size) => array_chunk(enhanced, size),
1540
+ merge: (...arrays) => new EnhancedArray(...array_merge(enhanced, ...arrays)),
1541
+ unique: () => new EnhancedArray(...array_unique(enhanced)),
1542
+ reverse: (preserveKeys = false) => new EnhancedArray(...array_reverse(enhanced, preserveKeys)),
1543
+ search: (needle) => array_search(needle, enhanced),
1544
+ sum: () => array_sum(enhanced),
1545
+ product: () => array_product(enhanced),
1546
+ rand: (num2 = 1) => array_rand(enhanced, num2),
1547
+ flip: () => array_flip(enhanced),
1548
+ countValues: () => array_count_values(enhanced),
1549
+ intersect: (...arrays) => new EnhancedArray(...array_intersect(enhanced, ...arrays)),
1550
+ diff: (...arrays) => new EnhancedArray(...array_diff(enhanced, ...arrays)),
1551
+ column: (column) => array_column(enhanced, column),
1552
+ // PHP sorting as methods
1553
+ sort: () => new EnhancedArray(...sort(enhanced)),
1554
+ rsort: () => new EnhancedArray(...rsort(enhanced)),
1555
+ shuffle: () => new EnhancedArray(...shuffle(enhanced)),
1556
+ usort: (compareFunction) => new EnhancedArray(...usort(enhanced, compareFunction))
1557
+ });
1558
+ return enhanced;
1559
+ };
1560
+
1561
+ // src/datetime.ts
1562
+ var import_dayjs = __toESM(require("dayjs"), 1);
1563
+ var import_isBetween = __toESM(require("dayjs/plugin/isBetween"), 1);
1564
+ var import_isSameOrAfter = __toESM(require("dayjs/plugin/isSameOrAfter"), 1);
1565
+ var import_isSameOrBefore = __toESM(require("dayjs/plugin/isSameOrBefore"), 1);
1566
+ var import_relativeTime = __toESM(require("dayjs/plugin/relativeTime"), 1);
1567
+ var import_utc = __toESM(require("dayjs/plugin/utc"), 1);
1568
+ import_dayjs.default.extend(import_isBetween.default);
1569
+ import_dayjs.default.extend(import_isSameOrAfter.default);
1570
+ import_dayjs.default.extend(import_isSameOrBefore.default);
1571
+ import_dayjs.default.extend(import_relativeTime.default);
1572
+ import_dayjs.default.extend(import_utc.default);
1573
+ var dayjs = import_dayjs.default;
1574
+ var now = () => dayjs();
1575
+ var today = () => dayjs().startOf("day");
1576
+ var tomorrow = () => dayjs().add(1, "day").startOf("day");
1577
+ var yesterday = () => dayjs().subtract(1, "day").startOf("day");
1578
+ var isBetweenDates = (date, start, end, unit = "day", inclusivity = "[]") => {
1579
+ return dayjs(date).isBetween(dayjs(start), dayjs(end), unit, inclusivity);
1580
+ };
1581
+ var fromNow = (date) => dayjs(date).fromNow();
1582
+ var isToday = (date) => dayjs(date).isSame(dayjs(), "day");
1583
+ var isPast = (date) => dayjs(date).isBefore(dayjs());
1584
+ var isFuture = (date) => dayjs(date).isAfter(dayjs());
1585
+
1586
+ // src/schemas.ts
1587
+ var import_zod = require("zod");
1588
+ var EmailSchema = import_zod.z.string().email("Invalid email format").min(1, "Email is required");
1589
+ var PhoneSchema = import_zod.z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number format");
1590
+ var UrlSchema = import_zod.z.string().url("Invalid URL format");
1591
+ var DateSchema = import_zod.z.union([
1592
+ import_zod.z.string().datetime(),
1593
+ import_zod.z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid date format (YYYY-MM-DD)"),
1594
+ import_zod.z.date()
1595
+ ]);
1596
+ var ApiResponseSchema = (dataSchema) => import_zod.z.object({
1597
+ success: import_zod.z.boolean(),
1598
+ data: dataSchema.optional(),
1599
+ message: import_zod.z.string().optional(),
1600
+ errors: import_zod.z.array(import_zod.z.string()).optional()
1601
+ });
1602
+ var PaginationSchema = import_zod.z.object({
1603
+ page: import_zod.z.number().int().positive().default(1),
1604
+ perPage: import_zod.z.number().int().min(1).max(100).default(15),
1605
+ total: import_zod.z.number().int().nonnegative(),
1606
+ lastPage: import_zod.z.number().int().positive()
1607
+ });
1608
+ var PaginatedResponseSchema = (itemSchema) => import_zod.z.object({
1609
+ data: import_zod.z.array(itemSchema),
1610
+ pagination: PaginationSchema
1611
+ });
1612
+ var validateSchema = (schema, data) => {
1613
+ const result = schema.safeParse(data);
1614
+ if (!result.success) {
1615
+ const errors = result.error.issues.map((err) => `${err.path.join(".")}: ${err.message}`);
1616
+ throw new Error(`Validation failed: ${errors.join(", ")}`);
1617
+ }
1618
+ return result.data;
1619
+ };
1620
+ var safeValidateSchema = (schema, data) => {
1621
+ const result = schema.safeParse(data);
1622
+ if (result.success) {
1623
+ return { success: true, data: result.data };
1624
+ }
1625
+ const errors = result.error.issues.map((err) => `${err.path.join(".")}: ${err.message}`);
1626
+ return { success: false, errors };
1627
+ };
1628
+
1629
+ // src/number.ts
1630
+ var Numberable = class {
1631
+ /**
1632
+ * Create a new Numberable instance.
1633
+ *
1634
+ * @param {unknown} value The initial value
1635
+ */
1636
+ constructor(value2) {
1637
+ this.value = Number(value2 ?? 0);
1638
+ if (isNaN(this.value)) {
1639
+ this.value = 0;
1640
+ }
1641
+ }
1642
+ /**
1643
+ * Get the raw number value.
1644
+ *
1645
+ * @returns {number} The raw value
1646
+ */
1647
+ toNumber() {
1648
+ return this.value;
1649
+ }
1650
+ /**
1651
+ * Alias for toNumber().
1652
+ *
1653
+ * @returns {number} The raw value
1654
+ */
1655
+ get() {
1656
+ return this.value;
1657
+ }
1658
+ /**
1659
+ * Format the number with locale-specific formatting.
1660
+ *
1661
+ * @param {number} [decimals=0] The number of decimal points
1662
+ * @param {string} [locale='en-US'] The locale to use for formatting
1663
+ * @returns {string} The formatted number
1664
+ */
1665
+ format(decimals = 0, locale = "en-US") {
1666
+ return new Intl.NumberFormat(locale, {
1667
+ minimumFractionDigits: decimals,
1668
+ maximumFractionDigits: decimals
1669
+ }).format(this.value);
1670
+ }
1671
+ /**
1672
+ * Format the number as currency.
1673
+ *
1674
+ * @param {string} [currency='USD'] The currency code (e.g., 'USD', 'EUR')
1675
+ * @param {string} [locale='en-US'] The locale to use for formatting
1676
+ * @returns {string} The formatted currency string
1677
+ */
1678
+ currency(currency = "USD", locale = "en-US") {
1679
+ return new Intl.NumberFormat(locale, {
1680
+ style: "currency",
1681
+ currency
1682
+ }).format(this.value);
1683
+ }
1684
+ /**
1685
+ * Format the number as a percentage.
1686
+ *
1687
+ * @param {number} [decimals=0] The number of decimal points
1688
+ * @param {string} [locale='en-US'] The locale to use for formatting
1689
+ * @returns {string} The formatted percentage string
1690
+ */
1691
+ percentage(decimals = 0, locale = "en-US") {
1692
+ return new Intl.NumberFormat(locale, {
1693
+ style: "percent",
1694
+ minimumFractionDigits: decimals,
1695
+ maximumFractionDigits: decimals
1696
+ }).format(this.value / 100);
1697
+ }
1698
+ /**
1699
+ * Format the number as a human-readable file size.
1700
+ *
1701
+ * @param {number} [precision=2] The number of decimal points
1702
+ * @returns {string} The formatted file size (e.g., "1.50 MB")
1703
+ */
1704
+ fileSize(precision = 2) {
1705
+ if (0 === this.value) {
1706
+ return "0 B";
1707
+ }
1708
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1709
+ const i = Math.floor(Math.log(this.value) / Math.log(1024));
1710
+ return `${parseFloat((this.value / Math.pow(1024, i)).toFixed(precision))} ${units[i]}`;
1711
+ }
1712
+ /**
1713
+ * Abbreviate the number (e.g., 1K, 1M, 1B).
1714
+ *
1715
+ * @param {number} [precision=1] The number of decimal points
1716
+ * @returns {string} The abbreviated number
1717
+ */
1718
+ abbreviate(precision = 1) {
1719
+ if (1e3 > this.value) {
1720
+ return String(this.value);
1721
+ }
1722
+ const units = ["", "K", "M", "B", "T"];
1723
+ const i = Math.floor(Math.log10(this.value) / 3);
1724
+ return `${parseFloat((this.value / Math.pow(1e3, i)).toFixed(precision))}${units[i]}`;
1725
+ }
1726
+ /**
1727
+ * Add an ordinal suffix to the number (e.g., 1st, 2nd, 3rd).
1728
+ *
1729
+ * @returns {string} The number with its ordinal suffix
1730
+ */
1731
+ ordinal() {
1732
+ const s = ["th", "st", "nd", "rd"];
1733
+ const v = this.value % 100;
1734
+ return this.value + (s[(v - 20) % 10] || s[v] || s[0]);
1735
+ }
1736
+ /**
1737
+ * Clamp the number between a minimum and maximum value.
1738
+ *
1739
+ * @param {number} min The minimum value
1740
+ * @param {number} max The maximum value
1741
+ * @returns {this} The Numberable instance
1742
+ */
1743
+ clamp(min, max) {
1744
+ this.value = Math.min(Math.max(this.value, min), max);
1745
+ return this;
1746
+ }
1747
+ /**
1748
+ * Check if the number is between a minimum and maximum value.
1749
+ *
1750
+ * @param {number} min The minimum value
1751
+ * @param {number} max The maximum value
1752
+ * @param {boolean} [inclusive=true] Whether to include the boundaries
1753
+ * @returns {boolean} True if the number is between min and max
1754
+ */
1755
+ isBetween(min, max, inclusive = true) {
1756
+ return inclusive ? this.value >= min && this.value <= max : this.value > min && this.value < max;
1757
+ }
1758
+ /**
1759
+ * Add a value to the current number.
1760
+ *
1761
+ * @param {number} value The value to add
1762
+ * @returns {this} The Numberable instance
1763
+ */
1764
+ add(value2) {
1765
+ this.value += value2;
1766
+ return this;
1767
+ }
1768
+ /**
1769
+ * Subtract a value from the current number.
1770
+ *
1771
+ * @param {number} value The value to subtract
1772
+ * @returns {this} The Numberable instance
1773
+ */
1774
+ sub(value2) {
1775
+ this.value -= value2;
1776
+ return this;
1777
+ }
1778
+ /**
1779
+ * Multiply the current number by a value.
1780
+ *
1781
+ * @param {number} value The value to multiply by
1782
+ * @returns {this} The Numberable instance
1783
+ */
1784
+ mul(value2) {
1785
+ this.value *= value2;
1786
+ return this;
1787
+ }
1788
+ /**
1789
+ * Divide the current number by a value.
1790
+ *
1791
+ * @param {number} value The value to divide by
1792
+ * @returns {this} The Numberable instance
1793
+ */
1794
+ div(value2) {
1795
+ if (0 !== value2) {
1796
+ this.value /= value2;
1797
+ }
1798
+ return this;
1799
+ }
1800
+ /**
1801
+ * Round the number to a specified precision.
1802
+ *
1803
+ * @param {number} [precision=0] The number of decimal points
1804
+ * @returns {this} The Numberable instance
1805
+ */
1806
+ round(precision = 0) {
1807
+ const factor = Math.pow(10, precision);
1808
+ this.value = Math.round(this.value * factor) / factor;
1809
+ return this;
1810
+ }
1811
+ /**
1812
+ * Round the number up to a specified precision.
1813
+ *
1814
+ * @param {number} [precision=0] The number of decimal points
1815
+ * @returns {this} The Numberable instance
1816
+ */
1817
+ ceil(precision = 0) {
1818
+ const factor = Math.pow(10, precision);
1819
+ this.value = Math.ceil(this.value * factor) / factor;
1820
+ return this;
1821
+ }
1822
+ /**
1823
+ * Round the number down to a specified precision.
1824
+ *
1825
+ * @param {number} [precision=0] The number of decimal points
1826
+ * @returns {this} The Numberable instance
1827
+ */
1828
+ floor(precision = 0) {
1829
+ const factor = Math.pow(10, precision);
1830
+ this.value = Math.floor(this.value * factor) / factor;
1831
+ return this;
1832
+ }
1833
+ /**
1834
+ * Pipe the current Numberable instance to a callback.
1835
+ *
1836
+ * @param {Function} callback The callback to execute
1837
+ * @returns {U} The result of the callback
1838
+ */
1839
+ pipe(callback) {
1840
+ return callback(this);
1841
+ }
1842
+ /**
1843
+ * Execute a callback if a condition is met.
1844
+ *
1845
+ * @param {boolean | Function} condition The condition to check
1846
+ * @param {Function} callback The callback to execute if condition is true
1847
+ * @returns {this} The Numberable instance
1848
+ */
1849
+ when(condition, callback) {
1850
+ const shouldExecute = "function" === typeof condition ? condition() : condition;
1851
+ if (shouldExecute) {
1852
+ callback(this);
1853
+ }
1854
+ return this;
1855
+ }
1856
+ };
1857
+ var num = (value2) => {
1858
+ return new Numberable(value2);
1859
+ };
1860
+ var NumberHelper = {
1861
+ /** Create a new Numberable instance */
1862
+ of: (value2) => new Numberable(value2),
1863
+ /** Format the number with locale-specific formatting */
1864
+ format: (value2, decimals = 0, locale = "en-US") => new Numberable(value2).format(decimals, locale),
1865
+ /** Format the number as currency */
1866
+ currency: (value2, currency = "USD", locale = "en-US") => new Numberable(value2).currency(currency, locale),
1867
+ /** Format the number as a percentage */
1868
+ percentage: (value2, decimals = 0, locale = "en-US") => new Numberable(value2).percentage(decimals, locale),
1869
+ /** Format the number as a human-readable file size */
1870
+ fileSize: (value2, precision = 2) => new Numberable(value2).fileSize(precision),
1871
+ /** Abbreviate the number */
1872
+ abbreviate: (value2, precision = 1) => new Numberable(value2).abbreviate(precision),
1873
+ /** Add an ordinal suffix to the number */
1874
+ ordinal: (value2) => new Numberable(value2).ordinal()
1875
+ };
1876
+
1877
+ // src/runtime.ts
1878
+ function isRecord(value2) {
1879
+ return null !== value2 && "object" === typeof value2 && !Array.isArray(value2);
1880
+ }
1881
+ var tap = (value2, callback) => {
1882
+ callback(value2);
1883
+ return value2;
1884
+ };
1885
+ var when = (condition, onTrue, onFalse) => {
1886
+ const shouldExecute = "function" === typeof condition ? condition() : Boolean(condition);
1887
+ if (shouldExecute) {
1888
+ return onTrue();
1889
+ } else if (onFalse) {
1890
+ return onFalse();
1891
+ }
1892
+ return void 0;
1893
+ };
1894
+ var value = (val) => {
1895
+ return "function" === typeof val ? val() : val;
1896
+ };
1897
+ var data_get = (target, key, defaultValue = null) => {
1898
+ if (!isRecord(target) && !Array.isArray(target)) {
1899
+ return defaultValue;
1900
+ }
1901
+ const parts = Array.isArray(key) ? key : key.split(".");
1902
+ let result = target;
1903
+ for (const part of parts) {
1904
+ if (!isRecord(result) && !Array.isArray(result)) {
1905
+ return defaultValue;
1906
+ }
1907
+ if (part in result) {
1908
+ result = result[part];
1909
+ } else {
1910
+ return defaultValue;
1911
+ }
1912
+ }
1913
+ return result;
1914
+ };
1915
+ var data_set = (target, key, value2) => {
1916
+ if (!isRecord(target) && !Array.isArray(target)) {
1917
+ return target;
1918
+ }
1919
+ const parts = Array.isArray(key) ? key : key.split(".");
1920
+ let current = target;
1921
+ for (let i = 0; i < parts.length - 1; i++) {
1922
+ const part = parts[i];
1923
+ if (!isRecord(current)) {
1924
+ break;
1925
+ }
1926
+ const currentRecord = current;
1927
+ if (!(part in currentRecord) || !isRecord(currentRecord[part])) {
1928
+ currentRecord[part] = {};
1929
+ }
1930
+ current = currentRecord[part];
1931
+ }
1932
+ if (isRecord(current)) {
1933
+ ;
1934
+ current[parts[parts.length - 1]] = value2;
1935
+ }
1936
+ return target;
1937
+ };
1938
+ var optional = (value2) => {
1939
+ return value2 ?? null;
1940
+ };
1941
+ var retry = async (times, callback, sleepMilliseconds = 0) => {
1942
+ let lastError;
1943
+ for (let attempt = 1; attempt <= times; attempt++) {
1944
+ try {
1945
+ return await callback(attempt);
1946
+ } catch (error) {
1947
+ lastError = error instanceof Error ? error : new Error(String(error));
1948
+ if (attempt < times && 0 < sleepMilliseconds) {
1949
+ await new Promise((resolve) => setTimeout(resolve, sleepMilliseconds));
1950
+ }
1951
+ }
1952
+ }
1953
+ throw lastError ?? new Error(`Retry failed after ${times} attempts`);
1954
+ };
1955
+ var throw_if = (condition, exception) => {
1956
+ if ("function" === typeof condition ? condition() : Boolean(condition)) {
1957
+ throw "string" === typeof exception ? new Error(exception) : exception;
1958
+ }
1959
+ };
1960
+ var throw_unless = (condition, exception) => {
1961
+ if (!("function" === typeof condition ? condition() : Boolean(condition))) {
1962
+ throw "string" === typeof exception ? new Error(exception) : exception;
1963
+ }
1964
+ };
1965
+
1966
+ // src/obj.ts
1967
+ var Objectable = class _Objectable {
1968
+ /**
1969
+ * Create a new Objectable instance.
1970
+ *
1971
+ * @param {T} value The initial object value
1972
+ */
1973
+ constructor(value2) {
1974
+ this.value = structuredClone(value2);
1975
+ this.originalValue = structuredClone(value2);
1976
+ }
1977
+ /**
1978
+ * Get the current object state.
1979
+ *
1980
+ * @returns {T} The current object
1981
+ */
1982
+ toObject() {
1983
+ return this.value;
1984
+ }
1985
+ /**
1986
+ * Alias for toObject().
1987
+ *
1988
+ * @returns {T} The current object
1989
+ */
1990
+ get() {
1991
+ return this.value;
1992
+ }
1993
+ /**
1994
+ * Get the original state from construction.
1995
+ *
1996
+ * @returns {T} The original object
1997
+ */
1998
+ getOriginal() {
1999
+ return this.originalValue;
2000
+ }
2001
+ /**
2002
+ * Sync original state with current state (marking it as clean).
2003
+ *
2004
+ * @returns {this} The Objectable instance
2005
+ */
2006
+ syncOriginal() {
2007
+ this.originalValue = structuredClone(this.value);
2008
+ return this;
2009
+ }
2010
+ /**
2011
+ * Determine if any attribute has been modified.
2012
+ *
2013
+ * @param {string} [key] Optional key to check specifically
2014
+ * @returns {boolean} True if dirty, false otherwise
2015
+ */
2016
+ isDirty(key) {
2017
+ if (key) {
2018
+ return !isEqual(data_get(this.originalValue, key), data_get(this.value, key));
2019
+ }
2020
+ return !isEqual(this.originalValue, this.value);
2021
+ }
2022
+ /**
2023
+ * Determine if the object is equivalent to its original state.
2024
+ *
2025
+ * @param {string} [key] Optional key to check specifically
2026
+ * @returns {boolean} True if clean, false otherwise
2027
+ */
2028
+ isClean(key) {
2029
+ return !this.isDirty(key);
2030
+ }
2031
+ /**
2032
+ * Get the attributes that have been modified.
2033
+ *
2034
+ * @returns {Partial<T>} The dirty attributes
2035
+ */
2036
+ getDirty() {
2037
+ return diff(this.originalValue, this.value);
2038
+ }
2039
+ /**
2040
+ * Get a value by dot notation.
2041
+ *
2042
+ * @param {string} key The key to retrieve
2043
+ * @param {unknown} [defaultValue=null] The default value if not found
2044
+ * @returns {unknown} The retrieved value
2045
+ */
2046
+ dataGet(key, defaultValue = null) {
2047
+ return data_get(this.value, key, defaultValue);
2048
+ }
2049
+ /**
2050
+ * Set a value by dot notation.
2051
+ *
2052
+ * @param {string} key The key to set
2053
+ * @param {unknown} value The value to set
2054
+ * @returns {this} The Objectable instance
2055
+ */
2056
+ dataSet(key, value2) {
2057
+ data_set(this.value, key, value2);
2058
+ return this;
2059
+ }
2060
+ /**
2061
+ * Get only specified keys.
2062
+ *
2063
+ * @param {K[]} keys The keys to include
2064
+ * @returns {Objectable<Pick<T, K>>} A new Objectable instance
2065
+ */
2066
+ only(keys) {
2067
+ const result = {};
2068
+ keys.forEach((key) => {
2069
+ const k = key;
2070
+ if (k in this.value) {
2071
+ result[k] = this.value[k];
2072
+ }
2073
+ });
2074
+ return new _Objectable(result);
2075
+ }
2076
+ /**
2077
+ * Get all keys except specified ones.
2078
+ *
2079
+ * @param {K[]} keys The keys to exclude
2080
+ * @returns {Objectable<Omit<T, K>>} A new Objectable instance
2081
+ */
2082
+ except(keys) {
2083
+ const result = { ...this.value };
2084
+ keys.forEach((key) => {
2085
+ const k = key;
2086
+ delete result[k];
2087
+ });
2088
+ return new _Objectable(result);
2089
+ }
2090
+ /**
2091
+ * Map over object entries.
2092
+ *
2093
+ * @param {Function} callback The callback to execute
2094
+ * @returns {Record<string, U>} The resulting object
2095
+ */
2096
+ map(callback) {
2097
+ const result = {};
2098
+ for (const [key, val] of Object.entries(this.value)) {
2099
+ result[key] = callback(val, key);
2100
+ }
2101
+ return result;
2102
+ }
2103
+ /**
2104
+ * Filter object entries.
2105
+ *
2106
+ * @param {Function} callback The callback to execute
2107
+ * @returns {this} The Objectable instance
2108
+ */
2109
+ filter(callback) {
2110
+ const result = {};
2111
+ for (const [key, val] of Object.entries(this.value)) {
2112
+ if (callback(val, key)) {
2113
+ result[key] = val;
2114
+ }
2115
+ }
2116
+ this.value = result;
2117
+ return this;
2118
+ }
2119
+ /**
2120
+ * Merge with another object.
2121
+ *
2122
+ * @param {U} other The object to merge with
2123
+ * @returns {Objectable<T & U>} A new Objectable instance
2124
+ */
2125
+ merge(other) {
2126
+ return new _Objectable({ ...this.value, ...other });
2127
+ }
2128
+ /**
2129
+ * Deep merge with another object (non-mutating on source).
2130
+ *
2131
+ * @param {Record<string, unknown>} other The object to deep merge with
2132
+ * @returns {this} The Objectable instance
2133
+ */
2134
+ mergeDeep(other) {
2135
+ const merge = (target, source) => {
2136
+ const result = { ...target };
2137
+ for (const key of Object.keys(source)) {
2138
+ const srcVal = source[key];
2139
+ const tgtVal = target[key];
2140
+ if (srcVal !== null && "object" === typeof srcVal && !Array.isArray(srcVal) && tgtVal !== null && "object" === typeof tgtVal && !Array.isArray(tgtVal)) {
2141
+ result[key] = merge(tgtVal, srcVal);
2142
+ } else {
2143
+ result[key] = srcVal;
2144
+ }
2145
+ }
2146
+ return result;
2147
+ };
2148
+ this.value = merge(this.value, other);
2149
+ return this;
2150
+ }
2151
+ /**
2152
+ * Check if object has key.
2153
+ *
2154
+ * @param {string} key The key to check
2155
+ * @returns {boolean} True if key exists
2156
+ */
2157
+ has(key) {
2158
+ return key in this.value;
2159
+ }
2160
+ /**
2161
+ * Get keys.
2162
+ *
2163
+ * @returns {string[]} The object keys
2164
+ */
2165
+ keys() {
2166
+ return Object.keys(this.value);
2167
+ }
2168
+ /**
2169
+ * Get values.
2170
+ *
2171
+ * @returns {unknown[]} The object values
2172
+ */
2173
+ values() {
2174
+ return Object.values(this.value);
2175
+ }
2176
+ /**
2177
+ * Clone the object.
2178
+ *
2179
+ * @returns {Objectable<T>} A new cloned Objectable instance
2180
+ */
2181
+ clone() {
2182
+ return new _Objectable(structuredClone(this.value));
2183
+ }
2184
+ /**
2185
+ * Pipe to a callback.
2186
+ *
2187
+ * @param {Function} callback The callback to execute
2188
+ * @returns {U} The result of the callback
2189
+ */
2190
+ pipe(callback) {
2191
+ return callback(this);
2192
+ }
2193
+ /**
2194
+ * Execute callback if condition is met.
2195
+ *
2196
+ * @param {boolean | Function} condition The condition to check
2197
+ * @param {Function} callback The callback to execute
2198
+ * @returns {this} The Objectable instance
2199
+ */
2200
+ when(condition, callback) {
2201
+ const shouldExecute = "function" === typeof condition ? condition() : condition;
2202
+ if (shouldExecute) {
2203
+ callback(this);
2204
+ }
2205
+ return this;
2206
+ }
2207
+ };
2208
+ var obj = (value2) => {
2209
+ return new Objectable(value2);
2210
+ };
2211
+ var Obj = {
2212
+ /** Create a new Objectable instance */
2213
+ of: (value2) => new Objectable(value2),
2214
+ /** Get object keys */
2215
+ keys: (value2) => Object.keys(value2),
2216
+ /** Get object values */
2217
+ values: (value2) => Object.values(value2),
2218
+ /** Merge objects */
2219
+ merge: (target, ...sources) => Object.assign({}, target, ...sources)
2220
+ };
2221
+
2222
+ // src/str.ts
2223
+ var Stringable = class {
2224
+ constructor(value2) {
2225
+ this.value = String(value2 ?? "");
2226
+ }
2227
+ /**
2228
+ * Get the raw string value
2229
+ *
2230
+ * @returns {string} The raw string
2231
+ */
2232
+ toString() {
2233
+ return this.value;
2234
+ }
2235
+ /**
2236
+ * Alias for toString()
2237
+ *
2238
+ * @returns {string} The raw string
2239
+ */
2240
+ get() {
2241
+ return this.value;
2242
+ }
2243
+ /**
2244
+ * Convert to title case
2245
+ *
2246
+ * @returns {this} The Stringable instance
2247
+ */
2248
+ title() {
2249
+ this.value = titleCase(this.value);
2250
+ return this;
2251
+ }
2252
+ /**
2253
+ * Convert to slug
2254
+ *
2255
+ * @returns {this} The Stringable instance
2256
+ */
2257
+ slug() {
2258
+ this.value = slugify(this.value);
2259
+ return this;
2260
+ }
2261
+ /**
2262
+ * Convert to snake_case
2263
+ *
2264
+ * @returns {this} The Stringable instance
2265
+ */
2266
+ snake() {
2267
+ this.value = snakeCase(this.value);
2268
+ return this;
2269
+ }
2270
+ /**
2271
+ * Convert to kebab-case
2272
+ *
2273
+ * @returns {this} The Stringable instance
2274
+ */
2275
+ kebab() {
2276
+ this.value = kebabCase(this.value);
2277
+ return this;
2278
+ }
2279
+ /**
2280
+ * Convert to camelCase
2281
+ *
2282
+ * @returns {this} The Stringable instance
2283
+ */
2284
+ camel() {
2285
+ this.value = camelCase(this.value);
2286
+ return this;
2287
+ }
2288
+ /**
2289
+ * Convert to StudlyCase
2290
+ *
2291
+ * @returns {this} The Stringable instance
2292
+ */
2293
+ studly() {
2294
+ this.value = studlyCase(this.value);
2295
+ return this;
2296
+ }
2297
+ /**
2298
+ * Limit the string length
2299
+ *
2300
+ * @param {number} size The maximum length
2301
+ * @param {string} [end='…'] The string to append if limited
2302
+ * @returns {this} The Stringable instance
2303
+ */
2304
+ limit(size, end = "\u2026") {
2305
+ this.value = strLimit(this.value, size);
2306
+ if (this.value.endsWith("\u2026") && "\u2026" !== end) {
2307
+ this.value = this.value.slice(0, -1) + end;
2308
+ }
2309
+ return this;
2310
+ }
2311
+ /**
2312
+ * Append a value to the string
2313
+ *
2314
+ * @param {...unknown[]} values The values to append
2315
+ * @returns {this} The Stringable instance
2316
+ */
2317
+ append(...values) {
2318
+ this.value += values.join("");
2319
+ return this;
2320
+ }
2321
+ /**
2322
+ * Prepend a value to the string
2323
+ *
2324
+ * @param {...unknown[]} values The values to prepend
2325
+ * @returns {this} The Stringable instance
2326
+ */
2327
+ prepend(...values) {
2328
+ this.value = values.join("") + this.value;
2329
+ return this;
2330
+ }
2331
+ /**
2332
+ * Cap the string with a value if it doesn't already end with it
2333
+ *
2334
+ * @param {string} cap The string to end with
2335
+ * @returns {this} The Stringable instance
2336
+ */
2337
+ finish(cap) {
2338
+ this.value = strFinish(this.value, cap);
2339
+ return this;
2340
+ }
2341
+ /**
2342
+ * Start the string with a value if it doesn't already start with it
2343
+ *
2344
+ * @param {string} prefix The string to start with
2345
+ * @returns {this} The Stringable instance
2346
+ */
2347
+ start(prefix) {
2348
+ this.value = strStart(this.value, prefix);
2349
+ return this;
2350
+ }
2351
+ /**
2352
+ * Replace the first occurrence of a value
2353
+ *
2354
+ * @param {string | RegExp} search The value to search for
2355
+ * @param {string} replace The value to replace with
2356
+ * @returns {this} The Stringable instance
2357
+ */
2358
+ replace(search, replace) {
2359
+ this.value = this.value.replace(search, replace);
2360
+ return this;
2361
+ }
2362
+ /**
2363
+ * Replace all occurrences of a value
2364
+ *
2365
+ * @param {string | RegExp} search The value to search for
2366
+ * @param {string} replace The value to replace with
2367
+ * @returns {this} The Stringable instance
2368
+ */
2369
+ replaceAll(search, replace) {
2370
+ if ("string" === typeof search) {
2371
+ this.value = this.value.split(search).join(replace);
2372
+ } else {
2373
+ const flags = search.flags.includes("g") ? search.flags : `${search.flags}g`;
2374
+ this.value = this.value.replace(new RegExp(search.source, flags), replace);
2375
+ }
2376
+ return this;
2377
+ }
2378
+ /**
2379
+ * Reverse the string
2380
+ *
2381
+ * @returns {this} The Stringable instance
2382
+ */
2383
+ reverse() {
2384
+ this.value = strReverse(this.value);
2385
+ return this;
2386
+ }
2387
+ /**
2388
+ * Mask a portion of the string
2389
+ *
2390
+ * @param {string} character The masking character
2391
+ * @param {number} index The starting index
2392
+ * @param {number} [length] The number of characters to mask
2393
+ * @returns {this} The Stringable instance
2394
+ */
2395
+ mask(character, index, length) {
2396
+ this.value = strMask(this.value, character, index, length);
2397
+ return this;
2398
+ }
2399
+ /**
2400
+ * Trim the string
2401
+ *
2402
+ * @param {string} [chars] The characters to trim (defaults to whitespace)
2403
+ * @returns {this} The Stringable instance
2404
+ */
2405
+ trim(chars) {
2406
+ if (!chars) {
2407
+ this.value = this.value.trim();
2408
+ } else {
2409
+ const pattern = new RegExp(`^[${chars}]+|[${chars}]+$`, "g");
2410
+ this.value = this.value.replace(pattern, "");
2411
+ }
2412
+ return this;
2413
+ }
2414
+ /**
2415
+ * Convert to lower case
2416
+ *
2417
+ * @returns {this} The Stringable instance
2418
+ */
2419
+ lower() {
2420
+ this.value = this.value.toLowerCase();
2421
+ return this;
2422
+ }
2423
+ /**
2424
+ * Convert to upper case
2425
+ *
2426
+ * @returns {this} The Stringable instance
2427
+ */
2428
+ upper() {
2429
+ this.value = this.value.toUpperCase();
2430
+ return this;
2431
+ }
2432
+ /**
2433
+ * Capitalize the first letter
2434
+ *
2435
+ * @returns {this} The Stringable instance
2436
+ */
2437
+ capitalize() {
2438
+ this.value = capitalize(this.value);
2439
+ return this;
2440
+ }
2441
+ /**
2442
+ * Check if string contains a value
2443
+ *
2444
+ * @param {string | string[]} needles The values to search for
2445
+ * @returns {boolean} True if the string contains any of the values
2446
+ */
2447
+ contains(needles) {
2448
+ if (Array.isArray(needles)) {
2449
+ return strContainsAny(this.value, needles);
2450
+ }
2451
+ return this.value.includes(needles);
2452
+ }
2453
+ /**
2454
+ * Check if string contains all values
2455
+ *
2456
+ * @param {string[]} needles The values to search for
2457
+ * @returns {boolean} True if the string contains all values
2458
+ */
2459
+ containsAll(needles) {
2460
+ return strContainsAll(this.value, needles);
2461
+ }
2462
+ /**
2463
+ * Check if string starts with a value
2464
+ *
2465
+ * @param {string | string[]} needles The values to check
2466
+ * @returns {boolean} True if the string starts with any of the values
2467
+ */
2468
+ startsWith(needles) {
2469
+ if (Array.isArray(needles)) {
2470
+ return needles.some((needle) => this.value.startsWith(needle));
2471
+ }
2472
+ return this.value.startsWith(needles);
2473
+ }
2474
+ /**
2475
+ * Check if string ends with a value
2476
+ *
2477
+ * @param {string | string[]} needles The values to check
2478
+ * @returns {boolean} True if the string ends with any of the values
2479
+ */
2480
+ endsWith(needles) {
2481
+ if (Array.isArray(needles)) {
2482
+ return needles.some((needle) => this.value.endsWith(needle));
2483
+ }
2484
+ return this.value.endsWith(needles);
2485
+ }
2486
+ /**
2487
+ * Execute a callback with the stringable and return the result
2488
+ *
2489
+ * @param {(str: this) => U} callback The callback to execute
2490
+ * @returns {U} The result of the callback
2491
+ */
2492
+ pipe(callback) {
2493
+ return callback(this);
2494
+ }
2495
+ /**
2496
+ * Conditionally execute a callback
2497
+ *
2498
+ * @param {boolean | (() => boolean)} condition The condition to check
2499
+ * @param {(str: this) => void} callback The callback to execute
2500
+ * @returns {this} The Stringable instance
2501
+ */
2502
+ when(condition, callback) {
2503
+ const shouldExecute = "function" === typeof condition ? condition() : condition;
2504
+ if (shouldExecute) {
2505
+ callback(this);
2506
+ }
2507
+ return this;
2508
+ }
2509
+ /**
2510
+ * Execute a callback and return the stringable (for side effects)
2511
+ *
2512
+ * @param {(str: this) => void} callback The callback to execute
2513
+ * @returns {this} The Stringable instance
2514
+ */
2515
+ tap(callback) {
2516
+ callback(this);
2517
+ return this;
2518
+ }
2519
+ };
2520
+ var str = (value2) => {
2521
+ return new Stringable(value2);
2522
+ };
2523
+ var Str = {
2524
+ /**
2525
+ * Create a new fluent stringable instance
2526
+ *
2527
+ * @param {unknown} value The initial string value
2528
+ * @returns {Stringable} A new Stringable instance
2529
+ */
2530
+ of: (value2) => new Stringable(value2),
2531
+ /**
2532
+ * Convert a string to a slug
2533
+ *
2534
+ * @param {string} value The string to slugify
2535
+ * @returns {string} The slugified string
2536
+ */
2537
+ slug: (value2) => slugify(value2),
2538
+ /**
2539
+ * Convert a string to snake_case
2540
+ *
2541
+ * @param {string} value The string to convert
2542
+ * @returns {string} The snake_case string
2543
+ */
2544
+ snake: (value2) => snakeCase(value2),
2545
+ /**
2546
+ * Convert a string to kebab-case
2547
+ *
2548
+ * @param {string} value The string to convert
2549
+ * @returns {string} The kebab-case string
2550
+ */
2551
+ kebab: (value2) => kebabCase(value2),
2552
+ /**
2553
+ * Convert a string to camelCase
2554
+ *
2555
+ * @param {string} value The string to convert
2556
+ * @returns {string} The camelCase string
2557
+ */
2558
+ camel: (value2) => camelCase(value2),
2559
+ /**
2560
+ * Convert a string to StudlyCase
2561
+ *
2562
+ * @param {string} value The string to convert
2563
+ * @returns {string} The StudlyCase string
2564
+ */
2565
+ studly: (value2) => studlyCase(value2),
2566
+ /**
2567
+ * Convert a string to title case
2568
+ *
2569
+ * @param {string} value The string to convert
2570
+ * @returns {string} The title case string
2571
+ */
2572
+ title: (value2) => titleCase(value2),
2573
+ /**
2574
+ * Limit the length of a string
2575
+ *
2576
+ * @param {string} value The string to limit
2577
+ * @param {number} size The maximum length
2578
+ * @param {string} [end='…'] The string to append if limited
2579
+ * @returns {string} The limited string
2580
+ */
2581
+ limit: (value2, size, end = "\u2026") => {
2582
+ const result = strLimit(value2, size);
2583
+ return result.endsWith("\u2026") && "\u2026" !== end ? result.slice(0, -1) + end : result;
2584
+ },
2585
+ /**
2586
+ * Generate a random alphanumeric string
2587
+ *
2588
+ * @param {number} [length=16] The length of the random string
2589
+ * @returns {string} The random string
2590
+ */
2591
+ random: (length = 16) => {
2592
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2593
+ let result = "";
2594
+ for (let i = 0; i < length; i++) {
2595
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
2596
+ }
2597
+ return result;
2598
+ },
2599
+ /**
2600
+ * Generate a UUID (version 4)
2601
+ *
2602
+ * @returns {string} The generated UUID
2603
+ */
2604
+ uuid: () => crypto.randomUUID()
2605
+ };
2606
+
2607
+ // src/validator.ts
2608
+ var import_zod2 = require("zod");
2609
+ var Validator = class {
2610
+ /**
2611
+ * Create a new validation instance
2612
+ *
2613
+ * @param {unknown} data The data to validate
2614
+ * @param {T | z.ZodObject<T>} rules The validation rules (Zod shape or object)
2615
+ * @returns {ValidationInstance<z.ZodObject<T>>} A new ValidationInstance
2616
+ */
2617
+ static make(data, rules) {
2618
+ const schema = rules instanceof import_zod2.z.ZodObject ? rules : import_zod2.z.object(rules);
2619
+ return new ValidationInstance(data, schema);
2620
+ }
2621
+ /**
2622
+ * Validate data against rules and throw if it fails
2623
+ *
2624
+ * @param {unknown} data The data to validate
2625
+ * @param {T | z.ZodObject<T>} rules The validation rules (Zod shape or object)
2626
+ * @returns {z.infer<z.ZodObject<T>>} The validated data
2627
+ * @throws {z.ZodError} If validation fails
2628
+ */
2629
+ static validate(data, rules) {
2630
+ const schema = rules instanceof import_zod2.z.ZodObject ? rules : import_zod2.z.object(rules);
2631
+ return schema.parse(data);
2632
+ }
2633
+ /**
2634
+ * Compare two objects for equality
2635
+ *
2636
+ * @param {unknown} a First object
2637
+ * @param {unknown} b Second object
2638
+ * @returns {boolean} True if the objects are equal
2639
+ */
2640
+ static isEqual(a, b) {
2641
+ return isEqual(a, b);
2642
+ }
2643
+ /**
2644
+ * Get the differences between two objects
2645
+ *
2646
+ * @param {unknown} a First object
2647
+ * @param {unknown} b Second object
2648
+ * @returns {GenericRecord} An object containing the differences
2649
+ */
2650
+ static diff(a, b) {
2651
+ return diff(a, b);
2652
+ }
2653
+ };
2654
+ var ValidationInstance = class {
2655
+ constructor(data, schema) {
2656
+ this.data = data;
2657
+ this.schema = schema;
2658
+ this.result = this.schema.safeParse(this.data);
2659
+ }
2660
+ /**
2661
+ * Check if validation failed
2662
+ *
2663
+ * @returns {boolean} True if validation failed
2664
+ */
2665
+ fails() {
2666
+ return !this.result.success;
2667
+ }
2668
+ /**
2669
+ * Check if validation passed
2670
+ *
2671
+ * @returns {boolean} True if validation passed
2672
+ */
2673
+ passes() {
2674
+ return this.result.success;
2675
+ }
2676
+ /**
2677
+ * Get validation errors
2678
+ *
2679
+ * @returns {Record<string, string[]>} An object with field names as keys and arrays of error messages as values
2680
+ */
2681
+ errors() {
2682
+ if (this.result.success) {
2683
+ return {};
2684
+ }
2685
+ const errors = {};
2686
+ this.result.error.issues.forEach((err) => {
2687
+ const path = err.path.join(".") || "root";
2688
+ if (!errors[path]) {
2689
+ errors[path] = [];
2690
+ }
2691
+ errors[path].push(err.message);
2692
+ });
2693
+ return errors;
2694
+ }
2695
+ /**
2696
+ * Get the first error message for a given field
2697
+ *
2698
+ * @param {string} field The field name
2699
+ * @returns {string | undefined} The first error message or undefined
2700
+ */
2701
+ firstError(field) {
2702
+ const fieldErrors = this.errors()[field];
2703
+ return fieldErrors ? fieldErrors[0] : void 0;
2704
+ }
2705
+ /**
2706
+ * Get the validated data
2707
+ *
2708
+ * @returns {z.infer<T>} The validated data
2709
+ * @throws {Error} If validation failed
2710
+ */
2711
+ validated() {
2712
+ if (!this.result.success) {
2713
+ throw new Error("Validation failed");
2714
+ }
2715
+ return this.result.data;
2716
+ }
2717
+ /**
2718
+ * Get all error messages as a flat array
2719
+ *
2720
+ * @returns {string[]} An array of all error messages
2721
+ */
2722
+ allErrors() {
2723
+ if (this.result.success) {
2724
+ return [];
2725
+ }
2726
+ return this.result.error.issues.map((err) => `${err.path.join(".")}: ${err.message}`);
2727
+ }
2728
+ };
2729
+ var validator = (data, rules) => {
2730
+ return Validator.make(data, rules);
2731
+ };
2732
+
2733
+ // src/pipe.ts
2734
+ function pipe(value2) {
2735
+ return {
2736
+ /**
2737
+ * Pass the value through a callback.
2738
+ *
2739
+ * @param {Function} fn The callback function
2740
+ * @returns {ReturnType<typeof pipe>} A new pipe instance with the result
2741
+ */
2742
+ through(fn) {
2743
+ const result = fn(value2);
2744
+ return pipe(result);
2745
+ },
2746
+ /**
2747
+ * Get the current value of the pipe.
2748
+ *
2749
+ * @returns {T} The current value
2750
+ */
2751
+ value() {
2752
+ return value2;
2753
+ }
2754
+ };
2755
+ }
2756
+ // Annotate the CommonJS export names for ESM import in node:
2757
+ 0 && (module.exports = {
2758
+ ApiResponseSchema,
2759
+ DateSchema,
2760
+ EmailSchema,
2761
+ EnhancedArray,
2762
+ EnhancedMap,
2763
+ NumberHelper,
2764
+ Numberable,
2765
+ Obj,
2766
+ Objectable,
2767
+ PaginatedResponseSchema,
2768
+ PaginationSchema,
2769
+ PhoneSchema,
2770
+ Str,
2771
+ Stringable,
2772
+ UrlSchema,
2773
+ ValidationInstance,
2774
+ Validator,
2775
+ arrayAdd,
2776
+ arrayCollapse,
2777
+ arrayDivide,
2778
+ arrayDot,
2779
+ arrayExcept,
2780
+ arrayFirst,
2781
+ arrayFlatten,
2782
+ arrayGet,
2783
+ arrayGroupBy,
2784
+ arrayHas,
2785
+ arrayOnly,
2786
+ arrayPluck,
2787
+ arrayUnique,
2788
+ arrayWhere,
2789
+ array_chunk,
2790
+ array_column,
2791
+ array_count_values,
2792
+ array_diff,
2793
+ array_filter,
2794
+ array_flip,
2795
+ array_intersect,
2796
+ array_key_exists,
2797
+ array_keys,
2798
+ array_map,
2799
+ array_merge,
2800
+ array_pop,
2801
+ array_product,
2802
+ array_push,
2803
+ array_rand,
2804
+ array_reduce,
2805
+ array_reverse,
2806
+ array_search,
2807
+ array_shift,
2808
+ array_slice,
2809
+ array_splice,
2810
+ array_sum,
2811
+ array_unique,
2812
+ array_unshift,
2813
+ blank,
2814
+ camelCase,
2815
+ capitalize,
2816
+ collect,
2817
+ collectMap,
2818
+ data_get,
2819
+ data_set,
2820
+ dayjs,
2821
+ diff,
2822
+ filled,
2823
+ fromNow,
2824
+ isArray,
2825
+ isBase64,
2826
+ isBetweenDates,
2827
+ isBlank,
2828
+ isBoolean,
2829
+ isDate,
2830
+ isEmail,
2831
+ isEmpty,
2832
+ isEqual,
2833
+ isEven,
2834
+ isFalse,
2835
+ isFloat,
2836
+ isFunction,
2837
+ isFuture,
2838
+ isInteger,
2839
+ isIp,
2840
+ isJson,
2841
+ isMacAddress,
2842
+ isNotEmpty,
2843
+ isNull,
2844
+ isNumber,
2845
+ isNumeric,
2846
+ isObject,
2847
+ isOdd,
2848
+ isPast,
2849
+ isPresent,
2850
+ isRecord,
2851
+ isSet,
2852
+ isString,
2853
+ isToday,
2854
+ isTrue,
2855
+ isUndefined,
2856
+ isUrl,
2857
+ isUuid,
2858
+ kebabCase,
2859
+ mapToObject,
2860
+ normalizeString,
2861
+ now,
2862
+ num,
2863
+ numberFormat,
2864
+ obj,
2865
+ objectToMap,
2866
+ optional,
2867
+ php_array,
2868
+ pipe,
2869
+ range,
2870
+ retry,
2871
+ rsort,
2872
+ safeValidateSchema,
2873
+ shuffle,
2874
+ slugify,
2875
+ snakeCase,
2876
+ sort,
2877
+ str,
2878
+ strContainsAll,
2879
+ strContainsAny,
2880
+ strFinish,
2881
+ strLimit,
2882
+ strMask,
2883
+ strPadBoth,
2884
+ strPadLeft,
2885
+ strPadRight,
2886
+ strRemove,
2887
+ strReverse,
2888
+ strStart,
2889
+ strWordCount,
2890
+ strWords,
2891
+ studlyCase,
2892
+ tap,
2893
+ throw_if,
2894
+ throw_unless,
2895
+ titleCase,
2896
+ today,
2897
+ tomorrow,
2898
+ uasort,
2899
+ uksort,
2900
+ usort,
2901
+ validateSchema,
2902
+ validator,
2903
+ value,
2904
+ when,
2905
+ yesterday
2906
+ });