@makebelieve21213-packages/nest-common 1.0.0

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 (391) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +1905 -0
  3. package/dist/__tests__/index.spec.d.ts +2 -0
  4. package/dist/__tests__/index.spec.d.ts.map +1 -0
  5. package/dist/__tests__/index.spec.js +36 -0
  6. package/dist/__tests__/index.spec.js.map +1 -0
  7. package/dist/__tests__/mocks/logger-service.mock.d.ts +7 -0
  8. package/dist/__tests__/mocks/logger-service.mock.d.ts.map +1 -0
  9. package/dist/__tests__/mocks/logger-service.mock.js +16 -0
  10. package/dist/__tests__/mocks/logger-service.mock.js.map +1 -0
  11. package/dist/__tests__/setup.d.ts +2 -0
  12. package/dist/__tests__/setup.d.ts.map +1 -0
  13. package/dist/__tests__/setup.js +3 -0
  14. package/dist/__tests__/setup.js.map +1 -0
  15. package/dist/base/__tests__/base.controller.spec.d.ts +2 -0
  16. package/dist/base/__tests__/base.controller.spec.d.ts.map +1 -0
  17. package/dist/base/__tests__/base.controller.spec.js +50 -0
  18. package/dist/base/__tests__/base.controller.spec.js.map +1 -0
  19. package/dist/base/base.controller.d.ts +8 -0
  20. package/dist/base/base.controller.d.ts.map +1 -0
  21. package/dist/base/base.controller.js +15 -0
  22. package/dist/base/base.controller.js.map +1 -0
  23. package/dist/decorators/__tests__/api-key.decorator.spec.d.ts +2 -0
  24. package/dist/decorators/__tests__/api-key.decorator.spec.d.ts.map +1 -0
  25. package/dist/decorators/__tests__/api-key.decorator.spec.js +25 -0
  26. package/dist/decorators/__tests__/api-key.decorator.spec.js.map +1 -0
  27. package/dist/decorators/__tests__/permissions.decorator.spec.d.ts +2 -0
  28. package/dist/decorators/__tests__/permissions.decorator.spec.d.ts.map +1 -0
  29. package/dist/decorators/__tests__/permissions.decorator.spec.js +29 -0
  30. package/dist/decorators/__tests__/permissions.decorator.spec.js.map +1 -0
  31. package/dist/decorators/__tests__/public.decorator.spec.d.ts +2 -0
  32. package/dist/decorators/__tests__/public.decorator.spec.d.ts.map +1 -0
  33. package/dist/decorators/__tests__/public.decorator.spec.js +25 -0
  34. package/dist/decorators/__tests__/public.decorator.spec.js.map +1 -0
  35. package/dist/decorators/__tests__/roles.decorator.spec.d.ts +2 -0
  36. package/dist/decorators/__tests__/roles.decorator.spec.d.ts.map +1 -0
  37. package/dist/decorators/__tests__/roles.decorator.spec.js +29 -0
  38. package/dist/decorators/__tests__/roles.decorator.spec.js.map +1 -0
  39. package/dist/decorators/__tests__/serialize.decorator.spec.d.ts +2 -0
  40. package/dist/decorators/__tests__/serialize.decorator.spec.d.ts.map +1 -0
  41. package/dist/decorators/__tests__/serialize.decorator.spec.js +28 -0
  42. package/dist/decorators/__tests__/serialize.decorator.spec.js.map +1 -0
  43. package/dist/decorators/api-key.decorator.d.ts +3 -0
  44. package/dist/decorators/api-key.decorator.d.ts.map +1 -0
  45. package/dist/decorators/api-key.decorator.js +6 -0
  46. package/dist/decorators/api-key.decorator.js.map +1 -0
  47. package/dist/decorators/permissions.decorator.d.ts +3 -0
  48. package/dist/decorators/permissions.decorator.d.ts.map +1 -0
  49. package/dist/decorators/permissions.decorator.js +6 -0
  50. package/dist/decorators/permissions.decorator.js.map +1 -0
  51. package/dist/decorators/public.decorator.d.ts +3 -0
  52. package/dist/decorators/public.decorator.d.ts.map +1 -0
  53. package/dist/decorators/public.decorator.js +6 -0
  54. package/dist/decorators/public.decorator.js.map +1 -0
  55. package/dist/decorators/roles.decorator.d.ts +3 -0
  56. package/dist/decorators/roles.decorator.d.ts.map +1 -0
  57. package/dist/decorators/roles.decorator.js +6 -0
  58. package/dist/decorators/roles.decorator.js.map +1 -0
  59. package/dist/decorators/serialize.decorator.d.ts +3 -0
  60. package/dist/decorators/serialize.decorator.d.ts.map +1 -0
  61. package/dist/decorators/serialize.decorator.js +6 -0
  62. package/dist/decorators/serialize.decorator.js.map +1 -0
  63. package/dist/errors/__tests__/http.error.spec.d.ts +2 -0
  64. package/dist/errors/__tests__/http.error.spec.d.ts.map +1 -0
  65. package/dist/errors/__tests__/http.error.spec.js +667 -0
  66. package/dist/errors/__tests__/http.error.spec.js.map +1 -0
  67. package/dist/errors/__tests__/rpc.error.spec.d.ts +2 -0
  68. package/dist/errors/__tests__/rpc.error.spec.d.ts.map +1 -0
  69. package/dist/errors/__tests__/rpc.error.spec.js +336 -0
  70. package/dist/errors/__tests__/rpc.error.spec.js.map +1 -0
  71. package/dist/errors/__tests__/socket.error.spec.d.ts +2 -0
  72. package/dist/errors/__tests__/socket.error.spec.d.ts.map +1 -0
  73. package/dist/errors/__tests__/socket.error.spec.js +105 -0
  74. package/dist/errors/__tests__/socket.error.spec.js.map +1 -0
  75. package/dist/errors/http.error.d.ts +17 -0
  76. package/dist/errors/http.error.d.ts.map +1 -0
  77. package/dist/errors/http.error.js +170 -0
  78. package/dist/errors/http.error.js.map +1 -0
  79. package/dist/errors/nest-common.error.d.ts +7 -0
  80. package/dist/errors/nest-common.error.d.ts.map +1 -0
  81. package/dist/errors/nest-common.error.js +18 -0
  82. package/dist/errors/nest-common.error.js.map +1 -0
  83. package/dist/errors/rpc.error.d.ts +27 -0
  84. package/dist/errors/rpc.error.d.ts.map +1 -0
  85. package/dist/errors/rpc.error.js +170 -0
  86. package/dist/errors/rpc.error.js.map +1 -0
  87. package/dist/errors/socket.error.d.ts +20 -0
  88. package/dist/errors/socket.error.d.ts.map +1 -0
  89. package/dist/errors/socket.error.js +47 -0
  90. package/dist/errors/socket.error.js.map +1 -0
  91. package/dist/filters/__tests__/http-exception-handler.spec.d.ts +2 -0
  92. package/dist/filters/__tests__/http-exception-handler.spec.d.ts.map +1 -0
  93. package/dist/filters/__tests__/http-exception-handler.spec.js +86 -0
  94. package/dist/filters/__tests__/http-exception-handler.spec.js.map +1 -0
  95. package/dist/filters/__tests__/rpc-exception-handler.spec.d.ts +2 -0
  96. package/dist/filters/__tests__/rpc-exception-handler.spec.d.ts.map +1 -0
  97. package/dist/filters/__tests__/rpc-exception-handler.spec.js +220 -0
  98. package/dist/filters/__tests__/rpc-exception-handler.spec.js.map +1 -0
  99. package/dist/filters/__tests__/unified-exception.filter.spec.d.ts +2 -0
  100. package/dist/filters/__tests__/unified-exception.filter.spec.d.ts.map +1 -0
  101. package/dist/filters/__tests__/unified-exception.filter.spec.js +233 -0
  102. package/dist/filters/__tests__/unified-exception.filter.spec.js.map +1 -0
  103. package/dist/filters/__tests__/websocket-exception-handler.spec.d.ts +2 -0
  104. package/dist/filters/__tests__/websocket-exception-handler.spec.d.ts.map +1 -0
  105. package/dist/filters/__tests__/websocket-exception-handler.spec.js +78 -0
  106. package/dist/filters/__tests__/websocket-exception-handler.spec.js.map +1 -0
  107. package/dist/filters/http-exception-handler.d.ts +8 -0
  108. package/dist/filters/http-exception-handler.d.ts.map +1 -0
  109. package/dist/filters/http-exception-handler.js +37 -0
  110. package/dist/filters/http-exception-handler.js.map +1 -0
  111. package/dist/filters/rpc-exception-handler.d.ts +11 -0
  112. package/dist/filters/rpc-exception-handler.d.ts.map +1 -0
  113. package/dist/filters/rpc-exception-handler.js +87 -0
  114. package/dist/filters/rpc-exception-handler.js.map +1 -0
  115. package/dist/filters/unified-exception.filter.d.ts +12 -0
  116. package/dist/filters/unified-exception.filter.d.ts.map +1 -0
  117. package/dist/filters/unified-exception.filter.js +63 -0
  118. package/dist/filters/unified-exception.filter.js.map +1 -0
  119. package/dist/filters/websocket-exception-handler.d.ts +8 -0
  120. package/dist/filters/websocket-exception-handler.d.ts.map +1 -0
  121. package/dist/filters/websocket-exception-handler.js +47 -0
  122. package/dist/filters/websocket-exception-handler.js.map +1 -0
  123. package/dist/guards/__tests__/api-key.guard.spec.d.ts +2 -0
  124. package/dist/guards/__tests__/api-key.guard.spec.d.ts.map +1 -0
  125. package/dist/guards/__tests__/api-key.guard.spec.js +123 -0
  126. package/dist/guards/__tests__/api-key.guard.spec.js.map +1 -0
  127. package/dist/guards/__tests__/jwt-auth.guard.spec.d.ts +2 -0
  128. package/dist/guards/__tests__/jwt-auth.guard.spec.d.ts.map +1 -0
  129. package/dist/guards/__tests__/jwt-auth.guard.spec.js +61 -0
  130. package/dist/guards/__tests__/jwt-auth.guard.spec.js.map +1 -0
  131. package/dist/guards/__tests__/permissions.guard.spec.d.ts +2 -0
  132. package/dist/guards/__tests__/permissions.guard.spec.d.ts.map +1 -0
  133. package/dist/guards/__tests__/permissions.guard.spec.js +77 -0
  134. package/dist/guards/__tests__/permissions.guard.spec.js.map +1 -0
  135. package/dist/guards/__tests__/rate-limit.guard.spec.d.ts +2 -0
  136. package/dist/guards/__tests__/rate-limit.guard.spec.d.ts.map +1 -0
  137. package/dist/guards/__tests__/rate-limit.guard.spec.js +117 -0
  138. package/dist/guards/__tests__/rate-limit.guard.spec.js.map +1 -0
  139. package/dist/guards/__tests__/roles.guard.spec.d.ts +2 -0
  140. package/dist/guards/__tests__/roles.guard.spec.d.ts.map +1 -0
  141. package/dist/guards/__tests__/roles.guard.spec.js +83 -0
  142. package/dist/guards/__tests__/roles.guard.spec.js.map +1 -0
  143. package/dist/guards/__tests__/websocket-auth.guard.spec.d.ts +2 -0
  144. package/dist/guards/__tests__/websocket-auth.guard.spec.d.ts.map +1 -0
  145. package/dist/guards/__tests__/websocket-auth.guard.spec.js +72 -0
  146. package/dist/guards/__tests__/websocket-auth.guard.spec.js.map +1 -0
  147. package/dist/guards/api-key.guard.d.ts +10 -0
  148. package/dist/guards/api-key.guard.d.ts.map +1 -0
  149. package/dist/guards/api-key.guard.js +58 -0
  150. package/dist/guards/api-key.guard.js.map +1 -0
  151. package/dist/guards/jwt-auth.guard.d.ts +8 -0
  152. package/dist/guards/jwt-auth.guard.d.ts.map +1 -0
  153. package/dist/guards/jwt-auth.guard.js +41 -0
  154. package/dist/guards/jwt-auth.guard.js.map +1 -0
  155. package/dist/guards/permissions.guard.d.ts +8 -0
  156. package/dist/guards/permissions.guard.d.ts.map +1 -0
  157. package/dist/guards/permissions.guard.js +48 -0
  158. package/dist/guards/permissions.guard.js.map +1 -0
  159. package/dist/guards/rate-limit.guard.d.ts +16 -0
  160. package/dist/guards/rate-limit.guard.d.ts.map +1 -0
  161. package/dist/guards/rate-limit.guard.js +89 -0
  162. package/dist/guards/rate-limit.guard.js.map +1 -0
  163. package/dist/guards/roles.guard.d.ts +8 -0
  164. package/dist/guards/roles.guard.d.ts.map +1 -0
  165. package/dist/guards/roles.guard.js +48 -0
  166. package/dist/guards/roles.guard.js.map +1 -0
  167. package/dist/guards/websocket-auth.guard.d.ts +8 -0
  168. package/dist/guards/websocket-auth.guard.d.ts.map +1 -0
  169. package/dist/guards/websocket-auth.guard.js +41 -0
  170. package/dist/guards/websocket-auth.guard.js.map +1 -0
  171. package/dist/index.d.ts +46 -0
  172. package/dist/index.d.ts.map +1 -0
  173. package/dist/index.js +38 -0
  174. package/dist/index.js.map +1 -0
  175. package/dist/interceptors/__tests__/compression.interceptor.spec.d.ts +2 -0
  176. package/dist/interceptors/__tests__/compression.interceptor.spec.d.ts.map +1 -0
  177. package/dist/interceptors/__tests__/compression.interceptor.spec.js +93 -0
  178. package/dist/interceptors/__tests__/compression.interceptor.spec.js.map +1 -0
  179. package/dist/interceptors/__tests__/http-logging.interceptor.spec.d.ts +2 -0
  180. package/dist/interceptors/__tests__/http-logging.interceptor.spec.d.ts.map +1 -0
  181. package/dist/interceptors/__tests__/http-logging.interceptor.spec.js +135 -0
  182. package/dist/interceptors/__tests__/http-logging.interceptor.spec.js.map +1 -0
  183. package/dist/interceptors/__tests__/request-id-response.interceptor.spec.d.ts +2 -0
  184. package/dist/interceptors/__tests__/request-id-response.interceptor.spec.d.ts.map +1 -0
  185. package/dist/interceptors/__tests__/request-id-response.interceptor.spec.js +39 -0
  186. package/dist/interceptors/__tests__/request-id-response.interceptor.spec.js.map +1 -0
  187. package/dist/interceptors/__tests__/response.interceptor.spec.d.ts +2 -0
  188. package/dist/interceptors/__tests__/response.interceptor.spec.d.ts.map +1 -0
  189. package/dist/interceptors/__tests__/response.interceptor.spec.js +95 -0
  190. package/dist/interceptors/__tests__/response.interceptor.spec.js.map +1 -0
  191. package/dist/interceptors/__tests__/rpc-logging.interceptor.spec.d.ts +2 -0
  192. package/dist/interceptors/__tests__/rpc-logging.interceptor.spec.d.ts.map +1 -0
  193. package/dist/interceptors/__tests__/rpc-logging.interceptor.spec.js +113 -0
  194. package/dist/interceptors/__tests__/rpc-logging.interceptor.spec.js.map +1 -0
  195. package/dist/interceptors/__tests__/serialize.interceptor.spec.d.ts +2 -0
  196. package/dist/interceptors/__tests__/serialize.interceptor.spec.d.ts.map +1 -0
  197. package/dist/interceptors/__tests__/serialize.interceptor.spec.js +114 -0
  198. package/dist/interceptors/__tests__/serialize.interceptor.spec.js.map +1 -0
  199. package/dist/interceptors/__tests__/unified.interceptor.spec.d.ts +2 -0
  200. package/dist/interceptors/__tests__/unified.interceptor.spec.d.ts.map +1 -0
  201. package/dist/interceptors/__tests__/unified.interceptor.spec.js +256 -0
  202. package/dist/interceptors/__tests__/unified.interceptor.spec.js.map +1 -0
  203. package/dist/interceptors/__tests__/websocket-logging.interceptor.spec.d.ts +2 -0
  204. package/dist/interceptors/__tests__/websocket-logging.interceptor.spec.d.ts.map +1 -0
  205. package/dist/interceptors/__tests__/websocket-logging.interceptor.spec.js +119 -0
  206. package/dist/interceptors/__tests__/websocket-logging.interceptor.spec.js.map +1 -0
  207. package/dist/interceptors/compression.interceptor.d.ts +10 -0
  208. package/dist/interceptors/compression.interceptor.d.ts.map +1 -0
  209. package/dist/interceptors/compression.interceptor.js +53 -0
  210. package/dist/interceptors/compression.interceptor.js.map +1 -0
  211. package/dist/interceptors/http-logging.interceptor.d.ts +9 -0
  212. package/dist/interceptors/http-logging.interceptor.d.ts.map +1 -0
  213. package/dist/interceptors/http-logging.interceptor.js +41 -0
  214. package/dist/interceptors/http-logging.interceptor.js.map +1 -0
  215. package/dist/interceptors/request-id-response.interceptor.d.ts +6 -0
  216. package/dist/interceptors/request-id-response.interceptor.d.ts.map +1 -0
  217. package/dist/interceptors/request-id-response.interceptor.js +27 -0
  218. package/dist/interceptors/request-id-response.interceptor.js.map +1 -0
  219. package/dist/interceptors/response.interceptor.d.ts +8 -0
  220. package/dist/interceptors/response.interceptor.d.ts.map +1 -0
  221. package/dist/interceptors/response.interceptor.js +42 -0
  222. package/dist/interceptors/response.interceptor.js.map +1 -0
  223. package/dist/interceptors/rpc-logging.interceptor.d.ts +9 -0
  224. package/dist/interceptors/rpc-logging.interceptor.d.ts.map +1 -0
  225. package/dist/interceptors/rpc-logging.interceptor.js +31 -0
  226. package/dist/interceptors/rpc-logging.interceptor.js.map +1 -0
  227. package/dist/interceptors/serialize.interceptor.d.ts +9 -0
  228. package/dist/interceptors/serialize.interceptor.d.ts.map +1 -0
  229. package/dist/interceptors/serialize.interceptor.js +48 -0
  230. package/dist/interceptors/serialize.interceptor.js.map +1 -0
  231. package/dist/interceptors/unified.interceptor.d.ts +12 -0
  232. package/dist/interceptors/unified.interceptor.d.ts.map +1 -0
  233. package/dist/interceptors/unified.interceptor.js +54 -0
  234. package/dist/interceptors/unified.interceptor.js.map +1 -0
  235. package/dist/interceptors/websocket-logging.interceptor.d.ts +9 -0
  236. package/dist/interceptors/websocket-logging.interceptor.d.ts.map +1 -0
  237. package/dist/interceptors/websocket-logging.interceptor.js +36 -0
  238. package/dist/interceptors/websocket-logging.interceptor.js.map +1 -0
  239. package/dist/pipes/__tests__/file-validation.pipe.spec.d.ts +2 -0
  240. package/dist/pipes/__tests__/file-validation.pipe.spec.d.ts.map +1 -0
  241. package/dist/pipes/__tests__/file-validation.pipe.spec.js +60 -0
  242. package/dist/pipes/__tests__/file-validation.pipe.spec.js.map +1 -0
  243. package/dist/pipes/__tests__/header-validation.pipe.spec.d.ts +2 -0
  244. package/dist/pipes/__tests__/header-validation.pipe.spec.d.ts.map +1 -0
  245. package/dist/pipes/__tests__/header-validation.pipe.spec.js +111 -0
  246. package/dist/pipes/__tests__/header-validation.pipe.spec.js.map +1 -0
  247. package/dist/pipes/__tests__/http-validation.pipe.spec.d.ts +2 -0
  248. package/dist/pipes/__tests__/http-validation.pipe.spec.d.ts.map +1 -0
  249. package/dist/pipes/__tests__/http-validation.pipe.spec.js +114 -0
  250. package/dist/pipes/__tests__/http-validation.pipe.spec.js.map +1 -0
  251. package/dist/pipes/__tests__/query-validation.pipe.spec.d.ts +2 -0
  252. package/dist/pipes/__tests__/query-validation.pipe.spec.d.ts.map +1 -0
  253. package/dist/pipes/__tests__/query-validation.pipe.spec.js +103 -0
  254. package/dist/pipes/__tests__/query-validation.pipe.spec.js.map +1 -0
  255. package/dist/pipes/__tests__/rpc-validation.pipe.spec.d.ts +2 -0
  256. package/dist/pipes/__tests__/rpc-validation.pipe.spec.d.ts.map +1 -0
  257. package/dist/pipes/__tests__/rpc-validation.pipe.spec.js +126 -0
  258. package/dist/pipes/__tests__/rpc-validation.pipe.spec.js.map +1 -0
  259. package/dist/pipes/file-validation.pipe.d.ts +10 -0
  260. package/dist/pipes/file-validation.pipe.d.ts.map +1 -0
  261. package/dist/pipes/file-validation.pipe.js +41 -0
  262. package/dist/pipes/file-validation.pipe.js.map +1 -0
  263. package/dist/pipes/header-validation.pipe.d.ts +8 -0
  264. package/dist/pipes/header-validation.pipe.d.ts.map +1 -0
  265. package/dist/pipes/header-validation.pipe.js +58 -0
  266. package/dist/pipes/header-validation.pipe.js.map +1 -0
  267. package/dist/pipes/http-validation.pipe.d.ts +8 -0
  268. package/dist/pipes/http-validation.pipe.d.ts.map +1 -0
  269. package/dist/pipes/http-validation.pipe.js +41 -0
  270. package/dist/pipes/http-validation.pipe.js.map +1 -0
  271. package/dist/pipes/query-validation.pipe.d.ts +8 -0
  272. package/dist/pipes/query-validation.pipe.d.ts.map +1 -0
  273. package/dist/pipes/query-validation.pipe.js +58 -0
  274. package/dist/pipes/query-validation.pipe.js.map +1 -0
  275. package/dist/pipes/rpc-validation.pipe.d.ts +8 -0
  276. package/dist/pipes/rpc-validation.pipe.d.ts.map +1 -0
  277. package/dist/pipes/rpc-validation.pipe.js +49 -0
  278. package/dist/pipes/rpc-validation.pipe.js.map +1 -0
  279. package/dist/types/circuit-breaker-types.d.ts +19 -0
  280. package/dist/types/circuit-breaker-types.d.ts.map +1 -0
  281. package/dist/types/circuit-breaker-types.js +8 -0
  282. package/dist/types/circuit-breaker-types.js.map +1 -0
  283. package/dist/types/compression-types.d.ts +22 -0
  284. package/dist/types/compression-types.d.ts.map +1 -0
  285. package/dist/types/compression-types.js +2 -0
  286. package/dist/types/compression-types.js.map +1 -0
  287. package/dist/types/context-types.d.ts +18 -0
  288. package/dist/types/context-types.d.ts.map +1 -0
  289. package/dist/types/context-types.js +8 -0
  290. package/dist/types/context-types.js.map +1 -0
  291. package/dist/types/cors-types.d.ts +11 -0
  292. package/dist/types/cors-types.d.ts.map +1 -0
  293. package/dist/types/cors-types.js +2 -0
  294. package/dist/types/cors-types.js.map +1 -0
  295. package/dist/types/error-types.d.ts +13 -0
  296. package/dist/types/error-types.d.ts.map +1 -0
  297. package/dist/types/error-types.js +15 -0
  298. package/dist/types/error-types.js.map +1 -0
  299. package/dist/types/file-types.d.ts +13 -0
  300. package/dist/types/file-types.d.ts.map +1 -0
  301. package/dist/types/file-types.js +2 -0
  302. package/dist/types/file-types.js.map +1 -0
  303. package/dist/types/file-validation-types.d.ts +10 -0
  304. package/dist/types/file-validation-types.d.ts.map +1 -0
  305. package/dist/types/file-validation-types.js +2 -0
  306. package/dist/types/file-validation-types.js.map +1 -0
  307. package/dist/types/get-service-path-types.d.ts +16 -0
  308. package/dist/types/get-service-path-types.d.ts.map +1 -0
  309. package/dist/types/get-service-path-types.js +2 -0
  310. package/dist/types/get-service-path-types.js.map +1 -0
  311. package/dist/types/guard-types.d.ts +5 -0
  312. package/dist/types/guard-types.d.ts.map +1 -0
  313. package/dist/types/guard-types.js +2 -0
  314. package/dist/types/guard-types.js.map +1 -0
  315. package/dist/types/http-response.d.ts +19 -0
  316. package/dist/types/http-response.d.ts.map +1 -0
  317. package/dist/types/http-response.js +2 -0
  318. package/dist/types/http-response.js.map +1 -0
  319. package/dist/types/rpc-types.d.ts +21 -0
  320. package/dist/types/rpc-types.d.ts.map +1 -0
  321. package/dist/types/rpc-types.js +17 -0
  322. package/dist/types/rpc-types.js.map +1 -0
  323. package/dist/types/versioning-types.d.ts +8 -0
  324. package/dist/types/versioning-types.d.ts.map +1 -0
  325. package/dist/types/versioning-types.js +2 -0
  326. package/dist/types/versioning-types.js.map +1 -0
  327. package/dist/utils/__tests__/circuit-breaker.spec.d.ts +2 -0
  328. package/dist/utils/__tests__/circuit-breaker.spec.d.ts.map +1 -0
  329. package/dist/utils/__tests__/circuit-breaker.spec.js +206 -0
  330. package/dist/utils/__tests__/circuit-breaker.spec.js.map +1 -0
  331. package/dist/utils/__tests__/compression.utils.spec.d.ts +2 -0
  332. package/dist/utils/__tests__/compression.utils.spec.d.ts.map +1 -0
  333. package/dist/utils/__tests__/compression.utils.spec.js +106 -0
  334. package/dist/utils/__tests__/compression.utils.spec.js.map +1 -0
  335. package/dist/utils/__tests__/context.utils.spec.d.ts +2 -0
  336. package/dist/utils/__tests__/context.utils.spec.d.ts.map +1 -0
  337. package/dist/utils/__tests__/context.utils.spec.js +112 -0
  338. package/dist/utils/__tests__/context.utils.spec.js.map +1 -0
  339. package/dist/utils/__tests__/cors.utils.spec.d.ts +2 -0
  340. package/dist/utils/__tests__/cors.utils.spec.d.ts.map +1 -0
  341. package/dist/utils/__tests__/cors.utils.spec.js +54 -0
  342. package/dist/utils/__tests__/cors.utils.spec.js.map +1 -0
  343. package/dist/utils/__tests__/env-validator.spec.d.ts +2 -0
  344. package/dist/utils/__tests__/env-validator.spec.d.ts.map +1 -0
  345. package/dist/utils/__tests__/env-validator.spec.js +88 -0
  346. package/dist/utils/__tests__/env-validator.spec.js.map +1 -0
  347. package/dist/utils/__tests__/file.utils.spec.d.ts +2 -0
  348. package/dist/utils/__tests__/file.utils.spec.d.ts.map +1 -0
  349. package/dist/utils/__tests__/file.utils.spec.js +95 -0
  350. package/dist/utils/__tests__/file.utils.spec.js.map +1 -0
  351. package/dist/utils/__tests__/get-service-path.spec.d.ts +2 -0
  352. package/dist/utils/__tests__/get-service-path.spec.d.ts.map +1 -0
  353. package/dist/utils/__tests__/get-service-path.spec.js +385 -0
  354. package/dist/utils/__tests__/get-service-path.spec.js.map +1 -0
  355. package/dist/utils/__tests__/versioning.utils.spec.d.ts +2 -0
  356. package/dist/utils/__tests__/versioning.utils.spec.d.ts.map +1 -0
  357. package/dist/utils/__tests__/versioning.utils.spec.js +66 -0
  358. package/dist/utils/__tests__/versioning.utils.spec.js.map +1 -0
  359. package/dist/utils/circuit-breaker.d.ts +15 -0
  360. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  361. package/dist/utils/circuit-breaker.js +96 -0
  362. package/dist/utils/circuit-breaker.js.map +1 -0
  363. package/dist/utils/compression.utils.d.ts +3 -0
  364. package/dist/utils/compression.utils.d.ts.map +1 -0
  365. package/dist/utils/compression.utils.js +25 -0
  366. package/dist/utils/compression.utils.js.map +1 -0
  367. package/dist/utils/context.utils.d.ts +7 -0
  368. package/dist/utils/context.utils.d.ts.map +1 -0
  369. package/dist/utils/context.utils.js +24 -0
  370. package/dist/utils/context.utils.js.map +1 -0
  371. package/dist/utils/cors.utils.d.ts +4 -0
  372. package/dist/utils/cors.utils.d.ts.map +1 -0
  373. package/dist/utils/cors.utils.js +23 -0
  374. package/dist/utils/cors.utils.js.map +1 -0
  375. package/dist/utils/env-validator.d.ts +2 -0
  376. package/dist/utils/env-validator.d.ts.map +1 -0
  377. package/dist/utils/env-validator.js +22 -0
  378. package/dist/utils/env-validator.js.map +1 -0
  379. package/dist/utils/file.utils.d.ts +6 -0
  380. package/dist/utils/file.utils.d.ts.map +1 -0
  381. package/dist/utils/file.utils.js +42 -0
  382. package/dist/utils/file.utils.js.map +1 -0
  383. package/dist/utils/get-service-path.d.ts +9 -0
  384. package/dist/utils/get-service-path.d.ts.map +1 -0
  385. package/dist/utils/get-service-path.js +65 -0
  386. package/dist/utils/get-service-path.js.map +1 -0
  387. package/dist/utils/versioning.utils.d.ts +4 -0
  388. package/dist/utils/versioning.utils.d.ts.map +1 -0
  389. package/dist/utils/versioning.utils.js +30 -0
  390. package/dist/utils/versioning.utils.js.map +1 -0
  391. package/package.json +95 -0
package/README.md ADDED
@@ -0,0 +1,1905 @@
1
+ # @makebelieve21213-packages/nest-common
2
+
3
+ Общий пакет с утилитами для NestJS микросервисов проекта NakolenkeChain. Предоставляет единую систему обработки ошибок, валидации, логирования и базовые классы для HTTP, RPC и WebSocket контекстов.
4
+
5
+ ## 📋 Содержание
6
+
7
+ 1. [Обзор](#обзор)
8
+ 2. [Система обработки ошибок](#система-обработки-ошибок)
9
+ 3. [Классы ошибок](#классы-ошибок)
10
+ 4. [Глобальные фильтры](#глобальные-фильтры)
11
+ 5. [Перехватчики](#перехватчики)
12
+ 6. [Базовые классы](#базовые-классы)
13
+ 7. [Пайпы валидации](#пайпы-валидации)
14
+ 8. [Утилиты](#утилиты)
15
+ 9. [Типы](#типы)
16
+ 10. [Использование](#использование)
17
+ 11. [Best Practices](#best-practices)
18
+ 12. [Обработка ошибок WebSocket](#обработка-ошибок-websocket)
19
+ 13. [Дополнительные ресурсы](#дополнительные-ресурсы)
20
+
21
+ ---
22
+
23
+ ## 🎯 Обзор
24
+
25
+ Пакет предоставляет единую систему обработки ошибок для всех типов контекстов:
26
+ - **HTTP** - для HTTP контроллеров (api-service)
27
+ - **RPC** - для RabbitMQ RPC запросов (analytics-service, data-service, token-service)
28
+ - **WebSocket** - для Socket.io соединений (api-service)
29
+
30
+ Все ошибки автоматически преобразуются между контекстами с сохранением типа и статус-кода.
31
+
32
+ ---
33
+
34
+ ## 🔄 Система обработки ошибок
35
+
36
+ ### Архитектура
37
+
38
+ ```
39
+ ┌─────────────────────────────────────────────────────────────┐
40
+ │ HTTP Контекст (api-service) │
41
+ ├─────────────────────────────────────────────────────────────┤
42
+ │ │
43
+ │ HTTP Controller (БЕЗ catch блоков) │
44
+ │ ↓ │
45
+ │ Сервис (может иметь catch для логирования) │
46
+ │ ↓ (await rabbitMQService.publish) │
47
+ │ RpcException от RabbitMQ │
48
+ │ ↓ (пробрасывается дальше) │
49
+ │ UnifiedExceptionFilter (глобальный) │
50
+ │ ↓ HttpExceptionFilter.handleException() │
51
+ │ ↓ HttpError.fromUnknown() │
52
+ │ HttpError с правильным статусом │
53
+ │ ↓ │
54
+ │ HTTP Response для фронтенда │
55
+ │ │
56
+ └─────────────────────────────────────────────────────────────┘
57
+
58
+ ┌─────────────────────────────────────────────────────────────┐
59
+ │ RPC Контекст (analytics-service) │
60
+ ├─────────────────────────────────────────────────────────────┤
61
+ │ │
62
+ │ RPC Controller (БЕЗ catch блоков) │
63
+ │ ↓ │
64
+ │ Сервис (ошибка в бизнес-логике) │
65
+ │ ↓ (пробрасывается дальше) │
66
+ │ UnifiedExceptionFilter (глобальный) │
67
+ │ ↓ RpcExceptionFilter.handleException() │
68
+ │ ↓ RpcError.fromUnknown() │
69
+ │ RpcError с типом (временная/постоянная) │
70
+ │ ↓ (определяет retry/DLX логику) │
71
+ │ Отправка через RabbitMQ в api-service │
72
+ │ │
73
+ └─────────────────────────────────────────────────────────────┘
74
+
75
+ ┌─────────────────────────────────────────────────────────────┐
76
+ │ WebSocket Контекст (api-service) │
77
+ ├─────────────────────────────────────────────────────────────┤
78
+ │ │
79
+ │ SocketGateway.publish() │
80
+ │ ↓ (ошибка при отправке события) │
81
+ │ SocketError.fromUnknown() │
82
+ │ ↓ │
83
+ │ Логирование + сохранение в Redis │
84
+ │ ↓ (опционально) │
85
+ │ Отправка события ERROR на фронт через socket │
86
+ │ │
87
+ └─────────────────────────────────────────────────────────────┘
88
+ ```
89
+
90
+ ### Принципы работы
91
+
92
+ 1. **Глобальные фильтры** - все ошибки обрабатываются автоматически через глобальные фильтры
93
+ 2. **Без catch блоков в контроллерах** - контроллеры не должны иметь try-catch блоков
94
+ 3. **Автоматическое преобразование** - ошибки автоматически преобразуются между контекстами
95
+ 4. **Сохранение типа и статуса** - тип ошибки и статус-код сохраняются при преобразовании
96
+
97
+ ---
98
+
99
+ ## 🚨 Классы ошибок
100
+
101
+ ### HttpError
102
+
103
+ Класс ошибок для HTTP контекста. Используется в `api-service` для обработки HTTP запросов.
104
+
105
+ **Расположение:** `src/errors/http.error.ts`
106
+
107
+ **Наследование:** `HttpException` (NestJS)
108
+
109
+ **Особенности:**
110
+ - Автоматически преобразует `RpcException`/`RpcError` в HTTP ошибку
111
+ - Автоматически преобразует `SocketError` в HTTP ошибку
112
+ - Сохраняет правильный HTTP статус-код
113
+ - Включает stack trace в ответе, если он доступен в исходной ошибке
114
+
115
+ **Пример использования:**
116
+
117
+ ```typescript
118
+ // В HTTP контроллере (БЕЗ catch блока)
119
+ @Get("/analytics/global")
120
+ async getGlobal() {
121
+ // Ошибка автоматически обработается UnifiedExceptionFilter
122
+ return await this.analyticsService.getGlobalData();
123
+ }
124
+
125
+ // В сервисе (опционально для логирования)
126
+ async getGlobalData() {
127
+ try {
128
+ const data = await this.rabbitMQService.publish(...);
129
+ return data;
130
+ } catch (error) {
131
+ // Дополнительное логирование (опционально)
132
+ this.logger.error(`Ошибка RPC: ${error}`);
133
+ // Пробрасываем дальше - фильтр преобразует в HttpError
134
+ throw error;
135
+ }
136
+ }
137
+ ```
138
+
139
+ **Преобразование ошибок:**
140
+
141
+ ```typescript
142
+ // HttpError.fromUnknown() автоматически обрабатывает:
143
+ - HttpError → возвращает как есть (с опциональным descriptionPrefix)
144
+ - HttpException → извлекает статус и тип, сохраняет оригинальный формат message (массив остается массивом в getResponse())
145
+ - RpcException/RpcError → преобразует в HTTP с правильным статусом
146
+ - SocketError → преобразует в HTTP
147
+ - Error → определяет тип и создает HttpError
148
+ - Объекты с полем message → преобразует в HttpError
149
+ - Неизвестные типы → преобразует в строку и создает HttpError
150
+ ```
151
+
152
+ **Важно:**
153
+ - При преобразовании `HttpException` с массивом сообщений, оригинальный массив сохраняется в `getResponse()`, но для внутреннего `message` используется строка (массив объединяется через `"; "`).
154
+ - Опциональный параметр `descriptionPrefix` добавляется к сообщению ошибки для дополнительного контекста.
155
+
156
+ ### RpcError
157
+
158
+ Класс ошибок для RabbitMQ RPC контекста. Используется в `analytics-service`, `data-service`, `token-service`.
159
+
160
+ **Расположение:** `src/errors/rpc.error.ts`
161
+
162
+ **Наследование:** `RpcException` (NestJS)
163
+
164
+ **Особенности:**
165
+ - Автоматически определяет тип ошибки (временная/постоянная)
166
+ - Сохраняет статус-код для будущего преобразования в HTTP
167
+ - Сериализуется через RabbitMQ с сохранением типа и сообщения
168
+ - Используется в `RpcExceptionFilter` для retry/DLX логики
169
+
170
+ **Типы ошибок:**
171
+
172
+ **Временные (retry):**
173
+ - `RPC_TIMEOUT` - таймаут соединения
174
+ - `SERVICE_UNAVAILABLE` - сервис недоступен
175
+ - `RPC_SERVICE_UNAVAILABLE` - RPC сервис недоступен
176
+
177
+ **Постоянные (DLX сразу):**
178
+ - `BAD_REQUEST` - неправильный запрос
179
+ - `UNAUTHORIZED` - ошибка авторизации
180
+ - `FORBIDDEN` - ошибка доступа
181
+ - `NOT_FOUND` - ресурс не найден
182
+ - `VALIDATION_ERROR` - ошибка валидации
183
+ - `RPC_VALIDATION_ERROR` - ошибка валидации RPC
184
+
185
+ **Методы:**
186
+ - `isTransient(): boolean` - проверяет, является ли ошибка временной (требует retry)
187
+
188
+ **Пример использования:**
189
+
190
+ ```typescript
191
+ // В RPC контроллере (БЕЗ catch блока)
192
+ @MessagePattern(ROUTING_KEYS.ANALYTICS_GLOBAL)
193
+ async getGlobalData(
194
+ @Payload() _: GlobalDataIncomeDto,
195
+ @Ctx() ctx: RmqContext,
196
+ ): Promise<GlobalDataOutcomeDto> {
197
+ // Ошибка автоматически обработается UnifiedExceptionFilter
198
+ const data = await this.analyticsService.getGlobalData();
199
+ this.acknowledge(ctx);
200
+ return data;
201
+ }
202
+ ```
203
+
204
+ **Преобразование ошибок:**
205
+
206
+ ```typescript
207
+ // RpcError.fromUnknown() автоматически:
208
+ - Распознает ошибки с свойством isAxiosError и преобразует их с сохранением типа и статуса
209
+ - Определяет тип ошибки из сообщения
210
+ - Классифицирует как временную или постоянную
211
+ - Сохраняет оригинальную ошибку для логирования
212
+ - Обрабатывает сериализованные объекты ошибок из RabbitMQ
213
+ ```
214
+
215
+ **Интеграция с AxiosError:**
216
+
217
+ `RpcError.fromUnknown()` автоматически распознает ошибки с свойством `isAxiosError` и преобразует их в `RpcError` с сохранением типа ошибки и статус-кода из оригинальной Axios ошибки.
218
+
219
+ ### SocketError
220
+
221
+ Класс ошибок для WebSocket контекста. Используется в `api-service` для обработки ошибок Socket.io.
222
+
223
+ **Расположение:** `src/errors/socket.error.ts`
224
+
225
+ **Наследование:** `HttpException` (NestJS) - для совместимости с HTTP фильтрами
226
+
227
+ **Особенности:**
228
+ - Используется для обработки ошибок при отправке событий через Socket.io
229
+ - Логируется и сохраняется в Redis
230
+ - Может быть отправлена на фронт через событие `SOCKET_EVENTS.ERROR`
231
+ - Не связана с HTTP или RPC ошибками
232
+
233
+ **Пример использования:**
234
+
235
+ ```typescript
236
+ // В SocketGateway
237
+ async publish(userId: string, event: SOCKET_EVENTS, payload: unknown) {
238
+ try {
239
+ await this.io.timeout(5000).to(`user:${userId}`).emitWithAck(event, payload);
240
+ } catch (error) {
241
+ const socketError = SocketError.fromUnknown(error);
242
+
243
+ // Логирование
244
+ this.logger.error(`Ошибка отправки события: ${socketError.message}`);
245
+
246
+ // Сохранение в Redis
247
+ await this.redisService.hSet(
248
+ REDIS_H_KEYS.SOCKET_ERROR,
249
+ userId,
250
+ socketError.message,
251
+ );
252
+
253
+ // Опционально: отправка ошибки на фронт
254
+ await this.io.to(`user:${userId}`).emit(SOCKET_EVENTS.ERROR, {
255
+ status: "error",
256
+ message: socketError.message,
257
+ });
258
+
259
+ throw socketError;
260
+ }
261
+ }
262
+ ```
263
+
264
+ ---
265
+
266
+ ## 🛡️ Глобальные фильтры
267
+
268
+ ### UnifiedExceptionFilter
269
+
270
+ Единый глобальный фильтр для обработки HTTP и RPC ошибок. Автоматически определяет тип контекста и использует соответствующий обработчик.
271
+
272
+ **Расположение:** `src/filters/unified-exception.filter.ts`
273
+
274
+ **Регистрация:**
275
+
276
+ ```typescript
277
+ // В main.ts микросервиса
278
+ import { UnifiedExceptionFilter } from "@packages/nest-common";
279
+
280
+ async function bootstrap() {
281
+ const app = await NestFactory.create(AppModule);
282
+ const logger = await connectLogger(app, "ServiceName");
283
+
284
+ // Регистрируем глобальный фильтр
285
+ // Для RPC контекста можно передать dlxExchange для DLX логики
286
+ app.useGlobalFilters(
287
+ new UnifiedExceptionFilter(logger, dlxExchange), // dlxExchange опционально
288
+ );
289
+
290
+ await app.listen(PORT);
291
+ }
292
+ ```
293
+
294
+ **Логика работы:**
295
+
296
+ 1. Определяет тип контекста (HTTP или RPC)
297
+ 2. Использует соответствующий обработчик:
298
+ - **HTTP контекст** → `HttpExceptionFilter.handleException()`
299
+ - **RPC контекст** → `RpcExceptionFilter.handleException()`
300
+ 3. Обработчики преобразуют ошибки и формируют ответы
301
+
302
+ **Внутренние обработчики:**
303
+
304
+ - **HttpExceptionFilter** (`src/filters/http-exception-handler.ts`) - обрабатывает HTTP ошибки
305
+ - **RpcExceptionFilter** (`src/filters/rpc-exception-handler.ts`) - обрабатывает RPC ошибки с поддержкой retry/DLX
306
+
307
+ **Формат HTTP ответа:**
308
+
309
+ ```json
310
+ {
311
+ "statusCode": 500,
312
+ "timestamp": "2024-01-01T00:00:00.000Z",
313
+ "path": "/api/analytics/global",
314
+ "error": "INTERNAL_SERVER_ERROR",
315
+ "message": "Ошибка получения данных",
316
+ "stack": "..." // Если доступен в исходной ошибке
317
+ }
318
+ ```
319
+
320
+ **Retry логика для RPC:**
321
+
322
+ ```typescript
323
+ // Постоянная ошибка (BAD_REQUEST, UNAUTHORIZED, etc.)
324
+ if (!isTransient) {
325
+ // Сразу в DLX, не тратим попытки retry
326
+ channel.publish(dlxExchange, routingKey, content);
327
+ channel.ack(msg);
328
+ throw rpcError; // Отправляем клиенту
329
+ }
330
+
331
+ // Временная ошибка (TIMEOUT, SERVICE_UNAVAILABLE)
332
+ if (retries < MAX_RETRIES) {
333
+ // Отправляем в retry очередь
334
+ channel.nack(msg, false, false);
335
+ return; // НЕ throw - сообщение будет обработано повторно
336
+ } else {
337
+ // Превышен лимит - в DLX
338
+ channel.publish(dlxExchange, routingKey, content);
339
+ channel.ack(msg);
340
+ throw rpcError; // Отправляем клиенту
341
+ }
342
+ ```
343
+
344
+ ---
345
+
346
+ ## 🔍 Перехватчики
347
+
348
+ Перехватчики (Interceptors) используются для логирования и мониторинга всех запросов в приложении. Они автоматически перехватывают запросы до и после их выполнения, позволяя логировать метрики производительности и отслеживать все входящие запросы.
349
+
350
+ ### UnifiedInterceptor
351
+
352
+ Единый глобальный перехватчик для логирования HTTP и RPC запросов. Автоматически определяет тип контекста и использует соответствующий обработчик.
353
+
354
+ **Расположение:** `src/interceptors/unified.interceptor.ts`
355
+
356
+ **Особенности:**
357
+ - Автоматически определяет тип контекста (HTTP или RPC)
358
+ - Использует соответствующий обработчик для логирования
359
+ - Логирует все входящие запросы с метриками производительности
360
+ - Работает с любыми эндпоинтами автоматически
361
+
362
+ **Регистрация:**
363
+
364
+ ```typescript
365
+ // В main.ts микросервиса
366
+ import { UnifiedInterceptor } from "@packages/nest-common";
367
+ import { LoggerService } from "@makebelieve21213-packages/logger";
368
+
369
+ async function bootstrap() {
370
+ const app = await NestFactory.create(AppModule);
371
+ const logger = await connectLogger(app, "ServiceName");
372
+
373
+ // Регистрируем глобальный перехватчик
374
+ app.useGlobalInterceptors(new UnifiedInterceptor(logger));
375
+
376
+ await app.listen(PORT);
377
+ }
378
+ ```
379
+
380
+ **Внутренние обработчики:**
381
+
382
+ - **HttpLoggingInterceptor** (`src/interceptors/http-logging.interceptor.ts`) - логирует HTTP запросы
383
+ - **RpcLoggingInterceptor** (`src/interceptors/rpc-logging.interceptor.ts`) - логирует RPC запросы
384
+ - **WebSocketLoggingInterceptor** (`src/interceptors/websocket-logging.interceptor.ts`) - логирует WebSocket запросы
385
+
386
+ **Логика работы:**
387
+
388
+ 1. Определяет тип контекста (HTTP, RPC или WebSocket)
389
+ 2. Использует соответствующий обработчик:
390
+ - **HTTP контекст** → `HttpLoggingInterceptor.intercept()`
391
+ - **RPC контекст** → `RpcLoggingInterceptor.intercept()`
392
+ 3. Обработчики логируют запросы с метриками времени выполнения
393
+
394
+ **Формат логов HTTP:**
395
+
396
+ ```
397
+ [HTTP] Incoming request [GET /api/analytics/global] from 127.0.0.1 (Mozilla/5.0...)
398
+ [HTTP] Request completed [GET /api/analytics/global] 200 45ms
399
+ [HTTP] Request failed [GET /api/analytics/global] 500 120ms - Internal server error
400
+ ```
401
+
402
+ **Формат логов RPC:**
403
+
404
+ ```
405
+ [RPC] Incoming request [pattern: analytics.global]
406
+ [RPC] Request completed [pattern: analytics.global, duration: 45ms]
407
+ [RPC] Request failed [pattern: analytics.global, duration: 120ms, error: Service unavailable]
408
+ ```
409
+
410
+ ---
411
+
412
+ ## 🎛️ Базовые классы
413
+
414
+ ### BaseController
415
+
416
+ Базовый контроллер для всех контроллеров проекта. Предоставляет общую функциональность для HTTP и RPC контроллеров.
417
+
418
+ **Расположение:** `src/base/base.controller.ts`
419
+
420
+ **Особенности:**
421
+ - Предоставляет общие методы для HTTP и RPC контроллеров
422
+ - Метод `acknowledge(ctx: RmqContext)` для подтверждения RPC сообщений
423
+ - Автоматически настраивает контекст логирования на имя класса контроллера
424
+
425
+ **Методы:**
426
+ - `protected acknowledge(ctx: RmqContext): void` - отправляет acknowledge сообщение в RabbitMQ
427
+
428
+ **Пример использования:**
429
+
430
+ ```typescript
431
+ import { Controller, Get } from "@nestjs/common";
432
+ import { BaseController } from "@packages/nest-common";
433
+ import { LoggerService } from "@makebelieve21213-packages/logger";
434
+
435
+ @Controller("analytics")
436
+ export default class AnalyticsController extends BaseController {
437
+ constructor(
438
+ private readonly analyticsService: AnalyticsService,
439
+ logger: LoggerService,
440
+ ) {
441
+ super(logger);
442
+ }
443
+
444
+ @Get("global")
445
+ async getGlobal() {
446
+ // БЕЗ try-catch - глобальный фильтр все обработает
447
+ return await this.analyticsService.getGlobalData();
448
+ }
449
+ }
450
+ ```
451
+
452
+ ---
453
+
454
+ ## 🔧 Пайпы валидации
455
+
456
+ ### HttpValidationPipe
457
+
458
+ Валидация DTO для HTTP контроллеров с использованием `class-validator`.
459
+
460
+ **Расположение:** `src/pipes/http-validation.pipe.ts`
461
+
462
+ **Особенности:**
463
+ - Автоматическое преобразование plain objects в DTO экземпляры через `plainToInstance` с `enableImplicitConversion: true`
464
+ - Валидация с `whitelist: true` и `forbidNonWhitelisted: true`
465
+ - Выбрасывает `BadRequestException` при ошибках валидации
466
+ - Сообщения об ошибках объединяются через `"; "`
467
+
468
+ **Использование:**
469
+
470
+ ```typescript
471
+ import { Controller, Post, Body } from "@nestjs/common";
472
+ import { HttpValidationPipe } from "@packages/nest-common";
473
+ import { CreateDto } from "@packages/dtos";
474
+
475
+ @Controller("tokens")
476
+ export default class TokenController extends BaseController {
477
+ @Post("create")
478
+ @UsePipes(new HttpValidationPipe(CreateDto))
479
+ async create(@Body() dto: CreateDto) {
480
+ return await this.tokenService.create(dto);
481
+ }
482
+ }
483
+ ```
484
+
485
+ ### RpcValidationPipe
486
+
487
+ Валидация DTO для RabbitMQ микросервисов с использованием `class-validator`.
488
+
489
+ **Расположение:** `src/pipes/rpc-validation.pipe.ts`
490
+
491
+ **Особенности:**
492
+ - Автоматическое преобразование plain objects в DTO экземпляры через `plainToInstance` с `enableImplicitConversion: true`
493
+ - Обрабатывает случаи, когда value может быть `undefined` или `null` (для пустых DTO передает пустой объект)
494
+ - Автоматически извлекает и исключает `correlationId` и `correlationTimestamp` из сообщения перед валидацией (для поддержки идемпотентности)
495
+ - Валидация с `whitelist: true` и `forbidNonWhitelisted: true`
496
+ - Выбрасывает `RpcException` при ошибках валидации
497
+ - Сообщения об ошибках объединяются через `"; "`
498
+
499
+ **Использование:**
500
+
501
+ ```typescript
502
+ import { Controller } from "@nestjs/common";
503
+ import { MessagePattern, Payload } from "@nestjs/microservices";
504
+ import { RpcValidationPipe } from "@packages/nest-common";
505
+ import { GlobalDataIncomeDto } from "@packages/dtos";
506
+
507
+ @Controller()
508
+ export default class AnalyticsController extends BaseController {
509
+ @MessagePattern(ROUTING_KEYS.ANALYTICS_GLOBAL)
510
+ @UsePipes(new RpcValidationPipe(GlobalDataIncomeDto))
511
+ async getGlobalData(@Payload() dto: GlobalDataIncomeDto) {
512
+ return await this.analyticsService.getGlobalData();
513
+ }
514
+ }
515
+ ```
516
+
517
+ **Обработка correlationId и correlationTimestamp:**
518
+
519
+ Pipe автоматически извлекает поля `correlationId` и `correlationTimestamp` из входящего сообщения (если они присутствуют) и исключает их из валидации DTO. Это позволяет использовать эти поля для идемпотентности без необходимости добавлять их в DTO классы.
520
+
521
+ ### FileValidationPipe
522
+
523
+ Валидация загруженных файлов с проверкой размера, MIME типа и расширения.
524
+
525
+ **Расположение:** `src/pipes/file-validation.pipe.ts`
526
+
527
+ **Особенности:**
528
+ - Валидирует одиночные файлы и массивы файлов
529
+ - Проверяет размер файла (по умолчанию максимум 10MB)
530
+ - Проверяет MIME тип файла
531
+ - Проверяет расширение файла
532
+ - Выбрасывает `BadRequestException` при ошибках валидации
533
+
534
+ **Использование:**
535
+
536
+ ```typescript
537
+ import { Controller, Post, UploadedFile, UseInterceptors } from "@nestjs/common";
538
+ import { FileInterceptor } from "@nestjs/platform-express";
539
+ import { FileValidationPipe } from "@packages/nest-common";
540
+
541
+ @Controller("upload")
542
+ export default class UploadController extends BaseController {
543
+ @Post("file")
544
+ @UseInterceptors(FileInterceptor("file"))
545
+ async uploadFile(
546
+ @UploadedFile(
547
+ new FileValidationPipe({
548
+ maxSize: 5 * 1024 * 1024, // 5MB
549
+ allowedMimeTypes: ["image/jpeg", "image/png"],
550
+ allowedExtensions: ["jpg", "jpeg", "png"],
551
+ }),
552
+ )
553
+ file: MulterFile,
554
+ ) {
555
+ return await this.uploadService.saveFile(file);
556
+ }
557
+ }
558
+ ```
559
+
560
+ ### QueryValidationPipe
561
+
562
+ Валидация query параметров HTTP запросов с использованием `class-validator`.
563
+
564
+ **Расположение:** `src/pipes/query-validation.pipe.ts`
565
+
566
+ **Особенности:**
567
+ - Автоматическое преобразование plain objects в DTO экземпляры через `plainToInstance`
568
+ - Валидация только для query параметров (`metadata.type === "query"`)
569
+ - Выбрасывает `BadRequestException` с детальными ошибками валидации
570
+ - Поддерживает вложенные объекты и массивы
571
+
572
+ **Использование:**
573
+
574
+ ```typescript
575
+ import { Controller, Get, Query } from "@nestjs/common";
576
+ import { QueryValidationPipe } from "@packages/nest-common";
577
+ import { PaginationDto } from "@packages/dtos";
578
+
579
+ @Controller("users")
580
+ export default class UsersController extends BaseController {
581
+ @Get()
582
+ async getUsers(
583
+ @Query(new QueryValidationPipe(PaginationDto)) query: PaginationDto,
584
+ ) {
585
+ return await this.usersService.findAll(query);
586
+ }
587
+ }
588
+ ```
589
+
590
+ ### HeaderValidationPipe
591
+
592
+ Валидация заголовков HTTP запросов с использованием `class-validator`.
593
+
594
+ **Расположение:** `src/pipes/header-validation.pipe.ts`
595
+
596
+ **Особенности:**
597
+ - Автоматическое преобразование plain objects в DTO экземпляры через `plainToInstance`
598
+ - Валидация только для custom параметров (`metadata.type === "custom"`)
599
+ - Выбрасывает `BadRequestException` с детальными ошибками валидации
600
+ - Поддерживает вложенные объекты и массивы
601
+
602
+ **Использование:**
603
+
604
+ ```typescript
605
+ import { Controller, Get, Headers } from "@nestjs/common";
606
+ import { HeaderValidationPipe } from "@packages/nest-common";
607
+ import { ApiHeadersDto } from "@packages/dtos";
608
+
609
+ @Controller("api")
610
+ export default class ApiController extends BaseController {
611
+ @Get("data")
612
+ async getData(
613
+ @Headers(new HeaderValidationPipe(ApiHeadersDto)) headers: ApiHeadersDto,
614
+ ) {
615
+ return await this.apiService.getData(headers);
616
+ }
617
+ }
618
+ ```
619
+
620
+ ---
621
+
622
+ ## 🔍 Перехватчики (дополнительные)
623
+
624
+ ### ResponseInterceptor
625
+
626
+ Перехватчик для стандартизации формата HTTP ответов. Автоматически оборачивает ответы в стандартный формат `StandardResponse`.
627
+
628
+ **Расположение:** `src/interceptors/response.interceptor.ts`
629
+
630
+ **Особенности:**
631
+ - Автоматически оборачивает ответы в формат `{ success: true, data: T, meta: {...} }`
632
+ - Добавляет метаданные: timestamp, path, requestId
633
+ - Если ответ уже в стандартном формате, возвращает как есть
634
+ - Работает только с HTTP контекстом
635
+
636
+ **Использование:**
637
+
638
+ ```typescript
639
+ import { Controller, Get, UseInterceptors } from "@nestjs/common";
640
+ import { ResponseInterceptor } from "@packages/nest-common";
641
+
642
+ @Controller("users")
643
+ @UseInterceptors(ResponseInterceptor)
644
+ export default class UsersController extends BaseController {
645
+ @Get()
646
+ async getUsers() {
647
+ // Ответ автоматически обернется в StandardResponse
648
+ return await this.usersService.findAll();
649
+ }
650
+ }
651
+ ```
652
+
653
+ **Формат ответа:**
654
+
655
+ ```json
656
+ {
657
+ "success": true,
658
+ "data": { /* ваши данные */ },
659
+ "meta": {
660
+ "timestamp": "2024-01-01T00:00:00.000Z",
661
+ "path": "/api/users",
662
+ "requestId": "req-123"
663
+ }
664
+ }
665
+ ```
666
+
667
+ ### SerializeInterceptor
668
+
669
+ Перехватчик для сериализации ответов с исключением чувствительных данных на основе DTO классов.
670
+
671
+ **Расположение:** `src/interceptors/serialize.interceptor.ts`
672
+
673
+ **Особенности:**
674
+ - Использует декоратор `@Serialize()` для указания DTO класса
675
+ - Автоматически исключает поля, не помеченные `@Expose()` в DTO
676
+ - Поддерживает массивы данных
677
+ - Работает с `class-transformer` и `excludeExtraneousValues: true`
678
+
679
+ **Использование:**
680
+
681
+ ```typescript
682
+ import { Controller, Get, UseInterceptors } from "@nestjs/common";
683
+ import { SerializeInterceptor, Serialize } from "@packages/nest-common";
684
+ import { UserResponseDto } from "@packages/dtos";
685
+
686
+ @Controller("users")
687
+ @UseInterceptors(SerializeInterceptor)
688
+ export default class UsersController extends BaseController {
689
+ @Get(":id")
690
+ @Serialize(UserResponseDto) // Указываем DTO для сериализации
691
+ async getUser(@Param("id") id: string) {
692
+ // Поля, не помеченные @Expose() в UserResponseDto, будут исключены
693
+ return await this.usersService.findOne(id);
694
+ }
695
+ }
696
+ ```
697
+
698
+ ### CompressionInterceptor
699
+
700
+ Перехватчик для автоматического сжатия больших HTTP ответов с использованием gzip.
701
+
702
+ **Расположение:** `src/interceptors/compression.interceptor.ts`
703
+
704
+ **Особенности:**
705
+ - Автоматически сжимает ответы больше заданного порога (по умолчанию 1024 байт)
706
+ - Использует gzip сжатие
707
+ - Проверяет эффективность сжатия (минимальный коэффициент сжатия 0.8)
708
+ - Устанавливает заголовки `Content-Encoding: gzip` и `Content-Type: application/json`
709
+ - Если сжатие неэффективно, возвращает исходные данные
710
+
711
+ **Использование:**
712
+
713
+ ```typescript
714
+ import { Controller, Get, UseInterceptors } from "@nestjs/common";
715
+ import { CompressionInterceptor } from "@packages/nest-common";
716
+
717
+ @Controller("data")
718
+ @UseInterceptors(new CompressionInterceptor(2048, 0.7)) // Порог 2KB, коэффициент 0.7
719
+ export default class DataController extends BaseController {
720
+ @Get("large")
721
+ async getLargeData() {
722
+ // Большие ответы автоматически сжимаются
723
+ return await this.dataService.getLargeDataset();
724
+ }
725
+ }
726
+ ```
727
+
728
+ ### RequestIdResponseInterceptor
729
+
730
+ Перехватчик для добавления Request ID в заголовки HTTP ответов.
731
+
732
+ **Расположение:** `src/interceptors/request-id-response.interceptor.ts`
733
+
734
+ **Особенности:**
735
+ - Извлекает Request ID из заголовков запроса (`x-request-id`) или `request.id`
736
+ - Добавляет Request ID в заголовок ответа `X-Request-ID`
737
+ - Работает только с HTTP контекстом
738
+
739
+ **Использование:**
740
+
741
+ ```typescript
742
+ import { Controller, Get, UseInterceptors } from "@nestjs/common";
743
+ import { RequestIdResponseInterceptor } from "@packages/nest-common";
744
+
745
+ @Controller("api")
746
+ @UseInterceptors(RequestIdResponseInterceptor)
747
+ export default class ApiController extends BaseController {
748
+ @Get("data")
749
+ async getData() {
750
+ // Request ID автоматически добавится в заголовки ответа
751
+ return await this.apiService.getData();
752
+ }
753
+ }
754
+ ```
755
+
756
+ ---
757
+
758
+ ## 🛡️ Guards (Охранники)
759
+
760
+ Guards используются для контроля доступа к эндпоинтам на основе аутентификации, авторизации и других условий.
761
+
762
+ ### JwtAuthGuard
763
+
764
+ Guard для проверки JWT токена и аутентификации пользователя.
765
+
766
+ **Расположение:** `src/guards/jwt-auth.guard.ts`
767
+
768
+ **Особенности:**
769
+ - Проверяет наличие пользователя в `request.user`
770
+ - Уважает декоратор `@Public()` - пропускает публичные эндпоинты
771
+ - Выбрасывает `UnauthorizedException` если пользователь не аутентифицирован
772
+
773
+ **Использование:**
774
+
775
+ ```typescript
776
+ import { Controller, Get, UseGuards } from "@nestjs/common";
777
+ import { JwtAuthGuard } from "@packages/nest-common";
778
+
779
+ @Controller("users")
780
+ @UseGuards(JwtAuthGuard)
781
+ export default class UsersController extends BaseController {
782
+ @Get("profile")
783
+ async getProfile(@Request() req) {
784
+ // req.user доступен после прохождения JwtAuthGuard
785
+ return await this.usersService.getProfile(req.user);
786
+ }
787
+ }
788
+ ```
789
+
790
+ ### ApiKeyGuard
791
+
792
+ Guard для проверки API ключа в заголовках запроса.
793
+
794
+ **Расположение:** `src/guards/api-key.guard.ts`
795
+
796
+ **Особенности:**
797
+ - Проверяет наличие API ключа в заголовке (по умолчанию `x-api-key`)
798
+ - Уважает декоратор `@Public()` - пропускает публичные эндпоинты
799
+ - Работает только с эндпоинтами, помеченными декоратором `@ApiKey()`
800
+ - Опционально проверяет ключ против списка валидных ключей
801
+ - Выбрасывает `UnauthorizedException` при отсутствии или невалидном ключе
802
+
803
+ **Использование:**
804
+
805
+ ```typescript
806
+ import { Controller, Get, UseGuards } from "@nestjs/common";
807
+ import { ApiKeyGuard, ApiKey } from "@packages/nest-common";
808
+
809
+ @Controller("api")
810
+ export default class ApiController extends BaseController {
811
+ constructor() {
812
+ // Создаем guard с валидными ключами
813
+ super();
814
+ }
815
+
816
+ @Get("data")
817
+ @UseGuards(new ApiKeyGuard(undefined, "x-api-key", new Set(["key1", "key2"])))
818
+ @ApiKey() // Помечаем эндпоинт как требующий API ключ
819
+ async getData() {
820
+ return await this.apiService.getData();
821
+ }
822
+ }
823
+ ```
824
+
825
+ ### RolesGuard
826
+
827
+ Guard для проверки ролей пользователя.
828
+
829
+ **Расположение:** `src/guards/roles.guard.ts`
830
+
831
+ **Особенности:**
832
+ - Проверяет наличие требуемых ролей у пользователя
833
+ - Использует декоратор `@Roles()` для указания требуемых ролей
834
+ - Проверяет, что у пользователя есть хотя бы одна из указанных ролей
835
+ - Выбрасывает `ForbiddenException` при недостаточных правах
836
+
837
+ **Использование:**
838
+
839
+ ```typescript
840
+ import { Controller, Get, UseGuards } from "@nestjs/common";
841
+ import { JwtAuthGuard, RolesGuard, Roles } from "@packages/nest-common";
842
+
843
+ @Controller("admin")
844
+ @UseGuards(JwtAuthGuard, RolesGuard)
845
+ export default class AdminController extends BaseController {
846
+ @Get("users")
847
+ @Roles("admin", "moderator") // Требуются роли admin или moderator
848
+ async getUsers() {
849
+ return await this.adminService.getUsers();
850
+ }
851
+ }
852
+ ```
853
+
854
+ ### PermissionsGuard
855
+
856
+ Guard для проверки разрешений пользователя.
857
+
858
+ **Расположение:** `src/guards/permissions.guard.ts`
859
+
860
+ **Особенности:**
861
+ - Проверяет наличие требуемых разрешений у пользователя
862
+ - Использует декоратор `@Permissions()` для указания требуемых разрешений
863
+ - Проверяет, что у пользователя есть ВСЕ указанные разрешения
864
+ - Выбрасывает `ForbiddenException` при недостаточных правах
865
+
866
+ **Использование:**
867
+
868
+ ```typescript
869
+ import { Controller, Delete, UseGuards } from "@nestjs/common";
870
+ import { JwtAuthGuard, PermissionsGuard, Permissions } from "@packages/nest-common";
871
+
872
+ @Controller("users")
873
+ @UseGuards(JwtAuthGuard, PermissionsGuard)
874
+ export default class UsersController extends BaseController {
875
+ @Delete(":id")
876
+ @Permissions("users:delete", "users:write") // Требуются ВСЕ указанные разрешения
877
+ async deleteUser(@Param("id") id: string) {
878
+ return await this.usersService.delete(id);
879
+ }
880
+ }
881
+ ```
882
+
883
+ ### RateLimitGuard
884
+
885
+ Guard для ограничения частоты запросов (Rate Limiting).
886
+
887
+ **Расположение:** `src/guards/rate-limit.guard.ts`
888
+
889
+ **Особенности:**
890
+ - Ограничивает количество запросов за временное окно
891
+ - По умолчанию: 100 запросов в минуту для аутентифицированных пользователей
892
+ - Для публичных эндпоинтов применяется более строгий лимит (50% от базового)
893
+ - Использует IP адрес и путь запроса для идентификации клиента
894
+ - Поддерживает кастомный генератор ключей
895
+ - Выбрасывает `HttpException` с кодом 429 (Too Many Requests) при превышении лимита
896
+ - Автоматически очищает устаревшие записи
897
+
898
+ **Использование:**
899
+
900
+ ```typescript
901
+ import { Controller, Get, UseGuards } from "@nestjs/common";
902
+ import { RateLimitGuard } from "@packages/nest-common";
903
+
904
+ @Controller("api")
905
+ @UseGuards(new RateLimitGuard(undefined, 200, 60000)) // 200 запросов в минуту
906
+ export default class ApiController extends BaseController {
907
+ @Get("data")
908
+ async getData() {
909
+ return await this.apiService.getData();
910
+ }
911
+ }
912
+ ```
913
+
914
+ ### WebSocketAuthGuard
915
+
916
+ Guard для проверки аутентификации при подключении к WebSocket.
917
+
918
+ **Расположение:** `src/guards/websocket-auth.guard.ts`
919
+
920
+ **Особенности:**
921
+ - Проверяет наличие токена в данных подключения или handshake
922
+ - Поддерживает кастомный валидатор токена через коллбек `TokenValidator`
923
+ - Выбрасывает `WsException` при отсутствии или невалидном токене
924
+
925
+ **Использование:**
926
+
927
+ ```typescript
928
+ import { WebSocketGateway, SubscribeMessage, UseGuards } from "@nestjs/websockets";
929
+ import { WebSocketAuthGuard } from "@packages/nest-common";
930
+
931
+ @WebSocketGateway()
932
+ export default class ChatGateway {
933
+ constructor(
934
+ @Inject(WebSocketAuthGuard)
935
+ private readonly authGuard: WebSocketAuthGuard,
936
+ ) {
937
+ // Создаем guard с валидатором токена
938
+ this.authGuard = new WebSocketAuthGuard(async (token, context) => {
939
+ return await this.authService.validateToken(token);
940
+ });
941
+ }
942
+
943
+ @SubscribeMessage("message")
944
+ @UseGuards(this.authGuard)
945
+ async handleMessage(client: Socket, payload: unknown) {
946
+ // Токен проверен через WebSocketAuthGuard
947
+ return await this.chatService.sendMessage(payload);
948
+ }
949
+ }
950
+ ```
951
+
952
+ ---
953
+
954
+ ## 🎨 Декораторы
955
+
956
+ Декораторы используются для добавления метаданных к эндпоинтам и контроллерам.
957
+
958
+ ### @Public()
959
+
960
+ Декоратор для пометки эндпоинта как публичного (без аутентификации).
961
+
962
+ **Расположение:** `src/decorators/public.decorator.ts`
963
+
964
+ **Использование:**
965
+
966
+ ```typescript
967
+ import { Controller, Get } from "@nestjs/common";
968
+ import { Public } from "@packages/nest-common";
969
+
970
+ @Controller("public")
971
+ export default class PublicController extends BaseController {
972
+ @Get("info")
973
+ @Public() // Эндпоинт доступен без аутентификации
974
+ async getInfo() {
975
+ return { message: "Public information" };
976
+ }
977
+ }
978
+ ```
979
+
980
+ ### @Roles()
981
+
982
+ Декоратор для указания ролей, необходимых для доступа к эндпоинту.
983
+
984
+ **Расположение:** `src/decorators/roles.decorator.ts`
985
+
986
+ **Использование:**
987
+
988
+ ```typescript
989
+ import { Controller, Get } from "@nestjs/common";
990
+ import { Roles } from "@packages/nest-common";
991
+
992
+ @Controller("admin")
993
+ export default class AdminController extends BaseController {
994
+ @Get("dashboard")
995
+ @Roles("admin", "moderator") // Требуются роли admin или moderator
996
+ async getDashboard() {
997
+ return await this.adminService.getDashboard();
998
+ }
999
+ }
1000
+ ```
1001
+
1002
+ ### @Permissions()
1003
+
1004
+ Декоратор для указания разрешений, необходимых для доступа к эндпоинту.
1005
+
1006
+ **Расположение:** `src/decorators/permissions.decorator.ts`
1007
+
1008
+ **Использование:**
1009
+
1010
+ ```typescript
1011
+ import { Controller, Delete } from "@nestjs/common";
1012
+ import { Permissions } from "@packages/nest-common";
1013
+
1014
+ @Controller("users")
1015
+ export default class UsersController extends BaseController {
1016
+ @Delete(":id")
1017
+ @Permissions("users:delete", "users:write") // Требуются ВСЕ указанные разрешения
1018
+ async deleteUser(@Param("id") id: string) {
1019
+ return await this.usersService.delete(id);
1020
+ }
1021
+ }
1022
+ ```
1023
+
1024
+ ### @ApiKey()
1025
+
1026
+ Декоратор для пометки эндпоинта как требующего API ключ.
1027
+
1028
+ **Расположение:** `src/decorators/api-key.decorator.ts`
1029
+
1030
+ **Использование:**
1031
+
1032
+ ```typescript
1033
+ import { Controller, Get } from "@nestjs/common";
1034
+ import { ApiKey } from "@packages/nest-common";
1035
+
1036
+ @Controller("api")
1037
+ export default class ApiController extends BaseController {
1038
+ @Get("data")
1039
+ @ApiKey() // Эндпоинт требует API ключ в заголовке x-api-key
1040
+ async getData() {
1041
+ return await this.apiService.getData();
1042
+ }
1043
+ }
1044
+ ```
1045
+
1046
+ ### @Serialize()
1047
+
1048
+ Декоратор для указания класса DTO для сериализации ответа.
1049
+
1050
+ **Расположение:** `src/decorators/serialize.decorator.ts`
1051
+
1052
+ **Использование:**
1053
+
1054
+ ```typescript
1055
+ import { Controller, Get } from "@nestjs/common";
1056
+ import { Serialize } from "@packages/nest-common";
1057
+ import { UserResponseDto } from "@packages/dtos";
1058
+
1059
+ @Controller("users")
1060
+ export default class UsersController extends BaseController {
1061
+ @Get(":id")
1062
+ @Serialize(UserResponseDto) // Ответ будет сериализован через UserResponseDto
1063
+ async getUser(@Param("id") id: string) {
1064
+ return await this.usersService.findOne(id);
1065
+ }
1066
+ }
1067
+ ```
1068
+
1069
+ ---
1070
+
1071
+ ## 🛠️ Утилиты
1072
+
1073
+ ### validateEnv
1074
+
1075
+ Функция валидации переменных окружения с использованием Joi.
1076
+
1077
+ **Расположение:** `src/utils/env-validator.ts`
1078
+
1079
+ **Особенности:**
1080
+ - Валидация обязательных переменных окружения
1081
+ - Выбрасывает `Error` с описанием отсутствующих ключей
1082
+ - Возвращает валидированный объект env
1083
+ - Использует `Joi.string().required()` для каждого обязательного ключа
1084
+ - Разрешает дополнительные ключи через `unknown(true)`
1085
+ - Использует `abortEarly: false` для получения всех ошибок валидации
1086
+
1087
+ **Использование:**
1088
+
1089
+ ```typescript
1090
+ import { validateEnv } from "@packages/nest-common";
1091
+
1092
+ const env = process.env;
1093
+ const requiredKeys = ["DATABASE_URL", "REDIS_URL", "RABBITMQ_URL"];
1094
+
1095
+ // Выбрасывает Error если ключи отсутствуют
1096
+ const validatedEnv = validateEnv(env, requiredKeys);
1097
+ ```
1098
+
1099
+ ### Утилиты для работы с контекстом
1100
+
1101
+ Функции для извлечения данных из контекста выполнения запроса.
1102
+
1103
+ **Расположение:** `src/utils/context.utils.ts`
1104
+
1105
+ **Функции:**
1106
+ - `getUserFromContext(context: ExecutionContext): UserFromContext | undefined` - извлекает пользователя из контекста
1107
+ - `getIpFromContext(context: ExecutionContext): string` - извлекает IP адрес из контекста
1108
+ - `getUserAgentFromContext(context: ExecutionContext): string` - извлекает User-Agent из контекста
1109
+ - `getRequestIdFromContext(context: ExecutionContext): string` - извлекает Request ID из контекста
1110
+
1111
+ **Использование:**
1112
+
1113
+ ```typescript
1114
+ import { getUserFromContext, getIpFromContext } from "@packages/nest-common";
1115
+
1116
+ @Controller("users")
1117
+ export default class UsersController extends BaseController {
1118
+ @Get("profile")
1119
+ async getProfile(@ExecutionContext() context: ExecutionContext) {
1120
+ const user = getUserFromContext(context);
1121
+ const ip = getIpFromContext(context);
1122
+
1123
+ return await this.usersService.getProfile(user, ip);
1124
+ }
1125
+ }
1126
+ ```
1127
+
1128
+ ### createCorsOptions
1129
+
1130
+ Функция для создания опций CORS для NestJS приложения.
1131
+
1132
+ **Расположение:** `src/utils/cors.utils.ts`
1133
+
1134
+ **Особенности:**
1135
+ - Настраивает CORS с разумными значениями по умолчанию
1136
+ - Поддерживает кастомные настройки origin, methods, headers и т.д.
1137
+ - По умолчанию разрешает все источники, основные HTTP методы и стандартные заголовки
1138
+
1139
+ **Использование:**
1140
+
1141
+ ```typescript
1142
+ import { NestFactory } from "@nestjs/core";
1143
+ import { createCorsOptions } from "@packages/nest-common";
1144
+
1145
+ async function bootstrap() {
1146
+ const app = await NestFactory.create(AppModule);
1147
+
1148
+ app.enableCors(createCorsOptions({
1149
+ origin: ["https://example.com"],
1150
+ credentials: true,
1151
+ }));
1152
+
1153
+ await app.listen(3000);
1154
+ }
1155
+ ```
1156
+
1157
+ ### createCompressionOptions
1158
+
1159
+ Функция для создания опций compression для NestJS приложения.
1160
+
1161
+ **Расположение:** `src/utils/compression.utils.ts`
1162
+
1163
+ **Особенности:**
1164
+ - Настраивает compression middleware с разумными значениями по умолчанию
1165
+ - По умолчанию сжимает только текстовые типы контента
1166
+ - Поддерживает кастомные настройки уровня сжатия, порога и фильтров
1167
+
1168
+ **Использование:**
1169
+
1170
+ ```typescript
1171
+ import { NestFactory } from "@nestjs/core";
1172
+ import { createCompressionOptions } from "@packages/nest-common";
1173
+ import compression from "compression";
1174
+
1175
+ async function bootstrap() {
1176
+ const app = await NestFactory.create(AppModule);
1177
+
1178
+ app.use(compression(createCompressionOptions({
1179
+ level: 9, // Максимальное сжатие
1180
+ threshold: 512, // Сжимать ответы больше 512 байт
1181
+ })));
1182
+
1183
+ await app.listen(3000);
1184
+ }
1185
+ ```
1186
+
1187
+ ### createVersioningOptions
1188
+
1189
+ Функция для создания опций версионирования API для NestJS приложения.
1190
+
1191
+ **Расположение:** `src/utils/versioning.utils.ts`
1192
+
1193
+ **Особенности:**
1194
+ - Поддерживает три стратегии версионирования: URI, Header, Media-Type
1195
+ - Настраивает версионирование с указанием типа и версии по умолчанию
1196
+
1197
+ **Использование:**
1198
+
1199
+ ```typescript
1200
+ import { NestFactory } from "@nestjs/core";
1201
+ import { createVersioningOptions } from "@packages/nest-common";
1202
+
1203
+ async function bootstrap() {
1204
+ const app = await NestFactory.create(AppModule);
1205
+
1206
+ app.enableVersioning(createVersioningOptions({
1207
+ type: "uri",
1208
+ defaultVersion: "1",
1209
+ }));
1210
+
1211
+ await app.listen(3000);
1212
+ }
1213
+ ```
1214
+
1215
+ ### Утилиты для работы с файлами
1216
+
1217
+ Функции для валидации и работы с файлами.
1218
+
1219
+ **Расположение:** `src/utils/file.utils.ts`
1220
+
1221
+ **Функции:**
1222
+ - `validateFile(file: MulterFile, options?: FileValidationOptions): FileValidationResult` - валидирует файл по заданным опциям
1223
+ - `getFileExtension(filename: string): string` - получает расширение файла из имени
1224
+ - `formatFileSize(bytes: number): string` - форматирует размер файла в читаемый формат
1225
+
1226
+ **Использование:**
1227
+
1228
+ ```typescript
1229
+ import { validateFile, formatFileSize } from "@packages/nest-common";
1230
+
1231
+ const result = validateFile(file, {
1232
+ maxSize: 5 * 1024 * 1024, // 5MB
1233
+ allowedMimeTypes: ["image/jpeg", "image/png"],
1234
+ allowedExtensions: ["jpg", "jpeg", "png"],
1235
+ });
1236
+
1237
+ if (!result.isValid) {
1238
+ console.error(result.errors);
1239
+ }
1240
+
1241
+ const size = formatFileSize(1024 * 1024); // "1 MB"
1242
+ ```
1243
+
1244
+ ### CircuitBreakerService
1245
+
1246
+ Сервис для реализации паттерна Circuit Breaker для защиты от каскадных сбоев.
1247
+
1248
+ **Расположение:** `src/utils/circuit-breaker.ts`
1249
+
1250
+ **Особенности:**
1251
+ - Реализует три состояния: CLOSED (нормальная работа), OPEN (разомкнут), HALF_OPEN (тестирование)
1252
+ - Автоматически открывает circuit при превышении порога ошибок
1253
+ - Автоматически закрывает circuit при успешных запросах в HALF_OPEN состоянии
1254
+ - Поддерживает настройку порогов ошибок и успешных запросов
1255
+ - Логирует переходы между состояниями
1256
+
1257
+ **Использование:**
1258
+
1259
+ ```typescript
1260
+ import { CircuitBreakerService } from "@packages/nest-common";
1261
+ import { LoggerService } from "@makebelieve21213-packages/logger";
1262
+
1263
+ const circuitBreaker = new CircuitBreakerService(logger, {
1264
+ failureThreshold: 5, // Открыть после 5 ошибок
1265
+ successThreshold: 2, // Закрыть после 2 успешных запросов
1266
+ resetTimeout: 60000, // Переход в HALF_OPEN через 1 минуту
1267
+ });
1268
+
1269
+ try {
1270
+ const result = await circuitBreaker.execute("external-api", async () => {
1271
+ return await externalApi.call();
1272
+ });
1273
+ } catch (error) {
1274
+ // Circuit breaker открыт или произошла ошибка
1275
+ }
1276
+ ```
1277
+
1278
+ ### getServicePath
1279
+
1280
+ Универсальная функция для определения пути в сервисе независимо от точки запуска и режима (dev/production).
1281
+
1282
+ **Расположение:** `src/utils/get-service-path.ts`
1283
+
1284
+ **Особенности:**
1285
+ - Работает одинаково в dev (src) и production (dist) режимах
1286
+ - Всегда использует пути относительно src/
1287
+ - Поддерживает три типа путей: locales, srcRoot, file
1288
+ - Автоматически находит корень сервиса по наличию папки src
1289
+
1290
+ **Использование:**
1291
+
1292
+ ```typescript
1293
+ import { getServicePath } from "@packages/nest-common";
1294
+
1295
+ // Получить путь к локалям
1296
+ const localesPath = getServicePath({
1297
+ serviceName: "api-service",
1298
+ dirname: __dirname,
1299
+ pathType: "locales",
1300
+ relativePath: "locales",
1301
+ });
1302
+
1303
+ // Получить путь к файлу
1304
+ const filePath = getServicePath({
1305
+ serviceName: "api-service",
1306
+ dirname: __dirname,
1307
+ pathType: "file",
1308
+ relativePath: "config/app.config.ts",
1309
+ });
1310
+ ```
1311
+
1312
+ ---
1313
+
1314
+ ## 📝 Типы
1315
+
1316
+ ### ErrorResponse
1317
+
1318
+ Интерфейс для HTTP ответов с ошибками.
1319
+
1320
+ **Расположение:** `src/types/http-response.ts`
1321
+
1322
+ ```typescript
1323
+ interface ErrorResponse {
1324
+ statusCode: number;
1325
+ timestamp: string;
1326
+ path: string;
1327
+ error: string;
1328
+ message: string;
1329
+ stack?: string; // Если доступен в исходной ошибке
1330
+ }
1331
+ ```
1332
+
1333
+ ### StandardResponse
1334
+
1335
+ Интерфейс стандартизированного ответа для HTTP запросов.
1336
+
1337
+ **Расположение:** `src/types/http-response.ts`
1338
+
1339
+ ```typescript
1340
+ interface StandardResponse<T = unknown> {
1341
+ success: boolean;
1342
+ data: T;
1343
+ meta?: {
1344
+ timestamp: string;
1345
+ path?: string;
1346
+ requestId?: string;
1347
+ [key: string]: unknown;
1348
+ };
1349
+ }
1350
+ ```
1351
+
1352
+ ### RpcErrorType
1353
+
1354
+ Enum типов ошибок RPC для классификации временных и постоянных ошибок.
1355
+
1356
+ **Расположение:** `src/types/rpc-types.ts`
1357
+
1358
+ **Временные ошибки (retry):**
1359
+ - `RPC_TIMEOUT` - таймаут соединения
1360
+ - `SERVICE_UNAVAILABLE` - сервис недоступен
1361
+ - `RPC_SERVICE_UNAVAILABLE` - RPC сервис недоступен
1362
+
1363
+ **Постоянные ошибки (DLX сразу):**
1364
+ - `BAD_REQUEST` - неправильный запрос
1365
+ - `UNAUTHORIZED` - ошибка авторизации
1366
+ - `FORBIDDEN` - ошибка доступа
1367
+ - `NOT_FOUND` - ресурс не найден
1368
+ - `VALIDATION_ERROR` - ошибка валидации
1369
+ - `RPC_VALIDATION_ERROR` - ошибка валидации RPC
1370
+
1371
+ ### UserFromContext
1372
+
1373
+ Интерфейс пользователя из контекста запроса.
1374
+
1375
+ **Расположение:** `src/types/context-types.ts`
1376
+
1377
+ ```typescript
1378
+ interface UserFromContext {
1379
+ id?: string | number;
1380
+ email?: string;
1381
+ roles?: string[];
1382
+ permissions?: string[];
1383
+ [key: string]: unknown;
1384
+ }
1385
+ ```
1386
+
1387
+ ### FileValidationOptions и FileValidationResult
1388
+
1389
+ Типы для валидации файлов.
1390
+
1391
+ **Расположение:** `src/types/file-validation-types.ts`
1392
+
1393
+ ```typescript
1394
+ interface FileValidationOptions {
1395
+ maxSize?: number; // Максимальный размер в байтах
1396
+ allowedMimeTypes?: string[]; // Разрешенные MIME типы
1397
+ allowedExtensions?: string[]; // Разрешенные расширения файлов
1398
+ }
1399
+
1400
+ interface FileValidationResult {
1401
+ isValid: boolean;
1402
+ errors: string[];
1403
+ }
1404
+ ```
1405
+
1406
+ ### CircuitBreakerState и CircuitBreakerOptions
1407
+
1408
+ Типы для Circuit Breaker.
1409
+
1410
+ **Расположение:** `src/types/circuit-breaker-types.ts`
1411
+
1412
+ ```typescript
1413
+ enum CircuitBreakerState {
1414
+ CLOSED = "CLOSED", // Нормальная работа
1415
+ OPEN = "OPEN", // Разомкнут (ошибки превысили порог)
1416
+ HALF_OPEN = "HALF_OPEN", // Полуоткрыт (тестирование восстановления)
1417
+ }
1418
+
1419
+ interface CircuitBreakerOptions {
1420
+ failureThreshold?: number; // Порог ошибок для открытия
1421
+ successThreshold?: number; // Порог успешных запросов для закрытия
1422
+ timeout?: number; // Время ожидания в открытом состоянии (мс)
1423
+ resetTimeout?: number; // Время до перехода в HALF_OPEN (мс)
1424
+ }
1425
+ ```
1426
+
1427
+ ### CorsOptionsConfig
1428
+
1429
+ Тип для настройки CORS.
1430
+
1431
+ **Расположение:** `src/types/cors-types.ts`
1432
+
1433
+ ```typescript
1434
+ interface CorsOptionsConfig {
1435
+ origin?: string | string[] | boolean | RegExp | ((origin: string) => boolean);
1436
+ methods?: string | string[];
1437
+ allowedHeaders?: string | string[];
1438
+ exposedHeaders?: string | string[];
1439
+ credentials?: boolean;
1440
+ maxAge?: number;
1441
+ preflightContinue?: boolean;
1442
+ optionsSuccessStatus?: number;
1443
+ }
1444
+ ```
1445
+
1446
+ ### CompressionOptionsConfig
1447
+
1448
+ Тип для настройки compression.
1449
+
1450
+ **Расположение:** `src/types/compression-types.ts`
1451
+
1452
+ ```typescript
1453
+ interface CompressionOptionsConfig {
1454
+ filter?: (req: Request, res: Response) => boolean;
1455
+ level?: number;
1456
+ threshold?: number;
1457
+ chunkSize?: number;
1458
+ windowBits?: number;
1459
+ memLevel?: number;
1460
+ strategy?: number;
1461
+ dictionary?: Buffer | Buffer[] | string;
1462
+ }
1463
+ ```
1464
+
1465
+ ### VersioningOptionsConfig
1466
+
1467
+ Тип для настройки версионирования API.
1468
+
1469
+ **Расположение:** `src/types/versioning-types.ts`
1470
+
1471
+ ```typescript
1472
+ type VersioningStrategy = "uri" | "header" | "media-type";
1473
+
1474
+ interface VersioningOptionsConfig {
1475
+ type: VersioningStrategy;
1476
+ defaultVersion?: string;
1477
+ header?: string;
1478
+ key?: string;
1479
+ }
1480
+ ```
1481
+
1482
+ ### GetServicePathOptions
1483
+
1484
+ Тип для опций функции getServicePath.
1485
+
1486
+ **Расположение:** `src/types/get-service-path-types.ts`
1487
+
1488
+ ```typescript
1489
+ type ServicePathType = "locales" | "srcRoot" | "file";
1490
+
1491
+ interface GetServicePathOptions {
1492
+ serviceName: string;
1493
+ dirname: string;
1494
+ pathType: ServicePathType;
1495
+ relativePath: string;
1496
+ }
1497
+ ```
1498
+
1499
+ ### MulterFile
1500
+
1501
+ Тип файла Multer.
1502
+
1503
+ **Расположение:** `src/types/file-types.ts`
1504
+
1505
+ ```typescript
1506
+ interface MulterFile {
1507
+ fieldname: string;
1508
+ originalname: string;
1509
+ encoding: string;
1510
+ mimetype: string;
1511
+ size: number;
1512
+ buffer: Buffer;
1513
+ destination: string;
1514
+ filename: string;
1515
+ path: string;
1516
+ stream: NodeJS.ReadableStream;
1517
+ }
1518
+ ```
1519
+
1520
+ ---
1521
+
1522
+ ## 🚨 Классы ошибок (дополнительные)
1523
+
1524
+ ### NestCommonError
1525
+
1526
+ Базовый класс ошибок пакета nest-common для внутренних ошибок пакета.
1527
+
1528
+ **Расположение:** `src/errors/nest-common.error.ts`
1529
+
1530
+ **Наследование:** `Error`
1531
+
1532
+ **Особенности:**
1533
+ - Используется для внутренних ошибок пакета
1534
+ - Сохраняет оригинальную ошибку для логирования
1535
+ - Корректно работает с `instanceof`
1536
+
1537
+ **Использование:**
1538
+
1539
+ ```typescript
1540
+ import { NestCommonError } from "@packages/nest-common";
1541
+
1542
+ throw new NestCommonError("Internal package error", originalError);
1543
+ ```
1544
+
1545
+ ---
1546
+
1547
+ ## 📖 Использование
1548
+
1549
+ ### HTTP контроллер (api-service)
1550
+
1551
+ ```typescript
1552
+ import { Controller, Get } from "@nestjs/common";
1553
+ import { BaseController } from "@packages/nest-common";
1554
+ import { LoggerService } from "@makebelieve21213-packages/logger";
1555
+
1556
+ @Controller("analytics")
1557
+ export default class AnalyticsController extends BaseController {
1558
+ constructor(
1559
+ private readonly analyticsService: AnalyticsService,
1560
+ logger: LoggerService,
1561
+ ) {
1562
+ super(logger);
1563
+ }
1564
+
1565
+ @Get("global")
1566
+ async getGlobal() {
1567
+ // БЕЗ try-catch - глобальный фильтр все обработает
1568
+ return await this.analyticsService.getGlobalData();
1569
+ }
1570
+ }
1571
+ ```
1572
+
1573
+ ### RPC контроллер (analytics-service)
1574
+
1575
+ ```typescript
1576
+ import { Controller } from "@nestjs/common";
1577
+ import { MessagePattern, Payload, Ctx } from "@nestjs/microservices";
1578
+ import { BaseController } from "@packages/nest-common";
1579
+ import { LoggerService } from "@makebelieve21213-packages/logger";
1580
+
1581
+ @Controller()
1582
+ export default class AnalyticsController extends BaseController {
1583
+ constructor(
1584
+ private readonly analyticsService: AnalyticsService,
1585
+ logger: LoggerService,
1586
+ ) {
1587
+ super(logger);
1588
+ }
1589
+
1590
+ @MessagePattern(ROUTING_KEYS.ANALYTICS_GLOBAL)
1591
+ async getGlobalData(
1592
+ @Payload() _: GlobalDataIncomeDto,
1593
+ @Ctx() ctx: RmqContext,
1594
+ ): Promise<GlobalDataOutcomeDto> {
1595
+ // БЕЗ try-catch - глобальный фильтр все обработает
1596
+ const data = await this.analyticsService.getGlobalData();
1597
+ this.acknowledge(ctx);
1598
+ return data;
1599
+ }
1600
+ }
1601
+ ```
1602
+
1603
+ ### WebSocket Gateway (api-service)
1604
+
1605
+ ```typescript
1606
+ import { WebSocketGateway, WebSocketServer } from "@nestjs/websockets";
1607
+ import { SocketError } from "@packages/nest-common";
1608
+ import { SOCKET_EVENTS } from "@packages/types";
1609
+
1610
+ @WebSocketGateway()
1611
+ export default class SocketGateway extends BaseGateway {
1612
+ @WebSocketServer()
1613
+ io!: Server;
1614
+
1615
+ async publish(userId: string, event: SOCKET_EVENTS, payload: unknown) {
1616
+ try {
1617
+ await this.io.timeout(5000).to(`user:${userId}`).emitWithAck(event, payload);
1618
+ } catch (error) {
1619
+ const socketError = SocketError.fromUnknown(error);
1620
+
1621
+ // Логирование
1622
+ this.logger.error(`Ошибка отправки события: ${socketError.message}`);
1623
+
1624
+ // Сохранение в Redis
1625
+ await this.redisService.hSet(REDIS_H_KEYS.SOCKET_ERROR, userId, socketError.message);
1626
+
1627
+ // Опционально: отправка на фронт
1628
+ await this.io.to(`user:${userId}`).emit(SOCKET_EVENTS.ERROR, {
1629
+ status: "error",
1630
+ message: socketError.message,
1631
+ });
1632
+
1633
+ throw socketError;
1634
+ }
1635
+ }
1636
+ }
1637
+ ```
1638
+
1639
+ ---
1640
+
1641
+ ## ✅ Best Practices
1642
+
1643
+ ### 1. Не используйте catch блоки в контроллерах
1644
+
1645
+ ```typescript
1646
+ // ❌ ПЛОХО
1647
+ @Get("global")
1648
+ async getGlobal() {
1649
+ try {
1650
+ return await this.service.getData();
1651
+ } catch (error) {
1652
+ // Обработка ошибок через try-catch не нужна
1653
+ }
1654
+ }
1655
+
1656
+ // ✅ ХОРОШО
1657
+ @Get("global")
1658
+ async getGlobal() {
1659
+ // Глобальный фильтр все обработает
1660
+ return await this.service.getData();
1661
+ }
1662
+ ```
1663
+
1664
+ ### 2. Используйте catch блоки в сервисах только для логирования
1665
+
1666
+ ```typescript
1667
+ // ✅ ХОРОШО - дополнительное логирование
1668
+ async getData() {
1669
+ try {
1670
+ return await this.externalService.call();
1671
+ } catch (error) {
1672
+ this.logger.error(`Дополнительное логирование: ${error}`);
1673
+ // Пробрасываем дальше - фильтр преобразует
1674
+ throw error;
1675
+ }
1676
+ }
1677
+ ```
1678
+
1679
+ ### 3. Отправляйте ошибки на фронт через Socket.io
1680
+
1681
+ ```typescript
1682
+ // ✅ ХОРОШО - отправка ошибки на фронт
1683
+ try {
1684
+ await this.processData();
1685
+ } catch (error) {
1686
+ await this.socketGateway.publish(
1687
+ userId,
1688
+ SOCKET_EVENTS.ERROR,
1689
+ {
1690
+ status: "error",
1691
+ message: error.message,
1692
+ },
1693
+ );
1694
+ }
1695
+ ```
1696
+
1697
+ ### 4. Не преобразуйте ошибки вручную в контроллерах
1698
+
1699
+ ```typescript
1700
+ // ❌ ПЛОХО
1701
+ @Get("global")
1702
+ async getGlobal() {
1703
+ try {
1704
+ return await this.service.getData();
1705
+ } catch (error) {
1706
+ const httpError = HttpError.fromUnknown(error);
1707
+ throw httpError;
1708
+ }
1709
+ }
1710
+
1711
+ // ✅ ХОРОШО - фильтр сделает это автоматически
1712
+ @Get("global")
1713
+ async getGlobal() {
1714
+ return await this.service.getData();
1715
+ }
1716
+ ```
1717
+
1718
+ ### 5. Используйте правильный тип ошибки для контекста
1719
+
1720
+ ```typescript
1721
+ // HTTP контекст → HttpError (автоматически через UnifiedExceptionFilter)
1722
+ // RPC контекст → RpcError (автоматически через UnifiedExceptionFilter)
1723
+ // Socket контекст → SocketError (вручную в SocketGateway.publish())
1724
+ ```
1725
+
1726
+ ---
1727
+
1728
+ ## 🔍 Обработка ошибок WebSocket
1729
+
1730
+ ### Типы ошибок WebSocket
1731
+
1732
+ 1. **Ошибки отправки событий** - обрабатываются через `SocketError` в `SocketGateway.publish()`
1733
+ 2. **Ошибки подключения** - обрабатываются автоматически Socket.io (событие `disconnect`)
1734
+ 3. **Внутренние ошибки сервера** - логируются, опционально отправляются на фронт через событие `ERROR`
1735
+
1736
+ ### Отправка ошибок на фронт
1737
+
1738
+ ```typescript
1739
+ // В сервисе при возникновении ошибки
1740
+ await this.socketGateway.publish(
1741
+ userId,
1742
+ SOCKET_EVENTS.ERROR,
1743
+ {
1744
+ status: "error",
1745
+ message: "Произошла ошибка при обработке данных",
1746
+ },
1747
+ );
1748
+ ```
1749
+
1750
+ ### Обработка на фронтенде
1751
+
1752
+ ```typescript
1753
+ socket.on(SOCKET_EVENTS.ERROR, (payload, ack) => {
1754
+ // Останавливаем загрузки
1755
+ setLoadingGlobal(false);
1756
+
1757
+ // Устанавливаем критическую ошибку
1758
+ useGlobalStore.setState({ criticalError: payload.message });
1759
+
1760
+ // Подтверждаем получение
1761
+ ack({ status: "received", ts: Date.now() });
1762
+ });
1763
+ ```
1764
+
1765
+ ### Внутренние ошибки Socket.io
1766
+
1767
+ Внутренние ошибки (подключение/отключение) обрабатываются автоматически:
1768
+
1769
+ - **Ошибка подключения** → Socket.io разрывает соединение, фронт получает событие `disconnect`
1770
+ - **Ошибка отключения** → Socket.io очищает соединение, фронт получает событие `disconnect`
1771
+ - **Таймаут соединения** → Socket.io автоматически переподключается, фронт получает событие `reconnect`
1772
+
1773
+ ---
1774
+
1775
+ ## 🧪 Тестирование
1776
+
1777
+ Пакет имеет высокое покрытие тестами (>95% для веток, 100% для statements и функций).
1778
+
1779
+ ```bash
1780
+ # Запуск тестов
1781
+ pnpm test
1782
+
1783
+ # Запуск тестов с покрытием
1784
+ pnpm test:coverage
1785
+ ```
1786
+
1787
+ **Покрытие тестами:**
1788
+ - Statements: 100%
1789
+ - Branches: 95.45%
1790
+ - Functions: 100%
1791
+ - Lines: 100%
1792
+
1793
+ **Тестовые сценарии:**
1794
+ - Все классы ошибок (HttpError, RpcError, SocketError, NestCommonError)
1795
+ - Глобальные фильтры (UnifiedExceptionFilter, HttpExceptionFilter, RpcExceptionFilter, WebSocketExceptionHandler)
1796
+ - Перехватчики (UnifiedInterceptor, HttpLoggingInterceptor, RpcLoggingInterceptor, WebSocketLoggingInterceptor, ResponseInterceptor, SerializeInterceptor, CompressionInterceptor, RequestIdResponseInterceptor)
1797
+ - Пайпы валидации (HttpValidationPipe, RpcValidationPipe, FileValidationPipe, QueryValidationPipe, HeaderValidationPipe)
1798
+ - Guards (JwtAuthGuard, ApiKeyGuard, RolesGuard, PermissionsGuard, RateLimitGuard, WebSocketAuthGuard)
1799
+ - Декораторы (Public, Roles, Permissions, ApiKey, Serialize)
1800
+ - Базовые классы (BaseController)
1801
+ - Утилиты (validateEnv, getUserFromContext, getIpFromContext, getUserAgentFromContext, getRequestIdFromContext, createCorsOptions, createCompressionOptions, createVersioningOptions, validateFile, getFileExtension, formatFileSize, CircuitBreakerService, getServicePath)
1802
+ - Преобразование ошибок между контекстами
1803
+ - Обработка граничных случаев и различных типов ошибок
1804
+ - Логирование HTTP, RPC и WebSocket запросов с метриками времени выполнения
1805
+ - Валидация файлов, query параметров и заголовков
1806
+ - Авторизация и аутентификация через guards
1807
+ - Rate limiting и circuit breaker паттерны
1808
+
1809
+ ## 📚 Дополнительные ресурсы
1810
+
1811
+ - [NestJS Exception Filters](https://docs.nestjs.com/exception-filters)
1812
+ - [NestJS Microservices](https://docs.nestjs.com/microservices/basics)
1813
+ - [Socket.io Error Handling](https://socket.io/docs/v4/error-handling/)
1814
+
1815
+ ## 📦 Установка
1816
+
1817
+ ```bash
1818
+ pnpm add @makebelieve21213-packages/nest-common
1819
+ ```
1820
+
1821
+ Или добавьте в `package.json` вашего микросервиса:
1822
+ ```json
1823
+ {
1824
+ "dependencies": {
1825
+ "@makebelieve21213-packages/nest-common": "workspace:*"
1826
+ }
1827
+ }
1828
+ ```
1829
+
1830
+ ## 🏗️ Разработка
1831
+
1832
+ ### Технический стек
1833
+ - **TypeScript 5.7+** - строгая типизация
1834
+ - **ESM модули** - современный стандарт модулей JavaScript
1835
+ - **NestJS 11.x** - фреймворк для микросервисов
1836
+ - **Jest** - тестирование
1837
+
1838
+ ### Процесс сборки
1839
+ Пакет использует многоэтапную сборку для корректной работы ESM:
1840
+ 1. **TypeScript компиляция** (`tsc --build`) - компиляция TypeScript в JavaScript
1841
+ 2. **Замена алиасов** (`tsc-alias`) - замена путей `src/*` на относительные
1842
+ 3. **Исправление ESM** (`tsc-esm-fix`) - добавление `.js` расширений к импортам
1843
+
1844
+ ```bash
1845
+ # Установка зависимостей
1846
+ pnpm install
1847
+
1848
+ # Сборка
1849
+ pnpm build
1850
+
1851
+ # Запуск тестов
1852
+ pnpm test
1853
+
1854
+ # Запуск тестов с покрытием
1855
+ pnpm test:coverage
1856
+
1857
+ # Линтер
1858
+ pnpm lint
1859
+ pnpm lint:fix
1860
+
1861
+ # Форматирование
1862
+ pnpm format
1863
+ pnpm format:fix
1864
+ ```
1865
+
1866
+ ### Git Hooks (Husky)
1867
+
1868
+ Пакет использует Husky для автоматической проверки кода:
1869
+
1870
+ - **pre-commit**: Автоматически исправляет линтер и форматирование перед коммитом
1871
+ - **pre-push**: Запускает тесты с проверкой покрытия перед push
1872
+
1873
+ ## 🐳 Развертывание в Docker
1874
+
1875
+ ### Сборка образа
1876
+
1877
+ Соберите Docker образ из корня проекта:
1878
+
1879
+ ```bash
1880
+ docker build -t nest-common-package:latest .
1881
+ ```
1882
+
1883
+ ### Запуск контейнера
1884
+
1885
+ ```bash
1886
+ docker run -d \
1887
+ --name nest-common-package \
1888
+ nest-common-package:latest
1889
+ ```
1890
+
1891
+ ## Совместимость
1892
+
1893
+ - **Node.js**: >=22.11.0
1894
+ - **pnpm**: >=10.18.0
1895
+ - **@nestjs/common**: ^11.1.6
1896
+ - **@nestjs/microservices**: ^11.1.3
1897
+ - **rxjs**: ^7.8.2
1898
+
1899
+ ## 📝 Лицензия
1900
+
1901
+ MIT License - см. файл [LICENSE](LICENSE) для деталей.
1902
+
1903
+ ## 🤝 Contribution
1904
+
1905
+ Pull requests приветствуются! Для крупных изменений, пожалуйста, сначала откройте issue для обсуждения.