@h3ravel/support 0.12.0 → 0.14.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.
package/dist/index.cjs CHANGED
@@ -37,138 +37,44 @@ let util = require("util");
37
37
  util = __toESM(util);
38
38
  let dayjs = require("dayjs");
39
39
  dayjs = __toESM(dayjs);
40
- let dayjs_plugin_advancedFormat = require("dayjs/plugin/advancedFormat");
41
- dayjs_plugin_advancedFormat = __toESM(dayjs_plugin_advancedFormat);
42
- let dayjs_plugin_customParseFormat = require("dayjs/plugin/customParseFormat");
43
- dayjs_plugin_customParseFormat = __toESM(dayjs_plugin_customParseFormat);
44
- let dayjs_plugin_dayOfYear = require("dayjs/plugin/dayOfYear");
45
- dayjs_plugin_dayOfYear = __toESM(dayjs_plugin_dayOfYear);
46
- let dayjs_plugin_isBetween = require("dayjs/plugin/isBetween");
47
- dayjs_plugin_isBetween = __toESM(dayjs_plugin_isBetween);
48
- let dayjs_plugin_isLeapYear = require("dayjs/plugin/isLeapYear");
49
- dayjs_plugin_isLeapYear = __toESM(dayjs_plugin_isLeapYear);
50
- let dayjs_plugin_relativeTime = require("dayjs/plugin/relativeTime");
51
- dayjs_plugin_relativeTime = __toESM(dayjs_plugin_relativeTime);
52
- let dayjs_plugin_timezone = require("dayjs/plugin/timezone");
53
- dayjs_plugin_timezone = __toESM(dayjs_plugin_timezone);
54
- let dayjs_plugin_utc = require("dayjs/plugin/utc");
55
- dayjs_plugin_utc = __toESM(dayjs_plugin_utc);
40
+ let dayjs_plugin_advancedFormat_js = require("dayjs/plugin/advancedFormat.js");
41
+ dayjs_plugin_advancedFormat_js = __toESM(dayjs_plugin_advancedFormat_js);
42
+ let dayjs_plugin_customParseFormat_js = require("dayjs/plugin/customParseFormat.js");
43
+ dayjs_plugin_customParseFormat_js = __toESM(dayjs_plugin_customParseFormat_js);
44
+ let dayjs_plugin_dayOfYear_js = require("dayjs/plugin/dayOfYear.js");
45
+ dayjs_plugin_dayOfYear_js = __toESM(dayjs_plugin_dayOfYear_js);
46
+ let dayjs_plugin_isBetween_js = require("dayjs/plugin/isBetween.js");
47
+ dayjs_plugin_isBetween_js = __toESM(dayjs_plugin_isBetween_js);
48
+ let dayjs_plugin_isLeapYear_js = require("dayjs/plugin/isLeapYear.js");
49
+ dayjs_plugin_isLeapYear_js = __toESM(dayjs_plugin_isLeapYear_js);
50
+ let dayjs_plugin_relativeTime_js = require("dayjs/plugin/relativeTime.js");
51
+ dayjs_plugin_relativeTime_js = __toESM(dayjs_plugin_relativeTime_js);
52
+ let dayjs_plugin_timezone_js = require("dayjs/plugin/timezone.js");
53
+ dayjs_plugin_timezone_js = __toESM(dayjs_plugin_timezone_js);
54
+ let dayjs_plugin_utc_js = require("dayjs/plugin/utc.js");
55
+ dayjs_plugin_utc_js = __toESM(dayjs_plugin_utc_js);
56
56
 
57
- //#region src/Helpers/Arr.ts
58
- var Arr_exports = /* @__PURE__ */ __export({
59
- alternate: () => alternate,
60
- chunk: () => chunk,
61
- collapse: () => collapse,
62
- combine: () => combine,
63
- find: () => find,
64
- first: () => first,
65
- flatten: () => flatten,
66
- forget: () => forget,
67
- isEmpty: () => isEmpty,
68
- isNotEmpty: () => isNotEmpty,
69
- last: () => last,
70
- pop: () => pop,
71
- prepend: () => prepend,
72
- range: () => range,
73
- reverse: () => reverse,
74
- shift: () => shift,
75
- take: () => take
76
- });
77
- /**
78
- * Splits an array into chunks of a specified size.
79
- *
80
- * @template T - Type of elements in the array
81
- * @param arr - The input array
82
- * @param size - Size of each chunk (default: 2)
83
- * @returns An array of chunks (arrays)
84
- */
85
- const chunk = (arr, size = 2) => {
86
- if (size <= 0) throw new Error("Chunk size must be greater than 0");
87
- const chunks = [];
88
- for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size));
89
- return chunks;
90
- };
91
- /**
92
- * Collapse an array of arrays into a single array.
93
- */
94
- const collapse = (arr) => {
95
- const result = [];
96
- for (const item of arr) if (Array.isArray(item)) result.push(...item);
97
- else result.push(item);
98
- return result;
99
- };
57
+ //#region src/Exceptions/InvalidArgumentException.ts
100
58
  /**
101
- * Alternates between two arrays, creating a zipped result.
59
+ * Custom error for invalid type coercion
102
60
  */
103
- const alternate = (a, b) => {
104
- const result = [];
105
- const max = Math.max(a.length, b.length);
106
- for (let i = 0; i < max; i++) {
107
- if (i < a.length) result.push(a[i]);
108
- if (i < b.length) result.push(b[i]);
61
+ var InvalidArgumentException = class extends Error {
62
+ constructor(message) {
63
+ super(message);
64
+ this.name = "InvalidArgumentException";
109
65
  }
110
- return result;
111
- };
112
- /**
113
- * Combine arrays and sum their values element by element.
114
- */
115
- const combine = (...arr) => {
116
- const maxLength = Math.max(...arr.map((a) => a.length));
117
- const result = new Array(maxLength).fill(0);
118
- for (let i = 0; i < maxLength; i++) for (const array of arr) result[i] += array[i] || 0;
119
- return result;
120
- };
121
- /** Find the value associated with a given key. */
122
- const find = (key, arr) => arr.find((item) => item === key) || null;
123
- /** Returns a new array without the given indices. */
124
- const forget = (arr, keys) => arr.filter((_, i) => !keys.includes(i));
125
- /** Remove the first element and return tuple [el, rest]. */
126
- const first = (arr) => {
127
- if (!arr.length) throw new Error("Cannot shift from empty array");
128
- return [arr[0], arr.slice(1)];
129
66
  };
130
- /** Remove the last element and return tuple [el, rest]. */
131
- const last = (arr) => {
132
- if (!arr.length) throw new Error("Cannot pop from empty array");
133
- return [arr[arr.length - 1], arr.slice(0, -1)];
134
- };
135
- /** Check if array is empty. */
136
- const isEmpty = (arr) => {
137
- if (arr.length === 0) return true;
138
- else return false;
139
- };
140
- /** Check if array is empty. */
141
- const isNotEmpty = (arr) => arr.length > 0;
142
- /** Pop the element off the end of array. */
143
- const pop = (arr) => arr.slice(0, -1);
144
- /** Add elements to the beginning of array. */
145
- const prepend = (arr, ...elements) => [...elements, ...arr];
146
- /** Take first n elements of array. */
147
- const take = (amount, arr) => arr.slice(0, Math.max(0, amount));
148
- /** Create a new array in reverse order. */
149
- const reverse = (arr) => [...arr].reverse();
150
- /** Alias for first element removal. */
151
- const shift = first;
67
+
68
+ //#endregion
69
+ //#region src/Exceptions/RuntimeException.ts
152
70
  /**
153
- * Generates an array of sequential numbers.
154
- *
155
- * @param size - Number of elements in the range
156
- * @param startAt - Starting number (default: 0)
157
- * @returns An array of numbers from startAt to startAt + size - 1
71
+ * Custom error for invalid type coercion
158
72
  */
159
- const range = (size, startAt = 0) => {
160
- if (size <= 0 || !Number.isFinite(size)) return [];
161
- return Array.from({ length: size }, (_, i) => startAt + i);
162
- };
163
- /** Flatten multi-dimensional arrays into single level. */
164
- const flatten = (arr) => {
165
- const result = [];
166
- const recurse = (input) => {
167
- for (const item of input) if (Array.isArray(item)) recurse(item);
168
- else result.push(item);
169
- };
170
- recurse(arr);
171
- return result;
73
+ var RuntimeException = class extends Error {
74
+ constructor(message) {
75
+ super(message);
76
+ this.name = "RuntimeException";
77
+ }
172
78
  };
173
79
 
174
80
  //#endregion
@@ -335,10 +241,10 @@ const verifyChecksum = (data, expectedChecksum, algorithm = "sha256") => {
335
241
  * @param shift - Number of positions to shift (default: 13)
336
242
  * @returns Encrypted/decrypted text
337
243
  */
338
- const caesarCipher = (text, shift$1 = 13) => {
244
+ const caesarCipher = (text, shift = 13) => {
339
245
  return text.replace(/[a-zA-Z]/g, (char) => {
340
246
  const baseCharCode = char === char.toUpperCase() ? "A" : "a";
341
- const shiftedCharCode = (char.charCodeAt(0) - baseCharCode.charCodeAt(0) + shift$1) % 26;
247
+ const shiftedCharCode = (char.charCodeAt(0) - baseCharCode.charCodeAt(0) + shift) % 26;
342
248
  const newCharCode = (shiftedCharCode < 0 ? 26 + shiftedCharCode : shiftedCharCode) + baseCharCode.charCodeAt(0);
343
249
  return String.fromCharCode(newCharCode);
344
250
  });
@@ -550,22 +456,27 @@ const toHumanTime = (seconds = 0, worded = false) => {
550
456
  if (secs || !hours && !minutes) parts.push(`${secs}sec`);
551
457
  return parts.join(" ");
552
458
  }
553
- const hh = hours > 0 ? `${hours}:` : "";
554
- const mm = (hours > 0 && minutes < 10 ? `0${minutes}` : minutes) + ":";
555
- const ss = secs < 10 ? `0${secs}` : secs;
556
- return `${hh}${mm}${ss}`;
459
+ return `${hours > 0 ? `${hours}:` : ""}${(hours > 0 && minutes < 10 ? `0${minutes}` : minutes) + ":"}${secs < 10 ? `0${secs}` : secs}`;
557
460
  };
558
461
 
559
462
  //#endregion
560
463
  //#region src/Helpers/Obj.ts
561
464
  var Obj_exports = /* @__PURE__ */ __export({
465
+ Obj: () => Obj,
466
+ data_fill: () => data_fill,
467
+ data_forget: () => data_forget,
468
+ data_get: () => data_get,
469
+ data_set: () => data_set,
562
470
  dot: () => dot,
563
471
  extractProperties: () => extractProperties,
564
472
  getValue: () => getValue,
565
473
  modObj: () => modObj,
566
474
  safeDot: () => safeDot,
567
475
  setNested: () => setNested,
568
- slugifyKeys: () => slugifyKeys
476
+ slugifyKeys: () => slugifyKeys,
477
+ toCssClasses: () => toCssClasses,
478
+ toCssStyles: () => toCssStyles,
479
+ undot: () => undot
569
480
  });
570
481
  /**
571
482
  * Flattens a nested object into a single-level object
@@ -639,74 +550,1119 @@ const getValue = (key, item) => {
639
550
  if (child !== void 0) return String(item?.[parent]?.[child] ?? item?.[parent] ?? `${String(parent)}.${String(child)}`);
640
551
  return String(item?.[parent] ?? parent);
641
552
  }
642
- return String(item?.[key] ?? key);
643
- };
644
- /**
645
- * Maps over an object's entries and returns a new object
646
- * with transformed keys and/or values.
647
- *
648
- * @template T - Type of the input object
649
- * @template R - Type of the new values
650
- * @param obj - The object to transform
651
- * @param callback - Function that receives [key, value] and returns [newKey, newValue]
652
- * @returns A new object with transformed entries
653
- */
654
- const modObj = (obj, callback) => {
655
- return Object.fromEntries(Object.entries(obj).map(([key, value]) => callback([key, value])));
656
- };
657
- function safeDot(data, key) {
658
- if (!key) return data;
659
- return key.split(".").reduce((acc, k) => acc?.[k], data);
660
- }
661
- /**
662
- * Sets a nested property on an object using dot notation.
663
- *
664
- * @example
665
- * const obj = {}
666
- * setNested(obj, 'app.user.name', 'Legacy')
667
- * console.log(obj)
668
- * // Output: { app: { user: { name: 'Legacy' } } }
669
- *
670
- * @param obj - The target object to modify.
671
- * @param key - The dot-separated key (e.g., 'app.user.name').
672
- * @param value - The value to set at the specified path.
673
- */
674
- const setNested = (obj, key, value) => {
675
- if (!key.includes(".")) {
676
- obj[key] = value;
677
- return;
553
+ return String(item?.[key] ?? key);
554
+ };
555
+ /**
556
+ * Maps over an object's entries and returns a new object
557
+ * with transformed keys and/or values.
558
+ *
559
+ * @template T - Type of the input object
560
+ * @template R - Type of the new values
561
+ * @param obj - The object to transform
562
+ * @param callback - Function that receives [key, value] and returns [newKey, newValue]
563
+ * @returns A new object with transformed entries
564
+ */
565
+ const modObj = (obj, callback) => {
566
+ return Object.fromEntries(Object.entries(obj).map(([key, value]) => callback([key, value])));
567
+ };
568
+ function safeDot(data, key) {
569
+ if (!key) return data;
570
+ return key.split(".").reduce((acc, k) => acc?.[k], data);
571
+ }
572
+ /**
573
+ * Sets a nested property on an object using dot notation.
574
+ *
575
+ * @example
576
+ * const obj = {}
577
+ * setNested(obj, 'app.user.name', 'Legacy')
578
+ * console.log(obj)
579
+ * // Output: { app: { user: { name: 'Legacy' } } }
580
+ *
581
+ * @param obj - The target object to modify.
582
+ * @param key - The dot-separated key (e.g., 'app.user.name').
583
+ * @param value - The value to set at the specified path.
584
+ */
585
+ const setNested = (obj, key, value) => {
586
+ if (!key.includes(".")) {
587
+ obj[key] = value;
588
+ return;
589
+ }
590
+ const parts = key.split(".");
591
+ let current = obj;
592
+ for (let i = 0; i < parts.length; i++) {
593
+ const part = parts[i];
594
+ /**
595
+ * If we're at the last key, assign the value
596
+ */
597
+ if (i === parts.length - 1) current[part] = value;
598
+ else {
599
+ /**
600
+ * If the key doesn't exist or isn't an object, create it
601
+ */
602
+ if (typeof current[part] !== "object" || current[part] === null) current[part] = {};
603
+ current = current[part];
604
+ }
605
+ }
606
+ };
607
+ /**
608
+ * Converts object keys to a slugified format (e.g., snake_case).
609
+ *
610
+ * @template T - Type of the input object
611
+ * @param obj - The object whose keys will be slugified
612
+ * @param only - Optional array of keys to slugify (others remain unchanged)
613
+ * @param separator - Separator for slugified keys (default: "_")
614
+ * @returns A new object with slugified keys
615
+ */
616
+ const slugifyKeys = (obj, only = [], separator = "_") => {
617
+ const slugify = (key) => key.replace(/([a-z])([A-Z])/g, `$1${separator}$2`).replace(/[\s\W]+/g, separator).replace(new RegExp(`${separator}{2,}`, "g"), separator).replace(new RegExp(`^${separator}|${separator}$`, "g"), "").toLowerCase();
618
+ let entries = Object.entries(obj);
619
+ if (only.length) entries = entries.filter(([key]) => only.includes(key));
620
+ return Object.fromEntries(entries.map(([key, value]) => [slugify(key), value]));
621
+ };
622
+ /**
623
+ * toCssClasses
624
+ *
625
+ * Convert array/object/string input into a CSS class string.
626
+ * - Arrays: included if truthy
627
+ * - Objects: keys included if value is truthy
628
+ * - Strings: included as-is
629
+ */
630
+ function toCssClasses(input) {
631
+ if (!input) return "";
632
+ const classes = [];
633
+ if (typeof input === "string") return input.trim();
634
+ if (Array.isArray(input)) input.forEach((item) => {
635
+ if (item) classes.push(String(item).trim());
636
+ });
637
+ else if (typeof input === "object") {
638
+ for (const [key, value] of Object.entries(input)) if (value) classes.push(key);
639
+ }
640
+ return classes.join(" ");
641
+ }
642
+ /**
643
+ * toCssStyles
644
+ *
645
+ * Convert object input into CSS style string.
646
+ * - Only includes truthy values (ignores null/undefined/false)
647
+ */
648
+ function toCssStyles(styles) {
649
+ const parts = [];
650
+ for (const [k, v] of Object.entries(styles)) {
651
+ if (v === null || v === void 0 || v === false) continue;
652
+ parts.push(`${k}:${v}`);
653
+ }
654
+ return parts.join(";");
655
+ }
656
+ /**
657
+ * undot
658
+ *
659
+ * Convert a dot-notated object back into nested structure.
660
+ *
661
+ * Example:
662
+ * undot({ 'a.b': 1, 'c.0': 2 }) -> { a: { b: 1 }, c: [2] }
663
+ */
664
+ function undot(obj) {
665
+ const result = {};
666
+ for (const [key, value] of Object.entries(obj)) {
667
+ const parts = key.split(".");
668
+ let node = result;
669
+ for (let i = 0; i < parts.length; i++) {
670
+ const part = parts[i];
671
+ const isLast = i === parts.length - 1;
672
+ const nextPart = parts[i + 1];
673
+ const isArrayIndex = !isNaN(Number(nextPart));
674
+ if (isLast) node[part] = value;
675
+ else {
676
+ if (!(part in node)) node[part] = isArrayIndex ? [] : {};
677
+ node = node[part];
678
+ }
679
+ }
680
+ }
681
+ return result;
682
+ }
683
+ /**
684
+ * data_get
685
+ *
686
+ * Get a value from an object using dot notation.
687
+ */
688
+ function data_get(obj, path, defaultValue) {
689
+ if (!obj) return defaultValue;
690
+ const parts = Array.isArray(path) ? path : path.split(".");
691
+ let current = obj;
692
+ for (const part of parts) {
693
+ if (!current || !(part in current)) return defaultValue;
694
+ current = current[part];
695
+ }
696
+ return current;
697
+ }
698
+ /**
699
+ * data_set
700
+ *
701
+ * Set a value in an object using dot notation. Mutates the object.
702
+ */
703
+ function data_set(obj, path, value) {
704
+ const parts = Array.isArray(path) ? path : path.split(".");
705
+ let current = obj;
706
+ for (let i = 0; i < parts.length; i++) {
707
+ const part = parts[i];
708
+ if (i === parts.length - 1) current[part] = value;
709
+ else {
710
+ if (!(part in current) || typeof current[part] !== "object" || current[part] === null) current[part] = {};
711
+ current = current[part];
712
+ }
713
+ }
714
+ }
715
+ /**
716
+ * data_fill
717
+ *
718
+ * Like data_set, but only sets the value if the key does NOT exist.
719
+ */
720
+ function data_fill(obj, path, value) {
721
+ if (data_get(obj, path) === void 0) data_set(obj, path, value);
722
+ }
723
+ /**
724
+ * data_forget
725
+ *
726
+ * Remove a key from an object using dot notation.
727
+ */
728
+ function data_forget(obj, path) {
729
+ const parts = Array.isArray(path) ? path : path.split(".");
730
+ let current = obj;
731
+ for (let i = 0; i < parts.length; i++) {
732
+ const part = parts[i];
733
+ if (i === parts.length - 1) delete current[part];
734
+ else {
735
+ if (!current[part] || typeof current[part] !== "object") break;
736
+ current = current[part];
737
+ }
738
+ }
739
+ }
740
+ var Obj = class Obj {
741
+ /**
742
+ * Check if the value is a non-null object (associative/accessible).
743
+ */
744
+ static accessible(value) {
745
+ return value !== null && typeof value === "object";
746
+ }
747
+ /**
748
+ * Add a key-value pair to an object only if the key does not already exist.
749
+ *
750
+ * Returns a new object (does not mutate original).
751
+ */
752
+ static add(obj, key, value) {
753
+ if (!(key in obj)) return {
754
+ ...obj,
755
+ [key]: value
756
+ };
757
+ return obj;
758
+ }
759
+ /**
760
+ * Split object into [keys, values]
761
+ */
762
+ static divide(obj) {
763
+ return [Object.keys(obj), Object.values(obj)];
764
+ }
765
+ /**
766
+ * Check if a key exists in the object.
767
+ */
768
+ static exists(obj, key) {
769
+ return Object.prototype.hasOwnProperty.call(obj, key);
770
+ }
771
+ /**
772
+ * Get a value from an object using dot notation.
773
+ *
774
+ * Example:
775
+ * Obj.get({a:{b:1}}, 'a.b') -> 1
776
+ */
777
+ static get(obj, path, defaultValue) {
778
+ if (!Obj.accessible(obj)) return defaultValue;
779
+ const parts = Array.isArray(path) ? path : path.split(".");
780
+ let current = obj;
781
+ for (const part of parts) {
782
+ if (!Obj.accessible(current) || !(part in current)) return defaultValue;
783
+ current = current[part];
784
+ }
785
+ return current;
786
+ }
787
+ /**
788
+ * Check if the object has a given key or keys (dot notation supported).
789
+ */
790
+ static has(obj, keys) {
791
+ if (!Obj.accessible(obj)) return false;
792
+ return (Array.isArray(keys) ? keys : [keys]).every((key) => {
793
+ const parts = key.split(".");
794
+ let current = obj;
795
+ for (const part of parts) {
796
+ if (!Obj.accessible(current) || !(part in current)) return false;
797
+ current = current[part];
798
+ }
799
+ return true;
800
+ });
801
+ }
802
+ /**
803
+ * Check if an object is associative (has at least one non-numeric key).
804
+ */
805
+ static isAssoc(obj) {
806
+ if (!Obj.accessible(obj)) return false;
807
+ return Object.keys(obj).some((k) => isNaN(Number(k)));
808
+ }
809
+ /**
810
+ * Add a prefix to all keys of the object.
811
+ */
812
+ static prependKeysWith(obj, prefix) {
813
+ if (!Obj.accessible(obj)) return {};
814
+ const result = {};
815
+ for (const [k, v] of Object.entries(obj)) result[`${prefix}${k}`] = v;
816
+ return result;
817
+ }
818
+ /**
819
+ * Convert an object into a URL query string.
820
+ *
821
+ * Nested objects/arrays are flattened using bracket notation.
822
+ */
823
+ static query(obj) {
824
+ const encode = encodeURIComponent;
825
+ const parts = [];
826
+ function build(key, value) {
827
+ if (Array.isArray(value)) value.forEach((v, i) => build(`${key}[${i}]`, v));
828
+ else if (Obj.accessible(value)) Object.entries(value).forEach(([k, v]) => build(`${key}[${k}]`, v));
829
+ else parts.push(`${encode(key)}=${encode(value)}`);
830
+ }
831
+ Object.entries(obj).forEach(([k, v]) => build(k, v));
832
+ return parts.join("&");
833
+ }
834
+ };
835
+
836
+ //#endregion
837
+ //#region src/Helpers/Arr.ts
838
+ /**
839
+ * Arr — Laravel-like array helpers for JavaScript.
840
+ *
841
+ * - Methods aim for clear, predictable JS behavior.
842
+ * - Inputs are validated where useful; functions try not to mutate arguments.
843
+ */
844
+ var Arr = class Arr {
845
+ /**
846
+ * Helper: is a value an object (but not null).
847
+ */
848
+ static _isObject(value) {
849
+ return value !== null && typeof value === "object" && !Array.isArray(value);
850
+ }
851
+ /**
852
+ * Helper: deep clone for safety (simple).
853
+ * Uses JSON methods — good for typical data shapes (no functions, Dates, Maps).
854
+ */
855
+ static _clone(value) {
856
+ try {
857
+ return JSON.parse(JSON.stringify(value));
858
+ } catch {
859
+ return value;
860
+ }
861
+ }
862
+ /**
863
+ * Retrieve a value using dot notation
864
+ * Throws if value is not an array
865
+ */
866
+ static array(obj, path, defaultValue) {
867
+ const val = data_get(obj, path, defaultValue);
868
+ if (!Array.isArray(val)) throw new InvalidArgumentException(`Value at "${path}" is not an array.`);
869
+ return val;
870
+ }
871
+ /**
872
+ * Retrieve a value using dot notation
873
+ * Throws if value is not a boolean
874
+ */
875
+ static boolean(obj, path, defaultValue) {
876
+ const val = data_get(obj, path, defaultValue);
877
+ if (typeof val !== "boolean") throw new InvalidArgumentException(`Value at "${path}" is not a boolean.`);
878
+ return val;
879
+ }
880
+ /**
881
+ * Flatten an array of arrays by one level.
882
+ *
883
+ * Example:
884
+ * Arr.collapse([[1,2], [3], 4]) -> [1,2,3,4]
885
+ */
886
+ static collapse(array) {
887
+ if (!Array.isArray(array)) return [];
888
+ const result = [];
889
+ for (const item of array) if (Array.isArray(item)) result.push(...item);
890
+ else result.push(item);
891
+ return result;
892
+ }
893
+ /**
894
+ * Cartesian product of arrays.
895
+ *
896
+ * Example:
897
+ * Arr.crossJoin([1,2], ['a','b']) -> [[1,'a'], [1,'b'], [2,'a'], [2,'b']]
898
+ *
899
+ * Accepts any number of array arguments (or single array-of-arrays).
900
+ */
901
+ static crossJoin(...arrays) {
902
+ let inputs = arrays;
903
+ if (arrays.length === 1 && Array.isArray(arrays[0]) && arrays[0].some(Array.isArray)) inputs = arrays[0];
904
+ inputs = inputs.map((a) => Array.isArray(a) ? a : [a]);
905
+ let product = [[]];
906
+ for (const arr of inputs) {
907
+ const next = [];
908
+ for (const prefix of product) for (const value of arr) next.push([...prefix, value]);
909
+ product = next;
910
+ }
911
+ return product;
912
+ }
913
+ /**
914
+ * Split an array (or object) into two arrays: [keys, values].
915
+ *
916
+ * For arrays, keys are numeric indices. For objects, keys are property names.
917
+ *
918
+ * Example:
919
+ * Arr.divide(['a','b']) -> [[0,1], ['a','b']]
920
+ * Arr.divide({x:1,y:2}) -> [['x','y'], [1,2]]
921
+ */
922
+ static divide(input) {
923
+ if (Array.isArray(input)) return [input.map((_, i) => i), input.slice()];
924
+ if (Arr._isObject(input)) {
925
+ const keys = Object.keys(input);
926
+ return [keys, keys.map((k) => input[k])];
927
+ }
928
+ return [[], []];
929
+ }
930
+ /**
931
+ * Flatten a nested array/object structure into a single-level object
932
+ * with dot-notated keys.
933
+ *
934
+ * Example:
935
+ * Arr.dot({ a: { b: 1 }, c: [2,3] }) -> { 'a.b': 1, 'c.0': 2, 'c.1': 3 }
936
+ *
937
+ * Works for arrays and plain objects.
938
+ */
939
+ static dot(input, prefix = "") {
940
+ const result = {};
941
+ const recurse = (val, path) => {
942
+ if (Array.isArray(val)) for (let i = 0; i < val.length; i++) recurse(val[i], path ? `${path}.${i}` : String(i));
943
+ else if (Arr._isObject(val)) for (const [k, v] of Object.entries(val)) recurse(v, path ? `${path}.${k}` : k);
944
+ else result[path] = val;
945
+ };
946
+ if (Array.isArray(input) || Arr._isObject(input)) recurse(input, prefix);
947
+ return result;
948
+ }
949
+ /**
950
+ * Checks if all elements satisfy the predicate
951
+ */
952
+ static every(array, predicate) {
953
+ return array.every(predicate);
954
+ }
955
+ /**
956
+ * Remove items by keys/indices from an array or properties from an object.
957
+ *
958
+ * For arrays: keys are numeric indices (single number or array of numbers).
959
+ *
960
+ * Returns a shallow-copied result (does not mutate input).
961
+ *
962
+ * Example:
963
+ * Arr.except([10,20,30], [1]) -> [10,30]
964
+ */
965
+ static except(input, keys) {
966
+ const keySet = new Set(Array.isArray(keys) ? keys : [keys]);
967
+ if (Array.isArray(input)) return input.filter((_, idx) => !keySet.has(idx));
968
+ if (Arr._isObject(input)) {
969
+ const out = {};
970
+ for (const [k, v] of Object.entries(input)) if (!keySet.has(k)) out[k] = v;
971
+ return out;
972
+ }
973
+ return input;
974
+ }
975
+ /**
976
+ * Return the first element of an array that satisfies the predicate,
977
+ * or the first element if no predicate is provided, otherwise the defaultValue.
978
+ *
979
+ * Predicate can be true (boolean), a function or a value to match (strict equality).
980
+ *
981
+ * When predicate is true (boolean), the first element will be removed and a tuple will be returned [el, rest].
982
+ *
983
+ * @param array
984
+ * @param predicate
985
+ * @param defaultValue
986
+ *
987
+ * @returns
988
+ */
989
+ static first(array, predicate, defaultValue) {
990
+ if (predicate === true) {
991
+ if (!array.length) throw new Error("Cannot shift from empty array");
992
+ return [array[0], array.slice(1)];
993
+ }
994
+ if (!Array.isArray(array) || array.length === 0) return defaultValue;
995
+ if (predicate === void 0) return array[0];
996
+ if (typeof predicate === "function") {
997
+ for (const item of array) if (predicate(item)) return item;
998
+ return defaultValue;
999
+ }
1000
+ for (const item of array) if (typeof predicate !== "boolean" && item === predicate) return item;
1001
+ return defaultValue;
1002
+ }
1003
+ /**
1004
+ * Recursively flatten an array up to `depth` levels (default: Infinity).
1005
+ *
1006
+ * Example:
1007
+ * Arr.flatten([1, [2, [3]]], 1) -> [1,2,[3]]
1008
+ */
1009
+ static flatten(array, depth = Infinity) {
1010
+ if (!Array.isArray(array)) return [];
1011
+ if (depth < 1) return array.slice();
1012
+ const result = [];
1013
+ for (const item of array) if (Array.isArray(item) && depth > 0) result.push(...Arr.flatten(item, depth - 1));
1014
+ else result.push(item);
1015
+ return result;
1016
+ }
1017
+ /**
1018
+ * Retrieve a value from an array/object using dot notation
1019
+ * Throws if value is not a float
1020
+ */
1021
+ static float(obj, path, defaultValue) {
1022
+ const val = data_get(obj, path, defaultValue);
1023
+ if (typeof val !== "number" || Number.isNaN(val)) throw new InvalidArgumentException(`Value at "${path}" is not a float.`);
1024
+ return val;
1025
+ }
1026
+ /**
1027
+ * Remove element(s) by index or dot-notated path from an array/object.
1028
+ *
1029
+ * For arrays: accepts numeric index or array of indices. Returns a new array.
1030
+ *
1031
+ * For objects: supports dot notation to remove nested keys.
1032
+ *
1033
+ * Example:
1034
+ * Arr.forget([1,2,3], 1) -> [1,3]
1035
+ * Arr.forget({a:{b:1}}, 'a.b') -> { a: {} }
1036
+ */
1037
+ static forget(input, keys) {
1038
+ if (Array.isArray(input)) {
1039
+ const removeSet = new Set(Array.isArray(keys) ? keys : [keys]);
1040
+ return input.filter((_, i) => !removeSet.has(i));
1041
+ }
1042
+ if (Arr._isObject(input)) {
1043
+ const out = Arr._clone(input);
1044
+ const keyList = Array.isArray(keys) ? keys : [keys];
1045
+ for (const key of keyList) {
1046
+ const parts = String(key).split(".");
1047
+ let node = out;
1048
+ for (let i = 0; i < parts.length; i++) {
1049
+ const part = parts[i];
1050
+ if (i === parts.length - 1) {
1051
+ if (node && Object.prototype.hasOwnProperty.call(node, part)) delete node[part];
1052
+ } else {
1053
+ if (!Arr._isObject(node[part])) break;
1054
+ node = node[part];
1055
+ }
1056
+ }
1057
+ }
1058
+ return out;
1059
+ }
1060
+ return input;
1061
+ }
1062
+ /**
1063
+ * Converts various input types into a plain array
1064
+ * Supports Arrays, Objects, Iterables, Map, WeakMap, and custom toArray/toJSON/jsonSerialize methods
1065
+ */
1066
+ static from(value) {
1067
+ if (value == null) return [];
1068
+ if (Array.isArray(value)) return value;
1069
+ if (Symbol.iterator in Object(value)) return [...value];
1070
+ if (value.toArray) return value.toArray();
1071
+ if (value.toJSON) return value.toJSON();
1072
+ if (value.jsonSerialize) return value.jsonSerialize();
1073
+ if (value instanceof Map) return Array.from(value.entries());
1074
+ if (value instanceof WeakMap) return [];
1075
+ if (typeof value === "object") return Object.values(value);
1076
+ return [value];
1077
+ }
1078
+ /**
1079
+ * Checks if an object has all the specified keys
1080
+ */
1081
+ static hasAll(obj, keys) {
1082
+ return keys.every((k) => k in obj);
1083
+ }
1084
+ /**
1085
+ * For arrays: check if the array contains any of the provided values.
1086
+ *
1087
+ * values can be single value or array of values.
1088
+ *
1089
+ * Example:
1090
+ * Arr.hasAny([1,2,3], [4,2]) -> true
1091
+ */
1092
+ static hasAny(array, values) {
1093
+ if (!Array.isArray(array)) return false;
1094
+ const vs = Array.isArray(values) ? values : [values];
1095
+ const set = new Set(array);
1096
+ for (const v of vs) if (set.has(v)) return true;
1097
+ return false;
1098
+ }
1099
+ /**
1100
+ * Retrieve a value using dot notation
1101
+ * Throws if value is not an integer
1102
+ */
1103
+ static integer(obj, path, defaultValue) {
1104
+ const val = data_get(obj, path, defaultValue);
1105
+ if (!Number.isInteger(val)) throw new InvalidArgumentException(`Value at "${path}" is not an integer.`);
1106
+ return val;
1107
+ }
1108
+ /**
1109
+ * Determine if the input is a "list-like" array: an Array with
1110
+ * contiguous numeric indices starting at 0 (no gaps).
1111
+ *
1112
+ * Example:
1113
+ * Arr.isList([1,2,3]) -> true
1114
+ * const a = []; a[2] = 5; Arr.isList(a) -> false
1115
+ */
1116
+ static isList(value) {
1117
+ if (!Array.isArray(value)) return false;
1118
+ for (let i = 0; i < value.length; i++) if (!(i in value)) return false;
1119
+ return true;
1120
+ }
1121
+ /**
1122
+ * Join array elements into a string using the given separator.
1123
+ *
1124
+ * Example:
1125
+ * Arr.join([1,2,3], '-') -> '1-2-3'
1126
+ */
1127
+ static join(array, separator = ",") {
1128
+ return Array.isArray(array) ? array.join(separator) : "";
1129
+ }
1130
+ /**
1131
+ * Create an object indexed by a key or callback function.
1132
+ *
1133
+ * Example:
1134
+ * Arr.keyBy([{id:1},{id:2}], 'id') -> { '1': {id:1}, '2': {id:2} }
1135
+ */
1136
+ static keyBy(array, key) {
1137
+ const result = {};
1138
+ if (!Array.isArray(array)) return result;
1139
+ for (const item of array) {
1140
+ let k;
1141
+ if (typeof key === "function") k = key(item);
1142
+ else k = String(item[key]);
1143
+ result[k] = item;
1144
+ }
1145
+ return result;
1146
+ }
1147
+ /**
1148
+ * Get the last element of an array, optionally matching a predicate,
1149
+ * or the last element if no predicate is provided, otherwise the defaultValue.
1150
+ *
1151
+ * Predicate can be a true (boolean), a function or a value to match (strict equality).
1152
+ *
1153
+ * When predicate is true (boolean), the last element will be removed and a tuple will be returned [el, rest].
1154
+ *
1155
+ * @param array
1156
+ * @param predicate
1157
+ * @param defaultValue
1158
+ *
1159
+ * @returns
1160
+ */
1161
+ static last(array, predicate, defaultValue) {
1162
+ if (predicate === true) {
1163
+ if (!array.length) throw new Error("Cannot pop from empty array");
1164
+ return [array[array.length - 1], array.slice(0, -1)];
1165
+ }
1166
+ if (!Array.isArray(array) || array.length === 0) return defaultValue;
1167
+ if (!predicate) return array[array.length - 1];
1168
+ if (typeof predicate === "function") {
1169
+ for (let i = array.length - 1; i >= 0; i--) if (predicate(array[i])) return array[i];
1170
+ } else for (let i = array.length - 1; i >= 0; i--) if (array[i] === predicate) return array[i];
1171
+ return defaultValue;
1172
+ }
1173
+ /**
1174
+ * Transform each element in an array using a callback.
1175
+ */
1176
+ static map(array, callback) {
1177
+ return Array.isArray(array) ? array.map(callback) : [];
1178
+ }
1179
+ /**
1180
+ * Maps a multi-dimensional array with a spread callback
1181
+ */
1182
+ static mapSpread(array, callback) {
1183
+ return array.map((item) => callback(...Array.isArray(item) ? item : [item]));
1184
+ }
1185
+ /**
1186
+ * Map each element to a key-value pair.
1187
+ *
1188
+ * Example:
1189
+ * Arr.mapWithKeys([{id:1, name:'A'}], x => [x.id, x.name])
1190
+ * -> { '1': 'A' }
1191
+ */
1192
+ static mapWithKeys(array, callback) {
1193
+ const result = {};
1194
+ if (!Array.isArray(array)) return result;
1195
+ array.forEach((item, idx) => {
1196
+ const [k, v] = callback(item, idx);
1197
+ result[String(k)] = v;
1198
+ });
1199
+ return result;
1200
+ }
1201
+ /**
1202
+ * Return only elements at the given indices.
1203
+ *
1204
+ * Example:
1205
+ * Arr.only([10,20,30], [0,2]) -> [10,30]
1206
+ */
1207
+ static only(array, keys) {
1208
+ if (!Array.isArray(array)) return [];
1209
+ const keyArray = Array.isArray(keys) ? keys : [keys];
1210
+ return array.filter((_, idx) => keyArray.includes(idx));
1211
+ }
1212
+ /**
1213
+ * Split an array into two arrays based on a predicate
1214
+ */
1215
+ static partition(array, predicate) {
1216
+ const truthy = [];
1217
+ const falsy = [];
1218
+ array.forEach((item) => (predicate(item) ? truthy : falsy).push(item));
1219
+ return [truthy, falsy];
1220
+ }
1221
+ /**
1222
+ * Extract a property from each element in an array of objects.
1223
+ *
1224
+ * Example:
1225
+ * Arr.pluck([{name:'A'},{name:'B'}], 'name') -> ['A','B']
1226
+ */
1227
+ static pluck(array, key) {
1228
+ if (!Array.isArray(array)) return [];
1229
+ return array.map((item) => item[key]);
1230
+ }
1231
+ /**
1232
+ * Add elements to the beginning of an array and return a new array.
1233
+ *
1234
+ * @param array
1235
+ * @param value
1236
+ * @returns
1237
+ */
1238
+ static prepend(array, ...value) {
1239
+ return [...value, ...Array.isArray(array) ? array : []];
1240
+ }
1241
+ /**
1242
+ * Remove a value from an array by index and return it.
1243
+ * Returns a tuple: [newArray, removedValue]
1244
+ */
1245
+ static pull(array, key) {
1246
+ if (!Array.isArray(array) || key < 0 || key >= array.length) return [array, void 0];
1247
+ const copy = array.slice();
1248
+ const [removed] = copy.splice(key, 1);
1249
+ return [copy, removed];
1250
+ }
1251
+ /**
1252
+ * Append values to an array (mutable)
1253
+ */
1254
+ static push(array, ...values) {
1255
+ array.push(...values);
1256
+ return array;
1257
+ }
1258
+ /**
1259
+ * Pick one or more random elements from an array.
1260
+ */
1261
+ static random(array, count = 1) {
1262
+ if (!Array.isArray(array) || array.length === 0) return void 0;
1263
+ const shuffled = Arr.shuffle(array);
1264
+ if (count === 1) return shuffled[0];
1265
+ return shuffled.slice(0, count);
1266
+ }
1267
+ /**
1268
+ * Returns array elements that do NOT satisfy the predicate
1269
+ */
1270
+ static reject(array, predicate) {
1271
+ return array.filter((item) => !predicate(item));
1272
+ }
1273
+ /**
1274
+ * Pick keys from an array of objects or an object
1275
+ */
1276
+ static select(obj, keys) {
1277
+ const result = {};
1278
+ keys.forEach((k) => {
1279
+ if (k in obj) result[k] = obj[k];
1280
+ });
1281
+ return result;
1282
+ }
1283
+ /**
1284
+ * Returns the only element that passes a callback, throws if none or multiple
1285
+ */
1286
+ static sole(array, predicate) {
1287
+ const filtered = array.filter(predicate);
1288
+ if (filtered.length === 0) throw new InvalidArgumentException("No element satisfies the condition.");
1289
+ if (filtered.length > 1) throw new InvalidArgumentException("Multiple elements satisfy the condition.");
1290
+ return filtered[0];
1291
+ }
1292
+ /**
1293
+ * Checks if at least one element satisfies the predicate
1294
+ */
1295
+ static some(array, predicate) {
1296
+ return array.some(predicate);
1297
+ }
1298
+ /**
1299
+ * Randomly shuffle an array and return a new array.
1300
+ */
1301
+ static shuffle(array) {
1302
+ if (!Array.isArray(array)) return [];
1303
+ const copy = array.slice();
1304
+ for (let i = copy.length - 1; i > 0; i--) {
1305
+ const j = Math.floor(Math.random() * (i + 1));
1306
+ [copy[i], copy[j]] = [copy[j], copy[i]];
1307
+ }
1308
+ return copy;
1309
+ }
1310
+ /**
1311
+ * Sort an array ascending using optional comparator.
1312
+ */
1313
+ static sort(array, comparator) {
1314
+ if (!Array.isArray(array)) return [];
1315
+ return array.slice().sort(comparator);
1316
+ }
1317
+ /**
1318
+ * Sort an array descending using optional comparator.
1319
+ */
1320
+ static sortDesc(array, comparator) {
1321
+ return Arr.sort(array, comparator ? (a, b) => comparator(b, a) : void 0);
1322
+ }
1323
+ /**
1324
+ * Recursively sort arrays inside an array.
1325
+ */
1326
+ static sortRecursive(array) {
1327
+ if (!Array.isArray(array)) return [];
1328
+ return array.map((item) => Array.isArray(item) ? Arr.sortRecursive(item) : item).sort();
1329
+ }
1330
+ /**
1331
+ * Recursively sort arrays inside an array descending.
1332
+ */
1333
+ static sortRecursiveDesc(array) {
1334
+ if (!Array.isArray(array)) return [];
1335
+ return array.map((item) => Array.isArray(item) ? Arr.sortRecursiveDesc(item) : item).sort().reverse();
1336
+ }
1337
+ /**
1338
+ * Retrieve a value using dot notation
1339
+ * Throws if value is not a string
1340
+ */
1341
+ static string(obj, path, defaultValue) {
1342
+ const val = data_get(obj, path, defaultValue);
1343
+ if (typeof val !== "string") throw new InvalidArgumentException(`Value at "${path}" is not a string.`);
1344
+ return val;
1345
+ }
1346
+ /**
1347
+ * Return the first N elements of an array.
1348
+ *
1349
+ * @param array
1350
+ * @param count
1351
+ * @returns
1352
+ */
1353
+ static take(array, count) {
1354
+ if (!Array.isArray(array)) return [];
1355
+ return array.slice(0, count);
1356
+ }
1357
+ /**
1358
+ * Filter an array based on a predicate function or key-value match.
1359
+ */
1360
+ static where(array, predicate) {
1361
+ if (!Array.isArray(array)) return [];
1362
+ if (typeof predicate === "function") return array.filter(predicate);
1363
+ return array.filter((item) => Object.entries(predicate).every(([k, v]) => item[k] === v));
1364
+ }
1365
+ /**
1366
+ * Filter an array of objects, keeping elements where the given key is not null/undefined.
1367
+ */
1368
+ static whereNotNull(array, key) {
1369
+ if (!Array.isArray(array)) return [];
1370
+ return array.filter((item) => item[key] !== null && item[key] !== void 0);
1371
+ }
1372
+ /**
1373
+ * If the given value is not an array and not null, wrap it in one.
1374
+ *
1375
+ * Non-array values become [value]; null/undefined becomes [].
1376
+ *
1377
+ * @param value
1378
+ * @returns
1379
+ */
1380
+ static wrap(value) {
1381
+ if (value === null || value === void 0) return [];
1382
+ return Array.isArray(value) ? value : [value];
1383
+ }
1384
+ /**
1385
+ * Return the first element of an array, undefined if empty.
1386
+ */
1387
+ static head(array) {
1388
+ return Array.isArray(array) && array.length ? array[0] : void 0;
1389
+ }
1390
+ /**
1391
+ * Splits an array into chunks of a specified size.
1392
+ *
1393
+ * @template T - Type of elements in the array
1394
+ * @param arr - The input array
1395
+ * @param size - Size of each chunk (default: 2)
1396
+ * @returns An array of chunks (arrays)
1397
+ */
1398
+ static chunk = (arr, size = 2) => {
1399
+ if (size <= 0) throw new Error("Chunk size must be greater than 0");
1400
+ const chunks = [];
1401
+ for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size));
1402
+ return chunks;
1403
+ };
1404
+ /**
1405
+ * Alternates between two arrays, creating a zipped result.
1406
+ *
1407
+ * @param a
1408
+ * @param b
1409
+ * @returns
1410
+ */
1411
+ static alternate(a, b) {
1412
+ const result = [];
1413
+ const max = Math.max(a.length, b.length);
1414
+ for (let i = 0; i < max; i++) {
1415
+ if (i < a.length) result.push(a[i]);
1416
+ if (i < b.length) result.push(b[i]);
1417
+ }
1418
+ return result;
1419
+ }
1420
+ /**
1421
+ * Combine arrays and sum their values element by element.
1422
+ *
1423
+ * @param arr
1424
+ * @returns
1425
+ */
1426
+ static combine(...arr) {
1427
+ const maxLength = Math.max(...arr.map((a) => a.length));
1428
+ const result = new Array(maxLength).fill(0);
1429
+ for (let i = 0; i < maxLength; i++) for (const array of arr) result[i] += array[i] || 0;
1430
+ return result;
1431
+ }
1432
+ /**
1433
+ * Find the value associated with a given key.
1434
+ *
1435
+ * @param key
1436
+ * @param arr
1437
+ * @returns
1438
+ */
1439
+ static find(key, arr) {
1440
+ return arr.find((item) => item === key) || null;
1441
+ }
1442
+ /**
1443
+ * Check if array is empty.
1444
+ *
1445
+ * @param arr
1446
+ * @returns
1447
+ */
1448
+ static isEmpty(arr) {
1449
+ if (arr.length === 0) return true;
1450
+ else return false;
1451
+ }
1452
+ /**
1453
+ * Check if array is empty.
1454
+ *
1455
+ * @param arr
1456
+ * @returns
1457
+ */
1458
+ static isNotEmpty(arr) {
1459
+ return arr.length > 0;
1460
+ }
1461
+ /**
1462
+ * Pop the element off the end of array.
1463
+ *
1464
+ * @param arr
1465
+ * @returns
1466
+ */
1467
+ static pop(arr) {
1468
+ return arr.slice(0, -1);
1469
+ }
1470
+ /**
1471
+ * Create a new array in reverse order.
1472
+ *
1473
+ * @param arr
1474
+ * @returns
1475
+ */
1476
+ static reverse(arr) {
1477
+ return [...arr].reverse();
1478
+ }
1479
+ /**
1480
+ * Return the first element of an array that satisfies the predicate,
1481
+ * or the first element if no predicate is provided, otherwise the defaultValue.
1482
+ *
1483
+ * Predicate can be true (boolean), a function or a value to match (strict equality).
1484
+ *
1485
+ * When predicate is true (boolean), the first element will be removed and a tuple will be returned [el, rest].
1486
+ *
1487
+ * @param array
1488
+ * @param predicate
1489
+ * @param defaultValue
1490
+ *
1491
+ * @alias Arr.first()
1492
+ * @returns
1493
+ */
1494
+ static shift(array, predicate, defaultValue) {
1495
+ return Arr.first(array, predicate, defaultValue);
1496
+ }
1497
+ /**
1498
+ * Generates an array of sequential numbers.
1499
+ *
1500
+ * @param size - Number of elements in the range
1501
+ * @param startAt - Starting number (default: 0)
1502
+ * @returns An array of numbers from startAt to startAt + size - 1
1503
+ */
1504
+ static range(size, startAt = 0) {
1505
+ if (size <= 0 || !Number.isFinite(size)) return [];
1506
+ return Array.from({ length: size }, (_, i) => startAt + i);
1507
+ }
1508
+ };
1509
+
1510
+ //#endregion
1511
+ //#region src/Helpers/Time.ts
1512
+ dayjs.default.extend(dayjs_plugin_utc_js.default);
1513
+ dayjs.default.extend(dayjs_plugin_timezone_js.default);
1514
+ dayjs.default.extend(dayjs_plugin_dayOfYear_js.default);
1515
+ dayjs.default.extend(dayjs_plugin_isBetween_js.default);
1516
+ dayjs.default.extend(dayjs_plugin_isLeapYear_js.default);
1517
+ dayjs.default.extend(dayjs_plugin_relativeTime_js.default);
1518
+ dayjs.default.extend(dayjs_plugin_advancedFormat_js.default);
1519
+ dayjs.default.extend(dayjs_plugin_customParseFormat_js.default);
1520
+ const phpToDayjsTokens = (format$1) => format$1.replace(/Y/g, "YYYY").replace(/m/g, "MM").replace(/d/g, "DD").replace(/H/g, "HH").replace(/i/g, "mm").replace(/s/g, "ss");
1521
+ function format(date, fmt) {
1522
+ return (0, dayjs.default)(date).format(phpToDayjsTokens(fmt));
1523
+ }
1524
+ const TimeClass = class {};
1525
+ var DateTime = class DateTime extends TimeClass {
1526
+ instance;
1527
+ constructor(config) {
1528
+ super(config);
1529
+ this.instance = (0, dayjs.default)(config);
1530
+ return new Proxy(this, { get: (target, prop, receiver) => {
1531
+ if (prop in target) return Reflect.get(target, prop, receiver);
1532
+ const value = Reflect.get(this.instance, prop, receiver);
1533
+ if (typeof value === "function") return (...args) => {
1534
+ const result = value.apply(this.instance, args);
1535
+ return dayjs.default.isDayjs(result) ? new DateTime(result) : result;
1536
+ };
1537
+ return value;
1538
+ } });
1539
+ }
1540
+ /**
1541
+ * Start time of a specific unit.
1542
+ *
1543
+ * @returns
1544
+ */
1545
+ start(unit = "days") {
1546
+ return this.startOf(unit);
1547
+ }
1548
+ /**
1549
+ * End time of a specific unit.
1550
+ *
1551
+ * @returns
1552
+ */
1553
+ end(unit = "days") {
1554
+ return this.endOf(unit);
1555
+ }
1556
+ /**
1557
+ * Get the first day of the month of the given date
1558
+ *
1559
+ * @returns
1560
+ */
1561
+ firstDayOfMonth() {
1562
+ return new DateTime(new Date(Date.UTC(this.year(), this.month(), 1)));
1563
+ }
1564
+ carbonFormat(template) {
1565
+ return template ? this.format(phpToDayjsTokens(template)) : this.format();
1566
+ }
1567
+ /**
1568
+ * Get the last day of the month of the given date
1569
+ *
1570
+ * @returns
1571
+ */
1572
+ lastDayOfMonth() {
1573
+ return new DateTime(new Date(Date.UTC(this.year(), this.month() + 1, 0)));
1574
+ }
1575
+ /**
1576
+ * Get a random time between the specified hour and minute.
1577
+ *
1578
+ * @param startHour
1579
+ * @param startMinute
1580
+ * @param endHour
1581
+ * @param endMinute
1582
+ * @returns
1583
+ */
1584
+ randomTime(startHour = 9, startMinute = 0, endHour = 17, endMinute = 0) {
1585
+ const today = /* @__PURE__ */ new Date();
1586
+ const startMinutes = startHour * 60 + startMinute;
1587
+ const endMinutes = endHour * 60 + endMinute;
1588
+ const randomMinutes = Math.floor(Math.random() * (endMinutes - startMinutes)) + startMinutes;
1589
+ const hour = Math.floor(randomMinutes / 60);
1590
+ const minute = randomMinutes % 60;
1591
+ const date = new Date(today);
1592
+ date.setHours(hour, minute, 0, 0);
1593
+ return new DateTime(date);
1594
+ }
1595
+ /**
1596
+ * Create a date for a given timestamp.
1597
+ *
1598
+ * @param timestamp - Unix timestamp
1599
+ *
1600
+ * @return {Date} object
1601
+ */
1602
+ static fromTimestamp(timestamp) {
1603
+ return /* @__PURE__ */ new Date(timestamp * 1e3);
1604
+ }
1605
+ /**
1606
+ * Get current time instance.
1607
+ *
1608
+ * @returns Current time
1609
+ */
1610
+ static now() {
1611
+ return new DateTime();
1612
+ }
1613
+ /**
1614
+ * Parse the time
1615
+ *
1616
+ * @param date
1617
+ * @returns
1618
+ */
1619
+ static parse(date) {
1620
+ return new DateTime(date);
678
1621
  }
679
- const parts = key.split(".");
680
- let current = obj;
681
- for (let i = 0; i < parts.length; i++) {
682
- const part = parts[i];
683
- /**
684
- * If we're at the last key, assign the value
685
- */
686
- if (i === parts.length - 1) current[part] = value;
687
- else {
688
- /**
689
- * If the key doesn't exist or isn't an object, create it
690
- */
691
- if (typeof current[part] !== "object" || current[part] === null) current[part] = {};
692
- current = current[part];
693
- }
1622
+ /**
1623
+ * Get the formatted date according to the string of tokens passed in.
1624
+ *
1625
+ * To escape characters, wrap them in square brackets (e.g. [MM]).
1626
+ *
1627
+ * @param time - current time
1628
+ * @param template - time format
1629
+ */
1630
+ static format(time, template) {
1631
+ return new DateTime(time).format(template);
1632
+ }
1633
+ /**
1634
+ * Get the difference in days from today.
1635
+ *
1636
+ * @param time
1637
+ * @param startHour
1638
+ * @param startMinute
1639
+ * @param endHour
1640
+ * @param endMinute
1641
+ * @returns
1642
+ */
1643
+ static randomTime(time, startHour, startMinute, endHour, endMinute) {
1644
+ return new DateTime(time).randomTime(startHour, startMinute, endHour, endMinute);
1645
+ }
1646
+ /**
1647
+ * Get the first day of the month of the given date
1648
+ *
1649
+ * @param time
1650
+ *
1651
+ * @returns
1652
+ */
1653
+ static firstDayOfMonth(time) {
1654
+ return new DateTime(time).firstDayOfMonth();
1655
+ }
1656
+ /**
1657
+ * Get the last day of the month of the given date
1658
+ *
1659
+ * @param time
1660
+ *
1661
+ * @returns
1662
+ */
1663
+ static lastDayOfMonth(time) {
1664
+ return new DateTime(time).lastDayOfMonth();
694
1665
  }
695
- };
696
- /**
697
- * Converts object keys to a slugified format (e.g., snake_case).
698
- *
699
- * @template T - Type of the input object
700
- * @param obj - The object whose keys will be slugified
701
- * @param only - Optional array of keys to slugify (others remain unchanged)
702
- * @param separator - Separator for slugified keys (default: "_")
703
- * @returns A new object with slugified keys
704
- */
705
- const slugifyKeys = (obj, only = [], separator = "_") => {
706
- const slugify = (key) => key.replace(/([a-z])([A-Z])/g, `$1${separator}$2`).replace(/[\s\W]+/g, separator).replace(new RegExp(`${separator}{2,}`, "g"), separator).replace(new RegExp(`^${separator}|${separator}$`, "g"), "").toLowerCase();
707
- let entries = Object.entries(obj);
708
- if (only.length) entries = entries.filter(([key]) => only.includes(key));
709
- return Object.fromEntries(entries.map(([key, value]) => [slugify(key), value]));
710
1666
  };
711
1667
 
712
1668
  //#endregion
@@ -5048,164 +6004,6 @@ function matchCase(value, comparison) {
5048
6004
  return value;
5049
6005
  }
5050
6006
 
5051
- //#endregion
5052
- //#region src/Helpers/Time.ts
5053
- dayjs.default.extend(dayjs_plugin_utc.default);
5054
- dayjs.default.extend(dayjs_plugin_timezone.default);
5055
- dayjs.default.extend(dayjs_plugin_dayOfYear.default);
5056
- dayjs.default.extend(dayjs_plugin_isBetween.default);
5057
- dayjs.default.extend(dayjs_plugin_isLeapYear.default);
5058
- dayjs.default.extend(dayjs_plugin_relativeTime.default);
5059
- dayjs.default.extend(dayjs_plugin_advancedFormat.default);
5060
- dayjs.default.extend(dayjs_plugin_customParseFormat.default);
5061
- const phpToDayjsTokens = (format$1) => format$1.replace(/Y/g, "YYYY").replace(/m/g, "MM").replace(/d/g, "DD").replace(/H/g, "HH").replace(/i/g, "mm").replace(/s/g, "ss");
5062
- function format(date, fmt) {
5063
- return (0, dayjs.default)(date).format(phpToDayjsTokens(fmt));
5064
- }
5065
- const TimeClass = class {};
5066
- var Time = class Time extends TimeClass {
5067
- instance;
5068
- constructor(config) {
5069
- super(config);
5070
- this.instance = (0, dayjs.default)(config);
5071
- return new Proxy(this, { get: (target, prop, receiver) => {
5072
- if (prop in target) return Reflect.get(target, prop, receiver);
5073
- const value = Reflect.get(this.instance, prop, receiver);
5074
- if (typeof value === "function") return (...args) => {
5075
- const result = value.apply(this.instance, args);
5076
- return dayjs.default.isDayjs(result) ? new Time(result) : result;
5077
- };
5078
- return value;
5079
- } });
5080
- }
5081
- /**
5082
- * Start time of a specific unit.
5083
- *
5084
- * @returns
5085
- */
5086
- start(unit = "days") {
5087
- return this.startOf(unit);
5088
- }
5089
- /**
5090
- * End time of a specific unit.
5091
- *
5092
- * @returns
5093
- */
5094
- end(unit = "days") {
5095
- return this.endOf(unit);
5096
- }
5097
- /**
5098
- * Get the first day of the month of the given date
5099
- *
5100
- * @returns
5101
- */
5102
- firstDayOfMonth() {
5103
- return new Time(new Date(Date.UTC(this.year(), this.month(), 1)));
5104
- }
5105
- carbonFormat(template) {
5106
- return template ? this.format(phpToDayjsTokens(template)) : this.format();
5107
- }
5108
- /**
5109
- * Get the last day of the month of the given date
5110
- *
5111
- * @returns
5112
- */
5113
- lastDayOfMonth() {
5114
- return new Time(new Date(Date.UTC(this.year(), this.month() + 1, 0)));
5115
- }
5116
- /**
5117
- * Get a random time between the specified hour and minute.
5118
- *
5119
- * @param startHour
5120
- * @param startMinute
5121
- * @param endHour
5122
- * @param endMinute
5123
- * @returns
5124
- */
5125
- randomTime(startHour = 9, startMinute = 0, endHour = 17, endMinute = 0) {
5126
- const today = /* @__PURE__ */ new Date();
5127
- const startMinutes = startHour * 60 + startMinute;
5128
- const endMinutes = endHour * 60 + endMinute;
5129
- const randomMinutes = Math.floor(Math.random() * (endMinutes - startMinutes)) + startMinutes;
5130
- const hour = Math.floor(randomMinutes / 60);
5131
- const minute = randomMinutes % 60;
5132
- const date = new Date(today);
5133
- date.setHours(hour, minute, 0, 0);
5134
- return new Time(date);
5135
- }
5136
- /**
5137
- * Create a date for a given timestamp.
5138
- *
5139
- * @param timestamp - Unix timestamp
5140
- *
5141
- * @return {Date} object
5142
- */
5143
- static fromTimestamp(timestamp) {
5144
- return /* @__PURE__ */ new Date(timestamp * 1e3);
5145
- }
5146
- /**
5147
- * Get current time instance.
5148
- *
5149
- * @returns Current time
5150
- */
5151
- static now() {
5152
- return new Time();
5153
- }
5154
- /**
5155
- * Parse the time
5156
- *
5157
- * @param date
5158
- * @returns
5159
- */
5160
- static parse(date) {
5161
- return new Time(date);
5162
- }
5163
- /**
5164
- * Get the formatted date according to the string of tokens passed in.
5165
- *
5166
- * To escape characters, wrap them in square brackets (e.g. [MM]).
5167
- *
5168
- * @param time - current time
5169
- * @param template - time format
5170
- */
5171
- static format(time, template) {
5172
- return new Time(time).format(template);
5173
- }
5174
- /**
5175
- * Get the difference in days from today.
5176
- *
5177
- * @param time
5178
- * @param startHour
5179
- * @param startMinute
5180
- * @param endHour
5181
- * @param endMinute
5182
- * @returns
5183
- */
5184
- static randomTime(time, startHour, startMinute, endHour, endMinute) {
5185
- return new Time(time).randomTime(startHour, startMinute, endHour, endMinute);
5186
- }
5187
- /**
5188
- * Get the first day of the month of the given date
5189
- *
5190
- * @param time
5191
- *
5192
- * @returns
5193
- */
5194
- static firstDayOfMonth(time) {
5195
- return new Time(time).firstDayOfMonth();
5196
- }
5197
- /**
5198
- * Get the last day of the month of the given date
5199
- *
5200
- * @param time
5201
- *
5202
- * @returns
5203
- */
5204
- static lastDayOfMonth(time) {
5205
- return new Time(time).lastDayOfMonth();
5206
- }
5207
- };
5208
-
5209
6007
  //#endregion
5210
6008
  //#region src/GlobalBootstrap.ts
5211
6009
  /**
@@ -5232,12 +6030,12 @@ var Time = class Time extends TimeClass {
5232
6030
  */
5233
6031
  function loadHelpers(target = globalThis) {
5234
6032
  const globalHelpers = {
5235
- Arr: Arr_exports,
6033
+ Arr,
5236
6034
  Crypto: Crypto_exports,
5237
6035
  Number: Number_exports,
5238
- Obj: Obj_exports,
6036
+ Obj,
5239
6037
  Str,
5240
- Time,
6038
+ DateTime,
5241
6039
  DumpDie: DumpDie_exports,
5242
6040
  apa: Str.apa,
5243
6041
  title: Str.title,
@@ -5251,24 +6049,26 @@ function loadHelpers(target = globalThis) {
5251
6049
  plural: Str.plural,
5252
6050
  singular: Str.singular,
5253
6051
  capitalize: Str.capitalize,
5254
- collapse,
5255
- alternate,
5256
- combine,
5257
- forget,
5258
- first,
5259
- last,
5260
- isEmpty,
5261
- isNotEmpty,
5262
- prepend,
5263
- range,
5264
- flatten,
6052
+ collapse: Arr.collapse,
6053
+ forget: Arr.forget,
6054
+ first: Arr.first,
6055
+ last: Arr.last,
6056
+ prepend: Arr.prepend,
6057
+ flatten: Arr.flatten,
5265
6058
  dot,
6059
+ undot,
5266
6060
  extractProperties,
5267
6061
  getValue,
5268
6062
  modObj,
5269
6063
  safeDot,
5270
6064
  setNested,
6065
+ toCssClasses,
5271
6066
  slugifyKeys,
6067
+ toCssStyles,
6068
+ data_get,
6069
+ data_set,
6070
+ data_fill,
6071
+ data_forget,
5272
6072
  uuid,
5273
6073
  random,
5274
6074
  randomSecure,
@@ -5283,13 +6083,13 @@ function loadHelpers(target = globalThis) {
5283
6083
  checksum,
5284
6084
  verifyChecksum,
5285
6085
  caesarCipher,
5286
- now: Time.now,
5287
- format: Time.format,
5288
- fromTimestamp: Time.fromTimestamp,
5289
- parse: Time.parse,
5290
- randomTime: Time.randomTime,
5291
- firstDayOfMonth: Time.firstDayOfMonth,
5292
- lastDayOfMonth: Time.lastDayOfMonth,
6086
+ now: DateTime.now,
6087
+ format: DateTime.format,
6088
+ fromTimestamp: DateTime.fromTimestamp,
6089
+ parse: DateTime.parse,
6090
+ randomTime: DateTime.randomTime,
6091
+ firstDayOfMonth: DateTime.firstDayOfMonth,
6092
+ lastDayOfMonth: DateTime.lastDayOfMonth,
5293
6093
  abbreviate,
5294
6094
  humanize,
5295
6095
  toBytes,
@@ -5350,6 +6150,13 @@ function cleanHelpers(target = globalThis) {
5350
6150
  "safeDot",
5351
6151
  "setNested",
5352
6152
  "slugifyKeys",
6153
+ "toCssClasses",
6154
+ "undot",
6155
+ "toCssStyles",
6156
+ "data_get",
6157
+ "data_set",
6158
+ "data_fill",
6159
+ "data_forget",
5353
6160
  "Crypto",
5354
6161
  "uuid",
5355
6162
  "random",
@@ -5387,18 +6194,14 @@ function cleanHelpers(target = globalThis) {
5387
6194
  }
5388
6195
 
5389
6196
  //#endregion
5390
- Object.defineProperty(exports, 'Arr', {
5391
- enumerable: true,
5392
- get: function () {
5393
- return Arr_exports;
5394
- }
5395
- });
6197
+ exports.Arr = Arr;
5396
6198
  Object.defineProperty(exports, 'Crypto', {
5397
6199
  enumerable: true,
5398
6200
  get: function () {
5399
6201
  return Crypto_exports;
5400
6202
  }
5401
6203
  });
6204
+ exports.DateTime = DateTime;
5402
6205
  Object.defineProperty(exports, 'DumpDie', {
5403
6206
  enumerable: true,
5404
6207
  get: function () {
@@ -5406,6 +6209,7 @@ Object.defineProperty(exports, 'DumpDie', {
5406
6209
  }
5407
6210
  });
5408
6211
  exports.HtmlString = HtmlString;
6212
+ exports.InvalidArgumentException = InvalidArgumentException;
5409
6213
  exports.Mode = Mode;
5410
6214
  Object.defineProperty(exports, 'Number', {
5411
6215
  enumerable: true,
@@ -5419,54 +6223,44 @@ Object.defineProperty(exports, 'Obj', {
5419
6223
  return Obj_exports;
5420
6224
  }
5421
6225
  });
6226
+ exports.RuntimeException = RuntimeException;
5422
6227
  exports.Str = Str;
5423
6228
  exports.Stringable = Stringable;
5424
- exports.Time = Time;
5425
6229
  exports.abbreviate = abbreviate;
5426
- exports.alternate = alternate;
5427
6230
  exports.base64Decode = base64Decode;
5428
6231
  exports.base64Encode = base64Encode;
5429
6232
  exports.caesarCipher = caesarCipher;
5430
6233
  exports.checksum = checksum;
5431
- exports.chunk = chunk;
5432
6234
  exports.cleanHelpers = cleanHelpers;
5433
- exports.collapse = collapse;
5434
- exports.combine = combine;
6235
+ exports.data_fill = data_fill;
6236
+ exports.data_forget = data_forget;
6237
+ exports.data_get = data_get;
6238
+ exports.data_set = data_set;
5435
6239
  exports.dd = dd;
5436
6240
  exports.dot = dot;
5437
6241
  exports.dump = dump;
5438
6242
  exports.extractProperties = extractProperties;
5439
- exports.find = find;
5440
- exports.first = first;
5441
- exports.flatten = flatten;
5442
- exports.forget = forget;
5443
6243
  exports.format = format;
5444
6244
  exports.getValue = getValue;
5445
6245
  exports.hash = hash;
5446
6246
  exports.hmac = hmac;
5447
6247
  exports.humanize = humanize;
5448
- exports.isEmpty = isEmpty;
5449
- exports.isNotEmpty = isNotEmpty;
5450
- exports.last = last;
5451
6248
  exports.loadHelpers = loadHelpers;
5452
6249
  exports.modObj = modObj;
5453
- exports.pop = pop;
5454
- exports.prepend = prepend;
5455
6250
  exports.random = random;
5456
6251
  exports.randomColor = randomColor;
5457
6252
  exports.randomPassword = randomPassword;
5458
6253
  exports.randomSecure = randomSecure;
5459
- exports.range = range;
5460
- exports.reverse = reverse;
5461
6254
  exports.safeDot = safeDot;
5462
6255
  exports.secureToken = secureToken;
5463
6256
  exports.setNested = setNested;
5464
- exports.shift = shift;
5465
6257
  exports.slugifyKeys = slugifyKeys;
5466
6258
  exports.str = str;
5467
- exports.take = take;
5468
6259
  exports.toBytes = toBytes;
6260
+ exports.toCssClasses = toCssClasses;
6261
+ exports.toCssStyles = toCssStyles;
5469
6262
  exports.toHumanTime = toHumanTime;
6263
+ exports.undot = undot;
5470
6264
  exports.uuid = uuid;
5471
6265
  exports.verifyChecksum = verifyChecksum;
5472
6266
  exports.xor = xor;