update packages, clean code

This commit is contained in:
sbriat 2023-10-17 11:41:12 +02:00
parent aa77a64cd2
commit b3232e3896
25 changed files with 3308 additions and 3061 deletions

View File

@ -10,6 +10,7 @@ DATABASE_URL="postgresql://mobicoop:mobicoop@v3-db:5432/mobicoop?schema=user"
# MESSAGE BROKER # MESSAGE BROKER
MESSAGE_BROKER_URI=amqp://v3-broker:5672 MESSAGE_BROKER_URI=amqp://v3-broker:5672
MESSAGE_BROKER_EXCHANGE=mobicoop MESSAGE_BROKER_EXCHANGE=mobicoop
MESSAGE_BROKER_EXCHANGE_DURABILITY=true
# REDIS # REDIS
REDIS_HOST=v3-redis REDIS_HOST=v3-redis

6104
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -30,53 +30,53 @@
"migrate:deploy": "npx prisma migrate deploy" "migrate:deploy": "npx prisma migrate deploy"
}, },
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.8.0", "@grpc/grpc-js": "^1.9.5",
"@grpc/proto-loader": "^0.7.4", "@grpc/proto-loader": "^0.7.10",
"@liaoliaots/nestjs-redis": "^9.0.5", "@songkeys/nestjs-redis": "^10.0.0",
"@mobicoop/configuration-module": "^1.2.0", "@mobicoop/configuration-module": "^2.0.0",
"@mobicoop/ddd-library": "^1.0.0", "@mobicoop/ddd-library": "^2.0.0",
"@mobicoop/health-module": "^2.0.0", "@mobicoop/health-module": "^2.3.1",
"@mobicoop/message-broker-module": "^1.2.0", "@mobicoop/message-broker-module": "^2.1.1",
"@nestjs/cache-manager": "^1.0.0", "@nestjs/cache-manager": "^2.1.0",
"@nestjs/common": "^9.0.0", "@nestjs/common": "^10.2.7",
"@nestjs/config": "^2.2.0", "@nestjs/config": "^3.1.1",
"@nestjs/core": "^9.0.0", "@nestjs/core": "^10.2.7",
"@nestjs/cqrs": "^9.0.1", "@nestjs/cqrs": "^10.2.6",
"@nestjs/event-emitter": "^2.0.0", "@nestjs/event-emitter": "^2.0.2",
"@nestjs/microservices": "^9.2.1", "@nestjs/microservices": "^10.2.7",
"@nestjs/platform-express": "^9.0.0", "@nestjs/platform-express": "^10.2.7",
"@nestjs/terminus": "^9.2.2", "@nestjs/terminus": "^10.1.1",
"@prisma/client": "^4.7.1", "@prisma/client": "^5.4.2",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.14",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^6.8.0",
"@typescript-eslint/parser": "^5.0.0", "@typescript-eslint/parser": "^6.8.0",
"cache-manager": "^5.2.1", "cache-manager": "^5.2.4",
"cache-manager-ioredis-yet": "^1.1.0", "cache-manager-ioredis-yet": "^1.2.2",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.0", "class-validator": "^0.14.0",
"dotenv-cli": "^6.0.0", "dotenv-cli": "^7.3.0",
"ioredis": "^5.3.0" "ioredis": "^5.3.2"
}, },
"devDependencies": { "devDependencies": {
"@nestjs/cli": "^9.0.0", "@nestjs/cli": "^10.1.18",
"@nestjs/schematics": "^9.0.0", "@nestjs/schematics": "^10.0.2",
"@nestjs/testing": "^9.0.0", "@nestjs/testing": "^10.2.7",
"@types/jest": "^29.2.5", "@types/jest": "^29.5.5",
"@types/node": "^18.11.18", "@types/node": "^20.8.6",
"@types/uuid": "^9.0.2", "@types/uuid": "^9.0.5",
"eslint": "^8.0.1", "eslint": "^8.51.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^5.0.1",
"jest": "28.1.3", "jest": "29.7.0",
"prettier": "^2.3.2", "prettier": "^3.0.3",
"prisma": "^4.7.1", "prisma": "^5.4.2",
"source-map-support": "^0.5.20", "source-map-support": "^0.5.21",
"supertest": "^6.1.3", "supertest": "^6.3.3",
"ts-jest": "28.0.8", "ts-jest": "29.1.1",
"ts-loader": "^9.2.3", "ts-loader": "^9.5.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsconfig-paths": "4.1.0", "tsconfig-paths": "4.2.0",
"typescript": "^4.9.4" "typescript": "^5.2.2"
}, },
"jest": { "jest": {
"moduleFileExtensions": [ "moduleFileExtensions": [

16
src/app.constants.ts Normal file
View File

@ -0,0 +1,16 @@
// service
export const SERVICE_NAME = 'user';
// grpc
export const GRPC_SERVICE_NAME = 'UserService';
// configuration
export const SERVICE_CONFIGURATION_SET_QUEUE = 'user-configuration-set';
export const SERVICE_CONFIGURATION_DELETE_QUEUE = 'user-configuration-delete';
export const SERVICE_CONFIGURATION_PROPAGATE_QUEUE =
'user-configuration-propagate';
// health
export const HEALTH_SERVICE_NAME = 'health';
export const HEALTH_USER_REPOSITORY = 'UserRepository';
export const HEALTH_CRITICAL_LOGGING_KEY = 'logging.user.health.crit';

View File

@ -15,6 +15,14 @@ import { USER_REPOSITORY } from './modules/user/user.di-tokens';
import { MESSAGE_PUBLISHER } from './modules/messager/messager.di-tokens'; import { MESSAGE_PUBLISHER } from './modules/messager/messager.di-tokens';
import { MessagePublisherPort } from '@mobicoop/ddd-library'; import { MessagePublisherPort } from '@mobicoop/ddd-library';
import { EventEmitterModule } from '@nestjs/event-emitter'; import { EventEmitterModule } from '@nestjs/event-emitter';
import {
HEALTH_CRITICAL_LOGGING_KEY,
HEALTH_USER_REPOSITORY,
SERVICE_CONFIGURATION_DELETE_QUEUE,
SERVICE_CONFIGURATION_PROPAGATE_QUEUE,
SERVICE_CONFIGURATION_SET_QUEUE,
SERVICE_NAME,
} from './app.constants';
@Module({ @Module({
imports: [ imports: [
@ -26,19 +34,23 @@ import { EventEmitterModule } from '@nestjs/event-emitter';
useFactory: async ( useFactory: async (
configService: ConfigService, configService: ConfigService,
): Promise<ConfigurationModuleOptions> => ({ ): Promise<ConfigurationModuleOptions> => ({
domain: configService.get<string>('SERVICE_CONFIGURATION_DOMAIN'), domain: configService.get<string>(
'SERVICE_CONFIGURATION_DOMAIN',
) as string,
messageBroker: { messageBroker: {
uri: configService.get<string>('MESSAGE_BROKER_URI'), uri: configService.get<string>('MESSAGE_BROKER_URI') as string,
exchange: configService.get<string>('MESSAGE_BROKER_EXCHANGE'), exchange: configService.get<string>(
'MESSAGE_BROKER_EXCHANGE',
) as string,
}, },
redis: { redis: {
host: configService.get<string>('REDIS_HOST'), host: configService.get<string>('REDIS_HOST') as string,
password: configService.get<string>('REDIS_PASSWORD'), password: configService.get<string>('REDIS_PASSWORD'),
port: configService.get<number>('REDIS_PORT'), port: configService.get<number>('REDIS_PORT') as number,
}, },
setConfigurationBrokerQueue: 'user-configuration-create-update', setConfigurationBrokerQueue: SERVICE_CONFIGURATION_SET_QUEUE,
deleteConfigurationQueue: 'user-configuration-delete', deleteConfigurationQueue: SERVICE_CONFIGURATION_DELETE_QUEUE,
propagateConfigurationQueue: 'user-configuration-propagate', propagateConfigurationQueue: SERVICE_CONFIGURATION_PROPAGATE_QUEUE,
}), }),
}), }),
HealthModule.forRootAsync({ HealthModule.forRootAsync({
@ -48,11 +60,11 @@ import { EventEmitterModule } from '@nestjs/event-emitter';
userRepository: HealthRepositoryPort, userRepository: HealthRepositoryPort,
messagePublisher: MessagePublisherPort, messagePublisher: MessagePublisherPort,
): Promise<HealthModuleOptions> => ({ ): Promise<HealthModuleOptions> => ({
serviceName: 'user', serviceName: SERVICE_NAME,
criticalLoggingKey: 'logging.user.health.crit', criticalLoggingKey: HEALTH_CRITICAL_LOGGING_KEY,
checkRepositories: [ checkRepositories: [
{ {
name: 'UserRepository', name: HEALTH_USER_REPOSITORY,
repository: userRepository, repository: userRepository,
}, },
], ],

View File

@ -2,6 +2,7 @@ import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices'; import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { join } from 'path'; import { join } from 'path';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { HEALTH_SERVICE_NAME, SERVICE_NAME } from './app.constants';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
@ -11,17 +12,17 @@ async function bootstrap() {
app.connectMicroservice<MicroserviceOptions>({ app.connectMicroservice<MicroserviceOptions>({
transport: Transport.GRPC, transport: Transport.GRPC,
options: { options: {
package: ['user', 'health'], package: [SERVICE_NAME, HEALTH_SERVICE_NAME],
protoPath: [ protoPath: [
join(__dirname, 'modules/user/interface/grpc-controllers/user.proto'), join(__dirname, 'modules/user/interface/grpc-controllers/user.proto'),
join(__dirname, 'health.proto'), join(__dirname, 'health.proto'),
], ],
url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT, url: `${process.env.SERVICE_URL}:${process.env.SERVICE_PORT}`,
loader: { keepCase: true }, loader: { keepCase: true, enums: String },
}, },
}); });
await app.startAllMicroservices(); await app.startAllMicroservices();
await app.listen(process.env.HEALTH_SERVICE_PORT); await app.listen(process.env.HEALTH_SERVICE_PORT as unknown as number);
} }
bootstrap(); bootstrap();

View File

@ -6,6 +6,7 @@ import {
MessageBrokerPublisher, MessageBrokerPublisher,
} from '@mobicoop/message-broker-module'; } from '@mobicoop/message-broker-module';
import { ConfigModule, ConfigService } from '@nestjs/config'; import { ConfigModule, ConfigService } from '@nestjs/config';
import { SERVICE_NAME } from '@src/app.constants';
const imports = [ const imports = [
MessageBrokerModule.forRootAsync({ MessageBrokerModule.forRootAsync({
@ -14,9 +15,14 @@ const imports = [
useFactory: async ( useFactory: async (
configService: ConfigService, configService: ConfigService,
): Promise<MessageBrokerModuleOptions> => ({ ): Promise<MessageBrokerModuleOptions> => ({
uri: configService.get<string>('MESSAGE_BROKER_URI'), uri: configService.get<string>('MESSAGE_BROKER_URI') as string,
exchange: configService.get<string>('MESSAGE_BROKER_EXCHANGE'), exchange: {
name: 'user', name: configService.get<string>('MESSAGE_BROKER_EXCHANGE') as string,
durable: configService.get<boolean>(
'MESSAGE_BROKER_EXCHANGE_DURABILITY',
) as boolean,
},
name: SERVICE_NAME,
}), }),
}), }),
]; ];

View File

@ -1,10 +1,10 @@
import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library'; import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library';
export class UserCreatedIntegrationEvent extends IntegrationEvent { export class UserCreatedIntegrationEvent extends IntegrationEvent {
readonly firstName: string; readonly firstName?: string;
readonly lastName: string; readonly lastName?: string;
readonly email: string; readonly email?: string;
readonly phone: string; readonly phone?: string;
constructor(props: IntegrationEventProps<UserCreatedIntegrationEvent>) { constructor(props: IntegrationEventProps<UserCreatedIntegrationEvent>) {
super(props); super(props);

View File

@ -1,10 +1,10 @@
import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library'; import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library';
export class UserUpdatedIntegrationEvent extends IntegrationEvent { export class UserUpdatedIntegrationEvent extends IntegrationEvent {
readonly firstName: string; readonly firstName?: string;
readonly lastName: string; readonly lastName?: string;
readonly email: string; readonly email?: string;
readonly phone: string; readonly phone?: string;
constructor(props: IntegrationEventProps<UserUpdatedIntegrationEvent>) { constructor(props: IntegrationEventProps<UserUpdatedIntegrationEvent>) {
super(props); super(props);

View File

@ -1,10 +1,10 @@
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library'; import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
export class UserCreatedDomainEvent extends DomainEvent { export class UserCreatedDomainEvent extends DomainEvent {
readonly firstName: string; readonly firstName?: string;
readonly lastName: string; readonly lastName?: string;
readonly email: string; readonly email?: string;
readonly phone: string; readonly phone?: string;
constructor(props: DomainEventProps<UserCreatedDomainEvent>) { constructor(props: DomainEventProps<UserCreatedDomainEvent>) {
super(props); super(props);

View File

@ -1,10 +1,10 @@
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library'; import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
export class UserUpdatedDomainEvent extends DomainEvent { export class UserUpdatedDomainEvent extends DomainEvent {
readonly firstName: string; readonly firstName?: string;
readonly lastName: string; readonly lastName?: string;
readonly email: string; readonly email?: string;
readonly phone: string; readonly phone?: string;
constructor(props: DomainEventProps<UserUpdatedDomainEvent>) { constructor(props: DomainEventProps<UserUpdatedDomainEvent>) {
super(props); super(props);

View File

@ -1,4 +1,4 @@
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common'; import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from '@prisma/client';
@Injectable() @Injectable()
@ -6,10 +6,4 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() { async onModuleInit() {
await this.$connect(); await this.$connect();
} }
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
} }

View File

@ -10,18 +10,19 @@ import { UserEntity } from '../core/domain/user.entity';
import { UserRepositoryPort } from '../core/application/ports/user.repository.port'; import { UserRepositoryPort } from '../core/application/ports/user.repository.port';
import { UserMapper } from '../user.mapper'; import { UserMapper } from '../user.mapper';
import { USER_MESSAGE_PUBLISHER } from '../user.di-tokens'; import { USER_MESSAGE_PUBLISHER } from '../user.di-tokens';
import { SERVICE_NAME } from '@src/app.constants';
export type UserBaseModel = { export type UserBaseModel = {
uuid: string; uuid: string;
firstName: string; firstName?: string;
lastName: string; lastName?: string;
email: string; email?: string;
phone: string; phone?: string;
}; };
export type UserReadModel = UserBaseModel & { export type UserReadModel = UserBaseModel & {
createdAt?: Date; createdAt: Date;
updatedAt?: Date; updatedAt: Date;
}; };
export type UserWriteModel = UserBaseModel; export type UserWriteModel = UserBaseModel;
@ -48,7 +49,7 @@ export class UserRepository
eventEmitter, eventEmitter,
new LoggerBase({ new LoggerBase({
logger: new Logger(UserRepository.name), logger: new Logger(UserRepository.name),
domain: 'user', domain: SERVICE_NAME,
messagePublisher, messagePublisher,
}), }),
); );

View File

@ -1,8 +1,8 @@
import { ResponseBase } from '@mobicoop/ddd-library'; import { ResponseBase } from '@mobicoop/ddd-library';
export class UserResponseDto extends ResponseBase { export class UserResponseDto extends ResponseBase {
firstName: string; firstName?: string;
lastName: string; lastName?: string;
email: string; email?: string;
phone: string; phone?: string;
} }

View File

@ -12,6 +12,7 @@ import {
PhoneAlreadyExistsException, PhoneAlreadyExistsException,
UserAlreadyExistsException, UserAlreadyExistsException,
} from '@modules/user/core/domain/user.errors'; } from '@modules/user/core/domain/user.errors';
import { GRPC_SERVICE_NAME } from '@src/app.constants';
@UsePipes( @UsePipes(
new RpcValidationPipe({ new RpcValidationPipe({
@ -23,7 +24,7 @@ import {
export class CreateUserGrpcController { export class CreateUserGrpcController {
constructor(private readonly commandBus: CommandBus) {} constructor(private readonly commandBus: CommandBus) {}
@GrpcMethod('UserService', 'Create') @GrpcMethod(GRPC_SERVICE_NAME, 'Create')
async create( async create(
createUserRequestDto: CreateUserRequestDto, createUserRequestDto: CreateUserRequestDto,
): Promise<IdResponse> { ): Promise<IdResponse> {

View File

@ -9,6 +9,7 @@ import { CommandBus } from '@nestjs/cqrs';
import { GrpcMethod, RpcException } from '@nestjs/microservices'; import { GrpcMethod, RpcException } from '@nestjs/microservices';
import { DeleteUserRequestDto } from './dtos/delete-user.request.dto'; import { DeleteUserRequestDto } from './dtos/delete-user.request.dto';
import { DeleteUserCommand } from '@modules/user/core/application/commands/delete-user/delete-user.command'; import { DeleteUserCommand } from '@modules/user/core/application/commands/delete-user/delete-user.command';
import { GRPC_SERVICE_NAME } from '@src/app.constants';
@UsePipes( @UsePipes(
new RpcValidationPipe({ new RpcValidationPipe({
@ -20,7 +21,7 @@ import { DeleteUserCommand } from '@modules/user/core/application/commands/delet
export class DeleteUserGrpcController { export class DeleteUserGrpcController {
constructor(private readonly commandBus: CommandBus) {} constructor(private readonly commandBus: CommandBus) {}
@GrpcMethod('UserService', 'Delete') @GrpcMethod(GRPC_SERVICE_NAME, 'Delete')
async delete(data: DeleteUserRequestDto): Promise<void> { async delete(data: DeleteUserRequestDto): Promise<void> {
try { try {
await this.commandBus.execute(new DeleteUserCommand(data)); await this.commandBus.execute(new DeleteUserCommand(data));

View File

@ -9,6 +9,7 @@ import { FindUserByIdRequestDto } from './dtos/find-user-by-id.request.dto';
import { UserResponseDto } from '../dtos/user.response.dto'; import { UserResponseDto } from '../dtos/user.response.dto';
import { UserEntity } from '@modules/user/core/domain/user.entity'; import { UserEntity } from '@modules/user/core/domain/user.entity';
import { FindUserByIdQuery } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query'; import { FindUserByIdQuery } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query';
import { GRPC_SERVICE_NAME } from '@src/app.constants';
@UsePipes( @UsePipes(
new RpcValidationPipe({ new RpcValidationPipe({
@ -23,7 +24,7 @@ export class FindUserByIdGrpcController {
private readonly queryBus: QueryBus, private readonly queryBus: QueryBus,
) {} ) {}
@GrpcMethod('UserService', 'FindOneById') @GrpcMethod(GRPC_SERVICE_NAME, 'FindOneById')
async findOnebyId(data: FindUserByIdRequestDto): Promise<UserResponseDto> { async findOnebyId(data: FindUserByIdRequestDto): Promise<UserResponseDto> {
try { try {
const user: UserEntity = await this.queryBus.execute( const user: UserEntity = await this.queryBus.execute(

View File

@ -14,6 +14,7 @@ import {
PhoneAlreadyExistsException, PhoneAlreadyExistsException,
UserAlreadyExistsException, UserAlreadyExistsException,
} from '@modules/user/core/domain/user.errors'; } from '@modules/user/core/domain/user.errors';
import { GRPC_SERVICE_NAME } from '@src/app.constants';
@UsePipes( @UsePipes(
new RpcValidationPipe({ new RpcValidationPipe({
@ -25,7 +26,7 @@ import {
export class UpdateUserGrpcController { export class UpdateUserGrpcController {
constructor(private readonly commandBus: CommandBus) {} constructor(private readonly commandBus: CommandBus) {}
@GrpcMethod('UserService', 'Update') @GrpcMethod(GRPC_SERVICE_NAME, 'Update')
async updateUser(data: UpdateUserRequestDto): Promise<IdResponse> { async updateUser(data: UpdateUserRequestDto): Promise<IdResponse> {
try { try {
const aggregateID: AggregateID = await this.commandBus.execute( const aggregateID: AggregateID = await this.commandBus.execute(

View File

@ -64,9 +64,8 @@ describe('create-user.service', () => {
UserEntity.create = jest.fn().mockReturnValue({ UserEntity.create = jest.fn().mockReturnValue({
id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', id: '047a6ecf-23d4-4d3e-877c-3225d560a8da',
}); });
const result: AggregateID = await createUserService.execute( const result: AggregateID =
createUserCommand, await createUserService.execute(createUserCommand);
);
expect(result).toBe('047a6ecf-23d4-4d3e-877c-3225d560a8da'); expect(result).toBe('047a6ecf-23d4-4d3e-877c-3225d560a8da');
}); });
it('should throw an error if something bad happens', async () => { it('should throw an error if something bad happens', async () => {

View File

@ -41,9 +41,8 @@ describe('Delete User Service', () => {
describe('execution', () => { describe('execution', () => {
const deleteUserCommand = new DeleteUserCommand(deleteUserRequest); const deleteUserCommand = new DeleteUserCommand(deleteUserRequest);
it('should delete a user', async () => { it('should delete a user', async () => {
const result: boolean = await deleteUserService.execute( const result: boolean =
deleteUserCommand, await deleteUserService.execute(deleteUserCommand);
);
expect(result).toBeTruthy(); expect(result).toBeTruthy();
}); });
}); });

View File

@ -49,9 +49,8 @@ describe('find-user-by-id.query-handler', () => {
const findUserbyIdQuery = new FindUserByIdQuery( const findUserbyIdQuery = new FindUserByIdQuery(
'dd264806-13b4-4226-9b18-87adf0ad5dd1', 'dd264806-13b4-4226-9b18-87adf0ad5dd1',
); );
const user: UserEntity = await findUserByIdQueryHandler.execute( const user: UserEntity =
findUserbyIdQuery, await findUserByIdQueryHandler.execute(findUserbyIdQuery);
);
expect(user.getProps().lastName).toBe('Doe'); expect(user.getProps().lastName).toBe('Doe');
}); });
}); });

View File

@ -98,9 +98,8 @@ describe('update-user.service', () => {
const updateUserCommand = new UpdateUserCommand( const updateUserCommand = new UpdateUserCommand(
updateFirstNameUserRequest, updateFirstNameUserRequest,
); );
const result: AggregateID = await updateUserService.execute( const result: AggregateID =
updateUserCommand, await updateUserService.execute(updateUserCommand);
);
expect(result).toBe('c97b1783-76cf-4840-b298-b90b13c58894'); expect(result).toBe('c97b1783-76cf-4840-b298-b90b13c58894');
expect(userToUpdate.update).toHaveBeenCalledTimes(1); expect(userToUpdate.update).toHaveBeenCalledTimes(1);
}); });

View File

@ -65,9 +65,8 @@ describe('Create User Grpc Controller', () => {
it('should create a new user', async () => { it('should create a new user', async () => {
jest.spyOn(mockCommandBus, 'execute'); jest.spyOn(mockCommandBus, 'execute');
const result: IdResponse = await createUserGrpcController.create( const result: IdResponse =
createUserRequest, await createUserGrpcController.create(createUserRequest);
);
expect(result).toBeInstanceOf(IdResponse); expect(result).toBeInstanceOf(IdResponse);
expect(result.id).toBe('200d61a8-d878-4378-a609-c19ea71633d2'); expect(result.id).toBe('200d61a8-d878-4378-a609-c19ea71633d2');
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);

View File

@ -1,4 +1,3 @@
import { RedisClientOptions } from '@liaoliaots/nestjs-redis';
import { Module, Provider } from '@nestjs/common'; import { Module, Provider } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config'; import { ConfigModule, ConfigService } from '@nestjs/config';
import { CqrsModule } from '@nestjs/cqrs'; import { CqrsModule } from '@nestjs/cqrs';
@ -20,6 +19,7 @@ import { FindUserByIdQueryHandler } from './core/application/queries/find-user-b
import { PublishMessageWhenUserIsCreatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler'; import { PublishMessageWhenUserIsCreatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler';
import { PublishMessageWhenUserIsUpdatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler'; import { PublishMessageWhenUserIsUpdatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler';
import { PublishMessageWhenUserIsDeletedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler'; import { PublishMessageWhenUserIsDeletedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler';
import { RedisClientOptions } from '@songkeys/nestjs-redis';
const imports = [ const imports = [
CqrsModule, CqrsModule,

View File

@ -12,12 +12,13 @@
"baseUrl": "./", "baseUrl": "./",
"incremental": true, "incremental": true,
"skipLibCheck": true, "skipLibCheck": true,
"strictNullChecks": false, "strictNullChecks": true,
"noImplicitAny": false, "noImplicitAny": true,
"strictBindCallApply": false, "strictBindCallApply": false,
"forceConsistentCasingInFileNames": false, "forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": false, "noFallthroughCasesInSwitch": false,
"paths": { "paths": {
"@libs/*": ["src/libs/*"],
"@modules/*": ["src/modules/*"], "@modules/*": ["src/modules/*"],
"@src/*": ["src/*"] "@src/*": ["src/*"]
} }