import type { VextApp } from "../types/app.js"; import type { StartupProfiler } from "./startup-profiler.js"; /** * plugin-loader.ts — 插件自动加载器 * * 扫描用户项目的 src/plugins/ 目录,自动加载所有插件文件, * 按拓扑排序(基于 dependencies/after 声明)依次执行 setup()。 * * 核心流程: * 1. 递归扫描 pluginsDir 下的所有 .ts/.js/.mjs/.cjs 文件 * 2. 排除 _ 开头的文件/目录、.d.ts、.test./.spec. 文件 * 3. 动态 import 每个文件,获取 default export(必须是 definePlugin 结果) * 4. Fail Fast 验证:名称重复、依赖不存在、循环依赖 * 5. 按 dependencies 字段拓扑排序(Kahn 算法) * 6. 依次执行 plugin.setup(app),带超时保护(默认 30s) * 7. 每次 setup 完成后 clearTimeout,防止定时器泄漏 * * Fail Fast 检测项: * - 文件无 default export 或格式错误 * - 插件名称重复 * - dependencies 引用不存在的插件 * - 循环依赖 * - setup() 超时 * - setup() 抛出异常 * * @module lib/plugin-loader * @see IMPLEMENTATION-PLAN.md 任务 1.9 * @see 04-plugins.md §2(目录结构与加载规则) * @see 04-plugins.md §4(框架内部 plugin-loader.ts) */ /** * 插件加载配置 */ export interface LoadPluginsOptions { /** * 插件 setup() 超时时间(毫秒) * * 每个插件的 setup() 必须在此时间内完成,否则抛出超时错误。 * 超时后框架 clearTimeout 并 reject,启动终止。 * * @default 30_000 (30 秒) */ setupTimeout?: number; /** * Optional startup profiler used by dev bootstrap diagnostics. * * Omitted in production/testing paths unless the caller explicitly wants * startup timing events. */ startupProfiler?: StartupProfiler; } /** * loadPlugins — 扫描 plugins/ 目录,拓扑排序后依次执行 setup * * @param app VextApp 实例(plugin 的 setup 接收此对象) * @param pluginsDir plugins/ 目录的绝对路径(如 /path/to/my-app/src/plugins) * @param options 加载选项 * * @example * ```typescript * // bootstrap 内部 * await loadPlugins(app, path.join(rootDir, 'src/plugins'), { * setupTimeout: app.config.plugin?.setupTimeout ?? 30_000, * }) * ``` */ export declare function loadPlugins(app: VextApp, pluginsDir: string, options?: LoadPluginsOptions): Promise;