/**
 * DevCompiler — esbuild 预编译器（Phase 2A 核心组件）
 *
 * 所有用户源码（TS、ESM、CJS）通过 esbuild 统一编译为 CJS `.js` 文件，
 * 解决了 ESM `import` 无法清除缓存的根本问题。
 *
 * 核心职责：
 *
 * | 职责              | 方法                         | 说明                                     |
 * |-------------------|------------------------------|------------------------------------------|
 * | 首次全量编译      | `start()`                    | 扫描 `src/` 下所有源文件，编译到 `.vext/dev/`  |
 * | Tier 1 单文件编译 | `compileSingle()` / `compileFiles()` | 代码修改时 O(1) 编译               |
 * | Tier 2 全量重编译 | `rebuildWithNewEntryPoints()`| 文件增删时重建 context                    |
 * | 路径映射          | `resolveCompiled()` / `resolveSource()` | 源文件 ↔ 编译产物              |
 *
 * 编译产物结构：
 *   src/routes/user.ts      →  .vext/dev/routes/user.js
 *   src/services/auth.ts    →  .vext/dev/services/auth.js
 *   src/config/default.ts   →  .vext/dev/config/default.js
 *
 * 分级编译策略：
 *   - Tier 1（~95% 场景）：文件内容修改 → `compileSingle()` ~1-5ms/文件（O(changed)）
 *   - Tier 2（~5% 场景）：文件新增/删除 → `rebuildWithNewEntryPoints()` ~50-600ms（O(all)）
 *
 * tsconfig 处理（v2.2）：
 *   - `esbuild.context()` 的 `tsconfig` 参数接受文件路径，能自动解析 `extends` 链
 *   - `esbuild.transform()` 的 `tsconfigRaw` 只接受 JSON 字符串，不解析 `extends`
 *   - 为保证 Tier 1 和 Tier 2 行为一致，`start()` 时预解析 tsconfig（展平 extends 链），
 *     缓存结果供 `compileSingle()` 使用
 *
 * @module lib/dev/compiler
 * @see 11a-dev-compiler.md（完整设计文档）
 * @see 09a-build.md §2.1（与 BuildCompiler 共享配置）
 * @see IMPLEMENTATION-PLAN.md 任务 2.1
 */
/**
 * DevCompiler 构造选项
 */
export interface DevCompilerOptions {
    /** 源码目录（绝对路径），通常是 `<projectRoot>/src` */
    srcDir: string;
    /** 编译输出目录（绝对路径），通常是 `<projectRoot>/.vext/dev` */
    outDir: string;
    /** tsconfig.json 路径（可选，绝对路径）。未提供时 esbuild 使用默认设置 */
    tsconfig?: string;
}
/**
 * DevCompiler 编译统计信息
 *
 * 由 `start()` 和 `rebuildWithNewEntryPoints()` 返回，
 * 用于 CLI 打印编译耗时和文件数等信息。
 */
export interface CompileStats {
    /** 编译的入口文件数量 */
    fileCount: number;
    /** 编译耗时（毫秒） */
    elapsed: number;
}
export declare class DevCompiler {
    /**
     * esbuild 增量编译上下文
     *
     * 通过 `esbuild.context()` 创建，支持 `rebuild()` 增量编译。
     * 当文件新增/删除时需要重建（`rebuildWithNewEntryPoints()`），
     * 因为 entryPoints 发生了变化。
     */
    private ctx;
    private readonly srcDir;
    private readonly outDir;
    private readonly tsconfig;
    /**
     * v2.2：预解析并展平的 tsconfig 内容（字符串形式）。
     *
     * esbuild.context() 的 `tsconfig` 参数接受文件路径，能自动解析 `extends` 链。
     * 但 esbuild.transform() 的 `tsconfigRaw` 只接受 JSON 字符串，不解析 `extends`。
     *
     * 为保证 Tier 1 (transform) 和 Tier 2 (context.rebuild) 行为一致，
     * 在 start() 时预解析 tsconfig（展平 extends 链），缓存结果供 compileSingle() 使用。
     */
    private resolvedTsconfigRaw;
    /**
     * 经过验证的 tsconfig 路径（文件确实存在时才有值）。
     *
     * 用户传入的 tsconfig 路径可能不存在（如项目初始化阶段），
     * esbuild.context() 会直接报错 "Cannot find tsconfig file"。
     * 因此在 resolveTsconfig() 中验证文件存在性，不存在时置为 undefined，
     * 后续 esbuild.context() 和 esbuild.transform() 均使用默认设置。
     */
    private validatedTsconfig;
    constructor(options: DevCompilerOptions);
    /**
     * start — 初始化 esbuild context 并执行首次全量编译
     *
     * 只应调用一次（在 dev bootstrap 启动时）。
     *
     * 流程：
     *   1. 清空输出目录（.vext/dev/）确保干净状态
     *   2. 预解析 tsconfig（展平 extends 链）
     *   3. 扫描 src/ 下所有源文件作为 entryPoints
     *   4. 创建 esbuild.context（增量编译上下文）
     *   5. 执行首次 rebuild（全量编译）
     *
     * @returns 编译统计信息
     * @throws esbuild 编译错误（语法错误等）会透传
     */
    start(): Promise<CompileStats>;
    /**
     * rebuild — 使用现有 context 执行全量增量重编译
     *
     * 当新增/删除文件时需要使用 `rebuildWithNewEntryPoints()` 而非此方法，
     * 因为 entry points 可能变化。
     *
     * 此方法用于 entry points 不变但需要重编译的场景（通常较少使用）。
     *
     * 典型耗时：
     *   - 50 文件项目:  ~10-30ms
     *   - 500 文件项目: ~50-200ms
     *   - 2000 文件项目: ~200-500ms
     *
     * @throws DevCompiler 未启动时抛出错误
     */
    rebuild(): Promise<void>;
    /**
     * rebuildWithNewEntryPoints — 文件增删时重建 esbuild context
     *
     * 当检测到文件新增或删除时调用（因为 entryPoints 发生了变化）。
     *
     * 流程：
     *   1. 释放旧的 esbuild context
     *   2. 重新扫描 src/ 下的源文件
     *   3. 创建新的 esbuild context（新 entryPoints）
     *   4. 执行全量编译
     *
     * 典型耗时：
     *   - 50 文件项目:  ~20-50ms
     *   - 500 文件项目: ~80-250ms
     *   - 2000 文件项目: ~250-600ms
     *
     * 仅在文件增删时触发（约 5% 场景），95% 的代码变更走 compileSingle() 路径。
     *
     * @returns 编译统计信息
     */
    rebuildWithNewEntryPoints(): Promise<CompileStats>;
    /**
     * compileSingle — 单文件编译（Tier 1：代码变更时使用）
     *
     * 使用 esbuild.transform() 只编译单个变更文件，不涉及其他文件。
     * 由于 Vext 不使用 bundle 模式（每个文件独立编译），transform() 的
     * 输出与 context.rebuild() 对同一文件的输出完全等价。
     *
     * 典型耗时：~1-5ms/文件，与项目总文件数无关（O(1) 编译）
     *
     * v2.2 修复：使用预解析的 resolvedTsconfigRaw 替代直接读取 tsconfig 文件，
     * 确保 extends 链被正确展平，与 context.rebuild() 行为一致。
     *
     * @param srcFile 变更的源文件绝对路径
     * @returns 编译产物的绝对路径
     * @throws 文件读取失败、esbuild 编译错误时抛出
     */
    compileSingle(srcFile: string): Promise<string>;
    /**
     * compileFiles — 批量单文件编译（多文件同时变更时并行编译）
     *
     * 当防抖窗口内多个文件同时变更时，并行调用 compileSingle。
     * 每个文件的编译是独立的，适合 Promise.all 并行。
     *
     * @param srcFiles 变更的源文件绝对路径列表
     * @returns 编译产物的绝对路径列表
     */
    compileFiles(srcFiles: string[]): Promise<string[]>;
    /**
     * resolveCompiled — 将源文件路径映射为编译后的产物路径
     *
     * 支持两种输入：
     *   - 绝对路径: /project/src/routes/user.ts → /project/.vext/dev/routes/user.js
     *   - 相对于项目根目录的路径: src/routes/user.ts → /project/.vext/dev/routes/user.js
     *
     * 映射规则：
     *   1. 去掉 srcDir 前缀，得到相对路径
     *   2. 将 .ts / .mts / .cts / .mjs / .cjs 扩展名替换为 .js
     *   3. 拼接到 outDir
     *
     * @param srcFile 源文件路径（绝对路径或相对于项目根目录）
     * @returns 编译产物的绝对路径
     */
    resolveCompiled(srcFile: string): string;
    /**
     * resolveSource — 将编译产物路径映射回源文件路径（反向映射）
     *
     * 用于错误堆栈显示、日志中将编译产物路径转换回用户可理解的源文件路径。
     *
     * 注意：反向映射不恢复原始扩展名（.ts / .mjs 等），
     * 因为编译产物只有 .js 扩展名，无法确定原始扩展名。
     * 返回的路径使用 .js 扩展名，调用方如需精确匹配可自行检查。
     *
     * @param compiledFile 编译产物的绝对路径
     * @returns 对应的源文件路径（使用 .js 扩展名）
     */
    resolveSource(compiledFile: string): string;
    /** 获取源码目录（绝对路径） */
    getSrcDir(): string;
    /** 获取编译输出目录（绝对路径） */
    getOutDir(): string;
    /** 获取项目根目录（srcDir 的父目录） */
    getProjectRoot(): string;
    /**
     * dispose — 释放 esbuild 资源
     *
     * 关闭 esbuild context（释放子进程/内存）。
     * 在 dev 服务器关闭时调用（graceful shutdown）。
     * 调用后不可再使用 rebuild / compileSingle 等方法。
     */
    dispose(): Promise<void>;
    /**
     * scanEntryPoints — 扫描 src/ 目录下的所有可编译源文件
     *
     * 使用 fast-glob 扫描，返回相对于 srcDir 的路径列表。
     * 排除 .d.ts 声明文件和测试文件。
     *
     * @returns 相对于 srcDir 的源文件路径列表
     */
    private scanEntryPoints;
    /**
     * resolveTsconfig — 预解析 tsconfig.json，展平 extends 链（v2.2）
     *
     * 读取 tsconfig.json，如果包含 extends，递归合并父配置，
     * 最终输出一个不含 extends 的纯 JSON 字符串。
     * 这样 esbuild.transform() 的 tsconfigRaw 能获得与 esbuild.context()
     * 的 tsconfig（路径参数）完全一致的编译行为。
     *
     * 注意：只提取 esbuild 实际使用的字段（compilerOptions 中的
     * target、jsx、jsxFactory、jsxFragment、useDefineForClassFields、
     * importsNotUsedAsValues、preserveValueImports、experimentalDecorators、
     * verbatimModuleSyntax 等），其他字段不影响 transform 行为。
     *
     * 错误处理：tsconfig 不存在或解析失败时静默降级，
     * transform 将使用 esbuild 默认设置。
     */
    private resolveTsconfig;
    /**
     * flattenTsconfig — 递归展平 tsconfig，合并 extends 链
     *
     * 递归处理 tsconfig 的 extends 字段：
     *   1. 读取当前 tsconfig 文件
     *   2. 移除 JSON 中的注释（tsconfig 允许单行和多行注释）
     *   3. 解析 JSON
     *   4. 如果有 extends → 递归加载父配置
     *   5. 子配置的 compilerOptions 覆盖父配置（浅合并）
     *
     * @param tsconfigPath tsconfig 文件的绝对路径
     * @returns 展平后的配置对象（仅包含 compilerOptions）
     */
    private flattenTsconfig;
}
