@koalarx/nest-cli 3.0.2 → 3.0.4

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/commands/new-project/index.js +70 -0
  3. package/commands/new-project/new-project.js +69 -0
  4. package/index.js +39 -0
  5. package/package.json +9 -3
  6. package/templates/startup-project/.prettierrc.json +9 -0
  7. package/templates/startup-project/eslint.config.mts +85 -0
  8. package/templates/{root-files-folders → startup-project}/package.json +1 -1
  9. package/templates/startup-project/prisma/migrations/20250320165043_init/migration.sql +19 -0
  10. package/templates/startup-project/prisma/migrations/20250320171528_aplicando_map_de_tabelas_e_colunas/migration.sql +35 -0
  11. package/templates/startup-project/prisma/migrations/20250321190248_incluindo_status_ao_person/migration.sql +2 -0
  12. package/templates/startup-project/prisma/migrations/20250326185507_incluindo_tabela_de_endereco/migration.sql +19 -0
  13. package/templates/startup-project/prisma/migrations/20250326195627_aplicando_on_delete_cascade/migration.sql +5 -0
  14. package/templates/startup-project/prisma/migrations/20250326200821_removendo_ondelete_cascade/migration.sql +5 -0
  15. package/templates/startup-project/prisma/migrations/migration_lock.toml +3 -0
  16. package/templates/startup-project/prisma/schema.prisma +39 -0
  17. package/templates/startup-project/prisma.config.ts +8 -0
  18. package/templates/startup-project/src/application/mapping/mapping.profile.ts +10 -0
  19. package/templates/startup-project/src/application/mapping/person.mapping.ts +39 -0
  20. package/templates/startup-project/src/application/person/common/persist-person.request.ts +28 -0
  21. package/templates/startup-project/src/application/person/create/create-person.handler.spec.ts +22 -0
  22. package/templates/startup-project/src/application/person/create/create-person.handler.ts +39 -0
  23. package/templates/startup-project/src/application/person/create/create-person.request.ts +11 -0
  24. package/templates/startup-project/src/application/person/create/create-person.response.ts +3 -0
  25. package/templates/startup-project/src/application/person/create/create-person.validator.ts +19 -0
  26. package/templates/startup-project/src/application/person/create-person-job/create-person-job.ts +58 -0
  27. package/templates/startup-project/src/application/person/delete/delete-person.handler.spec.ts +24 -0
  28. package/templates/startup-project/src/application/person/delete/delete-person.handler.ts +33 -0
  29. package/templates/startup-project/src/application/person/delete-inative-job/delete-inactive-job.ts +49 -0
  30. package/templates/startup-project/src/application/person/events/inactive-person/inactive-person-event.ts +3 -0
  31. package/templates/startup-project/src/application/person/events/inactive-person/inactive-person-handler.ts +27 -0
  32. package/templates/startup-project/src/application/person/events/person-event.job.ts +11 -0
  33. package/templates/startup-project/src/application/person/read/read-person.handler.spec.ts +28 -0
  34. package/templates/startup-project/src/application/person/read/read-person.handler.ts +37 -0
  35. package/templates/startup-project/src/application/person/read/read-person.response.ts +44 -0
  36. package/templates/startup-project/src/application/person/read-many/read-many-person.handler.spec.ts +67 -0
  37. package/templates/startup-project/src/application/person/read-many/read-many-person.handler.ts +47 -0
  38. package/templates/startup-project/src/application/person/read-many/read-many-person.request.ts +21 -0
  39. package/templates/startup-project/src/application/person/read-many/read-many-person.response.ts +16 -0
  40. package/templates/startup-project/src/application/person/read-many/read-many.validator.ts +16 -0
  41. package/templates/startup-project/src/application/person/update/update-person.handler.spec.ts +47 -0
  42. package/templates/startup-project/src/application/person/update/update-person.handler.ts +57 -0
  43. package/templates/startup-project/src/application/person/update/update-person.request.ts +36 -0
  44. package/templates/startup-project/src/application/person/update/update-person.validator.ts +21 -0
  45. package/templates/startup-project/src/core/env.ts +6 -0
  46. package/templates/startup-project/src/domain/dtos/read-many-person.dto.ts +16 -0
  47. package/templates/startup-project/src/domain/entities/person/person-address.ts +12 -0
  48. package/templates/startup-project/src/domain/entities/person/person-phone.ts +12 -0
  49. package/templates/startup-project/src/domain/entities/person/person.ts +24 -0
  50. package/templates/startup-project/src/domain/repositories/iperson.repository.ts +10 -0
  51. package/templates/startup-project/src/host/app.module.ts +19 -0
  52. package/templates/startup-project/src/host/controllers/controller.module.ts +16 -0
  53. package/templates/startup-project/src/host/controllers/person/create-person.controller.ts +30 -0
  54. package/templates/startup-project/src/host/controllers/person/delete-person.controller.ts +22 -0
  55. package/templates/startup-project/src/host/controllers/person/person.controller.e2e-spec.ts +158 -0
  56. package/templates/startup-project/src/host/controllers/person/person.module.ts +37 -0
  57. package/templates/startup-project/src/host/controllers/person/read-many-person.controller.ts +29 -0
  58. package/templates/startup-project/src/host/controllers/person/read-person.controller.ts +26 -0
  59. package/templates/startup-project/src/host/controllers/person/router.config.ts +9 -0
  60. package/templates/startup-project/src/host/controllers/person/update-person.controller.ts +30 -0
  61. package/templates/startup-project/src/host/main.ts +38 -0
  62. package/templates/startup-project/src/infra/database/db-transaction-context.ts +24 -0
  63. package/templates/startup-project/src/infra/database/repositories/person.repository.ts +54 -0
  64. package/templates/startup-project/src/infra/database/repositories/repositories.module.ts +15 -0
  65. package/templates/startup-project/src/infra/infra.module.ts +8 -0
  66. package/templates/startup-project/src/test/create-e2e-test-app.ts +27 -0
  67. package/templates/startup-project/src/test/create-unit-test-app.ts +24 -0
  68. package/templates/startup-project/src/test/mockup/person/create-person-request.mockup.ts +9 -0
  69. package/templates/startup-project/src/test/repositories/person.repository.ts +36 -0
  70. package/templates/startup-project/src/test/setup-e2e.ts +12 -0
  71. package/templates/startup-project/tsconfig.app.json +8 -0
  72. package/tsconfig.tsbuildinfo +1 -0
  73. package/CHANGELOG.md +0 -11
  74. package/src/commands/new-project/index.ts +0 -99
  75. package/src/commands/new-project/new-project.ts +0 -91
  76. package/src/index.ts +0 -51
  77. package/tsconfig.json +0 -14
  78. /package/templates/{root-files-folders → startup-project}/.dockerignore +0 -0
  79. /package/templates/{root-files-folders → startup-project}/.gitattributes +0 -0
  80. /package/templates/{root-files-folders → startup-project}/.vscode/launch.json +0 -0
  81. /package/templates/{root-files-folders → startup-project}/.vscode/mcp.json +0 -0
  82. /package/templates/{root-files-folders → startup-project}/.vscode/settings.json +0 -0
  83. /package/templates/{root-files-folders → startup-project}/.vscode/tasks.json +0 -0
  84. /package/templates/{root-files-folders → startup-project}/Dockerfile +0 -0
  85. /package/templates/{root-files-folders → startup-project}/README.md +0 -0
  86. /package/templates/{root-files-folders → startup-project}/bunfig.toml +0 -0
  87. /package/templates/{root-files-folders → startup-project}/nest-cli.json +0 -0
  88. /package/templates/{root-files-folders → startup-project}/tsconfig.build.json +0 -0
  89. /package/templates/{root-files-folders → startup-project}/tsconfig.json +0 -0
  90. /package/templates/{root-files-folders → startup-project}/tsconfig.prisma.json +0 -0
@@ -0,0 +1,16 @@
1
+ import { PaginatedRequestProps } from '@koalarx/nest/core/controllers/pagination.request'
2
+ import { PaginationDto } from '@koalarx/nest/core/dtos/pagination.dto'
3
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
4
+
5
+ export class ReadManyPersonDto extends PaginationDto {
6
+ @AutoMap()
7
+ name?: string
8
+
9
+ @AutoMap()
10
+ active?: boolean
11
+
12
+ constructor(props?: PaginatedRequestProps<ReadManyPersonDto>) {
13
+ super()
14
+ Object.assign(this, props)
15
+ }
16
+ }
@@ -0,0 +1,12 @@
1
+ import { EntityBase } from '@koalarx/nest/core/database/entity.base'
2
+ import { Entity } from '@koalarx/nest/core/database/entity.decorator'
3
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
4
+
5
+ @Entity()
6
+ export class PersonAddress extends EntityBase<PersonAddress> {
7
+ @AutoMap()
8
+ id: number
9
+
10
+ @AutoMap()
11
+ address: string
12
+ }
@@ -0,0 +1,12 @@
1
+ import { EntityBase } from '@koalarx/nest/core/database/entity.base'
2
+ import { Entity } from '@koalarx/nest/core/database/entity.decorator'
3
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
4
+
5
+ @Entity()
6
+ export class PersonPhone extends EntityBase<PersonPhone> {
7
+ @AutoMap()
8
+ id: number
9
+
10
+ @AutoMap()
11
+ phone: string
12
+ }
@@ -0,0 +1,24 @@
1
+ import { EntityBase } from '@koalarx/nest/core/database/entity.base'
2
+ import { Entity } from '@koalarx/nest/core/database/entity.decorator'
3
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
4
+ import { List } from '@koalarx/nest/core/utils/list'
5
+ import { PersonAddress } from './person-address'
6
+ import { PersonPhone } from './person-phone'
7
+
8
+ @Entity()
9
+ export class Person extends EntityBase<Person> {
10
+ @AutoMap()
11
+ id: number
12
+
13
+ @AutoMap()
14
+ name: string
15
+
16
+ @AutoMap({ type: () => List })
17
+ phones = new List(PersonPhone)
18
+
19
+ @AutoMap({ type: () => PersonAddress })
20
+ address: PersonAddress
21
+
22
+ @AutoMap()
23
+ active: boolean
24
+ }
@@ -0,0 +1,10 @@
1
+ import { ListResponseBase } from '@koalarx/nest/core/controllers/list-response.base'
2
+ import { ReadManyPersonDto } from '../dtos/read-many-person.dto'
3
+ import { Person } from '../entities/person/person'
4
+
5
+ export abstract class IPersonRepository {
6
+ abstract save(person: Person): Promise<any>
7
+ abstract read(id: number): Promise<Person | null>
8
+ abstract readMany(query: ReadManyPersonDto): Promise<ListResponseBase<Person>>
9
+ abstract delete(id: number): Promise<void>
10
+ }
@@ -0,0 +1,19 @@
1
+ import { CreatePersonJob } from '@/application/person/create-person-job/create-person-job'
2
+ import { DeleteInactiveJob } from '@/application/person/delete-inative-job/delete-inactive-job'
3
+ import { InactivePersonHandler } from '@/application/person/events/inactive-person/inactive-person-handler'
4
+ import { env } from '@/core/env'
5
+ import { KoalaNestModule } from '@koalarx/nest/core/koala-nest.module'
6
+ import { Module } from '@nestjs/common'
7
+ import { PersonModule } from './controllers/person/person.module'
8
+
9
+ @Module({
10
+ imports: [
11
+ KoalaNestModule.register({
12
+ env,
13
+ controllers: [PersonModule],
14
+ cronJobs: [DeleteInactiveJob, CreatePersonJob],
15
+ eventJobs: [InactivePersonHandler],
16
+ }),
17
+ ],
18
+ })
19
+ export class AppModule {}
@@ -0,0 +1,16 @@
1
+ import { MappingProfile } from '@/application/mapping/mapping.profile'
2
+ import { InfraModule } from '@/infra/infra.module'
3
+ import { KoalaNestHttpModule } from '@koalarx/nest/core/koala-nest-http.module'
4
+ import { Module } from '@nestjs/common'
5
+
6
+ @Module({
7
+ imports: [
8
+ KoalaNestHttpModule.register({
9
+ imports: [InfraModule],
10
+ automapperProfile: MappingProfile,
11
+ middlewares: [],
12
+ }),
13
+ ],
14
+ exports: [KoalaNestHttpModule],
15
+ })
16
+ export class ControllerModule {}
@@ -0,0 +1,30 @@
1
+ import { CreatePersonHandler } from '@/application/person/create/create-person.handler'
2
+ import { CreatePersonRequest } from '@/application/person/create/create-person.request'
3
+ import { CreatePersonResponse } from '@/application/person/create/create-person.response'
4
+ import { IController } from '@koalarx/nest/core/controllers/base.controller'
5
+ import { Controller } from '@koalarx/nest/core/controllers/controller.decorator'
6
+ import { Body, HttpCode, HttpStatus, Post } from '@nestjs/common'
7
+ import { ApiCreatedResponse } from '@nestjs/swagger'
8
+ import { PERSON_ROUTER_CONFIG } from './router.config'
9
+
10
+ @Controller(PERSON_ROUTER_CONFIG)
11
+ export class CreatePersonController
12
+ implements IController<CreatePersonRequest, CreatePersonResponse>
13
+ {
14
+ constructor(private readonly handler: CreatePersonHandler) {}
15
+
16
+ @Post()
17
+ @ApiCreatedResponse({ type: CreatePersonResponse })
18
+ @HttpCode(HttpStatus.CREATED)
19
+ async handle(
20
+ @Body() request: CreatePersonRequest,
21
+ ): Promise<CreatePersonResponse> {
22
+ const response = await this.handler.handle(request)
23
+
24
+ if (response.isFailure()) {
25
+ throw response.value
26
+ }
27
+
28
+ return response.value
29
+ }
30
+ }
@@ -0,0 +1,22 @@
1
+ import { DeletePersonHandler } from '@/application/person/delete/delete-person.handler'
2
+ import { IController } from '@koalarx/nest/core/controllers/base.controller'
3
+ import { Controller } from '@koalarx/nest/core/controllers/controller.decorator'
4
+ import { Delete, HttpCode, HttpStatus, Param } from '@nestjs/common'
5
+ import { ApiNoContentResponse } from '@nestjs/swagger'
6
+ import { PERSON_ROUTER_CONFIG } from './router.config'
7
+
8
+ @Controller(PERSON_ROUTER_CONFIG)
9
+ export class DeletePersonController implements IController<null, void, string> {
10
+ constructor(private readonly handler: DeletePersonHandler) {}
11
+
12
+ @Delete(':id')
13
+ @ApiNoContentResponse()
14
+ @HttpCode(HttpStatus.NO_CONTENT)
15
+ async handle(_, @Param('id') id: string): Promise<void> {
16
+ const response = await this.handler.handle(+id)
17
+
18
+ if (response.isFailure()) {
19
+ throw response.value
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,158 @@
1
+ import { createE2ETestApp } from '@/test/create-e2e-test-app'
2
+ import { INestApplication } from '@nestjs/common'
3
+ import request from 'supertest'
4
+ import { PERSON_ROUTER_CONFIG } from './router.config'
5
+
6
+ describe(`CRUD OF PERSON`, () => {
7
+ let app: INestApplication
8
+ let personId: number
9
+ let addressId: number
10
+
11
+ beforeAll(async () => {
12
+ app = await createE2ETestApp()
13
+ })
14
+
15
+ it('should create a person', async () => {
16
+ const response = await request(app.getHttpServer())
17
+ .post(PERSON_ROUTER_CONFIG.group)
18
+ .send({
19
+ name: 'John Doe',
20
+ phones: [],
21
+ address: {
22
+ address: 'Streat 1',
23
+ },
24
+ })
25
+
26
+ personId = response.body.id
27
+
28
+ expect(response.statusCode).toBe(201)
29
+ expect(response.body).toStrictEqual({
30
+ id: expect.any(Number),
31
+ })
32
+ })
33
+
34
+ it('should get the created person', async () => {
35
+ const response = await request(app.getHttpServer()).get(
36
+ `${PERSON_ROUTER_CONFIG.group}/${personId}`,
37
+ )
38
+
39
+ // Capturar o ID do endereço da resposta
40
+ addressId = response.body.address.id
41
+
42
+ expect(response.statusCode).toBe(200)
43
+ expect(response.body).toStrictEqual({
44
+ id: personId,
45
+ name: 'John Doe',
46
+ phones: [],
47
+ address: {
48
+ id: expect.any(Number),
49
+ address: 'Streat 1',
50
+ },
51
+ active: true,
52
+ })
53
+ })
54
+
55
+ it('should get all persons', async () => {
56
+ const response = await request(app.getHttpServer()).get(
57
+ PERSON_ROUTER_CONFIG.group,
58
+ )
59
+
60
+ expect(response.statusCode).toBe(200)
61
+ expect(response.body).toStrictEqual({
62
+ items: [
63
+ {
64
+ id: personId,
65
+ name: 'John Doe',
66
+ phones: [],
67
+ address: {
68
+ id: addressId,
69
+ address: 'Streat 1',
70
+ },
71
+ active: true,
72
+ },
73
+ ],
74
+ count: 1,
75
+ })
76
+ })
77
+
78
+ it('should get all inactive persons', async () => {
79
+ const response = await request(app.getHttpServer()).get(
80
+ `${PERSON_ROUTER_CONFIG.group}?active=false`,
81
+ )
82
+
83
+ expect(response.statusCode).toBe(200)
84
+ expect(response.body).toStrictEqual({
85
+ items: [],
86
+ count: 0,
87
+ })
88
+ })
89
+
90
+ it('should get persons by name', async () => {
91
+ const response = await request(app.getHttpServer()).get(
92
+ `${PERSON_ROUTER_CONFIG.group}?name=John`,
93
+ )
94
+
95
+ expect(response.statusCode).toBe(200)
96
+ expect(response.body).toStrictEqual({
97
+ items: [
98
+ {
99
+ id: personId,
100
+ name: 'John Doe',
101
+ phones: [],
102
+ address: {
103
+ id: addressId,
104
+ address: 'Streat 1',
105
+ },
106
+ active: true,
107
+ },
108
+ ],
109
+ count: 1,
110
+ })
111
+ })
112
+
113
+ it('should update the created person', async () => {
114
+ const updateResponse = await request(app.getHttpServer())
115
+ .put(`${PERSON_ROUTER_CONFIG.group}/${personId}`)
116
+ .send({
117
+ name: 'John Doe Updated',
118
+ phones: [],
119
+ address: {
120
+ id: addressId,
121
+ address: 'Streat 2',
122
+ },
123
+ active: true,
124
+ })
125
+
126
+ expect(updateResponse.statusCode).toBe(200)
127
+
128
+ const response = await request(app.getHttpServer()).get(
129
+ `${PERSON_ROUTER_CONFIG.group}/${personId}`,
130
+ )
131
+
132
+ expect(response.body).toStrictEqual({
133
+ id: personId,
134
+ name: 'John Doe Updated',
135
+ phones: [],
136
+ address: {
137
+ id: addressId,
138
+ address: 'Streat 2',
139
+ },
140
+ active: true,
141
+ })
142
+ })
143
+
144
+ it('should delete the created person', async () => {
145
+ const deleteResponse = await request(app.getHttpServer()).delete(
146
+ `${PERSON_ROUTER_CONFIG.group}/${personId}`,
147
+ )
148
+
149
+ expect(deleteResponse).toBeTruthy()
150
+ expect(deleteResponse.statusCode).toBe(204)
151
+
152
+ const response = await request(app.getHttpServer()).get(
153
+ `${PERSON_ROUTER_CONFIG.group}/${personId}`,
154
+ )
155
+
156
+ expect(response.statusCode).toBe(404)
157
+ })
158
+ })
@@ -0,0 +1,37 @@
1
+ import { CreatePersonHandler } from '@/application/person/create/create-person.handler'
2
+ import { DeletePersonHandler } from '@/application/person/delete/delete-person.handler'
3
+ import { ReadManyPersonHandler } from '@/application/person/read-many/read-many-person.handler'
4
+ import { ReadPersonHandler } from '@/application/person/read/read-person.handler'
5
+ import { UpdatePersonHandler } from '@/application/person/update/update-person.handler'
6
+ import { Module } from '@nestjs/common'
7
+ import { ControllerModule } from '../controller.module'
8
+ import { CreatePersonController } from './create-person.controller'
9
+ import { DeletePersonController } from './delete-person.controller'
10
+ import { ReadManyPersonController } from './read-many-person.controller'
11
+ import { ReadPersonController } from './read-person.controller'
12
+ import { UpdatePersonController } from './update-person.controller'
13
+
14
+ @Module({
15
+ imports: [ControllerModule],
16
+ controllers: [
17
+ CreatePersonController,
18
+ ReadPersonController,
19
+ ReadManyPersonController,
20
+ UpdatePersonController,
21
+ DeletePersonController,
22
+ ],
23
+ providers: [
24
+ CreatePersonHandler,
25
+ ReadPersonHandler,
26
+ ReadManyPersonHandler,
27
+ UpdatePersonHandler,
28
+ DeletePersonHandler,
29
+ ],
30
+ exports: [
31
+ ControllerModule,
32
+ CreatePersonHandler,
33
+ ReadManyPersonHandler,
34
+ DeletePersonHandler,
35
+ ],
36
+ })
37
+ export class PersonModule {}
@@ -0,0 +1,29 @@
1
+ import { ReadManyPersonHandler } from '@/application/person/read-many/read-many-person.handler'
2
+ import { ReadManyPersonRequest } from '@/application/person/read-many/read-many-person.request'
3
+ import { ReadManyPersonResponse } from '@/application/person/read-many/read-many-person.response'
4
+ import { IController } from '@koalarx/nest/core/controllers/base.controller'
5
+ import { Controller } from '@koalarx/nest/core/controllers/controller.decorator'
6
+ import { Get, Query } from '@nestjs/common'
7
+ import { ApiOkResponse } from '@nestjs/swagger'
8
+ import { PERSON_ROUTER_CONFIG } from './router.config'
9
+
10
+ @Controller(PERSON_ROUTER_CONFIG)
11
+ export class ReadManyPersonController
12
+ implements IController<ReadManyPersonRequest, ReadManyPersonResponse>
13
+ {
14
+ constructor(private readonly handler: ReadManyPersonHandler) {}
15
+
16
+ @Get()
17
+ @ApiOkResponse({ type: ReadManyPersonResponse })
18
+ async handle(
19
+ @Query() query: ReadManyPersonRequest,
20
+ ): Promise<ReadManyPersonResponse> {
21
+ const response = await this.handler.handle(query)
22
+
23
+ if (response.isFailure()) {
24
+ throw response.value
25
+ }
26
+
27
+ return response.value
28
+ }
29
+ }
@@ -0,0 +1,26 @@
1
+ import { ReadPersonHandler } from '@/application/person/read/read-person.handler'
2
+ import { ReadPersonResponse } from '@/application/person/read/read-person.response'
3
+ import { IController } from '@koalarx/nest/core/controllers/base.controller'
4
+ import { Controller } from '@koalarx/nest/core/controllers/controller.decorator'
5
+ import { Get, Param } from '@nestjs/common'
6
+ import { ApiOkResponse } from '@nestjs/swagger'
7
+ import { PERSON_ROUTER_CONFIG } from './router.config'
8
+
9
+ @Controller(PERSON_ROUTER_CONFIG)
10
+ export class ReadPersonController
11
+ implements IController<null, ReadPersonResponse, string>
12
+ {
13
+ constructor(private readonly handler: ReadPersonHandler) {}
14
+
15
+ @Get(':id')
16
+ @ApiOkResponse({ type: ReadPersonResponse })
17
+ async handle(_, @Param('id') id: string): Promise<ReadPersonResponse> {
18
+ const response = await this.handler.handle(+id)
19
+
20
+ if (response.isFailure()) {
21
+ throw response.value
22
+ }
23
+
24
+ return response.value
25
+ }
26
+ }
@@ -0,0 +1,9 @@
1
+ import { RouterConfigBase } from '@koalarx/nest/core/controllers/router-config.base'
2
+
3
+ class PersonRouterConfig extends RouterConfigBase {
4
+ constructor() {
5
+ super('Person', '/person')
6
+ }
7
+ }
8
+
9
+ export const PERSON_ROUTER_CONFIG = new PersonRouterConfig()
@@ -0,0 +1,30 @@
1
+ import { UpdatePersonHandler } from '@/application/person/update/update-person.handler'
2
+ import { UpdatePersonRequest } from '@/application/person/update/update-person.request'
3
+ import { IController } from '@koalarx/nest/core/controllers/base.controller'
4
+ import { Controller } from '@koalarx/nest/core/controllers/controller.decorator'
5
+ import { Body, Param, Put } from '@nestjs/common'
6
+ import { ApiOkResponse } from '@nestjs/swagger'
7
+ import { PERSON_ROUTER_CONFIG } from './router.config'
8
+
9
+ @Controller(PERSON_ROUTER_CONFIG)
10
+ export class UpdatePersonController
11
+ implements IController<UpdatePersonRequest, void>
12
+ {
13
+ constructor(private readonly handler: UpdatePersonHandler) {}
14
+
15
+ @Put(':id')
16
+ @ApiOkResponse()
17
+ async handle(
18
+ @Body() request: UpdatePersonRequest,
19
+ @Param('id') id: string,
20
+ ): Promise<void> {
21
+ const response = await this.handler.handle({
22
+ id: +id,
23
+ data: request,
24
+ })
25
+
26
+ if (response.isFailure()) {
27
+ throw response.value
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,38 @@
1
+ import { CreatePersonJob } from '@/application/person/create-person-job/create-person-job'
2
+ import { DeleteInactiveJob } from '@/application/person/delete-inative-job/delete-inactive-job'
3
+ import { InactivePersonHandler } from '@/application/person/events/inactive-person/inactive-person-handler'
4
+ import { DbTransactionContext } from '@/infra/database/db-transaction-context'
5
+ import { setPrismaClientOptions } from '@koalarx/nest/core/database/prisma.service'
6
+ import { KoalaApp } from '@koalarx/nest/core/koala-app'
7
+ import { NestFactory } from '@nestjs/core'
8
+ import { PrismaPg } from '@prisma/adapter-pg'
9
+ import 'dotenv/config'
10
+ import { Pool } from 'pg'
11
+ import { AppModule } from './app.module'
12
+
13
+ async function bootstrap() {
14
+ const pool = new Pool({
15
+ connectionString: process.env.DATABASE_URL,
16
+ })
17
+ const adapter = new PrismaPg(pool)
18
+ setPrismaClientOptions({ adapter })
19
+
20
+ return NestFactory.create(AppModule).then((app) =>
21
+ new KoalaApp(app)
22
+ .useDoc({
23
+ ui: 'scalar',
24
+ endpoint: '/doc',
25
+ title: 'API de Demonstração',
26
+ version: '1.0',
27
+ })
28
+ .addCronJob(CreatePersonJob)
29
+ .addCronJob(DeleteInactiveJob)
30
+ .addEventJob(InactivePersonHandler)
31
+ .setAppName('example')
32
+ .setInternalUserName('integration.bot')
33
+ .setDbTransactionContext(DbTransactionContext)
34
+ .enableCors()
35
+ .buildAndServe(),
36
+ )
37
+ }
38
+ bootstrap()
@@ -0,0 +1,24 @@
1
+ import { PrismaClientWithCustomTransaction } from '@koalarx/nest/core/database/prisma-client-with-custom-transaction.interface'
2
+ import { PrismaTransactionalClient } from '@koalarx/nest/core/database/prisma-transactional-client'
3
+ import { DefaultArgs } from '@prisma/client/runtime/client'
4
+ import { Prisma } from 'prisma/generated/client'
5
+
6
+ export class DbTransactionContext
7
+ extends PrismaTransactionalClient
8
+ implements PrismaClientWithCustomTransaction
9
+ {
10
+ get person(): Prisma.PersonDelegate<DefaultArgs> {
11
+ return this.transactionalClient.person
12
+ }
13
+
14
+ get personPhone(): Prisma.PersonPhoneDelegate<DefaultArgs> {
15
+ return this.transactionalClient.personPhone
16
+ }
17
+
18
+ get personAddress(): Prisma.PersonAddressDelegate<
19
+ DefaultArgs,
20
+ Prisma.PrismaClientOptions
21
+ > {
22
+ return this.transactionalClient.personAddress
23
+ }
24
+ }
@@ -0,0 +1,54 @@
1
+ import { ReadManyPersonDto } from '@/domain/dtos/read-many-person.dto'
2
+ import { Person } from '@/domain/entities/person/person'
3
+ import { IPersonRepository } from '@/domain/repositories/iperson.repository'
4
+ import { CreatedRegistreWithIdResponse } from '@koalarx/nest/core/controllers/created-registre-response.base'
5
+ import { ListResponseBase } from '@koalarx/nest/core/controllers/list-response.base'
6
+ import { RepositoryBase } from '@koalarx/nest/core/database/repository.base'
7
+ import { PRISMA_TOKEN } from '@koalarx/nest/core/koala-nest-database.module'
8
+ import { Inject, Injectable } from '@nestjs/common'
9
+ import { Prisma } from 'prisma/generated/client'
10
+ import { DbTransactionContext } from '../db-transaction-context'
11
+
12
+ @Injectable()
13
+ export class PersonRepository
14
+ extends RepositoryBase<Person>
15
+ implements IPersonRepository
16
+ {
17
+ constructor(
18
+ @Inject(PRISMA_TOKEN)
19
+ prisma: DbTransactionContext,
20
+ ) {
21
+ super({
22
+ modelName: Person,
23
+ context: prisma,
24
+ include: {
25
+ phones: true,
26
+ address: true,
27
+ },
28
+ })
29
+ }
30
+
31
+ async save(person: Person): Promise<CreatedRegistreWithIdResponse | null> {
32
+ return this.saveChanges(person)
33
+ }
34
+
35
+ read(id: number): Promise<Person | null> {
36
+ return this.findById(id)
37
+ }
38
+
39
+ readMany(query: ReadManyPersonDto): Promise<ListResponseBase<Person>> {
40
+ return this.findManyAndCount<Prisma.PersonWhereInput>(
41
+ {
42
+ name: {
43
+ contains: query.name,
44
+ },
45
+ active: query.active,
46
+ },
47
+ query,
48
+ )
49
+ }
50
+
51
+ delete(id: number): Promise<void> {
52
+ return this.remove<Prisma.PersonWhereUniqueInput>({ id })
53
+ }
54
+ }
@@ -0,0 +1,15 @@
1
+ import { IPersonRepository } from '@/domain/repositories/iperson.repository'
2
+ import { KoalaNestDatabaseModule } from '@koalarx/nest/core/koala-nest-database.module'
3
+ import { Module } from '@nestjs/common'
4
+ import { PersonRepository } from './person.repository'
5
+
6
+ @Module({
7
+ imports: [
8
+ KoalaNestDatabaseModule.register({
9
+ repositories: [{ interface: IPersonRepository, class: PersonRepository }],
10
+ services: [],
11
+ }),
12
+ ],
13
+ exports: [KoalaNestDatabaseModule],
14
+ })
15
+ export class RepositoriesModule {}
@@ -0,0 +1,8 @@
1
+ import { RepositoriesModule } from '@/infra/database/repositories/repositories.module'
2
+ import { Module } from '@nestjs/common'
3
+
4
+ @Module({
5
+ imports: [RepositoriesModule],
6
+ exports: [RepositoriesModule],
7
+ })
8
+ export class InfraModule {}
@@ -0,0 +1,27 @@
1
+ import { AppModule } from '@/host/app.module'
2
+ import { DbTransactionContext } from '@/infra/database/db-transaction-context'
3
+ import { setPrismaClientOptions } from '@koalarx/nest/core/database/prisma.service'
4
+ import { KoalaAppTest } from '@koalarx/nest/test/koala-app-test'
5
+ import { Test } from '@nestjs/testing'
6
+ import { PrismaPg } from '@prisma/adapter-pg'
7
+ import 'dotenv/config'
8
+ import { Pool } from 'pg'
9
+
10
+ export async function createE2ETestApp() {
11
+ const pool = new Pool({
12
+ connectionString: process.env.DATABASE_URL,
13
+ })
14
+ const adapter = new PrismaPg(pool)
15
+ setPrismaClientOptions({ adapter })
16
+
17
+ return Test.createTestingModule({ imports: [AppModule] })
18
+ .compile()
19
+ .then((moduleRef) => moduleRef.createNestApplication())
20
+ .then((app) =>
21
+ new KoalaAppTest(app)
22
+ .setDbTransactionContext(DbTransactionContext)
23
+ .enableCors()
24
+ .build(),
25
+ )
26
+ .then((app) => app.init())
27
+ }
@@ -0,0 +1,24 @@
1
+ import { CreatePersonHandler } from '@/application/person/create/create-person.handler'
2
+ import { MappingProfile } from '@/application/mapping/mapping.profile'
3
+ import { AutoMappingService } from '@koalarx/nest/core/mapping/auto-mapping.service'
4
+ import { KoalaAppTestDependencies } from '@koalarx/nest/test/koala-app-test-dependencies'
5
+ import { PersonRepository } from './repositories/person.repository'
6
+ import { DeletePersonHandler } from '@/application/person/delete/delete-person.handler'
7
+ import { ReadPersonHandler } from '@/application/person/read/read-person.handler'
8
+ import { ReadManyPersonHandler } from '@/application/person/read-many/read-many-person.handler'
9
+ import { UpdatePersonHandler } from '@/application/person/update/update-person.handler'
10
+
11
+ export function createUnitTestApp() {
12
+ const automapService = new AutoMappingService(new MappingProfile())
13
+ const personRepository = new PersonRepository()
14
+
15
+ return new KoalaAppTestDependencies({
16
+ dependencies: [
17
+ new CreatePersonHandler(automapService, personRepository),
18
+ new ReadPersonHandler(automapService, personRepository),
19
+ new ReadManyPersonHandler(automapService, personRepository),
20
+ new UpdatePersonHandler(automapService, personRepository),
21
+ new DeletePersonHandler(personRepository),
22
+ ],
23
+ })
24
+ }