findAdByUuid, functional basic AdModule
This commit is contained in:
parent
47e4abf594
commit
5fbc399924
|
@ -0,0 +1,54 @@
|
|||
image: docker:20.10.22
|
||||
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
|
||||
##############
|
||||
# TEST STAGE #
|
||||
##############
|
||||
|
||||
test:
|
||||
stage: test
|
||||
image: docker/compose:latest
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: ''
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- docker-compose -f docker-compose.ci.tools.yml -p ad-tools --env-file ci/.env.ci up -d
|
||||
- sh ci/wait-up.sh
|
||||
- docker-compose -f docker-compose.ci.service.yml -p ad-service --env-file ci/.env.ci up -d
|
||||
# - docker exec -t v3-ad-api sh -c "npm run test:integration:ci"
|
||||
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
|
||||
rules:
|
||||
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_MESSAGE =~ /--check/ || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
when: always
|
||||
|
||||
###############
|
||||
# BUILD STAGE #
|
||||
###############
|
||||
|
||||
build:
|
||||
stage: build
|
||||
image: docker:20.10.22
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: ''
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- echo -n $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
|
||||
script:
|
||||
- export VERSION=$(docker run --rm -v "$PWD":/usr/src/app:ro -w /usr/src/app node:slim node -p "require('./package.json').version")
|
||||
- docker pull $CI_REGISTRY_IMAGE:latest || true
|
||||
- >
|
||||
docker build
|
||||
--pull
|
||||
--cache-from $CI_REGISTRY_IMAGE:latest
|
||||
--tag $CI_REGISTRY_IMAGE:$VERSION
|
||||
--tag $CI_REGISTRY_IMAGE:latest
|
||||
.
|
||||
- docker push $CI_REGISTRY_IMAGE:$VERSION
|
||||
- docker push $CI_REGISTRY_IMAGE:latest
|
||||
only:
|
||||
- main
|
|
@ -0,0 +1,15 @@
|
|||
# SERVICE
|
||||
SERVICE_URL=0.0.0.0
|
||||
SERVICE_PORT=5006
|
||||
|
||||
# PRISMA
|
||||
DATABASE_URL="postgresql://mobicoop:mobicoop@v3-db:5432/mobicoop?schema=public"
|
||||
|
||||
# RABBIT MQ
|
||||
RMQ_URI=amqp://v3-broker:5672
|
||||
|
||||
# MESSAGE BROKER
|
||||
BROKER_IMAGE=rabbitmq:3-alpine
|
||||
|
||||
# POSTGRES
|
||||
POSTGRES_IMAGE=postgis/postgis:15-3.3
|
|
@ -0,0 +1,33 @@
|
|||
###################
|
||||
# BUILD FOR CI TESTING
|
||||
###################
|
||||
|
||||
FROM node:18-alpine3.16
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
||||
COPY package*.json ./
|
||||
|
||||
# Install app dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Bundle app source
|
||||
COPY . .
|
||||
|
||||
# Generate prisma client
|
||||
RUN npx prisma generate
|
||||
|
||||
# Create a "dist" folder
|
||||
RUN npm run build
|
||||
|
||||
# Run unit tests
|
||||
RUN npm run test:unit:ci
|
||||
|
||||
# ESLint / Prettier
|
||||
RUN npm run lint:check
|
||||
RUN npm run pretty:check
|
||||
|
||||
# Start the server
|
||||
CMD [ "node", "dist/main.js" ]
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
testlog() {
|
||||
docker logs v3-db | grep -q "database system is ready to accept connections"
|
||||
}
|
||||
|
||||
testlog 2> /dev/null
|
||||
while [ $? -ne 0 ];
|
||||
do
|
||||
sleep 5
|
||||
echo "Waiting for Test DB to be up..."
|
||||
testlog 2> /dev/null
|
||||
done
|
|
@ -0,0 +1,19 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
v3-ad-api:
|
||||
container_name: v3-ad-api
|
||||
build:
|
||||
dockerfile: ci/Dockerfile
|
||||
context: .
|
||||
env_file:
|
||||
- ci/.env.ci
|
||||
ports:
|
||||
- 5006:5006
|
||||
networks:
|
||||
- v3-network
|
||||
|
||||
networks:
|
||||
v3-network:
|
||||
name: v3-network
|
||||
external: true
|
|
@ -0,0 +1,26 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
db:
|
||||
container_name: v3-db
|
||||
image: ${POSTGRES_IMAGE}
|
||||
environment:
|
||||
POSTGRES_DB: mobicoop
|
||||
POSTGRES_USER: mobicoop
|
||||
POSTGRES_PASSWORD: mobicoop
|
||||
ports:
|
||||
- 5432:5432
|
||||
networks:
|
||||
- v3-network
|
||||
|
||||
broker:
|
||||
container_name: v3-broker
|
||||
image: ${BROKER_IMAGE}
|
||||
ports:
|
||||
- 5672:5672
|
||||
networks:
|
||||
- v3-network
|
||||
|
||||
networks:
|
||||
v3-network:
|
||||
name: v3-network
|
|
@ -24,6 +24,7 @@
|
|||
"@nestjs/platform-express": "^9.0.0",
|
||||
"@nestjs/terminus": "^9.2.2",
|
||||
"@prisma/client": "^4.13.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"ioredis": "^5.3.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
|
@ -3564,6 +3565,11 @@
|
|||
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/class-transformer": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
|
||||
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
|
||||
},
|
||||
"node_modules/class-validator": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz",
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"@nestjs/platform-express": "^9.0.0",
|
||||
"@nestjs/terminus": "^9.2.2",
|
||||
"@prisma/client": "^4.13.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"ioredis": "^5.3.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
|
|
|
@ -1,28 +1,34 @@
|
|||
-- CreateEnum
|
||||
CREATE TYPE "Frequency" AS ENUM ('PUNCTUAL', 'RECURRENT');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AddressType" AS ENUM ('HOUSE_NUMBER', 'STREET_ADDRESS', 'LOCALITY', 'VENUE', 'OTHER');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ad" (
|
||||
"uuid" UUID NOT NULL,
|
||||
"userUuid" UUID NOT NULL,
|
||||
"driver" BOOLEAN NOT NULL,
|
||||
"passenger" BOOLEAN NOT NULL,
|
||||
"frequency" INTEGER NOT NULL,
|
||||
"driver" BOOLEAN,
|
||||
"passenger" BOOLEAN,
|
||||
"frequency" "Frequency" NOT NULL DEFAULT 'RECURRENT',
|
||||
"fromDate" DATE NOT NULL,
|
||||
"toDate" DATE NOT NULL,
|
||||
"monTime" TIMESTAMPTZ NOT NULL,
|
||||
"tueTime" TIMESTAMPTZ NOT NULL,
|
||||
"wedTime" TIMESTAMPTZ NOT NULL,
|
||||
"thuTime" TIMESTAMPTZ NOT NULL,
|
||||
"friTime" TIMESTAMPTZ NOT NULL,
|
||||
"satTime" TIMESTAMPTZ NOT NULL,
|
||||
"sunTime" TIMESTAMPTZ NOT NULL,
|
||||
"monMargin" INTEGER NOT NULL,
|
||||
"tueMargin" INTEGER NOT NULL,
|
||||
"wedMargin" INTEGER NOT NULL,
|
||||
"thuMargin" INTEGER NOT NULL,
|
||||
"friMargin" INTEGER NOT NULL,
|
||||
"satMargin" INTEGER NOT NULL,
|
||||
"sunMargin" INTEGER NOT NULL,
|
||||
"seatsDriver" SMALLINT NOT NULL,
|
||||
"seatsPassenger" SMALLINT NOT NULL,
|
||||
"toDate" DATE,
|
||||
"monTime" TIMESTAMPTZ,
|
||||
"tueTime" TIMESTAMPTZ,
|
||||
"wedTime" TIMESTAMPTZ,
|
||||
"thuTime" TIMESTAMPTZ,
|
||||
"friTime" TIMESTAMPTZ,
|
||||
"satTime" TIMESTAMPTZ,
|
||||
"sunTime" TIMESTAMPTZ,
|
||||
"monMargin" INTEGER,
|
||||
"tueMargin" INTEGER,
|
||||
"wedMargin" INTEGER,
|
||||
"thuMargin" INTEGER,
|
||||
"friMargin" INTEGER,
|
||||
"satMargin" INTEGER,
|
||||
"sunMargin" INTEGER,
|
||||
"seatsDriver" SMALLINT,
|
||||
"seatsPassenger" SMALLINT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
|
@ -33,14 +39,15 @@ CREATE TABLE "ad" (
|
|||
CREATE TABLE "address" (
|
||||
"uuid" UUID NOT NULL,
|
||||
"adUuid" UUID NOT NULL,
|
||||
"position" SMALLINT NOT NULL,
|
||||
"lon" DOUBLE PRECISION NOT NULL,
|
||||
"lat" DOUBLE PRECISION NOT NULL,
|
||||
"houseNumber" TEXT NOT NULL,
|
||||
"street" TEXT NOT NULL,
|
||||
"locality" TEXT NOT NULL,
|
||||
"postalCode" TEXT NOT NULL,
|
||||
"country" TEXT NOT NULL,
|
||||
"type" SMALLINT NOT NULL,
|
||||
"houseNumber" TEXT,
|
||||
"street" TEXT,
|
||||
"locality" TEXT,
|
||||
"postalCode" TEXT,
|
||||
"country" TEXT,
|
||||
"type" "AddressType" DEFAULT 'OTHER',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
|
@ -60,4 +67,4 @@ CREATE INDEX "ad_fromDate_idx" ON "ad"("fromDate");
|
|||
CREATE INDEX "ad_toDate_idx" ON "ad"("toDate");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "address" ADD CONSTRAINT "address_adUuid_fkey" FOREIGN KEY ("adUuid") REFERENCES "ad"("uuid") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "address" ADD CONSTRAINT "address_adUuid_fkey" FOREIGN KEY ("adUuid") REFERENCES "ad"("uuid") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -13,27 +13,27 @@ datasource db {
|
|||
model Ad {
|
||||
uuid String @id @default(uuid()) @db.Uuid
|
||||
userUuid String @db.Uuid
|
||||
driver Boolean
|
||||
passenger Boolean
|
||||
frequency Int
|
||||
driver Boolean?
|
||||
passenger Boolean?
|
||||
frequency Frequency @default(RECURRENT)
|
||||
fromDate DateTime @db.Date
|
||||
toDate DateTime @db.Date
|
||||
monTime DateTime @db.Timestamptz()
|
||||
tueTime DateTime @db.Timestamptz()
|
||||
wedTime DateTime @db.Timestamptz()
|
||||
thuTime DateTime @db.Timestamptz()
|
||||
friTime DateTime @db.Timestamptz()
|
||||
satTime DateTime @db.Timestamptz()
|
||||
sunTime DateTime @db.Timestamptz()
|
||||
monMargin Int
|
||||
tueMargin Int
|
||||
wedMargin Int
|
||||
thuMargin Int
|
||||
friMargin Int
|
||||
satMargin Int
|
||||
sunMargin Int
|
||||
seatsDriver Int @db.SmallInt
|
||||
seatsPassenger Int @db.SmallInt
|
||||
toDate DateTime? @db.Date
|
||||
monTime DateTime? @db.Timestamptz()
|
||||
tueTime DateTime? @db.Timestamptz()
|
||||
wedTime DateTime? @db.Timestamptz()
|
||||
thuTime DateTime? @db.Timestamptz()
|
||||
friTime DateTime? @db.Timestamptz()
|
||||
satTime DateTime? @db.Timestamptz()
|
||||
sunTime DateTime? @db.Timestamptz()
|
||||
monMargin Int?
|
||||
tueMargin Int?
|
||||
wedMargin Int?
|
||||
thuMargin Int?
|
||||
friMargin Int?
|
||||
satMargin Int?
|
||||
sunMargin Int?
|
||||
seatsDriver Int? @db.SmallInt
|
||||
seatsPassenger Int? @db.SmallInt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
addresses Address[]
|
||||
|
@ -46,19 +46,33 @@ model Ad {
|
|||
}
|
||||
|
||||
model Address {
|
||||
uuid String @id @default(uuid()) @db.Uuid
|
||||
adUuid String @db.Uuid
|
||||
uuid String @id @default(uuid()) @db.Uuid
|
||||
adUuid String @db.Uuid
|
||||
position Int @db.SmallInt
|
||||
lon Float
|
||||
lat Float
|
||||
houseNumber String
|
||||
street String
|
||||
locality String
|
||||
postalCode String
|
||||
country String
|
||||
type Int @db.SmallInt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
Ad Ad @relation(fields: [adUuid], references: [uuid])
|
||||
houseNumber String?
|
||||
street String?
|
||||
locality String?
|
||||
postalCode String?
|
||||
country String?
|
||||
type AddressType? @default(OTHER)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
Ad Ad @relation(fields: [adUuid], references: [uuid], onDelete: Cascade)
|
||||
|
||||
@@map("address")
|
||||
}
|
||||
|
||||
enum Frequency {
|
||||
PUNCTUAL
|
||||
RECURRENT
|
||||
}
|
||||
|
||||
enum AddressType {
|
||||
HOUSE_NUMBER
|
||||
STREET_ADDRESS
|
||||
LOCALITY
|
||||
VENUE
|
||||
OTHER
|
||||
}
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { AutoMap } from '@automapper/classes';
|
||||
|
||||
export class AdPresenter {
|
||||
@AutoMap()
|
||||
uuid: string;
|
||||
|
||||
@AutoMap()
|
||||
driver: boolean;
|
||||
}
|
|
@ -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 {}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue