@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.
- package/LICENSE +21 -0
- package/README.md +17 -0
- package/code-base/startup-project/.gitattributes +1 -0
- package/code-base/startup-project/LICENSE +21 -0
- package/code-base/startup-project/README.md +5 -0
- package/code-base/startup-project/eslint.config.mjs +22 -0
- package/code-base/startup-project/nest-cli.json +35 -0
- package/code-base/startup-project/package.json +68 -0
- package/code-base/startup-project/prisma/schema.prisma +30 -0
- package/code-base/startup-project/src/application/person/create/create-person.handler.spec.ts +22 -0
- package/code-base/startup-project/src/application/person/create/create-person.handler.ts +39 -0
- package/code-base/startup-project/src/application/person/create/create-person.request.ts +18 -0
- package/code-base/startup-project/src/application/person/create/create-person.response.ts +3 -0
- package/code-base/startup-project/src/application/person/create/create-person.validator.ts +16 -0
- package/code-base/startup-project/src/application/person/create-person-job/create-person-job.ts +57 -0
- package/code-base/startup-project/src/application/person/delete/delete-person.handler.spec.ts +24 -0
- package/code-base/startup-project/src/application/person/delete/delete-person.handler.ts +33 -0
- package/code-base/startup-project/src/application/person/delete-inative-job/delete-inactive-job.ts +49 -0
- package/code-base/startup-project/src/application/person/events/inactive-person/inactive-person-event.ts +3 -0
- package/code-base/startup-project/src/application/person/events/inactive-person/inactive-person-handler.ts +27 -0
- package/code-base/startup-project/src/application/person/events/person-event.job.ts +11 -0
- package/code-base/startup-project/src/application/person/read/read-person.handler.spec.ts +29 -0
- package/code-base/startup-project/src/application/person/read/read-person.handler.ts +37 -0
- package/code-base/startup-project/src/application/person/read/read-person.response.ts +30 -0
- package/code-base/startup-project/src/application/person/read-many/read-many-person.handler.spec.ts +72 -0
- package/code-base/startup-project/src/application/person/read-many/read-many-person.handler.ts +42 -0
- package/code-base/startup-project/src/application/person/read-many/read-many-person.request.ts +15 -0
- package/code-base/startup-project/src/application/person/read-many/read-many-person.response.ts +16 -0
- package/code-base/startup-project/src/application/person/read-many/read-many.validator.ts +16 -0
- package/code-base/startup-project/src/application/person/update/update-person.handler.spec.ts +42 -0
- package/code-base/startup-project/src/application/person/update/update-person.handler.ts +56 -0
- package/code-base/startup-project/src/application/person/update/update-person.request.ts +26 -0
- package/code-base/startup-project/src/application/person/update/update-person.validator.ts +17 -0
- package/code-base/startup-project/src/domain/entities/person/person-phone.ts +10 -0
- package/code-base/startup-project/src/domain/entities/person/person.ts +18 -0
- package/code-base/startup-project/src/domain/mapping/mapping.profile.ts +10 -0
- package/code-base/startup-project/src/domain/mapping/person.mapping.ts +24 -0
- package/code-base/startup-project/src/domain/repositories/iperson.repository.ts +14 -0
- package/code-base/startup-project/src/infra/app.module.ts +27 -0
- package/code-base/startup-project/src/infra/controllers/controller.module.ts +16 -0
- package/code-base/startup-project/src/infra/controllers/controllers.module.ts +12 -0
- package/code-base/startup-project/src/infra/controllers/person/create-person.controller.ts +30 -0
- package/code-base/startup-project/src/infra/controllers/person/delete-person.controller.ts +22 -0
- package/code-base/startup-project/src/infra/controllers/person/person.controller.e2e-spec.ts +120 -0
- package/code-base/startup-project/src/infra/controllers/person/person.module.ts +31 -0
- package/code-base/startup-project/src/infra/controllers/person/read-many-person.controller.ts +29 -0
- package/code-base/startup-project/src/infra/controllers/person/read-person.controller.ts +26 -0
- package/code-base/startup-project/src/infra/controllers/person/router.config.ts +9 -0
- package/code-base/startup-project/src/infra/controllers/person/update-person.controller.ts +30 -0
- package/code-base/startup-project/src/infra/database/db-transaction-context.ts +18 -0
- package/code-base/startup-project/src/infra/database/repositories/person.repository.ts +51 -0
- package/code-base/startup-project/src/infra/database/repositories/repositories.module.ts +14 -0
- package/code-base/startup-project/src/infra/main.ts +30 -0
- package/code-base/startup-project/src/test/create-e2e-test-app.ts +17 -0
- package/code-base/startup-project/src/test/create-unit-test-app.ts +24 -0
- package/code-base/startup-project/src/test/mockup/person/create-person-request.mockup.ts +8 -0
- package/code-base/startup-project/src/test/repositories/person.repository.ts +27 -0
- package/code-base/startup-project/src/test/setup-e2e.ts +7 -0
- package/code-base/startup-project/tsconfig.json +31 -0
- package/code-base/startup-project/vitest.config.e2e.mts +18 -0
- package/code-base/startup-project/vitest.config.mts +10 -0
- package/commands/new-project/index.d.ts +3 -0
- package/commands/new-project/index.js +80 -0
- package/index.d.ts +1 -0
- package/index.js +152 -0
- package/package.json +61 -0
- package/utils/copy-folder.d.ts +3 -0
- package/utils/copy-folder.js +59 -0
package/code-base/startup-project/src/application/person/read-many/read-many-person.handler.spec.ts
ADDED
|
@@ -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
|
+
})
|
package/code-base/startup-project/src/application/person/read-many/read-many-person.handler.ts
ADDED
|
@@ -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
|
+
}
|
package/code-base/startup-project/src/application/person/read-many/read-many-person.request.ts
ADDED
|
@@ -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
|
+
}
|
package/code-base/startup-project/src/application/person/read-many/read-many-person.response.ts
ADDED
|
@@ -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 {}
|