@dangao/bun-server 1.7.0 → 1.8.0

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 (144) hide show
  1. package/README.md +196 -19
  2. package/dist/cache/cache-module.d.ts +18 -0
  3. package/dist/cache/cache-module.d.ts.map +1 -1
  4. package/dist/cache/index.d.ts +3 -1
  5. package/dist/cache/index.d.ts.map +1 -1
  6. package/dist/cache/interceptors.d.ts +41 -0
  7. package/dist/cache/interceptors.d.ts.map +1 -0
  8. package/dist/cache/service-proxy.d.ts +62 -0
  9. package/dist/cache/service-proxy.d.ts.map +1 -0
  10. package/dist/controller/controller.d.ts +8 -0
  11. package/dist/controller/controller.d.ts.map +1 -1
  12. package/dist/core/application.d.ts +5 -0
  13. package/dist/core/application.d.ts.map +1 -1
  14. package/dist/di/container.d.ts +18 -1
  15. package/dist/di/container.d.ts.map +1 -1
  16. package/dist/di/decorators.d.ts +37 -0
  17. package/dist/di/decorators.d.ts.map +1 -1
  18. package/dist/di/index.d.ts +2 -2
  19. package/dist/di/index.d.ts.map +1 -1
  20. package/dist/di/module-registry.d.ts +17 -0
  21. package/dist/di/module-registry.d.ts.map +1 -1
  22. package/dist/di/types.d.ts +22 -0
  23. package/dist/di/types.d.ts.map +1 -1
  24. package/dist/events/decorators.d.ts +52 -0
  25. package/dist/events/decorators.d.ts.map +1 -0
  26. package/dist/events/event-module.d.ts +97 -0
  27. package/dist/events/event-module.d.ts.map +1 -0
  28. package/dist/events/index.d.ts +5 -0
  29. package/dist/events/index.d.ts.map +1 -0
  30. package/dist/events/service.d.ts +76 -0
  31. package/dist/events/service.d.ts.map +1 -0
  32. package/dist/events/types.d.ts +184 -0
  33. package/dist/events/types.d.ts.map +1 -0
  34. package/dist/index.d.ts +6 -4
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +4641 -2840
  37. package/dist/security/filter.d.ts +23 -0
  38. package/dist/security/filter.d.ts.map +1 -1
  39. package/dist/security/guards/builtin/auth-guard.d.ts +44 -0
  40. package/dist/security/guards/builtin/auth-guard.d.ts.map +1 -0
  41. package/dist/security/guards/builtin/index.d.ts +3 -0
  42. package/dist/security/guards/builtin/index.d.ts.map +1 -0
  43. package/dist/security/guards/builtin/roles-guard.d.ts +66 -0
  44. package/dist/security/guards/builtin/roles-guard.d.ts.map +1 -0
  45. package/dist/security/guards/decorators.d.ts +50 -0
  46. package/dist/security/guards/decorators.d.ts.map +1 -0
  47. package/dist/security/guards/execution-context.d.ts +56 -0
  48. package/dist/security/guards/execution-context.d.ts.map +1 -0
  49. package/dist/security/guards/guard-registry.d.ts +67 -0
  50. package/dist/security/guards/guard-registry.d.ts.map +1 -0
  51. package/dist/security/guards/index.d.ts +7 -0
  52. package/dist/security/guards/index.d.ts.map +1 -0
  53. package/dist/security/guards/reflector.d.ts +57 -0
  54. package/dist/security/guards/reflector.d.ts.map +1 -0
  55. package/dist/security/guards/types.d.ts +126 -0
  56. package/dist/security/guards/types.d.ts.map +1 -0
  57. package/dist/security/index.d.ts +1 -0
  58. package/dist/security/index.d.ts.map +1 -1
  59. package/dist/security/security-module.d.ts +20 -0
  60. package/dist/security/security-module.d.ts.map +1 -1
  61. package/dist/validation/class-validator.d.ts +108 -0
  62. package/dist/validation/class-validator.d.ts.map +1 -0
  63. package/dist/validation/custom-validator.d.ts +130 -0
  64. package/dist/validation/custom-validator.d.ts.map +1 -0
  65. package/dist/validation/errors.d.ts +22 -2
  66. package/dist/validation/errors.d.ts.map +1 -1
  67. package/dist/validation/index.d.ts +7 -1
  68. package/dist/validation/index.d.ts.map +1 -1
  69. package/dist/validation/rules/array.d.ts +33 -0
  70. package/dist/validation/rules/array.d.ts.map +1 -0
  71. package/dist/validation/rules/common.d.ts +90 -0
  72. package/dist/validation/rules/common.d.ts.map +1 -0
  73. package/dist/validation/rules/conditional.d.ts +30 -0
  74. package/dist/validation/rules/conditional.d.ts.map +1 -0
  75. package/dist/validation/rules/index.d.ts +5 -0
  76. package/dist/validation/rules/index.d.ts.map +1 -0
  77. package/dist/validation/rules/object.d.ts +30 -0
  78. package/dist/validation/rules/object.d.ts.map +1 -0
  79. package/dist/validation/types.d.ts +52 -1
  80. package/dist/validation/types.d.ts.map +1 -1
  81. package/docs/events.md +494 -0
  82. package/docs/guards.md +376 -0
  83. package/docs/guide.md +309 -1
  84. package/docs/request-lifecycle.md +444 -0
  85. package/docs/symbol-interface-pattern.md +431 -0
  86. package/docs/validation.md +407 -0
  87. package/docs/zh/events.md +494 -0
  88. package/docs/zh/guards.md +376 -0
  89. package/docs/zh/guide.md +309 -1
  90. package/docs/zh/request-lifecycle.md +444 -0
  91. package/docs/zh/symbol-interface-pattern.md +431 -0
  92. package/docs/zh/validation.md +407 -0
  93. package/package.json +1 -1
  94. package/src/cache/cache-module.ts +37 -0
  95. package/src/cache/index.ts +16 -1
  96. package/src/cache/interceptors.ts +295 -0
  97. package/src/cache/service-proxy.ts +219 -0
  98. package/src/controller/controller.ts +30 -6
  99. package/src/core/application.ts +25 -1
  100. package/src/di/container.ts +57 -7
  101. package/src/di/decorators.ts +46 -0
  102. package/src/di/index.ts +17 -2
  103. package/src/di/module-registry.ts +39 -0
  104. package/src/di/types.ts +29 -0
  105. package/src/events/decorators.ts +103 -0
  106. package/src/events/event-module.ts +272 -0
  107. package/src/events/index.ts +32 -0
  108. package/src/events/service.ts +352 -0
  109. package/src/events/types.ts +223 -0
  110. package/src/index.ts +140 -1
  111. package/src/security/filter.ts +88 -8
  112. package/src/security/guards/builtin/auth-guard.ts +68 -0
  113. package/src/security/guards/builtin/index.ts +3 -0
  114. package/src/security/guards/builtin/roles-guard.ts +165 -0
  115. package/src/security/guards/decorators.ts +124 -0
  116. package/src/security/guards/execution-context.ts +152 -0
  117. package/src/security/guards/guard-registry.ts +164 -0
  118. package/src/security/guards/index.ts +7 -0
  119. package/src/security/guards/reflector.ts +99 -0
  120. package/src/security/guards/types.ts +144 -0
  121. package/src/security/index.ts +1 -0
  122. package/src/security/security-module.ts +72 -2
  123. package/src/validation/class-validator.ts +322 -0
  124. package/src/validation/custom-validator.ts +289 -0
  125. package/src/validation/errors.ts +50 -2
  126. package/src/validation/index.ts +103 -1
  127. package/src/validation/rules/array.ts +118 -0
  128. package/src/validation/rules/common.ts +286 -0
  129. package/src/validation/rules/conditional.ts +52 -0
  130. package/src/validation/rules/index.ts +51 -0
  131. package/src/validation/rules/object.ts +86 -0
  132. package/src/validation/types.ts +61 -1
  133. package/tests/cache/cache-decorators.test.ts +284 -0
  134. package/tests/controller/path-combination.test.ts +353 -0
  135. package/tests/di/global-module.test.ts +487 -0
  136. package/tests/events/event-decorators.test.ts +173 -0
  137. package/tests/events/event-emitter.test.ts +373 -0
  138. package/tests/events/event-module.test.ts +373 -0
  139. package/tests/security/guards/guards-integration.test.ts +371 -0
  140. package/tests/security/guards/guards.test.ts +775 -0
  141. package/tests/security/security-module.test.ts +2 -2
  142. package/tests/validation/class-validator.test.ts +349 -0
  143. package/tests/validation/custom-validator.test.ts +335 -0
  144. package/tests/validation/rules.test.ts +543 -0
@@ -0,0 +1,152 @@
1
+ import 'reflect-metadata';
2
+ import type { ServerWebSocket } from 'bun';
3
+ import type { Context } from '../../core/context';
4
+ import type { ResponseBuilder } from '../../request/response';
5
+ import type { Constructor } from '../../core/types';
6
+ import type {
7
+ ExecutionContext,
8
+ HttpArgumentsHost,
9
+ WsArgumentsHost,
10
+ } from './types';
11
+
12
+ /**
13
+ * HTTP 参数主机实现
14
+ */
15
+ class HttpArgumentsHostImpl implements HttpArgumentsHost {
16
+ public constructor(
17
+ private readonly ctx: Context,
18
+ private readonly responseBuilder?: ResponseBuilder,
19
+ ) {}
20
+
21
+ /**
22
+ * 获取请求上下文
23
+ */
24
+ public getRequest(): Context {
25
+ return this.ctx;
26
+ }
27
+
28
+ /**
29
+ * 获取响应构建器
30
+ */
31
+ public getResponse(): ResponseBuilder | undefined {
32
+ return this.responseBuilder;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * WebSocket 参数主机实现
38
+ */
39
+ class WsArgumentsHostImpl implements WsArgumentsHost {
40
+ public constructor(
41
+ private readonly client: ServerWebSocket<unknown>,
42
+ private readonly data: unknown,
43
+ ) {}
44
+
45
+ /**
46
+ * 获取 WebSocket 客户端
47
+ */
48
+ public getClient(): ServerWebSocket<unknown> {
49
+ return this.client;
50
+ }
51
+
52
+ /**
53
+ * 获取消息数据
54
+ */
55
+ public getData(): unknown {
56
+ return this.data;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * 执行上下文实现
62
+ */
63
+ export class ExecutionContextImpl implements ExecutionContext {
64
+ private readonly httpHost: HttpArgumentsHost;
65
+ private wsHost?: WsArgumentsHost;
66
+
67
+ public constructor(
68
+ private readonly ctx: Context,
69
+ private readonly controllerClass: Constructor<unknown>,
70
+ private readonly methodName: string,
71
+ private readonly handler: Function,
72
+ private readonly args: unknown[] = [],
73
+ responseBuilder?: ResponseBuilder,
74
+ ) {
75
+ this.httpHost = new HttpArgumentsHostImpl(ctx, responseBuilder);
76
+ }
77
+
78
+ /**
79
+ * 设置 WebSocket 上下文
80
+ * @param client - WebSocket 客户端
81
+ * @param data - 消息数据
82
+ */
83
+ public setWsContext(client: ServerWebSocket<unknown>, data: unknown): void {
84
+ this.wsHost = new WsArgumentsHostImpl(client, data);
85
+ }
86
+
87
+ /**
88
+ * 获取 HTTP 上下文
89
+ */
90
+ public switchToHttp(): HttpArgumentsHost {
91
+ return this.httpHost;
92
+ }
93
+
94
+ /**
95
+ * 获取 WebSocket 上下文
96
+ */
97
+ public switchToWs(): WsArgumentsHost {
98
+ if (!this.wsHost) {
99
+ throw new Error('WebSocket context is not available');
100
+ }
101
+ return this.wsHost;
102
+ }
103
+
104
+ /**
105
+ * 获取当前处理的控制器类
106
+ */
107
+ public getClass(): Constructor<unknown> {
108
+ return this.controllerClass;
109
+ }
110
+
111
+ /**
112
+ * 获取当前处理的方法
113
+ */
114
+ public getHandler(): Function {
115
+ return this.handler;
116
+ }
117
+
118
+ /**
119
+ * 获取方法名
120
+ */
121
+ public getMethodName(): string {
122
+ return this.methodName;
123
+ }
124
+
125
+ /**
126
+ * 获取方法或类的元数据
127
+ * @param key - 元数据键
128
+ * @returns 元数据值
129
+ */
130
+ public getMetadata<T>(key: string | symbol): T | undefined {
131
+ // 先尝试从方法获取
132
+ const methodMetadata = Reflect.getMetadata(
133
+ key,
134
+ this.controllerClass.prototype,
135
+ this.methodName,
136
+ );
137
+ if (methodMetadata !== undefined) {
138
+ return methodMetadata as T;
139
+ }
140
+
141
+ // 如果方法没有,尝试从类获取
142
+ return Reflect.getMetadata(key, this.controllerClass) as T | undefined;
143
+ }
144
+
145
+ /**
146
+ * 获取请求参数
147
+ */
148
+ public getArgs(): unknown[] {
149
+ return this.args;
150
+ }
151
+ }
152
+
@@ -0,0 +1,164 @@
1
+ import type { Container } from '../../di/container';
2
+ import type { Constructor } from '../../core/types';
3
+ import type {
4
+ CanActivate,
5
+ GuardType,
6
+ ExecutionContext,
7
+ } from './types';
8
+ import { getGuardsMetadata } from './decorators';
9
+ import { ForbiddenException } from '../../error/http-exception';
10
+ import { ErrorCode } from '../../error/error-codes';
11
+
12
+ /**
13
+ * 守卫注册表
14
+ * 管理全局守卫和执行守卫链
15
+ */
16
+ export class GuardRegistry {
17
+ /**
18
+ * 全局守卫列表
19
+ */
20
+ private globalGuards: GuardType[] = [];
21
+
22
+ /**
23
+ * 守卫实例缓存(用于缓存从 DI 容器解析的守卫实例)
24
+ */
25
+ private guardInstances = new Map<Constructor<CanActivate>, CanActivate>();
26
+
27
+ /**
28
+ * 注册全局守卫
29
+ * @param guards - 守卫类或实例
30
+ */
31
+ public addGlobalGuards(...guards: GuardType[]): void {
32
+ this.globalGuards.push(...guards);
33
+ }
34
+
35
+ /**
36
+ * 获取全局守卫
37
+ * @returns 全局守卫列表
38
+ */
39
+ public getGlobalGuards(): GuardType[] {
40
+ return [...this.globalGuards];
41
+ }
42
+
43
+ /**
44
+ * 清除所有全局守卫
45
+ */
46
+ public clearGlobalGuards(): void {
47
+ this.globalGuards = [];
48
+ this.guardInstances.clear();
49
+ }
50
+
51
+ /**
52
+ * 解析守卫实例
53
+ * @param guard - 守卫类或实例
54
+ * @param container - DI 容器
55
+ * @returns 守卫实例
56
+ */
57
+ private resolveGuard(guard: GuardType, container: Container): CanActivate {
58
+ // 如果已经是实例,直接返回
59
+ if (typeof guard !== 'function') {
60
+ return guard;
61
+ }
62
+
63
+ // 检查缓存
64
+ const cached = this.guardInstances.get(guard as Constructor<CanActivate>);
65
+ if (cached) {
66
+ return cached;
67
+ }
68
+
69
+ // 尝试从 DI 容器解析
70
+ try {
71
+ if (container.isRegistered(guard)) {
72
+ const instance = container.resolve<CanActivate>(guard);
73
+ this.guardInstances.set(guard as Constructor<CanActivate>, instance);
74
+ return instance;
75
+ }
76
+ } catch {
77
+ // 如果容器解析失败,继续尝试手动实例化
78
+ }
79
+
80
+ // 手动实例化(不支持依赖注入)
81
+ const GuardClass = guard as Constructor<CanActivate>;
82
+ const instance = new GuardClass();
83
+ this.guardInstances.set(guard as Constructor<CanActivate>, instance);
84
+ return instance;
85
+ }
86
+
87
+ /**
88
+ * 获取控制器级别的守卫
89
+ * @param controllerClass - 控制器类
90
+ * @returns 守卫列表
91
+ */
92
+ public getControllerGuards(controllerClass: Constructor<unknown>): GuardType[] {
93
+ return getGuardsMetadata(controllerClass);
94
+ }
95
+
96
+ /**
97
+ * 获取方法级别的守卫
98
+ * @param controllerClass - 控制器类
99
+ * @param methodName - 方法名
100
+ * @returns 守卫列表
101
+ */
102
+ public getMethodGuards(
103
+ controllerClass: Constructor<unknown>,
104
+ methodName: string,
105
+ ): GuardType[] {
106
+ return getGuardsMetadata(controllerClass.prototype, methodName);
107
+ }
108
+
109
+ /**
110
+ * 收集所有守卫(全局 + 控制器 + 方法)
111
+ * @param controllerClass - 控制器类
112
+ * @param methodName - 方法名
113
+ * @returns 按顺序排列的守卫列表
114
+ */
115
+ public collectGuards(
116
+ controllerClass: Constructor<unknown>,
117
+ methodName: string,
118
+ ): GuardType[] {
119
+ const globalGuards = this.getGlobalGuards();
120
+ const controllerGuards = this.getControllerGuards(controllerClass);
121
+ const methodGuards = this.getMethodGuards(controllerClass, methodName);
122
+
123
+ // 执行顺序:全局 -> 控制器 -> 方法
124
+ return [...globalGuards, ...controllerGuards, ...methodGuards];
125
+ }
126
+
127
+ /**
128
+ * 执行守卫链
129
+ * @param context - 执行上下文
130
+ * @param container - DI 容器
131
+ * @returns 是否允许访问
132
+ * @throws ForbiddenException 如果守卫拒绝访问
133
+ */
134
+ public async executeGuards(
135
+ context: ExecutionContext,
136
+ container: Container,
137
+ ): Promise<boolean> {
138
+ const controllerClass = context.getClass();
139
+ const methodName = context.getMethodName();
140
+ const guards = this.collectGuards(controllerClass, methodName);
141
+
142
+ if (guards.length === 0) {
143
+ return true;
144
+ }
145
+
146
+ for (const guard of guards) {
147
+ const guardInstance = this.resolveGuard(guard, container);
148
+ const result = await guardInstance.canActivate(context);
149
+
150
+ if (!result) {
151
+ // 获取守卫名称用于错误消息
152
+ const guardName = typeof guard === 'function' ? guard.name : guard.constructor.name;
153
+ throw new ForbiddenException(
154
+ `Access denied by guard: ${guardName}`,
155
+ { guard: guardName },
156
+ ErrorCode.AUTH_INSUFFICIENT_PERMISSIONS,
157
+ );
158
+ }
159
+ }
160
+
161
+ return true;
162
+ }
163
+ }
164
+
@@ -0,0 +1,7 @@
1
+ export * from './types';
2
+ export * from './decorators';
3
+ export * from './execution-context';
4
+ export * from './guard-registry';
5
+ export * from './reflector';
6
+ export * from './builtin';
7
+
@@ -0,0 +1,99 @@
1
+ import 'reflect-metadata';
2
+ import type { Constructor } from '../../core/types';
3
+
4
+ /**
5
+ * Reflector 工具类
6
+ * 用于获取类和方法的元数据
7
+ */
8
+ export class Reflector {
9
+ /**
10
+ * 获取元数据
11
+ * 优先从方法获取,如果方法没有则从类获取
12
+ *
13
+ * @param metadataKey - 元数据键
14
+ * @param target - 目标类或方法
15
+ * @returns 元数据值
16
+ */
17
+ public get<T>(
18
+ metadataKey: string | symbol,
19
+ target: Function | Object,
20
+ ): T | undefined {
21
+ return Reflect.getMetadata(metadataKey, target) as T | undefined;
22
+ }
23
+
24
+ /**
25
+ * 从类获取元数据
26
+ * @param metadataKey - 元数据键
27
+ * @param target - 目标类
28
+ * @returns 元数据值
29
+ */
30
+ public getFromClass<T>(
31
+ metadataKey: string | symbol,
32
+ target: Constructor<unknown>,
33
+ ): T | undefined {
34
+ return Reflect.getMetadata(metadataKey, target) as T | undefined;
35
+ }
36
+
37
+ /**
38
+ * 从方法获取元数据
39
+ * @param metadataKey - 元数据键
40
+ * @param target - 目标类原型
41
+ * @param propertyKey - 方法名
42
+ * @returns 元数据值
43
+ */
44
+ public getFromMethod<T>(
45
+ metadataKey: string | symbol,
46
+ target: Object,
47
+ propertyKey: string | symbol,
48
+ ): T | undefined {
49
+ return Reflect.getMetadata(metadataKey, target, propertyKey) as T | undefined;
50
+ }
51
+
52
+ /**
53
+ * 获取元数据(支持合并类和方法的元数据)
54
+ * 对于数组类型,将类和方法的元数据合并
55
+ *
56
+ * @param metadataKey - 元数据键
57
+ * @param target - 目标类
58
+ * @param propertyKey - 方法名
59
+ * @returns 合并后的元数据值
60
+ */
61
+ public getAllAndMerge<T extends unknown[]>(
62
+ metadataKey: string | symbol,
63
+ target: Constructor<unknown>,
64
+ propertyKey: string | symbol,
65
+ ): T {
66
+ const classMetadata = this.getFromClass<T>(metadataKey, target) || ([] as unknown as T);
67
+ const methodMetadata = this.getFromMethod<T>(metadataKey, target.prototype, propertyKey) || ([] as unknown as T);
68
+
69
+ // 合并数组
70
+ return [...classMetadata, ...methodMetadata] as T;
71
+ }
72
+
73
+ /**
74
+ * 获取元数据(方法优先)
75
+ * 如果方法有元数据则返回方法的,否则返回类的
76
+ *
77
+ * @param metadataKey - 元数据键
78
+ * @param target - 目标类
79
+ * @param propertyKey - 方法名
80
+ * @returns 元数据值
81
+ */
82
+ public getAllAndOverride<T>(
83
+ metadataKey: string | symbol,
84
+ target: Constructor<unknown>,
85
+ propertyKey: string | symbol,
86
+ ): T | undefined {
87
+ const methodMetadata = this.getFromMethod<T>(metadataKey, target.prototype, propertyKey);
88
+ if (methodMetadata !== undefined) {
89
+ return methodMetadata;
90
+ }
91
+ return this.getFromClass<T>(metadataKey, target);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Reflector Token
97
+ */
98
+ export const REFLECTOR_TOKEN = Symbol('@dangao/bun-server:reflector');
99
+
@@ -0,0 +1,144 @@
1
+ import type { Context } from '../../core/context';
2
+ import type { ResponseBuilder } from '../../request/response';
3
+ import type { Constructor } from '../../core/types';
4
+ import type { ServerWebSocket } from 'bun';
5
+
6
+ /**
7
+ * 守卫接口
8
+ * 守卫用于决定请求是否可以继续执行
9
+ */
10
+ export interface CanActivate {
11
+ /**
12
+ * 判断是否允许访问
13
+ * @param context - 执行上下文
14
+ * @returns 是否允许访问,可以是同步或异步的布尔值
15
+ */
16
+ canActivate(context: ExecutionContext): boolean | Promise<boolean>;
17
+ }
18
+
19
+ /**
20
+ * HTTP 参数主机接口
21
+ * 提供 HTTP 请求相关的上下文信息
22
+ */
23
+ export interface HttpArgumentsHost {
24
+ /**
25
+ * 获取请求上下文
26
+ * @returns Context 对象
27
+ */
28
+ getRequest(): Context;
29
+
30
+ /**
31
+ * 获取响应构建器
32
+ * @returns ResponseBuilder 对象(可能为 undefined)
33
+ */
34
+ getResponse(): ResponseBuilder | undefined;
35
+ }
36
+
37
+ /**
38
+ * WebSocket 参数主机接口
39
+ * 提供 WebSocket 连接相关的上下文信息
40
+ */
41
+ export interface WsArgumentsHost {
42
+ /**
43
+ * 获取 WebSocket 客户端
44
+ * @returns WebSocket 连接对象
45
+ */
46
+ getClient(): ServerWebSocket<unknown>;
47
+
48
+ /**
49
+ * 获取消息数据
50
+ * @returns 消息数据
51
+ */
52
+ getData(): unknown;
53
+ }
54
+
55
+ /**
56
+ * 执行上下文接口
57
+ * 提供请求处理过程中的上下文信息
58
+ */
59
+ export interface ExecutionContext {
60
+ /**
61
+ * 获取 HTTP 上下文
62
+ * @returns HTTP 参数主机
63
+ */
64
+ switchToHttp(): HttpArgumentsHost;
65
+
66
+ /**
67
+ * 获取 WebSocket 上下文
68
+ * @returns WebSocket 参数主机
69
+ */
70
+ switchToWs(): WsArgumentsHost;
71
+
72
+ /**
73
+ * 获取当前处理的控制器类
74
+ * @returns 控制器类构造函数
75
+ */
76
+ getClass(): Constructor<unknown>;
77
+
78
+ /**
79
+ * 获取当前处理的方法
80
+ * @returns 方法函数
81
+ */
82
+ getHandler(): Function;
83
+
84
+ /**
85
+ * 获取方法名
86
+ * @returns 方法名字符串
87
+ */
88
+ getMethodName(): string;
89
+
90
+ /**
91
+ * 获取方法或类的元数据
92
+ * @param key - 元数据键
93
+ * @returns 元数据值,如果不存在则返回 undefined
94
+ */
95
+ getMetadata<T>(key: string | symbol): T | undefined;
96
+
97
+ /**
98
+ * 获取请求参数
99
+ * @returns 请求参数数组
100
+ */
101
+ getArgs(): unknown[];
102
+ }
103
+
104
+ /**
105
+ * 守卫类型:可以是守卫类构造函数或守卫实例
106
+ */
107
+ export type GuardType = Constructor<CanActivate> | CanActivate;
108
+
109
+ /**
110
+ * 守卫元数据
111
+ */
112
+ export interface GuardMetadata {
113
+ /**
114
+ * 守卫列表
115
+ */
116
+ guards: GuardType[];
117
+ }
118
+
119
+ /**
120
+ * 守卫配置选项
121
+ */
122
+ export interface GuardOptions {
123
+ /**
124
+ * 是否跳过全局守卫
125
+ * @default false
126
+ */
127
+ skipGlobalGuards?: boolean;
128
+ }
129
+
130
+ /**
131
+ * 守卫元数据键
132
+ */
133
+ export const GUARDS_METADATA_KEY = Symbol('@dangao/bun-server:guards');
134
+
135
+ /**
136
+ * 守卫注册表 Token
137
+ */
138
+ export const GUARD_REGISTRY_TOKEN = Symbol('@dangao/bun-server:guard-registry');
139
+
140
+ /**
141
+ * Roles 元数据键
142
+ */
143
+ export const ROLES_METADATA_KEY = Symbol('@dangao/bun-server:roles');
144
+
@@ -5,4 +5,5 @@ export * from './access-decision-manager';
5
5
  export * from './filter';
6
6
  export * from './providers';
7
7
  export * from './security-module';
8
+ export * from './guards';
8
9
 
@@ -2,11 +2,15 @@ import { Module, MODULE_METADATA_KEY } from '../di/module';
2
2
  import { AuthenticationManager } from './authentication-manager';
3
3
  import { JwtAuthenticationProvider } from './providers/jwt-provider';
4
4
  import { OAuth2AuthenticationProvider } from './providers/oauth2-provider';
5
- import { createSecurityFilter } from './filter';
5
+ import { createSecurityFilter, getGuardRegistry, registerReflector } from './filter';
6
6
  import { JWTUtil } from '../auth/jwt';
7
7
  import { OAuth2Service } from '../auth/oauth2';
8
8
  import { OAuth2Controller, OAUTH2_SERVICE_TOKEN, JWT_UTIL_TOKEN } from '../auth/controller';
9
9
  import type { JWTConfig, OAuth2Client, UserInfo } from '../auth/types';
10
+ import type { GuardType } from './guards/types';
11
+ import { GUARD_REGISTRY_TOKEN } from './guards/types';
12
+ import { GuardRegistry } from './guards/guard-registry';
13
+ import { Reflector, REFLECTOR_TOKEN } from './guards/reflector';
10
14
 
11
15
  /**
12
16
  * 安全模块配置
@@ -45,8 +49,17 @@ export interface SecurityModuleConfig {
45
49
  * @default false
46
50
  */
47
51
  defaultAuthRequired?: boolean;
52
+ /**
53
+ * 全局守卫列表
54
+ */
55
+ globalGuards?: GuardType[];
48
56
  }
49
57
 
58
+ /**
59
+ * 内部存储:容器引用和守卫注册表
60
+ */
61
+ let _guardRegistry: GuardRegistry | null = null;
62
+
50
63
  /**
51
64
  * 安全模块
52
65
  */
@@ -82,7 +95,23 @@ export class SecurityModule {
82
95
  new OAuth2AuthenticationProvider(oauth2Service, jwtUtil),
83
96
  );
84
97
 
85
- // 创建安全过滤器
98
+ // 创建守卫注册表(每次 forRoot 都创建新实例,避免测试间污染)
99
+ const guardRegistry = new GuardRegistry();
100
+ // 清理旧的 registry(如果存在)
101
+ if (_guardRegistry) {
102
+ _guardRegistry.clearGlobalGuards();
103
+ }
104
+ _guardRegistry = guardRegistry;
105
+
106
+ // 添加全局守卫
107
+ if (config.globalGuards && config.globalGuards.length > 0) {
108
+ guardRegistry.addGlobalGuards(...config.globalGuards);
109
+ }
110
+
111
+ // 创建 Reflector
112
+ const reflector = new Reflector();
113
+
114
+ // 创建安全过滤器(暂时不传 container,将在模块注册时更新)
86
115
  const securityFilter = createSecurityFilter({
87
116
  authenticationManager,
88
117
  excludePaths: [
@@ -92,6 +121,7 @@ export class SecurityModule {
92
121
  : []),
93
122
  ],
94
123
  defaultAuthRequired: config.defaultAuthRequired ?? false,
124
+ guardRegistry,
95
125
  });
96
126
 
97
127
  const controllers: any[] = [];
@@ -117,6 +147,14 @@ export class SecurityModule {
117
147
  provide: AuthenticationManager,
118
148
  useValue: authenticationManager,
119
149
  },
150
+ {
151
+ provide: GUARD_REGISTRY_TOKEN,
152
+ useValue: guardRegistry,
153
+ },
154
+ {
155
+ provide: REFLECTOR_TOKEN,
156
+ useValue: reflector,
157
+ },
120
158
  );
121
159
 
122
160
  // 添加安全过滤器中间件
@@ -135,11 +173,43 @@ export class SecurityModule {
135
173
  JWT_UTIL_TOKEN,
136
174
  OAUTH2_SERVICE_TOKEN,
137
175
  AuthenticationManager,
176
+ GUARD_REGISTRY_TOKEN,
177
+ REFLECTOR_TOKEN,
138
178
  ],
139
179
  };
140
180
  Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SecurityModule);
141
181
 
142
182
  return SecurityModule;
143
183
  }
184
+
185
+ /**
186
+ * 获取守卫注册表
187
+ * @returns 守卫注册表实例
188
+ */
189
+ public static getGuardRegistry(): GuardRegistry | null {
190
+ return _guardRegistry;
191
+ }
192
+
193
+ /**
194
+ * 添加全局守卫
195
+ * @param guards - 守卫类或实例
196
+ */
197
+ public static addGlobalGuards(...guards: GuardType[]): void {
198
+ if (_guardRegistry) {
199
+ _guardRegistry.addGlobalGuards(...guards);
200
+ }
201
+ }
202
+
203
+ /**
204
+ * 重置模块状态(主要用于测试)
205
+ */
206
+ public static reset(): void {
207
+ if (_guardRegistry) {
208
+ _guardRegistry.clearGlobalGuards();
209
+ }
210
+ _guardRegistry = null;
211
+ // 清除模块元数据
212
+ Reflect.deleteMetadata(MODULE_METADATA_KEY, SecurityModule);
213
+ }
144
214
  }
145
215