@h3ravel/support 0.10.3 → 0.11.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.js CHANGED
@@ -1,7 +1,28 @@
1
+ import { __export } from "./chunk-PECeCxCb.js";
2
+ import { createHash, createHmac, randomBytes, randomUUID } from "crypto";
1
3
  import process from "process";
2
4
  import util from "util";
3
5
 
4
6
  //#region src/Helpers/Arr.ts
7
+ var Arr_exports = /* @__PURE__ */ __export({
8
+ alternate: () => alternate,
9
+ chunk: () => chunk,
10
+ collapse: () => collapse,
11
+ combine: () => combine,
12
+ find: () => find,
13
+ first: () => first,
14
+ flatten: () => flatten,
15
+ forget: () => forget,
16
+ isEmpty: () => isEmpty,
17
+ isNotEmpty: () => isNotEmpty,
18
+ last: () => last,
19
+ pop: () => pop,
20
+ prepend: () => prepend,
21
+ range: () => range,
22
+ reverse: () => reverse,
23
+ shift: () => shift,
24
+ take: () => take
25
+ });
5
26
  /**
6
27
  * Splits an array into chunks of a specified size.
7
28
  *
@@ -17,6 +38,67 @@ const chunk = (arr, size = 2) => {
17
38
  return chunks;
18
39
  };
19
40
  /**
41
+ * Collapse an array of arrays into a single array.
42
+ */
43
+ const collapse = (arr) => {
44
+ const result = [];
45
+ for (const item of arr) if (Array.isArray(item)) result.push(...item);
46
+ else result.push(item);
47
+ return result;
48
+ };
49
+ /**
50
+ * Alternates between two arrays, creating a zipped result.
51
+ */
52
+ const alternate = (a, b) => {
53
+ const result = [];
54
+ const max = Math.max(a.length, b.length);
55
+ for (let i = 0; i < max; i++) {
56
+ if (i < a.length) result.push(a[i]);
57
+ if (i < b.length) result.push(b[i]);
58
+ }
59
+ return result;
60
+ };
61
+ /**
62
+ * Combine arrays and sum their values element by element.
63
+ */
64
+ const combine = (...arr) => {
65
+ const maxLength = Math.max(...arr.map((a) => a.length));
66
+ const result = new Array(maxLength).fill(0);
67
+ for (let i = 0; i < maxLength; i++) for (const array of arr) result[i] += array[i] || 0;
68
+ return result;
69
+ };
70
+ /** Find the value associated with a given key. */
71
+ const find = (key, arr) => arr.find((item) => item === key) || null;
72
+ /** Returns a new array without the given indices. */
73
+ const forget = (arr, keys) => arr.filter((_, i) => !keys.includes(i));
74
+ /** Remove the first element and return tuple [el, rest]. */
75
+ const first = (arr) => {
76
+ if (!arr.length) throw new Error("Cannot shift from empty array");
77
+ return [arr[0], arr.slice(1)];
78
+ };
79
+ /** Remove the last element and return tuple [el, rest]. */
80
+ const last = (arr) => {
81
+ if (!arr.length) throw new Error("Cannot pop from empty array");
82
+ return [arr[arr.length - 1], arr.slice(0, -1)];
83
+ };
84
+ /** Check if array is empty. */
85
+ const isEmpty = (arr) => {
86
+ if (arr.length === 0) return true;
87
+ else return false;
88
+ };
89
+ /** Check if array is empty. */
90
+ const isNotEmpty = (arr) => arr.length > 0;
91
+ /** Pop the element off the end of array. */
92
+ const pop = (arr) => arr.slice(0, -1);
93
+ /** Add elements to the beginning of array. */
94
+ const prepend = (arr, ...elements) => [...elements, ...arr];
95
+ /** Take first n elements of array. */
96
+ const take = (amount, arr) => arr.slice(0, Math.max(0, amount));
97
+ /** Create a new array in reverse order. */
98
+ const reverse = (arr) => [...arr].reverse();
99
+ /** Alias for first element removal. */
100
+ const shift = first;
101
+ /**
20
102
  * Generates an array of sequential numbers.
21
103
  *
22
104
  * @param size - Number of elements in the range
@@ -27,40 +109,197 @@ const range = (size, startAt = 0) => {
27
109
  if (size <= 0 || !Number.isFinite(size)) return [];
28
110
  return Array.from({ length: size }, (_, i) => startAt + i);
29
111
  };
112
+ /** Flatten multi-dimensional arrays into single level. */
113
+ const flatten = (arr) => {
114
+ const result = [];
115
+ const recurse = (input) => {
116
+ for (const item of input) Array.isArray(item) ? recurse(item) : result.push(item);
117
+ };
118
+ recurse(arr);
119
+ return result;
120
+ };
30
121
 
31
122
  //#endregion
32
- //#region src/Helpers/DumpDie.ts
33
- const inspect = (thing) => {
34
- return util.inspect(thing, {
35
- showHidden: true,
36
- depth: null,
37
- colors: true
38
- });
123
+ //#region src/Helpers/Crypto.ts
124
+ var Crypto_exports = /* @__PURE__ */ __export({
125
+ base64Decode: () => base64Decode,
126
+ base64Encode: () => base64Encode,
127
+ caesarCipher: () => caesarCipher,
128
+ checksum: () => checksum,
129
+ hash: () => hash,
130
+ hmac: () => hmac,
131
+ random: () => random,
132
+ randomColor: () => randomColor,
133
+ randomPassword: () => randomPassword,
134
+ randomSecure: () => randomSecure,
135
+ secureToken: () => secureToken,
136
+ uuid: () => uuid,
137
+ verifyChecksum: () => verifyChecksum,
138
+ xor: () => xor
139
+ });
140
+ /**
141
+ * Generate a random UUID string.
142
+ *
143
+ * @returns A random UUID string
144
+ */
145
+ const uuid = () => {
146
+ return randomUUID();
39
147
  };
40
148
  /**
41
- * Dump something and kill the process for quick debugging. Based on Laravel's dd()
149
+ * Generate a random string of specified length.
42
150
  *
43
- * @param args
151
+ * @param length - Length of the random string (default: 16)
152
+ * @param charset - Character set to use (default: alphanumeric)
153
+ * @returns A random string
44
154
  */
45
- const dd = (...args) => {
46
- args.forEach((thing) => {
47
- console.log(inspect(thing));
48
- });
49
- process.exit(1);
155
+ const random = (length = 16, charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") => {
156
+ let result = "";
157
+ for (let i = 0; i < length; i++) result += charset.charAt(Math.floor(Math.random() * charset.length));
158
+ return result;
50
159
  };
51
160
  /**
52
- * Dump something but keep the process for quick debugging. Based on Laravel's dump()
161
+ * Secure random string generator that uses crypto.randomBytes.
53
162
  *
54
- * @param args
163
+ * @param length - Length of the random string (default: 32)
164
+ * @returns A cryptographically secure random string
55
165
  */
56
- const dump = (...args) => {
57
- args.forEach((thing) => {
58
- console.log(inspect(thing));
166
+ const randomSecure = (length = 32) => {
167
+ return randomBytes(Math.ceil(length / 2)).toString("hex").slice(0, length);
168
+ };
169
+ /**
170
+ * Hash a string using the specified algorithm.
171
+ *
172
+ * @param data - Data to hash
173
+ * @param algorithm - Hash algorithm (default: 'sha256')
174
+ * @returns Hexadecimal hash string
175
+ */
176
+ const hash = (data, algorithm = "sha256") => {
177
+ return createHash(algorithm).update(data).digest("hex");
178
+ };
179
+ /**
180
+ * Hash a string with salt using HMAC.
181
+ *
182
+ * @param data - Data to hash
183
+ * @param key - Secret key for HMAC
184
+ * @param algorithm - Hash algorithm (default: 'sha256')
185
+ * @returns Hexadecimal hash string
186
+ */
187
+ const hmac = (data, key, algorithm = "sha256") => {
188
+ return createHmac(algorithm, key).update(data).digest("hex");
189
+ };
190
+ /**
191
+ * Encode data to base64.
192
+ *
193
+ * @param data - Data to encode
194
+ * @returns Base64 encoded string
195
+ */
196
+ const base64Encode = (data) => {
197
+ return Buffer.from(data, "utf8").toString("base64");
198
+ };
199
+ /**
200
+ * Decode base64 data.
201
+ *
202
+ * @param data - Base64 string to decode
203
+ * @returns Decoded string
204
+ */
205
+ const base64Decode = (data) => {
206
+ return Buffer.from(data, "base64").toString("utf8");
207
+ };
208
+ /**
209
+ * Simple XOR encryption/decryption.
210
+ *
211
+ * @param data - Data to encrypt/decrypt
212
+ * @param key - Encryption key
213
+ * @returns Encrypted/decrypted string
214
+ */
215
+ const xor = (data, key) => {
216
+ let result = "";
217
+ const keyLength = key.length;
218
+ for (let i = 0; i < data.length; i++) {
219
+ const dataCharCode = data.charCodeAt(i);
220
+ const keyCharCode = key.charCodeAt(i % keyLength);
221
+ result += String.fromCharCode(dataCharCode ^ keyCharCode);
222
+ }
223
+ return result;
224
+ };
225
+ /**
226
+ * Generate a random hex color code.
227
+ *
228
+ * @returns A hex color code string (e.g., '#a3b2f3')
229
+ */
230
+ const randomColor = () => {
231
+ return `#${random(6, "0123456789abcdef").toLowerCase()}`;
232
+ };
233
+ const randomPassword = (length = 16, options = {}) => {
234
+ const opts = {
235
+ useUppercase: true,
236
+ useLowercase: true,
237
+ useNumbers: true,
238
+ useSymbols: true,
239
+ ...options
240
+ };
241
+ let charset = "";
242
+ if (opts.useUppercase) charset += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
243
+ if (opts.useLowercase) charset += "abcdefghijklmnopqrstuvwxyz";
244
+ if (opts.useNumbers) charset += "0123456789";
245
+ if (opts.useSymbols) charset += "!@#$%^&*()_+-=[]{}|;:,.<>?";
246
+ if (charset.length === 0) throw new Error("At least one character type must be enabled");
247
+ return random(length, charset);
248
+ };
249
+ /**
250
+ * Generate a cryptographically secure token for APIs, sessions, etc.
251
+ *
252
+ * @param strength - Token strength (bytes) (default: 32)
253
+ * @returns A secure token string
254
+ */
255
+ const secureToken = (strength = 32) => {
256
+ return randomBytes(strength).toString("hex");
257
+ };
258
+ /**
259
+ * Create a checksum for data integrity verification.
260
+ *
261
+ * @param data - Data to create checksum for
262
+ * @param algorithm - Hash algorithm (default: 'sha256')
263
+ * @returns SHA256 checksum
264
+ */
265
+ const checksum = (data, algorithm = "sha256") => {
266
+ return hash(data, algorithm);
267
+ };
268
+ /**
269
+ * Verify data integrity using checksum.
270
+ *
271
+ * @param data - Data to verify
272
+ * @param expectedChecksum - Expected checksum
273
+ * @param algorithm - Hash algorithm (default: 'sha256')
274
+ * @returns True if checksums match
275
+ */
276
+ const verifyChecksum = (data, expectedChecksum, algorithm = "sha256") => {
277
+ return checksum(data, algorithm) === expectedChecksum;
278
+ };
279
+ /**
280
+ * Simple Caesar cipher implementation.
281
+ *
282
+ * @param text - Text to encrypt/decrypt
283
+ * @param shift - Number of positions to shift (default: 13)
284
+ * @returns Encrypted/decrypted text
285
+ */
286
+ const caesarCipher = (text, shift$1 = 13) => {
287
+ return text.replace(/[a-zA-Z]/g, (char) => {
288
+ const baseCharCode = char === char.toUpperCase() ? "A" : "a";
289
+ const shiftedCharCode = (char.charCodeAt(0) - baseCharCode.charCodeAt(0) + shift$1) % 26;
290
+ const newCharCode = (shiftedCharCode < 0 ? 26 + shiftedCharCode : shiftedCharCode) + baseCharCode.charCodeAt(0);
291
+ return String.fromCharCode(newCharCode);
59
292
  });
60
293
  };
61
294
 
62
295
  //#endregion
63
296
  //#region src/Helpers/Number.ts
297
+ var Number_exports = /* @__PURE__ */ __export({
298
+ abbreviate: () => abbreviate,
299
+ humanize: () => humanize,
300
+ toBytes: () => toBytes,
301
+ toHumanTime: () => toHumanTime
302
+ });
64
303
  /**
65
304
  * Abbreviates large numbers using SI symbols (K, M, B...)
66
305
  * and formats the output according to the given locale.
@@ -160,10 +399,10 @@ const humanize = (num, slugify$1) => {
160
399
  if (numString.length == 3) if (numString[1] === "0" && numString[2] === "0") return ones[numString[0]] + " hundred";
161
400
  else return ones[numString[0]] + " hundred and " + humanize(+((numString[1] || "") + numString[2]), slugify$1);
162
401
  if (numString.length === 4) {
163
- const end = +((numString[1] || "") + numString[2] + numString[3]);
164
- if (end === 0) return ones[numString[0]] + " thousand";
165
- if (end < 100) return ones[numString[0]] + " thousand and " + humanize(end, slugify$1);
166
- return ones[numString[0]] + " thousand " + humanize(end, slugify$1);
402
+ const end$1 = +((numString[1] || "") + numString[2] + numString[3]);
403
+ if (end$1 === 0) return ones[numString[0]] + " thousand";
404
+ if (end$1 < 100) return ones[numString[0]] + " thousand and " + humanize(end$1, slugify$1);
405
+ return ones[numString[0]] + " thousand " + humanize(end$1, slugify$1);
167
406
  }
168
407
  return num;
169
408
  };
@@ -226,12 +465,21 @@ const toHumanTime = (seconds = 0, worded = false) => {
226
465
  }
227
466
  const hh = hours > 0 ? `${hours}:` : "";
228
467
  const mm = (hours > 0 && minutes < 10 ? `0${minutes}` : minutes) + ":";
229
- const ss = secs < 10 ? `0${secs}` : secs;
230
- return `${hh}${mm}${ss}`;
468
+ const ss$1 = secs < 10 ? `0${secs}` : secs;
469
+ return `${hh}${mm}${ss$1}`;
231
470
  };
232
471
 
233
472
  //#endregion
234
473
  //#region src/Helpers/Obj.ts
474
+ var Obj_exports = /* @__PURE__ */ __export({
475
+ dot: () => dot,
476
+ extractProperties: () => extractProperties,
477
+ getValue: () => getValue,
478
+ modObj: () => modObj,
479
+ safeDot: () => safeDot,
480
+ setNested: () => setNested,
481
+ slugifyKeys: () => slugifyKeys
482
+ });
235
483
  /**
236
484
  * Flattens a nested object into a single-level object
237
485
  * with dot-separated keys.
@@ -376,6 +624,33 @@ const slugifyKeys = (obj, only = [], separator = "_") => {
376
624
 
377
625
  //#endregion
378
626
  //#region src/Helpers/Str.ts
627
+ var Str_exports = /* @__PURE__ */ __export({
628
+ after: () => after,
629
+ afterLast: () => afterLast,
630
+ before: () => before,
631
+ beforeLast: () => beforeLast,
632
+ capitalize: () => capitalize,
633
+ chop: () => chop,
634
+ esc: () => esc,
635
+ firstLines: () => firstLines,
636
+ isInteger: () => isInteger,
637
+ isNumber: () => isNumber,
638
+ lastLines: () => lastLines,
639
+ padString: () => padString,
640
+ pluralize: () => pluralize,
641
+ replacePunctuation: () => replacePunctuation,
642
+ rot: () => rot,
643
+ singularize: () => singularize,
644
+ slugify: () => slugify,
645
+ split: () => split,
646
+ ss: () => ss,
647
+ sub: () => sub,
648
+ subString: () => subString,
649
+ substitute: () => substitute,
650
+ substr: () => substr,
651
+ translate: () => translate,
652
+ truncate: () => truncate
653
+ });
379
654
  /**
380
655
  * Get the portion of the string after the first occurrence of the given value.
381
656
  *
@@ -424,22 +699,13 @@ const beforeLast = (value, search) => {
424
699
  const lastIndex = value.lastIndexOf(search);
425
700
  return lastIndex !== -1 ? value.slice(0, lastIndex) : value;
426
701
  };
427
- /**
428
- * Capitalizes the first character of a string.
429
- *
430
- * @param str - The input string
431
- * @returns The string with the first character capitalized
432
- */
702
+ /** Capitalizes the first character of a string. */
433
703
  function capitalize(str) {
434
704
  if (!str) return "";
435
705
  return str[0].toUpperCase() + str.slice(1);
436
706
  }
437
707
  /**
438
708
  * Returns the pluralized form of a word based on the given number.
439
- *
440
- * @param word - The word to pluralize
441
- * @param count - The number determining pluralization
442
- * @returns Singular if count === 1, otherwise plural form
443
709
  */
444
710
  const pluralize = (word, count) => {
445
711
  if (count === 1) return word;
@@ -459,16 +725,11 @@ const pluralize = (word, count) => {
459
725
  "i",
460
726
  "o",
461
727
  "u"
462
- ].includes(word[word.length - 2]?.toLowerCase() ?? "")) return word.slice(0, -1) + "ies";
728
+ ].includes(word.at(-2)?.toLowerCase() ?? "")) return word.slice(0, -1) + "ies";
463
729
  if (/(s|ss|sh|ch|x|z)$/i.test(word)) return word + "es";
464
730
  return word + "s";
465
731
  };
466
- /**
467
- * Converts a plural English word into its singular form.
468
- *
469
- * @param word - The word to singularize
470
- * @returns The singular form of the word
471
- */
732
+ /** Converts a plural English word into its singular form. */
472
733
  const singularize = (word) => {
473
734
  const irregulars = {
474
735
  feet: "foot",
@@ -485,42 +746,17 @@ const singularize = (word) => {
485
746
  if (/s$/i.test(word) && word.length > 1) return word.replace(/s$/i, "");
486
747
  return word;
487
748
  };
488
- /**
489
- * Converts a string into a slug format.
490
- * Handles camelCase, spaces, and non-alphanumeric characters.
491
- *
492
- * @param str - The input string to slugify
493
- * @param joiner - The character used to join words (default: "_")
494
- * @returns A slugified string
495
- */
749
+ /** Converts a string into a slug format. */
496
750
  const slugify = (str, joiner = "_") => {
497
- return str.replace(/([a-z])([A-Z])/g, `$1${joiner}$2`).replace(/[\s\W]+/g, joiner).replace(new RegExp(`${joiner}{2,}`, "g"), joiner).replace(new RegExp(`^${joiner}|${joiner}$`, "g"), "").toLowerCase();
751
+ return str.replace(/([a-z])([A-Z])/g, `$1${joiner}$2`).replace(/[\s\W]+/g, joiner).replace(new RegExp(`${joiner}{2,}`, "g"), joiner).toLowerCase();
498
752
  };
499
- /**
500
- * Truncates a string to a specified length and appends an ellipsis if needed.
501
- *
502
- * @param str - The input string
503
- * @param len - Maximum length of the result (including ellipsis)
504
- * @param ellipsis - String to append if truncated (default: "...")
505
- * @returns The truncated string
506
- */
753
+ /** Truncates a string to a specified length and appends an ellipsis if needed. */
507
754
  const subString = (str, len, ellipsis = "...") => {
508
755
  if (!str) return "";
509
756
  if (len <= ellipsis.length) return ellipsis;
510
757
  return str.length > len ? str.substring(0, len - ellipsis.length).trimEnd() + ellipsis : str;
511
758
  };
512
- /**
513
- * Replaces placeholders in a string with corresponding values from a data object.
514
- *
515
- * Example:
516
- * substitute("Hello { user.name }!", { user: { name: "John" } })
517
- * // "Hello John!"
518
- *
519
- * @param str - The string containing placeholders wrapped in { } braces.
520
- * @param data - Object containing values to substitute. Supports nested keys via dot notation.
521
- * @param def - Default value to use if a key is missing. (Optional)
522
- * @returns The substituted string or undefined if the input string or data is invalid.
523
- */
759
+ /** Substitute placeholders { key } using object with dot notation. */
524
760
  const substitute = (str, data = {}, def) => {
525
761
  if (!str || !data) return void 0;
526
762
  const regex = /{\s*([a-zA-Z0-9_.]+)\s*}/g;
@@ -530,21 +766,588 @@ const substitute = (str, data = {}, def) => {
530
766
  return value !== void 0 ? String(value) : def ?? "";
531
767
  });
532
768
  };
533
- /**
534
- * Truncates a string to a specified length, removing HTML tags and
535
- * appending a suffix if the string exceeds the length.
536
- *
537
- * @param str - The string to truncate
538
- * @param len - Maximum length (default: 20)
539
- * @param suffix - Suffix to append if truncated (default: "...")
540
- * @returns The truncated string
541
- */
769
+ /** Truncate string removing HTML tags and append suffix if needed. */
542
770
  const truncate = (str, len = 20, suffix = "...") => {
543
771
  if (!str) return "";
544
772
  const clean = str.replace(/<[^>]+>/g, "");
545
773
  return (clean.length > len ? clean.substring(0, len - suffix.length) + suffix : clean).replace(/\n/g, " ").replace(/* @__PURE__ */ new RegExp(`\\s+${suffix.replace(/\./g, "\\.")}$`), suffix);
546
774
  };
775
+ /** Get substring from offset/length similar to PHP substr. */
776
+ const substr = (string, offset, length) => {
777
+ if (offset < 0) offset += string.length;
778
+ if (length === void 0) return string.substring(offset);
779
+ return string.substring(offset, offset + length);
780
+ };
781
+ /** Get substring by start/stop indexes. */
782
+ const sub = (string, start$1, stop) => string.substring(start$1, stop);
783
+ /** Escape string for JSON encoding (returns string without quotes). */
784
+ const esc = (string) => JSON.stringify(string).slice(1, -1);
785
+ /** Padding to a fixed size, right by default. */
786
+ const padString = (string, size, padString$1 = " ", padRight = true) => {
787
+ if (string.length >= size) return string;
788
+ const pad = padString$1.repeat(size - string.length);
789
+ return padRight ? string + pad : pad + string;
790
+ };
791
+ /** Split by delimiter with edge-case rule. */
792
+ const split = (string, delimiter) => {
793
+ if (string.startsWith(delimiter) || string.endsWith(delimiter)) return [""];
794
+ return string.split(delimiter);
795
+ };
796
+ /** Returns all the characters except the last. */
797
+ const chop = (string) => string.slice(0, -1);
798
+ /** Number checks. */
799
+ const isNumber = (string) => !isNaN(Number(string)) && string.trim() !== "";
800
+ const isInteger = (string) => Number.isInteger(Number(string)) && string.trim() !== "";
801
+ /** ROT-N cipher. */
802
+ const rot = (string, n = 13) => {
803
+ return string.replace(/[a-zA-Z]/g, (char) => {
804
+ const code = char.charCodeAt(0);
805
+ const start$1 = char >= "a" ? "a".charCodeAt(0) : "A".charCodeAt(0);
806
+ const end$1 = char >= "a" ? "z".charCodeAt(0) : "Z".charCodeAt(0);
807
+ let next = code + n;
808
+ while (next < start$1) next += 26;
809
+ while (next > end$1) next -= 26;
810
+ return String.fromCharCode(next);
811
+ });
812
+ };
813
+ /** Replace trailing punctuation with new format. */
814
+ const replacePunctuation = (string, newFormat) => string.replace(/[.,;:!?]*$/, "") + newFormat;
815
+ /** Array/object driven text replacement. */
816
+ const translate = (string, replacements) => {
817
+ let result = string;
818
+ if (Array.isArray(replacements)) for (const [from, to] of replacements) result = result.replace(new RegExp(from, "g"), to);
819
+ else for (const [from, to] of Object.entries(replacements)) result = result.replace(new RegExp(from, "g"), to);
820
+ return result;
821
+ };
822
+ /** Strip slashes recursively. */
823
+ const ss = (string) => string.replace(/\\(.)/g, "$1");
824
+ /** First and last N lines. */
825
+ const firstLines = (string, amount = 1) => string.split("\n").slice(0, amount).join("\n");
826
+ const lastLines = (string, amount = 1) => string.split("\n").slice(-amount).join("\n");
827
+
828
+ //#endregion
829
+ //#region src/Helpers/Time.ts
830
+ var Time_exports = /* @__PURE__ */ __export({
831
+ add: () => add,
832
+ dayOfYear: () => dayOfYear,
833
+ diff: () => diff,
834
+ end: () => end,
835
+ firstDayOfMonth: () => firstDayOfMonth,
836
+ format: () => format,
837
+ fromNow: () => fromNow,
838
+ fromTimestamp: () => fromTimestamp,
839
+ isBetween: () => isBetween,
840
+ isLeapYear: () => isLeapYear,
841
+ lastDayOfMonth: () => lastDayOfMonth,
842
+ now: () => now,
843
+ randomTime: () => randomTime,
844
+ start: () => start,
845
+ subtract: () => subtract,
846
+ unix: () => unix
847
+ });
848
+ /**
849
+ * Get current timestamp in milliseconds.
850
+ *
851
+ * @returns Current timestamp as number
852
+ */
853
+ const now = () => {
854
+ return Date.now();
855
+ };
856
+ /**
857
+ * Get current Unix timestamp.
858
+ *
859
+ * @returns Current Unix timestamp
860
+ */
861
+ const unix = () => {
862
+ return Math.floor(Date.now() / 1e3);
863
+ };
864
+ /**
865
+ * Format a date string according to a specified format (UTC-based for determinism).
866
+ *
867
+ * @param date - Date string or Date object
868
+ * @param format - Format to output (default: 'Y-m-d H:i:s')
869
+ * @returns Formatted date string
870
+ */
871
+ const format = (date, format$1 = "Y-m-d H:i:s") => {
872
+ const d = new Date(date);
873
+ if (isNaN(d.getTime())) throw new Error("Invalid date provided");
874
+ const year = d.getUTCFullYear();
875
+ const month = String(d.getUTCMonth() + 1).padStart(2, "0");
876
+ const day = String(d.getUTCDate()).padStart(2, "0");
877
+ const hours = String(d.getUTCHours()).padStart(2, "0");
878
+ const minutes = String(d.getUTCMinutes()).padStart(2, "0");
879
+ const seconds = String(d.getUTCSeconds()).padStart(2, "0");
880
+ const monthNames = [
881
+ "January",
882
+ "February",
883
+ "March",
884
+ "April",
885
+ "May",
886
+ "June",
887
+ "July",
888
+ "August",
889
+ "September",
890
+ "October",
891
+ "November",
892
+ "December"
893
+ ];
894
+ const monthNamesShort = [
895
+ "Jan",
896
+ "Feb",
897
+ "Mar",
898
+ "Apr",
899
+ "May",
900
+ "Jun",
901
+ "Jul",
902
+ "Aug",
903
+ "Sep",
904
+ "Oct",
905
+ "Nov",
906
+ "Dec"
907
+ ];
908
+ const dayNames = [
909
+ "Sun",
910
+ "Mon",
911
+ "Tue",
912
+ "Wed",
913
+ "Thu",
914
+ "Fri",
915
+ "Sat"
916
+ ];
917
+ switch (format$1) {
918
+ case "Y-m-d": return `${year}-${month}-${day}`;
919
+ case "Y-m-d H:i:s": return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
920
+ case "d-m-Y": return `${day}-${month}-${year}`;
921
+ case "d/m/Y": return `${day}/${month}/${year}`;
922
+ case "M j, Y": return `${monthNamesShort[d.getUTCMonth()]} ${d.getUTCDate()}, ${year}`;
923
+ case "F j, Y": return `${monthNames[d.getUTCMonth()]} ${d.getUTCDate()}, ${year}`;
924
+ case "D j M": return `${dayNames[d.getUTCDay()]} ${d.getUTCDate()} ${monthNamesShort[d.getUTCMonth()]}`;
925
+ case "timestamp": return d.toISOString();
926
+ case "unix": return Math.floor(d.getTime() / 1e3).toString();
927
+ default: return d.toISOString();
928
+ }
929
+ };
930
+ /**
931
+ * Create a date for a given timestamp.
932
+ *
933
+ * @param timestamp - Unix timestamp
934
+ * @returns Date object
935
+ */
936
+ const fromTimestamp = (timestamp) => {
937
+ return /* @__PURE__ */ new Date(timestamp * 1e3);
938
+ };
939
+ /**
940
+ * Return the difference for given date in seconds.
941
+ *
942
+ * @param date - Date to compare
943
+ * @param referenceDate - Reference date (optional, defaults to now)
944
+ * @returns Number of seconds difference
945
+ */
946
+ const diff = (date, referenceDate) => {
947
+ const d1 = new Date(date);
948
+ const d2 = referenceDate ? new Date(referenceDate) : /* @__PURE__ */ new Date();
949
+ if (isNaN(d1.getTime()) || isNaN(d2.getTime())) throw new Error("Invalid date provided");
950
+ return Math.floor((d2.getTime() - d1.getTime()) / 1e3);
951
+ };
952
+ /**
953
+ * Subtract time from the given date.
954
+ */
955
+ const subtract = (date, amount = 1, unit = "days") => {
956
+ const d = new Date(date);
957
+ if (isNaN(d.getTime())) throw new Error("Invalid date provided");
958
+ const multiplier = {
959
+ milliseconds: 1,
960
+ seconds: 1e3,
961
+ minutes: 60 * 1e3,
962
+ hours: 3600 * 1e3,
963
+ days: 1440 * 60 * 1e3
964
+ }[unit] || 1e3;
965
+ return new Date(d.getTime() - amount * multiplier);
966
+ };
967
+ /**
968
+ * Add time to the given date.
969
+ */
970
+ const add = (date, amount = 1, unit = "days") => {
971
+ const d = new Date(date);
972
+ if (isNaN(d.getTime())) throw new Error("Invalid date provided");
973
+ const multiplier = {
974
+ milliseconds: 1,
975
+ seconds: 1e3,
976
+ minutes: 60 * 1e3,
977
+ hours: 3600 * 1e3,
978
+ days: 1440 * 60 * 1e3
979
+ }[unit] || 1e3;
980
+ return new Date(d.getTime() + amount * multiplier);
981
+ };
982
+ /**
983
+ * Start time of a specific unit.
984
+ */
985
+ const start = (date, unit = "days") => {
986
+ const d = new Date(date);
987
+ if (isNaN(d.getTime())) throw new Error("Invalid date provided");
988
+ const newDt = new Date(d);
989
+ switch (unit) {
990
+ case "days":
991
+ newDt.setHours(0, 0, 0, 0);
992
+ break;
993
+ case "hours":
994
+ newDt.setMinutes(0, 0, 0);
995
+ break;
996
+ case "minutes":
997
+ newDt.setSeconds(0, 0);
998
+ break;
999
+ case "seconds":
1000
+ newDt.setMilliseconds(0);
1001
+ break;
1002
+ case "milliseconds": break;
1003
+ }
1004
+ return newDt;
1005
+ };
1006
+ /**
1007
+ * End time of a specific unit.
1008
+ */
1009
+ const end = (date, unit = "days") => {
1010
+ const d = new Date(date);
1011
+ if (isNaN(d.getTime())) throw new Error("Invalid date provided");
1012
+ const newDt = new Date(d);
1013
+ switch (unit) {
1014
+ case "days":
1015
+ newDt.setHours(23, 59, 59, 999);
1016
+ break;
1017
+ case "hours":
1018
+ newDt.setMinutes(59, 59, 999);
1019
+ break;
1020
+ case "minutes":
1021
+ newDt.setSeconds(59, 999);
1022
+ break;
1023
+ case "seconds":
1024
+ newDt.setMilliseconds(999);
1025
+ break;
1026
+ case "milliseconds": break;
1027
+ }
1028
+ return newDt;
1029
+ };
1030
+ /**
1031
+ * Get the difference in days from today.
1032
+ */
1033
+ const fromNow = (date) => {
1034
+ return diff(date) / (1440 * 60);
1035
+ };
1036
+ /**
1037
+ * Get a random time between the specified hour and minute.
1038
+ */
1039
+ const randomTime = (startHour = 9, startMinute = 0, endHour = 17, endMinute = 0) => {
1040
+ const today = /* @__PURE__ */ new Date();
1041
+ const startMinutes = startHour * 60 + startMinute;
1042
+ const endMinutes = endHour * 60 + endMinute;
1043
+ const randomMinutes = Math.floor(Math.random() * (endMinutes - startMinutes)) + startMinutes;
1044
+ const hour = Math.floor(randomMinutes / 60);
1045
+ const minute = randomMinutes % 60;
1046
+ const date = new Date(today);
1047
+ date.setHours(hour, minute, 0, 0);
1048
+ return date;
1049
+ };
1050
+ /**
1051
+ * Check if the current time is between the specified durations.
1052
+ */
1053
+ const isBetween = (startTime, endTime) => {
1054
+ const now$1 = /* @__PURE__ */ new Date();
1055
+ const currentHours = now$1.getHours();
1056
+ const currentMinutes = now$1.getMinutes();
1057
+ const currentTotalMinutes = currentHours * 60 + currentMinutes;
1058
+ const parseTime = (timeStr) => {
1059
+ const [hours, minutes] = timeStr.split(":").map(Number);
1060
+ return hours * 60 + minutes;
1061
+ };
1062
+ const startTotalMinutes = parseTime(startTime);
1063
+ const endTotalMinutes = parseTime(endTime);
1064
+ if (startTotalMinutes <= endTotalMinutes) return currentTotalMinutes >= startTotalMinutes && currentTotalMinutes <= endTotalMinutes;
1065
+ else return currentTotalMinutes >= startTotalMinutes || currentTotalMinutes <= endTotalMinutes;
1066
+ };
1067
+ /** Day of year, first/last day of month, leap year checks. */
1068
+ const dayOfYear = (date = /* @__PURE__ */ new Date()) => {
1069
+ const d = new Date(date);
1070
+ const start$1 = new Date(Date.UTC(d.getUTCFullYear(), 0, 0));
1071
+ const diff$1 = d.getTime() - start$1.getTime();
1072
+ return Math.floor(diff$1 / (1e3 * 60 * 60 * 24));
1073
+ };
1074
+ const firstDayOfMonth = (date = /* @__PURE__ */ new Date()) => {
1075
+ const d = new Date(date);
1076
+ return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1));
1077
+ };
1078
+ const lastDayOfMonth = (date = /* @__PURE__ */ new Date()) => {
1079
+ const d = new Date(date);
1080
+ return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0));
1081
+ };
1082
+ const isLeapYear = (year = (/* @__PURE__ */ new Date()).getUTCFullYear()) => {
1083
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
1084
+ };
1085
+
1086
+ //#endregion
1087
+ //#region src/Helpers/DumpDie.ts
1088
+ const inspect = (thing) => {
1089
+ return util.inspect(thing, {
1090
+ showHidden: true,
1091
+ depth: null,
1092
+ colors: true
1093
+ });
1094
+ };
1095
+ /**
1096
+ * Dump something and kill the process for quick debugging. Based on Laravel's dd()
1097
+ *
1098
+ * @param args
1099
+ */
1100
+ const dd = (...args) => {
1101
+ args.forEach((thing) => {
1102
+ console.log(inspect(thing));
1103
+ });
1104
+ process.exit(1);
1105
+ };
1106
+ /**
1107
+ * Dump something but keep the process for quick debugging. Based on Laravel's dump()
1108
+ *
1109
+ * @param args
1110
+ */
1111
+ const dump = (...args) => {
1112
+ args.forEach((thing) => {
1113
+ console.log(inspect(thing));
1114
+ });
1115
+ };
1116
+
1117
+ //#endregion
1118
+ //#region src/GlobalBootstrap.ts
1119
+ /**
1120
+ * Bootstrap the global helpers into the global scope.
1121
+ * This enables optional global access to all helper functions.
1122
+ *
1123
+ * Example usage:
1124
+ * ```typescript
1125
+ * import { bootstrap } from '@h3ravel/support'
1126
+ *
1127
+ * // Make helpers globally available
1128
+ * bootstrap()
1129
+ *
1130
+ * // Now you can use:
1131
+ * Arr.chunk([1, 2, 3, 4], 2)
1132
+ * // or directly:
1133
+ * chunk([1, 2, 3, 4], 2)
1134
+ * Str.capitalize('hello world')
1135
+ * // or directly:
1136
+ * capitalize('hello world')
1137
+ * ```
1138
+ *
1139
+ * @param target - The target object to attach helpers to (default: globalThis)
1140
+ */
1141
+ function bootstrap(target = globalThis) {
1142
+ const globalHelpers = {
1143
+ Arr: Arr_exports,
1144
+ Crypto: Crypto_exports,
1145
+ Number: Number_exports,
1146
+ Obj: Obj_exports,
1147
+ Str: Str_exports,
1148
+ Time: Time_exports,
1149
+ chunk,
1150
+ collapse,
1151
+ alternate,
1152
+ combine,
1153
+ find,
1154
+ forget,
1155
+ first,
1156
+ last,
1157
+ isEmpty,
1158
+ isNotEmpty,
1159
+ pop,
1160
+ prepend,
1161
+ take,
1162
+ reverse,
1163
+ shift,
1164
+ range,
1165
+ flatten,
1166
+ after,
1167
+ afterLast,
1168
+ before,
1169
+ beforeLast,
1170
+ capitalize,
1171
+ pluralize,
1172
+ singularize,
1173
+ slugify,
1174
+ subString,
1175
+ substitute,
1176
+ truncate,
1177
+ substr,
1178
+ sub,
1179
+ esc,
1180
+ padString,
1181
+ split,
1182
+ chop,
1183
+ isNumber,
1184
+ isInteger,
1185
+ rot,
1186
+ replacePunctuation,
1187
+ translate,
1188
+ ss,
1189
+ firstLines,
1190
+ lastLines,
1191
+ dot,
1192
+ extractProperties,
1193
+ getValue,
1194
+ modObj,
1195
+ safeDot,
1196
+ setNested,
1197
+ slugifyKeys,
1198
+ uuid,
1199
+ random,
1200
+ randomSecure,
1201
+ hash,
1202
+ hmac,
1203
+ base64Encode,
1204
+ base64Decode,
1205
+ xor,
1206
+ randomColor,
1207
+ randomPassword,
1208
+ secureToken,
1209
+ checksum,
1210
+ verifyChecksum,
1211
+ caesarCipher,
1212
+ now,
1213
+ unix,
1214
+ format,
1215
+ fromTimestamp,
1216
+ diff,
1217
+ subtract,
1218
+ add,
1219
+ start,
1220
+ end,
1221
+ fromNow,
1222
+ randomTime,
1223
+ isBetween,
1224
+ dayOfYear,
1225
+ firstDayOfMonth,
1226
+ lastDayOfMonth,
1227
+ isLeapYear,
1228
+ abbreviate,
1229
+ humanize,
1230
+ toBytes,
1231
+ toHumanTime,
1232
+ dump,
1233
+ dd
1234
+ };
1235
+ Object.assign(target, globalHelpers);
1236
+ }
1237
+ /**
1238
+ * Clean up global helpers by removing them from the global scope.
1239
+ * This function removes all global helper attachments.
1240
+ *
1241
+ * @param target - The target object to clean up (default: globalThis)
1242
+ */
1243
+ function cleanBootstrap(target = globalThis) {
1244
+ [
1245
+ "Arr",
1246
+ "chunk",
1247
+ "collapse",
1248
+ "alternate",
1249
+ "combine",
1250
+ "each",
1251
+ "keys",
1252
+ "find",
1253
+ "forget",
1254
+ "first",
1255
+ "last",
1256
+ "isEmpty",
1257
+ "isNotEmpty",
1258
+ "pop",
1259
+ "prepend",
1260
+ "take",
1261
+ "reverse",
1262
+ "shift",
1263
+ "range",
1264
+ "where",
1265
+ "skip",
1266
+ "flatten",
1267
+ "Str",
1268
+ "after",
1269
+ "afterLast",
1270
+ "before",
1271
+ "beforeLast",
1272
+ "capitalize",
1273
+ "pluralize",
1274
+ "singularize",
1275
+ "slugify",
1276
+ "subString",
1277
+ "substitute",
1278
+ "truncate",
1279
+ "startsWith",
1280
+ "endsWith",
1281
+ "substr",
1282
+ "sub",
1283
+ "esc",
1284
+ "padString",
1285
+ "trim",
1286
+ "ltrim",
1287
+ "rtrim",
1288
+ "trimChars",
1289
+ "split",
1290
+ "chop",
1291
+ "isNumber",
1292
+ "isInteger",
1293
+ "rot",
1294
+ "replacePunctuation",
1295
+ "translate",
1296
+ "ss",
1297
+ "firstLines",
1298
+ "lastLines",
1299
+ "Obj",
1300
+ "dot",
1301
+ "extractProperties",
1302
+ "getValue",
1303
+ "modObj",
1304
+ "safeDot",
1305
+ "setNested",
1306
+ "slugifyKeys",
1307
+ "Crypto",
1308
+ "uuid",
1309
+ "random",
1310
+ "randomSecure",
1311
+ "hash",
1312
+ "hmac",
1313
+ "base64Encode",
1314
+ "base64Decode",
1315
+ "xor",
1316
+ "randomColor",
1317
+ "randomPassword",
1318
+ "secureToken",
1319
+ "checksum",
1320
+ "verifyChecksum",
1321
+ "caesarCipher",
1322
+ "Time",
1323
+ "now",
1324
+ "unix",
1325
+ "format",
1326
+ "fromTimestamp",
1327
+ "diff",
1328
+ "subtract",
1329
+ "add",
1330
+ "start",
1331
+ "end",
1332
+ "fromNow",
1333
+ "randomTime",
1334
+ "isBetween",
1335
+ "dayOfYear",
1336
+ "firstDayOfMonth",
1337
+ "lastDayOfMonth",
1338
+ "isLeapYear",
1339
+ "Number",
1340
+ "abbreviate",
1341
+ "humanize",
1342
+ "toBytes",
1343
+ "toHumanTime",
1344
+ "dump",
1345
+ "dd"
1346
+ ].forEach((helper) => {
1347
+ if (helper in target) delete target[helper];
1348
+ });
1349
+ }
547
1350
 
548
1351
  //#endregion
549
- export { abbreviate, after, afterLast, before, beforeLast, capitalize, chunk, dd, dot, dump, extractProperties, getValue, humanize, modObj, pluralize, range, safeDot, setNested, singularize, slugify, slugifyKeys, subString, substitute, toBytes, toHumanTime, truncate };
1352
+ export { abbreviate, add, after, afterLast, alternate, base64Decode, base64Encode, before, beforeLast, bootstrap, caesarCipher, capitalize, checksum, chop, chunk, cleanBootstrap, collapse, combine, dayOfYear, dd, diff, dot, dump, end, esc, extractProperties, find, first, firstDayOfMonth, firstLines, flatten, forget, format, fromNow, fromTimestamp, getValue, hash, hmac, humanize, isBetween, isEmpty, isInteger, isLeapYear, isNotEmpty, isNumber, last, lastDayOfMonth, lastLines, modObj, now, padString, pluralize, pop, prepend, random, randomColor, randomPassword, randomSecure, randomTime, range, replacePunctuation, reverse, rot, safeDot, secureToken, setNested, shift, singularize, slugify, slugifyKeys, split, ss, start, sub, subString, substitute, substr, subtract, take, toBytes, toHumanTime, translate, truncate, unix, uuid, verifyChecksum, xor };
550
1353
  //# sourceMappingURL=index.js.map