@catbee/utils 0.0.8-rc.0 → 0.0.8-rc.2

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 (281) hide show
  1. package/README.md +25 -1
  2. package/build/esm/config.d.ts +0 -1
  3. package/build/esm/config.js +6 -7
  4. package/build/esm/index.d.ts +0 -1
  5. package/build/esm/index.js +0 -1
  6. package/build/esm/servers/server.builder.d.ts +0 -1
  7. package/build/esm/servers/server.builder.js +99 -147
  8. package/build/esm/servers/server.d.ts +0 -1
  9. package/build/esm/servers/server.js +591 -876
  10. package/build/esm/types/api-response.d.ts +0 -1
  11. package/build/esm/types/api-response.js +0 -1
  12. package/build/esm/types/index.d.ts +0 -1
  13. package/build/esm/types/index.js +0 -1
  14. package/build/esm/types/server.d.ts +0 -1
  15. package/build/esm/types/server.js +0 -1
  16. package/build/esm/utils/array.utils.d.ts +0 -1
  17. package/build/esm/utils/array.utils.js +48 -86
  18. package/build/esm/utils/async.utils.d.ts +0 -1
  19. package/build/esm/utils/async.utils.js +247 -524
  20. package/build/esm/utils/cache.utils.d.ts +0 -1
  21. package/build/esm/utils/cache.utils.js +96 -301
  22. package/build/esm/utils/context-store.utils.d.ts +0 -1
  23. package/build/esm/utils/context-store.utils.js +62 -79
  24. package/build/esm/utils/crypto.utils.d.ts +0 -1
  25. package/build/esm/utils/crypto.utils.js +78 -175
  26. package/build/esm/utils/date.utils.d.ts +0 -1
  27. package/build/esm/utils/date.utils.js +47 -53
  28. package/build/esm/utils/decorators.utils.d.ts +201 -5
  29. package/build/esm/utils/decorators.utils.js +632 -285
  30. package/build/esm/utils/dir.utils.d.ts +0 -1
  31. package/build/esm/utils/dir.utils.js +264 -786
  32. package/build/esm/utils/env.utils.d.ts +0 -1
  33. package/build/esm/utils/env.utils.js +180 -271
  34. package/build/esm/utils/exception.utils.d.ts +0 -1
  35. package/build/esm/utils/exception.utils.js +112 -289
  36. package/build/esm/utils/fs.utils.d.ts +0 -1
  37. package/build/esm/utils/fs.utils.js +169 -401
  38. package/build/esm/utils/http-status-codes.d.ts +0 -1
  39. package/build/esm/utils/http-status-codes.js +0 -1
  40. package/build/esm/utils/id.utils.d.ts +0 -1
  41. package/build/esm/utils/id.utils.js +5 -9
  42. package/build/esm/utils/logger.utils.d.ts +0 -1
  43. package/build/esm/utils/logger.utils.js +34 -71
  44. package/build/esm/utils/middleware.utils.d.ts +0 -1
  45. package/build/esm/utils/middleware.utils.js +65 -155
  46. package/build/esm/utils/obj.utils.d.ts +0 -1
  47. package/build/esm/utils/obj.utils.js +69 -176
  48. package/build/esm/utils/performance.utils.d.ts +0 -1
  49. package/build/esm/utils/performance.utils.js +92 -195
  50. package/build/esm/utils/request.utils.d.ts +0 -1
  51. package/build/esm/utils/request.utils.js +41 -74
  52. package/build/esm/utils/response.utils.d.ts +0 -1
  53. package/build/esm/utils/response.utils.js +84 -107
  54. package/build/esm/utils/stream.utils.d.ts +0 -1
  55. package/build/esm/utils/stream.utils.js +38 -113
  56. package/build/esm/utils/string.utils.d.ts +0 -1
  57. package/build/esm/utils/string.utils.js +6 -11
  58. package/build/esm/utils/type.utils.d.ts +0 -1
  59. package/build/esm/utils/type.utils.js +8 -12
  60. package/build/esm/utils/url.utils.d.ts +0 -1
  61. package/build/esm/utils/url.utils.js +49 -127
  62. package/build/esm/utils/validate.utils.d.ts +0 -1
  63. package/build/esm/utils/validate.utils.js +23 -40
  64. package/package.json +3 -33
  65. package/build/esm/config.js.map +0 -1
  66. package/build/esm/index.js.map +0 -1
  67. package/build/esm/servers/server.builder.js.map +0 -1
  68. package/build/esm/servers/server.js.map +0 -1
  69. package/build/esm/types/api-response.js.map +0 -1
  70. package/build/esm/types/index.js.map +0 -1
  71. package/build/esm/types/server.js.map +0 -1
  72. package/build/esm/utils/array.utils.js.map +0 -1
  73. package/build/esm/utils/async.utils.js.map +0 -1
  74. package/build/esm/utils/cache.utils.js.map +0 -1
  75. package/build/esm/utils/context-store.utils.js.map +0 -1
  76. package/build/esm/utils/crypto.utils.js.map +0 -1
  77. package/build/esm/utils/date.utils.js.map +0 -1
  78. package/build/esm/utils/decorators.utils.js.map +0 -1
  79. package/build/esm/utils/dir.utils.js.map +0 -1
  80. package/build/esm/utils/env.utils.js.map +0 -1
  81. package/build/esm/utils/exception.utils.js.map +0 -1
  82. package/build/esm/utils/fs.utils.js.map +0 -1
  83. package/build/esm/utils/http-status-codes.js.map +0 -1
  84. package/build/esm/utils/id.utils.js.map +0 -1
  85. package/build/esm/utils/logger.utils.js.map +0 -1
  86. package/build/esm/utils/middleware.utils.js.map +0 -1
  87. package/build/esm/utils/obj.utils.js.map +0 -1
  88. package/build/esm/utils/performance.utils.js.map +0 -1
  89. package/build/esm/utils/request.utils.js.map +0 -1
  90. package/build/esm/utils/response.utils.js.map +0 -1
  91. package/build/esm/utils/stream.utils.js.map +0 -1
  92. package/build/esm/utils/string.utils.js.map +0 -1
  93. package/build/esm/utils/type.utils.js.map +0 -1
  94. package/build/esm/utils/url.utils.js.map +0 -1
  95. package/build/esm/utils/validate.utils.js.map +0 -1
  96. package/build/esnext/config.d.ts +0 -122
  97. package/build/esnext/config.js +0 -133
  98. package/build/esnext/config.js.map +0 -1
  99. package/build/esnext/index.d.ts +0 -27
  100. package/build/esnext/index.js +0 -50
  101. package/build/esnext/index.js.map +0 -1
  102. package/build/esnext/servers/server.builder.d.ts +0 -508
  103. package/build/esnext/servers/server.builder.js +0 -657
  104. package/build/esnext/servers/server.builder.js.map +0 -1
  105. package/build/esnext/servers/server.d.ts +0 -256
  106. package/build/esnext/servers/server.js +0 -955
  107. package/build/esnext/servers/server.js.map +0 -1
  108. package/build/esnext/types/api-response.d.ts +0 -152
  109. package/build/esnext/types/api-response.js +0 -34
  110. package/build/esnext/types/api-response.js.map +0 -1
  111. package/build/esnext/types/index.d.ts +0 -125
  112. package/build/esnext/types/index.js +0 -25
  113. package/build/esnext/types/index.js.map +0 -1
  114. package/build/esnext/types/server.d.ts +0 -268
  115. package/build/esnext/types/server.js +0 -25
  116. package/build/esnext/types/server.js.map +0 -1
  117. package/build/esnext/utils/array.utils.d.ts +0 -168
  118. package/build/esnext/utils/array.utils.js +0 -345
  119. package/build/esnext/utils/array.utils.js.map +0 -1
  120. package/build/esnext/utils/async.utils.d.ts +0 -265
  121. package/build/esnext/utils/async.utils.js +0 -620
  122. package/build/esnext/utils/async.utils.js.map +0 -1
  123. package/build/esnext/utils/cache.utils.d.ts +0 -153
  124. package/build/esnext/utils/cache.utils.js +0 -293
  125. package/build/esnext/utils/cache.utils.js.map +0 -1
  126. package/build/esnext/utils/context-store.utils.d.ts +0 -189
  127. package/build/esnext/utils/context-store.utils.js +0 -289
  128. package/build/esnext/utils/context-store.utils.js.map +0 -1
  129. package/build/esnext/utils/crypto.utils.d.ts +0 -160
  130. package/build/esnext/utils/crypto.utils.js +0 -276
  131. package/build/esnext/utils/crypto.utils.js.map +0 -1
  132. package/build/esnext/utils/date.utils.d.ts +0 -159
  133. package/build/esnext/utils/date.utils.js +0 -384
  134. package/build/esnext/utils/date.utils.js.map +0 -1
  135. package/build/esnext/utils/decorators.utils.d.ts +0 -315
  136. package/build/esnext/utils/decorators.utils.js +0 -504
  137. package/build/esnext/utils/decorators.utils.js.map +0 -1
  138. package/build/esnext/utils/dir.utils.d.ts +0 -196
  139. package/build/esnext/utils/dir.utils.js +0 -477
  140. package/build/esnext/utils/dir.utils.js.map +0 -1
  141. package/build/esnext/utils/env.utils.d.ts +0 -377
  142. package/build/esnext/utils/env.utils.js +0 -785
  143. package/build/esnext/utils/env.utils.js.map +0 -1
  144. package/build/esnext/utils/exception.utils.d.ts +0 -230
  145. package/build/esnext/utils/exception.utils.js +0 -381
  146. package/build/esnext/utils/exception.utils.js.map +0 -1
  147. package/build/esnext/utils/fs.utils.d.ts +0 -164
  148. package/build/esnext/utils/fs.utils.js +0 -349
  149. package/build/esnext/utils/fs.utils.js.map +0 -1
  150. package/build/esnext/utils/http-status-codes.d.ts +0 -266
  151. package/build/esnext/utils/http-status-codes.js +0 -295
  152. package/build/esnext/utils/http-status-codes.js.map +0 -1
  153. package/build/esnext/utils/id.utils.d.ts +0 -36
  154. package/build/esnext/utils/id.utils.js +0 -84
  155. package/build/esnext/utils/id.utils.js.map +0 -1
  156. package/build/esnext/utils/logger.utils.d.ts +0 -160
  157. package/build/esnext/utils/logger.utils.js +0 -300
  158. package/build/esnext/utils/logger.utils.js.map +0 -1
  159. package/build/esnext/utils/middleware.utils.d.ts +0 -100
  160. package/build/esnext/utils/middleware.utils.js +0 -236
  161. package/build/esnext/utils/middleware.utils.js.map +0 -1
  162. package/build/esnext/utils/obj.utils.d.ts +0 -124
  163. package/build/esnext/utils/obj.utils.js +0 -413
  164. package/build/esnext/utils/obj.utils.js.map +0 -1
  165. package/build/esnext/utils/performance.utils.d.ts +0 -136
  166. package/build/esnext/utils/performance.utils.js +0 -271
  167. package/build/esnext/utils/performance.utils.js.map +0 -1
  168. package/build/esnext/utils/request.utils.d.ts +0 -86
  169. package/build/esnext/utils/request.utils.js +0 -186
  170. package/build/esnext/utils/request.utils.js.map +0 -1
  171. package/build/esnext/utils/response.utils.d.ts +0 -163
  172. package/build/esnext/utils/response.utils.js +0 -247
  173. package/build/esnext/utils/response.utils.js.map +0 -1
  174. package/build/esnext/utils/stream.utils.d.ts +0 -88
  175. package/build/esnext/utils/stream.utils.js +0 -210
  176. package/build/esnext/utils/stream.utils.js.map +0 -1
  177. package/build/esnext/utils/string.utils.d.ts +0 -93
  178. package/build/esnext/utils/string.utils.js +0 -165
  179. package/build/esnext/utils/string.utils.js.map +0 -1
  180. package/build/esnext/utils/type.utils.d.ts +0 -90
  181. package/build/esnext/utils/type.utils.js +0 -187
  182. package/build/esnext/utils/type.utils.js.map +0 -1
  183. package/build/esnext/utils/url.utils.d.ts +0 -141
  184. package/build/esnext/utils/url.utils.js +0 -304
  185. package/build/esnext/utils/url.utils.js.map +0 -1
  186. package/build/esnext/utils/validate.utils.d.ts +0 -177
  187. package/build/esnext/utils/validate.utils.js +0 -320
  188. package/build/esnext/utils/validate.utils.js.map +0 -1
  189. package/build/src/config.d.ts +0 -122
  190. package/build/src/config.js +0 -138
  191. package/build/src/config.js.map +0 -1
  192. package/build/src/index.d.ts +0 -27
  193. package/build/src/index.js +0 -69
  194. package/build/src/index.js.map +0 -1
  195. package/build/src/servers/server.builder.d.ts +0 -508
  196. package/build/src/servers/server.builder.js +0 -661
  197. package/build/src/servers/server.builder.js.map +0 -1
  198. package/build/src/servers/server.d.ts +0 -256
  199. package/build/src/servers/server.js +0 -962
  200. package/build/src/servers/server.js.map +0 -1
  201. package/build/src/types/api-response.d.ts +0 -152
  202. package/build/src/types/api-response.js +0 -37
  203. package/build/src/types/api-response.js.map +0 -1
  204. package/build/src/types/index.d.ts +0 -125
  205. package/build/src/types/index.js +0 -26
  206. package/build/src/types/index.js.map +0 -1
  207. package/build/src/types/server.d.ts +0 -268
  208. package/build/src/types/server.js +0 -26
  209. package/build/src/types/server.js.map +0 -1
  210. package/build/src/utils/array.utils.d.ts +0 -168
  211. package/build/src/utils/array.utils.js +0 -364
  212. package/build/src/utils/array.utils.js.map +0 -1
  213. package/build/src/utils/async.utils.d.ts +0 -265
  214. package/build/src/utils/async.utils.js +0 -641
  215. package/build/src/utils/async.utils.js.map +0 -1
  216. package/build/src/utils/cache.utils.d.ts +0 -153
  217. package/build/src/utils/cache.utils.js +0 -297
  218. package/build/src/utils/cache.utils.js.map +0 -1
  219. package/build/src/utils/context-store.utils.d.ts +0 -189
  220. package/build/src/utils/context-store.utils.js +0 -296
  221. package/build/src/utils/context-store.utils.js.map +0 -1
  222. package/build/src/utils/crypto.utils.d.ts +0 -160
  223. package/build/src/utils/crypto.utils.js +0 -293
  224. package/build/src/utils/crypto.utils.js.map +0 -1
  225. package/build/src/utils/date.utils.d.ts +0 -159
  226. package/build/src/utils/date.utils.js +0 -396
  227. package/build/src/utils/date.utils.js.map +0 -1
  228. package/build/src/utils/decorators.utils.d.ts +0 -315
  229. package/build/src/utils/decorators.utils.js +0 -516
  230. package/build/src/utils/decorators.utils.js.map +0 -1
  231. package/build/src/utils/dir.utils.d.ts +0 -196
  232. package/build/src/utils/dir.utils.js +0 -501
  233. package/build/src/utils/dir.utils.js.map +0 -1
  234. package/build/src/utils/env.utils.d.ts +0 -377
  235. package/build/src/utils/env.utils.js +0 -789
  236. package/build/src/utils/env.utils.js.map +0 -1
  237. package/build/src/utils/exception.utils.d.ts +0 -230
  238. package/build/src/utils/exception.utils.js +0 -407
  239. package/build/src/utils/exception.utils.js.map +0 -1
  240. package/build/src/utils/fs.utils.d.ts +0 -164
  241. package/build/src/utils/fs.utils.js +0 -372
  242. package/build/src/utils/fs.utils.js.map +0 -1
  243. package/build/src/utils/http-status-codes.d.ts +0 -266
  244. package/build/src/utils/http-status-codes.js +0 -298
  245. package/build/src/utils/http-status-codes.js.map +0 -1
  246. package/build/src/utils/id.utils.d.ts +0 -36
  247. package/build/src/utils/id.utils.js +0 -91
  248. package/build/src/utils/id.utils.js.map +0 -1
  249. package/build/src/utils/logger.utils.d.ts +0 -160
  250. package/build/src/utils/logger.utils.js +0 -346
  251. package/build/src/utils/logger.utils.js.map +0 -1
  252. package/build/src/utils/middleware.utils.d.ts +0 -100
  253. package/build/src/utils/middleware.utils.js +0 -244
  254. package/build/src/utils/middleware.utils.js.map +0 -1
  255. package/build/src/utils/obj.utils.d.ts +0 -124
  256. package/build/src/utils/obj.utils.js +0 -429
  257. package/build/src/utils/obj.utils.js.map +0 -1
  258. package/build/src/utils/performance.utils.d.ts +0 -136
  259. package/build/src/utils/performance.utils.js +0 -278
  260. package/build/src/utils/performance.utils.js.map +0 -1
  261. package/build/src/utils/request.utils.d.ts +0 -86
  262. package/build/src/utils/request.utils.js +0 -195
  263. package/build/src/utils/request.utils.js.map +0 -1
  264. package/build/src/utils/response.utils.d.ts +0 -163
  265. package/build/src/utils/response.utils.js +0 -260
  266. package/build/src/utils/response.utils.js.map +0 -1
  267. package/build/src/utils/stream.utils.d.ts +0 -88
  268. package/build/src/utils/stream.utils.js +0 -218
  269. package/build/src/utils/stream.utils.js.map +0 -1
  270. package/build/src/utils/string.utils.d.ts +0 -93
  271. package/build/src/utils/string.utils.js +0 -179
  272. package/build/src/utils/string.utils.js.map +0 -1
  273. package/build/src/utils/type.utils.d.ts +0 -90
  274. package/build/src/utils/type.utils.js +0 -196
  275. package/build/src/utils/type.utils.js.map +0 -1
  276. package/build/src/utils/url.utils.d.ts +0 -141
  277. package/build/src/utils/url.utils.js +0 -317
  278. package/build/src/utils/url.utils.js.map +0 -1
  279. package/build/src/utils/validate.utils.d.ts +0 -177
  280. package/build/src/utils/validate.utils.js +0 -345
  281. package/build/src/utils/validate.utils.js.map +0 -1
@@ -21,91 +21,153 @@
21
21
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
22
  * SOFTWARE.
23
23
  */
24
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
25
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
26
- return new (P || (P = Promise))(function (resolve, reject) {
27
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
28
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
29
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
30
- step((generator = generator.apply(thisArg, _arguments || [])).next());
31
- });
32
- };
33
- var __generator = (this && this.__generator) || function (thisArg, body) {
34
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
35
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
36
- function verb(n) { return function (v) { return step([n, v]); }; }
37
- function step(op) {
38
- if (f) throw new TypeError("Generator is already executing.");
39
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
40
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
41
- if (y = 0, t) op = [op[0] & 2, t.value];
42
- switch (op[0]) {
43
- case 0: case 1: t = op; break;
44
- case 4: _.label++; return { value: op[1], done: false };
45
- case 5: _.label++; y = op[1]; op = [0]; continue;
46
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
47
- default:
48
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
49
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
50
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
51
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
52
- if (t[2]) _.ops.pop();
53
- _.trys.pop(); continue;
54
- }
55
- op = body.call(thisArg, _);
56
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
57
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
24
+ import 'reflect-metadata';
25
+ import { getLogger } from './logger.utils';
26
+ import { createFinalErrorResponse } from './response.utils';
27
+ import { HttpStatusCodes } from './http-status-codes';
28
+ import { rateLimit } from 'express-rate-limit';
29
+ import { TTLCache } from './cache.utils';
30
+ // Metadata keys
31
+ const ROUTES_KEY = Symbol('routes');
32
+ const MIDDLEWARE_KEY = Symbol('middlewares');
33
+ const PARAMS_KEY = Symbol('params');
34
+ const HTTP_CODE_KEY = Symbol('httpCode');
35
+ const HEADER_KEY = Symbol('headers');
36
+ const BEFORE_KEY = Symbol('before');
37
+ const AFTER_KEY = Symbol('after');
38
+ const ROLES_KEY = Symbol('roles');
39
+ const REDIRECT_KEY = Symbol('redirect');
40
+ const CACHE_KEY = Symbol('cache');
41
+ const RATE_LIMIT_KEY = Symbol('rateLimit');
42
+ const CONTENT_TYPE_KEY = Symbol('contentType');
43
+ const VERSION_KEY = Symbol('version');
44
+ const TIMEOUT_KEY = Symbol('timeout');
45
+ const LOG_KEY = Symbol('log');
46
+ /**
47
+ * RateLimiter cache that uses TTLCache for automatic TTL and LRU handling.
48
+ */
49
+ class RateLimiterCache {
50
+ cache;
51
+ constructor(maxSize = 100, ttlMs = 5 * 60 * 1000) {
52
+ this.cache = new TTLCache({
53
+ maxSize,
54
+ ttlMs
55
+ });
58
56
  }
59
- };
60
- var __read = (this && this.__read) || function (o, n) {
61
- var m = typeof Symbol === "function" && o[Symbol.iterator];
62
- if (!m) return o;
63
- var i = m.call(o), r, ar = [], e;
64
- try {
65
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
57
+ generateKey(options) {
58
+ return `${options.max}:${options.windowMs}:${options.standardHeaders}:${options.legacyHeaders}`;
66
59
  }
67
- catch (error) { e = { error: error }; }
68
- finally {
69
- try {
70
- if (r && !r.done && (m = i["return"])) m.call(i);
60
+ get(options) {
61
+ const key = this.generateKey(options);
62
+ const cached = this.cache.get(key);
63
+ if (cached) {
64
+ return cached.limiter;
71
65
  }
72
- finally { if (e) throw e.error; }
66
+ // Create new limiter
67
+ const limiter = rateLimit({
68
+ ...options,
69
+ handler: (req, res) => {
70
+ const errorResponse = createFinalErrorResponse(req, HttpStatusCodes.TOO_MANY_REQUESTS, 'Too Many Requests');
71
+ res.status(HttpStatusCodes.TOO_MANY_REQUESTS).json(errorResponse);
72
+ }
73
+ });
74
+ // Store in cache
75
+ this.cache.set(key, {
76
+ limiter,
77
+ config: key
78
+ });
79
+ return limiter;
73
80
  }
74
- return ar;
75
- };
76
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
77
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
78
- if (ar || !(i in from)) {
79
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
80
- ar[i] = from[i];
81
+ clear() {
82
+ this.cache.clear();
83
+ }
84
+ size() {
85
+ return this.cache.size();
86
+ }
87
+ destroy() {
88
+ this.cache.destroy();
89
+ }
90
+ }
91
+ // Global cache instance
92
+ const rateLimiterCache = new RateLimiterCache();
93
+ export class DIContainer {
94
+ instances = new Map();
95
+ constructing = new Map();
96
+ register(target) {
97
+ // Mark as injectable, but do not instantiate yet
98
+ if (!this.instances.has(target) && !this.constructing.has(target)) {
99
+ // No-op: instantiation is deferred until get()
81
100
  }
82
101
  }
83
- return to.concat(ar || Array.prototype.slice.call(from));
84
- };
85
- var __values = (this && this.__values) || function(o) {
86
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
87
- if (m) return m.call(o);
88
- if (o && typeof o.length === "number") return {
89
- next: function () {
90
- if (o && i >= o.length) o = void 0;
91
- return { value: o && o[i++], done: !o };
102
+ get(target) {
103
+ // Return existing instance if available
104
+ if (this.instances.has(target)) {
105
+ return this.instances.get(target);
106
+ }
107
+ // If currently constructing, return the proxy (for circular refs)
108
+ if (this.constructing.has(target)) {
109
+ return this.constructing.get(target);
92
110
  }
111
+ // Mark as constructing (for circular dependency support)
112
+ let proxy = {};
113
+ this.constructing.set(target, proxy);
114
+ // Resolve constructor dependencies
115
+ const paramTypes = Reflect.getMetadata('design:paramtypes', target) || [];
116
+ const dependencies = paramTypes.map(dep => this.get(dep));
117
+ const instance = new target(...dependencies);
118
+ // Copy instance properties to proxy (for circular refs)
119
+ Object.assign(proxy, instance);
120
+ // Replace proxy with real instance
121
+ this.instances.set(target, proxy);
122
+ this.constructing.delete(target);
123
+ // Copy prototype (for instanceof checks)
124
+ Object.setPrototypeOf(proxy, target.prototype);
125
+ return proxy;
126
+ }
127
+ clear() {
128
+ this.instances.clear();
129
+ this.constructing.clear();
130
+ }
131
+ }
132
+ const diContainer = new DIContainer();
133
+ function normalizeHeaderValue(value) {
134
+ if (typeof value === 'undefined')
135
+ return undefined;
136
+ if (typeof value === 'string')
137
+ return value;
138
+ if (Array.isArray(value) && value.every(item => typeof item === 'string')) {
139
+ return value;
140
+ }
141
+ return String(value);
142
+ }
143
+ /**
144
+ * Injectable decorator for marking classes as injectable.
145
+ *
146
+ * @returns Class decorator that marks a class as injectable and registers it with the DI container.
147
+ */
148
+ export function Injectable() {
149
+ return target => {
150
+ Reflect.defineMetadata('injectable', true, target);
151
+ diContainer.register(target);
93
152
  };
94
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
95
- };
96
- import 'reflect-metadata';
97
- import { HttpStatusCodes } from './http-status-codes';
98
- import { ForbiddenException } from './exception.utils';
99
- // Metadata keys
100
- var ROUTES_KEY = Symbol('routes');
101
- var MIDDLEWARE_KEY = Symbol('middlewares');
102
- var PARAMS_KEY = Symbol('params');
103
- var HTTP_CODE_KEY = Symbol('httpCode');
104
- var HEADER_KEY = Symbol('headers');
105
- var BEFORE_KEY = Symbol('before');
106
- var AFTER_KEY = Symbol('after');
107
- var ROLES_KEY = Symbol('roles');
108
- var REDIRECT_KEY = Symbol('redirect');
153
+ }
154
+ /**
155
+ * Inject decorator for injecting dependencies into class properties.
156
+ *
157
+ * @param targetClass - The class to inject
158
+ * @returns Property decorator that injects the specified class into the property
159
+ */
160
+ export function Inject(targetClass) {
161
+ return (target, propertyKey) => {
162
+ Object.defineProperty(target, propertyKey, {
163
+ get: function () {
164
+ return diContainer.get(targetClass);
165
+ },
166
+ enumerable: true,
167
+ configurable: true
168
+ });
169
+ };
170
+ }
109
171
  /**
110
172
  * Factory function that creates HTTP method decorators.
111
173
  *
@@ -113,12 +175,12 @@ var REDIRECT_KEY = Symbol('redirect');
113
175
  * @returns A method decorator function
114
176
  */
115
177
  function createRouteDecorator(method) {
116
- return function (path) {
117
- return function (target, propertyKey, descriptor) {
118
- var routes = Reflect.getMetadata(ROUTES_KEY, target.constructor) || [];
178
+ return (path) => {
179
+ return (target, propertyKey, descriptor) => {
180
+ const routes = Reflect.getMetadata(ROUTES_KEY, target.constructor) || [];
119
181
  routes.push({
120
- path: path,
121
- method: method,
182
+ path,
183
+ method,
122
184
  handlerName: propertyKey
123
185
  });
124
186
  Reflect.defineMetadata(ROUTES_KEY, routes, target.constructor);
@@ -139,7 +201,7 @@ function createRouteDecorator(method) {
139
201
  * }
140
202
  * ```
141
203
  */
142
- export var Get = createRouteDecorator('get');
204
+ export const Get = createRouteDecorator('get');
143
205
  /**
144
206
  * Decorator for POST HTTP method routes.
145
207
  *
@@ -154,56 +216,56 @@ export var Get = createRouteDecorator('get');
154
216
  * }
155
217
  * ```
156
218
  */
157
- export var Post = createRouteDecorator('post');
219
+ export const Post = createRouteDecorator('post');
158
220
  /**
159
221
  * Decorator for PUT HTTP method routes.
160
222
  *
161
223
  * @param path - URL path for the route
162
224
  * @returns Method decorator
163
225
  */
164
- export var Put = createRouteDecorator('put');
226
+ export const Put = createRouteDecorator('put');
165
227
  /**
166
228
  * Decorator for PATCH HTTP method routes.
167
229
  *
168
230
  * @param path - URL path for the route
169
231
  * @returns Method decorator
170
232
  */
171
- export var Patch = createRouteDecorator('patch');
233
+ export const Patch = createRouteDecorator('patch');
172
234
  /**
173
235
  * Decorator for DELETE HTTP method routes.
174
236
  *
175
237
  * @param path - URL path for the route
176
238
  * @returns Method decorator
177
239
  */
178
- export var Delete = createRouteDecorator('delete');
240
+ export const Delete = createRouteDecorator('delete');
179
241
  /**
180
242
  * Decorator for OPTIONS HTTP method routes.
181
243
  *
182
244
  * @param path - URL path for the route
183
245
  * @returns Method decorator
184
246
  */
185
- export var Options = createRouteDecorator('options');
247
+ export const Options = createRouteDecorator('options');
186
248
  /**
187
249
  * Decorator for HEAD HTTP method routes.
188
250
  *
189
251
  * @param path - URL path for the route
190
252
  * @returns Method decorator
191
253
  */
192
- export var Head = createRouteDecorator('head');
254
+ export const Head = createRouteDecorator('head');
193
255
  /**
194
256
  * Decorator for TRACE HTTP method routes.
195
257
  *
196
258
  * @param path - URL path for the route
197
259
  * @returns Method decorator
198
260
  */
199
- export var Trace = createRouteDecorator('trace');
261
+ export const Trace = createRouteDecorator('trace');
200
262
  /**
201
263
  * Decorator for CONNECT HTTP method routes.
202
264
  *
203
265
  * @param path - URL path for the route
204
266
  * @returns Method decorator
205
267
  */
206
- export var Connect = createRouteDecorator('connect');
268
+ export const Connect = createRouteDecorator('connect');
207
269
  /**
208
270
  * Decorator that marks a class as a controller with a base path.
209
271
  * Used as the entry point for routing configuration.
@@ -220,7 +282,7 @@ export var Connect = createRouteDecorator('connect');
220
282
  * ```
221
283
  */
222
284
  export function Controller(basePath) {
223
- return function (target) {
285
+ return target => {
224
286
  Reflect.defineMetadata('basePath', basePath, target);
225
287
  };
226
288
  }
@@ -240,14 +302,10 @@ export function Controller(basePath) {
240
302
  * }
241
303
  * ```
242
304
  */
243
- export function Use() {
244
- var middlewares = [];
245
- for (var _i = 0; _i < arguments.length; _i++) {
246
- middlewares[_i] = arguments[_i];
247
- }
248
- return function (target, propertyKey, _descriptor) {
249
- var existing = Reflect.getMetadata(MIDDLEWARE_KEY, target, propertyKey) || [];
250
- Reflect.defineMetadata(MIDDLEWARE_KEY, __spreadArray(__spreadArray([], __read(existing), false), __read(middlewares), false), target, propertyKey);
305
+ export function Use(...middlewares) {
306
+ return (target, propertyKey, _descriptor) => {
307
+ const existing = Reflect.getMetadata(MIDDLEWARE_KEY, target, propertyKey) || [];
308
+ Reflect.defineMetadata(MIDDLEWARE_KEY, [...existing, ...middlewares], target, propertyKey);
251
309
  };
252
310
  }
253
311
  /**
@@ -258,12 +316,12 @@ export function Use() {
258
316
  * @returns Parameter decorator function
259
317
  */
260
318
  function createParamDecorator(type, key) {
261
- return function (paramKey) {
262
- return function (target, propertyKey, parameterIndex) {
263
- var params = Reflect.getMetadata(PARAMS_KEY, target, propertyKey) || [];
319
+ return (paramKey) => {
320
+ return (target, propertyKey, parameterIndex) => {
321
+ const params = Reflect.getMetadata(PARAMS_KEY, target, propertyKey) || [];
264
322
  // Ensure parameters are ordered by index
265
- params.push({ index: parameterIndex, type: type, key: paramKey || key });
266
- params.sort(function (a, b) { return a.index - b.index; });
323
+ params.push({ index: parameterIndex, type, key: paramKey || key });
324
+ params.sort((a, b) => a.index - b.index);
267
325
  Reflect.defineMetadata(PARAMS_KEY, params, target, propertyKey);
268
326
  };
269
327
  };
@@ -282,7 +340,7 @@ function createParamDecorator(type, key) {
282
340
  * }
283
341
  * ```
284
342
  */
285
- export var Query = createParamDecorator('query');
343
+ export const Query = createParamDecorator('query');
286
344
  /**
287
345
  * Decorator that extracts route parameters from request.
288
346
  *
@@ -297,7 +355,7 @@ export var Query = createParamDecorator('query');
297
355
  * }
298
356
  * ```
299
357
  */
300
- export var Param = createParamDecorator('param');
358
+ export const Param = createParamDecorator('param');
301
359
  /**
302
360
  * Decorator that extracts body or body property from request.
303
361
  *
@@ -317,7 +375,7 @@ export var Param = createParamDecorator('param');
317
375
  * }
318
376
  * ```
319
377
  */
320
- export var Body = createParamDecorator('body');
378
+ export const Body = createParamDecorator('body');
321
379
  /**
322
380
  * Decorator that injects the entire request object.
323
381
  *
@@ -332,7 +390,7 @@ export var Body = createParamDecorator('body');
332
390
  * }
333
391
  * ```
334
392
  */
335
- export var Req = createParamDecorator('req');
393
+ export const Req = createParamDecorator('req');
336
394
  /**
337
395
  * Decorator that injects the response object.
338
396
  *
@@ -347,7 +405,7 @@ export var Req = createParamDecorator('req');
347
405
  * }
348
406
  * ```
349
407
  */
350
- export var Res = createParamDecorator('res');
408
+ export const Res = createParamDecorator('res');
351
409
  /**
352
410
  * Decorator that sets a custom HTTP status code for a response.
353
411
  *
@@ -365,15 +423,15 @@ export var Res = createParamDecorator('res');
365
423
  * ```
366
424
  */
367
425
  export function HttpCode(status) {
368
- return function (target, propertyKey, _descriptor) {
426
+ return (target, propertyKey, _descriptor) => {
369
427
  Reflect.defineMetadata(HTTP_CODE_KEY, status, target, propertyKey);
370
428
  };
371
429
  }
372
430
  /**
373
431
  * Decorator that adds a custom HTTP header to the response.
374
432
  *
375
- * @param name - Header name
376
- * @param value - Header value
433
+ * @param header - Header name-value pairs or a single header name and value
434
+ * @param value - Header value if a single header name is provided
377
435
  * @returns Method decorator
378
436
  *
379
437
  * @example
@@ -384,13 +442,53 @@ export function HttpCode(status) {
384
442
  * // Response will include the Cache-Control header
385
443
  * return { data: '...' };
386
444
  * }
387
- * ```
388
445
  */
389
446
  export function Header(name, value) {
390
- return function (target, propertyKey, _descriptor) {
391
- var headers = Reflect.getMetadata(HEADER_KEY, target, propertyKey) || {};
392
- headers[name] = value;
393
- Reflect.defineMetadata(HEADER_KEY, headers, target, propertyKey);
447
+ return Headers(name, value);
448
+ }
449
+ /**
450
+ * Decorator that adds a custom HTTP headers to the response.
451
+ *
452
+ * @param headers - Header name-value pairs or a single header name and value
453
+ * @param value - Header value if a single header name is provided
454
+ * @returns Method decorator
455
+ *
456
+ * @example
457
+ * ```ts
458
+ * @Get('/data')
459
+ * @Headers('Cache-Control', 'max-age=60')
460
+ * getData() {
461
+ * // Response will include the Cache-Control header
462
+ * return { data: '...' };
463
+ * }
464
+ *
465
+ * @Get('/data/:id')
466
+ * @Headers({
467
+ * 'Cache-Control': 'max-age=60',
468
+ * 'X-Custom-Header': 'custom-value',
469
+ * 'Content-Security-Policy': "default-src 'self'"
470
+ * })
471
+ * getData() {
472
+ * // Response will include all specified headers
473
+ * return { data: '...' };
474
+ * }
475
+ *
476
+ * ```
477
+ */
478
+ export function Headers(headers, value) {
479
+ return (target, propertyKey) => {
480
+ if (typeof propertyKey === 'undefined') {
481
+ // Class decorator
482
+ const existing = Reflect.getMetadata(HEADER_KEY, target) || {};
483
+ const newHeaders = typeof headers === 'string' ? { [headers]: value } : headers;
484
+ Reflect.defineMetadata(HEADER_KEY, { ...existing, ...newHeaders }, target);
485
+ }
486
+ else {
487
+ // Method decorator
488
+ const existing = Reflect.getMetadata(HEADER_KEY, target, propertyKey) || {};
489
+ const newHeaders = typeof headers === 'string' ? { [headers]: value } : headers;
490
+ Reflect.defineMetadata(HEADER_KEY, { ...existing, ...newHeaders }, target, propertyKey);
491
+ }
394
492
  };
395
493
  }
396
494
  /**
@@ -410,8 +508,8 @@ export function Header(name, value) {
410
508
  * ```
411
509
  */
412
510
  export function Before(fn) {
413
- return function (target, propertyKey, _descriptor) {
414
- var hooks = Reflect.getMetadata(BEFORE_KEY, target, propertyKey) || [];
511
+ return (target, propertyKey, _descriptor) => {
512
+ const hooks = Reflect.getMetadata(BEFORE_KEY, target, propertyKey) || [];
415
513
  hooks.push(fn);
416
514
  Reflect.defineMetadata(BEFORE_KEY, hooks, target, propertyKey);
417
515
  };
@@ -434,8 +532,8 @@ export function Before(fn) {
434
532
  * ```
435
533
  */
436
534
  export function After(fn) {
437
- return function (target, propertyKey, _descriptor) {
438
- var hooks = Reflect.getMetadata(AFTER_KEY, target, propertyKey) || [];
535
+ return (target, propertyKey, _descriptor) => {
536
+ const hooks = Reflect.getMetadata(AFTER_KEY, target, propertyKey) || [];
439
537
  hooks.push(fn);
440
538
  Reflect.defineMetadata(AFTER_KEY, hooks, target, propertyKey);
441
539
  };
@@ -444,6 +542,8 @@ export function After(fn) {
444
542
  * Decorator that requires specific roles for accessing a route.
445
543
  * Must be used with authentication middleware.
446
544
  *
545
+ * Check req.user.roles for user roles[].
546
+ *
447
547
  * @param roles - List of roles that can access this route
448
548
  * @returns Method decorator
449
549
  *
@@ -457,13 +557,16 @@ export function After(fn) {
457
557
  * }
458
558
  * ```
459
559
  */
460
- export function Roles() {
461
- var roles = [];
462
- for (var _i = 0; _i < arguments.length; _i++) {
463
- roles[_i] = arguments[_i];
464
- }
465
- return function (target, propertyKey, _descriptor) {
466
- Reflect.defineMetadata(ROLES_KEY, roles, target, propertyKey);
560
+ export function Roles(...roles) {
561
+ return (target, propertyKey, _descriptor) => {
562
+ if (typeof propertyKey === 'undefined') {
563
+ // Class decorator
564
+ Reflect.defineMetadata(ROLES_KEY, roles, target);
565
+ }
566
+ else {
567
+ // Method decorator
568
+ Reflect.defineMetadata(ROLES_KEY, roles, target, propertyKey);
569
+ }
467
570
  };
468
571
  }
469
572
  /**
@@ -489,14 +592,220 @@ export function Roles() {
489
592
  * }
490
593
  * ```
491
594
  */
492
- export function Redirect(url, statusCode) {
493
- if (statusCode === void 0) { statusCode = 302; }
494
- return function (target, propertyKey, descriptor) {
595
+ export function Redirect(url, statusCode = 302) {
596
+ return (target, propertyKey, descriptor) => {
495
597
  // Store the redirect information in metadata
496
- Reflect.defineMetadata(REDIRECT_KEY, { url: url, statusCode: statusCode }, target, propertyKey);
598
+ Reflect.defineMetadata(REDIRECT_KEY, { url, statusCode }, target, propertyKey);
497
599
  return descriptor;
498
600
  };
499
601
  }
602
+ /**
603
+ * Decorator that adds caching to a route response.
604
+ *
605
+ * @param ttlSeconds - Time to live in seconds for the cache
606
+ * @returns Method decorator
607
+ *
608
+ * @example
609
+ * ```ts
610
+ * @Get('/data')
611
+ * @Cache(300) // Cache for 5 minutes
612
+ * getData() {
613
+ * return { data: 'expensive operation result' };
614
+ * }
615
+ * ```
616
+ */
617
+ export function Cache(ttlSeconds) {
618
+ return (target, propertyKey, _descriptor) => {
619
+ if (typeof propertyKey === 'undefined') {
620
+ // Class decorator
621
+ Reflect.defineMetadata(CACHE_KEY, { ttlSeconds }, target);
622
+ }
623
+ else {
624
+ // Method decorator
625
+ Reflect.defineMetadata(CACHE_KEY, { ttlSeconds }, target, propertyKey);
626
+ }
627
+ };
628
+ }
629
+ /**
630
+ * Decorator that applies rate limiting to a route.
631
+ * Note: Requires 'express-rate-limit' package to be installed.
632
+ *
633
+ * @param limit - Maximum number of requests allowed in the window
634
+ * @param windowMs - Time window in milliseconds
635
+ * @returns Method decorator
636
+ *
637
+ * Default Options:
638
+ * - standardHeaders: true
639
+ * - legacyHeaders: false
640
+ *
641
+ * @example
642
+ * ```ts
643
+ * @Post('/login')
644
+ * @RateLimit({ max: 5, windowMs: 60000, standardHeaders: true, legacyHeaders: false }) // 5 requests per minute
645
+ * login(@Body() credentials: LoginDto) {
646
+ * return this.authService.login(credentials);
647
+ * }
648
+ * ```
649
+ */
650
+ export function RateLimit(options) {
651
+ const opts = {
652
+ standardHeaders: true,
653
+ legacyHeaders: false,
654
+ ...options
655
+ };
656
+ return (target, propertyKey, _descriptor) => {
657
+ if (typeof propertyKey === 'undefined') {
658
+ // Class decorator
659
+ Reflect.defineMetadata(RATE_LIMIT_KEY, opts, target);
660
+ }
661
+ else {
662
+ // Method decorator
663
+ Reflect.defineMetadata(RATE_LIMIT_KEY, opts, target, propertyKey);
664
+ }
665
+ };
666
+ }
667
+ /**
668
+ * Decorator that sets the content type for the response.
669
+ *
670
+ * @param type - MIME type for the response
671
+ * @returns Method decorator
672
+ *
673
+ * @example
674
+ * ```ts
675
+ * @Get('/download')
676
+ * @ContentType('application/pdf')
677
+ * downloadPdf() {
678
+ * return this.fileService.generatePdf();
679
+ * }
680
+ * ```
681
+ */
682
+ export function ContentType(type) {
683
+ return (target, propertyKey, _descriptor) => {
684
+ Reflect.defineMetadata(CONTENT_TYPE_KEY, { type }, target, propertyKey);
685
+ };
686
+ }
687
+ /**
688
+ * Decorator that adds API versioning to a route.
689
+ *
690
+ * @param version - Version string for the API endpoint
691
+ * @param options - Versioning options
692
+ * @returns Method decorator
693
+ *
694
+ * Default Options:
695
+ * - addPrefix: true
696
+ * - addHeader: true
697
+ * - headerName: 'X-API-Version'
698
+ *
699
+ * @example
700
+ * ```ts
701
+ *
702
+ * @Get('/users')
703
+ * @Version('v2')
704
+ * getUsersV2() {
705
+ * return this.userService.findAllV2();
706
+ * }
707
+ *
708
+ * @Get('/users')
709
+ * @Version('v2', { addPrefix: true, addHeader: true, headerName: 'X-API-Version' })
710
+ * getUsersV2() {
711
+ * // Route becomes /v2/users
712
+ * return this.userService.findAllV2();
713
+ * }
714
+ * ```
715
+ */
716
+ export function Version(version, options) {
717
+ const opts = {
718
+ addPrefix: true,
719
+ addHeader: true,
720
+ headerName: 'X-API-Version',
721
+ ...options
722
+ };
723
+ return (target, propertyKey, _descriptor) => {
724
+ if (typeof propertyKey === 'undefined') {
725
+ // Class decorator
726
+ Reflect.defineMetadata(VERSION_KEY, { version, options: opts }, target);
727
+ }
728
+ else {
729
+ // Method decorator
730
+ Reflect.defineMetadata(VERSION_KEY, { version, options: opts }, target, propertyKey);
731
+ }
732
+ };
733
+ }
734
+ /**
735
+ * Decorator that sets a timeout for route execution.
736
+ *
737
+ * @param ms - Timeout in milliseconds
738
+ * @returns Method decorator
739
+ *
740
+ * @example
741
+ * ```ts
742
+ * @Get('/slow-operation')
743
+ * @Timeout(30000) // 30 second timeout
744
+ * slowOperation() {
745
+ * return this.heavyService.processData();
746
+ * }
747
+ * ```
748
+ */
749
+ export function Timeout(ms) {
750
+ return (target, propertyKey, _descriptor) => {
751
+ if (typeof propertyKey === 'undefined') {
752
+ // Class decorator
753
+ Reflect.defineMetadata(TIMEOUT_KEY, { ms }, target);
754
+ }
755
+ else {
756
+ // Method decorator
757
+ Reflect.defineMetadata(TIMEOUT_KEY, { ms }, target, propertyKey);
758
+ }
759
+ };
760
+ }
761
+ /**
762
+ * Decorator that adds comprehensive logging to a route.
763
+ *
764
+ * @param options - Logging configuration options
765
+ * @returns Method decorator
766
+ *
767
+ * Default Options:
768
+ * - logEntry: true
769
+ * - logExit: true
770
+ * - logBody: false
771
+ * - logParams: false
772
+ * - logResponse: false
773
+ *
774
+ * @example
775
+ * ```ts
776
+ * @Post('/users')
777
+ * @Log({
778
+ * logEntry: true,
779
+ * logExit: true,
780
+ * logBody: true,
781
+ * logParams: true,
782
+ * logResponse: false
783
+ * })
784
+ * createUser(@Body() userData: any) {
785
+ * return this.userService.create(userData);
786
+ * }
787
+ * ```
788
+ */
789
+ export function Log(options) {
790
+ return (target, propertyKey, _descriptor) => {
791
+ const config = {
792
+ logEntry: true,
793
+ logExit: true,
794
+ logBody: false,
795
+ logParams: false,
796
+ logResponse: false,
797
+ ...options
798
+ };
799
+ if (typeof propertyKey === 'undefined') {
800
+ // Class decorator
801
+ Reflect.defineMetadata(LOG_KEY, config, target);
802
+ }
803
+ else {
804
+ // Method decorator
805
+ Reflect.defineMetadata(LOG_KEY, config, target, propertyKey);
806
+ }
807
+ };
808
+ }
500
809
  /**
501
810
  * Registers all controller classes with the provided router.
502
811
  * This function processes all decorators and sets up the Express routes.
@@ -505,162 +814,200 @@ export function Redirect(url, statusCode) {
505
814
  * @param controllers - Array of controller classes
506
815
  */
507
816
  export function registerControllers(router, controllers) {
508
- var _this = this;
509
- controllers.forEach(function (ControllerClass) {
510
- var instance = new ControllerClass();
511
- var basePath = Reflect.getMetadata('basePath', ControllerClass) || '';
512
- var routes = Reflect.getMetadata(ROUTES_KEY, ControllerClass) || [];
513
- routes.forEach(function (_a) {
514
- var _b;
515
- var path = _a.path, method = _a.method, handlerName = _a.handlerName;
516
- var middlewares = Reflect.getMetadata(MIDDLEWARE_KEY, instance, handlerName) || [];
517
- var params = Reflect.getMetadata(PARAMS_KEY, instance, handlerName) || [];
518
- var httpCode = Reflect.getMetadata(HTTP_CODE_KEY, instance, handlerName);
519
- var headers = Reflect.getMetadata(HEADER_KEY, instance, handlerName) || {};
520
- var beforeHooks = Reflect.getMetadata(BEFORE_KEY, instance, handlerName) || [];
521
- var afterHooks = Reflect.getMetadata(AFTER_KEY, instance, handlerName) || [];
522
- var roles = Reflect.getMetadata(ROLES_KEY, instance, handlerName) || [];
523
- var redirect = Reflect.getMetadata(REDIRECT_KEY, instance, handlerName);
524
- var handler = function (req, res, next) { return __awaiter(_this, void 0, void 0, function () {
525
- var beforeHooks_1, beforeHooks_1_1, fn, e_1_1, args_1, result, awaited, _a, redirectUrl, redirectStatus, _b, _c, _d, k, v, afterHooks_1, afterHooks_1_1, fn, e_2_1, err_1;
526
- var e_1, _e, _f, e_3, _g, e_2, _h;
527
- var _j, _k, _l, _m;
528
- return __generator(this, function (_o) {
529
- switch (_o.label) {
530
- case 0:
531
- _o.trys.push([0, 20, , 21]);
532
- // Handle roles-based access control
533
- if (roles.length && !((_k = (_j = req === null || req === void 0 ? void 0 : req.user) === null || _j === void 0 ? void 0 : _j.roles) === null || _k === void 0 ? void 0 : _k.some(function (role) { return roles.includes(role); }))) {
534
- res.status(HttpStatusCodes.FORBIDDEN).json(new ForbiddenException('Forbidden Insufficient Roles'));
535
- return [2 /*return*/];
536
- }
537
- // Process static redirect if configured
538
- if (redirect && redirect.url) {
539
- return [2 /*return*/, res.redirect(redirect.statusCode, redirect.url)];
540
- }
541
- _o.label = 1;
542
- case 1:
543
- _o.trys.push([1, 6, 7, 8]);
544
- beforeHooks_1 = __values(beforeHooks), beforeHooks_1_1 = beforeHooks_1.next();
545
- _o.label = 2;
546
- case 2:
547
- if (!!beforeHooks_1_1.done) return [3 /*break*/, 5];
548
- fn = beforeHooks_1_1.value;
549
- return [4 /*yield*/, fn(req, res)];
550
- case 3:
551
- _o.sent();
552
- _o.label = 4;
553
- case 4:
554
- beforeHooks_1_1 = beforeHooks_1.next();
555
- return [3 /*break*/, 2];
556
- case 5: return [3 /*break*/, 8];
557
- case 6:
558
- e_1_1 = _o.sent();
559
- e_1 = { error: e_1_1 };
560
- return [3 /*break*/, 8];
561
- case 7:
562
- try {
563
- if (beforeHooks_1_1 && !beforeHooks_1_1.done && (_e = beforeHooks_1.return)) _e.call(beforeHooks_1);
564
- }
565
- finally { if (e_1) throw e_1.error; }
566
- return [7 /*endfinally*/];
567
- case 8:
568
- args_1 = [];
569
- if (params.length) {
570
- params.forEach(function (_a) {
571
- var _b;
572
- var index = _a.index, type = _a.type, key = _a.key;
573
- switch (type) {
574
- case 'query':
575
- args_1[index] = key ? req.query[key] : req.query;
576
- break;
577
- case 'param':
578
- args_1[index] = key ? req.params[key] : req.params;
579
- break;
580
- case 'body':
581
- args_1[index] = key ? (_b = req.body) === null || _b === void 0 ? void 0 : _b[key] : req.body;
582
- break;
583
- case 'req':
584
- args_1[index] = req;
585
- break;
586
- case 'res':
587
- args_1[index] = res;
588
- break;
589
- }
590
- });
591
- }
592
- result = (_f = instance)[handlerName].apply(_f, __spreadArray([], __read(args_1), false));
593
- if (!(result instanceof Promise)) return [3 /*break*/, 10];
594
- return [4 /*yield*/, result];
595
- case 9:
596
- _a = _o.sent();
597
- return [3 /*break*/, 11];
598
- case 10:
599
- _a = result;
600
- _o.label = 11;
601
- case 11:
602
- awaited = _a;
603
- // Handle dynamic redirects
604
- if (redirect && awaited && typeof awaited === 'object' && 'url' in awaited) {
605
- redirectUrl = awaited.url;
606
- redirectStatus = awaited.statusCode || redirect.statusCode;
607
- return [2 /*return*/, res.redirect(redirectStatus, redirectUrl)];
817
+ controllers.forEach(ControllerClass => {
818
+ // Use DI container to resolve controller (constructor injection + property injection)
819
+ const instance = diContainer.get(ControllerClass);
820
+ const basePath = Reflect.getMetadata('basePath', ControllerClass) || '';
821
+ const routes = Reflect.getMetadata(ROUTES_KEY, ControllerClass) || [];
822
+ // Get controller-level decorators (fallback values)
823
+ const controllerRateLimit = Reflect.getMetadata(RATE_LIMIT_KEY, ControllerClass);
824
+ const controllerCache = Reflect.getMetadata(CACHE_KEY, ControllerClass);
825
+ const controllerTimeout = Reflect.getMetadata(TIMEOUT_KEY, ControllerClass);
826
+ const controllerVersion = Reflect.getMetadata(VERSION_KEY, ControllerClass);
827
+ const controllerRoles = Reflect.getMetadata(ROLES_KEY, ControllerClass);
828
+ const controllerLogConfig = Reflect.getMetadata(LOG_KEY, ControllerClass);
829
+ const controllerHeaders = Reflect.getMetadata(HEADER_KEY, ControllerClass) || {};
830
+ routes.forEach(({ path, method, handlerName }) => {
831
+ const middlewares = Reflect.getMetadata(MIDDLEWARE_KEY, instance, handlerName) || [];
832
+ const params = Reflect.getMetadata(PARAMS_KEY, instance, handlerName) || [];
833
+ const httpCode = Reflect.getMetadata(HTTP_CODE_KEY, instance, handlerName);
834
+ // Merge controller-level and method-level headers
835
+ const methodHeaders = Reflect.getMetadata(HEADER_KEY, instance, handlerName) || {};
836
+ const headers = { ...controllerHeaders, ...methodHeaders };
837
+ const beforeHooks = Reflect.getMetadata(BEFORE_KEY, instance, handlerName) || [];
838
+ const afterHooks = Reflect.getMetadata(AFTER_KEY, instance, handlerName) || [];
839
+ const redirect = Reflect.getMetadata(REDIRECT_KEY, instance, handlerName);
840
+ const contentType = Reflect.getMetadata(CONTENT_TYPE_KEY, instance, handlerName);
841
+ // Use method-level decorators if present, otherwise fall back to controller-level
842
+ const roles = Reflect.getMetadata(ROLES_KEY, instance, handlerName) || controllerRoles || [];
843
+ const cache = Reflect.getMetadata(CACHE_KEY, instance, handlerName) || controllerCache;
844
+ const rateLimitOptions = Reflect.getMetadata(RATE_LIMIT_KEY, instance, handlerName) || controllerRateLimit;
845
+ const version = Reflect.getMetadata(VERSION_KEY, instance, handlerName) || controllerVersion;
846
+ const timeout = Reflect.getMetadata(TIMEOUT_KEY, instance, handlerName) || controllerTimeout;
847
+ const logConfig = Reflect.getMetadata(LOG_KEY, instance, handlerName) || controllerLogConfig;
848
+ // Create rate limiter for this specific route if needed
849
+ let rateLimiter = null;
850
+ if (rateLimitOptions) {
851
+ try {
852
+ rateLimiter = rateLimiterCache.get(rateLimitOptions);
853
+ }
854
+ catch (err) {
855
+ getLogger().warn({ err }, 'express-rate-limit not available, skipping rate limiting for this route');
856
+ }
857
+ }
858
+ let finalPath = path;
859
+ if (version?.options?.addPrefix) {
860
+ finalPath = `/${version.version}${path}`;
861
+ }
862
+ const handler = async (req, res, next) => {
863
+ // Set start time for duration tracking
864
+ req['startTime'] = Date.now();
865
+ let timeoutId;
866
+ let timedOut = false;
867
+ try {
868
+ // Handle timeout setup
869
+ if (timeout) {
870
+ timeoutId = setTimeout(() => {
871
+ if (!res.headersSent && !timedOut) {
872
+ timedOut = true;
873
+ const errorResponse = createFinalErrorResponse(req, HttpStatusCodes.REQUEST_TIMEOUT, 'Request timed out');
874
+ res.status(HttpStatusCodes.REQUEST_TIMEOUT).json(errorResponse);
608
875
  }
609
- if (!res.headersSent && typeof awaited !== 'undefined') {
610
- if (httpCode)
611
- (_l = res.status) === null || _l === void 0 ? void 0 : _l.call(res, httpCode);
612
- try {
613
- for (_b = __values(Object.entries(headers)), _c = _b.next(); !_c.done; _c = _b.next()) {
614
- _d = __read(_c.value, 2), k = _d[0], v = _d[1];
615
- (_m = res.set) === null || _m === void 0 ? void 0 : _m.call(res, k, v);
616
- }
617
- }
618
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
619
- finally {
620
- try {
621
- if (_c && !_c.done && (_g = _b.return)) _g.call(_b);
622
- }
623
- finally { if (e_3) throw e_3.error; }
624
- }
625
- res.json(awaited);
876
+ }, timeout.ms);
877
+ }
878
+ if (timedOut)
879
+ return;
880
+ // Handle rate limiting
881
+ if (rateLimiter) {
882
+ await new Promise((resolve, reject) => {
883
+ rateLimiter(req, res, (err) => {
884
+ if (err)
885
+ reject(err);
886
+ else
887
+ resolve();
888
+ });
889
+ });
890
+ }
891
+ // Handle content type
892
+ if (!res.headersSent && contentType) {
893
+ res.setHeader('Content-Type', contentType.type);
894
+ }
895
+ // Handle versioning header
896
+ if (version?.options?.addHeader && version?.options?.headerName && version?.version) {
897
+ if (!res.headersSent) {
898
+ res.setHeader(version.options.headerName, version.version);
899
+ }
900
+ }
901
+ // Handle caching
902
+ if (cache && !res.headersSent) {
903
+ res.setHeader('Cache-Control', `public, max-age=${cache.ttlSeconds}`);
904
+ }
905
+ // Handle logging - entry
906
+ if (logConfig?.logEntry) {
907
+ const logger = getLogger();
908
+ const logData = {
909
+ method: req.method,
910
+ url: req.originalUrl || req.url,
911
+ userAgent: req.get('User-Agent')
912
+ };
913
+ if (logConfig.logParams) {
914
+ logData.params = req.params;
915
+ logData.query = req.query;
916
+ }
917
+ if (logConfig.logBody)
918
+ logData.body = req.body;
919
+ logger.info({ entry: logData }, 'Route Entry:');
920
+ }
921
+ // Handle roles-based access control
922
+ if (roles.length && !req?.user?.roles?.some((role) => roles.includes(role))) {
923
+ const errorResponse = createFinalErrorResponse(req, HttpStatusCodes.FORBIDDEN, 'Forbidden Insufficient Roles');
924
+ res.status(HttpStatusCodes.FORBIDDEN).json(errorResponse);
925
+ if (timeoutId) {
926
+ clearTimeout(timeoutId);
927
+ }
928
+ return;
929
+ }
930
+ // Process static redirect if configured
931
+ if (redirect && redirect.url) {
932
+ if (timeoutId) {
933
+ clearTimeout(timeoutId);
934
+ }
935
+ return res.redirect(redirect.statusCode, redirect.url);
936
+ }
937
+ for (const fn of beforeHooks)
938
+ await fn(req, res);
939
+ const args = [];
940
+ if (params.length) {
941
+ params.forEach(({ index, type, key }) => {
942
+ switch (type) {
943
+ case 'query':
944
+ args[index] = key ? req.query[key] : req.query;
945
+ break;
946
+ case 'param':
947
+ args[index] = key ? req.params[key] : req.params;
948
+ break;
949
+ case 'body':
950
+ args[index] = key ? req.body?.[key] : req.body;
951
+ break;
952
+ case 'req':
953
+ args[index] = req;
954
+ break;
955
+ case 'res':
956
+ args[index] = res;
957
+ break;
626
958
  }
627
- _o.label = 12;
628
- case 12:
629
- _o.trys.push([12, 17, 18, 19]);
630
- afterHooks_1 = __values(afterHooks), afterHooks_1_1 = afterHooks_1.next();
631
- _o.label = 13;
632
- case 13:
633
- if (!!afterHooks_1_1.done) return [3 /*break*/, 16];
634
- fn = afterHooks_1_1.value;
635
- return [4 /*yield*/, fn(req, res, awaited)];
636
- case 14:
637
- _o.sent();
638
- _o.label = 15;
639
- case 15:
640
- afterHooks_1_1 = afterHooks_1.next();
641
- return [3 /*break*/, 13];
642
- case 16: return [3 /*break*/, 19];
643
- case 17:
644
- e_2_1 = _o.sent();
645
- e_2 = { error: e_2_1 };
646
- return [3 /*break*/, 19];
647
- case 18:
648
- try {
649
- if (afterHooks_1_1 && !afterHooks_1_1.done && (_h = afterHooks_1.return)) _h.call(afterHooks_1);
959
+ });
960
+ }
961
+ const result = instance[handlerName](...args);
962
+ // Support both sync and async handlers
963
+ const awaited = result instanceof Promise ? await result : result;
964
+ // Clear timeout if operation completed
965
+ if (timeoutId) {
966
+ clearTimeout(timeoutId);
967
+ }
968
+ if (timedOut)
969
+ return;
970
+ // Handle dynamic redirects
971
+ if (redirect && awaited && typeof awaited === 'object' && 'url' in awaited) {
972
+ const redirectUrl = awaited.url;
973
+ const redirectStatus = awaited.statusCode || redirect.statusCode;
974
+ return res.redirect(redirectStatus, redirectUrl);
975
+ }
976
+ if (!res.headersSent && typeof awaited !== 'undefined') {
977
+ if (httpCode)
978
+ res.status(httpCode);
979
+ for (const [k, v] of Object.entries(headers)) {
980
+ const normalized = normalizeHeaderValue(v);
981
+ if (typeof normalized !== 'undefined') {
982
+ res.set(k, normalized);
650
983
  }
651
- finally { if (e_2) throw e_2.error; }
652
- return [7 /*endfinally*/];
653
- case 19: return [3 /*break*/, 21];
654
- case 20:
655
- err_1 = _o.sent();
656
- next(err_1);
657
- return [3 /*break*/, 21];
658
- case 21: return [2 /*return*/];
984
+ }
985
+ res.json(awaited);
986
+ }
987
+ // Handle logging - exit
988
+ if (logConfig?.logExit) {
989
+ const logger = getLogger();
990
+ const logData = {
991
+ method: req.method,
992
+ url: req.originalUrl || req.url,
993
+ statusCode: res.statusCode,
994
+ duration: `${Date.now() - req.startTime}ms`
995
+ };
996
+ if (logConfig.logResponse)
997
+ logData.response = awaited;
998
+ logger.info({ exit: logData }, 'Route Exit:');
999
+ }
1000
+ for (const fn of afterHooks)
1001
+ await fn(req, res, awaited);
1002
+ }
1003
+ catch (err) {
1004
+ if (timeoutId) {
1005
+ clearTimeout(timeoutId);
659
1006
  }
660
- });
661
- }); };
662
- (_b = router)[method].apply(_b, __spreadArray(__spreadArray([basePath + path], __read(middlewares), false), [handler], false));
1007
+ next(err);
1008
+ }
1009
+ };
1010
+ router[method](basePath + finalPath, ...middlewares, handler);
663
1011
  });
664
1012
  });
665
1013
  }
666
- //# sourceMappingURL=decorators.utils.js.map