@digitaldefiance/node-express-suite 3.11.32 → 3.12.1

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 (146) hide show
  1. package/README.md +874 -8
  2. package/package.json +5 -5
  3. package/src/controllers/openapi.d.ts +67 -0
  4. package/src/controllers/openapi.d.ts.map +1 -0
  5. package/src/controllers/openapi.js +89 -0
  6. package/src/controllers/openapi.js.map +1 -0
  7. package/src/decorators/auth.d.ts +128 -0
  8. package/src/decorators/auth.d.ts.map +1 -0
  9. package/src/decorators/auth.js +230 -0
  10. package/src/decorators/auth.js.map +1 -0
  11. package/src/decorators/base-controller.d.ts +144 -6
  12. package/src/decorators/base-controller.d.ts.map +1 -1
  13. package/src/decorators/base-controller.js +487 -31
  14. package/src/decorators/base-controller.js.map +1 -1
  15. package/src/decorators/controller.d.ts +63 -7
  16. package/src/decorators/controller.d.ts.map +1 -1
  17. package/src/decorators/controller.js +70 -39
  18. package/src/decorators/controller.js.map +1 -1
  19. package/src/decorators/handler-args.d.ts +68 -0
  20. package/src/decorators/handler-args.d.ts.map +1 -0
  21. package/src/decorators/handler-args.js +83 -0
  22. package/src/decorators/handler-args.js.map +1 -0
  23. package/src/decorators/http-methods.d.ts +143 -0
  24. package/src/decorators/http-methods.d.ts.map +1 -0
  25. package/src/decorators/http-methods.js +265 -0
  26. package/src/decorators/http-methods.js.map +1 -0
  27. package/src/decorators/index.d.ts +22 -0
  28. package/src/decorators/index.d.ts.map +1 -1
  29. package/src/decorators/index.js +56 -0
  30. package/src/decorators/index.js.map +1 -1
  31. package/src/decorators/lifecycle.d.ts +248 -0
  32. package/src/decorators/lifecycle.d.ts.map +1 -0
  33. package/src/decorators/lifecycle.js +301 -0
  34. package/src/decorators/lifecycle.js.map +1 -0
  35. package/src/decorators/metadata-collector.d.ts +175 -0
  36. package/src/decorators/metadata-collector.d.ts.map +1 -0
  37. package/src/decorators/metadata-collector.js +272 -0
  38. package/src/decorators/metadata-collector.js.map +1 -0
  39. package/src/decorators/metadata-keys.d.ts +121 -0
  40. package/src/decorators/metadata-keys.d.ts.map +1 -0
  41. package/src/decorators/metadata-keys.js +116 -0
  42. package/src/decorators/metadata-keys.js.map +1 -0
  43. package/src/decorators/middleware.d.ts +181 -0
  44. package/src/decorators/middleware.d.ts.map +1 -0
  45. package/src/decorators/middleware.js +400 -0
  46. package/src/decorators/middleware.js.map +1 -0
  47. package/src/decorators/openapi-params.d.ts +192 -0
  48. package/src/decorators/openapi-params.d.ts.map +1 -0
  49. package/src/decorators/openapi-params.js +332 -0
  50. package/src/decorators/openapi-params.js.map +1 -0
  51. package/src/decorators/openapi.d.ts +201 -0
  52. package/src/decorators/openapi.d.ts.map +1 -0
  53. package/src/decorators/openapi.js +334 -0
  54. package/src/decorators/openapi.js.map +1 -0
  55. package/src/decorators/params.d.ts +217 -0
  56. package/src/decorators/params.d.ts.map +1 -0
  57. package/src/decorators/params.js +323 -0
  58. package/src/decorators/params.js.map +1 -0
  59. package/src/decorators/response.d.ts +200 -0
  60. package/src/decorators/response.d.ts.map +1 -0
  61. package/src/decorators/response.js +315 -0
  62. package/src/decorators/response.js.map +1 -0
  63. package/src/decorators/schema.d.ts +99 -0
  64. package/src/decorators/schema.d.ts.map +1 -0
  65. package/src/decorators/schema.js +329 -0
  66. package/src/decorators/schema.js.map +1 -0
  67. package/src/decorators/transaction.d.ts +69 -0
  68. package/src/decorators/transaction.d.ts.map +1 -0
  69. package/src/decorators/transaction.js +80 -0
  70. package/src/decorators/transaction.js.map +1 -0
  71. package/src/decorators/validation.d.ts +188 -0
  72. package/src/decorators/validation.d.ts.map +1 -0
  73. package/src/decorators/validation.js +269 -0
  74. package/src/decorators/validation.js.map +1 -0
  75. package/src/decorators/zod-validation.d.ts +164 -4
  76. package/src/decorators/zod-validation.d.ts.map +1 -1
  77. package/src/decorators/zod-validation.js +692 -13
  78. package/src/decorators/zod-validation.js.map +1 -1
  79. package/src/index.d.ts +1 -0
  80. package/src/index.d.ts.map +1 -1
  81. package/src/index.js +1 -0
  82. package/src/index.js.map +1 -1
  83. package/src/interfaces/openApi/decoratorOptions.d.ts +760 -0
  84. package/src/interfaces/openApi/decoratorOptions.d.ts.map +1 -0
  85. package/src/interfaces/openApi/decoratorOptions.js +734 -0
  86. package/src/interfaces/openApi/decoratorOptions.js.map +1 -0
  87. package/src/interfaces/openApi/index.d.ts +1 -0
  88. package/src/interfaces/openApi/index.d.ts.map +1 -1
  89. package/src/interfaces/openApi/index.js +23 -0
  90. package/src/interfaces/openApi/index.js.map +1 -1
  91. package/src/interfaces/openApi/parameter.d.ts +2 -0
  92. package/src/interfaces/openApi/parameter.d.ts.map +1 -1
  93. package/src/interfaces/openApi/parameter.js +3 -1
  94. package/src/interfaces/openApi/parameter.js.map +1 -1
  95. package/src/interfaces/openApi/parameterSchema.d.ts +2 -0
  96. package/src/interfaces/openApi/parameterSchema.d.ts.map +1 -1
  97. package/src/interfaces/openApi/parameterSchema.js +3 -0
  98. package/src/interfaces/openApi/parameterSchema.js.map +1 -1
  99. package/src/openapi/builder.d.ts +249 -0
  100. package/src/openapi/builder.d.ts.map +1 -0
  101. package/src/openapi/builder.js +352 -0
  102. package/src/openapi/builder.js.map +1 -0
  103. package/src/openapi/controller.d.ts +153 -0
  104. package/src/openapi/controller.d.ts.map +1 -0
  105. package/src/openapi/controller.js +331 -0
  106. package/src/openapi/controller.js.map +1 -0
  107. package/src/openapi/index.d.ts +12 -0
  108. package/src/openapi/index.d.ts.map +1 -0
  109. package/src/openapi/index.js +20 -0
  110. package/src/openapi/index.js.map +1 -0
  111. package/src/openapi/markdown-generator.d.ts +52 -0
  112. package/src/openapi/markdown-generator.d.ts.map +1 -0
  113. package/src/openapi/markdown-generator.js +569 -0
  114. package/src/openapi/markdown-generator.js.map +1 -0
  115. package/src/openapi/middleware/index.d.ts +9 -0
  116. package/src/openapi/middleware/index.d.ts.map +1 -0
  117. package/src/openapi/middleware/index.js +15 -0
  118. package/src/openapi/middleware/index.js.map +1 -0
  119. package/src/openapi/middleware/redoc.d.ts +314 -0
  120. package/src/openapi/middleware/redoc.d.ts.map +1 -0
  121. package/src/openapi/middleware/redoc.js +181 -0
  122. package/src/openapi/middleware/redoc.js.map +1 -0
  123. package/src/openapi/middleware/swagger-ui.d.ts +123 -0
  124. package/src/openapi/middleware/swagger-ui.d.ts.map +1 -0
  125. package/src/openapi/middleware/swagger-ui.js +227 -0
  126. package/src/openapi/middleware/swagger-ui.js.map +1 -0
  127. package/src/openapi/schemas.d.ts +170 -0
  128. package/src/openapi/schemas.d.ts.map +1 -0
  129. package/src/openapi/schemas.js +340 -0
  130. package/src/openapi/schemas.js.map +1 -0
  131. package/src/registry/controller-registry.d.ts +78 -0
  132. package/src/registry/controller-registry.d.ts.map +1 -0
  133. package/src/registry/controller-registry.js +86 -0
  134. package/src/registry/controller-registry.js.map +1 -0
  135. package/src/registry/index.d.ts +2 -0
  136. package/src/registry/index.d.ts.map +1 -1
  137. package/src/registry/index.js +3 -1
  138. package/src/registry/index.js.map +1 -1
  139. package/src/routers/api.d.ts +2 -1
  140. package/src/routers/api.d.ts.map +1 -1
  141. package/src/routers/api.js +7 -1
  142. package/src/routers/api.js.map +1 -1
  143. package/src/types.d.ts +1 -0
  144. package/src/types.d.ts.map +1 -1
  145. package/src/types.js +1 -0
  146. package/src/types.js.map +1 -1
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @digitaldefiance/node-express-suite
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40digitaldefiance%2Fnode-express-suite.svg)](https://badge.fury.io/js/%40digitaldefiance%2Fnode-express-suite)
4
- [![Tests](https://img.shields.io/badge/tests-604%20passing-brightgreen)]()
4
+ [![Tests](https://img.shields.io/badge/tests-2541%20passing-brightgreen)]()
5
5
  [![Coverage](https://img.shields.io/badge/coverage-57.86%25-yellow)]()
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
7
 
@@ -11,6 +11,46 @@ It is an 'out of the box' solution with a specific recipe (Mongo, Express, React
11
11
 
12
12
  Part of [Express Suite](https://github.com/Digital-Defiance/express-suite)
13
13
 
14
+ ## What's New in v3.12.0
15
+
16
+ ✨ **Comprehensive Decorator API for Express Controllers** - A complete decorator-based API for defining controllers, routes, validation, and OpenAPI documentation with automatic spec generation.
17
+
18
+ **New Decorators:**
19
+
20
+ | Category | Decorators |
21
+ |----------|------------|
22
+ | Controller | `@Controller`, `@ApiController` |
23
+ | HTTP Methods | `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch` (enhanced with OpenAPI support) |
24
+ | Authentication | `@RequireAuth`, `@RequireCryptoAuth`, `@Public`, `@AuthFailureStatus` |
25
+ | Parameters | `@Param`, `@Body`, `@Query`, `@Header`, `@CurrentUser`, `@EciesUser`, `@Req`, `@Res`, `@Next` |
26
+ | Validation | `@ValidateBody`, `@ValidateParams`, `@ValidateQuery` (Zod & express-validator) |
27
+ | Response | `@Returns`, `@ResponseDoc`, `@RawJson`, `@Paginated` |
28
+ | Middleware | `@UseMiddleware`, `@CacheResponse`, `@RateLimit` |
29
+ | Transaction | `@Transactional` |
30
+ | OpenAPI | `@ApiOperation`, `@ApiTags`, `@ApiSummary`, `@ApiDescription`, `@Deprecated`, `@ApiOperationId`, `@ApiExample` |
31
+ | OpenAPI Params | `@ApiParam`, `@ApiQuery`, `@ApiHeader`, `@ApiRequestBody` |
32
+ | Lifecycle | `@OnSuccess`, `@OnError`, `@Before`, `@After` |
33
+ | Schema | `@ApiSchema`, `@ApiProperty` |
34
+
35
+ **Key Features:**
36
+ - **Full RouteConfig Parity**: Every feature available in manual `RouteConfig` has a decorator equivalent
37
+ - **Automatic OpenAPI Generation**: Decorators automatically generate complete OpenAPI 3.0.3 specifications
38
+ - **Zod Integration**: Zod schemas are automatically converted to OpenAPI request body schemas
39
+ - **Metadata Merging**: Multiple decorators on the same method merge their OpenAPI metadata
40
+ - **Class-Level Inheritance**: Class-level decorators (auth, tags, middleware) apply to all methods unless overridden
41
+ - **Parameter Injection**: Clean, typed parameter injection with `@Param`, `@Body`, `@Query`, `@Header`
42
+ - **Lifecycle Hooks**: `@Before`, `@After`, `@OnSuccess`, `@OnError` for request lifecycle management
43
+
44
+ **Documentation Middleware:**
45
+ - `SwaggerUIMiddleware` - Serve Swagger UI with customization options
46
+ - `ReDocMiddleware` - Serve ReDoc documentation
47
+ - `generateMarkdownDocs()` - Generate markdown documentation from OpenAPI spec
48
+
49
+ **Migration Support:**
50
+ - Full backward compatibility with existing `RouteConfig` approach
51
+ - Comprehensive migration guide in `docs/DECORATOR_MIGRATION.md`
52
+ - Mixed usage supported (decorated + manual routes in same controller)
53
+
14
54
  ## What's New in v3.11.25
15
55
 
16
56
  ✨ **String Key Enum Registration & i18n v4 Integration** - Upgraded to `@digitaldefiance/i18n-lib` v4.0.5 with branded enum translation support and `translateStringKey()` for automatic component ID resolution.
@@ -75,7 +115,7 @@ yarn add @digitaldefiance/node-express-suite
75
115
 
76
116
  ```typescript
77
117
  import { Application, DatabaseInitializationService, emailServiceRegistry } from '@digitaldefiance/node-express-suite';
78
- import { CoreLanguage } from '@digitaldefiance/i18n-lib';
118
+ import { LanguageCodes } from '@digitaldefiance/i18n-lib';
79
119
  import { EmailService } from './services/email'; // Your concrete implementation
80
120
 
81
121
  // Create application instance
@@ -83,7 +123,7 @@ const app = new Application({
83
123
  port: 3000,
84
124
  mongoUri: 'mongodb://localhost:27017/myapp',
85
125
  jwtSecret: process.env.JWT_SECRET,
86
- defaultLanguage: CoreLanguage.EnglishUS
126
+ defaultLanguage: LanguageCodes.EN_US
87
127
  });
88
128
 
89
129
  // Configure email service (required before using middleware)
@@ -523,7 +563,7 @@ Built-in support for multiple languages using the plugin-based i18n architecture
523
563
 
524
564
  ```typescript
525
565
  import { getGlobalI18nEngine, translateExpressSuite } from '@digitaldefiance/node-express-suite';
526
- import { CoreLanguage } from '@digitaldefiance/i18n-lib';
566
+ import { LanguageCodes } from '@digitaldefiance/i18n-lib';
527
567
 
528
568
  // Get the global i18n engine
529
569
  const i18n = getGlobalI18nEngine();
@@ -533,12 +573,12 @@ const i18n = getGlobalI18nEngine();
533
573
  const message = translateExpressSuite(
534
574
  ExpressSuiteStringKey.Common_Ready,
535
575
  {},
536
- CoreLanguage.French
576
+ LanguageCodes.FR
537
577
  );
538
578
  // "Prêt"
539
579
 
540
580
  // Change language globally
541
- i18n.setLanguage(CoreLanguage.Spanish);
581
+ i18n.setLanguage(LanguageCodes.ES);
542
582
  ```
543
583
 
544
584
  ### Direct String Key Translation
@@ -597,7 +637,7 @@ try {
597
637
 
598
638
  ## Testing
599
639
 
600
- Comprehensive test suite with 604 passing tests:
640
+ Comprehensive test suite with 2541 passing tests:
601
641
 
602
642
  ```bash
603
643
  # Run all tests
@@ -640,7 +680,7 @@ yarn add -D @faker-js/faker
640
680
 
641
681
  ### Test Coverage (v2.1)
642
682
 
643
- - **604 tests** passing (100% success rate)
683
+ - **2541 tests** passing (100% success rate)
644
684
  - **57.86%** overall coverage
645
685
  - **11 modules** at 100% coverage
646
686
  - All critical paths tested (validation, auth, services)
@@ -725,6 +765,14 @@ yarn add -D @faker-js/faker
725
765
  - `BackupCodeService` - Backup code management
726
766
  - `MnemonicService` - Mnemonic storage and retrieval
727
767
  - `SystemUserService` - System user operations
768
+ - `DatabaseInitializationService` - Database initialization with default users and roles
769
+ - `DirectLoginTokenService` - One-time login token management
770
+ - `RequestUserService` - Extract user from request context
771
+ - `ChecksumService` - CRC checksum operations
772
+ - `SymmetricService` - Symmetric encryption operations
773
+ - `XorService` - XOR cipher operations
774
+ - `FecService` - Forward error correction
775
+ - `DummyEmailService` - Test email service implementation
728
776
 
729
777
  ### Utilities
730
778
 
@@ -919,6 +967,710 @@ describe('Cross-Package Integration', () => {
919
967
  });
920
968
  ```
921
969
 
970
+ ## Decorator API
971
+
972
+ The decorator API provides a declarative, type-safe approach to building Express APIs with automatic OpenAPI documentation generation. Decorators eliminate boilerplate while maintaining full feature parity with manual `RouteConfig`.
973
+
974
+ ### Overview
975
+
976
+ | Category | Decorators | Purpose |
977
+ |----------|------------|---------|
978
+ | Controller | `@Controller`, `@ApiController` | Define controller base path and OpenAPI metadata |
979
+ | HTTP Methods | `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch` | Define route handlers with OpenAPI support |
980
+ | Authentication | `@RequireAuth`, `@RequireCryptoAuth`, `@Public`, `@AuthFailureStatus` | Control authentication requirements |
981
+ | Parameters | `@Param`, `@Body`, `@Query`, `@Header`, `@CurrentUser`, `@EciesUser`, `@Req`, `@Res`, `@Next` | Inject request data into handler parameters |
982
+ | Validation | `@ValidateBody`, `@ValidateParams`, `@ValidateQuery` | Validate request data with Zod or express-validator |
983
+ | Response | `@Returns`, `@ResponseDoc`, `@RawJson`, `@Paginated` | Document response types for OpenAPI |
984
+ | Middleware | `@UseMiddleware`, `@CacheResponse`, `@RateLimit` | Attach middleware to routes |
985
+ | Transaction | `@Transactional` | Wrap handlers in MongoDB transactions |
986
+ | OpenAPI | `@ApiOperation`, `@ApiTags`, `@ApiSummary`, `@ApiDescription`, `@Deprecated`, `@ApiOperationId`, `@ApiExample` | Add OpenAPI documentation |
987
+ | OpenAPI Params | `@ApiParam`, `@ApiQuery`, `@ApiHeader`, `@ApiRequestBody` | Document parameters with full OpenAPI metadata |
988
+ | Lifecycle | `@OnSuccess`, `@OnError`, `@Before`, `@After` | Hook into request lifecycle events |
989
+ | Handler Args | `@HandlerArgs` | Pass additional arguments to handlers |
990
+ | Schema | `@ApiSchema`, `@ApiProperty` | Register OpenAPI schemas from classes |
991
+
992
+ ### Quick Start Example
993
+
994
+ ```typescript
995
+ import {
996
+ ApiController,
997
+ Get,
998
+ Post,
999
+ Put,
1000
+ Delete,
1001
+ RequireAuth,
1002
+ Public,
1003
+ Param,
1004
+ Body,
1005
+ Query,
1006
+ ValidateBody,
1007
+ Returns,
1008
+ ApiTags,
1009
+ Transactional,
1010
+ DecoratorBaseController,
1011
+ } from '@digitaldefiance/node-express-suite';
1012
+ import { z } from 'zod';
1013
+
1014
+ // Define validation schema
1015
+ const CreateUserSchema = z.object({
1016
+ name: z.string().min(1).max(100),
1017
+ email: z.string().email(),
1018
+ role: z.enum(['admin', 'user']).optional(),
1019
+ });
1020
+
1021
+ @RequireAuth() // All routes require authentication by default
1022
+ @ApiTags('Users')
1023
+ @ApiController('/api/users', {
1024
+ description: 'User management endpoints',
1025
+ })
1026
+ class UserController extends DecoratorBaseController {
1027
+ @Public() // Override class-level auth - this route is public
1028
+ @Returns(200, 'User[]', { description: 'List of users' })
1029
+ @Get('/')
1030
+ async listUsers(
1031
+ @Query('page', { schema: { type: 'integer' } }) page: number = 1,
1032
+ @Query('limit') limit: number = 20,
1033
+ ) {
1034
+ return this.userService.findAll({ page, limit });
1035
+ }
1036
+
1037
+ @Returns(200, 'User', { description: 'User details' })
1038
+ @Returns(404, 'ErrorResponse', { description: 'User not found' })
1039
+ @Get('/:id')
1040
+ async getUser(@Param('id', { description: 'User ID' }) id: string) {
1041
+ return this.userService.findById(id);
1042
+ }
1043
+
1044
+ @ValidateBody(CreateUserSchema)
1045
+ @Transactional()
1046
+ @Returns(201, 'User', { description: 'Created user' })
1047
+ @Post('/')
1048
+ async createUser(@Body() data: z.infer<typeof CreateUserSchema>) {
1049
+ return this.userService.create(data);
1050
+ }
1051
+
1052
+ @Transactional()
1053
+ @Returns(200, 'User', { description: 'Updated user' })
1054
+ @Put('/:id')
1055
+ async updateUser(
1056
+ @Param('id') id: string,
1057
+ @Body() data: Partial<z.infer<typeof CreateUserSchema>>,
1058
+ ) {
1059
+ return this.userService.update(id, data);
1060
+ }
1061
+
1062
+ @Transactional()
1063
+ @Returns(204, undefined, { description: 'User deleted' })
1064
+ @Delete('/:id')
1065
+ async deleteUser(@Param('id') id: string) {
1066
+ await this.userService.delete(id);
1067
+ }
1068
+ }
1069
+ ```
1070
+
1071
+ ### Controller Decorators
1072
+
1073
+ ```typescript
1074
+ // Basic controller (no OpenAPI metadata)
1075
+ @Controller('/api/items')
1076
+ class ItemController {}
1077
+
1078
+ // OpenAPI-enabled controller with metadata
1079
+ @ApiController('/api/users', {
1080
+ tags: ['Users', 'Admin'],
1081
+ description: 'User management endpoints',
1082
+ deprecated: false,
1083
+ name: 'UserController', // Optional, defaults to class name
1084
+ })
1085
+ class UserController extends DecoratorBaseController {}
1086
+ ```
1087
+
1088
+ ### HTTP Method Decorators
1089
+
1090
+ All HTTP method decorators support inline OpenAPI options:
1091
+
1092
+ ```typescript
1093
+ @Get('/users/:id', {
1094
+ summary: 'Get user by ID',
1095
+ description: 'Retrieves a user by their unique identifier',
1096
+ tags: ['Users'],
1097
+ operationId: 'getUserById',
1098
+ deprecated: false,
1099
+ auth: true, // Shorthand for @RequireAuth()
1100
+ cryptoAuth: false, // Shorthand for @RequireCryptoAuth()
1101
+ rawJson: false, // Shorthand for @RawJson()
1102
+ transaction: false, // Shorthand for @Transactional()
1103
+ middleware: [], // Express middleware array
1104
+ validation: [], // express-validator chains
1105
+ schema: zodSchema, // Zod schema for body validation
1106
+ })
1107
+ async getUser() {}
1108
+ ```
1109
+
1110
+ ### Authentication Decorators
1111
+
1112
+ ```typescript
1113
+ // Require JWT authentication
1114
+ @RequireAuth()
1115
+ @ApiController('/api/secure')
1116
+ class SecureController {
1117
+ @Get('/data')
1118
+ getData() {} // Requires auth (inherited from class)
1119
+
1120
+ @Public()
1121
+ @Get('/public')
1122
+ getPublic() {} // No auth required (overrides class-level)
1123
+ }
1124
+
1125
+ // Require ECIES crypto authentication
1126
+ @RequireCryptoAuth()
1127
+ @Post('/encrypted')
1128
+ async createEncrypted() {}
1129
+
1130
+ // Custom auth failure status code
1131
+ @AuthFailureStatus(403)
1132
+ @Get('/admin')
1133
+ getAdmin() {} // Returns 403 instead of 401 on auth failure
1134
+ ```
1135
+
1136
+ ### Parameter Injection Decorators
1137
+
1138
+ ```typescript
1139
+ @Get('/:id')
1140
+ async getUser(
1141
+ // Path parameter with OpenAPI documentation
1142
+ @Param('id', { description: 'User ID', schema: { type: 'string', format: 'uuid' } }) id: string,
1143
+
1144
+ // Query parameters
1145
+ @Query('include', { description: 'Fields to include' }) include?: string,
1146
+
1147
+ // Header value
1148
+ @Header('X-Request-ID') requestId?: string,
1149
+
1150
+ // Authenticated user from JWT
1151
+ @CurrentUser() user: AuthenticatedUser,
1152
+
1153
+ // ECIES authenticated member
1154
+ @EciesUser() member: EciesMember,
1155
+
1156
+ // Raw Express objects (use sparingly)
1157
+ @Req() req: Request,
1158
+ @Res() res: Response,
1159
+ @Next() next: NextFunction,
1160
+ ) {}
1161
+
1162
+ @Post('/')
1163
+ async createUser(
1164
+ // Entire request body
1165
+ @Body() data: CreateUserDto,
1166
+
1167
+ // Specific field from body
1168
+ @Body('email') email: string,
1169
+ ) {}
1170
+ ```
1171
+
1172
+ ### Validation Decorators
1173
+
1174
+ ```typescript
1175
+ // Zod schema validation
1176
+ const CreateUserSchema = z.object({
1177
+ name: z.string().min(1),
1178
+ email: z.string().email(),
1179
+ });
1180
+
1181
+ @ValidateBody(CreateUserSchema)
1182
+ @Post('/')
1183
+ async createUser(@Body() data: z.infer<typeof CreateUserSchema>) {}
1184
+
1185
+ // express-validator chains
1186
+ @ValidateBody([
1187
+ body('name').isString().notEmpty(),
1188
+ body('email').isEmail(),
1189
+ ])
1190
+ @Post('/')
1191
+ async createUser() {}
1192
+
1193
+ // Language-aware validation with constants
1194
+ @ValidateBody(function(lang) {
1195
+ return [
1196
+ body('username')
1197
+ .matches(this.constants.UsernameRegex)
1198
+ .withMessage(getTranslation(lang, 'invalidUsername')),
1199
+ ];
1200
+ })
1201
+ @Post('/')
1202
+ async createUser() {}
1203
+
1204
+ // Validate path parameters
1205
+ @ValidateParams(z.object({ id: z.string().uuid() }))
1206
+ @Get('/:id')
1207
+ async getUser() {}
1208
+
1209
+ // Validate query parameters
1210
+ @ValidateQuery(z.object({
1211
+ page: z.coerce.number().int().positive().optional(),
1212
+ limit: z.coerce.number().int().max(100).optional(),
1213
+ }))
1214
+ @Get('/')
1215
+ async listUsers() {}
1216
+ ```
1217
+
1218
+ ### Response Decorators
1219
+
1220
+ ```typescript
1221
+ // Document response types (stackable for multiple status codes)
1222
+ @Returns(200, 'User', { description: 'User found' })
1223
+ @Returns(404, 'ErrorResponse', { description: 'User not found' })
1224
+ @Get('/:id')
1225
+ async getUser() {}
1226
+
1227
+ // Inline schema for simple responses
1228
+ @ResponseDoc(200, {
1229
+ description: 'Health check response',
1230
+ schema: {
1231
+ type: 'object',
1232
+ properties: {
1233
+ status: { type: 'string' },
1234
+ timestamp: { type: 'string', format: 'date-time' },
1235
+ },
1236
+ },
1237
+ })
1238
+ @Get('/health')
1239
+ healthCheck() {}
1240
+
1241
+ // Raw JSON response (bypasses response wrapper)
1242
+ @RawJson()
1243
+ @Get('/raw')
1244
+ getRawData() {}
1245
+
1246
+ // Paginated endpoint (adds page/limit query params to OpenAPI)
1247
+ @Paginated({ defaultPageSize: 20, maxPageSize: 100 })
1248
+ @Returns(200, 'User[]')
1249
+ @Get('/')
1250
+ async listUsers() {}
1251
+
1252
+ // Offset-based pagination
1253
+ @Paginated({ useOffset: true, defaultPageSize: 20 })
1254
+ @Get('/items')
1255
+ async listItems() {}
1256
+ ```
1257
+
1258
+ ### Middleware Decorators
1259
+
1260
+ ```typescript
1261
+ // Attach middleware (class or method level)
1262
+ @UseMiddleware(loggerMiddleware)
1263
+ @ApiController('/api/data')
1264
+ class DataController {
1265
+ @UseMiddleware([validateMiddleware, sanitizeMiddleware])
1266
+ @Post('/')
1267
+ createData() {}
1268
+ }
1269
+
1270
+ // Response caching
1271
+ @CacheResponse({ ttl: 60 }) // Cache for 60 seconds
1272
+ @Get('/static')
1273
+ getStaticData() {}
1274
+
1275
+ @CacheResponse({
1276
+ ttl: 300,
1277
+ varyByUser: true, // Different cache per user
1278
+ varyByQuery: ['page'], // Different cache per query param
1279
+ keyPrefix: 'users', // Custom cache key prefix
1280
+ })
1281
+ @Get('/user-data')
1282
+ getUserData() {}
1283
+
1284
+ // Rate limiting (auto-adds 429 response to OpenAPI)
1285
+ @RateLimit({ requests: 5, window: 60 }) // 5 requests per minute
1286
+ @Post('/login')
1287
+ login() {}
1288
+
1289
+ @RateLimit({
1290
+ requests: 100,
1291
+ window: 3600,
1292
+ byUser: true, // Limit per user instead of IP
1293
+ message: 'Hourly limit exceeded',
1294
+ keyGenerator: (req) => req.ip, // Custom key generator
1295
+ })
1296
+ @Get('/api-data')
1297
+ getApiData() {}
1298
+ ```
1299
+
1300
+ ### Transaction Decorator
1301
+
1302
+ ```typescript
1303
+ // Basic transaction
1304
+ @Transactional()
1305
+ @Post('/')
1306
+ async createOrder() {
1307
+ // this.session available automatically in DecoratorBaseController
1308
+ await this.orderService.create(data, this.session);
1309
+ }
1310
+
1311
+ // Transaction with timeout
1312
+ @Transactional({ timeout: 30000 }) // 30 second timeout
1313
+ @Post('/bulk')
1314
+ async bulkCreate() {}
1315
+ ```
1316
+
1317
+ ### OpenAPI Operation Decorators
1318
+
1319
+ ```typescript
1320
+ // Full operation metadata
1321
+ @ApiOperation({
1322
+ summary: 'Get user by ID',
1323
+ description: 'Retrieves a user by their unique identifier',
1324
+ tags: ['Users'],
1325
+ operationId: 'getUserById',
1326
+ deprecated: false,
1327
+ })
1328
+ @Get('/:id')
1329
+ getUser() {}
1330
+
1331
+ // Individual decorators (composable)
1332
+ @ApiSummary('Get user by ID')
1333
+ @ApiDescription('Retrieves a user by their unique identifier')
1334
+ @ApiTags('Users', 'Public')
1335
+ @ApiOperationId('getUserById')
1336
+ @Deprecated()
1337
+ @Get('/:id')
1338
+ getUser() {}
1339
+
1340
+ // Class-level tags apply to all methods
1341
+ @ApiTags('Users')
1342
+ @ApiController('/api/users')
1343
+ class UserController {
1344
+ @ApiTags('Admin') // Adds to class tags: ['Users', 'Admin']
1345
+ @Get('/admin')
1346
+ adminEndpoint() {}
1347
+ }
1348
+
1349
+ // Add examples
1350
+ @ApiExample({
1351
+ name: 'validUser',
1352
+ summary: 'A valid user response',
1353
+ value: { id: '123', name: 'John Doe', email: 'john@example.com' },
1354
+ type: 'response',
1355
+ statusCode: 200,
1356
+ })
1357
+ @Get('/:id')
1358
+ getUser() {}
1359
+ ```
1360
+
1361
+ ### OpenAPI Parameter Decorators
1362
+
1363
+ ```typescript
1364
+ // Document path parameter with full metadata
1365
+ @ApiParam('id', {
1366
+ description: 'User ID',
1367
+ schema: { type: 'string', format: 'uuid' },
1368
+ example: '123e4567-e89b-12d3-a456-426614174000',
1369
+ })
1370
+ @Get('/:id')
1371
+ getUser(@Param('id') id: string) {}
1372
+
1373
+ // Document query parameters
1374
+ @ApiQuery('page', {
1375
+ description: 'Page number',
1376
+ schema: { type: 'integer', minimum: 1 },
1377
+ required: false,
1378
+ example: 1,
1379
+ })
1380
+ @ApiQuery('sort', {
1381
+ description: 'Sort field',
1382
+ enum: ['name', 'date', 'id'],
1383
+ })
1384
+ @Get('/')
1385
+ listUsers() {}
1386
+
1387
+ // Document headers
1388
+ @ApiHeader('X-Request-ID', {
1389
+ description: 'Request tracking ID',
1390
+ schema: { type: 'string', format: 'uuid' },
1391
+ required: true,
1392
+ })
1393
+ @Get('/')
1394
+ getData() {}
1395
+
1396
+ // Document request body
1397
+ @ApiRequestBody({
1398
+ schema: 'CreateUserDto', // Reference to registered schema
1399
+ description: 'User data to create',
1400
+ required: true,
1401
+ example: { name: 'John', email: 'john@example.com' },
1402
+ })
1403
+ @Post('/')
1404
+ createUser() {}
1405
+
1406
+ // Or with Zod schema
1407
+ @ApiRequestBody({
1408
+ schema: CreateUserSchema, // Zod schema
1409
+ description: 'User data',
1410
+ })
1411
+ @Post('/')
1412
+ createUser() {}
1413
+ ```
1414
+
1415
+ ### Lifecycle Decorators
1416
+
1417
+ ```typescript
1418
+ // Execute after successful response
1419
+ @OnSuccess(({ req, result }) => {
1420
+ console.log(`User ${req.params.id} fetched:`, result);
1421
+ })
1422
+ @Get('/:id')
1423
+ getUser() {}
1424
+
1425
+ // Execute on error
1426
+ @OnError(({ req, error }) => {
1427
+ logger.error(`Error on ${req.path}:`, error);
1428
+ })
1429
+ @Get('/:id')
1430
+ getUser() {}
1431
+
1432
+ // Execute before handler
1433
+ @Before(({ req }) => {
1434
+ console.log(`Incoming request to ${req.path}`);
1435
+ })
1436
+ @Get('/')
1437
+ listUsers() {}
1438
+
1439
+ // Execute after handler (success or error)
1440
+ @After(({ req, result, error }) => {
1441
+ metrics.recordRequest(req.path, error ? 'error' : 'success');
1442
+ })
1443
+ @Get('/')
1444
+ listUsers() {}
1445
+
1446
+ // Class-level hooks apply to all methods
1447
+ @OnError(({ error }) => logger.error(error))
1448
+ @ApiController('/api/users')
1449
+ class UserController {}
1450
+ ```
1451
+
1452
+ ### Handler Args Decorator
1453
+
1454
+ ```typescript
1455
+ // Pass additional arguments to handler
1456
+ @HandlerArgs({ maxItems: 100 })
1457
+ @Get('/')
1458
+ listItems(req: Request, config: { maxItems: number }) {
1459
+ // config.maxItems === 100
1460
+ }
1461
+
1462
+ // Multiple arguments
1463
+ @HandlerArgs('prefix', 42, { option: true })
1464
+ @Post('/')
1465
+ createItem(req: Request, prefix: string, count: number, options: object) {}
1466
+ ```
1467
+
1468
+ ### Schema Decorators
1469
+
1470
+ ```typescript
1471
+ // Register class as OpenAPI schema
1472
+ @ApiSchema({ description: 'User entity' })
1473
+ class User {
1474
+ @ApiProperty({
1475
+ type: 'string',
1476
+ format: 'uuid',
1477
+ description: 'Unique identifier',
1478
+ example: '123e4567-e89b-12d3-a456-426614174000',
1479
+ })
1480
+ id: string;
1481
+
1482
+ @ApiProperty({
1483
+ type: 'string',
1484
+ format: 'email',
1485
+ required: true,
1486
+ })
1487
+ email: string;
1488
+
1489
+ @ApiProperty({
1490
+ type: 'integer',
1491
+ minimum: 0,
1492
+ maximum: 150,
1493
+ })
1494
+ age?: number;
1495
+
1496
+ @ApiProperty({
1497
+ type: 'array',
1498
+ items: 'Role', // Reference to another schema
1499
+ })
1500
+ roles: Role[];
1501
+ }
1502
+
1503
+ // Inheritance is supported
1504
+ @ApiSchema()
1505
+ class AdminUser extends User {
1506
+ @ApiProperty({ type: 'string' })
1507
+ adminLevel: string;
1508
+ }
1509
+ ```
1510
+
1511
+ ### Decorator Composition and Stacking
1512
+
1513
+ Decorators can be freely composed and stacked. Order matters for some decorators:
1514
+
1515
+ ```typescript
1516
+ // Middleware executes top to bottom
1517
+ @UseMiddleware(first)
1518
+ @UseMiddleware(second)
1519
+ @UseMiddleware(third)
1520
+ @Get('/')
1521
+ handler() {} // Executes: first → second → third → handler
1522
+
1523
+ // Multiple @Returns accumulate (don't replace)
1524
+ @Returns(200, 'User')
1525
+ @Returns(400, 'ValidationError')
1526
+ @Returns(404, 'NotFoundError')
1527
+ @Returns(500, 'ServerError')
1528
+ @Get('/:id')
1529
+ getUser() {}
1530
+
1531
+ // Tags merge (class + method)
1532
+ @ApiTags('Users')
1533
+ @ApiController('/api/users')
1534
+ class UserController {
1535
+ @ApiTags('Admin')
1536
+ @Get('/admin')
1537
+ admin() {} // Tags: ['Users', 'Admin']
1538
+ }
1539
+
1540
+ // Method-level overrides class-level for same field
1541
+ @RequireAuth()
1542
+ @ApiController('/api/data')
1543
+ class DataController {
1544
+ @Get('/private')
1545
+ private() {} // Requires auth (inherited)
1546
+
1547
+ @Public()
1548
+ @Get('/public')
1549
+ public() {} // No auth (overridden)
1550
+ }
1551
+ ```
1552
+
1553
+ ### Comparison: Manual RouteConfig vs Decorators
1554
+
1555
+ | RouteConfig Field | Decorator Equivalent |
1556
+ |-------------------|---------------------|
1557
+ | `method` | `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch` |
1558
+ | `path` | Decorator path argument |
1559
+ | `handlerKey` | Decorated method name (automatic) |
1560
+ | `handlerArgs` | `@HandlerArgs(...args)` |
1561
+ | `useAuthentication` | `@RequireAuth()` |
1562
+ | `useCryptoAuthentication` | `@RequireCryptoAuth()` |
1563
+ | `middleware` | `@UseMiddleware(...)` |
1564
+ | `validation` | `@ValidateBody()`, `@ValidateParams()`, `@ValidateQuery()` |
1565
+ | `rawJsonHandler` | `@RawJson()` |
1566
+ | `authFailureStatusCode` | `@AuthFailureStatus(code)` |
1567
+ | `useTransaction` | `@Transactional()` |
1568
+ | `transactionTimeout` | `@Transactional({ timeout })` |
1569
+ | `openapi.summary` | `@ApiSummary(text)` |
1570
+ | `openapi.description` | `@ApiDescription(text)` |
1571
+ | `openapi.tags` | `@ApiTags(...tags)` |
1572
+ | `openapi.operationId` | `@ApiOperationId(id)` |
1573
+ | `openapi.deprecated` | `@Deprecated()` |
1574
+ | `openapi.requestBody` | `@ApiRequestBody(options)` |
1575
+ | `openapi.responses` | `@Returns(code, schema)` |
1576
+ | `openapi.parameters` | `@ApiParam()`, `@ApiQuery()`, `@ApiHeader()` |
1577
+
1578
+ ### Decorator Options TypeScript Types
1579
+
1580
+ ```typescript
1581
+ // Controller options
1582
+ interface ApiControllerOptions {
1583
+ tags?: string[];
1584
+ description?: string;
1585
+ deprecated?: boolean;
1586
+ name?: string;
1587
+ }
1588
+
1589
+ // Route decorator options
1590
+ interface RouteDecoratorOptions<TLanguage> {
1591
+ validation?: ValidationChain[] | ((lang: TLanguage) => ValidationChain[]);
1592
+ schema?: z.ZodSchema;
1593
+ middleware?: RequestHandler[];
1594
+ auth?: boolean;
1595
+ cryptoAuth?: boolean;
1596
+ rawJson?: boolean;
1597
+ transaction?: boolean;
1598
+ transactionTimeout?: number;
1599
+ summary?: string;
1600
+ description?: string;
1601
+ tags?: string[];
1602
+ operationId?: string;
1603
+ deprecated?: boolean;
1604
+ openapi?: OpenAPIRouteMetadata;
1605
+ }
1606
+
1607
+ // Parameter decorator options
1608
+ interface ParamDecoratorOptions {
1609
+ description?: string;
1610
+ example?: unknown;
1611
+ required?: boolean;
1612
+ schema?: OpenAPIParameterSchema;
1613
+ }
1614
+
1615
+ // Cache options
1616
+ interface CacheDecoratorOptions {
1617
+ ttl: number; // Time to live in seconds
1618
+ keyPrefix?: string;
1619
+ varyByUser?: boolean;
1620
+ varyByQuery?: string[];
1621
+ }
1622
+
1623
+ // Rate limit options
1624
+ interface RateLimitDecoratorOptions {
1625
+ requests: number; // Max requests
1626
+ window: number; // Time window in seconds
1627
+ message?: string;
1628
+ byUser?: boolean;
1629
+ keyGenerator?: (req: Request) => string;
1630
+ }
1631
+
1632
+ // Pagination options
1633
+ interface PaginatedDecoratorOptions {
1634
+ defaultPageSize?: number;
1635
+ maxPageSize?: number;
1636
+ useOffset?: boolean; // Use offset/limit instead of page/limit
1637
+ }
1638
+
1639
+ // Transaction options
1640
+ interface TransactionalDecoratorOptions {
1641
+ timeout?: number; // Timeout in milliseconds
1642
+ }
1643
+ ```
1644
+
1645
+ ### Troubleshooting
1646
+
1647
+ **Decorators not working?**
1648
+ - Ensure `experimentalDecorators: true` and `emitDecoratorMetadata: true` in tsconfig.json
1649
+ - Import `reflect-metadata` at the top of your entry file
1650
+ - Extend `DecoratorBaseController` for full decorator support
1651
+
1652
+ **OpenAPI metadata not appearing?**
1653
+ - Use `@ApiController` instead of `@Controller` for OpenAPI support
1654
+ - Ensure decorators are applied before HTTP method decorators (bottom-up execution)
1655
+ - Check that schemas are registered with `@ApiSchema` or `OpenAPISchemaRegistry`
1656
+
1657
+ **Authentication not enforced?**
1658
+ - Verify `@RequireAuth()` is applied at class or method level
1659
+ - Check that `@Public()` isn't overriding at method level
1660
+ - Ensure auth middleware is configured in your application
1661
+
1662
+ **Validation errors not returning 400?**
1663
+ - Validation decorators automatically add 400 response to OpenAPI
1664
+ - Ensure validation middleware is properly configured
1665
+ - Check that Zod schemas or express-validator chains are valid
1666
+
1667
+ **Parameter injection not working?**
1668
+ - Parameter decorators must be on method parameters, not properties
1669
+ - Ensure the handler is called through the decorated controller
1670
+ - Check parameter index matches the decorator position
1671
+
1672
+ For detailed migration instructions, see [docs/DECORATOR_MIGRATION.md](./docs/DECORATOR_MIGRATION.md).
1673
+
922
1674
  ## Documentation
923
1675
 
924
1676
  📚 **Comprehensive documentation is available in the [`docs/`](./docs) directory.**
@@ -1360,6 +2112,120 @@ The following v1.x patterns still work in v2.0:
1360
2112
 
1361
2113
  ## ChangeLog
1362
2114
 
2115
+ ### Version 3.12.0
2116
+
2117
+ **Comprehensive Decorator API for Express Controllers**
2118
+
2119
+ This release introduces a complete decorator-based API for defining controllers, routes, validation, and OpenAPI documentation. The decorator system provides a declarative, type-safe approach to building Express APIs with automatic OpenAPI 3.0.3 specification generation.
2120
+
2121
+ **New Decorator Categories:**
2122
+
2123
+ *Controller Decorators:*
2124
+ - `@Controller(basePath)` - Define controller base path (existing, preserved for backward compatibility)
2125
+ - `@ApiController(basePath, options?)` - Define controller with OpenAPI metadata (tags, description, deprecated)
2126
+
2127
+ *HTTP Method Decorators (Enhanced):*
2128
+ - `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch` - Now support inline OpenAPI options (summary, description, tags, operationId, deprecated)
2129
+
2130
+ *Authentication Decorators:*
2131
+ - `@RequireAuth()` - Require JWT authentication (auto-adds 401 response to OpenAPI)
2132
+ - `@RequireCryptoAuth()` - Require ECIES crypto authentication
2133
+ - `@Public()` - Mark route as public (overrides class-level auth)
2134
+ - `@AuthFailureStatus(code)` - Set custom auth failure status code
2135
+
2136
+ *Parameter Injection Decorators:*
2137
+ - `@Param(name, options?)` - Inject path parameter (auto-adds to OpenAPI)
2138
+ - `@Body(field?)` - Inject request body or specific field
2139
+ - `@Query(name, options?)` - Inject query parameter (auto-adds to OpenAPI)
2140
+ - `@Header(name, options?)` - Inject header value (auto-adds to OpenAPI)
2141
+ - `@CurrentUser()` - Inject authenticated user (`req.user`)
2142
+ - `@EciesUser()` - Inject ECIES authenticated member (`req.eciesUser`)
2143
+ - `@Req()`, `@Res()`, `@Next()` - Inject Express request/response/next
2144
+
2145
+ *Validation Decorators:*
2146
+ - `@ValidateBody(schema)` - Validate request body with Zod or express-validator (auto-adds 400 response)
2147
+ - `@ValidateParams(schema)` - Validate path parameters
2148
+ - `@ValidateQuery(schema)` - Validate query parameters
2149
+
2150
+ *Response Decorators:*
2151
+ - `@Returns(statusCode, schema, options?)` - Document response type (stackable for multiple status codes)
2152
+ - `@ResponseDoc(responses)` - Document multiple responses at once
2153
+ - `@RawJson()` - Bypass standard response wrapper
2154
+ - `@Paginated(options?)` - Add pagination query parameters and response envelope
2155
+
2156
+ *Middleware Decorators:*
2157
+ - `@UseMiddleware(...middleware)` - Attach Express middleware (class or method level)
2158
+ - `@CacheResponse(options)` - Add response caching middleware
2159
+ - `@RateLimit(options)` - Add rate limiting middleware (auto-adds 429 response)
2160
+
2161
+ *Transaction Decorator:*
2162
+ - `@Transactional(options?)` - Wrap handler in MongoDB transaction with optional timeout
2163
+
2164
+ *OpenAPI Operation Decorators:*
2165
+ - `@ApiOperation(metadata)` - Set full OpenAPI operation metadata
2166
+ - `@ApiTags(...tags)` - Add tags (class or method level, additive)
2167
+ - `@ApiSummary(text)` - Set operation summary
2168
+ - `@ApiDescription(text)` - Set operation description
2169
+ - `@Deprecated()` - Mark operation as deprecated
2170
+ - `@ApiOperationId(id)` - Set unique operation ID
2171
+ - `@ApiExample(example)` - Add request/response examples
2172
+
2173
+ *OpenAPI Parameter Decorators:*
2174
+ - `@ApiParam(name, options)` - Document path parameter with full OpenAPI metadata
2175
+ - `@ApiQuery(name, options)` - Document query parameter
2176
+ - `@ApiHeader(name, options)` - Document header parameter
2177
+ - `@ApiRequestBody(options)` - Document request body with schema, example, description
2178
+
2179
+ *Lifecycle Decorators:*
2180
+ - `@OnSuccess(callback)` - Execute after successful response
2181
+ - `@OnError(callback)` - Execute when error occurs
2182
+ - `@Before(callback)` - Execute before handler
2183
+ - `@After(callback)` - Execute after handler (success or error)
2184
+
2185
+ *Handler Args Decorator:*
2186
+ - `@HandlerArgs(...args)` - Pass additional arguments to handler
2187
+
2188
+ *Schema Decorators:*
2189
+ - `@ApiSchema(name?)` - Register class as OpenAPI schema
2190
+ - `@ApiProperty(options)` - Add property metadata (type, description, required, example)
2191
+
2192
+ **New Documentation Middleware:**
2193
+ - `SwaggerUIMiddleware(options)` - Serve Swagger UI with customization (title, favicon, CSS, JS)
2194
+ - `ReDocMiddleware(options)` - Serve ReDoc documentation with customization
2195
+ - `generateMarkdownDocs(spec)` - Generate markdown documentation from OpenAPI spec
2196
+
2197
+ **New Infrastructure:**
2198
+ - `src/decorators/metadata-keys.ts` - Symbol constants for all decorator metadata
2199
+ - `src/decorators/metadata-collector.ts` - Utility for metadata operations
2200
+ - `src/interfaces/openApi/decoratorOptions.ts` - All decorator option interfaces
2201
+ - Enhanced `DecoratorBaseController` with full metadata collection and parameter injection
2202
+
2203
+ **Zod Integration:**
2204
+ - Comprehensive Zod to OpenAPI schema conversion
2205
+ - Support for nested objects, arrays, unions, enums
2206
+ - Automatic extraction of descriptions and examples from Zod schemas
2207
+
2208
+ **Key Features:**
2209
+ - Full feature parity with manual `RouteConfig` approach
2210
+ - Automatic OpenAPI 3.0.3 specification generation
2211
+ - Metadata merging from multiple decorators
2212
+ - Class-level decorator inheritance with method-level overrides
2213
+ - Backward compatible - existing code continues to work unchanged
2214
+
2215
+ **Documentation:**
2216
+ - Updated README with comprehensive Decorator API section
2217
+ - New `docs/DECORATOR_MIGRATION.md` with complete migration guide
2218
+ - Updated `docs/CONTROLLERS.md` featuring decorator-based approach
2219
+ - JSDoc documentation on all public decorators and types
2220
+
2221
+ **Testing:**
2222
+ - Property-based tests for decorator correctness properties
2223
+ - Integration tests for full controller with all decorators
2224
+ - E2E tests for HTTP requests to decorated endpoints
2225
+
2226
+ **Deprecations:**
2227
+ - None. This release is fully backward compatible with existing code.
2228
+
1363
2229
  ### Version 3.11.x (3.11.0 - 3.11.20)
1364
2230
 
1365
2231
  **String Key Enum Registration & translateStringKey Support**