@dangao/bun-server 0.1.3 → 0.1.4

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 (68) hide show
  1. package/dist/auth/controller.d.ts +35 -0
  2. package/dist/auth/controller.d.ts.map +1 -0
  3. package/dist/auth/decorators.d.ts +38 -0
  4. package/dist/auth/decorators.d.ts.map +1 -0
  5. package/dist/auth/index.d.ts +6 -0
  6. package/dist/auth/index.d.ts.map +1 -0
  7. package/dist/auth/jwt.d.ts +43 -0
  8. package/dist/auth/jwt.d.ts.map +1 -0
  9. package/dist/auth/oauth2.d.ts +45 -0
  10. package/dist/auth/oauth2.d.ts.map +1 -0
  11. package/dist/auth/types.d.ts +238 -0
  12. package/dist/auth/types.d.ts.map +1 -0
  13. package/dist/controller/controller.d.ts +5 -0
  14. package/dist/controller/controller.d.ts.map +1 -1
  15. package/dist/core/application.d.ts.map +1 -1
  16. package/dist/core/context.d.ts.map +1 -1
  17. package/dist/di/module-registry.d.ts +14 -2
  18. package/dist/di/module-registry.d.ts.map +1 -1
  19. package/dist/di/module.d.ts +12 -1
  20. package/dist/di/module.d.ts.map +1 -1
  21. package/dist/extensions/index.d.ts +1 -0
  22. package/dist/extensions/index.d.ts.map +1 -1
  23. package/dist/extensions/logger-module.d.ts +30 -0
  24. package/dist/extensions/logger-module.d.ts.map +1 -0
  25. package/dist/index.d.ts +4 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1154 -12
  28. package/dist/router/registry.d.ts +4 -1
  29. package/dist/router/registry.d.ts.map +1 -1
  30. package/dist/router/route.d.ts +9 -1
  31. package/dist/router/route.d.ts.map +1 -1
  32. package/dist/router/router.d.ts +8 -1
  33. package/dist/router/router.d.ts.map +1 -1
  34. package/dist/security/access-decision-manager.d.ts +14 -0
  35. package/dist/security/access-decision-manager.d.ts.map +1 -0
  36. package/dist/security/authentication-manager.d.ts +22 -0
  37. package/dist/security/authentication-manager.d.ts.map +1 -0
  38. package/dist/security/context.d.ts +46 -0
  39. package/dist/security/context.d.ts.map +1 -0
  40. package/dist/security/filter.d.ts +27 -0
  41. package/dist/security/filter.d.ts.map +1 -0
  42. package/dist/security/index.d.ts +8 -0
  43. package/dist/security/index.d.ts.map +1 -0
  44. package/dist/security/providers/index.d.ts +3 -0
  45. package/dist/security/providers/index.d.ts.map +1 -0
  46. package/dist/security/providers/jwt-provider.d.ts +19 -0
  47. package/dist/security/providers/jwt-provider.d.ts.map +1 -0
  48. package/dist/security/providers/oauth2-provider.d.ts +19 -0
  49. package/dist/security/providers/oauth2-provider.d.ts.map +1 -0
  50. package/dist/security/security-module.d.ts +50 -0
  51. package/dist/security/security-module.d.ts.map +1 -0
  52. package/dist/security/types.d.ts +152 -0
  53. package/dist/security/types.d.ts.map +1 -0
  54. package/dist/swagger/decorators.d.ts +56 -0
  55. package/dist/swagger/decorators.d.ts.map +1 -0
  56. package/dist/swagger/generator.d.ts +17 -0
  57. package/dist/swagger/generator.d.ts.map +1 -0
  58. package/dist/swagger/index.d.ts +7 -0
  59. package/dist/swagger/index.d.ts.map +1 -0
  60. package/dist/swagger/swagger-extension.d.ts +25 -0
  61. package/dist/swagger/swagger-extension.d.ts.map +1 -0
  62. package/dist/swagger/swagger-module.d.ts +37 -0
  63. package/dist/swagger/swagger-module.d.ts.map +1 -0
  64. package/dist/swagger/types.d.ts +176 -0
  65. package/dist/swagger/types.d.ts.map +1 -0
  66. package/dist/swagger/ui.d.ts +13 -0
  67. package/dist/swagger/ui.d.ts.map +1 -0
  68. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,20 @@
1
1
  // @bun
2
+ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
5
+ r = Reflect.decorate(decorators, target, key, desc);
6
+ else
7
+ for (var i = decorators.length - 1;i >= 0; i--)
8
+ if (d = decorators[i])
9
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ var __legacyDecorateParamTS = (index, decorator) => (target, key) => decorator(target, key, index);
13
+ var __legacyMetadataTS = (k, v) => {
14
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
15
+ return Reflect.metadata(k, v);
16
+ };
17
+
2
18
  // src/request/body-parser.ts
3
19
  class BodyParser {
4
20
  static async parse(request) {
@@ -141,9 +157,12 @@ class Context {
141
157
  this.statusCode = code;
142
158
  }
143
159
  createResponse(body, init) {
160
+ if (body instanceof Response) {
161
+ return body;
162
+ }
144
163
  const headers = new Headers(this.responseHeaders);
145
164
  if (body !== undefined && body !== null) {
146
- if (typeof body === "object" && !(body instanceof Response) && !(body instanceof ArrayBuffer)) {
165
+ if (typeof body === "object" && !(body instanceof ArrayBuffer) && !(body instanceof Blob)) {
147
166
  headers.set("Content-Type", "application/json");
148
167
  const jsonString = JSON.stringify(body);
149
168
  return new Response(jsonString, {
@@ -271,15 +290,19 @@ class Route {
271
290
  method;
272
291
  path;
273
292
  handler;
293
+ controllerClass;
294
+ methodName;
274
295
  pattern;
275
296
  paramNames;
276
297
  middlewarePipeline;
277
298
  staticKey;
278
299
  isStatic;
279
- constructor(method, path, handler, middlewares = []) {
300
+ constructor(method, path, handler, middlewares = [], controllerClass, methodName) {
280
301
  this.method = method;
281
302
  this.path = path;
282
303
  this.handler = handler;
304
+ this.controllerClass = controllerClass;
305
+ this.methodName = methodName;
283
306
  const { pattern, paramNames } = this.parsePath(path);
284
307
  this.pattern = pattern;
285
308
  this.paramNames = paramNames;
@@ -328,8 +351,15 @@ class Router {
328
351
  routes = [];
329
352
  staticRoutes = new Map;
330
353
  dynamicRoutes = [];
331
- register(method, path, handler, middlewares = []) {
332
- const route = new Route(method, path, handler, middlewares);
354
+ normalizePath(path) {
355
+ if (path.length > 1 && path.endsWith("/")) {
356
+ return path.slice(0, -1);
357
+ }
358
+ return path;
359
+ }
360
+ register(method, path, handler, middlewares = [], controllerClass, methodName) {
361
+ const normalizedPath = this.normalizePath(path);
362
+ const route = new Route(method, normalizedPath, handler, middlewares, controllerClass, methodName);
333
363
  this.routes.push(route);
334
364
  const staticKey = route.getStaticKey();
335
365
  if (staticKey) {
@@ -368,14 +398,21 @@ class Router {
368
398
  }
369
399
  async handle(context) {
370
400
  const method = context.method;
371
- const route = this.findRoute(method, context.path);
401
+ const path = this.normalizePath(context.path);
402
+ const route = this.findRoute(method, path);
372
403
  if (!route) {
373
404
  return;
374
405
  }
375
- const match = route.match(method, context.path);
406
+ const match = route.match(method, path);
376
407
  if (match.matched) {
377
408
  context.params = match.params;
378
409
  }
410
+ if (route.controllerClass && route.methodName) {
411
+ context.routeHandler = {
412
+ controller: route.controllerClass,
413
+ method: route.methodName
414
+ };
415
+ }
379
416
  return await route.execute(context);
380
417
  }
381
418
  getRoutes() {
@@ -401,8 +438,8 @@ class RouteRegistry {
401
438
  }
402
439
  return RouteRegistry.instance;
403
440
  }
404
- register(method, path, handler, middlewares = []) {
405
- this.router.register(method, path, handler, middlewares);
441
+ register(method, path, handler, middlewares = [], controllerClass, methodName) {
442
+ this.router.register(method, path, handler, middlewares, controllerClass, methodName);
406
443
  }
407
444
  get(path, handler, middlewares = []) {
408
445
  this.router.get(path, handler, middlewares);
@@ -1487,6 +1524,9 @@ class ControllerRegistry {
1487
1524
  }
1488
1525
  const result = method.apply(controllerInstance, params);
1489
1526
  const responseData = await Promise.resolve(result);
1527
+ if (responseData instanceof Response) {
1528
+ return responseData;
1529
+ }
1490
1530
  return context.createResponse(responseData);
1491
1531
  } catch (error) {
1492
1532
  if (error instanceof ValidationError) {
@@ -1512,7 +1552,7 @@ class ControllerRegistry {
1512
1552
  if (propertyKey) {
1513
1553
  middlewares.push(...getMethodMiddlewares(prototype, propertyKey));
1514
1554
  }
1515
- registry.register(route.method, fullPath, handler, middlewares);
1555
+ registry.register(route.method, fullPath, handler, middlewares, controllerClass, propertyKey);
1516
1556
  }
1517
1557
  }
1518
1558
  combinePaths(basePath, methodPath) {
@@ -1526,6 +1566,9 @@ class ControllerRegistry {
1526
1566
  getContainer() {
1527
1567
  return this.container;
1528
1568
  }
1569
+ getRegisteredControllers() {
1570
+ return Array.from(this.controllerContainers.keys());
1571
+ }
1529
1572
  clear() {
1530
1573
  this.controllers.clear();
1531
1574
  this.container.clear();
@@ -1685,7 +1728,9 @@ function getModuleMetadata(moduleClass) {
1685
1728
  imports: metadata.imports ?? [],
1686
1729
  controllers: metadata.controllers ?? [],
1687
1730
  providers: metadata.providers ?? [],
1688
- exports: metadata.exports ?? []
1731
+ exports: metadata.exports ?? [],
1732
+ extensions: metadata.extensions ?? [],
1733
+ middlewares: metadata.middlewares ?? []
1689
1734
  };
1690
1735
  }
1691
1736
 
@@ -1744,7 +1789,9 @@ class ModuleRegistry {
1744
1789
  metadata,
1745
1790
  container,
1746
1791
  controllersRegistered: false,
1747
- attachedParents: new Set
1792
+ attachedParents: new Set,
1793
+ extensions: metadata.extensions ?? [],
1794
+ middlewares: metadata.middlewares ?? []
1748
1795
  };
1749
1796
  this.registerControllers(ref);
1750
1797
  this.moduleRefs.set(moduleClass, ref);
@@ -1796,6 +1843,27 @@ class ModuleRegistry {
1796
1843
  for (const exportedToken of moduleRef.metadata.exports) {
1797
1844
  this.registerExport(parentContainer, moduleRef, exportedToken);
1798
1845
  }
1846
+ for (const imported of moduleRef.metadata.imports) {
1847
+ const importedRef = this.moduleRefs.get(imported);
1848
+ if (importedRef) {
1849
+ moduleRef.extensions.push(...importedRef.extensions);
1850
+ moduleRef.middlewares.push(...importedRef.middlewares);
1851
+ }
1852
+ }
1853
+ }
1854
+ getModuleExtensions(moduleClass) {
1855
+ const moduleRef = this.moduleRefs.get(moduleClass);
1856
+ if (!moduleRef) {
1857
+ return [];
1858
+ }
1859
+ return moduleRef.extensions;
1860
+ }
1861
+ getModuleMiddlewares(moduleClass) {
1862
+ const moduleRef = this.moduleRefs.get(moduleClass);
1863
+ if (!moduleRef) {
1864
+ return [];
1865
+ }
1866
+ return moduleRef.middlewares;
1799
1867
  }
1800
1868
  registerExport(parentContainer, moduleRef, token) {
1801
1869
  if (!moduleRef.container.isRegistered(token)) {
@@ -1868,6 +1936,14 @@ class Application {
1868
1936
  registerModule(moduleClass) {
1869
1937
  const registry = ModuleRegistry.getInstance();
1870
1938
  registry.register(moduleClass, this.getContainer());
1939
+ const extensions = registry.getModuleExtensions(moduleClass);
1940
+ for (const extension of extensions) {
1941
+ this.registerExtension(extension);
1942
+ }
1943
+ const middlewares = registry.getModuleMiddlewares(moduleClass);
1944
+ for (const middleware of middlewares) {
1945
+ this.use(middleware);
1946
+ }
1871
1947
  }
1872
1948
  registerWebSocketGateway(gatewayClass) {
1873
1949
  this.websocketRegistry.register(gatewayClass);
@@ -1993,8 +2069,1048 @@ class ResponseBuilder {
1993
2069
  });
1994
2070
  }
1995
2071
  }
2072
+ // src/extensions/logger-module.ts
2073
+ class LoggerModule {
2074
+ static forRoot(options = {}) {
2075
+ const extensions = [];
2076
+ const middlewares = [];
2077
+ const loggerExtension = new LoggerExtension(options.logger);
2078
+ extensions.push(loggerExtension);
2079
+ if (options.enableRequestLogging !== false) {
2080
+ const requestLoggingMiddleware = createLoggerMiddleware({
2081
+ prefix: options.requestLoggingPrefix
2082
+ });
2083
+ middlewares.push(requestLoggingMiddleware);
2084
+ }
2085
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, LoggerModule) || {};
2086
+ const metadata = {
2087
+ ...existingMetadata,
2088
+ extensions,
2089
+ middlewares
2090
+ };
2091
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, LoggerModule);
2092
+ return LoggerModule;
2093
+ }
2094
+ }
2095
+ LoggerModule = __legacyDecorateClassTS([
2096
+ Module({
2097
+ extensions: [],
2098
+ middlewares: []
2099
+ })
2100
+ ], LoggerModule);
2101
+
1996
2102
  // src/extensions/index.ts
1997
2103
  import { LoggerManager as LoggerManager7, LogLevel as LogLevel2, SimpleLogger as SimpleLogger2 } from "@dangao/logsmith";
2104
+ // src/swagger/decorators.ts
2105
+ import"reflect-metadata";
2106
+ var API_TAG_METADATA_KEY = Symbol("swagger:api-tag");
2107
+ var API_OPERATION_METADATA_KEY = Symbol("swagger:api-operation");
2108
+ var API_PARAM_METADATA_KEY = Symbol("swagger:api-param");
2109
+ var API_BODY_METADATA_KEY = Symbol("swagger:api-body");
2110
+ var API_RESPONSE_METADATA_KEY = Symbol("swagger:api-response");
2111
+ function ApiTags(...tags) {
2112
+ return function(target, propertyKey) {
2113
+ if (propertyKey === undefined) {
2114
+ Reflect.defineMetadata(API_TAG_METADATA_KEY, tags, target);
2115
+ } else {
2116
+ const existingTags = Reflect.getMetadata(API_TAG_METADATA_KEY, target, propertyKey) || [];
2117
+ Reflect.defineMetadata(API_TAG_METADATA_KEY, [...existingTags, ...tags], target, propertyKey);
2118
+ }
2119
+ };
2120
+ }
2121
+ function ApiOperation(metadata) {
2122
+ return function(target, propertyKey) {
2123
+ Reflect.defineMetadata(API_OPERATION_METADATA_KEY, metadata, target, propertyKey);
2124
+ };
2125
+ }
2126
+ function ApiParam(metadata) {
2127
+ return function(target, propertyKey, parameterIndex) {
2128
+ const existingParams = Reflect.getMetadata(API_PARAM_METADATA_KEY, target, propertyKey) || [];
2129
+ existingParams.push({ index: parameterIndex, metadata });
2130
+ Reflect.defineMetadata(API_PARAM_METADATA_KEY, existingParams, target, propertyKey);
2131
+ };
2132
+ }
2133
+ function ApiBody(metadata) {
2134
+ return function(target, propertyKey) {
2135
+ Reflect.defineMetadata(API_BODY_METADATA_KEY, metadata, target, propertyKey);
2136
+ };
2137
+ }
2138
+ function ApiResponse(metadata) {
2139
+ return function(target, propertyKey) {
2140
+ const existingResponses = Reflect.getMetadata(API_RESPONSE_METADATA_KEY, target, propertyKey) || [];
2141
+ existingResponses.push(metadata);
2142
+ Reflect.defineMetadata(API_RESPONSE_METADATA_KEY, existingResponses, target, propertyKey);
2143
+ };
2144
+ }
2145
+ function getApiTags(target, propertyKey) {
2146
+ if (propertyKey === undefined) {
2147
+ return Reflect.getMetadata(API_TAG_METADATA_KEY, target) || [];
2148
+ }
2149
+ return Reflect.getMetadata(API_TAG_METADATA_KEY, target, propertyKey) || [];
2150
+ }
2151
+ function getApiOperation(target, propertyKey) {
2152
+ return Reflect.getMetadata(API_OPERATION_METADATA_KEY, target, propertyKey);
2153
+ }
2154
+ function getApiParams(target, propertyKey) {
2155
+ return Reflect.getMetadata(API_PARAM_METADATA_KEY, target, propertyKey) || [];
2156
+ }
2157
+ function getApiBody(target, propertyKey) {
2158
+ return Reflect.getMetadata(API_BODY_METADATA_KEY, target, propertyKey);
2159
+ }
2160
+ function getApiResponses(target, propertyKey) {
2161
+ return Reflect.getMetadata(API_RESPONSE_METADATA_KEY, target, propertyKey) || [];
2162
+ }
2163
+ // src/swagger/generator.ts
2164
+ class SwaggerGenerator {
2165
+ options;
2166
+ constructor(options) {
2167
+ this.options = options;
2168
+ }
2169
+ generate() {
2170
+ const document = {
2171
+ openapi: "3.0.0",
2172
+ info: {
2173
+ title: this.options.info.title,
2174
+ version: this.options.info.version,
2175
+ description: this.options.info.description,
2176
+ contact: this.options.info.contact,
2177
+ license: this.options.info.license
2178
+ },
2179
+ servers: this.options.servers,
2180
+ tags: this.options.tags,
2181
+ paths: {}
2182
+ };
2183
+ const controllerRegistry = ControllerRegistry.getInstance();
2184
+ const controllers = controllerRegistry.getRegisteredControllers();
2185
+ if (controllers.length === 0) {
2186
+ return document;
2187
+ }
2188
+ for (const controllerClass of controllers) {
2189
+ const controllerMetadata = getControllerMetadata(controllerClass);
2190
+ if (!controllerMetadata) {
2191
+ console.log(`[SwaggerGenerator] No metadata for controller: ${controllerClass.name}`);
2192
+ continue;
2193
+ }
2194
+ const basePath = controllerMetadata.path;
2195
+ const prototype = controllerClass.prototype;
2196
+ const routes = getRouteMetadata(prototype);
2197
+ if (!routes || routes.length === 0) {
2198
+ continue;
2199
+ }
2200
+ const controllerTags = getApiTags(controllerClass);
2201
+ for (const route of routes) {
2202
+ let propertyKey = route.propertyKey;
2203
+ if (!propertyKey && route.handler) {
2204
+ propertyKey = route.handler.name;
2205
+ if (!propertyKey || propertyKey === "") {
2206
+ const propertyNames = Object.getOwnPropertyNames(prototype);
2207
+ for (const key of propertyNames) {
2208
+ if (key === "constructor")
2209
+ continue;
2210
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
2211
+ if (descriptor && descriptor.value === route.handler) {
2212
+ propertyKey = key;
2213
+ break;
2214
+ }
2215
+ }
2216
+ }
2217
+ }
2218
+ if (!propertyKey) {
2219
+ continue;
2220
+ }
2221
+ const method = route.method.toLowerCase();
2222
+ let methodPath = route.path;
2223
+ if (methodPath && !methodPath.startsWith("/")) {
2224
+ methodPath = "/" + methodPath;
2225
+ }
2226
+ const swaggerPath = (basePath + methodPath).replace(/:([^/]+)/g, "{$1}");
2227
+ const fullPath = this.normalizePath(swaggerPath);
2228
+ const operationMetadata = getApiOperation(prototype, propertyKey);
2229
+ const methodTags = getApiTags(prototype, propertyKey);
2230
+ const params = getApiParams(prototype, propertyKey);
2231
+ const body = getApiBody(prototype, propertyKey);
2232
+ const responses = getApiResponses(prototype, propertyKey);
2233
+ const tags = [...new Set([...controllerTags, ...methodTags])];
2234
+ const pathItem = {
2235
+ summary: operationMetadata?.summary,
2236
+ description: operationMetadata?.description,
2237
+ operationId: operationMetadata?.operationId || propertyKey,
2238
+ tags: tags.length > 0 ? tags : undefined,
2239
+ deprecated: operationMetadata?.deprecated
2240
+ };
2241
+ const pathParams = [];
2242
+ const pathParamMatches = fullPath.matchAll(/\{([^}]+)\}/g);
2243
+ for (const match of pathParamMatches) {
2244
+ const paramName = match[1];
2245
+ const existingParam = params.find((p) => p.metadata.name === paramName && p.metadata.in === "path");
2246
+ if (!existingParam) {
2247
+ pathParams.push({
2248
+ name: paramName,
2249
+ in: "path",
2250
+ required: true,
2251
+ schema: { type: "string" }
2252
+ });
2253
+ }
2254
+ }
2255
+ for (const param of params) {
2256
+ pathParams.push({
2257
+ name: param.metadata.name,
2258
+ in: param.metadata.in,
2259
+ description: param.metadata.description,
2260
+ required: param.metadata.required,
2261
+ schema: param.metadata.schema
2262
+ });
2263
+ }
2264
+ if (pathParams.length > 0) {
2265
+ pathItem.parameters = pathParams;
2266
+ }
2267
+ if (body) {
2268
+ pathItem.requestBody = {
2269
+ description: body.description,
2270
+ required: body.required,
2271
+ content: {
2272
+ "application/json": {
2273
+ schema: body.schema,
2274
+ examples: body.examples
2275
+ }
2276
+ }
2277
+ };
2278
+ }
2279
+ if (responses.length > 0) {
2280
+ pathItem.responses = {};
2281
+ for (const response of responses) {
2282
+ pathItem.responses[String(response.status)] = {
2283
+ description: response.description,
2284
+ content: {
2285
+ "application/json": {
2286
+ schema: response.schema,
2287
+ examples: response.examples
2288
+ }
2289
+ }
2290
+ };
2291
+ }
2292
+ } else {
2293
+ pathItem.responses = {
2294
+ "200": {
2295
+ description: "Success"
2296
+ }
2297
+ };
2298
+ }
2299
+ if (!document.paths[fullPath]) {
2300
+ document.paths[fullPath] = {};
2301
+ }
2302
+ document.paths[fullPath][method] = pathItem;
2303
+ }
2304
+ }
2305
+ return document;
2306
+ }
2307
+ normalizePath(path) {
2308
+ path = path.replace(/\/+/g, "/");
2309
+ if (!path.startsWith("/")) {
2310
+ path = "/" + path;
2311
+ }
2312
+ if (path.length > 1 && path.endsWith("/")) {
2313
+ path = path.slice(0, -1);
2314
+ }
2315
+ return path;
2316
+ }
2317
+ }
2318
+ // src/swagger/swagger-extension.ts
2319
+ class SwaggerExtension {
2320
+ options;
2321
+ generator;
2322
+ constructor(options) {
2323
+ this.options = options;
2324
+ }
2325
+ register(_container) {
2326
+ this.generator = new SwaggerGenerator(this.options);
2327
+ }
2328
+ getGenerator() {
2329
+ if (!this.generator) {
2330
+ this.generator = new SwaggerGenerator(this.options);
2331
+ }
2332
+ return this.generator;
2333
+ }
2334
+ generateJSON() {
2335
+ return JSON.stringify(this.getGenerator().generate(), null, 2);
2336
+ }
2337
+ }
2338
+ // src/swagger/ui.ts
2339
+ var SWAGGER_UI_HTML = (jsonUrl, title) => `<!DOCTYPE html>
2340
+ <html lang="en">
2341
+ <head>
2342
+ <meta charset="UTF-8">
2343
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
2344
+ <title>${title} - Swagger UI</title>
2345
+ <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css" />
2346
+ <style>
2347
+ html {
2348
+ box-sizing: border-box;
2349
+ overflow: -moz-scrollbars-vertical;
2350
+ overflow-y: scroll;
2351
+ }
2352
+ *, *:before, *:after {
2353
+ box-sizing: inherit;
2354
+ }
2355
+ body {
2356
+ margin:0;
2357
+ background: #fafafa;
2358
+ }
2359
+ </style>
2360
+ </head>
2361
+ <body>
2362
+ <div id="swagger-ui"></div>
2363
+ <script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-bundle.js"></script>
2364
+ <script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-standalone-preset.js"></script>
2365
+ <script>
2366
+ window.onload = function() {
2367
+ const ui = SwaggerUIBundle({
2368
+ url: "${jsonUrl}",
2369
+ dom_id: '#swagger-ui',
2370
+ deepLinking: true,
2371
+ presets: [
2372
+ SwaggerUIBundle.presets.apis,
2373
+ SwaggerUIStandalonePreset
2374
+ ],
2375
+ plugins: [
2376
+ SwaggerUIBundle.plugins.DownloadUrl
2377
+ ],
2378
+ layout: "StandaloneLayout"
2379
+ });
2380
+ };
2381
+ </script>
2382
+ </body>
2383
+ </html>`;
2384
+ function createSwaggerUIMiddleware(extension, options = {}) {
2385
+ const uiPath = options.uiPath || "/swagger";
2386
+ const jsonPath = options.jsonPath || "/swagger.json";
2387
+ const title = options.title || "API Documentation";
2388
+ return async (ctx, next) => {
2389
+ const url = new URL(ctx.request.url);
2390
+ const pathname = url.pathname;
2391
+ if (pathname === uiPath || pathname === `${uiPath}/`) {
2392
+ const html = SWAGGER_UI_HTML(jsonPath, title);
2393
+ return new Response(html, {
2394
+ headers: {
2395
+ "Content-Type": "text/html; charset=utf-8"
2396
+ }
2397
+ });
2398
+ }
2399
+ if (pathname === jsonPath) {
2400
+ const json = extension.generateJSON();
2401
+ return new Response(json, {
2402
+ headers: {
2403
+ "Content-Type": "application/json; charset=utf-8"
2404
+ }
2405
+ });
2406
+ }
2407
+ return await next();
2408
+ };
2409
+ }
2410
+
2411
+ // src/swagger/swagger-module.ts
2412
+ class SwaggerModule {
2413
+ static forRoot(options) {
2414
+ const extensions = [];
2415
+ const middlewares = [];
2416
+ const swaggerExtension = new SwaggerExtension({
2417
+ info: options.info,
2418
+ servers: options.servers,
2419
+ basePath: options.basePath,
2420
+ tags: options.tags
2421
+ });
2422
+ extensions.push(swaggerExtension);
2423
+ if (options.enableUI !== false) {
2424
+ const uiMiddleware = createSwaggerUIMiddleware(swaggerExtension, {
2425
+ uiPath: options.uiPath || "/swagger",
2426
+ jsonPath: options.jsonPath || "/swagger.json",
2427
+ title: options.uiTitle || options.info.title || "API Documentation"
2428
+ });
2429
+ middlewares.push(uiMiddleware);
2430
+ }
2431
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, SwaggerModule) || {};
2432
+ const metadata = {
2433
+ ...existingMetadata,
2434
+ extensions,
2435
+ middlewares
2436
+ };
2437
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SwaggerModule);
2438
+ return SwaggerModule;
2439
+ }
2440
+ }
2441
+ SwaggerModule = __legacyDecorateClassTS([
2442
+ Module({
2443
+ extensions: [],
2444
+ middlewares: []
2445
+ })
2446
+ ], SwaggerModule);
2447
+ // src/security/context.ts
2448
+ class SecurityContextImpl {
2449
+ _authentication = null;
2450
+ get authentication() {
2451
+ return this._authentication;
2452
+ }
2453
+ setAuthentication(authentication) {
2454
+ this._authentication = authentication;
2455
+ }
2456
+ isAuthenticated() {
2457
+ return this._authentication?.authenticated ?? false;
2458
+ }
2459
+ getPrincipal() {
2460
+ return this._authentication?.principal ?? null;
2461
+ }
2462
+ getAuthorities() {
2463
+ return this._authentication?.authorities ?? [];
2464
+ }
2465
+ clear() {
2466
+ this._authentication = null;
2467
+ }
2468
+ }
2469
+
2470
+ class SecurityContextHolder {
2471
+ static contexts = new Map;
2472
+ static getContext() {
2473
+ const threadId = Bun.main ? 0 : Date.now();
2474
+ if (!this.contexts.has(threadId)) {
2475
+ this.contexts.set(threadId, new SecurityContextImpl);
2476
+ }
2477
+ return this.contexts.get(threadId);
2478
+ }
2479
+ static clearContext() {
2480
+ const threadId = Bun.main ? 0 : Date.now();
2481
+ this.contexts.delete(threadId);
2482
+ }
2483
+ }
2484
+ // src/security/authentication-manager.ts
2485
+ class AuthenticationManager {
2486
+ providers = [];
2487
+ registerProvider(provider) {
2488
+ this.providers.push(provider);
2489
+ }
2490
+ async authenticate(request) {
2491
+ const type = request.type || "default";
2492
+ const provider = this.providers.find((p) => p.supports(type));
2493
+ if (!provider) {
2494
+ throw new Error(`No authentication provider found for type: ${type}`);
2495
+ }
2496
+ return await provider.authenticate(request);
2497
+ }
2498
+ getProviders() {
2499
+ return [...this.providers];
2500
+ }
2501
+ }
2502
+ // src/security/access-decision-manager.ts
2503
+ class RoleBasedAccessDecisionManager {
2504
+ decide(authentication, requiredAuthorities) {
2505
+ if (requiredAuthorities.length === 0) {
2506
+ return true;
2507
+ }
2508
+ if (!authentication.authenticated) {
2509
+ return false;
2510
+ }
2511
+ const userAuthorities = authentication.authorities || [];
2512
+ return requiredAuthorities.some((required) => userAuthorities.includes(required));
2513
+ }
2514
+ }
2515
+ // src/auth/decorators.ts
2516
+ import"reflect-metadata";
2517
+ var AUTH_METADATA_KEY = Symbol("@dangao/bun-server:auth");
2518
+ function Auth(config = {}) {
2519
+ return (target, propertyKey) => {
2520
+ const metadata = Reflect.getMetadata(AUTH_METADATA_KEY, target) || {};
2521
+ metadata[propertyKey] = {
2522
+ required: config.required !== false,
2523
+ roles: config.roles || [],
2524
+ allowAnonymous: config.allowAnonymous || false
2525
+ };
2526
+ Reflect.defineMetadata(AUTH_METADATA_KEY, metadata, target);
2527
+ };
2528
+ }
2529
+ function getAuthMetadata(target, propertyKey) {
2530
+ const metadata = Reflect.getMetadata(AUTH_METADATA_KEY, target);
2531
+ return metadata?.[propertyKey];
2532
+ }
2533
+ function requiresAuth(target, propertyKey) {
2534
+ const config = getAuthMetadata(target, propertyKey);
2535
+ return config?.required !== false;
2536
+ }
2537
+ function checkRoles(target, propertyKey, userRoles = []) {
2538
+ const config = getAuthMetadata(target, propertyKey);
2539
+ if (!config?.roles || config.roles.length === 0) {
2540
+ return true;
2541
+ }
2542
+ return config.roles.some((role) => userRoles.includes(role));
2543
+ }
2544
+
2545
+ // src/security/filter.ts
2546
+ function createSecurityFilter(config) {
2547
+ const {
2548
+ authenticationManager,
2549
+ accessDecisionManager = new RoleBasedAccessDecisionManager,
2550
+ excludePaths = [],
2551
+ defaultAuthRequired = true,
2552
+ extractToken
2553
+ } = config;
2554
+ return async (ctx, next) => {
2555
+ const path = ctx.request.url.split("?")[0];
2556
+ if (excludePaths.some((exclude) => path.startsWith(exclude))) {
2557
+ return await next();
2558
+ }
2559
+ const securityContext = SecurityContextHolder.getContext();
2560
+ try {
2561
+ const token = extractToken ? extractToken(ctx) : extractTokenFromHeader(ctx);
2562
+ if (token) {
2563
+ const request = {
2564
+ principal: "",
2565
+ credentials: token,
2566
+ type: "jwt"
2567
+ };
2568
+ const authentication = await authenticationManager.authenticate(request);
2569
+ if (authentication) {
2570
+ securityContext.setAuthentication(authentication);
2571
+ }
2572
+ }
2573
+ const handler = ctx.routeHandler;
2574
+ if (handler) {
2575
+ const controller = handler.controller;
2576
+ const method = handler.method;
2577
+ if (requiresAuth(controller, method)) {
2578
+ const authentication = securityContext.authentication;
2579
+ if (!authentication || !authentication.authenticated) {
2580
+ throw new UnauthorizedException("Authentication required");
2581
+ }
2582
+ const requiredRoles = getRequiredRoles(controller, method);
2583
+ if (requiredRoles.length > 0) {
2584
+ const hasAccess = accessDecisionManager.decide(authentication, requiredRoles);
2585
+ if (!hasAccess) {
2586
+ const userRoles = authentication.authorities || [];
2587
+ throw new ForbiddenException(`Insufficient permissions. Required roles: ${requiredRoles.join(", ")}, User roles: ${userRoles.join(", ")}`);
2588
+ }
2589
+ }
2590
+ }
2591
+ } else if (defaultAuthRequired && !securityContext.isAuthenticated()) {
2592
+ throw new UnauthorizedException("Authentication required");
2593
+ }
2594
+ ctx.security = securityContext;
2595
+ ctx.auth = {
2596
+ isAuthenticated: securityContext.isAuthenticated(),
2597
+ user: securityContext.getPrincipal(),
2598
+ payload: securityContext.authentication?.details
2599
+ };
2600
+ return await next();
2601
+ } finally {}
2602
+ };
2603
+ }
2604
+ function extractTokenFromHeader(ctx) {
2605
+ const authHeader = ctx.getHeader("authorization");
2606
+ if (!authHeader) {
2607
+ return null;
2608
+ }
2609
+ const parts = authHeader.split(" ");
2610
+ if (parts.length !== 2 || parts[0] !== "Bearer") {
2611
+ return null;
2612
+ }
2613
+ return parts[1];
2614
+ }
2615
+ function getRequiredRoles(target, propertyKey) {
2616
+ const metadata = getAuthMetadata(target, propertyKey);
2617
+ return metadata?.roles || [];
2618
+ }
2619
+ // src/security/providers/jwt-provider.ts
2620
+ class JwtAuthenticationProvider {
2621
+ jwtUtil;
2622
+ supportedTypes = ["jwt", "bearer"];
2623
+ constructor(jwtUtil) {
2624
+ this.jwtUtil = jwtUtil;
2625
+ }
2626
+ supports(type) {
2627
+ return this.supportedTypes.includes(type.toLowerCase());
2628
+ }
2629
+ async authenticate(request) {
2630
+ const token = request.credentials;
2631
+ if (!token) {
2632
+ return null;
2633
+ }
2634
+ const payload = this.jwtUtil.verify(token);
2635
+ if (!payload) {
2636
+ return null;
2637
+ }
2638
+ const principal = {
2639
+ id: payload.sub,
2640
+ username: payload.username || payload.sub,
2641
+ roles: payload.roles || []
2642
+ };
2643
+ const authorities = principal.roles || [];
2644
+ return {
2645
+ authenticated: true,
2646
+ principal,
2647
+ credentials: { type: "jwt", data: token },
2648
+ authorities,
2649
+ details: payload
2650
+ };
2651
+ }
2652
+ }
2653
+ // src/security/providers/oauth2-provider.ts
2654
+ class OAuth2AuthenticationProvider {
2655
+ oauth2Service;
2656
+ supportedTypes = ["oauth2", "authorization_code"];
2657
+ constructor(oauth2Service) {
2658
+ this.oauth2Service = oauth2Service;
2659
+ }
2660
+ supports(type) {
2661
+ return this.supportedTypes.includes(type.toLowerCase());
2662
+ }
2663
+ async authenticate(request) {
2664
+ const credentials = request.credentials;
2665
+ if (!credentials || credentials.grantType !== "authorization_code") {
2666
+ return null;
2667
+ }
2668
+ const tokenResponse = await this.oauth2Service.exchangeCodeForToken(credentials);
2669
+ if (!tokenResponse) {
2670
+ return null;
2671
+ }
2672
+ const userInfo = {
2673
+ id: "user-1",
2674
+ username: "user",
2675
+ roles: ["user"]
2676
+ };
2677
+ const principal = {
2678
+ id: userInfo.id,
2679
+ username: userInfo.username,
2680
+ roles: userInfo.roles
2681
+ };
2682
+ return {
2683
+ authenticated: true,
2684
+ principal,
2685
+ credentials: {
2686
+ type: "oauth2",
2687
+ data: tokenResponse
2688
+ },
2689
+ authorities: principal.roles || [],
2690
+ details: tokenResponse
2691
+ };
2692
+ }
2693
+ }
2694
+ // src/auth/jwt.ts
2695
+ class JWTUtil {
2696
+ config;
2697
+ constructor(config) {
2698
+ this.config = {
2699
+ secret: config.secret,
2700
+ accessTokenExpiresIn: config.accessTokenExpiresIn ?? 3600,
2701
+ refreshTokenExpiresIn: config.refreshTokenExpiresIn ?? 86400 * 7,
2702
+ algorithm: config.algorithm ?? "HS256"
2703
+ };
2704
+ }
2705
+ generateAccessToken(payload) {
2706
+ const now = Math.floor(Date.now() / 1000);
2707
+ const tokenPayload = {
2708
+ ...payload,
2709
+ sub: payload.sub,
2710
+ iat: now,
2711
+ exp: now + this.config.accessTokenExpiresIn
2712
+ };
2713
+ return this.sign(tokenPayload);
2714
+ }
2715
+ generateRefreshToken(payload) {
2716
+ const now = Math.floor(Date.now() / 1000);
2717
+ const tokenPayload = {
2718
+ ...payload,
2719
+ sub: payload.sub,
2720
+ iat: now,
2721
+ exp: now + this.config.refreshTokenExpiresIn
2722
+ };
2723
+ return this.sign(tokenPayload);
2724
+ }
2725
+ verify(token) {
2726
+ try {
2727
+ const parts = token.split(".");
2728
+ if (parts.length !== 3) {
2729
+ return null;
2730
+ }
2731
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
2732
+ const signature = this.signature(parts[0] + "." + parts[1]);
2733
+ if (signature !== parts[2]) {
2734
+ return null;
2735
+ }
2736
+ if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) {
2737
+ return null;
2738
+ }
2739
+ return payload;
2740
+ } catch {
2741
+ return null;
2742
+ }
2743
+ }
2744
+ sign(payload) {
2745
+ const header = {
2746
+ alg: this.config.algorithm,
2747
+ typ: "JWT"
2748
+ };
2749
+ const encodedHeader = this.base64UrlEncode(JSON.stringify(header));
2750
+ const encodedPayload = this.base64UrlEncode(JSON.stringify(payload));
2751
+ const signature = this.signature(encodedHeader + "." + encodedPayload);
2752
+ return `${encodedHeader}.${encodedPayload}.${signature}`;
2753
+ }
2754
+ signature(data) {
2755
+ const encoder = new TextEncoder;
2756
+ const keyData = encoder.encode(this.config.secret);
2757
+ const messageData = encoder.encode(data);
2758
+ const hash = this.hmacSha256(keyData, messageData);
2759
+ return this.base64UrlEncode(Buffer.from(hash).toString("base64"));
2760
+ }
2761
+ hmacSha256(key, data) {
2762
+ const blockSize = 64;
2763
+ let keyBuffer;
2764
+ if (key.length > blockSize) {
2765
+ const hasher = new Bun.CryptoHasher("sha256");
2766
+ hasher.update(key);
2767
+ keyBuffer = new Uint8Array(hasher.digest());
2768
+ } else {
2769
+ keyBuffer = new Uint8Array(blockSize);
2770
+ keyBuffer.set(key);
2771
+ }
2772
+ const oKeyPad = new Uint8Array(blockSize);
2773
+ const iKeyPad = new Uint8Array(blockSize);
2774
+ for (let i = 0;i < blockSize; i++) {
2775
+ oKeyPad[i] = keyBuffer[i] ^ 92;
2776
+ iKeyPad[i] = keyBuffer[i] ^ 54;
2777
+ }
2778
+ const innerData = new Uint8Array(iKeyPad.length + data.length);
2779
+ innerData.set(iKeyPad);
2780
+ innerData.set(data, iKeyPad.length);
2781
+ const innerHasher = new Bun.CryptoHasher("sha256");
2782
+ innerHasher.update(innerData);
2783
+ const innerHash = new Uint8Array(innerHasher.digest());
2784
+ const outerData = new Uint8Array(oKeyPad.length + innerHash.length);
2785
+ outerData.set(oKeyPad);
2786
+ outerData.set(innerHash, oKeyPad.length);
2787
+ const outerHasher = new Bun.CryptoHasher("sha256");
2788
+ outerHasher.update(outerData);
2789
+ return new Uint8Array(outerHasher.digest());
2790
+ }
2791
+ base64UrlEncode(str) {
2792
+ return Buffer.from(str).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
2793
+ }
2794
+ }
2795
+
2796
+ // src/auth/oauth2.ts
2797
+ class OAuth2Service {
2798
+ jwtUtil;
2799
+ clients;
2800
+ codes;
2801
+ codeConfig;
2802
+ userProvider;
2803
+ constructor(jwtUtil, clients = [], codeConfig = {}, userProvider) {
2804
+ this.jwtUtil = jwtUtil;
2805
+ this.clients = new Map;
2806
+ this.codes = new Map;
2807
+ this.codeConfig = {
2808
+ expiresIn: codeConfig.expiresIn ?? 600,
2809
+ length: codeConfig.length ?? 32
2810
+ };
2811
+ for (const client of clients) {
2812
+ this.clients.set(client.clientId, client);
2813
+ }
2814
+ this.userProvider = userProvider;
2815
+ setInterval(() => this.cleanupExpiredCodes(), 60000);
2816
+ }
2817
+ registerClient(client) {
2818
+ this.clients.set(client.clientId, client);
2819
+ }
2820
+ validateAuthorizationRequest(request) {
2821
+ const client = this.clients.get(request.clientId);
2822
+ if (!client) {
2823
+ return { valid: false, error: "invalid_client" };
2824
+ }
2825
+ if (request.responseType !== "code") {
2826
+ return { valid: false, error: "unsupported_response_type" };
2827
+ }
2828
+ if (!client.redirectUris.includes(request.redirectUri)) {
2829
+ return { valid: false, error: "invalid_redirect_uri" };
2830
+ }
2831
+ return { valid: true };
2832
+ }
2833
+ generateAuthorizationCode(clientId, redirectUri, userId, scope) {
2834
+ const code = this.generateRandomString(this.codeConfig.length);
2835
+ const expiresAt = Date.now() + this.codeConfig.expiresIn * 1000;
2836
+ this.codes.set(code, {
2837
+ code,
2838
+ clientId,
2839
+ redirectUri,
2840
+ userId,
2841
+ scope,
2842
+ expiresAt
2843
+ });
2844
+ return code;
2845
+ }
2846
+ async exchangeCodeForToken(request) {
2847
+ if (request.grantType !== "authorization_code") {
2848
+ return null;
2849
+ }
2850
+ const codeData = this.codes.get(request.code);
2851
+ if (!codeData) {
2852
+ return null;
2853
+ }
2854
+ if (codeData.expiresAt < Date.now()) {
2855
+ this.codes.delete(request.code);
2856
+ return null;
2857
+ }
2858
+ const client = this.clients.get(request.clientId);
2859
+ if (!client || client.clientSecret !== request.clientSecret) {
2860
+ return null;
2861
+ }
2862
+ if (codeData.redirectUri !== request.redirectUri) {
2863
+ return null;
2864
+ }
2865
+ this.codes.delete(request.code);
2866
+ let userInfo = null;
2867
+ if (this.userProvider) {
2868
+ userInfo = await this.userProvider(codeData.userId);
2869
+ }
2870
+ if (!userInfo) {
2871
+ userInfo = {
2872
+ id: codeData.userId,
2873
+ username: codeData.userId
2874
+ };
2875
+ }
2876
+ const payload = {
2877
+ sub: userInfo.id,
2878
+ username: userInfo.username,
2879
+ roles: userInfo.roles
2880
+ };
2881
+ const accessToken = this.jwtUtil.generateAccessToken(payload);
2882
+ const refreshToken = this.jwtUtil.generateRefreshToken(payload);
2883
+ return {
2884
+ accessToken,
2885
+ tokenType: "Bearer",
2886
+ expiresIn: this.jwtUtil["config"].accessTokenExpiresIn,
2887
+ refreshToken,
2888
+ scope: codeData.scope
2889
+ };
2890
+ }
2891
+ async refreshToken(refreshToken) {
2892
+ const payload = this.jwtUtil.verify(refreshToken);
2893
+ if (!payload || !payload.sub) {
2894
+ return null;
2895
+ }
2896
+ let userInfo = null;
2897
+ if (this.userProvider) {
2898
+ userInfo = await this.userProvider(payload.sub);
2899
+ }
2900
+ if (!userInfo) {
2901
+ userInfo = {
2902
+ id: payload.sub,
2903
+ username: payload.username || payload.sub,
2904
+ roles: payload.roles
2905
+ };
2906
+ }
2907
+ const newPayload = {
2908
+ sub: userInfo.id,
2909
+ username: userInfo.username,
2910
+ roles: userInfo.roles
2911
+ };
2912
+ const accessToken = this.jwtUtil.generateAccessToken(newPayload);
2913
+ const newRefreshToken = this.jwtUtil.generateRefreshToken(newPayload);
2914
+ return {
2915
+ accessToken,
2916
+ tokenType: "Bearer",
2917
+ expiresIn: this.jwtUtil["config"].accessTokenExpiresIn,
2918
+ refreshToken: newRefreshToken
2919
+ };
2920
+ }
2921
+ generateRandomString(length) {
2922
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2923
+ let result = "";
2924
+ for (let i = 0;i < length; i++) {
2925
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
2926
+ }
2927
+ return result;
2928
+ }
2929
+ cleanupExpiredCodes() {
2930
+ const now = Date.now();
2931
+ for (const [code, data] of this.codes.entries()) {
2932
+ if (data.expiresAt < now) {
2933
+ this.codes.delete(code);
2934
+ }
2935
+ }
2936
+ }
2937
+ }
2938
+ // src/auth/controller.ts
2939
+ var OAUTH2_SERVICE_TOKEN = Symbol("OAUTH2_SERVICE");
2940
+ var JWT_UTIL_TOKEN = Symbol("JWT_UTIL");
2941
+
2942
+ class OAuth2Controller {
2943
+ oauth2Service;
2944
+ constructor(oauth2Service) {
2945
+ this.oauth2Service = oauth2Service;
2946
+ }
2947
+ authorize(clientId, redirectUri, state, scope) {
2948
+ const query = {
2949
+ client_id: clientId,
2950
+ redirect_uri: redirectUri,
2951
+ ...state && { state },
2952
+ ...scope && { scope }
2953
+ };
2954
+ const request = {
2955
+ clientId: query.client_id || "",
2956
+ redirectUri: query.redirect_uri || "",
2957
+ responseType: "code",
2958
+ scope: query.scope,
2959
+ state: query.state
2960
+ };
2961
+ const validation = this.oauth2Service.validateAuthorizationRequest(request);
2962
+ if (!validation.valid) {
2963
+ throw new Error(`Invalid authorization request: ${validation.error}`);
2964
+ }
2965
+ const userId = "user-1";
2966
+ const code = this.oauth2Service.generateAuthorizationCode(request.clientId, request.redirectUri, userId, request.scope);
2967
+ const redirectUrl = new URL(request.redirectUri);
2968
+ redirectUrl.searchParams.set("code", code);
2969
+ if (request.state) {
2970
+ redirectUrl.searchParams.set("state", request.state);
2971
+ }
2972
+ return ResponseBuilder.redirect(redirectUrl.toString());
2973
+ }
2974
+ async token(body) {
2975
+ const request = {
2976
+ code: body.code || "",
2977
+ clientId: body.client_id || "",
2978
+ clientSecret: body.client_secret || "",
2979
+ redirectUri: body.redirect_uri || "",
2980
+ grantType: body.grant_type || "authorization_code",
2981
+ refreshToken: body.refresh_token
2982
+ };
2983
+ if (request.grantType === "authorization_code") {
2984
+ const tokenResponse = await this.oauth2Service.exchangeCodeForToken(request);
2985
+ if (!tokenResponse) {
2986
+ return {
2987
+ error: "invalid_grant",
2988
+ error_description: "Invalid authorization code"
2989
+ };
2990
+ }
2991
+ return tokenResponse;
2992
+ }
2993
+ if (request.grantType === "refresh_token" && request.refreshToken) {
2994
+ const tokenResponse = await this.oauth2Service.refreshToken(request.refreshToken);
2995
+ if (!tokenResponse) {
2996
+ return {
2997
+ error: "invalid_grant",
2998
+ error_description: "Invalid refresh token"
2999
+ };
3000
+ }
3001
+ return tokenResponse;
3002
+ }
3003
+ return {
3004
+ error: "unsupported_grant_type",
3005
+ error_description: "Unsupported grant type"
3006
+ };
3007
+ }
3008
+ userinfo() {
3009
+ return {
3010
+ sub: "user-1",
3011
+ username: "alice",
3012
+ roles: ["user"]
3013
+ };
3014
+ }
3015
+ }
3016
+ __legacyDecorateClassTS([
3017
+ GET("/authorize"),
3018
+ __legacyDecorateParamTS(0, Query("client_id")),
3019
+ __legacyDecorateParamTS(1, Query("redirect_uri")),
3020
+ __legacyDecorateParamTS(2, Query("state")),
3021
+ __legacyDecorateParamTS(3, Query("scope")),
3022
+ __legacyMetadataTS("design:type", Function),
3023
+ __legacyMetadataTS("design:paramtypes", [
3024
+ String,
3025
+ String,
3026
+ String,
3027
+ String
3028
+ ]),
3029
+ __legacyMetadataTS("design:returntype", undefined)
3030
+ ], OAuth2Controller.prototype, "authorize", null);
3031
+ __legacyDecorateClassTS([
3032
+ POST("/token"),
3033
+ __legacyDecorateParamTS(0, Body()),
3034
+ __legacyMetadataTS("design:type", Function),
3035
+ __legacyMetadataTS("design:paramtypes", [
3036
+ typeof Record === "undefined" ? Object : Record
3037
+ ]),
3038
+ __legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
3039
+ ], OAuth2Controller.prototype, "token", null);
3040
+ __legacyDecorateClassTS([
3041
+ GET("/userinfo"),
3042
+ Auth(),
3043
+ __legacyMetadataTS("design:type", Function),
3044
+ __legacyMetadataTS("design:paramtypes", []),
3045
+ __legacyMetadataTS("design:returntype", undefined)
3046
+ ], OAuth2Controller.prototype, "userinfo", null);
3047
+ OAuth2Controller = __legacyDecorateClassTS([
3048
+ Controller("/oauth2"),
3049
+ Injectable(),
3050
+ __legacyDecorateParamTS(0, Inject(OAUTH2_SERVICE_TOKEN)),
3051
+ __legacyMetadataTS("design:paramtypes", [
3052
+ typeof OAuth2Service === "undefined" ? Object : OAuth2Service
3053
+ ])
3054
+ ], OAuth2Controller);
3055
+
3056
+ // src/security/security-module.ts
3057
+ class SecurityModule {
3058
+ static forRoot(config) {
3059
+ const jwtUtil = new JWTUtil(config.jwt);
3060
+ const userProvider = config.userProvider ? async (userId) => config.userProvider.findById(userId) : undefined;
3061
+ const oauth2Service = new OAuth2Service(jwtUtil, config.oauth2Clients || [], {}, userProvider);
3062
+ const authenticationManager = new AuthenticationManager;
3063
+ authenticationManager.registerProvider(new JwtAuthenticationProvider(jwtUtil));
3064
+ authenticationManager.registerProvider(new OAuth2AuthenticationProvider(oauth2Service));
3065
+ const securityFilter = createSecurityFilter({
3066
+ authenticationManager,
3067
+ excludePaths: [
3068
+ ...config.excludePaths || [],
3069
+ ...config.enableOAuth2Endpoints !== false ? [config.oauth2Prefix || "/oauth2"] : []
3070
+ ],
3071
+ defaultAuthRequired: config.defaultAuthRequired ?? false
3072
+ });
3073
+ const controllers = [];
3074
+ const providers = [];
3075
+ const middlewares = [];
3076
+ if (config.enableOAuth2Endpoints !== false) {
3077
+ controllers.push(OAuth2Controller);
3078
+ }
3079
+ providers.push({
3080
+ provide: JWT_UTIL_TOKEN,
3081
+ useValue: jwtUtil
3082
+ }, {
3083
+ provide: OAUTH2_SERVICE_TOKEN,
3084
+ useValue: oauth2Service
3085
+ }, {
3086
+ provide: AuthenticationManager,
3087
+ useValue: authenticationManager
3088
+ });
3089
+ middlewares.push(securityFilter);
3090
+ const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, SecurityModule) || {};
3091
+ const metadata = {
3092
+ ...existingMetadata,
3093
+ controllers: [...existingMetadata.controllers || [], ...controllers],
3094
+ providers: [...existingMetadata.providers || [], ...providers],
3095
+ middlewares: [...existingMetadata.middlewares || [], ...middlewares],
3096
+ exports: [
3097
+ ...existingMetadata.exports || [],
3098
+ JWT_UTIL_TOKEN,
3099
+ OAUTH2_SERVICE_TOKEN,
3100
+ AuthenticationManager
3101
+ ]
3102
+ };
3103
+ Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SecurityModule);
3104
+ return SecurityModule;
3105
+ }
3106
+ }
3107
+ SecurityModule = __legacyDecorateClassTS([
3108
+ Module({
3109
+ controllers: [],
3110
+ providers: [],
3111
+ middlewares: []
3112
+ })
3113
+ ], SecurityModule);
1998
3114
  // src/testing/harness.ts
1999
3115
  import { performance as performance2 } from "perf_hooks";
2000
3116
 
@@ -2056,22 +3172,33 @@ class StressTester {
2056
3172
  }
2057
3173
  }
2058
3174
  export {
3175
+ requiresAuth,
3176
+ getAuthMetadata,
3177
+ createSwaggerUIMiddleware,
2059
3178
  createStaticFileMiddleware,
3179
+ createSecurityFilter,
2060
3180
  createRequestLoggingMiddleware,
2061
3181
  createLoggerMiddleware,
2062
3182
  createFileUploadMiddleware,
2063
3183
  createErrorHandlingMiddleware,
2064
3184
  createCorsMiddleware,
3185
+ checkRoles,
2065
3186
  WebSocketGatewayRegistry,
2066
3187
  WebSocketGateway,
2067
3188
  ValidationError,
2068
3189
  Validate,
2069
3190
  UseMiddleware,
2070
3191
  UnauthorizedException,
3192
+ SwaggerModule,
3193
+ SwaggerGenerator,
3194
+ SwaggerExtension,
2071
3195
  StressTester,
3196
+ SecurityModule,
3197
+ SecurityContextHolder,
2072
3198
  Router,
2073
3199
  RouteRegistry,
2074
3200
  Route,
3201
+ RoleBasedAccessDecisionManager,
2075
3202
  ResponseBuilder,
2076
3203
  RequestWrapper,
2077
3204
  Query,
@@ -2084,15 +3211,23 @@ export {
2084
3211
  OnOpen,
2085
3212
  OnMessage,
2086
3213
  OnClose,
3214
+ OAuth2Service,
3215
+ OAuth2Controller,
3216
+ OAuth2AuthenticationProvider,
3217
+ OAUTH2_SERVICE_TOKEN,
2087
3218
  NotFoundException,
2088
3219
  ModuleRegistry,
2089
3220
  Module,
2090
3221
  MinLength,
2091
3222
  MiddlewarePipeline,
3223
+ LoggerModule,
2092
3224
  LoggerExtension,
2093
3225
  LogLevel2 as LogLevel,
2094
3226
  Lifecycle,
2095
3227
  LOGGER_TOKEN,
3228
+ JwtAuthenticationProvider,
3229
+ JWT_UTIL_TOKEN,
3230
+ JWTUtil,
2096
3231
  IsString,
2097
3232
  IsOptional,
2098
3233
  IsNumber,
@@ -2114,5 +3249,12 @@ export {
2114
3249
  BodyParser,
2115
3250
  Body,
2116
3251
  BadRequestException,
2117
- Application
3252
+ AuthenticationManager,
3253
+ Auth,
3254
+ Application,
3255
+ ApiTags,
3256
+ ApiResponse,
3257
+ ApiParam,
3258
+ ApiOperation,
3259
+ ApiBody
2118
3260
  };