/**
 * config-loader.ts — 配置加载器
 *
 * 负责加载并合并三层配置文件（default → env → local），
 * 执行 Fail Fast 校验，然后 deepFreeze 返回只读配置对象。
 *
 * 合并规则（含 CJS interop 支持）：
 *   - 普通标量（port、host）：覆盖（后者优先）
 *   - 普通对象（logger、cors）：深度合并（只覆盖写了的子字段）
 *   - middlewares[] 数组：按 name patch 合并（匹配则浅合并，未匹配则追加）
 *
 * 配置文件结构：
 *   src/config/
 *   ├── default.ts       — 基准配置（必须存在）
 *   ├── development.ts   — 开发环境覆盖（可选）
 *   ├── production.ts    — 生产环境覆盖（可选）
 *   └── local.ts         — 本地覆盖（最高优先级，可选，不提交 git）
 *
 * @module lib/config-loader
 * @see 05-config.md §5（配置合并规则）
 * @see IMPLEMENTATION-PLAN.md 任务 1.1
 */
import type { VextConfig, VextMiddlewareConfig } from "../types/app.js";
import { type BootstrapCommand } from "./bootstrap-config.js";
/**
 * 中间件声明的两种形式：
 *   - 字符串：中间件名称（如 'auth'）
 *   - 对象：带配置的中间件声明（如 { name: 'auth', options: { ... } }）
 */
type MiddlewareDecl = string | (VextMiddlewareConfig & {
    enabled?: boolean;
});
export interface LoadConfigMetadata {
    providerPatch?: Record<string, unknown>;
}
export interface LoadConfigOptions {
    rootDir?: string;
    command?: BootstrapCommand;
    isBuilt?: boolean;
    env?: NodeJS.ProcessEnv;
    meta?: LoadConfigMetadata;
}
/**
 * 在 configDir 下查找指定名称的配置文件
 *
 * 按 EXTENSIONS 顺序尝试，返回第一个存在的文件路径。
 *
 * @param configDir 配置目录绝对路径
 * @param name      文件名（不含扩展名），如 'default'、'production'、'local'
 * @returns 完整文件路径，或 null（不存在）
 */
declare function resolveConfigFile(configDir: string, name: string): string | null;
/**
 * 深度合并两个对象（target 上叠加 source）
 *
 * 合并策略：
 *   - 普通对象：递归合并（只覆盖 source 中有的字段，其余继承 target）
 *   - 数组：整体覆盖（非 middlewares，middlewares 走专用 patch）
 *   - 标量 / null / undefined：source 覆盖 target
 *
 * 注意：middlewares 字段不在此函数中处理，由 patchMiddlewares 单独处理。
 *
 * @param target 基准对象
 * @param source 覆盖对象
 * @returns 合并后的新对象（不修改 target 和 source）
 */
declare function deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T;
/**
 * middlewares 专用 patch 合并
 *
 * 按 name 匹配：
 *   1. 以 base 数组为基准（保持原始顺序）
 *   2. override 中每一项按 name 在 base 中查找
 *   3. 匹配到 → 浅合并该项（options / enabled 等字段覆盖）
 *   4. 未匹配到 → 追加到数组末尾
 *
 * @param base     基准数组（来自 default.ts 或上一层合并结果）
 * @param override 覆盖数组（来自 env.ts 或 local.ts）
 * @returns 合并后的新数组
 */
declare function patchMiddlewares(base: MiddlewareDecl[], override: MiddlewareDecl[]): MiddlewareDecl[];
declare function applyConfigLayer(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown>;
declare function applyCliOverrides(merged: Record<string, unknown>, env: NodeJS.ProcessEnv): Record<string, unknown>;
/**
 * 递归深冻结对象
 *
 * Object.freeze 只冻结顶层属性（浅冻结），嵌套对象仍可被修改。
 * deepFreeze 递归冻结所有层级，确保 config 完全只读。
 *
 * 跳过规则：
 *   - null / 非对象 / 已冻结对象 → 避免无意义递归
 *   - Date / RegExp / Buffer / Map / Set 等非纯对象 →
 *     冻结这些对象会破坏其内部状态（如 Date.setTime() 失效）
 *   - 跳过非纯对象的检查（Q23：不要冻结非纯对象）
 *
 * @param obj 待冻结对象
 * @returns 冻结后的对象（同一引用）
 */
declare function deepFreeze<T>(obj: T): T;
/**
 * 配置校验（启动时 Fail Fast）
 *
 * 在应用启动时立即校验配置合法性，发现问题立即抛出错误终止启动，
 * 避免运行时出现难以追踪的配置问题。
 *
 * @param config 合并后的配置对象
 * @throws Error 配置不合法时抛出描述性错误
 */
declare function validateConfig(config: Record<string, unknown>): void;
/**
 * 加载并合并配置文件
 *
 * 合并顺序：default → {NODE_ENV} → local
 * 合并完成后执行 Fail Fast 校验，通过后 deepFreeze 返回只读对象。
 *
 * @param configDir 配置目录绝对路径（通常为 path.join(projectRoot, 'src/config')）
 * @returns 合并、校验、冻结后的 VextConfig
 * @throws Error 配置文件缺失或配置不合法时抛出
 *
 * @example
 * ```typescript
 * import { loadConfig } from './config-loader.js'
 * import path from 'node:path'
 *
 * const config = await loadConfig(path.join(process.cwd(), 'src/config'))
 * // config 已 deepFreeze，运行时不可修改
 * ```
 */
export declare function loadRawConfig(configDir: string, options?: LoadConfigOptions): Promise<Record<string, unknown>>;
export declare function finalizeConfig(rawConfig: Record<string, unknown>): VextConfig;
export declare function loadConfig(configDir: string, options?: LoadConfigOptions): Promise<VextConfig>;
export { deepMerge as _deepMerge, deepFreeze as _deepFreeze, patchMiddlewares as _patchMiddlewares, applyCliOverrides as _applyCliOverrides, applyConfigLayer as _applyConfigLayer, validateConfig as _validateConfig, resolveConfigFile as _resolveConfigFile, };
