@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
@@ -0,0 +1,154 @@
1
+ import { Type } from '@nestjs/common'
2
+ import { findOnList } from '../utils/find-on-list'
3
+ import { getTypeByProp } from '../utils/get-type-by-prop'
4
+ import { List } from '../utils/list'
5
+ import { AutoMappingClassContext } from './auto-mapping-class-context'
6
+ import { AutoMappingContext } from './auto-mapping-context'
7
+ import { ForMemberDefinition } from './for-member'
8
+
9
+ interface AutoMappingGetContext {
10
+ mapContext: AutoMappingContext | null
11
+ propSourceContext: AutoMappingClassContext | null
12
+ propTargetContext: AutoMappingClassContext | null
13
+ }
14
+
15
+ export class AutoMappingList {
16
+ private static _mappedPropList: List<AutoMappingClassContext> | undefined
17
+ private static _mappingProfileList: List<AutoMappingContext> | undefined
18
+
19
+ private static initializeLists() {
20
+ if (!this._mappedPropList) {
21
+ this._mappedPropList = new List(AutoMappingClassContext)
22
+ }
23
+ if (!this._mappingProfileList) {
24
+ this._mappingProfileList = new List(AutoMappingContext)
25
+ }
26
+ }
27
+
28
+ static add(
29
+ source: Type<any>,
30
+ target: Type<any>,
31
+ ...forMember: ForMemberDefinition<any, any>
32
+ ) {
33
+ this.initializeLists()
34
+ this._mappingProfileList!.add(
35
+ new AutoMappingContext(source, target, forMember),
36
+ )
37
+ this._mappedPropList!.add(new AutoMappingClassContext(source))
38
+ this._mappedPropList!.add(new AutoMappingClassContext(target))
39
+
40
+ this.addExtendedPropsIntoSubClass(source)
41
+ this.addExtendedPropsIntoSubClass(target)
42
+ }
43
+
44
+ static get(source: Type<any>, target: Type<any>): AutoMappingGetContext {
45
+ this.initializeLists()
46
+ return {
47
+ mapContext: findOnList(
48
+ this._mappingProfileList!,
49
+ (mp) =>
50
+ mp.source.name === source.name && mp.target.name === target.name,
51
+ (mp) =>
52
+ Object.getPrototypeOf(mp.source.prototype.constructor) === source &&
53
+ mp.target.name === target.name,
54
+ ),
55
+ propSourceContext: this._mappedPropList!.find(
56
+ (mp) => mp.source.name === source.name,
57
+ ),
58
+ propTargetContext: this._mappedPropList!.find(
59
+ (mp) => mp.source.name === target.name,
60
+ ),
61
+ }
62
+ }
63
+
64
+ static getSourceByName(sourceName: string) {
65
+ this.initializeLists()
66
+ return this._mappedPropList!.find((mp) => mp.source.name === sourceName)
67
+ ?.source
68
+ }
69
+
70
+ static getPropDefinitions(source: Type<any>, propName: string) {
71
+ this.initializeLists()
72
+ const prop = this._mappedPropList!.find(
73
+ (mp) => mp.source.name === source.name,
74
+ )?.props.find((prop) => prop.name === propName)
75
+
76
+ if (!prop) {
77
+ return undefined
78
+ }
79
+
80
+ return {
81
+ ...prop,
82
+ type: getTypeByProp(prop),
83
+ }
84
+ }
85
+
86
+ static getTargets(source: Type<any>) {
87
+ this.initializeLists()
88
+ return this._mappingProfileList!.filter(
89
+ (mp) =>
90
+ mp.source.name === source.name ||
91
+ Object.getPrototypeOf(mp.source.prototype.constructor) === source,
92
+ )
93
+ .map((mp) => mp.target)
94
+ .toArray()
95
+ }
96
+
97
+ static addMappedProp(source: Type<any>, propName: string) {
98
+ this.initializeLists()
99
+ let mappedClass = this._mappedPropList!.find(
100
+ (mp) => mp.source.name === source.name,
101
+ )
102
+
103
+ if (!mappedClass) {
104
+ mappedClass = new AutoMappingClassContext(source)
105
+
106
+ const mappedExtendedClass = this._mappedPropList!.find(
107
+ (mp) =>
108
+ mp.source === Object.getPrototypeOf(source.prototype.constructor),
109
+ )
110
+
111
+ if (mappedExtendedClass) {
112
+ mappedClass.props.setList(mappedExtendedClass.props.toArray())
113
+ }
114
+
115
+ this._mappedPropList!.add(mappedClass)
116
+ }
117
+
118
+ const type = Reflect.getMetadata('design:type', source.prototype, propName)
119
+ const compositionType = Reflect.getMetadata(
120
+ 'composition:type',
121
+ source.prototype,
122
+ propName,
123
+ )
124
+ const compositionAction = Reflect.getMetadata(
125
+ 'composition:action',
126
+ source.prototype,
127
+ propName,
128
+ )
129
+
130
+ mappedClass.props.add({
131
+ name: propName,
132
+ type,
133
+ compositionType,
134
+ compositionAction,
135
+ })
136
+ }
137
+
138
+ static addExtendedPropsIntoSubClass(source: Type<any>) {
139
+ this.initializeLists()
140
+ const mappedExtendedClass = this._mappedPropList!.find(
141
+ (mp) => mp.source === Object.getPrototypeOf(source.prototype.constructor),
142
+ )
143
+ if (mappedExtendedClass) {
144
+ const mappedClass = this._mappedPropList!.find(
145
+ (mp) => mp.source.name === source.name,
146
+ )
147
+ if (mappedClass) {
148
+ mappedExtendedClass.props
149
+ .toArray()
150
+ .forEach((prop) => mappedClass.props.add(prop))
151
+ }
152
+ }
153
+ }
154
+ }
@@ -0,0 +1,3 @@
1
+ export abstract class AutoMappingProfile {
2
+ abstract profile(): void
3
+ }
@@ -0,0 +1,54 @@
1
+ import { Type } from '@nestjs/common'
2
+ import { AutoMappingList } from './auto-mapping-list'
3
+
4
+ interface AutoMapConfig<T> {
5
+ type?: () => Type<T>
6
+ isArray?: boolean | { addTo: boolean }
7
+ }
8
+
9
+ export function AutoMap<T>(config?: AutoMapConfig<T>) {
10
+ return function (target: any, propertyKey: string) {
11
+ const isArray = config?.isArray
12
+
13
+ let customMetadata: (() => any) | undefined = config?.type
14
+
15
+ if (!customMetadata) {
16
+ customMetadata = isArray ? Array : undefined
17
+ }
18
+
19
+ if (customMetadata) {
20
+ if (isArray) {
21
+ Reflect.defineMetadata(
22
+ 'composition:type',
23
+ customMetadata,
24
+ target,
25
+ propertyKey,
26
+ )
27
+ Reflect.defineMetadata(
28
+ 'composition:action',
29
+ `${isArray === true || !isArray.addTo ? 'onlySet' : 'addTo'}`,
30
+ target,
31
+ propertyKey,
32
+ )
33
+
34
+ if (customMetadata !== Array) {
35
+ customMetadata = Array
36
+ }
37
+ }
38
+
39
+ if (
40
+ !Reflect.getMetadata('design:type', target, propertyKey) ||
41
+ !isArray
42
+ ) {
43
+ Reflect.defineMetadata(
44
+ 'design:type',
45
+ customMetadata,
46
+ target,
47
+ propertyKey,
48
+ )
49
+ }
50
+ }
51
+
52
+ AutoMappingList.addMappedProp(target.constructor, propertyKey)
53
+ }
54
+ }
@@ -0,0 +1,17 @@
1
+ import { DynamicModule, Module, Type } from '@nestjs/common'
2
+ import { AutoMappingProfile } from './auto-mapping-profile'
3
+ import { AutoMappingService } from './auto-mapping.service'
4
+
5
+ @Module({})
6
+ export class AutoMappingModule {
7
+ static register(profile: Type<AutoMappingProfile>): DynamicModule {
8
+ return {
9
+ module: AutoMappingModule,
10
+ providers: [
11
+ { provide: AutoMappingProfile, useClass: profile },
12
+ AutoMappingService,
13
+ ],
14
+ exports: [AutoMappingService],
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,187 @@
1
+ import { Injectable, Type } from '@nestjs/common'
2
+ import { getTypeByProp } from '../utils/get-type-by-prop'
3
+ import { List } from '../utils/list'
4
+ import { AutoMappingList } from './auto-mapping-list'
5
+ import { AutoMappingProfile } from './auto-mapping-profile'
6
+
7
+ @Injectable()
8
+ export class AutoMappingService {
9
+ private readonly _contextList = AutoMappingList
10
+
11
+ constructor(automappingProfile: AutoMappingProfile) {
12
+ automappingProfile.profile()
13
+ }
14
+
15
+ private getInstanceType(
16
+ prop: () => Type<any> | ArrayConstructor,
17
+ ): Type<any> | ArrayConstructor {
18
+ try {
19
+ return prop() ?? prop
20
+ } catch {
21
+ return prop as any
22
+ }
23
+ }
24
+
25
+ map<S, T>(data: any, source: Type<S>, target: Type<T>): T {
26
+ const { mapContext, propSourceContext, propTargetContext } =
27
+ this._contextList.get(source, target)
28
+
29
+ if (!mapContext) {
30
+ throw new Error(
31
+ `No mapping context found for ${source.name} to ${target.name}`,
32
+ )
33
+ }
34
+
35
+ const mappedTarget = new target.prototype.constructor()
36
+
37
+ propSourceContext?.props.forEach((propSource) => {
38
+ const value = data[propSource.name]
39
+ const compositionType = propSource.compositionType
40
+ const compositionAction = propSource.compositionAction
41
+
42
+ if (value !== undefined) {
43
+ const targetProp = propTargetContext?.props.find(
44
+ (tp) => tp.name === propSource.name,
45
+ )
46
+
47
+ if (targetProp) {
48
+ const typeSource = getTypeByProp(propSource)
49
+ const typeTarget = getTypeByProp(targetProp)
50
+
51
+ const listToArray =
52
+ typeSource === List.name &&
53
+ typeTarget === Array.name &&
54
+ value instanceof List
55
+
56
+ const arrayToList =
57
+ typeSource === Array.name &&
58
+ typeTarget === List.name &&
59
+ value instanceof Array &&
60
+ !!compositionType
61
+
62
+ const arrayToArray =
63
+ typeSource === Array.name &&
64
+ typeTarget === Array.name &&
65
+ value instanceof Array &&
66
+ !!compositionType
67
+
68
+ let mappedValue = value
69
+
70
+ if (listToArray) {
71
+ mappedValue = this.mapListToArray(value)
72
+ } else if (arrayToList) {
73
+ mappedValue = this.mapArrayToList(
74
+ value,
75
+ this.getInstanceType(compositionType),
76
+ compositionAction === 'onlySet',
77
+ )
78
+ } else if (arrayToArray) {
79
+ mappedValue = this.mapArrayToArray(
80
+ value,
81
+ this.getInstanceType(compositionType),
82
+ )
83
+ } else {
84
+ const propSourceInstance =
85
+ this._contextList.getSourceByName(typeSource)
86
+ if (propSourceInstance) {
87
+ mappedValue = this.mapNestedProp(value, propSourceInstance)
88
+ }
89
+ }
90
+
91
+ mappedTarget[targetProp.name] = mappedValue
92
+ }
93
+ }
94
+ })
95
+
96
+ propTargetContext?.props.forEach((prop) => {
97
+ const formMemberDefinition = mapContext.forMemberDifinitions?.find(
98
+ (def) => def[prop.name],
99
+ )?.[prop.name]
100
+
101
+ if (formMemberDefinition) {
102
+ mappedTarget[prop.name] = formMemberDefinition(data)
103
+ }
104
+ })
105
+
106
+ return mappedTarget
107
+ }
108
+
109
+ private getTarget(data: any, source: Type<any>) {
110
+ if (this.isPrimitiveType(data)) {
111
+ return data
112
+ }
113
+
114
+ const targets = this._contextList.getTargets(source.prototype.constructor)
115
+
116
+ if (targets.length === 0) {
117
+ throw new Error(`No mapping context found for ${source.name}`)
118
+ }
119
+
120
+ return targets[0]
121
+ }
122
+
123
+ private mapNestedProp(data: any, source: Type<any>) {
124
+ return this.map(
125
+ data,
126
+ source.prototype.constructor,
127
+ this.getTarget(data, source),
128
+ )
129
+ }
130
+
131
+ private mapListToArray(value: List<any>) {
132
+ return value.toArray().map((item) => {
133
+ const entityOnList = value.entityType?.prototype.constructor
134
+
135
+ if (entityOnList) {
136
+ return this.mapNestedProp(item, entityOnList) ?? {}
137
+ }
138
+
139
+ return {}
140
+ })
141
+ }
142
+
143
+ private mapArrayToList(
144
+ value: Array<any>,
145
+ compositionType: Type<any>,
146
+ onlySet = true,
147
+ ) {
148
+ const list = new List(
149
+ this.getTarget(value, compositionType.prototype.constructor),
150
+ )
151
+
152
+ const mappedValue = value.map(
153
+ (item) =>
154
+ this.mapNestedProp(item, compositionType.prototype.constructor) ?? {},
155
+ )
156
+
157
+ if (onlySet) {
158
+ list.setList(mappedValue)
159
+ } else {
160
+ list.update(mappedValue)
161
+ }
162
+
163
+ return list
164
+ }
165
+
166
+ private mapArrayToArray(value: Array<any>, compositionType: Type<any>) {
167
+ return value.map(
168
+ (item) =>
169
+ this.mapNestedProp(item, compositionType.prototype.constructor) ?? {},
170
+ )
171
+ }
172
+
173
+ private isPrimitiveType(value: any) {
174
+ switch (typeof value) {
175
+ case 'string':
176
+ case 'number':
177
+ case 'bigint':
178
+ case 'boolean':
179
+ return true
180
+ case 'symbol':
181
+ case 'undefined':
182
+ case 'object':
183
+ case 'function':
184
+ return false
185
+ }
186
+ }
187
+ }
@@ -0,0 +1,11 @@
1
+ import { Type } from '@nestjs/common'
2
+ import { AutoMappingList } from './auto-mapping-list'
3
+ import { ForMemberDefinition } from './for-member'
4
+
5
+ export function createMap<TSource, TTarget>(
6
+ source: Type<TSource>,
7
+ target: Type<TTarget>,
8
+ ...formMember: ForMemberDefinition<TTarget, TSource>
9
+ ) {
10
+ AutoMappingList.add(source, target, ...formMember)
11
+ }
@@ -0,0 +1,16 @@
1
+ export type ForMemberResult<TTarget, TSource> = {
2
+ [Key in keyof TTarget]: (source: TSource) => TTarget[Key]
3
+ }
4
+
5
+ export type ForMemberDefinition<TTarget, TSource> = Array<
6
+ Partial<ForMemberResult<TTarget, TSource>>
7
+ >
8
+
9
+ export function forMember<TTarget, TSource>(
10
+ targetProp: keyof TTarget,
11
+ map: (source: TSource) => TTarget[keyof TTarget],
12
+ ): Partial<ForMemberResult<TTarget, TSource>> {
13
+ return {
14
+ [targetProp]: map,
15
+ } as Partial<ForMemberResult<TTarget, TSource>>
16
+ }
@@ -0,0 +1,8 @@
1
+ import { RequestResult } from './request-result'
2
+
3
+ export abstract class RequestHandlerBase<
4
+ TRequest,
5
+ TResponse extends RequestResult<Error, any>,
6
+ > {
7
+ abstract handle(req: TRequest): Promise<TResponse>
8
+ }
@@ -0,0 +1,23 @@
1
+ import { RequestResult, failure, ok } from './request-result'
2
+
3
+ function doSometing(shouldSuccess: boolean): RequestResult<string, number> {
4
+ if (shouldSuccess) {
5
+ return ok(10)
6
+ } else {
7
+ return failure('error')
8
+ }
9
+ }
10
+
11
+ test('success result', () => {
12
+ const result = doSometing(true)
13
+
14
+ expect(result.isOk()).toBe(true)
15
+ expect(result.isFailure()).toBe(false)
16
+ })
17
+
18
+ test('error result', () => {
19
+ const result = doSometing(false)
20
+
21
+ expect(result.isFailure()).toBe(true)
22
+ expect(result.isOk()).toBe(false)
23
+ })
@@ -0,0 +1,41 @@
1
+ export class Failure<L, R> {
2
+ readonly value: L
3
+
4
+ constructor(value: L) {
5
+ this.value = value
6
+ }
7
+
8
+ isFailure(): this is Failure<L, R> {
9
+ return true
10
+ }
11
+
12
+ isOk(): this is Ok<L, R> {
13
+ return false
14
+ }
15
+ }
16
+
17
+ export class Ok<L, R> {
18
+ readonly value: R
19
+
20
+ constructor(value: R) {
21
+ this.value = value
22
+ }
23
+
24
+ isFailure(): this is Failure<L, R> {
25
+ return false
26
+ }
27
+
28
+ isOk(): this is Ok<L, R> {
29
+ return true
30
+ }
31
+ }
32
+
33
+ export type RequestResult<L, R> = Failure<L, R> | Ok<L, R>
34
+
35
+ export const failure = <L, R>(value: L): RequestResult<L, R> => {
36
+ return new Failure(value)
37
+ }
38
+
39
+ export const ok = <L, R>(value: R): RequestResult<L, R> => {
40
+ return new Ok(value)
41
+ }
@@ -0,0 +1,33 @@
1
+ import { ZodType } from 'zod'
2
+
3
+ export abstract class RequestValidatorBase<
4
+ TRequest extends Record<string, any>,
5
+ > {
6
+ protected _request: Record<string, any>
7
+
8
+ constructor(request: TRequest) {
9
+ this._request = { ...request }
10
+ }
11
+
12
+ validate(): TRequest {
13
+ Object.keys(this._request).forEach((key) => {
14
+ if (key.includes('[]')) {
15
+ const newKey = key.replace('[]', '')
16
+ const value = this._request[key]
17
+ this._request[newKey] =
18
+ typeof value === 'string' ? value.split(',') : value
19
+ delete this._request[key]
20
+ }
21
+ })
22
+
23
+ const requestParsed = this.schema.safeParse(this._request)
24
+
25
+ if (requestParsed.success) {
26
+ return Object.assign(this._request as any, requestParsed.data)
27
+ }
28
+
29
+ throw requestParsed.error
30
+ }
31
+
32
+ protected abstract get schema(): ZodType
33
+ }
@@ -0,0 +1,45 @@
1
+ import { UnauthorizedException } from '@nestjs/common'
2
+ import { Request } from 'express'
3
+ import { Strategy } from 'passport-custom'
4
+
5
+ export type DoneFn = (err: Error | null, user?: any) => void
6
+
7
+ interface ApiKeyStrategyOptions {
8
+ header: string
9
+ prefix?: string
10
+ }
11
+
12
+ abstract class ApiKeyStrategyBase extends Strategy {
13
+ constructor({ header, prefix }: ApiKeyStrategyOptions) {
14
+ super(async (request: Request, done: DoneFn) => {
15
+ try {
16
+ const apikey = request.headers[header.toLowerCase()] as string
17
+ const apiKeyEncoded = apikey?.replace(`${prefix || ''} `, '')
18
+
19
+ if (apiKeyEncoded) {
20
+ return await this.validate(apiKeyEncoded, done, request)
21
+ }
22
+
23
+ return done(new UnauthorizedException())
24
+ } catch (err) {
25
+ return done(err, null)
26
+ }
27
+ })
28
+ }
29
+
30
+ abstract validate(
31
+ apikey: string,
32
+ done: DoneFn,
33
+ request: Request,
34
+ ): Promise<void> | void
35
+ }
36
+
37
+ export class ApiKeyStrategy extends ApiKeyStrategyBase {
38
+ constructor(options: ApiKeyStrategyOptions) {
39
+ super(options)
40
+ }
41
+
42
+ validate(apikey: string, done: DoneFn, request: Request) {
43
+ throw new Error('Method not implemented.')
44
+ }
45
+ }
@@ -0,0 +1,9 @@
1
+ import { Type } from '@nestjs/common'
2
+
3
+ export type ObjectProps<T> = {
4
+ [K in keyof T as T[K] extends Function ? never : K]: T[K]
5
+ }
6
+
7
+ export function assignObject<T>(Target: Type<T>, source: ObjectProps<T>): T {
8
+ return Object.assign(new Target() as any, source)
9
+ }
@@ -0,0 +1,17 @@
1
+ export class EnvConfig {
2
+ static get isEnvTest() {
3
+ return process.env.NODE_ENV === 'test'
4
+ }
5
+
6
+ static get isEnvDevelop() {
7
+ return process.env.NODE_ENV === 'develop'
8
+ }
9
+
10
+ static get isEnvStaging() {
11
+ return process.env.NODE_ENV === 'staging'
12
+ }
13
+
14
+ static get isEnvProduction() {
15
+ return process.env.NODE_ENV === 'production'
16
+ }
17
+ }
@@ -0,0 +1,23 @@
1
+ import { ArgumentsHost } from '@nestjs/common/interfaces'
2
+ import { Request, Response } from 'express'
3
+
4
+ export class FilterRequestParams {
5
+ static get(host: ArgumentsHost) {
6
+ const ctx = host.switchToHttp()
7
+ const response = ctx.getResponse<Response>()
8
+ const request = ctx.getRequest<Request & { user?: { login: string } }>()
9
+ const method = request.method
10
+ const isGetMethod = method === 'GET'
11
+
12
+ return {
13
+ response,
14
+ loggedUserName:
15
+ request?.user?.login ?? request.headers.origin ?? request.ip ?? '',
16
+ filterParams: {
17
+ method,
18
+ payload: !isGetMethod ? request.body : undefined,
19
+ endpoint: request.url,
20
+ },
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,18 @@
1
+ import { List } from './list'
2
+
3
+ export function findOnList<T>(
4
+ list: List<T>,
5
+ ...predicates: ((item: T) => boolean)[]
6
+ ) {
7
+ let result: T | null = null
8
+
9
+ for (const predicate of predicates) {
10
+ result = list.find(predicate)
11
+
12
+ if (result) {
13
+ break
14
+ }
15
+ }
16
+
17
+ return result
18
+ }
@@ -0,0 +1,9 @@
1
+ import { AutoMappingClassProp } from '../mapping/auto-mapping-class-context'
2
+
3
+ export function getTypeByProp(prop: AutoMappingClassProp) {
4
+ try {
5
+ return prop.type().name ?? prop.type.name ?? ''
6
+ } catch {
7
+ return prop.type.name ?? ''
8
+ }
9
+ }