mirror of
https://gitlab.com/mobicoop/v3/service/ad.git
synced 2026-01-03 08:22:41 +00:00
findAdByUuid, functional basic AdModule
This commit is contained in:
@@ -3,10 +3,13 @@ import { ConfigModule } from '@nestjs/config';
|
||||
import { ConfigurationModule } from './modules/configuration/configuration.module';
|
||||
import { HealthModule } from './modules/health/health.module';
|
||||
import { AdModule } from './modules/ad/ad.module';
|
||||
import { AutomapperModule } from '@automapper/nestjs';
|
||||
import { classes } from '@automapper/classes';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({ isGlobal: true }),
|
||||
AutomapperModule.forRoot({ strategyInitializer: classes() }),
|
||||
ConfigurationModule,
|
||||
HealthModule,
|
||||
AdModule,
|
||||
|
||||
@@ -11,10 +11,9 @@ async function bootstrap() {
|
||||
app.connectMicroservice<MicroserviceOptions>({
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
// package: ['ad', 'health'],
|
||||
package: ['health'],
|
||||
package: ['ad', 'health'],
|
||||
protoPath: [
|
||||
// join(__dirname, 'modules/ad/adapters/primaries/ad.proto'),
|
||||
join(__dirname, 'modules/ad/adapters/primaries/ad.proto'),
|
||||
join(__dirname, 'modules/health/adapters/primaries/health.proto'),
|
||||
],
|
||||
url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT,
|
||||
|
||||
@@ -1,8 +1,34 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AdController } from './adapters/primaries/ad.controller';
|
||||
import { DatabaseModule } from '../database/database.module';
|
||||
import { CqrsModule } from '@nestjs/cqrs';
|
||||
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { AdProfile } from './mappers/ad.profile';
|
||||
import { AdsRepository } from './adapters/secondaries/ads.repository';
|
||||
import { Messager } from './adapters/secondaries/messager';
|
||||
import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [],
|
||||
providers: [],
|
||||
imports: [
|
||||
DatabaseModule,
|
||||
CqrsModule,
|
||||
RabbitMQModule.forRootAsync(RabbitMQModule, {
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => ({
|
||||
exchanges: [
|
||||
{
|
||||
name: configService.get<string>('RMQ_EXCHANGE'),
|
||||
type: 'topic',
|
||||
},
|
||||
],
|
||||
uri: configService.get<string>('RMQ_URI'),
|
||||
connectionInitOptions: { wait: false },
|
||||
}),
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
controllers: [AdController],
|
||||
providers: [AdProfile, AdsRepository, Messager, FindAdByUuidUseCase],
|
||||
})
|
||||
export class AdModule {}
|
||||
|
||||
38
src/modules/ad/adapters/primaries/ad.controller.ts
Normal file
38
src/modules/ad/adapters/primaries/ad.controller.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Mapper } from '@automapper/core';
|
||||
import { InjectMapper } from '@automapper/nestjs';
|
||||
import { Controller, UsePipes } from '@nestjs/common';
|
||||
import { QueryBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe';
|
||||
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
|
||||
import { AdPresenter } from './ad.presenter';
|
||||
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
||||
import { Ad } from '../../domain/entities/ad';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
whitelist: false,
|
||||
forbidUnknownValues: false,
|
||||
}),
|
||||
)
|
||||
@Controller()
|
||||
export class AdController {
|
||||
constructor(
|
||||
private readonly queryBus: QueryBus,
|
||||
@InjectMapper() private readonly _mapper: Mapper,
|
||||
) {}
|
||||
|
||||
@GrpcMethod('AdsService', 'FindOneByUuid')
|
||||
async findOnebyUuid(data: FindAdByUuidRequest): Promise<AdPresenter> {
|
||||
try {
|
||||
console.log('ici');
|
||||
const ad = await this.queryBus.execute(new FindAdByUuidQuery(data));
|
||||
return this._mapper.map(ad, Ad, AdPresenter);
|
||||
} catch (e) {
|
||||
throw new RpcException({
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/modules/ad/adapters/primaries/ad.presenter.ts
Normal file
9
src/modules/ad/adapters/primaries/ad.presenter.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { AutoMap } from '@automapper/classes';
|
||||
|
||||
export class AdPresenter {
|
||||
@AutoMap()
|
||||
uuid: string;
|
||||
|
||||
@AutoMap()
|
||||
driver: boolean;
|
||||
}
|
||||
86
src/modules/ad/adapters/primaries/ad.proto
Normal file
86
src/modules/ad/adapters/primaries/ad.proto
Normal file
@@ -0,0 +1,86 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ad;
|
||||
|
||||
service AdsService {
|
||||
rpc FindOneByUuid(AdByUuid) returns (Ad);
|
||||
rpc FindAll(AdFilter) returns (Ads);
|
||||
rpc Create(Ad) returns (Ad);
|
||||
rpc Update(Ad) returns (Ad);
|
||||
rpc Delete(AdByUuid) returns (Empty);
|
||||
}
|
||||
|
||||
message AdByUuid {
|
||||
string uuid = 1;
|
||||
}
|
||||
|
||||
message Ad {
|
||||
string uuid = 1;
|
||||
string userUuid = 2;
|
||||
bool driver = 3;
|
||||
bool passenger = 4;
|
||||
int32 frequency = 5;
|
||||
string fromDate = 6;
|
||||
string toDate = 7;
|
||||
Schedule schedule = 8;
|
||||
MarginDurations marginDurations = 9;
|
||||
int32 seatsPassenger = 10;
|
||||
int32 seatsDriver = 11;
|
||||
bool strict = 12;
|
||||
Addresses addresses = 13;
|
||||
}
|
||||
|
||||
message Schedule {
|
||||
string mon = 1;
|
||||
string tue = 2;
|
||||
string wed = 3;
|
||||
string thu = 4;
|
||||
string fri = 5;
|
||||
string sat = 6;
|
||||
string sun = 7;
|
||||
}
|
||||
|
||||
message MarginDurations {
|
||||
int32 mon = 1;
|
||||
int32 tue = 2;
|
||||
int32 wed = 3;
|
||||
int32 thu = 4;
|
||||
int32 fri = 5;
|
||||
int32 sat = 6;
|
||||
int32 sun = 7;
|
||||
}
|
||||
|
||||
message Addresses {
|
||||
repeated Address address = 1;
|
||||
}
|
||||
|
||||
message Address {
|
||||
float lon = 1;
|
||||
float lat = 2;
|
||||
string houseNumber = 3;
|
||||
string street = 4;
|
||||
string locality = 5;
|
||||
string postalCode = 6;
|
||||
string country = 7;
|
||||
AddressType type = 8;
|
||||
}
|
||||
|
||||
enum AddressType {
|
||||
HOUSE_NUMBER = 1;
|
||||
STREET_ADDRESS = 2;
|
||||
LOCALITY = 3;
|
||||
VENUE = 4;
|
||||
OTHER = 5;
|
||||
}
|
||||
|
||||
message AdFilter {
|
||||
optional int32 page = 1;
|
||||
optional int32 perPage = 2;
|
||||
}
|
||||
|
||||
message Ads {
|
||||
repeated Ad data = 1;
|
||||
int32 total = 2;
|
||||
}
|
||||
|
||||
message Empty {}
|
||||
18
src/modules/ad/adapters/secondaries/messager.ts
Normal file
18
src/modules/ad/adapters/secondaries/messager.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { IMessageBroker } from '../../domain/interfaces/message-broker';
|
||||
|
||||
@Injectable()
|
||||
export class Messager extends IMessageBroker {
|
||||
constructor(
|
||||
private readonly _amqpConnection: AmqpConnection,
|
||||
configService: ConfigService,
|
||||
) {
|
||||
super(configService.get<string>('RMQ_EXCHANGE'));
|
||||
}
|
||||
|
||||
publish(routingKey: string, message: string): void {
|
||||
this._amqpConnection.publish(this.exchange, routingKey, message);
|
||||
}
|
||||
}
|
||||
7
src/modules/ad/domain/dtos/find-ad-by-uuid.request.ts
Normal file
7
src/modules/ad/domain/dtos/find-ad-by-uuid.request.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class FindAdByUuidRequest {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
uuid: string;
|
||||
}
|
||||
@@ -3,4 +3,7 @@ import { AutoMap } from '@automapper/classes';
|
||||
export class Ad {
|
||||
@AutoMap()
|
||||
uuid: string;
|
||||
|
||||
@AutoMap()
|
||||
driver: boolean;
|
||||
}
|
||||
|
||||
12
src/modules/ad/domain/interfaces/message-broker.ts
Normal file
12
src/modules/ad/domain/interfaces/message-broker.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export abstract class IMessageBroker {
|
||||
exchange: string;
|
||||
|
||||
constructor(exchange: string) {
|
||||
this.exchange = exchange;
|
||||
}
|
||||
|
||||
abstract publish(routingKey: string, message: string): void;
|
||||
}
|
||||
31
src/modules/ad/domain/usecases/find-ad-by-uuid.usecase.ts
Normal file
31
src/modules/ad/domain/usecases/find-ad-by-uuid.usecase.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { NotFoundException } from '@nestjs/common';
|
||||
import { QueryHandler } from '@nestjs/cqrs';
|
||||
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
||||
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
||||
import { Messager } from '../../adapters/secondaries/messager';
|
||||
import { Ad } from '../entities/ad';
|
||||
|
||||
@QueryHandler(FindAdByUuidQuery)
|
||||
export class FindAdByUuidUseCase {
|
||||
constructor(
|
||||
private readonly repository: AdsRepository,
|
||||
private readonly messager: Messager,
|
||||
) {}
|
||||
|
||||
async execute(findAdByUuid: FindAdByUuidQuery): Promise<Ad> {
|
||||
try {
|
||||
const ad = await this.repository.findOneByUuid(findAdByUuid.uuid);
|
||||
if (!ad) throw new NotFoundException();
|
||||
return ad;
|
||||
} catch (error) {
|
||||
this.messager.publish(
|
||||
'logging.ad.read.warning',
|
||||
JSON.stringify({
|
||||
query: findAdByUuid,
|
||||
error,
|
||||
}),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/modules/ad/mappers/ad.profile.ts
Normal file
18
src/modules/ad/mappers/ad.profile.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createMap, Mapper } from '@automapper/core';
|
||||
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Ad } from '../domain/entities/ad';
|
||||
import { AdPresenter } from '../adapters/primaries/ad.presenter';
|
||||
|
||||
@Injectable()
|
||||
export class AdProfile extends AutomapperProfile {
|
||||
constructor(@InjectMapper() mapper: Mapper) {
|
||||
super(mapper);
|
||||
}
|
||||
|
||||
override get profile() {
|
||||
return (mapper) => {
|
||||
createMap(mapper, Ad, AdPresenter);
|
||||
};
|
||||
}
|
||||
}
|
||||
9
src/modules/ad/queries/find-ad-by-uuid.query.ts
Normal file
9
src/modules/ad/queries/find-ad-by-uuid.query.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { FindAdByUuidRequest } from '../domain/dtos/find-ad-by-uuid.request';
|
||||
|
||||
export class FindAdByUuidQuery {
|
||||
readonly uuid: string;
|
||||
|
||||
constructor(findAdByUuidRequest: FindAdByUuidRequest) {
|
||||
this.uuid = findAdByUuidRequest.uuid;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user