@pawells/nestjs-shared 1.0.0-dev.4c8c698

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 (286) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +802 -0
  3. package/build/LICENSE +21 -0
  4. package/build/README.md +802 -0
  5. package/build/common/common.module.d.ts +49 -0
  6. package/build/common/common.module.d.ts.map +1 -0
  7. package/build/common/common.module.js +178 -0
  8. package/build/common/common.module.js.map +1 -0
  9. package/build/common/constants/histogram-buckets.constants.d.ts +12 -0
  10. package/build/common/constants/histogram-buckets.constants.d.ts.map +1 -0
  11. package/build/common/constants/histogram-buckets.constants.js +51 -0
  12. package/build/common/constants/histogram-buckets.constants.js.map +1 -0
  13. package/build/common/constants/http-status.constants.d.ts +27 -0
  14. package/build/common/constants/http-status.constants.d.ts.map +1 -0
  15. package/build/common/constants/http-status.constants.js +27 -0
  16. package/build/common/constants/http-status.constants.js.map +1 -0
  17. package/build/common/constants/timeout.constants.d.ts +29 -0
  18. package/build/common/constants/timeout.constants.d.ts.map +1 -0
  19. package/build/common/constants/timeout.constants.js +45 -0
  20. package/build/common/constants/timeout.constants.js.map +1 -0
  21. package/build/common/controllers/metrics.controller.d.ts +23 -0
  22. package/build/common/controllers/metrics.controller.d.ts.map +1 -0
  23. package/build/common/controllers/metrics.controller.js +66 -0
  24. package/build/common/controllers/metrics.controller.js.map +1 -0
  25. package/build/common/decorators/common-decorators.d.ts +90 -0
  26. package/build/common/decorators/common-decorators.d.ts.map +1 -0
  27. package/build/common/decorators/common-decorators.js +101 -0
  28. package/build/common/decorators/common-decorators.js.map +1 -0
  29. package/build/common/decorators/decorator-factory.d.ts +108 -0
  30. package/build/common/decorators/decorator-factory.d.ts.map +1 -0
  31. package/build/common/decorators/decorator-factory.js +104 -0
  32. package/build/common/decorators/decorator-factory.js.map +1 -0
  33. package/build/common/decorators/guard.decorators.d.ts +48 -0
  34. package/build/common/decorators/guard.decorators.d.ts.map +1 -0
  35. package/build/common/decorators/guard.decorators.js +49 -0
  36. package/build/common/decorators/guard.decorators.js.map +1 -0
  37. package/build/common/decorators/index.d.ts +10 -0
  38. package/build/common/decorators/index.d.ts.map +1 -0
  39. package/build/common/decorators/index.js +11 -0
  40. package/build/common/decorators/index.js.map +1 -0
  41. package/build/common/decorators/instrument.decorator.d.ts +128 -0
  42. package/build/common/decorators/instrument.decorator.d.ts.map +1 -0
  43. package/build/common/decorators/instrument.decorator.js +165 -0
  44. package/build/common/decorators/instrument.decorator.js.map +1 -0
  45. package/build/common/decorators/metric.decorators.d.ts +42 -0
  46. package/build/common/decorators/metric.decorators.d.ts.map +1 -0
  47. package/build/common/decorators/metric.decorators.js +85 -0
  48. package/build/common/decorators/metric.decorators.js.map +1 -0
  49. package/build/common/decorators/request-property.decorator.d.ts +65 -0
  50. package/build/common/decorators/request-property.decorator.d.ts.map +1 -0
  51. package/build/common/decorators/request-property.decorator.js +102 -0
  52. package/build/common/decorators/request-property.decorator.js.map +1 -0
  53. package/build/common/errors/base-application-error.d.ts +98 -0
  54. package/build/common/errors/base-application-error.d.ts.map +1 -0
  55. package/build/common/errors/base-application-error.js +133 -0
  56. package/build/common/errors/base-application-error.js.map +1 -0
  57. package/build/common/errors/error-factory.d.ts +93 -0
  58. package/build/common/errors/error-factory.d.ts.map +1 -0
  59. package/build/common/errors/error-factory.js +105 -0
  60. package/build/common/errors/error-factory.js.map +1 -0
  61. package/build/common/errors/index.d.ts +13 -0
  62. package/build/common/errors/index.d.ts.map +1 -0
  63. package/build/common/errors/index.js +15 -0
  64. package/build/common/errors/index.js.map +1 -0
  65. package/build/common/factories/index.d.ts +5 -0
  66. package/build/common/factories/index.d.ts.map +1 -0
  67. package/build/common/factories/index.js +3 -0
  68. package/build/common/factories/index.js.map +1 -0
  69. package/build/common/factories/module-factory.d.ts +178 -0
  70. package/build/common/factories/module-factory.d.ts.map +1 -0
  71. package/build/common/factories/module-factory.js +253 -0
  72. package/build/common/factories/module-factory.js.map +1 -0
  73. package/build/common/factories/rate-limit-config.factory.d.ts +79 -0
  74. package/build/common/factories/rate-limit-config.factory.d.ts.map +1 -0
  75. package/build/common/factories/rate-limit-config.factory.js +115 -0
  76. package/build/common/factories/rate-limit-config.factory.js.map +1 -0
  77. package/build/common/factories/security-bootstrap.factory.d.ts +77 -0
  78. package/build/common/factories/security-bootstrap.factory.d.ts.map +1 -0
  79. package/build/common/factories/security-bootstrap.factory.js +222 -0
  80. package/build/common/factories/security-bootstrap.factory.js.map +1 -0
  81. package/build/common/filters/global-exception.filter.d.ts +78 -0
  82. package/build/common/filters/global-exception.filter.d.ts.map +1 -0
  83. package/build/common/filters/global-exception.filter.js +192 -0
  84. package/build/common/filters/global-exception.filter.js.map +1 -0
  85. package/build/common/filters/http-exception.filter.d.ts +37 -0
  86. package/build/common/filters/http-exception.filter.d.ts.map +1 -0
  87. package/build/common/filters/http-exception.filter.js +91 -0
  88. package/build/common/filters/http-exception.filter.js.map +1 -0
  89. package/build/common/guards/csrf.guard.d.ts +53 -0
  90. package/build/common/guards/csrf.guard.d.ts.map +1 -0
  91. package/build/common/guards/csrf.guard.js +109 -0
  92. package/build/common/guards/csrf.guard.js.map +1 -0
  93. package/build/common/guards/metrics.guard.d.ts +42 -0
  94. package/build/common/guards/metrics.guard.d.ts.map +1 -0
  95. package/build/common/guards/metrics.guard.js +124 -0
  96. package/build/common/guards/metrics.guard.js.map +1 -0
  97. package/build/common/index.d.ts +43 -0
  98. package/build/common/index.d.ts.map +1 -0
  99. package/build/common/index.js +50 -0
  100. package/build/common/index.js.map +1 -0
  101. package/build/common/interceptors/http-client.interceptor.d.ts +11 -0
  102. package/build/common/interceptors/http-client.interceptor.d.ts.map +1 -0
  103. package/build/common/interceptors/http-client.interceptor.js +69 -0
  104. package/build/common/interceptors/http-client.interceptor.js.map +1 -0
  105. package/build/common/interceptors/http-instrumentation.interceptor.d.ts +64 -0
  106. package/build/common/interceptors/http-instrumentation.interceptor.d.ts.map +1 -0
  107. package/build/common/interceptors/http-instrumentation.interceptor.js +148 -0
  108. package/build/common/interceptors/http-instrumentation.interceptor.js.map +1 -0
  109. package/build/common/interceptors/http-metrics.interceptor.d.ts +46 -0
  110. package/build/common/interceptors/http-metrics.interceptor.d.ts.map +1 -0
  111. package/build/common/interceptors/http-metrics.interceptor.js +120 -0
  112. package/build/common/interceptors/http-metrics.interceptor.js.map +1 -0
  113. package/build/common/interceptors/logging.interceptor.d.ts +22 -0
  114. package/build/common/interceptors/logging.interceptor.d.ts.map +1 -0
  115. package/build/common/interceptors/logging.interceptor.js +67 -0
  116. package/build/common/interceptors/logging.interceptor.js.map +1 -0
  117. package/build/common/interfaces/cache-provider.interface.d.ts +54 -0
  118. package/build/common/interfaces/cache-provider.interface.d.ts.map +1 -0
  119. package/build/common/interfaces/cache-provider.interface.js +6 -0
  120. package/build/common/interfaces/cache-provider.interface.js.map +1 -0
  121. package/build/common/interfaces/index.d.ts +7 -0
  122. package/build/common/interfaces/index.d.ts.map +1 -0
  123. package/build/common/interfaces/index.js +3 -0
  124. package/build/common/interfaces/index.js.map +1 -0
  125. package/build/common/interfaces/log-context.interface.d.ts +77 -0
  126. package/build/common/interfaces/log-context.interface.d.ts.map +1 -0
  127. package/build/common/interfaces/log-context.interface.js +2 -0
  128. package/build/common/interfaces/log-context.interface.js.map +1 -0
  129. package/build/common/interfaces/log-entry.interface.d.ts +26 -0
  130. package/build/common/interfaces/log-entry.interface.d.ts.map +1 -0
  131. package/build/common/interfaces/log-entry.interface.js +33 -0
  132. package/build/common/interfaces/log-entry.interface.js.map +1 -0
  133. package/build/common/interfaces/logger.interface.d.ts +62 -0
  134. package/build/common/interfaces/logger.interface.d.ts.map +1 -0
  135. package/build/common/interfaces/logger.interface.js +2 -0
  136. package/build/common/interfaces/logger.interface.js.map +1 -0
  137. package/build/common/interfaces/metrics-exporter.interface.d.ts +275 -0
  138. package/build/common/interfaces/metrics-exporter.interface.d.ts.map +1 -0
  139. package/build/common/interfaces/metrics-exporter.interface.js +8 -0
  140. package/build/common/interfaces/metrics-exporter.interface.js.map +1 -0
  141. package/build/common/metrics/base-metrics-collector.d.ts +81 -0
  142. package/build/common/metrics/base-metrics-collector.d.ts.map +1 -0
  143. package/build/common/metrics/base-metrics-collector.js +88 -0
  144. package/build/common/metrics/base-metrics-collector.js.map +1 -0
  145. package/build/common/metrics/index.d.ts +2 -0
  146. package/build/common/metrics/index.d.ts.map +1 -0
  147. package/build/common/metrics/index.js +2 -0
  148. package/build/common/metrics/index.js.map +1 -0
  149. package/build/common/metrics.module.d.ts +50 -0
  150. package/build/common/metrics.module.d.ts.map +1 -0
  151. package/build/common/metrics.module.js +77 -0
  152. package/build/common/metrics.module.js.map +1 -0
  153. package/build/common/modules/throttler.module.d.ts +69 -0
  154. package/build/common/modules/throttler.module.d.ts.map +1 -0
  155. package/build/common/modules/throttler.module.js +117 -0
  156. package/build/common/modules/throttler.module.js.map +1 -0
  157. package/build/common/pipes/base-validation.pipe.d.ts +67 -0
  158. package/build/common/pipes/base-validation.pipe.d.ts.map +1 -0
  159. package/build/common/pipes/base-validation.pipe.js +95 -0
  160. package/build/common/pipes/base-validation.pipe.js.map +1 -0
  161. package/build/common/pipes/validation.pipe.d.ts +32 -0
  162. package/build/common/pipes/validation.pipe.d.ts.map +1 -0
  163. package/build/common/pipes/validation.pipe.js +60 -0
  164. package/build/common/pipes/validation.pipe.js.map +1 -0
  165. package/build/common/registry/instrumentation-registry.d.ts +227 -0
  166. package/build/common/registry/instrumentation-registry.d.ts.map +1 -0
  167. package/build/common/registry/instrumentation-registry.js +414 -0
  168. package/build/common/registry/instrumentation-registry.js.map +1 -0
  169. package/build/common/services/audit-logger.service.d.ts +91 -0
  170. package/build/common/services/audit-logger.service.d.ts.map +1 -0
  171. package/build/common/services/audit-logger.service.js +180 -0
  172. package/build/common/services/audit-logger.service.js.map +1 -0
  173. package/build/common/services/csrf.service.d.ts +202 -0
  174. package/build/common/services/csrf.service.d.ts.map +1 -0
  175. package/build/common/services/csrf.service.js +478 -0
  176. package/build/common/services/csrf.service.js.map +1 -0
  177. package/build/common/services/error-categorizer.service.d.ts +82 -0
  178. package/build/common/services/error-categorizer.service.d.ts.map +1 -0
  179. package/build/common/services/error-categorizer.service.js +339 -0
  180. package/build/common/services/error-categorizer.service.js.map +1 -0
  181. package/build/common/services/error-sanitizer.service.d.ts +146 -0
  182. package/build/common/services/error-sanitizer.service.d.ts.map +1 -0
  183. package/build/common/services/error-sanitizer.service.js +287 -0
  184. package/build/common/services/error-sanitizer.service.js.map +1 -0
  185. package/build/common/services/health-check.service.d.ts +86 -0
  186. package/build/common/services/health-check.service.d.ts.map +1 -0
  187. package/build/common/services/health-check.service.js +132 -0
  188. package/build/common/services/health-check.service.js.map +1 -0
  189. package/build/common/services/http-client.service.d.ts +113 -0
  190. package/build/common/services/http-client.service.d.ts.map +1 -0
  191. package/build/common/services/http-client.service.js +294 -0
  192. package/build/common/services/http-client.service.js.map +1 -0
  193. package/build/common/services/logger.service.d.ts +189 -0
  194. package/build/common/services/logger.service.d.ts.map +1 -0
  195. package/build/common/services/logger.service.js +423 -0
  196. package/build/common/services/logger.service.js.map +1 -0
  197. package/build/common/services/metrics-registry.service.d.ts +98 -0
  198. package/build/common/services/metrics-registry.service.d.ts.map +1 -0
  199. package/build/common/services/metrics-registry.service.js +262 -0
  200. package/build/common/services/metrics-registry.service.js.map +1 -0
  201. package/build/common/services/nest-logger-adapter.service.d.ts +62 -0
  202. package/build/common/services/nest-logger-adapter.service.d.ts.map +1 -0
  203. package/build/common/services/nest-logger-adapter.service.js +120 -0
  204. package/build/common/services/nest-logger-adapter.service.js.map +1 -0
  205. package/build/common/utils/error.utils.d.ts +16 -0
  206. package/build/common/utils/error.utils.d.ts.map +1 -0
  207. package/build/common/utils/error.utils.js +26 -0
  208. package/build/common/utils/error.utils.js.map +1 -0
  209. package/build/common/utils/lazy-getter.types.d.ts +190 -0
  210. package/build/common/utils/lazy-getter.types.d.ts.map +1 -0
  211. package/build/common/utils/lazy-getter.types.js +114 -0
  212. package/build/common/utils/lazy-getter.types.js.map +1 -0
  213. package/build/common/utils/module.utils.d.ts +33 -0
  214. package/build/common/utils/module.utils.d.ts.map +1 -0
  215. package/build/common/utils/module.utils.js +48 -0
  216. package/build/common/utils/module.utils.js.map +1 -0
  217. package/build/common/utils/sanitization.utils.d.ts +69 -0
  218. package/build/common/utils/sanitization.utils.d.ts.map +1 -0
  219. package/build/common/utils/sanitization.utils.js +141 -0
  220. package/build/common/utils/sanitization.utils.js.map +1 -0
  221. package/build/config/config.module.d.ts +30 -0
  222. package/build/config/config.module.d.ts.map +1 -0
  223. package/build/config/config.module.js +49 -0
  224. package/build/config/config.module.js.map +1 -0
  225. package/build/config/config.service.d.ts +74 -0
  226. package/build/config/config.service.d.ts.map +1 -0
  227. package/build/config/config.service.js +145 -0
  228. package/build/config/config.service.js.map +1 -0
  229. package/build/config/config.types.d.ts +143 -0
  230. package/build/config/config.types.d.ts.map +1 -0
  231. package/build/config/config.types.js +2 -0
  232. package/build/config/config.types.js.map +1 -0
  233. package/build/config/decorators/config.decorators.d.ts +43 -0
  234. package/build/config/decorators/config.decorators.d.ts.map +1 -0
  235. package/build/config/decorators/config.decorators.js +68 -0
  236. package/build/config/decorators/config.decorators.js.map +1 -0
  237. package/build/config/decorators/index.d.ts +2 -0
  238. package/build/config/decorators/index.d.ts.map +1 -0
  239. package/build/config/decorators/index.js +2 -0
  240. package/build/config/decorators/index.js.map +1 -0
  241. package/build/config/index.d.ts +7 -0
  242. package/build/config/index.d.ts.map +1 -0
  243. package/build/config/index.js +9 -0
  244. package/build/config/index.js.map +1 -0
  245. package/build/config/validation.utils.d.ts +136 -0
  246. package/build/config/validation.utils.d.ts.map +1 -0
  247. package/build/config/validation.utils.js +263 -0
  248. package/build/config/validation.utils.js.map +1 -0
  249. package/build/errors/index.d.ts +9 -0
  250. package/build/errors/index.d.ts.map +1 -0
  251. package/build/errors/index.js +12 -0
  252. package/build/errors/index.js.map +1 -0
  253. package/build/guards/custom-throttle.guard.d.ts +28 -0
  254. package/build/guards/custom-throttle.guard.d.ts.map +1 -0
  255. package/build/guards/custom-throttle.guard.js +52 -0
  256. package/build/guards/custom-throttle.guard.js.map +1 -0
  257. package/build/guards/index.d.ts +2 -0
  258. package/build/guards/index.d.ts.map +1 -0
  259. package/build/guards/index.js +2 -0
  260. package/build/guards/index.js.map +1 -0
  261. package/build/index.d.ts +53 -0
  262. package/build/index.d.ts.map +1 -0
  263. package/build/index.js +61 -0
  264. package/build/index.js.map +1 -0
  265. package/build/logging/index.d.ts +7 -0
  266. package/build/logging/index.d.ts.map +1 -0
  267. package/build/logging/index.js +7 -0
  268. package/build/logging/index.js.map +1 -0
  269. package/build/metrics/index.d.ts +6 -0
  270. package/build/metrics/index.d.ts.map +1 -0
  271. package/build/metrics/index.js +11 -0
  272. package/build/metrics/index.js.map +1 -0
  273. package/build/package.json +72 -0
  274. package/build/security/index.d.ts +8 -0
  275. package/build/security/index.d.ts.map +1 -0
  276. package/build/security/index.js +11 -0
  277. package/build/security/index.js.map +1 -0
  278. package/build/test-setup.d.ts +2 -0
  279. package/build/test-setup.d.ts.map +1 -0
  280. package/build/test-setup.js +40 -0
  281. package/build/test-setup.js.map +1 -0
  282. package/build/validation/index.d.ts +6 -0
  283. package/build/validation/index.d.ts.map +1 -0
  284. package/build/validation/index.js +8 -0
  285. package/build/validation/index.js.map +1 -0
  286. package/package.json +71 -0
@@ -0,0 +1,190 @@
1
+ /**
2
+ * @pawells/nestjs-shared - Lazy Module Ref Pattern Utilities
3
+ *
4
+ * This file provides type definitions and utilities for implementing the lazy ModuleRef
5
+ * dependency injection pattern. This pattern enables deferred dependency resolution,
6
+ * reducing constructor complexity and enabling circular dependency handling.
7
+ *
8
+ * @see {@link .claude/skills/lazy-module-ref-pattern.md} - Comprehensive pattern guide
9
+ */
10
+ import { ModuleRef } from '@nestjs/core';
11
+ /**
12
+ * Type for a lazy-loaded getter that retrieves a dependency from ModuleRef
13
+ *
14
+ * @template T - The type of dependency being retrieved
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * public get Logger(): AppLogger {
19
+ * return this.Module.get(AppLogger);
20
+ * }
21
+ * ```
22
+ */
23
+ export type LazyGetter<T> = () => T;
24
+ /**
25
+ * Type for an optional lazy-loaded getter that may return undefined
26
+ *
27
+ * @template T - The type of dependency being retrieved
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * public get OptionalConfig(): ConfigService | undefined {
32
+ * try {
33
+ * return this.Module.get(ConfigService, { strict: false });
34
+ * } catch {
35
+ * return undefined;
36
+ * }
37
+ * }
38
+ * ```
39
+ */
40
+ export type OptionalLazyGetter<T> = () => T | undefined;
41
+ /**
42
+ * Type for a lazy-loaded getter using a string-based injection token
43
+ *
44
+ * @template T - The type of dependency being retrieved
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * public get PubSub(): PubSub {
49
+ * return this.Module.get('PUB_SUB');
50
+ * }
51
+ * ```
52
+ */
53
+ export type TokenLazyGetter<T> = (token: string) => T;
54
+ /**
55
+ * Interface for a service using lazy ModuleRef pattern
56
+ *
57
+ * Services implementing this pattern should have ModuleRef as their only
58
+ * constructor dependency and provide typed getters for accessing other services.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * @Injectable()
63
+ * export class ExampleService implements LazyModuleRefService {
64
+ * constructor(public readonly Module: ModuleRef) {}
65
+ *
66
+ * public get SomeService(): SomeServiceType {
67
+ * return this.Module.get(SomeServiceType);
68
+ * }
69
+ * }
70
+ * ```
71
+ */
72
+ export interface LazyModuleRefService {
73
+ /**
74
+ * The ModuleRef instance for lazy dependency resolution
75
+ * This should be the ONLY injected dependency
76
+ */
77
+ Module: ModuleRef;
78
+ }
79
+ /**
80
+ * Utility type to extract dependencies from a service with lazy getters
81
+ *
82
+ * Maps getter names to their return types for documentation and type inference.
83
+ *
84
+ * @template S - The service type with lazy getters
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * type AuthServiceDeps = LazyGetterDependencies<AuthService>;
89
+ * // Results in: { Config: ConfigService, Logger: AppLogger }
90
+ * ```
91
+ */
92
+ export type LazyGetterDependencies<S> = {
93
+ [K in keyof S as S[K] extends LazyGetter<any> ? K : never]: S[K] extends LazyGetter<infer T> ? T : never;
94
+ };
95
+ /**
96
+ * Configuration for optional dependency resolution
97
+ * Used when a service may not be registered in the module
98
+ */
99
+ export interface OptionalGetterConfig {
100
+ /**
101
+ * Set to false to return undefined instead of throwing if not found
102
+ * @default true
103
+ */
104
+ strict?: boolean;
105
+ }
106
+ /**
107
+ * Utility function to create a memoized lazy getter
108
+ * Caches the resolved dependency to avoid repeated lookups
109
+ *
110
+ * @template T - The type of dependency
111
+ * @param getterFn - Function that retrieves the dependency
112
+ * @returns A memoized getter function
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * private _cachedService: ServiceType | undefined;
117
+ *
118
+ * public get Service(): ServiceType {
119
+ * if (!this._cachedService) {
120
+ * this._cachedService = this.Module.get(ServiceType);
121
+ * }
122
+ * return this._cachedService;
123
+ * }
124
+ * ```
125
+ */
126
+ export declare function CreateMemoizedLazyGetter<T>(getterFn: () => T): () => T;
127
+ /**
128
+ * Utility function to create a lazy getter with error handling for optional dependencies
129
+ *
130
+ * @template T - The type of dependency
131
+ * @param module - The ModuleRef instance
132
+ * @param token - The dependency token
133
+ * @param config - Optional configuration
134
+ * @returns The dependency or undefined
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * public get OptionalService(): ServiceType | undefined {
139
+ * return createOptionalLazyGetter(this.Module, ServiceType);
140
+ * }
141
+ * ```
142
+ */
143
+ export declare function CreateOptionalLazyGetter<T>(module: ModuleRef, token: string | Function, config?: OptionalGetterConfig): T | undefined;
144
+ /**
145
+ * Type guard to check if a value is a LazyModuleRefService
146
+ *
147
+ * @param value - The value to check
148
+ * @returns True if the value has a Module property of type ModuleRef
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * if (isLazyModuleRefService(service)) {
153
+ * // service.Module is available
154
+ * }
155
+ * ```
156
+ */
157
+ export declare function IsLazyModuleRefService(value: any): value is LazyModuleRefService;
158
+ /**
159
+ * Pattern naming convention constants
160
+ * Use these as documentation helpers for your lazy getter implementations
161
+ */
162
+ export declare const LazyGetterNamingConventions: {
163
+ /**
164
+ * Getter names should use PascalCase matching the service/type name
165
+ * Examples: Config, Logger, CacheService, OrderModel
166
+ */
167
+ NAMING_PATTERN: string;
168
+ /**
169
+ * Getter names should NOT include 'get' prefix or 'Service' suffix if redundant
170
+ * Example: public get Config() NOT public get getConfigService()
171
+ */
172
+ AVOID_REDUNDANCY: boolean;
173
+ /**
174
+ * For Mongoose models, use PascalCase + 'Model' suffix
175
+ * Example: public get OrderModel()
176
+ */
177
+ MODEL_SUFFIX: string;
178
+ /**
179
+ * For string-based tokens, use meaningful names representing the service
180
+ * Example: public get PubSub() for 'PUB_SUB' token
181
+ */
182
+ TOKEN_MAPPING: string;
183
+ };
184
+ /**
185
+ * Backwards compatibility aliases - exported functions use PascalCase per project conventions
186
+ */
187
+ export declare const createMemoizedLazyGetter: typeof CreateMemoizedLazyGetter;
188
+ export declare const createOptionalLazyGetter: typeof CreateOptionalLazyGetter;
189
+ export declare const isLazyModuleRefService: typeof IsLazyModuleRefService;
190
+ //# sourceMappingURL=lazy-getter.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-getter.types.d.ts","sourceRoot":"","sources":["../../../src/common/utils/lazy-getter.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;AAEtD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,MAAM,EAAE,SAAS,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI;KACtC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GACzF,CAAC,GACD,KAAK;CACR,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACzC,QAAQ,EAAE,MAAM,CAAC,GACf,MAAM,CAAC,CAWT;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACzC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,GAAG,QAAQ,EACxB,MAAM,CAAC,EAAE,oBAAoB,GAC3B,CAAC,GAAG,SAAS,CAMf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,oBAAoB,CAEhF;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B;IACvC;;;OAGG;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;;OAGG;;CAEH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,iCAA2B,CAAC;AACjE,eAAO,MAAM,wBAAwB,iCAA2B,CAAC;AACjE,eAAO,MAAM,sBAAsB,+BAAyB,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @pawells/nestjs-shared - Lazy Module Ref Pattern Utilities
3
+ *
4
+ * This file provides type definitions and utilities for implementing the lazy ModuleRef
5
+ * dependency injection pattern. This pattern enables deferred dependency resolution,
6
+ * reducing constructor complexity and enabling circular dependency handling.
7
+ *
8
+ * @see {@link .claude/skills/lazy-module-ref-pattern.md} - Comprehensive pattern guide
9
+ */
10
+ import { ModuleRef } from '@nestjs/core';
11
+ /**
12
+ * Utility function to create a memoized lazy getter
13
+ * Caches the resolved dependency to avoid repeated lookups
14
+ *
15
+ * @template T - The type of dependency
16
+ * @param getterFn - Function that retrieves the dependency
17
+ * @returns A memoized getter function
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * private _cachedService: ServiceType | undefined;
22
+ *
23
+ * public get Service(): ServiceType {
24
+ * if (!this._cachedService) {
25
+ * this._cachedService = this.Module.get(ServiceType);
26
+ * }
27
+ * return this._cachedService;
28
+ * }
29
+ * ```
30
+ */
31
+ export function CreateMemoizedLazyGetter(getterFn) {
32
+ let cached;
33
+ let initialized = false;
34
+ return () => {
35
+ if (!initialized) {
36
+ cached = getterFn();
37
+ initialized = true;
38
+ }
39
+ return cached;
40
+ };
41
+ }
42
+ /**
43
+ * Utility function to create a lazy getter with error handling for optional dependencies
44
+ *
45
+ * @template T - The type of dependency
46
+ * @param module - The ModuleRef instance
47
+ * @param token - The dependency token
48
+ * @param config - Optional configuration
49
+ * @returns The dependency or undefined
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * public get OptionalService(): ServiceType | undefined {
54
+ * return createOptionalLazyGetter(this.Module, ServiceType);
55
+ * }
56
+ * ```
57
+ */
58
+ export function CreateOptionalLazyGetter(module, token, config) {
59
+ try {
60
+ return module.get(token, { strict: config?.strict ?? true });
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ }
66
+ /**
67
+ * Type guard to check if a value is a LazyModuleRefService
68
+ *
69
+ * @param value - The value to check
70
+ * @returns True if the value has a Module property of type ModuleRef
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * if (isLazyModuleRefService(service)) {
75
+ * // service.Module is available
76
+ * }
77
+ * ```
78
+ */
79
+ export function IsLazyModuleRefService(value) {
80
+ return !!(value && typeof value === 'object' && 'Module' in value && value.Module instanceof ModuleRef);
81
+ }
82
+ /**
83
+ * Pattern naming convention constants
84
+ * Use these as documentation helpers for your lazy getter implementations
85
+ */
86
+ export const LazyGetterNamingConventions = {
87
+ /**
88
+ * Getter names should use PascalCase matching the service/type name
89
+ * Examples: Config, Logger, CacheService, OrderModel
90
+ */
91
+ NAMING_PATTERN: 'PascalCase (matching service/type name)',
92
+ /**
93
+ * Getter names should NOT include 'get' prefix or 'Service' suffix if redundant
94
+ * Example: public get Config() NOT public get getConfigService()
95
+ */
96
+ AVOID_REDUNDANCY: true,
97
+ /**
98
+ * For Mongoose models, use PascalCase + 'Model' suffix
99
+ * Example: public get OrderModel()
100
+ */
101
+ MODEL_SUFFIX: 'Model',
102
+ /**
103
+ * For string-based tokens, use meaningful names representing the service
104
+ * Example: public get PubSub() for 'PUB_SUB' token
105
+ */
106
+ TOKEN_MAPPING: 'Meaningful name for token string',
107
+ };
108
+ /**
109
+ * Backwards compatibility aliases - exported functions use PascalCase per project conventions
110
+ */
111
+ export const createMemoizedLazyGetter = CreateMemoizedLazyGetter;
112
+ export const createOptionalLazyGetter = CreateOptionalLazyGetter;
113
+ export const isLazyModuleRefService = IsLazyModuleRefService;
114
+ //# sourceMappingURL=lazy-getter.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-getter.types.js","sourceRoot":"","sources":["../../../src/common/utils/lazy-getter.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAyGzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,wBAAwB,CACvC,QAAiB;IAEjB,IAAI,MAAqB,CAAC;IAC1B,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,OAAO,GAAG,EAAE;QACX,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,MAAM,GAAG,QAAQ,EAAE,CAAC;YACpB,WAAW,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,MAAW,CAAC;IACpB,CAAC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,wBAAwB,CACvC,MAAiB,EACjB,KAAwB,EACxB,MAA6B;IAE7B,IAAI,CAAC;QACJ,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAU;IAChD,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,YAAY,SAAS,CAAC,CAAC;AACzG,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IAC1C;;;OAGG;IACH,cAAc,EAAE,yCAAyC;IAEzD;;;OAGG;IACH,gBAAgB,EAAE,IAAI;IAEtB;;;OAGG;IACH,YAAY,EAAE,OAAO;IAErB;;;OAGG;IACH,aAAa,EAAE,kCAAkC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AACjE,MAAM,CAAC,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AACjE,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { InjectionToken, OptionalFactoryDependency, Provider, Type } from '@nestjs/common';
2
+ /**
3
+ * Generic shape for forRootAsync() options.
4
+ *
5
+ * F is the factory interface (e.g. NatsOptionsFactory, QdrantModuleOptionsFactory).
6
+ * T is the resolved options type.
7
+ */
8
+ export interface AsyncModuleOptions<T, F = unknown> {
9
+ useFactory?: (...args: unknown[]) => T | Promise<T>;
10
+ useClass?: Type<F>;
11
+ useExisting?: Type<F>;
12
+ inject?: Array<InjectionToken | OptionalFactoryDependency>;
13
+ }
14
+ /**
15
+ * Creates the single async options provider (the injection-token → resolved-options
16
+ * mapping) for a forRootAsync() module.
17
+ *
18
+ * @param options The async options passed to forRootAsync()
19
+ * @param token Injection token to provide the resolved options under
20
+ * @param factoryFn Calls the factory method on the options-factory instance,
21
+ * e.g. `(f) => f.createNatsOptions()`
22
+ */
23
+ export declare function createAsyncOptionsProvider<T, F>(options: AsyncModuleOptions<T, F>, token: InjectionToken, factoryFn: (factory: F) => T | Promise<T>): Provider<T>;
24
+ /**
25
+ * Creates the full provider array for a forRootAsync() module — the options
26
+ * provider plus an optional self-binding for useClass.
27
+ *
28
+ * @param options The async options passed to forRootAsync()
29
+ * @param token Injection token to provide the resolved options under
30
+ * @param factoryFn Calls the factory method on the options-factory instance
31
+ */
32
+ export declare function createAsyncProviders<T, F>(options: AsyncModuleOptions<T, F>, token: InjectionToken, factoryFn: (factory: F) => T | Promise<T>): Provider[];
33
+ //# sourceMappingURL=module.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils/module.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,yBAAyB,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEhG;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO;IACjD,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACnB,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,GAAG,yBAAyB,CAAC,CAAC;CAC3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,CAAC,EAC9C,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACjC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvC,QAAQ,CAAC,CAAC,CAAC,CAmBb;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EACxC,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,EACjC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvC,QAAQ,EAAE,CAaZ"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Creates the single async options provider (the injection-token → resolved-options
3
+ * mapping) for a forRootAsync() module.
4
+ *
5
+ * @param options The async options passed to forRootAsync()
6
+ * @param token Injection token to provide the resolved options under
7
+ * @param factoryFn Calls the factory method on the options-factory instance,
8
+ * e.g. `(f) => f.createNatsOptions()`
9
+ */
10
+ export function createAsyncOptionsProvider(options, token, factoryFn) {
11
+ if (options.useFactory !== undefined) {
12
+ return {
13
+ provide: token,
14
+ useFactory: options.useFactory,
15
+ inject: (options.inject ?? []),
16
+ };
17
+ }
18
+ const factoryToken = options.useExisting ?? options.useClass;
19
+ if (factoryToken === undefined) {
20
+ throw new Error('Invalid async module options: must specify useFactory, useClass, or useExisting.');
21
+ }
22
+ return {
23
+ provide: token,
24
+ useFactory: factoryFn,
25
+ inject: [factoryToken],
26
+ };
27
+ }
28
+ /**
29
+ * Creates the full provider array for a forRootAsync() module — the options
30
+ * provider plus an optional self-binding for useClass.
31
+ *
32
+ * @param options The async options passed to forRootAsync()
33
+ * @param token Injection token to provide the resolved options under
34
+ * @param factoryFn Calls the factory method on the options-factory instance
35
+ */
36
+ export function createAsyncProviders(options, token, factoryFn) {
37
+ if (options.useExisting !== undefined || options.useFactory !== undefined) {
38
+ return [createAsyncOptionsProvider(options, token, factoryFn)];
39
+ }
40
+ if (options.useClass !== undefined) {
41
+ return [
42
+ createAsyncOptionsProvider(options, token, factoryFn),
43
+ { provide: options.useClass, useClass: options.useClass },
44
+ ];
45
+ }
46
+ throw new Error('Invalid async module options: must specify useFactory, useClass, or useExisting.');
47
+ }
48
+ //# sourceMappingURL=module.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.utils.js","sourceRoot":"","sources":["../../../src/common/utils/module.utils.ts"],"names":[],"mappings":"AAeA;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACzC,OAAiC,EACjC,KAAqB,EACrB,SAAyC;IAEzC,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO;YACN,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAsD;SACnF,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IAC7D,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACd,kFAAkF,CAClF,CAAC;IACH,CAAC;IACD,OAAO;QACN,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,CAAC,YAAY,CAAC;KACtB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CACnC,OAAiC,EACjC,KAAqB,EACrB,SAAyC;IAEzC,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QAC3E,OAAO,CAAC,0BAA0B,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;YACN,0BAA0B,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC;YACrD,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;SACzD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACd,kFAAkF,CAClF,CAAC;AACH,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { Logger } from '@nestjs/common';
2
+ /**
3
+ * Maximum recursion depth for sanitization operations.
4
+ * Prevents stack overflow attacks and infinite loops on circular references.
5
+ */
6
+ export declare const MAX_SANITIZE_DEPTH = 20;
7
+ /**
8
+ * Escapes newline characters and other special characters that could be used for log injection attacks.
9
+ * Replaces newlines with \n literal strings to prevent log forging where an attacker might inject
10
+ * a newline to create fake log entries.
11
+ *
12
+ * @param str The string to escape
13
+ * @returns String with newlines and carriage returns escaped
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * escapeNewlines('Hello\nWorld') // Returns: 'Hello\\nWorld'
18
+ * escapeNewlines('foo\rbar') // Returns: 'foo\\rbar'
19
+ * ```
20
+ */
21
+ export declare function escapeNewlines(str: string): string;
22
+ /**
23
+ * Recursively sanitizes object keys to prevent MongoDB injection attacks.
24
+ * This function only sanitizes keys (property names), not values, to prevent
25
+ * destruction of legitimate data like email addresses or S3 paths.
26
+ *
27
+ * CRITICAL: This function must be applied to the complete root request object.
28
+ * Extracting a sub-object and passing it separately bypasses sanitization for
29
+ * parent levels. Always sanitize at the entry point (request body, params, query).
30
+ *
31
+ * Behavior at max depth: Throws an error to prevent bypass of sanitization.
32
+ * A highly nested object may indicate an attack or data structure issue.
33
+ *
34
+ * @param value The value to sanitize (keys only)
35
+ * @param depth Current recursion depth (internal use)
36
+ * @param logger Optional logger instance for warnings
37
+ * @returns Sanitized value with dangerous characters in keys replaced
38
+ * @throws Error if maximum sanitization depth is exceeded
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * // CORRECT: Sanitize at entry point
43
+ * app.use((req, res, next) => {
44
+ * req.body = sanitizeObject(req.body);
45
+ * next();
46
+ * });
47
+ *
48
+ * // WRONG: Don't extract sub-object and sanitize separately
49
+ * const user = sanitizeObject(req.body.user); // Misses req.body itself
50
+ *
51
+ * // CORRECT: Sanitize complete object first
52
+ * const sanitized = sanitizeObject(req.body);
53
+ * const user = sanitized.user; // Now safe
54
+ * ```
55
+ */
56
+ export declare function sanitizeObject(value: any, depth?: number, logger?: Logger): any;
57
+ /**
58
+ * Recursively sanitizes object values to prevent XSS attacks.
59
+ * Strips dangerous HTML tags, JavaScript event handlers, and protocol handlers
60
+ * from string values while preserving legitimate data.
61
+ *
62
+ * Uses the xss library for server-side HTML string sanitization.
63
+ *
64
+ * @param value The value to sanitize (strings and nested objects)
65
+ * @param logger Optional logger instance for warnings
66
+ * @returns Sanitized value with XSS vectors removed
67
+ */
68
+ export declare function sanitizeXss(value: unknown, logger?: Logger): unknown;
69
+ //# sourceMappingURL=sanitization.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitization.utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils/sanitization.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAIxC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,GAAE,MAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,CAyClF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAqCpE"}
@@ -0,0 +1,141 @@
1
+ import xss from 'xss';
2
+ import { getErrorMessage } from './error.utils.js';
3
+ /**
4
+ * Maximum recursion depth for sanitization operations.
5
+ * Prevents stack overflow attacks and infinite loops on circular references.
6
+ */
7
+ export const MAX_SANITIZE_DEPTH = 20;
8
+ /**
9
+ * Escapes newline characters and other special characters that could be used for log injection attacks.
10
+ * Replaces newlines with \n literal strings to prevent log forging where an attacker might inject
11
+ * a newline to create fake log entries.
12
+ *
13
+ * @param str The string to escape
14
+ * @returns String with newlines and carriage returns escaped
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * escapeNewlines('Hello\nWorld') // Returns: 'Hello\\nWorld'
19
+ * escapeNewlines('foo\rbar') // Returns: 'foo\\rbar'
20
+ * ```
21
+ */
22
+ export function escapeNewlines(str) {
23
+ if (typeof str !== 'string') {
24
+ return String(str);
25
+ }
26
+ return str
27
+ .replace(/\n/g, '\\n')
28
+ .replace(/\r/g, '\\r')
29
+ .replace(/\t/g, '\\t');
30
+ }
31
+ /**
32
+ * Recursively sanitizes object keys to prevent MongoDB injection attacks.
33
+ * This function only sanitizes keys (property names), not values, to prevent
34
+ * destruction of legitimate data like email addresses or S3 paths.
35
+ *
36
+ * CRITICAL: This function must be applied to the complete root request object.
37
+ * Extracting a sub-object and passing it separately bypasses sanitization for
38
+ * parent levels. Always sanitize at the entry point (request body, params, query).
39
+ *
40
+ * Behavior at max depth: Throws an error to prevent bypass of sanitization.
41
+ * A highly nested object may indicate an attack or data structure issue.
42
+ *
43
+ * @param value The value to sanitize (keys only)
44
+ * @param depth Current recursion depth (internal use)
45
+ * @param logger Optional logger instance for warnings
46
+ * @returns Sanitized value with dangerous characters in keys replaced
47
+ * @throws Error if maximum sanitization depth is exceeded
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * // CORRECT: Sanitize at entry point
52
+ * app.use((req, res, next) => {
53
+ * req.body = sanitizeObject(req.body);
54
+ * next();
55
+ * });
56
+ *
57
+ * // WRONG: Don't extract sub-object and sanitize separately
58
+ * const user = sanitizeObject(req.body.user); // Misses req.body itself
59
+ *
60
+ * // CORRECT: Sanitize complete object first
61
+ * const sanitized = sanitizeObject(req.body);
62
+ * const user = sanitized.user; // Now safe
63
+ * ```
64
+ */
65
+ export function sanitizeObject(value, depth = 0, logger) {
66
+ if (depth >= MAX_SANITIZE_DEPTH) {
67
+ if (logger) {
68
+ logger.error(`Sanitization depth limit exceeded at depth ${MAX_SANITIZE_DEPTH}`);
69
+ }
70
+ throw new Error(`Input object exceeds maximum sanitization depth of ${MAX_SANITIZE_DEPTH}. Deeply nested objects may be malicious.`);
71
+ }
72
+ if (typeof value === 'object' && value !== null) {
73
+ if (Array.isArray(value)) {
74
+ return value.map(item => sanitizeObject(item, depth + 1, logger));
75
+ }
76
+ const sanitized = {};
77
+ for (const [key, val] of Object.entries(value)) {
78
+ // Sanitize keys to prevent MongoDB operator injection
79
+ // MongoDB operators start with '$', and command expressions with 'eval', 'function', etc.
80
+ // Replace dangerous key patterns: $ at start, eval, function in keys
81
+ let sanitizedKey = key;
82
+ // Prevent MongoDB operators (e.g., $where, $regex, etc.)
83
+ if (sanitizedKey.startsWith('$')) {
84
+ sanitizedKey = '_' + sanitizedKey.slice(1);
85
+ }
86
+ // Prevent arbitrary code execution patterns in key names
87
+ const dangerousKeyPatterns = ['eval', 'function', '__proto__', 'constructor', 'prototype'];
88
+ for (const pattern of dangerousKeyPatterns) {
89
+ if (sanitizedKey.toLowerCase().includes(pattern)) {
90
+ sanitizedKey = sanitizedKey.replace(new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'), '_redacted_');
91
+ }
92
+ }
93
+ // Recursively sanitize nested objects/arrays, but preserve string values
94
+ sanitized[sanitizedKey] = typeof val === 'object' ? sanitizeObject(val, depth + 1, logger) : val;
95
+ }
96
+ return sanitized;
97
+ }
98
+ return value;
99
+ }
100
+ /**
101
+ * Recursively sanitizes object values to prevent XSS attacks.
102
+ * Strips dangerous HTML tags, JavaScript event handlers, and protocol handlers
103
+ * from string values while preserving legitimate data.
104
+ *
105
+ * Uses the xss library for server-side HTML string sanitization.
106
+ *
107
+ * @param value The value to sanitize (strings and nested objects)
108
+ * @param logger Optional logger instance for warnings
109
+ * @returns Sanitized value with XSS vectors removed
110
+ */
111
+ export function sanitizeXss(value, logger) {
112
+ if (typeof value === 'string') {
113
+ // Use xss library for server-side HTML string sanitization
114
+ // Removes common XSS patterns: script tags, event handlers, dangerous protocols
115
+ // Static import ensures dependency is resolved at module load time and fails fast if missing
116
+ let sanitized = value;
117
+ try {
118
+ // xss is statically imported at module top to ensure TypeScript and bundlers
119
+ // can properly resolve the dependency at build time
120
+ sanitized = xss(sanitized);
121
+ }
122
+ catch (error) {
123
+ if (logger) {
124
+ logger.warn(`XSS sanitization (xss library) failed: ${getErrorMessage(error)}`);
125
+ }
126
+ }
127
+ // Final protocol stripping as defense-in-depth
128
+ sanitized = sanitized
129
+ .replace(/javascript:/gi, '')
130
+ .replace(/vbscript:/gi, '');
131
+ return sanitized;
132
+ }
133
+ if (Array.isArray(value)) {
134
+ return value.map(v => sanitizeXss(v, logger));
135
+ }
136
+ if (value && typeof value === 'object') {
137
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, sanitizeXss(v, logger)]));
138
+ }
139
+ return value;
140
+ }
141
+ //# sourceMappingURL=sanitization.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitization.utils.js","sourceRoot":"","sources":["../../../src/common/utils/sanitization.utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Configuration Module.
3
+ * Provides configuration services with environment variable access, validation, and logging.
4
+ * MUST be imported before CommonModule in your application.
5
+ *
6
+ * Exports:
7
+ * - ConfigService: Typed configuration accessor
8
+ * - ValidationService: Configuration validation utilities
9
+ *
10
+ * @remarks
11
+ * - ConfigService is required by CommonModule and other @pawells packages
12
+ * - Initializes logging for configuration operations
13
+ * - Import order critical: ConfigModule must come BEFORE CommonModule
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * @Module({
18
+ * imports: [
19
+ * ConfigModule, // FIRST
20
+ * CommonModule, // SECOND (depends on ConfigModule)
21
+ * MetricsModule.forRoot(),
22
+ * // ... other modules
23
+ * ]
24
+ * })
25
+ * export class AppModule {}
26
+ * ```
27
+ */
28
+ export declare class ConfigModule {
29
+ }
30
+ //# sourceMappingURL=config.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.module.d.ts","sourceRoot":"","sources":["../../src/config/config.module.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,qBAOa,YAAY;CAAG"}