@mikemajesty/microservice-crud 4.5.14 → 5.0.0
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/package.json +1 -1
- package/src/cli.js +8 -8
- package/src/templates/libs/service.js +1 -1
- package/src/templates/module/controller.js +4 -5
- package/src/templates/module/module.js +3 -12
- package/src/templates/module/swagger.js +3 -3
- package/src/templates/mongo/core/use-cases/__tests__/create.spec.js +26 -10
- package/src/templates/mongo/core/use-cases/__tests__/delete.spec.js +11 -9
- package/src/templates/mongo/core/use-cases/__tests__/get-by-id.spec.js +19 -17
- package/src/templates/mongo/core/use-cases/__tests__/list.spec.js +8 -6
- package/src/templates/mongo/core/use-cases/__tests__/update.spec.js +13 -10
- package/src/templates/mongo/core/use-cases/create.js +14 -8
- package/src/templates/mongo/core/use-cases/delete.js +2 -2
- package/src/templates/mongo/core/use-cases/get-by-id.js +7 -7
- package/src/templates/mongo/core/use-cases/list.js +1 -1
- package/src/templates/mongo/core/use-cases/update.js +2 -2
- package/src/templates/mongo/modules/adapter.js +3 -3
- package/src/templates/mongo/modules/controller.js +13 -11
- package/src/templates/mongo/modules/module.js +7 -7
- package/src/templates/mongo/modules/repository.js +1 -1
- package/src/templates/mongo/modules/swagger.js +30 -17
- package/src/templates/postgres/core/repository/repository.js +6 -2
- package/src/templates/postgres/core/use-cases/__tests__/create.spec.js +24 -8
- package/src/templates/postgres/core/use-cases/__tests__/delete.spec.js +11 -9
- package/src/templates/postgres/core/use-cases/__tests__/get-by-id.spec.js +19 -17
- package/src/templates/postgres/core/use-cases/__tests__/list.spec.js +8 -6
- package/src/templates/postgres/core/use-cases/__tests__/update.spec.js +11 -9
- package/src/templates/postgres/core/use-cases/create.js +13 -5
- package/src/templates/postgres/core/use-cases/delete.js +4 -4
- package/src/templates/postgres/core/use-cases/get-by-id.js +9 -9
- package/src/templates/postgres/core/use-cases/list.js +1 -1
- package/src/templates/postgres/core/use-cases/update.js +5 -5
- package/src/templates/postgres/modules/adapter.js +3 -3
- package/src/templates/postgres/modules/controller.js +13 -11
- package/src/templates/postgres/modules/module.js +12 -10
- package/src/templates/postgres/modules/repository.js +27 -23
- package/src/templates/postgres/modules/swagger.js +31 -18
- package/src/templates/postgres/schemas/schema.js +7 -21
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -21,8 +21,8 @@ const { getCoreUsecaseCreateTest } = require('./templates/postgres/core/use-case
|
|
|
21
21
|
const { getCoreUsecaseUpdateTest } = require('./templates/postgres/core/use-cases/__tests__/update.spec');
|
|
22
22
|
const { getCoreUsecaseDeleteTest } = require('./templates/postgres/core/use-cases/__tests__/delete.spec');
|
|
23
23
|
const { getCoreUsecaseListTest } = require('./templates/postgres/core/use-cases/__tests__/list.spec');
|
|
24
|
-
const {
|
|
25
|
-
const {
|
|
24
|
+
const { getCoreUsecaseGetByIDTest } = require('./templates/postgres/core/use-cases/__tests__/get-by-id.spec');
|
|
25
|
+
const { getCoreUsecaseGetByID } = require('./templates/postgres/core/use-cases/get-by-id');
|
|
26
26
|
const { getCoreUsecaseList } = require('./templates/postgres/core/use-cases/list');
|
|
27
27
|
const { getCoreEntity } = require('./templates/postgres/core/entity/entity');
|
|
28
28
|
const { getCoreRepository } = require('./templates/postgres/core/repository/repository');
|
|
@@ -41,8 +41,8 @@ const { getCoreUsecaseCreateTest: getCoreUsecaseCreateMongoTest } = require('./t
|
|
|
41
41
|
const { getCoreUsecaseUpdateTest: getCoreUsecaseUpdateMongoTest } = require('./templates/mongo/core/use-cases/__tests__/update.spec');
|
|
42
42
|
const { getCoreUsecaseDeleteTest: getCoreUsecaseDeleteMongoTest } = require('./templates/mongo/core/use-cases/__tests__/delete.spec');
|
|
43
43
|
const { getCoreUsecaseListTest: getCoreUsecaseListMongoTest } = require('./templates/mongo/core/use-cases/__tests__/list.spec');
|
|
44
|
-
const {
|
|
45
|
-
const {
|
|
44
|
+
const { getCoreUsecaseGetByIDTest: getCoreUsecaseGetByIDMongoTest } = require('./templates/mongo/core/use-cases/__tests__/get-by-id.spec');
|
|
45
|
+
const { getCoreUsecaseGetByID: getCoreUsecaseGetByIDMongo } = require('./templates/mongo/core/use-cases/get-by-id');
|
|
46
46
|
const { getCoreUsecaseList: getCoreUsecaseListMongo } = require('./templates/mongo/core/use-cases/list');
|
|
47
47
|
const { getCoreEntity: getCoreEntityMongo } = require('./templates/mongo/core/entity/entity');
|
|
48
48
|
const { getCoreRepository: getCoreRepositoryMongo } = require('./templates/mongo/core/repository/repository');
|
|
@@ -172,7 +172,7 @@ const createPostgresCrud = async (name) => {
|
|
|
172
172
|
|
|
173
173
|
fs.writeFileSync(`${useCasesPath}/${name}-create.ts`, getCoreUsecaseCreate(name))
|
|
174
174
|
fs.writeFileSync(`${useCasesPath}/${name}-delete.ts`, getCoreUsecaseDelete(name))
|
|
175
|
-
fs.writeFileSync(`${useCasesPath}/${name}-get-by-id.ts`,
|
|
175
|
+
fs.writeFileSync(`${useCasesPath}/${name}-get-by-id.ts`, getCoreUsecaseGetByID(name))
|
|
176
176
|
fs.writeFileSync(`${useCasesPath}/${name}-list.ts`, getCoreUsecaseList(name))
|
|
177
177
|
fs.writeFileSync(`${useCasesPath}/${name}-update.ts`, getCoreUsecaseUpdate(name))
|
|
178
178
|
|
|
@@ -182,7 +182,7 @@ const createPostgresCrud = async (name) => {
|
|
|
182
182
|
fs.writeFileSync(`${useCasesPathTest}/${name}-update.spec.ts`, getCoreUsecaseUpdateTest(name))
|
|
183
183
|
fs.writeFileSync(`${useCasesPathTest}/${name}-delete.spec.ts`, getCoreUsecaseDeleteTest(name))
|
|
184
184
|
fs.writeFileSync(`${useCasesPathTest}/${name}-list.spec.ts`, getCoreUsecaseListTest(name))
|
|
185
|
-
fs.writeFileSync(`${useCasesPathTest}/${name}-get-by-id.spec.ts`,
|
|
185
|
+
fs.writeFileSync(`${useCasesPathTest}/${name}-get-by-id.spec.ts`, getCoreUsecaseGetByIDTest(name))
|
|
186
186
|
|
|
187
187
|
const schemasPath = `${__dirname}/scafold/postgres/schemas`;
|
|
188
188
|
if (fs.existsSync(schemasPath)) {
|
|
@@ -244,7 +244,7 @@ const createMongoCrud = async (name) => {
|
|
|
244
244
|
|
|
245
245
|
fs.writeFileSync(`${useCasesPath}/${name}-create.ts`, getCoreUsecaseCreateMongo(name))
|
|
246
246
|
fs.writeFileSync(`${useCasesPath}/${name}-delete.ts`, getCoreUsecaseDeleteMongo(name))
|
|
247
|
-
fs.writeFileSync(`${useCasesPath}/${name}-get-by-id.ts`,
|
|
247
|
+
fs.writeFileSync(`${useCasesPath}/${name}-get-by-id.ts`, getCoreUsecaseGetByIDMongo(name))
|
|
248
248
|
fs.writeFileSync(`${useCasesPath}/${name}-list.ts`, getCoreUsecaseListMongo(name))
|
|
249
249
|
fs.writeFileSync(`${useCasesPath}/${name}-update.ts`, getCoreUsecaseUpdateMongo(name))
|
|
250
250
|
|
|
@@ -255,7 +255,7 @@ const createMongoCrud = async (name) => {
|
|
|
255
255
|
fs.writeFileSync(`${useCasesPathTest}/${name}-update.spec.ts`, getCoreUsecaseUpdateMongoTest(name))
|
|
256
256
|
fs.writeFileSync(`${useCasesPathTest}/${name}-delete.spec.ts`, getCoreUsecaseDeleteMongoTest(name))
|
|
257
257
|
fs.writeFileSync(`${useCasesPathTest}/${name}-list.spec.ts`, getCoreUsecaseListMongoTest(name))
|
|
258
|
-
fs.writeFileSync(`${useCasesPathTest}/${name}-get-by-id.spec.ts`,
|
|
258
|
+
fs.writeFileSync(`${useCasesPathTest}/${name}-get-by-id.spec.ts`, getCoreUsecaseGetByIDMongoTest(name))
|
|
259
259
|
|
|
260
260
|
const schemasPath = `${__dirname}/scafold/mongo/schemas`;
|
|
261
261
|
|
|
@@ -6,7 +6,7 @@ function capitalizeFirstLetter(string) {
|
|
|
6
6
|
const getServiceLib = (name) => `import { Injectable } from '@nestjs/common';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
|
|
9
|
-
import { ValidateSchema } from '@/
|
|
9
|
+
import { ValidateSchema } from '@/common/decorators';
|
|
10
10
|
|
|
11
11
|
import { I${capitalizeFirstLetter(name)}Adapter } from './adapter';
|
|
12
12
|
|
|
@@ -6,18 +6,17 @@ function capitalizeFirstLetter(string) {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
const getModuleControllerModule = (name) => `import { Controller, Get, Req } from '@nestjs/common';
|
|
9
|
-
import {
|
|
9
|
+
import { ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
10
10
|
|
|
11
11
|
import { ApiRequest } from '@/utils/request';
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { SwaggerResponse } from './swagger';
|
|
14
14
|
|
|
15
15
|
@Controller('${pluralize(name)}')
|
|
16
|
-
@ApiTags('${name}')
|
|
17
|
-
@ApiBearerAuth()
|
|
16
|
+
@ApiTags('${pluralize(name)}')
|
|
18
17
|
export class ${capitalizeFirstLetter(name)}Controller {
|
|
19
18
|
@Get()
|
|
20
|
-
@ApiResponse(
|
|
19
|
+
@ApiResponse(SwaggerResponse.get[200])
|
|
21
20
|
async get(@Req() {}: ApiRequest): Promise<string> {
|
|
22
21
|
return 'text';
|
|
23
22
|
}
|
|
@@ -2,24 +2,15 @@ function capitalizeFirstLetter(string) {
|
|
|
2
2
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
const getModuleModule = (name) => `import {
|
|
6
|
-
|
|
7
|
-
import { IsLoggedMiddleware } from '@/observables/middlewares';
|
|
8
|
-
import { RedisCacheModule } from '@/infra/cache/redis';
|
|
9
|
-
import { LoggerModule } from '@/infra/logger';
|
|
10
|
-
import { TokenLibModule } from '@/libs/token';
|
|
5
|
+
const getModuleModule = (name) => `import { Module } from '@nestjs/common';
|
|
11
6
|
|
|
12
7
|
import { ${capitalizeFirstLetter(name)}Controller } from './controller';
|
|
13
8
|
|
|
14
9
|
@Module({
|
|
15
|
-
imports: [
|
|
10
|
+
imports: [],
|
|
16
11
|
controllers: [${capitalizeFirstLetter(name)}Controller]
|
|
17
12
|
})
|
|
18
|
-
export class ${capitalizeFirstLetter(name)}Module
|
|
19
|
-
configure(consumer: MiddlewareConsumer) {
|
|
20
|
-
consumer.apply(IsLoggedMiddleware).forRoutes(${capitalizeFirstLetter(name)}Controller);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
13
|
+
export class ${capitalizeFirstLetter(name)}Module {}
|
|
23
14
|
`
|
|
24
15
|
|
|
25
16
|
module.exports = {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
const getModuleSwaggerModule = (name) => `import { Swagger } from '@/utils/docs/swagger';
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const SwaggerResponse = {
|
|
4
4
|
get: {
|
|
5
5
|
200: Swagger.defaultResponseJSON({
|
|
6
6
|
status: 200,
|
|
7
7
|
json: 'text',
|
|
8
|
-
description: '${name}
|
|
8
|
+
description: 'get ${name}.'
|
|
9
9
|
})
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const SwaggerRequest = {};
|
|
14
14
|
`
|
|
15
15
|
|
|
16
16
|
module.exports = {
|
|
@@ -7,13 +7,19 @@ const getCoreUsecaseCreateTest = (name) => `import { Test } from '@nestjs/testin
|
|
|
7
7
|
|
|
8
8
|
import { ILoggerAdapter } from '@/infra/logger';
|
|
9
9
|
import { I${capitalizeFirstLetter(name)}CreateAdapter } from '@/modules/${name}/adapter';
|
|
10
|
+
import { ApiInternalServerException } from '@/utils/exception';
|
|
10
11
|
import { expectZodError, getMockUUID } from '@/utils/tests';
|
|
11
12
|
|
|
12
13
|
import { ${capitalizeFirstLetter(name)}Entity } from '../../entity/${name}';
|
|
13
14
|
import { I${capitalizeFirstLetter(name)}Repository } from '../../repository/${name}';
|
|
14
15
|
import { ${capitalizeFirstLetter(name)}CreateInput, ${capitalizeFirstLetter(name)}CreateOutput, ${capitalizeFirstLetter(name)}CreateUsecase } from '../${name}-create';
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
const successInput: ${capitalizeFirstLetter(name)}CreateInput = {
|
|
18
|
+
name: 'name'
|
|
19
|
+
};
|
|
20
|
+
const failureInput: ${capitalizeFirstLetter(name)}CreateInput = {};
|
|
21
|
+
|
|
22
|
+
describe('${capitalizeFirstLetter(name)}CreateUsecase', () => {
|
|
17
23
|
let usecase: I${capitalizeFirstLetter(name)}CreateAdapter;
|
|
18
24
|
let repository: I${capitalizeFirstLetter(name)}Repository;
|
|
19
25
|
|
|
@@ -32,8 +38,8 @@ describe(${capitalizeFirstLetter(name)}CreateUsecase.name, () => {
|
|
|
32
38
|
},
|
|
33
39
|
{
|
|
34
40
|
provide: I${capitalizeFirstLetter(name)}CreateAdapter,
|
|
35
|
-
useFactory: (
|
|
36
|
-
return new ${capitalizeFirstLetter(name)}CreateUsecase(
|
|
41
|
+
useFactory: (birdRepository: I${capitalizeFirstLetter(name)}Repository, logger: ILoggerAdapter) => {
|
|
42
|
+
return new ${capitalizeFirstLetter(name)}CreateUsecase(birdRepository, logger);
|
|
37
43
|
},
|
|
38
44
|
inject: [I${capitalizeFirstLetter(name)}Repository, ILoggerAdapter]
|
|
39
45
|
}
|
|
@@ -46,24 +52,34 @@ describe(${capitalizeFirstLetter(name)}CreateUsecase.name, () => {
|
|
|
46
52
|
|
|
47
53
|
test('when no input is specified, should expect an error', async () => {
|
|
48
54
|
await expectZodError(
|
|
49
|
-
() => usecase.execute(
|
|
55
|
+
() => usecase.execute(failureInput),
|
|
50
56
|
(issues) => {
|
|
51
57
|
expect(issues).toEqual([{ message: 'Required', path: ${capitalizeFirstLetter(name)}Entity.nameOf('name') }]);
|
|
52
58
|
}
|
|
53
59
|
);
|
|
54
60
|
});
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
name: 'name'
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
test('when ${name} created successfully, should expect a ${name}', async () => {
|
|
62
|
+
test('when ${name} created successfully, should expect a ${name} that has been created', async () => {
|
|
61
63
|
const createOutput: ${capitalizeFirstLetter(name)}CreateOutput = { created: true, id: getMockUUID() };
|
|
62
64
|
|
|
63
65
|
repository.findOne = jest.fn().mockResolvedValue(null);
|
|
64
66
|
repository.create = jest.fn().mockResolvedValue(createOutput);
|
|
67
|
+
repository.startSession = jest.fn().mockResolvedValue({
|
|
68
|
+
commitTransaction: jest.fn()
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await expect(usecase.execute(successInput)).resolves.toEqual(createOutput);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('when transaction throw an error, should expect an error', async () => {
|
|
75
|
+
repository.findOne = jest.fn().mockResolvedValue(null);
|
|
76
|
+
repository.create = jest.fn().mockRejectedValue(new ApiInternalServerException());
|
|
77
|
+
repository.startSession = jest.fn().mockResolvedValue({
|
|
78
|
+
commitTransaction: jest.fn(),
|
|
79
|
+
abortTransaction: jest.fn()
|
|
80
|
+
});
|
|
65
81
|
|
|
66
|
-
await expect(usecase.execute(
|
|
82
|
+
await expect(usecase.execute(successInput)).rejects.toThrow(ApiInternalServerException);
|
|
67
83
|
});
|
|
68
84
|
});
|
|
69
85
|
`
|
|
@@ -13,7 +13,13 @@ import { ${capitalizeFirstLetter(name)}Entity } from '../../entity/${name}';
|
|
|
13
13
|
import { I${capitalizeFirstLetter(name)}Repository } from '../../repository/${name}';
|
|
14
14
|
import { ${capitalizeFirstLetter(name)}DeleteInput, ${capitalizeFirstLetter(name)}DeleteOutput, ${capitalizeFirstLetter(name)}DeleteUsecase } from '../${name}-delete';
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
const successInput: ${capitalizeFirstLetter(name)}DeleteInput = {
|
|
17
|
+
id: getMockUUID()
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const failureInput: ${capitalizeFirstLetter(name)}DeleteInput = {};
|
|
21
|
+
|
|
22
|
+
describe('${capitalizeFirstLetter(name)}DeleteUsecase', () => {
|
|
17
23
|
let usecase: I${capitalizeFirstLetter(name)}DeleteAdapter;
|
|
18
24
|
let repository: I${capitalizeFirstLetter(name)}Repository;
|
|
19
25
|
|
|
@@ -41,24 +47,20 @@ describe(${capitalizeFirstLetter(name)}DeleteUsecase.name, () => {
|
|
|
41
47
|
|
|
42
48
|
test('when no input is specified, should expect an error', async () => {
|
|
43
49
|
await expectZodError(
|
|
44
|
-
() => usecase.execute(
|
|
50
|
+
() => usecase.execute(failureInput),
|
|
45
51
|
(issues) => {
|
|
46
52
|
expect(issues).toEqual([{ message: 'Required', path: ${capitalizeFirstLetter(name)}Entity.nameOf('id') }]);
|
|
47
53
|
}
|
|
48
54
|
);
|
|
49
55
|
});
|
|
50
56
|
|
|
51
|
-
const input: ${capitalizeFirstLetter(name)}DeleteInput = {
|
|
52
|
-
id: getMockUUID()
|
|
53
|
-
};
|
|
54
|
-
|
|
55
57
|
test('when ${name} not found, should expect an error', async () => {
|
|
56
58
|
repository.findById = jest.fn().mockResolvedValue(null);
|
|
57
59
|
|
|
58
|
-
await expect(usecase.execute(
|
|
60
|
+
await expect(usecase.execute(successInput)).rejects.toThrowError(ApiNotFoundException);
|
|
59
61
|
});
|
|
60
62
|
|
|
61
|
-
test('when ${name} deleted successfully, should expect a ${name}', async () => {
|
|
63
|
+
test('when ${name} deleted successfully, should expect a ${name} that has been deleted', async () => {
|
|
62
64
|
const findByIdOutput: ${capitalizeFirstLetter(name)}DeleteOutput = new ${capitalizeFirstLetter(name)}Entity({
|
|
63
65
|
id: getMockUUID(),
|
|
64
66
|
name: 'dummy'
|
|
@@ -67,7 +69,7 @@ describe(${capitalizeFirstLetter(name)}DeleteUsecase.name, () => {
|
|
|
67
69
|
repository.findById = jest.fn().mockResolvedValue(findByIdOutput);
|
|
68
70
|
repository.updateOne = jest.fn();
|
|
69
71
|
|
|
70
|
-
await expect(usecase.execute(
|
|
72
|
+
await expect(usecase.execute(successInput)).resolves.toEqual({
|
|
71
73
|
...findByIdOutput,
|
|
72
74
|
deletedAt: expect.any(Date)
|
|
73
75
|
});
|
|
@@ -3,18 +3,24 @@ function capitalizeFirstLetter(string) {
|
|
|
3
3
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const getCoreUsecaseGetByIDTest = (name) => `import { Test } from '@nestjs/testing';
|
|
7
7
|
|
|
8
|
-
import { I${capitalizeFirstLetter(name)}
|
|
8
|
+
import { I${capitalizeFirstLetter(name)}GetByIDAdapter } from '@/modules/${name}/adapter';
|
|
9
9
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
10
10
|
import { expectZodError, getMockUUID } from '@/utils/tests';
|
|
11
11
|
|
|
12
12
|
import { ${capitalizeFirstLetter(name)}Entity } from '../../entity/${name}';
|
|
13
13
|
import { I${capitalizeFirstLetter(name)}Repository } from '../../repository/${name}';
|
|
14
|
-
import { ${capitalizeFirstLetter(name)}
|
|
14
|
+
import { ${capitalizeFirstLetter(name)}GetByIDInput, ${capitalizeFirstLetter(name)}GetByIDOutput, ${capitalizeFirstLetter(name)}GetByIdUsecase } from '../${name}-get-by-id';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const successInput: ${capitalizeFirstLetter(name)}GetByIDInput = {
|
|
17
|
+
id: getMockUUID()
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const failureInput: ${capitalizeFirstLetter(name)}GetByIDInput = {};
|
|
21
|
+
|
|
22
|
+
describe('${capitalizeFirstLetter(name)}GetByIdUsecase', () => {
|
|
23
|
+
let usecase: I${capitalizeFirstLetter(name)}GetByIDAdapter;
|
|
18
24
|
let repository: I${capitalizeFirstLetter(name)}Repository;
|
|
19
25
|
|
|
20
26
|
beforeEach(async () => {
|
|
@@ -26,7 +32,7 @@ describe(${capitalizeFirstLetter(name)}GetByIdUsecase.name, () => {
|
|
|
26
32
|
useValue: {}
|
|
27
33
|
},
|
|
28
34
|
{
|
|
29
|
-
provide: I${capitalizeFirstLetter(name)}
|
|
35
|
+
provide: I${capitalizeFirstLetter(name)}GetByIDAdapter,
|
|
30
36
|
useFactory: (${name}Repository: I${capitalizeFirstLetter(name)}Repository) => {
|
|
31
37
|
return new ${capitalizeFirstLetter(name)}GetByIdUsecase(${name}Repository);
|
|
32
38
|
},
|
|
@@ -35,42 +41,38 @@ describe(${capitalizeFirstLetter(name)}GetByIdUsecase.name, () => {
|
|
|
35
41
|
]
|
|
36
42
|
}).compile();
|
|
37
43
|
|
|
38
|
-
usecase = app.get(I${capitalizeFirstLetter(name)}
|
|
44
|
+
usecase = app.get(I${capitalizeFirstLetter(name)}GetByIDAdapter);
|
|
39
45
|
repository = app.get(I${capitalizeFirstLetter(name)}Repository);
|
|
40
46
|
});
|
|
41
47
|
|
|
42
48
|
test('when no input is specified, should expect an error', async () => {
|
|
43
49
|
await expectZodError(
|
|
44
|
-
() => usecase.execute(
|
|
50
|
+
() => usecase.execute(failureInput),
|
|
45
51
|
(issues) => {
|
|
46
52
|
expect(issues).toEqual([{ message: 'Required', path: ${capitalizeFirstLetter(name)}Entity.nameOf('id') }]);
|
|
47
53
|
}
|
|
48
54
|
);
|
|
49
55
|
});
|
|
50
56
|
|
|
51
|
-
const input: ${capitalizeFirstLetter(name)}GetByIdInput = {
|
|
52
|
-
id: getMockUUID()
|
|
53
|
-
};
|
|
54
|
-
|
|
55
57
|
test('when ${name} not found, should expect an error', async () => {
|
|
56
58
|
repository.findById = jest.fn().mockResolvedValue(null);
|
|
57
59
|
|
|
58
|
-
await expect(usecase.execute(
|
|
60
|
+
await expect(usecase.execute(successInput)).rejects.toThrowError(ApiNotFoundException);
|
|
59
61
|
});
|
|
60
62
|
|
|
61
|
-
test('when ${name} found, should expect a ${name}', async () => {
|
|
62
|
-
const findByIdOutput: ${capitalizeFirstLetter(name)}
|
|
63
|
+
test('when ${name} found, should expect a ${name} that has been found', async () => {
|
|
64
|
+
const findByIdOutput: ${capitalizeFirstLetter(name)}GetByIDOutput = new ${capitalizeFirstLetter(name)}Entity({
|
|
63
65
|
id: '61cc35f3-03d9-4b7f-9c63-59f32b013ef5',
|
|
64
66
|
name: 'dummy'
|
|
65
67
|
});
|
|
66
68
|
|
|
67
69
|
repository.findById = jest.fn().mockResolvedValue(findByIdOutput);
|
|
68
70
|
|
|
69
|
-
await expect(usecase.execute(
|
|
71
|
+
await expect(usecase.execute(successInput)).resolves.toEqual(findByIdOutput);
|
|
70
72
|
});
|
|
71
73
|
});
|
|
72
74
|
`
|
|
73
75
|
|
|
74
76
|
module.exports = {
|
|
75
|
-
|
|
77
|
+
getCoreUsecaseGetByIDTest
|
|
76
78
|
}
|
|
@@ -12,7 +12,11 @@ import { ${capitalizeFirstLetter(name)}Entity } from '../../entity/${name}';
|
|
|
12
12
|
import { I${capitalizeFirstLetter(name)}Repository } from '../../repository/${name}';
|
|
13
13
|
import { ${capitalizeFirstLetter(name)}ListInput, ${capitalizeFirstLetter(name)}ListOutput, ${capitalizeFirstLetter(name)}ListUsecase } from '../${name}-list';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const successInput: ${capitalizeFirstLetter(name)}ListInput = { limit: 1, page: 1, search: {}, sort: { createdAt: -1 } };
|
|
16
|
+
|
|
17
|
+
const failureInput: ${capitalizeFirstLetter(name)}ListInput = { search: null, sort: null, limit: 10, page: 1 };
|
|
18
|
+
|
|
19
|
+
describe('${capitalizeFirstLetter(name)}ListUsecase', () => {
|
|
16
20
|
let usecase: I${capitalizeFirstLetter(name)}ListAdapter;
|
|
17
21
|
let repository: I${capitalizeFirstLetter(name)}Repository;
|
|
18
22
|
|
|
@@ -40,15 +44,13 @@ describe(${capitalizeFirstLetter(name)}ListUsecase.name, () => {
|
|
|
40
44
|
|
|
41
45
|
test('when sort input is specified, should expect an error', async () => {
|
|
42
46
|
await expectZodError(
|
|
43
|
-
() => usecase.execute(
|
|
47
|
+
() => usecase.execute(failureInput),
|
|
44
48
|
(issues) => {
|
|
45
49
|
expect(issues).toEqual([{ message: 'Expected object, received null', path: 'sort' }]);
|
|
46
50
|
}
|
|
47
51
|
);
|
|
48
52
|
});
|
|
49
53
|
|
|
50
|
-
const input: ${capitalizeFirstLetter(name)}ListInput = { limit: 1, page: 1, search: {}, sort: { createdAt: -1 } };
|
|
51
|
-
|
|
52
54
|
test('when ${name} are found, should expect an ${name} list', async () => {
|
|
53
55
|
const doc = new ${capitalizeFirstLetter(name)}Entity({
|
|
54
56
|
id: getMockUUID(),
|
|
@@ -61,7 +63,7 @@ describe(${capitalizeFirstLetter(name)}ListUsecase.name, () => {
|
|
|
61
63
|
|
|
62
64
|
repository.paginate = jest.fn().mockResolvedValue(paginateOutput);
|
|
63
65
|
|
|
64
|
-
await expect(usecase.execute(
|
|
66
|
+
await expect(usecase.execute(successInput)).resolves.toEqual({
|
|
65
67
|
docs: [doc],
|
|
66
68
|
page: 1,
|
|
67
69
|
limit: 1,
|
|
@@ -74,7 +76,7 @@ describe(${capitalizeFirstLetter(name)}ListUsecase.name, () => {
|
|
|
74
76
|
|
|
75
77
|
repository.paginate = jest.fn().mockResolvedValue(paginateOutput);
|
|
76
78
|
|
|
77
|
-
await expect(usecase.execute(
|
|
79
|
+
await expect(usecase.execute(successInput)).resolves.toEqual(paginateOutput);
|
|
78
80
|
});
|
|
79
81
|
});
|
|
80
82
|
`
|
|
@@ -12,9 +12,16 @@ import { expectZodError, getMockUUID } from '@/utils/tests';
|
|
|
12
12
|
|
|
13
13
|
import { ${capitalizeFirstLetter(name)}Entity } from '../../entity/${name}';
|
|
14
14
|
import { I${capitalizeFirstLetter(name)}Repository } from '../../repository/${name}';
|
|
15
|
-
import { ${capitalizeFirstLetter(name)}UpdateInput, ${capitalizeFirstLetter(name)}UpdateOutput
|
|
15
|
+
import { ${capitalizeFirstLetter(name)}UpdateInput, ${capitalizeFirstLetter(name)}UpdateOutput } from '../${name}-update';
|
|
16
|
+
import { ${capitalizeFirstLetter(name)}UpdateUsecase } from '../${name}-update';
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
const successInput: ${capitalizeFirstLetter(name)}UpdateInput = {
|
|
19
|
+
id: getMockUUID()
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const failureInput: ${capitalizeFirstLetter(name)}UpdateInput = {};
|
|
23
|
+
|
|
24
|
+
describe('${capitalizeFirstLetter(name)}UpdateUsecase', () => {
|
|
18
25
|
let usecase: I${capitalizeFirstLetter(name)}UpdateAdapter;
|
|
19
26
|
let repository: I${capitalizeFirstLetter(name)}Repository;
|
|
20
27
|
|
|
@@ -42,24 +49,20 @@ describe(${capitalizeFirstLetter(name)}UpdateUsecase.name, () => {
|
|
|
42
49
|
|
|
43
50
|
test('when no input is specified, should expect an error', async () => {
|
|
44
51
|
await expectZodError(
|
|
45
|
-
() => usecase.execute(
|
|
52
|
+
() => usecase.execute(failureInput),
|
|
46
53
|
(issues) => {
|
|
47
54
|
expect(issues).toEqual([{ message: 'Required', path: ${capitalizeFirstLetter(name)}Entity.nameOf('id') }]);
|
|
48
55
|
}
|
|
49
56
|
);
|
|
50
57
|
});
|
|
51
58
|
|
|
52
|
-
const input: ${capitalizeFirstLetter(name)}UpdateInput = {
|
|
53
|
-
id: getMockUUID()
|
|
54
|
-
};
|
|
55
|
-
|
|
56
59
|
test('when ${name} not found, should expect an error', async () => {
|
|
57
60
|
repository.findById = jest.fn().mockResolvedValue(null);
|
|
58
61
|
|
|
59
|
-
await expect(usecase.execute(
|
|
62
|
+
await expect(usecase.execute(successInput)).rejects.toThrowError(ApiNotFoundException);
|
|
60
63
|
});
|
|
61
64
|
|
|
62
|
-
test('when ${name} updated successfully, should expect an ${name}', async () => {
|
|
65
|
+
test('when ${name} updated successfully, should expect an ${name} that has been updated', async () => {
|
|
63
66
|
const findByIdOutput: ${capitalizeFirstLetter(name)}UpdateOutput = new ${capitalizeFirstLetter(name)}Entity({
|
|
64
67
|
id: getMockUUID(),
|
|
65
68
|
name: 'dummy'
|
|
@@ -68,7 +71,7 @@ describe(${capitalizeFirstLetter(name)}UpdateUsecase.name, () => {
|
|
|
68
71
|
repository.findById = jest.fn().mockResolvedValue(findByIdOutput);
|
|
69
72
|
repository.updateOne = jest.fn().mockResolvedValue(null);
|
|
70
73
|
|
|
71
|
-
await expect(usecase.execute(
|
|
74
|
+
await expect(usecase.execute(successInput)).resolves.toEqual(findByIdOutput);
|
|
72
75
|
});
|
|
73
76
|
});
|
|
74
77
|
`
|
|
@@ -5,9 +5,9 @@ function capitalizeFirstLetter(string) {
|
|
|
5
5
|
|
|
6
6
|
const getCoreUsecaseCreate = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
|
+
import { ValidateSchema } from '@/common/decorators';
|
|
8
9
|
import { ILoggerAdapter } from '@/infra/logger';
|
|
9
10
|
import { CreatedModel } from '@/infra/repository';
|
|
10
|
-
import { ValidateSchema } from '@/utils/decorators';
|
|
11
11
|
import { IUsecase } from '@/utils/usecase';
|
|
12
12
|
|
|
13
13
|
import { ${capitalizeFirstLetter(name)}Entity, ${capitalizeFirstLetter(name)}EntitySchema } from '../entity/${name}';
|
|
@@ -21,19 +21,25 @@ export type ${capitalizeFirstLetter(name)}CreateInput = z.infer<typeof ${capital
|
|
|
21
21
|
export type ${capitalizeFirstLetter(name)}CreateOutput = CreatedModel;
|
|
22
22
|
|
|
23
23
|
export class ${capitalizeFirstLetter(name)}CreateUsecase implements IUsecase {
|
|
24
|
-
constructor(
|
|
25
|
-
private readonly ${name}Repository: I${capitalizeFirstLetter(name)}Repository,
|
|
26
|
-
private readonly loggerService: ILoggerAdapter
|
|
27
|
-
) {}
|
|
24
|
+
constructor(private readonly ${name}Repository: I${capitalizeFirstLetter(name)}Repository, private readonly loggerService: ILoggerAdapter) {}
|
|
28
25
|
|
|
29
26
|
@ValidateSchema(${capitalizeFirstLetter(name)}CreateSchema)
|
|
30
27
|
async execute(input: ${capitalizeFirstLetter(name)}CreateInput): Promise<${capitalizeFirstLetter(name)}CreateOutput> {
|
|
31
28
|
const entity = new ${capitalizeFirstLetter(name)}Entity(input);
|
|
32
29
|
|
|
33
|
-
const
|
|
30
|
+
const session = await this.${name}Repository.startSession();
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
try {
|
|
33
|
+
const ${name} = await this.${name}Repository.create(entity, { session });
|
|
34
|
+
|
|
35
|
+
await session.commitTransaction();
|
|
36
|
+
|
|
37
|
+
this.loggerService.info({ message: '${name} created.', obj: { ${name} } });
|
|
38
|
+
return ${name};
|
|
39
|
+
} catch (error) {
|
|
40
|
+
await session.abortTransaction();
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
`
|
|
@@ -5,7 +5,7 @@ function capitalizeFirstLetter(string) {
|
|
|
5
5
|
|
|
6
6
|
const getCoreUsecaseDelete = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
import { ValidateSchema } from '@/
|
|
8
|
+
import { ValidateSchema } from '@/common/decorators';
|
|
9
9
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
10
10
|
import { IUsecase } from '@/utils/usecase';
|
|
11
11
|
|
|
@@ -27,7 +27,7 @@ export class ${capitalizeFirstLetter(name)}DeleteUsecase implements IUsecase {
|
|
|
27
27
|
const model = await this.${name}Repository.findById(id);
|
|
28
28
|
|
|
29
29
|
if (!model) {
|
|
30
|
-
throw new ApiNotFoundException(
|
|
30
|
+
throw new ApiNotFoundException();
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const ${name} = new ${capitalizeFirstLetter(name)}Entity(model);
|
|
@@ -3,9 +3,9 @@ function capitalizeFirstLetter(string) {
|
|
|
3
3
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const getCoreUsecaseGetByID = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
import { ValidateSchema } from '@/
|
|
8
|
+
import { ValidateSchema } from '@/common/decorators';
|
|
9
9
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
10
10
|
import { IUsecase } from '@/utils/usecase';
|
|
11
11
|
|
|
@@ -15,18 +15,18 @@ import { I${capitalizeFirstLetter(name)}Repository } from '../repository/${name}
|
|
|
15
15
|
export const ${capitalizeFirstLetter(name)}GetByIdSchema = ${capitalizeFirstLetter(name)}EntitySchema.pick({
|
|
16
16
|
id: true
|
|
17
17
|
});
|
|
18
|
-
export type ${capitalizeFirstLetter(name)}
|
|
19
|
-
export type ${capitalizeFirstLetter(name)}
|
|
18
|
+
export type ${capitalizeFirstLetter(name)}GetByIDInput = z.infer<typeof ${capitalizeFirstLetter(name)}GetByIdSchema>;
|
|
19
|
+
export type ${capitalizeFirstLetter(name)}GetByIDOutput = ${capitalizeFirstLetter(name)}Entity;
|
|
20
20
|
|
|
21
21
|
export class ${capitalizeFirstLetter(name)}GetByIdUsecase implements IUsecase {
|
|
22
22
|
constructor(private readonly ${name}Repository: I${capitalizeFirstLetter(name)}Repository) {}
|
|
23
23
|
|
|
24
24
|
@ValidateSchema(${capitalizeFirstLetter(name)}GetByIdSchema)
|
|
25
|
-
async execute({ id }: ${capitalizeFirstLetter(name)}
|
|
25
|
+
async execute({ id }: ${capitalizeFirstLetter(name)}GetByIDInput): Promise<${capitalizeFirstLetter(name)}GetByIDOutput> {
|
|
26
26
|
const ${name} = await this.${name}Repository.findById(id);
|
|
27
27
|
|
|
28
28
|
if (!${name}) {
|
|
29
|
-
throw new ApiNotFoundException(
|
|
29
|
+
throw new ApiNotFoundException();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const entity = new ${capitalizeFirstLetter(name)}Entity(${name});
|
|
@@ -37,5 +37,5 @@ export class ${capitalizeFirstLetter(name)}GetByIdUsecase implements IUsecase {
|
|
|
37
37
|
`
|
|
38
38
|
|
|
39
39
|
module.exports = {
|
|
40
|
-
|
|
40
|
+
getCoreUsecaseGetByID
|
|
41
41
|
}
|
|
@@ -6,7 +6,7 @@ function capitalizeFirstLetter(string) {
|
|
|
6
6
|
|
|
7
7
|
const getCoreUsecaseList = (name) => `import { z } from 'zod';
|
|
8
8
|
|
|
9
|
-
import { ValidateSchema } from '@/
|
|
9
|
+
import { ValidateSchema } from '@/common/decorators';
|
|
10
10
|
import { PaginationInput, PaginationOutput, PaginationSchema } from '@/utils/pagination';
|
|
11
11
|
import { SearchSchema } from '@/utils/search';
|
|
12
12
|
import { SortSchema } from '@/utils/sort';
|
|
@@ -5,7 +5,7 @@ function capitalizeFirstLetter(string) {
|
|
|
5
5
|
|
|
6
6
|
const getCoreUsecaseUpdate = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
import { ValidateSchema } from '@/
|
|
8
|
+
import { ValidateSchema } from '@/common/decorators';
|
|
9
9
|
import { ILoggerAdapter } from '@/infra/logger';
|
|
10
10
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
11
11
|
import { IUsecase } from '@/utils/usecase';
|
|
@@ -28,7 +28,7 @@ export class ${capitalizeFirstLetter(name)}UpdateUsecase implements IUsecase {
|
|
|
28
28
|
const ${name} = await this.${name}Repository.findById(input.id);
|
|
29
29
|
|
|
30
30
|
if (!${name}) {
|
|
31
|
-
throw new ApiNotFoundException(
|
|
31
|
+
throw new ApiNotFoundException();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const ${name}Finded = new ${capitalizeFirstLetter(name)}Entity(${name});
|
|
@@ -5,7 +5,7 @@ function capitalizeFirstLetter(string) {
|
|
|
5
5
|
|
|
6
6
|
const getModuleAdapter = (name) => `import { ${capitalizeFirstLetter(name)}CreateInput, ${capitalizeFirstLetter(name)}CreateOutput } from '@/core/${name}/use-cases/${name}-create';
|
|
7
7
|
import { ${capitalizeFirstLetter(name)}DeleteInput, ${capitalizeFirstLetter(name)}DeleteOutput } from '@/core/${name}/use-cases/${name}-delete';
|
|
8
|
-
import { ${capitalizeFirstLetter(name)}
|
|
8
|
+
import { ${capitalizeFirstLetter(name)}GetByIDInput, ${capitalizeFirstLetter(name)}GetByIDOutput } from '@/core/${name}/use-cases/${name}-get-by-id';
|
|
9
9
|
import { ${capitalizeFirstLetter(name)}ListInput, ${capitalizeFirstLetter(name)}ListOutput } from '@/core/${name}/use-cases/${name}-list';
|
|
10
10
|
import { ${capitalizeFirstLetter(name)}UpdateInput, ${capitalizeFirstLetter(name)}UpdateOutput } from '@/core/${name}/use-cases/${name}-update';
|
|
11
11
|
import { IUsecase } from '@/utils/usecase';
|
|
@@ -26,8 +26,8 @@ export abstract class I${capitalizeFirstLetter(name)}DeleteAdapter implements IU
|
|
|
26
26
|
abstract execute(input: ${capitalizeFirstLetter(name)}DeleteInput): Promise<${capitalizeFirstLetter(name)}DeleteOutput>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export abstract class I${capitalizeFirstLetter(name)}
|
|
30
|
-
abstract execute(input: ${capitalizeFirstLetter(name)}
|
|
29
|
+
export abstract class I${capitalizeFirstLetter(name)}GetByIDAdapter implements IUsecase {
|
|
30
|
+
abstract execute(input: ${capitalizeFirstLetter(name)}GetByIDInput): Promise<${capitalizeFirstLetter(name)}GetByIDOutput>;
|
|
31
31
|
}
|
|
32
32
|
`
|
|
33
33
|
|