nebula-engine 1.0.0-beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1255 -0
- package/dist/index.d.mts +1984 -0
- package/dist/index.d.ts +1984 -0
- package/dist/index.js +3533 -0
- package/dist/index.mjs +3457 -0
- package/docs/plugin-system.md +733 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1984 @@
|
|
|
1
|
+
import { Hono, MiddlewareHandler, Context } from 'hono';
|
|
2
|
+
export { Context, MiddlewareHandler } from 'hono';
|
|
3
|
+
import * as hono_utils_html from 'hono/utils/html';
|
|
4
|
+
import * as hono_jsx_jsx_dev_runtime from 'hono/jsx/jsx-dev-runtime';
|
|
5
|
+
import { ContentfulStatusCode } from 'hono/utils/http-status';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
export { z } from 'zod';
|
|
8
|
+
import winston from 'winston';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 微服务引擎实现类
|
|
12
|
+
* @internal 此类型仅供内部使用,用户应通过 Factory.create() 创建引擎实例
|
|
13
|
+
*/
|
|
14
|
+
declare class Microservice<ModuleOptions = Record<string, any>> {
|
|
15
|
+
private modules;
|
|
16
|
+
protected plugins: Plugin<Record<string, any>>[];
|
|
17
|
+
protected pluginRegistry: Map<string, Plugin<Record<string, any>>>;
|
|
18
|
+
private moduleInstances;
|
|
19
|
+
readonly options: Readonly<MicroserviceOptions>;
|
|
20
|
+
private started;
|
|
21
|
+
private readonly moduleMetadataKey;
|
|
22
|
+
private actualPort;
|
|
23
|
+
private hono;
|
|
24
|
+
private server;
|
|
25
|
+
constructor(options: MicroserviceOptions, moduleMetadataKey: symbol);
|
|
26
|
+
/**
|
|
27
|
+
* 获取 Hono 实例(供插件使用)
|
|
28
|
+
*/
|
|
29
|
+
getHono(): Hono;
|
|
30
|
+
/**
|
|
31
|
+
* 内部注册插件方法(供构造函数和子类使用)
|
|
32
|
+
* @protected
|
|
33
|
+
*/
|
|
34
|
+
protected registerPlugin<T>(plugin: Plugin<T>): void;
|
|
35
|
+
/**
|
|
36
|
+
* 加载并注册所有模块(通过唯一的 key 查找)
|
|
37
|
+
* 在引擎启动时调用,使用双向访问机制查找所有被装饰的类
|
|
38
|
+
*
|
|
39
|
+
* 注意:
|
|
40
|
+
* - 每个引擎实例使用唯一的 moduleMetadataKey,实现隔离
|
|
41
|
+
* - 模块类是静态的,可以被多个引擎实例共享
|
|
42
|
+
* - 每个引擎实例会创建独立的模块实例,互不影响
|
|
43
|
+
*/
|
|
44
|
+
private loadModules;
|
|
45
|
+
/**
|
|
46
|
+
* 加载Handler元数据(平铺结构)
|
|
47
|
+
* 每个装饰器都是独立的HandlerMetadata条目
|
|
48
|
+
* 为每个方法创建包装链管理器,提供简单的 wrap API
|
|
49
|
+
*/
|
|
50
|
+
private loadHandlerMetadata;
|
|
51
|
+
/**
|
|
52
|
+
* 应用所有包装链到原型
|
|
53
|
+
* 在所有插件执行完 onHandlerLoad 后调用
|
|
54
|
+
*/
|
|
55
|
+
private applyWrapperChains;
|
|
56
|
+
/**
|
|
57
|
+
* 寻找一个随机的可用端口
|
|
58
|
+
*/
|
|
59
|
+
private getRandomPort;
|
|
60
|
+
/**
|
|
61
|
+
* 启动引擎
|
|
62
|
+
* @param requestedPort 启动端口(可选,默认0,表示随机端口)
|
|
63
|
+
* @returns 实际使用的端口号
|
|
64
|
+
*/
|
|
65
|
+
start(requestedPort?: number): Promise<number>;
|
|
66
|
+
/**
|
|
67
|
+
* 确定实际使用的端口
|
|
68
|
+
*/
|
|
69
|
+
private determinePort;
|
|
70
|
+
/**
|
|
71
|
+
* 初始化模块和插件
|
|
72
|
+
*/
|
|
73
|
+
private initializeModulesAndPlugins;
|
|
74
|
+
/**
|
|
75
|
+
* 处理 Handler 元数据和插件包装
|
|
76
|
+
*/
|
|
77
|
+
private processHandlers;
|
|
78
|
+
/**
|
|
79
|
+
* 执行插件启动钩子
|
|
80
|
+
*/
|
|
81
|
+
private executePluginStartHooks;
|
|
82
|
+
/**
|
|
83
|
+
* 注册版本路由(/prefix/version)
|
|
84
|
+
* 用于健康检查和探针
|
|
85
|
+
*/
|
|
86
|
+
private registerVersionRoute;
|
|
87
|
+
/**
|
|
88
|
+
* 启动 HTTP 服务器
|
|
89
|
+
*/
|
|
90
|
+
private startHttpServer;
|
|
91
|
+
/**
|
|
92
|
+
* 按优先级排序插件
|
|
93
|
+
*/
|
|
94
|
+
private sortPluginsByPriority;
|
|
95
|
+
/**
|
|
96
|
+
* 获取插件优先级
|
|
97
|
+
*/
|
|
98
|
+
private getPluginPriority;
|
|
99
|
+
/**
|
|
100
|
+
* 分离包装插件和路由插件
|
|
101
|
+
*/
|
|
102
|
+
private separateWrapperAndRoutePlugins;
|
|
103
|
+
/**
|
|
104
|
+
* 执行插件钩子(通用方法)
|
|
105
|
+
*/
|
|
106
|
+
private executePluginHook;
|
|
107
|
+
/**
|
|
108
|
+
* 停止引擎
|
|
109
|
+
*/
|
|
110
|
+
stop(): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* 获取模块实例(单例)
|
|
113
|
+
* @param moduleClass 模块类
|
|
114
|
+
* @returns 模块实例
|
|
115
|
+
*/
|
|
116
|
+
get<T extends Class>(moduleClass: T): InstanceType<T>;
|
|
117
|
+
/**
|
|
118
|
+
* 获取已注册的模块列表
|
|
119
|
+
*/
|
|
120
|
+
getModules(): ModuleMetadata<Record<string, any>>[];
|
|
121
|
+
/**
|
|
122
|
+
* 获取实际使用的端口
|
|
123
|
+
*/
|
|
124
|
+
getPort(): number | null;
|
|
125
|
+
/**
|
|
126
|
+
* 确保引擎已初始化(模块和处理器已加载)
|
|
127
|
+
* 如果引擎未启动,则执行必要的初始化步骤
|
|
128
|
+
*/
|
|
129
|
+
private ensureInitialized;
|
|
130
|
+
/**
|
|
131
|
+
* 获取模块处理器方法(不启动 HTTP 服务器)
|
|
132
|
+
* 适用于测试场景,可以完整执行中间件和处理逻辑
|
|
133
|
+
*
|
|
134
|
+
* 返回一个已绑定模块和方法名的调用函数,调用时只需要传递方法参数
|
|
135
|
+
* 类型推导:自动推导方法参数类型和返回值类型(无需显式指定泛型参数)
|
|
136
|
+
*
|
|
137
|
+
* @param moduleClass 模块类
|
|
138
|
+
* @param methodName 方法名(handler 名称)
|
|
139
|
+
* @returns 调用函数,只需要传递方法参数
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* @Module("users")
|
|
144
|
+
* class UserService {
|
|
145
|
+
* @Action({ params: [z.string(), z.number()] })
|
|
146
|
+
* add(a: string, b: number): { result: number } {
|
|
147
|
+
* return { result: Number(a) + b };
|
|
148
|
+
* }
|
|
149
|
+
*
|
|
150
|
+
* @Action({ params: [z.string()] })
|
|
151
|
+
* getUser(id: string): Promise<{ id: string; name: string }> {
|
|
152
|
+
* return Promise.resolve({ id, name: "Alice" });
|
|
153
|
+
* }
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* // 获取 handler 并调用(类型自动推导,无需显式指定泛型)
|
|
157
|
+
* const addHandler = engine.handler(UserService, "add");
|
|
158
|
+
* const result1 = await addHandler("10", 20);
|
|
159
|
+
* // result1 的类型是 { result: number }
|
|
160
|
+
*
|
|
161
|
+
* // 也可以链式调用
|
|
162
|
+
* const result2 = await engine.handler(UserService, "getUser")("123");
|
|
163
|
+
* // result2 的类型是 { id: string; name: string }(自动解包 Promise)
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
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>;
|
|
167
|
+
/**
|
|
168
|
+
* 使用 Hono 的 request 方法调用路由处理器(不启动 HTTP 服务器)
|
|
169
|
+
* 适用于测试场景,可以完整执行中间件和处理逻辑
|
|
170
|
+
*
|
|
171
|
+
* @param input Request 对象、URL 字符串或相对路径
|
|
172
|
+
* @param init RequestInit 选项(当 input 是字符串时使用)
|
|
173
|
+
* @returns Response 对象
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* // 使用相对路径
|
|
178
|
+
* const response = await engine.request("/api/users/123");
|
|
179
|
+
*
|
|
180
|
+
* // 使用完整 URL
|
|
181
|
+
* const response = await engine.request("http://localhost/api/users/123");
|
|
182
|
+
*
|
|
183
|
+
* // 使用 Request 对象
|
|
184
|
+
* const request = new Request("http://localhost/api/users/123", {
|
|
185
|
+
* method: "POST",
|
|
186
|
+
* headers: { "Content-Type": "application/json" },
|
|
187
|
+
* body: JSON.stringify({ name: "Alice" }),
|
|
188
|
+
* });
|
|
189
|
+
* const response = await engine.request(request);
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
request(input: RequestInit | URL | string, init?: RequestInit): Promise<Response>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* 核心类型定义
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
type Class = new (...args: any[]) => any;
|
|
200
|
+
/**
|
|
201
|
+
* 插件Module配置Schema(运行时+类型双维度)
|
|
202
|
+
*/
|
|
203
|
+
interface PluginModuleOptionsSchema<T = Record<string, any>> {
|
|
204
|
+
_type: T;
|
|
205
|
+
validate?: (options: T) => boolean | string;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* 插件优先级
|
|
209
|
+
* 数值越小,优先级越高(越先执行)
|
|
210
|
+
* 引擎会自动按优先级排序,用户无需关心注册顺序
|
|
211
|
+
*/
|
|
212
|
+
declare enum PluginPriority {
|
|
213
|
+
/**
|
|
214
|
+
* 系统级优先级:系统核心功能插件(优雅停机等)
|
|
215
|
+
* 最高优先级,应该最先执行
|
|
216
|
+
*/
|
|
217
|
+
SYSTEM = 50,
|
|
218
|
+
/**
|
|
219
|
+
* 最高优先级:安全相关插件(限流、认证等)
|
|
220
|
+
* 应该最先执行,快速拒绝无效请求
|
|
221
|
+
*/
|
|
222
|
+
SECURITY = 100,
|
|
223
|
+
/**
|
|
224
|
+
* 高优先级:日志、监控等插件
|
|
225
|
+
* 记录所有请求,包括被安全插件拒绝的
|
|
226
|
+
*/
|
|
227
|
+
LOGGING = 200,
|
|
228
|
+
/**
|
|
229
|
+
* 中优先级:业务逻辑插件(数据转换等)
|
|
230
|
+
* 在安全和日志之后执行
|
|
231
|
+
*/
|
|
232
|
+
BUSINESS = 300,
|
|
233
|
+
/**
|
|
234
|
+
* 低优先级:性能优化插件(缓存等)
|
|
235
|
+
* 在业务逻辑之后执行,避免重复计算
|
|
236
|
+
*/
|
|
237
|
+
PERFORMANCE = 400,
|
|
238
|
+
/**
|
|
239
|
+
* 最低优先级:路由插件
|
|
240
|
+
* 必须最后执行,注册HTTP路由
|
|
241
|
+
*/
|
|
242
|
+
ROUTE = 1000
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* 核心插件接口
|
|
246
|
+
*/
|
|
247
|
+
interface Plugin<TModuleOptions = Record<string, any>> {
|
|
248
|
+
name: string;
|
|
249
|
+
/**
|
|
250
|
+
* 插件优先级(可选)
|
|
251
|
+
* 如果不指定,默认为 PluginPriority.BUSINESS
|
|
252
|
+
* 引擎会自动按优先级排序,用户无需关心注册顺序
|
|
253
|
+
*
|
|
254
|
+
* 优先级规则:
|
|
255
|
+
* - 数值越小,优先级越高(越先执行)
|
|
256
|
+
* - 相同优先级按注册顺序执行
|
|
257
|
+
*/
|
|
258
|
+
priority?: PluginPriority | number;
|
|
259
|
+
getModuleOptionsSchema?: () => PluginModuleOptionsSchema<TModuleOptions>;
|
|
260
|
+
onInit?: (engine: Microservice) => void;
|
|
261
|
+
onModuleLoad?: (modules: ModuleMetadata[]) => void;
|
|
262
|
+
onHandlerLoad?: (handlers: HandlerMetadata[]) => void;
|
|
263
|
+
onBeforeStart?: (engine: Microservice) => void;
|
|
264
|
+
onAfterStart?: (engine: Microservice) => void | Promise<void>;
|
|
265
|
+
onDestroy?: () => void | Promise<void>;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* 引擎创建选项
|
|
269
|
+
*/
|
|
270
|
+
interface MicroserviceOptions {
|
|
271
|
+
name: string;
|
|
272
|
+
version: string;
|
|
273
|
+
hostname?: string;
|
|
274
|
+
prefix?: string;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Module装饰器类型(由引擎实例创建,自动推导类型)
|
|
278
|
+
* 使用最新的 Stage 3 装饰器标准
|
|
279
|
+
*/
|
|
280
|
+
type ModuleDecorator<TOptions = Record<string, any>> = (name: string, options?: TOptions) => (target: Class, context: ClassDecoratorContext) => void;
|
|
281
|
+
/**
|
|
282
|
+
* 模块元数据
|
|
283
|
+
*/
|
|
284
|
+
interface ModuleMetadata<TOptions = Record<string, any>> {
|
|
285
|
+
name: string;
|
|
286
|
+
clazz: Class;
|
|
287
|
+
options: TOptions;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Handler包装函数类型
|
|
291
|
+
* 插件只需要提供这个函数,引擎自动管理包装链
|
|
292
|
+
*
|
|
293
|
+
* @param next 调用下一个包装层或原始方法
|
|
294
|
+
* @param instance 模块实例
|
|
295
|
+
* @param args 方法参数
|
|
296
|
+
* @returns 方法执行结果
|
|
297
|
+
*/
|
|
298
|
+
type HandlerWrapper = (next: () => Promise<any> | any, instance: any, ...args: any[]) => Promise<any> | any;
|
|
299
|
+
/**
|
|
300
|
+
* Handler元数据(单组元数据)
|
|
301
|
+
* 提供简单的 wrap API,引擎自动管理包装链和执行顺序
|
|
302
|
+
*/
|
|
303
|
+
interface HandlerMetadata {
|
|
304
|
+
type: string;
|
|
305
|
+
options: Record<string, any>;
|
|
306
|
+
method: Function;
|
|
307
|
+
methodName: string;
|
|
308
|
+
module: Class;
|
|
309
|
+
/**
|
|
310
|
+
* 包装当前方法(引擎自动管理包装链)
|
|
311
|
+
*
|
|
312
|
+
* 插件只需要调用这个方法,引擎会自动:
|
|
313
|
+
* - 按插件优先级构建包装链
|
|
314
|
+
* - 确保 RoutePlugin 最后执行
|
|
315
|
+
* - 自动应用包装到原型
|
|
316
|
+
*
|
|
317
|
+
* @param wrapper 包装函数
|
|
318
|
+
* - next: 调用下一个包装层或原始方法
|
|
319
|
+
* - instance: 模块实例
|
|
320
|
+
* - args: 方法参数
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* handler.wrap(async (next, instance, ...args) => {
|
|
325
|
+
* // 前置逻辑
|
|
326
|
+
* const result = await next();
|
|
327
|
+
* // 后置逻辑
|
|
328
|
+
* return result;
|
|
329
|
+
* });
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
wrap(wrapper: HandlerWrapper): void;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Stage 3 装饰器上下文类型
|
|
336
|
+
*/
|
|
337
|
+
type ClassDecoratorContext = {
|
|
338
|
+
kind: "class";
|
|
339
|
+
name: string | undefined;
|
|
340
|
+
addInitializer(initializer: () => void): void;
|
|
341
|
+
};
|
|
342
|
+
type ClassMethodDecoratorContext$1 = {
|
|
343
|
+
kind: "method";
|
|
344
|
+
name: string | symbol;
|
|
345
|
+
static: boolean;
|
|
346
|
+
private: boolean;
|
|
347
|
+
addInitializer(initializer: () => void): void;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* 通用Handler装饰器(支持多应用)
|
|
352
|
+
* 使用最新的 Stage 3 装饰器标准
|
|
353
|
+
*
|
|
354
|
+
* @param config Handler配置
|
|
355
|
+
* @returns 方法装饰器
|
|
356
|
+
*/
|
|
357
|
+
declare function Handler<T = Record<string, any>>(config: {
|
|
358
|
+
type: string;
|
|
359
|
+
options?: T;
|
|
360
|
+
}): (target: Function, context: ClassMethodDecoratorContext) => void;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* 核心异常类型定义
|
|
364
|
+
*/
|
|
365
|
+
declare class PluginNameRequiredError extends Error {
|
|
366
|
+
constructor(pluginName?: string);
|
|
367
|
+
}
|
|
368
|
+
declare class ModuleConfigValidationError extends Error {
|
|
369
|
+
constructor(moduleName: string, pluginName: string, message: string);
|
|
370
|
+
}
|
|
371
|
+
declare class DuplicateModuleError extends Error {
|
|
372
|
+
constructor(moduleName: string);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
interface PreStartChecker {
|
|
376
|
+
name: string;
|
|
377
|
+
check: () => Promise<void> | void;
|
|
378
|
+
skip?: boolean;
|
|
379
|
+
}
|
|
380
|
+
declare function startCheck(checkers: PreStartChecker[], pass?: () => void | Promise<void>): Promise<void>;
|
|
381
|
+
|
|
382
|
+
declare const BaseLayout: (props?: {
|
|
383
|
+
children?: any;
|
|
384
|
+
title?: string;
|
|
385
|
+
heads?: any;
|
|
386
|
+
}) => hono_utils_html.HtmlEscapedString | Promise<hono_utils_html.HtmlEscapedString>;
|
|
387
|
+
declare const HtmxLayout: (props?: {
|
|
388
|
+
children?: any;
|
|
389
|
+
title: string;
|
|
390
|
+
favicon?: any;
|
|
391
|
+
}) => hono_utils_html.HtmlEscapedString | Promise<hono_utils_html.HtmlEscapedString>;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* 服务状态信息接口
|
|
395
|
+
* 基于 MicroserviceOptions,并添加运行时信息
|
|
396
|
+
*/
|
|
397
|
+
interface ServiceStatusInfo {
|
|
398
|
+
name: string;
|
|
399
|
+
version: string;
|
|
400
|
+
prefix?: string;
|
|
401
|
+
hostname?: string;
|
|
402
|
+
port?: number;
|
|
403
|
+
env?: string;
|
|
404
|
+
status?: string;
|
|
405
|
+
}
|
|
406
|
+
declare const ServiceInfoCards: ({ serviceInfo, }: {
|
|
407
|
+
serviceInfo: ServiceStatusInfo;
|
|
408
|
+
}) => hono_jsx_jsx_dev_runtime.JSX.Element;
|
|
409
|
+
declare const ServiceStatusPage: ({ serviceInfo, }: {
|
|
410
|
+
serviceInfo: ServiceStatusInfo;
|
|
411
|
+
}) => hono_jsx_jsx_dev_runtime.JSX.Element;
|
|
412
|
+
|
|
413
|
+
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
|
|
414
|
+
/**
|
|
415
|
+
* Route装饰器配置选项
|
|
416
|
+
*/
|
|
417
|
+
interface RouteOptions {
|
|
418
|
+
/**
|
|
419
|
+
* HTTP方法(可选,默认为 GET)
|
|
420
|
+
* 如果未指定,则默认为 GET 方法
|
|
421
|
+
*/
|
|
422
|
+
method?: HTTPMethod | HTTPMethod[];
|
|
423
|
+
/**
|
|
424
|
+
* 路由路径(支持单个路径或多个路径)
|
|
425
|
+
* 如果提供数组,将为每个路径注册相同的处理器
|
|
426
|
+
*/
|
|
427
|
+
path: string | string[];
|
|
428
|
+
/**
|
|
429
|
+
* 路由专属中间件
|
|
430
|
+
*/
|
|
431
|
+
middlewares?: MiddlewareHandler[];
|
|
432
|
+
/**
|
|
433
|
+
* 路由描述(用于文档和日志)
|
|
434
|
+
*/
|
|
435
|
+
description?: string;
|
|
436
|
+
/**
|
|
437
|
+
* 请求参数校验规则
|
|
438
|
+
*/
|
|
439
|
+
validate?: {
|
|
440
|
+
query?: Record<string, any>;
|
|
441
|
+
body?: Record<string, any>;
|
|
442
|
+
params?: Record<string, any>;
|
|
443
|
+
};
|
|
444
|
+
/**
|
|
445
|
+
* 响应配置
|
|
446
|
+
*/
|
|
447
|
+
response?: {
|
|
448
|
+
status?: ContentfulStatusCode;
|
|
449
|
+
type?: "json" | "text" | "html";
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* RoutePlugin的Module配置
|
|
454
|
+
* 注意:配置直接平铺在 Module options 中,不使用 route 命名空间
|
|
455
|
+
* 插件作者需要确保字段名不与其他插件冲突
|
|
456
|
+
*/
|
|
457
|
+
interface RouteModuleOptions {
|
|
458
|
+
routePrefix?: string;
|
|
459
|
+
routeMiddlewares?: MiddlewareHandler[];
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* 错误转换函数
|
|
463
|
+
* 当路由处理器抛出异常时,可以自定义错误响应格式
|
|
464
|
+
* @param ctx Hono Context 对象
|
|
465
|
+
* @param error 捕获到的错误对象
|
|
466
|
+
* @param handler Handler 元数据,包含路由信息、方法名等
|
|
467
|
+
* @returns Response 对象或可序列化的值(会被自动转换为 Response)
|
|
468
|
+
*/
|
|
469
|
+
type ErrorTransformer = (ctx: Context, error: unknown, handler: HandlerMetadata) => Response | Promise<Response>;
|
|
470
|
+
/**
|
|
471
|
+
* RoutePlugin 配置选项
|
|
472
|
+
*/
|
|
473
|
+
interface RoutePluginOptions {
|
|
474
|
+
/**
|
|
475
|
+
* 全局路径前缀(应用于所有路由)
|
|
476
|
+
* 路径拼接顺序:全局前缀 + 模块前缀 + 路由路径
|
|
477
|
+
* 例如:prefix="/api", routePrefix="/v1", path="/users" => "/api/v1/users"
|
|
478
|
+
*/
|
|
479
|
+
prefix?: string;
|
|
480
|
+
/**
|
|
481
|
+
* 全局中间件(应用于所有路由)
|
|
482
|
+
* 执行顺序:全局中间件 -> 模块级中间件 -> 路由级中间件
|
|
483
|
+
* 常用于鉴权、日志等全局功能
|
|
484
|
+
*/
|
|
485
|
+
globalMiddlewares?: MiddlewareHandler[];
|
|
486
|
+
/**
|
|
487
|
+
* 错误转换函数(可选)
|
|
488
|
+
* 当路由处理器抛出异常时,可以自定义错误响应格式
|
|
489
|
+
* 如果不提供,将使用默认的错误响应格式
|
|
490
|
+
*/
|
|
491
|
+
errorTransformer?: ErrorTransformer;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Route装饰器(Handler的语法糖封装)
|
|
496
|
+
* 固定type="route",简化HTTP路由标注
|
|
497
|
+
* 使用最新的 Stage 3 装饰器标准
|
|
498
|
+
*
|
|
499
|
+
* @example
|
|
500
|
+
* ```typescript
|
|
501
|
+
* @Route({ method: "GET", path: "/users" })
|
|
502
|
+
* async getUsers(ctx: Context) {
|
|
503
|
+
* return ctx.json({ users: [] });
|
|
504
|
+
* }
|
|
505
|
+
*
|
|
506
|
+
* // 支持多个路径
|
|
507
|
+
* @Route({ path: ["/", "/home", "/dashboard"] })
|
|
508
|
+
* async homePage(ctx: Context) {
|
|
509
|
+
* return <HomePage />;
|
|
510
|
+
* }
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
declare function Route(options: RouteOptions): (target: Function, context: ClassMethodDecoratorContext) => void;
|
|
514
|
+
/**
|
|
515
|
+
* Page装饰器(Route的别名,用于向后兼容)
|
|
516
|
+
* 专门用于页面路由,默认使用 GET 方法
|
|
517
|
+
*
|
|
518
|
+
* @example
|
|
519
|
+
* ```typescript
|
|
520
|
+
* @Page({ path: ["/", "/home"] })
|
|
521
|
+
* async adminPage(ctx: Context) {
|
|
522
|
+
* return HtmxLayout({ title: "Admin", children: <AdminLayout /> });
|
|
523
|
+
* }
|
|
524
|
+
* ```
|
|
525
|
+
*/
|
|
526
|
+
declare function Page(options: RouteOptions): (target: Function, context: ClassMethodDecoratorContext) => void;
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* RoutePlugin - 核心路由插件
|
|
530
|
+
* 负责解析type="route"的Handler元数据,注册HTTP路由到Hono实例
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```typescript
|
|
534
|
+
* // 使用全局前缀和中间件
|
|
535
|
+
* const authMiddleware = async (ctx, next) => {
|
|
536
|
+
* // 验证 token
|
|
537
|
+
* await next();
|
|
538
|
+
* };
|
|
539
|
+
*
|
|
540
|
+
* const routePlugin = new RoutePlugin({
|
|
541
|
+
* prefix: "/api", // 全局路径前缀,所有路由都会加上这个前缀
|
|
542
|
+
* globalMiddlewares: [authMiddleware],
|
|
543
|
+
* });
|
|
544
|
+
* ```
|
|
545
|
+
*/
|
|
546
|
+
declare class RoutePlugin implements Plugin<RouteModuleOptions> {
|
|
547
|
+
readonly name = "route-plugin";
|
|
548
|
+
readonly priority = PluginPriority.ROUTE;
|
|
549
|
+
private engine;
|
|
550
|
+
private globalPrefix;
|
|
551
|
+
private globalMiddlewares;
|
|
552
|
+
private errorTransformer?;
|
|
553
|
+
/**
|
|
554
|
+
* 构造函数
|
|
555
|
+
* @param options 插件配置选项
|
|
556
|
+
*/
|
|
557
|
+
constructor(options?: RoutePluginOptions);
|
|
558
|
+
/**
|
|
559
|
+
* 声明Module配置Schema(用于类型推导+运行时校验)
|
|
560
|
+
*/
|
|
561
|
+
getModuleOptionsSchema(): PluginModuleOptionsSchema<RouteModuleOptions>;
|
|
562
|
+
/**
|
|
563
|
+
* 引擎初始化钩子:获取Hono实例
|
|
564
|
+
*/
|
|
565
|
+
onInit(engine: Microservice): void;
|
|
566
|
+
/**
|
|
567
|
+
* Handler加载钩子:解析type="route"的Handler元数据,注册HTTP路由
|
|
568
|
+
*/
|
|
569
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Action装饰器配置选项
|
|
574
|
+
*/
|
|
575
|
+
interface ActionOptions {
|
|
576
|
+
/**
|
|
577
|
+
* 动作描述
|
|
578
|
+
*/
|
|
579
|
+
description?: string;
|
|
580
|
+
/**
|
|
581
|
+
* 参数校验 Schema(使用 zod)
|
|
582
|
+
* 数组顺序对应方法参数的顺序
|
|
583
|
+
*/
|
|
584
|
+
params: z.ZodTypeAny[];
|
|
585
|
+
/**
|
|
586
|
+
* 返回值校验 Schema(使用 zod)
|
|
587
|
+
*/
|
|
588
|
+
returns?: z.ZodTypeAny;
|
|
589
|
+
/**
|
|
590
|
+
* 是否流式返回(默认 false)
|
|
591
|
+
*/
|
|
592
|
+
stream?: boolean;
|
|
593
|
+
/**
|
|
594
|
+
* 是否幂等(默认 false)
|
|
595
|
+
*/
|
|
596
|
+
idempotence?: boolean;
|
|
597
|
+
/**
|
|
598
|
+
* 路由专属中间件
|
|
599
|
+
*/
|
|
600
|
+
middlewares?: MiddlewareHandler[];
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* ActionPlugin的Module配置
|
|
604
|
+
*/
|
|
605
|
+
interface ActionModuleOptions {
|
|
606
|
+
/**
|
|
607
|
+
* 模块级路由中间件
|
|
608
|
+
*/
|
|
609
|
+
actionMiddlewares?: MiddlewareHandler[];
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* ActionPlugin - 动作处理插件
|
|
614
|
+
* 提供基于下标的参数传递、zod 校验和自动参数注入
|
|
615
|
+
*/
|
|
616
|
+
declare class ActionPlugin implements Plugin<ActionModuleOptions> {
|
|
617
|
+
readonly name = "action-plugin";
|
|
618
|
+
readonly priority = PluginPriority.ROUTE;
|
|
619
|
+
private engine;
|
|
620
|
+
/**
|
|
621
|
+
* 声明Module配置Schema(用于类型推导+运行时校验)
|
|
622
|
+
*/
|
|
623
|
+
getModuleOptionsSchema(): PluginModuleOptionsSchema<ActionModuleOptions>;
|
|
624
|
+
/**
|
|
625
|
+
* 引擎初始化钩子:获取Hono实例
|
|
626
|
+
*/
|
|
627
|
+
onInit(engine: Microservice): void;
|
|
628
|
+
/**
|
|
629
|
+
* Handler加载钩子:解析type="action"的Handler元数据,注册HTTP路由
|
|
630
|
+
*/
|
|
631
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Action装饰器(Handler的语法糖封装)
|
|
636
|
+
* 固定type="action",用于标注动作处理方法
|
|
637
|
+
*/
|
|
638
|
+
declare function Action(options: ActionOptions): (target: Function, context: ClassMethodDecoratorContext) => void;
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Cache装饰器配置选项
|
|
642
|
+
*/
|
|
643
|
+
interface CacheOptions {
|
|
644
|
+
/**
|
|
645
|
+
* 缓存失效时间(毫秒)
|
|
646
|
+
* 默认:60000 (1分钟)
|
|
647
|
+
*/
|
|
648
|
+
ttl?: number;
|
|
649
|
+
/**
|
|
650
|
+
* 缓存键生成函数
|
|
651
|
+
* 函数签名应该和处理器方法一样,接收相同的参数
|
|
652
|
+
* 可以返回任意值,返回值会被 ejson 序列化后进行 hash 生成缓存键
|
|
653
|
+
* 如果不提供,将使用入参(args)进行相同的计算
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```typescript
|
|
657
|
+
* @Cache({
|
|
658
|
+
* key: (id: string, name: string) => ({ id, name }), // 返回对象
|
|
659
|
+
* ttl: 5000
|
|
660
|
+
* })
|
|
661
|
+
* async getUser(id: string, name: string) {
|
|
662
|
+
* return { id, name };
|
|
663
|
+
* }
|
|
664
|
+
* ```
|
|
665
|
+
*/
|
|
666
|
+
key?: (...args: any[]) => any;
|
|
667
|
+
/**
|
|
668
|
+
* 是否启用缓存
|
|
669
|
+
* 默认:true
|
|
670
|
+
*/
|
|
671
|
+
enabled?: boolean;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* CachePlugin的Module配置
|
|
675
|
+
* 注意:配置直接平铺在 Module options 中
|
|
676
|
+
*/
|
|
677
|
+
interface CacheModuleOptions {
|
|
678
|
+
/**
|
|
679
|
+
* 默认缓存失效时间(毫秒)
|
|
680
|
+
* 默认:60000 (1分钟)
|
|
681
|
+
*/
|
|
682
|
+
cacheDefaultTtl?: number;
|
|
683
|
+
/**
|
|
684
|
+
* 是否启用全局缓存
|
|
685
|
+
* 默认:true
|
|
686
|
+
*/
|
|
687
|
+
cacheEnabled?: boolean;
|
|
688
|
+
/**
|
|
689
|
+
* 缓存清理间隔(毫秒)
|
|
690
|
+
* 默认:60000 (1分钟)
|
|
691
|
+
*/
|
|
692
|
+
cacheCleanupInterval?: number;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* 缓存项数据结构
|
|
696
|
+
*/
|
|
697
|
+
interface CacheItem<T = any> {
|
|
698
|
+
value: T;
|
|
699
|
+
expiresAt: number;
|
|
700
|
+
createdAt: number;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Cache Adapter 接口
|
|
705
|
+
* 定义缓存存储的抽象接口,支持不同的存储后端
|
|
706
|
+
*/
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* 缓存适配器接口
|
|
710
|
+
*/
|
|
711
|
+
interface CacheAdapter {
|
|
712
|
+
/**
|
|
713
|
+
* 获取缓存项
|
|
714
|
+
* @param key 缓存键
|
|
715
|
+
* @returns 缓存项,如果不存在或已过期则返回 null
|
|
716
|
+
*/
|
|
717
|
+
get<T = any>(key: string): Promise<CacheItem<T> | null>;
|
|
718
|
+
/**
|
|
719
|
+
* 设置缓存项
|
|
720
|
+
* @param key 缓存键
|
|
721
|
+
* @param item 缓存项
|
|
722
|
+
*/
|
|
723
|
+
set<T = any>(key: string, item: CacheItem<T>): Promise<void>;
|
|
724
|
+
/**
|
|
725
|
+
* 删除缓存项
|
|
726
|
+
* @param key 缓存键
|
|
727
|
+
* @returns 是否删除成功
|
|
728
|
+
*/
|
|
729
|
+
delete(key: string): Promise<boolean>;
|
|
730
|
+
/**
|
|
731
|
+
* 清空所有缓存
|
|
732
|
+
*/
|
|
733
|
+
clear(): Promise<void>;
|
|
734
|
+
/**
|
|
735
|
+
* 获取所有缓存键(用于统计)
|
|
736
|
+
* @returns 缓存键数组(不包含过期项)
|
|
737
|
+
*/
|
|
738
|
+
keys(): Promise<string[]>;
|
|
739
|
+
/**
|
|
740
|
+
* 清理所有过期项(高效批量清理)
|
|
741
|
+
* @returns 清理的过期项数量
|
|
742
|
+
*/
|
|
743
|
+
cleanupExpired?(): Promise<number>;
|
|
744
|
+
/**
|
|
745
|
+
* 获取缓存统计信息
|
|
746
|
+
*/
|
|
747
|
+
getStats(): Promise<{
|
|
748
|
+
size: number;
|
|
749
|
+
entries: Array<{
|
|
750
|
+
key: string;
|
|
751
|
+
expiresAt: number;
|
|
752
|
+
createdAt: number;
|
|
753
|
+
}>;
|
|
754
|
+
}>;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* 内存缓存适配器
|
|
758
|
+
* 使用 Map 存储,适合单进程应用
|
|
759
|
+
*
|
|
760
|
+
* 注意:过期项会在以下情况被自动清理:
|
|
761
|
+
* 1. get() 时检查并删除过期项
|
|
762
|
+
* 2. keys() 和 getStats() 会过滤过期项
|
|
763
|
+
* 3. 建议通过 CachePlugin 的定期清理机制主动清理过期项
|
|
764
|
+
*/
|
|
765
|
+
declare class MemoryCacheAdapter implements CacheAdapter {
|
|
766
|
+
private cache;
|
|
767
|
+
get<T = any>(key: string): Promise<CacheItem<T> | null>;
|
|
768
|
+
set<T = any>(key: string, item: CacheItem<T>): Promise<void>;
|
|
769
|
+
delete(key: string): Promise<boolean>;
|
|
770
|
+
clear(): Promise<void>;
|
|
771
|
+
keys(): Promise<string[]>;
|
|
772
|
+
/**
|
|
773
|
+
* 清理所有过期项(高效批量清理)
|
|
774
|
+
* 这个方法比通过 keys() + get() + delete() 更高效
|
|
775
|
+
*/
|
|
776
|
+
cleanupExpired(): Promise<number>;
|
|
777
|
+
getStats(): Promise<{
|
|
778
|
+
size: number;
|
|
779
|
+
entries: Array<{
|
|
780
|
+
key: string;
|
|
781
|
+
expiresAt: number;
|
|
782
|
+
createdAt: number;
|
|
783
|
+
}>;
|
|
784
|
+
}>;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Redis 缓存适配器配置
|
|
788
|
+
*/
|
|
789
|
+
interface RedisCacheAdapterOptions {
|
|
790
|
+
/**
|
|
791
|
+
* Redis 客户端实例(需要实现基本的 get/set/del/keys 方法)
|
|
792
|
+
* 可以是 ioredis、node-redis 等
|
|
793
|
+
*/
|
|
794
|
+
client: {
|
|
795
|
+
get(key: string): Promise<string | null>;
|
|
796
|
+
set(key: string, value: string, expiryMode?: string, time?: number): Promise<string | null>;
|
|
797
|
+
del(key: string): Promise<number>;
|
|
798
|
+
keys(pattern: string): Promise<string[]>;
|
|
799
|
+
};
|
|
800
|
+
/**
|
|
801
|
+
* 键前缀,用于区分不同应用的缓存
|
|
802
|
+
* 默认:'cache:'
|
|
803
|
+
*/
|
|
804
|
+
keyPrefix?: string;
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Redis 缓存适配器
|
|
808
|
+
* 使用 Redis 作为存储后端,适合分布式应用
|
|
809
|
+
*
|
|
810
|
+
* 注意:Redis 本身支持 TTL(Time To Live),过期键会自动删除,
|
|
811
|
+
* 因此不需要手动清理过期项。当使用 SET key value EX seconds 时,
|
|
812
|
+
* Redis 会在过期后自动删除键。
|
|
813
|
+
*/
|
|
814
|
+
declare class RedisCacheAdapter implements CacheAdapter {
|
|
815
|
+
private client;
|
|
816
|
+
private keyPrefix;
|
|
817
|
+
constructor(options: RedisCacheAdapterOptions);
|
|
818
|
+
private getKey;
|
|
819
|
+
get<T = any>(key: string): Promise<CacheItem<T> | null>;
|
|
820
|
+
set<T = any>(key: string, item: CacheItem<T>): Promise<void>;
|
|
821
|
+
delete(key: string): Promise<boolean>;
|
|
822
|
+
clear(): Promise<void>;
|
|
823
|
+
keys(): Promise<string[]>;
|
|
824
|
+
/**
|
|
825
|
+
* 清理所有过期项
|
|
826
|
+
*
|
|
827
|
+
* 注意:Redis 本身支持自动过期(通过 SET key value EX seconds),
|
|
828
|
+
* 过期键会被 Redis 自动删除。但在某些情况下(如测试环境、某些 Redis 客户端),
|
|
829
|
+
* 可能需要手动清理。此方法会检查并清理:
|
|
830
|
+
* 1. 已过期但尚未被 Redis 删除的键(双重保险)
|
|
831
|
+
* 2. JSON 解析失败的数据
|
|
832
|
+
*/
|
|
833
|
+
cleanupExpired(): Promise<number>;
|
|
834
|
+
getStats(): Promise<{
|
|
835
|
+
size: number;
|
|
836
|
+
entries: Array<{
|
|
837
|
+
key: string;
|
|
838
|
+
expiresAt: number;
|
|
839
|
+
createdAt: number;
|
|
840
|
+
}>;
|
|
841
|
+
}>;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* CachePlugin - 缓存插件
|
|
846
|
+
* 负责为标记了 @Cache 装饰器的方法提供缓存功能
|
|
847
|
+
*
|
|
848
|
+
* @example
|
|
849
|
+
* ```ts
|
|
850
|
+
* // 使用内存缓存(默认)
|
|
851
|
+
* const cachePlugin = new CachePlugin();
|
|
852
|
+
*
|
|
853
|
+
* // 使用自定义适配器
|
|
854
|
+
* const cachePlugin = new CachePlugin(new MemoryCacheAdapter());
|
|
855
|
+
*
|
|
856
|
+
* // 使用 Redis 适配器
|
|
857
|
+
* import { RedisCacheAdapter } from "./adapter";
|
|
858
|
+
* const cachePlugin = new CachePlugin(new RedisCacheAdapter({ client: redisClient }));
|
|
859
|
+
* ```
|
|
860
|
+
*/
|
|
861
|
+
declare class CachePlugin implements Plugin<CacheModuleOptions> {
|
|
862
|
+
readonly name = "cache-plugin";
|
|
863
|
+
readonly priority = PluginPriority.PERFORMANCE;
|
|
864
|
+
private adapter;
|
|
865
|
+
private cleanupTimer;
|
|
866
|
+
private engine;
|
|
867
|
+
private defaultTtl;
|
|
868
|
+
private cacheEnabled;
|
|
869
|
+
private cleanupInterval;
|
|
870
|
+
/**
|
|
871
|
+
* 构造函数
|
|
872
|
+
* @param adapter 缓存适配器,如果不提供则使用默认的内存缓存适配器
|
|
873
|
+
*/
|
|
874
|
+
constructor(adapter?: CacheAdapter);
|
|
875
|
+
/**
|
|
876
|
+
* 声明Module配置Schema
|
|
877
|
+
*/
|
|
878
|
+
getModuleOptionsSchema(): PluginModuleOptionsSchema<CacheModuleOptions>;
|
|
879
|
+
/**
|
|
880
|
+
* 引擎初始化前钩子
|
|
881
|
+
*/
|
|
882
|
+
onInit(engine: Microservice): void;
|
|
883
|
+
/**
|
|
884
|
+
* Handler加载后钩子
|
|
885
|
+
* 拦截带有 type="cache" 的 Handler,包装原始方法实现缓存逻辑
|
|
886
|
+
*/
|
|
887
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
888
|
+
/**
|
|
889
|
+
* 引擎启动前钩子
|
|
890
|
+
*/
|
|
891
|
+
onBeforeStart(engine: Microservice): void;
|
|
892
|
+
/**
|
|
893
|
+
* 引擎停止时钩子
|
|
894
|
+
*/
|
|
895
|
+
onDestroy(): Promise<void>;
|
|
896
|
+
/**
|
|
897
|
+
* 生成缓存键
|
|
898
|
+
* @param moduleName 模块名
|
|
899
|
+
* @param methodName 方法名
|
|
900
|
+
* @param keyFunction 可选的 key 函数
|
|
901
|
+
* @param args 方法参数
|
|
902
|
+
* @returns 缓存键(格式:模块名:方法名:hash)
|
|
903
|
+
*/
|
|
904
|
+
private generateCacheKey;
|
|
905
|
+
/**
|
|
906
|
+
* 清理过期缓存
|
|
907
|
+
*/
|
|
908
|
+
private cleanup;
|
|
909
|
+
/**
|
|
910
|
+
* 获取缓存统计信息
|
|
911
|
+
*/
|
|
912
|
+
getStats(): Promise<{
|
|
913
|
+
size: number;
|
|
914
|
+
entries: Array<{
|
|
915
|
+
key: string;
|
|
916
|
+
expiresAt: number;
|
|
917
|
+
createdAt: number;
|
|
918
|
+
}>;
|
|
919
|
+
}>;
|
|
920
|
+
/**
|
|
921
|
+
* 清空所有缓存
|
|
922
|
+
*/
|
|
923
|
+
clear(): Promise<void>;
|
|
924
|
+
/**
|
|
925
|
+
* 删除指定的缓存项
|
|
926
|
+
*/
|
|
927
|
+
delete(key: string): Promise<boolean>;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Cache装饰器
|
|
932
|
+
* 用于标记需要缓存的方法
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
* ```typescript
|
|
936
|
+
* @Cache({ ttl: 5000 })
|
|
937
|
+
* async getUser(id: number) {
|
|
938
|
+
* return { id, name: "John" };
|
|
939
|
+
* }
|
|
940
|
+
* ```
|
|
941
|
+
*/
|
|
942
|
+
declare function Cache(options?: CacheOptions): (target: Function, context: ClassMethodDecoratorContext) => void;
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* 优雅停机插件配置选项
|
|
946
|
+
*/
|
|
947
|
+
interface GracefulShutdownPluginOptions {
|
|
948
|
+
/**
|
|
949
|
+
* 停机超时时间(毫秒)
|
|
950
|
+
* 默认:10分钟(600000ms)
|
|
951
|
+
*/
|
|
952
|
+
shutdownTimeout?: number;
|
|
953
|
+
/**
|
|
954
|
+
* 是否启用优雅停机
|
|
955
|
+
* 默认:true
|
|
956
|
+
*/
|
|
957
|
+
enabled?: boolean;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* 优雅停机插件
|
|
962
|
+
*
|
|
963
|
+
* 功能:
|
|
964
|
+
* 1. 追踪所有处理器的执行状态(包括 Action、Route、Schedule 等)
|
|
965
|
+
* 2. 监听系统停机信号(SIGINT、SIGTERM 等)
|
|
966
|
+
* 3. 收到信号后,等待所有正在执行的处理器完成
|
|
967
|
+
* 4. 如果超时或所有处理完成,执行优雅停机
|
|
968
|
+
*
|
|
969
|
+
* @example
|
|
970
|
+
* ```typescript
|
|
971
|
+
* // 使用默认配置(10分钟超时)
|
|
972
|
+
* const gracefulShutdownPlugin = new GracefulShutdownPlugin();
|
|
973
|
+
*
|
|
974
|
+
* // 自定义超时时间(5分钟)
|
|
975
|
+
* const gracefulShutdownPlugin = new GracefulShutdownPlugin({
|
|
976
|
+
* shutdownTimeout: 5 * 60 * 1000, // 5分钟
|
|
977
|
+
* });
|
|
978
|
+
* ```
|
|
979
|
+
*/
|
|
980
|
+
declare class GracefulShutdownPlugin implements Plugin {
|
|
981
|
+
readonly name = "graceful-shutdown-plugin";
|
|
982
|
+
readonly priority = PluginPriority.SYSTEM;
|
|
983
|
+
private engine;
|
|
984
|
+
private options;
|
|
985
|
+
private activeHandlers;
|
|
986
|
+
private isShuttingDown;
|
|
987
|
+
private shutdownTimer;
|
|
988
|
+
private signalListeners;
|
|
989
|
+
constructor(options?: GracefulShutdownPluginOptions);
|
|
990
|
+
/**
|
|
991
|
+
* 引擎初始化钩子
|
|
992
|
+
*/
|
|
993
|
+
onInit(engine: Microservice): void;
|
|
994
|
+
/**
|
|
995
|
+
* Handler加载钩子:拦截所有处理器,追踪执行状态
|
|
996
|
+
*/
|
|
997
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
998
|
+
/**
|
|
999
|
+
* 引擎启动后钩子:注册系统信号监听器
|
|
1000
|
+
*/
|
|
1001
|
+
onAfterStart(engine: Microservice): Promise<void>;
|
|
1002
|
+
/**
|
|
1003
|
+
* 注册系统信号监听器
|
|
1004
|
+
*/
|
|
1005
|
+
private registerSignalHandlers;
|
|
1006
|
+
/**
|
|
1007
|
+
* 增加活跃处理器计数
|
|
1008
|
+
*/
|
|
1009
|
+
private incrementActiveHandlers;
|
|
1010
|
+
/**
|
|
1011
|
+
* 减少活跃处理器计数
|
|
1012
|
+
*/
|
|
1013
|
+
private decrementActiveHandlers;
|
|
1014
|
+
/**
|
|
1015
|
+
* 启动优雅停机流程
|
|
1016
|
+
*/
|
|
1017
|
+
private initiateShutdown;
|
|
1018
|
+
/**
|
|
1019
|
+
* 完成停机流程
|
|
1020
|
+
*/
|
|
1021
|
+
private completeShutdown;
|
|
1022
|
+
/**
|
|
1023
|
+
* 清理信号监听器
|
|
1024
|
+
*/
|
|
1025
|
+
private cleanupSignalHandlers;
|
|
1026
|
+
/**
|
|
1027
|
+
* 引擎销毁钩子:清理资源
|
|
1028
|
+
*/
|
|
1029
|
+
onDestroy(): Promise<void>;
|
|
1030
|
+
/**
|
|
1031
|
+
* 获取当前活跃处理器数量(用于测试和监控)
|
|
1032
|
+
*/
|
|
1033
|
+
getActiveHandlersCount(): number;
|
|
1034
|
+
/**
|
|
1035
|
+
* 检查是否正在停机(用于测试和监控)
|
|
1036
|
+
*/
|
|
1037
|
+
isShuttingDownNow(): boolean;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* 调度模式
|
|
1042
|
+
*/
|
|
1043
|
+
declare enum ScheduleMode {
|
|
1044
|
+
/**
|
|
1045
|
+
* 固定频率模式:无论任务执行时间多长,都会按照固定间隔执行
|
|
1046
|
+
* 例如:每 5 秒执行一次,即使上次任务执行了 10 秒
|
|
1047
|
+
*/
|
|
1048
|
+
FIXED_RATE = "FIXED_RATE",
|
|
1049
|
+
/**
|
|
1050
|
+
* 固定延迟模式:任务执行完成后,等待固定间隔再执行下一次
|
|
1051
|
+
* 例如:任务执行了 10 秒,间隔 5 秒,则下次执行在 15 秒后
|
|
1052
|
+
*/
|
|
1053
|
+
FIXED_DELAY = "FIXED_DELAY"
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* 调度选项
|
|
1057
|
+
*/
|
|
1058
|
+
interface ScheduleOptions {
|
|
1059
|
+
/**
|
|
1060
|
+
* 执行间隔(毫秒)
|
|
1061
|
+
*/
|
|
1062
|
+
interval: number;
|
|
1063
|
+
/**
|
|
1064
|
+
* 调度模式(默认 FIXED_RATE)
|
|
1065
|
+
*/
|
|
1066
|
+
mode?: ScheduleMode;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* 调度元数据
|
|
1070
|
+
*/
|
|
1071
|
+
interface ScheduleMetadata {
|
|
1072
|
+
/**
|
|
1073
|
+
* 方法名称
|
|
1074
|
+
*/
|
|
1075
|
+
name: string;
|
|
1076
|
+
/**
|
|
1077
|
+
* 执行间隔(毫秒)
|
|
1078
|
+
*/
|
|
1079
|
+
interval: number;
|
|
1080
|
+
/**
|
|
1081
|
+
* 调度模式
|
|
1082
|
+
*/
|
|
1083
|
+
mode: ScheduleMode;
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* SchedulePlugin 配置选项
|
|
1087
|
+
*/
|
|
1088
|
+
interface SchedulePluginOptions {
|
|
1089
|
+
/**
|
|
1090
|
+
* Etcd3 客户端实例
|
|
1091
|
+
* 如果未提供且 useMockEtcd 为 false,插件将不会启动调度任务
|
|
1092
|
+
*/
|
|
1093
|
+
etcdClient?: Etcd3$1;
|
|
1094
|
+
/**
|
|
1095
|
+
* 是否使用 Mock Etcd(用于测试和本地开发)
|
|
1096
|
+
* 当设置为 true 时,将使用内置的 MockEtcd3,始终选举自己作为 leader
|
|
1097
|
+
* 这样可以在没有真实 etcd 的情况下运行调度任务
|
|
1098
|
+
*
|
|
1099
|
+
* @default false
|
|
1100
|
+
*/
|
|
1101
|
+
useMockEtcd?: boolean;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Etcd3 类型定义(避免直接依赖 etcd3 包)
|
|
1105
|
+
* 这些类型定义与 etcd3@1.1.2 的实际类型兼容
|
|
1106
|
+
*/
|
|
1107
|
+
interface Etcd3$1 {
|
|
1108
|
+
election(key: string, ttl: number): Election;
|
|
1109
|
+
close(): void;
|
|
1110
|
+
delete(): any;
|
|
1111
|
+
get(key: string): any;
|
|
1112
|
+
}
|
|
1113
|
+
interface Election {
|
|
1114
|
+
observe(): Promise<Observer>;
|
|
1115
|
+
campaign(candidate: string): Campaign;
|
|
1116
|
+
}
|
|
1117
|
+
interface Observer {
|
|
1118
|
+
on(event: "change", callback: (leader: string | undefined) => void): Observer;
|
|
1119
|
+
on(event: "disconnected", callback: (error: Error) => void): Observer;
|
|
1120
|
+
on(event: "error", callback: (error: Error) => void): Observer;
|
|
1121
|
+
}
|
|
1122
|
+
interface Campaign {
|
|
1123
|
+
on(event: "error", callback: (error: any) => void): Campaign;
|
|
1124
|
+
on(event: "elected", callback: () => void): Campaign;
|
|
1125
|
+
resign(): Promise<void>;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* Schedule装饰器
|
|
1130
|
+
* 用于标记需要定时调度的方法
|
|
1131
|
+
*
|
|
1132
|
+
* @example
|
|
1133
|
+
* ```typescript
|
|
1134
|
+
* @Schedule({ interval: 5000, mode: ScheduleMode.FIXED_RATE })
|
|
1135
|
+
* async syncData() {
|
|
1136
|
+
* // 定时执行的任务
|
|
1137
|
+
* }
|
|
1138
|
+
* ```
|
|
1139
|
+
*/
|
|
1140
|
+
declare function Schedule(options: ScheduleOptions): (target: Function, context: ClassMethodDecoratorContext) => void;
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* SchedulePlugin - 调度任务插件
|
|
1144
|
+
* 使用 etcd 选举机制实现分布式定时任务,确保多个实例中只有一个执行任务
|
|
1145
|
+
*/
|
|
1146
|
+
declare class SchedulePlugin implements Plugin {
|
|
1147
|
+
readonly name = "schedule-plugin";
|
|
1148
|
+
readonly priority = PluginPriority.BUSINESS;
|
|
1149
|
+
private engine;
|
|
1150
|
+
private scheduler;
|
|
1151
|
+
private etcdClient;
|
|
1152
|
+
private scheduleHandlers;
|
|
1153
|
+
private useMockEtcd;
|
|
1154
|
+
constructor(options?: SchedulePluginOptions);
|
|
1155
|
+
/**
|
|
1156
|
+
* 引擎初始化钩子
|
|
1157
|
+
*/
|
|
1158
|
+
onInit(engine: Microservice): void;
|
|
1159
|
+
/**
|
|
1160
|
+
* Handler加载钩子:收集所有调度任务
|
|
1161
|
+
*/
|
|
1162
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
1163
|
+
/**
|
|
1164
|
+
* 引擎启动后钩子:启动所有调度任务
|
|
1165
|
+
*/
|
|
1166
|
+
onAfterStart(engine: Microservice): Promise<void>;
|
|
1167
|
+
/**
|
|
1168
|
+
* 引擎销毁钩子:停止所有调度任务
|
|
1169
|
+
*/
|
|
1170
|
+
onDestroy(): Promise<void>;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* 调度器类
|
|
1175
|
+
* 负责管理基于 etcd 选举的分布式定时任务
|
|
1176
|
+
*/
|
|
1177
|
+
declare class Scheduler {
|
|
1178
|
+
private etcdClient;
|
|
1179
|
+
private campaigns;
|
|
1180
|
+
private timers;
|
|
1181
|
+
private isLeader;
|
|
1182
|
+
constructor(etcdClient: Etcd3$1);
|
|
1183
|
+
/**
|
|
1184
|
+
* 启动调度任务
|
|
1185
|
+
*/
|
|
1186
|
+
startSchedule(serviceId: string, moduleName: string, methodName: string, electionKey: string, metadata: ScheduleMetadata, method: Function): Promise<void>;
|
|
1187
|
+
/**
|
|
1188
|
+
* 启动定时器
|
|
1189
|
+
*/
|
|
1190
|
+
private startTimer;
|
|
1191
|
+
/**
|
|
1192
|
+
* 停止定时器
|
|
1193
|
+
*/
|
|
1194
|
+
private stopTimer;
|
|
1195
|
+
/**
|
|
1196
|
+
* 停止所有调度任务
|
|
1197
|
+
*/
|
|
1198
|
+
stop(): Promise<void>;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Mock Etcd3 客户端
|
|
1203
|
+
* 用于测试和本地开发,模拟 etcd 的选举机制
|
|
1204
|
+
* 始终选举第一个参与选举的候选者作为 leader
|
|
1205
|
+
*/
|
|
1206
|
+
declare class MockEtcd3 implements Etcd3$1 {
|
|
1207
|
+
private elections;
|
|
1208
|
+
election(key: string, ttl: number): Election;
|
|
1209
|
+
close(): void;
|
|
1210
|
+
delete(): any;
|
|
1211
|
+
get(key: string): any;
|
|
1212
|
+
getElection(key: string): MockElection | undefined;
|
|
1213
|
+
clearElections(): void;
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Mock Election
|
|
1217
|
+
*/
|
|
1218
|
+
declare class MockElection implements Election {
|
|
1219
|
+
private key;
|
|
1220
|
+
private observers;
|
|
1221
|
+
private campaigns;
|
|
1222
|
+
private currentLeader;
|
|
1223
|
+
constructor(key: string);
|
|
1224
|
+
observe(): Promise<Observer>;
|
|
1225
|
+
campaign(candidate: string): Campaign;
|
|
1226
|
+
setLeader(leader: string): void;
|
|
1227
|
+
getCurrentLeader(): string | null;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/**
|
|
1231
|
+
* ClientCodePlugin 配置选项
|
|
1232
|
+
*/
|
|
1233
|
+
interface ClientCodePluginOptions {
|
|
1234
|
+
/**
|
|
1235
|
+
* 客户端代码保存路径(可选)
|
|
1236
|
+
* 如果设置,将在生成代码后自动保存到该路径
|
|
1237
|
+
* 通常用于开发阶段自动生成客户端代码用于调试或测试
|
|
1238
|
+
*
|
|
1239
|
+
* @example
|
|
1240
|
+
* ```ts
|
|
1241
|
+
* new ClientCodePlugin({ clientSavePath: "./generated/client.ts" })
|
|
1242
|
+
* ```
|
|
1243
|
+
*/
|
|
1244
|
+
clientSavePath?: string;
|
|
1245
|
+
}
|
|
1246
|
+
/**
|
|
1247
|
+
* ClientCodePlugin - 客户端代码生成插件
|
|
1248
|
+
* 收集所有 Action handlers,生成类型化的客户端代码,
|
|
1249
|
+
* 并提供 /client.ts 路由供远程下载
|
|
1250
|
+
*/
|
|
1251
|
+
declare class ClientCodePlugin implements Plugin {
|
|
1252
|
+
readonly name = "client-code-plugin";
|
|
1253
|
+
readonly priority = PluginPriority.ROUTE;
|
|
1254
|
+
private engine;
|
|
1255
|
+
private actionHandlers;
|
|
1256
|
+
private generatedCode;
|
|
1257
|
+
private readonly clientSavePath?;
|
|
1258
|
+
constructor(options?: ClientCodePluginOptions);
|
|
1259
|
+
/**
|
|
1260
|
+
* 引擎初始化钩子
|
|
1261
|
+
*/
|
|
1262
|
+
onInit(engine: Microservice): void;
|
|
1263
|
+
/**
|
|
1264
|
+
* Handler加载钩子:收集所有 Action handlers
|
|
1265
|
+
*/
|
|
1266
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
1267
|
+
/**
|
|
1268
|
+
* 引擎启动后钩子:注册客户端代码下载路由
|
|
1269
|
+
*/
|
|
1270
|
+
onAfterStart(engine: Microservice): Promise<void>;
|
|
1271
|
+
/**
|
|
1272
|
+
* 生成客户端代码
|
|
1273
|
+
*/
|
|
1274
|
+
private generateCode;
|
|
1275
|
+
/**
|
|
1276
|
+
* 保存代码到文件
|
|
1277
|
+
*/
|
|
1278
|
+
private saveCodeToFile;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Action 信息(用于生成客户端代码)
|
|
1283
|
+
*/
|
|
1284
|
+
interface ActionInfo {
|
|
1285
|
+
/**
|
|
1286
|
+
* 动作描述
|
|
1287
|
+
*/
|
|
1288
|
+
description?: string;
|
|
1289
|
+
/**
|
|
1290
|
+
* 参数校验 Schema(使用 zod)
|
|
1291
|
+
*/
|
|
1292
|
+
params: z.ZodTypeAny[];
|
|
1293
|
+
/**
|
|
1294
|
+
* 返回值校验 Schema(使用 zod)
|
|
1295
|
+
*/
|
|
1296
|
+
returns?: z.ZodTypeAny;
|
|
1297
|
+
/**
|
|
1298
|
+
* 是否流式返回(默认 false)
|
|
1299
|
+
*/
|
|
1300
|
+
stream?: boolean;
|
|
1301
|
+
/**
|
|
1302
|
+
* 是否幂等(默认 false)
|
|
1303
|
+
*/
|
|
1304
|
+
idempotence?: boolean;
|
|
1305
|
+
/**
|
|
1306
|
+
* 参数名称数组(从方法定义中提取)
|
|
1307
|
+
*/
|
|
1308
|
+
paramNames?: string[];
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* 模块信息(用于生成客户端代码)
|
|
1312
|
+
*/
|
|
1313
|
+
interface ModuleInfo {
|
|
1314
|
+
/**
|
|
1315
|
+
* 模块名称
|
|
1316
|
+
*/
|
|
1317
|
+
name: string;
|
|
1318
|
+
/**
|
|
1319
|
+
* 模块的所有 actions
|
|
1320
|
+
*/
|
|
1321
|
+
actions: Record<string, ActionInfo>;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
/**
|
|
1325
|
+
* 获取 Zod 类型的 TypeScript 类型字符串
|
|
1326
|
+
*/
|
|
1327
|
+
declare function getZodTypeString(schema: z.ZodType<any>, defaultOptional?: boolean): string;
|
|
1328
|
+
/**
|
|
1329
|
+
* 生成客户端代码
|
|
1330
|
+
* @param modules 模块信息
|
|
1331
|
+
* @returns 生成的客户端代码
|
|
1332
|
+
*/
|
|
1333
|
+
declare function generateClientCode(modules: Record<string, ModuleInfo>): Promise<string>;
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* 将 HandlerMetadata 数组转换为 ModuleInfo 格式
|
|
1337
|
+
* @param handlers Action handlers
|
|
1338
|
+
* @returns 模块信息映射
|
|
1339
|
+
*/
|
|
1340
|
+
declare function convertHandlersToModuleInfo(handlers: HandlerMetadata[]): Record<string, ModuleInfo>;
|
|
1341
|
+
/**
|
|
1342
|
+
* 从引擎获取模块信息并转换为 ModuleInfo 格式
|
|
1343
|
+
* @param handlers Action handlers
|
|
1344
|
+
* @param getModuleMetadata 获取模块元数据的函数
|
|
1345
|
+
* @returns 模块信息映射
|
|
1346
|
+
*/
|
|
1347
|
+
declare function convertHandlersToModuleInfoWithMetadata(handlers: HandlerMetadata[], getModuleMetadata: (moduleClass: any) => {
|
|
1348
|
+
name: string;
|
|
1349
|
+
} | undefined): Record<string, ModuleInfo>;
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* 配置项元数据
|
|
1353
|
+
*
|
|
1354
|
+
* 定义配置的基本信息,包括键、描述、Schema、默认值等
|
|
1355
|
+
*/
|
|
1356
|
+
interface ConfigMetadata {
|
|
1357
|
+
/**
|
|
1358
|
+
* 配置键(用于 etcd 存储)
|
|
1359
|
+
*/
|
|
1360
|
+
key: string;
|
|
1361
|
+
/**
|
|
1362
|
+
* 配置描述
|
|
1363
|
+
*/
|
|
1364
|
+
description?: string;
|
|
1365
|
+
/**
|
|
1366
|
+
* 配置的 Zod Schema(用于运行时验证)
|
|
1367
|
+
*/
|
|
1368
|
+
schema?: z.ZodTypeAny;
|
|
1369
|
+
/**
|
|
1370
|
+
* 默认值
|
|
1371
|
+
*/
|
|
1372
|
+
defaultValue?: any;
|
|
1373
|
+
/**
|
|
1374
|
+
* 是否为敏感信息(日志中脱敏)
|
|
1375
|
+
*/
|
|
1376
|
+
sensitive?: boolean;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* 动态配置装饰器选项
|
|
1380
|
+
*
|
|
1381
|
+
* 扩展 ConfigMetadata,添加 onChange 回调支持
|
|
1382
|
+
*
|
|
1383
|
+
* 配置优先级:ETCD > 环境变量 > defaultValue
|
|
1384
|
+
* 环境变量名由 key 自动转换(kebab-case -> UPPER_SNAKE_CASE)
|
|
1385
|
+
*
|
|
1386
|
+
* 💡 **推荐**:直接使用 UPPER_SNAKE_CASE 格式作为 key,与环境变量名保持一致
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```typescript
|
|
1390
|
+
* // 推荐:使用 UPPER_SNAKE_CASE 格式 + 属性装饰器
|
|
1391
|
+
* @Config({
|
|
1392
|
+
* key: "MAX_CONNECTIONS", // 直接对应环境变量 MAX_CONNECTIONS
|
|
1393
|
+
* defaultValue: 100,
|
|
1394
|
+
* })
|
|
1395
|
+
* maxConnections!: number; // TypeScript 完美推断类型
|
|
1396
|
+
*
|
|
1397
|
+
* // 也支持:使用 kebab-case 格式(自动转换)
|
|
1398
|
+
* @Config({
|
|
1399
|
+
* key: "max-connections", // 自动转换为环境变量 MAX_CONNECTIONS
|
|
1400
|
+
* defaultValue: 100,
|
|
1401
|
+
* })
|
|
1402
|
+
* maxConnections!: number;
|
|
1403
|
+
* ```
|
|
1404
|
+
*/
|
|
1405
|
+
interface DynamicConfigOptions extends ConfigMetadata {
|
|
1406
|
+
/**
|
|
1407
|
+
* 配置变更回调(可选)
|
|
1408
|
+
*
|
|
1409
|
+
* 当配置值发生变化时,会触发此回调函数
|
|
1410
|
+
*
|
|
1411
|
+
* @param newValue 新的配置值
|
|
1412
|
+
* @param oldValue 旧的配置值
|
|
1413
|
+
*/
|
|
1414
|
+
onChange?: (newValue: any, oldValue: any) => void | Promise<void>;
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* 插件配置选项
|
|
1418
|
+
*
|
|
1419
|
+
* 定义 DynamicConfigPlugin 的初始化选项
|
|
1420
|
+
*/
|
|
1421
|
+
interface DynamicConfigPluginOptions {
|
|
1422
|
+
/**
|
|
1423
|
+
* Etcd3 客户端实例
|
|
1424
|
+
* 如果未提供且 useMockEtcd 为 false,插件将使用默认配置
|
|
1425
|
+
*/
|
|
1426
|
+
etcdClient?: Etcd3;
|
|
1427
|
+
/**
|
|
1428
|
+
* 是否使用 Mock Etcd(用于测试和本地开发)
|
|
1429
|
+
* @default false
|
|
1430
|
+
*/
|
|
1431
|
+
useMockEtcd?: boolean;
|
|
1432
|
+
/**
|
|
1433
|
+
* etcd 配置键前缀
|
|
1434
|
+
* @default "/config"
|
|
1435
|
+
*/
|
|
1436
|
+
etcdPrefix?: string;
|
|
1437
|
+
/**
|
|
1438
|
+
* 是否启用配置缓存(缓存到 MySQL)
|
|
1439
|
+
* @default false
|
|
1440
|
+
*/
|
|
1441
|
+
enablePersistence?: boolean;
|
|
1442
|
+
/**
|
|
1443
|
+
* MySQL 数据库配置(当 enablePersistence 为 true 时需要)
|
|
1444
|
+
*/
|
|
1445
|
+
mysql?: {
|
|
1446
|
+
host: string;
|
|
1447
|
+
port: number;
|
|
1448
|
+
user: string;
|
|
1449
|
+
password: string;
|
|
1450
|
+
database: string;
|
|
1451
|
+
};
|
|
1452
|
+
/**
|
|
1453
|
+
* 配置同步间隔(毫秒)
|
|
1454
|
+
* 从 MySQL 同步配置到 etcd 的间隔
|
|
1455
|
+
* @default 30000 (30秒)
|
|
1456
|
+
*/
|
|
1457
|
+
syncInterval?: number;
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* 配置存储接口
|
|
1461
|
+
*
|
|
1462
|
+
* 定义配置存储的标准操作,支持 etcd 和内存两种实现
|
|
1463
|
+
*/
|
|
1464
|
+
interface ConfigStorage {
|
|
1465
|
+
/**
|
|
1466
|
+
* 获取配置
|
|
1467
|
+
*/
|
|
1468
|
+
get(key: string): Promise<any>;
|
|
1469
|
+
/**
|
|
1470
|
+
* 设置配置
|
|
1471
|
+
*/
|
|
1472
|
+
set(key: string, value: any, metadata?: ConfigMetadata): Promise<void>;
|
|
1473
|
+
/**
|
|
1474
|
+
* 删除配置
|
|
1475
|
+
*/
|
|
1476
|
+
delete(key: string): Promise<void>;
|
|
1477
|
+
/**
|
|
1478
|
+
* 获取所有配置
|
|
1479
|
+
*/
|
|
1480
|
+
getAll(prefix?: string): Promise<Map<string, any>>;
|
|
1481
|
+
/**
|
|
1482
|
+
* 监听配置变化
|
|
1483
|
+
*/
|
|
1484
|
+
watch(key: string, callback: (newValue: any, oldValue: any) => void): () => void;
|
|
1485
|
+
/**
|
|
1486
|
+
* 同步获取缓存的配置(不访问 etcd)
|
|
1487
|
+
* 用于 configProxy 的同步访问
|
|
1488
|
+
*/
|
|
1489
|
+
getCached?(key: string): any;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* 配置项(用于前端管理界面)
|
|
1493
|
+
*
|
|
1494
|
+
* 包含配置的详细信息,用于前端展示和编辑
|
|
1495
|
+
*/
|
|
1496
|
+
interface ConfigItem {
|
|
1497
|
+
/**
|
|
1498
|
+
* 配置键
|
|
1499
|
+
*/
|
|
1500
|
+
key: string;
|
|
1501
|
+
/**
|
|
1502
|
+
* 配置值
|
|
1503
|
+
*/
|
|
1504
|
+
value: any;
|
|
1505
|
+
/**
|
|
1506
|
+
* 配置描述
|
|
1507
|
+
*/
|
|
1508
|
+
description?: string;
|
|
1509
|
+
/**
|
|
1510
|
+
* 配置类型
|
|
1511
|
+
*/
|
|
1512
|
+
type: string;
|
|
1513
|
+
/**
|
|
1514
|
+
* 是否为敏感信息
|
|
1515
|
+
*/
|
|
1516
|
+
sensitive: boolean;
|
|
1517
|
+
/**
|
|
1518
|
+
* 创建时间
|
|
1519
|
+
*/
|
|
1520
|
+
createdAt: Date;
|
|
1521
|
+
/**
|
|
1522
|
+
* 更新时间
|
|
1523
|
+
*/
|
|
1524
|
+
updatedAt: Date;
|
|
1525
|
+
/**
|
|
1526
|
+
* 创建人
|
|
1527
|
+
*/
|
|
1528
|
+
createdBy?: string;
|
|
1529
|
+
/**
|
|
1530
|
+
* 更新人
|
|
1531
|
+
*/
|
|
1532
|
+
updatedBy?: string;
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* 配置变更历史
|
|
1536
|
+
*
|
|
1537
|
+
* 记录配置的每次变更,用于审计和回滚
|
|
1538
|
+
*/
|
|
1539
|
+
interface ConfigHistory {
|
|
1540
|
+
/**
|
|
1541
|
+
* 历史 ID
|
|
1542
|
+
*/
|
|
1543
|
+
id: string;
|
|
1544
|
+
/**
|
|
1545
|
+
* 配置键
|
|
1546
|
+
*/
|
|
1547
|
+
key: string;
|
|
1548
|
+
/**
|
|
1549
|
+
* 旧值
|
|
1550
|
+
*/
|
|
1551
|
+
oldValue: any;
|
|
1552
|
+
/**
|
|
1553
|
+
* 新值
|
|
1554
|
+
*/
|
|
1555
|
+
newValue: any;
|
|
1556
|
+
/**
|
|
1557
|
+
* 变更时间
|
|
1558
|
+
*/
|
|
1559
|
+
changedAt: Date;
|
|
1560
|
+
/**
|
|
1561
|
+
* 变更人
|
|
1562
|
+
*/
|
|
1563
|
+
changedBy: string;
|
|
1564
|
+
/**
|
|
1565
|
+
* 变更原因
|
|
1566
|
+
*/
|
|
1567
|
+
reason?: string;
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Module 配置选项
|
|
1571
|
+
*
|
|
1572
|
+
* 用于 @Module 装饰器的 options 参数
|
|
1573
|
+
*/
|
|
1574
|
+
interface DynamicConfigModuleOptions {
|
|
1575
|
+
/**
|
|
1576
|
+
* 配置命名空间(用于区分不同模块的配置)
|
|
1577
|
+
*
|
|
1578
|
+
* 默认使用模块名
|
|
1579
|
+
*/
|
|
1580
|
+
configNamespace?: string;
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Etcd3 类型定义
|
|
1584
|
+
*
|
|
1585
|
+
* 避免直接依赖 etcd3 包,提供最小化的类型定义
|
|
1586
|
+
*/
|
|
1587
|
+
interface Etcd3 {
|
|
1588
|
+
get(key: string): {
|
|
1589
|
+
string(): Promise<string | null>;
|
|
1590
|
+
};
|
|
1591
|
+
put(key: string): {
|
|
1592
|
+
value(value: string): Promise<void>;
|
|
1593
|
+
};
|
|
1594
|
+
delete(): {
|
|
1595
|
+
key(key: string): Promise<void>;
|
|
1596
|
+
};
|
|
1597
|
+
getAll(): {
|
|
1598
|
+
prefix(prefix: string): {
|
|
1599
|
+
strings(): Promise<Record<string, string>>;
|
|
1600
|
+
};
|
|
1601
|
+
};
|
|
1602
|
+
watch(): Watch;
|
|
1603
|
+
}
|
|
1604
|
+
interface Watch {
|
|
1605
|
+
key(key: string): WatchBuilder;
|
|
1606
|
+
}
|
|
1607
|
+
interface WatchBuilder {
|
|
1608
|
+
create(): Promise<Watcher>;
|
|
1609
|
+
}
|
|
1610
|
+
interface Watcher {
|
|
1611
|
+
on(event: "put", callback: (kv: {
|
|
1612
|
+
key: Buffer;
|
|
1613
|
+
value: Buffer;
|
|
1614
|
+
}) => void): void;
|
|
1615
|
+
on(event: "delete", callback: (kv: {
|
|
1616
|
+
key: Buffer;
|
|
1617
|
+
}) => void): void;
|
|
1618
|
+
cancel(): void;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
/**
|
|
1622
|
+
* DynamicConfigPlugin - 动态配置插件
|
|
1623
|
+
*
|
|
1624
|
+
* 提供基于 etcd 的动态配置功能,支持:
|
|
1625
|
+
* - 装饰器驱动的配置定义 (@Config)
|
|
1626
|
+
* - 实时配置热更新(通过 etcd watch 机制)
|
|
1627
|
+
* - 类型安全(Zod Schema 运行时验证)
|
|
1628
|
+
* - 完美的 TypeScript 类型推断
|
|
1629
|
+
* - 自动预加载配置到缓存
|
|
1630
|
+
* - 配置变更回调
|
|
1631
|
+
* - 同步访问配置
|
|
1632
|
+
*
|
|
1633
|
+
* @example
|
|
1634
|
+
* ```typescript
|
|
1635
|
+
* // 基础用法
|
|
1636
|
+
* const plugin = new DynamicConfigPlugin({
|
|
1637
|
+
* etcdClient: etcdInstance,
|
|
1638
|
+
* etcdPrefix: "/config",
|
|
1639
|
+
* });
|
|
1640
|
+
*
|
|
1641
|
+
* @Module("user-service")
|
|
1642
|
+
* class UserService {
|
|
1643
|
+
* @Config({
|
|
1644
|
+
* key: "MAX_LOGIN_ATTEMPTS",
|
|
1645
|
+
* defaultValue: 5,
|
|
1646
|
+
* schema: z.number().min(1).max(10),
|
|
1647
|
+
* })
|
|
1648
|
+
* maxLoginAttempts!: number;
|
|
1649
|
+
* }
|
|
1650
|
+
* ```
|
|
1651
|
+
*/
|
|
1652
|
+
declare class DynamicConfigPlugin implements Plugin<DynamicConfigModuleOptions> {
|
|
1653
|
+
readonly name = "dynamic-config-plugin";
|
|
1654
|
+
readonly priority = PluginPriority.BUSINESS;
|
|
1655
|
+
private engine;
|
|
1656
|
+
private storage;
|
|
1657
|
+
private configHandlers;
|
|
1658
|
+
private unwatchFunctions;
|
|
1659
|
+
constructor(options?: DynamicConfigPluginOptions);
|
|
1660
|
+
/**
|
|
1661
|
+
* 声明 Module 配置 Schema
|
|
1662
|
+
*/
|
|
1663
|
+
getModuleOptionsSchema(): PluginModuleOptionsSchema<DynamicConfigModuleOptions>;
|
|
1664
|
+
/**
|
|
1665
|
+
* 引擎初始化钩子
|
|
1666
|
+
*/
|
|
1667
|
+
onInit(engine: Microservice): void;
|
|
1668
|
+
/**
|
|
1669
|
+
* Handler 加载钩子:收集所有动态配置
|
|
1670
|
+
*/
|
|
1671
|
+
onHandlerLoad(handlers: HandlerMetadata[]): void;
|
|
1672
|
+
/**
|
|
1673
|
+
* 包装配置方法,实现动态配置注入
|
|
1674
|
+
*/
|
|
1675
|
+
private wrapConfigHandler;
|
|
1676
|
+
/**
|
|
1677
|
+
* 引擎启动后钩子:启动配置监听和预加载配置
|
|
1678
|
+
*/
|
|
1679
|
+
onAfterStart(engine: Microservice): Promise<void>;
|
|
1680
|
+
/**
|
|
1681
|
+
* 预加载所有配置到缓存,并将配置方法/属性转换为同步 getter
|
|
1682
|
+
*/
|
|
1683
|
+
private preloadConfigs;
|
|
1684
|
+
/**
|
|
1685
|
+
* 引擎销毁钩子:清理资源
|
|
1686
|
+
*/
|
|
1687
|
+
onDestroy(): Promise<void>;
|
|
1688
|
+
/**
|
|
1689
|
+
* 获取模块名称
|
|
1690
|
+
*/
|
|
1691
|
+
private getModuleName;
|
|
1692
|
+
/**
|
|
1693
|
+
* 构建完整的配置键
|
|
1694
|
+
*/
|
|
1695
|
+
private buildConfigKey;
|
|
1696
|
+
/**
|
|
1697
|
+
* 公共 API:获取配置
|
|
1698
|
+
*/
|
|
1699
|
+
getConfig(key: string): Promise<any>;
|
|
1700
|
+
/**
|
|
1701
|
+
* 公共 API:同步获取配置(从缓存)
|
|
1702
|
+
* 用于 configProxy 的同步访问
|
|
1703
|
+
*/
|
|
1704
|
+
getConfigCached(key: string): any;
|
|
1705
|
+
/**
|
|
1706
|
+
* 公共 API:设置配置
|
|
1707
|
+
*/
|
|
1708
|
+
setConfig(key: string, value: any, metadata?: ConfigMetadata): Promise<void>;
|
|
1709
|
+
/**
|
|
1710
|
+
* 公共 API:删除配置
|
|
1711
|
+
*/
|
|
1712
|
+
deleteConfig(key: string): Promise<void>;
|
|
1713
|
+
/**
|
|
1714
|
+
* 公共 API:获取所有配置
|
|
1715
|
+
*/
|
|
1716
|
+
getAllConfigs(prefix?: string): Promise<Map<string, any>>;
|
|
1717
|
+
/**
|
|
1718
|
+
* 公共 API:监听配置变化
|
|
1719
|
+
*/
|
|
1720
|
+
watchConfig(key: string, callback: (newValue: any, oldValue: any) => void): () => void;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
/**
|
|
1724
|
+
* Config 属性装饰器
|
|
1725
|
+
*
|
|
1726
|
+
* 标记需要动态配置的属性,使其能够从 etcd 动态读取配置值
|
|
1727
|
+
* ✅ 完美的 TypeScript 类型推断,无需类型断言
|
|
1728
|
+
*
|
|
1729
|
+
* @param options 动态配置选项
|
|
1730
|
+
* @returns 属性装饰器
|
|
1731
|
+
*
|
|
1732
|
+
* @example
|
|
1733
|
+
* ```typescript
|
|
1734
|
+
* @Module("user-service")
|
|
1735
|
+
* class UserService {
|
|
1736
|
+
* // ✅ 使用属性装饰器,完美的类型推断
|
|
1737
|
+
* @Config({
|
|
1738
|
+
* key: "MAX_LOGIN_ATTEMPTS",
|
|
1739
|
+
* description: "最大登录尝试次数",
|
|
1740
|
+
* schema: z.number().min(1).max(10),
|
|
1741
|
+
* defaultValue: 5,
|
|
1742
|
+
* })
|
|
1743
|
+
* maxLoginAttempts!: number; // TypeScript 正确识别为 number
|
|
1744
|
+
*
|
|
1745
|
+
* async login(username: string, password: string) {
|
|
1746
|
+
* // ✅ 完美:直接访问,类型正确
|
|
1747
|
+
* const maxAttempts = this.maxLoginAttempts; // number 类型
|
|
1748
|
+
* if (attempts > maxAttempts) {
|
|
1749
|
+
* throw new Error("Too many attempts");
|
|
1750
|
+
* }
|
|
1751
|
+
* }
|
|
1752
|
+
* }
|
|
1753
|
+
* ```
|
|
1754
|
+
*
|
|
1755
|
+
* @example
|
|
1756
|
+
* ```typescript
|
|
1757
|
+
* // 带变更回调
|
|
1758
|
+
* type FeatureFlags = {
|
|
1759
|
+
* enableNewUI: boolean;
|
|
1760
|
+
* enableBetaFeatures: boolean;
|
|
1761
|
+
* };
|
|
1762
|
+
*
|
|
1763
|
+
* @Config({
|
|
1764
|
+
* key: "FEATURE_FLAGS",
|
|
1765
|
+
* schema: z.object({
|
|
1766
|
+
* enableNewUI: z.boolean(),
|
|
1767
|
+
* enableBetaFeatures: z.boolean(),
|
|
1768
|
+
* }),
|
|
1769
|
+
* defaultValue: {
|
|
1770
|
+
* enableNewUI: false,
|
|
1771
|
+
* enableBetaFeatures: false,
|
|
1772
|
+
* },
|
|
1773
|
+
* onChange: async (newValue, oldValue) => {
|
|
1774
|
+
* console.log("Feature flags changed:", { newValue, oldValue });
|
|
1775
|
+
* },
|
|
1776
|
+
* })
|
|
1777
|
+
* featureFlags!: FeatureFlags; // TypeScript 正确识别类型
|
|
1778
|
+
* ```
|
|
1779
|
+
*
|
|
1780
|
+
* @example
|
|
1781
|
+
* ```typescript
|
|
1782
|
+
* // 支持环境变量(优先级:ETCD > ENV > DEFAULT)
|
|
1783
|
+
* @Config({
|
|
1784
|
+
* key: "MAX_CONNECTIONS",
|
|
1785
|
+
* schema: z.number().min(1).max(1000),
|
|
1786
|
+
* defaultValue: 100,
|
|
1787
|
+
* })
|
|
1788
|
+
* maxConnections!: number;
|
|
1789
|
+
*
|
|
1790
|
+
* // 使用时完美
|
|
1791
|
+
* useConnection() {
|
|
1792
|
+
* const num = this.maxConnections + 10; // ✅ 类型正确,可以直接运算
|
|
1793
|
+
* const sum = this.maxConnections * 2; // ✅ 类型正确,可以直接运算
|
|
1794
|
+
* }
|
|
1795
|
+
* ```
|
|
1796
|
+
*/
|
|
1797
|
+
declare function Config(options: DynamicConfigOptions): (target: undefined, context: ClassFieldDecoratorContext) => void;
|
|
1798
|
+
|
|
1799
|
+
/**
|
|
1800
|
+
* Etcd 配置存储实现
|
|
1801
|
+
*
|
|
1802
|
+
* 负责与 etcd 交互,提供配置的读取、写入、删除、监听功能
|
|
1803
|
+
* 内置缓存机制,减少 etcd 访问次数
|
|
1804
|
+
*/
|
|
1805
|
+
declare class EtcdConfigStorage implements ConfigStorage {
|
|
1806
|
+
private etcdClient;
|
|
1807
|
+
private prefix;
|
|
1808
|
+
private watchers;
|
|
1809
|
+
private cache;
|
|
1810
|
+
constructor(etcdClient: Etcd3, prefix?: string);
|
|
1811
|
+
/**
|
|
1812
|
+
* 构建完整的 etcd 键
|
|
1813
|
+
*/
|
|
1814
|
+
private buildKey;
|
|
1815
|
+
/**
|
|
1816
|
+
* 获取配置
|
|
1817
|
+
*/
|
|
1818
|
+
get(key: string): Promise<any>;
|
|
1819
|
+
/**
|
|
1820
|
+
* 同步获取缓存的配置(不访问 etcd)
|
|
1821
|
+
* 用于 configProxy 的同步访问
|
|
1822
|
+
*/
|
|
1823
|
+
getCached(key: string): any;
|
|
1824
|
+
/**
|
|
1825
|
+
* 设置配置
|
|
1826
|
+
*/
|
|
1827
|
+
set(key: string, value: any, metadata?: ConfigMetadata): Promise<void>;
|
|
1828
|
+
/**
|
|
1829
|
+
* 删除配置
|
|
1830
|
+
*/
|
|
1831
|
+
delete(key: string): Promise<void>;
|
|
1832
|
+
/**
|
|
1833
|
+
* 获取所有配置
|
|
1834
|
+
*/
|
|
1835
|
+
getAll(prefix?: string): Promise<Map<string, any>>;
|
|
1836
|
+
/**
|
|
1837
|
+
* 监听配置变化
|
|
1838
|
+
*/
|
|
1839
|
+
watch(key: string, callback: (newValue: any, oldValue: any) => void): () => void;
|
|
1840
|
+
/**
|
|
1841
|
+
* 清理资源
|
|
1842
|
+
*/
|
|
1843
|
+
destroy(): Promise<void>;
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1846
|
+
* 内存配置存储实现
|
|
1847
|
+
*
|
|
1848
|
+
* 用于测试和本地开发环境,不依赖 etcd
|
|
1849
|
+
* 配置存储在内存中,服务重启后会丢失
|
|
1850
|
+
*/
|
|
1851
|
+
declare class MemoryConfigStorage implements ConfigStorage {
|
|
1852
|
+
private storage;
|
|
1853
|
+
private watchers;
|
|
1854
|
+
get(key: string): Promise<any>;
|
|
1855
|
+
getCached(key: string): any;
|
|
1856
|
+
set(key: string, value: any, metadata?: ConfigMetadata): Promise<void>;
|
|
1857
|
+
delete(key: string): Promise<void>;
|
|
1858
|
+
getAll(prefix?: string): Promise<Map<string, any>>;
|
|
1859
|
+
watch(key: string, callback: (newValue: any, oldValue: any) => void): () => void;
|
|
1860
|
+
destroy(): Promise<void>;
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
/**
|
|
1864
|
+
* 从插件数组中提取聚合的配置类型
|
|
1865
|
+
*/
|
|
1866
|
+
type ExtractPluginOptions<T extends readonly Plugin<any>[]> = T extends readonly [infer P1, ...infer Rest] ? P1 extends Plugin<infer T1> ? Rest extends readonly Plugin<any>[] ? T1 & ExtractPluginOptions<Rest> : T1 : ExtractPluginOptions<Rest extends readonly Plugin<any>[] ? Rest : []> : Record<string, any>;
|
|
1867
|
+
/**
|
|
1868
|
+
* Factory - 创建类型化的引擎实例
|
|
1869
|
+
*
|
|
1870
|
+
* 注意:所有插件都必须显式注册,不会自动包含任何默认插件
|
|
1871
|
+
*/
|
|
1872
|
+
declare class Factory {
|
|
1873
|
+
/**
|
|
1874
|
+
* 创建类型化的引擎工厂
|
|
1875
|
+
*
|
|
1876
|
+
* @param plugins 插件列表(必须显式提供所有需要的插件)
|
|
1877
|
+
* @returns 包含类型化的 Module 装饰器和 Microservice 类的对象
|
|
1878
|
+
*/
|
|
1879
|
+
static create<TPlugins extends readonly Plugin<any>[]>(...plugins: TPlugins): {
|
|
1880
|
+
Module: ModuleDecorator<ExtractPluginOptions<TPlugins>>;
|
|
1881
|
+
Microservice: new (options: MicroserviceOptions) => Microservice<ExtractPluginOptions<TPlugins>>;
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
/**
|
|
1886
|
+
* 测试辅助模块
|
|
1887
|
+
* 提供常用的测试工具函数和类型,简化测试代码编写
|
|
1888
|
+
*/
|
|
1889
|
+
|
|
1890
|
+
/**
|
|
1891
|
+
* 默认测试配置
|
|
1892
|
+
*/
|
|
1893
|
+
declare const DEFAULT_TEST_OPTIONS: {
|
|
1894
|
+
readonly name: "test-service";
|
|
1895
|
+
readonly version: "1.0.0";
|
|
1896
|
+
};
|
|
1897
|
+
/**
|
|
1898
|
+
* 创建测试引擎
|
|
1899
|
+
*
|
|
1900
|
+
* @example
|
|
1901
|
+
* ```ts
|
|
1902
|
+
* // 只传插件
|
|
1903
|
+
* const { engine, Module } = Testing.createTestEngine({
|
|
1904
|
+
* plugins: [new CachePlugin()]
|
|
1905
|
+
* });
|
|
1906
|
+
*
|
|
1907
|
+
* // 传插件和 options
|
|
1908
|
+
* const { engine, Module } = Testing.createTestEngine({
|
|
1909
|
+
* plugins: [new CachePlugin()],
|
|
1910
|
+
* options: { prefix: "/api" }
|
|
1911
|
+
* });
|
|
1912
|
+
* ```
|
|
1913
|
+
*/
|
|
1914
|
+
declare function createTestEngine<TPlugins extends readonly Plugin<any>[]>(config: {
|
|
1915
|
+
plugins: TPlugins;
|
|
1916
|
+
options?: Partial<MicroserviceOptions>;
|
|
1917
|
+
}): ReturnType<typeof Factory.create<TPlugins>> & {
|
|
1918
|
+
engine: InstanceType<ReturnType<typeof Factory.create<TPlugins>>["Microservice"]>;
|
|
1919
|
+
};
|
|
1920
|
+
/**
|
|
1921
|
+
* 等待指定时间(用于异步测试)
|
|
1922
|
+
*
|
|
1923
|
+
* @param ms 等待的毫秒数
|
|
1924
|
+
* @returns Promise
|
|
1925
|
+
*/
|
|
1926
|
+
declare function wait(ms: number): Promise<void>;
|
|
1927
|
+
/**
|
|
1928
|
+
* 测试辅助工具命名空间
|
|
1929
|
+
* 所有测试相关的工具函数都通过这个命名空间导出,避免命名冲突
|
|
1930
|
+
*/
|
|
1931
|
+
declare const Testing: {
|
|
1932
|
+
readonly createTestEngine: typeof createTestEngine;
|
|
1933
|
+
readonly DEFAULT_TEST_OPTIONS: {
|
|
1934
|
+
readonly name: "test-service";
|
|
1935
|
+
readonly version: "1.0.0";
|
|
1936
|
+
};
|
|
1937
|
+
readonly wait: typeof wait;
|
|
1938
|
+
};
|
|
1939
|
+
|
|
1940
|
+
declare const logger: winston.Logger;
|
|
1941
|
+
|
|
1942
|
+
/**
|
|
1943
|
+
* Nebula ID Generator - 基于 nanoid 的 ID 生成器
|
|
1944
|
+
*
|
|
1945
|
+
* 使用自定义字符集(仅包含大小写字母和数字)生成唯一 ID
|
|
1946
|
+
* 字符集:A-Z, a-z, 0-9 (共62个字符)
|
|
1947
|
+
*
|
|
1948
|
+
* @example
|
|
1949
|
+
* ```typescript
|
|
1950
|
+
* import { nebulaId } from "nebula-engine";
|
|
1951
|
+
*
|
|
1952
|
+
* // 生成默认长度(12)的 ID
|
|
1953
|
+
* const id1 = nebulaId();
|
|
1954
|
+
* console.log(id1); // 例如: "V1StGXR8IZ5j"
|
|
1955
|
+
*
|
|
1956
|
+
* // 生成指定长度的 ID
|
|
1957
|
+
* const id2 = nebulaId(10);
|
|
1958
|
+
* console.log(id2); // 例如: "V1StGXR8IZ"
|
|
1959
|
+
* ```
|
|
1960
|
+
*/
|
|
1961
|
+
/**
|
|
1962
|
+
* Nebula ID 字符集
|
|
1963
|
+
* 仅包含大小写字母和数字(A-Z, a-z, 0-9),不包含下划线和横线
|
|
1964
|
+
*/
|
|
1965
|
+
declare const NEBULA_ID_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
1966
|
+
/**
|
|
1967
|
+
* 生成 Nebula ID
|
|
1968
|
+
*
|
|
1969
|
+
* @param length - ID 长度(默认 12
|
|
1970
|
+
* @returns 生成的 ID 字符串
|
|
1971
|
+
*
|
|
1972
|
+
* @example
|
|
1973
|
+
* ```typescript
|
|
1974
|
+
* // 生成默认长度的 ID
|
|
1975
|
+
* const id1 = nebulaId();
|
|
1976
|
+
*
|
|
1977
|
+
* // 生成指定长度的 ID
|
|
1978
|
+
* const id2 = nebulaId(10);
|
|
1979
|
+
* const id3 = nebulaId(32);
|
|
1980
|
+
* ```
|
|
1981
|
+
*/
|
|
1982
|
+
declare function nebulaId(length?: number): string;
|
|
1983
|
+
|
|
1984
|
+
export { Action, type ActionInfo, type ActionModuleOptions, type ActionOptions, ActionPlugin, BaseLayout, Cache, type CacheAdapter, type CacheItem, type CacheModuleOptions, type CacheOptions, CachePlugin, type Campaign, type Class, type ClassDecoratorContext, type ClassMethodDecoratorContext$1 as ClassMethodDecoratorContext, ClientCodePlugin, type ClientCodePluginOptions, Config, type ConfigHistory, type ConfigItem, type ConfigMetadata, type ConfigStorage, DEFAULT_TEST_OPTIONS, DuplicateModuleError, type DynamicConfigModuleOptions, type DynamicConfigOptions, DynamicConfigPlugin, type DynamicConfigPluginOptions, type Election, type ErrorTransformer, type Etcd3$1 as Etcd3, EtcdConfigStorage, Factory, GracefulShutdownPlugin, type GracefulShutdownPluginOptions, type HTTPMethod, Handler, type HandlerMetadata, type HandlerWrapper, HtmxLayout, MemoryCacheAdapter, MemoryConfigStorage, Microservice, type MicroserviceOptions, MockEtcd3, ModuleConfigValidationError, type ModuleDecorator, type ModuleInfo, type ModuleMetadata, NEBULA_ID_ALPHABET, type Observer, Page, type Plugin, type PluginModuleOptionsSchema, PluginNameRequiredError, PluginPriority, type PreStartChecker, RedisCacheAdapter, type RedisCacheAdapterOptions, Route, type RouteModuleOptions, type RouteOptions, RoutePlugin, type RoutePluginOptions, Schedule, type ScheduleMetadata, ScheduleMode, type ScheduleOptions, SchedulePlugin, type SchedulePluginOptions, Scheduler, ServiceInfoCards, type ServiceStatusInfo, ServiceStatusPage, Testing, convertHandlersToModuleInfo, convertHandlersToModuleInfoWithMetadata, generateClientCode, getZodTypeString, logger, nebulaId, startCheck };
|