@koalarx/nest-cli 1.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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/code-base/startup-project/.gitattributes +1 -0
  4. package/code-base/startup-project/LICENSE +21 -0
  5. package/code-base/startup-project/README.md +5 -0
  6. package/code-base/startup-project/eslint.config.mjs +22 -0
  7. package/code-base/startup-project/nest-cli.json +35 -0
  8. package/code-base/startup-project/package.json +68 -0
  9. package/code-base/startup-project/prisma/schema.prisma +30 -0
  10. package/code-base/startup-project/src/application/person/create/create-person.handler.spec.ts +22 -0
  11. package/code-base/startup-project/src/application/person/create/create-person.handler.ts +39 -0
  12. package/code-base/startup-project/src/application/person/create/create-person.request.ts +18 -0
  13. package/code-base/startup-project/src/application/person/create/create-person.response.ts +3 -0
  14. package/code-base/startup-project/src/application/person/create/create-person.validator.ts +16 -0
  15. package/code-base/startup-project/src/application/person/create-person-job/create-person-job.ts +57 -0
  16. package/code-base/startup-project/src/application/person/delete/delete-person.handler.spec.ts +24 -0
  17. package/code-base/startup-project/src/application/person/delete/delete-person.handler.ts +33 -0
  18. package/code-base/startup-project/src/application/person/delete-inative-job/delete-inactive-job.ts +49 -0
  19. package/code-base/startup-project/src/application/person/events/inactive-person/inactive-person-event.ts +3 -0
  20. package/code-base/startup-project/src/application/person/events/inactive-person/inactive-person-handler.ts +27 -0
  21. package/code-base/startup-project/src/application/person/events/person-event.job.ts +11 -0
  22. package/code-base/startup-project/src/application/person/read/read-person.handler.spec.ts +29 -0
  23. package/code-base/startup-project/src/application/person/read/read-person.handler.ts +37 -0
  24. package/code-base/startup-project/src/application/person/read/read-person.response.ts +30 -0
  25. package/code-base/startup-project/src/application/person/read-many/read-many-person.handler.spec.ts +72 -0
  26. package/code-base/startup-project/src/application/person/read-many/read-many-person.handler.ts +42 -0
  27. package/code-base/startup-project/src/application/person/read-many/read-many-person.request.ts +15 -0
  28. package/code-base/startup-project/src/application/person/read-many/read-many-person.response.ts +16 -0
  29. package/code-base/startup-project/src/application/person/read-many/read-many.validator.ts +16 -0
  30. package/code-base/startup-project/src/application/person/update/update-person.handler.spec.ts +42 -0
  31. package/code-base/startup-project/src/application/person/update/update-person.handler.ts +56 -0
  32. package/code-base/startup-project/src/application/person/update/update-person.request.ts +26 -0
  33. package/code-base/startup-project/src/application/person/update/update-person.validator.ts +17 -0
  34. package/code-base/startup-project/src/domain/entities/person/person-phone.ts +10 -0
  35. package/code-base/startup-project/src/domain/entities/person/person.ts +18 -0
  36. package/code-base/startup-project/src/domain/mapping/mapping.profile.ts +10 -0
  37. package/code-base/startup-project/src/domain/mapping/person.mapping.ts +24 -0
  38. package/code-base/startup-project/src/domain/repositories/iperson.repository.ts +14 -0
  39. package/code-base/startup-project/src/infra/app.module.ts +27 -0
  40. package/code-base/startup-project/src/infra/controllers/controller.module.ts +16 -0
  41. package/code-base/startup-project/src/infra/controllers/controllers.module.ts +12 -0
  42. package/code-base/startup-project/src/infra/controllers/person/create-person.controller.ts +30 -0
  43. package/code-base/startup-project/src/infra/controllers/person/delete-person.controller.ts +22 -0
  44. package/code-base/startup-project/src/infra/controllers/person/person.controller.e2e-spec.ts +120 -0
  45. package/code-base/startup-project/src/infra/controllers/person/person.module.ts +31 -0
  46. package/code-base/startup-project/src/infra/controllers/person/read-many-person.controller.ts +29 -0
  47. package/code-base/startup-project/src/infra/controllers/person/read-person.controller.ts +26 -0
  48. package/code-base/startup-project/src/infra/controllers/person/router.config.ts +9 -0
  49. package/code-base/startup-project/src/infra/controllers/person/update-person.controller.ts +30 -0
  50. package/code-base/startup-project/src/infra/database/db-transaction-context.ts +18 -0
  51. package/code-base/startup-project/src/infra/database/repositories/person.repository.ts +51 -0
  52. package/code-base/startup-project/src/infra/database/repositories/repositories.module.ts +14 -0
  53. package/code-base/startup-project/src/infra/main.ts +30 -0
  54. package/code-base/startup-project/src/test/create-e2e-test-app.ts +17 -0
  55. package/code-base/startup-project/src/test/create-unit-test-app.ts +24 -0
  56. package/code-base/startup-project/src/test/mockup/person/create-person-request.mockup.ts +8 -0
  57. package/code-base/startup-project/src/test/repositories/person.repository.ts +27 -0
  58. package/code-base/startup-project/src/test/setup-e2e.ts +7 -0
  59. package/code-base/startup-project/tsconfig.json +31 -0
  60. package/code-base/startup-project/vitest.config.e2e.mts +18 -0
  61. package/code-base/startup-project/vitest.config.mts +10 -0
  62. package/commands/new-project/index.d.ts +3 -0
  63. package/commands/new-project/index.js +80 -0
  64. package/index.d.ts +1 -0
  65. package/index.js +152 -0
  66. package/package.json +61 -0
  67. package/utils/copy-folder.d.ts +3 -0
  68. package/utils/copy-folder.js +59 -0
@@ -0,0 +1,72 @@
1
+ import { createUnitTestApp } from "@/test/create-unit-test-app"
2
+ import { createPersonRequestMockup } from "@/test/mockup/person/create-person-request.mockup"
3
+ import { CreatePersonHandler } from "../create/create-person.handler"
4
+ import { ReadManyPersonHandler } from "./read-many-person.handler"
5
+ import { ReadManyPersonRequest } from "./read-many-person.request"
6
+ import { RequestResult } from "@koalarx/nest/core/request-overflow/request-result"
7
+ import { CreatePersonResponse } from "../create/create-person.response"
8
+
9
+ describe('ReadManyPersonHandler', () => {
10
+ const app = createUnitTestApp()
11
+ const person = createPersonRequestMockup
12
+
13
+ let personId: number
14
+ let createResult: RequestResult<Error, CreatePersonResponse>
15
+
16
+ beforeAll(async () => {
17
+ createResult = await app
18
+ .get(CreatePersonHandler)
19
+ .handle(createPersonRequestMockup)
20
+
21
+ expect(createResult.isOk()).toBeTruthy()
22
+
23
+ if (createResult.isOk()) {
24
+ personId = createResult.value.id
25
+ }
26
+ })
27
+
28
+ it('should get all persons', async () => {
29
+ const result = await app
30
+ .get(ReadManyPersonHandler)
31
+ .handle(new ReadManyPersonRequest())
32
+
33
+ expect(result.value).toEqual({
34
+ items: [{
35
+ ...person,
36
+ id: personId,
37
+ status: 'inactive'
38
+ }],
39
+ count: 1
40
+ })
41
+ })
42
+
43
+ it('should get persons by name', async () => {
44
+ const result = await app
45
+ .get(ReadManyPersonHandler)
46
+ .handle(new ReadManyPersonRequest({
47
+ name: person.name
48
+ }))
49
+
50
+ expect(result.value).toEqual({
51
+ items: [{
52
+ ...person,
53
+ id: personId,
54
+ status: 'inactive'
55
+ }],
56
+ count: 1
57
+ })
58
+ })
59
+
60
+ it('should get persons by status', async () => {
61
+ const result = await app
62
+ .get(ReadManyPersonHandler)
63
+ .handle(new ReadManyPersonRequest({
64
+ active: true
65
+ }))
66
+
67
+ expect(result.value).toEqual({
68
+ items: [],
69
+ count: 0
70
+ })
71
+ })
72
+ })
@@ -0,0 +1,42 @@
1
+ import { Person } from '@/domain/entities/person/person'
2
+ import { IPersonRepository } from '@/domain/repositories/iperson.repository'
3
+ import { ResourceNotFoundError } from '@koalarx/nest/core/errors/resource-not-found.error'
4
+ import { AutoMappingService } from '@koalarx/nest/core/mapping/auto-mapping.service'
5
+ import { RequestHandlerBase } from '@koalarx/nest/core/request-overflow/request-handler.base'
6
+ import {
7
+ ok,
8
+ RequestResult,
9
+ } from '@koalarx/nest/core/request-overflow/request-result'
10
+ import { Injectable } from '@nestjs/common'
11
+ import { ReadPersonResponse } from '../read/read-person.response'
12
+ import { ReadManyPersonRequest } from './read-many-person.request'
13
+ import { ReadManyPersonResponse } from './read-many-person.response'
14
+ import { ReadManyPersonValidator } from './read-many.validator'
15
+
16
+ @Injectable()
17
+ export class ReadManyPersonHandler extends RequestHandlerBase<
18
+ ReadManyPersonRequest,
19
+ RequestResult<ResourceNotFoundError, ReadManyPersonResponse>
20
+ > {
21
+ constructor(
22
+ private readonly mapper: AutoMappingService,
23
+ private readonly repository: IPersonRepository,
24
+ ) {
25
+ super()
26
+ }
27
+
28
+ async handle(
29
+ query: ReadManyPersonRequest,
30
+ ): Promise<RequestResult<ResourceNotFoundError, ReadManyPersonResponse>> {
31
+ const listOfPerson = await this.repository.readMany(
32
+ new ReadManyPersonValidator(query).validate(),
33
+ )
34
+
35
+ return ok({
36
+ ...listOfPerson,
37
+ items: listOfPerson.items.map((person) =>
38
+ this.mapper.map(person, Person, ReadPersonResponse),
39
+ )
40
+ })
41
+ }
42
+ }
@@ -0,0 +1,15 @@
1
+ import { PaginatedRequestProps, PaginationParams } from '@koalarx/nest/core/models/pagination-params'
2
+ import { ApiProperty } from '@nestjs/swagger'
3
+
4
+ export class ReadManyPersonRequest extends PaginationParams {
5
+ @ApiProperty({ required: false })
6
+ name?: string
7
+
8
+ @ApiProperty({ required: false })
9
+ active?: boolean
10
+
11
+ constructor(props?: PaginatedRequestProps<ReadManyPersonRequest>) {
12
+ super()
13
+ Object.assign(this, props)
14
+ }
15
+ }
@@ -0,0 +1,16 @@
1
+ import { ListResponse } from '@koalarx/nest/core/@types'
2
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
3
+ import { ApiProperty } from '@nestjs/swagger'
4
+ import { ReadPersonResponse } from '../read/read-person.response'
5
+
6
+ export class ReadManyPersonResponse
7
+ implements ListResponse<ReadPersonResponse>
8
+ {
9
+ @ApiProperty({ type: [ReadPersonResponse] })
10
+ @AutoMap()
11
+ items: ReadPersonResponse[]
12
+
13
+ @ApiProperty()
14
+ @AutoMap()
15
+ count: number
16
+ }
@@ -0,0 +1,16 @@
1
+ import { booleanSchema } from '@koalarx/nest/core/controllers/schemas/boolean.schema'
2
+ import { LIST_QUERY_SCHEMA } from '@koalarx/nest/core/controllers/schemas/list-query.schema'
3
+ import { RequestValidatorBase } from '@koalarx/nest/core/request-overflow/request-validator.base'
4
+ import { z, ZodType, ZodTypeDef } from 'zod'
5
+ import { ReadManyPersonRequest } from './read-many-person.request'
6
+
7
+ export class ReadManyPersonValidator extends RequestValidatorBase<ReadManyPersonRequest> {
8
+ protected get schema(): ZodType<any, ZodTypeDef, any> {
9
+ return LIST_QUERY_SCHEMA.merge(
10
+ z.object({
11
+ name: z.string().optional().nullable(),
12
+ active: booleanSchema().optional().nullable(),
13
+ }),
14
+ )
15
+ }
16
+ }
@@ -0,0 +1,42 @@
1
+ import { createUnitTestApp } from "@/test/create-unit-test-app"
2
+ import { createPersonRequestMockup } from "@/test/mockup/person/create-person-request.mockup"
3
+ import { CreatePersonHandler } from "../create/create-person.handler"
4
+ import { ReadPersonHandler } from "../read/read-person.handler"
5
+ import { UpdatePersonHandler } from "./update-person.handler"
6
+
7
+ describe('UpdatePersonHandler', () => {
8
+ const app = createUnitTestApp()
9
+
10
+ it('should update a person by id', async () => {
11
+ const person = createPersonRequestMockup
12
+ const createResult = await app
13
+ .get(CreatePersonHandler)
14
+ .handle(createPersonRequestMockup)
15
+
16
+ expect(createResult.isOk()).toBeTruthy()
17
+
18
+ if (createResult.isOk()) {
19
+ const updateResult = await app
20
+ .get(UpdatePersonHandler)
21
+ .handle({
22
+ id: createResult.value.id,
23
+ data: {
24
+ ...person,
25
+ active: true
26
+ }
27
+ })
28
+
29
+ expect(updateResult.isOk()).toBeTruthy()
30
+
31
+ const result = await app
32
+ .get(ReadPersonHandler)
33
+ .handle(createResult.value.id)
34
+
35
+ expect(result.value).toEqual({
36
+ ...person,
37
+ id: createResult.value.id,
38
+ status: 'active'
39
+ })
40
+ }
41
+ })
42
+ })
@@ -0,0 +1,56 @@
1
+ import { Person } from '@/domain/entities/person/person'
2
+ import { IPersonRepository } from '@/domain/repositories/iperson.repository'
3
+ import { ResourceNotFoundError } from '@koalarx/nest/core/errors/resource-not-found.error'
4
+ import { AutoMappingService } from '@koalarx/nest/core/mapping/auto-mapping.service'
5
+ import { RequestHandlerBase } from '@koalarx/nest/core/request-overflow/request-handler.base'
6
+ import {
7
+ failure,
8
+ ok,
9
+ RequestResult,
10
+ } from '@koalarx/nest/core/request-overflow/request-result'
11
+ import { Injectable } from '@nestjs/common'
12
+ import { UpdatePersonRequest } from './update-person.request'
13
+ import { UpdatePersonValidator } from './update-person.validator'
14
+
15
+ type UpdatePersonHandleRequest = {
16
+ id: number
17
+ data: UpdatePersonRequest
18
+ }
19
+
20
+ @Injectable()
21
+ export class UpdatePersonHandler extends RequestHandlerBase<
22
+ UpdatePersonHandleRequest,
23
+ RequestResult<ResourceNotFoundError, null>
24
+ > {
25
+ constructor(
26
+ private readonly mapper: AutoMappingService,
27
+ private readonly repository: IPersonRepository,
28
+ ) {
29
+ super()
30
+ }
31
+
32
+ async handle({
33
+ id,
34
+ data,
35
+ }: UpdatePersonHandleRequest): Promise<RequestResult<Error, null>> {
36
+ const personInBd = await this.repository.read(id)
37
+
38
+ if (!personInBd) {
39
+ return failure(new ResourceNotFoundError('Person'))
40
+ }
41
+
42
+ const person = this.mapper.map(
43
+ new UpdatePersonValidator(data).validate(),
44
+ UpdatePersonRequest,
45
+ Person,
46
+ )
47
+
48
+ personInBd.name = person.name
49
+ personInBd.active = person.active
50
+ personInBd.phones.update(person.phones.toArray())
51
+
52
+ await this.repository.save(personInBd)
53
+
54
+ return ok(null)
55
+ }
56
+ }
@@ -0,0 +1,26 @@
1
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
2
+ import { ApiProperty } from '@nestjs/swagger'
3
+
4
+ export class UpdatePersonPhoneRequest {
5
+ @ApiProperty({required: false})
6
+ @AutoMap()
7
+ id?: number
8
+
9
+ @ApiProperty()
10
+ @AutoMap()
11
+ phone: string
12
+ }
13
+
14
+ export class UpdatePersonRequest {
15
+ @ApiProperty()
16
+ @AutoMap()
17
+ name: string
18
+
19
+ @ApiProperty()
20
+ @AutoMap()
21
+ active: boolean
22
+
23
+ @ApiProperty({ type: [UpdatePersonPhoneRequest] })
24
+ @AutoMap({ type: UpdatePersonPhoneRequest, isArray: true })
25
+ phones: Array<UpdatePersonPhoneRequest>
26
+ }
@@ -0,0 +1,17 @@
1
+ import { RequestValidatorBase } from '@koalarx/nest/core/request-overflow/request-validator.base'
2
+ import { z, ZodType, ZodTypeDef } from 'zod'
3
+ import { UpdatePersonRequest } from './update-person.request'
4
+
5
+ export class UpdatePersonValidator extends RequestValidatorBase<UpdatePersonRequest> {
6
+ protected get schema(): ZodType<any, ZodTypeDef, any> {
7
+ return z.object({
8
+ name: z.string(),
9
+ phones: z.array(
10
+ z.object({
11
+ id: z.number().nullable().optional(),
12
+ phone: z.string(),
13
+ }),
14
+ ),
15
+ })
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ import { EntityBase } from '@koalarx/nest/core/database/entity.base'
2
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
3
+
4
+ export class PersonPhone extends EntityBase<PersonPhone> {
5
+ @AutoMap()
6
+ id: number
7
+
8
+ @AutoMap()
9
+ phone: string
10
+ }
@@ -0,0 +1,18 @@
1
+ import { EntityBase } from '@koalarx/nest/core/database/entity.base'
2
+ import { AutoMap } from '@koalarx/nest/core/mapping/auto-mapping.decorator'
3
+ import { List } from '@koalarx/nest/core/utils/list'
4
+ import { PersonPhone } from './person-phone'
5
+
6
+ export class Person extends EntityBase<Person> {
7
+ @AutoMap()
8
+ id: number
9
+
10
+ @AutoMap()
11
+ name: string
12
+
13
+ @AutoMap({ type: List })
14
+ phones = new List(PersonPhone)
15
+
16
+ @AutoMap()
17
+ active: boolean
18
+ }
@@ -0,0 +1,10 @@
1
+ import { AutoMappingProfile } from '@koalarx/nest/core/mapping/auto-mapping-profile'
2
+ import { Injectable } from '@nestjs/common'
3
+ import { PersonMapping } from './person.mapping'
4
+
5
+ @Injectable()
6
+ export class MappingProfile implements AutoMappingProfile {
7
+ profile(): void {
8
+ PersonMapping.createMap()
9
+ }
10
+ }
@@ -0,0 +1,24 @@
1
+ import { CreatePersonPhoneRequest, CreatePersonRequest } from '@/application/person/create/create-person.request'
2
+ import { ReadPersonPhoneResponse, ReadPersonResponse } from '@/application/person/read/read-person.response'
3
+ import { UpdatePersonPhoneRequest, UpdatePersonRequest } from '@/application/person/update/update-person.request'
4
+ import { createMap } from '@koalarx/nest/core/mapping/create-map'
5
+ import { forMember } from '@koalarx/nest/core/mapping/for-member'
6
+ import { Person } from '../entities/person/person'
7
+ import { PersonPhone } from '../entities/person/person-phone'
8
+
9
+ export class PersonMapping {
10
+ static createMap() {
11
+ createMap(CreatePersonPhoneRequest, PersonPhone)
12
+ createMap(CreatePersonRequest, Person)
13
+
14
+ createMap(PersonPhone, ReadPersonPhoneResponse)
15
+ createMap(
16
+ Person,
17
+ ReadPersonResponse,
18
+ forMember('status', (s) => (s.active === true ? 'active' : 'inactive')),
19
+ )
20
+
21
+ createMap(UpdatePersonPhoneRequest, PersonPhone)
22
+ createMap(UpdatePersonRequest, Person)
23
+ }
24
+ }
@@ -0,0 +1,14 @@
1
+ import { CreatedRegistreResponseBase } from '@koalarx/nest/core/controllers/created-registre-response.base'
2
+ import { ListResponseBase } from '@koalarx/nest/core/controllers/list-response.base'
3
+ import { Person } from '../entities/person/person'
4
+ import { ReadManyPersonRequest } from '@/application/person/read-many/read-many-person.request'
5
+
6
+ export abstract class IPersonRepository {
7
+ abstract save(person: Person): Promise<CreatedRegistreResponseBase<number>>
8
+ abstract read(id: number): Promise<Person | null>
9
+ abstract readMany(
10
+ query: ReadManyPersonRequest,
11
+ ): Promise<ListResponseBase<Person>>
12
+
13
+ abstract delete(id: number): Promise<void>
14
+ }
@@ -0,0 +1,27 @@
1
+ import { CreatePersonJob } from '@/application/person/create-person-job/create-person-job'
2
+ import { CreatePersonHandler } from '@/application/person/create/create-person.handler'
3
+ import { DeleteInactiveJob } from '@/application/person/delete-inative-job/delete-inactive-job'
4
+ import { DeletePersonHandler } from '@/application/person/delete/delete-person.handler'
5
+ import { InactivePersonHandler } from '@/application/person/events/inactive-person/inactive-person-handler'
6
+ import { ReadManyPersonHandler } from '@/application/person/read-many/read-many-person.handler'
7
+ import { KoalaNestModule } from '@koalarx/nest/core/koala-nest.module'
8
+ import { Module } from '@nestjs/common'
9
+ import { ControllersModule } from './controllers/controllers.module'
10
+ import { RepositoriesModule } from './database/repositories/repositories.module'
11
+
12
+ @Module({
13
+ imports: [
14
+ KoalaNestModule.register(),
15
+ RepositoriesModule,
16
+ ControllersModule
17
+ ],
18
+ providers: [
19
+ CreatePersonHandler,
20
+ ReadManyPersonHandler,
21
+ DeletePersonHandler,
22
+ DeleteInactiveJob,
23
+ CreatePersonJob,
24
+ InactivePersonHandler,
25
+ ],
26
+ })
27
+ export class AppModule {}
@@ -0,0 +1,16 @@
1
+ import { MappingProfile } from '@/domain/mapping/mapping.profile'
2
+ import { KoalaNestHttpModule } from '@koalarx/nest/core/koala-nest-http.module'
3
+ import { Module } from '@nestjs/common'
4
+ import { RepositoriesModule } from '../database/repositories/repositories.module'
5
+
6
+ @Module({
7
+ imports: [
8
+ KoalaNestHttpModule.register({
9
+ automapperProfile: MappingProfile,
10
+ middlewares: [],
11
+ }),
12
+ RepositoriesModule,
13
+ ],
14
+ exports: [KoalaNestHttpModule, RepositoriesModule],
15
+ })
16
+ export class ControllerModule {}
@@ -0,0 +1,12 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { ControllerModule } from './controller.module'
3
+ import { PersonModule } from './person/person.module'
4
+
5
+ @Module({
6
+ imports: [
7
+ ControllerModule,
8
+ PersonModule,
9
+ ],
10
+ exports: [ControllerModule],
11
+ })
12
+ export class ControllersModule {}
@@ -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 { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common'
6
+ import { ApiCreatedResponse, ApiTags } from '@nestjs/swagger'
7
+ import { PERSON_ROUTER_CONFIG } from './router.config'
8
+
9
+ @ApiTags(PERSON_ROUTER_CONFIG.tag)
10
+ @Controller(PERSON_ROUTER_CONFIG.group)
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, Delete, HttpCode, HttpStatus, Param } from '@nestjs/common'
4
+ import { ApiNoContentResponse, ApiTags } from '@nestjs/swagger'
5
+ import { PERSON_ROUTER_CONFIG } from './router.config'
6
+
7
+ @ApiTags(PERSON_ROUTER_CONFIG.tag)
8
+ @Controller(PERSON_ROUTER_CONFIG.group)
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,120 @@
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
+
10
+ beforeAll(async () => {
11
+ app = await createE2ETestApp()
12
+ })
13
+
14
+ it('should create a person', async () => {
15
+ const response = await request(app.getHttpServer())
16
+ .post(PERSON_ROUTER_CONFIG.group)
17
+ .send({
18
+ name: 'John Doe',
19
+ phones: []
20
+ })
21
+
22
+ personId = response.body.id
23
+
24
+ expect(response.statusCode).toBe(201)
25
+ expect(response.body).toStrictEqual({
26
+ id: expect.any(Number)
27
+ })
28
+ })
29
+
30
+ it('should get the created person', async () => {
31
+ const response = await request(app.getHttpServer())
32
+ .get(`${PERSON_ROUTER_CONFIG.group}/${personId}`)
33
+
34
+ expect(response.statusCode).toBe(200)
35
+ expect(response.body).toStrictEqual({
36
+ id: personId,
37
+ name: 'John Doe',
38
+ phones: [],
39
+ status: 'active'
40
+ })
41
+ })
42
+
43
+ it('should get all persons', async () => {
44
+ const response = await request(app.getHttpServer())
45
+ .get(PERSON_ROUTER_CONFIG.group)
46
+
47
+ expect(response.statusCode).toBe(200)
48
+ expect(response.body).toStrictEqual({
49
+ items: [{
50
+ id: personId,
51
+ name: 'John Doe',
52
+ phones: [],
53
+ status: 'active'
54
+ }],
55
+ count: 1
56
+ })
57
+ })
58
+
59
+ it('should get all inactive persons', async () => {
60
+ const response = await request(app.getHttpServer())
61
+ .get(`${PERSON_ROUTER_CONFIG.group}?active=false`)
62
+
63
+ expect(response.statusCode).toBe(200)
64
+ expect(response.body).toStrictEqual({
65
+ items: [],
66
+ count: 0
67
+ })
68
+ })
69
+
70
+ it('should get persons by name', async () => {
71
+ const response = await request(app.getHttpServer())
72
+ .get(`${PERSON_ROUTER_CONFIG.group}?name=John`)
73
+
74
+ expect(response.statusCode).toBe(200)
75
+ expect(response.body).toStrictEqual({
76
+ items: [{
77
+ id: personId,
78
+ name: 'John Doe',
79
+ phones: [],
80
+ status: 'active'
81
+ }],
82
+ count: 1
83
+ })
84
+ })
85
+
86
+ it('should update the created person', async () => {
87
+ const updateResponse = await request(app.getHttpServer())
88
+ .put(`${PERSON_ROUTER_CONFIG.group}/${personId}`)
89
+ .send({
90
+ name: 'John Doe Updated',
91
+ phones: [],
92
+ status: 'active'
93
+ })
94
+
95
+ expect(updateResponse.statusCode).toBe(200)
96
+
97
+ const response = await request(app.getHttpServer())
98
+ .get(`${PERSON_ROUTER_CONFIG.group}/${personId}`)
99
+
100
+ expect(response.body).toStrictEqual({
101
+ id: personId,
102
+ name: 'John Doe Updated',
103
+ phones: [],
104
+ status: 'active'
105
+ })
106
+ })
107
+
108
+ it('should delete the created person', async () => {
109
+ const deleteResponse = await request(app.getHttpServer())
110
+ .delete(`${PERSON_ROUTER_CONFIG.group}/${personId}`)
111
+
112
+ expect(deleteResponse).toBeTruthy()
113
+ expect(deleteResponse.statusCode).toBe(204)
114
+
115
+ const response = await request(app.getHttpServer())
116
+ .get(`${PERSON_ROUTER_CONFIG.group}/${personId}`)
117
+
118
+ expect(response.statusCode).toBe(404)
119
+ })
120
+ })
@@ -0,0 +1,31 @@
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
+ })
31
+ export class PersonModule {}