import type { VextMiddleware } from "../types/middleware.js"; import type { VextLogger } from "../types/app.js"; /** * middleware-loader.ts — 路由级中间件白名单加载器 * * 按 config/default.ts 中 middlewares 白名单声明,从 src/middlewares/ 目录 * 加载用户定义的路由级中间件,构建 MiddlewareRegistry 供 router-loader 使用。 * * 核心流程: * 1. 遍历 config.middlewares 白名单(字符串或 { name, options } 对象) * 2. 按 name 在 middlewaresDir 中查找对应文件(.ts/.js/.mjs/.cjs 优先级) * 3. 动态 import 获取 default export * 4. 通过 isMiddleware / isMiddlewareFactory 检测类型(显式标记优先) * 5. 兜底:未使用 defineMiddleware / defineMiddlewareFactory 的裸函数 → 运行时推断 + 警告 * 6. 声明一致性检查(普通中间件不能带 options / 工厂中间件不带 options 时宽松处理) * 7. 构建 MiddlewareRegistry(name → { handler, defaultOptions, kind }) * * Fail Fast 检测项: * - 白名单声明了但文件不存在 * - 文件无 default export * - default export 不是函数 * - 普通中间件(defineMiddleware)却在白名单中声明了 options * * @module lib/middleware-loader * @see IMPLEMENTATION-PLAN.md 任务 1.10 * @see 01b-middlewares.md §7(框架内部 middleware-loader.ts) */ /** * 中间件白名单中的声明格式 * * 与 config/default.ts 中 middlewares 数组的元素类型对齐。 * * 字符串:只声明名称,无默认参数 * 对象:声明名称 + 默认参数(工厂中间件使用) */ export type MiddlewareDecl = string | { name: string; options?: Record; }; /** * 中间件注册表中的单条记录 * * 包含中间件处理函数、默认参数和类型标识。 * router-loader 在路由注册时从 registry 中按 name 取出记录, * 根据 kind 决定是直接使用还是调用工厂函数。 */ export interface MiddlewareRegistryEntry { /** 中间件处理函数(普通)或工厂函数 */ handler: VextMiddleware | ((options?: Record) => VextMiddleware); /** 白名单中声明的默认参数(仅工厂中间件有值) */ defaultOptions: Record | undefined; /** 中间件类型标识 */ kind: "middleware" | "factory"; } /** * MiddlewareRegistry — 中间件注册表 * * name → MiddlewareRegistryEntry 的映射。 * 由 loadMiddlewares() 构建,传递给 router-loader 使用。 */ export type MiddlewareRegistry = Record; /** * loadMiddlewares — 按白名单加载中间件,构建 MiddlewareRegistry * * @param middlewaresDir src/middlewares/ 目录的绝对路径 * @param declarations config.middlewares 白名单声明数组 * @param logger VextLogger 实例(输出兼容性警告) * @returns MiddlewareRegistry(name → { handler, defaultOptions, kind }) * * @example * ```typescript * // bootstrap 内部 * const middlewareDefs = await loadMiddlewares( * path.join(rootDir, 'src/middlewares'), * app.config.middlewares, * app.logger, * ) * ``` */ export declare function loadMiddlewares(middlewaresDir: string, declarations: MiddlewareDecl[], logger: VextLogger, lifecycleLevel?: "concise" | "verbose"): Promise; /** * resolveMiddleware — 从 registry 中解析单个中间件引用 * * 路由 options.middlewares 中的每个引用(字符串或 { name, options }) * 通过此函数从 registry 中取出并实例化: * - 普通中间件 → 直接返回 handler * - 工厂中间件 → 使用路由覆盖 options 或默认 options 调用工厂 * * @param ref 路由中的中间件引用 * @param registry 已构建的中间件注册表 * @returns 实例化后的 VextMiddleware * @throws 引用的中间件不在 registry 中 / 类型不匹配 */ export declare function resolveMiddleware(ref: string | { name: string; options?: Record; }, registry: MiddlewareRegistry): VextMiddleware; /** * resolveMiddlewares — 批量解析中间件引用列表 * * 将路由 options.middlewares 数组中的所有引用解析为 VextMiddleware 数组。 * * @param refs 中间件引用列表 * @param registry 已构建的中间件注册表 * @returns VextMiddleware 数组(按声明顺序) */ export declare function resolveMiddlewares(refs: Array; }>, registry: MiddlewareRegistry): VextMiddleware[]; /** * validateMiddlewareRefs — 启动时统一验证所有路由的中间件引用 * * 在所有路由加载完成后调用,检查每条路由引用的中间件名称 * 是否都在 registry 中存在。不存在则 Fail Fast。 * * 这是 router-loader 在注册所有路由后的最后一道防线, * 确保不会有运行时才暴露的"中间件未注册"错误。 * * @param routeDefs 所有加载的路由定义对象 * @param registry 已构建的中间件注册表 * @throws 引用的中间件名称不在 registry 中 */ export declare function validateMiddlewareRefs(routeDefs: Array<{ routes: Array<{ method: string; path: string; options: { middlewares?: Array; }; }>; sourceFile: string; }>, registry: MiddlewareRegistry): void;