@dangao/bun-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/controller/controller.d.ts +63 -0
  2. package/dist/controller/controller.d.ts.map +1 -0
  3. package/dist/controller/decorators.d.ts +46 -0
  4. package/dist/controller/decorators.d.ts.map +1 -0
  5. package/dist/controller/index.d.ts +7 -0
  6. package/dist/controller/index.d.ts.map +1 -0
  7. package/dist/controller/metadata.d.ts +17 -0
  8. package/dist/controller/metadata.d.ts.map +1 -0
  9. package/dist/controller/param-binder.d.ts +51 -0
  10. package/dist/controller/param-binder.d.ts.map +1 -0
  11. package/dist/core/application.d.ts +80 -0
  12. package/dist/core/application.d.ts.map +1 -0
  13. package/dist/core/context.d.ts +117 -0
  14. package/dist/core/context.d.ts.map +1 -0
  15. package/dist/core/index.d.ts +4 -0
  16. package/dist/core/index.d.ts.map +1 -0
  17. package/dist/core/server.d.ts +53 -0
  18. package/dist/core/server.d.ts.map +1 -0
  19. package/dist/core/types.d.ts +2 -0
  20. package/dist/core/types.d.ts.map +1 -0
  21. package/dist/di/container.d.ts +80 -0
  22. package/dist/di/container.d.ts.map +1 -0
  23. package/dist/di/decorators.d.ts +43 -0
  24. package/dist/di/decorators.d.ts.map +1 -0
  25. package/dist/di/index.d.ts +4 -0
  26. package/dist/di/index.d.ts.map +1 -0
  27. package/dist/di/module-registry.d.ts +27 -0
  28. package/dist/di/module-registry.d.ts.map +1 -0
  29. package/dist/di/module.d.ts +30 -0
  30. package/dist/di/module.d.ts.map +1 -0
  31. package/dist/di/types.d.ts +57 -0
  32. package/dist/di/types.d.ts.map +1 -0
  33. package/dist/error/filter.d.ts +18 -0
  34. package/dist/error/filter.d.ts.map +1 -0
  35. package/dist/error/handler.d.ts +6 -0
  36. package/dist/error/handler.d.ts.map +1 -0
  37. package/dist/error/http-exception.d.ts +24 -0
  38. package/dist/error/http-exception.d.ts.map +1 -0
  39. package/dist/error/index.d.ts +5 -0
  40. package/dist/error/index.d.ts.map +1 -0
  41. package/dist/extensions/index.d.ts +5 -0
  42. package/dist/extensions/index.d.ts.map +1 -0
  43. package/dist/extensions/logger-extension.d.ts +13 -0
  44. package/dist/extensions/logger-extension.d.ts.map +1 -0
  45. package/dist/extensions/types.d.ts +12 -0
  46. package/dist/extensions/types.d.ts.map +1 -0
  47. package/dist/files/index.d.ts +5 -0
  48. package/dist/files/index.d.ts.map +1 -0
  49. package/dist/files/static-middleware.d.ts +8 -0
  50. package/dist/files/static-middleware.d.ts.map +1 -0
  51. package/dist/files/storage.d.ts +10 -0
  52. package/dist/files/storage.d.ts.map +1 -0
  53. package/dist/files/types.d.ts +27 -0
  54. package/dist/files/types.d.ts.map +1 -0
  55. package/dist/files/upload-middleware.d.ts +7 -0
  56. package/dist/files/upload-middleware.d.ts.map +1 -0
  57. package/dist/index.d.ts +23 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +2118 -0
  60. package/dist/middleware/builtin/cors.d.ts +14 -0
  61. package/dist/middleware/builtin/cors.d.ts.map +1 -0
  62. package/dist/middleware/builtin/error-handler.d.ts +23 -0
  63. package/dist/middleware/builtin/error-handler.d.ts.map +1 -0
  64. package/dist/middleware/builtin/file-upload.d.ts +9 -0
  65. package/dist/middleware/builtin/file-upload.d.ts.map +1 -0
  66. package/dist/middleware/builtin/index.d.ts +6 -0
  67. package/dist/middleware/builtin/index.d.ts.map +1 -0
  68. package/dist/middleware/builtin/logger.d.ts +26 -0
  69. package/dist/middleware/builtin/logger.d.ts.map +1 -0
  70. package/dist/middleware/builtin/static-file.d.ts +14 -0
  71. package/dist/middleware/builtin/static-file.d.ts.map +1 -0
  72. package/dist/middleware/decorators.d.ts +22 -0
  73. package/dist/middleware/decorators.d.ts.map +1 -0
  74. package/dist/middleware/index.d.ts +5 -0
  75. package/dist/middleware/index.d.ts.map +1 -0
  76. package/dist/middleware/middleware.d.ts +10 -0
  77. package/dist/middleware/middleware.d.ts.map +1 -0
  78. package/dist/middleware/pipeline.d.ts +38 -0
  79. package/dist/middleware/pipeline.d.ts.map +1 -0
  80. package/dist/request/body-parser.d.ts +37 -0
  81. package/dist/request/body-parser.d.ts.map +1 -0
  82. package/dist/request/file-handler.d.ts +13 -0
  83. package/dist/request/file-handler.d.ts.map +1 -0
  84. package/dist/request/index.d.ts +5 -0
  85. package/dist/request/index.d.ts.map +1 -0
  86. package/dist/request/request.d.ts +67 -0
  87. package/dist/request/request.d.ts.map +1 -0
  88. package/dist/request/response.d.ts +65 -0
  89. package/dist/request/response.d.ts.map +1 -0
  90. package/dist/router/decorators.d.ts +45 -0
  91. package/dist/router/decorators.d.ts.map +1 -0
  92. package/dist/router/index.d.ts +6 -0
  93. package/dist/router/index.d.ts.map +1 -0
  94. package/dist/router/registry.d.ts +54 -0
  95. package/dist/router/registry.d.ts.map +1 -0
  96. package/dist/router/route.d.ts +57 -0
  97. package/dist/router/route.d.ts.map +1 -0
  98. package/dist/router/router.d.ts +76 -0
  99. package/dist/router/router.d.ts.map +1 -0
  100. package/dist/router/types.d.ts +23 -0
  101. package/dist/router/types.d.ts.map +1 -0
  102. package/dist/testing/harness.d.ts +26 -0
  103. package/dist/testing/harness.d.ts.map +1 -0
  104. package/dist/validation/decorators.d.ts +20 -0
  105. package/dist/validation/decorators.d.ts.map +1 -0
  106. package/dist/validation/errors.d.ts +19 -0
  107. package/dist/validation/errors.d.ts.map +1 -0
  108. package/dist/validation/index.d.ts +5 -0
  109. package/dist/validation/index.d.ts.map +1 -0
  110. package/dist/validation/types.d.ts +29 -0
  111. package/dist/validation/types.d.ts.map +1 -0
  112. package/dist/validation/validator.d.ts +8 -0
  113. package/dist/validation/validator.d.ts.map +1 -0
  114. package/dist/websocket/decorators.d.ts +16 -0
  115. package/dist/websocket/decorators.d.ts.map +1 -0
  116. package/dist/websocket/index.d.ts +4 -0
  117. package/dist/websocket/index.d.ts.map +1 -0
  118. package/dist/websocket/registry.d.ts +22 -0
  119. package/dist/websocket/registry.d.ts.map +1 -0
  120. package/package.json +56 -0
package/dist/index.js ADDED
@@ -0,0 +1,2118 @@
1
+ // @bun
2
+ // src/request/body-parser.ts
3
+ class BodyParser {
4
+ static async parse(request) {
5
+ const contentType = request.headers.get("content-type") ?? "";
6
+ if (request.method === "GET" || request.method === "HEAD") {
7
+ return;
8
+ }
9
+ const contentLength = request.headers.get("content-length");
10
+ if (contentLength === "0") {
11
+ return;
12
+ }
13
+ try {
14
+ if (contentType.includes("application/json")) {
15
+ const result = await this.parseJSON(request);
16
+ return result;
17
+ }
18
+ if (contentType.includes("multipart/form-data")) {
19
+ return await this.parseFormData(request);
20
+ }
21
+ if (contentType.includes("application/x-www-form-urlencoded")) {
22
+ const result = await this.parseURLEncoded(request);
23
+ return result;
24
+ }
25
+ if (contentType.includes("text/")) {
26
+ return await this.parseText(request);
27
+ }
28
+ if (!contentType && !contentLength) {
29
+ try {
30
+ const text = await request.text();
31
+ if (!text || text.length === 0) {
32
+ return;
33
+ }
34
+ try {
35
+ return JSON.parse(text);
36
+ } catch {
37
+ return text;
38
+ }
39
+ } catch {
40
+ return;
41
+ }
42
+ }
43
+ const fallbackText = await request.text();
44
+ if (!fallbackText) {
45
+ return;
46
+ }
47
+ try {
48
+ return JSON.parse(fallbackText);
49
+ } catch {
50
+ return fallbackText;
51
+ }
52
+ } catch (error) {
53
+ return;
54
+ }
55
+ }
56
+ static async parseJSON(request) {
57
+ const text = await request.text();
58
+ if (!text) {
59
+ return;
60
+ }
61
+ return JSON.parse(text);
62
+ }
63
+ static async parseFormData(request) {
64
+ return await request.formData();
65
+ }
66
+ static async parseURLEncoded(request) {
67
+ const text = await request.text();
68
+ if (!text || text.length === 0) {
69
+ return;
70
+ }
71
+ const params = new URLSearchParams(text);
72
+ const result = {};
73
+ params.forEach((value, key) => {
74
+ result[key] = value;
75
+ });
76
+ return result;
77
+ }
78
+ static async parseText(request) {
79
+ return await request.text();
80
+ }
81
+ }
82
+
83
+ // src/core/context.ts
84
+ class Context {
85
+ request;
86
+ response;
87
+ url;
88
+ method;
89
+ path;
90
+ query;
91
+ params = {};
92
+ headers;
93
+ responseHeaders;
94
+ statusCode = 200;
95
+ files = [];
96
+ _body;
97
+ _bodyParsed = false;
98
+ constructor(request) {
99
+ this.request = request;
100
+ this.url = new URL(request.url);
101
+ this.method = request.method;
102
+ this.path = this.url.pathname;
103
+ this.query = this.url.searchParams;
104
+ this.headers = request.headers;
105
+ this.responseHeaders = new Headers;
106
+ }
107
+ async getBody() {
108
+ if (!this._bodyParsed) {
109
+ this._body = await BodyParser.parse(this.request);
110
+ this._bodyParsed = true;
111
+ }
112
+ return this._body;
113
+ }
114
+ get body() {
115
+ return this._body;
116
+ }
117
+ set body(body) {
118
+ this._body = body;
119
+ this._bodyParsed = true;
120
+ }
121
+ getQuery(key) {
122
+ return this.query.get(key);
123
+ }
124
+ getQueryAll() {
125
+ const result = {};
126
+ this.query.forEach((value, key) => {
127
+ result[key] = value;
128
+ });
129
+ return result;
130
+ }
131
+ getParam(key) {
132
+ return this.params[key];
133
+ }
134
+ getHeader(key) {
135
+ return this.headers.get(key);
136
+ }
137
+ setHeader(key, value) {
138
+ this.responseHeaders.set(key, value);
139
+ }
140
+ setStatus(code) {
141
+ this.statusCode = code;
142
+ }
143
+ createResponse(body, init) {
144
+ const headers = new Headers(this.responseHeaders);
145
+ if (body !== undefined && body !== null) {
146
+ if (typeof body === "object" && !(body instanceof Response) && !(body instanceof ArrayBuffer)) {
147
+ headers.set("Content-Type", "application/json");
148
+ const jsonString = JSON.stringify(body);
149
+ return new Response(jsonString, {
150
+ status: this.statusCode,
151
+ headers,
152
+ ...init
153
+ });
154
+ }
155
+ }
156
+ return new Response(body, {
157
+ status: this.statusCode,
158
+ headers,
159
+ ...init
160
+ });
161
+ }
162
+ }
163
+
164
+ // src/core/server.ts
165
+ import { LoggerManager } from "@dangao/logsmith";
166
+
167
+ class BunServer {
168
+ server;
169
+ options;
170
+ constructor(options) {
171
+ this.options = options;
172
+ }
173
+ start() {
174
+ if (this.server) {
175
+ throw new Error("Server is already running");
176
+ }
177
+ const logger = LoggerManager.getLogger();
178
+ this.server = Bun.serve({
179
+ port: this.options.port ?? 3000,
180
+ hostname: this.options.hostname,
181
+ fetch: (request, server) => {
182
+ const upgradeHeader = request.headers.get("upgrade");
183
+ if (this.options.websocketRegistry && upgradeHeader && upgradeHeader.toLowerCase() === "websocket") {
184
+ const url = new URL(request.url);
185
+ if (!this.options.websocketRegistry.hasGateway(url.pathname)) {
186
+ return new Response("WebSocket gateway not found", { status: 404 });
187
+ }
188
+ const upgraded = server.upgrade(request, {
189
+ data: { path: url.pathname }
190
+ });
191
+ if (upgraded) {
192
+ return;
193
+ }
194
+ return new Response("WebSocket upgrade failed", { status: 400 });
195
+ }
196
+ const context = new Context(request);
197
+ return this.options.fetch(context);
198
+ },
199
+ websocket: {
200
+ open: (ws) => {
201
+ this.options.websocketRegistry?.handleOpen(ws);
202
+ },
203
+ message: (ws, message) => {
204
+ this.options.websocketRegistry?.handleMessage(ws, message);
205
+ },
206
+ close: (ws, code, reason) => {
207
+ this.options.websocketRegistry?.handleClose(ws, code, reason);
208
+ }
209
+ }
210
+ });
211
+ const hostname = this.options.hostname ?? "localhost";
212
+ const port = this.options.port ?? 3000;
213
+ logger.info(`Server started at http://${hostname}:${port}`);
214
+ }
215
+ stop() {
216
+ if (this.server) {
217
+ const logger = LoggerManager.getLogger();
218
+ this.server.stop();
219
+ this.server = undefined;
220
+ logger.info("Server stopped");
221
+ }
222
+ }
223
+ getServer() {
224
+ return this.server;
225
+ }
226
+ isRunning() {
227
+ return this.server !== undefined;
228
+ }
229
+ }
230
+
231
+ // src/middleware/pipeline.ts
232
+ class MiddlewarePipeline {
233
+ middlewares = [];
234
+ constructor(initialMiddlewares = []) {
235
+ this.middlewares.push(...initialMiddlewares);
236
+ }
237
+ use(middleware) {
238
+ this.middlewares.push(middleware);
239
+ }
240
+ clear() {
241
+ this.middlewares.length = 0;
242
+ }
243
+ hasMiddlewares() {
244
+ return this.middlewares.length > 0;
245
+ }
246
+ async run(context, finalHandler) {
247
+ const length = this.middlewares.length;
248
+ if (length === 0) {
249
+ return await finalHandler();
250
+ }
251
+ const called = new Array(length).fill(false);
252
+ const chain = new Array(length + 1);
253
+ chain[length] = finalHandler;
254
+ for (let i = length - 1;i >= 0; i--) {
255
+ const middleware = this.middlewares[i];
256
+ const downstream = chain[i + 1];
257
+ chain[i] = async () => {
258
+ if (called[i]) {
259
+ throw new Error("next() called multiple times");
260
+ }
261
+ called[i] = true;
262
+ return await middleware(context, downstream);
263
+ };
264
+ }
265
+ return await chain[0]();
266
+ }
267
+ }
268
+
269
+ // src/router/route.ts
270
+ class Route {
271
+ method;
272
+ path;
273
+ handler;
274
+ pattern;
275
+ paramNames;
276
+ middlewarePipeline;
277
+ staticKey;
278
+ isStatic;
279
+ constructor(method, path, handler, middlewares = []) {
280
+ this.method = method;
281
+ this.path = path;
282
+ this.handler = handler;
283
+ const { pattern, paramNames } = this.parsePath(path);
284
+ this.pattern = pattern;
285
+ this.paramNames = paramNames;
286
+ this.middlewarePipeline = middlewares.length > 0 ? new MiddlewarePipeline(middlewares) : null;
287
+ this.isStatic = !path.includes(":") && !path.includes("*");
288
+ if (this.isStatic) {
289
+ this.staticKey = `${method}:${path}`;
290
+ }
291
+ }
292
+ parsePath(path) {
293
+ const paramNames = [];
294
+ const patternString = path.replace(/:([^/]+)/g, (_, paramName) => {
295
+ paramNames.push(paramName);
296
+ return "([^/]+)";
297
+ }).replace(/\*/g, ".*");
298
+ const pattern = new RegExp(`^${patternString}$`);
299
+ return { pattern, paramNames };
300
+ }
301
+ match(method, path) {
302
+ if (this.method !== method) {
303
+ return { matched: false, params: {} };
304
+ }
305
+ const match = path.match(this.pattern);
306
+ if (!match) {
307
+ return { matched: false, params: {} };
308
+ }
309
+ const params = {};
310
+ for (let i = 0;i < this.paramNames.length; i++) {
311
+ params[this.paramNames[i]] = match[i + 1] ?? "";
312
+ }
313
+ return { matched: true, params };
314
+ }
315
+ async execute(context) {
316
+ if (!this.middlewarePipeline || !this.middlewarePipeline.hasMiddlewares()) {
317
+ return await this.handler(context);
318
+ }
319
+ return await this.middlewarePipeline.run(context, async () => this.handler(context));
320
+ }
321
+ getStaticKey() {
322
+ return this.staticKey;
323
+ }
324
+ }
325
+
326
+ // src/router/router.ts
327
+ class Router {
328
+ routes = [];
329
+ staticRoutes = new Map;
330
+ dynamicRoutes = [];
331
+ register(method, path, handler, middlewares = []) {
332
+ const route = new Route(method, path, handler, middlewares);
333
+ this.routes.push(route);
334
+ const staticKey = route.getStaticKey();
335
+ if (staticKey) {
336
+ this.staticRoutes.set(staticKey, route);
337
+ } else {
338
+ this.dynamicRoutes.push(route);
339
+ }
340
+ }
341
+ get(path, handler, middlewares = []) {
342
+ this.register("GET", path, handler, middlewares);
343
+ }
344
+ post(path, handler, middlewares = []) {
345
+ this.register("POST", path, handler, middlewares);
346
+ }
347
+ put(path, handler, middlewares = []) {
348
+ this.register("PUT", path, handler, middlewares);
349
+ }
350
+ delete(path, handler, middlewares = []) {
351
+ this.register("DELETE", path, handler, middlewares);
352
+ }
353
+ patch(path, handler, middlewares = []) {
354
+ this.register("PATCH", path, handler, middlewares);
355
+ }
356
+ findRoute(method, path) {
357
+ const staticRoute = this.staticRoutes.get(`${method}:${path}`);
358
+ if (staticRoute) {
359
+ return staticRoute;
360
+ }
361
+ for (const route of this.dynamicRoutes) {
362
+ const match = route.match(method, path);
363
+ if (match.matched) {
364
+ return route;
365
+ }
366
+ }
367
+ return;
368
+ }
369
+ async handle(context) {
370
+ const method = context.method;
371
+ const route = this.findRoute(method, context.path);
372
+ if (!route) {
373
+ return;
374
+ }
375
+ const match = route.match(method, context.path);
376
+ if (match.matched) {
377
+ context.params = match.params;
378
+ }
379
+ return await route.execute(context);
380
+ }
381
+ getRoutes() {
382
+ return this.routes;
383
+ }
384
+ clear() {
385
+ this.routes.length = 0;
386
+ this.dynamicRoutes.length = 0;
387
+ this.staticRoutes.clear();
388
+ }
389
+ }
390
+
391
+ // src/router/registry.ts
392
+ class RouteRegistry {
393
+ static instance;
394
+ router;
395
+ constructor() {
396
+ this.router = new Router;
397
+ }
398
+ static getInstance() {
399
+ if (!RouteRegistry.instance) {
400
+ RouteRegistry.instance = new RouteRegistry;
401
+ }
402
+ return RouteRegistry.instance;
403
+ }
404
+ register(method, path, handler, middlewares = []) {
405
+ this.router.register(method, path, handler, middlewares);
406
+ }
407
+ get(path, handler, middlewares = []) {
408
+ this.router.get(path, handler, middlewares);
409
+ }
410
+ post(path, handler, middlewares = []) {
411
+ this.router.post(path, handler, middlewares);
412
+ }
413
+ put(path, handler, middlewares = []) {
414
+ this.router.put(path, handler, middlewares);
415
+ }
416
+ delete(path, handler, middlewares = []) {
417
+ this.router.delete(path, handler, middlewares);
418
+ }
419
+ patch(path, handler, middlewares = []) {
420
+ this.router.patch(path, handler, middlewares);
421
+ }
422
+ getRouter() {
423
+ return this.router;
424
+ }
425
+ clear() {
426
+ this.router.clear();
427
+ }
428
+ }
429
+
430
+ // src/controller/controller.ts
431
+ import"reflect-metadata";
432
+
433
+ // src/di/container.ts
434
+ import"reflect-metadata";
435
+
436
+ // src/di/types.ts
437
+ var Lifecycle;
438
+ ((Lifecycle2) => {
439
+ Lifecycle2["Singleton"] = "singleton";
440
+ Lifecycle2["Transient"] = "transient";
441
+ Lifecycle2["Scoped"] = "scoped";
442
+ })(Lifecycle ||= {});
443
+
444
+ // src/di/decorators.ts
445
+ import"reflect-metadata";
446
+ import { LoggerManager as LoggerManager2 } from "@dangao/logsmith";
447
+ var DEPENDENCY_METADATA_KEY = Symbol("dependency:metadata");
448
+ var INJECTABLE_METADATA_KEY = Symbol("injectable");
449
+ var typeReferenceMap = new WeakMap;
450
+ function Injectable(config) {
451
+ return function(target) {
452
+ Reflect.defineMetadata(INJECTABLE_METADATA_KEY, true, target);
453
+ if (config?.lifecycle) {
454
+ Reflect.defineMetadata("lifecycle", config.lifecycle, target);
455
+ }
456
+ };
457
+ }
458
+ function Inject(token) {
459
+ return function(target, _propertyKey, parameterIndex) {
460
+ const logger = LoggerManager2.getLogger();
461
+ const constructor = typeof target === "function" ? target : target?.constructor;
462
+ if (!constructor) {
463
+ return;
464
+ }
465
+ const paramTypes = Reflect.getMetadata("design:paramtypes", constructor);
466
+ const paramType = paramTypes?.[parameterIndex];
467
+ let metadata = Reflect.getMetadata(DEPENDENCY_METADATA_KEY, constructor) || [];
468
+ const paramCount = paramTypes?.length || 0;
469
+ while (metadata.length < paramCount) {
470
+ metadata.push(undefined);
471
+ }
472
+ let dependencyType;
473
+ let dependencyToken;
474
+ if (token) {
475
+ if (typeof token === "string" || typeof token === "symbol") {
476
+ dependencyToken = token;
477
+ dependencyType = paramType || Object;
478
+ } else {
479
+ dependencyType = token;
480
+ }
481
+ } else {
482
+ if (!paramType) {
483
+ throw new Error(`Cannot determine dependency type for parameter ${parameterIndex} of ${constructor.name}. ` + "Please provide explicit type using @Inject(Type) or ensure emitDecoratorMetadata is enabled.");
484
+ }
485
+ dependencyType = paramType;
486
+ }
487
+ if (!typeReferenceMap.has(constructor)) {
488
+ typeReferenceMap.set(constructor, new Map);
489
+ }
490
+ const typeRefs = typeReferenceMap.get(constructor);
491
+ typeRefs.set(String(parameterIndex), dependencyType);
492
+ metadata[parameterIndex] = {
493
+ index: parameterIndex,
494
+ type: dependencyType,
495
+ token: dependencyToken
496
+ };
497
+ if (constructor.name === "Service" || constructor.name === "Level2") {
498
+ logger.debug(`[DI Debug] @Inject(${token ? typeof token === "function" ? token.name : String(token) : "auto"}) on ${constructor.name}[${parameterIndex}]: saving metadata.length=${metadata.length}`);
499
+ }
500
+ Reflect.defineMetadata(DEPENDENCY_METADATA_KEY, metadata, constructor);
501
+ if (constructor.name === "Service" || constructor.name === "Level2") {
502
+ const savedMetadata = Reflect.getMetadata(DEPENDENCY_METADATA_KEY, constructor);
503
+ logger.debug(`[DI Debug] @Inject on ${constructor.name}: saved metadata.exists=${savedMetadata ? "yes" : "no"}, length=${savedMetadata?.length || 0}`);
504
+ }
505
+ };
506
+ }
507
+ function getDependencyMetadata(target) {
508
+ const constructor = typeof target === "function" ? target : target?.constructor;
509
+ if (!constructor) {
510
+ return [];
511
+ }
512
+ const rawMetadata = Reflect.getMetadata(DEPENDENCY_METADATA_KEY, constructor);
513
+ const metadata = rawMetadata || [];
514
+ if (constructor.name === "Service" || constructor.name === "Level2") {
515
+ LoggerManager2.getLogger().debug(`[DI Debug] getDependencyMetadata(${constructor.name}): rawMetadata=${rawMetadata ? "exists" : "undefined"}, length=${metadata.length}`);
516
+ }
517
+ const typeRefs = typeReferenceMap.get(constructor);
518
+ if (typeRefs) {
519
+ for (let i = 0;i < metadata.length; i++) {
520
+ const meta = metadata[i];
521
+ if (meta !== undefined && meta !== null) {
522
+ const typeRef = typeRefs.get(String(meta.index));
523
+ if (typeRef && typeof typeRef === "function") {
524
+ meta.type = typeRef;
525
+ }
526
+ }
527
+ }
528
+ }
529
+ return metadata;
530
+ }
531
+ function getLifecycle(target) {
532
+ return Reflect.getMetadata("lifecycle", target);
533
+ }
534
+ function getTypeReference(constructor, parameterIndex) {
535
+ const typeRefs = typeReferenceMap.get(constructor);
536
+ if (typeRefs) {
537
+ return typeRefs.get(String(parameterIndex));
538
+ }
539
+ return;
540
+ }
541
+
542
+ // src/di/container.ts
543
+ import { LoggerManager as LoggerManager3 } from "@dangao/logsmith";
544
+
545
+ class Container {
546
+ parent;
547
+ constructor(options = {}) {
548
+ this.parent = options.parent;
549
+ }
550
+ providers = new Map;
551
+ singletons = new Map;
552
+ typeToToken = new Map;
553
+ dependencyPlans = new Map;
554
+ register(token, config) {
555
+ const tokenKey = this.getTokenKey(token);
556
+ let lifecycle = config?.lifecycle;
557
+ if (!lifecycle && typeof token === "function") {
558
+ lifecycle = getLifecycle(token);
559
+ }
560
+ const providerConfig = {
561
+ lifecycle: lifecycle || "singleton" /* Singleton */,
562
+ ...config
563
+ };
564
+ if (typeof token === "function" && !providerConfig.factory && !providerConfig.implementation) {
565
+ providerConfig.implementation = token;
566
+ }
567
+ this.providers.set(tokenKey, providerConfig);
568
+ if (typeof token === "function") {
569
+ this.typeToToken.set(token, tokenKey);
570
+ }
571
+ }
572
+ registerInstance(token, instance) {
573
+ const tokenKey = this.getTokenKey(token);
574
+ this.singletons.set(tokenKey, instance);
575
+ this.providers.set(tokenKey, {
576
+ lifecycle: "singleton" /* Singleton */
577
+ });
578
+ }
579
+ resolve(token) {
580
+ const tokenKey = this.getTokenKey(token);
581
+ const provider = this.providers.get(tokenKey);
582
+ if (!provider) {
583
+ if (this.parent) {
584
+ return this.parent.resolve(token);
585
+ }
586
+ if (typeof token === "function") {
587
+ const paramTypes = Reflect.getMetadata("design:paramtypes", token);
588
+ if (paramTypes && paramTypes.length > 0) {
589
+ throw new Error(`Provider not found for token: ${String(tokenKey)}`);
590
+ }
591
+ return new token;
592
+ }
593
+ throw new Error(`Provider not found for token: ${String(tokenKey)}`);
594
+ }
595
+ if (provider.lifecycle === "singleton" /* Singleton */) {
596
+ const singleton = this.singletons.get(tokenKey);
597
+ if (singleton) {
598
+ return singleton;
599
+ }
600
+ }
601
+ let instance;
602
+ if (provider.factory) {
603
+ instance = provider.factory();
604
+ } else if (typeof token === "function") {
605
+ instance = this.instantiate(token);
606
+ } else if (provider.implementation && typeof provider.implementation === "function") {
607
+ instance = this.instantiate(provider.implementation);
608
+ } else {
609
+ throw new Error(`Cannot instantiate token: ${String(tokenKey)}. Factory function required.`);
610
+ }
611
+ if (provider.lifecycle === "singleton" /* Singleton */) {
612
+ this.singletons.set(tokenKey, instance);
613
+ }
614
+ return instance;
615
+ }
616
+ resolveInternal(token) {
617
+ const tokenType = typeof token;
618
+ const tokenString = String(token);
619
+ const logger = LoggerManager3.getLogger();
620
+ if (tokenString.includes("Level2") || tokenString.includes("Dependency") || tokenString.includes("Service")) {
621
+ logger.debug(`[DI Debug] resolveInternal: token=${tokenString}, tokenType=${tokenType}`);
622
+ }
623
+ if (typeof token === "string" || typeof token === "symbol") {
624
+ const provider = this.providers.get(token);
625
+ if (!provider) {
626
+ if (this.parent) {
627
+ return this.parent.resolveInternal(token);
628
+ }
629
+ throw new Error(`Provider not found for token: ${String(token)}`);
630
+ }
631
+ if (provider.lifecycle === "singleton" /* Singleton */) {
632
+ const singleton = this.singletons.get(token);
633
+ if (singleton) {
634
+ return singleton;
635
+ }
636
+ }
637
+ if (provider.factory) {
638
+ const instance = provider.factory();
639
+ if (provider.lifecycle === "singleton" /* Singleton */) {
640
+ this.singletons.set(token, instance);
641
+ }
642
+ return instance;
643
+ }
644
+ if (provider.implementation && typeof provider.implementation === "function") {
645
+ const instance = this.instantiate(provider.implementation);
646
+ if (provider.lifecycle === "singleton" /* Singleton */) {
647
+ this.singletons.set(token, instance);
648
+ }
649
+ return instance;
650
+ }
651
+ throw new Error(`Cannot instantiate token: ${String(token)}. Factory function required.`);
652
+ }
653
+ if (typeof token === "function") {
654
+ return this.resolve(token);
655
+ }
656
+ throw new Error(`Invalid token type: ${tokenType}. Token: ${String(token)}`);
657
+ }
658
+ instantiate(constructor) {
659
+ const plan = this.getDependencyPlan(constructor);
660
+ if (plan.paramLength === 0) {
661
+ return new constructor;
662
+ }
663
+ const dependencies = new Array(plan.paramLength);
664
+ for (let index = 0;index < plan.paramLength; index++) {
665
+ dependencies[index] = this.resolveFromPlan(constructor, plan, index);
666
+ }
667
+ return new constructor(...dependencies);
668
+ }
669
+ getTokenKey(token) {
670
+ if (typeof token === "function") {
671
+ return token.name || Symbol(token.toString());
672
+ }
673
+ return token;
674
+ }
675
+ clear() {
676
+ this.providers.clear();
677
+ this.singletons.clear();
678
+ this.typeToToken.clear();
679
+ this.dependencyPlans.clear();
680
+ }
681
+ isRegistered(token) {
682
+ const tokenKey = this.getTokenKey(token);
683
+ return this.providers.has(tokenKey);
684
+ }
685
+ getDependencyPlan(constructor) {
686
+ let plan = this.dependencyPlans.get(constructor);
687
+ if (plan) {
688
+ return plan;
689
+ }
690
+ const paramTypes = Reflect.getMetadata("design:paramtypes", constructor) ?? [];
691
+ const dependencyMetadata = getDependencyMetadata(constructor);
692
+ const metadataMap = new Map;
693
+ let paramLength = paramTypes.length;
694
+ for (const meta of dependencyMetadata) {
695
+ if (meta && typeof meta.index === "number") {
696
+ metadataMap.set(meta.index, meta);
697
+ if (meta.index + 1 > paramLength) {
698
+ paramLength = meta.index + 1;
699
+ }
700
+ }
701
+ }
702
+ const resolvedTypes = new Map;
703
+ for (let i = 0;i < paramLength; i++) {
704
+ const typeRef = getTypeReference(constructor, i);
705
+ if (typeRef && typeof typeRef === "function") {
706
+ resolvedTypes.set(i, typeRef);
707
+ }
708
+ }
709
+ for (const [index, meta] of metadataMap.entries()) {
710
+ const depType = meta?.type;
711
+ if (typeof depType === "function") {
712
+ resolvedTypes.set(index, depType);
713
+ } else if (typeof depType === "string") {
714
+ const globalType = globalThis[depType];
715
+ if (typeof globalType === "function") {
716
+ resolvedTypes.set(index, globalType);
717
+ }
718
+ }
719
+ }
720
+ plan = {
721
+ paramTypes,
722
+ metadataMap,
723
+ resolvedTypes,
724
+ paramLength
725
+ };
726
+ this.dependencyPlans.set(constructor, plan);
727
+ return plan;
728
+ }
729
+ resolveFromPlan(constructor, plan, index) {
730
+ const meta = plan.metadataMap.get(index);
731
+ if (meta?.token) {
732
+ return this.resolveInternal(meta.token);
733
+ }
734
+ const resolvedType = plan.resolvedTypes.get(index);
735
+ if (resolvedType) {
736
+ return this.resolveInternal(resolvedType);
737
+ }
738
+ const paramType = plan.paramTypes[index];
739
+ if (paramType) {
740
+ const token = this.typeToToken.get(paramType);
741
+ if (token) {
742
+ return this.resolveInternal(token);
743
+ }
744
+ return this.resolveInternal(paramType);
745
+ }
746
+ throw new Error(`Cannot resolve dependency at index ${index} of ${constructor.name}. ` + "Parameter type is undefined. Use @Inject() decorator to specify the dependency type.");
747
+ }
748
+ }
749
+
750
+ // src/controller/decorators.ts
751
+ import"reflect-metadata";
752
+ var PARAM_METADATA_KEY = Symbol("param");
753
+ function createParamDecorator(type, key) {
754
+ return function(target, propertyKey, parameterIndex) {
755
+ const existingParams = Reflect.getMetadata(PARAM_METADATA_KEY, target, propertyKey) || [];
756
+ existingParams.push({ type, key, index: parameterIndex });
757
+ Reflect.defineMetadata(PARAM_METADATA_KEY, existingParams, target, propertyKey);
758
+ };
759
+ }
760
+ function Body(key) {
761
+ return createParamDecorator("body" /* BODY */, key);
762
+ }
763
+ function Query(key) {
764
+ return createParamDecorator("query" /* QUERY */, key);
765
+ }
766
+ function Param(key) {
767
+ return createParamDecorator("param" /* PARAM */, key);
768
+ }
769
+ function Header(key) {
770
+ return createParamDecorator("header" /* HEADER */, key);
771
+ }
772
+ function getParamMetadata(target, propertyKey) {
773
+ return Reflect.getMetadata(PARAM_METADATA_KEY, target, propertyKey) || [];
774
+ }
775
+
776
+ // src/controller/param-binder.ts
777
+ class ParamBinder {
778
+ static async bind(target, propertyKey, context) {
779
+ const metadata = getParamMetadata(target, propertyKey);
780
+ const params = [];
781
+ metadata.sort((a, b) => a.index - b.index);
782
+ for (const meta of metadata) {
783
+ const value = await this.getValue(meta, context);
784
+ params[meta.index] = value;
785
+ }
786
+ const maxIndex = metadata.length > 0 ? Math.max(...metadata.map((m) => m.index)) : -1;
787
+ for (let i = 0;i <= maxIndex; i++) {
788
+ if (!(i in params)) {
789
+ params[i] = undefined;
790
+ }
791
+ }
792
+ return params;
793
+ }
794
+ static async getValue(meta, context) {
795
+ switch (meta.type) {
796
+ case "body" /* BODY */:
797
+ return await this.getBodyValue(meta.key, context);
798
+ case "query" /* QUERY */:
799
+ if (!meta.key) {
800
+ throw new Error("@Query() decorator requires a key parameter");
801
+ }
802
+ return this.getQueryValue(meta.key, context);
803
+ case "param" /* PARAM */:
804
+ if (!meta.key) {
805
+ throw new Error("@Param() decorator requires a key parameter");
806
+ }
807
+ return this.getParamValue(meta.key, context);
808
+ case "header" /* HEADER */:
809
+ if (!meta.key) {
810
+ throw new Error("@Header() decorator requires a key parameter");
811
+ }
812
+ return this.getHeaderValue(meta.key, context);
813
+ default:
814
+ return;
815
+ }
816
+ }
817
+ static async getBodyValue(key, context) {
818
+ const body = await context.getBody();
819
+ if (!key) {
820
+ return body;
821
+ }
822
+ if (typeof body === "object" && body !== null) {
823
+ return body[key];
824
+ }
825
+ return;
826
+ }
827
+ static getQueryValue(key, context) {
828
+ return context.getQuery(key);
829
+ }
830
+ static getParamValue(key, context) {
831
+ return context.getParam(key);
832
+ }
833
+ static getHeaderValue(key, context) {
834
+ return context.getHeader(key);
835
+ }
836
+ }
837
+
838
+ // src/controller/metadata.ts
839
+ import"reflect-metadata";
840
+
841
+ // src/router/decorators.ts
842
+ import"reflect-metadata";
843
+ var ROUTE_METADATA_KEY = Symbol("route");
844
+ function createRouteDecorator(method, path) {
845
+ return function(target, propertyKey, descriptor) {
846
+ const controllerMetadata = Reflect.getMetadata(CONTROLLER_METADATA_KEY, target.constructor);
847
+ if (controllerMetadata) {
848
+ const existingRoutes = Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
849
+ let propertyKeyStr;
850
+ if (propertyKey && propertyKey !== "") {
851
+ propertyKeyStr = typeof propertyKey === "string" ? propertyKey : String(propertyKey);
852
+ } else {
853
+ propertyKeyStr = descriptor.value.name || "";
854
+ }
855
+ if (!propertyKeyStr) {
856
+ const propertyNames = Object.getOwnPropertyNames(target);
857
+ for (const key of propertyNames) {
858
+ const targetDescriptor = Object.getOwnPropertyDescriptor(target, key);
859
+ if (targetDescriptor?.value === descriptor.value) {
860
+ propertyKeyStr = key;
861
+ break;
862
+ }
863
+ }
864
+ }
865
+ existingRoutes.push({
866
+ method,
867
+ path,
868
+ handler: descriptor.value,
869
+ propertyKey: propertyKeyStr || undefined
870
+ });
871
+ Reflect.defineMetadata(ROUTE_METADATA_KEY, existingRoutes, target);
872
+ } else {
873
+ const handler = descriptor.value;
874
+ const registry = RouteRegistry.getInstance();
875
+ registry.register(method, path, handler);
876
+ const existingRoutes = Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
877
+ existingRoutes.push({ method, path, handler });
878
+ Reflect.defineMetadata(ROUTE_METADATA_KEY, existingRoutes, target);
879
+ }
880
+ };
881
+ }
882
+ function GET(path) {
883
+ return createRouteDecorator("GET", path);
884
+ }
885
+ function POST(path) {
886
+ return createRouteDecorator("POST", path);
887
+ }
888
+ function PUT(path) {
889
+ return createRouteDecorator("PUT", path);
890
+ }
891
+ function DELETE(path) {
892
+ return createRouteDecorator("DELETE", path);
893
+ }
894
+ function PATCH(path) {
895
+ return createRouteDecorator("PATCH", path);
896
+ }
897
+
898
+ // src/controller/metadata.ts
899
+ function getControllerMetadata(target) {
900
+ return Reflect.getMetadata(CONTROLLER_METADATA_KEY, target);
901
+ }
902
+ function getRouteMetadata(target) {
903
+ return Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
904
+ }
905
+ // src/middleware/decorators.ts
906
+ import"reflect-metadata";
907
+ var CLASS_MIDDLEWARE_METADATA_KEY = Symbol("middleware:class");
908
+ var METHOD_MIDDLEWARE_METADATA_KEY = Symbol("middleware:method");
909
+ function appendMiddlewareMetadata(target, propertyKey, middlewares) {
910
+ if (!middlewares.length) {
911
+ return;
912
+ }
913
+ if (propertyKey === undefined) {
914
+ const existing2 = Reflect.getMetadata(CLASS_MIDDLEWARE_METADATA_KEY, target) || [];
915
+ Reflect.defineMetadata(CLASS_MIDDLEWARE_METADATA_KEY, existing2.concat(middlewares), target);
916
+ return;
917
+ }
918
+ const existing = Reflect.getMetadata(METHOD_MIDDLEWARE_METADATA_KEY, target, propertyKey) || [];
919
+ Reflect.defineMetadata(METHOD_MIDDLEWARE_METADATA_KEY, existing.concat(middlewares), target, propertyKey);
920
+ }
921
+ function UseMiddleware(...middlewares) {
922
+ return function(target, propertyKey) {
923
+ appendMiddlewareMetadata(propertyKey === undefined ? target : target, propertyKey, middlewares);
924
+ };
925
+ }
926
+ function getClassMiddlewares(constructor) {
927
+ return Reflect.getMetadata(CLASS_MIDDLEWARE_METADATA_KEY, constructor) || [];
928
+ }
929
+ function getMethodMiddlewares(target, propertyKey) {
930
+ return Reflect.getMetadata(METHOD_MIDDLEWARE_METADATA_KEY, target, propertyKey) || [];
931
+ }
932
+ // src/middleware/builtin/logger.ts
933
+ import { LoggerManager as LoggerManager4 } from "@dangao/logsmith";
934
+ function createLoggerMiddleware(options = {}) {
935
+ const log = options.logger ?? ((message, details) => {
936
+ const logger = LoggerManager4.getLogger();
937
+ if (details) {
938
+ logger.info(message, details);
939
+ } else {
940
+ logger.info(message);
941
+ }
942
+ });
943
+ const prefix = options.prefix ?? "[Logger]";
944
+ return async (context, next) => {
945
+ let response;
946
+ try {
947
+ response = await next();
948
+ return response;
949
+ } finally {
950
+ const status = response?.status ?? context.statusCode ?? 200;
951
+ log(`${prefix} ${context.method} ${context.path} ${status}`);
952
+ }
953
+ };
954
+ }
955
+ function createRequestLoggingMiddleware(options = {}) {
956
+ const log = options.logger ?? ((message, details) => {
957
+ const logger = LoggerManager4.getLogger();
958
+ logger.info(message, details);
959
+ });
960
+ const prefix = options.prefix ?? "[Request]";
961
+ const setHeader = options.setHeader ?? true;
962
+ return async (context, next) => {
963
+ const start = performance.now();
964
+ try {
965
+ const response = await next();
966
+ const duration = performance.now() - start;
967
+ log(`${prefix} ${context.method} ${context.path} ${response.status} ${duration.toFixed(2)}ms`);
968
+ if (setHeader) {
969
+ context.setHeader("x-request-duration", duration.toFixed(2));
970
+ }
971
+ return response;
972
+ } catch (error) {
973
+ const duration = performance.now() - start;
974
+ log(`${prefix} ${context.method} ${context.path} error ${duration.toFixed(2)}ms`, error instanceof Error ? { error: error.message } : undefined);
975
+ throw error;
976
+ }
977
+ };
978
+ }
979
+ // src/validation/decorators.ts
980
+ import"reflect-metadata";
981
+ var VALIDATION_METADATA_KEY = Symbol("validation:param");
982
+ function getOrCreateMetadata(target, propertyKey) {
983
+ const existing = Reflect.getMetadata(VALIDATION_METADATA_KEY, target, propertyKey);
984
+ if (existing) {
985
+ return existing;
986
+ }
987
+ const metadata = [];
988
+ Reflect.defineMetadata(VALIDATION_METADATA_KEY, metadata, target, propertyKey);
989
+ return metadata;
990
+ }
991
+ function Validate(...rules) {
992
+ return (target, propertyKey, parameterIndex) => {
993
+ if (!propertyKey) {
994
+ throw new Error("@Validate decorator can only be used on methods");
995
+ }
996
+ if (!rules.length) {
997
+ throw new Error("@Validate requires at least one validation rule");
998
+ }
999
+ const metadata = getOrCreateMetadata(target, propertyKey);
1000
+ let entry = metadata.find((item) => item.index === parameterIndex);
1001
+ if (!entry) {
1002
+ entry = { index: parameterIndex, rules: [] };
1003
+ metadata.push(entry);
1004
+ }
1005
+ entry.rules.push(...rules);
1006
+ };
1007
+ }
1008
+ function IsString(options = {}) {
1009
+ return {
1010
+ name: "isString",
1011
+ message: options.message ?? "\u5FC5\u987B\u662F\u5B57\u7B26\u4E32",
1012
+ validate: (value) => typeof value === "string"
1013
+ };
1014
+ }
1015
+ function IsNumber(options = {}) {
1016
+ return {
1017
+ name: "isNumber",
1018
+ message: options.message ?? "\u5FC5\u987B\u662F\u6570\u5B57",
1019
+ validate: (value) => typeof value === "number" && !Number.isNaN(value)
1020
+ };
1021
+ }
1022
+ function IsEmail(options = {}) {
1023
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1024
+ return {
1025
+ name: "isEmail",
1026
+ message: options.message ?? "\u5FC5\u987B\u662F\u5408\u6CD5\u7684\u90AE\u7BB1\u5730\u5740",
1027
+ validate: (value) => typeof value === "string" && emailRegex.test(value)
1028
+ };
1029
+ }
1030
+ function IsOptional() {
1031
+ return {
1032
+ name: "isOptional",
1033
+ message: "",
1034
+ optional: true,
1035
+ validate: () => true
1036
+ };
1037
+ }
1038
+ function MinLength(min, options = {}) {
1039
+ return {
1040
+ name: "minLength",
1041
+ message: options.message ?? `\u957F\u5EA6\u4E0D\u80FD\u5C0F\u4E8E ${min}`,
1042
+ validate: (value) => typeof value === "string" && value.length >= min
1043
+ };
1044
+ }
1045
+ function getValidationMetadata(target, propertyKey) {
1046
+ return Reflect.getMetadata(VALIDATION_METADATA_KEY, target, propertyKey) || [];
1047
+ }
1048
+ // src/validation/errors.ts
1049
+ class ValidationError extends Error {
1050
+ issues;
1051
+ constructor(message, issues) {
1052
+ super(message);
1053
+ this.name = "ValidationError";
1054
+ this.issues = issues;
1055
+ }
1056
+ }
1057
+
1058
+ // src/validation/validator.ts
1059
+ function shouldSkip(rule, value) {
1060
+ return rule.optional === true && (value === undefined || value === null);
1061
+ }
1062
+ function validateRule(rule, value, index) {
1063
+ if (shouldSkip(rule, value)) {
1064
+ return null;
1065
+ }
1066
+ const passed = rule.validate(value);
1067
+ if (passed) {
1068
+ return null;
1069
+ }
1070
+ return {
1071
+ index,
1072
+ rule: rule.name,
1073
+ message: rule.message
1074
+ };
1075
+ }
1076
+ function validateParameters(params, metadata) {
1077
+ if (!metadata.length) {
1078
+ return;
1079
+ }
1080
+ const issues = [];
1081
+ for (const item of metadata) {
1082
+ const value = params[item.index];
1083
+ let skipped = false;
1084
+ for (const rule of item.rules) {
1085
+ if (rule.optional && (value === undefined || value === null)) {
1086
+ skipped = true;
1087
+ break;
1088
+ }
1089
+ const issue = validateRule(rule, value, item.index);
1090
+ if (issue) {
1091
+ issues.push(issue);
1092
+ }
1093
+ }
1094
+ if (skipped) {
1095
+ continue;
1096
+ }
1097
+ }
1098
+ if (issues.length > 0) {
1099
+ throw new ValidationError("Validation failed", issues);
1100
+ }
1101
+ }
1102
+ // src/middleware/builtin/error-handler.ts
1103
+ import { LoggerManager as LoggerManager5 } from "@dangao/logsmith";
1104
+
1105
+ // src/error/http-exception.ts
1106
+ class HttpException extends Error {
1107
+ status;
1108
+ details;
1109
+ constructor(status, message, details) {
1110
+ super(message);
1111
+ this.name = this.constructor.name;
1112
+ this.status = status;
1113
+ this.details = details;
1114
+ }
1115
+ }
1116
+
1117
+ class BadRequestException extends HttpException {
1118
+ constructor(message = "Bad Request", details) {
1119
+ super(400, message, details);
1120
+ }
1121
+ }
1122
+
1123
+ class UnauthorizedException extends HttpException {
1124
+ constructor(message = "Unauthorized", details) {
1125
+ super(401, message, details);
1126
+ }
1127
+ }
1128
+
1129
+ class ForbiddenException extends HttpException {
1130
+ constructor(message = "Forbidden", details) {
1131
+ super(403, message, details);
1132
+ }
1133
+ }
1134
+
1135
+ class NotFoundException extends HttpException {
1136
+ constructor(message = "Not Found", details) {
1137
+ super(404, message, details);
1138
+ }
1139
+ }
1140
+
1141
+ class InternalServerErrorException extends HttpException {
1142
+ constructor(message = "Internal Server Error", details) {
1143
+ super(500, message, details);
1144
+ }
1145
+ }
1146
+ // src/error/filter.ts
1147
+ class ExceptionFilterRegistry {
1148
+ static instance;
1149
+ filters = [];
1150
+ constructor() {}
1151
+ static getInstance() {
1152
+ if (!ExceptionFilterRegistry.instance) {
1153
+ ExceptionFilterRegistry.instance = new ExceptionFilterRegistry;
1154
+ }
1155
+ return ExceptionFilterRegistry.instance;
1156
+ }
1157
+ register(filter) {
1158
+ this.filters.push(filter);
1159
+ }
1160
+ clear() {
1161
+ this.filters.length = 0;
1162
+ }
1163
+ async execute(error, context) {
1164
+ for (const filter of this.filters) {
1165
+ const result = await filter.catch(error, context);
1166
+ if (result) {
1167
+ return result;
1168
+ }
1169
+ }
1170
+ return;
1171
+ }
1172
+ }
1173
+ // src/error/handler.ts
1174
+ async function handleError(error, context) {
1175
+ const registry = ExceptionFilterRegistry.getInstance();
1176
+ const filterResponse = await registry.execute(error, context);
1177
+ if (filterResponse) {
1178
+ return filterResponse;
1179
+ }
1180
+ if (error instanceof HttpException) {
1181
+ context.setStatus(error.status);
1182
+ return context.createResponse({
1183
+ error: error.message,
1184
+ details: error.details
1185
+ });
1186
+ }
1187
+ if (error instanceof ValidationError) {
1188
+ context.setStatus(400);
1189
+ return context.createResponse({
1190
+ error: error.message,
1191
+ issues: error.issues
1192
+ });
1193
+ }
1194
+ const message = error instanceof Error ? error.message : String(error);
1195
+ context.setStatus(500);
1196
+ return context.createResponse({
1197
+ error: "Internal Server Error",
1198
+ details: message
1199
+ });
1200
+ }
1201
+ // src/middleware/builtin/error-handler.ts
1202
+ function createErrorHandlingMiddleware(options = {}) {
1203
+ const log = options.logger ?? ((error, context) => {
1204
+ LoggerManager5.getLogger().error("[Error]", { ...context, error });
1205
+ });
1206
+ const expose = options.exposeError ?? false;
1207
+ const defaultStatus = options.statusCode ?? 500;
1208
+ return async (context, next) => {
1209
+ const logger = LoggerManager5.getLogger();
1210
+ try {
1211
+ return await next();
1212
+ } catch (error) {
1213
+ log(error, { method: context.method, path: context.path });
1214
+ logger.error("Unhandled error", {
1215
+ method: context.method,
1216
+ path: context.path,
1217
+ error
1218
+ });
1219
+ if (error instanceof Response) {
1220
+ return error;
1221
+ }
1222
+ if (error instanceof ValidationError) {
1223
+ return context.createResponse({
1224
+ error: error.message,
1225
+ issues: error.issues
1226
+ }, {
1227
+ status: 400
1228
+ });
1229
+ }
1230
+ if (error instanceof HttpException) {
1231
+ if (!expose) {
1232
+ return await handleError(error, context);
1233
+ }
1234
+ return context.createResponse({
1235
+ error: error.message,
1236
+ details: error.details
1237
+ }, { status: error.status });
1238
+ }
1239
+ if (error instanceof Error && !expose) {
1240
+ return await handleError(error, context);
1241
+ }
1242
+ if (error instanceof Error) {
1243
+ return context.createResponse({
1244
+ error: error.message
1245
+ }, {
1246
+ status: defaultStatus
1247
+ });
1248
+ }
1249
+ return await handleError(error, context);
1250
+ }
1251
+ };
1252
+ }
1253
+ // src/middleware/builtin/cors.ts
1254
+ function getOriginHeader(option, requestOrigin) {
1255
+ if (!option || option === "*") {
1256
+ return "*";
1257
+ }
1258
+ if (Array.isArray(option)) {
1259
+ if (requestOrigin && option.includes(requestOrigin)) {
1260
+ return requestOrigin;
1261
+ }
1262
+ return option[0];
1263
+ }
1264
+ return option;
1265
+ }
1266
+ function createCorsMiddleware(options = {}) {
1267
+ const methods = options.methods ?? ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"];
1268
+ const allowedHeaders = options.allowedHeaders ?? ["Content-Type", "Authorization"];
1269
+ const exposedHeaders = options.exposedHeaders ?? [];
1270
+ const credentials = options.credentials ?? true;
1271
+ const maxAge = options.maxAge ?? 600;
1272
+ return async (context, next) => {
1273
+ const requestOrigin = context.getHeader("Origin");
1274
+ const originHeader = getOriginHeader(options.origin ?? "*", requestOrigin);
1275
+ context.setHeader("Access-Control-Allow-Origin", originHeader);
1276
+ if (credentials) {
1277
+ context.setHeader("Access-Control-Allow-Credentials", "true");
1278
+ }
1279
+ context.setHeader("Access-Control-Allow-Methods", methods.join(","));
1280
+ context.setHeader("Access-Control-Allow-Headers", allowedHeaders.join(","));
1281
+ if (exposedHeaders.length > 0) {
1282
+ context.setHeader("Access-Control-Expose-Headers", exposedHeaders.join(","));
1283
+ }
1284
+ context.setHeader("Access-Control-Max-Age", maxAge.toString());
1285
+ if (context.method === "OPTIONS") {
1286
+ return new Response(null, { status: 204, headers: context.responseHeaders });
1287
+ }
1288
+ return await next();
1289
+ };
1290
+ }
1291
+ // src/request/file-handler.ts
1292
+ class FileHandler {
1293
+ static MAX_SIZE = 10 * 1024 * 1024;
1294
+ static async parseFormData(context) {
1295
+ const contentType = context.getHeader("Content-Type");
1296
+ if (!contentType || !contentType.includes("multipart/form-data")) {
1297
+ throw new Error("Content-Type must be multipart/form-data");
1298
+ }
1299
+ const request = context.request;
1300
+ return await request.formData();
1301
+ }
1302
+ static async getFiles(formData) {
1303
+ const files = {};
1304
+ for (const [key, value] of formData.entries()) {
1305
+ if (value instanceof File) {
1306
+ const buffer = await value.arrayBuffer();
1307
+ if (buffer.byteLength > this.MAX_SIZE) {
1308
+ throw new Error(`File ${value.name} exceeds maximum size`);
1309
+ }
1310
+ if (!files[key]) {
1311
+ files[key] = [];
1312
+ }
1313
+ files[key].push({
1314
+ name: value.name,
1315
+ type: value.type,
1316
+ size: value.size,
1317
+ data: buffer
1318
+ });
1319
+ }
1320
+ }
1321
+ return files;
1322
+ }
1323
+ }
1324
+
1325
+ // src/middleware/builtin/file-upload.ts
1326
+ function createFileUploadMiddleware(options = {}) {
1327
+ const maxSize = options.maxSize ?? 10 * 1024 * 1024;
1328
+ return async (context, next) => {
1329
+ const contentType = context.getHeader("Content-Type");
1330
+ if (!contentType || !contentType.includes("multipart/form-data")) {
1331
+ return await next();
1332
+ }
1333
+ const formData = await FileHandler.parseFormData(context);
1334
+ const files = await FileHandler.getFiles(formData);
1335
+ for (const fileList of Object.values(files)) {
1336
+ for (const file of fileList) {
1337
+ if (file.size > maxSize) {
1338
+ context.setStatus(413);
1339
+ return context.createResponse({ error: `File ${file.name} exceeds max size` });
1340
+ }
1341
+ }
1342
+ }
1343
+ context.body = {
1344
+ fields: Object.fromEntries(formData.entries()),
1345
+ files
1346
+ };
1347
+ return await next();
1348
+ };
1349
+ }
1350
+ // src/middleware/builtin/static-file.ts
1351
+ import { normalize, resolve, sep } from "path";
1352
+ function isSubPath(root, target) {
1353
+ const normalizedRoot = normalize(root);
1354
+ const normalizedTarget = normalize(target);
1355
+ if (normalizedRoot === normalizedTarget) {
1356
+ return true;
1357
+ }
1358
+ const rootWithSep = normalizedRoot.endsWith(sep) ? normalizedRoot : normalizedRoot + sep;
1359
+ return normalizedTarget.startsWith(rootWithSep);
1360
+ }
1361
+ function createStaticFileMiddleware(options) {
1362
+ if (!options.root) {
1363
+ throw new Error("Static file middleware requires a root directory");
1364
+ }
1365
+ const root = resolve(options.root);
1366
+ const prefix = options.prefix ?? "/";
1367
+ const indexFile = options.indexFile ?? "index.html";
1368
+ const enableCache = options.enableCache ?? true;
1369
+ return async (context, next) => {
1370
+ if (!context.path.startsWith(prefix)) {
1371
+ return await next();
1372
+ }
1373
+ let relativePath = context.path.slice(prefix.length);
1374
+ if (!relativePath || relativePath === "") {
1375
+ relativePath = "/";
1376
+ }
1377
+ let cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
1378
+ if (cleanPath === "") {
1379
+ cleanPath = ".";
1380
+ }
1381
+ const segments = cleanPath.split("/").filter((segment) => segment.length > 0);
1382
+ if (segments.some((segment) => segment === "..")) {
1383
+ context.setStatus(403);
1384
+ return context.createResponse({ error: "Forbidden" });
1385
+ }
1386
+ let targetPath = resolve(root, cleanPath);
1387
+ if (context.path.endsWith("/") || relativePath === "/") {
1388
+ targetPath = resolve(root, cleanPath, indexFile);
1389
+ }
1390
+ if (!isSubPath(root, targetPath)) {
1391
+ context.setStatus(403);
1392
+ return context.createResponse({ error: "Forbidden" });
1393
+ }
1394
+ const file = Bun.file(targetPath);
1395
+ if (!await file.exists()) {
1396
+ return await next();
1397
+ }
1398
+ const headers = new Headers(options.headers);
1399
+ if (enableCache) {
1400
+ headers.set("Cache-Control", "public, max-age=31536000, immutable");
1401
+ }
1402
+ if (!headers.has("Content-Type") && file.type) {
1403
+ headers.set("Content-Type", file.type);
1404
+ }
1405
+ return new Response(file, {
1406
+ status: 200,
1407
+ headers
1408
+ });
1409
+ };
1410
+ }
1411
+ // src/controller/controller.ts
1412
+ var CONTROLLER_METADATA_KEY = Symbol("controller");
1413
+ function Controller(path = "") {
1414
+ return function(target) {
1415
+ Reflect.defineMetadata(CONTROLLER_METADATA_KEY, { path, target }, target);
1416
+ };
1417
+ }
1418
+
1419
+ class ControllerRegistry {
1420
+ static instance;
1421
+ container;
1422
+ controllers = new Map;
1423
+ controllerContainers = new Map;
1424
+ constructor() {
1425
+ this.container = new Container;
1426
+ }
1427
+ static getInstance() {
1428
+ if (!ControllerRegistry.instance) {
1429
+ ControllerRegistry.instance = new ControllerRegistry;
1430
+ }
1431
+ return ControllerRegistry.instance;
1432
+ }
1433
+ register(controllerClass, container) {
1434
+ const targetContainer = container ?? this.container;
1435
+ this.controllerContainers.set(controllerClass, targetContainer);
1436
+ if (!targetContainer.isRegistered(controllerClass)) {
1437
+ targetContainer.register(controllerClass);
1438
+ }
1439
+ const metadata = getControllerMetadata(controllerClass);
1440
+ if (!metadata) {
1441
+ throw new Error(`Controller ${controllerClass.name} must be decorated with @Controller()`);
1442
+ }
1443
+ const prototype = controllerClass.prototype;
1444
+ const routes = getRouteMetadata(prototype);
1445
+ if (!routes || routes.length === 0) {
1446
+ return;
1447
+ }
1448
+ const classMiddlewares = getClassMiddlewares(controllerClass);
1449
+ const basePath = metadata.path;
1450
+ const registry = RouteRegistry.getInstance();
1451
+ for (const route of routes) {
1452
+ const fullPath = this.combinePaths(basePath, route.path);
1453
+ let propertyKey = route.propertyKey;
1454
+ if (!propertyKey) {
1455
+ const prototype2 = controllerClass.prototype;
1456
+ const propertyNames = Object.getOwnPropertyNames(prototype2);
1457
+ for (const key of propertyNames) {
1458
+ if (key === "constructor")
1459
+ continue;
1460
+ const descriptor = Object.getOwnPropertyDescriptor(prototype2, key);
1461
+ if (descriptor && descriptor.value === route.handler) {
1462
+ propertyKey = key;
1463
+ break;
1464
+ }
1465
+ }
1466
+ }
1467
+ if (!propertyKey) {
1468
+ continue;
1469
+ }
1470
+ const handler = async (context) => {
1471
+ try {
1472
+ const controllerContainer = this.controllerContainers.get(controllerClass) ?? this.container;
1473
+ const controllerInstance = controllerContainer.resolve(controllerClass);
1474
+ const prototype2 = controllerClass.prototype;
1475
+ const params = await ParamBinder.bind(prototype2, propertyKey, context);
1476
+ const validationMetadata = getValidationMetadata(prototype2, propertyKey);
1477
+ if (validationMetadata.length > 0) {
1478
+ validateParameters(params, validationMetadata);
1479
+ }
1480
+ let method = controllerInstance[propertyKey];
1481
+ if (!method || typeof method !== "function") {
1482
+ const prototype3 = controllerClass.prototype;
1483
+ method = prototype3[propertyKey];
1484
+ }
1485
+ if (!method || typeof method !== "function") {
1486
+ throw new Error(`Method ${propertyKey} not found on controller ${controllerClass.name}`);
1487
+ }
1488
+ const result = method.apply(controllerInstance, params);
1489
+ const responseData = await Promise.resolve(result);
1490
+ return context.createResponse(responseData);
1491
+ } catch (error) {
1492
+ if (error instanceof ValidationError) {
1493
+ context.setStatus(400);
1494
+ return context.createResponse({
1495
+ error: error.message,
1496
+ issues: error.issues
1497
+ });
1498
+ }
1499
+ if (error instanceof HttpException) {
1500
+ context.setStatus(error.status);
1501
+ return context.createResponse({
1502
+ error: error.message,
1503
+ details: error.details
1504
+ });
1505
+ }
1506
+ context.setStatus(500);
1507
+ const errorMessage = error instanceof Error ? error.message : String(error);
1508
+ return context.createResponse({ error: errorMessage });
1509
+ }
1510
+ };
1511
+ const middlewares = [...classMiddlewares];
1512
+ if (propertyKey) {
1513
+ middlewares.push(...getMethodMiddlewares(prototype, propertyKey));
1514
+ }
1515
+ registry.register(route.method, fullPath, handler, middlewares);
1516
+ }
1517
+ }
1518
+ combinePaths(basePath, methodPath) {
1519
+ const base = basePath.replace(/\/$/, "").replace(/^\/?/, "/");
1520
+ const method = methodPath.replace(/^\//, "");
1521
+ if (!method) {
1522
+ return base === "/" ? "/" : base;
1523
+ }
1524
+ return base + "/" + method;
1525
+ }
1526
+ getContainer() {
1527
+ return this.container;
1528
+ }
1529
+ clear() {
1530
+ this.controllers.clear();
1531
+ this.container.clear();
1532
+ this.controllerContainers.clear();
1533
+ }
1534
+ }
1535
+
1536
+ // src/websocket/decorators.ts
1537
+ import"reflect-metadata";
1538
+ var GATEWAY_METADATA_KEY = Symbol("websocket:gateway");
1539
+ var HANDLER_METADATA_KEY = Symbol("websocket:handlers");
1540
+ function WebSocketGateway(path) {
1541
+ return (target) => {
1542
+ Reflect.defineMetadata(GATEWAY_METADATA_KEY, { path }, target);
1543
+ };
1544
+ }
1545
+ function createHandlerDecorator(type) {
1546
+ return function(target, propertyKey) {
1547
+ if (typeof propertyKey !== "string") {
1548
+ throw new Error("@OnOpen/@OnMessage/@OnClose only support string method names");
1549
+ }
1550
+ const existing = Reflect.getMetadata(HANDLER_METADATA_KEY, target) || {};
1551
+ existing[type] = propertyKey;
1552
+ Reflect.defineMetadata(HANDLER_METADATA_KEY, existing, target);
1553
+ };
1554
+ }
1555
+ var OnOpen = createHandlerDecorator("open");
1556
+ var OnMessage = createHandlerDecorator("message");
1557
+ var OnClose = createHandlerDecorator("close");
1558
+ function getGatewayMetadata(constructor) {
1559
+ return Reflect.getMetadata(GATEWAY_METADATA_KEY, constructor);
1560
+ }
1561
+ function getHandlerMetadata(target) {
1562
+ return Reflect.getMetadata(HANDLER_METADATA_KEY, target) || {};
1563
+ }
1564
+
1565
+ // src/websocket/registry.ts
1566
+ class WebSocketGatewayRegistry {
1567
+ static instance;
1568
+ container;
1569
+ gateways = new Map;
1570
+ constructor() {
1571
+ this.container = ControllerRegistry.getInstance().getContainer();
1572
+ }
1573
+ static getInstance() {
1574
+ if (!WebSocketGatewayRegistry.instance) {
1575
+ WebSocketGatewayRegistry.instance = new WebSocketGatewayRegistry;
1576
+ }
1577
+ return WebSocketGatewayRegistry.instance;
1578
+ }
1579
+ register(gatewayClass) {
1580
+ const metadata = getGatewayMetadata(gatewayClass);
1581
+ if (!metadata) {
1582
+ throw new Error(`WebSocket gateway ${gatewayClass.name} must use @WebSocketGateway()`);
1583
+ }
1584
+ const handlers = getHandlerMetadata(gatewayClass.prototype);
1585
+ if (!handlers.open && !handlers.message && !handlers.close) {
1586
+ throw new Error(`WebSocket gateway ${gatewayClass.name} must define at least one handler`);
1587
+ }
1588
+ if (!this.container.isRegistered(gatewayClass)) {
1589
+ this.container.register(gatewayClass);
1590
+ }
1591
+ this.gateways.set(metadata.path, {
1592
+ path: metadata.path,
1593
+ gatewayClass,
1594
+ handlers
1595
+ });
1596
+ }
1597
+ hasGateway(path) {
1598
+ return this.gateways.has(path);
1599
+ }
1600
+ clear() {
1601
+ this.gateways.clear();
1602
+ }
1603
+ getGateway(path) {
1604
+ return this.gateways.get(path);
1605
+ }
1606
+ getGatewayInstance(definition) {
1607
+ if (!definition.instance) {
1608
+ definition.instance = this.container.resolve(definition.gatewayClass);
1609
+ }
1610
+ return definition.instance;
1611
+ }
1612
+ invokeHandler(ws, definition, handlerName, ...args) {
1613
+ if (!handlerName) {
1614
+ return;
1615
+ }
1616
+ const instance = this.getGatewayInstance(definition);
1617
+ const handler = instance[handlerName];
1618
+ if (typeof handler === "function") {
1619
+ handler.apply(instance, [ws, ...args]);
1620
+ }
1621
+ }
1622
+ handleOpen(ws) {
1623
+ const path = ws.data?.path;
1624
+ const definition = path ? this.getGateway(path) : undefined;
1625
+ if (!definition) {
1626
+ ws.close(1008, "Gateway not found");
1627
+ return;
1628
+ }
1629
+ this.invokeHandler(ws, definition, definition.handlers.open);
1630
+ }
1631
+ handleMessage(ws, message) {
1632
+ const path = ws.data?.path;
1633
+ const definition = path ? this.getGateway(path) : undefined;
1634
+ if (!definition) {
1635
+ ws.close(1008, "Gateway not found");
1636
+ return;
1637
+ }
1638
+ this.invokeHandler(ws, definition, definition.handlers.message, message);
1639
+ }
1640
+ handleClose(ws, code, reason) {
1641
+ const path = ws.data?.path;
1642
+ const definition = path ? this.getGateway(path) : undefined;
1643
+ if (!definition) {
1644
+ return;
1645
+ }
1646
+ this.invokeHandler(ws, definition, definition.handlers.close, code, reason);
1647
+ }
1648
+ }
1649
+
1650
+ // src/extensions/logger-extension.ts
1651
+ import {
1652
+ LoggerManager as LoggerManager6,
1653
+ LogLevel,
1654
+ SimpleLogger
1655
+ } from "@dangao/logsmith";
1656
+ var LOGGER_TOKEN = Symbol("@dangao/bun-server:logger");
1657
+
1658
+ class LoggerExtension {
1659
+ options;
1660
+ constructor(options = {}) {
1661
+ this.options = {
1662
+ level: LogLevel.INFO,
1663
+ ...options
1664
+ };
1665
+ }
1666
+ register(container) {
1667
+ const logger = new SimpleLogger(this.options);
1668
+ LoggerManager6.setLogger(logger);
1669
+ container.registerInstance(SimpleLogger, logger);
1670
+ container.registerInstance(LOGGER_TOKEN, logger);
1671
+ }
1672
+ }
1673
+
1674
+ // src/di/module.ts
1675
+ import"reflect-metadata";
1676
+ var MODULE_METADATA_KEY = Symbol("@dangao/bun-server:module");
1677
+ function Module(metadata) {
1678
+ return (target) => {
1679
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, target);
1680
+ };
1681
+ }
1682
+ function getModuleMetadata(moduleClass) {
1683
+ const metadata = Reflect.getMetadata(MODULE_METADATA_KEY, moduleClass) ?? {};
1684
+ return {
1685
+ imports: metadata.imports ?? [],
1686
+ controllers: metadata.controllers ?? [],
1687
+ providers: metadata.providers ?? [],
1688
+ exports: metadata.exports ?? []
1689
+ };
1690
+ }
1691
+
1692
+ // src/di/module-registry.ts
1693
+ class ModuleRegistry {
1694
+ static instance;
1695
+ moduleRefs = new Map;
1696
+ processing = new Set;
1697
+ rootContainer;
1698
+ static getInstance() {
1699
+ if (!ModuleRegistry.instance) {
1700
+ ModuleRegistry.instance = new ModuleRegistry;
1701
+ }
1702
+ return ModuleRegistry.instance;
1703
+ }
1704
+ register(moduleClass, parentContainer) {
1705
+ if (!this.rootContainer) {
1706
+ this.rootContainer = parentContainer;
1707
+ }
1708
+ return this.processModule(moduleClass, parentContainer);
1709
+ }
1710
+ getModuleRef(moduleClass) {
1711
+ return this.moduleRefs.get(moduleClass);
1712
+ }
1713
+ clear() {
1714
+ this.moduleRefs.clear();
1715
+ this.processing.clear();
1716
+ this.rootContainer = undefined;
1717
+ }
1718
+ processModule(moduleClass, parentContainer) {
1719
+ if (this.processing.has(moduleClass)) {
1720
+ throw new Error(`Circular module dependency detected for ${moduleClass.name}`);
1721
+ }
1722
+ const moduleRef = this.getOrCreateModuleRef(moduleClass);
1723
+ this.processing.add(moduleClass);
1724
+ for (const imported of moduleRef.metadata.imports) {
1725
+ this.processModule(imported, moduleRef.container);
1726
+ }
1727
+ this.processing.delete(moduleClass);
1728
+ this.attachModuleToParent(moduleRef, parentContainer);
1729
+ return moduleRef;
1730
+ }
1731
+ getOrCreateModuleRef(moduleClass) {
1732
+ let ref = this.moduleRefs.get(moduleClass);
1733
+ if (ref) {
1734
+ return ref;
1735
+ }
1736
+ if (!this.rootContainer) {
1737
+ throw new Error("ModuleRegistry is not initialized with a root container");
1738
+ }
1739
+ const metadata = getModuleMetadata(moduleClass);
1740
+ const container = new Container({ parent: this.rootContainer });
1741
+ this.registerProviders(container, metadata.providers);
1742
+ ref = {
1743
+ moduleClass,
1744
+ metadata,
1745
+ container,
1746
+ controllersRegistered: false,
1747
+ attachedParents: new Set
1748
+ };
1749
+ this.registerControllers(ref);
1750
+ this.moduleRefs.set(moduleClass, ref);
1751
+ return ref;
1752
+ }
1753
+ registerProviders(container, providers) {
1754
+ for (const provider of providers) {
1755
+ if (typeof provider === "function") {
1756
+ if (!container.isRegistered(provider)) {
1757
+ container.register(provider);
1758
+ }
1759
+ continue;
1760
+ }
1761
+ if ("useValue" in provider) {
1762
+ container.registerInstance(provider.provide, provider.useValue);
1763
+ continue;
1764
+ }
1765
+ if ("useFactory" in provider) {
1766
+ container.register(provider.provide, {
1767
+ lifecycle: provider.lifecycle ?? "singleton" /* Singleton */,
1768
+ factory: () => provider.useFactory(container)
1769
+ });
1770
+ continue;
1771
+ }
1772
+ if ("useClass" in provider) {
1773
+ const token = provider.provide ?? provider.useClass;
1774
+ container.register(token, {
1775
+ lifecycle: provider.lifecycle ?? "singleton" /* Singleton */,
1776
+ implementation: provider.useClass
1777
+ });
1778
+ }
1779
+ }
1780
+ }
1781
+ registerControllers(moduleRef) {
1782
+ if (moduleRef.controllersRegistered) {
1783
+ return;
1784
+ }
1785
+ const controllerRegistry = ControllerRegistry.getInstance();
1786
+ for (const controller of moduleRef.metadata.controllers) {
1787
+ controllerRegistry.register(controller, moduleRef.container);
1788
+ }
1789
+ moduleRef.controllersRegistered = true;
1790
+ }
1791
+ attachModuleToParent(moduleRef, parentContainer) {
1792
+ if (moduleRef.attachedParents.has(parentContainer)) {
1793
+ return;
1794
+ }
1795
+ moduleRef.attachedParents.add(parentContainer);
1796
+ for (const exportedToken of moduleRef.metadata.exports) {
1797
+ this.registerExport(parentContainer, moduleRef, exportedToken);
1798
+ }
1799
+ }
1800
+ registerExport(parentContainer, moduleRef, token) {
1801
+ if (!moduleRef.container.isRegistered(token)) {
1802
+ throw new Error(`Module ${moduleRef.moduleClass.name} cannot export ${typeof token === "function" ? token.name : String(token)} because it is not registered`);
1803
+ }
1804
+ if (parentContainer.isRegistered(token)) {
1805
+ return;
1806
+ }
1807
+ parentContainer.register(token, {
1808
+ lifecycle: "singleton" /* Singleton */,
1809
+ factory: () => moduleRef.container.resolve(token)
1810
+ });
1811
+ }
1812
+ }
1813
+
1814
+ // src/core/application.ts
1815
+ class Application {
1816
+ server;
1817
+ options;
1818
+ middlewarePipeline;
1819
+ websocketRegistry;
1820
+ extensions = [];
1821
+ constructor(options = {}) {
1822
+ this.options = options;
1823
+ this.middlewarePipeline = new MiddlewarePipeline([createErrorHandlingMiddleware()]);
1824
+ this.websocketRegistry = WebSocketGatewayRegistry.getInstance();
1825
+ RouteRegistry.getInstance().clear();
1826
+ ControllerRegistry.getInstance().clear();
1827
+ ModuleRegistry.getInstance().clear();
1828
+ this.registerExtension(new LoggerExtension);
1829
+ }
1830
+ use(middleware) {
1831
+ this.middlewarePipeline.use(middleware);
1832
+ }
1833
+ listen(port, hostname) {
1834
+ if (this.server?.isRunning()) {
1835
+ throw new Error("Application is already running");
1836
+ }
1837
+ const serverOptions = {
1838
+ port: port ?? this.options.port ?? 3000,
1839
+ hostname: hostname ?? this.options.hostname,
1840
+ fetch: this.handleRequest.bind(this),
1841
+ websocketRegistry: this.websocketRegistry
1842
+ };
1843
+ this.server = new BunServer(serverOptions);
1844
+ this.server.start();
1845
+ }
1846
+ stop() {
1847
+ this.server?.stop();
1848
+ }
1849
+ async handleRequest(context) {
1850
+ if (["POST", "PUT", "PATCH"].includes(context.method)) {
1851
+ await context.getBody();
1852
+ }
1853
+ const registry = RouteRegistry.getInstance();
1854
+ const router = registry.getRouter();
1855
+ return await this.middlewarePipeline.run(context, async () => {
1856
+ const response = await router.handle(context);
1857
+ if (response) {
1858
+ return response;
1859
+ }
1860
+ context.setStatus(404);
1861
+ return context.createResponse({ error: "Not Found" });
1862
+ });
1863
+ }
1864
+ registerController(controllerClass) {
1865
+ const registry = ControllerRegistry.getInstance();
1866
+ registry.register(controllerClass);
1867
+ }
1868
+ registerModule(moduleClass) {
1869
+ const registry = ModuleRegistry.getInstance();
1870
+ registry.register(moduleClass, this.getContainer());
1871
+ }
1872
+ registerWebSocketGateway(gatewayClass) {
1873
+ this.websocketRegistry.register(gatewayClass);
1874
+ }
1875
+ registerExtension(extension) {
1876
+ this.extensions.push(extension);
1877
+ extension.register(this.getContainer());
1878
+ }
1879
+ getServer() {
1880
+ return this.server;
1881
+ }
1882
+ getContainer() {
1883
+ return ControllerRegistry.getInstance().getContainer();
1884
+ }
1885
+ }
1886
+ // src/request/request.ts
1887
+ class RequestWrapper {
1888
+ request;
1889
+ url;
1890
+ method;
1891
+ path;
1892
+ query;
1893
+ headers;
1894
+ _body;
1895
+ _bodyParsed = false;
1896
+ constructor(request) {
1897
+ this.request = request;
1898
+ this.url = new URL(request.url);
1899
+ this.method = request.method;
1900
+ this.path = this.url.pathname;
1901
+ this.query = this.url.searchParams;
1902
+ this.headers = request.headers;
1903
+ }
1904
+ async body() {
1905
+ if (!this._bodyParsed) {
1906
+ this._body = await BodyParser.parse(this.request);
1907
+ this._bodyParsed = true;
1908
+ }
1909
+ return this._body;
1910
+ }
1911
+ getBody() {
1912
+ return this._body;
1913
+ }
1914
+ getQuery(key) {
1915
+ return this.query.get(key);
1916
+ }
1917
+ getQueryAll() {
1918
+ const result = {};
1919
+ this.query.forEach((value, key) => {
1920
+ result[key] = value;
1921
+ });
1922
+ return result;
1923
+ }
1924
+ getHeader(key) {
1925
+ return this.headers.get(key);
1926
+ }
1927
+ }
1928
+ // src/request/response.ts
1929
+ class ResponseBuilder {
1930
+ static json(data, status = 200, headers) {
1931
+ const responseHeaders = new Headers(headers);
1932
+ responseHeaders.set("Content-Type", "application/json");
1933
+ return new Response(JSON.stringify(data), {
1934
+ status,
1935
+ headers: responseHeaders
1936
+ });
1937
+ }
1938
+ static text(text, status = 200, headers) {
1939
+ const responseHeaders = new Headers(headers);
1940
+ responseHeaders.set("Content-Type", "text/plain");
1941
+ return new Response(text, {
1942
+ status,
1943
+ headers: responseHeaders
1944
+ });
1945
+ }
1946
+ static html(html, status = 200, headers) {
1947
+ const responseHeaders = new Headers(headers);
1948
+ responseHeaders.set("Content-Type", "text/html");
1949
+ return new Response(html, {
1950
+ status,
1951
+ headers: responseHeaders
1952
+ });
1953
+ }
1954
+ static empty(status = 204, headers) {
1955
+ const responseHeaders = headers ? new Headers(headers) : undefined;
1956
+ return new Response(null, {
1957
+ status,
1958
+ headers: responseHeaders
1959
+ });
1960
+ }
1961
+ static redirect(url, status = 302) {
1962
+ return new Response(null, {
1963
+ status,
1964
+ headers: {
1965
+ Location: url
1966
+ }
1967
+ });
1968
+ }
1969
+ static error(message, status = 500) {
1970
+ return this.json({ error: message }, status);
1971
+ }
1972
+ static file(source, options = {}) {
1973
+ const headers = new Headers(options.headers);
1974
+ if (options.fileName) {
1975
+ headers.set("Content-Disposition", `attachment; filename="${options.fileName}"`);
1976
+ }
1977
+ if (options.contentType) {
1978
+ headers.set("Content-Type", options.contentType);
1979
+ }
1980
+ if (typeof source === "string") {
1981
+ const file = Bun.file(source);
1982
+ if (!headers.has("Content-Type") && file.type) {
1983
+ headers.set("Content-Type", file.type);
1984
+ }
1985
+ return new Response(file, {
1986
+ status: options.status ?? 200,
1987
+ headers
1988
+ });
1989
+ }
1990
+ return new Response(source, {
1991
+ status: options.status ?? 200,
1992
+ headers
1993
+ });
1994
+ }
1995
+ }
1996
+ // src/extensions/index.ts
1997
+ import { LoggerManager as LoggerManager7, LogLevel as LogLevel2, SimpleLogger as SimpleLogger2 } from "@dangao/logsmith";
1998
+ // src/testing/harness.ts
1999
+ import { performance as performance2 } from "perf_hooks";
2000
+
2001
+ class PerformanceHarness {
2002
+ static async benchmark(name, iterations, runner) {
2003
+ if (iterations <= 0) {
2004
+ throw new Error("iterations must be greater than 0");
2005
+ }
2006
+ const start = performance2.now();
2007
+ for (let i = 0;i < iterations; i++) {
2008
+ await runner(i);
2009
+ }
2010
+ const durationMs = performance2.now() - start;
2011
+ const opsPerSecond = iterations / Math.max(durationMs / 1000, 0.0001);
2012
+ return {
2013
+ name,
2014
+ iterations,
2015
+ durationMs,
2016
+ opsPerSecond
2017
+ };
2018
+ }
2019
+ }
2020
+
2021
+ class StressTester {
2022
+ static async run(name, iterations, concurrency, task) {
2023
+ if (iterations <= 0) {
2024
+ throw new Error("iterations must be greater than 0");
2025
+ }
2026
+ if (concurrency <= 0) {
2027
+ throw new Error("concurrency must be greater than 0");
2028
+ }
2029
+ let next = 0;
2030
+ let errors = 0;
2031
+ const start = performance2.now();
2032
+ const worker = async () => {
2033
+ while (true) {
2034
+ const current = next;
2035
+ next += 1;
2036
+ if (current >= iterations) {
2037
+ break;
2038
+ }
2039
+ try {
2040
+ await task(current);
2041
+ } catch (error) {
2042
+ errors += 1;
2043
+ }
2044
+ }
2045
+ };
2046
+ const workers = Array.from({ length: Math.min(concurrency, iterations) }, () => worker());
2047
+ await Promise.all(workers);
2048
+ const durationMs = performance2.now() - start;
2049
+ return {
2050
+ name,
2051
+ iterations,
2052
+ concurrency: Math.min(concurrency, iterations),
2053
+ durationMs,
2054
+ errors
2055
+ };
2056
+ }
2057
+ }
2058
+ export {
2059
+ createStaticFileMiddleware,
2060
+ createRequestLoggingMiddleware,
2061
+ createLoggerMiddleware,
2062
+ createFileUploadMiddleware,
2063
+ createErrorHandlingMiddleware,
2064
+ createCorsMiddleware,
2065
+ WebSocketGatewayRegistry,
2066
+ WebSocketGateway,
2067
+ ValidationError,
2068
+ Validate,
2069
+ UseMiddleware,
2070
+ UnauthorizedException,
2071
+ StressTester,
2072
+ Router,
2073
+ RouteRegistry,
2074
+ Route,
2075
+ ResponseBuilder,
2076
+ RequestWrapper,
2077
+ Query,
2078
+ PerformanceHarness,
2079
+ ParamBinder,
2080
+ Param,
2081
+ PUT,
2082
+ POST,
2083
+ PATCH,
2084
+ OnOpen,
2085
+ OnMessage,
2086
+ OnClose,
2087
+ NotFoundException,
2088
+ ModuleRegistry,
2089
+ Module,
2090
+ MinLength,
2091
+ MiddlewarePipeline,
2092
+ LoggerExtension,
2093
+ LogLevel2 as LogLevel,
2094
+ Lifecycle,
2095
+ LOGGER_TOKEN,
2096
+ IsString,
2097
+ IsOptional,
2098
+ IsNumber,
2099
+ IsEmail,
2100
+ InternalServerErrorException,
2101
+ Injectable,
2102
+ Inject,
2103
+ HttpException,
2104
+ Header,
2105
+ GET,
2106
+ ForbiddenException,
2107
+ ExceptionFilterRegistry,
2108
+ DELETE,
2109
+ ControllerRegistry,
2110
+ Controller,
2111
+ Context,
2112
+ Container,
2113
+ BunServer,
2114
+ BodyParser,
2115
+ Body,
2116
+ BadRequestException,
2117
+ Application
2118
+ };