imean-service-engine 2.0.0 → 2.0.2

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.
Files changed (72) hide show
  1. package/dist/index.d.mts +77 -52
  2. package/dist/index.d.ts +77 -52
  3. package/dist/index.js +2078 -1945
  4. package/dist/index.mjs +2076 -1944
  5. package/package.json +9 -2
  6. package/.vscode/settings.json +0 -8
  7. package/src/core/checker.ts +0 -33
  8. package/src/core/decorators.test.ts +0 -96
  9. package/src/core/decorators.ts +0 -68
  10. package/src/core/engine.test.ts +0 -218
  11. package/src/core/engine.ts +0 -635
  12. package/src/core/errors.ts +0 -28
  13. package/src/core/factory.test.ts +0 -73
  14. package/src/core/factory.ts +0 -92
  15. package/src/core/logger.ts +0 -65
  16. package/src/core/testing.ts +0 -73
  17. package/src/core/types.ts +0 -191
  18. package/src/index.ts +0 -49
  19. package/src/metadata/README.md +0 -422
  20. package/src/metadata/metadata.test.ts +0 -369
  21. package/src/metadata/metadata.ts +0 -512
  22. package/src/plugins/action/action-plugin.test.ts +0 -660
  23. package/src/plugins/action/decorator.ts +0 -14
  24. package/src/plugins/action/index.ts +0 -4
  25. package/src/plugins/action/plugin.ts +0 -349
  26. package/src/plugins/action/types.ts +0 -49
  27. package/src/plugins/action/utils.test.ts +0 -196
  28. package/src/plugins/action/utils.ts +0 -111
  29. package/src/plugins/cache/adapter.test.ts +0 -689
  30. package/src/plugins/cache/adapter.ts +0 -324
  31. package/src/plugins/cache/cache-plugin.test.ts +0 -269
  32. package/src/plugins/cache/decorator.ts +0 -26
  33. package/src/plugins/cache/index.ts +0 -20
  34. package/src/plugins/cache/plugin.ts +0 -299
  35. package/src/plugins/cache/types.ts +0 -69
  36. package/src/plugins/client-code/client-code-plugin.test.ts +0 -511
  37. package/src/plugins/client-code/format.ts +0 -9
  38. package/src/plugins/client-code/generator.test.ts +0 -52
  39. package/src/plugins/client-code/generator.ts +0 -263
  40. package/src/plugins/client-code/index.ts +0 -15
  41. package/src/plugins/client-code/plugin.ts +0 -158
  42. package/src/plugins/client-code/types.ts +0 -52
  43. package/src/plugins/client-code/utils.ts +0 -164
  44. package/src/plugins/graceful-shutdown/graceful-shutdown-plugin.test.ts +0 -401
  45. package/src/plugins/graceful-shutdown/index.ts +0 -3
  46. package/src/plugins/graceful-shutdown/plugin.ts +0 -279
  47. package/src/plugins/graceful-shutdown/types.ts +0 -17
  48. package/src/plugins/rate-limit/rate-limit-plugin.example.ts +0 -171
  49. package/src/plugins/route/components/Layout.tsx +0 -42
  50. package/src/plugins/route/components/ServiceStatusPage.tsx +0 -141
  51. package/src/plugins/route/decorator.ts +0 -50
  52. package/src/plugins/route/index.ts +0 -16
  53. package/src/plugins/route/plugin.ts +0 -218
  54. package/src/plugins/route/route-plugin.test.ts +0 -759
  55. package/src/plugins/route/types.ts +0 -72
  56. package/src/plugins/schedule/README.md +0 -309
  57. package/src/plugins/schedule/decorator.ts +0 -25
  58. package/src/plugins/schedule/index.ts +0 -12
  59. package/src/plugins/schedule/mock-etcd.ts +0 -145
  60. package/src/plugins/schedule/plugin.ts +0 -164
  61. package/src/plugins/schedule/schedule-plugin.test.ts +0 -312
  62. package/src/plugins/schedule/scheduler.ts +0 -164
  63. package/src/plugins/schedule/types.ts +0 -94
  64. package/src/plugins/schedule/utils.test.ts +0 -163
  65. package/src/plugins/schedule/utils.ts +0 -41
  66. package/tests/integration/client.test.ts +0 -203
  67. package/tests/integration/dev-service.ts +0 -301
  68. package/tests/integration/generated/client.ts +0 -123
  69. package/tests/integration/start-service.ts +0 -21
  70. package/tsconfig.json +0 -27
  71. package/tsup.config.ts +0 -16
  72. package/vitest.config.ts +0 -19
@@ -1,299 +0,0 @@
1
- import { createHash } from "crypto";
2
- import * as ejson from "ejson";
3
- import { Microservice } from "../../core/engine";
4
- import {
5
- HandlerMetadata,
6
- Plugin,
7
- PluginModuleOptionsSchema,
8
- PluginPriority,
9
- } from "../../core/types";
10
- import logger from "../../core/logger";
11
- import { CacheItem, CacheModuleOptions } from "./types";
12
- import {
13
- CacheAdapter,
14
- MemoryCacheAdapter,
15
- } from "./adapter";
16
-
17
- /**
18
- * CachePlugin - 缓存插件
19
- * 负责为标记了 @Cache 装饰器的方法提供缓存功能
20
- *
21
- * @example
22
- * ```ts
23
- * // 使用内存缓存(默认)
24
- * const cachePlugin = new CachePlugin();
25
- *
26
- * // 使用自定义适配器
27
- * const cachePlugin = new CachePlugin(new MemoryCacheAdapter());
28
- *
29
- * // 使用 Redis 适配器
30
- * import { RedisCacheAdapter } from "./adapter";
31
- * const cachePlugin = new CachePlugin(new RedisCacheAdapter({ client: redisClient }));
32
- * ```
33
- */
34
- export class CachePlugin implements Plugin<CacheModuleOptions> {
35
- public readonly name = "cache-plugin";
36
- public readonly priority = PluginPriority.PERFORMANCE; // 性能优化插件,优先级较低
37
-
38
- // 缓存适配器
39
- private adapter: CacheAdapter;
40
-
41
- // 清理定时器
42
- private cleanupTimer: NodeJS.Timeout | null = null;
43
-
44
- // 引擎引用
45
- private engine: Microservice | null = null;
46
-
47
- // 模块配置
48
- private defaultTtl: number = 60000; // 默认1分钟
49
- private cacheEnabled: boolean = true;
50
- private cleanupInterval: number = 60000; // 默认1分钟清理一次
51
-
52
- /**
53
- * 构造函数
54
- * @param adapter 缓存适配器,如果不提供则使用默认的内存缓存适配器
55
- */
56
- constructor(adapter?: CacheAdapter) {
57
- this.adapter = adapter || new MemoryCacheAdapter();
58
- }
59
-
60
- /**
61
- * 声明Module配置Schema
62
- */
63
- getModuleOptionsSchema(): PluginModuleOptionsSchema<CacheModuleOptions> {
64
- return {
65
- _type: {} as CacheModuleOptions,
66
- validate: (options) => {
67
- if (
68
- options.cacheDefaultTtl !== undefined &&
69
- options.cacheDefaultTtl < 0
70
- ) {
71
- return `cacheDefaultTtl must be >= 0`;
72
- }
73
- if (
74
- options.cacheCleanupInterval !== undefined &&
75
- options.cacheCleanupInterval < 0
76
- ) {
77
- return `cacheCleanupInterval must be >= 0`;
78
- }
79
- return true;
80
- },
81
- };
82
- }
83
-
84
- /**
85
- * 引擎初始化前钩子
86
- */
87
- onInit(engine: Microservice): void {
88
- this.engine = engine;
89
- logger.info("CachePlugin initialized cache storage");
90
- }
91
-
92
- /**
93
- * Handler加载后钩子
94
- * 拦截带有 type="cache" 的 Handler,包装原始方法实现缓存逻辑
95
- */
96
- onHandlerLoad(handlers: HandlerMetadata[]): void {
97
- // 筛选出所有type="cache"的Handler元数据
98
- const cacheHandlers = handlers.filter(
99
- (handler) => handler.type === "cache"
100
- );
101
-
102
- logger.info(`Found ${cacheHandlers.length} cache handler(s)`);
103
-
104
- // 遍历缓存Handler,包装方法
105
- // 注意:使用原型上的当前方法(可能已被其他插件包装),而不是 handler.method
106
- for (const handler of cacheHandlers) {
107
- const methodName = handler.methodName;
108
- const moduleClass = handler.module;
109
- const cacheOptions = handler.options || {};
110
-
111
- // 获取模块元数据以读取配置
112
- const moduleMetadata = this.engine
113
- ?.getModules()
114
- .find((m) => m.clazz === moduleClass);
115
-
116
- if (!moduleMetadata) {
117
- logger.warn(
118
- `Module metadata not found for ${moduleClass.name}`
119
- );
120
- continue;
121
- }
122
-
123
- // 获取模块配置
124
- const moduleOptions = moduleMetadata.options as CacheModuleOptions;
125
- const moduleDefaultTtl =
126
- moduleOptions?.cacheDefaultTtl ?? this.defaultTtl;
127
- const moduleCacheEnabled =
128
- moduleOptions?.cacheEnabled ?? this.cacheEnabled;
129
-
130
- // 确定TTL
131
- const ttl = cacheOptions.ttl ?? moduleDefaultTtl;
132
- const enabled = cacheOptions.enabled ?? moduleCacheEnabled;
133
-
134
- if (!enabled) {
135
- logger.info(
136
- `Cache disabled for ${moduleClass.name}.${methodName}`
137
- );
138
- continue;
139
- }
140
-
141
- // 获取模块名
142
- const moduleName = moduleMetadata.name;
143
-
144
- // 使用简单的 wrap API,引擎自动管理包装链
145
- handler.wrap(async (next, instance, ...args) => {
146
- // 生成缓存键
147
- const cacheKey = this.generateCacheKey(
148
- moduleName,
149
- methodName,
150
- cacheOptions.key,
151
- args
152
- );
153
-
154
- // 检查缓存
155
- const cached = await this.adapter.get(cacheKey);
156
- if (cached) {
157
- logger.debug(`Cache hit for ${cacheKey}`);
158
- return cached.value;
159
- }
160
-
161
- // 缓存未命中,调用下一个包装层或原始方法
162
- logger.debug(`Cache miss for ${cacheKey}`);
163
- const result = await next();
164
-
165
- // 存储到缓存
166
- await this.adapter.set(cacheKey, {
167
- value: result,
168
- expiresAt: Date.now() + ttl,
169
- createdAt: Date.now(),
170
- });
171
-
172
- return result;
173
- });
174
-
175
- logger.info(
176
- `Wrapped ${moduleClass.name}.${methodName} with cache (TTL: ${ttl}ms)`
177
- );
178
- }
179
- }
180
-
181
- /**
182
- * 引擎启动前钩子
183
- */
184
- onBeforeStart(engine: Microservice): void {
185
- // 启动缓存清理定时器
186
- const moduleOptions = engine.options as CacheModuleOptions;
187
- const cleanupInterval =
188
- moduleOptions?.cacheCleanupInterval ?? this.cleanupInterval;
189
-
190
- if (cleanupInterval > 0) {
191
- this.cleanupTimer = setInterval(() => {
192
- this.cleanup().catch((error) => {
193
- logger.error("Cache cleanup failed", error);
194
- });
195
- }, cleanupInterval);
196
-
197
- logger.info(
198
- `Started cache cleanup timer (interval: ${cleanupInterval}ms)`
199
- );
200
- }
201
- }
202
-
203
- /**
204
- * 引擎停止时钩子
205
- */
206
- async onDestroy(): Promise<void> {
207
- // 清理定时器
208
- if (this.cleanupTimer) {
209
- clearInterval(this.cleanupTimer);
210
- this.cleanupTimer = null;
211
- }
212
-
213
- // 清空缓存
214
- await this.adapter.clear();
215
- logger.info("Cache storage cleared");
216
- }
217
-
218
- /**
219
- * 生成缓存键
220
- * @param moduleName 模块名
221
- * @param methodName 方法名
222
- * @param keyFunction 可选的 key 函数
223
- * @param args 方法参数
224
- * @returns 缓存键(格式:模块名:方法名:hash)
225
- */
226
- private generateCacheKey(
227
- moduleName: string,
228
- methodName: string,
229
- keyFunction: ((...args: any[]) => any) | undefined,
230
- args: any[]
231
- ): string {
232
- // 如果提供了 key 函数,使用它的返回值;否则使用 args
233
- const keyData = keyFunction ? keyFunction(...args) : args;
234
-
235
- // 使用 ejson 序列化
236
- const serialized = ejson.stringify(keyData);
237
-
238
- // 生成 hash(使用 SHA256)
239
- const hash = createHash("sha256").update(serialized).digest("hex");
240
-
241
- // 返回格式:模块名:方法名:hash
242
- return `${moduleName}:${methodName}:${hash}`;
243
- }
244
-
245
- /**
246
- * 清理过期缓存
247
- */
248
- private async cleanup(): Promise<void> {
249
- // 如果适配器支持 cleanupExpired,使用更高效的方法
250
- if (typeof this.adapter.cleanupExpired === "function") {
251
- const cleaned = await this.adapter.cleanupExpired();
252
- if (cleaned > 0) {
253
- logger.debug(`Cleaned up ${cleaned} expired cache entry(ies)`);
254
- }
255
- } else {
256
- // 降级方案:通过 keys() + get() + delete() 清理
257
- const now = Date.now();
258
- let cleaned = 0;
259
-
260
- const keys = await this.adapter.keys();
261
- for (const key of keys) {
262
- const item = await this.adapter.get(key);
263
- if (!item || item.expiresAt <= now) {
264
- await this.adapter.delete(key);
265
- cleaned++;
266
- }
267
- }
268
-
269
- if (cleaned > 0) {
270
- logger.debug(`Cleaned up ${cleaned} expired cache entry(ies)`);
271
- }
272
- }
273
- }
274
-
275
- /**
276
- * 获取缓存统计信息
277
- */
278
- async getStats(): Promise<{
279
- size: number;
280
- entries: Array<{ key: string; expiresAt: number; createdAt: number }>;
281
- }> {
282
- return await this.adapter.getStats();
283
- }
284
-
285
- /**
286
- * 清空所有缓存
287
- */
288
- async clear(): Promise<void> {
289
- await this.adapter.clear();
290
- logger.info("All cache cleared");
291
- }
292
-
293
- /**
294
- * 删除指定的缓存项
295
- */
296
- async delete(key: string): Promise<boolean> {
297
- return await this.adapter.delete(key);
298
- }
299
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * Cache装饰器配置选项
3
- */
4
- export interface CacheOptions {
5
- /**
6
- * 缓存失效时间(毫秒)
7
- * 默认:60000 (1分钟)
8
- */
9
- ttl?: number;
10
-
11
- /**
12
- * 缓存键生成函数
13
- * 函数签名应该和处理器方法一样,接收相同的参数
14
- * 可以返回任意值,返回值会被 ejson 序列化后进行 hash 生成缓存键
15
- * 如果不提供,将使用入参(args)进行相同的计算
16
- *
17
- * @example
18
- * ```typescript
19
- * @Cache({
20
- * key: (id: string, name: string) => ({ id, name }), // 返回对象
21
- * ttl: 5000
22
- * })
23
- * async getUser(id: string, name: string) {
24
- * return { id, name };
25
- * }
26
- * ```
27
- */
28
- key?: (...args: any[]) => any;
29
-
30
- /**
31
- * 是否启用缓存
32
- * 默认:true
33
- */
34
- enabled?: boolean;
35
- }
36
-
37
- /**
38
- * CachePlugin的Module配置
39
- * 注意:配置直接平铺在 Module options 中
40
- */
41
- export interface CacheModuleOptions {
42
- /**
43
- * 默认缓存失效时间(毫秒)
44
- * 默认:60000 (1分钟)
45
- */
46
- cacheDefaultTtl?: number;
47
-
48
- /**
49
- * 是否启用全局缓存
50
- * 默认:true
51
- */
52
- cacheEnabled?: boolean;
53
-
54
- /**
55
- * 缓存清理间隔(毫秒)
56
- * 默认:60000 (1分钟)
57
- */
58
- cacheCleanupInterval?: number;
59
- }
60
-
61
- /**
62
- * 缓存项数据结构
63
- */
64
- export interface CacheItem<T = any> {
65
- value: T;
66
- expiresAt: number; // 过期时间戳
67
- createdAt: number; // 创建时间戳
68
- }
69
-