/** * Deep merge utility — safely merges nested objects with configurable * conflict resolution, array merging, and prototype-pollution guarding. * * Used by: * - config-loader (config layer merging with primitive-array concatenation) * - secret-vault (config patching) * - json-path (json_merge tool with prefer-base / prefer-patch semantics) * * @module utils/deep-merge */ export declare const FORBIDDEN_PROTO_KEYS: Set; /** True when every element is a primitive or null (no nested objects/arrays). */ export declare function isPrimitiveArray(a: unknown[]): boolean; export interface DeepMergeOptions { /** * Which side wins on collision for scalars and arrays. * * - `'prefer-patch'` (default): patch value replaces base value. * - `'prefer-base'`: base value is kept, patch value is ignored. */ conflictResolution?: 'prefer-base' | 'prefer-patch'; /** * How to handle array values. * * - `'replace'` (default): patch array replaces base array entirely. * - `'concat-primitives'`: when both values are primitive arrays, * they are concatenated and deduped (via Set). Non-primitive * arrays still replace the base wholesale. */ arrayMode?: 'replace' | 'concat-primitives'; /** * Skip prototype-pollution keys (`__proto__`, `constructor`, etc.). * Enabled by default. Only disable when you control both inputs * and the keyset (e.g. when merging trusted JSON schemas). */ protectProto?: boolean; /** * Optional callback fired when a non-primitive (object) array is * replaced wholesale (only relevant with `arrayMode: 'concat-primitives'`). * Receives the key name, existing array length, and patch array length. * Used by config-loader for debug logging. */ onNonPrimitiveArrayReplace?: (key: string, existingLen: number, patchLen: number) => void; } /** * Recursively merge `patch` into `base`, returning a new object. * * - Nested plain objects are merged recursively. * - Arrays are handled per `options.arrayMode`. * - Scalar collisions are resolved per `options.conflictResolution`. * - `null` and non-object values in `patch` replace the base value * (unless `conflictResolution` is `'prefer-base'`). * - Keys in `base` that are absent from `patch` are preserved. * - `FORBIDDEN_PROTO_KEYS` are skipped in the patch (unless * `options.protectProto` is set to `false`). * * The function is generic over `T extends Record` for * callers that pass typed config objects, but the runtime signature * also accepts `unknown` inputs (used by the json-path plugin). */ export declare function deepMerge>(base: T, patch: Record, options?: DeepMergeOptions): T; export declare function deepMerge(base: unknown, patch: unknown, options?: DeepMergeOptions): unknown; //# sourceMappingURL=deep-merge.d.ts.map