@koalarx/nest 1.19.0 → 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 (311) hide show
  1. package/CHANGELOG.md +15 -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
@@ -0,0 +1,95 @@
1
+ import { KlArray, KlDate, KlTime } from '@koalarx/utils'
2
+ import { Type } from '@nestjs/common'
3
+ import { Overwrite } from '..'
4
+ import { AutoMappingList } from '../mapping/auto-mapping-list'
5
+ import { IComparable, IComparableId } from '../utils/interfaces/icomparable'
6
+ import { List } from '../utils/list'
7
+
8
+ export enum EntityActionType {
9
+ create = 1,
10
+ update,
11
+ }
12
+
13
+ export type EntityProps<T extends IComparable<T>> = Overwrite<
14
+ Omit<
15
+ {
16
+ [K in keyof T as T[K] extends Function ? never : K]: T[K]
17
+ },
18
+ '_id' | '_action'
19
+ >,
20
+ { id?: T extends { id: infer U } ? U : never }
21
+ >
22
+
23
+ export abstract class EntityBase<T extends IComparable<T>>
24
+ implements IComparable<T>
25
+ {
26
+ _id: IComparableId
27
+ _action: EntityActionType = EntityActionType.create
28
+
29
+ constructor(props?: EntityProps<T>) {
30
+ if (props) {
31
+ this.automap(props)
32
+ }
33
+ }
34
+
35
+ automap(props?: EntityProps<T>) {
36
+ if (props) {
37
+ for (const key of Object.keys(props)) {
38
+ if (props[key] === undefined) {
39
+ continue
40
+ }
41
+
42
+ const propDefinitions = AutoMappingList.getPropDefinitions(
43
+ this.constructor.prototype.constructor,
44
+ key,
45
+ )
46
+ const EntityOnPropKey = AutoMappingList.getSourceByName(
47
+ propDefinitions?.type ?? '',
48
+ )
49
+
50
+ if (Array.isArray(props[key]) && this[key] instanceof List) {
51
+ let value: any = props[key]
52
+
53
+ if (this[key].entityType) {
54
+ value = value.map((item) => {
55
+ const entity = new (this[key].entityType as Type<any>)()
56
+ entity._action = this._action
57
+ entity.automap(item)
58
+
59
+ return entity
60
+ })
61
+ }
62
+
63
+ this[key].setList(value)
64
+ } else if (
65
+ propDefinitions?.type === 'KlArray' &&
66
+ (props[key] instanceof Array || Array.isArray(props[key]))
67
+ ) {
68
+ this[key] = new KlArray(props[key])
69
+ } else if (propDefinitions?.type === 'KlDate' && props[key] instanceof Date) {
70
+ this[key] = new KlDate(props[key])
71
+ } else if (propDefinitions?.type === 'KlTime' && props[key] instanceof Date) {
72
+ this[key] = new KlTime(props[key].getHours(), props[key].getMinutes(), props[key].getSeconds(), props[key].getMilliseconds())
73
+ } else if (EntityOnPropKey) {
74
+ if (props[key]) {
75
+ const entity = new EntityOnPropKey()
76
+ entity._action = this._action
77
+ entity.automap(props[key])
78
+
79
+ this[key] = entity
80
+ }
81
+ } else if (propDefinitions) {
82
+ if (key === 'id') {
83
+ this._id = props[key] as IComparableId
84
+ }
85
+
86
+ this[key] = props[key]
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ public equals(obj: EntityBase<T>): boolean {
93
+ return obj._id === this._id
94
+ }
95
+ }
@@ -0,0 +1,71 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { AutoMap } from '../mapping/auto-mapping.decorator'
3
+ import { List } from '../utils/list'
4
+ import { EntityBase } from './entity.base'
5
+ import { Entity } from './entity.decorator'
6
+
7
+ @Entity()
8
+ export class PersonAddress extends EntityBase<PersonAddress> {
9
+ @AutoMap()
10
+ id: number
11
+
12
+ @AutoMap()
13
+ address: string
14
+ }
15
+
16
+ @Entity()
17
+ export class PersonPhone extends EntityBase<PersonPhone> {
18
+ @AutoMap()
19
+ id: number
20
+
21
+ @AutoMap()
22
+ phone: string
23
+ }
24
+
25
+ @Entity()
26
+ export class Person extends EntityBase<Person> {
27
+ @AutoMap()
28
+ id: number
29
+
30
+ @AutoMap()
31
+ name: string
32
+
33
+ @AutoMap({ type: List })
34
+ phones = new List(PersonPhone)
35
+
36
+ @AutoMap({ type: PersonAddress })
37
+ address: PersonAddress
38
+
39
+ @AutoMap()
40
+ active: boolean
41
+ }
42
+
43
+ describe('Entity decorator', () => {
44
+ it('should create an instance of Person', () => {
45
+ const person = new Person({
46
+ name: faker.person.fullName(),
47
+ phones: [
48
+ { phone: faker.phone.number() },
49
+ { phone: faker.phone.number() },
50
+ ],
51
+ address: { address: faker.location.streetAddress() },
52
+ active: true,
53
+ } as any)
54
+
55
+ expect(person).toBeInstanceOf(Person)
56
+ expect(person).toBeInstanceOf(EntityBase)
57
+ expect(person.constructor.name).toBe('Person')
58
+
59
+ expect(person.phones).toBeInstanceOf(List)
60
+ expect(person.phones.toArray()[0]).toBeInstanceOf(PersonPhone)
61
+ expect(person.phones.toArray()[1]).toBeInstanceOf(PersonPhone)
62
+ expect(person.phones.toArray()[0].phone).toBeDefined()
63
+ expect(person.phones.toArray()[1].phone).toBeDefined()
64
+
65
+ expect(person.address.constructor.name).toBe(PersonAddress.name)
66
+ expect(person.address.address).toBeDefined()
67
+
68
+ expect(person.name).toBeDefined()
69
+ expect(person.active).toBe(true)
70
+ })
71
+ })
@@ -0,0 +1,39 @@
1
+ import { EntityBase } from './entity.base'
2
+
3
+ type EntityProps<T> = Omit<
4
+ {
5
+ [K in keyof T as T[K] extends Function ? never : K]: T[K]
6
+ },
7
+ '_id' | '_action'
8
+ >
9
+
10
+ export function Entity<T extends new (...args: any[]) => EntityBase<any>>(
11
+ id?: keyof EntityProps<InstanceType<T>>,
12
+ ) {
13
+ return function (target: T) {
14
+ class NewConstructor extends target {
15
+ constructor(...args: any[]) {
16
+ super(...args) // Chama o construtor original
17
+
18
+ // Chama o método `automap` se ele existir
19
+ if (typeof this.automap === 'function') {
20
+ this.automap(args[0])
21
+ }
22
+ }
23
+ }
24
+
25
+ // Copia o protótipo e propriedades estáticas para o novo construtor
26
+ Object.setPrototypeOf(NewConstructor.prototype, target.prototype)
27
+ Object.setPrototypeOf(NewConstructor, target)
28
+
29
+ // Define o nome do novo construtor para corresponder ao nome da classe original
30
+ Object.defineProperty(NewConstructor, 'name', {
31
+ value: target.name,
32
+ writable: false,
33
+ })
34
+
35
+ Reflect.defineMetadata('entity:id', id, NewConstructor.prototype)
36
+
37
+ return NewConstructor
38
+ }
39
+ }
@@ -0,0 +1,13 @@
1
+ import { Prisma } from 'prisma/generated/client'
2
+
3
+ export interface PrismaClientWithCustomTransaction
4
+ extends Readonly<Prisma.TransactionClient> {
5
+ withTransaction<F>(
6
+ fn: (prisma: Prisma.TransactionClient) => Promise<F>,
7
+ options?: {
8
+ maxWait?: number | undefined
9
+ timeout?: number | undefined
10
+ isolationLevel?: Prisma.TransactionIsolationLevel | undefined
11
+ },
12
+ ): Promise<F>
13
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Resolver automático para o Prisma Client do projeto consumidor
3
+ * Tenta múltiplos caminhos para encontrar o cliente gerado
4
+ */
5
+ import * as path from 'path'
6
+ import * as fs from 'fs'
7
+
8
+ let cachedPrismaClient: any = null
9
+
10
+ function findPrismaClient(): string | null {
11
+ // Lista de caminhos possíveis onde o Prisma pode estar
12
+ const possiblePaths = [
13
+ path.join(process.cwd(), 'prisma/generated/client.js'),
14
+ path.join(__dirname, '../../../../../prisma/generated/client.js'),
15
+ path.join(process.cwd(), 'prisma/generated/client.ts'),
16
+ path.join(__dirname, '../../../../../prisma/generated/client.ts'),
17
+ ...(require.main?.filename
18
+ ? [
19
+ path.join(
20
+ path.dirname(require.main.filename),
21
+ '../prisma/generated/client.js',
22
+ ),
23
+ path.join(
24
+ path.dirname(require.main.filename),
25
+ '../prisma/generated/client.ts',
26
+ ),
27
+ ]
28
+ : []),
29
+ ]
30
+
31
+ for (const prismaPath of possiblePaths) {
32
+ if (fs.existsSync(prismaPath)) {
33
+ return prismaPath
34
+ }
35
+ }
36
+
37
+ return null
38
+ }
39
+
40
+ async function resolvePrismaClient() {
41
+ if (cachedPrismaClient) {
42
+ return cachedPrismaClient
43
+ }
44
+
45
+ const prismaPath = findPrismaClient()
46
+
47
+ if (!prismaPath) {
48
+ throw new Error(
49
+ `
50
+ Não foi possível carregar o Prisma Client automaticamente.
51
+
52
+ Certifique-se de que você:
53
+ 1. Executou 'bunx prisma generate' no seu projeto
54
+ 2. Tem a pasta 'prisma/generated/client' no seu projeto
55
+ 3. A lib @koalarx/nest está instalada como dependência
56
+
57
+ Se o problema persistir, você pode registrar manualmente o Prisma Client:
58
+
59
+ import { setPrismaClient } from '@koalarx/nest'
60
+ import { PrismaClient } from './prisma/generated/client'
61
+
62
+ setPrismaClient(PrismaClient)
63
+ `.trim(),
64
+ )
65
+ }
66
+
67
+ try {
68
+ // Carrega dinamicamente o módulo
69
+ const module = await import(prismaPath)
70
+ // Extrai PrismaClient do módulo (pode ser default export ou named export)
71
+ cachedPrismaClient = module.PrismaClient || module.default || module
72
+ return cachedPrismaClient
73
+ } catch (error) {
74
+ throw new Error(
75
+ `
76
+ Erro ao carregar o Prisma Client de ${prismaPath}:
77
+ ${error instanceof Error ? error.message : String(error)}
78
+
79
+ Certifique-se de que 'bunx prisma generate' foi executado com sucesso.
80
+ `.trim(),
81
+ )
82
+ }
83
+ }
84
+
85
+ // Variável global para registro manual
86
+ let manualPrismaClient: any = null
87
+
88
+ export function setPrismaClient(prismaClientClass: any) {
89
+ manualPrismaClient = prismaClientClass
90
+ cachedPrismaClient = null // Limpa cache
91
+ }
92
+
93
+ export function getPrismaClientClass() {
94
+ if (manualPrismaClient) {
95
+ return manualPrismaClient
96
+ }
97
+ // Retorna uma função que resolve o cliente quando necessário
98
+ return resolvePrismaClient()
99
+ }
@@ -0,0 +1,43 @@
1
+ import { Prisma } from 'prisma/generated/client'
2
+
3
+ export abstract class PrismaTransactionalClient {
4
+ [key: symbol]: any
5
+
6
+ constructor(
7
+ protected readonly transactionalClient: Prisma.TransactionClient,
8
+ ) {}
9
+
10
+ async withTransaction<F>(
11
+ fn: (prisma: Prisma.TransactionClient) => Promise<F>,
12
+ ): Promise<F> {
13
+ return await fn(this.transactionalClient)
14
+ }
15
+
16
+ $executeRaw(
17
+ query: TemplateStringsArray | Prisma.Sql,
18
+ ...values: any[]
19
+ ): Prisma.PrismaPromise<number> {
20
+ return this.transactionalClient.$executeRaw(query, ...values)
21
+ }
22
+
23
+ $executeRawUnsafe(
24
+ query: string,
25
+ ...values: any[]
26
+ ): Prisma.PrismaPromise<number> {
27
+ return this.transactionalClient.$executeRawUnsafe(query, ...values)
28
+ }
29
+
30
+ $queryRaw<T = unknown>(
31
+ query: TemplateStringsArray | Prisma.Sql,
32
+ ...values: any[]
33
+ ): Prisma.PrismaPromise<T> {
34
+ return this.transactionalClient.$queryRaw(query, ...values)
35
+ }
36
+
37
+ $queryRawUnsafe<T = unknown>(
38
+ query: string,
39
+ ...values: any[]
40
+ ): Prisma.PrismaPromise<T> {
41
+ return this.transactionalClient.$queryRawUnsafe(query, ...values)
42
+ }
43
+ }
@@ -0,0 +1,136 @@
1
+ import { EnvService } from '@koalarx/nest/env/env.service'
2
+ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'
3
+ import { PrismaClientWithCustomTransaction } from './prisma-client-with-custom-transaction.interface'
4
+ import { getPrismaClientClass } from './prisma-resolver'
5
+ import type { Prisma } from 'prisma/generated/client'
6
+
7
+ /**
8
+ * Configure opções padrão do PrismaClient (ex: adapter).
9
+ * Use isso na sua aplicação antes de inicializar o módulo Nest.
10
+ */
11
+ let globalPrismaOptions = {} as Prisma.PrismaClientOptions
12
+
13
+ export function setPrismaClientOptions(options: Prisma.PrismaClientOptions) {
14
+ globalPrismaOptions = options
15
+ }
16
+
17
+ // Wrapper para carregar o PrismaClient dinamicamente
18
+ let PrismaClientClass: any = null
19
+
20
+ async function loadPrismaClient() {
21
+ if (!PrismaClientClass) {
22
+ PrismaClientClass = await getPrismaClientClass()
23
+ }
24
+ return PrismaClientClass
25
+ }
26
+
27
+ @Injectable()
28
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
29
+ // @ts-ignore
30
+ export class PrismaService
31
+ implements OnModuleInit, OnModuleDestroy, PrismaClientWithCustomTransaction
32
+ {
33
+ private prismaInstance: any
34
+
35
+ constructor(private readonly env: EnvService) {
36
+ // Retorna um proxy para permitir acesso transparente às models
37
+ // Isso é necessário porque repository.base.ts tenta acessar this._context[modelName]
38
+ return new Proxy(this, {
39
+ get: (target, prop, receiver) => {
40
+ // Propriedades e métodos da instância têm prioridade
41
+ if (prop in target) {
42
+ const value = Reflect.get(target, prop, receiver)
43
+ if (typeof value === 'function') {
44
+ return value.bind(target)
45
+ }
46
+ return value
47
+ }
48
+
49
+ // Caso a propriedade não exista, tenta acessar no prismaInstance
50
+ // Isso permite acessar models (person, user, etc.) e métodos como $queryRaw
51
+ if (target.prismaInstance && typeof prop === 'string') {
52
+ const value = target.prismaInstance[prop]
53
+ if (typeof value === 'function') {
54
+ return value.bind(target.prismaInstance)
55
+ }
56
+ return value
57
+ }
58
+
59
+ return Reflect.get(target, prop, receiver)
60
+ },
61
+ }) as any
62
+ }
63
+
64
+ async initialize() {
65
+ const PrismaClientType = await loadPrismaClient()
66
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
67
+ // @ts-ignore
68
+ this.prismaInstance = new PrismaClientType({
69
+ log: [{ emit: 'event', level: 'query' }],
70
+ ...globalPrismaOptions,
71
+ } as Prisma.PrismaClientOptions)
72
+ }
73
+
74
+ async onModuleInit() {
75
+ await this.initialize()
76
+ if (this.env.get('PRISMA_QUERY_LOG')) {
77
+ this.prismaInstance?.$on?.('query', async (e: any) => {
78
+ console.log(`${e.query} ${e.params}`)
79
+ })
80
+ }
81
+ return this.prismaInstance?.$connect?.()
82
+ }
83
+
84
+ onModuleDestroy() {
85
+ return this.prismaInstance?.$disconnect?.()
86
+ }
87
+
88
+ async withTransaction<F>(
89
+ fn: (prisma: Prisma.TransactionClient) => Promise<F>,
90
+ options?: {
91
+ maxWait?: number
92
+ timeout?: number
93
+ isolationLevel?: Prisma.TransactionIsolationLevel
94
+ },
95
+ ): Promise<F> {
96
+ return this.prismaInstance?.$transaction?.(
97
+ fn,
98
+ options ?? {
99
+ maxWait: 20000,
100
+ timeout: 20000,
101
+ },
102
+ )
103
+ }
104
+
105
+ // Expõe métodos e properties do PrismaClient dynamicamente
106
+ // Isso permite que o repositório acesse models (person, user, etc.) via Proxy
107
+ [Symbol.toPrimitive]() {
108
+ return this.prismaInstance
109
+ }
110
+
111
+ toString() {
112
+ return '[PrismaService]'
113
+ }
114
+
115
+ // Métodos úteis do PrismaClient
116
+ get $connect() {
117
+ return this.prismaInstance?.$connect?.bind(this.prismaInstance)
118
+ }
119
+
120
+ get $disconnect() {
121
+ return this.prismaInstance?.$disconnect?.bind(this.prismaInstance)
122
+ }
123
+
124
+ get $transaction() {
125
+ return this.prismaInstance?.$transaction?.bind(this.prismaInstance)
126
+ }
127
+
128
+ get $on() {
129
+ return this.prismaInstance?.$on?.bind(this.prismaInstance)
130
+ }
131
+
132
+ // Proxy transparente para acessar models e qualquer outro property do PrismaClient
133
+ [Symbol.for('nodejs.util.inspect.custom')]() {
134
+ return this.prismaInstance
135
+ }
136
+ }