UNPKG

full-utils

Version:

Сomprehensive collection of pure, zero-dependency functions for everyday JavaScript and TypeScript development.

1,472 lines (1,449 loc) 155 kB
/** * Parse a human-typed string of function-like arguments into a normalized array of JS values. * * @summary * Splits by **top-level commas** (ignoring commas that appear inside quotes, parentheses, * brackets, or braces) and **coerces** each token to a sensible JavaScript type: * `null`, `undefined`, booleans, numbers (including `Infinity`/`-Infinity`), strings * (with quote stripping and unescaping), and JSON objects/arrays. Tokens that look like * a macro or call marker (start with `$` and end with `)`) are returned **as is**. * * @remarks * ### How parsing works * 1. **Input normalization** * - Non-string inputs are returned as a single-element array `[value]`. * - Leading/trailing whitespace is trimmed. * - If the entire string is wrapped in square brackets (`[...]`), the brackets are * removed (so the function accepts both `a,b,c` and `[a, b, c]`). * - Empty input (after trimming or after removing `[...]`) yields `[]`. * * 2. **Tokenization by top-level commas** * - The string is scanned left-to-right. * - The parser tracks nesting **depth** for `()`, `[]`, `{}` and whether it is * currently **inside quotes**. A comma only splits tokens at **depth 0** and * **outside quotes**. * * 3. **Per-token coercion (in this order)** * - **Macro / call marker**: If a token starts with `$`, contains `(`, and ends * with `)`, it is returned unchanged (e.g., `"$env(PATH)"`). * - **Literals**: `null` → `null`, `undefined` → `undefined`. * - **Booleans**: Using {@link isStrBool} + {@link formatToBool} (e.g., `"true"`, * `"False"`, `"yes"`, `"0"` depending on your implementation). * - **Numbers**: Using {@link formatToNum}. If the result is finite, it is returned. * Explicit `"Infinity"` and `"-Infinity"` are also supported. * - **Quoted strings**: `'text'` or `"text"` → inner text with escapes processed * (`\\` → `\`, `\'` → `'`, `\"` → `"`). * - **JSON**: If token begins with `{` and ends with `}`, or begins with `[` and * ends with `]`, the function attempts `jsonDecode`. On failure, the raw string * is returned. * - **Fallback**: Raw token as string. * * ### Escaping inside quotes * - Backslash escaping is supported while inside quotes: * - `\\` for a literal backslash * - `\"` inside double quotes * - `\'` inside single quotes * * ### Non-throwing behavior * - The function aims to be **robust** and **non-throwing**. Invalid JSON will be * returned as a plain string rather than crashing. * * ### Security considerations * - The parser **does not** evaluate code; it only returns strings or parsed values. * If you plan to execute anything returned (e.g., tokens starting with `$...`), * do so in a sandbox with explicit allow-lists. * * ### Limitations * - Numerical parsing relies on {@link formatToNum}. Extremely large or high-precision * decimals may still be subject to JavaScript `number` precision limits unless your * `formatToNum` converts to a safer representation. * - Only basic backslash escapes are handled in quoted strings (no `\uXXXX` decoding here). * - Whitespace outside quotes is trimmed from each token; internal whitespace is preserved. * * @example * // Basic values * formatStrToFuncArgs('1, true, "hello"'); // => [1, true, "hello"] * * @example * // Bracket-wrapped list * formatStrToFuncArgs('[1, 2, 3]'); // => [1, 2, 3] * * @example * // Nested structures and quoting * formatStrToFuncArgs('{"a":1,"b":[2,3]}, "te,xt", (x,y)'); // => [ {a:1,b:[2,3]}, "te,xt", "(x,y)" ] * * @example * // Booleans, null/undefined, and Infinity * formatStrToFuncArgs('yes, NO, null, undefined, Infinity, -Infinity'); * // => [true, false, null, undefined, Infinity, -Infinity] * * @example * // Macro-like token (returned as-is) * formatStrToFuncArgs('$env(PATH)'); // => ["$env(PATH)"] * * @example * // Escapes inside quotes * formatStrToFuncArgs('"He said: \\"Hi\\"", \'It\\\'s ok\', "\\\\path"'); * // => ['He said: "Hi"', "It's ok", "\\path"] * * @example * // Empty and whitespace inputs * formatStrToFuncArgs(' '); // => [] * formatStrToFuncArgs('[]'); // => [] * formatStrToFuncArgs('[ ]'); // => [] * formatStrToFuncArgs(' [ a , b ] '); // => ["a", "b"] * * @param value - Raw string containing comma-separated arguments. * If `value` is **not** a string, the function returns `[value]` unchanged. * * @returns An array of coerced values (`unknown[]`). Each item is one parsed token. * * @see isStrBool * @see formatToBool * @see formatToNum * @see jsonDecode * * @public * @since 2.0.0 */ declare function formatStrToFuncArgs(value: string): unknown[]; /** * Splits an input array into smaller subarrays (portions) of a given fixed size. * * @summary * Returns an array of chunks, where each chunk contains at most `portionLength` elements. * The final chunk may contain fewer elements if the input array length is not evenly divisible * by `portionLength`. * * @typeParam T - Type of the elements in the input array. * * @param arr - The source array to be split. It can be any readonly array (or tuple). * @param portionLength - The desired size of each portion. Must be a **positive integer**. * * @returns A new two-dimensional array (`T[][]`), where each inner array is one portion. * If `portionLength` is not a positive integer, an empty array is returned. * * @remarks * - This function is **non-mutating**: the original array is never modified. * - If `portionLength` exceeds the array length, the result will be a single chunk * containing the entire array. * - If the input array is empty, the result is an empty array. * - Uses `Array.prototype.slice()` internally, so the returned chunks are **shallow copies**. * * ### Performance * - Time complexity: **O(n)** — each element is visited exactly once. * - Space complexity: **O(n)** — proportional to the total number of elements copied. * - For extremely large arrays (millions of elements), prefer a streaming approach * if memory is a concern. * * ### Edge cases * - `portionLength <= 0` → returns `[]`. * - `portionLength` is not an integer (e.g. `2.5`, `NaN`) → returns `[]`. * - `arr.length === 0` → returns `[]`. * - Works correctly with frozen arrays and readonly tuples. * * @example * // Split an array into groups of 3 * splitArrToPortions([1, 2, 3, 4, 5, 6, 7], 3); * // => [[1, 2, 3], [4, 5, 6], [7]] * * @example * // Portion length larger than array * splitArrToPortions(['a', 'b'], 5); * // => [['a', 'b']] * * @example * // Non-integer or invalid sizes * splitArrToPortions([1, 2, 3], 0); // => [] * splitArrToPortions([1, 2, 3], -2); // => [] * splitArrToPortions([1, 2, 3], NaN); // => [] * * @example * // Works with readonly arrays * const input = [10, 20, 30, 40] as const; * const result = splitArrToPortions(input, 2); * // result: [[10, 20], [30, 40]] * * @category Array * @public * @since 2.0.0 */ declare function splitArrToPortions<T>(arr: readonly T[], portionLength: number): T[][]; /** * Converts any given value into a normalized boolean (`true` / `false`). * * @summary * Performs **loose coercion** of different input types into a `boolean` * following predictable rules for numbers, strings, and actual boolean values. * Non-recognized values always return `false`. * * @param value - Any unknown input that should be interpreted as a boolean. * * @returns The normalized boolean result (`true` or `false`). * * @remarks * This function is designed to **gracefully handle** a wide variety of input forms — * including primitive values, numeric types, and user-typed strings (like `"yes"`, `"no"`, `"on"`, `"off"`). * * ### Conversion Rules (in order of precedence) * 1. **Native booleans** → returned as-is. * - `true` → `true` * - `false` → `false` * * 2. **Positive numbers** → interpreted as `true`. * - `isNumP(value)` check passes (typically `> 0`). * - Examples: `1`, `42`, `3.14` → `true` * * 3. **Zero or negative numbers** → interpreted as `false`. * - `isNumNZ(value)` check passes (typically `<= 0`). * - Examples: `0`, `-1` → `false` * * 4. **Truthy strings** → `"true"`, `"1"`, `"yes"`, `"on"` (case-insensitive) * - `"TrUe"` → `true` * - `" YES "` → `true` * * 5. **Falsy strings** → `"false"`, `"0"`, `"no"`, `"off"` (case-insensitive) * - `"False"` → `false` * - `" off "` → `false` * * 6. **Everything else** → `false` * - `null`, `undefined`, `NaN`, empty string, symbols, objects, arrays, etc. * * ### String Handling * - Strings are **trimmed** and **lower-cased** before comparison. * - Case and whitespace are ignored. * - Empty strings (`""`) return `false`. * * ### Error Safety * - The function **never throws**. * - Non-primitive or unexpected types are handled safely and result in `false`. * * ### Performance * - Time complexity: **O(1)**. * - Space complexity: **O(1)**. * * ### Examples * * @example * // Native booleans * formatToBool(true); // => true * formatToBool(false); // => false * * @example * // Numeric values * formatToBool(1); // => true * formatToBool(0); // => false * formatToBool(-5); // => false * * @example * // String values * formatToBool('yes'); // => true * formatToBool('No'); // => false * formatToBool('TRUE'); // => true * formatToBool('false'); // => false * formatToBool('on'); // => true * formatToBool('off'); // => false * * @example * // Mixed and invalid inputs * formatToBool(null); // => false * formatToBool(undefined); // => false * formatToBool([]); // => false * formatToBool({}); // => false * formatToBool('maybe'); // => false * * @see isBool * @see isNumP * @see isNumNZ * @see isStrFilled * * @category Conversion * @public * @since 2.0.0 */ declare function formatToBool(value: unknown): boolean; /** * Waits asynchronously for the specified amount of time. * * @summary * A tiny promise-based delay utility that resolves after `timeout` milliseconds. * It wraps `setTimeout` in a `Promise`, making it convenient to use with * `async/await` or as part of larger promise chains. * * @param timeout - The delay duration in **milliseconds** before the promise resolves. * @defaultValue 0 * * @returns A `Promise<void | true>` that settles after the given delay. * * @example * // Basic usage: pause for ~500 ms * await wait(500); * console.log('Half a second later…'); * * @example * // Measure elapsed time * const started = Date.now(); * await wait(1200); * const elapsed = Date.now() - started; // ~= 1200ms (subject to timer clamping and scheduling) * * @example * // Use inside a retry/backoff loop * for (let attempt = 1; attempt <= 5; attempt++) { * try { * await doWork(); * break; * } catch (err) { * // exponential backoff between attempts * await wait(2 ** attempt * 100); * } * } * * @example * // Parallel delays (resolve when the longest finishes) * await Promise.all([wait(100), wait(250), wait(50)]); * * @remarks * - **Timing accuracy:** JavaScript timers are **best-effort** and may be delayed * by event-loop load, CPU throttling, tab being backgrounded, or platform-specific * clamping. Treat `timeout` as a *minimum* delay, not an exact scheduler. * - **Negative or non-finite values:** Passing `<= 0`, `NaN`, or a non-finite value * effectively behaves like `0` and resolves on a future macrotask tick. * - **Cancellation:** This helper **does not support cancellation**. If you need to * abort a wait, consider a variant that accepts an `AbortSignal` and clears the * timer when aborted. * - **Event loop semantics:** `setTimeout(0)` schedules a **macrotask**; it does not * run synchronously. Code after `await wait(0)` will execute on a subsequent turn * of the event loop. * * Notes: * - Suitable for throttling UI interactions, pacing network retries, and writing * deterministic tests (with caution re: flakiness). * - Keep delays small in performance-critical code paths; prefer debouncing or * requestAnimationFrame for UI-animation pacing when appropriate. * * Complexity: * - Time: **O(1)** (scheduling a single timer) * - Space: **O(1)** (a promise and a timer reference) * * Performance: * - The function allocates a single promise and a timer handle. * - Timer resolution is platform dependent; Node.js and browsers may clamp very * small delays to a minimum threshold under load. * * Security: * - No I/O, side effects, or data exposure. Purely schedules a future resolution. * * <b>Returns remarks</b>: * The internal promise resolves with the value `true`, but callers typically * use `await wait(...)` and ignore the value. If you need a strictly `void` * result, you can cast or ignore the resolution value. * * @category Utilities • Timing * @since 1.0.0 * @see {@link https://developer.mozilla.org/docs/Web/API/setTimeout MDN: setTimeout} */ declare function wait(timeout?: number): Promise<void>; /** * Represents a human-readable breakdown of a time duration * into its fundamental components — **days**, **hours**, **minutes**, and **seconds**. * * @remarks * This interface is used by time utility functions such as * {@link secondsToParts} and {@link partsToSeconds} to represent durations * in a normalized structure that is easy to read, format, or serialize. * * Each field is an **integer number** representing the whole count of that unit. * None of the fields are fractional, and they are expected to follow * these conventional bounds when generated by {@link secondsToParts}: * * ``` * days ≥ 0 * hours ∈ [0, 23] * minutes ∈ [0, 59] * seconds ∈ [0, 59] * ``` * * However, when constructing manually, these constraints are **not enforced** * by TypeScript — it is up to the user or calling function to maintain validity. * * @example * ```ts * // Example 1: Typical decomposition * const t: TimeParts = { days: 1, hours: 2, minutes: 30, seconds: 45 }; * * // Example 2: Used with utility converters * const total = partsToSeconds(t); // -> 95445 * const back = secondsToParts(total); // -> same structure again * ``` * * @example * ```ts * // Example 3: Display formatting * const p: TimeParts = { days: 0, hours: 5, minutes: 3, seconds: 9 }; * console.log(`${p.hours}h ${p.minutes}m ${p.seconds}s`); * // -> "5h 3m 9s" * ``` * * @property days - Whole number of days (24-hour periods). * @property hours - Whole number of hours in the remaining day (0–23 typical). * @property minutes - Whole number of minutes (0–59 typical). * @property seconds - Whole number of seconds (0–59 typical). * * @see {@link secondsToParts} — converts total seconds into this structure. * @see {@link partsToSeconds} — converts this structure back into total seconds. * * @public * @category Date & Time * @since 2.0.0 */ interface TimeParts { days: number; hours: number; minutes: number; seconds: number; } /** * Floors a given {@link Date} object down to the nearest time interval in minutes. * * @remarks * This utility function is commonly used for time bucketing, grouping logs, or * aligning timestamps to fixed intervals (e.g. 5-minute or 15-minute marks). * * It takes an arbitrary `Date` and returns a **new** `Date` instance (it does not * mutate the input) where: * * - The `minutes` value is floored down to the nearest multiple of `everyMinutes`. * - `seconds` and `milliseconds` are reset to `0`. * - The hour and day remain unchanged. * * The step is automatically clamped to the range **1 – 60 minutes** to prevent * invalid or nonsensical values. * * The function allocates a single new `Date` object. * It is safe for high-frequency use in real-time systems and event batching. * * @param everyMinutes - The step interval (in minutes) used for rounding down. * Must be a positive finite number. * Values below 1 are treated as 1, values above 60 as 60. * * @param date - The input date to be floored. * Defaults to the current time (`new Date()`). * * @returns A **new** `Date` instance, representing the same hour as the input, * but with minutes rounded down to the nearest `everyMinutes` multiple. * * @example * ```ts * // Example 1: Floor to the nearest 15-minute mark * const d = new Date('2025-10-18T10:43:27'); * floorDateToMinutes(15, d); * // -> 2025-10-18T10:30:00.000Z * ``` * * @example * ```ts * // Example 2: Using default date (current time) * const nowFloored = floorDateToMinutes(10); * // -> e.g. 2025-10-18T09:20:00.000Z * ``` * * @example * ```ts * // Example 3: Clamp behavior * floorDateToMinutes(-5, new Date()); // treated as 1 minute * floorDateToMinutes(999, new Date()); // treated as 60 minutes * ``` * * @throws Never throws — invalid step values are automatically normalized. * * @see {@link Date#setMinutes} for the underlying mutation logic. * @see {@link Date#getMinutes} for how minutes are extracted from a Date. * * @public * @category Date & Time * @since 2.0.0 */ declare function floorDateToMinutes(everyMinutes?: number, date?: Date): Date; /** * Formats a {@link Date} object into a human-readable timestamp string * using the pattern `"YYYY-MM-DD HH:mm:ss"`. * * @remarks * This function is a simple and locale-independent date formatter that always * outputs a **24-hour clock** timestamp with leading zeros for all numeric parts. * * It does **not** depend on the user's locale or time zone settings beyond what * is stored in the provided `Date` object. If you pass a `Date` constructed * from UTC or local time, the formatted output will reflect that same basis. * * Each date/time component (month, day, hours, minutes, seconds) is padded to * two digits using {@link String.padStart}, ensuring consistent width such as * `2025-03-07 09:04:02`. * * - The format is fixed-width and consistent — ideal for logs, filenames, * and database-friendly timestamps. * - The output is **not ISO 8601** (which uses a `'T'` separator and optional * timezone offset). * Example: ISO → `"2025-10-18T10:43:27Z"` * This function → `"2025-10-18 10:43:27"`. * * @param date - The date to format. Defaults to the **current system time** * (`new Date()`). * * @returns A formatted timestamp string in `"YYYY-MM-DD HH:mm:ss"` form. * * @example * ```ts * // Example 1: Specific date * const d = new Date('2025-10-18T10:43:27Z'); * formatDateToString(d); * // -> "2025-10-18 10:43:27" * ``` * * @example * ```ts * // Example 2: Default (current) date * formatDateToString(); * // -> e.g. "2025-10-18 12:07:55" * ``` * * @example * ```ts * // Example 3: Padding behavior * const d = new Date('2025-03-07T09:04:02'); * formatDateToString(d); * // -> "2025-03-07 09:04:02" * ``` * * @throws Never throws. * * @see {@link Date} for JavaScript’s native date-handling API. * @see {@link Intl.DateTimeFormat} for locale-aware formatting if needed. * * @public * @category Date & Time * @since 2.0.0 */ declare function formatDateToString(date?: Date): string; /** * Converts a partial {@link TimeParts} structure (days, hours, minutes, seconds) * into a total number of **seconds**. * * @remarks * This helper provides a simple way to normalize human-readable time components * into a single scalar duration in seconds. * It can be useful for: * - time-based arithmetic (e.g., adding offsets to timestamps), * - scheduling or delay computation, * - serializing durations into numeric fields (e.g., databases or APIs). * * All fields (`days`, `hours`, `minutes`, `seconds`) are **optional**; any missing * value defaults to `0`. The calculation uses fixed conversion factors: * * - 1 day = 86 400 seconds * - 1 hour = 3 600 seconds * - 1 minute = 60 seconds * * - Fractional or negative numbers are accepted and processed arithmetically. * Example: `{ minutes: 1.5 }` → `90`; `{ hours: -1 }` → `-3600`. * - The function performs no validation; it assumes numeric input. * TypeScript typing (`number`) ensures intended usage. * * @param parts - A partial object containing any subset of time fields. * Missing values default to zero. * * @returns The total number of seconds represented by the provided time parts. * * @example * ```ts * // Example 1: Simple conversion * partsToSeconds({ hours: 1, minutes: 30 }); // -> 5400 * * // Example 2: Full time span * partsToSeconds({ days: 2, hours: 3, minutes: 5, seconds: 10 }); * // -> 183910 * * // Example 3: Partial / missing fields * partsToSeconds({}); // -> 0 * partsToSeconds({ minutes: 5 }); // -> 300 * ``` * * @throws Never throws. * * @see {@link secondsToParts} — the inverse operation that expands seconds back into components. * * @public * @category Date & Time * @since 2.0.0 */ declare function partsToSeconds(parts: { days?: number; hours?: number; minutes?: number; seconds?: number; }): number; /** * Decomposes a total number of seconds into discrete time components: * **days**, **hours**, **minutes**, and **seconds**. * * @remarks * This is the inverse operation of {@link partsToSeconds}. * It converts a flat duration (in seconds) into a more human-readable structure * suitable for display, logging, or formatting. * * The function performs integer division using {@link Math.floor} for each component * and ensures that the result satisfies: * * ``` * 0 <= hours < 24 * 0 <= minutes < 60 * 0 <= seconds < 60 * ``` * * Any fractional part of the input (e.g., `12.75`) is truncated (floored) to the * nearest lower whole second. * Negative or non-finite inputs are considered invalid and will throw an error. * * - Uses only a few arithmetic operations and is **O(1)**. * - Safe for real-time conversions or high-frequency usage (e.g., monitoring dashboards). * * @param total - Total duration in seconds. * Must be a **finite, non-negative number**. * * @returns A {@link TimeParts} object with integer fields: * - `days` * - `hours` * - `minutes` * - `seconds` * * @example * ```ts * // Example 1: Basic conversion * secondsToParts(3661); * // -> { days: 0, hours: 1, minutes: 1, seconds: 1 } * ``` * * @example * ```ts * // Example 2: Multi-day value * secondsToParts(90061); * // -> { days: 1, hours: 1, minutes: 1, seconds: 1 } * ``` * * @example * ```ts * // Example 3: Invalid input * secondsToParts(-10); // throws Error("Invalid total seconds") * secondsToParts(NaN); // throws Error("Invalid total seconds") * ``` * * @throws {Error} * Thrown when `total` is not a finite, non-negative number. * * @see {@link partsToSeconds} — the complementary function that aggregates components into seconds. * @see {@link TimeParts} — the return type describing the breakdown of time. * * @public * @category Date & Time * @since 2.0.0 */ declare function secondsToParts(total: number): TimeParts; /** * Options that control how IPv4 ranges are iterated and materialized. * * @remarks * These options are primarily consumed by {@link rangeIPv4} and {@link rangeIPv4ToArr}. * They let you include/exclude the network and broadcast addresses when the input * is a CIDR block, and limit the maximum number of items when materializing to an array. * * @public * @category IPv4 * @since 2.0.0 */ interface RangeIPv4Options { /** * Hard cap on the number of elements to materialize into a returned array. * * @remarks * This option is **only** consulted by {@link rangeIPv4ToArr}. It prevents * accidentally allocating huge arrays when the supplied range is very large * (e.g. `0.0.0.0/0` contains 4,294,967,296 addresses). * * If the computed range size exceeds this limit, an error will be thrown. * * @defaultValue `1_000_000` * @example * ```ts * // Will throw because /16 has 65,536 addresses (> 10_000) * rangeIPv4ToArr('10.0.0.0/16', undefined, { limit: 10_000 }) * ``` */ limit?: number; /** * Whether to include the *network* address when iterating a CIDR range. * * @remarks * This flag is only applied when the input is a CIDR (e.g. `"192.168.0.0/24"`). * For non-CIDR, ad-hoc ranges, network/broadcast semantics are not inferred. * * For `/31` and `/32` specifically, there is no distinct network/broadcast * address to exclude, so this flag has no effect. * * @defaultValue `true` * @example * ```ts * // Exclude 192.168.1.0 from a /24 network * [...rangeIPv4('192.168.1.0/24', undefined, { includeNetwork: false })]; * ``` */ includeNetwork?: boolean; /** * Whether to include the *broadcast* address when iterating a CIDR range. * * @remarks * This flag is only applied when the input is a CIDR (e.g. `"192.168.0.0/24"`). * For `/31` and `/32`, there is no broadcast in the traditional sense, * so this flag has no effect. * * @defaultValue `true` * @example * ```ts * // Exclude 192.168.1.255 from a /24 network * [...rangeIPv4('192.168.1.0/24', undefined, { includeBroadcast: false })]; * ``` */ includeBroadcast?: boolean; } /** * Converts a CIDR block into its inclusive start/end IPv4 addresses. * * @remarks * The function validates the CIDR notation and returns a tuple of dotted-quad * IPv4 strings representing the first and last addresses in the block. * For `/0` the range spans the entire IPv4 address space. For `/32` the start * and end are the same single address. * * @param cidr - CIDR notation string, e.g. `"192.168.1.0/24"` or `"10.0.0.1/32"`. * @returns A tuple `[start, end]` in dotted-quad form, or `null` if input is invalid. * * @example * ```ts * cidrToRange('192.168.1.0/24'); // ['192.168.1.0','192.168.1.255'] * cidrToRange('10.0.0.1/32'); // ['10.0.0.1','10.0.0.1'] * cidrToRange('bad'); // null * ``` * * @throws Never throws; returns `null` on invalid input. * @see {@link parseIPv4} to parse an IPv4 string to a 32-bit number. * @see {@link toIPv4} to convert a number back to dotted-quad. * @public * @category IPv4 * @since 2.0.0 */ declare function cidrToRange(cidr: string): [string, string] | null; /** * Converts a dotted-decimal IPv4 address string (e.g. `"192.168.0.1"`) * into its **32-bit unsigned integer** representation. * * @remarks * This function performs a strict validation of the IPv4 address and encodes * each of its four octets into a 32-bit number using **big-endian (network byte order)**. * * The resulting number is in the range `0..4_294_967_295` (`0xFFFFFFFF`), * where: * * - `"0.0.0.0"` → `0` * - `"255.255.255.255"` → `4294967295` * * This representation is particularly useful for: * - performing numeric range comparisons (e.g., IP ranges, CIDR checks); * - storing IPv4 values compactly in binary structures or databases; * - bitwise operations such as masking and subnet arithmetic. * * - The conversion uses a {@link DataView} and explicit byte writes * to guarantee consistent big-endian behavior across platforms. * - The output number is safe for 32-bit unsigned arithmetic via `>>> 0`. * - If you need the inverse operation, see {@link numToIpAddr}. * * @param ip - The IPv4 address in dotted-quad string form. * * @returns A 32-bit **unsigned integer** representing the given IPv4 address. * * @example * ```ts * // Example 1: Simple conversion * ipAddrToNum("192.168.0.1"); * // -> 3232235521 * * // Example 2: Edge values * ipAddrToNum("0.0.0.0"); // -> 0 * ipAddrToNum("255.255.255.255"); // -> 4294967295 * ``` * * @example * ```ts * // Example 3: Invalid input * ipAddrToNum("192.168.1"); // throws Error("Invalid IPv4 address") * ipAddrToNum("256.0.0.1"); // throws Error("Invalid IPv4 address") * ipAddrToNum("abc.def.ghi.jkl"); // throws Error("Invalid IPv4 address") * ``` * * @throws {Error} * Thrown when: * - The input does not contain exactly four parts separated by dots. * - Any octet is not an integer between 0 and 255 inclusive. * * @see {@link numToIpAddr} — converts a 32-bit integer back to an IPv4 string. * @see {@link parseIPv4} — similar numeric parser using bitwise operations. * * @public * @category Network & IP * @since 2.0.0 */ declare function ipAddrToNum(ip: string): number; /** * Converts a 32-bit unsigned integer (numeric IPv4 representation) * back into its dotted-decimal string form (e.g. `"192.168.0.1"`). * * @remarks * This is the inverse of {@link ipAddrToNum}. * It interprets the input number as a **big-endian (network-byte-order)** * IPv4 value, extracting each of the four octets and joining them into * the standard dotted-quad notation. * * If the input is not a valid finite number (checked via {@link isNumP}), * an empty string `""` is returned instead of throwing an exception. * * The resulting string always consists of **exactly four decimal octets** * separated by dots, with each octet in the range `0–255`. * * - Internally uses {@link DataView} to ensure consistent big-endian behavior * across all platforms. * - The output format is always normalized (no leading zeros, no spaces). * - For the forward direction (string → number), see {@link ipAddrToNum}. * * @param num - The 32-bit unsigned integer representing an IPv4 address. * * @returns A dotted-decimal IPv4 string (e.g. `"10.0.0.1"`), * or an empty string if the input is invalid. * * @example * ```ts * // Example 1: Basic conversion * numToIpAddr(3232235521); * // -> "192.168.0.1" * * // Example 2: Edge values * numToIpAddr(0); // -> "0.0.0.0" * numToIpAddr(4294967295); // -> "255.255.255.255" * ``` * * @example * ```ts * // Example 3: Invalid inputs * numToIpAddr(NaN); // -> "" * numToIpAddr(Infinity); // -> "" * numToIpAddr(-5); // -> "" * ``` * * @throws Never throws; invalid inputs simply return an empty string. * * @see {@link ipAddrToNum} — converts dotted IPv4 strings to numeric form. * @see {@link parseIPv4} — alternative parser using bitwise arithmetic. * * @public * @category Network & IP * @since 2.0.0 */ declare function numToIpAddr(num: number): string; /** * Parses a dotted-quad IPv4 string (e.g. `"192.168.0.1"`) into a 32-bit unsigned integer. * * @remarks * The returned number is in the range `0..0xFFFFFFFF` and represents the IPv4 address * in big-endian order (i.e. the usual network order). * * The function is strict about format: * - Exactly 4 decimal octets separated by dots. * - Each octet must be `0..255`. * - Only digits are allowed in each octet. * * Leading zeros in octets are permitted (e.g. `"001.002.003.004"`), but you may * choose to forbid them in a custom variant to avoid legacy octal confusions. * * @param ip - Dotted-quad IPv4 string to parse. * @returns The IPv4 as an unsigned 32-bit number, or `null` if invalid. * * @example * ```ts * parseIPv4('127.0.0.1'); // 2130706433 * parseIPv4('256.0.0.1'); // null * parseIPv4('1.2.3'); // null * ``` * * @public * @category IPv4 * @since 2.0.0 */ declare function parseIPv4(ip: string): number | null; declare function rangeIPv4(from: string, to?: string): Generator<string>; /** * Creates a lazy generator over an inclusive IPv4 range. * * @remarks * The function supports two input modes: * * 1. **CIDR mode** — when `from` contains a slash and `to` is `undefined`: * ```ts * for (const ip of rangeIPv4('192.168.1.0/30')) { ... } * ``` * In this mode, {@link RangeIPv4Options.includeNetwork} and * {@link RangeIPv4Options.includeBroadcast} are honored for masks `<= /30`. * For `/31` and `/32` there is no traditional network/broadcast to exclude. * * 2. **Ad-hoc range mode** — when `from` is an IPv4 and `to` is either an IPv4 * or empty/omitted: * - If `to` is provided, the range is `[min(from,to) .. max(from,to)]`. * - If `to` is omitted or blank, the range spans to the end of the `/24` * block: `A.B.C.D .. A.B.C.255`. * * The iteration is inclusive of both endpoints and is safe around the upper * bound: if the current value is `0xFFFFFFFF`, the generator yields it once and terminates. * * This is a lazy generator: it does **not** allocate the entire range up-front, * making it suitable for very large ranges (iterate/stream/process on the fly). * If you need a materialized array, consider {@link rangeIPv4ToArr} but mind its `limit`. * * @overload * @param from - A CIDR string (e.g. `"10.0.0.0/8"`). If this overload is used, `to` must be `undefined`. * * @overload * @param from - Starting IPv4 address in dotted-quad form. * @param to - Optional ending IPv4 address in dotted-quad form. If omitted or empty, the range ends at `A.B.C.255`. * @param opts - Iteration options. * @returns A generator of dotted-quad IPv4 strings. * * @param from - See overloads. * @param to - See overloads. * @param opts - See overloads. * * @example * ```ts * // 1) CIDR iteration (include all) * [...rangeIPv4('192.168.1.0/30')]; * // -> ['192.168.1.0','192.168.1.1','192.168.1.2','192.168.1.3'] * * // 2) CIDR iteration without network/broadcast * [...rangeIPv4('192.168.1.0/30', undefined, { includeNetwork: false, includeBroadcast: false })]; * // -> ['192.168.1.1','192.168.1.2'] * * // 3) Ad-hoc range (explicit end) * [...rangeIPv4('10.0.0.1', '10.0.0.4')]; * // -> ['10.0.0.1','10.0.0.2','10.0.0.3','10.0.0.4'] * * // 4) Single address ⇒ to end of /24 * [...rangeIPv4('10.1.2.3')].at(-1); // '10.1.2.255' * ``` * * @throws {Error} * - If `from` is not a valid IPv4 (in non-CIDR mode). * - If `to` is supplied and is not a valid IPv4 (in non-CIDR mode). * - If `from` is not a valid CIDR in CIDR mode. * * @see {@link cidrToRange} to convert a CIDR to `[ start, end ]`. * @see {@link rangeIPv4ToArr} to materialize a range into an array with a safe limit. * @public * @category IPv4 * @since 2.0.0 */ declare function rangeIPv4(from: string, to: string | undefined, opts?: RangeIPv4Options): Generator<string>; /** * Materializes an IPv4 range into an array of dotted-quad strings. * * @remarks * This is a convenience wrapper around the lazy {@link rangeIPv4} generator that * collects the yielded addresses into a new array. To protect against excessive * memory usage, a hard {@link RangeIPv4Options.limit | limit} is enforced * (default `1_000_000`). If the range exceeds the limit, an error is thrown and * **no** partial array is returned. * * Prefer using the generator for very large ranges, streaming the results into * your processing pipeline (e.g. writing to a file or socket). * * @param from - See {@link rangeIPv4} for accepted forms (CIDR or IPv4). * @param to - Optional end address (non-CIDR mode). Ignored for CIDR input. * @param opts - Options including the array size `limit`. See {@link RangeIPv4Options}. * @returns A new array with all IPv4 addresses in the range (inclusive). * * @example * ```ts * // Small range OK * rangeIPv4ToArray('192.168.1.10', '192.168.1.13'); * // -> ['192.168.1.10','192.168.1.11','192.168.1.12','192.168.1.13'] * * // Will throw if exceeds the limit * rangeIPv4ToArray('10.0.0.0/16', undefined, { limit: 10_000 }); // Error * ``` * * @throws {Error} If the realized array would exceed `opts.limit`. * @see {@link rangeIPv4} for lazy iteration without materialization. * @public * @category IPv4 * @since 2.0.0 */ declare function rangeIPv4ToArr(from: string, to?: string, opts?: RangeIPv4Options): string[]; /** * Converts an unsigned 32-bit integer into a dotted-quad IPv4 string. * * @remarks * This is the inverse of {@link parseIPv4}. The function validates that the input * is a finite integer within `0..0xFFFFFFFF` and then formats it as `A.B.C.D`. * * @param n - Unsigned 32-bit IPv4 value (`0..0xFFFFFFFF`). * @returns A dotted-quad string such as `"192.168.0.1"`. * * @example * ```ts * toIPv4(0); // "0.0.0.0" * toIPv4(0xFFFFFFFF); // "255.255.255.255" * ``` * * @throws {Error} If `n` is not an integer in `0..0xFFFFFFFF`. * @see {@link parseIPv4} * @public * @category IPv4 * @since 2.0.0 */ declare function toIPv4(n: number): string; /** * Configuration options that define password validation rules. * * This interface allows you to specify various constraints * that determine whether a given password is considered valid. * * @example * ```ts * const options: PasswordOptions = { * minLength: 8, * maxLength: 32, * requireUppercase: true, * requireLowercase: true, * requireDigit: true, * requireSpecial: true, * }; * ``` * * @remarks * You can use these options to build password validation functions, * enforce strong password policies, or configure authentication modules. * * @since 2.0.0 */ interface PasswordOptions { /** * Minimum allowed number of characters in the password. * * @defaultValue `0` * @example * ```ts * { minLength: 8 } // password must contain at least 8 characters * ``` */ minLength?: number; /** * Maximum allowed number of characters in the password. * * @defaultValue `Infinity` * @example * ```ts * { maxLength: 32 } // password cannot exceed 32 characters * ``` */ maxLength?: number; /** * Whether the password must contain at least one uppercase Latin letter (A–Z). * * @defaultValue `false` * @example * ```ts * { requireUppercase: true } // 'Password1' - OK 'password1' - BAD * ``` */ requireUppercase?: boolean; /** * Whether the password must contain at least one lowercase Latin letter (a–z). * * @defaultValue `false` * @example * ```ts * { requireLowercase: true } // 'PASSWORD1' - BAD 'Password1' - OK * ``` */ requireLowercase?: boolean; /** * Whether the password must include at least one numeric digit (0–9). * * @defaultValue `false` * @example * ```ts * { requireDigit: true } // 'Password' - BAD 'Password1' - OK * ``` */ requireDigit?: boolean; /** * Whether the password must include at least one special character * (such as `!@#$%^&*()-_=+[]{};:'",.<>/?`). * * @defaultValue `false` * @example * ```ts * { requireSpecial: true } // 'Password1' - BAD 'Password1!' - OK * ``` */ requireSpecial?: boolean; } /** * Checks whether a given value is an array. * * @summary * A strongly typed wrapper around {@link Array.isArray}, with an enhanced TypeScript * type guard that asserts the value as a **readonly non-empty array** (`readonly [T, ...T[]]`). * * @typeParam T - The expected element type of the array (defaults to `unknown`). * * @param value - Any value to test. * * @returns `true` if the value is an array (of any kind), otherwise `false`. * The return type acts as a **type guard**, allowing TypeScript to infer that * `value` is a readonly array of `T` when the function returns `true`. * * @remarks * - Internally uses the native {@link Array.isArray} method. * - Works correctly across realms (e.g., iframes, worker contexts, etc.). * - The type guard ensures `value` is a **readonly non-empty array**, not just an empty list. * This provides safer downstream access patterns when empty arrays are not expected. * - If you need to allow empty arrays, consider changing the type to `readonly T[]`. * * ### Performance * - Time complexity: **O(1)** — constant time native check. * - Space complexity: **O(1)**. * * ### Common pitfalls * - `isArr([])` → `true`, even though the static type is `readonly [T, ...T[]]`. * TypeScript does not validate runtime emptiness; you should still check `value.length`. * - `isArr('abc')` → `false` * - `isArr({ length: 3 })` → `false` * * ### Examples * * @example * // Basic usage * isArr([1, 2, 3]); // => true * isArr('hello'); // => false * isArr({}); // => false * * @example * // With type inference * const val: unknown = [10, 20]; * if (isArr<number>(val)) { * // TypeScript now knows val: readonly [number, ...number[]] * console.log(val[0]); // OK * } * * @example * // With mixed content * isArr([true, 'text', 123]); // => true * * @see Array.isArray * * @category Type Guards * @public * @since 2.0.0 */ declare function isArr<T = unknown>(value: unknown): value is readonly [T, ...T[]]; /** * Checks whether a value is a **non-empty array**. * * @summary * A strongly-typed type guard that returns `true` only if the input value is an array * (via {@link isArr}) and contains at least one element (`length > 0`). * * Useful for narrowing unknown data to a **readonly non-empty tuple type** * (`readonly [T, ...T[]]`), which gives TypeScript safer access guarantees. * * @typeParam T - Expected element type of the array (defaults to `unknown`). * * @param value - Any value to test. * * @returns `true` if `value` is an array with at least one element; otherwise `false`. * * @remarks * ### Type narrowing * When this function returns `true`, TypeScript automatically infers that: * ```ts * value is readonly [T, ...T[]] * ``` * * That means inside the `if` block, you can safely access `value[0]` * without additional checks. * * ### Behavior * - Delegates the array check to {@link isArr}. * - Works with both mutable (`T[]`) and readonly arrays (`readonly T[]`). * - Does **not** mutate or clone the array. * - Returns `false` for: * - Non-array values (`null`, `undefined`, `object`, `string`, etc.). * - Empty arrays (`[]`). * * ### Performance * - Time complexity: **O(1)** (constant time check). * - Space complexity: **O(1)**. * * ### Examples * * @example * // Basic usage * isArrFilled([1, 2, 3]); // => true * isArrFilled([]); // => false * * @example * // With type inference * const maybeNumbers: unknown = [10, 20]; * if (isArrFilled<number>(maybeNumbers)) { * // value is now typed as: readonly [number, ...number[]] * console.log(maybeNumbers[0]); // OK * } * * @example * // Non-array values * isArrFilled('abc'); // => false * isArrFilled(null); // => false * isArrFilled(undefined); // => false * isArrFilled({ length: 2 }); // => false * * @see isArr * * @category Type Guards * @public * @since 2.0.0 */ declare function isArrFilled<T = unknown>(value: unknown): value is readonly [T, ...T[]]; /** * Checks whether a given value is a boolean (`true` or `false`). * * @summary * A strict type guard that returns `true` only if `value` is of type `"boolean"`. * * This helps safely narrow unknown or mixed-type values in TypeScript code, * especially when working with dynamic data sources, JSON, or user input. * * @param value - Any value to check. * * @returns `true` if the value is strictly a boolean, otherwise `false`. * * @remarks * - Uses the built-in `typeof` operator (`typeof value === "boolean"`). * - Does **not** coerce values — only primitive `true` or `false` are accepted. * - Returns `false` for Boolean objects created via `new Boolean()`, because those * are of type `"object"`, not `"boolean"`. * - Designed as a **type guard**, so when it returns `true`, TypeScript will infer: * ```ts * value is boolean * ``` * * ### Performance * - Time complexity: **O(1)** (constant). * - Space complexity: **O(1)**. * * ### Examples * * @example * // Basic usage * isBool(true); // => true * isBool(false); // => true * isBool(0); // => false * isBool('true'); // => false * * @example * // With type narrowing * const val: unknown = Math.random() > 0.5 ? true : 'yes'; * if (isBool(val)) { * // TypeScript now knows val: boolean * console.log(val ? 'OK' : 'NO'); * } * * @example * // Boolean object is not accepted * isBool(new Boolean(true)); // => false * * @category Type Guards * @public * @since 2.0.0 */ declare function isBool(value: unknown): value is boolean; /** * Checks whether a value represents a **valid JavaScript date**. * * @summary * Returns `true` if the given value is either: * - an actual `Date` instance with a valid timestamp, or * - a string or number that can be successfully parsed by the JavaScript `Date` constructor. * * Returns `false` for invalid dates (`Invalid Date`), empty strings, `NaN`, or non-date types. * * @param value - Any value to test (can be a `Date`, string, number, or other type). * * @returns `true` if the value can be interpreted as a valid date, otherwise `false`. * * @remarks * ### Validation logic * 1. **If `value` is a `Date` instance:** * Checks `!Number.isNaN(value.getTime())` — ensures it’s a real date, not an invalid one. * ```ts * isDate(new Date('invalid')); // false * ``` * * 2. **If `value` is a string or number:** * Attempts to construct a new `Date(value)`. * Returns `true` only if the resulting date’s timestamp is finite (not `NaN`). * * 3. **Otherwise:** * Returns `false`. * * ### What counts as "valid" * - OK: `"2024-12-31"`, `"2024-12-31T23:59:59Z"`, `1728000000000`, `new Date()` * - BAD: `"abc"`, `NaN`, `{}`, `null`, `undefined`, `new Date('invalid')` * * ### Type safety * - This is **not** a strict type guard (it doesn’t narrow to `Date`), * but you can pair it with a cast when `true`: * ```ts * if (isDate(v)) { * const d = new Date(v); // guaranteed valid * } * ``` * * ### Performance * - Time complexity: **O(1)** * (`Date` construction and timestamp check are constant-time operations). * - Space complexity: **O(1)**. * * ### Examples * * @example * // Valid Date instances * isDate(new Date()); // => true * isDate(new Date('2024-05-01')); // => true * * @example * // From strings or timestamps * isDate('2025-01-01T00:00:00Z'); // => true * isDate(1700000000000); // => true * isDate('not-a-date'); // => false * * @example * // Invalid cases * isDate({}); // => false * isDate([]); // => false * isDate(''); // => false * isDate(new Date('invalid')); // => false * * @see isStr * @see isNum * @see Date * * @category Type Guards * @public * @since 2.0.0 */ declare function isDate(value: unknown): boolean; /** * Checks whether a given value is a **valid email address**. * * @summary * Validates that the input is a non-empty string and matches a simplified but * practical email pattern according to RFC 5322-compatible syntax rules. * * @param value - Any value to test (string or unknown). * * @returns `true` if the value is a non-empty string that looks like a valid email, * otherwise `false`. * * @remarks * ### Validation process * 1. Ensures the input is a **non-empty string** via {@link isStrFilled}. * 2. Tests the value against a precompiled **regular expression**: * ``` * /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+ * @[a-zA-Z0-9] * (?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? * (?:\.[a-zA-Z]{2,})+$/ * ``` * This allows standard ASCII characters in the local part and enforces: * - at least one `@` separator * - valid domain and subdomain segments * - a top-level domain of at least two letters. * * ### Behavior notes * - Returns `false` for empty strings, `null`, `undefined`, or non-string inputs. * - Does **not** perform DNS or MX record validation — only syntactic matching. * - Intended for lightweight client-side or structural checks. * - If you need full compliance with RFC 6531 (Unicode / IDN), normalize the address first. * * ### Performance * - Time complexity: **O(n)** — proportional to input length. * - Space complexity: **O(1)**. * - The compiled regex is cached and reused for efficiency. * * ### Examples * * @example * // Valid emails * isEmail('user@example.com'); // => true * isEmail('john.doe+alias@mail.co.uk'); // => true * * @example * // Invalid formats * isEmail(''); // => false * isEmail('user@'); // => false * isEmail('@example.com'); // => false * isEmail('user@@example.com'); // => false * isEmail('user example@domain.com'); // => false * * @example * // Non-string inputs * isEmail(null); // => false * isEmail(undefined); // => false * isEmail(12345); // => false * * @see isStrFilled * * @category Validation * @public * @since 2.0.0 */ declare function isEmail(value: unknown): value is string; /** * Checks whether a value **exists** — i.e. is neither `null` nor `undefined`. * * @summary * A minimal and strongly typed utility that acts as a **type guard** * to filter out `null` and `undefined` values in TypeScript. * It is especially useful in array filters and conditional checks * where you need to ensure a value is "present". * * @typeParam T - The original type of the tested value. * * @param value - Any value that may be `null` or `undefined`. * * @returns `true` if `value` is not `null` and not `undefined`, otherwise `false`. * * @remarks * ### Type narrowing * When this function returns `true`, TypeScript automatically infers: * ```ts * value is T * ``` * * That means inside the `if` block (or after using `Array.filter(isExists)`), * the compiler knows the val