Skip to content

Instantly share code, notes, and snippets.

@kasir-barati
Created May 1, 2022 13:14
Show Gist options
  • Save kasir-barati/25d583896db45f93aef3e1fe4b06d640 to your computer and use it in GitHub Desktop.
Save kasir-barati/25d583896db45f93aef3e1fe4b06d640 to your computer and use it in GitHub Desktop.
Custom DTO for validating date
export const FlightRegionType: {
DOMESTIC: 'DOMESTIC',
INTERNATIONAL: 'INTERNATIONAL'
};
export const CabinClass: {
ECONOMY: 'ECONOMY',
BUSINESS: 'BUSINESS',
FIRST: 'FIRST'
};
export const TripType: {
ONE_WAY: 'ONE_WAY',
ROUND_TRIP: 'ROUND_TRIP',
MULTI_DESTINATION: 'MULTI_DESTINATION'
};
import { ClassConstructor } from 'class-transformer';
import {
registerDecorator,
ValidationArguments,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
} from 'class-validator';
export function IsBiggerThan<T>(
type: ClassConstructor<T>,
/**
* @description
* property can be departureDate or infant
*/
property: (o: T) => any,
biggerOrEqual: boolean,
validationArguments?: ValidationOptions,
) {
/**
* @description
* propertyName can be returnDate or adult
*/
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'IsBiggerThan',
propertyName: propertyName,
target: object.constructor,
validator: IsBiggerThanConstraint,
async: false,
constraints: [property, biggerOrEqual],
options: validationArguments,
});
};
}
@ValidatorConstraint({ name: 'IsBiggerThan', async: false })
export class IsBiggerThanConstraint
implements ValidatorConstraintInterface
{
/**
* @description
* propertyValue can be returnDate or infant
* targetPropertyValue can be departureDate or adult
*
* README: important note is that here I am relying on valueOf (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf)
*/
validate(propertyValue: any, args: ValidationArguments) {
const [fn, biggerOrEqual] = args.constraints;
const targetPropertyValue: any = fn(args.object);
return biggerOrEqual
? targetPropertyValue <= propertyValue
: targetPropertyValue < propertyValue;
}
defaultMessage(args: ValidationArguments) {
return `"${args.property}" must be less than "${args.constraints[0]}"`;
}
}
import { ApiProperty } from '@nestjs/swagger';
import {
IsDate,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
Max,
Min,
MinDate,
ValidateIf,
} from 'class-validator';
import {
CabinClass,
FlightRegionType,
TripType,
} from '@prisma/client';
import { Type } from 'class-transformer';
import { IsBiggerThan } from 'decorators/is-bigger-than.decorator';
export class SearchFlightsRequestDto {
@ApiProperty({
required: true,
enum: FlightRegionType,
description: `Flight region type.`,
example: FlightRegionType.INTERNATIONAL,
})
@IsNotEmpty()
@IsEnum(FlightRegionType)
flightRegionType: FlightRegionType = FlightRegionType.DOMESTIC;
@ApiProperty({
required: true,
description: 'Passenger origin city Id code',
example: 'TYO',
})
@IsNotEmpty()
originCity: string;
@ApiProperty({
required: true,
description: 'Passenger destination city Id code',
example: 'NYC',
})
@IsNotEmpty()
destinationCity: string;
@ApiProperty({
required: false,
description: 'Passenger origin airport Id code',
example: 'TYO',
})
@IsOptional()
originAirport?: string;
@ApiProperty({
required: false,
description: `Passenger destination airport Id code`,
example: 'AWZ',
})
@IsOptional()
destinationAirport?: string;
@ApiProperty({
required: true,
description: 'Departure flight date, When you go.',
example: new Date().toISOString(),
})
@IsDate()
@IsNotEmpty()
@MinDate(new Date())
departureDate: Date;
@ApiProperty({
required: false,
description: `Return flight date`,
})
@IsOptional()
@ValidateIf(
(filters: SearchFlightsRequestDto) =>
filters.tripType === TripType.ROUND_TRIP,
)
@IsDate()
@IsBiggerThan(
SearchFlightsRequestDto,
(searchFlightsRequest) => searchFlightsRequest.departureDate,
false,
)
returnDate?: Date;
@ApiProperty({
required: true,
enum: CabinClass,
description: `Flight cabin class, should be select between [ECONOMY, BUSINESS, FIRST]`,
example: 'ECONOMY',
})
@IsNotEmpty()
@IsEnum(CabinClass)
cabinClass: CabinClass;
@ApiProperty({
required: true,
enum: TripType,
description: `Flight type should be select between [ONE_WAY, ROUND_TRIP, MULTI_DESTINATION]`,
example: 'ONE_WAY',
})
@IsNotEmpty()
@IsEnum(TripType)
tripType: TripType;
@ApiProperty({
required: false,
description: `adult count`,
example: 1,
})
@IsOptional()
@Type(() => Number)
@IsNumber()
@Max(10)
@Min(1)
@IsBiggerThan(
SearchFlightsRequestDto,
(searchFlightsRequest) => searchFlightsRequest.infant,
true,
{
message:
'For each infant there should be an adult',
},
)
adult?: number = 1;
@ApiProperty({
required: false,
description: `children count`,
example: 0,
})
@IsOptional()
@Type(() => Number)
@IsNumber()
@Max(10)
@Min(0)
children?: number = 0;
@ApiProperty({
required: false,
description: `infant count`,
example: 0,
})
@IsOptional()
@Type(() => Number)
@IsNumber()
@Max(9)
@Min(0)
infant?: number = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment