refactor; create ad request validation

This commit is contained in:
sbriat
2023-04-26 12:10:22 +02:00
parent aeead7fb62
commit 5865464c53
28 changed files with 173 additions and 86 deletions

View File

@@ -5,28 +5,44 @@ import { InjectMapper } from '@automapper/nestjs';
import { Mapper } from '@automapper/core';
import { CommandBus } from '@nestjs/cqrs';
import { CreateAdCommand } from '../../commands/create-ad.command';
import { AdPresenter } from './ad.presenter';
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
import { ValidationError, validateOrReject } from 'class-validator';
@Controller()
export class AdMessagerController {
constructor(
private readonly _commandBus: CommandBus,
@InjectMapper() private readonly _mapper: Mapper,
private readonly commandBus: CommandBus,
@InjectMapper() private readonly mapper: Mapper,
) {}
@RabbitSubscribe({
name: 'adCreated',
})
async adCreatedHandler(message: string): Promise<AdPresenter> {
async adCreatedHandler(message: string): Promise<void> {
try {
const createAdRequest: CreateAdRequest = JSON.parse(message);
const ad: Ad = await this._commandBus.execute(
// parse message to conform to CreateAdRequest (not a real instance yet)
const parsedMessage: CreateAdRequest = JSON.parse(message);
// create a real instance of CreateAdRequest from parsed message
const createAdRequest: CreateAdRequest = this.mapper.map(
parsedMessage,
CreateAdRequest,
CreateAdRequest,
);
console.log(createAdRequest);
// validate instance
await validateOrReject(createAdRequest);
const ad: Ad = await this.commandBus.execute(
new CreateAdCommand(createAdRequest),
);
return this._mapper.map(ad, Ad, AdPresenter);
console.log(ad);
} catch (e) {
console.log('error', e);
if (Array.isArray(e)) {
e.forEach((error) =>
error instanceof ValidationError
? console.log(error.constraints)
: console.log(error),
);
}
}
}
}

View File

@@ -1,5 +1,18 @@
import { AutoMap } from '@automapper/classes';
import { IsBoolean, IsNotEmpty, IsNumber, IsString } from 'class-validator';
import {
ArrayMinSize,
IsArray,
IsBoolean,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
ValidateNested,
} from 'class-validator';
import { PointType } from '../../../geography/domain/types/point-type.enum';
import { Frequency } from '../types/frequency.enum';
import { Point } from '../../../geography/domain/types/point.type';
export class CreateAdRequest {
@IsString()
@@ -15,9 +28,10 @@ export class CreateAdRequest {
@AutoMap()
passenger: boolean;
@IsNumber()
@IsNotEmpty()
@IsEnum(Frequency)
@AutoMap()
frequency: number;
frequency: Frequency;
@IsString()
@AutoMap()
@@ -27,33 +41,40 @@ export class CreateAdRequest {
@AutoMap()
toDate: string;
@IsOptional()
@IsString()
@AutoMap()
monTime: string;
monTime: string | null;
@IsOptional()
@IsString()
@AutoMap()
tueTime: string;
tueTime: string | null;
@IsOptional()
@IsString()
@AutoMap()
wedTime: string;
wedTime: string | null;
@IsOptional()
@IsString()
@AutoMap()
thuTime: string;
thuTime!: string | null;
@IsOptional()
@IsString()
@AutoMap()
friTime: string;
friTime: string | null;
@IsOptional()
@IsString()
@AutoMap()
satTime: string;
satTime: string | null;
@IsOptional()
@IsString()
@AutoMap()
sunTime: string;
sunTime: string | null;
@IsNumber()
@AutoMap()
@@ -83,16 +104,19 @@ export class CreateAdRequest {
@AutoMap()
sunMargin: number;
@IsNumber()
@IsEnum(PointType)
@AutoMap()
originType: number;
originType: PointType;
@IsNumber()
@IsEnum(PointType)
@AutoMap()
destinationType: number;
destinationType: PointType;
@IsArray()
@ArrayMinSize(2)
@ValidateNested({ each: true })
@AutoMap()
waypoints: [];
waypoints: Array<Point>;
@IsNumber()
@AutoMap()
@@ -102,6 +126,7 @@ export class CreateAdRequest {
@AutoMap()
seatsPassenger: number;
@IsOptional()
@IsNumber()
@AutoMap()
seatsUsed: number;

View File

@@ -1,4 +1,7 @@
import { AutoMap } from '@automapper/classes';
import { ArrayMinSize, IsArray, IsEnum, ValidateNested } from 'class-validator';
import { PointType } from '../../../geography/domain/types/point-type.enum';
import { Point } from '../../../geography/domain/types/point.type';
export class Ad {
@AutoMap()
@@ -14,10 +17,10 @@ export class Ad {
frequency: number;
@AutoMap()
fromDate: string;
fromDate: Date;
@AutoMap()
toDate: string;
toDate: Date;
@AutoMap()
monTime: string;
@@ -73,14 +76,19 @@ export class Ad {
@AutoMap()
passengerDistance: number;
@IsEnum(PointType)
@AutoMap()
originType: number;
originType: PointType;
@IsEnum(PointType)
@AutoMap()
destinationType: number;
destinationType: PointType;
@IsArray()
@ArrayMinSize(2)
@ValidateNested({ each: true })
@AutoMap()
waypoints: [];
waypoints: Array<Point>;
@AutoMap()
direction: string;
@@ -101,8 +109,8 @@ export class Ad {
seatsUsed: number;
@AutoMap()
createdAt: string;
createdAt: Date;
@AutoMap()
updatedAt: string;
updatedAt: Date;
}

View File

@@ -0,0 +1,4 @@
export enum Frequency {
PUNCTUAL = 1,
RECURRENT = 2,
}

View File

@@ -2,14 +2,26 @@ import { CommandHandler } from '@nestjs/cqrs';
import { CreateAdCommand } from '../../commands/create-ad.command';
import { Ad } from '../entities/ad';
import { AdRepository } from '../../adapters/secondaries/ad.repository';
import { InjectMapper } from '@automapper/nestjs';
import { Mapper } from '@automapper/core';
import { CreateAdRequest } from '../dtos/create-ad.request';
@CommandHandler(CreateAdCommand)
export class CreateAdUseCase {
constructor(private readonly adRepository: AdRepository) {}
constructor(
@InjectMapper() private readonly mapper: Mapper,
private readonly adRepository: AdRepository,
) {}
async execute(command: CreateAdCommand): Promise<Ad> {
try {
return await this.adRepository.createAd(command.createAdRequest);
const adToCreate: Ad = this.mapper.map(
command.createAdRequest,
CreateAdRequest,
Ad,
);
return adToCreate;
// return await this.adRepository.createAd(adToCreate);
} catch (error) {
throw error;
}

View File

@@ -1,8 +1,9 @@
import { createMap, Mapper } from '@automapper/core';
import { createMap, forMember, mapFrom, 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';
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
@Injectable()
export class AdProfile extends AutomapperProfile {
@@ -13,6 +14,28 @@ export class AdProfile extends AutomapperProfile {
override get profile() {
return (mapper: any) => {
createMap(mapper, Ad, AdPresenter);
createMap(mapper, CreateAdRequest, CreateAdRequest);
createMap(
mapper,
CreateAdRequest,
Ad,
forMember(
(dest) => dest.fromDate,
mapFrom((source) => new Date(source.fromDate)),
),
forMember(
(dest) => dest.toDate,
mapFrom((source) => new Date(source.toDate)),
),
forMember(
(dest) => dest.createdAt,
mapFrom((source) => new Date(source.createdAt)),
),
forMember(
(dest) => dest.updatedAt,
mapFrom((source) => new Date(source.updatedAt)),
),
);
};
}
}