UNPKG

imean-service-engine

Version:

基于Hono的轻量级微服务引擎框架

2,263 lines (2,207 loc) 85 kB
import { Hono, MiddlewareHandler, Context } from 'hono'; export { Context, MiddlewareHandler } from 'hono'; import * as hono_utils_html from 'hono/utils/html'; import * as hono_jsx_jsx_dev_runtime from 'hono/jsx/jsx-dev-runtime'; import { ContentfulStatusCode } from 'hono/utils/http-status'; import { z } from 'zod'; export { z } from 'zod'; /** * 微服务引擎实现类 * @internal 此类型仅供内部使用,用户应通过 Factory.create() 创建引擎实例 */ declare class Microservice<ModuleOptions = Record<string, any>> { private modules; protected plugins: Plugin<Record<string, any>>[]; protected pluginRegistry: Map<string, Plugin<Record<string, any>>>; private moduleInstances; readonly options: Readonly<MicroserviceOptions>; private started; private readonly moduleMetadataKey; private actualPort; private hono; private server; constructor(options: MicroserviceOptions, moduleMetadataKey: symbol); /** * 获取 Hono 实例(供插件使用) */ getHono(): Hono; /** * 内部注册插件方法(供构造函数和子类使用) * @protected */ protected registerPlugin<T>(plugin: Plugin<T>): void; /** * 加载并注册所有模块(通过唯一的 key 查找) * 在引擎启动时调用,使用双向访问机制查找所有被装饰的类 * * 注意: * - 每个引擎实例使用唯一的 moduleMetadataKey,实现隔离 * - 模块类是静态的,可以被多个引擎实例共享 * - 每个引擎实例会创建独立的模块实例,互不影响 */ private loadModules; /** * 加载Handler元数据(平铺结构) * 每个装饰器都是独立的HandlerMetadata条目 * 为每个方法创建包装链管理器,提供简单的 wrap API */ private loadHandlerMetadata; /** * 应用所有包装链到原型 * 在所有插件执行完 onHandlerLoad 后调用 */ private applyWrapperChains; /** * 寻找一个随机的可用端口 */ private getRandomPort; /** * 启动引擎 * @param requestedPort 启动端口(可选,默认0,表示随机端口) * @returns 实际使用的端口号 */ start(requestedPort?: number): Promise<number>; /** * 确定实际使用的端口 */ private determinePort; /** * 初始化模块和插件 */ private initializeModulesAndPlugins; /** * 处理 Handler 元数据和插件包装 */ private processHandlers; /** * 执行插件启动钩子 */ private executePluginStartHooks; /** * 注册版本路由(/prefix/version) * 用于健康检查和探针 */ private registerVersionRoute; /** * 启动 HTTP 服务器 */ private startHttpServer; /** * 按优先级排序插件 */ private sortPluginsByPriority; /** * 获取插件优先级 */ private getPluginPriority; /** * 分离包装插件和路由插件 */ private separateWrapperAndRoutePlugins; /** * 执行插件钩子(通用方法) */ private executePluginHook; /** * 停止引擎 */ stop(): Promise<void>; /** * 获取模块实例(单例) * @param moduleClass 模块类 * @returns 模块实例 */ get<T extends Class>(moduleClass: T): InstanceType<T>; /** * 获取已注册的模块列表 */ getModules(): ModuleMetadata<Record<string, any>>[]; /** * 获取实际使用的端口 */ getPort(): number | null; /** * 确保引擎已初始化(模块和处理器已加载) * 如果引擎未启动,则执行必要的初始化步骤 */ private ensureInitialized; /** * 获取模块处理器方法(不启动 HTTP 服务器) * 适用于测试场景,可以完整执行中间件和处理逻辑 * * 返回一个已绑定模块和方法名的调用函数,调用时只需要传递方法参数 * 类型推导:自动推导方法参数类型和返回值类型(无需显式指定泛型参数) * * @param moduleClass 模块类 * @param methodName 方法名(handler 名称) * @returns 调用函数,只需要传递方法参数 * * @example * ```typescript * @Module("users") * class UserService { * @Action({ params: [z.string(), z.number()] }) * add(a: string, b: number): { result: number } { * return { result: Number(a) + b }; * } * * @Action({ params: [z.string()] }) * getUser(id: string): Promise<{ id: string; name: string }> { * return Promise.resolve({ id, name: "Alice" }); * } * } * * // 获取 handler 并调用(类型自动推导,无需显式指定泛型) * const addHandler = engine.handler(UserService, "add"); * const result1 = await addHandler("10", 20); * // result1 的类型是 { result: number } * * // 也可以链式调用 * const result2 = await engine.handler(UserService, "getUser")("123"); * // result2 的类型是 { id: string; name: string }(自动解包 Promise) * ``` */ handler<T extends Class, M extends keyof InstanceType<T> & string>(moduleClass: T, methodName: M): (...args: InstanceType<T>[M] extends (...args: infer P) => any ? P : never) => Promise<InstanceType<T>[M] extends (...args: any[]) => infer R ? R extends Promise<infer U> ? U : R : never>; /** * 使用 Hono 的 request 方法调用路由处理器(不启动 HTTP 服务器) * 适用于测试场景,可以完整执行中间件和处理逻辑 * * @param input Request 对象、URL 字符串或相对路径 * @param init RequestInit 选项(当 input 是字符串时使用) * @returns Response 对象 * * @example * ```typescript * // 使用相对路径 * const response = await engine.request("/api/users/123"); * * // 使用完整 URL * const response = await engine.request("http://localhost/api/users/123"); * * // 使用 Request 对象 * const request = new Request("http://localhost/api/users/123", { * method: "POST", * headers: { "Content-Type": "application/json" }, * body: JSON.stringify({ name: "Alice" }), * }); * const response = await engine.request(request); * ``` */ request(input: RequestInit | URL | string, init?: RequestInit): Promise<Response>; } /** * 核心类型定义 */ type Class = new (...args: any[]) => any; /** * 插件Module配置Schema(运行时+类型双维度) */ interface PluginModuleOptionsSchema<T = Record<string, any>> { _type: T; validate?: (options: T) => boolean | string; } /** * 插件优先级 * 数值越小,优先级越高(越先执行) * 引擎会自动按优先级排序,用户无需关心注册顺序 */ declare enum PluginPriority { /** * 系统级优先级:系统核心功能插件(优雅停机等) * 最高优先级,应该最先执行 */ SYSTEM = 50, /** * 最高优先级:安全相关插件(限流、认证等) * 应该最先执行,快速拒绝无效请求 */ SECURITY = 100, /** * 高优先级:日志、监控等插件 * 记录所有请求,包括被安全插件拒绝的 */ LOGGING = 200, /** * 中优先级:业务逻辑插件(数据转换等) * 在安全和日志之后执行 */ BUSINESS = 300, /** * 低优先级:性能优化插件(缓存等) * 在业务逻辑之后执行,避免重复计算 */ PERFORMANCE = 400, /** * 最低优先级:路由插件 * 必须最后执行,注册HTTP路由 */ ROUTE = 1000 } /** * 核心插件接口 */ interface Plugin<TModuleOptions = Record<string, any>> { name: string; /** * 插件优先级(可选) * 如果不指定,默认为 PluginPriority.BUSINESS * 引擎会自动按优先级排序,用户无需关心注册顺序 * * 优先级规则: * - 数值越小,优先级越高(越先执行) * - 相同优先级按注册顺序执行 */ priority?: PluginPriority | number; getModuleOptionsSchema?: () => PluginModuleOptionsSchema<TModuleOptions>; onInit?: (engine: Microservice) => void; onModuleLoad?: (modules: ModuleMetadata[]) => void; onHandlerLoad?: (handlers: HandlerMetadata[]) => void; onBeforeStart?: (engine: Microservice) => void; onAfterStart?: (engine: Microservice) => void | Promise<void>; onDestroy?: () => void | Promise<void>; } /** * 引擎创建选项 */ interface MicroserviceOptions { name: string; version: string; hostname?: string; prefix?: string; } /** * Module装饰器类型(由引擎实例创建,自动推导类型) * 使用最新的 Stage 3 装饰器标准 */ type ModuleDecorator<TOptions = Record<string, any>> = (name: string, options?: TOptions) => (target: Class, context: ClassDecoratorContext) => void; /** * 模块元数据 */ interface ModuleMetadata<TOptions = Record<string, any>> { name: string; clazz: Class; options: TOptions; } /** * Handler包装函数类型 * 插件只需要提供这个函数,引擎自动管理包装链 * * @param next 调用下一个包装层或原始方法 * @param instance 模块实例 * @param args 方法参数 * @returns 方法执行结果 */ type HandlerWrapper = (next: () => Promise<any> | any, instance: any, ...args: any[]) => Promise<any> | any; /** * Handler元数据(单组元数据) * 提供简单的 wrap API,引擎自动管理包装链和执行顺序 */ interface HandlerMetadata { type: string; options: Record<string, any>; method: Function; methodName: string; module: Class; /** * 包装当前方法(引擎自动管理包装链) * * 插件只需要调用这个方法,引擎会自动: * - 按插件优先级构建包装链 * - 确保 RoutePlugin 最后执行 * - 自动应用包装到原型 * * @param wrapper 包装函数 * - next: 调用下一个包装层或原始方法 * - instance: 模块实例 * - args: 方法参数 * * @example * ```typescript * handler.wrap(async (next, instance, ...args) => { * // 前置逻辑 * const result = await next(); * // 后置逻辑 * return result; * }); * ``` */ wrap(wrapper: HandlerWrapper): void; } /** * Stage 3 装饰器上下文类型 */ type ClassDecoratorContext = { kind: "class"; name: string | undefined; addInitializer(initializer: () => void): void; }; type ClassMethodDecoratorContext$1 = { kind: "method"; name: string | symbol; static: boolean; private: boolean; addInitializer(initializer: () => void): void; }; /** * 通用Handler装饰器(支持多应用) * 使用最新的 Stage 3 装饰器标准 * * @param config Handler配置 * @returns 方法装饰器 */ declare function Handler<T = Record<string, any>>(config: { type: string; options?: T; }): (target: Function, context: ClassMethodDecoratorContext) => void; /** * 核心异常类型定义 */ declare class PluginNameRequiredError extends Error { constructor(pluginName?: string); } declare class ModuleConfigValidationError extends Error { constructor(moduleName: string, pluginName: string, message: string); } declare class DuplicateModuleError extends Error { constructor(moduleName: string); } interface PreStartChecker { name: string; check: () => Promise<void> | void; skip?: boolean; } declare function startCheck(checkers: PreStartChecker[], pass?: () => void | Promise<void>): Promise<void>; declare const BaseLayout: (props?: { children?: any; title?: string; heads?: any; }) => hono_utils_html.HtmlEscapedString | Promise<hono_utils_html.HtmlEscapedString>; declare const HtmxLayout: (props?: { children?: any; title: string; favicon?: any; }) => hono_utils_html.HtmlEscapedString | Promise<hono_utils_html.HtmlEscapedString>; /** * 服务状态信息接口 * 基于 MicroserviceOptions,并添加运行时信息 */ interface ServiceStatusInfo { name: string; version: string; prefix?: string; hostname?: string; port?: number; env?: string; status?: string; } declare const ServiceInfoCards: ({ serviceInfo, }: { serviceInfo: ServiceStatusInfo; }) => hono_jsx_jsx_dev_runtime.JSX.Element; declare const ServiceStatusPage: ({ serviceInfo, }: { serviceInfo: ServiceStatusInfo; }) => hono_jsx_jsx_dev_runtime.JSX.Element; type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; /** * Route装饰器配置选项 */ interface RouteOptions { /** * HTTP方法(可选,默认为 GET) * 如果未指定,则默认为 GET 方法 */ method?: HTTPMethod | HTTPMethod[]; /** * 路由路径(支持单个路径或多个路径) * 如果提供数组,将为每个路径注册相同的处理器 */ path: string | string[]; /** * 路由专属中间件 */ middlewares?: MiddlewareHandler[]; /** * 路由描述(用于文档和日志) */ description?: string; /** * 请求参数校验规则 */ validate?: { query?: Record<string, any>; body?: Record<string, any>; params?: Record<string, any>; }; /** * 响应配置 */ response?: { status?: ContentfulStatusCode; type?: "json" | "text" | "html"; }; } /** * RoutePlugin的Module配置 * 注意:配置直接平铺在 Module options 中,不使用 route 命名空间 * 插件作者需要确保字段名不与其他插件冲突 */ interface RouteModuleOptions { routePrefix?: string; routeMiddlewares?: MiddlewareHandler[]; } /** * 错误转换函数 * 当路由处理器抛出异常时,可以自定义错误响应格式 * @param ctx Hono Context 对象 * @param error 捕获到的错误对象 * @param handler Handler 元数据,包含路由信息、方法名等 * @returns Response 对象或可序列化的值(会被自动转换为 Response) */ type ErrorTransformer = (ctx: Context, error: unknown, handler: HandlerMetadata) => Response | Promise<Response>; /** * RoutePlugin 配置选项 */ interface RoutePluginOptions { /** * 全局路径前缀(应用于所有路由) * 路径拼接顺序:全局前缀 + 模块前缀 + 路由路径 * 例如:prefix="/api", routePrefix="/v1", path="/users" => "/api/v1/users" */ prefix?: string; /** * 全局中间件(应用于所有路由) * 执行顺序:全局中间件 -> 模块级中间件 -> 路由级中间件 * 常用于鉴权、日志等全局功能 */ globalMiddlewares?: MiddlewareHandler[]; /** * 错误转换函数(可选) * 当路由处理器抛出异常时,可以自定义错误响应格式 * 如果不提供,将使用默认的错误响应格式 */ errorTransformer?: ErrorTransformer; } /** * Route装饰器(Handler的语法糖封装) * 固定type="route",简化HTTP路由标注 * 使用最新的 Stage 3 装饰器标准 * * @example * ```typescript * @Route({ method: "GET", path: "/users" }) * async getUsers(ctx: Context) { * return ctx.json({ users: [] }); * } * * // 支持多个路径 * @Route({ path: ["/", "/home", "/dashboard"] }) * async homePage(ctx: Context) { * return <HomePage />; * } * ``` */ declare function Route(options: RouteOptions): (target: Function, context: ClassMethodDecoratorContext) => void; /** * Page装饰器(Route的别名,用于向后兼容) * 专门用于页面路由,默认使用 GET 方法 * * @example * ```typescript * @Page({ path: ["/", "/home"] }) * async adminPage(ctx: Context) { * return HtmxLayout({ title: "Admin", children: <AdminLayout /> }); * } * ``` */ declare function Page(options: RouteOptions): (target: Function, context: ClassMethodDecoratorContext) => void; /** * RoutePlugin - 核心路由插件 * 负责解析type="route"的Handler元数据,注册HTTP路由到Hono实例 * * @example * ```typescript * // 使用全局前缀和中间件 * const authMiddleware = async (ctx, next) => { * // 验证 token * await next(); * }; * * const routePlugin = new RoutePlugin({ * prefix: "/api", // 全局路径前缀,所有路由都会加上这个前缀 * globalMiddlewares: [authMiddleware], * }); * ``` */ declare class RoutePlugin implements Plugin<RouteModuleOptions> { readonly name = "route-plugin"; readonly priority = PluginPriority.ROUTE; private engine; private globalPrefix; private globalMiddlewares; private errorTransformer?; /** * 构造函数 * @param options 插件配置选项 */ constructor(options?: RoutePluginOptions); /** * 声明Module配置Schema(用于类型推导+运行时校验) */ getModuleOptionsSchema(): PluginModuleOptionsSchema<RouteModuleOptions>; /** * 引擎初始化钩子:获取Hono实例 */ onInit(engine: Microservice): void; /** * Handler加载钩子:解析type="route"的Handler元数据,注册HTTP路由 */ onHandlerLoad(handlers: HandlerMetadata[]): void; } /** * Action装饰器配置选项 */ interface ActionOptions { /** * 动作描述 */ description?: string; /** * 参数校验 Schema(使用 zod) * 数组顺序对应方法参数的顺序 */ params: z.ZodTypeAny[]; /** * 返回值校验 Schema(使用 zod) */ returns?: z.ZodTypeAny; /** * 是否流式返回(默认 false) */ stream?: boolean; /** * 是否幂等(默认 false) */ idempotence?: boolean; /** * 路由专属中间件 */ middlewares?: MiddlewareHandler[]; } /** * ActionPlugin的Module配置 */ interface ActionModuleOptions { /** * 模块级路由中间件 */ actionMiddlewares?: MiddlewareHandler[]; } /** * ActionPlugin - 动作处理插件 * 提供基于下标的参数传递、zod 校验和自动参数注入 */ declare class ActionPlugin implements Plugin<ActionModuleOptions> { readonly name = "action-plugin"; readonly priority = PluginPriority.ROUTE; private engine; /** * 声明Module配置Schema(用于类型推导+运行时校验) */ getModuleOptionsSchema(): PluginModuleOptionsSchema<ActionModuleOptions>; /** * 引擎初始化钩子:获取Hono实例 */ onInit(engine: Microservice): void; /** * Handler加载钩子:解析type="action"的Handler元数据,注册HTTP路由 */ onHandlerLoad(handlers: HandlerMetadata[]): void; } /** * Action装饰器(Handler的语法糖封装) * 固定type="action",用于标注动作处理方法 */ declare function Action(options: ActionOptions): (target: Function, context: ClassMethodDecoratorContext) => void; /** * Cache装饰器配置选项 */ interface CacheOptions { /** * 缓存失效时间(毫秒) * 默认:60000 (1分钟) */ ttl?: number; /** * 缓存键生成函数 * 函数签名应该和处理器方法一样,接收相同的参数 * 可以返回任意值,返回值会被 ejson 序列化后进行 hash 生成缓存键 * 如果不提供,将使用入参(args)进行相同的计算 * * @example * ```typescript * @Cache({ * key: (id: string, name: string) => ({ id, name }), // 返回对象 * ttl: 5000 * }) * async getUser(id: string, name: string) { * return { id, name }; * } * ``` */ key?: (...args: any[]) => any; /** * 是否启用缓存 * 默认:true */ enabled?: boolean; } /** * CachePlugin的Module配置 * 注意:配置直接平铺在 Module options 中 */ interface CacheModuleOptions { /** * 默认缓存失效时间(毫秒) * 默认:60000 (1分钟) */ cacheDefaultTtl?: number; /** * 是否启用全局缓存 * 默认:true */ cacheEnabled?: boolean; /** * 缓存清理间隔(毫秒) * 默认:60000 (1分钟) */ cacheCleanupInterval?: number; } /** * 缓存项数据结构 */ interface CacheItem<T = any> { value: T; expiresAt: number; createdAt: number; } /** * Cache Adapter 接口 * 定义缓存存储的抽象接口,支持不同的存储后端 */ /** * 缓存适配器接口 */ interface CacheAdapter { /** * 获取缓存项 * @param key 缓存键 * @returns 缓存项,如果不存在或已过期则返回 null */ get<T = any>(key: string): Promise<CacheItem<T> | null>; /** * 设置缓存项 * @param key 缓存键 * @param item 缓存项 */ set<T = any>(key: string, item: CacheItem<T>): Promise<void>; /** * 删除缓存项 * @param key 缓存键 * @returns 是否删除成功 */ delete(key: string): Promise<boolean>; /** * 清空所有缓存 */ clear(): Promise<void>; /** * 获取所有缓存键(用于统计) * @returns 缓存键数组(不包含过期项) */ keys(): Promise<string[]>; /** * 清理所有过期项(高效批量清理) * @returns 清理的过期项数量 */ cleanupExpired?(): Promise<number>; /** * 获取缓存统计信息 */ getStats(): Promise<{ size: number; entries: Array<{ key: string; expiresAt: number; createdAt: number; }>; }>; } /** * 内存缓存适配器 * 使用 Map 存储,适合单进程应用 * * 注意:过期项会在以下情况被自动清理: * 1. get() 时检查并删除过期项 * 2. keys() 和 getStats() 会过滤过期项 * 3. 建议通过 CachePlugin 的定期清理机制主动清理过期项 */ declare class MemoryCacheAdapter implements CacheAdapter { private cache; get<T = any>(key: string): Promise<CacheItem<T> | null>; set<T = any>(key: string, item: CacheItem<T>): Promise<void>; delete(key: string): Promise<boolean>; clear(): Promise<void>; keys(): Promise<string[]>; /** * 清理所有过期项(高效批量清理) * 这个方法比通过 keys() + get() + delete() 更高效 */ cleanupExpired(): Promise<number>; getStats(): Promise<{ size: number; entries: Array<{ key: string; expiresAt: number; createdAt: number; }>; }>; } /** * Redis 缓存适配器配置 */ interface RedisCacheAdapterOptions { /** * Redis 客户端实例(需要实现基本的 get/set/del/keys 方法) * 可以是 ioredis、node-redis 等 */ client: { get(key: string): Promise<string | null>; set(key: string, value: string, expiryMode?: string, time?: number): Promise<string | null>; del(key: string): Promise<number>; keys(pattern: string): Promise<string[]>; }; /** * 键前缀,用于区分不同应用的缓存 * 默认:'cache:' */ keyPrefix?: string; } /** * Redis 缓存适配器 * 使用 Redis 作为存储后端,适合分布式应用 * * 注意:Redis 本身支持 TTL(Time To Live),过期键会自动删除, * 因此不需要手动清理过期项。当使用 SET key value EX seconds 时, * Redis 会在过期后自动删除键。 */ declare class RedisCacheAdapter implements CacheAdapter { private client; private keyPrefix; constructor(options: RedisCacheAdapterOptions); private getKey; get<T = any>(key: string): Promise<CacheItem<T> | null>; set<T = any>(key: string, item: CacheItem<T>): Promise<void>; delete(key: string): Promise<boolean>; clear(): Promise<void>; keys(): Promise<string[]>; /** * 清理所有过期项 * * 注意:Redis 本身支持自动过期(通过 SET key value EX seconds), * 过期键会被 Redis 自动删除。但在某些情况下(如测试环境、某些 Redis 客户端), * 可能需要手动清理。此方法会检查并清理: * 1. 已过期但尚未被 Redis 删除的键(双重保险) * 2. JSON 解析失败的数据 */ cleanupExpired(): Promise<number>; getStats(): Promise<{ size: number; entries: Array<{ key: string; expiresAt: number; createdAt: number; }>; }>; } /** * CachePlugin - 缓存插件 * 负责为标记了 @Cache 装饰器的方法提供缓存功能 * * @example * ```ts * // 使用内存缓存(默认) * const cachePlugin = new CachePlugin(); * * // 使用自定义适配器 * const cachePlugin = new CachePlugin(new MemoryCacheAdapter()); * * // 使用 Redis 适配器 * import { RedisCacheAdapter } from "./adapter"; * const cachePlugin = new CachePlugin(new RedisCacheAdapter({ client: redisClient })); * ``` */ declare class CachePlugin implements Plugin<CacheModuleOptions> { readonly name = "cache-plugin"; readonly priority = PluginPriority.PERFORMANCE; private adapter; private cleanupTimer; private engine; private defaultTtl; private cacheEnabled; private cleanupInterval; /** * 构造函数 * @param adapter 缓存适配器,如果不提供则使用默认的内存缓存适配器 */ constructor(adapter?: CacheAdapter); /** * 声明Module配置Schema */ getModuleOptionsSchema(): PluginModuleOptionsSchema<CacheModuleOptions>; /** * 引擎初始化前钩子 */ onInit(engine: Microservice): void; /** * Handler加载后钩子 * 拦截带有 type="cache" 的 Handler,包装原始方法实现缓存逻辑 */ onHandlerLoad(handlers: HandlerMetadata[]): void; /** * 引擎启动前钩子 */ onBeforeStart(engine: Microservice): void; /** * 引擎停止时钩子 */ onDestroy(): Promise<void>; /** * 生成缓存键 * @param moduleName 模块名 * @param methodName 方法名 * @param keyFunction 可选的 key 函数 * @param args 方法参数 * @returns 缓存键(格式:模块名:方法名:hash) */ private generateCacheKey; /** * 清理过期缓存 */ private cleanup; /** * 获取缓存统计信息 */ getStats(): Promise<{ size: number; entries: Array<{ key: string; expiresAt: number; createdAt: number; }>; }>; /** * 清空所有缓存 */ clear(): Promise<void>; /** * 删除指定的缓存项 */ delete(key: string): Promise<boolean>; } /** * Cache装饰器 * 用于标记需要缓存的方法 * * @example * ```typescript * @Cache({ ttl: 5000 }) * async getUser(id: number) { * return { id, name: "John" }; * } * ``` */ declare function Cache(options?: CacheOptions): (target: Function, context: ClassMethodDecoratorContext) => void; /** * 优雅停机插件配置选项 */ interface GracefulShutdownPluginOptions { /** * 停机超时时间(毫秒) * 默认:10分钟(600000ms) */ shutdownTimeout?: number; /** * 是否启用优雅停机 * 默认:true */ enabled?: boolean; } /** * 优雅停机插件 * * 功能: * 1. 追踪所有处理器的执行状态(包括 Action、Route、Schedule 等) * 2. 监听系统停机信号(SIGINT、SIGTERM 等) * 3. 收到信号后,等待所有正在执行的处理器完成 * 4. 如果超时或所有处理完成,执行优雅停机 * * @example * ```typescript * // 使用默认配置(10分钟超时) * const gracefulShutdownPlugin = new GracefulShutdownPlugin(); * * // 自定义超时时间(5分钟) * const gracefulShutdownPlugin = new GracefulShutdownPlugin({ * shutdownTimeout: 5 * 60 * 1000, // 5分钟 * }); * ``` */ declare class GracefulShutdownPlugin implements Plugin { readonly name = "graceful-shutdown-plugin"; readonly priority = PluginPriority.SYSTEM; private engine; private options; private activeHandlers; private isShuttingDown; private shutdownTimer; private signalListeners; constructor(options?: GracefulShutdownPluginOptions); /** * 引擎初始化钩子 */ onInit(engine: Microservice): void; /** * Handler加载钩子:拦截所有处理器,追踪执行状态 */ onHandlerLoad(handlers: HandlerMetadata[]): void; /** * 引擎启动后钩子:注册系统信号监听器 */ onAfterStart(engine: Microservice): Promise<void>; /** * 注册系统信号监听器 */ private registerSignalHandlers; /** * 增加活跃处理器计数 */ private incrementActiveHandlers; /** * 减少活跃处理器计数 */ private decrementActiveHandlers; /** * 启动优雅停机流程 */ private initiateShutdown; /** * 完成停机流程 */ private completeShutdown; /** * 清理信号监听器 */ private cleanupSignalHandlers; /** * 引擎销毁钩子:清理资源 */ onDestroy(): Promise<void>; /** * 获取当前活跃处理器数量(用于测试和监控) */ getActiveHandlersCount(): number; /** * 检查是否正在停机(用于测试和监控) */ isShuttingDownNow(): boolean; } /** * 调度模式 */ declare enum ScheduleMode { /** * 固定频率模式:无论任务执行时间多长,都会按照固定间隔执行 * 例如:每 5 秒执行一次,即使上次任务执行了 10 秒 */ FIXED_RATE = "FIXED_RATE", /** * 固定延迟模式:任务执行完成后,等待固定间隔再执行下一次 * 例如:任务执行了 10 秒,间隔 5 秒,则下次执行在 15 秒后 */ FIXED_DELAY = "FIXED_DELAY" } /** * 调度选项 */ interface ScheduleOptions { /** * 执行间隔(毫秒) */ interval: number; /** * 调度模式(默认 FIXED_RATE) */ mode?: ScheduleMode; } /** * 调度元数据 */ interface ScheduleMetadata { /** * 方法名称 */ name: string; /** * 执行间隔(毫秒) */ interval: number; /** * 调度模式 */ mode: ScheduleMode; } /** * SchedulePlugin 配置选项 */ interface SchedulePluginOptions { /** * Etcd3 客户端实例 * 如果未提供且 useMockEtcd 为 false,插件将不会启动调度任务 */ etcdClient?: Etcd3; /** * 是否使用 Mock Etcd(用于测试和本地开发) * 当设置为 true 时,将使用内置的 MockEtcd3,始终选举自己作为 leader * 这样可以在没有真实 etcd 的情况下运行调度任务 * * @default false */ useMockEtcd?: boolean; } /** * Etcd3 类型定义(避免直接依赖 etcd3 包) */ interface Etcd3 { election(key: string, ttl: number): Election; } interface Election { observe(): Promise<Observer>; campaign(candidate: string): Campaign; } interface Observer { on(event: "change", callback: (leader: string) => void): void; } interface Campaign { on(event: "error", callback: (error: any) => void): void; on(event: "elected", callback: () => void): void; resign(): Promise<void>; } /** * Schedule装饰器 * 用于标记需要定时调度的方法 * * @example * ```typescript * @Schedule({ interval: 5000, mode: ScheduleMode.FIXED_RATE }) * async syncData() { * // 定时执行的任务 * } * ``` */ declare function Schedule(options: ScheduleOptions): (target: Function, context: ClassMethodDecoratorContext) => void; /** * SchedulePlugin - 调度任务插件 * 使用 etcd 选举机制实现分布式定时任务,确保多个实例中只有一个执行任务 */ declare class SchedulePlugin implements Plugin { readonly name = "schedule-plugin"; readonly priority = PluginPriority.BUSINESS; private engine; private scheduler; private etcdClient; private scheduleHandlers; private useMockEtcd; constructor(options?: SchedulePluginOptions); /** * 引擎初始化钩子 */ onInit(engine: Microservice): void; /** * Handler加载钩子:收集所有调度任务 */ onHandlerLoad(handlers: HandlerMetadata[]): void; /** * 引擎启动后钩子:启动所有调度任务 */ onAfterStart(engine: Microservice): Promise<void>; /** * 引擎销毁钩子:停止所有调度任务 */ onDestroy(): Promise<void>; } /** * 调度器类 * 负责管理基于 etcd 选举的分布式定时任务 */ declare class Scheduler { private etcdClient; private campaigns; private timers; private isLeader; constructor(etcdClient: Etcd3); /** * 启动调度任务 */ startSchedule(serviceId: string, moduleName: string, methodName: string, electionKey: string, metadata: ScheduleMetadata, method: Function): Promise<void>; /** * 启动定时器 */ private startTimer; /** * 停止定时器 */ private stopTimer; /** * 停止所有调度任务 */ stop(): Promise<void>; } /** * Mock Etcd3 客户端 * 用于测试和本地开发,模拟 etcd 的选举机制 * 始终选举第一个参与选举的候选者作为 leader */ declare class MockEtcd3 implements Etcd3 { private elections; election(key: string, ttl: number): Election; getElection(key: string): MockElection | undefined; clearElections(): void; } /** * Mock Election */ declare class MockElection implements Election { private key; private observers; private campaigns; private currentLeader; constructor(key: string); observe(): Promise<Observer>; campaign(candidate: string): Campaign; setLeader(leader: string): void; getCurrentLeader(): string | null; } /** * ClientCodePlugin 配置选项 */ interface ClientCodePluginOptions { /** * 客户端代码保存路径(可选) * 如果设置,将在生成代码后自动保存到该路径 * 通常用于开发阶段自动生成客户端代码用于调试或测试 * * @example * ```ts * new ClientCodePlugin({ clientSavePath: "./generated/client.ts" }) * ``` */ clientSavePath?: string; } /** * ClientCodePlugin - 客户端代码生成插件 * 收集所有 Action handlers,生成类型化的客户端代码, * 并提供 /client.ts 路由供远程下载 */ declare class ClientCodePlugin implements Plugin { readonly name = "client-code-plugin"; readonly priority = PluginPriority.ROUTE; private engine; private actionHandlers; private generatedCode; private readonly clientSavePath?; constructor(options?: ClientCodePluginOptions); /** * 引擎初始化钩子 */ onInit(engine: Microservice): void; /** * Handler加载钩子:收集所有 Action handlers */ onHandlerLoad(handlers: HandlerMetadata[]): void; /** * 引擎启动后钩子:注册客户端代码下载路由 */ onAfterStart(engine: Microservice): Promise<void>; /** * 生成客户端代码 */ private generateCode; /** * 保存代码到文件 */ private saveCodeToFile; } /** * Action 信息(用于生成客户端代码) */ interface ActionInfo { /** * 动作描述 */ description?: string; /** * 参数校验 Schema(使用 zod) */ params: z.ZodTypeAny[]; /** * 返回值校验 Schema(使用 zod) */ returns?: z.ZodTypeAny; /** * 是否流式返回(默认 false) */ stream?: boolean; /** * 是否幂等(默认 false) */ idempotence?: boolean; /** * 参数名称数组(从方法定义中提取) */ paramNames?: string[]; } /** * 模块信息(用于生成客户端代码) */ interface ModuleInfo { /** * 模块名称 */ name: string; /** * 模块的所有 actions */ actions: Record<string, ActionInfo>; } /** * 获取 Zod 类型的 TypeScript 类型字符串 */ declare function getZodTypeString(schema: z.ZodType<any>, defaultOptional?: boolean): string; /** * 生成客户端代码 * @param modules 模块信息 * @returns 生成的客户端代码 */ declare function generateClientCode(modules: Record<string, ModuleInfo>): Promise<string>; /** * 将 HandlerMetadata 数组转换为 ModuleInfo 格式 * @param handlers Action handlers * @returns 模块信息映射 */ declare function convertHandlersToModuleInfo(handlers: HandlerMetadata[]): Record<string, ModuleInfo>; /** * 从引擎获取模块信息并转换为 ModuleInfo 格式 * @param handlers Action handlers * @param getModuleMetadata 获取模块元数据的函数 * @returns 模块信息映射 */ declare function convertHandlersToModuleInfoWithMetadata(handlers: HandlerMetadata[], getModuleMetadata: (moduleClass: any) => { name: string; } | undefined): Record<string, ModuleInfo>; /** * HtmxAdminPlugin 类型定义 */ /** * 导航项配置 */ interface NavItemConfig { /** 导航标签 */ label: string; /** 导航图标 */ icon?: string; /** 自定义路径 */ href: string; /** 嵌套子路由 */ children?: NavItemConfig[]; } /** * 用户信息接口 */ interface UserInfo { name?: string; avatar?: string; email?: string; [key: string]: any; } /** * 模块类型信息 */ interface ModuleTypeInfo { /** 模块标题 */ title: string; /** 模块描述 */ description: string; /** 模块基础路径 */ basePath: string; /** 是否有 list 类型的模块 */ hasList: boolean; /** 是否有 detail 类型的模块 */ hasDetail: boolean; /** 是否有 form 类型的模块 */ hasForm: boolean; /** 是否有 custom 类型的模块 */ hasCustom: boolean; } /** * 面包屑项 */ interface BreadcrumbItem { label: string; href?: string; } /** * 站点配置选项 */ interface HtmxAdminPluginOptions { /** 站点标题 */ title?: string; /** 站点 Logo URL(可选) */ logo?: string; /** 管理后台路径前缀(默认 /admin) */ prefix?: string; /** 首页路径(访问插件默认路径时重定向到此路径,如果未配置则使用第一个模块的路径) */ homePath?: string; /** 导航配置(集中式声明导航结构,支持嵌套) */ navigation?: NavItemConfig[]; /** 获取用户信息的函数(用于显示用户信息) */ getUserInfo?: (ctx: Context) => UserInfo | null | Promise<UserInfo | null>; } /** * 模块类型 */ type ModuleType = "list" | "detail" | "form" | "custom"; /** * 模块配置选项 * 通用配置放在这里,不同类型页面的差异配置通过类来实现 */ interface HtmxAdminModuleOptions { type: ModuleType; title?: string; description?: string; } /** * 列表数据源接口(仅用于 list 类型) */ interface ListDatasource<T = any> { /** 获取列表数据 */ getList(params: ListParams): Promise<ListResult<T>>; /** 删除数据(可选,如果不提供则列表页不显示删除操作) */ deleteItem?(id: string | number): Promise<boolean>; } /** * 详情数据源接口(仅用于 detail 类型) */ interface DetailDatasource<T = any> { /** 获取单条数据 */ getItem(id: string | number): Promise<T | null>; /** 删除数据(可选) */ deleteItem?(id: string | number): Promise<boolean>; } /** * 表单数据源接口(仅用于 form 类型) */ interface FormDatasource<T = any> { /** 获取单条数据(编辑时使用) */ getItem?(id: string | number): Promise<T | null>; /** 更新数据 */ updateItem?(id: string | number, data: Partial<T>): Promise<T | null>; /** 创建数据 */ createItem?(data: Partial<T>): Promise<T>; } /** * 列表查询参数 */ interface ListParams { /** 页码(从1开始) */ page?: number; /** 每页数量 */ pageSize?: number; /** 排序字段 */ sortBy?: string; /** 排序方向 */ sortOrder?: "asc" | "desc"; /** 筛选条件 */ filters?: Record<string, any>; } /** * 列表查询结果 */ interface ListResult<T> { /** 数据列表 */ items: T[]; /** 总数量 */ total: number; /** 当前页码 */ page: number; /** 每页数量 */ pageSize: number; /** 总页数 */ totalPages: number; } /** * Action Helper - 简化操作按钮定义 */ /** * Action Helper 类 * 提供便捷的方法来定义操作按钮,隐藏路径规则的具体实现 */ declare class PathHelper { private basePath; constructor(basePath: string); /** * 详情页动作 * 生成路径: {basePath}/detail/{id} * @param label 按钮标签 * @param dialog 是否在对话框中打开 */ detail(id: string | number, dialog?: boolean): string; /** * 编辑页动作 * 生成路径: {basePath}/edit/{id} * @param dialog 是否在对话框中打开 */ edit(id: string | number, dialog?: boolean): string; /** * 删除动作 * 生成路径: {basePath}/detail/{id},方法: DELETE */ delete(id: string | number): string; /** * 新建页动作 * 生成路径: {basePath}/new * @param label 按钮标签 * @param dialog 是否在对话框中打开 */ create(dialog?: boolean): string; /** * 列表页动作 * 生成路径: {basePath}/list */ list(): string; base(): string; } /** * HtmxAdmin 上下文对象 * 封装请求处理过程中的状态和操作 */ /** * 通知类型 */ type NotificationType = "error" | "warning" | "info" | "success"; /** * 通知项 */ interface Notification { type: NotificationType; title: string; message: string; } /** * HtmxAdmin 上下文 * 封装请求处理过程中的所有状态和操作 */ declare class HtmxAdminContext { /** 模块元数据 */ readonly moduleMetadata: ModuleTypeInfo; /** 插件选项 */ readonly pluginOptions: Required<HtmxAdminPluginOptions>; /** Hono Context */ readonly ctx: Context; /** 之前的模块名 */ readonly previousModuleName?: string; /** 是否是片段请求(HTMX 请求) */ readonly isFragment: boolean; /** 是否是对话框请求 */ readonly isDialog: boolean; /** 响应目标容器 */ readonly target: string; /** 交换方式 */ readonly swap: string; /** 用户信息 */ readonly userInfo: UserInfo | null; /** 通知队列 */ readonly notifications: Notification[]; /** 页面标题(用于 HX-Title 和页面展示) */ title: string; /** 页面描述(用于SEO和页面展示) */ description: string; /** 面包屑项 */ breadcrumbs: BreadcrumbItem[]; /** 主要内容 */ content: any; /** 需要重定向的 URL */ redirectUrl?: string; /** 是否需要刷新页面(用于 HX-Refresh) */ refresh: boolean; constructor(ctx: Context, userInfo: UserInfo | null, moduleMetadata: ModuleTypeInfo, pluginOptions: Required<HtmxAdminPluginOptions>); /** * 发送通知 * 通知将在响应时通过 OOB 更新到错误容器 */ sendNotification(type: NotificationType, title: string, message: string): void; /** * 发送错误通知(便捷方法) */ sendError(title: string, message: string): void; /** * 发送警告通知(便捷方法) */ sendWarning(title: string, message: string): void; /** * 发送信息通知(便捷方法) */ sendInfo(title: string, message: string): void; /** * 发送成功通知(便捷方法) */ sendSuccess(title: string, message: string): void; /** * 设置需要推送的 URL * 用于 HX-Push-Url 响应头 */ redirect(url: string): void; /** * 设置需要刷新页面 * 用于 HX-Refresh 响应头 */ setRefresh(refresh?: boolean): void; /** * 检查是否有列表页面 * 封装 moduleMetadata 访问,避免直接访问内部属性 */ hasList(): boolean; /** * 检查是否有详情页面 * 封装 moduleMetadata 访问,避免直接访问内部属性 */ hasDetail(): boolean; /** * 检查是否有表单页面 * 封装 moduleMetadata 访问,避免直接访问内部属性 */ hasForm(): boolean; /** * 检查是否有自定义页面 * 封装 moduleMetadata 访问,避免直接访问内部属性 */ hasCustom(): boolean; } /** * Page 模块基类 * 所有页面模块的基类,提供通用的属性和方法 */ /** * Page 页面模块基类 * 所有页面模块都继承此类,包括 ListPageModule、DetailPageModule、FormPageModule * * 对于 custom 类型的模块,必须实现 render 方法 * 对于其他类型的模块,可以重写 render 方法来自定义渲染,否则使用默认渲染逻辑 */ declare abstract class PageModule { /** HtmxAdmin 上下文对象 */ context: HtmxAdminContext; /** Action Helper 实例 */ paths: PathHelper; /** * 初始化模块实例(私有方法,仅由 RouteHandler 调用) * 用于设置模块的基础属性 */ __init(context: HtmxAdminContext): void; /** * 获取页面标题 * 子类可以重写此方法来返回页面标题 * 默认实现:使用模块名 */ getTitle(): string; /** * 获取页面描述 * 子类可以重写此方法来返回页面描述(用于SEO和页面展示) * 默认实现:返回空字符串 */ getDescription(): string; /** * 获取面包屑 * 子类可以重写此方法来自定义面包屑 * 默认实现:首页 => 自定义页面 */ getBreadcrumbs(): BreadcrumbItem[]; /** * 处理请求的统一入口(由 RouteHandler 调用) * 默认实现:直接调用 render 方法 * 子类可以重写此方法来处理请求级别的逻辑(如根据 HTTP method 分发) * * @param adminContext HtmxAdmin 上下文对象(必需),包含请求状态和 helper 方法 * @returns 页面内容 */ __handle(): Promise<any>; /** * 渲染页面内容 * * 所有页面模块都必须提供 render 方法 * - Custom 类型:必须实现此方法 * - List/Detail/Form 类型:基类提供默认实现,可以重写来自定义渲染 * * @param adminContext HtmxAdmin 上下文对象(必需),包含请求状态和 helper 方法 * 可以通过 adminContext.ctx 访问 Hono Context */ abstract render(): any | Promise<any>; } /** * Detail 模块基类 * 用于详情展示,继承自 PageModule */ /** * Detail 页面模块基类 * 继承自 PageModule,提供详情页面的默认行为 * * 可以重写 render 方法来自定义渲染,否则使用默认的详情渲染逻辑 */ declare abstract class DetailPageModule<T = any> extends PageModule { /** ID 字段名(默认 "id") */ protected readonly idField: string; /** * 获取数据源(抽象方法,必须实现) * 子类必须实现此方法来提供数据源 */ abstract getDatasource(): DetailDatasource<T>; /** * 获取字段标签(可选) * 子类可以重写此方法来自定义字段的中文标签 */ getFieldLabel?(field: string): string; /** * 渲染字段值(可选) * 子类可以重写此方法来自定义字段的渲染方式 */ renderField?(field: string, value: any, item: T): any; /** * 获取字段分组(可选) * 子类可以重写此方法来定义字段分组 * 返回 null 或 undefined 表示不分组,平铺显示 */ getFieldGroups?(item: T): Array<{ title: string; fields: string[]; }> | null; /** * 获取可见字段列表(可选) * 子类可以重写此方法来控制字段的显示顺序和可见性 * 返回 null 或 undefined 表示显示所有字段 */ getVisibleFields?(item: T): string[] | null; /** * 获取详情页操作按钮(可选) * 子类可以重写此方法来添加详情页的操作按钮 * 如果不定义,则根据模块元数据智能生成默认操作按钮 */ getDetailActions?(item: T): Array<{ label: string; href: string | ((item: T) => string); method?: string; class?: string; }>; /** * 渲染详情页面(默认实现) * 子类可以重写此方法来自定义渲染 */ render(): Promise<any>; } /** * Form 模块基类 * 用于表单(新建/编辑),继承自 PageModule */ /** * Form 页面模块基类 * 继承自 PageModule,提供表单页面的默认行为 * * 可以重写 render 方法来自定义渲染,否则使用默认的表单渲染逻辑 */ declare abstract class FormPageModule<T = any> extends PageModule { /** ID 字段名(默认 "id") */ protected idField: string; /** Zod Schema(可选,如果提供则自动生成表单字段和校验) */ protected schema?: z.ZodObject<any>; constructor(schema?: z.ZodObject<any>); /** * 获取数据源(抽象方法,必须实现) * 子类必须实现此方法来提供数据源 */ abstract getDatasource(): FormDatasource<T>; /** * 获取单条数据(编辑时使用) */ getItem(id: string | number): Promise<T | null>; /** * 获取字段标签(可选) * 子类可以重写此方法来自定义字段的中文标签 */ getFieldLabel?(field: string): string; /** * 获取表单字段定义 * * 如果提供了 schema,则自动从 schema 生成字段定义 * 否则子类必须实现此方法来定义表单的字段 */ getFormFields(item: T | null): Array<{ name: string; label: string; type?: "text" | "email" | "number" | "textarea" | "select" | "date" | "datetime-local"; required?: boolean; placeholder?: string; options?: Array<{ value: string | number; label: string; }>; }>; /** * 获取字段标签映射(可选) * 用于覆盖从 schema description 提取的标签 */ getFieldLabels?(): Record<string, string>; /** * 获取字段占位符映射(可选) */ getFieldPlaceholders?(): Record<string, string>; /** * 获取字段选项映射(可选) * 用于覆盖从 schema enum 提取的选项 */ getFieldOptions?(): Record<string, Array<{ value: string | number; label: string; }>>; /** * 获取字段类型映射(可选) * 用于覆盖自动推断的类型 */ getFieldTypes?(): Record<string, "text" | "email" | "number" | "textarea" | "select" | "date" | "datetime-local">; /** * 获取要排除的字段列表(可选) */ getExcludeFields?(): string[]; /** * 验证表单数据 * * 如果提供了 schema,则自动使用 schema 进行校验 * 否则子类可以重写此方法来验证表单数据 */ validateFormData(data: Record<string, any>, item: T | null): string | null; /** * 处理请求的统一入口(重写基类方法) * 根据 HTTP method 处理不同请求: * - GET: 渲染表单页面(调用 render) * - POST: 创建数据 * - PUT: 更新数据 * - DELETE: 删除数据 * 子类可以重写此方法来自定义请求处理逻辑 */ __handle(): Promise<any>; /** * 渲染表单页面(默认实现) * 子类可以重写此方法来自定义渲染 * @param formData 表单数据(用于回填验证失败时的值) */ render(formData?: Record<string, any>): Promise<any>; /** * 处理创建请求(POST) */ private handleCreate; /** * 处理更新请求(PUT) */ private handleUpdate; /** * 处理删除请求(DELETE) * 注意:FormDatasource 不包含 deleteItem,删除操作通常由 List 或 Detail 模块处理 * 这里提供默认实现,子类可以重写 */ private handleDelete; /** * 渲染表单页面(辅助方法) * 用于在验证失败时重新渲染表单页面 * @param adminContext 上下文对象 * @param item 原始数据项(编辑时) * @param isEdit 是否是编辑模式 * @param formData 表单数据(用于回填验证失败时的值) */ private renderFormPage; } /** * List 模块基类 * 用于列表展示,继承自 PageModule */ /** * List 页面模块基类 * 继承自 PageModule,提供列表页面的默认行为 * * 可以重写 render 方法来自定义渲染,否则使用默认的列表渲染逻辑 */ declare abstract class ListPageModule<T extends { id: string | number; } = { id: string | number; }> extends PageModule { /** ID 字段名(默认 "id") */ protected readonly idField: string; /** * 获取数据源(抽象方法,必须实现) * 子类必须实现此方法来提供数据源 */ abstract getDatasource(): ListDatasource<T>; /** * 获取列表数据 */ getList(params: ListParams): Promise<ListResult<T>>; /** * 删除数据(可选,如果数据源支持删除) */ deleteItem(id: string | number): Promise<boolean>; /** * 获取字段标签(可选) * 子类可以重写此方法来自定义字段的中文标签 */ getFieldLabel?(field: string): string; /** * 自定义列渲染(可选) * 子类可以重写此方法来自定义列的渲染逻辑 */ renderColumn?(field: string, value: any, item: T): any; /** * 获取统计信息(可选) * 子类可以重写此方法来返回 KPI 统计卡片数据 * 返回的数组将渲染为 StatCard 组件 */ getStats?(params: ListParams): Promise<Array<{ title: string; value: string | number; change?: number; changeLabel?: string; iconColor?: "blue" | "green" | "yellow" | "purple" | "red" | "indigo"; icon?: any; }>> | Array<{ title: string; value: string | number; change?: number; changeLabel?: string; iconColor?: "blue" | "green" | "yellow" | "purple" | "red" | "indigo"; icon?: any; }>; /** * 获取筛选器配置(可选) * 子类可以重写此方法来返回筛选器字段配置 * 返回的配置将渲染为 FilterCard 组件 */ getFilters?(params: ListParams): Array<{ name: string; label: string; options: Array<{ value: string | number; label: string; disabled?: boolean; }>; value?: string | number; defaultValue?: string | number; }>; /** * 获取表格标题(可选) * 子类可以重写此方法来返回表格标题 * 如果不定义,默认使用模块名 */ getTableTitle?(): string; /** * 获取表格操作按钮(可选) * 子类可以重写此方法来返回表格操作按钮配置(如导出、清空、刷新等) * 如果不定义,默认会生成一个刷新按钮 */ getTableActions?(params: ListParams, basePath: string): Array<{ label: string; href?: string; hxGet?: string; hxPost?: string; hxDelete?: string; variant?: "primary" | "secondary" | "danger" | "ghost"; hxConfirm?: string; }>; /** * 自定义操作按钮(可选) * 子类可以重写此方法来添加自定义操作按钮 * 如果不定义,则根据模块元数据智能生成默认操作按钮 */ getActions?(item: T): Array<{ label: string; href: string | ((item: T) => string); method?: string; class?: string; }>; /** * 渲染列表页面(默认实现) * 子类可以重写此方法来自定义渲染 */ render(): Promise<any>; } /** * 数据源接口和基础实现 */ /** * 内存数据源(完整实现,可用于 list、detail、form 类型) */ declare class MemoryListDatasource<T extends { id: string | number; }> implements ListDatasource<T>, DetailDatasource<T>, FormDatasource<T> { private data; constructor(data?: T[]); getList(params?: ListParams): Promise<ListResult<T>>; getItem(id: string | number): Promise<T | null>; deleteItem(id: string | number): Promise<boolean>; updateItem(id: string | number, data: Partial<T>): Promise<T | null>; createItem(data: Partial<T>): Promise<T>; } /** * HtmxAdminPlugin - 管理后台插件 * 使用 HTMX + Tailwind + Hyperscript + JSX 快速构建管理后台 */ /** * HtmxAdminPlugin */ declare class HtmxAdminPlugin implements Plugin<HtmxAdminModuleOptions> { readonly name = "htmx-admin-plugin"; readonly priority = PluginPriority.ROUTE; private engine; private hono; private options; private moduleTypeMap; constructor(options?: HtmxAdminPluginOptions); /** * 声明Module配置Schema */ getModuleOptionsSchema(): PluginModuleOptionsSchema<HtmxAdminModuleOptions>; /** * 引擎初始化钩子 */ onInit(engine: Microservice): void; /** * 检查并注册模块 */ private checkAndRegisterModules; /** * 注册路由 */ private registerRoutes; /** * 模块加载钩子:检查模块类型约束并注册路由 */ onModuleLoad(modules: ModuleMetadata[]): void; } /** * 渲染工具函数 */ /** * 安全渲染值(支持 JSX 和字符串 HTML) * 如果返回的是字符串 HTML,将其转换为 JSX 元素 */ declare function safeRender(value: any): any; /** * 表单组件(用于编辑和新建) */ /** * 字段定义 */ interface FormField$1 { /** 字段名 */ name: string; /** 字段标签 */ label: string; /** 字段类型 */ type?: "text" | "email" | "number" | "textarea" | "select" | "date" | "datetime-local"; /** 是否必填 */ required?: boolean; /** 占位符 */ placeholder?: string; /** 选项(用于 select 类型) */ options?: Array<{ value: string | number; label: string; }>; /** 自定义渲染函数 */ render?: (value: any, item: any) => any; } /** * 表单组件 Props */ interface FormProps<T = any> { /** 数据项(编辑时传入,新建时为 null) */ item: T | null; /** 字段定义列表 */ fields: FormField$1[]; /** 提交 URL */ submitUrl: string; /** 提交方法(默认 PUT) */ method?: "PUT" | "POST"; /** 提交后重定向 URL */ redirectUrl?: string; /** 页面标题(默认 "编辑" 或 "新建") */ title?: string; /** 取消按钮 URL */ cancelUrl?: string; /** 是否在对话框中显示 */ isDialog?: boolean; /** 表单数据(用于回填验证失败时的值) */ formData?: Record<string, any>; } /** * 表单组件 */ declare const Form: <T extends Record<string, any>>(props: FormProps<T>) => hono_jsx_jsx_dev_runtime.JSX.Element; /** * Zod Schema 表单工具 * 从 Zod Schema 自动生成表单字段定义和校验逻辑 */ /** * 从 Zod Object Schema 生成表单字段定义 */ declare function generateFormFieldsFromSchema<T extends z.ZodObject<any>>(schema: T, options?: { /** 字段标签映射(覆盖从 description 提取的标签) */ fieldLabels?: Record<string, string>; /** 字段占位符映射 */ fieldPlaceholders?: Record<string, string>; /** 字段选项映射(覆盖从 enum 提取的选项) */ fieldOptions?: Record<string, Array<{ value: string | number; label: string; }>>; /** 字段类型映射(覆盖自动推断的类型) */ fieldTypes?: Record<string, FormField$1["type"]>; /** 要排除的字段 */ excludeFields?: string[]; }): FormField$1[]; /** * 使用 Zod Schema 验证表单数据 */ declare function validateFormDataWithSchema<T extends z.ZodObject<any>>(schema: T, data: Record<string, any>): { success: true; data: z.infer<T>; } | { success: false; error: string; }; /** * 操作按钮组件 */ interface ActionButtonProps { /** 按钮文本 */ label: string; /** 链接地址 */ href: string | ((item: any) => string); /** HTTP 方法 */ method?: string; /** 自定义类名 */ className?: string; /** 数据项(用于生成动态链接) */ item?: any; } /** * 操作按钮组件 */ declare const ActionButton: (props: ActionButtonProps) => hono_jsx_jsx_dev_runtime.JSX.Element; /** * 最近活动卡片组件 */ interface ActivityItem { /** 活动描述 */ description: string; /** 时间(如"2分钟前") */ time: string; /** 活动类型颜色(blue, green, purple, gray等) */ color?: "blue" | "green" | "purple" | "gray" | "yellow" | "red"; } interface ActivityCardProps { /** 标题 */ title: string; /** 活动列表 */ activities: ActivityItem[]; /** 自定义类名 */ className?: string; } /** * 最近活动卡片组件 * 用于展示最近的活动记录列表 */ declare const ActivityCard: (props: ActivityCardProps) => hono_jsx_jsx_dev_runtime.JSX.Element; /** * 徽章组件(用于标签显示) */ interface BadgeProps { /** 标签文本 */ children: any; /** 颜色主题 */ variant?: "blue" | "green" | "yellow" | "red" | "gray" | "purple" | "indigo"; /** 自定义类名 */ className?: string; } /** * 徽章组件 * 用于显示状态标签,如日志级别、状态等 */ declare const Badge: (props: BadgeProps) => hono_jsx_jsx_dev_runtime.JSX.Element; /** * 按钮组件 */ interface ButtonProps { /** 按钮文本 */ children: any; /** 按钮类型 */ variant?: "primary" | "secondary" | "danger" | "ghost"; /** 按钮大小 */ size?: "sm" | "md" | "lg"; /** 是否禁用 */ disabled?: boolean; /** 自定义类名 */ className?: string; /** HTMX 属性 */ hxGet?: string; hxPost?: string; hxPut?: string; hxDelete?: string; hxTarget?: string; hxSwap?: string; hxPushUrl?: string | boolean; hxIndicator?: string; hxConfirm?: string; hxHeaders?: string; /** 其他属性 */ [key: string]: any; } /** * 按钮组件 */ declare const Button: (props: ButtonProps) => hono_jsx_jsx_dev_runtime.JSX.Element; /** * 卡片组件 */ interface CardProps { /** 卡片内容 */ children: any; /** 卡片标题 */ title?: string; /** 自定义类名 */ className?: string; /** 是否显示阴影 */ shadow?: boolean; /** 是否显示边框 */ bordered?: boolean; /** 是否去掉内边距 */ noPadding?: boolean; } /** * 卡片组件 */ declare