/***************************************************************************
 * XyPrissJS - Fast And Secure
 *
 * @author Nehonix
 * @license Nehonix OSL (NOSL)
 *
 * Copyright (c) 2025 Nehonix. All rights reserved.
 *
 * This License governs the use, modification, and distribution of software
 * provided by NEHONIX under its open source projects.
 * NEHONIX is committed to fostering collaborative innovation while strictly
 * protecting its intellectual property rights.
 * Violation of any term of this License will result in immediate termination of all granted rights
 * and may subject the violator to legal action.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL NEHONIX BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES ARISING FROM THE USE OR INABILITY TO USE THE SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 ***************************************************************************** */
export type ArrayStrategy = "replace" | "concat" | "merge";
export interface MergeOptions {
    /**
     * How to handle arrays when both `defaults` and `userOptions` have an
     * array at tme key.
     * - `"replace"` (default) — user array wins entirely.
     * - `"concat"`            — `[...defaultArray, ...userArray]`.
     * - `"merge"`             — element-wise: recurse for plain-object items,
     *                           otherwise use the user element (or the default
     *                           element when the user array is shorter).
     */
    arrayStrategy?: ArrayStrategy;
}
/**
 * mergeWithDefaults — Smart config merge utility
 *
 * Unlike `{ ...defaults, ...userOptions }` (shallow spread), this utility:
 *
 * 1. **User-provided keys always win** — a key present in `userOptions` (even
 *    if its value is `false`, `null`, `0`, or `""`) is NEVER overridden by a
 *    default. Only truly absent keys fall back to the default.
 *
 * 2. **Deep merge for plain objects** — nested objects are merged recursively
 *    at any depth, so that `userOptions.rateLimit.max` doesn't wipe out
 *    `defaults.rateLimit.windowMs`.
 *
 * 3. **No mutation** — returns a new object; inputs are untouched.
 *
 * 4. **Circular reference protection** — cycles are detected and broken
 *    (the circular reference is replaced by `undefined`).
 *
 * 5. **Prototype pollution protection** — dangerous keys (`__proto__`,
 *    `constructor`, `prototype`) are silently ignored.
 *
 * 6. **Array strategy** — configurable via `options.arrayStrategy`:
 *    - `"replace"` (default) — user array fully replaces the default array.
 *    - `"concat"`            — arrays are concatenated (defaults first).
 *    - `"merge"`             — elements are merged index-by-index (plain
 *                              objects recurse, primitives use user value).
 *
 * 7. **Symbol keys** — included in the merge alongside string keys.
 *
 * ### Example
 * ```ts
 * const defaults = {
 *   origin: true,
 *   credentials: false,
 *   maxAge: 86400,
 *   rateLimit: { max: 100, windowMs: 60_000 },
 * };
 * const user = {
 *   credentials: true,
 *   origin: ["http://localhost:5173"],
 *   rateLimit: { max: 50 },          // windowMs falls back to default
 * };
 *
 * mergeWithDefaults(defaults, user);
 * // → {
 * //     origin: ["http://localhost:5173"],
 * //     credentials: true,
 * //     maxAge: 86400,
 * //     rateLimit: { max: 50, windowMs: 60_000 },
 * //   }
 * ```
 */
export declare function mergeWithDefaults<T extends Record<string | symbol, any>>(defaults: T, userOptions: Partial<T> | undefined | null, options?: MergeOptions, 
/** @internal — tracks visited objects to break circular refs */
_seen?: WeakSet<object>): T;
//# sourceMappingURL=mergeWithDefaults.d.ts.map