@koalarx/nest 1.18.21 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +5 -36
  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 -485
  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/env/env.d.ts +0 -25
  254. package/env/env.js +0 -14
  255. package/env/env.module.d.ts +0 -2
  256. package/env/env.module.js +0 -20
  257. package/env/env.service.d.ts +0 -7
  258. package/env/env.service.js +0 -28
  259. package/filters/domain-errors.filter.d.ts +0 -18
  260. package/filters/domain-errors.filter.js +0 -92
  261. package/filters/global-exception.filter.d.ts +0 -8
  262. package/filters/global-exception.filter.js +0 -68
  263. package/filters/prisma-validation-exception.filter.d.ts +0 -10
  264. package/filters/prisma-validation-exception.filter.js +0 -82
  265. package/filters/zod-errors.filter.d.ts +0 -9
  266. package/filters/zod-errors.filter.js +0 -60
  267. package/services/logging/ilogging.service.d.ts +0 -16
  268. package/services/logging/ilogging.service.js +0 -6
  269. package/services/logging/logging.service.d.ts +0 -4
  270. package/services/logging/logging.service.js +0 -20
  271. package/services/redis/iredis.service.d.ts +0 -6
  272. package/services/redis/iredis.service.js +0 -6
  273. package/services/redis/redis.service.d.ts +0 -14
  274. package/services/redis/redis.service.js +0 -65
  275. package/services/redlock/ired-lock.service.d.ts +0 -4
  276. package/services/redlock/ired-lock.service.js +0 -6
  277. package/services/redlock/red-lock.service.d.ts +0 -9
  278. package/services/redlock/red-lock.service.js +0 -46
  279. package/test/koala-app-test-dependencies.d.ts +0 -10
  280. package/test/koala-app-test-dependencies.js +0 -13
  281. package/test/koala-app-test.d.ts +0 -22
  282. package/test/koala-app-test.js +0 -77
  283. package/test/repositories/in-memory-base.repository.d.ts +0 -17
  284. package/test/repositories/in-memory-base.repository.js +0 -65
  285. package/test/services/fake-logging.service.d.ts +0 -4
  286. package/test/services/fake-logging.service.js +0 -9
  287. package/test/services/fake-red-lock.service.d.ts +0 -5
  288. package/test/services/fake-red-lock.service.js +0 -11
  289. package/test/utils/create-e2e-database.d.ts +0 -2
  290. package/test/utils/create-e2e-database.js +0 -47
  291. package/test/utils/drop-e2e-database.d.ts +0 -2
  292. package/test/utils/drop-e2e-database.js +0 -33
  293. package/test/utils/wait-for.d.ts +0 -1
  294. package/test/utils/wait-for.js +0 -21
  295. package/tsconfig.lib.tsbuildinfo +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # @koalarx/nest
2
+
3
+ ## 3.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 3532e0d: Nova tentativa de publish
8
+ - 276bc25: Teste de publicação do koala-nest
9
+ - 9f4d18c: Adicionado link da dock no README inicial
10
+
11
+ ## 3.0.0
12
+
13
+ ### Major Changes
14
+
15
+ - 9c3cdf1: CLI migrada para este repositório em estrutura de monorepo, atualizações de eslint e ajustes na documentação
package/package.json CHANGED
@@ -1,41 +1,10 @@
1
1
  {
2
2
  "name": "@koalarx/nest",
3
- "version": "1.18.21",
3
+ "version": "3.0.1",
4
4
  "description": "",
5
- "repository": {
6
- "type": "git",
7
- "url": "git+https://github.com/igordrangel/koala-nest.git"
8
- },
9
5
  "author": "Igor D. Rangel",
10
- "license": "UNLICENSED",
11
- "bugs": {
12
- "url": "https://github.com/igordrangel/koala-nest/issues"
13
- },
14
- "homepage": "https://github.com/igordrangel/koala-nest#readme",
15
- "types": "./koala-nest.d.ts",
16
- "peerDependencies": {
17
- "@koalarx/utils": "^4.2.1",
18
- "@modelcontextprotocol/sdk": "^1.25.2",
19
- "@nestjs/common": "^11.0.12",
20
- "@nestjs/config": "^4.0.1",
21
- "@nestjs/core": "^11.0.12",
22
- "@nestjs/mapped-types": "^2.1.0",
23
- "@nestjs/passport": "^11.0.5",
24
- "@nestjs/platform-express": "^11.0.12",
25
- "@nestjs/swagger": "^11.0.7",
26
- "@prisma/adapter-pg": "^7.2.0",
27
- "@prisma/client": "^7.2.0",
28
- "@scalar/nestjs-api-reference": "^0.4.3",
29
- "consola": "^3.4.2",
30
- "dotenv": "^16.0.3",
31
- "express-basic-auth": "^1.2.1",
32
- "ioredis": "^5.3.2",
33
- "ngrok": "^5.0.0-beta.2",
34
- "passport": "^0.7.0",
35
- "passport-custom": "^1.1.1",
36
- "reflect-metadata": "^0.1.13",
37
- "rimraf": "^3.0.2",
38
- "zod": "^3.22.4",
39
- "zod-validation-error": "^1.5.0"
6
+ "license": "MIT",
7
+ "engines": {
8
+ "bun": ">=1.0.0"
40
9
  }
41
- }
10
+ }
@@ -0,0 +1,66 @@
1
+ import { delay } from '@koalarx/utils/KlDelay'
2
+ import { ILoggingService } from '../../../services/logging/ilogging.service'
3
+ import { IRedLockService } from '../../../services/redlock/ired-lock.service'
4
+ import { KoalaGlobalVars } from '../../koala-global-vars'
5
+ import { RequestResult } from '../../request-overflow/request-result'
6
+
7
+ export type CronJobResponse = RequestResult<Error, null>
8
+ export interface CronJobSettings {
9
+ isActive: boolean
10
+ timeInMinutes: number
11
+ }
12
+
13
+ export abstract class CronJobHandlerBase {
14
+ constructor(
15
+ private readonly redlockService: IRedLockService,
16
+ private readonly loggingService: ILoggingService,
17
+ ) {}
18
+
19
+ protected abstract run(): Promise<CronJobResponse>
20
+
21
+ protected abstract settings(): Promise<CronJobSettings>
22
+
23
+ async start(): Promise<void> {
24
+ const name = this.constructor.name
25
+
26
+ while (true) {
27
+ const settings = await this.settings()
28
+ const timeout = settings.timeInMinutes * 60 * 1000
29
+
30
+ if (settings.isActive) {
31
+ const ttlSecondsLock = timeout / 1000
32
+ const acquiredLock = await this.redlockService.acquiredLock(
33
+ name,
34
+ ttlSecondsLock,
35
+ )
36
+
37
+ if (acquiredLock) {
38
+ const error = await this.run()
39
+ .then((result) => {
40
+ if (result.isFailure()) {
41
+ return result.value
42
+ }
43
+ return null
44
+ })
45
+ .catch((error) => error)
46
+
47
+ if (error) {
48
+ try {
49
+ await this.loggingService.report({
50
+ error,
51
+ packageName: KoalaGlobalVars.appName,
52
+ loggedUsername: KoalaGlobalVars.internalUserName,
53
+ })
54
+ } catch {
55
+ console.error(error)
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ await delay(timeout)
62
+
63
+ await this.redlockService.releaseLock(name)
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,38 @@
1
+ import { delay } from '@koalarx/utils/KlDelay'
2
+ import { expect, spyOn, test } from 'bun:test'
3
+ import { FakeLoggingService } from '../../../test/services/fake-logging.service'
4
+ import { FakeRedLockService } from '../../../test/services/fake-red-lock.service'
5
+ import { ok } from '../../request-overflow/request-result'
6
+ import {
7
+ CronJobHandlerBase,
8
+ CronJobResponse,
9
+ CronJobSettings,
10
+ } from './cron-job.handler.base'
11
+
12
+ export class CronJobTest extends CronJobHandlerBase {
13
+ constructor() {
14
+ super(new FakeRedLockService(), new FakeLoggingService())
15
+ }
16
+
17
+ protected async settings(): Promise<CronJobSettings> {
18
+ return { isActive: true, timeInMinutes: 0.01 }
19
+ }
20
+
21
+ static async isCalled(): Promise<CronJobResponse> {
22
+ return ok(null)
23
+ }
24
+
25
+ protected run(): Promise<CronJobResponse> {
26
+ return CronJobTest.isCalled()
27
+ }
28
+ }
29
+
30
+ test('cron job', async () => {
31
+ const callbackSpy = spyOn(CronJobTest, 'isCalled')
32
+
33
+ new CronJobTest().start()
34
+
35
+ await delay(100)
36
+
37
+ expect(callbackSpy).toHaveBeenCalled()
38
+ })
@@ -0,0 +1,5 @@
1
+ export abstract class EventClass<TEntity = any> {
2
+ ocurredAt: Date = new Date()
3
+
4
+ constructor(public data?: TEntity) {}
5
+ }
@@ -0,0 +1,17 @@
1
+ import { Type } from '@nestjs/common'
2
+ import { EventClass } from './event-class'
3
+ import { EventQueue } from './event-queue'
4
+
5
+ export abstract class EventHandlerBase {
6
+ constructor(public readonly event: Type<EventClass>) {}
7
+
8
+ setupSubscriptions() {
9
+ EventQueue.register(
10
+ this.handleEvent.bind(this),
11
+ this.constructor.name,
12
+ this.event.name,
13
+ )
14
+ }
15
+
16
+ abstract handleEvent(event: InstanceType<this['event']>): Promise<void>
17
+ }
@@ -0,0 +1,3 @@
1
+ export class EventIsTrigger {
2
+ isTrigger() {}
3
+ }
@@ -0,0 +1,28 @@
1
+ import { Type } from '@nestjs/common'
2
+ import { EventClass } from './event-class'
3
+ import { EventHandlerBase } from './event-handler.base'
4
+ import { EventQueue } from './event-queue'
5
+ import { randomUUID } from 'node:crypto'
6
+
7
+ export abstract class EventJob<TEntity> {
8
+ _id = randomUUID()
9
+
10
+ private _eventQueue: EventQueue[] = []
11
+
12
+ constructor() {}
13
+
14
+ abstract defineHandlers(): Array<Type<EventHandlerBase>>
15
+
16
+ get eventQueue(): EventQueue[] {
17
+ return this._eventQueue
18
+ }
19
+
20
+ public clearQueue() {
21
+ this._eventQueue = []
22
+ }
23
+
24
+ public addEvent(event: EventClass<TEntity>): void {
25
+ this.eventQueue.push(event)
26
+ EventQueue.markAggregateForDispatch(this)
27
+ }
28
+ }
@@ -0,0 +1,47 @@
1
+ import { Type } from '@nestjs/common'
2
+ import { describe, expect, it, spyOn } from 'bun:test'
3
+ import { EventClass } from './event-class'
4
+ import { EventHandlerBase } from './event-handler.base'
5
+ import { EventJob } from './event-job'
6
+ import { EventQueue } from './event-queue'
7
+
8
+ class CustomEvent extends EventClass {}
9
+
10
+ class CustomEventHandler extends EventHandlerBase {
11
+ constructor() {
12
+ super(CustomEvent)
13
+ }
14
+
15
+ static async isCalled(): Promise<null> {
16
+ return null
17
+ }
18
+
19
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
20
+ async handleEvent(event: CustomEvent): Promise<void> {
21
+ await CustomEventHandler.isCalled()
22
+ }
23
+ }
24
+
25
+ class CustomEventJob extends EventJob<any> {
26
+ defineHandlers(): Array<Type<EventHandlerBase>> {
27
+ return [CustomEventHandler]
28
+ }
29
+ }
30
+
31
+ describe('event queue', () => {
32
+ it('should be able to dispatch and listen to events', () => {
33
+ const callbackSpy = spyOn(CustomEventHandler, 'isCalled')
34
+
35
+ new CustomEventHandler().setupSubscriptions()
36
+
37
+ const jobs = new CustomEventJob()
38
+ jobs.addEvent(new CustomEvent())
39
+
40
+ expect(jobs.eventQueue).toHaveLength(1)
41
+
42
+ EventQueue.dispatchEventsForAggregate(jobs._id)
43
+
44
+ expect(callbackSpy).toHaveBeenCalled()
45
+ expect(jobs.eventQueue).toHaveLength(0)
46
+ })
47
+ })
@@ -0,0 +1,107 @@
1
+ import { IComparableId } from '../../../core/utils/interfaces/icomparable'
2
+ import { EventClass } from './event-class'
3
+ import { EventJob } from './event-job'
4
+
5
+ type EventJobCallback = (event: any) => void
6
+ interface EventQueueJobItem {
7
+ eventClassName: string
8
+ callback: EventJobCallback
9
+ }
10
+
11
+ export class EventQueue {
12
+ private static handlersMap: Record<string, EventQueueJobItem[]> = {}
13
+
14
+ private static markedAggregates: EventJob<any>[] = []
15
+
16
+ public static markAggregateForDispatch(aggregate: EventJob<any>) {
17
+ const aggregateFound = !!this.findMarkedAggregateByID(aggregate._id)
18
+
19
+ if (!aggregateFound) {
20
+ this.markedAggregates.push(aggregate)
21
+ }
22
+ }
23
+
24
+ public static dispatchEventsForAggregate(id: IComparableId) {
25
+ const aggregate = this.findMarkedAggregateByID(id)
26
+
27
+ if (aggregate) {
28
+ this.dispatchAggregateEvents(aggregate)
29
+ aggregate.clearQueue()
30
+ this.removeAggregateFromMarkedDispatchList(aggregate)
31
+ }
32
+ }
33
+
34
+ public static register(
35
+ callback: EventJobCallback,
36
+ handlerClassName: string,
37
+ eventClassName: string,
38
+ ) {
39
+ const wasEventRegisteredBefore = handlerClassName in this.handlersMap
40
+
41
+ if (!wasEventRegisteredBefore) {
42
+ this.handlersMap[handlerClassName] = []
43
+ }
44
+
45
+ this.handlersMap[handlerClassName].push({
46
+ eventClassName,
47
+ callback,
48
+ })
49
+ }
50
+
51
+ public static clearHandlers() {
52
+ this.handlersMap = {}
53
+ }
54
+
55
+ public static clearMarkedAggregates() {
56
+ this.markedAggregates = []
57
+ }
58
+
59
+ private static dispatchAggregateEvents(aggregate: EventJob<any>) {
60
+ aggregate.eventQueue.forEach((event: EventClass<any>) =>
61
+ this.dispatch(event),
62
+ )
63
+ }
64
+
65
+ private static removeAggregateFromMarkedDispatchList(
66
+ aggregate: EventJob<any>,
67
+ ) {
68
+ const index = this.markedAggregates.findIndex(
69
+ (a) => a._id === aggregate._id,
70
+ )
71
+
72
+ this.markedAggregates.splice(index, 1)
73
+ }
74
+
75
+ private static findMarkedAggregateByID(
76
+ id: IComparableId,
77
+ ): EventJob<any> | undefined {
78
+ return this.markedAggregates.find((aggregate) => aggregate._id === id)
79
+ }
80
+
81
+ private static dispatch(event: EventClass<any>) {
82
+ const eventJobHandlers = this.markedAggregates.find((a) =>
83
+ a.eventQueue.find((e) => e === event),
84
+ )
85
+ const eventHandler = Object.keys(this.handlersMap).find((handlerName) =>
86
+ eventJobHandlers
87
+ ?.defineHandlers()
88
+ .find(
89
+ (handler) =>
90
+ handler.name === handlerName &&
91
+ this.handlersMap[handler.name].some(
92
+ (job) => job.eventClassName === event.constructor.name,
93
+ ),
94
+ ),
95
+ )
96
+
97
+ const isEventRegistered = !!eventHandler
98
+
99
+ if (isEventRegistered) {
100
+ const jobs = this.handlersMap[eventHandler]
101
+
102
+ for (const job of jobs) {
103
+ job.callback(event)
104
+ }
105
+ }
106
+ }
107
+ }
@@ -0,0 +1,7 @@
1
+ import type { QueryDirectionType } from '..'
2
+
3
+ export const QUERY_FILTER_PARAMS = {
4
+ direction: 'asc' as QueryDirectionType,
5
+ page: 0,
6
+ limit: 30,
7
+ }
@@ -0,0 +1,9 @@
1
+ import { Response as HttpResponse } from 'express'
2
+
3
+ export abstract class IController<Request, Response, Params = any> {
4
+ abstract handle(
5
+ request: Request,
6
+ params?: Params,
7
+ response?: HttpResponse,
8
+ ): Promise<Response>
9
+ }
@@ -0,0 +1,10 @@
1
+ import { RouterConfigBase } from './router-config.base'
2
+ import { Controller as NestController } from '@nestjs/common'
3
+ import { ApiTags } from '@nestjs/swagger'
4
+
5
+ export function Controller(config: RouterConfigBase) {
6
+ return function (target: any) {
7
+ NestController(config.group)(target)
8
+ ApiTags(config.tag)(target)
9
+ }
10
+ }
@@ -0,0 +1,17 @@
1
+ import { ApiProperty } from '@nestjs/swagger'
2
+ import { IComparableId } from '../../core/utils/interfaces/icomparable'
3
+
4
+ export abstract class CreatedRegistreResponseBase<TId = IComparableId> {
5
+ @ApiProperty()
6
+ id: TId
7
+ }
8
+
9
+ export abstract class CreatedRegistreWithUUIDResponse extends CreatedRegistreResponseBase<string> {
10
+ @ApiProperty({ type: 'string', format: 'uuid' })
11
+ declare id: string
12
+ }
13
+
14
+ export abstract class CreatedRegistreWithIdResponse extends CreatedRegistreResponseBase<number> {
15
+ @ApiProperty({ type: 'integer', format: 'int32' })
16
+ declare id: number
17
+ }
@@ -0,0 +1,8 @@
1
+ import { ApiProperty } from '@nestjs/swagger'
2
+
3
+ export abstract class ListResponseBase<TResponse> {
4
+ abstract items: Array<TResponse>
5
+
6
+ @ApiProperty()
7
+ count: number
8
+ }
@@ -0,0 +1,41 @@
1
+ import { ApiProperty } from '@nestjs/swagger'
2
+ import { AutoMap } from '../mapping/auto-mapping.decorator'
3
+ import { QUERY_FILTER_PARAMS } from '../constants/query-params'
4
+ import type { QueryDirectionType } from '..'
5
+
6
+ export type PaginatedRequestProps<T extends PaginationRequest> = Omit<
7
+ { [K in keyof T as T[K] extends Function ? never : K]: T[K] },
8
+ '_id'
9
+ >
10
+
11
+ export class PaginationRequest {
12
+ @ApiProperty({
13
+ required: false,
14
+ format: 'int32',
15
+ default: QUERY_FILTER_PARAMS.page,
16
+ })
17
+ @AutoMap()
18
+ page?: number = QUERY_FILTER_PARAMS.page
19
+
20
+ @ApiProperty({
21
+ required: false,
22
+ format: 'int32',
23
+ default: QUERY_FILTER_PARAMS.limit,
24
+ })
25
+ @AutoMap()
26
+ limit?: number = QUERY_FILTER_PARAMS.limit
27
+
28
+ @ApiProperty({
29
+ required: false,
30
+ })
31
+ @AutoMap()
32
+ orderBy?: string
33
+
34
+ @ApiProperty({
35
+ required: false,
36
+ enum: ['asc', 'desc'],
37
+ default: QUERY_FILTER_PARAMS.direction,
38
+ })
39
+ @AutoMap()
40
+ direction?: QueryDirectionType = QUERY_FILTER_PARAMS.direction
41
+ }
@@ -0,0 +1,14 @@
1
+ export abstract class RouterConfigBase {
2
+ protected constructor(
3
+ private readonly _tag: string,
4
+ private readonly _group: string,
5
+ ) {}
6
+
7
+ get group() {
8
+ return this._group
9
+ }
10
+
11
+ get tag() {
12
+ return this._tag
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod'
2
+
3
+ export function booleanSchema() {
4
+ return z.coerce.string().transform((value) => {
5
+ if (value !== undefined) {
6
+ return value === 'true'
7
+ }
8
+ return undefined
9
+ })
10
+ }
@@ -0,0 +1,23 @@
1
+ import { validateCnpj, validateCpf } from '@koalarx/utils/KlString'
2
+
3
+ export function documentNumberSchema(value: string) {
4
+ if (value !== '' && value !== 'undefined' && value !== 'null') {
5
+ if (value.includes('.')) {
6
+ if (value.length === 14) {
7
+ return validateCpf(value)
8
+ } else if (value.length === 18) {
9
+ return validateCnpj(value)
10
+ }
11
+ } else {
12
+ if (value.length === 11) {
13
+ return validateCpf(value)
14
+ } else if (value.length === 14) {
15
+ return validateCnpj(value)
16
+ }
17
+ }
18
+
19
+ return false
20
+ }
21
+
22
+ return true
23
+ }
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod'
2
+
3
+ export function emailSchema(email?: string, isRequired: boolean = false) {
4
+ if (isRequired && !email) {
5
+ return false
6
+ }
7
+
8
+ if (!email) {
9
+ return true
10
+ }
11
+
12
+ return z.coerce.string().max(50).email().parse(email)
13
+ }
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod'
2
+ import { QUERY_FILTER_PARAMS } from '../../constants/query-params'
3
+
4
+ export const LIST_QUERY_SCHEMA = z.object({
5
+ page: z.coerce
6
+ .number()
7
+ .transform((value) => {
8
+ if (value) {
9
+ return value - 1
10
+ }
11
+ return QUERY_FILTER_PARAMS.page
12
+ })
13
+ .optional(),
14
+ limit: z.coerce.number().default(QUERY_FILTER_PARAMS.limit).optional(),
15
+ orderBy: z.string().optional(),
16
+ direction: z.enum(['asc', 'desc']).default('asc').optional(),
17
+ })
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod'
2
+
3
+ interface NativeEnumInterface<TEnum> {
4
+ isOptional: (value: string) => TEnum[keyof TEnum] | undefined
5
+ isRequired: (value: string) => TEnum[keyof TEnum]
6
+ }
7
+
8
+ export function nativeEnumSchema<TEnum extends z.EnumLike>(
9
+ nativeEnum: TEnum,
10
+ ): NativeEnumInterface<TEnum> {
11
+ return {
12
+ isOptional: (value: string) => {
13
+ if (value === 'null' || value === '') {
14
+ return undefined
15
+ }
16
+
17
+ return z.coerce
18
+ .number()
19
+ .transform((value) => {
20
+ if (value !== undefined) {
21
+ return z.nativeEnum(nativeEnum).parse(value)
22
+ }
23
+ return undefined
24
+ })
25
+ .parse(value)
26
+ },
27
+ isRequired: (value: string) => {
28
+ return z.coerce
29
+ .number()
30
+ .transform((value) => z.nativeEnum(nativeEnum).parse(value))
31
+ .parse(value)
32
+ },
33
+ }
34
+ }
@@ -0,0 +1,13 @@
1
+ import { maskCnpj, maskCpf } from '@koalarx/utils'
2
+
3
+ export function setMaskDocumentNumber(document?: string) {
4
+ if (!document) {
5
+ return ''
6
+ }
7
+
8
+ const documentWithoutMask = document.replace(/[^0-9]/g, '')
9
+
10
+ return documentWithoutMask.length === 11
11
+ ? maskCpf(documentWithoutMask)
12
+ : maskCnpj(documentWithoutMask)
13
+ }