@lenne.tech/nest-server 11.32.4 → 11.33.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 (264) hide show
  1. package/.claude/rules/architecture.md +16 -0
  2. package/.claude/rules/configurable-features.md +11 -3
  3. package/.claude/rules/testing.md +101 -1
  4. package/CLAUDE.md +5 -0
  5. package/FRAMEWORK-API.md +58 -3
  6. package/dist/config.env.js +6 -0
  7. package/dist/config.env.js.map +1 -1
  8. package/dist/core/common/helpers/content-disposition.helper.d.ts +1 -0
  9. package/dist/core/common/helpers/content-disposition.helper.js +14 -0
  10. package/dist/core/common/helpers/content-disposition.helper.js.map +1 -0
  11. package/dist/core/common/helpers/file.helper.d.ts +7 -0
  12. package/dist/core/common/helpers/file.helper.js +21 -4
  13. package/dist/core/common/helpers/file.helper.js.map +1 -1
  14. package/dist/core/common/helpers/graceful-shutdown.helper.d.ts +2 -0
  15. package/dist/core/common/helpers/graceful-shutdown.helper.js +55 -0
  16. package/dist/core/common/helpers/graceful-shutdown.helper.js.map +1 -0
  17. package/dist/core/common/helpers/project-name.helper.d.ts +2 -0
  18. package/dist/core/common/helpers/project-name.helper.js +38 -0
  19. package/dist/core/common/helpers/project-name.helper.js.map +1 -0
  20. package/dist/core/common/interfaces/cron-job-config.interface.d.ts +1 -0
  21. package/dist/core/common/interfaces/server-options.interface.d.ts +39 -0
  22. package/dist/core/common/services/core-cron-jobs.initializer.d.ts +10 -0
  23. package/dist/core/common/services/core-cron-jobs.initializer.js +46 -0
  24. package/dist/core/common/services/core-cron-jobs.initializer.js.map +1 -0
  25. package/dist/core/common/services/core-cron-jobs.registry.d.ts +8 -0
  26. package/dist/core/common/services/core-cron-jobs.registry.js +12 -0
  27. package/dist/core/common/services/core-cron-jobs.registry.js.map +1 -0
  28. package/dist/core/common/services/core-cron-jobs.service.d.ts +37 -7
  29. package/dist/core/common/services/core-cron-jobs.service.js +278 -27
  30. package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
  31. package/dist/core/common/services/core-redis-pubsub.d.ts +20 -0
  32. package/dist/core/common/services/core-redis-pubsub.js +112 -0
  33. package/dist/core/common/services/core-redis-pubsub.js.map +1 -0
  34. package/dist/core/common/services/core-redis.service.d.ts +25 -0
  35. package/dist/core/common/services/core-redis.service.js +154 -0
  36. package/dist/core/common/services/core-redis.service.js.map +1 -0
  37. package/dist/core/common/services/core-s3.service.d.ts +51 -0
  38. package/dist/core/common/services/core-s3.service.js +261 -0
  39. package/dist/core/common/services/core-s3.service.js.map +1 -0
  40. package/dist/core/common/services/core-trust-proxy.initializer.d.ts +16 -0
  41. package/dist/core/common/services/core-trust-proxy.initializer.js +77 -0
  42. package/dist/core/common/services/core-trust-proxy.initializer.js.map +1 -0
  43. package/dist/core/common/services/rate-limit-store.d.ts +61 -0
  44. package/dist/core/common/services/rate-limit-store.js +235 -0
  45. package/dist/core/common/services/rate-limit-store.js.map +1 -0
  46. package/dist/core/modules/ai/core-ai-mcp.controller.d.ts +19 -3
  47. package/dist/core/modules/ai/core-ai-mcp.controller.js +148 -18
  48. package/dist/core/modules/ai/core-ai-mcp.controller.js.map +1 -1
  49. package/dist/core/modules/ai/services/core-ai.service.d.ts +7 -2
  50. package/dist/core/modules/ai/services/core-ai.service.js +24 -20
  51. package/dist/core/modules/ai/services/core-ai.service.js.map +1 -1
  52. package/dist/core/modules/auth/core-auth.module.js +4 -1
  53. package/dist/core/modules/auth/core-auth.module.js.map +1 -1
  54. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.d.ts +1 -1
  55. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +3 -14
  56. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -1
  57. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.d.ts +12 -10
  58. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js +30 -59
  59. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js.map +1 -1
  60. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.d.ts +8 -2
  61. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js +118 -45
  62. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js.map +1 -1
  63. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.d.ts +1 -1
  64. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.js +2 -11
  65. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.js.map +1 -1
  66. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.d.ts +12 -10
  67. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.js +30 -85
  68. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.js.map +1 -1
  69. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +0 -1
  70. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
  71. package/dist/core/modules/file/core-file.controller.d.ts +11 -2
  72. package/dist/core/modules/file/core-file.controller.js +52 -15
  73. package/dist/core/modules/file/core-file.controller.js.map +1 -1
  74. package/dist/core/modules/file/core-file.resolver.d.ts +4 -4
  75. package/dist/core/modules/file/core-file.resolver.js +23 -16
  76. package/dist/core/modules/file/core-file.resolver.js.map +1 -1
  77. package/dist/core/modules/file/core-file.service.d.ts +41 -7
  78. package/dist/core/modules/file/core-file.service.js +228 -8
  79. package/dist/core/modules/file/core-file.service.js.map +1 -1
  80. package/dist/core/modules/file/file-metadata.helper.d.ts +16 -0
  81. package/dist/core/modules/file/file-metadata.helper.js +33 -0
  82. package/dist/core/modules/file/file-metadata.helper.js.map +1 -0
  83. package/dist/core/modules/file/file-roles.helper.d.ts +4 -0
  84. package/dist/core/modules/file/file-roles.helper.js +53 -0
  85. package/dist/core/modules/file/file-roles.helper.js.map +1 -0
  86. package/dist/core/modules/file/file-storage.helper.d.ts +13 -0
  87. package/dist/core/modules/file/file-storage.helper.js +65 -0
  88. package/dist/core/modules/file/file-storage.helper.js.map +1 -0
  89. package/dist/core/modules/file/filesystem-file.helper.d.ts +22 -0
  90. package/dist/core/modules/file/filesystem-file.helper.js +77 -0
  91. package/dist/core/modules/file/filesystem-file.helper.js.map +1 -0
  92. package/dist/core/modules/file/interfaces/file-service-options.interface.d.ts +1 -0
  93. package/dist/core/modules/file/interfaces/file-upload.interface.d.ts +7 -1
  94. package/dist/core/modules/file/s3-file.helper.d.ts +37 -0
  95. package/dist/core/modules/file/s3-file.helper.js +81 -0
  96. package/dist/core/modules/file/s3-file.helper.js.map +1 -0
  97. package/dist/core/modules/hub/core-hub.controller.d.ts +8 -8
  98. package/dist/core/modules/hub/core-hub.controller.js +24 -22
  99. package/dist/core/modules/hub/core-hub.controller.js.map +1 -1
  100. package/dist/core/modules/hub/helpers/hub-mask.helper.js +2 -2
  101. package/dist/core/modules/hub/helpers/hub-mask.helper.js.map +1 -1
  102. package/dist/core/modules/hub/hub-buffer.d.ts +23 -0
  103. package/dist/core/modules/hub/hub-buffer.js +101 -0
  104. package/dist/core/modules/hub/hub-buffer.js.map +1 -0
  105. package/dist/core/modules/hub/services/core-hub-mailbox.service.d.ts +7 -5
  106. package/dist/core/modules/hub/services/core-hub-mailbox.service.js +14 -10
  107. package/dist/core/modules/hub/services/core-hub-mailbox.service.js.map +1 -1
  108. package/dist/core/modules/hub/services/hub-log-buffer.service.d.ts +5 -2
  109. package/dist/core/modules/hub/services/hub-log-buffer.service.js +17 -8
  110. package/dist/core/modules/hub/services/hub-log-buffer.service.js.map +1 -1
  111. package/dist/core/modules/hub/services/hub-query-profiler.service.d.ts +4 -2
  112. package/dist/core/modules/hub/services/hub-query-profiler.service.js +13 -7
  113. package/dist/core/modules/hub/services/hub-query-profiler.service.js.map +1 -1
  114. package/dist/core/modules/hub/services/hub-trace-buffer.service.d.ts +4 -2
  115. package/dist/core/modules/hub/services/hub-trace-buffer.service.js +13 -8
  116. package/dist/core/modules/hub/services/hub-trace-buffer.service.js.map +1 -1
  117. package/dist/core/modules/migrate/helpers/migration.helper.d.ts +2 -6
  118. package/dist/core/modules/migrate/helpers/migration.helper.js +4 -4
  119. package/dist/core/modules/migrate/helpers/migration.helper.js.map +1 -1
  120. package/dist/core/modules/migrate/migration-runner.d.ts +1 -0
  121. package/dist/core/modules/migrate/migration-runner.js +4 -0
  122. package/dist/core/modules/migrate/migration-runner.js.map +1 -1
  123. package/dist/core/modules/migrate/mongo-state-store.d.ts +1 -0
  124. package/dist/core/modules/migrate/mongo-state-store.js +98 -9
  125. package/dist/core/modules/migrate/mongo-state-store.js.map +1 -1
  126. package/dist/core/modules/system-setup/core-system-setup.service.d.ts +2 -0
  127. package/dist/core/modules/system-setup/core-system-setup.service.js +31 -1
  128. package/dist/core/modules/system-setup/core-system-setup.service.js.map +1 -1
  129. package/dist/core/modules/tenant/core-tenant.guard.d.ts +17 -3
  130. package/dist/core/modules/tenant/core-tenant.guard.js +92 -15
  131. package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
  132. package/dist/core/modules/tenant/core-tenant.module.js +3 -4
  133. package/dist/core/modules/tenant/core-tenant.module.js.map +1 -1
  134. package/dist/core/modules/tus/core-tus.controller.d.ts +2 -0
  135. package/dist/core/modules/tus/core-tus.controller.js +29 -3
  136. package/dist/core/modules/tus/core-tus.controller.js.map +1 -1
  137. package/dist/core/modules/tus/core-tus.service.d.ts +24 -1
  138. package/dist/core/modules/tus/core-tus.service.js +182 -28
  139. package/dist/core/modules/tus/core-tus.service.js.map +1 -1
  140. package/dist/core/modules/tus/interfaces/tus-config.interface.js +3 -0
  141. package/dist/core/modules/tus/interfaces/tus-config.interface.js.map +1 -1
  142. package/dist/core/modules/tus/tus-redis-locker.d.ts +25 -0
  143. package/dist/core/modules/tus/tus-redis-locker.js +87 -0
  144. package/dist/core/modules/tus/tus-redis-locker.js.map +1 -0
  145. package/dist/core/modules/tus/tus.module.d.ts +1 -0
  146. package/dist/core/modules/tus/tus.module.js +30 -4
  147. package/dist/core/modules/tus/tus.module.js.map +1 -1
  148. package/dist/core.module.js +18 -1
  149. package/dist/core.module.js.map +1 -1
  150. package/dist/index.d.ts +10 -0
  151. package/dist/index.js +10 -0
  152. package/dist/index.js.map +1 -1
  153. package/dist/main.js +2 -1
  154. package/dist/main.js.map +1 -1
  155. package/dist/server/modules/file/file.controller.js +2 -2
  156. package/dist/server/modules/file/file.controller.js.map +1 -1
  157. package/dist/server/modules/file/file.resolver.js +3 -14
  158. package/dist/server/modules/file/file.resolver.js.map +1 -1
  159. package/dist/server/modules/file/file.service.d.ts +10 -2
  160. package/dist/server/modules/file/file.service.js +23 -3
  161. package/dist/server/modules/file/file.service.js.map +1 -1
  162. package/dist/server/modules/user/avatar.controller.d.ts +5 -1
  163. package/dist/server/modules/user/avatar.controller.js +26 -10
  164. package/dist/server/modules/user/avatar.controller.js.map +1 -1
  165. package/dist/server/modules/user/user.model.js +3 -2
  166. package/dist/server/modules/user/user.model.js.map +1 -1
  167. package/dist/server/modules/user/user.module.js +6 -2
  168. package/dist/server/modules/user/user.module.js.map +1 -1
  169. package/dist/server/modules/user/user.service.d.ts +1 -1
  170. package/dist/server/modules/user/user.service.js +6 -13
  171. package/dist/server/modules/user/user.service.js.map +1 -1
  172. package/dist/tsconfig.build.tsbuildinfo +1 -1
  173. package/docs/REQUEST-LIFECYCLE.md +57 -8
  174. package/docs/security-overrides.md +21 -3
  175. package/migration-guides/11.32.3-to-11.32.4.md +15 -3
  176. package/migration-guides/11.32.x-to-11.33.x.md +1584 -0
  177. package/package.json +74 -42
  178. package/src/config.env.ts +45 -0
  179. package/src/core/common/helpers/content-disposition.helper.ts +90 -0
  180. package/src/core/common/helpers/file.helper.ts +53 -10
  181. package/src/core/common/helpers/graceful-shutdown.helper.ts +116 -0
  182. package/src/core/common/helpers/project-name.helper.ts +71 -0
  183. package/src/core/common/interfaces/cron-job-config.interface.ts +16 -0
  184. package/src/core/common/interfaces/server-options.interface.ts +439 -2
  185. package/src/core/common/services/core-cron-jobs.initializer.ts +39 -0
  186. package/src/core/common/services/core-cron-jobs.registry.ts +45 -0
  187. package/src/core/common/services/core-cron-jobs.service.ts +589 -47
  188. package/src/core/common/services/core-redis-pubsub.ts +183 -0
  189. package/src/core/common/services/core-redis.service.ts +249 -0
  190. package/src/core/common/services/core-s3.service.ts +465 -0
  191. package/src/core/common/services/core-trust-proxy.initializer.ts +112 -0
  192. package/src/core/common/services/rate-limit-store.ts +492 -0
  193. package/src/core/modules/ai/README.md +25 -0
  194. package/src/core/modules/ai/core-ai-mcp.controller.ts +253 -22
  195. package/src/core/modules/ai/services/core-ai.service.ts +33 -24
  196. package/src/core/modules/auth/core-auth.module.ts +7 -1
  197. package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +12 -21
  198. package/src/core/modules/auth/services/legacy-auth-rate-limiter.service.ts +49 -93
  199. package/src/core/modules/better-auth/core-better-auth-email-verification.service.ts +202 -66
  200. package/src/core/modules/better-auth/core-better-auth-rate-limit.middleware.ts +11 -18
  201. package/src/core/modules/better-auth/core-better-auth-rate-limiter.service.ts +51 -132
  202. package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +7 -1
  203. package/src/core/modules/file/INTEGRATION-CHECKLIST.md +120 -0
  204. package/src/core/modules/file/README.md +308 -53
  205. package/src/core/modules/file/core-file.controller.ts +168 -12
  206. package/src/core/modules/file/core-file.resolver.ts +46 -12
  207. package/src/core/modules/file/core-file.service.ts +517 -17
  208. package/src/core/modules/file/file-metadata.helper.ts +142 -0
  209. package/src/core/modules/file/file-roles.helper.ts +110 -0
  210. package/src/core/modules/file/file-storage.helper.ts +163 -0
  211. package/src/core/modules/file/filesystem-file.helper.ts +184 -0
  212. package/src/core/modules/file/interfaces/file-service-options.interface.ts +14 -0
  213. package/src/core/modules/file/interfaces/file-upload.interface.ts +17 -1
  214. package/src/core/modules/file/s3-file.helper.ts +209 -0
  215. package/src/core/modules/hub/README.md +48 -0
  216. package/src/core/modules/hub/core-hub.controller.ts +18 -16
  217. package/src/core/modules/hub/helpers/hub-mask.helper.ts +21 -4
  218. package/src/core/modules/hub/hub-buffer.ts +198 -0
  219. package/src/core/modules/hub/services/core-hub-mailbox.service.ts +22 -12
  220. package/src/core/modules/hub/services/hub-log-buffer.service.ts +24 -8
  221. package/src/core/modules/hub/services/hub-query-profiler.service.ts +9 -6
  222. package/src/core/modules/hub/services/hub-trace-buffer.service.ts +14 -9
  223. package/src/core/modules/migrate/README.md +33 -6
  224. package/src/core/modules/migrate/helpers/migration.helper.ts +13 -6
  225. package/src/core/modules/migrate/migration-runner.ts +10 -1
  226. package/src/core/modules/migrate/mongo-state-store.ts +179 -11
  227. package/src/core/modules/system-setup/README.md +7 -2
  228. package/src/core/modules/system-setup/core-system-setup.service.ts +95 -1
  229. package/src/core/modules/tenant/README.md +21 -1
  230. package/src/core/modules/tenant/core-tenant.guard.ts +135 -14
  231. package/src/core/modules/tenant/core-tenant.module.ts +8 -4
  232. package/src/core/modules/tus/INTEGRATION-CHECKLIST.md +93 -21
  233. package/src/core/modules/tus/README.md +35 -2
  234. package/src/core/modules/tus/core-tus.controller.ts +64 -12
  235. package/src/core/modules/tus/core-tus.service.ts +358 -34
  236. package/src/core/modules/tus/interfaces/tus-config.interface.ts +9 -0
  237. package/src/core/modules/tus/tus-redis-locker.ts +139 -0
  238. package/src/core/modules/tus/tus.module.ts +78 -6
  239. package/src/core.module.ts +26 -1
  240. package/src/index.ts +10 -0
  241. package/src/main.ts +7 -1
  242. package/src/server/modules/file/file.controller.ts +14 -5
  243. package/src/server/modules/file/file.resolver.ts +11 -19
  244. package/src/server/modules/file/file.service.ts +89 -4
  245. package/src/server/modules/user/avatar.controller.ts +46 -9
  246. package/src/server/modules/user/user.model.ts +9 -3
  247. package/src/server/modules/user/user.module.ts +12 -3
  248. package/src/server/modules/user/user.service.ts +20 -17
  249. package/src/test/README.md +7 -2
  250. package/src/core/common/helpers/file.helper.spec.ts +0 -145
  251. package/src/core/common/helpers/logging.helper.spec.ts +0 -61
  252. package/src/core/common/helpers/process-diagnostics.helper.spec.ts +0 -310
  253. package/src/core/common/services/brevo.service.spec.ts +0 -266
  254. package/src/core/modules/file/core-file.controller.spec.ts +0 -164
  255. package/src/core/modules/hub/core-hub.module.spec.ts +0 -108
  256. package/src/core/modules/hub/helpers/hub-command-shape.helper.spec.ts +0 -48
  257. package/src/core/modules/hub/helpers/hub-mask.helper.spec.ts +0 -67
  258. package/src/core/modules/hub/helpers/hub-mermaid.helper.spec.ts +0 -61
  259. package/src/core/modules/hub/helpers/hub-shell.helper.spec.ts +0 -106
  260. package/src/core/modules/hub/hub-config.helper.spec.ts +0 -108
  261. package/src/core/modules/hub/hub-ring-buffer.spec.ts +0 -95
  262. package/src/core/modules/hub/services/core-hub-mailbox.service.spec.ts +0 -116
  263. package/src/core/modules/hub/services/hub-trace-buffer.service.spec.ts +0 -112
  264. package/src/core/modules/migrate/helpers/migration.helper.spec.ts +0 -85
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var CoreRedisService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.CoreRedisService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const project_name_helper_1 = require("../helpers/project-name.helper");
16
+ const config_service_1 = require("./config.service");
17
+ let CoreRedisService = CoreRedisService_1 = class CoreRedisService {
18
+ configService;
19
+ logger = new common_1.Logger(CoreRedisService_1.name);
20
+ clients = [];
21
+ config;
22
+ RedisCtor;
23
+ sharedClient;
24
+ subscriberClient;
25
+ constructor(configService) {
26
+ this.configService = configService;
27
+ const raw = this.configService.getFastButReadOnly('redis');
28
+ if (raw === undefined || raw === null || raw === false) {
29
+ return;
30
+ }
31
+ const partial = typeof raw === 'boolean' ? {} : raw;
32
+ if (partial.enabled === false) {
33
+ return;
34
+ }
35
+ this.config = {
36
+ db: partial.db ?? 0,
37
+ host: partial.host ?? 'localhost',
38
+ keyPrefix: partial.keyPrefix ?? (0, project_name_helper_1.getProjectSlug)(),
39
+ options: partial.options,
40
+ password: partial.password,
41
+ port: partial.port ?? 6379,
42
+ url: partial.url,
43
+ username: partial.username,
44
+ };
45
+ }
46
+ get enabled() {
47
+ return !!this.config;
48
+ }
49
+ getConfig() {
50
+ return this.config;
51
+ }
52
+ key(...parts) {
53
+ return [this.config?.keyPrefix ?? (0, project_name_helper_1.getProjectSlug)(), ...parts].join(':');
54
+ }
55
+ async onModuleInit() {
56
+ if (!this.config) {
57
+ return;
58
+ }
59
+ try {
60
+ const mod = await Promise.resolve().then(() => require('ioredis'));
61
+ this.RedisCtor = mod.Redis ?? mod.default;
62
+ }
63
+ catch {
64
+ throw new Error('Redis is configured (ServerOptions.redis) but the optional peer dependency "ioredis" is not installed. ' +
65
+ 'Run: pnpm add ioredis');
66
+ }
67
+ this.sharedClient = this.newConnection('shared');
68
+ this.logActivationSummary();
69
+ }
70
+ logActivationSummary() {
71
+ if (!this.config) {
72
+ return;
73
+ }
74
+ const cfg = this.configService.configFastButReadOnly ?? {};
75
+ const changed = [
76
+ 'rate limits (legacy auth, better-auth, AI) — now exact across replicas instead of per replica',
77
+ 'cron jobs — deduplicated fleet-wide; per-job opt-out via `distributed: false`',
78
+ 'email-verification cooldown — one slot fleet-wide instead of one per replica',
79
+ ];
80
+ if (cfg.graphQl !== false) {
81
+ changed.push('GraphQL subscriptions — via Redis pub/sub; payloads must be JSON-serializable');
82
+ }
83
+ if (cfg.multiTenancy) {
84
+ changed.push('tenant-membership cache — invalidation is broadcast to every replica');
85
+ }
86
+ if (cfg.hub) {
87
+ changed.push('Hub log/trace/query buffers — mirrored to Redis, so they outlive the process');
88
+ }
89
+ if (cfg.ai?.mcp) {
90
+ changed.push('MCP sessions — ownership registry (sticky sessions still required)');
91
+ }
92
+ this.logger.log(`Redis configured (${this.config.url ? 'url' : `${this.config.host}:${this.config.port}`}, ` +
93
+ `db ${this.config.db}, keyPrefix "${this.config.keyPrefix}") — these subsystems are now ` +
94
+ `distributed:\n - ${changed.join('\n - ')}`);
95
+ }
96
+ getClient() {
97
+ if (!this.config) {
98
+ throw new Error('Redis is not configured/enabled (ServerOptions.redis)');
99
+ }
100
+ if (!this.sharedClient) {
101
+ throw new Error('CoreRedisService is not initialized yet (onModuleInit pending)');
102
+ }
103
+ return this.sharedClient;
104
+ }
105
+ getSubscriber() {
106
+ this.getClient();
107
+ if (!this.subscriberClient) {
108
+ this.subscriberClient = this.newConnection('subscriber');
109
+ }
110
+ return this.subscriberClient;
111
+ }
112
+ createClient(label = 'extra', overrides) {
113
+ this.getClient();
114
+ return this.newConnection(label, overrides);
115
+ }
116
+ async onApplicationShutdown() {
117
+ await Promise.allSettled(this.clients.map(async (client) => {
118
+ try {
119
+ await Promise.race([client.quit(), new Promise((resolve) => setTimeout(resolve, 2000).unref())]);
120
+ }
121
+ finally {
122
+ client.disconnect();
123
+ }
124
+ }));
125
+ this.clients = [];
126
+ this.sharedClient = undefined;
127
+ this.subscriberClient = undefined;
128
+ }
129
+ newConnection(label, overrides) {
130
+ if (!this.config || !this.RedisCtor) {
131
+ throw new Error('CoreRedisService is not initialized yet (onModuleInit pending)');
132
+ }
133
+ const { db, host, options, password, port, url, username } = this.config;
134
+ const baseOptions = {
135
+ commandTimeout: 2000,
136
+ ...options,
137
+ ...overrides,
138
+ };
139
+ const client = url
140
+ ? new this.RedisCtor(url, baseOptions)
141
+ : new this.RedisCtor({ db, host, password, port, username, ...baseOptions });
142
+ client.on?.('error', (error) => {
143
+ this.logger.error(`Redis connection error (${label}): ${error.message}`);
144
+ });
145
+ this.clients.push(client);
146
+ return client;
147
+ }
148
+ };
149
+ exports.CoreRedisService = CoreRedisService;
150
+ exports.CoreRedisService = CoreRedisService = CoreRedisService_1 = __decorate([
151
+ (0, common_1.Injectable)(),
152
+ __metadata("design:paramtypes", [config_service_1.ConfigService])
153
+ ], CoreRedisService);
154
+ //# sourceMappingURL=core-redis.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-redis.service.js","sourceRoot":"","sources":["../../../../src/core/common/services/core-redis.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { Logger, OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
2
+ import { ConfigService } from './config.service';
3
+ import type { IS3Config } from '../interfaces/server-options.interface';
4
+ import type { S3Client } from '@aws-sdk/client-s3';
5
+ import type { Readable } from 'stream';
6
+ export type NormalizedS3Config = Omit<IS3Config, 'enabled' | 'presignedDownloads'> & {
7
+ bucket: string;
8
+ forcePathStyle: boolean;
9
+ presignedDownloads?: {
10
+ expiresInSeconds: number;
11
+ };
12
+ region: string;
13
+ stagingBucket: string;
14
+ };
15
+ export declare class CoreS3Service implements OnApplicationShutdown, OnModuleInit {
16
+ protected readonly configService: ConfigService;
17
+ protected readonly logger: Logger;
18
+ protected config?: NormalizedS3Config;
19
+ protected client?: S3Client;
20
+ protected sdk?: typeof import('@aws-sdk/client-s3');
21
+ protected presigner?: typeof import('@aws-sdk/s3-request-presigner');
22
+ constructor(configService: ConfigService);
23
+ protected clampPresignedExpiry(seconds: number): number;
24
+ get enabled(): boolean;
25
+ getConfig(): NormalizedS3Config | undefined;
26
+ onModuleInit(): Promise<void>;
27
+ protected verifyBuckets(): Promise<void>;
28
+ protected bucketExists(bucket: string): Promise<boolean>;
29
+ getClient(): S3Client;
30
+ putObject(key: string, body: Buffer | Readable | string, contentType?: string, contentLength?: number): Promise<void>;
31
+ copyObject(sourceKey: string, destinationKey: string, sourceBucket?: string, contentType?: string): Promise<void>;
32
+ static readonly MAX_COPY_OBJECT_BYTES: number;
33
+ protected copySource(bucket: string, key: string): string;
34
+ protected isStream(body: unknown): body is Readable;
35
+ protected collect(stream: Readable): Promise<Buffer>;
36
+ getObject(key: string): Promise<{
37
+ body: Readable;
38
+ contentLength?: number;
39
+ contentType?: string;
40
+ }>;
41
+ deleteObject(key: string, bucket?: string): Promise<void>;
42
+ objectExists(key: string): Promise<boolean>;
43
+ getPresignedDownloadUrl(key: string, filename?: string): Promise<string | undefined>;
44
+ ensureBucket(bucket: string): Promise<void>;
45
+ onApplicationShutdown(): Promise<void>;
46
+ protected requireInit(): {
47
+ client: S3Client;
48
+ config: NormalizedS3Config;
49
+ sdk: typeof import('@aws-sdk/client-s3');
50
+ };
51
+ }
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var CoreS3Service_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.CoreS3Service = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const content_disposition_helper_1 = require("../helpers/content-disposition.helper");
16
+ const config_service_1 = require("./config.service");
17
+ const MAX_PRESIGNED_EXPIRY_SECONDS = 604_800;
18
+ const PRESIGNED_EXPIRY_ADVISORY_SECONDS = 900;
19
+ let CoreS3Service = class CoreS3Service {
20
+ static { CoreS3Service_1 = this; }
21
+ configService;
22
+ logger = new common_1.Logger(CoreS3Service_1.name);
23
+ config;
24
+ client;
25
+ sdk;
26
+ presigner;
27
+ constructor(configService) {
28
+ this.configService = configService;
29
+ const raw = this.configService.getFastButReadOnly('s3');
30
+ if (!raw || raw.enabled === false) {
31
+ return;
32
+ }
33
+ if (!raw.bucket) {
34
+ this.logger.warn('Ignoring the `s3` configuration: no `bucket` is set, so S3 cannot be used.');
35
+ return;
36
+ }
37
+ const presigned = raw.presignedDownloads;
38
+ this.config = {
39
+ accessKeyId: raw.accessKeyId,
40
+ autoCreateBucket: raw.autoCreateBucket ?? false,
41
+ bucket: raw.bucket,
42
+ endpoint: raw.endpoint,
43
+ forcePathStyle: raw.forcePathStyle ?? false,
44
+ presignedDownloads: presigned
45
+ ? {
46
+ expiresInSeconds: this.clampPresignedExpiry((typeof presigned === 'object' ? presigned.expiresInSeconds : undefined) ?? 300),
47
+ }
48
+ : undefined,
49
+ region: raw.region ?? 'us-east-1',
50
+ secretAccessKey: raw.secretAccessKey,
51
+ stagingBucket: raw.stagingBucket ?? raw.bucket,
52
+ };
53
+ }
54
+ clampPresignedExpiry(seconds) {
55
+ if (!Number.isFinite(seconds) || seconds <= 0) {
56
+ this.logger.warn(`s3.presignedDownloads.expiresInSeconds is "${seconds}", which is not a positive number — using 300s.`);
57
+ return 300;
58
+ }
59
+ if (seconds > MAX_PRESIGNED_EXPIRY_SECONDS) {
60
+ this.logger.warn(`s3.presignedDownloads.expiresInSeconds is ${seconds}s, above the ${MAX_PRESIGNED_EXPIRY_SECONDS}s AWS SigV4 ` +
61
+ 'maximum — capping it, since a longer signature is rejected by S3 rather than honored.');
62
+ return MAX_PRESIGNED_EXPIRY_SECONDS;
63
+ }
64
+ if (seconds > PRESIGNED_EXPIRY_ADVISORY_SECONDS) {
65
+ this.logger.warn(`s3.presignedDownloads.expiresInSeconds is ${seconds}s. A presigned URL is an unrevocable bearer capability ` +
66
+ 'authorized once at issue time — keep it just long enough for the download to start (a few minutes), not ' +
67
+ 'long enough for the link to be forwarded, logged and reused.');
68
+ }
69
+ return seconds;
70
+ }
71
+ get enabled() {
72
+ return !!this.config;
73
+ }
74
+ getConfig() {
75
+ return this.config;
76
+ }
77
+ async onModuleInit() {
78
+ if (!this.config) {
79
+ return;
80
+ }
81
+ try {
82
+ this.sdk = await Promise.resolve().then(() => require('@aws-sdk/client-s3'));
83
+ }
84
+ catch {
85
+ throw new Error('S3 is configured (ServerOptions.s3) but the optional peer dependency "@aws-sdk/client-s3" is not installed. ' +
86
+ 'Run: pnpm add @aws-sdk/client-s3');
87
+ }
88
+ const { accessKeyId, endpoint, forcePathStyle, region, secretAccessKey } = this.config;
89
+ this.client = new this.sdk.S3Client({
90
+ ...(endpoint ? { endpoint } : {}),
91
+ forcePathStyle,
92
+ region,
93
+ ...(accessKeyId && secretAccessKey ? { credentials: { accessKeyId, secretAccessKey } } : {}),
94
+ });
95
+ await this.verifyBuckets();
96
+ }
97
+ async verifyBuckets() {
98
+ const buckets = [...new Set([this.config.bucket, this.config.stagingBucket])];
99
+ for (const bucket of buckets) {
100
+ try {
101
+ if (await this.bucketExists(bucket)) {
102
+ continue;
103
+ }
104
+ if (this.config.autoCreateBucket) {
105
+ await this.ensureBucket(bucket);
106
+ this.logger.log(`Created S3 bucket "${bucket}" (s3.autoCreateBucket is on)`);
107
+ continue;
108
+ }
109
+ this.logger.error(`S3 bucket "${bucket}" does not exist. Every upload will fail until it is created. ` +
110
+ 'Create it in your object storage, or set s3.autoCreateBucket: true to have the server create it.');
111
+ }
112
+ catch (error) {
113
+ this.logger.error(`Could not verify S3 bucket "${bucket}": ${error instanceof Error ? error.message : 'Unknown error'}`);
114
+ }
115
+ }
116
+ }
117
+ async bucketExists(bucket) {
118
+ const { client, sdk } = this.requireInit();
119
+ try {
120
+ await client.send(new sdk.HeadBucketCommand({ Bucket: bucket }));
121
+ return true;
122
+ }
123
+ catch (error) {
124
+ const status = error?.$metadata?.httpStatusCode;
125
+ if (status === 404 || error?.name === 'NotFound' || error?.name === 'NoSuchBucket') {
126
+ return false;
127
+ }
128
+ throw error;
129
+ }
130
+ }
131
+ getClient() {
132
+ if (!this.config) {
133
+ throw new Error('S3 is not configured/enabled (ServerOptions.s3)');
134
+ }
135
+ if (!this.client || !this.sdk) {
136
+ throw new Error('CoreS3Service is not initialized yet (onModuleInit pending)');
137
+ }
138
+ return this.client;
139
+ }
140
+ async putObject(key, body, contentType, contentLength) {
141
+ const { client, config, sdk } = this.requireInit();
142
+ let payload = body;
143
+ let length = contentLength;
144
+ if (this.isStream(body) && length === undefined) {
145
+ payload = await this.collect(body);
146
+ length = payload.length;
147
+ }
148
+ else if (length === undefined && typeof body !== 'string') {
149
+ length = body.length;
150
+ }
151
+ await client.send(new sdk.PutObjectCommand({
152
+ Body: payload,
153
+ Bucket: config.bucket,
154
+ ...(contentType ? { ContentType: contentType } : {}),
155
+ ...(length === undefined ? {} : { ContentLength: length }),
156
+ Key: key,
157
+ }));
158
+ }
159
+ async copyObject(sourceKey, destinationKey, sourceBucket, contentType) {
160
+ const { client, config, sdk } = this.requireInit();
161
+ await client.send(new sdk.CopyObjectCommand({
162
+ Bucket: config.bucket,
163
+ CopySource: this.copySource(sourceBucket ?? config.bucket, sourceKey),
164
+ Key: destinationKey,
165
+ ...(contentType ? { ContentType: contentType, MetadataDirective: 'REPLACE' } : {}),
166
+ }));
167
+ }
168
+ static MAX_COPY_OBJECT_BYTES = 5 * 1024 * 1024 * 1024;
169
+ copySource(bucket, key) {
170
+ const encoded = key
171
+ .split('/')
172
+ .map((segment) => encodeURIComponent(segment))
173
+ .join('/');
174
+ return `/${encodeURIComponent(bucket)}/${encoded}`;
175
+ }
176
+ isStream(body) {
177
+ return !!body && typeof body.pipe === 'function';
178
+ }
179
+ async collect(stream) {
180
+ const chunks = [];
181
+ for await (const chunk of stream) {
182
+ chunks.push(Buffer.from(chunk));
183
+ }
184
+ return Buffer.concat(chunks);
185
+ }
186
+ async getObject(key) {
187
+ const { client, config, sdk } = this.requireInit();
188
+ const result = await client.send(new sdk.GetObjectCommand({ Bucket: config.bucket, Key: key }));
189
+ return {
190
+ body: result.Body,
191
+ contentLength: result.ContentLength,
192
+ contentType: result.ContentType,
193
+ };
194
+ }
195
+ async deleteObject(key, bucket) {
196
+ const { client, config, sdk } = this.requireInit();
197
+ await client.send(new sdk.DeleteObjectCommand({ Bucket: bucket ?? config.bucket, Key: key }));
198
+ }
199
+ async objectExists(key) {
200
+ const { client, config, sdk } = this.requireInit();
201
+ try {
202
+ await client.send(new sdk.HeadObjectCommand({ Bucket: config.bucket, Key: key }));
203
+ return true;
204
+ }
205
+ catch (error) {
206
+ if (error?.$metadata?.httpStatusCode === 404 || error?.name === 'NotFound') {
207
+ return false;
208
+ }
209
+ throw error;
210
+ }
211
+ }
212
+ async getPresignedDownloadUrl(key, filename) {
213
+ const { client, config, sdk } = this.requireInit();
214
+ if (!config.presignedDownloads) {
215
+ return undefined;
216
+ }
217
+ if (!this.presigner) {
218
+ try {
219
+ this.presigner = await Promise.resolve().then(() => require('@aws-sdk/s3-request-presigner'));
220
+ }
221
+ catch {
222
+ throw new Error('s3.presignedDownloads is enabled but the optional peer dependency "@aws-sdk/s3-request-presigner" is not installed. ' +
223
+ 'Run: pnpm add @aws-sdk/s3-request-presigner');
224
+ }
225
+ }
226
+ const command = new sdk.GetObjectCommand({
227
+ Bucket: config.bucket,
228
+ Key: key,
229
+ ...(filename ? { ResponseContentDisposition: (0, content_disposition_helper_1.buildContentDisposition)(filename) } : {}),
230
+ });
231
+ return this.presigner.getSignedUrl(client, command, { expiresIn: config.presignedDownloads.expiresInSeconds });
232
+ }
233
+ async ensureBucket(bucket) {
234
+ const { client, sdk } = this.requireInit();
235
+ try {
236
+ await client.send(new sdk.HeadBucketCommand({ Bucket: bucket }));
237
+ }
238
+ catch {
239
+ await client.send(new sdk.CreateBucketCommand({ Bucket: bucket }));
240
+ }
241
+ }
242
+ async onApplicationShutdown() {
243
+ this.client?.destroy();
244
+ this.client = undefined;
245
+ }
246
+ requireInit() {
247
+ if (!this.config) {
248
+ throw new Error('S3 is not configured/enabled (ServerOptions.s3)');
249
+ }
250
+ if (!this.client || !this.sdk) {
251
+ throw new Error('CoreS3Service is not initialized yet (onModuleInit pending)');
252
+ }
253
+ return { client: this.client, config: this.config, sdk: this.sdk };
254
+ }
255
+ };
256
+ exports.CoreS3Service = CoreS3Service;
257
+ exports.CoreS3Service = CoreS3Service = CoreS3Service_1 = __decorate([
258
+ (0, common_1.Injectable)(),
259
+ __metadata("design:paramtypes", [config_service_1.ConfigService])
260
+ ], CoreS3Service);
261
+ //# sourceMappingURL=core-s3.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-s3.service.js","sourceRoot":"","sources":["../../../../src/core/common/services/core-s3.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Logger, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
2
+ import { HttpAdapterHost } from '@nestjs/core';
3
+ import { IServerOptions } from '../interfaces/server-options.interface';
4
+ export declare class CoreTrustProxyInitializer implements OnApplicationBootstrap, OnModuleInit {
5
+ protected readonly httpAdapterHost?: HttpAdapterHost;
6
+ protected readonly logger: Logger;
7
+ constructor(httpAdapterHost?: HttpAdapterHost);
8
+ onModuleInit(): void;
9
+ onApplicationBootstrap(): void;
10
+ protected enabledIpRateLimiters(): string[];
11
+ protected getConfigured(): IServerOptions['trustProxy'];
12
+ protected getExpressApp(): undefined | {
13
+ get: (name: string) => any;
14
+ set: (name: string, value: any) => void;
15
+ };
16
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var CoreTrustProxyInitializer_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.CoreTrustProxyInitializer = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const core_1 = require("@nestjs/core");
19
+ const config_service_1 = require("./config.service");
20
+ const TRUST_PROXY = 'trust proxy';
21
+ let CoreTrustProxyInitializer = CoreTrustProxyInitializer_1 = class CoreTrustProxyInitializer {
22
+ httpAdapterHost;
23
+ logger = new common_1.Logger(CoreTrustProxyInitializer_1.name);
24
+ constructor(httpAdapterHost) {
25
+ this.httpAdapterHost = httpAdapterHost;
26
+ }
27
+ onModuleInit() {
28
+ const configured = this.getConfigured();
29
+ if (configured === undefined) {
30
+ return;
31
+ }
32
+ const app = this.getExpressApp();
33
+ if (!app) {
34
+ return;
35
+ }
36
+ app.set(TRUST_PROXY, configured);
37
+ this.logger.log(`Express "trust proxy" set to ${JSON.stringify(configured)} — request.ip follows X-Forwarded-For accordingly`);
38
+ }
39
+ onApplicationBootstrap() {
40
+ const limiters = this.enabledIpRateLimiters();
41
+ if (this.getConfigured() !== undefined || !limiters.length) {
42
+ return;
43
+ }
44
+ const app = this.getExpressApp();
45
+ if (!app || app.get(TRUST_PROXY)) {
46
+ return;
47
+ }
48
+ this.logger.warn(`Rate limiting is enabled (${limiters.join(', ')}) but Express "trust proxy" is not set. ` +
49
+ 'Behind a reverse proxy (Caddy, nginx, a Kubernetes ingress) request.ip is then the PROXY address for every ' +
50
+ 'request, so every client behind a reverse proxy shares one bucket and the limit throttles all of them at ' +
51
+ 'once. Set `trustProxy` in your server options to the number of proxy hops in front of this app ' +
52
+ '(e.g. `trustProxy: 1`), or `trustProxy: false` if nothing proxies it — which also silences this warning.');
53
+ }
54
+ enabledIpRateLimiters() {
55
+ return ['auth.rateLimit', 'betterAuth.rateLimit'].filter((path) => {
56
+ const config = config_service_1.ConfigService.getFastButReadOnly(path);
57
+ if (config === undefined || config === null || config === false) {
58
+ return false;
59
+ }
60
+ return typeof config === 'boolean' ? config : config.enabled !== false;
61
+ });
62
+ }
63
+ getConfigured() {
64
+ return config_service_1.ConfigService.getFastButReadOnly('trustProxy');
65
+ }
66
+ getExpressApp() {
67
+ const instance = this.httpAdapterHost?.httpAdapter?.getInstance?.();
68
+ return typeof instance?.set === 'function' && typeof instance?.get === 'function' ? instance : undefined;
69
+ }
70
+ };
71
+ exports.CoreTrustProxyInitializer = CoreTrustProxyInitializer;
72
+ exports.CoreTrustProxyInitializer = CoreTrustProxyInitializer = CoreTrustProxyInitializer_1 = __decorate([
73
+ (0, common_1.Injectable)(),
74
+ __param(0, (0, common_1.Optional)()),
75
+ __metadata("design:paramtypes", [core_1.HttpAdapterHost])
76
+ ], CoreTrustProxyInitializer);
77
+ //# sourceMappingURL=core-trust-proxy.initializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-trust-proxy.initializer.js","sourceRoot":"","sources":["../../../../src/core/common/services/core-trust-proxy.initializer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAoG;AACpG,uCAA+C;AAG/C,qDAAiD;AAGjD,MAAM,WAAW,GAAG,aAAa,CAAC;AAe3B,IAAM,yBAAyB,iCAA/B,MAAM,yBAAyB;IAGO;IAFxB,MAAM,GAAG,IAAI,eAAM,CAAC,2BAAyB,CAAC,IAAI,CAAC,CAAC;IAEvE,YAA2C,eAAiC;QAAjC,oBAAe,GAAf,eAAe,CAAkB;IAAG,CAAC;IAShF,YAAY;QACV,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,EAAE,CAAC;YAGT,OAAO;QACT,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,gCAAgC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,mDAAmD,CAC9G,CAAC;IACJ,CAAC;IAaD,sBAAsB;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC9C,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,6BAA6B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C;YACxF,6GAA6G;YAC7G,2GAA2G;YAC3G,iGAAiG;YACjG,0GAA0G,CAC7G,CAAC;IACJ,CAAC;IASS,qBAAqB;QAC7B,OAAQ,CAAC,gBAAgB,EAAE,sBAAsB,CAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YAC3E,MAAM,MAAM,GAAG,8BAAa,CAAC,kBAAkB,CAAkC,IAAI,CAAC,CAAC;YACvF,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC;IAGS,aAAa;QACrB,OAAO,8BAAa,CAAC,kBAAkB,CAA+B,YAAY,CAAC,CAAC;IACtF,CAAC;IAGS,aAAa;QACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,CAAC;QACpE,OAAO,OAAO,QAAQ,EAAE,GAAG,KAAK,UAAU,IAAI,OAAO,QAAQ,EAAE,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3G,CAAC;CACF,CAAA;AAzFY,8DAAyB;oCAAzB,yBAAyB;IADrC,IAAA,mBAAU,GAAE;IAIE,WAAA,IAAA,iBAAQ,GAAE,CAAA;qCAAsC,sBAAe;GAHjE,yBAAyB,CAyFrC"}
@@ -0,0 +1,61 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import type { CoreRedisService } from './core-redis.service';
3
+ export declare function rateLimitKey(...parts: string[]): string;
4
+ export declare function rateLimitKeyPrefix(...parts: string[]): string;
5
+ export interface RateLimitStoreHit {
6
+ count: number;
7
+ resetIn: number;
8
+ }
9
+ export interface RateLimitStore {
10
+ clear(): Promise<void>;
11
+ hit(key: string, windowSeconds: number): Promise<RateLimitStoreHit>;
12
+ resetByPrefix(prefix: string): Promise<void>;
13
+ size(): number;
14
+ destroy?(): void;
15
+ }
16
+ export declare class InMemoryRateLimitStore implements RateLimitStore {
17
+ protected readonly maxEntries: number;
18
+ protected readonly store: Map<string, {
19
+ count: number;
20
+ resetTime: number;
21
+ }>;
22
+ protected cleanupInterval: NodeJS.Timeout | null;
23
+ protected atCapacity: boolean;
24
+ protected capacityWarned: boolean;
25
+ protected readonly overflow: Map<number, {
26
+ count: number;
27
+ resetTime: number;
28
+ }>;
29
+ constructor(maxEntries?: number);
30
+ clear(): Promise<void>;
31
+ hit(key: string, windowSeconds: number): Promise<RateLimitStoreHit>;
32
+ resetByPrefix(prefix: string): Promise<void>;
33
+ protected hitOverflow(key: string, windowSeconds: number, now: number): RateLimitStoreHit;
34
+ size(): number;
35
+ destroy(): void;
36
+ protected removeExpired(): number;
37
+ protected evictOldest(): void;
38
+ }
39
+ export declare class RedisRateLimitStore implements RateLimitStore {
40
+ protected readonly redisService: CoreRedisService;
41
+ protected readonly namespace: string;
42
+ protected readonly maxKeys: number;
43
+ protected readonly fallback: InMemoryRateLimitStore;
44
+ protected degraded: boolean;
45
+ protected readonly logger: Logger;
46
+ protected capacityWarned: boolean;
47
+ protected readonly prepared: WeakSet<object>;
48
+ constructor(redisService: CoreRedisService, namespace: string, maxKeys?: number);
49
+ clear(): Promise<void>;
50
+ hit(key: string, windowSeconds: number): Promise<RateLimitStoreHit>;
51
+ protected runHit(key: string, windowSeconds: number): Promise<[number, number, number]>;
52
+ resetByPrefix(prefix: string): Promise<void>;
53
+ size(): number;
54
+ destroy(): void;
55
+ protected guard<T>(operation: () => Promise<T>, onFailure: (() => Promise<T> | T) | undefined): Promise<T>;
56
+ protected redisKey(key: string): string;
57
+ protected redisKeyPattern(prefix: string): string;
58
+ protected cardinalityKey(): string;
59
+ protected overflowKey(key: string): string;
60
+ protected deleteByPattern(pattern: string): Promise<void>;
61
+ }