@koalarx/nest 1.19.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/package.json +5 -37
  3. package/src/core/backgroud-services/cron-service/cron-job.handler.base.ts +66 -0
  4. package/src/core/backgroud-services/cron-service/cron-job.handler.spec.ts +38 -0
  5. package/src/core/backgroud-services/event-service/event-class.ts +5 -0
  6. package/src/core/backgroud-services/event-service/event-handler.base.ts +17 -0
  7. package/src/core/backgroud-services/event-service/event-is-trigger.ts +3 -0
  8. package/src/core/backgroud-services/event-service/event-job.ts +28 -0
  9. package/src/core/backgroud-services/event-service/event-queue.spec.ts +47 -0
  10. package/src/core/backgroud-services/event-service/event-queue.ts +107 -0
  11. package/src/core/constants/query-params.ts +7 -0
  12. package/src/core/controllers/base.controller.ts +9 -0
  13. package/src/core/controllers/controller.decorator.ts +10 -0
  14. package/src/core/controllers/created-registre-response.base.ts +17 -0
  15. package/src/core/controllers/list-response.base.ts +8 -0
  16. package/src/core/controllers/pagination.request.ts +41 -0
  17. package/src/core/controllers/router-config.base.ts +14 -0
  18. package/src/core/controllers/schemas/boolean.schema.ts +10 -0
  19. package/src/core/controllers/schemas/document-number.schema.ts +23 -0
  20. package/src/core/controllers/schemas/email.schema.ts +13 -0
  21. package/src/core/controllers/schemas/list-query.schema.ts +17 -0
  22. package/src/core/controllers/schemas/native-enum.schema.ts +34 -0
  23. package/src/core/controllers/schemas/set-mask-document-number.schema.ts +13 -0
  24. package/src/core/database/entity.base.ts +95 -0
  25. package/src/core/database/entity.decorator.spec.ts +71 -0
  26. package/src/core/database/entity.decorator.ts +39 -0
  27. package/src/core/database/prisma-client-with-custom-transaction.interface.ts +13 -0
  28. package/src/core/database/prisma-resolver.ts +99 -0
  29. package/src/core/database/prisma-transactional-client.ts +43 -0
  30. package/src/core/database/prisma.service.ts +136 -0
  31. package/src/core/database/repository.base.ts +548 -0
  32. package/src/core/dtos/pagination.dto.ts +35 -0
  33. package/src/core/errors/bad-request.error.ts +8 -0
  34. package/src/core/errors/conflict.error.ts +7 -0
  35. package/src/core/errors/error.base.ts +5 -0
  36. package/src/core/errors/no-content.error.ts +8 -0
  37. package/src/core/errors/not-allowed.error.ts +8 -0
  38. package/src/core/errors/resource-not-found.error.ts +8 -0
  39. package/{core/errors/use-case-error.d.ts → src/core/errors/use-case-error.ts} +1 -1
  40. package/src/core/errors/user-already-exist.error.ts +7 -0
  41. package/src/core/errors/wrong-credentials.error.ts +7 -0
  42. package/src/core/health-check/health-check.controller.ts +13 -0
  43. package/src/core/health-check/health-check.module.ts +7 -0
  44. package/src/core/index.ts +56 -0
  45. package/src/core/koala-app.ts +379 -0
  46. package/src/core/koala-global-vars.ts +8 -0
  47. package/src/core/koala-nest-database.module.ts +65 -0
  48. package/src/core/koala-nest-http.module.ts +44 -0
  49. package/src/core/koala-nest.module.ts +67 -0
  50. package/src/core/mapping/auto-mapping-class-context.ts +28 -0
  51. package/src/core/mapping/auto-mapping-context.ts +26 -0
  52. package/src/core/mapping/auto-mapping-list.ts +154 -0
  53. package/src/core/mapping/auto-mapping-profile.ts +3 -0
  54. package/src/core/mapping/auto-mapping.decorator.ts +54 -0
  55. package/src/core/mapping/auto-mapping.module.ts +17 -0
  56. package/src/core/mapping/auto-mapping.service.ts +187 -0
  57. package/src/core/mapping/create-map.ts +11 -0
  58. package/src/core/mapping/for-member.ts +16 -0
  59. package/src/core/request-overflow/request-handler.base.ts +8 -0
  60. package/src/core/request-overflow/request-result.spec.ts +23 -0
  61. package/src/core/request-overflow/request-result.ts +41 -0
  62. package/src/core/request-overflow/request-validator.base.ts +33 -0
  63. package/src/core/security/strategies/api-key.strategy.ts +45 -0
  64. package/src/core/utils/assing-object.ts +9 -0
  65. package/src/core/utils/env.config.ts +17 -0
  66. package/src/core/utils/filter-request-params.ts +23 -0
  67. package/src/core/utils/find-on-list.ts +18 -0
  68. package/src/core/utils/get-type-by-prop.ts +9 -0
  69. package/src/core/utils/instanciate-class-with-dependencies-injection.ts +12 -0
  70. package/src/core/utils/interfaces/icomparable.ts +6 -0
  71. package/src/core/utils/list.spec.ts +81 -0
  72. package/src/core/utils/list.ts +223 -0
  73. package/src/core/utils/promise-all.ts +24 -0
  74. package/src/core/utils/set-mask-document-number.ts +13 -0
  75. package/src/core/validators/file-validator.ts +113 -0
  76. package/src/decorators/api-exclude-endpoint-diff-develop.decorator.ts +15 -0
  77. package/src/decorators/api-property-enum.decorator.ts +58 -0
  78. package/src/decorators/api-property-only-develop.decorator.ts +6 -0
  79. package/src/decorators/cookies.decorator.ts +8 -0
  80. package/src/decorators/is-public.decorator.ts +5 -0
  81. package/src/decorators/upload.decorator.ts +31 -0
  82. package/src/env/env.module.ts +8 -0
  83. package/src/env/env.service.ts +12 -0
  84. package/src/env/env.ts +14 -0
  85. package/src/filters/domain-errors.filter.ts +97 -0
  86. package/src/filters/global-exception.filter.ts +60 -0
  87. package/src/filters/prisma-validation-exception.filter.ts +73 -0
  88. package/src/filters/zod-errors.filter.ts +48 -0
  89. package/src/services/logging/ilogging.service.ts +17 -0
  90. package/src/services/logging/logging.service.ts +10 -0
  91. package/src/services/redis/iredis.service.ts +11 -0
  92. package/src/services/redis/redis.service.ts +70 -0
  93. package/src/services/redlock/ired-lock.service.ts +4 -0
  94. package/src/services/redlock/red-lock.service.ts +36 -0
  95. package/src/test/koala-app-test-dependencies.ts +15 -0
  96. package/src/test/koala-app-test.ts +103 -0
  97. package/src/test/repositories/in-memory-base.repository.ts +90 -0
  98. package/src/test/services/fake-logging.service.ts +7 -0
  99. package/src/test/services/fake-red-lock.service.ts +11 -0
  100. package/src/test/utils/create-e2e-database.ts +55 -0
  101. package/src/test/utils/drop-e2e-database.ts +36 -0
  102. package/src/test/utils/wait-for.ts +31 -0
  103. package/tsconfig.lib.json +11 -0
  104. package/LICENSE +0 -21
  105. package/README.md +0 -499
  106. package/core/backgroud-services/cron-service/cron-job.handler.base.d.ts +0 -16
  107. package/core/backgroud-services/cron-service/cron-job.handler.base.js +0 -49
  108. package/core/backgroud-services/event-service/event-class.d.ts +0 -5
  109. package/core/backgroud-services/event-service/event-class.js +0 -11
  110. package/core/backgroud-services/event-service/event-handler.base.d.ts +0 -8
  111. package/core/backgroud-services/event-service/event-handler.base.js +0 -14
  112. package/core/backgroud-services/event-service/event-is-trigger.d.ts +0 -3
  113. package/core/backgroud-services/event-service/event-is-trigger.js +0 -7
  114. package/core/backgroud-services/event-service/event-job.d.ts +0 -13
  115. package/core/backgroud-services/event-service/event-job.js +0 -21
  116. package/core/backgroud-services/event-service/event-queue.d.ts +0 -17
  117. package/core/backgroud-services/event-service/event-queue.js +0 -62
  118. package/core/constants/query-params.d.ts +0 -6
  119. package/core/constants/query-params.js +0 -8
  120. package/core/controllers/base.controller.d.ts +0 -4
  121. package/core/controllers/base.controller.js +0 -6
  122. package/core/controllers/controller.decorator.d.ts +0 -2
  123. package/core/controllers/controller.decorator.js +0 -11
  124. package/core/controllers/created-registre-response.base.d.ts +0 -10
  125. package/core/controllers/created-registre-response.base.js +0 -35
  126. package/core/controllers/list-response.base.d.ts +0 -4
  127. package/core/controllers/list-response.base.js +0 -21
  128. package/core/controllers/pagination.request.d.ts +0 -10
  129. package/core/controllers/pagination.request.js +0 -56
  130. package/core/controllers/router-config.base.d.ts +0 -7
  131. package/core/controllers/router-config.base.js +0 -18
  132. package/core/controllers/schemas/boolean.schema.d.ts +0 -2
  133. package/core/controllers/schemas/boolean.schema.js +0 -12
  134. package/core/controllers/schemas/document-number.schema.d.ts +0 -1
  135. package/core/controllers/schemas/document-number.schema.js +0 -26
  136. package/core/controllers/schemas/email.schema.d.ts +0 -1
  137. package/core/controllers/schemas/email.schema.js +0 -13
  138. package/core/controllers/schemas/list-query.schema.d.ts +0 -17
  139. package/core/controllers/schemas/list-query.schema.js +0 -19
  140. package/core/controllers/schemas/native-enum.schema.d.ts +0 -7
  141. package/core/controllers/schemas/native-enum.schema.js +0 -28
  142. package/core/controllers/schemas/set-mask-document-number.schema.d.ts +0 -1
  143. package/core/controllers/schemas/set-mask-document-number.schema.js +0 -13
  144. package/core/database/entity.base.d.ts +0 -20
  145. package/core/database/entity.base.js +0 -71
  146. package/core/database/entity.decorator.d.ts +0 -13
  147. package/core/database/entity.decorator.js +0 -23
  148. package/core/database/prisma-client-with-custom-transaction.interface.d.ts +0 -8
  149. package/core/database/prisma-client-with-custom-transaction.interface.js +0 -2
  150. package/core/database/prisma-resolver.d.ts +0 -2
  151. package/core/database/prisma-resolver.js +0 -74
  152. package/core/database/prisma-transactional-client.d.ts +0 -11
  153. package/core/database/prisma-transactional-client.js +0 -25
  154. package/core/database/prisma.service.d.ts +0 -24
  155. package/core/database/prisma.service.js +0 -104
  156. package/core/database/repository.base.d.ts +0 -44
  157. package/core/database/repository.base.js +0 -360
  158. package/core/dtos/pagination.dto.d.ts +0 -9
  159. package/core/dtos/pagination.dto.js +0 -49
  160. package/core/errors/bad-request.error.d.ts +0 -5
  161. package/core/errors/bad-request.error.js +0 -10
  162. package/core/errors/conflict.error.d.ts +0 -4
  163. package/core/errors/conflict.error.js +0 -10
  164. package/core/errors/error.base.d.ts +0 -4
  165. package/core/errors/error.base.js +0 -11
  166. package/core/errors/no-content.error.d.ts +0 -5
  167. package/core/errors/no-content.error.js +0 -10
  168. package/core/errors/not-allowed.error.d.ts +0 -5
  169. package/core/errors/not-allowed.error.js +0 -10
  170. package/core/errors/resource-not-found.error.d.ts +0 -5
  171. package/core/errors/resource-not-found.error.js +0 -10
  172. package/core/errors/use-case-error.js +0 -2
  173. package/core/errors/user-already-exist.error.d.ts +0 -4
  174. package/core/errors/user-already-exist.error.js +0 -10
  175. package/core/errors/wrong-credentials.error.d.ts +0 -4
  176. package/core/errors/wrong-credentials.error.js +0 -10
  177. package/core/health-check/health-check.controller.d.ts +0 -5
  178. package/core/health-check/health-check.controller.js +0 -32
  179. package/core/health-check/health-check.module.d.ts +0 -2
  180. package/core/health-check/health-check.module.js +0 -19
  181. package/core/index.d.ts +0 -18
  182. package/core/index.js +0 -7
  183. package/core/koala-app.d.ts +0 -64
  184. package/core/koala-app.js +0 -252
  185. package/core/koala-global-vars.d.ts +0 -7
  186. package/core/koala-global-vars.js +0 -9
  187. package/core/koala-nest-database.module.d.ts +0 -16
  188. package/core/koala-nest-database.module.js +0 -52
  189. package/core/koala-nest-http.module.d.ts +0 -13
  190. package/core/koala-nest-http.module.js +0 -37
  191. package/core/koala-nest.module.d.ts +0 -17
  192. package/core/koala-nest.module.js +0 -66
  193. package/core/mapping/auto-mapping-class-context.d.ts +0 -16
  194. package/core/mapping/auto-mapping-class-context.js +0 -18
  195. package/core/mapping/auto-mapping-context.d.ts +0 -11
  196. package/core/mapping/auto-mapping-context.js +0 -24
  197. package/core/mapping/auto-mapping-list.d.ts +0 -27
  198. package/core/mapping/auto-mapping-list.js +0 -94
  199. package/core/mapping/auto-mapping-profile.d.ts +0 -3
  200. package/core/mapping/auto-mapping-profile.js +0 -6
  201. package/core/mapping/auto-mapping.decorator.d.ts +0 -9
  202. package/core/mapping/auto-mapping.decorator.js +0 -27
  203. package/core/mapping/auto-mapping.module.d.ts +0 -5
  204. package/core/mapping/auto-mapping.module.js +0 -29
  205. package/core/mapping/auto-mapping.service.d.ts +0 -14
  206. package/core/mapping/auto-mapping.service.js +0 -140
  207. package/core/mapping/create-map.d.ts +0 -3
  208. package/core/mapping/create-map.js +0 -7
  209. package/core/mapping/for-member.d.ts +0 -5
  210. package/core/mapping/for-member.js +0 -8
  211. package/core/request-overflow/request-handler.base.d.ts +0 -4
  212. package/core/request-overflow/request-handler.base.js +0 -6
  213. package/core/request-overflow/request-result.d.ts +0 -15
  214. package/core/request-overflow/request-result.js +0 -37
  215. package/core/request-overflow/request-validator.base.d.ts +0 -7
  216. package/core/request-overflow/request-validator.base.js +0 -26
  217. package/core/security/strategies/api-key.strategy.d.ts +0 -16
  218. package/core/security/strategies/api-key.strategy.js +0 -31
  219. package/core/utils/assing-object.d.ts +0 -5
  220. package/core/utils/assing-object.js +0 -6
  221. package/core/utils/env.config.d.ts +0 -6
  222. package/core/utils/env.config.js +0 -18
  223. package/core/utils/filter-request-params.d.ts +0 -13
  224. package/core/utils/filter-request-params.js +0 -22
  225. package/core/utils/find-on-list.d.ts +0 -2
  226. package/core/utils/find-on-list.js +0 -13
  227. package/core/utils/get-type-by-prop.d.ts +0 -2
  228. package/core/utils/get-type-by-prop.js +0 -11
  229. package/core/utils/instanciate-class-with-dependencies-injection.d.ts +0 -2
  230. package/core/utils/instanciate-class-with-dependencies-injection.js +0 -10
  231. package/core/utils/interfaces/icomparable.d.ts +0 -5
  232. package/core/utils/interfaces/icomparable.js +0 -6
  233. package/core/utils/list.d.ts +0 -39
  234. package/core/utils/list.js +0 -168
  235. package/core/utils/promise-all.d.ts +0 -7
  236. package/core/utils/promise-all.js +0 -19
  237. package/core/utils/set-mask-document-number.d.ts +0 -1
  238. package/core/utils/set-mask-document-number.js +0 -13
  239. package/core/validators/file-validator.d.ts +0 -27
  240. package/core/validators/file-validator.js +0 -94
  241. package/decorators/api-exclude-endpoint-diff-develop.decorator.d.ts +0 -1
  242. package/decorators/api-exclude-endpoint-diff-develop.decorator.js +0 -9
  243. package/decorators/api-property-enum.decorator.d.ts +0 -8
  244. package/decorators/api-property-enum.decorator.js +0 -21
  245. package/decorators/api-property-only-develop.decorator.d.ts +0 -2
  246. package/decorators/api-property-only-develop.decorator.js +0 -9
  247. package/decorators/cookies.decorator.d.ts +0 -1
  248. package/decorators/cookies.decorator.js +0 -8
  249. package/decorators/is-public.decorator.d.ts +0 -2
  250. package/decorators/is-public.decorator.js +0 -7
  251. package/decorators/upload.decorator.d.ts +0 -1
  252. package/decorators/upload.decorator.js +0 -18
  253. package/docs/00-cli-reference.md +0 -201
  254. package/docs/01-guia-instalacao.md +0 -113
  255. package/docs/02-configuracao-inicial.md +0 -176
  256. package/docs/04-tratamento-erros.md +0 -303
  257. package/docs/05-features-avancadas.md +0 -969
  258. package/docs/06-decoradores.md +0 -220
  259. package/docs/07-guia-bun.md +0 -176
  260. package/docs/08-prisma-client.md +0 -487
  261. package/docs/09-mcp-vscode-extension.md +0 -437
  262. package/docs/EXAMPLE.md +0 -1671
  263. package/docs/README.md +0 -59
  264. package/env/env.d.ts +0 -25
  265. package/env/env.js +0 -14
  266. package/env/env.module.d.ts +0 -2
  267. package/env/env.module.js +0 -20
  268. package/env/env.service.d.ts +0 -7
  269. package/env/env.service.js +0 -28
  270. package/filters/domain-errors.filter.d.ts +0 -18
  271. package/filters/domain-errors.filter.js +0 -92
  272. package/filters/global-exception.filter.d.ts +0 -8
  273. package/filters/global-exception.filter.js +0 -68
  274. package/filters/prisma-validation-exception.filter.d.ts +0 -10
  275. package/filters/prisma-validation-exception.filter.js +0 -82
  276. package/filters/zod-errors.filter.d.ts +0 -9
  277. package/filters/zod-errors.filter.js +0 -60
  278. package/mcp-server/mcp.json.example +0 -27
  279. package/mcp-server/server.d.ts +0 -2
  280. package/mcp-server/server.d.ts.map +0 -1
  281. package/mcp-server/server.js +0 -248
  282. package/mcp-server/server.js.map +0 -1
  283. package/services/logging/ilogging.service.d.ts +0 -16
  284. package/services/logging/ilogging.service.js +0 -6
  285. package/services/logging/logging.service.d.ts +0 -4
  286. package/services/logging/logging.service.js +0 -20
  287. package/services/redis/iredis.service.d.ts +0 -6
  288. package/services/redis/iredis.service.js +0 -6
  289. package/services/redis/redis.service.d.ts +0 -14
  290. package/services/redis/redis.service.js +0 -65
  291. package/services/redlock/ired-lock.service.d.ts +0 -4
  292. package/services/redlock/ired-lock.service.js +0 -6
  293. package/services/redlock/red-lock.service.d.ts +0 -9
  294. package/services/redlock/red-lock.service.js +0 -46
  295. package/test/koala-app-test-dependencies.d.ts +0 -10
  296. package/test/koala-app-test-dependencies.js +0 -13
  297. package/test/koala-app-test.d.ts +0 -22
  298. package/test/koala-app-test.js +0 -77
  299. package/test/repositories/in-memory-base.repository.d.ts +0 -17
  300. package/test/repositories/in-memory-base.repository.js +0 -65
  301. package/test/services/fake-logging.service.d.ts +0 -4
  302. package/test/services/fake-logging.service.js +0 -9
  303. package/test/services/fake-red-lock.service.d.ts +0 -5
  304. package/test/services/fake-red-lock.service.js +0 -11
  305. package/test/utils/create-e2e-database.d.ts +0 -2
  306. package/test/utils/create-e2e-database.js +0 -47
  307. package/test/utils/drop-e2e-database.d.ts +0 -2
  308. package/test/utils/drop-e2e-database.js +0 -33
  309. package/test/utils/wait-for.d.ts +0 -1
  310. package/test/utils/wait-for.js +0 -21
  311. package/tsconfig.lib.tsbuildinfo +0 -1
@@ -1,969 +0,0 @@
1
- # Features Avançadas
2
-
3
- ## 1. Cron Jobs (Tarefas Agendadas)
4
-
5
- Execute tarefas em intervalos regulares com sincronização via Redis/RedLock.
6
-
7
- ### Criar um Cron Job
8
-
9
- ```typescript
10
- // src/application/person/create-person-job/create-person-job.ts
11
- import { Injectable } from '@nestjs/common'
12
- import {
13
- CronJobHandlerBase,
14
- CronJobResponse,
15
- CronJobSettings,
16
- } from '@koalarx/nest/core/backgroud-services/cron-service/cron-job.handler.base'
17
- import { EventQueue } from '@koalarx/nest/core/backgroud-services/event-service/event-queue'
18
- import { ok } from '@koalarx/nest/core/request-overflow/request-result'
19
- import { ILoggingService } from '@koalarx/nest/services/logging/ilogging.service'
20
- import { IRedLockService } from '@koalarx/nest/services/redlock/ired-lock.service'
21
- import { Injectable } from '@nestjs/common'
22
- import { CreatePersonHandler } from '../create/create-person.handler'
23
- import { InactivePersonEvent } from '../events/inactive-person/inactive-person-event'
24
- import { IPersonRepository } from '@/domain/repositories/iperson.repository'
25
-
26
- @Injectable()
27
- export class CreatePersonJob extends CronJobHandlerBase {
28
- constructor(
29
- redlockService: IRedLockService,
30
- loggingService: ILoggingService,
31
- private readonly createPerson: CreatePersonHandler,
32
- private readonly repository: IPersonRepository,
33
- ) {
34
- super(redlockService, loggingService)
35
- }
36
-
37
- // Configurações do job (intervalo de execução)
38
- protected async settings(): Promise<CronJobSettings> {
39
- return {
40
- isActive: true,
41
- timeInMinutes: 1, // Executa a cada 1 minuto (use 1440 para 24 horas)
42
- }
43
- }
44
-
45
- // Lógica principal do job
46
- protected async run(): Promise<CronJobResponse> {
47
- const result = await this.createPerson.handle({
48
- name: 'John Doe',
49
- phones: [{ phone: '22999999999' }],
50
- address: { address: 'Street 1' },
51
- })
52
-
53
- if (result.isOk()) {
54
- const person = await this.repository.read(result.value.id)
55
-
56
- if (person) {
57
- // Emitir eventos para handlers processar
58
- const jobs = new PersonEventJob()
59
- jobs.addEvent(new InactivePersonEvent())
60
- EventQueue.dispatchEventsForAggregate(jobs._id)
61
- }
62
-
63
- console.log('Person created with id:', result.value.id)
64
- } else {
65
- console.error('Error creating person:', result.value)
66
- }
67
-
68
- // Sempre retorna ok(null) - erros são logados, não falham o job
69
- return ok(null)
70
- }
71
- }
72
- ```
73
-
74
- ### Registrar Cron Job
75
-
76
- **1. No `AppModule`, passe os jobs via `cronJobs`:**
77
-
78
- ```typescript
79
- // src/host/app.module.ts
80
- import { CreatePersonJob } from '@/application/person/create-person-job/create-person-job'
81
- import { DeleteInactiveJob } from '@/application/person/delete-inative-job/delete-inactive-job'
82
- import { env } from '@/core/env'
83
- import { KoalaNestModule } from '@koalarx/nest/core/koala-nest.module'
84
- import { Module } from '@nestjs/common'
85
- import { PersonModule } from './controllers/person/person.module'
86
-
87
- @Module({
88
- imports: [
89
- KoalaNestModule.register({
90
- env,
91
- controllers: [PersonModule],
92
- cronJobs: [DeleteInactiveJob, CreatePersonJob], // Registrar jobs
93
- }),
94
- ],
95
- })
96
- export class AppModule {}
97
- ```
98
-
99
- **2. No arquivo `main.ts`, adicione o job usando `.addCronJob()`:**
100
-
101
- ```typescript
102
- // src/main.ts
103
- import { CreatePersonJob } from '@/application/person/create-person-job/create-person-job'
104
- import { DeleteInactiveJob } from '@/application/person/delete-inative-job/delete-inactive-job'
105
-
106
- async function bootstrap() {
107
- const app = await NestFactory.create(AppModule)
108
-
109
- await new KoalaApp(app)
110
- .useDoc({
111
- ui: 'scalar',
112
- endpoint: '/doc',
113
- title: 'API de Demonstração',
114
- version: '1.0',
115
- })
116
- .addCronJob(CreatePersonJob) // Registrar primeiro job
117
- .addCronJob(DeleteInactiveJob) // Registrar segundo job
118
- .enableCors()
119
- .buildAndServe()
120
- }
121
-
122
- bootstrap()
123
- ```
124
-
125
- **Nota sobre RedLock:** Os Cron Jobs utilizam `IRedLockService` (que depende de Redis) para garantir que apenas uma instância execute o job simultaneamente em ambientes distribuídos. Certifique-se de configurar a `REDIS_URL` no arquivo `.env` para ambientes com múltiplas instâncias.
126
-
127
- ## 2. Event Jobs (Handlers de Eventos)
128
-
129
- Processe eventos de forma assincronizada usando o padrão EventJob com handlers especializados.
130
-
131
- ### Criar uma Classe de Evento
132
-
133
- Eventos devem estender `EventClass`:
134
-
135
- ```typescript
136
- // src/application/person/events/inactive-person/inactive-person-event.ts
137
- import { EventClass } from '@koalarx/nest/core/backgroud-services/event-service/event-class'
138
-
139
- export class InactivePersonEvent extends EventClass {}
140
- ```
141
-
142
- ### Criar um Event Handler
143
-
144
- Handler estende `EventHandlerBase` e processa eventos:
145
-
146
- ```typescript
147
- // src/application/person/events/inactive-person/inactive-person-handler.ts
148
- import { ReadManyPersonDto } from '@/domain/dtos/read-many-person.dto'
149
- import { IPersonRepository } from '@/domain/repositories/iperson.repository'
150
- import { EventHandlerBase } from '@koalarx/nest/core/backgroud-services/event-service/event-handler.base'
151
- import { Injectable } from '@nestjs/common'
152
- import { InactivePersonEvent } from './inactive-person-event'
153
-
154
- @Injectable()
155
- export class InactivePersonHandler extends EventHandlerBase {
156
- constructor(private readonly repository: IPersonRepository) {
157
- super(InactivePersonEvent) // Especifica qual evento processa
158
- }
159
-
160
- async handleEvent(): Promise<void> {
161
- // handleEvent() é chamado quando eventos estão na fila
162
- const result = await this.repository.readMany(
163
- new ReadManyPersonDto({ active: true }),
164
- )
165
-
166
- for (const person of result.items) {
167
- person.active = false
168
- await this.repository.save(person)
169
- }
170
-
171
- console.log(
172
- 'InactivePersonHandler: Registros ativos inativados com sucesso!',
173
- )
174
- }
175
- }
176
- ```
177
-
178
- ### Criar EventJob para Agrupar Handlers
179
-
180
- A classe `EventJob` agrupa handlers relacionados a uma entidade:
181
-
182
- ```typescript
183
- // src/application/person/events/person-event-job.ts
184
- import { Person } from '@/domain/entities/person/person'
185
- import { EventHandlerBase } from '@koalarx/nest/core/backgroud-services/event-service/event-handler.base'
186
- import { EventJob } from '@koalarx/nest/core/backgroud-services/event-service/event-job'
187
- import { Type } from '@nestjs/common'
188
- import { InactivePersonHandler } from './inactive-person/inactive-person-handler'
189
-
190
- export class PersonEventJob extends EventJob<Person> {
191
- defineHandlers(): Type<EventHandlerBase>[] {
192
- return [InactivePersonHandler]
193
- }
194
- }
195
- ```
196
-
197
- ### Registrar Event Handler
198
-
199
- **1. No `AppModule`, passe os handlers via `eventJobs`:**
200
-
201
- ```typescript
202
- // src/host/app.module.ts
203
- import { PersonEventJob } from '@/application/person/events/person-event-job'
204
- import { env } from '@/core/env'
205
- import { KoalaNestModule } from '@koalarx/nest/core/koala-nest.module'
206
- import { Module } from '@nestjs/common'
207
- import { PersonModule } from './controllers/person/person.module'
208
-
209
- @Module({
210
- imports: [
211
- KoalaNestModule.register({
212
- env,
213
- controllers: [PersonModule],
214
- eventJobs: [PersonEventJob], // Registrar a EventJob
215
- }),
216
- ],
217
- })
218
- export class AppModule {}
219
- ```
220
-
221
- **2. No arquivo `main.ts`, adicione o handler usando `.addEventJob()`:**
222
-
223
- ```typescript
224
- // src/main.ts
225
- import { PersonEventJob } from '@/application/person/events/person-event-job'
226
-
227
- async function bootstrap() {
228
- const app = await NestFactory.create(AppModule)
229
-
230
- await new KoalaApp(app)
231
- .useDoc({
232
- ui: 'scalar',
233
- endpoint: '/doc',
234
- title: 'API de Demonstração',
235
- version: '1.0',
236
- })
237
- .addEventJob(PersonEventJob) // Registrar a EventJob
238
- .setAppName('example')
239
- .setInternalUserName('integration.bot')
240
- .setDbTransactionContext(DbTransactionContext)
241
- .enableCors()
242
- .buildAndServe()
243
- }
244
-
245
- bootstrap()
246
- ```
247
-
248
- **Resumo de Registro:**
249
- - Event Handlers são agrupados em uma **EventJob** e registrados em duas etapas:
250
- 1. **AppModule**: Via `eventJobs: [PersonEventJob]` em `KoalaNestModule.register()`
251
- 2. **main.ts**: Via `.addEventJob(PersonEventJob)` em `KoalaApp`
252
- - A EventJob agrupa handlers por entidade (PersonEventJob agrupa InactivePersonHandler)
253
- - Múltiplos handlers podem estar na mesma EventJob
254
-
255
- ## Fluxo de Eventos
256
-
257
- ```
258
- Cron Job executa
259
- └─ Processa lógica
260
- └─ Emite evento via EventQueue.dispatchEventsForAggregate()
261
- └─ EventJob localiza handlers
262
- └─ Event Handler processa evento
263
- └─ handleEvent() é chamado
264
- └─ Lógica de negócio executada
265
- ```
266
-
267
- ## Quando Usar Events
268
-
269
- - **Background Sync**: Use Event Handlers para processar eventos de forma assincronizada
270
- - **Async Escalável**: EventQueue é sincronizado via Redis (RedLock) em ambientes distribuídos
271
- - **Agregados**: Agrupe múltiplos handlers em uma EventJob para organizar processamento por entidade
272
-
273
- ## 3. Autenticação e Autorização
274
-
275
- A biblioteca fornece o decorador `@IsPublic()` para marcar rotas públicas. Para proteger seus endpoints com Guards do NestJS usando Passport Strategies, você implementa de acordo com suas necessidades (JWT, API Key, OAuth, etc.).
276
-
277
- > **Importante**: Guards e Strategies são implementações específicas do seu projeto. A biblioteca não fornece Guards/Strategies prontas, pois estas são muito particulares de cada aplicação.
278
-
279
- > **Onde Registrar Guards**: Use o método `.addGlobalGuard()` no builder do `KoalaApp` em `main.ts` para registrar seus guards globalmente. Veja a seção "Registrar Guards Globalmente" mais abaixo.
280
-
281
- ### Criar Estratégia JWT
282
-
283
- Aqui está um exemplo de como implementar uma estratégia customizada para validar tokens JWT:
284
-
285
- ```typescript
286
- // src/host/security/strategies/jwt.strategy.ts
287
- import { Injectable, UnauthorizedException } from '@nestjs/common'
288
- import { PassportStrategy } from '@nestjs/passport'
289
- import { Strategy } from 'passport-custom'
290
- import { jwtDecode } from 'jwt-decode'
291
- import { IUserRepository } from '@/domain/repositories/iuser.repository'
292
-
293
- export type DoneFn = (err: Error | null, user?: any) => void
294
-
295
- @Injectable()
296
- export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
297
- constructor(private readonly userRepository: IUserRepository) {
298
- super()
299
- }
300
-
301
- async validate(request: any, done: DoneFn) {
302
- const token = request.headers?.authorization?.replace('Bearer ', '')
303
-
304
- if (token) {
305
- try {
306
- const decodedToken = jwtDecode(token) as any
307
-
308
- // Validar expiração
309
- if (decodedToken.exp * 1000 < Date.now()) {
310
- done(new UnauthorizedException('Token expirado'))
311
- return
312
- }
313
-
314
- // Buscar usuário no banco
315
- const user = await this.userRepository.findByEmail(decodedToken.email)
316
-
317
- if (user) {
318
- done(null, user)
319
- } else {
320
- done(new UnauthorizedException('Usuário não encontrado'))
321
- }
322
- } catch {
323
- done(new UnauthorizedException('Token inválido'))
324
- }
325
- } else {
326
- done(new UnauthorizedException('Token não fornecido'))
327
- }
328
- }
329
- }
330
- ```
331
-
332
- ### Estratégia de Autenticação com API Key
333
-
334
- Para suportar autenticação via API Key, estenda a classe base da biblioteca:
335
-
336
- ```typescript
337
- // src/host/security/strategies/api-key.strategy.ts
338
- import { Injectable, UnauthorizedException } from '@nestjs/common'
339
- import { JwtService } from '@nestjs/jwt'
340
- import { ApiKeyStrategyBase } from '@koalarx/nest/core/security/strategies/api-key.strategy'
341
- import { Request } from 'express'
342
-
343
- export type DoneFn = (err: Error | null, user?: any) => void
344
-
345
- @Injectable()
346
- export class ApiKeyStrategy extends ApiKeyStrategyBase {
347
- constructor(private readonly jwtService: JwtService) {
348
- super({ header: 'x-api-key' })
349
- }
350
-
351
- async validate(apikey: string, done: DoneFn, request: Request) {
352
- try {
353
- // Validar API Key usando JWT com chave pública
354
- const publicKey = process.env.JWT_PUBLIC_KEY
355
- ? Buffer.from(process.env.JWT_PUBLIC_KEY, 'base64')
356
- : undefined
357
-
358
- const user = await this.jwtService.verifyAsync(apikey, {
359
- algorithms: ['RS256'],
360
- publicKey,
361
- })
362
-
363
- done(null, user)
364
- } catch {
365
- done(new UnauthorizedException('API Key inválida ou expirada'))
366
- }
367
- }
368
- }
369
- ```
370
-
371
- ### Criar Guard de Autenticação
372
-
373
- Crie um guard que suporta múltiplas estratégias (JWT e API Key):
374
-
375
- ```typescript
376
- // src/host/security/guards/auth.guard.ts
377
- import { Injectable } from '@nestjs/common'
378
- import { ExecutionContext } from '@nestjs/common'
379
- import { AuthGuard as NestAuthGuard } from '@nestjs/passport'
380
- import { Reflector } from '@nestjs/core'
381
- import { IS_PUBLIC_KEY } from '@koalarx/nest/decorators/is-public.decorator'
382
-
383
- @Injectable()
384
- export class AuthGuard extends NestAuthGuard(['jwt', 'api-key']) {
385
- constructor(public readonly reflector: Reflector) {
386
- super()
387
- }
388
-
389
- async canActivate(context: ExecutionContext): Promise<boolean> {
390
- const isPublic = this.reflector.getAllAndOverride<boolean>(
391
- IS_PUBLIC_KEY,
392
- [context.getHandler(), context.getClass()],
393
- )
394
-
395
- const request = context.switchToHttp().getRequest()
396
-
397
- // Se rota é pública e não há header de autenticação, permitir
398
- if (
399
- isPublic &&
400
- !request.headers.authorization &&
401
- !request.headers['x-api-key']
402
- ) {
403
- return true
404
- }
405
-
406
- // Aplicar estratégia JWT ou API Key
407
- const canActivate = super.canActivate(context)
408
-
409
- if (typeof canActivate === 'boolean') {
410
- return canActivate
411
- }
412
-
413
- return canActivate as Promise<boolean>
414
- }
415
- }
416
- ```
417
-
418
- ### Guard de Autorização (Perfis)
419
-
420
- Para autorização por perfil de usuário:
421
-
422
- ```typescript
423
- // src/host/security/guards/profiles.guard.ts
424
- import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'
425
- import { Reflector } from '@nestjs/core'
426
- import { UserProfileEnum } from '@/domain/entities/user/enums/user-profile.enum'
427
-
428
- @Injectable()
429
- export class ProfilesGuard implements CanActivate {
430
- constructor(private readonly reflector: Reflector) {}
431
-
432
- canActivate(context: ExecutionContext): boolean {
433
- // Obter perfis requeridos do metadata
434
- const requiredProfiles = this.reflector.get<UserProfileEnum[]>(
435
- 'profiles',
436
- context.getHandler(),
437
- )
438
-
439
- if (!requiredProfiles || requiredProfiles.length === 0) {
440
- return true
441
- }
442
-
443
- const request = context.switchToHttp().getRequest()
444
- const user = request.user
445
-
446
- // Verificar se usuário possui um dos perfis requeridos
447
- return requiredProfiles.includes(user?.profile)
448
- }
449
- }
450
- ```
451
-
452
- ### Registrar Estratégias e Guards
453
-
454
- Crie um módulo de segurança com suporte a JWT e API Key:
455
-
456
- ```typescript
457
- // src/host/security/security.module.ts
458
- import { Module } from '@nestjs/common'
459
- import { PassportModule } from '@nestjs/passport'
460
- import { JwtModule } from '@nestjs/jwt'
461
- import { JwtStrategy } from './strategies/jwt.strategy'
462
- import { ApiKeyStrategy } from './strategies/api-key.strategy'
463
- import { InfraModule } from '@/infra/infra.module'
464
-
465
- @Module({
466
- imports: [
467
- InfraModule,
468
- PassportModule,
469
- JwtModule.register({
470
- secret: process.env.JWT_SECRET,
471
- signOptions: { expiresIn: '1h' },
472
- }),
473
- ],
474
- providers: [JwtStrategy, ApiKeyStrategy],
475
- })
476
- export class SecurityModule {}
477
- ```
478
-
479
- ### Registrar Guards Globalmente
480
-
481
- A biblioteca fornece o método `.addGlobalGuard()` no builder do `KoalaApp` para registrar seus guards globalmente:
482
-
483
- ```typescript
484
- // src/host/main.ts
485
- import { AuthGuard } from './security/guards/auth.guard'
486
- import { ProfilesGuard } from './security/guards/profiles.guard'
487
-
488
- async function bootstrap() {
489
- const app = await NestFactory.create(AppModule)
490
-
491
- await new KoalaApp(app)
492
- .useDoc({...})
493
- .addGlobalGuard(AuthGuard) // Guard de autenticação (JWT + API Key)
494
- .addGlobalGuard(ProfilesGuard) // Guard de autorização
495
- .buildAndServe()
496
- }
497
- ```
498
-
499
- > **Onde Adicionar Guards**: Use `.addGlobalGuard()` no `KoalaApp` builder em `main.ts` para registrar seus guards globalmente. A ordem importa - guards são executados na ordem que são adicionados.
500
-
501
- ### Usar em Controllers
502
-
503
- ```typescript
504
- // src/host/controllers/person/person.controller.ts
505
- import { IsPublic } from '@koalarx/nest/decorators/is-public.decorator'
506
-
507
- @Controller('persons')
508
- export class PersonController {
509
- @Post('login')
510
- @IsPublic()
511
- async login(@Body() credentials: LoginDto) {
512
- // Acesso público - sem autenticação
513
- return { token: 'jwt-token' }
514
- }
515
-
516
- @Get()
517
- async list() {
518
- // Requer autenticação (JWT)
519
- return { items: [] }
520
- }
521
-
522
- @Delete(':id')
523
- async delete(@Param('id') id: number) {
524
- // Requer autenticação
525
- return { success: true }
526
- }
527
- }
528
- ```
529
-
530
- ## 4. Documentação Swagger/Scalar
531
-
532
- Configure a documentação automática da API usando Swagger ou Scalar.
533
-
534
- ### Configuração Básica
535
-
536
- No seu arquivo `main.ts`, use `.useDoc()`:
537
-
538
- ```typescript
539
- // src/host/main.ts
540
- await new KoalaApp(app)
541
- .useDoc({
542
- ui: 'scalar', // 'swagger' ou 'scalar'
543
- endpoint: '/doc',
544
- title: 'API de Demonstração',
545
- version: '1.0',
546
- })
547
- .buildAndServe()
548
- ```
549
-
550
- ### Com Servidores Adicionais
551
-
552
- ```typescript
553
- .useDoc({
554
- ui: 'scalar',
555
- endpoint: '/doc',
556
- title: 'My API',
557
- version: '1.0.0',
558
- servers: [
559
- {
560
- url: 'http://localhost:3000',
561
- description: 'Local development',
562
- },
563
- {
564
- url: 'https://api.example.com',
565
- description: 'Production',
566
- },
567
- ],
568
- })
569
- ```
570
-
571
- ### Com Autenticação Bearer
572
-
573
- ```typescript
574
- .useDoc({
575
- ui: 'scalar',
576
- endpoint: '/doc',
577
- title: 'My API',
578
- version: '1.0.0',
579
- authorizations: [
580
- {
581
- name: 'bearer',
582
- config: {
583
- type: 'http',
584
- scheme: 'bearer',
585
- },
586
- },
587
- ],
588
- })
589
- ```
590
-
591
- ## 5. CORS (Cross-Origin Requests)
592
-
593
- Habilite requisições cross-origin com um único método:
594
-
595
- ```typescript
596
- // src/host/main.ts
597
- await new KoalaApp(app)
598
- .enableCors()
599
- .buildAndServe()
600
- ```
601
-
602
- **Configuração padrão aplicada:**
603
- - `credentials: true` - Permite cookies
604
- - `origin: true` - Aceita qualquer origem
605
- - `optionsSuccessStatus: 200` - Status de sucesso para preflight
606
-
607
- ## 6. Validação com Zod
608
-
609
- Valide dados automaticamente usando Zod integrado ao `RequestValidatorBase`.
610
-
611
- ### Definir Schema Zod
612
-
613
- ```typescript
614
- // src/application/person/create/create-person.request.ts
615
- import { z } from 'zod'
616
-
617
- export const CreatePersonSchema = z.object({
618
- name: z.string().min(2).max(100),
619
- email: z.string().email(),
620
- phone: z.string().optional(),
621
- active: z.boolean().default(true),
622
- })
623
-
624
- export type CreatePersonRequest = z.infer<typeof CreatePersonSchema>
625
- ```
626
-
627
- ### Usar em Validator
628
-
629
- ```typescript
630
- // src/application/person/create/create-person.validator.ts
631
- import { Injectable } from '@nestjs/common'
632
- import { RequestValidatorBase } from '@koalarx/nest/core/request-handler/request-validator.base'
633
- import { CreatePersonSchema, CreatePersonRequest } from './create-person.request'
634
-
635
- @Injectable()
636
- export class CreatePersonValidator extends RequestValidatorBase<CreatePersonRequest> {
637
- protected get schema() {
638
- return CreatePersonSchema
639
- }
640
- }
641
- ```
642
-
643
- ### Erros de Validação
644
-
645
- Erros Zod são capturados automaticamente pelo `ZodErrorsFilter`:
646
-
647
- ```typescript
648
- // src/host/main.ts - O filter já está registrado automaticamente
649
- // Erros Zod retornam Status 400 com detalhes dos campos inválidos
650
- ```
651
-
652
- ## 7. Redis (Sincronização de Background Services)
653
-
654
- Redis é essencial para sincronizar `CronJobs` e `EventHandlers` em ambientes distribuídos usando **RedLock**.
655
-
656
- ### Como Funciona
657
-
658
- - **RedLock**: Distributed locking que garante apenas uma instância execute cada job
659
- - **Cron Jobs**: Sincronizam via RedLock para execução única por intervalo
660
- - **Event Handlers**: Usam Redis para coordenação entre instâncias
661
-
662
- ### Configurar Redis
663
-
664
- Defina em `.env`:
665
-
666
- ```env
667
- REDIS_URL=redis://localhost:6379
668
- ```
669
-
670
- ### Usar Redis para Cache (Opcional)
671
-
672
- Além do controle de jobs, use Redis para cache:
673
-
674
- ```typescript
675
- // src/services/cache.service.ts
676
- import { Injectable } from '@nestjs/common'
677
- import { IRedisService } from '@koalarx/nest/services/redis/iredis.service'
678
-
679
- @Injectable()
680
- export class CacheService {
681
- constructor(private readonly redisService: IRedisService) {}
682
-
683
- async set(key: string, value: any, expiresIn: number = 3600): Promise<void> {
684
- await this.redisService.set(key, JSON.stringify(value), 'EX', expiresIn)
685
- }
686
-
687
- async get<T>(key: string): Promise<T | null> {
688
- const value = await this.redisService.get(key)
689
- return value ? JSON.parse(value) : null
690
- }
691
-
692
- async delete(key: string): Promise<void> {
693
- await this.redisService.del(key)
694
- }
695
- }
696
- ```
697
-
698
- **Nota importante:** Redis é essencial quando rodando múltiplas instâncias da aplicação. Sem Redis, CronJobs executarão em paralelo em todos os servidores!
699
-
700
- ## 8. Transações com Prisma
701
-
702
- Execute múltiplas operações de banco em uma transação atômica através do repositório.
703
-
704
- ### Implementar DbTransactionContext
705
-
706
- ```typescript
707
- // src/infra/database/db-transaction-context.ts
708
- import { PrismaTransactionalClient } from '@koalarx/nest/core/database/prisma-transactional-client'
709
- import { Prisma } from 'prisma/generated/client'
710
- import { DefaultArgs } from '@prisma/client/runtime/library'
711
-
712
- export class DbTransactionContext
713
- extends PrismaTransactionalClient
714
- implements PrismaClientWithCustomTransaction
715
- {
716
- get person(): Prisma.PersonDelegate<DefaultArgs> {
717
- return this.transactionalClient.person
718
- }
719
-
720
- get personPhone(): Prisma.PersonPhoneDelegate<DefaultArgs> {
721
- return this.transactionalClient.personPhone
722
- }
723
-
724
- get personAddress(): Prisma.PersonAddressDelegate<DefaultArgs> {
725
- return this.transactionalClient.personAddress
726
- }
727
- }
728
- ```
729
-
730
- ### Injetar DbTransactionContext no Repositório
731
-
732
- ```typescript
733
- // src/infra/database/repositories/person.repository.ts
734
- import { PRISMA_TOKEN } from '@koalarx/nest/core/koala-nest-database.module'
735
- import { RepositoryBase } from '@koalarx/nest/core/database/repository.base'
736
- import { Inject, Injectable } from '@nestjs/common'
737
- import { DbTransactionContext } from '../db-transaction-context'
738
-
739
- @Injectable()
740
- export class PersonRepository
741
- extends RepositoryBase<Person>
742
- implements IPersonRepository
743
- {
744
- constructor(
745
- @Inject(PRISMA_TOKEN)
746
- prisma: DbTransactionContext,
747
- ) {
748
- super({
749
- modelName: Person,
750
- context: prisma,
751
- include: {
752
- phones: true,
753
- address: true,
754
- },
755
- })
756
- }
757
-
758
- // Os métodos herdados de RepositoryBase já usam transações automaticamente
759
- async save(person: Person): Promise<CreatedRegistreWithIdResponse | null> {
760
- return this.saveChanges(person) // Transação automática
761
- }
762
-
763
- read(id: number): Promise<Person | null> {
764
- return this.findById(id)
765
- }
766
- }
767
- ```
768
-
769
- ### Registrar no KoalaApp
770
-
771
- ```typescript
772
- // src/host/main.ts
773
- await new KoalaApp(app)
774
- .setDbTransactionContext(DbTransactionContext)
775
- .buildAndServe()
776
- ```
777
-
778
- As transações são executadas **automaticamente** pelo `RepositoryBase` quando você usa métodos como `saveChanges()`, `remove()` e outras operações de escrita. Múltiplas operações dentro do repositório são garantidas como atômicas.
779
-
780
- ## 9. Logging Customizado
781
-
782
- A biblioteca possui um sistema de logging abstrato que por padrão escreve erros no console, mas permite customização para enviar logs para diferentes destinos (Azure Storage, CloudWatch, Sentry, etc).
783
-
784
- ### Entender o Contrato de Logging
785
-
786
- O contrato é definido em `apps/koala-nest/src/services/logging/ilogging.service.ts`:
787
-
788
- ```typescript
789
- export interface LoggingReportProps {
790
- loggedUsername: string // Usuário que gerou o erro
791
- packageName: string // Pacote/módulo onde ocorreu
792
- error: Error // Objeto do erro
793
- httpRequest?: {
794
- method: string // GET, POST, PUT, DELETE, etc
795
- endpoint: string // Path do endpoint
796
- queryParams?: string // Query params da requisição
797
- payload?: object // Body da requisição
798
- statusCode: number // Status HTTP da resposta
799
- response?: object // Response enviado
800
- }
801
- }
802
-
803
- export abstract class ILoggingService {
804
- abstract report(data: LoggingReportProps): Promise<void>
805
- }
806
- ```
807
-
808
- ### Implementação Padrão (Console)
809
-
810
- Por padrão, a biblioteca usa `LoggingService` que escreve no console:
811
-
812
- ```typescript
813
- // apps/koala-nest/src/services/logging/logging.service.ts
814
- import { Injectable } from '@nestjs/common'
815
- import { ILoggingService, LoggingReportProps } from './ilogging.service'
816
- import consola from 'consola'
817
-
818
- @Injectable()
819
- export class LoggingService implements ILoggingService {
820
- async report(data: LoggingReportProps): Promise<void> {
821
- consola.error(data.error)
822
- }
823
- }
824
- ```
825
-
826
- ### Criar Implementação Customizada
827
-
828
- Para enviar logs para um local diferente (ex: Azure Storage), crie uma nova classe implementando `ILoggingService`:
829
-
830
- ```typescript
831
- // src/infra/logging/azure-logging.service.ts
832
- import { Injectable } from '@nestjs/common'
833
- import { ILoggingService, LoggingReportProps } from '@koalarx/nest/services/logging'
834
- import { BlobServiceClient } from '@azure/storage-blob'
835
-
836
- @Injectable()
837
- export class AzureLoggingService implements ILoggingService {
838
- private blobClient: BlobServiceClient
839
-
840
- constructor(connectionString: string) {
841
- this.blobClient = BlobServiceClient.fromConnectionString(connectionString)
842
- }
843
-
844
- async report(data: LoggingReportProps): Promise<void> {
845
- try {
846
- const containerClient = this.blobClient.getContainerClient('logs')
847
- const timestamp = new Date().toISOString()
848
- const blobName = `logs/${data.packageName}/${timestamp}.json`
849
-
850
- const logEntry = {
851
- timestamp,
852
- username: data.loggedUsername,
853
- packageName: data.packageName,
854
- error: {
855
- name: data.error.name,
856
- message: data.error.message,
857
- stack: data.error.stack,
858
- },
859
- httpRequest: data.httpRequest,
860
- }
861
-
862
- const blobClient = containerClient.getBlockBlobClient(blobName)
863
- await blobClient.upload(
864
- JSON.stringify(logEntry),
865
- Buffer.byteLength(JSON.stringify(logEntry))
866
- )
867
- } catch (error) {
868
- console.error('Erro ao enviar log para Azure:', error)
869
- }
870
- }
871
- }
872
- ```
873
-
874
- ### Registrar no AppModule
875
-
876
- Passe a classe de logging customizada diretamente em `logging`:
877
-
878
- ```typescript
879
- // src/host/app.module.ts
880
- import { AzureLoggingService } from '@/infra/logging/azure-logging.service'
881
- import { KoalaNestModule } from '@koalarx/nest/core/koala-nest.module'
882
- import { Module } from '@nestjs/common'
883
-
884
- @Module({
885
- imports: [
886
- KoalaNestModule.register({
887
- env,
888
- controllers: [PersonModule],
889
- logging: AzureLoggingService, // Passar a classe diretamente
890
- // ... outras configurações
891
- }),
892
- ],
893
- })
894
- export class AppModule {}
895
- ```
896
-
897
- **Nota**: Se não configurar `logging`, a biblioteca usará `LoggingService` padrão (console).
898
-
899
- ### Usar Logging em Handlers
900
-
901
- O `ILoggingService` é automaticamente injetado em serviços que precisem fazer logging manual:
902
-
903
- ```typescript
904
- import { ILoggingService } from '@koalarx/nest/services/logging'
905
- import { Injectable } from '@nestjs/common'
906
-
907
- @Injectable()
908
- export class MyHandler {
909
- constructor(private readonly loggingService: ILoggingService) {}
910
-
911
- async handle() {
912
- try {
913
- // sua lógica aqui
914
- } catch (error) {
915
- await this.loggingService.report({
916
- loggedUsername: 'system',
917
- packageName: 'MyHandler',
918
- error: error as Error,
919
- })
920
- }
921
- }
922
- }
923
- ```
924
-
925
- ## 10. Variáveis Globais
926
-
927
- Acesse informações globais configuradas na inicialização da aplicação.
928
-
929
- ### Configurar no main.ts
930
-
931
- ```typescript
932
- // src/host/main.ts
933
- await new KoalaApp(app)
934
- .setAppName('example')
935
- .setInternalUserName('integration.bot')
936
- .buildAndServe()
937
- ```
938
-
939
- ### Acessar em Qualquer Lugar
940
-
941
- ```typescript
942
- import { KoalaGlobalVars } from '@koalarx/nest/core/koala-global-vars'
943
-
944
- // Em qualquer componente
945
- console.log(KoalaGlobalVars.appName) // 'example'
946
- console.log(KoalaGlobalVars.internalUserName) // 'integration.bot'
947
- ```
948
-
949
- ## 11. Ngrok (Exposição Pública em Desenvolvimento)
950
-
951
- Exponha sua aplicação local na internet para testes ou webhooks.
952
-
953
- ### Configurar Token Ngrok
954
-
955
- ```env
956
- # .env
957
- NGROK_AUTH_TOKEN=seu_token_aqui
958
- ```
959
-
960
- ### Usar no main.ts
961
-
962
- ```typescript
963
- // src/host/main.ts
964
- await new KoalaApp(app)
965
- .useNgrok(process.env.NGROK_AUTH_TOKEN!)
966
- .buildAndServe()
967
- ```
968
-
969
- A URL pública do ngrok será exibida no console durante a inicialização da aplicação.