import type { VextApp } from "../types/app.js"; /** * service-loader.ts — 服务层自动加载器 * * 扫描用户项目的 src/services/ 目录,自动加载所有 service 文件, * 通过 new ServiceClass(app) 实例化后按文件路径映射为嵌套 key * 注入到 app.services 对象上。 * * 核心流程: * 1. 递归扫描 servicesDir 下的所有 .ts/.js/.mjs/.cjs 文件 * 2. 排除 _ 开头的文件/目录、.d.ts、.test./.spec. 文件 * 3. 动态 import 每个文件,获取 default export(必须是 class / 构造函数) * 4. 文件路径 → 嵌套 service key(kebab-case → camelCase) * 5. new mod.default(app) 实例化,通过 setNestedKey 挂载到 app.services * 6. Fail Fast:key 冲突、非 class 导出 * 7. 所有 service 加载完成后,执行循环依赖静态检测(源码正则分析 + DFS) * * 路径映射示例: * services/user.ts → app.services.user * services/user-profile.ts → app.services.userProfile * services/payment/stripe.ts → app.services.payment.stripe * services/payment/alipay.ts → app.services.payment.alipay * services/_helpers.ts → 跳过(_ 前缀) * * Fail Fast 检测项: * - 文件无 default export 或导出非 class/构造函数 * - service key 冲突(两个文件映射到相同的 key 路径) * - service 之间循环依赖(静态源码分析 + DFS) * * @module lib/service-loader * @see IMPLEMENTATION-PLAN.md 任务 1.12 * @see 02-services.md §4(框架内部 service-loader.ts) * @see 02-services.md §7.1(循环依赖运行时检测) */ /** * loadServices 配置选项 */ export interface LoadServicesOptions { /** * 是否执行循环依赖检测 * * 生产环境(vext start)和开发环境(vext dev)均默认开启。 * 可通过此选项关闭(仅用于特殊测试场景)。 * * @default true */ checkCircularDeps?: boolean; } /** * loadServices — 扫描 services/ 目录,实例化并注入到 app.services * * @param app VextApp 实例(service 构造函数接收此对象) * @param servicesDir services/ 目录的绝对路径(如 /path/to/my-app/src/services) * @param options 加载选项 * * @example * ```typescript * // bootstrap 内部 * await loadServices(app, path.join(rootDir, 'src/services'), { * checkCircularDeps: true, * }) * ``` */ export declare function loadServices(app: VextApp, servicesDir: string, options?: LoadServicesOptions): Promise;