@h3ravel/support 0.10.4 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["chunks: T[][]","slugify","numString: string","slugify","irregularPlurals: Record<string, string>","irregulars: Record<string, string>"],"sources":["../src/Helpers/Arr.ts","../src/Helpers/DumpDie.ts","../src/Helpers/Number.ts","../src/Helpers/Obj.ts","../src/Helpers/Str.ts"],"sourcesContent":["/**\n * Splits an array into chunks of a specified size.\n *\n * @template T - Type of elements in the array\n * @param arr - The input array\n * @param size - Size of each chunk (default: 2)\n * @returns An array of chunks (arrays)\n */\nexport const chunk = <T> (arr: T[], size: number = 2): T[][] => {\n if (size <= 0) throw new Error('Chunk size must be greater than 0')\n\n const chunks: T[][] = []\n\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size))\n }\n\n return chunks\n}\n\n\n/**\n * Generates an array of sequential numbers.\n *\n * @param size - Number of elements in the range\n * @param startAt - Starting number (default: 0)\n * @returns An array of numbers from startAt to startAt + size - 1\n */\nexport const range = (size: number, startAt: number = 0): number[] => {\n if (size <= 0 || !Number.isFinite(size)) return []\n\n return Array.from({ length: size }, (_, i) => startAt + i)\n}\n","import process from 'process'\nimport util from 'util'\n\nconst inspect = (thing: any) => {\n return util.inspect(thing, {\n showHidden: true,\n depth: null,\n colors: true\n })\n}\n\n/**\n * Dump something and kill the process for quick debugging. Based on Laravel's dd()\n * \n * @param args \n */\nexport const dd = (...args: unknown[]): never => {\n args.forEach((thing) => {\n console.log(inspect(thing))\n })\n\n process.exit(1)\n}\n\n/**\n * Dump something but keep the process for quick debugging. Based on Laravel's dump()\n * \n * @param args \n */\nexport const dump = (...args: unknown[]): void => {\n args.forEach((thing) => {\n console.log(inspect(thing))\n })\n} \n","/**\n * Abbreviates large numbers using SI symbols (K, M, B...) \n * and formats the output according to the given locale.\n *\n * @param value - The number to abbreviate\n * @param locale - Optional locale string (default: \"en-US\")\n * @returns A localized, abbreviated number string\n */\nexport const abbreviate = (value?: number, locale: string = 'en-US'): string => {\n if (!value) return '0'\n\n // Numbers less than 1000 don't need abbreviation\n if (value < 1000) {\n return new Intl.NumberFormat(locale).format(value)\n }\n\n const si = [\n { v: 1e18, s: 'E' },\n { v: 1e15, s: 'P' },\n { v: 1e12, s: 'T' },\n { v: 1e9, s: 'B' },\n { v: 1e6, s: 'M' },\n { v: 1e3, s: 'K' },\n ]\n\n const match = si.find(scale => value >= scale.v)\n if (!match) return new Intl.NumberFormat(locale).format(value)\n\n const formatted = value / match.v\n\n return (\n new Intl.NumberFormat(locale, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n }).format(formatted) + match.s\n )\n}\n\n/**\n * Concverts a number into human readable string\n *\n * @param num The number to convert\n * @param slugify convert the ouput into a slug using this as a separator\n * @returns\n */\nexport const humanize = (num: number, slugify?: '-' | '_'): string => {\n if (!num) {\n return ''\n }\n\n if (slugify === '-' || slugify === '_') {\n const h = humanize(num)\n return typeof h === 'string' ? h.replace(' ', slugify).toLowerCase() : h\n }\n\n const ones = [\n '',\n 'one',\n 'two',\n 'three',\n 'four',\n 'five',\n 'six',\n 'seven',\n 'eight',\n 'nine',\n 'ten',\n 'eleven',\n 'twelve',\n 'thirteen',\n 'fourteen',\n 'fifteen',\n 'sixteen',\n 'seventeen',\n 'eighteen',\n 'nineteen',\n ]\n const tens = [\n '',\n '',\n 'twenty',\n 'thirty',\n 'forty',\n 'fifty',\n 'sixty',\n 'seventy',\n 'eighty',\n 'ninety',\n ]\n\n const numString: string = num.toString()\n\n if (num < 0) throw new Error('Negative numbers are not supported.')\n\n if (num === 0) return 'zero'\n\n //the case of 1 - 20\n if (num < 20) {\n return ones[num] ?? ''\n }\n\n if (numString.length === 2) {\n return tens[numString[0] as unknown as number] + ' ' + ones[numString[1] as unknown as number]\n }\n\n //100 and more\n if (numString.length == 3) {\n if (numString[1] === '0' && numString[2] === '0')\n return ones[numString[0] as unknown as number] + ' hundred'\n else\n return (\n ones[numString[0] as unknown as number] +\n ' hundred and ' +\n humanize(+((numString[1] || '') + numString[2]), slugify)\n )\n }\n\n if (numString.length === 4) {\n const end = +((numString[1] || '') + numString[2] + numString[3])\n if (end === 0) return ones[numString[0] as unknown as number] + ' thousand'\n if (end < 100)\n return ones[numString[0] as unknown as number] + ' thousand and ' + humanize(end, slugify)\n return ones[numString[0] as unknown as number] + ' thousand ' + humanize(end, slugify)\n }\n\n return num as unknown as string\n}\n\n/**\n * Converts a number of bytes into a human-readable string.\n *\n * @param bytes - The size in bytes to convert\n * @param decimals - Number of decimal places to display (default: 2)\n * @param bits - If true, uses 1000-based (SI) units (B, KB, MB...); \n * otherwise uses 1024-based binary units (Bytes, KiB...)\n * @returns A formatted string with the appropriate unit\n */\nexport const toBytes = (\n bytes?: number,\n decimals: number = 2,\n bits: boolean = false\n): string => {\n if (!bytes || isNaN(bytes)) {\n return bits ? '0 B' : '0 Bytes'\n }\n\n const base = bits ? 1000 : 1024\n const dm = decimals < 0 ? 0 : decimals\n const sizes = bits\n ? ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] // SI units\n : ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] // Binary units\n\n const index = Math.floor(Math.log(bytes) / Math.log(base))\n\n const value = parseFloat((bytes / Math.pow(base, index)).toFixed(dm))\n return `${value} ${sizes[index]}`\n}\n\n/**\n * Formats a duration (in seconds) into a human-readable string.\n *\n * @param seconds - Duration in seconds\n * @param worded - If true, outputs worded format (e.g., \"1hr 2min 3sec\"),\n * otherwise HH:MM:SS (e.g., \"01:02:03\")\n * @returns A formatted time string\n */\nexport const toHumanTime = (\n seconds: number = 0,\n worded: boolean = false\n): string => {\n // Ensure seconds is a number and not negative\n if (isNaN(seconds) || seconds < 0) seconds = 0\n\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n const secs = Math.floor(seconds % 60)\n\n // Worded format → \"1hr 2min 3sec\"\n if (worded) {\n const parts = []\n if (hours) parts.push(`${hours}hr`)\n if (minutes) parts.push(`${minutes}min`)\n if (secs || (!hours && !minutes)) parts.push(`${secs}sec`)\n return parts.join(' ')\n }\n\n // HH:MM:SS format → zero-padded\n const hh = hours > 0 ? `${hours}:` : ''\n const mm = (hours > 0 && minutes < 10 ? `0${minutes}` : minutes) + ':'\n const ss = secs < 10 ? `0${secs}` : secs\n\n return `${hh}${mm}${ss}`\n}\n\n","import type { DotFlatten, DotNestedKeys, DotNestedValue } from '@h3ravel/shared'\n\nimport type { KeysToSnakeCase } from '../Contracts/ObjContract'\n\n/**\n * Flattens a nested object into a single-level object\n * with dot-separated keys.\n *\n * Example:\n * doter({\n * user: { name: \"John\", address: { city: \"NY\" } },\n * active: true\n * })\n * \n * Output:\n * {\n * \"user.name\": \"John\",\n * \"user.address.city\": \"NY\",\n * \"active\": true\n * }\n *\n * @template T - The type of the input object\n * @param obj - The nested object to flatten\n * @returns A flattened object with dotted keys and inferred types\n */\nexport const dot = <T extends Record<string, any>> (obj: T): DotFlatten<T> => {\n const result = {} as Record<string, unknown>\n\n /**\n * Internal recursive function to traverse and flatten the object.\n * \n * @param o - Current object to flatten\n * @param prefix - Key path accumulated so far\n */\n const recurse = (o: Record<string, any>, prefix = ''): void => {\n for (const [key, value] of Object.entries(o)) {\n const newKey = prefix ? `${prefix}.${key}` : key\n\n /**\n * Recurse if the value is a plain object\n */\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n recurse(value, newKey)\n } else {\n /**\n * Otherwise, assign directly\n */\n result[newKey] = value\n }\n }\n }\n\n recurse(obj)\n return result as DotFlatten<T>\n}\n\n/**\n * Extracts a subset of properties from an object.\n *\n * @template T - Type of the source object\n * @template K - Keys of T to extract\n * @param obj - The source object\n * @param keys - Array of keys to extract\n * @returns A new object with only the specified keys\n */\nexport const extractProperties = <T extends object, K extends keyof T> (\n obj: T,\n keys: readonly K[] = []\n): Pick<T, K> => {\n return Object.fromEntries(\n keys.map(key => [key, obj[key]])\n ) as Pick<T, K>\n}\n\n/**\n * Safely retrieves a value from an object by key or nested keys.\n *\n * @template T - Type of the source object\n * @param key - Single key or tuple [parentKey, childKey]\n * @param item - The source object\n * @returns The found value as a string or the key itself if not found\n */\nexport const getValue = <\n T extends Record<string, any> // Allow nested objects\n> (\n key: string | [keyof T, keyof T[string]],\n item: T\n): string => {\n if (Array.isArray(key)) {\n const [parent, child] = key\n\n if (child !== undefined) {\n // Access nested property: item[parent][child]\n return (\n String(item?.[parent]?.[child] ??\n item?.[parent] ??\n `${String(parent)}.${String(child)}`)\n )\n }\n\n // Only top-level key\n return String(item?.[parent] ?? parent)\n }\n\n // Single key access\n return String(item?.[key] ?? key)\n}\n\n/**\n * Maps over an object's entries and returns a new object \n * with transformed keys and/or values.\n *\n * @template T - Type of the input object\n * @template R - Type of the new values\n * @param obj - The object to transform\n * @param callback - Function that receives [key, value] and returns [newKey, newValue]\n * @returns A new object with transformed entries\n */\nexport const modObj = <T extends object, R> (\n obj: T,\n callback: (_entry: [keyof T & string, T[keyof T]]) => [string, R]\n): Record<string, R> => {\n return Object.fromEntries(\n Object.entries(obj).map(([key, value]) =>\n callback([key as keyof T & string, value as T[keyof T]])\n )\n ) as Record<string, R>\n}\n\n\nexport function safeDot<T extends Record<string, any>> (_data: T): T\nexport function safeDot<\n T extends Record<string, any>,\n K extends DotNestedKeys<T>\n> (_data: T, _key?: K): DotNestedValue<T, K>\nexport function safeDot<\n T extends Record<string, any>,\n K extends DotNestedKeys<T>\n> (data: T, key?: K): any {\n if (!key) return data\n return key.split('.').reduce((acc: any, k) => acc?.[k], data)\n}\n\n/**\n * Sets a nested property on an object using dot notation.\n * \n * @example\n * const obj = {}\n * setNested(obj, 'app.user.name', 'Legacy')\n * console.log(obj)\n * // Output: { app: { user: { name: 'Legacy' } } }\n * \n * @param obj - The target object to modify.\n * @param key - The dot-separated key (e.g., 'app.user.name').\n * @param value - The value to set at the specified path.\n */\nexport const setNested = (\n obj: Record<string, any>,\n key: string,\n value: any\n): void => {\n if (!key.includes('.')) {\n obj[key] = value\n return\n }\n\n const parts = key.split('.')\n let current = obj\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]\n\n /**\n * If we're at the last key, assign the value\n */\n if (i === parts.length - 1) {\n current[part] = value\n } else {\n /**\n * If the key doesn't exist or isn't an object, create it\n */\n if (typeof current[part] !== 'object' || current[part] === null) {\n current[part] = {}\n }\n current = current[part]\n }\n }\n}\n\n/**\n * Converts object keys to a slugified format (e.g., snake_case).\n *\n * @template T - Type of the input object\n * @param obj - The object whose keys will be slugified\n * @param only - Optional array of keys to slugify (others remain unchanged)\n * @param separator - Separator for slugified keys (default: \"_\")\n * @returns A new object with slugified keys\n */\nexport const slugifyKeys = <T extends object> (\n obj: T,\n only: string[] = [],\n separator: string = '_'\n): KeysToSnakeCase<T> => {\n const slugify = (key: string): string =>\n key\n .replace(/([a-z])([A-Z])/g, `$1${separator}$2`) // Handle camelCase\n .replace(/[\\s\\W]+/g, separator) // Replace spaces/symbols\n .replace(new RegExp(`${separator}{2,}`, 'g'), separator) // Remove duplicate separators\n .replace(new RegExp(`^${separator}|${separator}$`, 'g'), '') // Trim edges\n .toLowerCase()\n\n let entries = Object.entries(obj)\n\n // Filter if `only` is provided\n if (only.length) {\n entries = entries.filter(([key]) => only.includes(key))\n }\n\n return Object.fromEntries(\n entries.map(([key, value]) => [slugify(key), value])\n ) as KeysToSnakeCase<T>\n}\n","import { dot } from './Obj'\n\n/**\n * Get the portion of the string after the first occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const after = (value: string, search: string): string => {\n if (!search) return value\n const index = value.indexOf(search)\n return index !== -1 ? value.slice(index + search.length) : value\n}\n\n/**\n * Get the portion of the string after the last occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const afterLast = (value: string, search: string): string => {\n if (!search) return value\n const lastIndex = value.lastIndexOf(search)\n return lastIndex !== -1 ? value.slice(lastIndex + search.length) : value\n}\n\n/**\n * Get the portion of the string before the first occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const before = (value: string, search: string): string => {\n if (!search) return value\n const index = value.indexOf(search)\n return index !== -1 ? value.slice(0, index) : value\n}\n\n/**\n * Get the portion of the string before the last occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const beforeLast = (value: string, search: string): string => {\n if (!search) return value\n const lastIndex = value.lastIndexOf(search)\n return lastIndex !== -1 ? value.slice(0, lastIndex) : value\n}\n\n/**\n * Capitalizes the first character of a string.\n *\n * @param str - The input string\n * @returns The string with the first character capitalized\n */\nexport function capitalize (str: string): string {\n if (!str) return '' // Handle empty or undefined strings safely\n return str[0].toUpperCase() + str.slice(1)\n}\n\n\n/**\n * Returns the pluralized form of a word based on the given number.\n *\n * @param word - The word to pluralize\n * @param count - The number determining pluralization\n * @returns Singular if count === 1, otherwise plural form\n */\nexport const pluralize = (word: string, count: number): string => {\n // If count is exactly 1 → singular\n if (count === 1) return word\n\n // Irregular plurals map\n const irregularPlurals: Record<string, string> = {\n foot: 'feet',\n child: 'children',\n mouse: 'mice',\n goose: 'geese',\n person: 'people',\n man: 'men',\n woman: 'women',\n }\n\n // Handle irregular cases first\n if (word in irregularPlurals) {\n return irregularPlurals[word]\n }\n\n // If word ends with consonant + \"y\" → replace \"y\" with \"ies\"\n if (\n word.endsWith('y') &&\n !['a', 'e', 'i', 'o', 'u'].includes(word[word.length - 2]?.toLowerCase() ?? '')\n ) {\n return word.slice(0, -1) + 'ies'\n }\n\n // If word ends in \"s\", \"ss\", \"sh\", \"ch\", \"x\", or \"z\" → add \"es\"\n if (/(s|ss|sh|ch|x|z)$/i.test(word)) {\n return word + 'es'\n }\n\n // Default: just add \"s\"\n return word + 's'\n}\n\n/**\n * Converts a plural English word into its singular form.\n *\n * @param word - The word to singularize\n * @returns The singular form of the word\n */\nexport const singularize = (word: string): string => {\n // Irregular plurals map (reverse of pluralize)\n const irregulars: Record<string, string> = {\n feet: 'foot',\n children: 'child',\n mice: 'mouse',\n geese: 'goose',\n people: 'person',\n men: 'man',\n women: 'woman',\n }\n\n // Handle irregular cases\n if (word in irregulars) return irregulars[word]\n\n // Words ending in \"ies\" → change to \"y\" (e.g., \"bodies\" → \"body\")\n if (/ies$/i.test(word) && word.length > 3) {\n return word.replace(/ies$/i, 'y')\n }\n\n // Words ending in \"es\" after certain consonants → remove \"es\"\n if (/(ches|shes|sses|xes|zes)$/i.test(word)) {\n return word.replace(/es$/i, '')\n }\n\n // Generic case: remove trailing \"s\"\n if (/s$/i.test(word) && word.length > 1) {\n return word.replace(/s$/i, '')\n }\n\n return word\n}\n\n/**\n * Converts a string into a slug format.\n * Handles camelCase, spaces, and non-alphanumeric characters.\n *\n * @param str - The input string to slugify\n * @param joiner - The character used to join words (default: \"_\")\n * @returns A slugified string\n */\nexport const slugify = (str: string, joiner = '_'): string => {\n return str\n // Handle camelCase by adding joiner between lowercase → uppercase\n .replace(/([a-z])([A-Z])/g, `$1${joiner}$2`)\n // Replace spaces and non-alphanumeric characters with joiner\n .replace(/[\\s\\W]+/g, joiner)\n // Remove duplicate joiners\n .replace(new RegExp(`${joiner}{2,}`, 'g'), joiner)\n // Trim joiners from start/end\n .replace(new RegExp(`^${joiner}|${joiner}$`, 'g'), '')\n .toLowerCase()\n}\n\n/**\n * Truncates a string to a specified length and appends an ellipsis if needed.\n *\n * @param str - The input string\n * @param len - Maximum length of the result (including ellipsis)\n * @param ellipsis - String to append if truncated (default: \"...\")\n * @returns The truncated string\n */\nexport const subString = (\n str: string,\n len: number,\n ellipsis: string = '...'\n): string => {\n if (!str) return ''\n if (len <= ellipsis.length) return ellipsis // Avoid negative slicing\n\n return str.length > len\n ? str.substring(0, len - ellipsis.length).trimEnd() + ellipsis\n : str\n}\n\n/**\n * Replaces placeholders in a string with corresponding values from a data object.\n * \n * Example:\n * substitute(\"Hello { user.name }!\", { user: { name: \"John\" } })\n * // \"Hello John!\"\n *\n * @param str - The string containing placeholders wrapped in { } braces.\n * @param data - Object containing values to substitute. Supports nested keys via dot notation.\n * @param def - Default value to use if a key is missing. (Optional)\n * @returns The substituted string or undefined if the input string or data is invalid.\n */\nexport const substitute = (\n str: string,\n data: Record<string, unknown> = {},\n def?: string\n): string | undefined => {\n if (!str || !data) return undefined\n\n // Matches { key } or { nested.key } placeholders\n const regex = /{\\s*([a-zA-Z0-9_.]+)\\s*}/g\n\n // Flatten the data so we can directly access dot notation keys\n const flattened = dot(data)\n\n // Replace each placeholder with its value or the default\n const out = str.replace(regex, (_, key: string) => {\n const value = flattened[key]\n return value !== undefined ? String(value) : def ?? ''\n })\n\n return out\n}\n\n/**\n * Truncates a string to a specified length, removing HTML tags and \n * appending a suffix if the string exceeds the length.\n *\n * @param str - The string to truncate\n * @param len - Maximum length (default: 20)\n * @param suffix - Suffix to append if truncated (default: \"...\")\n * @returns The truncated string\n */\nexport const truncate = (\n str: string,\n len: number = 20,\n suffix: string = '...'\n): string => {\n if (!str) return ''\n\n // Remove any HTML tags\n const clean = str.replace(/<[^>]+>/g, '')\n\n // Determine if we need to truncate\n const truncated =\n clean.length > len\n ? clean.substring(0, len - suffix.length) + suffix\n : clean\n\n // Normalize spaces and line breaks\n return truncated\n .replace(/\\n/g, ' ') // Replace all line breaks\n .replace(new RegExp(`\\\\s+${suffix.replace(/\\./g, '\\\\.')}$`), suffix) // Avoid extra space before suffix\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["chunks: T[][]","result: T[]","result: number[]","shift","slugify","numString: string","end","ss","slugify","irregularPlurals: Record<string, string>","irregulars: Record<string, string>","start","padString","end","format","now","start","diff","globalHelpers: GlobalHelpers","Arr.chunk","Arr.collapse","Arr.alternate","Arr.combine","Arr.find","Arr.forget","Arr.first","Arr.last","Arr.isEmpty","Arr.isNotEmpty","Arr.pop","Arr.prepend","Arr.take","Arr.reverse","Arr.shift","Arr.range","Arr.flatten","Str.after","Str.afterLast","Str.before","Str.beforeLast","Str.capitalize","Str.pluralize","Str.singularize","Str.slugify","Str.subString","Str.substitute","Str.truncate","Str.substr","Str.sub","Str.esc","Str.padString","Str.split","Str.chop","Str.isNumber","Str.isInteger","Str.rot","Str.replacePunctuation","Str.translate","Str.ss","Str.firstLines","Str.lastLines","Obj.dot","Obj.extractProperties","Obj.getValue","Obj.modObj","Obj.safeDot","Obj.setNested","Obj.slugifyKeys","Crypto.uuid","Crypto.random","Crypto.randomSecure","Crypto.hash","Crypto.hmac","Crypto.base64Encode","Crypto.base64Decode","Crypto.xor","Crypto.randomColor","Crypto.randomPassword","Crypto.secureToken","Crypto.checksum","Crypto.verifyChecksum","Crypto.caesarCipher","Time.now","Time.unix","Time.format","Time.fromTimestamp","Time.diff","Time.subtract","Time.add","Time.start","Time.end","Time.fromNow","Time.randomTime","Time.isBetween","Time.dayOfYear","Time.firstDayOfMonth","Time.lastDayOfMonth","Time.isLeapYear","Number.abbreviate","Number.humanize","Number.toBytes","Number.toHumanTime","DumpDie.dump","DumpDie.dd"],"sources":["../src/Helpers/Arr.ts","../src/Helpers/Crypto.ts","../src/Helpers/Number.ts","../src/Helpers/Obj.ts","../src/Helpers/Str.ts","../src/Helpers/Time.ts","../src/Helpers/DumpDie.ts","../src/GlobalBootstrap.ts"],"sourcesContent":["/**\n * Splits an array into chunks of a specified size.\n *\n * @template T - Type of elements in the array\n * @param arr - The input array\n * @param size - Size of each chunk (default: 2)\n * @returns An array of chunks (arrays)\n */\nexport const chunk = <T> (arr: T[], size: number = 2): T[][] => {\n if (size <= 0) throw new Error('Chunk size must be greater than 0')\n\n const chunks: T[][] = []\n\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size))\n }\n\n return chunks\n}\n\n/**\n * Collapse an array of arrays into a single array.\n */\nexport const collapse = <T> (arr: (T | T[])[]): T[] => {\n const result: T[] = []\n for (const item of arr) {\n if (Array.isArray(item)) result.push(...item)\n else result.push(item)\n }\n return result\n}\n\n/**\n * Alternates between two arrays, creating a zipped result.\n */\nexport const alternate = <T> (a: T[], b: T[]): T[] => {\n const result: T[] = []\n const max = Math.max(a.length, b.length)\n for (let i = 0; i < max; i++) {\n if (i < a.length) result.push(a[i])\n if (i < b.length) result.push(b[i])\n }\n return result\n}\n\n/**\n * Combine arrays and sum their values element by element.\n */\nexport const combine = (...arr: number[][]): number[] => {\n const maxLength = Math.max(...arr.map(a => a.length))\n const result: number[] = new Array(maxLength).fill(0)\n for (let i = 0; i < maxLength; i++) {\n for (const array of arr) result[i] += (array[i] || 0)\n }\n return result\n}\n\n/** Find the value associated with a given key. */\nexport const find = <T> (key: T, arr: T[]): T | null => arr.find(item => item === key) || null\n\n/** Returns a new array without the given indices. */\nexport const forget = <T> (arr: T[], keys: number[]): T[] => arr.filter((_, i) => !keys.includes(i))\n\n/** Remove the first element and return tuple [el, rest]. */\nexport const first = <T> (arr: T[]): [T, T[]] => {\n if (!arr.length) throw new Error('Cannot shift from empty array')\n return [arr[0], arr.slice(1)]\n}\n\n/** Remove the last element and return tuple [el, rest]. */\nexport const last = <T> (arr: T[]): [T, T[]] => {\n if (!arr.length) throw new Error('Cannot pop from empty array')\n const lastItem = arr[arr.length - 1]\n return [lastItem, arr.slice(0, -1)]\n}\n\n/** Check if array is empty. */\nexport const isEmpty = <T> (arr: T[]): boolean => {\n if (arr.length === 0) return true\n else return false\n}\n\n/** Check if array is empty. */\nexport const isNotEmpty = <T> (arr: T[]): boolean => arr.length > 0\n\n/** Pop the element off the end of array. */\nexport const pop = <T> (arr: T[]): T[] => arr.slice(0, -1)\n\n/** Add elements to the beginning of array. */\nexport const prepend = <T> (arr: T[], ...elements: T[]): T[] => [...elements, ...arr]\n\n/** Take first n elements of array. */\nexport const take = <T> (amount: number, arr: T[]): T[] => arr.slice(0, Math.max(0, amount))\n\n/** Create a new array in reverse order. */\nexport const reverse = <T> (arr: T[]): T[] => [...arr].reverse()\n\n/** Alias for first element removal. */\nexport const shift = first\n\n/**\n * Generates an array of sequential numbers.\n *\n * @param size - Number of elements in the range\n * @param startAt - Starting number (default: 0)\n * @returns An array of numbers from startAt to startAt + size - 1\n */\nexport const range = (size: number, startAt: number = 0): number[] => {\n if (size <= 0 || !Number.isFinite(size)) return []\n return Array.from({ length: size }, (_, i) => startAt + i)\n}\n\n/** Flatten multi-dimensional arrays into single level. */\nexport const flatten = <T> (arr: T[]): T[] => {\n const result: T[] = []\n const recurse = (input: any[]): void => {\n for (const item of input) Array.isArray(item) ? recurse(item) : result.push(item)\n }\n recurse(arr as any[])\n return result\n}\n","import { randomUUID, randomBytes, createHash, createHmac } from 'crypto'\n\n/**\n * Generate a random UUID string.\n * \n * @returns A random UUID string\n */\nexport const uuid = (): string => {\n return randomUUID()\n}\n\n/**\n * Generate a random string of specified length.\n * \n * @param length - Length of the random string (default: 16)\n * @param charset - Character set to use (default: alphanumeric)\n * @returns A random string\n */\nexport const random = (length: number = 16, charset: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'): string => {\n let result = ''\n for (let i = 0; i < length; i++) {\n result += charset.charAt(Math.floor(Math.random() * charset.length))\n }\n return result\n}\n\n/**\n * Secure random string generator that uses crypto.randomBytes.\n * \n * @param length - Length of the random string (default: 32)\n * @returns A cryptographically secure random string\n */\nexport const randomSecure = (length: number = 32): string => {\n return randomBytes(Math.ceil(length / 2)).toString('hex').slice(0, length)\n}\n\n/**\n * Hash a string using the specified algorithm.\n * \n * @param data - Data to hash\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @returns Hexadecimal hash string\n */\nexport const hash = (data: string, algorithm: string = 'sha256'): string => {\n return createHash(algorithm).update(data).digest('hex')\n}\n\n/**\n * Hash a string with salt using HMAC.\n * \n * @param data - Data to hash\n * @param key - Secret key for HMAC\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @returns Hexadecimal hash string\n */\nexport const hmac = (data: string, key: string, algorithm: string = 'sha256'): string => {\n return createHmac(algorithm, key).update(data).digest('hex')\n}\n\n/**\n * Encode data to base64.\n * \n * @param data - Data to encode\n * @returns Base64 encoded string\n */\nexport const base64Encode = (data: string): string => {\n return Buffer.from(data, 'utf8').toString('base64')\n}\n\n/**\n * Decode base64 data.\n * \n * @param data - Base64 string to decode\n * @returns Decoded string\n */\nexport const base64Decode = (data: string): string => {\n return Buffer.from(data, 'base64').toString('utf8')\n}\n\n/**\n * Simple XOR encryption/decryption.\n * \n * @param data - Data to encrypt/decrypt\n * @param key - Encryption key\n * @returns Encrypted/decrypted string\n */\nexport const xor = (data: string, key: string): string => {\n let result = ''\n const keyLength = key.length\n \n for (let i = 0; i < data.length; i++) {\n const dataCharCode = data.charCodeAt(i)\n const keyCharCode = key.charCodeAt(i % keyLength)\n result += String.fromCharCode(dataCharCode ^ keyCharCode)\n }\n \n return result\n}\n\n/**\n * Generate a random hex color code.\n * \n * @returns A hex color code string (e.g., '#a3b2f3')\n */\nexport const randomColor = (): string => {\n const hex = random(6, '0123456789abcdef').toLowerCase()\n return `#${hex}`\n}\n\n/**\n * Generate a secure password using configurable parameters.\n * \n * @param length - Password length (default: 16)\n * @param options - Character options\n * @returns A secure password string\n */\nexport interface PasswordOptions {\n useUppercase?: boolean\n useLowercase?: boolean\n useNumbers?: boolean\n useSymbols?: boolean\n}\n\nexport const randomPassword = (length: number = 16, options: PasswordOptions = {}): string => {\n const defaults: Required<PasswordOptions> = {\n useUppercase: true,\n useLowercase: true,\n useNumbers: true,\n useSymbols: true\n }\n \n const opts = { ...defaults, ...options }\n let charset = ''\n \n if (opts.useUppercase) charset += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n if (opts.useLowercase) charset += 'abcdefghijklmnopqrstuvwxyz'\n if (opts.useNumbers) charset += '0123456789'\n if (opts.useSymbols) charset += '!@#$%^&*()_+-=[]{}|;:,.<>?'\n \n if (charset.length === 0) {\n throw new Error('At least one character type must be enabled')\n }\n \n return random(length, charset)\n}\n\n/**\n * Generate a cryptographically secure token for APIs, sessions, etc.\n * \n * @param strength - Token strength (bytes) (default: 32)\n * @returns A secure token string\n */\nexport const secureToken = (strength: number = 32): string => {\n return randomBytes(strength).toString('hex')\n}\n\n/**\n * Create a checksum for data integrity verification.\n * \n * @param data - Data to create checksum for\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @returns SHA256 checksum\n */\nexport const checksum = (data: string, algorithm: string = 'sha256'): string => {\n return hash(data, algorithm)\n}\n\n/**\n * Verify data integrity using checksum.\n * \n * @param data - Data to verify\n * @param expectedChecksum - Expected checksum\n * @param algorithm - Hash algorithm (default: 'sha256')\n * @returns True if checksums match\n */\nexport const verifyChecksum = (data: string, expectedChecksum: string, algorithm: string = 'sha256'): boolean => {\n const actualChecksum = checksum(data, algorithm)\n return actualChecksum === expectedChecksum\n}\n\n/**\n * Simple Caesar cipher implementation.\n * \n * @param text - Text to encrypt/decrypt\n * @param shift - Number of positions to shift (default: 13)\n * @returns Encrypted/decrypted text\n */\nexport const caesarCipher = (text: string, shift: number = 13): string => {\n return text.replace(/[a-zA-Z]/g, (char: string) => {\n const isUpperCase = char === char.toUpperCase()\n const baseCharCode = isUpperCase ? 'A' : 'a'\n const shiftedCharCode = ((char.charCodeAt(0) - baseCharCode.charCodeAt(0) + shift) % 26)\n const newCharCode = (shiftedCharCode < 0 ? 26 + shiftedCharCode : shiftedCharCode) + baseCharCode.charCodeAt(0)\n return String.fromCharCode(newCharCode)\n })\n}\n","/**\n * Abbreviates large numbers using SI symbols (K, M, B...) \n * and formats the output according to the given locale.\n *\n * @param value - The number to abbreviate\n * @param locale - Optional locale string (default: \"en-US\")\n * @returns A localized, abbreviated number string\n */\nexport const abbreviate = (value?: number, locale: string = 'en-US'): string => {\n if (!value) return '0'\n\n // Numbers less than 1000 don't need abbreviation\n if (value < 1000) {\n return new Intl.NumberFormat(locale).format(value)\n }\n\n const si = [\n { v: 1e18, s: 'E' },\n { v: 1e15, s: 'P' },\n { v: 1e12, s: 'T' },\n { v: 1e9, s: 'B' },\n { v: 1e6, s: 'M' },\n { v: 1e3, s: 'K' },\n ]\n\n const match = si.find(scale => value >= scale.v)\n if (!match) return new Intl.NumberFormat(locale).format(value)\n\n const formatted = value / match.v\n\n return (\n new Intl.NumberFormat(locale, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n }).format(formatted) + match.s\n )\n}\n\n/**\n * Concverts a number into human readable string\n *\n * @param num The number to convert\n * @param slugify convert the ouput into a slug using this as a separator\n * @returns\n */\nexport const humanize = (num: number, slugify?: '-' | '_'): string => {\n if (!num) {\n return ''\n }\n\n if (slugify === '-' || slugify === '_') {\n const h = humanize(num)\n return typeof h === 'string' ? h.replace(' ', slugify).toLowerCase() : h\n }\n\n const ones = [\n '',\n 'one',\n 'two',\n 'three',\n 'four',\n 'five',\n 'six',\n 'seven',\n 'eight',\n 'nine',\n 'ten',\n 'eleven',\n 'twelve',\n 'thirteen',\n 'fourteen',\n 'fifteen',\n 'sixteen',\n 'seventeen',\n 'eighteen',\n 'nineteen',\n ]\n const tens = [\n '',\n '',\n 'twenty',\n 'thirty',\n 'forty',\n 'fifty',\n 'sixty',\n 'seventy',\n 'eighty',\n 'ninety',\n ]\n\n const numString: string = num.toString()\n\n if (num < 0) throw new Error('Negative numbers are not supported.')\n\n if (num === 0) return 'zero'\n\n //the case of 1 - 20\n if (num < 20) {\n return ones[num] ?? ''\n }\n\n if (numString.length === 2) {\n return tens[numString[0] as unknown as number] + ' ' + ones[numString[1] as unknown as number]\n }\n\n //100 and more\n if (numString.length == 3) {\n if (numString[1] === '0' && numString[2] === '0')\n return ones[numString[0] as unknown as number] + ' hundred'\n else\n return (\n ones[numString[0] as unknown as number] +\n ' hundred and ' +\n humanize(+((numString[1] || '') + numString[2]), slugify)\n )\n }\n\n if (numString.length === 4) {\n const end = +((numString[1] || '') + numString[2] + numString[3])\n if (end === 0) return ones[numString[0] as unknown as number] + ' thousand'\n if (end < 100)\n return ones[numString[0] as unknown as number] + ' thousand and ' + humanize(end, slugify)\n return ones[numString[0] as unknown as number] + ' thousand ' + humanize(end, slugify)\n }\n\n return num as unknown as string\n}\n\n/**\n * Converts a number of bytes into a human-readable string.\n *\n * @param bytes - The size in bytes to convert\n * @param decimals - Number of decimal places to display (default: 2)\n * @param bits - If true, uses 1000-based (SI) units (B, KB, MB...); \n * otherwise uses 1024-based binary units (Bytes, KiB...)\n * @returns A formatted string with the appropriate unit\n */\nexport const toBytes = (\n bytes?: number,\n decimals: number = 2,\n bits: boolean = false\n): string => {\n if (!bytes || isNaN(bytes)) {\n return bits ? '0 B' : '0 Bytes'\n }\n\n const base = bits ? 1000 : 1024\n const dm = decimals < 0 ? 0 : decimals\n const sizes = bits\n ? ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] // SI units\n : ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] // Binary units\n\n const index = Math.floor(Math.log(bytes) / Math.log(base))\n\n const value = parseFloat((bytes / Math.pow(base, index)).toFixed(dm))\n return `${value} ${sizes[index]}`\n}\n\n/**\n * Formats a duration (in seconds) into a human-readable string.\n *\n * @param seconds - Duration in seconds\n * @param worded - If true, outputs worded format (e.g., \"1hr 2min 3sec\"),\n * otherwise HH:MM:SS (e.g., \"01:02:03\")\n * @returns A formatted time string\n */\nexport const toHumanTime = (\n seconds: number = 0,\n worded: boolean = false\n): string => {\n // Ensure seconds is a number and not negative\n if (isNaN(seconds) || seconds < 0) seconds = 0\n\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n const secs = Math.floor(seconds % 60)\n\n // Worded format → \"1hr 2min 3sec\"\n if (worded) {\n const parts = []\n if (hours) parts.push(`${hours}hr`)\n if (minutes) parts.push(`${minutes}min`)\n if (secs || (!hours && !minutes)) parts.push(`${secs}sec`)\n return parts.join(' ')\n }\n\n // HH:MM:SS format → zero-padded\n const hh = hours > 0 ? `${hours}:` : ''\n const mm = (hours > 0 && minutes < 10 ? `0${minutes}` : minutes) + ':'\n const ss = secs < 10 ? `0${secs}` : secs\n\n return `${hh}${mm}${ss}`\n}\n\n","import type { DotFlatten, DotNestedKeys, DotNestedValue } from '@h3ravel/shared'\n\nimport type { KeysToSnakeCase } from '../Contracts/ObjContract'\n\n/**\n * Flattens a nested object into a single-level object\n * with dot-separated keys.\n *\n * Example:\n * doter({\n * user: { name: \"John\", address: { city: \"NY\" } },\n * active: true\n * })\n * \n * Output:\n * {\n * \"user.name\": \"John\",\n * \"user.address.city\": \"NY\",\n * \"active\": true\n * }\n *\n * @template T - The type of the input object\n * @param obj - The nested object to flatten\n * @returns A flattened object with dotted keys and inferred types\n */\nexport const dot = <T extends Record<string, any>> (obj: T): DotFlatten<T> => {\n const result = {} as Record<string, unknown>\n\n /**\n * Internal recursive function to traverse and flatten the object.\n * \n * @param o - Current object to flatten\n * @param prefix - Key path accumulated so far\n */\n const recurse = (o: Record<string, any>, prefix = ''): void => {\n for (const [key, value] of Object.entries(o)) {\n const newKey = prefix ? `${prefix}.${key}` : key\n\n /**\n * Recurse if the value is a plain object\n */\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n recurse(value, newKey)\n } else {\n /**\n * Otherwise, assign directly\n */\n result[newKey] = value\n }\n }\n }\n\n recurse(obj)\n return result as DotFlatten<T>\n}\n\n/**\n * Extracts a subset of properties from an object.\n *\n * @template T - Type of the source object\n * @template K - Keys of T to extract\n * @param obj - The source object\n * @param keys - Array of keys to extract\n * @returns A new object with only the specified keys\n */\nexport const extractProperties = <T extends object, K extends keyof T> (\n obj: T,\n keys: readonly K[] = []\n): Pick<T, K> => {\n return Object.fromEntries(\n keys.map(key => [key, obj[key]])\n ) as Pick<T, K>\n}\n\n/**\n * Safely retrieves a value from an object by key or nested keys.\n *\n * @template T - Type of the source object\n * @param key - Single key or tuple [parentKey, childKey]\n * @param item - The source object\n * @returns The found value as a string or the key itself if not found\n */\nexport const getValue = <\n T extends Record<string, any> // Allow nested objects\n> (\n key: string | [keyof T, keyof T[string]],\n item: T\n): string => {\n if (Array.isArray(key)) {\n const [parent, child] = key\n\n if (child !== undefined) {\n // Access nested property: item[parent][child]\n return (\n String(item?.[parent]?.[child] ??\n item?.[parent] ??\n `${String(parent)}.${String(child)}`)\n )\n }\n\n // Only top-level key\n return String(item?.[parent] ?? parent)\n }\n\n // Single key access\n return String(item?.[key] ?? key)\n}\n\n/**\n * Maps over an object's entries and returns a new object \n * with transformed keys and/or values.\n *\n * @template T - Type of the input object\n * @template R - Type of the new values\n * @param obj - The object to transform\n * @param callback - Function that receives [key, value] and returns [newKey, newValue]\n * @returns A new object with transformed entries\n */\nexport const modObj = <T extends object, R> (\n obj: T,\n callback: (_entry: [keyof T & string, T[keyof T]]) => [string, R]\n): Record<string, R> => {\n return Object.fromEntries(\n Object.entries(obj).map(([key, value]) =>\n callback([key as keyof T & string, value as T[keyof T]])\n )\n ) as Record<string, R>\n}\n\n\nexport function safeDot<T extends Record<string, any>> (_data: T): T\nexport function safeDot<\n T extends Record<string, any>,\n K extends DotNestedKeys<T>\n> (_data: T, _key?: K): DotNestedValue<T, K>\nexport function safeDot<\n T extends Record<string, any>,\n K extends DotNestedKeys<T>\n> (data: T, key?: K): any {\n if (!key) return data\n return key.split('.').reduce((acc: any, k) => acc?.[k], data)\n}\n\n/**\n * Sets a nested property on an object using dot notation.\n * \n * @example\n * const obj = {}\n * setNested(obj, 'app.user.name', 'Legacy')\n * console.log(obj)\n * // Output: { app: { user: { name: 'Legacy' } } }\n * \n * @param obj - The target object to modify.\n * @param key - The dot-separated key (e.g., 'app.user.name').\n * @param value - The value to set at the specified path.\n */\nexport const setNested = (\n obj: Record<string, any>,\n key: string,\n value: any\n): void => {\n if (!key.includes('.')) {\n obj[key] = value\n return\n }\n\n const parts = key.split('.')\n let current = obj\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]\n\n /**\n * If we're at the last key, assign the value\n */\n if (i === parts.length - 1) {\n current[part] = value\n } else {\n /**\n * If the key doesn't exist or isn't an object, create it\n */\n if (typeof current[part] !== 'object' || current[part] === null) {\n current[part] = {}\n }\n current = current[part]\n }\n }\n}\n\n/**\n * Converts object keys to a slugified format (e.g., snake_case).\n *\n * @template T - Type of the input object\n * @param obj - The object whose keys will be slugified\n * @param only - Optional array of keys to slugify (others remain unchanged)\n * @param separator - Separator for slugified keys (default: \"_\")\n * @returns A new object with slugified keys\n */\nexport const slugifyKeys = <T extends object> (\n obj: T,\n only: string[] = [],\n separator: string = '_'\n): KeysToSnakeCase<T> => {\n const slugify = (key: string): string =>\n key\n .replace(/([a-z])([A-Z])/g, `$1${separator}$2`) // Handle camelCase\n .replace(/[\\s\\W]+/g, separator) // Replace spaces/symbols\n .replace(new RegExp(`${separator}{2,}`, 'g'), separator) // Remove duplicate separators\n .replace(new RegExp(`^${separator}|${separator}$`, 'g'), '') // Trim edges\n .toLowerCase()\n\n let entries = Object.entries(obj)\n\n // Filter if `only` is provided\n if (only.length) {\n entries = entries.filter(([key]) => only.includes(key))\n }\n\n return Object.fromEntries(\n entries.map(([key, value]) => [slugify(key), value])\n ) as KeysToSnakeCase<T>\n}\n","import { dot } from './Obj'\n\n/**\n * Get the portion of the string after the first occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const after = (value: string, search: string): string => {\n if (!search) return value\n const index = value.indexOf(search)\n return index !== -1 ? value.slice(index + search.length) : value\n}\n\n/**\n * Get the portion of the string after the last occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const afterLast = (value: string, search: string): string => {\n if (!search) return value\n const lastIndex = value.lastIndexOf(search)\n return lastIndex !== -1 ? value.slice(lastIndex + search.length) : value\n}\n\n/**\n * Get the portion of the string before the first occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const before = (value: string, search: string): string => {\n if (!search) return value\n const index = value.indexOf(search)\n return index !== -1 ? value.slice(0, index) : value\n}\n\n/**\n * Get the portion of the string before the last occurrence of the given value.\n * \n * @param value \n * @param search \n * @returns \n */\nexport const beforeLast = (value: string, search: string): string => {\n if (!search) return value\n const lastIndex = value.lastIndexOf(search)\n return lastIndex !== -1 ? value.slice(0, lastIndex) : value\n}\n\n/** Capitalizes the first character of a string. */\nexport function capitalize (str: string): string {\n if (!str) return ''\n return str[0].toUpperCase() + str.slice(1)\n}\n\n/**\n * Returns the pluralized form of a word based on the given number.\n */\nexport const pluralize = (word: string, count: number): string => {\n if (count === 1) return word\n const irregularPlurals: Record<string, string> = {\n foot: 'feet', child: 'children', mouse: 'mice', goose: 'geese',\n person: 'people', man: 'men', woman: 'women',\n }\n if (word in irregularPlurals) return irregularPlurals[word]\n if (word.endsWith('y') && !['a','e','i','o','u'].includes(word.at(-2)?.toLowerCase() ?? '')) {\n return word.slice(0, -1) + 'ies'\n }\n if (/(s|ss|sh|ch|x|z)$/i.test(word)) return word + 'es'\n return word + 's'\n}\n\n/** Converts a plural English word into its singular form. */\nexport const singularize = (word: string): string => {\n const irregulars: Record<string, string> = {\n feet: 'foot', children: 'child', mice: 'mouse', geese: 'goose',\n people: 'person', men: 'man', women: 'woman',\n }\n if (word in irregulars) return irregulars[word]\n if (/ies$/i.test(word) && word.length > 3) return word.replace(/ies$/i, 'y')\n if (/(ches|shes|sses|xes|zes)$/i.test(word)) return word.replace(/es$/i, '')\n if (/s$/i.test(word) && word.length > 1) return word.replace(/s$/i, '')\n return word\n}\n\n/** Converts a string into a slug format. */\nexport const slugify = (str: string, joiner = '_'): string => {\n const core = str\n .replace(/([a-z])([A-Z])/g, `$1${joiner}$2`)\n .replace(/[\\s\\W]+/g, joiner)\n .replace(new RegExp(`${joiner}{2,}`, 'g'), joiner)\n .toLowerCase()\n return core\n}\n\n/** Truncates a string to a specified length and appends an ellipsis if needed. */\nexport const subString = (\n str: string,\n len: number,\n ellipsis: string = '...'\n): string => {\n if (!str) return ''\n if (len <= ellipsis.length) return ellipsis\n return str.length > len ? str.substring(0, len - ellipsis.length).trimEnd() + ellipsis : str\n}\n\n/** Substitute placeholders { key } using object with dot notation. */\nexport const substitute = (\n str: string,\n data: Record<string, unknown> = {},\n def?: string\n): string | undefined => {\n if (!str || !data) return undefined\n const regex = /{\\s*([a-zA-Z0-9_.]+)\\s*}/g\n const flattened = dot(data)\n return str.replace(regex, (_, key: string) => {\n const value = flattened[key]\n return value !== undefined ? String(value) : def ?? ''\n })\n}\n\n/** Truncate string removing HTML tags and append suffix if needed. */\nexport const truncate = (\n str: string,\n len: number = 20,\n suffix: string = '...'\n): string => {\n if (!str) return ''\n const clean = str.replace(/<[^>]+>/g, '')\n const out = clean.length > len ? clean.substring(0, len - suffix.length) + suffix : clean\n return out.replace(/\\n/g, ' ').replace(new RegExp(`\\\\s+${suffix.replace(/\\./g, '\\\\.')}$`), suffix)\n}\n\n/** Get substring from offset/length similar to PHP substr. */\nexport const substr = (string: string, offset: number, length?: number): string => {\n if (offset < 0) offset += string.length\n if (length === undefined) return string.substring(offset)\n return string.substring(offset, offset + length)\n}\n\n/** Get substring by start/stop indexes. */\nexport const sub = (string: string, start: number, stop: number): string => string.substring(start, stop)\n\n/** Escape string for JSON encoding (returns string without quotes). */\nexport const esc = (string: string): string => JSON.stringify(string).slice(1, -1)\n\n/** Padding to a fixed size, right by default. */\nexport const padString = (\n string: string,\n size: number,\n padString: string = ' ',\n padRight: boolean = true\n): string => {\n if (string.length >= size) return string\n const pad = padString.repeat(size - string.length)\n return padRight ? string + pad : pad + string\n}\n\n/** Split by delimiter with edge-case rule. */\nexport const split = (string: string, delimiter: string): string[] => {\n if (string.startsWith(delimiter) || string.endsWith(delimiter)) return ['']\n return string.split(delimiter)\n}\n\n/** Returns all the characters except the last. */\nexport const chop = (string: string): string => string.slice(0, -1)\n\n/** Number checks. */\nexport const isNumber = (string: string): boolean => !isNaN(Number(string)) && string.trim() !== ''\nexport const isInteger = (string: string): boolean => Number.isInteger(Number(string)) && string.trim() !== ''\n\n/** ROT-N cipher. */\nexport const rot = (string: string, n: number = 13): string => {\n return string.replace(/[a-zA-Z]/g, (char: string) => {\n const code = char.charCodeAt(0)\n const start = char >= 'a' ? 'a'.charCodeAt(0) : 'A'.charCodeAt(0)\n const end = char >= 'a' ? 'z'.charCodeAt(0) : 'Z'.charCodeAt(0)\n let next = code + n\n while (next < start) next += 26\n while (next > end) next -= 26\n return String.fromCharCode(next)\n })\n}\n\n/** Replace trailing punctuation with new format. */\nexport const replacePunctuation = (string: string, newFormat: string): string => string.replace(/[.,;:!?]*$/, '') + newFormat\n\n/** Array/object driven text replacement. */\nexport const translate = (string: string, replacements: Record<string, string> | Array<[string, string]>): string => {\n let result = string\n if (Array.isArray(replacements)) {\n for (const [from, to] of replacements) result = result.replace(new RegExp(from, 'g'), to)\n } else {\n for (const [from, to] of Object.entries(replacements)) result = result.replace(new RegExp(from, 'g'), to)\n }\n return result\n}\n\n/** Strip slashes recursively. */\nexport const ss = (string: string): string => string.replace(/\\\\(.)/g, '$1')\n\n/** First and last N lines. */\nexport const firstLines = (string: string, amount: number = 1): string => string.split('\\n').slice(0, amount).join('\\n')\nexport const lastLines = (string: string, amount: number = 1): string => string.split('\\n').slice(-amount).join('\\n')\n\n","export type TimeFormat = 'Y-m-d' | 'Y-m-d H:i:s' | 'd-m-Y' | 'd/m/Y' | 'M j, Y' | 'F j, Y' | 'D j M' | 'timestamp' | 'unix'\nexport type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days'\n\n/**\n * Get current timestamp in milliseconds.\n *\n * @returns Current timestamp as number\n */\nexport const now = (): number => {\n return Date.now()\n}\n\n/**\n * Get current Unix timestamp.\n *\n * @returns Current Unix timestamp\n */\nexport const unix = (): number => {\n return Math.floor(Date.now() / 1000)\n}\n\n/**\n * Format a date string according to a specified format (UTC-based for determinism).\n *\n * @param date - Date string or Date object\n * @param format - Format to output (default: 'Y-m-d H:i:s')\n * @returns Formatted date string\n */\nexport const format = (date: string | Date, format: TimeFormat = 'Y-m-d H:i:s'): string => {\n const d = new Date(date)\n \n if (isNaN(d.getTime())) {\n throw new Error('Invalid date provided')\n }\n \n const year = d.getUTCFullYear()\n const month = String(d.getUTCMonth() + 1).padStart(2, '0')\n const day = String(d.getUTCDate()).padStart(2, '0')\n const hours = String(d.getUTCHours()).padStart(2, '0')\n const minutes = String(d.getUTCMinutes()).padStart(2, '0')\n const seconds = String(d.getUTCSeconds()).padStart(2, '0')\n \n const monthNames = [\n 'January', 'February', 'March', 'April', 'May', 'June',\n 'July', 'August', 'September', 'October', 'November', 'December'\n ]\n const monthNamesShort = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'\n ]\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']\n \n switch (format) {\n case 'Y-m-d':\n return `${year}-${month}-${day}`\n case 'Y-m-d H:i:s':\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n case 'd-m-Y':\n return `${day}-${month}-${year}`\n case 'd/m/Y':\n return `${day}/${month}/${year}`\n case 'M j, Y':\n return `${monthNamesShort[d.getUTCMonth()]} ${d.getUTCDate()}, ${year}`\n case 'F j, Y':\n return `${monthNames[d.getUTCMonth()]} ${d.getUTCDate()}, ${year}`\n case 'D j M':\n return `${dayNames[d.getUTCDay()]} ${d.getUTCDate()} ${monthNamesShort[d.getUTCMonth()]}`\n case 'timestamp':\n return d.toISOString()\n case 'unix':\n return Math.floor(d.getTime() / 1000).toString()\n default:\n return d.toISOString()\n }\n}\n\n/**\n * Create a date for a given timestamp.\n *\n * @param timestamp - Unix timestamp\n * @returns Date object\n */\nexport const fromTimestamp = (timestamp: number): Date => {\n return new Date(timestamp * 1000)\n}\n\n/**\n * Return the difference for given date in seconds.\n *\n * @param date - Date to compare\n * @param referenceDate - Reference date (optional, defaults to now)\n * @returns Number of seconds difference\n */\nexport const diff = (date: string | Date, referenceDate?: string | Date): number => {\n const d1 = new Date(date)\n const d2 = referenceDate ? new Date(referenceDate) : new Date()\n \n if (isNaN(d1.getTime()) || isNaN(d2.getTime())) {\n throw new Error('Invalid date provided')\n }\n \n const diffInSeconds = Math.floor((d2.getTime() - d1.getTime()) / 1000)\n return diffInSeconds\n}\n\n/**\n * Subtract time from the given date.\n */\nexport const subtract = (date: string | Date, amount: number = 1, unit: TimeUnit = 'days'): Date => {\n const d = new Date(date)\n if (isNaN(d.getTime())) throw new Error('Invalid date provided')\n const amounts: Record<TimeUnit, number> = {\n milliseconds: 1,\n seconds: 1000,\n minutes: 60 * 1000,\n hours: 60 * 60 * 1000,\n days: 24 * 60 * 60 * 1000\n }\n const multiplier = amounts[unit] || 1000\n return new Date(d.getTime() - (amount * multiplier))\n}\n\n/**\n * Add time to the given date.\n */\nexport const add = (date: string | Date, amount: number = 1, unit: TimeUnit = 'days'): Date => {\n const d = new Date(date)\n if (isNaN(d.getTime())) throw new Error('Invalid date provided')\n const amounts: Record<TimeUnit, number> = {\n milliseconds: 1,\n seconds: 1000,\n minutes: 60 * 1000,\n hours: 60 * 60 * 1000,\n days: 24 * 60 * 60 * 1000\n }\n const multiplier = amounts[unit] || 1000\n return new Date(d.getTime() + (amount * multiplier))\n}\n\n/**\n * Start time of a specific unit.\n */\nexport const start = (date: string | Date, unit: TimeUnit = 'days'): Date => {\n const d = new Date(date)\n if (isNaN(d.getTime())) throw new Error('Invalid date provided')\n const newDt = new Date(d)\n switch (unit) {\n case 'days': newDt.setHours(0, 0, 0, 0); break\n case 'hours': newDt.setMinutes(0, 0, 0); break\n case 'minutes': newDt.setSeconds(0, 0); break\n case 'seconds': newDt.setMilliseconds(0); break\n case 'milliseconds': break\n }\n return newDt\n}\n\n/**\n * End time of a specific unit.\n */\nexport const end = (date: string | Date, unit: TimeUnit = 'days'): Date => {\n const d = new Date(date)\n if (isNaN(d.getTime())) throw new Error('Invalid date provided')\n const newDt = new Date(d)\n switch (unit) {\n case 'days': newDt.setHours(23, 59, 59, 999); break\n case 'hours': newDt.setMinutes(59, 59, 999); break\n case 'minutes': newDt.setSeconds(59, 999); break\n case 'seconds': newDt.setMilliseconds(999); break\n case 'milliseconds': break\n }\n return newDt\n}\n\n/**\n * Get the difference in days from today.\n */\nexport const fromNow = (date: string | Date): number => {\n return diff(date) / (24 * 60 * 60)\n}\n\n/**\n * Get a random time between the specified hour and minute.\n */\nexport const randomTime = (\n startHour: number = 9,\n startMinute: number = 0,\n endHour: number = 17,\n endMinute: number = 0\n): Date => {\n const today = new Date()\n const startMinutes = startHour * 60 + startMinute\n const endMinutes = endHour * 60 + endMinute\n const randomMinutes = Math.floor(Math.random() * (endMinutes - startMinutes)) + startMinutes\n const hour = Math.floor(randomMinutes / 60)\n const minute = randomMinutes % 60\n const date = new Date(today)\n date.setHours(hour, minute, 0, 0)\n return date\n}\n\n/**\n * Check if the current time is between the specified durations.\n */\nexport const isBetween = (startTime: string, endTime: string): boolean => {\n const now = new Date()\n const currentHours = now.getHours()\n const currentMinutes = now.getMinutes()\n const currentTotalMinutes = currentHours * 60 + currentMinutes\n const parseTime = (timeStr: string) => {\n const [hours, minutes] = timeStr.split(':').map(Number)\n return hours * 60 + minutes\n }\n const startTotalMinutes = parseTime(startTime)\n const endTotalMinutes = parseTime(endTime)\n if (startTotalMinutes <= endTotalMinutes) {\n return currentTotalMinutes >= startTotalMinutes && currentTotalMinutes <= endTotalMinutes\n } else {\n return currentTotalMinutes >= startTotalMinutes || currentTotalMinutes <= endTotalMinutes\n }\n}\n\n/** Day of year, first/last day of month, leap year checks. */\nexport const dayOfYear = (date: string | Date = new Date()): number => {\n const d = new Date(date)\n const start = new Date(Date.UTC(d.getUTCFullYear(), 0, 0))\n const diff = d.getTime() - start.getTime()\n return Math.floor(diff / (1000 * 60 * 60 * 24))\n}\n\nexport const firstDayOfMonth = (date: string | Date = new Date()): Date => {\n const d = new Date(date)\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1))\n}\n\nexport const lastDayOfMonth = (date: string | Date = new Date()): Date => {\n const d = new Date(date)\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0))\n}\n\nexport const isLeapYear = (year: number = new Date().getUTCFullYear()): boolean => {\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\n}\n\n","import process from 'process'\nimport util from 'util'\n\nconst inspect = (thing: any) => {\n return util.inspect(thing, {\n showHidden: true,\n depth: null,\n colors: true\n })\n}\n\n/**\n * Dump something and kill the process for quick debugging. Based on Laravel's dd()\n * \n * @param args \n */\nexport const dd = (...args: unknown[]): never => {\n args.forEach((thing) => {\n console.log(inspect(thing))\n })\n\n process.exit(1)\n}\n\n/**\n * Dump something but keep the process for quick debugging. Based on Laravel's dump()\n * \n * @param args \n */\nexport const dump = (...args: unknown[]): void => {\n args.forEach((thing) => {\n console.log(inspect(thing))\n })\n} \n","import * as Arr from './Helpers/Arr'\nimport * as Crypto from './Helpers/Crypto'\nimport * as Number from './Helpers/Number'\nimport * as Obj from './Helpers/Obj'\nimport * as Str from './Helpers/Str'\nimport * as Time from './Helpers/Time'\nimport * as DumpDie from './Helpers/DumpDie'\n\n/**\n * Global helpers interface that mirrors Laravel's helpers\n * and provides convenient access to all utility functions\n */\nexport interface GlobalHelpers {\n // Array helpers\n Arr: typeof Arr\n chunk: typeof Arr.chunk\n collapse: typeof Arr.collapse\n alternate: typeof Arr.alternate\n combine: typeof Arr.combine\n find: typeof Arr.find\n forget: typeof Arr.forget\n first: typeof Arr.first\n last: typeof Arr.last\n isEmpty: typeof Arr.isEmpty\n isNotEmpty: typeof Arr.isNotEmpty\n pop: typeof Arr.pop\n prepend: typeof Arr.prepend\n take: typeof Arr.take\n reverse: typeof Arr.reverse\n shift: typeof Arr.shift\n range: typeof Arr.range\n flatten: typeof Arr.flatten\n \n // String helpers\n Str: typeof Str\n after: typeof Str.after\n afterLast: typeof Str.afterLast\n before: typeof Str.before\n beforeLast: typeof Str.beforeLast\n capitalize: typeof Str.capitalize\n pluralize: typeof Str.pluralize\n singularize: typeof Str.singularize\n slugify: typeof Str.slugify\n subString: typeof Str.subString\n substitute: typeof Str.substitute\n truncate: typeof Str.truncate\n substr: typeof Str.substr\n sub: typeof Str.sub\n esc: typeof Str.esc\n padString: typeof Str.padString\n split: typeof Str.split\n chop: typeof Str.chop\n isNumber: typeof Str.isNumber\n isInteger: typeof Str.isInteger\n rot: typeof Str.rot\n replacePunctuation: typeof Str.replacePunctuation\n translate: typeof Str.translate\n ss: typeof Str.ss\n firstLines: typeof Str.firstLines\n lastLines: typeof Str.lastLines\n \n // Object helpers\n Obj: typeof Obj\n dot: typeof Obj.dot\n extractProperties: typeof Obj.extractProperties\n getValue: typeof Obj.getValue\n modObj: typeof Obj.modObj\n safeDot: typeof Obj.safeDot\n setNested: typeof Obj.setNested\n slugifyKeys: typeof Obj.slugifyKeys\n \n // Crypto helpers\n Crypto: typeof Crypto\n uuid: typeof Crypto.uuid\n random: typeof Crypto.random\n randomSecure: typeof Crypto.randomSecure\n hash: typeof Crypto.hash\n hmac: typeof Crypto.hmac\n base64Encode: typeof Crypto.base64Encode\n base64Decode: typeof Crypto.base64Decode\n xor: typeof Crypto.xor\n randomColor: typeof Crypto.randomColor\n randomPassword: typeof Crypto.randomPassword\n secureToken: typeof Crypto.secureToken\n checksum: typeof Crypto.checksum\n verifyChecksum: typeof Crypto.verifyChecksum\n caesarCipher: typeof Crypto.caesarCipher\n \n // Time helpers\n Time: typeof Time\n now: typeof Time.now\n unix: typeof Time.unix\n format: typeof Time.format\n fromTimestamp: typeof Time.fromTimestamp\n diff: typeof Time.diff\n subtract: typeof Time.subtract\n add: typeof Time.add\n start: typeof Time.start\n end: typeof Time.end\n fromNow: typeof Time.fromNow\n randomTime: typeof Time.randomTime\n isBetween: typeof Time.isBetween\n dayOfYear: typeof Time.dayOfYear\n firstDayOfMonth: typeof Time.firstDayOfMonth\n lastDayOfMonth: typeof Time.lastDayOfMonth\n isLeapYear: typeof Time.isLeapYear\n \n // Number helpers\n Number: typeof Number\n abbreviate: typeof Number.abbreviate\n humanize: typeof Number.humanize\n toBytes: typeof Number.toBytes\n toHumanTime: typeof Number.toHumanTime\n \n // Debug helpers\n dump: typeof DumpDie.dump\n dd: typeof DumpDie.dd\n}\n\n/**\n * Bootstrap the global helpers into the global scope.\n * This enables optional global access to all helper functions.\n * \n * Example usage:\n * ```typescript\n * import { bootstrap } from '@h3ravel/support'\n * \n * // Make helpers globally available\n * bootstrap()\n * \n * // Now you can use:\n * Arr.chunk([1, 2, 3, 4], 2)\n * // or directly:\n * chunk([1, 2, 3, 4], 2)\n * Str.capitalize('hello world')\n * // or directly:\n * capitalize('hello world')\n * ```\n * \n * @param target - The target object to attach helpers to (default: globalThis)\n */\nexport function bootstrap(target: any = globalThis): void {\n const globalHelpers: GlobalHelpers = {\n // Re-export helpers as modules\n Arr,\n Crypto,\n Number,\n Obj,\n Str,\n Time,\n \n // Array helpers\n chunk: Arr.chunk,\n collapse: Arr.collapse,\n alternate: Arr.alternate,\n combine: Arr.combine,\n find: Arr.find,\n forget: Arr.forget,\n first: Arr.first,\n last: Arr.last,\n isEmpty: Arr.isEmpty,\n isNotEmpty: Arr.isNotEmpty,\n pop: Arr.pop,\n prepend: Arr.prepend,\n take: Arr.take,\n reverse: Arr.reverse,\n shift: Arr.shift,\n range: Arr.range,\n flatten: Arr.flatten,\n \n // String helpers\n after: Str.after,\n afterLast: Str.afterLast,\n before: Str.before,\n beforeLast: Str.beforeLast,\n capitalize: Str.capitalize,\n pluralize: Str.pluralize,\n singularize: Str.singularize,\n slugify: Str.slugify,\n subString: Str.subString,\n substitute: Str.substitute,\n truncate: Str.truncate,\n substr: Str.substr,\n sub: Str.sub,\n esc: Str.esc,\n padString: Str.padString,\n split: Str.split,\n chop: Str.chop,\n isNumber: Str.isNumber,\n isInteger: Str.isInteger,\n rot: Str.rot,\n replacePunctuation: Str.replacePunctuation,\n translate: Str.translate,\n ss: Str.ss,\n firstLines: Str.firstLines,\n lastLines: Str.lastLines,\n \n // Object helpers\n dot: Obj.dot,\n extractProperties: Obj.extractProperties,\n getValue: Obj.getValue,\n modObj: Obj.modObj,\n safeDot: Obj.safeDot as any,\n setNested: Obj.setNested,\n slugifyKeys: Obj.slugifyKeys,\n \n // Crypto helpers\n uuid: Crypto.uuid,\n random: Crypto.random,\n randomSecure: Crypto.randomSecure,\n hash: Crypto.hash,\n hmac: Crypto.hmac,\n base64Encode: Crypto.base64Encode,\n base64Decode: Crypto.base64Decode,\n xor: Crypto.xor,\n randomColor: Crypto.randomColor,\n randomPassword: Crypto.randomPassword,\n secureToken: Crypto.secureToken,\n checksum: Crypto.checksum,\n verifyChecksum: Crypto.verifyChecksum,\n caesarCipher: Crypto.caesarCipher,\n \n // Time helpers\n now: Time.now,\n unix: Time.unix,\n format: Time.format,\n fromTimestamp: Time.fromTimestamp,\n diff: Time.diff,\n subtract: Time.subtract,\n add: Time.add,\n start: Time.start,\n end: Time.end,\n fromNow: Time.fromNow,\n randomTime: Time.randomTime,\n isBetween: Time.isBetween,\n dayOfYear: Time.dayOfYear,\n firstDayOfMonth: Time.firstDayOfMonth,\n lastDayOfMonth: Time.lastDayOfMonth,\n isLeapYear: Time.isLeapYear,\n \n // Number helpers\n abbreviate: Number.abbreviate,\n humanize: Number.humanize,\n toBytes: Number.toBytes,\n toHumanTime: Number.toHumanTime,\n \n // Debug helpers\n dump: DumpDie.dump,\n dd: DumpDie.dd,\n }\n \n // Attach helpers to target\n Object.assign(target, globalHelpers)\n}\n\n/**\n * Clean up global helpers by removing them from the global scope.\n * This function removes all global helper attachments.\n * \n * @param target - The target object to clean up (default: globalThis)\n */\nexport function cleanBootstrap(target: any = globalThis): void {\n const helpersToRemove = [\n // Array helpers\n 'Arr', 'chunk', 'collapse', 'alternate', 'combine', 'each', 'keys', 'find',\n 'forget', 'first', 'last', 'isEmpty', 'isNotEmpty', 'pop', 'prepend', 'take',\n 'reverse', 'shift', 'range', 'where', 'skip', 'flatten',\n \n // String helpers\n 'Str', 'after', 'afterLast', 'before', 'beforeLast', 'capitalize', 'pluralize',\n 'singularize', 'slugify', 'subString', 'substitute', 'truncate', 'startsWith',\n 'endsWith', 'substr', 'sub', 'esc', 'padString', 'trim', 'ltrim', 'rtrim',\n 'trimChars', 'split', 'chop', 'isNumber', 'isInteger', 'rot', 'replacePunctuation',\n 'translate', 'ss', 'firstLines', 'lastLines',\n \n // Object helpers\n 'Obj', 'dot', 'extractProperties', 'getValue', 'modObj', 'safeDot', 'setNested', 'slugifyKeys',\n \n // Crypto helpers\n 'Crypto', 'uuid', 'random', 'randomSecure', 'hash', 'hmac', 'base64Encode',\n 'base64Decode', 'xor', 'randomColor', 'randomPassword', 'secureToken',\n 'checksum', 'verifyChecksum', 'caesarCipher',\n \n // Time helpers\n 'Time', 'now', 'unix', 'format', 'fromTimestamp', 'diff', 'subtract', 'add',\n 'start', 'end', 'fromNow', 'randomTime', 'isBetween', 'dayOfYear',\n 'firstDayOfMonth', 'lastDayOfMonth', 'isLeapYear',\n \n // Number helpers\n 'Number', 'abbreviate', 'humanize', 'toBytes', 'toHumanTime',\n \n // Debug helpers\n 'dump', 'dd'\n ]\n \n helpersToRemove.forEach(helper => {\n if (helper in target) {\n delete target[helper]\n }\n })\n}\n\n// Also export as default bootstrap function for convenience\nexport default bootstrap\n"],"mappings":"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"}