@dangao/bun-server 0.3.0 → 1.0.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 (96) hide show
  1. package/dist/auth/controller.d.ts +1 -1
  2. package/dist/auth/controller.d.ts.map +1 -1
  3. package/dist/cache/cache-module.d.ts +9 -0
  4. package/dist/cache/cache-module.d.ts.map +1 -0
  5. package/dist/cache/decorators.d.ts +110 -0
  6. package/dist/cache/decorators.d.ts.map +1 -0
  7. package/dist/cache/index.d.ts +6 -0
  8. package/dist/cache/index.d.ts.map +1 -0
  9. package/dist/cache/service.d.ts +76 -0
  10. package/dist/cache/service.d.ts.map +1 -0
  11. package/dist/cache/types.d.ts +160 -0
  12. package/dist/cache/types.d.ts.map +1 -0
  13. package/dist/controller/controller.d.ts.map +1 -1
  14. package/dist/controller/decorators.d.ts +9 -1
  15. package/dist/controller/decorators.d.ts.map +1 -1
  16. package/dist/controller/param-binder.d.ts +4 -1
  17. package/dist/controller/param-binder.d.ts.map +1 -1
  18. package/dist/core/application.d.ts +10 -2
  19. package/dist/core/application.d.ts.map +1 -1
  20. package/dist/database/connection-manager.d.ts +72 -0
  21. package/dist/database/connection-manager.d.ts.map +1 -0
  22. package/dist/database/connection-pool.d.ts +79 -0
  23. package/dist/database/connection-pool.d.ts.map +1 -0
  24. package/dist/database/database-extension.d.ts +20 -0
  25. package/dist/database/database-extension.d.ts.map +1 -0
  26. package/dist/database/database-module.d.ts +18 -0
  27. package/dist/database/database-module.d.ts.map +1 -0
  28. package/dist/database/health-indicator.d.ts +15 -0
  29. package/dist/database/health-indicator.d.ts.map +1 -0
  30. package/dist/database/index.d.ts +9 -0
  31. package/dist/database/index.d.ts.map +1 -0
  32. package/dist/database/orm/decorators.d.ts +70 -0
  33. package/dist/database/orm/decorators.d.ts.map +1 -0
  34. package/dist/database/orm/drizzle-repository.d.ts +34 -0
  35. package/dist/database/orm/drizzle-repository.d.ts.map +1 -0
  36. package/dist/database/orm/index.d.ts +11 -0
  37. package/dist/database/orm/index.d.ts.map +1 -0
  38. package/dist/database/orm/repository-decorator.d.ts +21 -0
  39. package/dist/database/orm/repository-decorator.d.ts.map +1 -0
  40. package/dist/database/orm/repository.d.ts +36 -0
  41. package/dist/database/orm/repository.d.ts.map +1 -0
  42. package/dist/database/orm/service.d.ts +26 -0
  43. package/dist/database/orm/service.d.ts.map +1 -0
  44. package/dist/database/orm/transaction-decorator.d.ts +17 -0
  45. package/dist/database/orm/transaction-decorator.d.ts.map +1 -0
  46. package/dist/database/orm/transaction-interceptor.d.ts +28 -0
  47. package/dist/database/orm/transaction-interceptor.d.ts.map +1 -0
  48. package/dist/database/orm/transaction-manager.d.ts +77 -0
  49. package/dist/database/orm/transaction-manager.d.ts.map +1 -0
  50. package/dist/database/orm/transaction-types.d.ts +136 -0
  51. package/dist/database/orm/transaction-types.d.ts.map +1 -0
  52. package/dist/database/orm/types.d.ts +95 -0
  53. package/dist/database/orm/types.d.ts.map +1 -0
  54. package/dist/database/service.d.ts +71 -0
  55. package/dist/database/service.d.ts.map +1 -0
  56. package/dist/database/types.d.ts +168 -0
  57. package/dist/database/types.d.ts.map +1 -0
  58. package/dist/error/error-codes.d.ts +49 -3
  59. package/dist/error/error-codes.d.ts.map +1 -1
  60. package/dist/error/handler.d.ts.map +1 -1
  61. package/dist/error/http-exception.d.ts +26 -7
  62. package/dist/error/http-exception.d.ts.map +1 -1
  63. package/dist/error/i18n.d.ts +46 -2
  64. package/dist/error/i18n.d.ts.map +1 -1
  65. package/dist/error/index.d.ts +1 -1
  66. package/dist/error/index.d.ts.map +1 -1
  67. package/dist/index.d.ts +7 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +2454 -111
  70. package/dist/middleware/pipeline.d.ts.map +1 -1
  71. package/dist/queue/decorators.d.ts +63 -0
  72. package/dist/queue/decorators.d.ts.map +1 -0
  73. package/dist/queue/index.d.ts +6 -0
  74. package/dist/queue/index.d.ts.map +1 -0
  75. package/dist/queue/queue-module.d.ts +9 -0
  76. package/dist/queue/queue-module.d.ts.map +1 -0
  77. package/dist/queue/service.d.ts +93 -0
  78. package/dist/queue/service.d.ts.map +1 -0
  79. package/dist/queue/types.d.ts +204 -0
  80. package/dist/queue/types.d.ts.map +1 -0
  81. package/dist/router/router.d.ts +16 -1
  82. package/dist/router/router.d.ts.map +1 -1
  83. package/dist/session/decorators.d.ts +16 -0
  84. package/dist/session/decorators.d.ts.map +1 -0
  85. package/dist/session/index.d.ts +8 -0
  86. package/dist/session/index.d.ts.map +1 -0
  87. package/dist/session/middleware.d.ts +8 -0
  88. package/dist/session/middleware.d.ts.map +1 -0
  89. package/dist/session/service.d.ts +86 -0
  90. package/dist/session/service.d.ts.map +1 -0
  91. package/dist/session/session-module.d.ts +9 -0
  92. package/dist/session/session-module.d.ts.map +1 -0
  93. package/dist/session/types.d.ts +193 -0
  94. package/dist/session/types.d.ts.map +1 -0
  95. package/package.json +1 -1
  96. package/readme.md +98 -117
package/dist/index.js CHANGED
@@ -1,5 +1,20 @@
1
1
  // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
2
4
  var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
3
18
  var __export = (target, all) => {
4
19
  for (var name in all)
5
20
  __defProp(target, name, {
@@ -25,6 +40,7 @@ var __legacyMetadataTS = (k, v) => {
25
40
  return Reflect.metadata(k, v);
26
41
  };
27
42
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
43
+ var __require = import.meta.require;
28
44
 
29
45
  // src/validation/decorators.ts
30
46
  import"reflect-metadata";
@@ -175,38 +191,98 @@ var init_error_codes = __esm(() => {
175
191
  ["INVALID_REQUEST" /* INVALID_REQUEST */]: 400,
176
192
  ["RESOURCE_NOT_FOUND" /* RESOURCE_NOT_FOUND */]: 404,
177
193
  ["METHOD_NOT_ALLOWED" /* METHOD_NOT_ALLOWED */]: 405,
194
+ ["RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */]: 429,
195
+ ["SERVICE_UNAVAILABLE" /* SERVICE_UNAVAILABLE */]: 503,
196
+ ["TIMEOUT" /* TIMEOUT */]: 408,
178
197
  ["AUTH_REQUIRED" /* AUTH_REQUIRED */]: 401,
179
198
  ["AUTH_INVALID_TOKEN" /* AUTH_INVALID_TOKEN */]: 401,
180
199
  ["AUTH_TOKEN_EXPIRED" /* AUTH_TOKEN_EXPIRED */]: 401,
181
200
  ["AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */]: 403,
201
+ ["AUTH_INVALID_CREDENTIALS" /* AUTH_INVALID_CREDENTIALS */]: 401,
202
+ ["AUTH_ACCOUNT_LOCKED" /* AUTH_ACCOUNT_LOCKED */]: 423,
203
+ ["AUTH_ACCOUNT_DISABLED" /* AUTH_ACCOUNT_DISABLED */]: 403,
182
204
  ["VALIDATION_FAILED" /* VALIDATION_FAILED */]: 400,
183
205
  ["VALIDATION_REQUIRED_FIELD" /* VALIDATION_REQUIRED_FIELD */]: 400,
184
206
  ["VALIDATION_INVALID_FORMAT" /* VALIDATION_INVALID_FORMAT */]: 400,
185
207
  ["VALIDATION_OUT_OF_RANGE" /* VALIDATION_OUT_OF_RANGE */]: 400,
208
+ ["VALIDATION_TYPE_MISMATCH" /* VALIDATION_TYPE_MISMATCH */]: 400,
209
+ ["VALIDATION_CONSTRAINT_VIOLATION" /* VALIDATION_CONSTRAINT_VIOLATION */]: 400,
186
210
  ["OAUTH2_INVALID_CLIENT" /* OAUTH2_INVALID_CLIENT */]: 400,
187
211
  ["OAUTH2_INVALID_GRANT" /* OAUTH2_INVALID_GRANT */]: 400,
188
212
  ["OAUTH2_INVALID_SCOPE" /* OAUTH2_INVALID_SCOPE */]: 400,
189
213
  ["OAUTH2_INVALID_REDIRECT_URI" /* OAUTH2_INVALID_REDIRECT_URI */]: 400,
190
- ["OAUTH2_UNSUPPORTED_GRANT_TYPE" /* OAUTH2_UNSUPPORTED_GRANT_TYPE */]: 400
214
+ ["OAUTH2_UNSUPPORTED_GRANT_TYPE" /* OAUTH2_UNSUPPORTED_GRANT_TYPE */]: 400,
215
+ ["OAUTH2_ACCESS_DENIED" /* OAUTH2_ACCESS_DENIED */]: 403,
216
+ ["OAUTH2_SERVER_ERROR" /* OAUTH2_SERVER_ERROR */]: 500,
217
+ ["DATABASE_CONNECTION_FAILED" /* DATABASE_CONNECTION_FAILED */]: 503,
218
+ ["DATABASE_QUERY_FAILED" /* DATABASE_QUERY_FAILED */]: 500,
219
+ ["DATABASE_TRANSACTION_FAILED" /* DATABASE_TRANSACTION_FAILED */]: 500,
220
+ ["DATABASE_CONSTRAINT_VIOLATION" /* DATABASE_CONSTRAINT_VIOLATION */]: 409,
221
+ ["DATABASE_TIMEOUT" /* DATABASE_TIMEOUT */]: 504,
222
+ ["DATABASE_POOL_EXHAUSTED" /* DATABASE_POOL_EXHAUSTED */]: 503,
223
+ ["DATABASE_MIGRATION_FAILED" /* DATABASE_MIGRATION_FAILED */]: 500,
224
+ ["FILE_NOT_FOUND" /* FILE_NOT_FOUND */]: 404,
225
+ ["FILE_UPLOAD_FAILED" /* FILE_UPLOAD_FAILED */]: 500,
226
+ ["FILE_DOWNLOAD_FAILED" /* FILE_DOWNLOAD_FAILED */]: 500,
227
+ ["FILE_SIZE_EXCEEDED" /* FILE_SIZE_EXCEEDED */]: 413,
228
+ ["FILE_TYPE_NOT_ALLOWED" /* FILE_TYPE_NOT_ALLOWED */]: 415,
229
+ ["FILE_ACCESS_DENIED" /* FILE_ACCESS_DENIED */]: 403,
230
+ ["FILE_PATH_TRAVERSAL" /* FILE_PATH_TRAVERSAL */]: 400,
231
+ ["MIDDLEWARE_EXECUTION_FAILED" /* MIDDLEWARE_EXECUTION_FAILED */]: 500,
232
+ ["MIDDLEWARE_TIMEOUT" /* MIDDLEWARE_TIMEOUT */]: 504,
233
+ ["CORS_NOT_ALLOWED" /* CORS_NOT_ALLOWED */]: 403,
234
+ ["CONFIG_INVALID" /* CONFIG_INVALID */]: 500,
235
+ ["CONFIG_MISSING" /* CONFIG_MISSING */]: 500,
236
+ ["CONFIG_VALIDATION_FAILED" /* CONFIG_VALIDATION_FAILED */]: 500
191
237
  };
192
238
  ERROR_CODE_MESSAGES = {
193
239
  ["INTERNAL_ERROR" /* INTERNAL_ERROR */]: "Internal Server Error",
194
240
  ["INVALID_REQUEST" /* INVALID_REQUEST */]: "Invalid Request",
195
241
  ["RESOURCE_NOT_FOUND" /* RESOURCE_NOT_FOUND */]: "Resource Not Found",
196
242
  ["METHOD_NOT_ALLOWED" /* METHOD_NOT_ALLOWED */]: "Method Not Allowed",
243
+ ["RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */]: "Rate Limit Exceeded",
244
+ ["SERVICE_UNAVAILABLE" /* SERVICE_UNAVAILABLE */]: "Service Unavailable",
245
+ ["TIMEOUT" /* TIMEOUT */]: "Request Timeout",
197
246
  ["AUTH_REQUIRED" /* AUTH_REQUIRED */]: "Authentication Required",
198
247
  ["AUTH_INVALID_TOKEN" /* AUTH_INVALID_TOKEN */]: "Invalid Authentication Token",
199
248
  ["AUTH_TOKEN_EXPIRED" /* AUTH_TOKEN_EXPIRED */]: "Authentication Token Expired",
200
249
  ["AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */]: "Insufficient Permissions",
250
+ ["AUTH_INVALID_CREDENTIALS" /* AUTH_INVALID_CREDENTIALS */]: "Invalid Credentials",
251
+ ["AUTH_ACCOUNT_LOCKED" /* AUTH_ACCOUNT_LOCKED */]: "Account Locked",
252
+ ["AUTH_ACCOUNT_DISABLED" /* AUTH_ACCOUNT_DISABLED */]: "Account Disabled",
201
253
  ["VALIDATION_FAILED" /* VALIDATION_FAILED */]: "Validation Failed",
202
254
  ["VALIDATION_REQUIRED_FIELD" /* VALIDATION_REQUIRED_FIELD */]: "Required Field Missing",
203
255
  ["VALIDATION_INVALID_FORMAT" /* VALIDATION_INVALID_FORMAT */]: "Invalid Format",
204
256
  ["VALIDATION_OUT_OF_RANGE" /* VALIDATION_OUT_OF_RANGE */]: "Value Out of Range",
257
+ ["VALIDATION_TYPE_MISMATCH" /* VALIDATION_TYPE_MISMATCH */]: "Type Mismatch",
258
+ ["VALIDATION_CONSTRAINT_VIOLATION" /* VALIDATION_CONSTRAINT_VIOLATION */]: "Constraint Violation",
205
259
  ["OAUTH2_INVALID_CLIENT" /* OAUTH2_INVALID_CLIENT */]: "Invalid Client",
206
260
  ["OAUTH2_INVALID_GRANT" /* OAUTH2_INVALID_GRANT */]: "Invalid Grant",
207
261
  ["OAUTH2_INVALID_SCOPE" /* OAUTH2_INVALID_SCOPE */]: "Invalid Scope",
208
262
  ["OAUTH2_INVALID_REDIRECT_URI" /* OAUTH2_INVALID_REDIRECT_URI */]: "Invalid Redirect URI",
209
- ["OAUTH2_UNSUPPORTED_GRANT_TYPE" /* OAUTH2_UNSUPPORTED_GRANT_TYPE */]: "Unsupported Grant Type"
263
+ ["OAUTH2_UNSUPPORTED_GRANT_TYPE" /* OAUTH2_UNSUPPORTED_GRANT_TYPE */]: "Unsupported Grant Type",
264
+ ["OAUTH2_ACCESS_DENIED" /* OAUTH2_ACCESS_DENIED */]: "Access Denied",
265
+ ["OAUTH2_SERVER_ERROR" /* OAUTH2_SERVER_ERROR */]: "OAuth2 Server Error",
266
+ ["DATABASE_CONNECTION_FAILED" /* DATABASE_CONNECTION_FAILED */]: "Database Connection Failed",
267
+ ["DATABASE_QUERY_FAILED" /* DATABASE_QUERY_FAILED */]: "Database Query Failed",
268
+ ["DATABASE_TRANSACTION_FAILED" /* DATABASE_TRANSACTION_FAILED */]: "Database Transaction Failed",
269
+ ["DATABASE_CONSTRAINT_VIOLATION" /* DATABASE_CONSTRAINT_VIOLATION */]: "Database Constraint Violation",
270
+ ["DATABASE_TIMEOUT" /* DATABASE_TIMEOUT */]: "Database Timeout",
271
+ ["DATABASE_POOL_EXHAUSTED" /* DATABASE_POOL_EXHAUSTED */]: "Database Connection Pool Exhausted",
272
+ ["DATABASE_MIGRATION_FAILED" /* DATABASE_MIGRATION_FAILED */]: "Database Migration Failed",
273
+ ["FILE_NOT_FOUND" /* FILE_NOT_FOUND */]: "File Not Found",
274
+ ["FILE_UPLOAD_FAILED" /* FILE_UPLOAD_FAILED */]: "File Upload Failed",
275
+ ["FILE_DOWNLOAD_FAILED" /* FILE_DOWNLOAD_FAILED */]: "File Download Failed",
276
+ ["FILE_SIZE_EXCEEDED" /* FILE_SIZE_EXCEEDED */]: "File Size Exceeded",
277
+ ["FILE_TYPE_NOT_ALLOWED" /* FILE_TYPE_NOT_ALLOWED */]: "File Type Not Allowed",
278
+ ["FILE_ACCESS_DENIED" /* FILE_ACCESS_DENIED */]: "File Access Denied",
279
+ ["FILE_PATH_TRAVERSAL" /* FILE_PATH_TRAVERSAL */]: "Path Traversal Detected",
280
+ ["MIDDLEWARE_EXECUTION_FAILED" /* MIDDLEWARE_EXECUTION_FAILED */]: "Middleware Execution Failed",
281
+ ["MIDDLEWARE_TIMEOUT" /* MIDDLEWARE_TIMEOUT */]: "Middleware Timeout",
282
+ ["CORS_NOT_ALLOWED" /* CORS_NOT_ALLOWED */]: "CORS Not Allowed",
283
+ ["CONFIG_INVALID" /* CONFIG_INVALID */]: "Invalid Configuration",
284
+ ["CONFIG_MISSING" /* CONFIG_MISSING */]: "Missing Configuration",
285
+ ["CONFIG_VALIDATION_FAILED" /* CONFIG_VALIDATION_FAILED */]: "Configuration Validation Failed"
210
286
  };
211
287
  });
212
288
 
@@ -218,42 +294,44 @@ var init_http_exception = __esm(() => {
218
294
  status;
219
295
  code;
220
296
  details;
221
- constructor(status, message, details, code) {
297
+ messageParams;
298
+ constructor(status, message, details, code, messageParams) {
222
299
  super(message);
223
300
  this.name = this.constructor.name;
224
301
  this.status = status;
225
302
  this.code = code;
226
303
  this.details = details;
304
+ this.messageParams = messageParams;
227
305
  }
228
- static withCode(code, message, details) {
306
+ static withCode(code, message, details, messageParams) {
229
307
  const status = ERROR_CODE_TO_STATUS[code] || 500;
230
308
  const finalMessage = message || ERROR_CODE_MESSAGES[code] || "Internal Server Error";
231
- return new HttpException(status, finalMessage, details, code);
309
+ return new HttpException(status, finalMessage, details, code, messageParams);
232
310
  }
233
311
  };
234
312
  BadRequestException = class BadRequestException extends HttpException {
235
- constructor(message = "Bad Request", details, code) {
236
- super(400, message, details, code);
313
+ constructor(message = "Bad Request", details, code, messageParams) {
314
+ super(400, message, details, code, messageParams);
237
315
  }
238
316
  };
239
317
  UnauthorizedException = class UnauthorizedException extends HttpException {
240
- constructor(message = "Unauthorized", details, code) {
241
- super(401, message, details, code);
318
+ constructor(message = "Unauthorized", details, code, messageParams) {
319
+ super(401, message, details, code, messageParams);
242
320
  }
243
321
  };
244
322
  ForbiddenException = class ForbiddenException extends HttpException {
245
- constructor(message = "Forbidden", details, code) {
246
- super(403, message, details, code);
323
+ constructor(message = "Forbidden", details, code, messageParams) {
324
+ super(403, message, details, code, messageParams);
247
325
  }
248
326
  };
249
327
  NotFoundException = class NotFoundException extends HttpException {
250
- constructor(message = "Not Found", details, code) {
251
- super(404, message, details, code);
328
+ constructor(message = "Not Found", details, code, messageParams) {
329
+ super(404, message, details, code, messageParams);
252
330
  }
253
331
  };
254
332
  InternalServerErrorException = class InternalServerErrorException extends HttpException {
255
- constructor(message = "Internal Server Error", details, code) {
256
- super(500, message, details, code);
333
+ constructor(message = "Internal Server Error", details, code, messageParams) {
334
+ super(500, message, details, code, messageParams);
257
335
  }
258
336
  };
259
337
  });
@@ -295,18 +373,35 @@ class ErrorMessageI18n {
295
373
  static getLanguage() {
296
374
  return this.currentLanguage;
297
375
  }
298
- static getMessage(code, language) {
376
+ static getMessage(code, language, params) {
299
377
  const lang = language || this.currentLanguage;
300
378
  const messages = ERROR_MESSAGES_I18N[lang];
301
- return messages?.[code] || ERROR_CODE_MESSAGES[code] || "Internal Server Error";
379
+ let message = messages?.[code] || ERROR_CODE_MESSAGES[code] || "Internal Server Error";
380
+ if (params) {
381
+ message = this.replaceTemplate(message, params);
382
+ }
383
+ return message;
384
+ }
385
+ static replaceTemplate(template, params) {
386
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
387
+ const value = params[key];
388
+ return value !== undefined ? String(value) : match;
389
+ });
302
390
  }
303
391
  static parseLanguageFromHeader(acceptLanguage) {
304
392
  if (!acceptLanguage) {
305
393
  return "en";
306
394
  }
307
- if (acceptLanguage.includes("zh-CN") || acceptLanguage.includes("zh")) {
395
+ const lowerAcceptLanguage = acceptLanguage.toLowerCase();
396
+ if (lowerAcceptLanguage.includes("zh-cn") || lowerAcceptLanguage.includes("zh")) {
308
397
  return "zh-CN";
309
398
  }
399
+ if (lowerAcceptLanguage.includes("ja")) {
400
+ return "ja";
401
+ }
402
+ if (lowerAcceptLanguage.includes("ko")) {
403
+ return "ko";
404
+ }
310
405
  return "en";
311
406
  }
312
407
  }
@@ -322,19 +417,65 @@ var init_i18n = __esm(() => {
322
417
  ["INVALID_REQUEST" /* INVALID_REQUEST */]: "\u65E0\u6548\u7684\u8BF7\u6C42",
323
418
  ["RESOURCE_NOT_FOUND" /* RESOURCE_NOT_FOUND */]: "\u8D44\u6E90\u672A\u627E\u5230",
324
419
  ["METHOD_NOT_ALLOWED" /* METHOD_NOT_ALLOWED */]: "\u65B9\u6CD5\u4E0D\u5141\u8BB8",
420
+ ["RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */]: "\u8BF7\u6C42\u9891\u7387\u8D85\u9650",
421
+ ["SERVICE_UNAVAILABLE" /* SERVICE_UNAVAILABLE */]: "\u670D\u52A1\u4E0D\u53EF\u7528",
422
+ ["TIMEOUT" /* TIMEOUT */]: "\u8BF7\u6C42\u8D85\u65F6",
325
423
  ["AUTH_REQUIRED" /* AUTH_REQUIRED */]: "\u9700\u8981\u8BA4\u8BC1",
326
424
  ["AUTH_INVALID_TOKEN" /* AUTH_INVALID_TOKEN */]: "\u65E0\u6548\u7684\u8BA4\u8BC1\u4EE4\u724C",
327
425
  ["AUTH_TOKEN_EXPIRED" /* AUTH_TOKEN_EXPIRED */]: "\u8BA4\u8BC1\u4EE4\u724C\u5DF2\u8FC7\u671F",
328
426
  ["AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */]: "\u6743\u9650\u4E0D\u8DB3",
427
+ ["AUTH_INVALID_CREDENTIALS" /* AUTH_INVALID_CREDENTIALS */]: "\u65E0\u6548\u7684\u51ED\u636E",
428
+ ["AUTH_ACCOUNT_LOCKED" /* AUTH_ACCOUNT_LOCKED */]: "\u8D26\u6237\u5DF2\u9501\u5B9A",
429
+ ["AUTH_ACCOUNT_DISABLED" /* AUTH_ACCOUNT_DISABLED */]: "\u8D26\u6237\u5DF2\u7981\u7528",
329
430
  ["VALIDATION_FAILED" /* VALIDATION_FAILED */]: "\u9A8C\u8BC1\u5931\u8D25",
330
431
  ["VALIDATION_REQUIRED_FIELD" /* VALIDATION_REQUIRED_FIELD */]: "\u5FC5\u586B\u5B57\u6BB5\u7F3A\u5931",
331
432
  ["VALIDATION_INVALID_FORMAT" /* VALIDATION_INVALID_FORMAT */]: "\u683C\u5F0F\u65E0\u6548",
332
433
  ["VALIDATION_OUT_OF_RANGE" /* VALIDATION_OUT_OF_RANGE */]: "\u503C\u8D85\u51FA\u8303\u56F4",
434
+ ["VALIDATION_TYPE_MISMATCH" /* VALIDATION_TYPE_MISMATCH */]: "\u7C7B\u578B\u4E0D\u5339\u914D",
435
+ ["VALIDATION_CONSTRAINT_VIOLATION" /* VALIDATION_CONSTRAINT_VIOLATION */]: "\u7EA6\u675F\u8FDD\u53CD",
333
436
  ["OAUTH2_INVALID_CLIENT" /* OAUTH2_INVALID_CLIENT */]: "\u65E0\u6548\u7684\u5BA2\u6237\u7AEF",
334
437
  ["OAUTH2_INVALID_GRANT" /* OAUTH2_INVALID_GRANT */]: "\u65E0\u6548\u7684\u6388\u6743",
335
438
  ["OAUTH2_INVALID_SCOPE" /* OAUTH2_INVALID_SCOPE */]: "\u65E0\u6548\u7684\u4F5C\u7528\u57DF",
336
439
  ["OAUTH2_INVALID_REDIRECT_URI" /* OAUTH2_INVALID_REDIRECT_URI */]: "\u65E0\u6548\u7684\u91CD\u5B9A\u5411 URI",
337
- ["OAUTH2_UNSUPPORTED_GRANT_TYPE" /* OAUTH2_UNSUPPORTED_GRANT_TYPE */]: "\u4E0D\u652F\u6301\u7684\u6388\u6743\u7C7B\u578B"
440
+ ["OAUTH2_UNSUPPORTED_GRANT_TYPE" /* OAUTH2_UNSUPPORTED_GRANT_TYPE */]: "\u4E0D\u652F\u6301\u7684\u6388\u6743\u7C7B\u578B",
441
+ ["OAUTH2_ACCESS_DENIED" /* OAUTH2_ACCESS_DENIED */]: "\u8BBF\u95EE\u88AB\u62D2\u7EDD",
442
+ ["OAUTH2_SERVER_ERROR" /* OAUTH2_SERVER_ERROR */]: "OAuth2 \u670D\u52A1\u5668\u9519\u8BEF",
443
+ ["DATABASE_CONNECTION_FAILED" /* DATABASE_CONNECTION_FAILED */]: "\u6570\u636E\u5E93\u8FDE\u63A5\u5931\u8D25",
444
+ ["DATABASE_QUERY_FAILED" /* DATABASE_QUERY_FAILED */]: "\u6570\u636E\u5E93\u67E5\u8BE2\u5931\u8D25",
445
+ ["DATABASE_TRANSACTION_FAILED" /* DATABASE_TRANSACTION_FAILED */]: "\u6570\u636E\u5E93\u4E8B\u52A1\u5931\u8D25",
446
+ ["DATABASE_CONSTRAINT_VIOLATION" /* DATABASE_CONSTRAINT_VIOLATION */]: "\u6570\u636E\u5E93\u7EA6\u675F\u8FDD\u53CD",
447
+ ["DATABASE_TIMEOUT" /* DATABASE_TIMEOUT */]: "\u6570\u636E\u5E93\u8D85\u65F6",
448
+ ["DATABASE_POOL_EXHAUSTED" /* DATABASE_POOL_EXHAUSTED */]: "\u6570\u636E\u5E93\u8FDE\u63A5\u6C60\u8017\u5C3D",
449
+ ["DATABASE_MIGRATION_FAILED" /* DATABASE_MIGRATION_FAILED */]: "\u6570\u636E\u5E93\u8FC1\u79FB\u5931\u8D25",
450
+ ["FILE_NOT_FOUND" /* FILE_NOT_FOUND */]: "\u6587\u4EF6\u672A\u627E\u5230",
451
+ ["FILE_UPLOAD_FAILED" /* FILE_UPLOAD_FAILED */]: "\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25",
452
+ ["FILE_DOWNLOAD_FAILED" /* FILE_DOWNLOAD_FAILED */]: "\u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25",
453
+ ["FILE_SIZE_EXCEEDED" /* FILE_SIZE_EXCEEDED */]: "\u6587\u4EF6\u5927\u5C0F\u8D85\u9650",
454
+ ["FILE_TYPE_NOT_ALLOWED" /* FILE_TYPE_NOT_ALLOWED */]: "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B",
455
+ ["FILE_ACCESS_DENIED" /* FILE_ACCESS_DENIED */]: "\u6587\u4EF6\u8BBF\u95EE\u88AB\u62D2\u7EDD",
456
+ ["FILE_PATH_TRAVERSAL" /* FILE_PATH_TRAVERSAL */]: "\u68C0\u6D4B\u5230\u8DEF\u5F84\u904D\u5386\u653B\u51FB",
457
+ ["MIDDLEWARE_EXECUTION_FAILED" /* MIDDLEWARE_EXECUTION_FAILED */]: "\u4E2D\u95F4\u4EF6\u6267\u884C\u5931\u8D25",
458
+ ["MIDDLEWARE_TIMEOUT" /* MIDDLEWARE_TIMEOUT */]: "\u4E2D\u95F4\u4EF6\u8D85\u65F6",
459
+ ["CORS_NOT_ALLOWED" /* CORS_NOT_ALLOWED */]: "CORS \u4E0D\u5141\u8BB8",
460
+ ["CONFIG_INVALID" /* CONFIG_INVALID */]: "\u65E0\u6548\u7684\u914D\u7F6E",
461
+ ["CONFIG_MISSING" /* CONFIG_MISSING */]: "\u7F3A\u5C11\u914D\u7F6E",
462
+ ["CONFIG_VALIDATION_FAILED" /* CONFIG_VALIDATION_FAILED */]: "\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25"
463
+ },
464
+ ja: {
465
+ ["INTERNAL_ERROR" /* INTERNAL_ERROR */]: "\u30B5\u30FC\u30D0\u30FC\u5185\u90E8\u30A8\u30E9\u30FC",
466
+ ["INVALID_REQUEST" /* INVALID_REQUEST */]: "\u7121\u52B9\u306A\u30EA\u30AF\u30A8\u30B9\u30C8",
467
+ ["RESOURCE_NOT_FOUND" /* RESOURCE_NOT_FOUND */]: "\u30EA\u30BD\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
468
+ ["AUTH_REQUIRED" /* AUTH_REQUIRED */]: "\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059",
469
+ ["AUTH_INVALID_TOKEN" /* AUTH_INVALID_TOKEN */]: "\u7121\u52B9\u306A\u8A8D\u8A3C\u30C8\u30FC\u30AF\u30F3",
470
+ ["VALIDATION_FAILED" /* VALIDATION_FAILED */]: "\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
471
+ },
472
+ ko: {
473
+ ["INTERNAL_ERROR" /* INTERNAL_ERROR */]: "\uC11C\uBC84 \uB0B4\uBD80 \uC624\uB958",
474
+ ["INVALID_REQUEST" /* INVALID_REQUEST */]: "\uC798\uBABB\uB41C \uC694\uCCAD",
475
+ ["RESOURCE_NOT_FOUND" /* RESOURCE_NOT_FOUND */]: "\uB9AC\uC18C\uC2A4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
476
+ ["AUTH_REQUIRED" /* AUTH_REQUIRED */]: "\uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4",
477
+ ["AUTH_INVALID_TOKEN" /* AUTH_INVALID_TOKEN */]: "\uC798\uBABB\uB41C \uC778\uC99D \uD1A0\uD070",
478
+ ["VALIDATION_FAILED" /* VALIDATION_FAILED */]: "\uC720\uD6A8\uC131 \uAC80\uC0AC \uC2E4\uD328"
338
479
  }
339
480
  };
340
481
  });
@@ -356,7 +497,7 @@ async function handleError(error, context) {
356
497
  if (error.code) {
357
498
  const acceptLanguage = context.getHeader("accept-language");
358
499
  const language = ErrorMessageI18n.parseLanguageFromHeader(acceptLanguage);
359
- errorMessage = ErrorMessageI18n.getMessage(error.code, language);
500
+ errorMessage = ErrorMessageI18n.getMessage(error.code, language, error.messageParams);
360
501
  }
361
502
  const responseBody = {
362
503
  error: errorMessage
@@ -390,6 +531,181 @@ var init_handler = __esm(() => {
390
531
  init_i18n();
391
532
  });
392
533
 
534
+ // src/database/orm/transaction-types.ts
535
+ var Propagation, IsolationLevel, TransactionStatus, TRANSACTION_SERVICE_TOKEN;
536
+ var init_transaction_types = __esm(() => {
537
+ ((Propagation2) => {
538
+ Propagation2["REQUIRED"] = "REQUIRED";
539
+ Propagation2["REQUIRES_NEW"] = "REQUIRES_NEW";
540
+ Propagation2["SUPPORTS"] = "SUPPORTS";
541
+ Propagation2["NOT_SUPPORTED"] = "NOT_SUPPORTED";
542
+ Propagation2["NEVER"] = "NEVER";
543
+ Propagation2["NESTED"] = "NESTED";
544
+ })(Propagation ||= {});
545
+ ((IsolationLevel2) => {
546
+ IsolationLevel2["READ_UNCOMMITTED"] = "READ_UNCOMMITTED";
547
+ IsolationLevel2["READ_COMMITTED"] = "READ_COMMITTED";
548
+ IsolationLevel2["REPEATABLE_READ"] = "REPEATABLE_READ";
549
+ IsolationLevel2["SERIALIZABLE"] = "SERIALIZABLE";
550
+ })(IsolationLevel ||= {});
551
+ ((TransactionStatus2) => {
552
+ TransactionStatus2["ACTIVE"] = "ACTIVE";
553
+ TransactionStatus2["COMMITTED"] = "COMMITTED";
554
+ TransactionStatus2["ROLLED_BACK"] = "ROLLED_BACK";
555
+ TransactionStatus2["SUSPENDED"] = "SUSPENDED";
556
+ })(TransactionStatus ||= {});
557
+ TRANSACTION_SERVICE_TOKEN = Symbol("@dangao/bun-server:orm:transaction:service");
558
+ });
559
+
560
+ // src/database/orm/transaction-decorator.ts
561
+ var exports_transaction_decorator = {};
562
+ __export(exports_transaction_decorator, {
563
+ getTransactionMetadata: () => getTransactionMetadata,
564
+ Transactional: () => Transactional,
565
+ TRANSACTION_METADATA_KEY: () => TRANSACTION_METADATA_KEY
566
+ });
567
+ import"reflect-metadata";
568
+ function Transactional(options) {
569
+ return (target, propertyKey, descriptor) => {
570
+ if (!descriptor || typeof descriptor.value !== "function") {
571
+ throw new Error("@Transactional() can only be applied to methods");
572
+ }
573
+ const metadata = {
574
+ propagation: options?.propagation ?? "REQUIRED" /* REQUIRED */,
575
+ isolationLevel: options?.isolationLevel,
576
+ timeout: options?.timeout,
577
+ readOnly: options?.readOnly ?? false,
578
+ rollbackFor: options?.rollbackFor ?? [],
579
+ noRollbackFor: options?.noRollbackFor ?? []
580
+ };
581
+ Reflect.defineMetadata(TRANSACTION_METADATA_KEY, metadata, target, propertyKey);
582
+ };
583
+ }
584
+ function getTransactionMetadata(target, propertyKey) {
585
+ if (typeof target === "object" && target !== null) {
586
+ return Reflect.getMetadata(TRANSACTION_METADATA_KEY, target, propertyKey);
587
+ }
588
+ return;
589
+ }
590
+ var TRANSACTION_METADATA_KEY;
591
+ var init_transaction_decorator = __esm(() => {
592
+ init_transaction_types();
593
+ TRANSACTION_METADATA_KEY = Symbol("@dangao/bun-server:orm:transaction");
594
+ });
595
+
596
+ // src/database/orm/transaction-interceptor.ts
597
+ var exports_transaction_interceptor = {};
598
+ __export(exports_transaction_interceptor, {
599
+ TransactionInterceptor: () => TransactionInterceptor
600
+ });
601
+
602
+ class TransactionInterceptor {
603
+ static async executeWithTransaction(target, propertyKey, originalMethod, args, container) {
604
+ const transactionMetadata = getTransactionMetadata(target, propertyKey);
605
+ if (!transactionMetadata) {
606
+ return await Promise.resolve(originalMethod.apply(target, args));
607
+ }
608
+ let transactionManager;
609
+ try {
610
+ transactionManager = container.resolve(TRANSACTION_SERVICE_TOKEN);
611
+ } catch (error) {
612
+ console.warn("TransactionManager not found, executing without transaction");
613
+ return await Promise.resolve(originalMethod.apply(target, args));
614
+ }
615
+ const propagation = transactionMetadata.propagation ?? "REQUIRED" /* REQUIRED */;
616
+ const currentTransaction = transactionManager.getCurrentTransaction();
617
+ switch (propagation) {
618
+ case "REQUIRED" /* REQUIRED */:
619
+ if (currentTransaction) {
620
+ return await this.executeInExistingTransaction(originalMethod, target, args, currentTransaction.id, transactionManager);
621
+ } else {
622
+ return await this.executeInNewTransaction(originalMethod, target, args, transactionMetadata, transactionManager);
623
+ }
624
+ case "REQUIRES_NEW" /* REQUIRES_NEW */:
625
+ return await this.executeInNewTransaction(originalMethod, target, args, transactionMetadata, transactionManager);
626
+ case "SUPPORTS" /* SUPPORTS */:
627
+ if (currentTransaction) {
628
+ return await this.executeInExistingTransaction(originalMethod, target, args, currentTransaction.id, transactionManager);
629
+ } else {
630
+ return await Promise.resolve(originalMethod.apply(target, args));
631
+ }
632
+ case "NOT_SUPPORTED" /* NOT_SUPPORTED */:
633
+ return await Promise.resolve(originalMethod.apply(target, args));
634
+ case "NEVER" /* NEVER */:
635
+ if (currentTransaction) {
636
+ throw new Error("Transaction propagation NEVER requires no existing transaction");
637
+ }
638
+ return await Promise.resolve(originalMethod.apply(target, args));
639
+ case "NESTED" /* NESTED */:
640
+ if (currentTransaction) {
641
+ return await this.executeInNestedTransaction(originalMethod, target, args, currentTransaction.id, transactionMetadata, transactionManager);
642
+ } else {
643
+ return await this.executeInNewTransaction(originalMethod, target, args, transactionMetadata, transactionManager);
644
+ }
645
+ default:
646
+ return await Promise.resolve(originalMethod.apply(target, args));
647
+ }
648
+ }
649
+ static async executeInNewTransaction(method, target, args, options, transactionManager) {
650
+ const context = await transactionManager.beginTransaction({
651
+ timeout: options.timeout
652
+ });
653
+ try {
654
+ const result = await Promise.resolve(method.apply(target, args));
655
+ await transactionManager.commitTransaction(context.id);
656
+ return result;
657
+ } catch (error) {
658
+ if (this.shouldRollback(error, options.rollbackFor, options.noRollbackFor)) {
659
+ await transactionManager.rollbackTransaction(context.id);
660
+ } else {
661
+ await transactionManager.commitTransaction(context.id);
662
+ }
663
+ throw error;
664
+ }
665
+ }
666
+ static async executeInExistingTransaction(method, target, args, transactionId, transactionManager) {
667
+ return await Promise.resolve(method.apply(target, args));
668
+ }
669
+ static async executeInNestedTransaction(method, target, args, parentTransactionId, options, transactionManager) {
670
+ const savepointName = await transactionManager.createSavepoint(parentTransactionId);
671
+ try {
672
+ const result = await Promise.resolve(method.apply(target, args));
673
+ return result;
674
+ } catch (error) {
675
+ if (this.shouldRollback(error, options.rollbackFor, options.noRollbackFor)) {
676
+ await transactionManager.rollbackToSavepoint(parentTransactionId, savepointName);
677
+ }
678
+ throw error;
679
+ }
680
+ }
681
+ static shouldRollback(error, rollbackFor, noRollbackFor) {
682
+ if (!error) {
683
+ return false;
684
+ }
685
+ if (noRollbackFor && noRollbackFor.length > 0) {
686
+ for (const ErrorClass of noRollbackFor) {
687
+ if (error instanceof ErrorClass) {
688
+ return false;
689
+ }
690
+ }
691
+ }
692
+ if (rollbackFor && rollbackFor.length > 0) {
693
+ for (const ErrorClass of rollbackFor) {
694
+ if (error instanceof ErrorClass) {
695
+ return true;
696
+ }
697
+ }
698
+ return false;
699
+ }
700
+ return true;
701
+ }
702
+ }
703
+ var init_transaction_interceptor = __esm(() => {
704
+ init_transaction_types();
705
+ init_transaction_decorator();
706
+ init_transaction_types();
707
+ });
708
+
393
709
  // src/request/body-parser.ts
394
710
  class BodyParser {
395
711
  static async parse(request) {
@@ -653,21 +969,23 @@ class MiddlewarePipeline {
653
969
  if (length === 0) {
654
970
  return await finalHandler();
655
971
  }
972
+ let currentIndex = 0;
656
973
  const called = new Array(length).fill(false);
657
- const chain = new Array(length + 1);
658
- chain[length] = finalHandler;
659
- for (let i = length - 1;i >= 0; i--) {
660
- const middleware = this.middlewares[i];
661
- const downstream = chain[i + 1];
662
- chain[i] = async () => {
663
- if (called[i]) {
974
+ const createNext = (index) => {
975
+ if (index >= length) {
976
+ return finalHandler;
977
+ }
978
+ return async () => {
979
+ if (called[index]) {
664
980
  throw new Error("next() called multiple times");
665
981
  }
666
- called[i] = true;
667
- return await middleware(context, downstream);
982
+ called[index] = true;
983
+ currentIndex = index + 1;
984
+ const middleware = this.middlewares[index];
985
+ return await middleware(context, createNext(index + 1));
668
986
  };
669
- }
670
- return await chain[0]();
987
+ };
988
+ return await createNext(0)();
671
989
  }
672
990
  }
673
991
 
@@ -737,6 +1055,7 @@ class Router {
737
1055
  routes = [];
738
1056
  staticRoutes = new Map;
739
1057
  dynamicRoutes = [];
1058
+ matchCache = new Map;
740
1059
  normalizePath(path) {
741
1060
  if (path.length > 1 && path.endsWith("/")) {
742
1061
  return path.slice(0, -1);
@@ -753,6 +1072,7 @@ class Router {
753
1072
  } else {
754
1073
  this.dynamicRoutes.push(route);
755
1074
  }
1075
+ this.matchCache.clear();
756
1076
  }
757
1077
  get(path, handler, middlewares = []) {
758
1078
  this.register("GET", path, handler, middlewares);
@@ -770,14 +1090,29 @@ class Router {
770
1090
  this.register("PATCH", path, handler, middlewares);
771
1091
  }
772
1092
  findRoute(method, path) {
773
- const staticRoute = this.staticRoutes.get(`${method}:${path}`);
1093
+ const result = this.findRouteWithMatch(method, path);
1094
+ return result?.route;
1095
+ }
1096
+ findRouteWithMatch(method, path) {
1097
+ const normalizedPath = this.normalizePath(path);
1098
+ const cacheKey = `${method}:${normalizedPath}`;
1099
+ const cached = this.matchCache.get(cacheKey);
1100
+ if (cached && cached.match.matched) {
1101
+ return cached;
1102
+ }
1103
+ const staticRoute = this.staticRoutes.get(cacheKey);
774
1104
  if (staticRoute) {
775
- return staticRoute;
1105
+ const match = { matched: true, params: {} };
1106
+ const result = { route: staticRoute, match };
1107
+ this.matchCache.set(cacheKey, result);
1108
+ return result;
776
1109
  }
777
1110
  for (const route of this.dynamicRoutes) {
778
- const match = route.match(method, path);
1111
+ const match = route.match(method, normalizedPath);
779
1112
  if (match.matched) {
780
- return route;
1113
+ const result = { route, match };
1114
+ this.matchCache.set(cacheKey, result);
1115
+ return result;
781
1116
  }
782
1117
  }
783
1118
  return;
@@ -785,11 +1120,11 @@ class Router {
785
1120
  async preHandle(context) {
786
1121
  const method = context.method;
787
1122
  const path = this.normalizePath(context.path);
788
- const route = this.findRoute(method, path);
789
- if (!route) {
1123
+ const result = this.findRouteWithMatch(method, path);
1124
+ if (!result) {
790
1125
  return;
791
1126
  }
792
- const match = route.match(method, path);
1127
+ const { route, match } = result;
793
1128
  if (match.matched) {
794
1129
  context.params = match.params;
795
1130
  }
@@ -801,13 +1136,22 @@ class Router {
801
1136
  }
802
1137
  }
803
1138
  async handle(context) {
804
- await this.preHandle(context);
805
1139
  const method = context.method;
806
1140
  const path = this.normalizePath(context.path);
807
- const route = this.findRoute(method, path);
808
- if (!route) {
1141
+ const result = this.findRouteWithMatch(method, path);
1142
+ if (!result) {
809
1143
  return;
810
1144
  }
1145
+ const { route, match } = result;
1146
+ if (match.matched) {
1147
+ context.params = match.params;
1148
+ }
1149
+ if (route.controllerClass && route.methodName) {
1150
+ context.routeHandler = {
1151
+ controller: route.controllerClass,
1152
+ method: route.methodName
1153
+ };
1154
+ }
811
1155
  return await route.execute(context);
812
1156
  }
813
1157
  getRoutes() {
@@ -817,6 +1161,7 @@ class Router {
817
1161
  this.routes.length = 0;
818
1162
  this.dynamicRoutes.length = 0;
819
1163
  this.staticRoutes.clear();
1164
+ this.matchCache.clear();
820
1165
  }
821
1166
  }
822
1167
 
@@ -1205,14 +1550,162 @@ function getParamMetadata(target, propertyKey) {
1205
1550
  return Reflect.getMetadata(PARAM_METADATA_KEY, target, propertyKey) || [];
1206
1551
  }
1207
1552
 
1553
+ // src/session/types.ts
1554
+ class MemorySessionStore {
1555
+ store = new Map;
1556
+ cleanupInterval;
1557
+ constructor(options) {
1558
+ if (options?.cleanupInterval !== undefined) {
1559
+ this.cleanupInterval = setInterval(() => {
1560
+ this.cleanup();
1561
+ }, options.cleanupInterval);
1562
+ }
1563
+ }
1564
+ async get(sessionId) {
1565
+ const session = this.store.get(sessionId);
1566
+ if (!session) {
1567
+ return;
1568
+ }
1569
+ if (Date.now() > session.expiresAt) {
1570
+ this.store.delete(sessionId);
1571
+ return;
1572
+ }
1573
+ return session;
1574
+ }
1575
+ async set(session, maxAge) {
1576
+ const now = Date.now();
1577
+ session.expiresAt = now + maxAge;
1578
+ session.lastAccessedAt = now;
1579
+ this.store.set(session.id, session);
1580
+ return true;
1581
+ }
1582
+ async delete(sessionId) {
1583
+ return this.store.delete(sessionId);
1584
+ }
1585
+ async has(sessionId) {
1586
+ const session = this.store.get(sessionId);
1587
+ if (!session) {
1588
+ return false;
1589
+ }
1590
+ if (Date.now() > session.expiresAt) {
1591
+ this.store.delete(sessionId);
1592
+ return false;
1593
+ }
1594
+ return true;
1595
+ }
1596
+ async touch(sessionId) {
1597
+ const session = this.store.get(sessionId);
1598
+ if (!session) {
1599
+ return false;
1600
+ }
1601
+ if (Date.now() > session.expiresAt) {
1602
+ this.store.delete(sessionId);
1603
+ return false;
1604
+ }
1605
+ session.lastAccessedAt = Date.now();
1606
+ return true;
1607
+ }
1608
+ async clear() {
1609
+ this.store.clear();
1610
+ return true;
1611
+ }
1612
+ cleanup() {
1613
+ const now = Date.now();
1614
+ for (const [sessionId, session] of this.store.entries()) {
1615
+ if (now > session.expiresAt) {
1616
+ this.store.delete(sessionId);
1617
+ }
1618
+ }
1619
+ }
1620
+ destroy() {
1621
+ if (this.cleanupInterval) {
1622
+ clearInterval(this.cleanupInterval);
1623
+ this.cleanupInterval = undefined;
1624
+ }
1625
+ this.store.clear();
1626
+ }
1627
+ }
1628
+
1629
+ class RedisSessionStore {
1630
+ client;
1631
+ keyPrefix;
1632
+ constructor(options) {
1633
+ this.client = options.client;
1634
+ this.keyPrefix = options.keyPrefix ?? "session:";
1635
+ }
1636
+ getKey(sessionId) {
1637
+ return `${this.keyPrefix}${sessionId}`;
1638
+ }
1639
+ async get(sessionId) {
1640
+ try {
1641
+ const value = await this.client.get(this.getKey(sessionId));
1642
+ if (value === null) {
1643
+ return;
1644
+ }
1645
+ return JSON.parse(value);
1646
+ } catch {
1647
+ return;
1648
+ }
1649
+ }
1650
+ async set(session, maxAge) {
1651
+ try {
1652
+ const serialized = JSON.stringify(session);
1653
+ await this.client.set(this.getKey(session.id), serialized, {
1654
+ PX: maxAge
1655
+ });
1656
+ return true;
1657
+ } catch {
1658
+ return false;
1659
+ }
1660
+ }
1661
+ async delete(sessionId) {
1662
+ try {
1663
+ await this.client.del(this.getKey(sessionId));
1664
+ return true;
1665
+ } catch {
1666
+ return false;
1667
+ }
1668
+ }
1669
+ async has(sessionId) {
1670
+ try {
1671
+ const result = await this.client.exists(this.getKey(sessionId));
1672
+ return result === 1;
1673
+ } catch {
1674
+ return false;
1675
+ }
1676
+ }
1677
+ async touch(sessionId) {
1678
+ try {
1679
+ const session = await this.get(sessionId);
1680
+ if (!session) {
1681
+ return false;
1682
+ }
1683
+ session.lastAccessedAt = Date.now();
1684
+ const remainingTime = session.expiresAt - Date.now();
1685
+ if (remainingTime > 0) {
1686
+ await this.client.expire(this.getKey(sessionId), Math.floor(remainingTime / 1000));
1687
+ return true;
1688
+ }
1689
+ return false;
1690
+ } catch {
1691
+ return false;
1692
+ }
1693
+ }
1694
+ async clear() {
1695
+ return false;
1696
+ }
1697
+ }
1698
+ var SESSION_SERVICE_TOKEN = Symbol("@dangao/bun-server:session:service");
1699
+ var SESSION_OPTIONS_TOKEN = Symbol("@dangao/bun-server:session:options");
1700
+
1208
1701
  // src/controller/param-binder.ts
1209
1702
  class ParamBinder {
1210
- static async bind(target, propertyKey, context) {
1703
+ static async bind(target, propertyKey, context, container) {
1211
1704
  const metadata = getParamMetadata(target, propertyKey);
1212
1705
  const params = [];
1213
1706
  metadata.sort((a, b) => a.index - b.index);
1214
1707
  for (const meta of metadata) {
1215
- const value = await this.getValue(meta, context);
1708
+ const value = await this.getValue(meta, context, container);
1216
1709
  params[meta.index] = value;
1217
1710
  }
1218
1711
  const maxIndex = metadata.length > 0 ? Math.max(...metadata.map((m) => m.index)) : -1;
@@ -1223,7 +1716,7 @@ class ParamBinder {
1223
1716
  }
1224
1717
  return params;
1225
1718
  }
1226
- static async getValue(meta, context) {
1719
+ static async getValue(meta, context, container) {
1227
1720
  switch (meta.type) {
1228
1721
  case "body" /* BODY */:
1229
1722
  return await this.getBodyValue(meta.key, context);
@@ -1242,6 +1735,24 @@ class ParamBinder {
1242
1735
  throw new Error("@Header() decorator requires a key parameter");
1243
1736
  }
1244
1737
  return this.getHeaderValue(meta.key, context);
1738
+ case "session" /* SESSION */:
1739
+ if (!container) {
1740
+ throw new Error("@Session() decorator requires a Container instance");
1741
+ }
1742
+ const session = context.session;
1743
+ if (session) {
1744
+ return session;
1745
+ }
1746
+ try {
1747
+ const sessionService = container.resolve(SESSION_SERVICE_TOKEN);
1748
+ if (sessionService) {
1749
+ const newSession = await sessionService.create();
1750
+ context.session = newSession;
1751
+ context.sessionId = newSession.id;
1752
+ return newSession;
1753
+ }
1754
+ } catch {}
1755
+ return;
1245
1756
  default:
1246
1757
  return;
1247
1758
  }
@@ -1800,7 +2311,7 @@ class ControllerRegistry {
1800
2311
  const controllerContainer = this.controllerContainers.get(controllerClass) ?? this.container;
1801
2312
  const controllerInstance = controllerContainer.resolve(controllerClass);
1802
2313
  const prototype2 = controllerClass.prototype;
1803
- const params = await ParamBinder.bind(prototype2, propertyKey, context);
2314
+ const params = await ParamBinder.bind(prototype2, propertyKey, context, controllerContainer);
1804
2315
  const validationMetadata = getValidationMetadata(prototype2, propertyKey);
1805
2316
  if (validationMetadata.length > 0) {
1806
2317
  validateParameters(params, validationMetadata);
@@ -1813,7 +2324,19 @@ class ControllerRegistry {
1813
2324
  if (!method || typeof method !== "function") {
1814
2325
  throw new Error(`Method ${propertyKey} not found on controller ${controllerClass.name}`);
1815
2326
  }
1816
- const result = method.apply(controllerInstance, params);
2327
+ let result;
2328
+ try {
2329
+ const { TransactionInterceptor: TransactionInterceptor2 } = await Promise.resolve().then(() => (init_transaction_interceptor(), exports_transaction_interceptor));
2330
+ const { getTransactionMetadata: getTransactionMetadata2 } = await Promise.resolve().then(() => (init_transaction_decorator(), exports_transaction_decorator));
2331
+ const hasTransaction = getTransactionMetadata2(prototype2, propertyKey);
2332
+ if (hasTransaction) {
2333
+ result = TransactionInterceptor2.executeWithTransaction(prototype2, propertyKey, method, params, controllerContainer);
2334
+ } else {
2335
+ result = method.apply(controllerInstance, params);
2336
+ }
2337
+ } catch (error) {
2338
+ result = method.apply(controllerInstance, params);
2339
+ }
1817
2340
  const responseData = await Promise.resolve(result);
1818
2341
  if (responseData instanceof Response) {
1819
2342
  return responseData;
@@ -2174,10 +2697,11 @@ class Application {
2174
2697
  use(middleware) {
2175
2698
  this.middlewarePipeline.use(middleware);
2176
2699
  }
2177
- listen(port, hostname) {
2700
+ async listen(port, hostname) {
2178
2701
  if (this.server?.isRunning()) {
2179
2702
  throw new Error("Application is already running");
2180
2703
  }
2704
+ await this.initializeExtensions();
2181
2705
  const serverOptions = {
2182
2706
  port: port ?? this.options.port ?? 3000,
2183
2707
  hostname: hostname ?? this.options.hostname,
@@ -2187,9 +2711,27 @@ class Application {
2187
2711
  this.server = new BunServer(serverOptions);
2188
2712
  this.server.start();
2189
2713
  }
2190
- stop() {
2714
+ async initializeExtensions() {
2715
+ const container = this.getContainer();
2716
+ for (const extension of this.extensions) {
2717
+ if (extension && typeof extension === "object" && "initialize" in extension && typeof extension.initialize === "function") {
2718
+ await extension.initialize(container);
2719
+ }
2720
+ }
2721
+ }
2722
+ async stop() {
2723
+ await this.closeExtensions();
2191
2724
  this.server?.stop();
2192
2725
  }
2726
+ async closeExtensions() {
2727
+ const container = this.getContainer();
2728
+ for (let i = this.extensions.length - 1;i >= 0; i--) {
2729
+ const extension = this.extensions[i];
2730
+ if (extension && typeof extension === "object" && "close" in extension && typeof extension.close === "function") {
2731
+ await extension.close(container);
2732
+ }
2733
+ }
2734
+ }
2193
2735
  async handleRequest(context) {
2194
2736
  if (["POST", "PUT", "PATCH"].includes(context.method)) {
2195
2737
  await context.getBody();
@@ -3245,19 +3787,19 @@ class OAuth2Controller {
3245
3787
  constructor(oauth2Service) {
3246
3788
  this.oauth2Service = oauth2Service;
3247
3789
  }
3248
- authorize(clientId, redirectUri, state, scope) {
3249
- const query = {
3250
- client_id: clientId,
3251
- redirect_uri: redirectUri,
3252
- ...state && { state },
3253
- ...scope && { scope }
3254
- };
3790
+ authorize(clientId, redirectUri, responseType, state, scope) {
3791
+ if (!clientId || !redirectUri) {
3792
+ throw new Error("Missing required parameters: client_id and redirect_uri are required");
3793
+ }
3794
+ if (responseType !== "code") {
3795
+ throw new Error(`Unsupported response_type: ${responseType}. Only 'code' is supported.`);
3796
+ }
3255
3797
  const request = {
3256
- clientId: query.client_id || "",
3257
- redirectUri: query.redirect_uri || "",
3798
+ clientId,
3799
+ redirectUri,
3258
3800
  responseType: "code",
3259
- scope: query.scope,
3260
- state: query.state
3801
+ scope: scope || undefined,
3802
+ state: state || undefined
3261
3803
  };
3262
3804
  const validation = this.oauth2Service.validateAuthorizationRequest(request);
3263
3805
  if (!validation.valid) {
@@ -3318,13 +3860,15 @@ __legacyDecorateClassTS([
3318
3860
  GET("/authorize"),
3319
3861
  __legacyDecorateParamTS(0, Query("client_id")),
3320
3862
  __legacyDecorateParamTS(1, Query("redirect_uri")),
3321
- __legacyDecorateParamTS(2, Query("state")),
3322
- __legacyDecorateParamTS(3, Query("scope")),
3863
+ __legacyDecorateParamTS(2, Query("response_type")),
3864
+ __legacyDecorateParamTS(3, Query("state")),
3865
+ __legacyDecorateParamTS(4, Query("scope")),
3323
3866
  __legacyMetadataTS("design:type", Function),
3324
3867
  __legacyMetadataTS("design:paramtypes", [
3325
3868
  String,
3326
3869
  String,
3327
3870
  String,
3871
+ String,
3328
3872
  String
3329
3873
  ]),
3330
3874
  __legacyMetadataTS("design:returntype", undefined)
@@ -3903,73 +4447,1826 @@ function createHttpMetricsMiddleware(collector) {
3903
4447
  return response;
3904
4448
  };
3905
4449
  }
3906
- // src/testing/harness.ts
3907
- import { performance as performance2 } from "perf_hooks";
4450
+ // src/database/types.ts
4451
+ var DATABASE_SERVICE_TOKEN = Symbol("@dangao/bun-server:database:service");
4452
+ var DATABASE_OPTIONS_TOKEN = Symbol("@dangao/bun-server:database:options");
3908
4453
 
3909
- class PerformanceHarness {
3910
- static async benchmark(name, iterations, runner) {
3911
- if (iterations <= 0) {
3912
- throw new Error("iterations must be greater than 0");
4454
+ // src/database/database-extension.ts
4455
+ class DatabaseExtension {
4456
+ register(container) {}
4457
+ async initialize(container) {
4458
+ try {
4459
+ const databaseService = container.resolve(DATABASE_SERVICE_TOKEN);
4460
+ await databaseService.initialize();
4461
+ } catch (error) {
4462
+ if (error instanceof Error && error.message.includes("Provider not found")) {
4463
+ return;
4464
+ }
4465
+ throw error;
3913
4466
  }
3914
- const start = performance2.now();
3915
- for (let i = 0;i < iterations; i++) {
3916
- await runner(i);
4467
+ }
4468
+ async close(container) {
4469
+ try {
4470
+ const databaseService = container.resolve(DATABASE_SERVICE_TOKEN);
4471
+ await databaseService.closePool();
4472
+ } catch (error) {
4473
+ if (error instanceof Error && error.message.includes("Provider not found")) {
4474
+ return;
4475
+ }
4476
+ throw error;
3917
4477
  }
3918
- const durationMs = performance2.now() - start;
3919
- const opsPerSecond = iterations / Math.max(durationMs / 1000, 0.0001);
3920
- return {
3921
- name,
3922
- iterations,
3923
- durationMs,
3924
- opsPerSecond
3925
- };
3926
4478
  }
3927
4479
  }
3928
4480
 
3929
- class StressTester {
3930
- static async run(name, iterations, concurrency, task) {
3931
- if (iterations <= 0) {
3932
- throw new Error("iterations must be greater than 0");
3933
- }
3934
- if (concurrency <= 0) {
3935
- throw new Error("concurrency must be greater than 0");
3936
- }
3937
- let next = 0;
3938
- let errors = 0;
3939
- const start = performance2.now();
3940
- const worker = async () => {
3941
- while (true) {
3942
- const current = next;
3943
- next += 1;
3944
- if (current >= iterations) {
3945
- break;
4481
+ // src/database/health-indicator.ts
4482
+ class DatabaseHealthIndicator {
4483
+ databaseService;
4484
+ name = "database";
4485
+ constructor(databaseService) {
4486
+ this.databaseService = databaseService;
4487
+ }
4488
+ async check() {
4489
+ try {
4490
+ const isHealthy = await this.databaseService.healthCheck();
4491
+ const connectionInfo = this.databaseService.getConnectionInfo();
4492
+ if (isHealthy) {
4493
+ return {
4494
+ status: "up",
4495
+ details: {
4496
+ type: connectionInfo.type,
4497
+ status: connectionInfo.status
4498
+ }
4499
+ };
4500
+ }
4501
+ return {
4502
+ status: "down",
4503
+ details: {
4504
+ type: connectionInfo.type,
4505
+ status: connectionInfo.status,
4506
+ error: connectionInfo.error
3946
4507
  }
3947
- try {
3948
- await task(current);
3949
- } catch (error) {
3950
- errors += 1;
4508
+ };
4509
+ } catch (error) {
4510
+ return {
4511
+ status: "down",
4512
+ details: {
4513
+ error: error instanceof Error ? error.message : String(error)
3951
4514
  }
3952
- }
3953
- };
3954
- const workers = Array.from({ length: Math.min(concurrency, iterations) }, () => worker());
3955
- await Promise.all(workers);
3956
- const durationMs = performance2.now() - start;
3957
- return {
3958
- name,
3959
- iterations,
3960
- concurrency: Math.min(concurrency, iterations),
3961
- durationMs,
3962
- errors
3963
- };
4515
+ };
4516
+ }
4517
+ }
4518
+ }
4519
+
4520
+ // src/database/orm/service.ts
4521
+ class OrmService {
4522
+ databaseService;
4523
+ options;
4524
+ drizzleInstance = null;
4525
+ constructor(databaseService, options = {}) {
4526
+ this.databaseService = databaseService;
4527
+ this.options = options;
3964
4528
  }
4529
+ getDrizzle() {
4530
+ if (this.options.drizzle) {
4531
+ return this.options.drizzle;
4532
+ }
4533
+ if (this.drizzleInstance) {
4534
+ return this.drizzleInstance;
4535
+ }
4536
+ return null;
4537
+ }
4538
+ setDrizzle(drizzle) {
4539
+ this.drizzleInstance = drizzle;
4540
+ }
4541
+ getDatabaseService() {
4542
+ return this.databaseService;
4543
+ }
4544
+ }
4545
+ OrmService = __legacyDecorateClassTS([
4546
+ Injectable(),
4547
+ __legacyMetadataTS("design:paramtypes", [
4548
+ typeof DatabaseService === "undefined" ? Object : DatabaseService,
4549
+ typeof OrmModuleOptions === "undefined" ? Object : OrmModuleOptions
4550
+ ])
4551
+ ], OrmService);
4552
+
4553
+ // src/database/orm/transaction-manager.ts
4554
+ init_transaction_types();
4555
+ class TransactionManager {
4556
+ databaseService;
4557
+ transactions = new Map;
4558
+ connectionTransactions = new Map;
4559
+ constructor(databaseService) {
4560
+ this.databaseService = databaseService;
4561
+ }
4562
+ async beginTransaction(options = {}) {
4563
+ const transactionId = this.generateTransactionId();
4564
+ const context2 = {
4565
+ id: transactionId,
4566
+ status: "ACTIVE" /* ACTIVE */,
4567
+ startTime: Date.now(),
4568
+ level: 0,
4569
+ savepoints: []
4570
+ };
4571
+ const connection = await this.databaseService.getConnection();
4572
+ this.connectionTransactions.set(connection, transactionId);
4573
+ this.transactions.set(transactionId, context2);
4574
+ await this.executeBegin(connection, options);
4575
+ return context2;
4576
+ }
4577
+ async commitTransaction(transactionId) {
4578
+ const context2 = this.transactions.get(transactionId);
4579
+ if (!context2) {
4580
+ throw new Error(`Transaction ${transactionId} not found`);
4581
+ }
4582
+ if (context2.status !== "ACTIVE" /* ACTIVE */) {
4583
+ throw new Error(`Transaction ${transactionId} is not active`);
4584
+ }
4585
+ const connection = this.findConnectionByTransactionId(transactionId);
4586
+ if (!connection) {
4587
+ throw new Error(`Connection not found for transaction ${transactionId}`);
4588
+ }
4589
+ await this.executeCommit(connection);
4590
+ context2.status = "COMMITTED" /* COMMITTED */;
4591
+ this.cleanupTransaction(transactionId);
4592
+ }
4593
+ async rollbackTransaction(transactionId) {
4594
+ const context2 = this.transactions.get(transactionId);
4595
+ if (!context2) {
4596
+ throw new Error(`Transaction ${transactionId} not found`);
4597
+ }
4598
+ const connection = this.findConnectionByTransactionId(transactionId);
4599
+ if (!connection) {
4600
+ throw new Error(`Connection not found for transaction ${transactionId}`);
4601
+ }
4602
+ await this.executeRollback(connection);
4603
+ context2.status = "ROLLED_BACK" /* ROLLED_BACK */;
4604
+ this.cleanupTransaction(transactionId);
4605
+ }
4606
+ async createSavepoint(transactionId) {
4607
+ const context2 = this.transactions.get(transactionId);
4608
+ if (!context2) {
4609
+ throw new Error(`Transaction ${transactionId} not found`);
4610
+ }
4611
+ const savepointName = `sp_${context2.level}_${Date.now()}`;
4612
+ context2.savepoints = context2.savepoints || [];
4613
+ context2.savepoints.push(savepointName);
4614
+ context2.level += 1;
4615
+ const connection = this.findConnectionByTransactionId(transactionId);
4616
+ if (connection) {
4617
+ await this.executeSavepoint(connection, savepointName);
4618
+ }
4619
+ return savepointName;
4620
+ }
4621
+ async rollbackToSavepoint(transactionId, savepointName) {
4622
+ const context2 = this.transactions.get(transactionId);
4623
+ if (!context2) {
4624
+ throw new Error(`Transaction ${transactionId} not found`);
4625
+ }
4626
+ const connection = this.findConnectionByTransactionId(transactionId);
4627
+ if (connection) {
4628
+ await this.executeRollbackToSavepoint(connection, savepointName);
4629
+ }
4630
+ const index = context2.savepoints?.indexOf(savepointName) ?? -1;
4631
+ if (index >= 0 && context2.savepoints) {
4632
+ context2.savepoints = context2.savepoints.slice(0, index);
4633
+ context2.level = index;
4634
+ }
4635
+ }
4636
+ getCurrentTransaction() {
4637
+ for (const context2 of this.transactions.values()) {
4638
+ if (context2.status === "ACTIVE" /* ACTIVE */) {
4639
+ return context2;
4640
+ }
4641
+ }
4642
+ return null;
4643
+ }
4644
+ hasActiveTransaction() {
4645
+ return this.getCurrentTransaction() !== null;
4646
+ }
4647
+ generateTransactionId() {
4648
+ return `tx_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
4649
+ }
4650
+ findConnectionByTransactionId(transactionId) {
4651
+ for (const [connection, txId] of this.connectionTransactions.entries()) {
4652
+ if (txId === transactionId) {
4653
+ return connection;
4654
+ }
4655
+ }
4656
+ return null;
4657
+ }
4658
+ cleanupTransaction(transactionId) {
4659
+ this.transactions.delete(transactionId);
4660
+ for (const [connection, txId] of this.connectionTransactions.entries()) {
4661
+ if (txId === transactionId) {
4662
+ this.connectionTransactions.delete(connection);
4663
+ break;
4664
+ }
4665
+ }
4666
+ }
4667
+ async executeBegin(connection, options) {
4668
+ const dbType = this.databaseService["config"].database.type;
4669
+ if (dbType === "sqlite") {
4670
+ await this.databaseService.query("BEGIN TRANSACTION");
4671
+ } else if (dbType === "postgres" || dbType === "mysql") {
4672
+ let sql = "START TRANSACTION";
4673
+ if (options.isolationLevel) {
4674
+ const isolation = this.getIsolationLevelSQL(options.isolationLevel);
4675
+ sql += ` ${isolation}`;
4676
+ }
4677
+ if (options.readOnly) {
4678
+ sql += " READ ONLY";
4679
+ }
4680
+ await this.databaseService.query(sql);
4681
+ }
4682
+ }
4683
+ async executeCommit(connection) {
4684
+ await this.databaseService.query("COMMIT");
4685
+ }
4686
+ async executeRollback(connection) {
4687
+ await this.databaseService.query("ROLLBACK");
4688
+ }
4689
+ async executeSavepoint(connection, savepointName) {
4690
+ await this.databaseService.query(`SAVEPOINT ${savepointName}`);
4691
+ }
4692
+ async executeRollbackToSavepoint(connection, savepointName) {
4693
+ await this.databaseService.query(`ROLLBACK TO SAVEPOINT ${savepointName}`);
4694
+ }
4695
+ getIsolationLevelSQL(level) {
4696
+ const dbType = this.databaseService["config"].database.type;
4697
+ const levelMap = {
4698
+ ["READ_UNCOMMITTED" /* READ_UNCOMMITTED */]: "READ UNCOMMITTED",
4699
+ ["READ_COMMITTED" /* READ_COMMITTED */]: "READ COMMITTED",
4700
+ ["REPEATABLE_READ" /* REPEATABLE_READ */]: "REPEATABLE READ",
4701
+ ["SERIALIZABLE" /* SERIALIZABLE */]: "SERIALIZABLE"
4702
+ };
4703
+ if (dbType === "postgres") {
4704
+ return `SET TRANSACTION ISOLATION LEVEL ${levelMap[level]}`;
4705
+ } else if (dbType === "mysql") {
4706
+ return `SET TRANSACTION ISOLATION LEVEL ${levelMap[level]}`;
4707
+ }
4708
+ return "";
4709
+ }
4710
+ }
4711
+ TransactionManager = __legacyDecorateClassTS([
4712
+ Injectable(),
4713
+ __legacyDecorateParamTS(0, Inject(DATABASE_SERVICE_TOKEN)),
4714
+ __legacyMetadataTS("design:paramtypes", [
4715
+ typeof DatabaseService === "undefined" ? Object : DatabaseService
4716
+ ])
4717
+ ], TransactionManager);
4718
+
4719
+ // src/database/connection-pool.ts
4720
+ class ConnectionPool {
4721
+ config;
4722
+ options;
4723
+ connections = [];
4724
+ pendingConnections = new Set;
4725
+ isClosing = false;
4726
+ constructor(config, options = {}) {
4727
+ this.config = config;
4728
+ this.options = {
4729
+ maxConnections: options.maxConnections ?? 10,
4730
+ connectionTimeout: options.connectionTimeout ?? 30000,
4731
+ retryCount: options.retryCount ?? 3,
4732
+ retryDelay: options.retryDelay ?? 1000
4733
+ };
4734
+ }
4735
+ async acquire() {
4736
+ if (this.isClosing) {
4737
+ throw new Error("Connection pool is closing");
4738
+ }
4739
+ const idleConnection = this.connections.find((conn) => !conn.inUse);
4740
+ if (idleConnection) {
4741
+ idleConnection.inUse = true;
4742
+ idleConnection.lastUsedAt = Date.now();
4743
+ return idleConnection.connection;
4744
+ }
4745
+ if (this.connections.length < this.options.maxConnections) {
4746
+ const connection = await this.createConnection();
4747
+ const poolConnection = {
4748
+ connection,
4749
+ inUse: true,
4750
+ createdAt: Date.now(),
4751
+ lastUsedAt: Date.now()
4752
+ };
4753
+ this.connections.push(poolConnection);
4754
+ return connection;
4755
+ }
4756
+ return await this.waitForConnection();
4757
+ }
4758
+ release(connection) {
4759
+ const poolConnection = this.connections.find((conn) => conn.connection === connection);
4760
+ if (poolConnection) {
4761
+ poolConnection.inUse = false;
4762
+ poolConnection.lastUsedAt = Date.now();
4763
+ }
4764
+ }
4765
+ async close() {
4766
+ this.isClosing = true;
4767
+ await Promise.all(Array.from(this.pendingConnections));
4768
+ const closePromises = this.connections.map((poolConnection) => this.closeConnection(poolConnection.connection));
4769
+ await Promise.all(closePromises);
4770
+ this.connections = [];
4771
+ this.isClosing = false;
4772
+ }
4773
+ getPoolStats() {
4774
+ const inUse = this.connections.filter((conn) => conn.inUse).length;
4775
+ return {
4776
+ total: this.connections.length,
4777
+ inUse,
4778
+ idle: this.connections.length - inUse,
4779
+ maxConnections: this.options.maxConnections
4780
+ };
4781
+ }
4782
+ async createConnection() {
4783
+ const createPromise = this.createConnectionWithRetry();
4784
+ this.pendingConnections.add(createPromise);
4785
+ try {
4786
+ const connection = await createPromise;
4787
+ return connection;
4788
+ } finally {
4789
+ this.pendingConnections.delete(createPromise);
4790
+ }
4791
+ }
4792
+ async createConnectionWithRetry() {
4793
+ let lastError;
4794
+ for (let i = 0;i <= this.options.retryCount; i++) {
4795
+ try {
4796
+ if (this.config.type === "sqlite") {
4797
+ return await this.createSqliteConnection(this.config.config);
4798
+ } else if (this.config.type === "postgres") {
4799
+ return await this.createPostgresConnection(this.config.config);
4800
+ } else if (this.config.type === "mysql") {
4801
+ return await this.createMysqlConnection(this.config.config);
4802
+ }
4803
+ } catch (error) {
4804
+ lastError = error instanceof Error ? error : new Error(String(error));
4805
+ if (i < this.options.retryCount) {
4806
+ await this.sleep(this.options.retryDelay);
4807
+ }
4808
+ }
4809
+ }
4810
+ throw lastError ?? new Error("Failed to create database connection");
4811
+ }
4812
+ async createSqliteConnection(config) {
4813
+ const { Database } = await import("bun:sqlite");
4814
+ const db = new Database(config.path);
4815
+ return db;
4816
+ }
4817
+ async createPostgresConnection(config) {
4818
+ const url = `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
4819
+ const { SQL } = await Promise.resolve(globalThis.Bun);
4820
+ return new SQL(url, {
4821
+ max: 1,
4822
+ tls: config.ssl ?? false
4823
+ });
4824
+ }
4825
+ async createMysqlConnection(config) {
4826
+ const url = `mysql://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
4827
+ const { SQL } = await Promise.resolve(globalThis.Bun);
4828
+ return new SQL(url, {
4829
+ max: 1
4830
+ });
4831
+ }
4832
+ async closeConnection(connection) {
4833
+ const dbType = this.config.type;
4834
+ if (dbType === "sqlite") {
4835
+ await this.closeSqliteConnection(connection);
4836
+ } else if (dbType === "postgres") {
4837
+ await this.closePostgresConnection(connection);
4838
+ } else if (dbType === "mysql") {
4839
+ await this.closeMysqlConnection(connection);
4840
+ }
4841
+ }
4842
+ async closeSqliteConnection(connection) {
4843
+ if (connection && typeof connection === "object" && "close" in connection && typeof connection.close === "function") {
4844
+ connection.close();
4845
+ }
4846
+ }
4847
+ async closePostgresConnection(_connection) {
4848
+ if (_connection && typeof _connection === "object" && "close" in _connection && typeof _connection.close === "function") {
4849
+ _connection.close();
4850
+ }
4851
+ }
4852
+ async closeMysqlConnection(_connection) {
4853
+ if (_connection && typeof _connection === "object" && "close" in _connection && typeof _connection.close === "function") {
4854
+ _connection.close();
4855
+ }
4856
+ }
4857
+ async waitForConnection() {
4858
+ const startTime = Date.now();
4859
+ const timeout = this.options.connectionTimeout;
4860
+ while (Date.now() - startTime < timeout) {
4861
+ const idleConnection = this.connections.find((conn) => !conn.inUse);
4862
+ if (idleConnection) {
4863
+ idleConnection.inUse = true;
4864
+ idleConnection.lastUsedAt = Date.now();
4865
+ return idleConnection.connection;
4866
+ }
4867
+ await this.sleep(100);
4868
+ }
4869
+ throw new Error(`Connection timeout: No available connection within ${timeout}ms`);
4870
+ }
4871
+ sleep(ms) {
4872
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
4873
+ }
4874
+ }
4875
+
4876
+ // src/database/connection-manager.ts
4877
+ class DatabaseConnectionManager {
4878
+ config;
4879
+ poolOptions;
4880
+ pool;
4881
+ currentConnection = null;
4882
+ status = "disconnected";
4883
+ error;
4884
+ constructor(config, poolOptions = {}) {
4885
+ this.config = config;
4886
+ this.poolOptions = {
4887
+ maxConnections: poolOptions.maxConnections ?? 10,
4888
+ connectionTimeout: poolOptions.connectionTimeout ?? 30000,
4889
+ retryCount: poolOptions.retryCount ?? 3,
4890
+ retryDelay: poolOptions.retryDelay ?? 1000
4891
+ };
4892
+ this.pool = new ConnectionPool(config, this.poolOptions);
4893
+ }
4894
+ async connect() {
4895
+ if (this.status === "connected") {
4896
+ return;
4897
+ }
4898
+ this.status = "connecting";
4899
+ try {
4900
+ this.currentConnection = await this.pool.acquire();
4901
+ this.status = "connected";
4902
+ this.error = undefined;
4903
+ } catch (error) {
4904
+ this.status = "error";
4905
+ this.error = error instanceof Error ? error.message : String(error);
4906
+ throw error;
4907
+ }
4908
+ }
4909
+ async disconnect() {
4910
+ if (this.status === "disconnected" || !this.currentConnection) {
4911
+ return;
4912
+ }
4913
+ try {
4914
+ this.pool.release(this.currentConnection);
4915
+ this.currentConnection = null;
4916
+ this.status = "disconnected";
4917
+ this.error = undefined;
4918
+ } catch (error) {
4919
+ this.status = "error";
4920
+ this.error = error instanceof Error ? error.message : String(error);
4921
+ throw error;
4922
+ }
4923
+ }
4924
+ async closePool() {
4925
+ await this.pool.close();
4926
+ this.currentConnection = null;
4927
+ this.status = "disconnected";
4928
+ this.error = undefined;
4929
+ }
4930
+ async healthCheck() {
4931
+ if (this.status !== "connected" || !this.currentConnection) {
4932
+ return false;
4933
+ }
4934
+ try {
4935
+ if (this.config.type === "sqlite") {
4936
+ return await this.healthCheckSqlite(this.currentConnection);
4937
+ } else if (this.config.type === "postgres") {
4938
+ return await this.healthCheckPostgres(this.currentConnection);
4939
+ } else if (this.config.type === "mysql") {
4940
+ return await this.healthCheckMysql(this.currentConnection);
4941
+ }
4942
+ return false;
4943
+ } catch {
4944
+ return false;
4945
+ }
4946
+ }
4947
+ getPoolStats() {
4948
+ return this.pool.getPoolStats();
4949
+ }
4950
+ getConnectionInfo() {
4951
+ return {
4952
+ status: this.status,
4953
+ type: this.config.type,
4954
+ error: this.error
4955
+ };
4956
+ }
4957
+ getConnection() {
4958
+ return this.currentConnection;
4959
+ }
4960
+ async acquireConnection() {
4961
+ return await this.pool.acquire();
4962
+ }
4963
+ releaseConnection(connection) {
4964
+ this.pool.release(connection);
4965
+ }
4966
+ getDatabaseType() {
4967
+ return this.config.type;
4968
+ }
4969
+ async healthCheckSqlite(connection) {
4970
+ try {
4971
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
4972
+ const db = connection;
4973
+ db.query("SELECT 1").all();
4974
+ return true;
4975
+ }
4976
+ return false;
4977
+ } catch {
4978
+ return false;
4979
+ }
4980
+ }
4981
+ async healthCheckPostgres(connection) {
4982
+ try {
4983
+ if (connection && typeof connection === "function") {
4984
+ const result = await connection`SELECT 1`;
4985
+ return Array.isArray(result) && result.length > 0;
4986
+ }
4987
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
4988
+ await connection.query("SELECT 1");
4989
+ return true;
4990
+ }
4991
+ return false;
4992
+ } catch {
4993
+ return false;
4994
+ }
4995
+ }
4996
+ async healthCheckMysql(connection) {
4997
+ try {
4998
+ if (connection && typeof connection === "function") {
4999
+ const result = await connection`SELECT 1`;
5000
+ return Array.isArray(result) && result.length > 0;
5001
+ }
5002
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
5003
+ await connection.query("SELECT 1");
5004
+ return true;
5005
+ }
5006
+ return false;
5007
+ } catch {
5008
+ return false;
5009
+ }
5010
+ }
5011
+ }
5012
+
5013
+ // src/database/service.ts
5014
+ class DatabaseService2 {
5015
+ connectionManager;
5016
+ options;
5017
+ constructor(options) {
5018
+ this.options = options;
5019
+ this.connectionManager = new DatabaseConnectionManager(options.database, options.pool);
5020
+ }
5021
+ async initialize() {
5022
+ await this.connectionManager.connect();
5023
+ }
5024
+ async close() {
5025
+ await this.connectionManager.disconnect();
5026
+ }
5027
+ async closePool() {
5028
+ await this.connectionManager.closePool();
5029
+ }
5030
+ getPoolStats() {
5031
+ return this.connectionManager.getPoolStats();
5032
+ }
5033
+ getConnection() {
5034
+ return this.connectionManager.getConnection();
5035
+ }
5036
+ get config() {
5037
+ return this.options;
5038
+ }
5039
+ getDatabaseType() {
5040
+ return this.connectionManager.getDatabaseType();
5041
+ }
5042
+ async healthCheck() {
5043
+ if (!this.options.enableHealthCheck) {
5044
+ return true;
5045
+ }
5046
+ return await this.connectionManager.healthCheck();
5047
+ }
5048
+ getConnectionInfo() {
5049
+ return this.connectionManager.getConnectionInfo();
5050
+ }
5051
+ query(sql, params) {
5052
+ const connection = this.getConnection();
5053
+ if (!connection) {
5054
+ throw new Error("Database connection is not established");
5055
+ }
5056
+ const dbType = this.getDatabaseType();
5057
+ if (dbType === "sqlite") {
5058
+ return this.querySqlite(connection, sql, params);
5059
+ } else if (dbType === "postgres" || dbType === "mysql") {
5060
+ return this.queryBunSQL(connection, sql, params);
5061
+ }
5062
+ throw new Error(`Query not supported for database type: ${dbType}`);
5063
+ }
5064
+ querySqlite(connection, sql, params) {
5065
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
5066
+ const db = connection;
5067
+ const statement = db.query(sql);
5068
+ const result = params && params.length > 0 ? statement.all(...params) : statement.all();
5069
+ return result;
5070
+ }
5071
+ throw new Error("Invalid SQLite connection");
5072
+ }
5073
+ async queryBunSQL(connection, sql, params) {
5074
+ if (connection && typeof connection === "function") {
5075
+ try {
5076
+ const sqlWithParams = this.interpolateParams(sql, params);
5077
+ const result = await connection`${sqlWithParams}`;
5078
+ return result;
5079
+ } catch {
5080
+ throw new Error("Bun.SQL parameterized queries are not fully supported. Consider using template string queries.");
5081
+ }
5082
+ }
5083
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
5084
+ const db = connection;
5085
+ const result = await db.query(sql, ...params ?? []);
5086
+ return result;
5087
+ }
5088
+ throw new Error("Invalid Bun.SQL connection");
5089
+ }
5090
+ interpolateParams(sql, params) {
5091
+ if (!params || params.length === 0) {
5092
+ return sql;
5093
+ }
5094
+ let result = sql;
5095
+ for (let i = 0;i < params.length; i++) {
5096
+ const param = params[i];
5097
+ const value = typeof param === "string" ? `'${param.replace(/'/g, "''")}'` : String(param);
5098
+ result = result.replace("?", value);
5099
+ }
5100
+ return result;
5101
+ }
5102
+ }
5103
+ DatabaseService2 = __legacyDecorateClassTS([
5104
+ Injectable(),
5105
+ __legacyMetadataTS("design:paramtypes", [
5106
+ typeof DatabaseModuleOptions === "undefined" ? Object : DatabaseModuleOptions
5107
+ ])
5108
+ ], DatabaseService2);
5109
+
5110
+ // src/database/orm/types.ts
5111
+ var ORM_SERVICE_TOKEN = Symbol("@dangao/bun-server:orm:service");
5112
+
5113
+ // src/database/database-module.ts
5114
+ init_transaction_types();
5115
+ class DatabaseModule {
5116
+ static forRoot(options) {
5117
+ const providers2 = [];
5118
+ const service = new DatabaseService2(options);
5119
+ providers2.push({
5120
+ provide: DATABASE_SERVICE_TOKEN,
5121
+ useValue: service
5122
+ }, {
5123
+ provide: DATABASE_OPTIONS_TOKEN,
5124
+ useValue: options
5125
+ }, DatabaseService2);
5126
+ if (options.orm?.enabled) {
5127
+ const ormService = new OrmService(service, {
5128
+ enabled: true,
5129
+ drizzle: options.orm.drizzle,
5130
+ databaseService: service
5131
+ });
5132
+ providers2.push({
5133
+ provide: ORM_SERVICE_TOKEN,
5134
+ useValue: ormService
5135
+ }, OrmService);
5136
+ }
5137
+ const transactionManager = new TransactionManager(service);
5138
+ providers2.push({
5139
+ provide: TRANSACTION_SERVICE_TOKEN,
5140
+ useValue: transactionManager
5141
+ }, TransactionManager);
5142
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, DatabaseModule) || {};
5143
+ const databaseExtension = new DatabaseExtension;
5144
+ const metadata = {
5145
+ ...existingMetadata,
5146
+ providers: [...existingMetadata.providers || [], ...providers2],
5147
+ exports: [
5148
+ ...existingMetadata.exports || [],
5149
+ DATABASE_SERVICE_TOKEN,
5150
+ DATABASE_OPTIONS_TOKEN,
5151
+ DatabaseService2,
5152
+ TRANSACTION_SERVICE_TOKEN,
5153
+ TransactionManager,
5154
+ ...options.orm?.enabled ? [ORM_SERVICE_TOKEN, OrmService] : []
5155
+ ],
5156
+ extensions: [
5157
+ ...existingMetadata.extensions || [],
5158
+ databaseExtension
5159
+ ]
5160
+ };
5161
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, DatabaseModule);
5162
+ return DatabaseModule;
5163
+ }
5164
+ static createHealthIndicator(databaseService) {
5165
+ return new DatabaseHealthIndicator(databaseService);
5166
+ }
5167
+ }
5168
+ DatabaseModule = __legacyDecorateClassTS([
5169
+ Module({
5170
+ providers: []
5171
+ })
5172
+ ], DatabaseModule);
5173
+ // src/database/orm/decorators.ts
5174
+ import"reflect-metadata";
5175
+ var ENTITY_METADATA_KEY = Symbol("@dangao/bun-server:orm:entity");
5176
+ var COLUMN_METADATA_KEY = Symbol("@dangao/bun-server:orm:column");
5177
+ function Entity(tableName) {
5178
+ return (target) => {
5179
+ Reflect.defineMetadata(ENTITY_METADATA_KEY, { tableName }, target);
5180
+ };
5181
+ }
5182
+ function Column(options) {
5183
+ return (target, propertyKey) => {
5184
+ const existingColumns = Reflect.getMetadata(COLUMN_METADATA_KEY, target.constructor) || [];
5185
+ const existingIndex = existingColumns.findIndex((col) => col.propertyKey === String(propertyKey));
5186
+ const columnDef = {
5187
+ name: options?.name ?? String(propertyKey),
5188
+ type: options?.type ?? "TEXT",
5189
+ primaryKey: options?.primaryKey ?? false,
5190
+ autoIncrement: options?.autoIncrement ?? false,
5191
+ nullable: options?.nullable !== undefined ? options.nullable : true,
5192
+ defaultValue: options?.defaultValue,
5193
+ propertyKey: String(propertyKey)
5194
+ };
5195
+ if (existingIndex >= 0) {
5196
+ const existing = existingColumns[existingIndex];
5197
+ existingColumns[existingIndex] = {
5198
+ ...existing,
5199
+ name: options?.name ?? existing.name,
5200
+ type: options?.type ?? existing.type,
5201
+ primaryKey: options?.primaryKey !== undefined ? options.primaryKey : existing.primaryKey,
5202
+ nullable: options?.nullable !== undefined ? options.nullable : existing.nullable,
5203
+ autoIncrement: options?.autoIncrement !== undefined ? options.autoIncrement : existing.autoIncrement,
5204
+ defaultValue: options?.defaultValue !== undefined ? options.defaultValue : existing.defaultValue,
5205
+ propertyKey: String(propertyKey)
5206
+ };
5207
+ } else {
5208
+ existingColumns.push(columnDef);
5209
+ }
5210
+ Reflect.defineMetadata(COLUMN_METADATA_KEY, existingColumns, target.constructor);
5211
+ };
5212
+ }
5213
+ function PrimaryKey() {
5214
+ return Column({ primaryKey: true, nullable: false });
5215
+ }
5216
+ function getEntityMetadata(target) {
5217
+ if (typeof target === "function" || typeof target === "object" && target !== null) {
5218
+ return Reflect.getMetadata(ENTITY_METADATA_KEY, target);
5219
+ }
5220
+ return;
5221
+ }
5222
+ function getColumnMetadata(target) {
5223
+ if (typeof target === "function" || typeof target === "object" && target !== null) {
5224
+ return Reflect.getMetadata(COLUMN_METADATA_KEY, target) || [];
5225
+ }
5226
+ return [];
5227
+ }
5228
+ // src/database/orm/repository-decorator.ts
5229
+ import"reflect-metadata";
5230
+ var REPOSITORY_METADATA_KEY = Symbol("@dangao/bun-server:orm:repository");
5231
+ function Repository(tableName, primaryKey = "id") {
5232
+ return function(target) {
5233
+ Injectable()(target);
5234
+ Reflect.defineMetadata(REPOSITORY_METADATA_KEY, { tableName, primaryKey }, target);
5235
+ return target;
5236
+ };
5237
+ }
5238
+ function getRepositoryMetadata(target) {
5239
+ if (typeof target === "function" || typeof target === "object" && target !== null) {
5240
+ return Reflect.getMetadata(REPOSITORY_METADATA_KEY, target);
5241
+ }
5242
+ return;
5243
+ }
5244
+
5245
+ // src/database/orm/index.ts
5246
+ init_transaction_decorator();
5247
+
5248
+ // src/database/orm/repository.ts
5249
+ class BaseRepository {
5250
+ databaseService;
5251
+ constructor(databaseService) {
5252
+ this.databaseService = databaseService;
5253
+ }
5254
+ async findAll() {
5255
+ const sql = `SELECT * FROM ${this.tableName}`;
5256
+ const result = await this.executeQuery(sql);
5257
+ return Array.isArray(result) ? result : [];
5258
+ }
5259
+ async findById(id) {
5260
+ const sql = `SELECT * FROM ${this.tableName} WHERE ${this.primaryKey} = ?`;
5261
+ const result = await this.executeQuery(sql, [id]);
5262
+ if (Array.isArray(result) && result.length > 0) {
5263
+ return result[0];
5264
+ }
5265
+ return null;
5266
+ }
5267
+ async create(data) {
5268
+ const keys = Object.keys(data);
5269
+ const values = Object.values(data);
5270
+ const placeholders = keys.map(() => "?").join(", ");
5271
+ const sql = `INSERT INTO ${this.tableName} (${keys.join(", ")}) VALUES (${placeholders})`;
5272
+ await this.executeQuery(sql, values);
5273
+ const lastIdResult = await this.executeQuery("SELECT last_insert_rowid() as id");
5274
+ const lastId = Array.isArray(lastIdResult) && lastIdResult[0] ? lastIdResult[0].id : null;
5275
+ if (lastId !== null) {
5276
+ return await this.findById(lastId);
5277
+ }
5278
+ return data;
5279
+ }
5280
+ async update(id, data) {
5281
+ const keys = Object.keys(data);
5282
+ const values = Object.values(data);
5283
+ const setClause = keys.map((key) => `${key} = ?`).join(", ");
5284
+ const sql = `UPDATE ${this.tableName} SET ${setClause} WHERE ${this.primaryKey} = ?`;
5285
+ await this.executeQuery(sql, [...values, id]);
5286
+ return await this.findById(id);
5287
+ }
5288
+ async delete(id) {
5289
+ const sql = `DELETE FROM ${this.tableName} WHERE ${this.primaryKey} = ?`;
5290
+ await this.executeQuery(sql, [id]);
5291
+ return true;
5292
+ }
5293
+ async executeQuery(sql, params) {
5294
+ const result = this.databaseService.query(sql, params);
5295
+ if (result instanceof Promise) {
5296
+ const resolved = await result;
5297
+ return Array.isArray(resolved) ? resolved : [resolved];
5298
+ }
5299
+ return Array.isArray(result) ? result : [result];
5300
+ }
5301
+ }
5302
+ BaseRepository = __legacyDecorateClassTS([
5303
+ __legacyDecorateParamTS(0, Inject(DATABASE_SERVICE_TOKEN)),
5304
+ __legacyMetadataTS("design:paramtypes", [
5305
+ typeof DatabaseService === "undefined" ? Object : DatabaseService
5306
+ ])
5307
+ ], BaseRepository);
5308
+ // src/database/orm/drizzle-repository.ts
5309
+ class DrizzleBaseRepository {
5310
+ databaseService;
5311
+ constructor(databaseService) {
5312
+ this.databaseService = databaseService;
5313
+ }
5314
+ }
5315
+
5316
+ // src/database/orm/index.ts
5317
+ init_transaction_interceptor();
5318
+ init_transaction_types();
5319
+ // src/testing/harness.ts
5320
+ import { performance as performance2 } from "perf_hooks";
5321
+
5322
+ class PerformanceHarness {
5323
+ static async benchmark(name, iterations, runner) {
5324
+ if (iterations <= 0) {
5325
+ throw new Error("iterations must be greater than 0");
5326
+ }
5327
+ const start = performance2.now();
5328
+ for (let i = 0;i < iterations; i++) {
5329
+ await runner(i);
5330
+ }
5331
+ const durationMs = performance2.now() - start;
5332
+ const opsPerSecond = iterations / Math.max(durationMs / 1000, 0.0001);
5333
+ return {
5334
+ name,
5335
+ iterations,
5336
+ durationMs,
5337
+ opsPerSecond
5338
+ };
5339
+ }
5340
+ }
5341
+
5342
+ class StressTester {
5343
+ static async run(name, iterations, concurrency, task) {
5344
+ if (iterations <= 0) {
5345
+ throw new Error("iterations must be greater than 0");
5346
+ }
5347
+ if (concurrency <= 0) {
5348
+ throw new Error("concurrency must be greater than 0");
5349
+ }
5350
+ let next = 0;
5351
+ let errors = 0;
5352
+ const start = performance2.now();
5353
+ const worker = async () => {
5354
+ while (true) {
5355
+ const current = next;
5356
+ next += 1;
5357
+ if (current >= iterations) {
5358
+ break;
5359
+ }
5360
+ try {
5361
+ await task(current);
5362
+ } catch (error) {
5363
+ errors += 1;
5364
+ }
5365
+ }
5366
+ };
5367
+ const workers = Array.from({ length: Math.min(concurrency, iterations) }, () => worker());
5368
+ await Promise.all(workers);
5369
+ const durationMs = performance2.now() - start;
5370
+ return {
5371
+ name,
5372
+ iterations,
5373
+ concurrency: Math.min(concurrency, iterations),
5374
+ durationMs,
5375
+ errors
5376
+ };
5377
+ }
5378
+ }
5379
+ // src/cache/types.ts
5380
+ class MemoryCacheStore {
5381
+ store = new Map;
5382
+ cleanupInterval;
5383
+ constructor(options) {
5384
+ if (options?.cleanupInterval !== undefined) {
5385
+ this.cleanupInterval = setInterval(() => {
5386
+ this.cleanup();
5387
+ }, options.cleanupInterval);
5388
+ }
5389
+ }
5390
+ async get(key) {
5391
+ const entry = this.store.get(key);
5392
+ if (!entry) {
5393
+ return;
5394
+ }
5395
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
5396
+ this.store.delete(key);
5397
+ return;
5398
+ }
5399
+ return entry.value;
5400
+ }
5401
+ async set(key, value, ttl) {
5402
+ const expiresAt = ttl && ttl > 0 ? Date.now() + ttl : undefined;
5403
+ this.store.set(key, { value, expiresAt });
5404
+ return true;
5405
+ }
5406
+ async delete(key) {
5407
+ return this.store.delete(key);
5408
+ }
5409
+ async has(key) {
5410
+ const entry = this.store.get(key);
5411
+ if (!entry) {
5412
+ return false;
5413
+ }
5414
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
5415
+ this.store.delete(key);
5416
+ return false;
5417
+ }
5418
+ return true;
5419
+ }
5420
+ async clear() {
5421
+ this.store.clear();
5422
+ return true;
5423
+ }
5424
+ async getMany(keys) {
5425
+ const result = new Map;
5426
+ const now = Date.now();
5427
+ for (const key of keys) {
5428
+ const entry = this.store.get(key);
5429
+ if (entry) {
5430
+ if (entry.expiresAt && now > entry.expiresAt) {
5431
+ this.store.delete(key);
5432
+ continue;
5433
+ }
5434
+ result.set(key, entry.value);
5435
+ }
5436
+ }
5437
+ return result;
5438
+ }
5439
+ async setMany(entries, ttl) {
5440
+ const expiresAt = ttl && ttl > 0 ? Date.now() + ttl : undefined;
5441
+ for (const { key, value } of entries) {
5442
+ this.store.set(key, { value, expiresAt });
5443
+ }
5444
+ return true;
5445
+ }
5446
+ async deleteMany(keys) {
5447
+ const deleted = [];
5448
+ for (const key of keys) {
5449
+ if (this.store.delete(key)) {
5450
+ deleted.push(key);
5451
+ }
5452
+ }
5453
+ return deleted;
5454
+ }
5455
+ cleanup() {
5456
+ const now = Date.now();
5457
+ for (const [key, entry] of this.store.entries()) {
5458
+ if (entry.expiresAt && now > entry.expiresAt) {
5459
+ this.store.delete(key);
5460
+ }
5461
+ }
5462
+ }
5463
+ destroy() {
5464
+ if (this.cleanupInterval) {
5465
+ clearInterval(this.cleanupInterval);
5466
+ this.cleanupInterval = undefined;
5467
+ }
5468
+ this.store.clear();
5469
+ }
5470
+ }
5471
+
5472
+ class RedisCacheStore {
5473
+ client;
5474
+ keyPrefix;
5475
+ constructor(options) {
5476
+ this.client = options.client;
5477
+ this.keyPrefix = options.keyPrefix ?? "cache:";
5478
+ }
5479
+ getKey(key) {
5480
+ return `${this.keyPrefix}${key}`;
5481
+ }
5482
+ async get(key) {
5483
+ const value = await this.client.get(this.getKey(key));
5484
+ if (value === null) {
5485
+ return;
5486
+ }
5487
+ try {
5488
+ return JSON.parse(value);
5489
+ } catch {
5490
+ return;
5491
+ }
5492
+ }
5493
+ async set(key, value, ttl) {
5494
+ try {
5495
+ const serialized = JSON.stringify(value);
5496
+ if (ttl && ttl > 0) {
5497
+ await this.client.set(this.getKey(key), serialized, { PX: ttl });
5498
+ } else {
5499
+ await this.client.set(this.getKey(key), serialized);
5500
+ }
5501
+ return true;
5502
+ } catch {
5503
+ return false;
5504
+ }
5505
+ }
5506
+ async delete(key) {
5507
+ try {
5508
+ await this.client.del(this.getKey(key));
5509
+ return true;
5510
+ } catch {
5511
+ return false;
5512
+ }
5513
+ }
5514
+ async has(key) {
5515
+ try {
5516
+ const result = await this.client.exists(this.getKey(key));
5517
+ return result === 1;
5518
+ } catch {
5519
+ return false;
5520
+ }
5521
+ }
5522
+ async clear() {
5523
+ try {
5524
+ await this.client.flushdb();
5525
+ return true;
5526
+ } catch {
5527
+ return false;
5528
+ }
5529
+ }
5530
+ async getMany(keys) {
5531
+ const result = new Map;
5532
+ if (keys.length === 0) {
5533
+ return result;
5534
+ }
5535
+ try {
5536
+ const prefixedKeys = keys.map((k) => this.getKey(k));
5537
+ const values = await this.client.mget(prefixedKeys);
5538
+ for (let i = 0;i < keys.length; i++) {
5539
+ const value = values[i];
5540
+ if (value !== null) {
5541
+ try {
5542
+ result.set(keys[i], JSON.parse(value));
5543
+ } catch {}
5544
+ }
5545
+ }
5546
+ } catch {}
5547
+ return result;
5548
+ }
5549
+ async setMany(entries, ttl) {
5550
+ if (entries.length === 0) {
5551
+ return true;
5552
+ }
5553
+ try {
5554
+ const redisEntries = entries.map(({ key, value }) => ({
5555
+ key: this.getKey(key),
5556
+ value: JSON.stringify(value)
5557
+ }));
5558
+ await this.client.mset(redisEntries);
5559
+ if (ttl && ttl > 0) {
5560
+ for (const entry of redisEntries) {
5561
+ await this.client.set(entry.key, entry.value, { PX: ttl });
5562
+ }
5563
+ }
5564
+ return true;
5565
+ } catch {
5566
+ return false;
5567
+ }
5568
+ }
5569
+ async deleteMany(keys) {
5570
+ if (keys.length === 0) {
5571
+ return [];
5572
+ }
5573
+ try {
5574
+ const prefixedKeys = keys.map((k) => this.getKey(k));
5575
+ const deleted = [];
5576
+ for (const key of prefixedKeys) {
5577
+ try {
5578
+ await this.client.del(key);
5579
+ deleted.push(key.replace(this.keyPrefix, ""));
5580
+ } catch {}
5581
+ }
5582
+ return deleted;
5583
+ } catch {
5584
+ return [];
5585
+ }
5586
+ }
5587
+ }
5588
+ var CACHE_SERVICE_TOKEN = Symbol("@dangao/bun-server:cache:service");
5589
+ var CACHE_OPTIONS_TOKEN = Symbol("@dangao/bun-server:cache:options");
5590
+
5591
+ // src/cache/service.ts
5592
+ class CacheService {
5593
+ store;
5594
+ defaultTtl;
5595
+ keyPrefix;
5596
+ constructor(options) {
5597
+ this.store = options.store;
5598
+ this.defaultTtl = options.defaultTtl ?? 3600000;
5599
+ this.keyPrefix = options.keyPrefix ?? "";
5600
+ }
5601
+ async get(key) {
5602
+ return this.store.get(this.getKey(key));
5603
+ }
5604
+ async set(key, value, ttl) {
5605
+ const finalTtl = ttl !== undefined ? ttl : this.defaultTtl;
5606
+ return this.store.set(this.getKey(key), value, finalTtl);
5607
+ }
5608
+ async delete(key) {
5609
+ return this.store.delete(this.getKey(key));
5610
+ }
5611
+ async has(key) {
5612
+ return this.store.has(this.getKey(key));
5613
+ }
5614
+ async clear() {
5615
+ return this.store.clear();
5616
+ }
5617
+ async getMany(keys) {
5618
+ const prefixedKeys = keys.map((k) => this.getKey(k));
5619
+ const result = await this.store.getMany(prefixedKeys);
5620
+ const map = new Map;
5621
+ for (const [key, value] of result.entries()) {
5622
+ map.set(key.replace(this.keyPrefix, ""), value);
5623
+ }
5624
+ return map;
5625
+ }
5626
+ async setMany(entries, ttl) {
5627
+ const finalTtl = ttl !== undefined ? ttl : this.defaultTtl;
5628
+ const prefixedEntries = entries.map(({ key, value }) => ({
5629
+ key: this.getKey(key),
5630
+ value
5631
+ }));
5632
+ return this.store.setMany(prefixedEntries, finalTtl);
5633
+ }
5634
+ async deleteMany(keys) {
5635
+ const prefixedKeys = keys.map((k) => this.getKey(k));
5636
+ const deleted = await this.store.deleteMany(prefixedKeys);
5637
+ return deleted.map((k) => k.replace(this.keyPrefix, ""));
5638
+ }
5639
+ async getOrSet(key, factory, ttl) {
5640
+ const cached = await this.get(key);
5641
+ if (cached !== undefined) {
5642
+ return cached;
5643
+ }
5644
+ const value = await factory();
5645
+ await this.set(key, value, ttl);
5646
+ return value;
5647
+ }
5648
+ getKey(key) {
5649
+ return this.keyPrefix ? `${this.keyPrefix}${key}` : key;
5650
+ }
5651
+ }
5652
+ CacheService = __legacyDecorateClassTS([
5653
+ Injectable(),
5654
+ __legacyDecorateParamTS(0, Inject(CACHE_OPTIONS_TOKEN)),
5655
+ __legacyMetadataTS("design:paramtypes", [
5656
+ typeof CacheModuleOptions === "undefined" ? Object : CacheModuleOptions
5657
+ ])
5658
+ ], CacheService);
5659
+
5660
+ // src/cache/cache-module.ts
5661
+ class CacheModule {
5662
+ static forRoot(options = {}) {
5663
+ const providers2 = [];
5664
+ const store = options.store ?? new MemoryCacheStore({
5665
+ cleanupInterval: 60000
5666
+ });
5667
+ const service = new CacheService({
5668
+ store,
5669
+ defaultTtl: options.defaultTtl,
5670
+ keyPrefix: options.keyPrefix
5671
+ });
5672
+ providers2.push({
5673
+ provide: CACHE_SERVICE_TOKEN,
5674
+ useValue: service
5675
+ }, {
5676
+ provide: CACHE_OPTIONS_TOKEN,
5677
+ useValue: options
5678
+ }, CacheService);
5679
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, CacheModule) || {};
5680
+ const metadata = {
5681
+ ...existingMetadata,
5682
+ providers: [...existingMetadata.providers || [], ...providers2],
5683
+ exports: [
5684
+ ...existingMetadata.exports || [],
5685
+ CACHE_SERVICE_TOKEN,
5686
+ CACHE_OPTIONS_TOKEN,
5687
+ CacheService
5688
+ ]
5689
+ };
5690
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, CacheModule);
5691
+ return CacheModule;
5692
+ }
5693
+ }
5694
+ CacheModule = __legacyDecorateClassTS([
5695
+ Module({
5696
+ providers: []
5697
+ })
5698
+ ], CacheModule);
5699
+ // src/cache/decorators.ts
5700
+ import"reflect-metadata";
5701
+ var CACHEABLE_METADATA_KEY = Symbol("@dangao/bun-server:cache:cacheable");
5702
+ var CACHE_EVICT_METADATA_KEY = Symbol("@dangao/bun-server:cache:cache-evict");
5703
+ var CACHE_PUT_METADATA_KEY = Symbol("@dangao/bun-server:cache:cache-put");
5704
+ function Cacheable(options = {}) {
5705
+ return function(target, propertyKey, descriptor) {
5706
+ const metadata = {
5707
+ key: options.key,
5708
+ keyPrefix: options.keyPrefix,
5709
+ ttl: options.ttl,
5710
+ condition: options.condition
5711
+ };
5712
+ Reflect.defineMetadata(CACHEABLE_METADATA_KEY, metadata, descriptor.value);
5713
+ };
5714
+ }
5715
+ function CacheEvict(options = {}) {
5716
+ return function(target, propertyKey, descriptor) {
5717
+ const metadata = {
5718
+ key: options.key,
5719
+ keyPrefix: options.keyPrefix,
5720
+ beforeInvocation: options.beforeInvocation ?? false,
5721
+ allEntries: options.allEntries ?? false
5722
+ };
5723
+ Reflect.defineMetadata(CACHE_EVICT_METADATA_KEY, metadata, descriptor.value);
5724
+ };
5725
+ }
5726
+ function CachePut(options = {}) {
5727
+ return function(target, propertyKey, descriptor) {
5728
+ const metadata = {
5729
+ key: options.key,
5730
+ keyPrefix: options.keyPrefix,
5731
+ ttl: options.ttl,
5732
+ condition: options.condition
5733
+ };
5734
+ Reflect.defineMetadata(CACHE_PUT_METADATA_KEY, metadata, descriptor.value);
5735
+ };
5736
+ }
5737
+ // src/queue/types.ts
5738
+ class MemoryQueueStore {
5739
+ queues = new Map;
5740
+ jobCounter = 0;
5741
+ async add(queueName, job) {
5742
+ const queue = this.getQueue(queueName);
5743
+ const jobId = job.options?.jobId ?? `job_${++this.jobCounter}_${Date.now()}`;
5744
+ const now = Date.now();
5745
+ const fullJob = {
5746
+ id: jobId,
5747
+ name: job.name,
5748
+ data: job.data,
5749
+ options: job.options,
5750
+ status: job.options?.delay ? "delayed" : "waiting",
5751
+ createdAt: now,
5752
+ updatedAt: now
5753
+ };
5754
+ queue.set(jobId, fullJob);
5755
+ return jobId;
5756
+ }
5757
+ async get(queueName, jobId) {
5758
+ const queue = this.getQueue(queueName);
5759
+ return queue.get(jobId);
5760
+ }
5761
+ async getNext(queueName) {
5762
+ const queue = this.getQueue(queueName);
5763
+ const now = Date.now();
5764
+ let nextJob;
5765
+ let highestPriority = -Infinity;
5766
+ for (const job of queue.values()) {
5767
+ if (job.status === "delayed" && job.options?.delay) {
5768
+ const delayEndTime = job.createdAt + job.options.delay;
5769
+ if (now >= delayEndTime) {
5770
+ if ((job.options.priority ?? 0) > highestPriority || !nextJob) {
5771
+ nextJob = job;
5772
+ highestPriority = job.options?.priority ?? 0;
5773
+ }
5774
+ }
5775
+ } else if (job.status === "waiting") {
5776
+ if ((job.options?.priority ?? 0) > highestPriority || !nextJob) {
5777
+ nextJob = job;
5778
+ highestPriority = job.options?.priority ?? 0;
5779
+ }
5780
+ }
5781
+ }
5782
+ return nextJob;
5783
+ }
5784
+ async updateStatus(queueName, jobId, status) {
5785
+ const queue = this.getQueue(queueName);
5786
+ const job = queue.get(jobId);
5787
+ if (!job) {
5788
+ return false;
5789
+ }
5790
+ job.status = status;
5791
+ job.updatedAt = Date.now();
5792
+ return true;
5793
+ }
5794
+ async delete(queueName, jobId) {
5795
+ const queue = this.getQueue(queueName);
5796
+ return queue.delete(jobId);
5797
+ }
5798
+ async clear(queueName) {
5799
+ const queue = this.getQueue(queueName);
5800
+ queue.clear();
5801
+ return true;
5802
+ }
5803
+ async count(queueName) {
5804
+ const queue = this.getQueue(queueName);
5805
+ return queue.size;
5806
+ }
5807
+ getQueue(queueName) {
5808
+ if (!this.queues.has(queueName)) {
5809
+ this.queues.set(queueName, new Map);
5810
+ }
5811
+ return this.queues.get(queueName);
5812
+ }
5813
+ }
5814
+ var QUEUE_SERVICE_TOKEN = Symbol("@dangao/bun-server:queue:service");
5815
+ var QUEUE_OPTIONS_TOKEN = Symbol("@dangao/bun-server:queue:options");
5816
+
5817
+ // src/queue/service.ts
5818
+ class QueueService {
5819
+ store;
5820
+ defaultQueue;
5821
+ enableWorker;
5822
+ concurrency;
5823
+ workers = new Map;
5824
+ cronJobs = new Map;
5825
+ cronTimers = new Map;
5826
+ constructor(options) {
5827
+ this.store = options.store;
5828
+ this.defaultQueue = options.defaultQueue ?? "default";
5829
+ this.enableWorker = options.enableWorker ?? true;
5830
+ this.concurrency = options.concurrency ?? 1;
5831
+ if (this.enableWorker) {
5832
+ this.startWorker(this.defaultQueue);
5833
+ }
5834
+ }
5835
+ async add(jobName, data, options, queueName) {
5836
+ const queue = queueName ?? this.defaultQueue;
5837
+ const jobId = await this.store.add(queue, {
5838
+ name: jobName,
5839
+ data,
5840
+ options
5841
+ });
5842
+ if (this.enableWorker && !this.workers.has(queue)) {
5843
+ this.startWorker(queue);
5844
+ }
5845
+ return jobId;
5846
+ }
5847
+ async get(jobId, queueName) {
5848
+ const queue = queueName ?? this.defaultQueue;
5849
+ return this.store.get(queue, jobId);
5850
+ }
5851
+ async delete(jobId, queueName) {
5852
+ const queue = queueName ?? this.defaultQueue;
5853
+ return this.store.delete(queue, jobId);
5854
+ }
5855
+ async clear(queueName) {
5856
+ const queue = queueName ?? this.defaultQueue;
5857
+ return this.store.clear(queue);
5858
+ }
5859
+ async count(queueName) {
5860
+ const queue = queueName ?? this.defaultQueue;
5861
+ return this.store.count(queue);
5862
+ }
5863
+ async registerHandler(jobName, handler, queueName) {
5864
+ const queue = queueName ?? this.defaultQueue;
5865
+ const key = `${queue}:${jobName}`;
5866
+ this.handlers = this.handlers ?? new Map;
5867
+ this.handlers.set(key, handler);
5868
+ }
5869
+ async registerCron(jobName, handler, options, queueName) {
5870
+ const queue = queueName ?? this.defaultQueue;
5871
+ const key = `${queue}:${jobName}`;
5872
+ this.cronJobs.set(key, { handler, options });
5873
+ if (options.runOnInit) {
5874
+ await this.add(jobName, {}, undefined, queue);
5875
+ }
5876
+ const interval = this.parseCronInterval(options.pattern);
5877
+ if (interval > 0) {
5878
+ const timer = setInterval(async () => {
5879
+ await this.add(jobName, {}, undefined, queue);
5880
+ }, interval);
5881
+ this.cronTimers.set(key, timer);
5882
+ }
5883
+ }
5884
+ startWorker(queueName) {
5885
+ if (this.workers.has(queueName)) {
5886
+ return;
5887
+ }
5888
+ const workerSet = new Set;
5889
+ this.workers.set(queueName, workerSet);
5890
+ for (let i = 0;i < this.concurrency; i++) {
5891
+ const worker = this.processQueue(queueName);
5892
+ workerSet.add(worker);
5893
+ }
5894
+ }
5895
+ async processQueue(queueName) {
5896
+ while (true) {
5897
+ try {
5898
+ const job = await this.store.getNext(queueName);
5899
+ if (!job) {
5900
+ await new Promise((resolve2) => setTimeout(resolve2, 1000));
5901
+ continue;
5902
+ }
5903
+ await this.store.updateStatus(queueName, job.id, "active");
5904
+ try {
5905
+ const handler = this.getHandler(job.name, queueName);
5906
+ if (handler) {
5907
+ await handler(job);
5908
+ await this.store.updateStatus(queueName, job.id, "completed");
5909
+ } else {
5910
+ await this.store.updateStatus(queueName, job.id, "failed");
5911
+ }
5912
+ } catch (error) {
5913
+ await this.store.updateStatus(queueName, job.id, "failed");
5914
+ console.error(`Job ${job.id} failed:`, error);
5915
+ }
5916
+ } catch (error) {
5917
+ console.error(`Error processing queue ${queueName}:`, error);
5918
+ await new Promise((resolve2) => setTimeout(resolve2, 1000));
5919
+ }
5920
+ }
5921
+ }
5922
+ getHandler(jobName, queueName) {
5923
+ const key = `${queueName}:${jobName}`;
5924
+ return this.handlers?.get(key);
5925
+ }
5926
+ parseCronInterval(pattern) {
5927
+ const parts = pattern.trim().split(/\s+/);
5928
+ if (parts.length !== 5) {
5929
+ return -1;
5930
+ }
5931
+ const [minute, hour, day, month, weekday] = parts;
5932
+ if (minute === "*" && hour === "*" && day === "*" && month === "*" && weekday === "*") {
5933
+ return 60000;
5934
+ }
5935
+ if (/^\d+$/.test(minute) && hour === "*" && day === "*" && month === "*" && weekday === "*") {
5936
+ return parseInt(minute, 10) * 60000;
5937
+ }
5938
+ return -1;
5939
+ }
5940
+ destroy() {
5941
+ for (const timer of this.cronTimers.values()) {
5942
+ clearInterval(timer);
5943
+ }
5944
+ this.cronTimers.clear();
5945
+ this.cronJobs.clear();
5946
+ this.workers.clear();
5947
+ }
5948
+ }
5949
+ QueueService = __legacyDecorateClassTS([
5950
+ Injectable(),
5951
+ __legacyDecorateParamTS(0, Inject(QUEUE_OPTIONS_TOKEN)),
5952
+ __legacyMetadataTS("design:paramtypes", [
5953
+ typeof QueueModuleOptions === "undefined" ? Object : QueueModuleOptions
5954
+ ])
5955
+ ], QueueService);
5956
+
5957
+ // src/queue/queue-module.ts
5958
+ class QueueModule {
5959
+ static forRoot(options = {}) {
5960
+ const providers2 = [];
5961
+ const store = options.store ?? new MemoryQueueStore;
5962
+ const service = new QueueService({
5963
+ store,
5964
+ defaultQueue: options.defaultQueue,
5965
+ enableWorker: options.enableWorker,
5966
+ concurrency: options.concurrency
5967
+ });
5968
+ providers2.push({
5969
+ provide: QUEUE_SERVICE_TOKEN,
5970
+ useValue: service
5971
+ }, {
5972
+ provide: QUEUE_OPTIONS_TOKEN,
5973
+ useValue: options
5974
+ }, QueueService);
5975
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, QueueModule) || {};
5976
+ const metadata = {
5977
+ ...existingMetadata,
5978
+ providers: [...existingMetadata.providers || [], ...providers2],
5979
+ exports: [
5980
+ ...existingMetadata.exports || [],
5981
+ QUEUE_SERVICE_TOKEN,
5982
+ QUEUE_OPTIONS_TOKEN,
5983
+ QueueService
5984
+ ]
5985
+ };
5986
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, QueueModule);
5987
+ return QueueModule;
5988
+ }
5989
+ }
5990
+ QueueModule = __legacyDecorateClassTS([
5991
+ Module({
5992
+ providers: []
5993
+ })
5994
+ ], QueueModule);
5995
+ // src/queue/decorators.ts
5996
+ import"reflect-metadata";
5997
+ var QUEUE_METADATA_KEY = Symbol("@dangao/bun-server:queue:queue");
5998
+ var CRON_METADATA_KEY = Symbol("@dangao/bun-server:queue:cron");
5999
+ function Queue(options = {}) {
6000
+ return function(target, propertyKey, descriptor) {
6001
+ const metadata = {
6002
+ name: options.name
6003
+ };
6004
+ Reflect.defineMetadata(QUEUE_METADATA_KEY, metadata, descriptor.value);
6005
+ };
6006
+ }
6007
+ function Cron(options) {
6008
+ return function(target, propertyKey, descriptor) {
6009
+ const metadata = {
6010
+ pattern: options.pattern,
6011
+ timezone: options.timezone,
6012
+ runOnInit: options.runOnInit ?? false,
6013
+ queueName: options.queueName
6014
+ };
6015
+ Reflect.defineMetadata(CRON_METADATA_KEY, metadata, descriptor.value);
6016
+ };
6017
+ }
6018
+ // src/session/service.ts
6019
+ import { randomBytes } from "crypto";
6020
+ class SessionService {
6021
+ store;
6022
+ name;
6023
+ maxAge;
6024
+ rolling;
6025
+ cookieOptions;
6026
+ constructor(options) {
6027
+ this.store = options.store;
6028
+ this.name = options.name ?? "sessionId";
6029
+ this.maxAge = options.maxAge ?? 86400000;
6030
+ this.rolling = options.rolling ?? true;
6031
+ this.cookieOptions = {
6032
+ secure: options.cookie?.secure ?? false,
6033
+ httpOnly: options.cookie?.httpOnly ?? true,
6034
+ path: options.cookie?.path ?? "/",
6035
+ domain: options.cookie?.domain,
6036
+ sameSite: options.cookie?.sameSite ?? "lax"
6037
+ };
6038
+ }
6039
+ generateSessionId() {
6040
+ return randomBytes(32).toString("hex");
6041
+ }
6042
+ async create(initialData = {}) {
6043
+ const now = Date.now();
6044
+ const session = {
6045
+ id: this.generateSessionId(),
6046
+ data: initialData,
6047
+ createdAt: now,
6048
+ lastAccessedAt: now,
6049
+ expiresAt: now + this.maxAge
6050
+ };
6051
+ await this.store.set(session, this.maxAge);
6052
+ return session;
6053
+ }
6054
+ async get(sessionId) {
6055
+ const session = await this.store.get(sessionId);
6056
+ if (!session) {
6057
+ return;
6058
+ }
6059
+ if (this.rolling) {
6060
+ await this.touch(sessionId);
6061
+ }
6062
+ return session;
6063
+ }
6064
+ async set(sessionId, data) {
6065
+ const session = await this.store.get(sessionId);
6066
+ if (!session) {
6067
+ return false;
6068
+ }
6069
+ session.data = { ...session.data, ...data };
6070
+ session.lastAccessedAt = Date.now();
6071
+ if (this.rolling) {
6072
+ session.expiresAt = Date.now() + this.maxAge;
6073
+ }
6074
+ return this.store.set(session, this.maxAge);
6075
+ }
6076
+ async getValue(sessionId, key) {
6077
+ const session = await this.store.get(sessionId);
6078
+ if (!session) {
6079
+ return;
6080
+ }
6081
+ return session.data[key];
6082
+ }
6083
+ async setValue(sessionId, key, value) {
6084
+ const session = await this.store.get(sessionId);
6085
+ if (!session) {
6086
+ return false;
6087
+ }
6088
+ session.data[key] = value;
6089
+ session.lastAccessedAt = Date.now();
6090
+ if (this.rolling) {
6091
+ session.expiresAt = Date.now() + this.maxAge;
6092
+ }
6093
+ return this.store.set(session, this.maxAge);
6094
+ }
6095
+ async deleteValue(sessionId, key) {
6096
+ const session = await this.store.get(sessionId);
6097
+ if (!session) {
6098
+ return false;
6099
+ }
6100
+ delete session.data[key];
6101
+ session.lastAccessedAt = Date.now();
6102
+ if (this.rolling) {
6103
+ session.expiresAt = Date.now() + this.maxAge;
6104
+ }
6105
+ return this.store.set(session, this.maxAge);
6106
+ }
6107
+ async delete(sessionId) {
6108
+ return this.store.delete(sessionId);
6109
+ }
6110
+ async touch(sessionId) {
6111
+ return this.store.touch(sessionId);
6112
+ }
6113
+ getCookieName() {
6114
+ return this.name;
6115
+ }
6116
+ getCookieOptions() {
6117
+ return this.cookieOptions;
6118
+ }
6119
+ getMaxAge() {
6120
+ return this.maxAge;
6121
+ }
6122
+ }
6123
+ SessionService = __legacyDecorateClassTS([
6124
+ Injectable(),
6125
+ __legacyDecorateParamTS(0, Inject(SESSION_OPTIONS_TOKEN)),
6126
+ __legacyMetadataTS("design:paramtypes", [
6127
+ typeof SessionModuleOptions === "undefined" ? Object : SessionModuleOptions
6128
+ ])
6129
+ ], SessionService);
6130
+
6131
+ // src/session/session-module.ts
6132
+ class SessionModule {
6133
+ static forRoot(options = {}) {
6134
+ const providers2 = [];
6135
+ const store = options.store ?? new MemorySessionStore({
6136
+ cleanupInterval: 60000
6137
+ });
6138
+ const service = new SessionService({
6139
+ store,
6140
+ name: options.name,
6141
+ maxAge: options.maxAge,
6142
+ rolling: options.rolling,
6143
+ cookie: options.cookie
6144
+ });
6145
+ providers2.push({
6146
+ provide: SESSION_SERVICE_TOKEN,
6147
+ useValue: service
6148
+ }, {
6149
+ provide: SESSION_OPTIONS_TOKEN,
6150
+ useValue: options
6151
+ }, SessionService);
6152
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, SessionModule) || {};
6153
+ const metadata = {
6154
+ ...existingMetadata,
6155
+ providers: [...existingMetadata.providers || [], ...providers2],
6156
+ exports: [
6157
+ ...existingMetadata.exports || [],
6158
+ SESSION_SERVICE_TOKEN,
6159
+ SESSION_OPTIONS_TOKEN,
6160
+ SessionService
6161
+ ]
6162
+ };
6163
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SessionModule);
6164
+ return SessionModule;
6165
+ }
6166
+ }
6167
+ SessionModule = __legacyDecorateClassTS([
6168
+ Module({
6169
+ providers: []
6170
+ })
6171
+ ], SessionModule);
6172
+ // src/session/middleware.ts
6173
+ function createSessionMiddleware(container) {
6174
+ return async (context2, next) => {
6175
+ let sessionService;
6176
+ try {
6177
+ sessionService = container.resolve(SESSION_SERVICE_TOKEN);
6178
+ } catch {
6179
+ return await next();
6180
+ }
6181
+ if (!sessionService) {
6182
+ return await next();
6183
+ }
6184
+ const cookieName = sessionService.getCookieName();
6185
+ const cookieHeader = context2.request.headers.get("cookie");
6186
+ let sessionId;
6187
+ if (cookieHeader) {
6188
+ const cookies = cookieHeader.split(";").map((c) => c.trim());
6189
+ for (const cookie of cookies) {
6190
+ if (cookie.startsWith(`${cookieName}=`)) {
6191
+ sessionId = cookie.substring(cookieName.length + 1).trim();
6192
+ break;
6193
+ }
6194
+ }
6195
+ }
6196
+ if (sessionId) {
6197
+ const session = await sessionService.get(sessionId);
6198
+ if (session) {
6199
+ context2.session = session;
6200
+ context2.sessionId = sessionId;
6201
+ } else {
6202
+ sessionId = undefined;
6203
+ }
6204
+ }
6205
+ if (!sessionId) {
6206
+ const newSession = await sessionService.create();
6207
+ context2.session = newSession;
6208
+ context2.sessionId = newSession.id;
6209
+ sessionId = newSession.id;
6210
+ }
6211
+ const response = await next();
6212
+ const currentSessionId = context2.sessionId;
6213
+ if (currentSessionId) {
6214
+ const cookieOptions = sessionService.getCookieOptions();
6215
+ const maxAge = sessionService.getMaxAge();
6216
+ const cookieValue = buildCookie(cookieName, currentSessionId, {
6217
+ ...cookieOptions,
6218
+ maxAge
6219
+ });
6220
+ const newHeaders = new Headers(response.headers);
6221
+ newHeaders.set("Set-Cookie", cookieValue);
6222
+ return new Response(response.body, {
6223
+ status: response.status,
6224
+ statusText: response.statusText,
6225
+ headers: newHeaders
6226
+ });
6227
+ }
6228
+ return response;
6229
+ };
6230
+ }
6231
+ function buildCookie(name, value, options) {
6232
+ let cookie = `${name}=${value}`;
6233
+ if (options.path) {
6234
+ cookie += `; Path=${options.path}`;
6235
+ }
6236
+ if (options.domain) {
6237
+ cookie += `; Domain=${options.domain}`;
6238
+ }
6239
+ if (options.maxAge) {
6240
+ cookie += `; Max-Age=${Math.floor(options.maxAge / 1000)}`;
6241
+ }
6242
+ if (options.secure) {
6243
+ cookie += "; Secure";
6244
+ }
6245
+ if (options.httpOnly) {
6246
+ cookie += "; HttpOnly";
6247
+ }
6248
+ if (options.sameSite) {
6249
+ cookie += `; SameSite=${options.sameSite}`;
6250
+ }
6251
+ return cookie;
6252
+ }
6253
+ // src/session/decorators.ts
6254
+ import"reflect-metadata";
6255
+ function Session() {
6256
+ return createParamDecorator("session" /* SESSION */);
3965
6257
  }
3966
6258
  export {
3967
6259
  requiresAuth,
6260
+ getTransactionMetadata,
6261
+ getRepositoryMetadata,
6262
+ getEntityMetadata,
6263
+ getColumnMetadata,
3968
6264
  getAuthMetadata,
3969
6265
  createUserKeyGenerator,
3970
6266
  createTokenKeyGenerator,
3971
6267
  createSwaggerUIMiddleware,
3972
6268
  createStaticFileMiddleware,
6269
+ createSessionMiddleware,
3973
6270
  createSecurityFilter,
3974
6271
  createRequestLoggingMiddleware,
3975
6272
  createRateLimitMiddleware,
@@ -3985,30 +6282,52 @@ export {
3985
6282
  Validate,
3986
6283
  UseMiddleware,
3987
6284
  UnauthorizedException,
6285
+ Transactional,
6286
+ TransactionStatus,
6287
+ TransactionManager,
6288
+ TransactionInterceptor,
6289
+ TRANSACTION_SERVICE_TOKEN,
3988
6290
  SwaggerModule,
3989
6291
  SwaggerGenerator,
3990
6292
  SwaggerExtension,
3991
6293
  StressTester,
6294
+ SessionService,
6295
+ SessionModule,
6296
+ Session,
3992
6297
  SecurityModule,
3993
6298
  SecurityContextHolder,
6299
+ SESSION_SERVICE_TOKEN,
6300
+ SESSION_OPTIONS_TOKEN,
3994
6301
  Router,
3995
6302
  RouteRegistry,
3996
6303
  Route,
3997
6304
  RoleBasedAccessDecisionManager,
3998
6305
  ResponseBuilder,
3999
6306
  RequestWrapper,
6307
+ Repository,
6308
+ RedisSessionStore,
6309
+ RedisCacheStore,
4000
6310
  RateLimit,
6311
+ QueueService,
6312
+ QueueModule,
6313
+ Queue,
4001
6314
  Query,
6315
+ QUEUE_SERVICE_TOKEN,
6316
+ QUEUE_OPTIONS_TOKEN,
6317
+ Propagation,
4002
6318
  PrometheusFormatter,
6319
+ PrimaryKey,
4003
6320
  PerformanceHarness,
4004
6321
  ParamBinder,
4005
6322
  Param,
4006
6323
  PUT,
4007
6324
  POST,
4008
6325
  PATCH,
6326
+ OrmService,
4009
6327
  OnOpen,
4010
6328
  OnMessage,
4011
6329
  OnClose,
6330
+ ORM_SERVICE_TOKEN,
4012
6331
  OAuth2Service,
4013
6332
  OAuth2Controller,
4014
6333
  OAuth2AuthenticationProvider,
@@ -4020,6 +6339,9 @@ export {
4020
6339
  MiddlewarePipeline,
4021
6340
  MetricsModule,
4022
6341
  MetricsCollector,
6342
+ MemorySessionStore,
6343
+ MemoryQueueStore,
6344
+ MemoryCacheStore,
4023
6345
  METRICS_SERVICE_TOKEN,
4024
6346
  METRICS_OPTIONS_TOKEN,
4025
6347
  LoggerModule,
@@ -4030,6 +6352,7 @@ export {
4030
6352
  JwtAuthenticationProvider,
4031
6353
  JWT_UTIL_TOKEN,
4032
6354
  JWTUtil,
6355
+ IsolationLevel,
4033
6356
  IsString,
4034
6357
  IsOptional,
4035
6358
  IsNumber,
@@ -4045,17 +6368,37 @@ export {
4045
6368
  GET,
4046
6369
  ForbiddenException,
4047
6370
  ExceptionFilterRegistry,
6371
+ Entity,
6372
+ DrizzleBaseRepository,
6373
+ DatabaseService2 as DatabaseService,
6374
+ DatabaseModule,
6375
+ DatabaseHealthIndicator,
6376
+ DatabaseExtension,
6377
+ DatabaseConnectionManager,
4048
6378
  DELETE,
6379
+ DATABASE_SERVICE_TOKEN,
6380
+ DATABASE_OPTIONS_TOKEN,
6381
+ Cron,
4049
6382
  ControllerRegistry,
4050
6383
  Controller,
4051
6384
  Context,
4052
6385
  Container,
6386
+ ConnectionPool,
4053
6387
  ConfigService,
4054
6388
  ConfigModule,
6389
+ Column,
6390
+ Cacheable,
6391
+ CacheService,
6392
+ CachePut,
6393
+ CacheModule,
6394
+ CacheEvict,
4055
6395
  CONFIG_SERVICE_TOKEN,
6396
+ CACHE_SERVICE_TOKEN,
6397
+ CACHE_OPTIONS_TOKEN,
4056
6398
  BunServer,
4057
6399
  BodyParser,
4058
6400
  Body,
6401
+ BaseRepository,
4059
6402
  BadRequestException,
4060
6403
  AuthenticationManager,
4061
6404
  Auth,