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.
@@ -0,0 +1,733 @@
1
+ # 插件系统完整指南
2
+
3
+ ## 目录
4
+
5
+ 1. [概述](#概述)
6
+ 2. [核心概念](#核心概念)
7
+ 3. [插件优先级系统](#插件优先级系统)
8
+ 4. [洋葱圈模型](#洋葱圈模型)
9
+ 5. [插件开发指南](#插件开发指南)
10
+ 6. [默认插件机制](#默认插件机制)
11
+ 7. [最佳实践](#最佳实践)
12
+
13
+ ## 概述
14
+
15
+ 本框架的插件系统采用**优先级驱动的洋葱圈模型**,让用户无需关心插件注册顺序,引擎会自动按优先级排序并构建执行链。
16
+
17
+ ### 核心特性
18
+
19
+ - ✅ **自动优先级排序**:插件声明优先级,引擎自动排序
20
+ - ✅ **洋葱圈执行模型**:支持前置和后置处理逻辑
21
+ - ✅ **用户友好**:用户按任意顺序注册插件即可
22
+ - ✅ **灵活扩展**:插件开发者可以声明自定义优先级
23
+
24
+ ## 核心概念
25
+
26
+ ### 插件接口
27
+
28
+ ```typescript
29
+ export interface Plugin<TModuleOptions = Record<string, any>> {
30
+ // 插件唯一名称
31
+ name: string;
32
+
33
+ // 插件优先级(可选,默认 BUSINESS = 300)
34
+ priority?: PluginPriority | number;
35
+
36
+ // 声明插件的Module配置Schema
37
+ getModuleOptionsSchema?: () => PluginModuleOptionsSchema<TModuleOptions>;
38
+
39
+ // 生命周期钩子
40
+ onInit?: (engine: BaseMicroservice) => void;
41
+ onModuleLoad?: (modules: ModuleMetadata[]) => void;
42
+ onHandlerLoad?: (handlers: HandlerMetadata[]) => void;
43
+ onBeforeStart?: (engine: BaseMicroservice) => void;
44
+ onAfterStart?: (engine: BaseMicroservice) => void;
45
+ onDestroy?: () => void;
46
+ }
47
+ ```
48
+
49
+ ### handler.wrap() API
50
+
51
+ 插件通过 `handler.wrap()` 包装方法,引擎自动管理包装链:
52
+
53
+ ```typescript
54
+ handler.wrap(async (next, instance, ...args) => {
55
+ // 前置逻辑
56
+ const result = await next(); // 调用下一个包装层或原始方法
57
+ // 后置逻辑
58
+ return result;
59
+ });
60
+ ```
61
+
62
+ ## 插件优先级系统
63
+
64
+ ### 设计理念
65
+
66
+ **将用户当成"傻子"**:用户只需要注册插件,不需要关心顺序。引擎会自动按优先级排序,确保插件按正确的顺序执行。
67
+
68
+ ### 优先级枚举
69
+
70
+ ```typescript
71
+ export enum PluginPriority {
72
+ /**
73
+ * 最高优先级:安全相关插件(限流、认证等)
74
+ * 应该最先执行,快速拒绝无效请求
75
+ */
76
+ SECURITY = 100,
77
+
78
+ /**
79
+ * 高优先级:日志、监控等插件
80
+ * 记录所有请求,包括被安全插件拒绝的
81
+ */
82
+ LOGGING = 200,
83
+
84
+ /**
85
+ * 中优先级:业务逻辑插件(数据转换等)
86
+ * 在安全和日志之后执行
87
+ */
88
+ BUSINESS = 300,
89
+
90
+ /**
91
+ * 低优先级:性能优化插件(缓存等)
92
+ * 在业务逻辑之后执行,避免重复计算
93
+ */
94
+ PERFORMANCE = 400,
95
+
96
+ /**
97
+ * 最低优先级:路由插件
98
+ * 必须最后执行,注册HTTP路由
99
+ */
100
+ ROUTE = 1000,
101
+ }
102
+ ```
103
+
104
+ ### 排序规则
105
+
106
+ 1. **按优先级排序**:数值越小,优先级越高(越先执行)
107
+ 2. **相同优先级**:按注册顺序执行(保持稳定排序)
108
+ 3. **默认优先级**:如果不指定,默认为 `PluginPriority.BUSINESS` (300)
109
+
110
+ ### 使用示例
111
+
112
+ #### 用户视角(无需关心顺序)
113
+
114
+ ```typescript
115
+ // 用户可以按任意顺序注册插件
116
+ const engine = new Microservice({
117
+ name: "my-service",
118
+ version: "1.0.0",
119
+ })
120
+ .plugin(new CachePlugin()) // PERFORMANCE = 400(可以放在前面)
121
+ .plugin(new RateLimitPlugin()) // SECURITY = 100(可以放在后面)
122
+ .plugin(new LogPlugin()) // LOGGING = 200(可以放在中间)
123
+ .plugin(new AuthPlugin()); // SECURITY = 100
124
+
125
+ // 引擎自动按优先级排序:
126
+ // 1. RateLimitPlugin (SECURITY = 100,先注册)
127
+ // 2. AuthPlugin (SECURITY = 100,后注册)
128
+ // 3. LogPlugin (LOGGING = 200)
129
+ // 4. CachePlugin (PERFORMANCE = 400)
130
+ // 5. RoutePlugin (ROUTE = 1000,自动注册)
131
+ ```
132
+
133
+ #### 插件开发者视角(声明优先级)
134
+
135
+ ```typescript
136
+ export class RateLimitPlugin implements Plugin {
137
+ public readonly name = "rate-limit-plugin";
138
+ public readonly priority = PluginPriority.SECURITY; // 声明为安全插件
139
+ }
140
+
141
+ export class CachePlugin implements Plugin {
142
+ public readonly name = "cache-plugin";
143
+ public readonly priority = PluginPriority.PERFORMANCE; // 声明为性能优化插件
144
+ }
145
+ ```
146
+
147
+ ### 优先级选择指南
148
+
149
+ | 插件类型 | 优先级 | 说明 | 示例 |
150
+ |---------|--------|------|------|
151
+ | 安全插件 | `SECURITY` (100) | 限流、认证等,快速拒绝无效请求 | RateLimitPlugin, AuthPlugin |
152
+ | 日志插件 | `LOGGING` (200) | 记录所有请求,包括被拒绝的 | LogPlugin, MonitorPlugin |
153
+ | 业务逻辑插件 | `BUSINESS` (300) | 数据转换、业务处理等 | DataTransformPlugin |
154
+ | 性能优化插件 | `PERFORMANCE` (400) | 缓存、压缩等 | CachePlugin |
155
+ | 路由插件 | `ROUTE` (1000) | 注册HTTP路由,必须最后 | RoutePlugin |
156
+
157
+ ## 洋葱圈模型
158
+
159
+ ### 工作原理
160
+
161
+ 插件包装机制采用**洋葱圈模型**(Onion Model),类似于 Koa.js 的中间件机制。每个插件可以包装方法,形成多层嵌套的执行链。
162
+
163
+ ### 执行流程图示
164
+
165
+ ```
166
+ 请求进入
167
+
168
+ ┌─────────────────────────────────────┐
169
+ │ RateLimitPlugin(最外层,SECURITY) │ ← 前置:限流检查
170
+ │ ↓ 调用 next() │
171
+ │ ┌─────────────────────────────────┐ │
172
+ │ │ AuthPlugin(中间层,SECURITY) │ │ ← 前置:认证检查
173
+ │ │ ↓ 调用 next() │ │
174
+ │ │ ┌─────────────────────────────┐ │ │
175
+ │ │ │ CachePlugin(内层,PERFORMANCE)│ │ │ ← 前置:缓存检查
176
+ │ │ │ ↓ 调用 next() │ │ │
177
+ │ │ │ ┌─────────────────────────┐ │ │ │
178
+ │ │ │ │ 原始业务方法(核心) │ │ │ │ ← 执行业务逻辑
179
+ │ │ │ └─────────────────────────┘ │ │ │
180
+ │ │ │ ← 后置:存储缓存 │ │ │
181
+ │ │ └─────────────────────────────┘ │ │
182
+ │ │ ← 后置:认证后处理 │ │
183
+ │ └─────────────────────────────────┘ │
184
+ │ ← 后置:限流后处理 │
185
+ └─────────────────────────────────────┘
186
+
187
+ 响应返回
188
+ ```
189
+
190
+ ### 包装链构建
191
+
192
+ 引擎按照**插件优先级**自动排序,然后**从后往前**应用包装,形成洋葱圈结构:
193
+
194
+ ```typescript
195
+ // 插件注册顺序(用户可以按任意顺序)
196
+ engine
197
+ .plugin(new CachePlugin()) // PERFORMANCE = 400
198
+ .plugin(new RateLimitPlugin()) // SECURITY = 100
199
+ .plugin(new AuthPlugin()); // SECURITY = 100
200
+
201
+ // 引擎自动按优先级排序:
202
+ // 1. RateLimitPlugin (SECURITY = 100)
203
+ // 2. AuthPlugin (SECURITY = 100)
204
+ // 3. CachePlugin (PERFORMANCE = 400)
205
+
206
+ // 包装链构建顺序(从后往前应用):
207
+ // CachePlugin -> AuthPlugin -> RateLimitPlugin -> 原始方法
208
+ ```
209
+
210
+ ### 代码示例
211
+
212
+ ```typescript
213
+ // RateLimitPlugin(最外层)
214
+ handler.wrap(async (next, instance, ...args) => {
215
+ console.log("1. RateLimit: 前置检查");
216
+ if (!checkRateLimit()) {
217
+ throw new Error("Rate limit exceeded");
218
+ }
219
+ const result = await next(); // 调用下一个包装层
220
+ console.log("1. RateLimit: 后置处理");
221
+ return result;
222
+ });
223
+
224
+ // AuthPlugin(中间层)
225
+ handler.wrap(async (next, instance, ...args) => {
226
+ console.log("2. Auth: 前置检查");
227
+ if (!isAuthenticated()) {
228
+ throw new Error("Unauthorized");
229
+ }
230
+ const result = await next(); // 调用下一个包装层
231
+ console.log("2. Auth: 后置处理");
232
+ return result;
233
+ });
234
+
235
+ // CachePlugin(内层)
236
+ handler.wrap(async (next, instance, ...args) => {
237
+ console.log("3. Cache: 前置检查");
238
+ const cached = getCache(...args);
239
+ if (cached) return cached;
240
+
241
+ const result = await next(); // 调用原始方法
242
+ console.log("3. Cache: 后置处理");
243
+ setCache(...args, result);
244
+ return result;
245
+ });
246
+ ```
247
+
248
+ **执行输出**:
249
+ ```
250
+ 1. RateLimit: 前置检查
251
+ 2. Auth: 前置检查
252
+ 3. Cache: 前置检查
253
+ [原始方法执行]
254
+ 3. Cache: 后置处理
255
+ 2. Auth: 后置处理
256
+ 1. RateLimit: 后置处理
257
+ ```
258
+
259
+ ### 关键特性
260
+
261
+ 1. **双向执行**:每个包装器可以在 `next()` 之前和之后执行代码
262
+ 2. **优先级排序**:包装器按照插件优先级自动排序,用户无需关心注册顺序
263
+ 3. **自动管理**:引擎自动构建和执行包装链,插件无需关心实现细节
264
+
265
+ ## 插件开发指南
266
+
267
+ ### 基本结构
268
+
269
+ ```typescript
270
+ import {
271
+ BaseMicroservice,
272
+ HandlerMetadata,
273
+ Plugin,
274
+ PluginModuleOptionsSchema,
275
+ PluginPriority,
276
+ } from "../../core/types";
277
+
278
+ export interface MyModuleOptions {
279
+ myOption?: string;
280
+ }
281
+
282
+ export class MyPlugin implements Plugin<MyModuleOptions> {
283
+ public readonly name = "my-plugin";
284
+ public readonly priority = PluginPriority.BUSINESS; // 声明优先级
285
+
286
+ getModuleOptionsSchema(): PluginModuleOptionsSchema<MyModuleOptions> {
287
+ return {
288
+ _type: {} as MyModuleOptions,
289
+ validate: (options) => {
290
+ if (options.myOption && typeof options.myOption !== "string") {
291
+ return "myOption must be a string";
292
+ }
293
+ return true;
294
+ },
295
+ };
296
+ }
297
+
298
+ onHandlerLoad(handlers: HandlerMetadata[]): void {
299
+ const myHandlers = handlers.filter((h) => h.type === "my-type");
300
+
301
+ for (const handler of myHandlers) {
302
+ // 使用 handler.wrap() API
303
+ handler.wrap(async (next, instance, ...args) => {
304
+ // 前置逻辑
305
+ console.log(`[MyPlugin] Before ${handler.methodName}`);
306
+
307
+ // 调用下一个包装层或原始方法
308
+ const result = await next();
309
+
310
+ // 后置逻辑
311
+ console.log(`[MyPlugin] After ${handler.methodName}`);
312
+
313
+ return result;
314
+ });
315
+ }
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### handler.wrap() API 详解
321
+
322
+ #### 签名
323
+
324
+ ```typescript
325
+ handler.wrap(wrapper: HandlerWrapper): void;
326
+
327
+ type HandlerWrapper = (
328
+ next: () => Promise<any> | any,
329
+ instance: any,
330
+ ...args: any[]
331
+ ) => Promise<any> | any;
332
+ ```
333
+
334
+ #### 参数说明
335
+
336
+ - `next`: 调用下一个包装层或原始方法的函数
337
+ - `instance`: 模块实例(`this`)
338
+ - `args`: 方法参数
339
+
340
+ #### 使用模式
341
+
342
+ **模式1:简单包装**
343
+ ```typescript
344
+ handler.wrap(async (next, instance, ...args) => {
345
+ const result = await next();
346
+ return result;
347
+ });
348
+ ```
349
+
350
+ **模式2:前置和后置逻辑**
351
+ ```typescript
352
+ handler.wrap(async (next, instance, ...args) => {
353
+ // 前置逻辑
354
+ console.log("Before:", args);
355
+
356
+ // 调用下一个包装层
357
+ const result = await next();
358
+
359
+ // 后置逻辑
360
+ console.log("After:", result);
361
+
362
+ return result;
363
+ });
364
+ ```
365
+
366
+ **模式3:条件执行**
367
+ ```typescript
368
+ handler.wrap(async (next, instance, ...args) => {
369
+ if (shouldSkip(...args)) {
370
+ return defaultValue;
371
+ }
372
+ return await next();
373
+ });
374
+ ```
375
+
376
+ **模式4:错误处理**
377
+ ```typescript
378
+ handler.wrap(async (next, instance, ...args) => {
379
+ try {
380
+ return await next();
381
+ } catch (error) {
382
+ // 错误处理逻辑
383
+ console.error("Error:", error);
384
+ throw error;
385
+ }
386
+ });
387
+ ```
388
+
389
+ ### 常见错误
390
+
391
+ #### ❌ 错误1:直接修改原型
392
+
393
+ ```typescript
394
+ // ❌ 错误
395
+ const prototype = handler.module.prototype;
396
+ prototype[handler.methodName] = wrappedMethod;
397
+
398
+ // ✅ 正确
399
+ handler.wrap(async (next, instance, ...args) => {
400
+ return await next();
401
+ });
402
+ ```
403
+
404
+ #### ❌ 错误2:使用 handler.method
405
+
406
+ ```typescript
407
+ // ❌ 错误(handler.method 是原始方法,不是当前方法)
408
+ const result = await handler.method.apply(instance, args);
409
+
410
+ // ✅ 正确(使用 next() 调用当前方法)
411
+ const result = await next();
412
+ ```
413
+
414
+ #### ❌ 错误3:忘记声明优先级
415
+
416
+ ```typescript
417
+ // ❌ 错误(不声明优先级,默认使用 BUSINESS,可能不是最佳选择)
418
+ export class RateLimitPlugin implements Plugin {
419
+ public readonly name = "rate-limit-plugin";
420
+ // 缺少 priority
421
+ }
422
+
423
+ // ✅ 正确(声明合理的优先级)
424
+ export class RateLimitPlugin implements Plugin {
425
+ public readonly name = "rate-limit-plugin";
426
+ public readonly priority = PluginPriority.SECURITY; // 安全插件,高优先级
427
+ }
428
+ ```
429
+
430
+ ## 默认插件机制
431
+
432
+ ### 概述
433
+
434
+ 框架支持将常用插件注册为**默认内置插件**,无需在每次创建引擎时手动注册。`RoutePlugin` 已经作为默认内置插件自动注册。
435
+
436
+ ### 使用方式
437
+
438
+ #### 基本使用(RoutePlugin 自动注册)
439
+
440
+ ```typescript
441
+ import { Microservice } from "nebula-engine";
442
+
443
+ // RoutePlugin 已经自动注册,无需手动添加
444
+ const engine = new Microservice({
445
+ name: "my-service",
446
+ version: "1.0.0",
447
+ }).plugin(new CachePlugin()); // 只需要注册其他插件
448
+
449
+ // 直接使用 @Route 装饰器
450
+ @Module("UserModule", {
451
+ routePrefix: "/api/users",
452
+ })
453
+ class UserService {
454
+ @Route({ method: "GET", path: "/list" })
455
+ async getUsers(ctx: Context) {
456
+ return ctx.json({ users: [] });
457
+ }
458
+ }
459
+ ```
460
+
461
+ #### 禁用默认插件
462
+
463
+ ```typescript
464
+ const engine = new Microservice({
465
+ name: "my-service",
466
+ version: "1.0.0",
467
+ disableDefaultPlugins: true, // 禁用默认插件
468
+ }).plugin(new CustomRoutePlugin()); // 使用自定义路由插件
469
+ ```
470
+
471
+ #### 覆盖默认插件
472
+
473
+ ```typescript
474
+ const engine = new Microservice({
475
+ name: "my-service",
476
+ version: "1.0.0",
477
+ }).plugin(new CustomRoutePlugin()); // 覆盖默认的 RoutePlugin
478
+ ```
479
+
480
+ ### 执行顺序保证
481
+
482
+ 即使 `RoutePlugin` 作为默认插件在构造函数中自动注册,引擎仍然会确保:
483
+
484
+ 1. **按优先级排序**:所有插件(包括默认插件)按优先级自动排序
485
+ 2. **包装插件先执行**:其他插件(如 `CachePlugin`、`AuthPlugin`)的 `onHandlerLoad` 先执行,调用 `handler.wrap()` 构建包装链
486
+ 3. **应用包装链**:引擎将所有包装链应用到原型上
487
+ 4. **RoutePlugin 最后执行**:`RoutePlugin` 的 `onHandlerLoad` 最后执行(优先级 `ROUTE = 1000`),注册路由时调用的是已被包装后的方法
488
+
489
+ **执行流程**:
490
+ ```
491
+ 1. 构造函数自动注册 RoutePlugin(作为默认插件,priority = ROUTE = 1000)
492
+ 2. 手动注册 CachePlugin(priority = PERFORMANCE = 400)
493
+ 3. 引擎启动:
494
+ a. 按优先级排序:CachePlugin (400) → RoutePlugin (1000)
495
+ b. CachePlugin.onHandlerLoad() → 调用 handler.wrap()
496
+ c. 应用包装链到原型
497
+ d. RoutePlugin.onHandlerLoad() → 注册路由(调用已被包装的方法)
498
+ ```
499
+
500
+ ### 注册新的默认插件
501
+
502
+ ```typescript
503
+ import { Microservice } from "nebula-engine";
504
+ import { MyPlugin } from "./my-plugin";
505
+
506
+ // 注册为默认插件
507
+ Microservice.registerDefaultPlugin(new MyPlugin());
508
+
509
+ // 之后创建的引擎实例都会自动包含 MyPlugin
510
+ const engine = new Microservice({
511
+ name: "my-service",
512
+ version: "1.0.0",
513
+ });
514
+ ```
515
+
516
+ ## 最佳实践
517
+
518
+ ### 1. 优先级选择
519
+
520
+ #### 安全插件 → `PluginPriority.SECURITY` (100)
521
+
522
+ ```typescript
523
+ export class RateLimitPlugin implements Plugin {
524
+ public readonly priority = PluginPriority.SECURITY;
525
+ }
526
+
527
+ export class AuthPlugin implements Plugin {
528
+ public readonly priority = PluginPriority.SECURITY;
529
+ }
530
+ ```
531
+
532
+ **原因**:安全插件应该最先执行,快速拒绝无效请求,避免消耗后续资源。
533
+
534
+ #### 日志插件 → `PluginPriority.LOGGING` (200)
535
+
536
+ ```typescript
537
+ export class LogPlugin implements Plugin {
538
+ public readonly priority = PluginPriority.LOGGING;
539
+ }
540
+ ```
541
+
542
+ **原因**:日志插件应该记录所有请求,包括被安全插件拒绝的请求。
543
+
544
+ #### 业务逻辑插件 → `PluginPriority.BUSINESS` (300,默认)
545
+
546
+ ```typescript
547
+ export class DataTransformPlugin implements Plugin {
548
+ // 不指定 priority,默认使用 BUSINESS (300)
549
+ }
550
+ ```
551
+
552
+ **原因**:业务逻辑插件在安全和日志之后执行。
553
+
554
+ #### 性能优化插件 → `PluginPriority.PERFORMANCE` (400)
555
+
556
+ ```typescript
557
+ export class CachePlugin implements Plugin {
558
+ public readonly priority = PluginPriority.PERFORMANCE;
559
+ }
560
+ ```
561
+
562
+ **原因**:性能优化插件应该在内层执行,避免外层插件重复执行。
563
+
564
+ #### 路由插件 → `PluginPriority.ROUTE` (1000)
565
+
566
+ ```typescript
567
+ export class RoutePlugin implements Plugin {
568
+ public readonly priority = PluginPriority.ROUTE;
569
+ }
570
+ ```
571
+
572
+ **原因**:路由插件必须最后执行,注册HTTP路由。
573
+
574
+ ### 2. 插件实现原则
575
+
576
+ #### ✅ 总是使用 `handler.wrap()`
577
+
578
+ ```typescript
579
+ // ✅ 正确
580
+ handler.wrap(async (next, instance, ...args) => {
581
+ return await next();
582
+ });
583
+
584
+ // ❌ 错误
585
+ const prototype = handler.module.prototype;
586
+ prototype[handler.methodName] = wrappedMethod;
587
+ ```
588
+
589
+ #### ✅ 使用 `next()` 调用
590
+
591
+ ```typescript
592
+ // ✅ 正确
593
+ const result = await next();
594
+
595
+ // ❌ 错误
596
+ const result = await handler.method.apply(instance, args);
597
+ ```
598
+
599
+ #### ✅ 声明合理的优先级
600
+
601
+ ```typescript
602
+ // ✅ 正确
603
+ export class RateLimitPlugin implements Plugin {
604
+ public readonly priority = PluginPriority.SECURITY;
605
+ }
606
+
607
+ // ❌ 错误(不声明优先级)
608
+ export class RateLimitPlugin implements Plugin {
609
+ // 缺少 priority
610
+ }
611
+ ```
612
+
613
+ ### 3. 典型场景示例
614
+
615
+ #### 场景1:限流 + 缓存
616
+
617
+ ```typescript
618
+ // 限流插件(外层,SECURITY = 100)
619
+ handler.wrap(async (next, instance, ...args) => {
620
+ if (!checkRateLimit()) {
621
+ throw new Error("Rate limit exceeded");
622
+ }
623
+ return await next();
624
+ });
625
+
626
+ // 缓存插件(内层,PERFORMANCE = 400)
627
+ handler.wrap(async (next, instance, ...args) => {
628
+ const cached = getCache(...args);
629
+ if (cached) return cached;
630
+
631
+ const result = await next();
632
+ setCache(...args, result);
633
+ return result;
634
+ });
635
+ ```
636
+
637
+ **执行顺序**:
638
+ 1. 限流检查(外层)
639
+ 2. 缓存检查(内层)
640
+ 3. 原始方法执行
641
+ 4. 缓存存储(内层)
642
+ 5. 限流后置处理(外层)
643
+
644
+ **优势**:缓存命中时不会进行限流检查,提高性能。
645
+
646
+ #### 场景2:认证 + 日志
647
+
648
+ ```typescript
649
+ // 日志插件(外层,LOGGING = 200)
650
+ handler.wrap(async (next, instance, ...args) => {
651
+ const start = Date.now();
652
+ console.log("Request started");
653
+
654
+ try {
655
+ const result = await next();
656
+ console.log(`Request completed in ${Date.now() - start}ms`);
657
+ return result;
658
+ } catch (error) {
659
+ console.error(`Request failed: ${error}`);
660
+ throw error;
661
+ }
662
+ });
663
+
664
+ // 认证插件(内层,SECURITY = 100)
665
+ handler.wrap(async (next, instance, ...args) => {
666
+ if (!isAuthenticated()) {
667
+ throw new Error("Unauthorized");
668
+ }
669
+ return await next();
670
+ });
671
+ ```
672
+
673
+ **执行顺序**:
674
+ 1. 日志记录开始(外层)
675
+ 2. 认证检查(内层)
676
+ 3. 如果未认证,返回 401,日志记录失败 ✅
677
+ 4. 如果已认证,执行原始方法,日志记录成功
678
+
679
+ **优势**:日志插件在外层,可以记录所有请求(包括认证失败的)。
680
+
681
+ ### 4. 测试建议
682
+
683
+ #### 测试插件配合
684
+
685
+ ```typescript
686
+ describe("插件配合", () => {
687
+ it("应该支持多个插件链式包装", async () => {
688
+ const engine = new Microservice({
689
+ name: "test-service",
690
+ version: "1.0.0",
691
+ })
692
+ .plugin(new RateLimitPlugin())
693
+ .plugin(new CachePlugin());
694
+
695
+ // 测试逻辑...
696
+ });
697
+ });
698
+ ```
699
+
700
+ #### 测试优先级排序
701
+
702
+ ```typescript
703
+ it("应该按优先级自动排序", () => {
704
+ const engine = new Microservice({
705
+ name: "test-service",
706
+ version: "1.0.0",
707
+ })
708
+ .plugin(new CachePlugin()) // PERFORMANCE = 400
709
+ .plugin(new RateLimitPlugin()); // SECURITY = 100
710
+
711
+ // 验证执行顺序:RateLimitPlugin → CachePlugin
712
+ });
713
+ ```
714
+
715
+ ## 总结
716
+
717
+ ### 核心要点
718
+
719
+ 1. **优先级系统**:插件声明优先级,引擎自动排序,用户无需关心注册顺序
720
+ 2. **洋葱圈模型**:支持前置和后置处理逻辑,执行顺序清晰可预测
721
+ 3. **handler.wrap() API**:简单的包装API,引擎自动管理包装链
722
+ 4. **默认插件**:常用插件自动注册,简化使用
723
+
724
+ ### 关键原则
725
+
726
+ - ✅ 使用 `handler.wrap()` API 包装方法
727
+ - ✅ 声明合理的优先级
728
+ - ✅ 使用 `next()` 调用下一个包装层
729
+ - ✅ 不要直接修改原型
730
+ - ✅ 不要使用 `handler.method`
731
+
732
+ 遵循这些原则,你的插件就能与其他插件正确配合,并且用户无需关心注册顺序。
733
+