@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.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +8 -8
  3. package/src/templates/libs/service.js +1 -1
  4. package/src/templates/module/controller.js +4 -5
  5. package/src/templates/module/module.js +3 -12
  6. package/src/templates/module/swagger.js +3 -3
  7. package/src/templates/mongo/core/use-cases/__tests__/create.spec.js +26 -10
  8. package/src/templates/mongo/core/use-cases/__tests__/delete.spec.js +11 -9
  9. package/src/templates/mongo/core/use-cases/__tests__/get-by-id.spec.js +19 -17
  10. package/src/templates/mongo/core/use-cases/__tests__/list.spec.js +8 -6
  11. package/src/templates/mongo/core/use-cases/__tests__/update.spec.js +13 -10
  12. package/src/templates/mongo/core/use-cases/create.js +14 -8
  13. package/src/templates/mongo/core/use-cases/delete.js +2 -2
  14. package/src/templates/mongo/core/use-cases/get-by-id.js +7 -7
  15. package/src/templates/mongo/core/use-cases/list.js +1 -1
  16. package/src/templates/mongo/core/use-cases/update.js +2 -2
  17. package/src/templates/mongo/modules/adapter.js +3 -3
  18. package/src/templates/mongo/modules/controller.js +13 -11
  19. package/src/templates/mongo/modules/module.js +7 -7
  20. package/src/templates/mongo/modules/repository.js +1 -1
  21. package/src/templates/mongo/modules/swagger.js +30 -17
  22. package/src/templates/postgres/core/repository/repository.js +6 -2
  23. package/src/templates/postgres/core/use-cases/__tests__/create.spec.js +24 -8
  24. package/src/templates/postgres/core/use-cases/__tests__/delete.spec.js +11 -9
  25. package/src/templates/postgres/core/use-cases/__tests__/get-by-id.spec.js +19 -17
  26. package/src/templates/postgres/core/use-cases/__tests__/list.spec.js +8 -6
  27. package/src/templates/postgres/core/use-cases/__tests__/update.spec.js +11 -9
  28. package/src/templates/postgres/core/use-cases/create.js +13 -5
  29. package/src/templates/postgres/core/use-cases/delete.js +4 -4
  30. package/src/templates/postgres/core/use-cases/get-by-id.js +9 -9
  31. package/src/templates/postgres/core/use-cases/list.js +1 -1
  32. package/src/templates/postgres/core/use-cases/update.js +5 -5
  33. package/src/templates/postgres/modules/adapter.js +3 -3
  34. package/src/templates/postgres/modules/controller.js +13 -11
  35. package/src/templates/postgres/modules/module.js +12 -10
  36. package/src/templates/postgres/modules/repository.js +27 -23
  37. package/src/templates/postgres/modules/swagger.js +31 -18
  38. package/src/templates/postgres/schemas/schema.js +7 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikemajesty/microservice-crud",
3
- "version": "4.5.14",
3
+ "version": "5.0.0",
4
4
  "description": "Monorepo CLI",
5
5
  "main": "src/cli.js",
6
6
  "scripts": {
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 { getCoreUsecaseGetByIdTest } = require('./templates/postgres/core/use-cases/__tests__/get-by-id.spec');
25
- const { getCoreUsecaseGetById } = require('./templates/postgres/core/use-cases/get-by-id');
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 { 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');
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`, getCoreUsecaseGetById(name))
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`, getCoreUsecaseGetByIdTest(name))
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`, getCoreUsecaseGetByIdMongo(name))
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`, getCoreUsecaseGetByIdMongoTest(name))
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 '@/utils/decorators';
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 { ApiBearerAuth, ApiResponse, ApiTags } from '@nestjs/swagger';
9
+ import { ApiResponse, ApiTags } from '@nestjs/swagger';
10
10
 
11
11
  import { ApiRequest } from '@/utils/request';
12
12
 
13
- import { SwagggerResponse } from './swagger';
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(SwagggerResponse.get[200])
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 { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
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: [TokenLibModule, LoggerModule, RedisCacheModule],
10
+ imports: [],
16
11
  controllers: [${capitalizeFirstLetter(name)}Controller]
17
12
  })
18
- export class ${capitalizeFirstLetter(name)}Module implements NestModule {
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 SwagggerResponse = {
3
+ export const SwaggerResponse = {
4
4
  get: {
5
5
  200: Swagger.defaultResponseJSON({
6
6
  status: 200,
7
7
  json: 'text',
8
- description: '${name} get.'
8
+ description: 'get ${name}.'
9
9
  })
10
10
  }
11
11
  };
12
12
 
13
- export const SwagggerRequest = {};
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
- describe(${capitalizeFirstLetter(name)}CreateUsecase.name, () => {
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: (${name}Repository: I${capitalizeFirstLetter(name)}Repository, logger: ILoggerAdapter) => {
36
- return new ${capitalizeFirstLetter(name)}CreateUsecase(${name}Repository, logger);
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
- const input: ${capitalizeFirstLetter(name)}CreateInput = {
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(input)).resolves.toEqual(createOutput);
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
- describe(${capitalizeFirstLetter(name)}DeleteUsecase.name, () => {
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(input)).rejects.toThrow(ApiNotFoundException);
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(input)).resolves.toEqual({
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 getCoreUsecaseGetByIdTest = (name) => `import { Test } from '@nestjs/testing';
6
+ const getCoreUsecaseGetByIDTest = (name) => `import { Test } from '@nestjs/testing';
7
7
 
8
- import { I${capitalizeFirstLetter(name)}GetByIdAdapter } from '@/modules/${name}/adapter';
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)}GetByIdInput, ${capitalizeFirstLetter(name)}GetByIdOutput, ${capitalizeFirstLetter(name)}GetByIdUsecase } from '../${name}-get-by-id';
14
+ import { ${capitalizeFirstLetter(name)}GetByIDInput, ${capitalizeFirstLetter(name)}GetByIDOutput, ${capitalizeFirstLetter(name)}GetByIdUsecase } from '../${name}-get-by-id';
15
15
 
16
- describe(${capitalizeFirstLetter(name)}GetByIdUsecase.name, () => {
17
- let usecase: I${capitalizeFirstLetter(name)}GetByIdAdapter;
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)}GetByIdAdapter,
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)}GetByIdAdapter);
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(input)).rejects.toThrow(ApiNotFoundException);
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)}GetByIdOutput = new ${capitalizeFirstLetter(name)}Entity({
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(input)).resolves.toEqual(findByIdOutput);
71
+ await expect(usecase.execute(successInput)).resolves.toEqual(findByIdOutput);
70
72
  });
71
73
  });
72
74
  `
73
75
 
74
76
  module.exports = {
75
- getCoreUsecaseGetByIdTest
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
- describe(${capitalizeFirstLetter(name)}ListUsecase.name, () => {
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({ search: null, sort: null, limit: 10, page: 1 }),
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(input)).resolves.toEqual({
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(input)).resolves.toEqual(paginateOutput);
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, ${capitalizeFirstLetter(name)}UpdateUsecase } from '../${name}-update';
15
+ import { ${capitalizeFirstLetter(name)}UpdateInput, ${capitalizeFirstLetter(name)}UpdateOutput } from '../${name}-update';
16
+ import { ${capitalizeFirstLetter(name)}UpdateUsecase } from '../${name}-update';
16
17
 
17
- describe(${capitalizeFirstLetter(name)}UpdateUsecase.name, () => {
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(input)).rejects.toThrow(ApiNotFoundException);
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(input)).resolves.toEqual(findByIdOutput);
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 ${name} = await this.${name}Repository.create(entity);
30
+ const session = await this.${name}Repository.startSession();
34
31
 
35
- this.loggerService.info({ message: '${name} created.', obj: { ${name} } });
36
- return ${name};
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 '@/utils/decorators';
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('${name}NotFound');
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 getCoreUsecaseGetById = (name) => `import { z } from 'zod';
6
+ const getCoreUsecaseGetByID = (name) => `import { z } from 'zod';
7
7
 
8
- import { ValidateSchema } from '@/utils/decorators';
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)}GetByIdInput = z.infer<typeof ${capitalizeFirstLetter(name)}GetByIdSchema>;
19
- export type ${capitalizeFirstLetter(name)}GetByIdOutput = ${capitalizeFirstLetter(name)}Entity;
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)}GetByIdInput): Promise<${capitalizeFirstLetter(name)}GetByIdOutput> {
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('${name}NotFound');
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
- getCoreUsecaseGetById
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 '@/utils/decorators';
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 '@/utils/decorators';
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('${name}NotFound');
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)}GetByIdInput, ${capitalizeFirstLetter(name)}GetByIdOutput } from '@/core/${name}/use-cases/${name}-get-by-id';
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)}GetByIdAdapter implements IUsecase {
30
- abstract execute(input: ${capitalizeFirstLetter(name)}GetByIdInput): Promise<${capitalizeFirstLetter(name)}GetByIdOutput>;
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