@dangao/bun-server 1.0.1 → 1.0.3

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 (200) hide show
  1. package/package.json +4 -2
  2. package/readme.md +163 -2
  3. package/src/auth/controller.ts +148 -0
  4. package/src/auth/decorators.ts +81 -0
  5. package/src/auth/index.ts +12 -0
  6. package/src/auth/jwt.ts +169 -0
  7. package/src/auth/oauth2.ts +244 -0
  8. package/src/auth/types.ts +248 -0
  9. package/src/cache/cache-module.ts +67 -0
  10. package/src/cache/decorators.ts +202 -0
  11. package/src/cache/index.ts +27 -0
  12. package/src/cache/service.ts +151 -0
  13. package/src/cache/types.ts +420 -0
  14. package/src/config/config-module.ts +76 -0
  15. package/src/config/index.ts +8 -0
  16. package/src/config/service.ts +93 -0
  17. package/src/config/types.ts +27 -0
  18. package/src/controller/controller.ts +251 -0
  19. package/src/controller/decorators.ts +84 -0
  20. package/src/controller/index.ts +7 -0
  21. package/src/controller/metadata.ts +27 -0
  22. package/src/controller/param-binder.ts +157 -0
  23. package/src/core/application.ts +233 -0
  24. package/src/core/context.ts +228 -0
  25. package/src/core/index.ts +4 -0
  26. package/src/core/server.ts +128 -0
  27. package/src/core/types.ts +2 -0
  28. package/src/database/connection-manager.ts +239 -0
  29. package/src/database/connection-pool.ts +322 -0
  30. package/src/database/database-extension.ts +62 -0
  31. package/src/database/database-module.ts +115 -0
  32. package/src/database/health-indicator.ts +51 -0
  33. package/src/database/index.ts +47 -0
  34. package/src/database/orm/decorators.ts +155 -0
  35. package/src/database/orm/drizzle-repository.ts +39 -0
  36. package/src/database/orm/index.ts +23 -0
  37. package/src/database/orm/repository-decorator.ts +39 -0
  38. package/src/database/orm/repository.ts +103 -0
  39. package/src/database/orm/service.ts +49 -0
  40. package/src/database/orm/transaction-decorator.ts +45 -0
  41. package/src/database/orm/transaction-interceptor.ts +243 -0
  42. package/src/database/orm/transaction-manager.ts +276 -0
  43. package/src/database/orm/transaction-types.ts +140 -0
  44. package/src/database/orm/types.ts +99 -0
  45. package/src/database/service.ts +221 -0
  46. package/src/database/types.ts +171 -0
  47. package/src/di/container.ts +398 -0
  48. package/src/di/decorators.ts +228 -0
  49. package/src/di/index.ts +4 -0
  50. package/src/di/module-registry.ts +188 -0
  51. package/src/di/module.ts +65 -0
  52. package/src/di/types.ts +67 -0
  53. package/src/error/error-codes.ts +222 -0
  54. package/src/error/filter.ts +43 -0
  55. package/src/error/handler.ts +66 -0
  56. package/src/error/http-exception.ts +115 -0
  57. package/src/error/i18n.ts +217 -0
  58. package/src/error/index.ts +16 -0
  59. package/src/extensions/index.ts +5 -0
  60. package/src/extensions/logger-extension.ts +31 -0
  61. package/src/extensions/logger-module.ts +69 -0
  62. package/src/extensions/types.ts +14 -0
  63. package/src/files/index.ts +5 -0
  64. package/src/files/static-middleware.ts +53 -0
  65. package/src/files/storage.ts +67 -0
  66. package/src/files/types.ts +33 -0
  67. package/src/files/upload-middleware.ts +45 -0
  68. package/src/health/controller.ts +76 -0
  69. package/src/health/health-module.ts +51 -0
  70. package/src/health/index.ts +12 -0
  71. package/src/health/types.ts +28 -0
  72. package/src/index.ts +270 -0
  73. package/src/metrics/collector.ts +209 -0
  74. package/src/metrics/controller.ts +40 -0
  75. package/src/metrics/index.ts +15 -0
  76. package/src/metrics/metrics-module.ts +58 -0
  77. package/src/metrics/middleware.ts +46 -0
  78. package/src/metrics/prometheus.ts +79 -0
  79. package/src/metrics/types.ts +103 -0
  80. package/src/middleware/builtin/cors.ts +60 -0
  81. package/src/middleware/builtin/error-handler.ts +90 -0
  82. package/src/middleware/builtin/file-upload.ts +42 -0
  83. package/src/middleware/builtin/index.ts +14 -0
  84. package/src/middleware/builtin/logger.ts +91 -0
  85. package/src/middleware/builtin/rate-limit.ts +252 -0
  86. package/src/middleware/builtin/static-file.ts +88 -0
  87. package/src/middleware/decorators.ts +91 -0
  88. package/src/middleware/index.ts +11 -0
  89. package/src/middleware/middleware.ts +13 -0
  90. package/src/middleware/pipeline.ts +93 -0
  91. package/src/queue/decorators.ts +110 -0
  92. package/src/queue/index.ts +26 -0
  93. package/src/queue/queue-module.ts +64 -0
  94. package/src/queue/service.ts +302 -0
  95. package/src/queue/types.ts +341 -0
  96. package/src/request/body-parser.ts +133 -0
  97. package/src/request/file-handler.ts +46 -0
  98. package/src/request/index.ts +5 -0
  99. package/src/request/request.ts +107 -0
  100. package/src/request/response.ts +150 -0
  101. package/src/router/decorators.ts +122 -0
  102. package/src/router/index.ts +6 -0
  103. package/src/router/registry.ts +98 -0
  104. package/src/router/route.ts +140 -0
  105. package/src/router/router.ts +241 -0
  106. package/src/router/types.ts +27 -0
  107. package/src/security/access-decision-manager.ts +34 -0
  108. package/src/security/authentication-manager.ts +47 -0
  109. package/src/security/context.ts +92 -0
  110. package/src/security/filter.ts +162 -0
  111. package/src/security/index.ts +8 -0
  112. package/src/security/providers/index.ts +3 -0
  113. package/src/security/providers/jwt-provider.ts +60 -0
  114. package/src/security/providers/oauth2-provider.ts +70 -0
  115. package/src/security/security-module.ts +145 -0
  116. package/src/security/types.ts +165 -0
  117. package/src/session/decorators.ts +45 -0
  118. package/src/session/index.ts +19 -0
  119. package/src/session/middleware.ts +143 -0
  120. package/src/session/service.ts +218 -0
  121. package/src/session/session-module.ts +69 -0
  122. package/src/session/types.ts +373 -0
  123. package/src/swagger/decorators.ts +133 -0
  124. package/src/swagger/generator.ts +234 -0
  125. package/src/swagger/index.ts +7 -0
  126. package/src/swagger/swagger-extension.ts +41 -0
  127. package/src/swagger/swagger-module.ts +83 -0
  128. package/src/swagger/types.ts +188 -0
  129. package/src/swagger/ui.ts +98 -0
  130. package/src/testing/harness.ts +96 -0
  131. package/src/validation/decorators.ts +95 -0
  132. package/src/validation/errors.ts +28 -0
  133. package/src/validation/index.ts +14 -0
  134. package/src/validation/types.ts +35 -0
  135. package/src/validation/validator.ts +63 -0
  136. package/src/websocket/decorators.ts +51 -0
  137. package/src/websocket/index.ts +12 -0
  138. package/src/websocket/registry.ts +133 -0
  139. package/tests/cache/cache-module.test.ts +212 -0
  140. package/tests/config/config-module.test.ts +151 -0
  141. package/tests/controller/controller.test.ts +189 -0
  142. package/tests/core/application.test.ts +57 -0
  143. package/tests/core/context-body.test.ts +44 -0
  144. package/tests/core/context.test.ts +86 -0
  145. package/tests/core/edge-cases.test.ts +432 -0
  146. package/tests/database/database-module.test.ts +385 -0
  147. package/tests/database/orm.test.ts +164 -0
  148. package/tests/database/postgres-mysql-integration.test.ts +395 -0
  149. package/tests/database/transaction.test.ts +238 -0
  150. package/tests/di/container.test.ts +264 -0
  151. package/tests/di/module.test.ts +128 -0
  152. package/tests/error/error-codes.test.ts +121 -0
  153. package/tests/error/error-handler.test.ts +68 -0
  154. package/tests/error/error-handling.test.ts +254 -0
  155. package/tests/error/http-exception.test.ts +37 -0
  156. package/tests/error/i18n-integration.test.ts +175 -0
  157. package/tests/extensions/logger-extension.test.ts +40 -0
  158. package/tests/files/static-middleware.test.ts +67 -0
  159. package/tests/files/upload-middleware.test.ts +43 -0
  160. package/tests/health/health-module.test.ts +116 -0
  161. package/tests/integration/application-router.test.ts +85 -0
  162. package/tests/integration/body-parsing.test.ts +88 -0
  163. package/tests/integration/cache-e2e.test.ts +114 -0
  164. package/tests/integration/oauth2-e2e.test.ts +615 -0
  165. package/tests/integration/session-e2e.test.ts +207 -0
  166. package/tests/metrics/metrics-module.test.ts +178 -0
  167. package/tests/middleware/builtin.test.ts +206 -0
  168. package/tests/middleware/file-upload.test.ts +41 -0
  169. package/tests/middleware/middleware.test.ts +120 -0
  170. package/tests/middleware/pipeline.test.ts +72 -0
  171. package/tests/middleware/rate-limit.test.ts +314 -0
  172. package/tests/middleware/static-file.test.ts +62 -0
  173. package/tests/perf/harness.test.ts +48 -0
  174. package/tests/perf/optimization.test.ts +183 -0
  175. package/tests/perf/regression.test.ts +120 -0
  176. package/tests/queue/queue-module.test.ts +217 -0
  177. package/tests/request/body-parser.test.ts +96 -0
  178. package/tests/request/response.test.ts +99 -0
  179. package/tests/router/decorators.test.ts +48 -0
  180. package/tests/router/registry.test.ts +51 -0
  181. package/tests/router/route.test.ts +71 -0
  182. package/tests/router/router-normalization.test.ts +106 -0
  183. package/tests/router/router.test.ts +133 -0
  184. package/tests/security/access-decision-manager.test.ts +84 -0
  185. package/tests/security/authentication-manager.test.ts +81 -0
  186. package/tests/security/context.test.ts +302 -0
  187. package/tests/security/filter.test.ts +225 -0
  188. package/tests/security/jwt-provider.test.ts +106 -0
  189. package/tests/security/oauth2-provider.test.ts +269 -0
  190. package/tests/security/security-module.test.ts +143 -0
  191. package/tests/session/session-module.test.ts +307 -0
  192. package/tests/stress/di-stress.test.ts +30 -0
  193. package/tests/swagger/decorators.test.ts +153 -0
  194. package/tests/swagger/generator.test.ts +202 -0
  195. package/tests/swagger/swagger-extension.test.ts +72 -0
  196. package/tests/swagger/swagger-module.test.ts +79 -0
  197. package/tests/utils/test-port.ts +10 -0
  198. package/tests/validation/controller-validation.test.ts +64 -0
  199. package/tests/validation/validation.test.ts +42 -0
  200. package/tests/websocket/gateway.test.ts +68 -0
@@ -0,0 +1,244 @@
1
+ import { JWTUtil } from './jwt';
2
+ import type {
3
+ OAuth2Client,
4
+ OAuth2AuthorizationRequest,
5
+ OAuth2TokenRequest,
6
+ OAuth2TokenResponse,
7
+ OAuth2CodeConfig,
8
+ JWTPayload,
9
+ UserInfo,
10
+ } from './types';
11
+
12
+ /**
13
+ * 授权码存储
14
+ */
15
+ interface AuthorizationCode {
16
+ code: string;
17
+ clientId: string;
18
+ redirectUri: string;
19
+ userId: string;
20
+ scope?: string;
21
+ expiresAt: number;
22
+ }
23
+
24
+ /**
25
+ * OAuth2 服务
26
+ */
27
+ export class OAuth2Service {
28
+ private readonly jwtUtil: JWTUtil;
29
+ private readonly clients: Map<string, OAuth2Client>;
30
+ private readonly codes: Map<string, AuthorizationCode>;
31
+ private readonly codeConfig: Required<OAuth2CodeConfig>;
32
+ private readonly userProvider?: (userId: string) => Promise<UserInfo | null>;
33
+
34
+ public constructor(
35
+ jwtUtil: JWTUtil,
36
+ clients: OAuth2Client[] = [],
37
+ codeConfig: OAuth2CodeConfig = {},
38
+ userProvider?: (userId: string) => Promise<UserInfo | null>,
39
+ ) {
40
+ this.jwtUtil = jwtUtil;
41
+ this.clients = new Map();
42
+ this.codes = new Map();
43
+ this.codeConfig = {
44
+ expiresIn: codeConfig.expiresIn ?? 600,
45
+ length: codeConfig.length ?? 32,
46
+ };
47
+
48
+ // 注册客户端
49
+ for (const client of clients) {
50
+ this.clients.set(client.clientId, client);
51
+ }
52
+
53
+ this.userProvider = userProvider;
54
+
55
+ // 定期清理过期的授权码
56
+ setInterval(() => this.cleanupExpiredCodes(), 60000);
57
+ }
58
+
59
+ /**
60
+ * 注册客户端
61
+ */
62
+ public registerClient(client: OAuth2Client): void {
63
+ this.clients.set(client.clientId, client);
64
+ }
65
+
66
+ /**
67
+ * 验证授权请求
68
+ */
69
+ public validateAuthorizationRequest(
70
+ request: OAuth2AuthorizationRequest,
71
+ ): { valid: boolean; error?: string } {
72
+ const client = this.clients.get(request.clientId);
73
+ if (!client) {
74
+ return { valid: false, error: 'invalid_client' };
75
+ }
76
+
77
+ if (request.responseType !== 'code') {
78
+ return { valid: false, error: 'unsupported_response_type' };
79
+ }
80
+
81
+ if (!client.redirectUris.includes(request.redirectUri)) {
82
+ return { valid: false, error: 'invalid_redirect_uri' };
83
+ }
84
+
85
+ return { valid: true };
86
+ }
87
+
88
+ /**
89
+ * 生成授权码
90
+ */
91
+ public generateAuthorizationCode(
92
+ clientId: string,
93
+ redirectUri: string,
94
+ userId: string,
95
+ scope?: string,
96
+ ): string {
97
+ const code = this.generateRandomString(this.codeConfig.length);
98
+ const expiresAt = Date.now() + this.codeConfig.expiresIn * 1000;
99
+
100
+ this.codes.set(code, {
101
+ code,
102
+ clientId,
103
+ redirectUri,
104
+ userId,
105
+ scope,
106
+ expiresAt,
107
+ });
108
+
109
+ return code;
110
+ }
111
+
112
+ /**
113
+ * 交换授权码获取令牌
114
+ */
115
+ public async exchangeCodeForToken(
116
+ request: OAuth2TokenRequest,
117
+ ): Promise<OAuth2TokenResponse | null> {
118
+ if (request.grantType !== 'authorization_code') {
119
+ return null;
120
+ }
121
+
122
+ const codeData = this.codes.get(request.code);
123
+ if (!codeData) {
124
+ return null;
125
+ }
126
+
127
+ // 验证授权码是否过期
128
+ if (codeData.expiresAt < Date.now()) {
129
+ this.codes.delete(request.code);
130
+ return null;
131
+ }
132
+
133
+ // 验证客户端
134
+ const client = this.clients.get(request.clientId);
135
+ if (!client || client.clientSecret !== request.clientSecret) {
136
+ return null;
137
+ }
138
+
139
+ // 验证重定向 URI
140
+ if (codeData.redirectUri !== request.redirectUri) {
141
+ return null;
142
+ }
143
+
144
+ // 删除已使用的授权码
145
+ this.codes.delete(request.code);
146
+
147
+ // 获取用户信息
148
+ let userInfo: UserInfo | null = null;
149
+ if (this.userProvider) {
150
+ userInfo = await this.userProvider(codeData.userId);
151
+ }
152
+
153
+ if (!userInfo) {
154
+ userInfo = {
155
+ id: codeData.userId,
156
+ username: codeData.userId,
157
+ };
158
+ }
159
+
160
+ // 生成令牌
161
+ const payload: Omit<JWTPayload, 'exp' | 'iat'> = {
162
+ sub: userInfo.id,
163
+ username: userInfo.username,
164
+ roles: userInfo.roles,
165
+ };
166
+
167
+ const accessToken = this.jwtUtil.generateAccessToken(payload);
168
+ const refreshToken = this.jwtUtil.generateRefreshToken(payload);
169
+
170
+ return {
171
+ accessToken,
172
+ tokenType: 'Bearer',
173
+ expiresIn: this.jwtUtil['config'].accessTokenExpiresIn,
174
+ refreshToken,
175
+ scope: codeData.scope,
176
+ };
177
+ }
178
+
179
+ /**
180
+ * 刷新令牌
181
+ */
182
+ public async refreshToken(refreshToken: string): Promise<OAuth2TokenResponse | null> {
183
+ const payload = this.jwtUtil.verify(refreshToken);
184
+ if (!payload || !payload.sub) {
185
+ return null;
186
+ }
187
+
188
+ // 获取用户信息
189
+ let userInfo: UserInfo | null = null;
190
+ if (this.userProvider) {
191
+ userInfo = await this.userProvider(payload.sub);
192
+ }
193
+
194
+ if (!userInfo) {
195
+ userInfo = {
196
+ id: payload.sub,
197
+ username: payload.username as string || payload.sub,
198
+ roles: payload.roles as string[],
199
+ };
200
+ }
201
+
202
+ // 生成新令牌
203
+ const newPayload: Omit<JWTPayload, 'exp' | 'iat'> = {
204
+ sub: userInfo.id,
205
+ username: userInfo.username,
206
+ roles: userInfo.roles,
207
+ };
208
+
209
+ const accessToken = this.jwtUtil.generateAccessToken(newPayload);
210
+ const newRefreshToken = this.jwtUtil.generateRefreshToken(newPayload);
211
+
212
+ return {
213
+ accessToken,
214
+ tokenType: 'Bearer',
215
+ expiresIn: this.jwtUtil['config'].accessTokenExpiresIn,
216
+ refreshToken: newRefreshToken,
217
+ };
218
+ }
219
+
220
+ /**
221
+ * 生成随机字符串
222
+ */
223
+ private generateRandomString(length: number): string {
224
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
225
+ let result = '';
226
+ for (let i = 0; i < length; i++) {
227
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
228
+ }
229
+ return result;
230
+ }
231
+
232
+ /**
233
+ * 清理过期的授权码
234
+ */
235
+ private cleanupExpiredCodes(): void {
236
+ const now = Date.now();
237
+ for (const [code, data] of this.codes.entries()) {
238
+ if (data.expiresAt < now) {
239
+ this.codes.delete(code);
240
+ }
241
+ }
242
+ }
243
+ }
244
+
@@ -0,0 +1,248 @@
1
+ /**
2
+ * 认证相关类型定义
3
+ */
4
+
5
+ /**
6
+ * JWT 载荷
7
+ */
8
+ export interface JWTPayload {
9
+ /**
10
+ * 用户 ID
11
+ */
12
+ sub: string;
13
+ /**
14
+ * 用户名
15
+ */
16
+ username?: string;
17
+ /**
18
+ * 角色列表
19
+ */
20
+ roles?: string[];
21
+ /**
22
+ * 过期时间(Unix 时间戳)
23
+ */
24
+ exp?: number;
25
+ /**
26
+ * 签发时间(Unix 时间戳)
27
+ */
28
+ iat?: number;
29
+ /**
30
+ * 其他自定义字段
31
+ */
32
+ [key: string]: unknown;
33
+ }
34
+
35
+ /**
36
+ * JWT 配置
37
+ */
38
+ export interface JWTConfig {
39
+ /**
40
+ * 密钥(用于签名和验证)
41
+ */
42
+ secret: string;
43
+ /**
44
+ * 访问令牌过期时间(秒)
45
+ * @default 3600 (1 hour)
46
+ */
47
+ accessTokenExpiresIn?: number;
48
+ /**
49
+ * 刷新令牌过期时间(秒)
50
+ * @default 86400 * 7 (7 days)
51
+ */
52
+ refreshTokenExpiresIn?: number;
53
+ /**
54
+ * 算法
55
+ * @default 'HS256'
56
+ */
57
+ algorithm?: 'HS256' | 'HS384' | 'HS512';
58
+ }
59
+
60
+ /**
61
+ * OAuth2 授权码配置
62
+ */
63
+ export interface OAuth2CodeConfig {
64
+ /**
65
+ * 授权码过期时间(秒)
66
+ * @default 600 (10 minutes)
67
+ */
68
+ expiresIn?: number;
69
+ /**
70
+ * 授权码长度
71
+ * @default 32
72
+ */
73
+ length?: number;
74
+ }
75
+
76
+ /**
77
+ * OAuth2 客户端配置
78
+ */
79
+ export interface OAuth2Client {
80
+ /**
81
+ * 客户端 ID
82
+ */
83
+ clientId: string;
84
+ /**
85
+ * 客户端密钥
86
+ */
87
+ clientSecret: string;
88
+ /**
89
+ * 重定向 URI 列表
90
+ */
91
+ redirectUris: string[];
92
+ /**
93
+ * 允许的授权类型
94
+ */
95
+ grantTypes: ('authorization_code' | 'refresh_token')[];
96
+ }
97
+
98
+ /**
99
+ * OAuth2 授权请求
100
+ */
101
+ export interface OAuth2AuthorizationRequest {
102
+ /**
103
+ * 客户端 ID
104
+ */
105
+ clientId: string;
106
+ /**
107
+ * 重定向 URI
108
+ */
109
+ redirectUri: string;
110
+ /**
111
+ * 响应类型
112
+ */
113
+ responseType: 'code';
114
+ /**
115
+ * 作用域(可选)
116
+ */
117
+ scope?: string;
118
+ /**
119
+ * 状态(用于 CSRF 防护)
120
+ */
121
+ state?: string;
122
+ }
123
+
124
+ /**
125
+ * OAuth2 令牌请求
126
+ */
127
+ export interface OAuth2TokenRequest {
128
+ /**
129
+ * 授权码
130
+ */
131
+ code: string;
132
+ /**
133
+ * 客户端 ID
134
+ */
135
+ clientId: string;
136
+ /**
137
+ * 客户端密钥
138
+ */
139
+ clientSecret: string;
140
+ /**
141
+ * 重定向 URI
142
+ */
143
+ redirectUri: string;
144
+ /**
145
+ * 授权类型
146
+ */
147
+ grantType: 'authorization_code' | 'refresh_token';
148
+ /**
149
+ * 刷新令牌(用于 refresh_token 授权类型)
150
+ */
151
+ refreshToken?: string;
152
+ }
153
+
154
+ /**
155
+ * OAuth2 令牌响应
156
+ */
157
+ export interface OAuth2TokenResponse {
158
+ /**
159
+ * 访问令牌
160
+ */
161
+ accessToken: string;
162
+ /**
163
+ * 令牌类型
164
+ */
165
+ tokenType: 'Bearer';
166
+ /**
167
+ * 过期时间(秒)
168
+ */
169
+ expiresIn: number;
170
+ /**
171
+ * 刷新令牌
172
+ */
173
+ refreshToken?: string;
174
+ /**
175
+ * 作用域
176
+ */
177
+ scope?: string;
178
+ }
179
+
180
+ /**
181
+ * 认证模块配置(已废弃,请使用 SecurityModuleConfig)
182
+ * @deprecated 使用 SecurityModule.forRoot() 替代
183
+ */
184
+ export interface AuthModuleOptions {
185
+ /**
186
+ * JWT 配置
187
+ */
188
+ jwt: JWTConfig;
189
+ /**
190
+ * OAuth2 客户端列表
191
+ */
192
+ clients?: OAuth2Client[];
193
+ /**
194
+ * 授权码配置
195
+ */
196
+ codeConfig?: OAuth2CodeConfig;
197
+ /**
198
+ * 是否启用 OAuth2 端点
199
+ * @default true
200
+ */
201
+ enableOAuth2Endpoints?: boolean;
202
+ /**
203
+ * OAuth2 端点前缀
204
+ * @default '/oauth2'
205
+ */
206
+ oauth2Prefix?: string;
207
+ }
208
+
209
+ /**
210
+ * 用户信息
211
+ */
212
+ export interface UserInfo {
213
+ /**
214
+ * 用户 ID
215
+ */
216
+ id: string;
217
+ /**
218
+ * 用户名
219
+ */
220
+ username: string;
221
+ /**
222
+ * 角色列表
223
+ */
224
+ roles?: string[];
225
+ /**
226
+ * 其他属性
227
+ */
228
+ [key: string]: unknown;
229
+ }
230
+
231
+ /**
232
+ * 认证上下文(附加到 Context)
233
+ */
234
+ export interface AuthContext {
235
+ /**
236
+ * 用户信息
237
+ */
238
+ user?: UserInfo;
239
+ /**
240
+ * JWT 载荷
241
+ */
242
+ payload?: JWTPayload;
243
+ /**
244
+ * 是否已认证
245
+ */
246
+ isAuthenticated: boolean;
247
+ }
248
+
@@ -0,0 +1,67 @@
1
+ import { Module, MODULE_METADATA_KEY, type ModuleProvider } from '../di/module';
2
+
3
+ import { CacheService } from './service';
4
+ import {
5
+ CACHE_OPTIONS_TOKEN,
6
+ CACHE_SERVICE_TOKEN,
7
+ MemoryCacheStore,
8
+ type CacheModuleOptions,
9
+ type CacheStore,
10
+ } from './types';
11
+
12
+ @Module({
13
+ providers: [],
14
+ })
15
+ export class CacheModule {
16
+ /**
17
+ * 创建缓存模块
18
+ * @param options - 模块配置
19
+ */
20
+ public static forRoot(
21
+ options: CacheModuleOptions = {},
22
+ ): typeof CacheModule {
23
+ const providers: ModuleProvider[] = [];
24
+
25
+ // 如果没有提供 store,使用默认的内存存储
26
+ const store: CacheStore =
27
+ options.store ??
28
+ new MemoryCacheStore({
29
+ cleanupInterval: 60000, // 每分钟清理一次
30
+ });
31
+
32
+ const service = new CacheService({
33
+ store,
34
+ defaultTtl: options.defaultTtl,
35
+ keyPrefix: options.keyPrefix,
36
+ });
37
+
38
+ providers.push(
39
+ {
40
+ provide: CACHE_SERVICE_TOKEN,
41
+ useValue: service,
42
+ },
43
+ {
44
+ provide: CACHE_OPTIONS_TOKEN,
45
+ useValue: options,
46
+ },
47
+ CacheService,
48
+ );
49
+
50
+ // 动态更新模块元数据
51
+ const existingMetadata =
52
+ Reflect.getMetadata(MODULE_METADATA_KEY, CacheModule) || {};
53
+ const metadata = {
54
+ ...existingMetadata,
55
+ providers: [...(existingMetadata.providers || []), ...providers],
56
+ exports: [
57
+ ...(existingMetadata.exports || []),
58
+ CACHE_SERVICE_TOKEN,
59
+ CACHE_OPTIONS_TOKEN,
60
+ CacheService,
61
+ ],
62
+ };
63
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, CacheModule);
64
+
65
+ return CacheModule;
66
+ }
67
+ }