@pawells/nestjs-shared 1.0.0-dev.3052c75

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
package/README.md ADDED
@@ -0,0 +1,802 @@
1
+ # NestJS Shared Module
2
+
3
+ [![GitHub Release](https://img.shields.io/github/v/release/PhillipAWells/nestjs-common)](https://github.com/PhillipAWells/nestjs-common/releases)
4
+ [![CI](https://github.com/PhillipAWells/nestjs-common/actions/workflows/ci.yml/badge.svg)](https://github.com/PhillipAWells/nestjs-common/actions/workflows/ci.yml)
5
+ [![npm version](https://img.shields.io/npm/v/@pawells/nestjs-shared.svg?style=flat)](https://www.npmjs.com/package/@pawells/nestjs-shared)
6
+ [![Node](https://img.shields.io/badge/node-%3E%3D24-brightgreen)](https://nodejs.org)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
8
+ [![GitHub Sponsors](https://img.shields.io/github/sponsors/PhillipAWells?style=social)](https://github.com/sponsors/PhillipAWells)
9
+
10
+ Foundational NestJS infrastructure library providing filters, guards, interceptors, logging, CSRF protection, error handling, configuration, metrics, and lazy loading utilities.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ yarn add @pawells/nestjs-shared
16
+ ```
17
+
18
+ ## Requirements
19
+
20
+ - **Node.js**: >= 24.0.0
21
+ - **NestJS**: >= 10.0.0
22
+
23
+ ## Peer Dependencies
24
+
25
+ ```json
26
+ {
27
+ "@nestjs/common": ">=10.0.0",
28
+ "@nestjs/config": ">=3.0.0",
29
+ "@nestjs/core": ">=10.0.0",
30
+ "@nestjs/throttler": ">=5.0.0",
31
+ "@opentelemetry/api": ">=1.0.0",
32
+ "class-transformer": ">=0.5.0",
33
+ "class-validator": ">=0.14.0",
34
+ "compression": ">=1.0.0",
35
+ "csrf-csrf": ">=3.0.0",
36
+ "express": ">=4.0.0",
37
+ "helmet": ">=7.0.0",
38
+ "joi": ">=17.0.0",
39
+ "prom-client": ">=15.0.0",
40
+ "rxjs": ">=7.0.0",
41
+ "xss": ">=1.0.0"
42
+ }
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ### 1. Initialize ConfigModule (MUST come first)
48
+
49
+ ```typescript
50
+ import { Module } from '@nestjs/common';
51
+ import { ConfigModule } from '@pawells/nestjs-shared';
52
+
53
+ @Module({
54
+ imports: [
55
+ ConfigModule, // Must be first
56
+ ],
57
+ })
58
+ export class AppModule {}
59
+ ```
60
+
61
+ ### 2. Import CommonModule
62
+
63
+ ```typescript
64
+ import { Module } from '@nestjs/common';
65
+ import { CommonModule } from '@pawells/nestjs-shared';
66
+
67
+ @Module({
68
+ imports: [
69
+ ConfigModule, // Must be first
70
+ CommonModule, // Depends on ConfigModule
71
+ ],
72
+ })
73
+ export class AppModule {}
74
+ ```
75
+
76
+ ### 3. Use Global Filters and Interceptors
77
+
78
+ Global filters and interceptors are automatically registered by CommonModule:
79
+ - **GlobalExceptionFilter** & **HttpExceptionFilter**: Standardized error responses
80
+ - **LoggingInterceptor**: Request/response logging
81
+ - **HTTPMetricsInterceptor**: HTTP metrics collection
82
+ - **ValidationPipe**: Automatic DTO validation
83
+
84
+ All are applied globally and available for injection in services.
85
+
86
+ ## Features
87
+
88
+ ### Error Handling
89
+
90
+ Comprehensive error handling with structured responses, categorization, and sanitization.
91
+
92
+ ```typescript
93
+ import {
94
+ BaseApplicationError,
95
+ GlobalExceptionFilter,
96
+ ErrorCategorizerService,
97
+ ErrorSanitizerService,
98
+ } from '@pawells/nestjs-shared';
99
+
100
+ // Create custom error
101
+ export class UserNotFoundError extends BaseApplicationError {
102
+ constructor(userId: string) {
103
+ super(`User ${userId} not found`, {
104
+ code: 'USER_NOT_FOUND',
105
+ statusCode: 404,
106
+ context: { userId }
107
+ });
108
+ }
109
+ }
110
+
111
+ // Throw it
112
+ throw new UserNotFoundError('123');
113
+
114
+ // Automatically caught by GlobalExceptionFilter
115
+ // Response includes code, message, timestamp, sanitized context, stack (dev only)
116
+ ```
117
+
118
+ **Error Categories**: Errors are automatically categorized as transient (retryable) or permanent (fail-fast) with recommended recovery strategies.
119
+
120
+ ### Logging
121
+
122
+ Centralized, structured logging with automatic redaction of sensitive data.
123
+
124
+ ```typescript
125
+ import { AppLogger } from '@pawells/nestjs-shared';
126
+
127
+ constructor(private logger: AppLogger) {}
128
+
129
+ // Flexible logging methods
130
+ this.logger.info('User created', 'UserService', { userId: '123' });
131
+ this.logger.debug('Cache hit', { metadata: { key: 'users:123' } });
132
+ this.logger.error('Database error', error.stack, { query: '...' });
133
+ this.logger.warn('Rate limit approaching', { context: 'RateLimiter' });
134
+ this.logger.fatal('System shutdown', { context: 'ShutdownService' });
135
+
136
+ // Automatic redaction of sensitive fields: passwords, tokens, API keys, emails, IPs
137
+ this.logger.info('Login attempt', { password: 'secret' });
138
+ // Logs: { password: '[REDACTED]' }
139
+
140
+ // OpenTelemetry integration: traceId and spanId automatically included
141
+ ```
142
+
143
+ **Log Levels**: Controlled by LOG_LEVEL environment variable (debug, info, warn, error, fatal, silent).
144
+
145
+ ### Metrics
146
+
147
+ Prometheus metrics for HTTP requests and custom metrics.
148
+
149
+ ```typescript
150
+ import { MetricsRegistryService } from '@pawells/nestjs-shared';
151
+
152
+ constructor(private metrics: MetricsRegistryService) {}
153
+
154
+ // Record custom metrics
155
+ const orderCounter = this.metrics.createCounter(
156
+ 'orders_total',
157
+ 'Total orders processed'
158
+ );
159
+ orderCounter.inc({ status: 'completed' });
160
+
161
+ // HTTP metrics are automatic (duration, count, size)
162
+ // Access at GET /metrics in Prometheus format
163
+ const prometheusMetrics = await this.metrics.getMetrics();
164
+ ```
165
+
166
+ **Features**:
167
+ - Automatic HTTP request metrics (duration histogram, request counter, size histogram)
168
+ - Dynamic path normalization (UUIDs, ObjectIDs, numeric IDs → `:id`) to prevent unbounded cardinality
169
+ - Default Node.js metrics collection
170
+ - Custom metric creation (counter, gauge, histogram)
171
+ - Controlled by METRICS_ENABLED environment variable (default: true)
172
+
173
+ ### CSRF Protection
174
+
175
+ Double-Submit Cookie pattern with per-IP rate limiting.
176
+
177
+ ```typescript
178
+ import { CSRFGuard, CSRFService } from '@pawells/nestjs-shared';
179
+
180
+ // Globally applied by CommonModule
181
+ // Or manually on specific controller
182
+ @UseGuards(CSRFGuard)
183
+ @Controller('api')
184
+ export class ApiController {
185
+ constructor(private csrf: CSRFService) {}
186
+
187
+ @Post('/form')
188
+ async submitForm(@Req() req: Request, @Res() res: Response) {
189
+ // Generate token
190
+ const token = await this.csrf.generateToken(req, res);
191
+ res.render('form', { csrfToken: token });
192
+ }
193
+
194
+ @Post('/process')
195
+ async processForm(@Req() req: Request) {
196
+ // Validation done automatically by CSRFGuard
197
+ // Safe methods (GET, HEAD, OPTIONS) bypass validation
198
+ }
199
+ }
200
+ ```
201
+
202
+ **Features**:
203
+ - Token generation with rate limiting (10 per IP per 60s)
204
+ - Session binding or IP-based fallback
205
+ - Automatic pruning of stale timestamps
206
+ - Capacity monitoring with safety margins
207
+ - Configurable proxy trust for X-Forwarded-For header
208
+ - CSRF_SECRET entropy validation at startup
209
+
210
+ ### Validation
211
+
212
+ Automatic DTO validation and transformation.
213
+
214
+ ```typescript
215
+ import { IsEmail, IsNotEmpty, MinLength } from 'class-validator';
216
+
217
+ export class CreateUserDto {
218
+ @IsNotEmpty()
219
+ @IsEmail()
220
+ email: string;
221
+
222
+ @IsNotEmpty()
223
+ @MinLength(8)
224
+ password: string;
225
+ }
226
+
227
+ @Post()
228
+ async createUser(@Body() dto: CreateUserDto) {
229
+ // DTO automatically validated and transformed
230
+ // Validation errors formatted as error array with field paths
231
+ }
232
+ ```
233
+
234
+ **Features**:
235
+ - Automatic DTO validation via ValidationPipe
236
+ - Nested object support with path prefixes
237
+ - Comprehensive error formatting
238
+ - Class transformation with class-transformer
239
+
240
+ ### Health Checks
241
+
242
+ Kubernetes-ready health, readiness, and liveness probes.
243
+
244
+ ```typescript
245
+ import { HealthCheckService, HealthStatus } from '@pawells/nestjs-shared';
246
+
247
+ constructor(private health: HealthCheckService) {}
248
+
249
+ @Get('/health')
250
+ getHealth() {
251
+ return this.health.getHealth('my-service', '1.0.0');
252
+ }
253
+
254
+ @Get('/ready')
255
+ getReadiness() {
256
+ return this.health.getReadiness({
257
+ database: HealthStatus.OK,
258
+ cache: HealthStatus.OK,
259
+ });
260
+ }
261
+
262
+ @Get('/live')
263
+ getLiveness() {
264
+ return this.health.getLiveness();
265
+ }
266
+ ```
267
+
268
+ ### Configuration
269
+
270
+ Type-safe environment variable access with validation.
271
+
272
+ ```typescript
273
+ import { ConfigService } from '@pawells/nestjs-shared';
274
+
275
+ constructor(private config: ConfigService) {}
276
+
277
+ // Type-safe getters
278
+ const port = this.config.getNumber('PORT') ?? 3000;
279
+ const nodeEnv = this.config.getString('NODE_ENV') ?? 'development';
280
+ const dbUrl = this.config.getOrThrow('DATABASE_URL');
281
+
282
+ // Validation
283
+ this.config.validate({
284
+ PORT: { required: true },
285
+ DATABASE_URL: { required: true },
286
+ LOG_LEVEL: { required: false },
287
+ });
288
+ ```
289
+
290
+ ### Audit Logging
291
+
292
+ Security event logging for compliance and forensics.
293
+
294
+ ```typescript
295
+ import { AuditLoggerService } from '@pawells/nestjs-shared';
296
+
297
+ constructor(private audit: AuditLoggerService) {}
298
+
299
+ // Log authentication
300
+ this.audit.logAuthenticationAttempt('user@example.com', true, '192.168.1.1');
301
+
302
+ // Log authorization failure
303
+ this.audit.logAuthorizationFailure('user-123', 'documents', 'delete', '192.168.1.1');
304
+
305
+ // Log CSRF violations
306
+ this.audit.logCsrfViolation('192.168.1.1', '/api/users');
307
+
308
+ // Log custom security events
309
+ this.audit.logSecurityEvent({
310
+ userId: 'user-123',
311
+ action: 'password_change',
312
+ resource: 'users/123',
313
+ result: 'success',
314
+ ipAddress: '192.168.1.1'
315
+ });
316
+ ```
317
+
318
+ ### Lazy Loading
319
+
320
+ Defer dependency resolution to avoid circular dependencies.
321
+
322
+ ```typescript
323
+ import {
324
+ LazyGetter,
325
+ LazyModuleRefService,
326
+ createMemoizedLazyGetter,
327
+ } from '@pawells/nestjs-shared';
328
+
329
+ @Injectable()
330
+ export class MyService implements LazyModuleRefService {
331
+ private readonly userService: LazyGetter<UserService> = createMemoizedLazyGetter(
332
+ () => this.moduleRef.get(UserService, { strict: false }),
333
+ );
334
+
335
+ constructor(public readonly Module: ModuleRef) {}
336
+
337
+ async getUser(id: string) {
338
+ // UserService resolved lazily on first call
339
+ return this.userService().getById(id);
340
+ }
341
+ }
342
+ ```
343
+
344
+ **Features**:
345
+ - LazyGetter<T>: Required dependency getter
346
+ - OptionalLazyGetter<T>: Optional dependency getter
347
+ - CreateMemoizedLazyGetter: Caching factory
348
+ - CreateOptionalLazyGetter: Safe optional resolution
349
+ - IsLazyModuleRefService: Type guard for pattern detection
350
+
351
+ ### HTTP Client
352
+
353
+ Robust HTTP client with timeout, SSL/TLS, and sensitive data redaction.
354
+
355
+ ```typescript
356
+ import { HttpClientService } from '@pawells/nestjs-shared';
357
+
358
+ constructor(private http: HttpClientService) {}
359
+
360
+ // GET request
361
+ const response = await this.http.get<User>('https://api.example.com/users/123');
362
+
363
+ // POST request with custom timeout
364
+ const response = await this.http.post<User>(
365
+ 'https://api.example.com/users',
366
+ { name: 'John', email: 'john@example.com' },
367
+ { timeout: 5000, correlationId: 'req-123' }
368
+ );
369
+
370
+ // HTTPS with custom CA certificate
371
+ const cert = fs.readFileSync('/path/to/ca.pem');
372
+ const response = await this.http.get(
373
+ 'https://internal-api.local/data',
374
+ { ca: cert }
375
+ );
376
+ ```
377
+
378
+ **Features**:
379
+ - Configurable timeouts (default: HTTP_CLIENT_TIMEOUT)
380
+ - SSL/TLS certificate validation (strict by default)
381
+ - Custom CA certificate support
382
+ - Payload size limit (10MB)
383
+ - Automatic content-type parsing
384
+ - Correlation ID support
385
+ - Sensitive data redaction in logs
386
+ - Duration tracking
387
+
388
+ ### Decorators
389
+
390
+ Request property extractors for cleaner controller methods.
391
+
392
+ ```typescript
393
+ import { Query, Params, Body, Headers, Cookies } from '@pawells/nestjs-shared';
394
+
395
+ @Controller('users')
396
+ export class UserController {
397
+ @Get(':id')
398
+ getUser(
399
+ @Params('id') id: string,
400
+ @Query('include') include?: string,
401
+ ) {
402
+ // Route params and query params extracted
403
+ }
404
+
405
+ @Post()
406
+ createUser(
407
+ @Body() dto: CreateUserDto,
408
+ @Headers('authorization') auth?: string,
409
+ ) {
410
+ // Body and headers extracted
411
+ }
412
+
413
+ @Get()
414
+ listUsers(@Cookies('sessionId') sessionId?: string) {
415
+ // Cookies extracted
416
+ }
417
+ }
418
+ ```
419
+
420
+ ## Core Modules
421
+
422
+ ### CommonModule
423
+
424
+ Global module providing all shared infrastructure.
425
+
426
+ ```typescript
427
+ // Automatically applied globally
428
+ @Global()
429
+ @Module({
430
+ providers: [
431
+ // Filters (global)
432
+ GlobalExceptionFilter,
433
+ HttpExceptionFilter,
434
+
435
+ // Interceptors (global)
436
+ LoggingInterceptor,
437
+ HTTPMetricsInterceptor,
438
+
439
+ // Pipe (global)
440
+ ValidationPipe,
441
+
442
+ // Services (injectable)
443
+ AppLogger,
444
+ AuditLoggerService,
445
+ CSRFService,
446
+ ErrorCategorizerService,
447
+ ErrorSanitizerService,
448
+ HttpClientService,
449
+ MetricsRegistryService,
450
+ HealthCheckService,
451
+ ],
452
+ exports: [...],
453
+ })
454
+ export class CommonModule {}
455
+ ```
456
+
457
+ ### ConfigModule
458
+
459
+ Configuration service with validation.
460
+
461
+ ```typescript
462
+ @Module({
463
+ imports: [ConfigModule],
464
+ // ConfigService and ValidationService automatically available
465
+ })
466
+ export class AppModule {}
467
+ ```
468
+
469
+ ### MetricsModule
470
+
471
+ Prometheus metrics endpoint and collection.
472
+
473
+ ```typescript
474
+ // Automatically imported by CommonModule
475
+ // Provides:
476
+ // - MetricsRegistryService (injectable)
477
+ // - GET /metrics endpoint (Prometheus format)
478
+ ```
479
+
480
+ ## API Reference
481
+
482
+ ### Services
483
+
484
+ #### AppLogger
485
+ Structured logging service with context support, metadata, and automatic sensitive data redaction.
486
+
487
+ **Methods**:
488
+ - `debug(message, context?, metadata?)`: Debug level
489
+ - `info(message, context?, metadata?)`: Info level
490
+ - `warn(message, context?, metadata?)`: Warning level
491
+ - `error(message, trace?, context?, metadata?)`: Error level with optional stack trace
492
+ - `fatal(message, trace?, context?, metadata?)`: Fatal level with optional stack trace
493
+ - `createContextualLogger(context)`: Create child logger with context
494
+
495
+ #### ErrorCategorizerService
496
+ Classifies errors as transient/permanent and recommends recovery strategy.
497
+
498
+ **Methods**:
499
+ - `categorizeError(error)`: Returns ErrorCategory with type, retryable, strategy, backoffMs
500
+ - `isRetryable(error)`: Boolean check
501
+ - `logRecoveryAttempt(error, attempt, maxAttempts)`: Log retry attempt
502
+ - `logRecoverySuccess(error, attempts)`: Log successful recovery
503
+ - `logRecoveryFailed(error, attempts)`: Log failed recovery
504
+
505
+ #### ErrorSanitizerService
506
+ Removes sensitive information from error responses and logs.
507
+
508
+ **Methods**:
509
+ - `sanitizeErrorResponse(error, isDevelopment)`: Sanitize error for response
510
+ - `sanitizeMessage(message)`: Sanitize error message string
511
+
512
+ Redactions: File paths, database URIs, API keys, Bearer tokens, email addresses, IP addresses, sensitive field values.
513
+
514
+ #### CSRFService
515
+ CSRF token generation and validation with rate limiting.
516
+
517
+ **Methods**:
518
+ - `generateToken(req, res)`: Generate and set CSRF token (rate limited)
519
+ - `validateToken(req)`: Validate CSRF token
520
+ - `refreshToken(req, res)`: Generate new token after sensitive operation
521
+ - `getMiddleware()`: Get CSRF protection middleware
522
+
523
+ #### MetricsRegistryService
524
+ Prometheus metrics management.
525
+
526
+ **Methods**:
527
+ - `recordHttpRequest(method, route, statusCode, duration, size?)`: Record HTTP metrics
528
+ - `createCounter(name, help, labelNames?)`: Create counter metric
529
+ - `createGauge(name, help, labelNames?)`: Create gauge metric
530
+ - `createHistogram(name, help, labelNames?, buckets?)`: Create histogram metric
531
+ - `recordCounter(name, value?, labels?)`: Record counter value
532
+ - `recordGauge(name, value, labels?)`: Record gauge value
533
+ - `recordHistogram(name, value, labels?)`: Record histogram value
534
+ - `getMetrics()`: Get metrics in Prometheus format
535
+ - `getMetricsAsJSON()`: Get metrics as JSON
536
+ - `clear()`: Clear all metrics (testing)
537
+
538
+ #### HealthCheckService
539
+ Kubernetes health probes.
540
+
541
+ **Methods**:
542
+ - `getHealth(serviceName?, version?)`: General health check
543
+ - `getReadiness(checks?)`: Readiness probe (can receive traffic)
544
+ - `getLiveness()`: Liveness probe (is alive)
545
+
546
+ #### HttpClientService
547
+ HTTP client with timeout and SSL/TLS support.
548
+
549
+ **Methods**:
550
+ - `request<T>(options)`: Make HTTP request
551
+ - `get<T>(url, options?)`: GET request
552
+ - `post<T>(url, data?, options?)`: POST request
553
+ - `put<T>(url, data?, options?)`: PUT request
554
+ - `delete<T>(url, options?)`: DELETE request
555
+
556
+ #### ConfigService
557
+ Type-safe environment variable access.
558
+
559
+ **Methods**:
560
+ - `get<T>(propertyPath, defaultValue?)`: Get config value
561
+ - `getOrThrow<T>(propertyPath)`: Get or throw
562
+ - `getString(propertyPath, defaultValue?)`: Get as string
563
+ - `getNumber(propertyPath, defaultValue?)`: Get as number
564
+ - `validate(schema)`: Validate configuration
565
+
566
+ #### AuditLoggerService
567
+ Security event logging.
568
+
569
+ **Methods**:
570
+ - `logAuthenticationAttempt(email, success, ipAddress?, reason?)`
571
+ - `logAuthorizationFailure(userId, resource, action, ipAddress?)`
572
+ - `logTokenGeneration(userId, tokenType)`
573
+ - `logTokenRevocation(userId, reason)`
574
+ - `logRateLimitViolation(endpoint, ipAddress, limit)`
575
+ - `logCsrfViolation(ipAddress, endpoint)`
576
+ - `logConfigurationChange(userId, config, oldValue, newValue)`
577
+ - `logDataAccess(userId, resource, action)`
578
+ - `logSecurityEvent(entry)`
579
+
580
+ ### Filters
581
+
582
+ #### GlobalExceptionFilter
583
+ Catches unhandled exceptions (except HttpException).
584
+
585
+ - Standardizes response format
586
+ - Sanitizes sensitive data
587
+ - Categorizes errors
588
+ - Logs with context
589
+
590
+ #### HttpExceptionFilter
591
+ Handles HTTP exceptions.
592
+
593
+ - Formats NestJS built-in exceptions
594
+ - Sanitizes responses
595
+ - Categorizes for logging
596
+
597
+ ### Interceptors
598
+
599
+ #### LoggingInterceptor
600
+ Logs incoming requests and outgoing responses.
601
+
602
+ - Uses DEBUG level for /health and /metrics
603
+ - Uses INFO level for other requests
604
+ - Includes method, URL, IP, duration
605
+
606
+ #### HTTPMetricsInterceptor
607
+ Collects HTTP request metrics.
608
+
609
+ - Duration histogram
610
+ - Request counter
611
+ - Request size histogram
612
+ - Automatic route normalization
613
+
614
+ ### Guards
615
+
616
+ #### CSRFGuard
617
+ Validates CSRF tokens on state-changing requests.
618
+
619
+ - Bypasses safe methods (GET, HEAD, OPTIONS)
620
+ - Enforces validation for POST/PUT/DELETE/PATCH
621
+ - Throws 403 on validation failure
622
+ - Logs violations to audit log
623
+
624
+ ### Pipes
625
+
626
+ #### ValidationPipe
627
+ Validates DTOs using class-validator.
628
+
629
+ - Automatic transformation via class-transformer
630
+ - Nested object support with path prefixes
631
+ - Comprehensive error formatting
632
+
633
+ ## Interfaces & Types
634
+
635
+ ### ILogger
636
+ Basic logging interface without contextual logger creation.
637
+
638
+ ### IContextualLogger
639
+ Extended logging with contextual logger creation.
640
+
641
+ ### LazyModuleRefService
642
+ Interface for services using lazy ModuleRef pattern.
643
+
644
+ ```typescript
645
+ interface LazyModuleRefService {
646
+ Module: ModuleRef;
647
+ }
648
+ ```
649
+
650
+ ### LazyGetter<T>
651
+ Function that returns a dependency.
652
+
653
+ ```typescript
654
+ type LazyGetter<T> = () => T;
655
+ ```
656
+
657
+ ### OptionalLazyGetter<T>
658
+ Function that returns a dependency or undefined.
659
+
660
+ ```typescript
661
+ type OptionalLazyGetter<T> = () => T | undefined;
662
+ ```
663
+
664
+ ### ErrorCategory
665
+ Error classification for recovery strategy.
666
+
667
+ ```typescript
668
+ interface ErrorCategory {
669
+ type: 'transient' | 'permanent';
670
+ retryable: boolean;
671
+ strategy: 'retry' | 'fail' | 'backoff';
672
+ backoffMs?: number;
673
+ }
674
+ ```
675
+
676
+ ### IHealthCheck
677
+ Health check response structure.
678
+
679
+ ```typescript
680
+ interface IHealthCheck {
681
+ status: string;
682
+ timestamp: string;
683
+ service?: string;
684
+ version?: string;
685
+ checks?: Record<string, string>;
686
+ }
687
+ ```
688
+
689
+ ## Conditional Exports
690
+
691
+ ```typescript
692
+ // Main exports (all major classes and utilities)
693
+ import { AppLogger, CSRFService } from '@pawells/nestjs-shared';
694
+
695
+ // Common-only exports (lower-level utilities)
696
+ import { CSRFService } from '@pawells/nestjs-shared/common';
697
+
698
+ // Lazy loader types
699
+ import { LazyGetter } from '@pawells/nestjs-shared/common/utils/lazy-getter.types';
700
+ ```
701
+
702
+ ## Configuration
703
+
704
+ ### Environment Variables
705
+
706
+ - **NODE_ENV**: development, production, etc. (affects error details, logging)
707
+ - **LOG_LEVEL**: debug, info, warn, error, fatal, silent (default: info)
708
+ - **PORT**: Server port (default: 3000)
709
+ - **CSRF_SECRET**: Required for CSRF protection (min 32 chars, high entropy)
710
+ - **METRICS_ENABLED**: Enable metrics (default: true)
711
+ - **SERVICE_NAME**: Service name for logging (default: unknown-service)
712
+
713
+ ### CSRF_SECRET Generation
714
+
715
+ ```bash
716
+ # Generate secure CSRF_SECRET
717
+ openssl rand -hex 32
718
+ ```
719
+
720
+ ## Security Defaults
721
+
722
+ - **Token Blacklist** (when implemented): Fails closed — treats unavailable cache as blacklist
723
+ - **CSRF Token Generation**: Per-IP rate limited (10 per 60s)
724
+ - **CSRF Validation**: Signed tokens with session/IP binding
725
+ - **Error Sanitization**: Stack traces only in development; sensitive fields redacted
726
+ - **CORS**: Implemented via security bootstrap (if configured)
727
+ - **HTTP Client**: Strict SSL/TLS certificate validation (rejectUnauthorized: true)
728
+ - **Metrics**: Dynamic path normalization prevents unbounded cardinality
729
+ - **Logging**: Automatic redaction of passwords, tokens, API keys, emails, IPs
730
+
731
+ ## Examples
732
+
733
+ ### Complete Application Setup
734
+
735
+ ```typescript
736
+ import { NestFactory } from '@nestjs/core';
737
+ import { ConfigModule, CommonModule, MetricsModule } from '@pawells/nestjs-shared';
738
+
739
+ @Module({
740
+ imports: [
741
+ ConfigModule, // MUST be first
742
+ CommonModule, // Depends on ConfigModule
743
+ MetricsModule.forRoot(), // Optional: Prometheus metrics
744
+ // ... feature modules
745
+ ],
746
+ })
747
+ export class AppModule {}
748
+
749
+ async function bootstrap() {
750
+ const app = await NestFactory.create(AppModule);
751
+
752
+ // All filters, interceptors, pipes already registered globally
753
+
754
+ const port = process.env['PORT'] ?? 3000;
755
+ await app.listen(port);
756
+ }
757
+
758
+ bootstrap();
759
+ ```
760
+
761
+ ### Custom Error Handling
762
+
763
+ ```typescript
764
+ import { BaseApplicationError, ErrorCategorizerService } from '@pawells/nestjs-shared';
765
+
766
+ export class InsufficientFundsError extends BaseApplicationError {
767
+ constructor(required: number, available: number) {
768
+ super(`Insufficient funds: need ${required}, have ${available}`, {
769
+ code: 'INSUFFICIENT_FUNDS',
770
+ statusCode: 402,
771
+ context: { required, available }
772
+ });
773
+ }
774
+ }
775
+
776
+ // In service
777
+ @Catch(InsufficientFundsError)
778
+ export class PaymentService {
779
+ constructor(private errorCategorizer: ErrorCategorizerService) {}
780
+
781
+ async processPayment(amount: number) {
782
+ if (amount > balance) {
783
+ const error = new InsufficientFundsError(amount, balance);
784
+ // Automatically caught by GlobalExceptionFilter
785
+ // Categorized by ErrorCategorizerService (permanent/fail)
786
+ // Sanitized by ErrorSanitizerService
787
+ throw error;
788
+ }
789
+ }
790
+ }
791
+ ```
792
+
793
+ ## Related Packages
794
+
795
+ - **[@pawells/nestjs-auth](https://www.npmjs.com/package/@pawells/nestjs-auth)** - JWT, sessions, OAuth/OIDC, Keycloak
796
+ - **[@pawells/nestjs-graphql](https://www.npmjs.com/package/@pawells/nestjs-graphql)** - GraphQL with caching and subscriptions
797
+ - **[@pawells/nestjs-open-telemetry](https://www.npmjs.com/package/@pawells/nestjs-open-telemetry)** - OpenTelemetry tracing
798
+ - **[@pawells/nestjs-prometheus](https://www.npmjs.com/package/@pawells/nestjs-prometheus)** - Prometheus metrics exporter
799
+
800
+ ## License
801
+
802
+ MIT