@dangao/bun-server 3.2.0 → 3.3.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 (131) hide show
  1. package/dist/ai/types.d.ts +4 -0
  2. package/dist/ai/types.d.ts.map +1 -1
  3. package/dist/auth/types.d.ts +4 -0
  4. package/dist/auth/types.d.ts.map +1 -1
  5. package/dist/cache/interceptors.d.ts +3 -3
  6. package/dist/cache/interceptors.d.ts.map +1 -1
  7. package/dist/cache/service.d.ts +6 -6
  8. package/dist/cache/service.d.ts.map +1 -1
  9. package/dist/cache/types.d.ts +12 -12
  10. package/dist/cache/types.d.ts.map +1 -1
  11. package/dist/config/service.d.ts +6 -4
  12. package/dist/config/service.d.ts.map +1 -1
  13. package/dist/core/application.d.ts +4 -0
  14. package/dist/core/application.d.ts.map +1 -1
  15. package/dist/core/context.d.ts +4 -2
  16. package/dist/core/context.d.ts.map +1 -1
  17. package/dist/database/sqlite-adapter.d.ts +4 -2
  18. package/dist/database/sqlite-adapter.d.ts.map +1 -1
  19. package/dist/di/container.d.ts +2 -0
  20. package/dist/di/container.d.ts.map +1 -1
  21. package/dist/di/module-registry.d.ts.map +1 -1
  22. package/dist/di/module.d.ts +11 -1
  23. package/dist/di/module.d.ts.map +1 -1
  24. package/dist/di/types.d.ts +1 -1
  25. package/dist/di/types.d.ts.map +1 -1
  26. package/dist/error/handler.d.ts.map +1 -1
  27. package/dist/error/http-exception.d.ts +8 -8
  28. package/dist/error/http-exception.d.ts.map +1 -1
  29. package/dist/error/index.d.ts +1 -0
  30. package/dist/error/index.d.ts.map +1 -1
  31. package/dist/events/service.d.ts +2 -2
  32. package/dist/events/service.d.ts.map +1 -1
  33. package/dist/events/types.d.ts +12 -3
  34. package/dist/events/types.d.ts.map +1 -1
  35. package/dist/index.js +63 -25
  36. package/dist/index.node.mjs +63 -25
  37. package/dist/interceptor/base-interceptor.d.ts +3 -3
  38. package/dist/interceptor/base-interceptor.d.ts.map +1 -1
  39. package/dist/interceptor/builtin/log-interceptor.d.ts +1 -1
  40. package/dist/interceptor/builtin/log-interceptor.d.ts.map +1 -1
  41. package/dist/interceptor/builtin/permission-interceptor.d.ts +1 -1
  42. package/dist/interceptor/builtin/permission-interceptor.d.ts.map +1 -1
  43. package/dist/interceptor/interceptor-chain.d.ts +1 -1
  44. package/dist/interceptor/interceptor-chain.d.ts.map +1 -1
  45. package/dist/interceptor/interceptor-registry.d.ts +3 -1
  46. package/dist/interceptor/interceptor-registry.d.ts.map +1 -1
  47. package/dist/interceptor/types.d.ts +6 -1
  48. package/dist/interceptor/types.d.ts.map +1 -1
  49. package/dist/microservice/service-client/types.d.ts +1 -0
  50. package/dist/microservice/service-client/types.d.ts.map +1 -1
  51. package/dist/microservice/tracing/tracer.d.ts +1 -0
  52. package/dist/microservice/tracing/tracer.d.ts.map +1 -1
  53. package/dist/middleware/builtin/file-upload.d.ts +2 -0
  54. package/dist/middleware/builtin/file-upload.d.ts.map +1 -1
  55. package/dist/middleware/builtin/rate-limit.d.ts +9 -1
  56. package/dist/middleware/builtin/rate-limit.d.ts.map +1 -1
  57. package/dist/queue/service.d.ts +2 -2
  58. package/dist/queue/service.d.ts.map +1 -1
  59. package/dist/queue/types.d.ts +25 -1
  60. package/dist/queue/types.d.ts.map +1 -1
  61. package/dist/router/decorators.d.ts +1 -2
  62. package/dist/router/decorators.d.ts.map +1 -1
  63. package/dist/security/guards/types.d.ts +1 -0
  64. package/dist/security/guards/types.d.ts.map +1 -1
  65. package/dist/security/types.d.ts +1 -1
  66. package/dist/security/types.d.ts.map +1 -1
  67. package/dist/session/types.d.ts +8 -0
  68. package/dist/session/types.d.ts.map +1 -1
  69. package/dist/swagger/decorators.d.ts +1 -1
  70. package/dist/swagger/decorators.d.ts.map +1 -1
  71. package/dist/swagger/types.d.ts +1 -1
  72. package/dist/swagger/types.d.ts.map +1 -1
  73. package/dist/testing/harness.d.ts +1 -1
  74. package/dist/testing/harness.d.ts.map +1 -1
  75. package/dist/testing/test-client.d.ts +1 -1
  76. package/dist/testing/test-client.d.ts.map +1 -1
  77. package/dist/testing/testing-module.d.ts +2 -2
  78. package/dist/testing/testing-module.d.ts.map +1 -1
  79. package/dist/validation/errors.d.ts +5 -1
  80. package/dist/validation/errors.d.ts.map +1 -1
  81. package/package.json +3 -3
  82. package/src/ai/types.ts +5 -0
  83. package/src/auth/types.ts +4 -1
  84. package/src/cache/interceptors.ts +6 -6
  85. package/src/cache/service-proxy.ts +2 -2
  86. package/src/cache/service.ts +17 -8
  87. package/src/cache/types.ts +12 -12
  88. package/src/config/service.ts +8 -6
  89. package/src/core/application.ts +7 -1
  90. package/src/core/context.ts +6 -3
  91. package/src/database/sqlite-adapter.ts +4 -3
  92. package/src/di/container.ts +13 -0
  93. package/src/di/module-registry.ts +2 -3
  94. package/src/di/module.ts +21 -2
  95. package/src/di/types.ts +1 -2
  96. package/src/error/handler.ts +3 -4
  97. package/src/error/http-exception.ts +11 -11
  98. package/src/error/index.ts +1 -1
  99. package/src/events/service.ts +4 -2
  100. package/src/events/types.ts +14 -3
  101. package/src/interceptor/base-interceptor.ts +5 -6
  102. package/src/interceptor/builtin/log-interceptor.ts +2 -3
  103. package/src/interceptor/builtin/permission-interceptor.ts +2 -3
  104. package/src/interceptor/interceptor-chain.ts +6 -7
  105. package/src/interceptor/interceptor-registry.ts +5 -3
  106. package/src/interceptor/types.ts +9 -4
  107. package/src/microservice/service-client/types.ts +1 -1
  108. package/src/microservice/tracing/tracer.ts +15 -3
  109. package/src/middleware/builtin/file-upload.ts +3 -2
  110. package/src/middleware/builtin/rate-limit.ts +22 -5
  111. package/src/queue/service.ts +1 -1
  112. package/src/queue/types.ts +40 -1
  113. package/src/router/decorators.ts +2 -3
  114. package/src/security/guards/types.ts +2 -1
  115. package/src/security/types.ts +1 -2
  116. package/src/session/service.ts +1 -1
  117. package/src/session/types.ts +10 -0
  118. package/src/swagger/decorators.ts +15 -4
  119. package/src/swagger/generator.ts +2 -3
  120. package/src/swagger/types.ts +1 -2
  121. package/src/testing/harness.ts +1 -2
  122. package/src/testing/test-client.ts +2 -2
  123. package/src/testing/testing-module.ts +5 -5
  124. package/src/validation/errors.ts +6 -2
  125. package/tests/bun-test-shim.d.ts +11 -0
  126. package/tests/controller/context-decorator.test.ts +1 -2
  127. package/tests/di/module.test.ts +199 -1
  128. package/tests/events/event-emitter.test.ts +2 -2
  129. package/tests/global.d.ts +30 -0
  130. package/tests/queue/queue-service.test.ts +14 -0
  131. package/tests/testing/testing-module.test.ts +20 -0
@@ -15,11 +15,11 @@ export abstract class BaseInterceptor implements Interceptor {
15
15
  public abstract execute<T>(
16
16
  target: unknown,
17
17
  propertyKey: string | symbol,
18
- originalMethod: (...args: unknown[]) => T | Promise<T>,
19
- args: unknown[],
18
+ originalMethod: (...args: any[]) => T | Promise<T>,
19
+ args: any[],
20
20
  container: Container,
21
21
  context?: Context,
22
- ): Promise<T>;
22
+ ): Promise<any>;
23
23
 
24
24
  /**
25
25
  * 前置处理(可选)
@@ -33,7 +33,7 @@ export abstract class BaseInterceptor implements Interceptor {
33
33
  protected async before(
34
34
  target: unknown,
35
35
  propertyKey: string | symbol,
36
- args: unknown[],
36
+ args: any[],
37
37
  container: Container,
38
38
  context?: Context,
39
39
  ): Promise<void> {
@@ -141,7 +141,7 @@ export abstract class BaseInterceptor implements Interceptor {
141
141
  */
142
142
  protected resolveService<T>(
143
143
  container: Container,
144
- token: (new (...args: unknown[]) => T) | string | symbol,
144
+ token: (new (...args: any[]) => T) | string | symbol,
145
145
  ): T {
146
146
  return container.resolve<T>(token);
147
147
  }
@@ -200,4 +200,3 @@ export abstract class BaseInterceptor implements Interceptor {
200
200
  return context.getParam(paramName);
201
201
  }
202
202
  }
203
-
@@ -84,8 +84,8 @@ export class LogInterceptor extends BaseInterceptor {
84
84
  public async execute<T>(
85
85
  target: unknown,
86
86
  propertyKey: string | symbol,
87
- originalMethod: (...args: unknown[]) => T | Promise<T>,
88
- args: unknown[],
87
+ originalMethod: (...args: any[]) => T | Promise<T>,
88
+ args: any[],
89
89
  container: Container,
90
90
  context?: Context,
91
91
  ): Promise<T> {
@@ -175,4 +175,3 @@ export class LogInterceptor extends BaseInterceptor {
175
175
  }
176
176
  }
177
177
  }
178
-
@@ -91,8 +91,8 @@ export class PermissionInterceptor extends BaseInterceptor {
91
91
  public async execute<T>(
92
92
  target: unknown,
93
93
  propertyKey: string | symbol,
94
- originalMethod: (...args: unknown[]) => T | Promise<T>,
95
- args: unknown[],
94
+ originalMethod: (...args: any[]) => T | Promise<T>,
95
+ args: any[],
96
96
  container: Container,
97
97
  context?: Context,
98
98
  ): Promise<T> {
@@ -170,4 +170,3 @@ export class PermissionInterceptor extends BaseInterceptor {
170
170
  return null;
171
171
  }
172
172
  }
173
-
@@ -22,8 +22,8 @@ export class InterceptorChain {
22
22
  interceptors: Interceptor[],
23
23
  target: unknown,
24
24
  propertyKey: string | symbol,
25
- originalMethod: (...args: unknown[]) => T | Promise<T>,
26
- args: unknown[],
25
+ originalMethod: (...args: any[]) => T | Promise<T>,
26
+ args: any[],
27
27
  container: Container,
28
28
  context?: Context,
29
29
  ): Promise<T> {
@@ -36,7 +36,7 @@ export class InterceptorChain {
36
36
  let index = 0;
37
37
  let currentArgs = args; // Track arguments that might be modified by interceptors
38
38
 
39
- const next = async (modifiedArgs?: unknown[]): Promise<T> => {
39
+ const next = async (modifiedArgs?: any[]): Promise<T> => {
40
40
  // 如果拦截器传递了新参数,使用新参数;否则使用当前参数
41
41
  if (modifiedArgs && modifiedArgs.length > 0) {
42
42
  currentArgs = modifiedArgs;
@@ -50,11 +50,11 @@ export class InterceptorChain {
50
50
  const interceptor = interceptors[index++];
51
51
 
52
52
  // 执行当前拦截器,传递 next 作为下一个执行函数
53
- // 注意:拦截器接口要求 originalMethod 的类型是 (...args: unknown[]) => T | Promise<T>
53
+ // 注意:拦截器接口要求 originalMethod 的类型是 (...args: any[]) => T | Promise<T>
54
54
  // 这允许原始方法可以是同步(返回 T)或异步(返回 Promise<T>)
55
55
  // 虽然 next 函数是异步的(总是返回 Promise<T>),但我们保持类型签名为 T | Promise<T>
56
56
  // 以符合拦截器接口的要求。拦截器应该使用 Promise.resolve() 来统一处理同步和异步返回值
57
- const wrappedNext = (...nextArgs: unknown[]): T | Promise<T> => {
57
+ const wrappedNext = (...nextArgs: any[]): T | Promise<T> => {
58
58
  // 如果拦截器传递了新参数,传递给 next;否则传递 undefined(使用当前参数)
59
59
  // next 是异步函数,总是返回 Promise<T>,但类型签名允许 T | Promise<T>
60
60
  const result = next(nextArgs.length > 0 ? nextArgs : undefined);
@@ -70,10 +70,9 @@ export class InterceptorChain {
70
70
  currentArgs, // Pass current args to the interceptor
71
71
  container,
72
72
  context,
73
- );
73
+ ) as T;
74
74
  };
75
75
 
76
76
  return await next();
77
77
  }
78
78
  }
79
-
@@ -22,8 +22,11 @@ export class InterceptorRegistry {
22
22
  public register(
23
23
  metadataKey: symbol,
24
24
  interceptor: Interceptor,
25
- priority: number = 100,
25
+ priority: number | { priority?: number } = 100,
26
26
  ): void {
27
+ const resolvedPriority = typeof priority === 'number'
28
+ ? priority
29
+ : priority.priority ?? 100;
27
30
  if (!this.interceptors.has(metadataKey)) {
28
31
  this.interceptors.set(metadataKey, []);
29
32
  }
@@ -39,7 +42,7 @@ export class InterceptorRegistry {
39
42
  metadataList.push({
40
43
  metadataKey,
41
44
  interceptor,
42
- priority,
45
+ priority: resolvedPriority,
43
46
  });
44
47
 
45
48
  // 按优先级排序(数字越小优先级越高)
@@ -129,4 +132,3 @@ export class InterceptorRegistry {
129
132
  return total;
130
133
  }
131
134
  }
132
-
@@ -6,6 +6,12 @@ import type { Context } from '../core/context';
6
6
  * 定义拦截器的核心执行方法
7
7
  */
8
8
  export interface Interceptor {
9
+ /**
10
+ * Optional priority used by registries/tests that carry interceptor metadata
11
+ * alongside the executable interceptor instance.
12
+ */
13
+ priority?: number;
14
+
9
15
  /**
10
16
  * 执行拦截器逻辑
11
17
  * @param target - 目标对象(控制器实例的原型)
@@ -19,11 +25,11 @@ export interface Interceptor {
19
25
  execute<T>(
20
26
  target: unknown,
21
27
  propertyKey: string | symbol,
22
- originalMethod: (...args: unknown[]) => T | Promise<T>,
23
- args: unknown[],
28
+ originalMethod: (...args: any[]) => T | Promise<T>,
29
+ args: any[],
24
30
  container: Container,
25
31
  context?: Context,
26
- ): Promise<T>;
32
+ ): Promise<any>;
27
33
  }
28
34
 
29
35
  /**
@@ -49,4 +55,3 @@ export interface InterceptorMetadata {
49
55
  * 拦截器注册表 Token
50
56
  */
51
57
  export const INTERCEPTOR_REGISTRY_TOKEN = Symbol('@dangao/bun-server:interceptor-registry');
52
-
@@ -1,4 +1,5 @@
1
1
  import type { ServiceInstance } from '../service-registry/types';
2
+ export type { ServiceInstance } from '../service-registry/types';
2
3
 
3
4
  /**
4
5
  * 负载均衡策略类型
@@ -183,4 +184,3 @@ export class ServiceCallError extends Error {
183
184
  this.name = 'ServiceCallError';
184
185
  }
185
186
  }
186
-
@@ -172,14 +172,27 @@ export class Tracer {
172
172
  /**
173
173
  * 添加 Span 事件
174
174
  */
175
- public addSpanEvent(spanId: SpanId, event: Omit<SpanEvent, 'timestamp'>): void {
175
+ public addSpanEvent(
176
+ spanId: SpanId,
177
+ event: string,
178
+ attributes?: Record<string, string | number | boolean>,
179
+ ): void;
180
+ public addSpanEvent(spanId: SpanId, event: Omit<SpanEvent, 'timestamp'>): void;
181
+ public addSpanEvent(
182
+ spanId: SpanId,
183
+ event: string | Omit<SpanEvent, 'timestamp'>,
184
+ attributes?: Record<string, string | number | boolean>,
185
+ ): void {
176
186
  const span = this.activeSpans.get(spanId);
177
187
  if (span) {
178
188
  if (!span.events) {
179
189
  span.events = [];
180
190
  }
191
+ const spanEvent = typeof event === 'string'
192
+ ? { name: event, attributes }
193
+ : event;
181
194
  span.events.push({
182
- ...event,
195
+ ...spanEvent,
183
196
  timestamp: Date.now(),
184
197
  });
185
198
  }
@@ -290,4 +303,3 @@ export class Tracer {
290
303
  this.activeSpans.clear();
291
304
  }
292
305
  }
293
-
@@ -3,13 +3,15 @@ import { FileHandler } from '../../request/file-handler';
3
3
 
4
4
  export interface FileUploadOptions {
5
5
  maxSize?: number;
6
+ maxFileSize?: number;
7
+ uploadDir?: string;
6
8
  }
7
9
 
8
10
  /**
9
11
  * 简单的文件上传中间件:解析 multipart/form-data 并将文件附加到 context.body
10
12
  */
11
13
  export function createFileUploadMiddleware(options: FileUploadOptions = {}): Middleware {
12
- const maxSize = options.maxSize ?? 10 * 1024 * 1024;
14
+ const maxSize = options.maxSize ?? options.maxFileSize ?? 10 * 1024 * 1024;
13
15
 
14
16
  return async (context, next) => {
15
17
  const contentType = context.getHeader('Content-Type');
@@ -39,4 +41,3 @@ export function createFileUploadMiddleware(options: FileUploadOptions = {}): Mid
39
41
  };
40
42
  }
41
43
 
42
-
@@ -88,7 +88,12 @@ export interface RateLimitOptions {
88
88
  /**
89
89
  * 时间窗口内的最大请求数
90
90
  */
91
- max: number;
91
+ max?: number;
92
+
93
+ /**
94
+ * 时间窗口内的最大请求数别名,兼容装饰器早期写法。
95
+ */
96
+ limit?: number;
92
97
 
93
98
  /**
94
99
  * 时间窗口(毫秒)
@@ -108,6 +113,11 @@ export interface RateLimitOptions {
108
113
  */
109
114
  keyGenerator?: (context: Context) => string | Promise<string>;
110
115
 
116
+ /**
117
+ * 返回 true 时跳过限流。
118
+ */
119
+ skip?: (context: Context) => boolean | Promise<boolean>;
120
+
111
121
  /**
112
122
  * 是否跳过成功响应(只对错误响应计数)
113
123
  * @default false
@@ -157,9 +167,11 @@ function defaultKeyGenerator(context: Context): string {
157
167
  export function createRateLimitMiddleware(options: RateLimitOptions): Middleware {
158
168
  const {
159
169
  max,
170
+ limit,
160
171
  windowMs = 60000, // 默认 1 分钟
161
172
  store = new MemoryRateLimitStore(),
162
173
  keyGenerator = defaultKeyGenerator,
174
+ skip,
163
175
  skipSuccessfulRequests = false,
164
176
  skipFailedRequests = false,
165
177
  message = 'Too Many Requests',
@@ -167,31 +179,36 @@ export function createRateLimitMiddleware(options: RateLimitOptions): Middleware
167
179
  standardHeaders = true,
168
180
  legacyHeaders = true,
169
181
  } = options;
182
+ const requestLimit = limit ?? max ?? 100;
170
183
 
171
184
  return async (context: Context, next) => {
185
+ if (skip && await skip(context)) {
186
+ return await next();
187
+ }
188
+
172
189
  // 生成限流键
173
190
  const key = await keyGenerator(context);
174
191
  const currentCount = await store.increment(key, windowMs);
175
192
 
176
193
  // 计算剩余请求数和重置时间
177
- const remaining = Math.max(0, max - currentCount);
194
+ const remaining = Math.max(0, requestLimit - currentCount);
178
195
  const resetTime = Date.now() + windowMs;
179
196
 
180
197
  // 设置响应头
181
198
  if (standardHeaders) {
182
- context.setHeader('RateLimit-Limit', max.toString());
199
+ context.setHeader('RateLimit-Limit', requestLimit.toString());
183
200
  context.setHeader('RateLimit-Remaining', remaining.toString());
184
201
  context.setHeader('RateLimit-Reset', Math.ceil(resetTime / 1000).toString());
185
202
  }
186
203
 
187
204
  if (legacyHeaders) {
188
- context.setHeader('X-RateLimit-Limit', max.toString());
205
+ context.setHeader('X-RateLimit-Limit', requestLimit.toString());
189
206
  context.setHeader('X-RateLimit-Remaining', remaining.toString());
190
207
  context.setHeader('X-RateLimit-Reset', Math.ceil(resetTime / 1000).toString());
191
208
  }
192
209
 
193
210
  // 检查是否超过限制
194
- if (currentCount > max) {
211
+ if (currentCount > requestLimit) {
195
212
  context.setStatus(statusCode);
196
213
  return context.createErrorResponse({
197
214
  error: message,
@@ -17,7 +17,7 @@ import { getRuntime } from '../platform/runtime';
17
17
  */
18
18
  @Injectable()
19
19
  export class QueueService {
20
- private store: QueueStore;
20
+ public readonly store: QueueStore;
21
21
  private defaultQueue: string;
22
22
  private enableWorker: boolean;
23
23
  private concurrency: number;
@@ -24,6 +24,11 @@ export interface JobOptions {
24
24
  */
25
25
  attempts?: number;
26
26
 
27
+ /**
28
+ * 任务重试次数别名,兼容早期 API。
29
+ */
30
+ retries?: number;
31
+
27
32
  /**
28
33
  * 任务重试延迟(毫秒)
29
34
  */
@@ -90,7 +95,22 @@ export interface Job<T = JobData> {
90
95
  /**
91
96
  * 更新时间
92
97
  */
93
- updatedAt: number;
98
+ updatedAt?: number;
99
+
100
+ /**
101
+ * 完成结果
102
+ */
103
+ result?: unknown;
104
+
105
+ /**
106
+ * 完成时间
107
+ */
108
+ completedAt?: number;
109
+
110
+ /**
111
+ * 失败错误信息
112
+ */
113
+ error?: string;
94
114
  }
95
115
 
96
116
  /**
@@ -141,6 +161,25 @@ export interface QueueStore {
141
161
  status: Job['status'],
142
162
  ): Promise<boolean>;
143
163
 
164
+ complete?(
165
+ queueName: string,
166
+ jobId: string,
167
+ result?: unknown,
168
+ ): Promise<boolean>;
169
+
170
+ fail?(
171
+ queueName: string,
172
+ jobId: string,
173
+ error: Error,
174
+ ): Promise<boolean>;
175
+
176
+ getStats?(queueName: string): Promise<{
177
+ waiting: number;
178
+ active: number;
179
+ completed: number;
180
+ failed: number;
181
+ }>;
182
+
144
183
  /**
145
184
  * 删除任务
146
185
  * @param queueName - 队列名称
@@ -1,5 +1,4 @@
1
1
  import 'reflect-metadata';
2
- import type { RouteHandler } from './types';
3
2
  import { RouteRegistry } from './registry';
4
3
  import type { HttpMethod } from './types';
5
4
  import { CONTROLLER_METADATA_KEY } from '../controller/controller';
@@ -15,7 +14,7 @@ export const ROUTE_METADATA_KEY = Symbol('route');
15
14
  export interface RouteMetadata {
16
15
  method: HttpMethod;
17
16
  path: string;
18
- handler: RouteHandler;
17
+ handler: (...args: any[]) => unknown;
19
18
  /**
20
19
  * 属性键(用于控制器方法)
21
20
  */
@@ -75,7 +74,7 @@ function createRouteDecorator(method: HttpMethod, path: string = '') {
75
74
  existingRoutes.push({
76
75
  method,
77
76
  path: path ?? '',
78
- handler: descriptor.value as RouteHandler,
77
+ handler: descriptor.value as (...args: any[]) => unknown,
79
78
  propertyKey: propertyKeyStr || undefined,
80
79
  });
81
80
  Reflect.defineMetadata(ROUTE_METADATA_KEY, existingRoutes, target);
@@ -16,6 +16,8 @@ export interface CanActivate {
16
16
  canActivate(context: ExecutionContext): boolean | Promise<boolean>;
17
17
  }
18
18
 
19
+ export type Guard = CanActivate;
20
+
19
21
  /**
20
22
  * HTTP 参数主机接口
21
23
  * 提供 HTTP 请求相关的上下文信息
@@ -141,4 +143,3 @@ export const GUARD_REGISTRY_TOKEN = Symbol('@dangao/bun-server:guard-registry');
141
143
  * Roles 元数据键
142
144
  */
143
145
  export const ROLES_METADATA_KEY = Symbol('@dangao/bun-server:roles');
144
-
@@ -35,7 +35,7 @@ export interface Credentials {
35
35
  /**
36
36
  * 凭据数据
37
37
  */
38
- data: unknown;
38
+ data: any;
39
39
  }
40
40
 
41
41
  /**
@@ -162,4 +162,3 @@ export interface SecurityContext {
162
162
  */
163
163
  getAuthorities(): string[];
164
164
  }
165
-
@@ -25,7 +25,7 @@ export class SessionService {
25
25
  ) {
26
26
  this.store = options.store!;
27
27
  this.name = options.name ?? 'sessionId';
28
- this.maxAge = options.maxAge ?? 86400000; // 24 小时
28
+ this.maxAge = options.maxAge ?? options.ttl ?? 86400000; // 24 小时
29
29
  this.rolling = options.rolling ?? true;
30
30
  this.cookieOptions = {
31
31
  secure: options.cookie?.secure ?? false,
@@ -317,6 +317,11 @@ export interface SessionModuleOptions {
317
317
  */
318
318
  maxAge?: number;
319
319
 
320
+ /**
321
+ * Session 最大存活时间别名。
322
+ */
323
+ ttl?: number;
324
+
320
325
  /**
321
326
  * 是否在每次访问时更新过期时间
322
327
  * @default true
@@ -327,6 +332,11 @@ export interface SessionModuleOptions {
327
332
  * Cookie 选项
328
333
  */
329
334
  cookie?: {
335
+ /**
336
+ * Cookie 名称别名,优先使用顶层 name。
337
+ */
338
+ name?: string;
339
+
330
340
  /**
331
341
  * 是否只在 HTTPS 下发送
332
342
  * @default false
@@ -50,13 +50,25 @@ export function ApiOperation(metadata: ApiOperationMetadata): MethodDecorator {
50
50
  * 用于描述 API 参数
51
51
  * @param metadata - 参数元数据
52
52
  */
53
- export function ApiParam(metadata: ApiParamMetadata): ParameterDecorator {
54
- return function (target: unknown, propertyKey: string | symbol | undefined, parameterIndex: number) {
53
+ export function ApiParam(metadata: ApiParamMetadata): ParameterDecorator & MethodDecorator {
54
+ const decorator = (
55
+ target: Object,
56
+ propertyKey: string | symbol | undefined,
57
+ descriptorOrParameterIndex: TypedPropertyDescriptor<any> | number,
58
+ ): void => {
59
+ const paramMetadata: ApiParamMetadata = {
60
+ in: 'path',
61
+ ...metadata,
62
+ };
55
63
  const existingParams: Array<{ index: number; metadata: ApiParamMetadata }> =
56
64
  Reflect.getMetadata(API_PARAM_METADATA_KEY, target as Object, propertyKey!) || [];
57
- existingParams.push({ index: parameterIndex, metadata });
65
+ const index = typeof descriptorOrParameterIndex === 'number'
66
+ ? descriptorOrParameterIndex
67
+ : -1;
68
+ existingParams.push({ index, metadata: paramMetadata });
58
69
  Reflect.defineMetadata(API_PARAM_METADATA_KEY, existingParams, target as Object, propertyKey!);
59
70
  };
71
+ return decorator as ParameterDecorator & MethodDecorator;
60
72
  }
61
73
 
62
74
  /**
@@ -130,4 +142,3 @@ export function getApiResponses(
130
142
  ): ApiResponseMetadata[] {
131
143
  return Reflect.getMetadata(API_RESPONSE_METADATA_KEY, target as Object, propertyKey) || [];
132
144
  }
133
-
@@ -139,7 +139,7 @@ export class SwaggerGenerator {
139
139
  for (const match of pathParamMatches) {
140
140
  const paramName = match[1];
141
141
  // 检查是否已经有手动定义的参数
142
- const existingParam = params.find((p) => p.metadata.name === paramName && p.metadata.in === 'path');
142
+ const existingParam = params.find((p) => p.metadata.name === paramName && (p.metadata.in ?? 'path') === 'path');
143
143
  if (!existingParam) {
144
144
  // 自动添加路径参数
145
145
  pathParams.push({
@@ -155,7 +155,7 @@ export class SwaggerGenerator {
155
155
  for (const param of params) {
156
156
  pathParams.push({
157
157
  name: param.metadata.name,
158
- in: param.metadata.in,
158
+ in: param.metadata.in ?? 'path',
159
159
  description: param.metadata.description,
160
160
  required: param.metadata.required,
161
161
  schema: param.metadata.schema,
@@ -332,4 +332,3 @@ export class SwaggerGenerator {
332
332
  return path;
333
333
  }
334
334
  }
335
-
@@ -60,7 +60,7 @@ export interface ApiParamMetadata {
60
60
  enum?: unknown[];
61
61
  default?: unknown;
62
62
  };
63
- in: 'query' | 'path' | 'header' | 'cookie';
63
+ in?: 'query' | 'path' | 'header' | 'cookie';
64
64
  }
65
65
 
66
66
  /**
@@ -185,4 +185,3 @@ export interface SwaggerDocument {
185
185
  patch?: SwaggerPathItem;
186
186
  }>;
187
187
  }
188
-
@@ -22,7 +22,7 @@ export class PerformanceHarness {
22
22
  public static async benchmark(
23
23
  name: string,
24
24
  iterations: number,
25
- runner: (iteration: number) => void | Promise<void>,
25
+ runner: (iteration: number) => unknown | Promise<unknown>,
26
26
  ): Promise<BenchmarkResult> {
27
27
  if (iterations <= 0) {
28
28
  throw new Error('iterations must be greater than 0');
@@ -93,4 +93,3 @@ export class StressTester {
93
93
  };
94
94
  }
95
95
  }
96
-
@@ -9,7 +9,7 @@ interface RequestOptions {
9
9
  interface TestResponse {
10
10
  status: number;
11
11
  headers: Headers;
12
- body: unknown;
12
+ body: any;
13
13
  text: string;
14
14
  ok: boolean;
15
15
  }
@@ -94,7 +94,7 @@ export class TestHttpClient {
94
94
  const response = await fetch(url, fetchOptions);
95
95
  const text = await response.text();
96
96
 
97
- let body: unknown;
97
+ let body: any;
98
98
  try {
99
99
  body = JSON.parse(text);
100
100
  } catch (_error) {
@@ -5,7 +5,7 @@ import { Container } from '../di/container';
5
5
  import { ModuleRegistry } from '../di/module-registry';
6
6
  import { ControllerRegistry } from '../controller/controller';
7
7
  import { RouteRegistry } from '../router/registry';
8
- import { MODULE_METADATA_KEY, type ModuleMetadata, type ModuleClass, type ModuleProvider, type ProviderToken } from '../di/module';
8
+ import { MODULE_METADATA_KEY, invokeFactoryProvider, type ModuleMetadata, type ModuleClass, type ModuleProvider, type ProviderToken } from '../di/module';
9
9
  import type { Constructor } from '../core/types';
10
10
  import { TestHttpClient } from './test-client';
11
11
 
@@ -13,7 +13,7 @@ interface ProviderOverride {
13
13
  token: ProviderToken;
14
14
  useValue?: unknown;
15
15
  useClass?: Constructor<unknown>;
16
- useFactory?: () => unknown;
16
+ useFactory?: (...args: any[]) => unknown;
17
17
  }
18
18
 
19
19
  /**
@@ -75,7 +75,7 @@ export class TestingModuleBuilder {
75
75
  } else if (override.useClass) {
76
76
  result.push({ provide: override.token, useClass: override.useClass });
77
77
  } else if (override.useFactory) {
78
- result.push({ provide: override.token, useFactory: override.useFactory as (container: Container) => unknown });
78
+ result.push({ provide: override.token, useFactory: override.useFactory });
79
79
  }
80
80
  overrideMap.delete(key as string | symbol);
81
81
  } else {
@@ -121,7 +121,7 @@ class ProviderOverrideBuilder {
121
121
  /**
122
122
  * 使用工厂函数覆盖
123
123
  */
124
- public useFactory(factory: () => unknown): TestingModuleBuilder {
124
+ public useFactory(factory: (...args: any[]) => unknown): TestingModuleBuilder {
125
125
  this.builder.addOverride({ token: this.token, useFactory: factory });
126
126
  return this.builder;
127
127
  }
@@ -177,7 +177,7 @@ export class TestingModule {
177
177
  container.registerInstance(provider.provide, provider.useValue);
178
178
  } else if ('useFactory' in provider && provider.provide) {
179
179
  container.register(provider.provide as Constructor<unknown>, {
180
- factory: () => (provider as { useFactory: (container: Container) => unknown }).useFactory(container),
180
+ factory: () => invokeFactoryProvider(provider, container),
181
181
  });
182
182
  } else if ('useClass' in provider) {
183
183
  const token = (provider as { provide?: ProviderToken }).provide ?? (provider as { useClass: Constructor<unknown> }).useClass;
@@ -9,10 +9,15 @@ export interface ValidationIssue {
9
9
  */
10
10
  property?: string;
11
11
 
12
+ /**
13
+ * 属性路径别名,兼容早期错误对象形状。
14
+ */
15
+ path?: string;
16
+
12
17
  /**
13
18
  * 失败的规则名称
14
19
  */
15
- rule: string;
20
+ rule?: string;
16
21
 
17
22
  /**
18
23
  * 错误信息
@@ -73,4 +78,3 @@ export class ValidationError extends Error {
73
78
  }
74
79
  }
75
80
 
76
-
@@ -0,0 +1,11 @@
1
+ declare module 'bun:test' {
2
+ export const describe: any;
3
+ export const test: any;
4
+ export const it: any;
5
+ export const expect: any;
6
+ export const beforeEach: any;
7
+ export const afterEach: any;
8
+ export const beforeAll: any;
9
+ export const afterAll: any;
10
+ export const mock: any;
11
+ }