WIP validation pipes
This commit is contained in:
parent
1db7dc1104
commit
ad10320f5f
|
@ -8,6 +8,7 @@ import { AdProfile } from './mappers/ad.profile';
|
||||||
import { AdsRepository } from './adapters/secondaries/ads.repository';
|
import { AdsRepository } from './adapters/secondaries/ads.repository';
|
||||||
import { Messager } from './adapters/secondaries/messager';
|
import { Messager } from './adapters/secondaries/messager';
|
||||||
import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
||||||
|
import { CreateAdUseCase } from './domain/usecases/create-ad.usecase';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -29,6 +30,12 @@ import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
controllers: [AdController],
|
controllers: [AdController],
|
||||||
providers: [AdProfile, AdsRepository, Messager, FindAdByUuidUseCase],
|
providers: [
|
||||||
|
AdProfile,
|
||||||
|
AdsRepository,
|
||||||
|
Messager,
|
||||||
|
FindAdByUuidUseCase,
|
||||||
|
CreateAdUseCase,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class AdModule {}
|
export class AdModule {}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import { Mapper } from '@automapper/core';
|
import { Mapper } from '@automapper/core';
|
||||||
import { InjectMapper } from '@automapper/nestjs';
|
import { InjectMapper } from '@automapper/nestjs';
|
||||||
import { Controller, UsePipes } from '@nestjs/common';
|
import { Controller, UsePipes } from '@nestjs/common';
|
||||||
import { QueryBus } from '@nestjs/cqrs';
|
import { CommandBus, QueryBus } from '@nestjs/cqrs';
|
||||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||||
import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe';
|
import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe';
|
||||||
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
|
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
|
||||||
import { AdPresenter } from './ad.presenter';
|
import { AdPresenter } from './ad.presenter';
|
||||||
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
||||||
import { Ad } from '../../domain/entities/ad';
|
import { Ad } from '../../domain/entities/ad';
|
||||||
|
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
|
||||||
|
import { CreateAdCommand } from '../../commands/create-ad.command';
|
||||||
|
import { DatabaseException } from 'src/modules/database/exceptions/database.exception';
|
||||||
|
|
||||||
@UsePipes(
|
@UsePipes(
|
||||||
new RpcValidationPipe({
|
new RpcValidationPipe({
|
||||||
|
@ -18,6 +21,7 @@ import { Ad } from '../../domain/entities/ad';
|
||||||
@Controller()
|
@Controller()
|
||||||
export class AdController {
|
export class AdController {
|
||||||
constructor(
|
constructor(
|
||||||
|
private readonly _commandBus: CommandBus,
|
||||||
private readonly queryBus: QueryBus,
|
private readonly queryBus: QueryBus,
|
||||||
@InjectMapper() private readonly _mapper: Mapper,
|
@InjectMapper() private readonly _mapper: Mapper,
|
||||||
) {}
|
) {}
|
||||||
|
@ -34,4 +38,22 @@ export class AdController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('AdsService', 'Create')
|
||||||
|
async createAd(data: CreateAdRequest): Promise<AdPresenter> {
|
||||||
|
try {
|
||||||
|
const ad = await this._commandBus.execute(new CreateAdCommand(data));
|
||||||
|
return this._mapper.map(ad, Ad, AdPresenter);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DatabaseException) {
|
||||||
|
if (e.message.includes('Already exists')) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 6,
|
||||||
|
message: 'Ad already exists',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RpcException({});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,15 @@ message Ad {
|
||||||
string userUuid = 2;
|
string userUuid = 2;
|
||||||
bool driver = 3;
|
bool driver = 3;
|
||||||
bool passenger = 4;
|
bool passenger = 4;
|
||||||
int32 frequency = 5;
|
Frequency frequency = 5;
|
||||||
string fromDate = 6;
|
string fromDate = 6;
|
||||||
string toDate = 7;
|
string toDate = 7;
|
||||||
Schedule schedule = 8;
|
Schedule schedule = 8;
|
||||||
MarginDurations marginDurations = 9;
|
MarginDurations marginDurations = 9;
|
||||||
int32 seatsPassenger = 10;
|
optional int32 seatsPassenger = 10;
|
||||||
int32 seatsDriver = 11;
|
optional int32 seatsDriver = 11;
|
||||||
bool strict = 12;
|
bool strict = 12;
|
||||||
Addresses addresses = 13;
|
repeated Address addresses = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Schedule {
|
message Schedule {
|
||||||
|
@ -50,10 +50,6 @@ message MarginDurations {
|
||||||
int32 sun = 7;
|
int32 sun = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Addresses {
|
|
||||||
repeated Address address = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Address {
|
message Address {
|
||||||
float lon = 1;
|
float lon = 1;
|
||||||
float lat = 2;
|
float lat = 2;
|
||||||
|
@ -73,6 +69,11 @@ enum AddressType {
|
||||||
OTHER = 5;
|
OTHER = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Frequency {
|
||||||
|
PUNCTUAL = 1;
|
||||||
|
RECURRENT = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message AdFilter {
|
message AdFilter {
|
||||||
optional int32 page = 1;
|
optional int32 page = 1;
|
||||||
optional int32 perPage = 2;
|
optional int32 perPage = 2;
|
||||||
|
|
|
@ -5,10 +5,12 @@ import {
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
IsDate,
|
IsDate,
|
||||||
IsInt,
|
IsInt,
|
||||||
MinLength,
|
|
||||||
ValidateIf,
|
ValidateIf,
|
||||||
|
ArrayMinSize,
|
||||||
|
IsArray,
|
||||||
|
IsEnum,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { FrequencyType } from '../entities/frequencyEnum';
|
import { Frequency } from '../entities/frequency.enum';
|
||||||
import { Address } from '../entities/address';
|
import { Address } from '../entities/address';
|
||||||
|
|
||||||
export class CreateAdRequest {
|
export class CreateAdRequest {
|
||||||
|
@ -22,21 +24,26 @@ export class CreateAdRequest {
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
|
|
||||||
@ValidateIf((ad) => (ad.passenger ? false : true))
|
@ValidateIf((ad) => (ad.passenger ? false : true))
|
||||||
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
driver?: boolean;
|
driver?: boolean;
|
||||||
|
|
||||||
@ValidateIf((ad) => (ad.driver ? false : true))
|
@ValidateIf((ad) => (ad.driver ? false : true))
|
||||||
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
passenger?: boolean;
|
passenger?: boolean;
|
||||||
|
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
frequency: FrequencyType;
|
@IsEnum(Frequency)
|
||||||
|
frequency: Frequency;
|
||||||
|
|
||||||
|
@IsDate()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
fromDate: Date;
|
fromDate: Date;
|
||||||
|
|
||||||
|
@IsDate()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
toDate: Date;
|
toDate: Date;
|
||||||
|
|
||||||
|
@ -111,11 +118,13 @@ export class CreateAdRequest {
|
||||||
sunMargin?: number;
|
sunMargin?: number;
|
||||||
|
|
||||||
@ValidateIf((ad) => (ad.passenger ? false : true))
|
@ValidateIf((ad) => (ad.passenger ? false : true))
|
||||||
|
@IsOptional()
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
seatsDriver?: number;
|
seatsDriver?: number;
|
||||||
|
|
||||||
@ValidateIf((ad) => (ad.driver ? false : true))
|
@ValidateIf((ad) => (ad.driver ? false : true))
|
||||||
|
@IsOptional()
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
seatsPassenger?: number;
|
seatsPassenger?: number;
|
||||||
|
@ -130,7 +139,7 @@ export class CreateAdRequest {
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
updatedAt?: Date;
|
updatedAt?: Date;
|
||||||
|
|
||||||
@MinLength(2)
|
@IsArray()
|
||||||
@AutoMap()
|
@AutoMap(() => [Address])
|
||||||
addresses?: Array<Address>;
|
addresses?: Array<Address>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
MinLength,
|
MinLength,
|
||||||
ValidateIf,
|
ValidateIf,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { FrequencyType } from '../entities/frequencyEnum';
|
import { Frequency } from './frequency.enum';
|
||||||
import { Address } from '../entities/address';
|
import { Address } from '../entities/address';
|
||||||
|
|
||||||
export class Ad {
|
export class Ad {
|
||||||
|
@ -31,7 +31,7 @@ export class Ad {
|
||||||
passenger?: boolean;
|
passenger?: boolean;
|
||||||
|
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
frequency: FrequencyType;
|
frequency: string;
|
||||||
|
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
fromDate: Date;
|
fromDate: Date;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { AutoMap } from '@automapper/classes';
|
import { AutoMap } from '@automapper/classes';
|
||||||
import { AddressType } from './addressEnum';
|
import { AddressType } from './address.enum';
|
||||||
|
|
||||||
export class Address {
|
export class Address {
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum Frequency {
|
||||||
|
PUNCTUAL = 1,
|
||||||
|
RECURRENT = 2,
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
export enum FrequencyType {
|
|
||||||
PUNCTUAL = 'PUNCTUAL',
|
|
||||||
RECURRENT = 'RECURRENT',
|
|
||||||
}
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { createMap, Mapper } from '@automapper/core';
|
import { createMap, forMember, mapFrom, Mapper } from '@automapper/core';
|
||||||
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Ad } from '../domain/entities/ad';
|
import { Ad } from '../domain/entities/ad';
|
||||||
import { AdPresenter } from '../adapters/primaries/ad.presenter';
|
import { AdPresenter } from '../adapters/primaries/ad.presenter';
|
||||||
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
|
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
|
||||||
|
import { Frequency } from '../domain/entities/frequency.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdProfile extends AutomapperProfile {
|
export class AdProfile extends AutomapperProfile {
|
||||||
|
@ -14,7 +15,17 @@ export class AdProfile extends AutomapperProfile {
|
||||||
override get profile() {
|
override get profile() {
|
||||||
return (mapper) => {
|
return (mapper) => {
|
||||||
createMap(mapper, Ad, AdPresenter);
|
createMap(mapper, Ad, AdPresenter);
|
||||||
createMap(mapper, CreateAdRequest, Ad);
|
createMap(
|
||||||
|
mapper,
|
||||||
|
CreateAdRequest,
|
||||||
|
Ad,
|
||||||
|
forMember(
|
||||||
|
(dest) => dest.frequency,
|
||||||
|
mapFrom((source) =>
|
||||||
|
source.frequency == Frequency.PUNCTUAL ? 'PUNCTUAL' : 'RECCURENT',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import { Address } from '../../domain/entities/address';
|
||||||
import { Messager } from '../../adapters/secondaries/messager';
|
import { Messager } from '../../adapters/secondaries/messager';
|
||||||
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
||||||
import { CreateAdCommand } from '../../commands/create-ad.command';
|
import { CreateAdCommand } from '../../commands/create-ad.command';
|
||||||
import { AddressType } from '../../domain/entities/addressEnum';
|
import { AddressType } from '../../domain/entities/address.enum';
|
||||||
import { AutomapperModule } from '@automapper/nestjs';
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
import { classes } from '@automapper/classes';
|
import { classes } from '@automapper/classes';
|
||||||
import { FrequencyType } from '../../domain/entities/frequencyEnum';
|
import { Frequency } from '../../domain/entities/frequency.enum';
|
||||||
import { Ad } from '../../domain/entities/ad';
|
import { Ad } from '../../domain/entities/ad';
|
||||||
import { AdProfile } from '../../mappers/ad.profile';
|
import { AdProfile } from '../../mappers/ad.profile';
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ const mockAddress1: Address = {
|
||||||
houseNumber: '5',
|
houseNumber: '5',
|
||||||
street: 'Avenue Foch',
|
street: 'Avenue Foch',
|
||||||
locality: 'Nancy',
|
locality: 'Nancy',
|
||||||
postalCode: '75000',
|
postalCode: '54000',
|
||||||
country: 'France',
|
country: 'France',
|
||||||
type: AddressType.HOUSE_NUMBER,
|
type: AddressType.HOUSE_NUMBER,
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,7 @@ const newAdRequest: CreateAdRequest = {
|
||||||
userUuid: '113e0000-0000-4000-a000-000000000000',
|
userUuid: '113e0000-0000-4000-a000-000000000000',
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: false,
|
passenger: false,
|
||||||
frequency: FrequencyType.RECURRENT,
|
frequency: Frequency.RECURRENT,
|
||||||
fromDate: new Date('01-05-2023'),
|
fromDate: new Date('01-05-2023'),
|
||||||
toDate: new Date('20-08-2023'),
|
toDate: new Date('20-08-2023'),
|
||||||
tueTime: new Date(''),
|
tueTime: new Date(''),
|
||||||
|
|
|
@ -88,6 +88,7 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||||
throw new DatabaseException(
|
throw new DatabaseException(
|
||||||
Prisma.PrismaClientKnownRequestError.name,
|
Prisma.PrismaClientKnownRequestError.name,
|
||||||
|
|
Loading…
Reference in New Issue