@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.
- package/dist/auth/controller.d.ts +1 -1
- package/dist/auth/controller.d.ts.map +1 -1
- package/dist/cache/cache-module.d.ts +9 -0
- package/dist/cache/cache-module.d.ts.map +1 -0
- package/dist/cache/decorators.d.ts +110 -0
- package/dist/cache/decorators.d.ts.map +1 -0
- package/dist/cache/index.d.ts +6 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/service.d.ts +76 -0
- package/dist/cache/service.d.ts.map +1 -0
- package/dist/cache/types.d.ts +160 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/controller/decorators.d.ts +9 -1
- package/dist/controller/decorators.d.ts.map +1 -1
- package/dist/controller/param-binder.d.ts +4 -1
- package/dist/controller/param-binder.d.ts.map +1 -1
- package/dist/core/application.d.ts +10 -2
- package/dist/core/application.d.ts.map +1 -1
- package/dist/database/connection-manager.d.ts +72 -0
- package/dist/database/connection-manager.d.ts.map +1 -0
- package/dist/database/connection-pool.d.ts +79 -0
- package/dist/database/connection-pool.d.ts.map +1 -0
- package/dist/database/database-extension.d.ts +20 -0
- package/dist/database/database-extension.d.ts.map +1 -0
- package/dist/database/database-module.d.ts +18 -0
- package/dist/database/database-module.d.ts.map +1 -0
- package/dist/database/health-indicator.d.ts +15 -0
- package/dist/database/health-indicator.d.ts.map +1 -0
- package/dist/database/index.d.ts +9 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/orm/decorators.d.ts +70 -0
- package/dist/database/orm/decorators.d.ts.map +1 -0
- package/dist/database/orm/drizzle-repository.d.ts +34 -0
- package/dist/database/orm/drizzle-repository.d.ts.map +1 -0
- package/dist/database/orm/index.d.ts +11 -0
- package/dist/database/orm/index.d.ts.map +1 -0
- package/dist/database/orm/repository-decorator.d.ts +21 -0
- package/dist/database/orm/repository-decorator.d.ts.map +1 -0
- package/dist/database/orm/repository.d.ts +36 -0
- package/dist/database/orm/repository.d.ts.map +1 -0
- package/dist/database/orm/service.d.ts +26 -0
- package/dist/database/orm/service.d.ts.map +1 -0
- package/dist/database/orm/transaction-decorator.d.ts +17 -0
- package/dist/database/orm/transaction-decorator.d.ts.map +1 -0
- package/dist/database/orm/transaction-interceptor.d.ts +28 -0
- package/dist/database/orm/transaction-interceptor.d.ts.map +1 -0
- package/dist/database/orm/transaction-manager.d.ts +77 -0
- package/dist/database/orm/transaction-manager.d.ts.map +1 -0
- package/dist/database/orm/transaction-types.d.ts +136 -0
- package/dist/database/orm/transaction-types.d.ts.map +1 -0
- package/dist/database/orm/types.d.ts +95 -0
- package/dist/database/orm/types.d.ts.map +1 -0
- package/dist/database/service.d.ts +71 -0
- package/dist/database/service.d.ts.map +1 -0
- package/dist/database/types.d.ts +168 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/error/error-codes.d.ts +49 -3
- package/dist/error/error-codes.d.ts.map +1 -1
- package/dist/error/handler.d.ts.map +1 -1
- package/dist/error/http-exception.d.ts +26 -7
- package/dist/error/http-exception.d.ts.map +1 -1
- package/dist/error/i18n.d.ts +46 -2
- package/dist/error/i18n.d.ts.map +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.d.ts.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2454 -111
- package/dist/middleware/pipeline.d.ts.map +1 -1
- package/dist/queue/decorators.d.ts +63 -0
- package/dist/queue/decorators.d.ts.map +1 -0
- package/dist/queue/index.d.ts +6 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/queue-module.d.ts +9 -0
- package/dist/queue/queue-module.d.ts.map +1 -0
- package/dist/queue/service.d.ts +93 -0
- package/dist/queue/service.d.ts.map +1 -0
- package/dist/queue/types.d.ts +204 -0
- package/dist/queue/types.d.ts.map +1 -0
- package/dist/router/router.d.ts +16 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/session/decorators.d.ts +16 -0
- package/dist/session/decorators.d.ts.map +1 -0
- package/dist/session/index.d.ts +8 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/middleware.d.ts +8 -0
- package/dist/session/middleware.d.ts.map +1 -0
- package/dist/session/service.d.ts +86 -0
- package/dist/session/service.d.ts.map +1 -0
- package/dist/session/session-module.d.ts +9 -0
- package/dist/session/session-module.d.ts.map +1 -0
- package/dist/session/types.d.ts +193 -0
- package/dist/session/types.d.ts.map +1 -0
- package/package.json +1 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
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[
|
|
667
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
1111
|
+
const match = route.match(method, normalizedPath);
|
|
779
1112
|
if (match.matched) {
|
|
780
|
-
|
|
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
|
|
789
|
-
if (!
|
|
1123
|
+
const result = this.findRouteWithMatch(method, path);
|
|
1124
|
+
if (!result) {
|
|
790
1125
|
return;
|
|
791
1126
|
}
|
|
792
|
-
const match =
|
|
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
|
|
808
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
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
|
|
3257
|
-
redirectUri
|
|
3798
|
+
clientId,
|
|
3799
|
+
redirectUri,
|
|
3258
3800
|
responseType: "code",
|
|
3259
|
-
scope:
|
|
3260
|
-
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("
|
|
3322
|
-
__legacyDecorateParamTS(3, Query("
|
|
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/
|
|
3907
|
-
|
|
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
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
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
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
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
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
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
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
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
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
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,
|