full-utils
Version:
Сomprehensive collection of pure, zero-dependency functions for everyday JavaScript and TypeScript development.
1,472 lines (1,449 loc) • 155 kB
text/typescript
/**
* 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