import { applyDecorators } from '@nestjs/common' ; import type { ApiPropertyOptions } from '@nestjs/swagger' ; import { ApiProperty } from '@nestjs/swagger' ; import { Type } from 'class-transformer' ; import { ArrayMaxSize , ArrayMinSize , ArrayNotEmpty , IsBoolean , IsDate , IsEmail , IsEnum , IsInt , IsNotEmpty , IsNumber , IsOptional , IsPositive , IsString , IsUrl , IsUUID , Max , MaxLength , Min , MinLength , ValidateNested , } from 'class-validator' ; import _ from 'lodash' ; import { supportedLanguageCount } from '../constants' ; import { ApiEnumProperty , ApiUUIDProperty } from './property.decorators' ; import { PhoneNumberSerializer , ToArray , ToBoolean , ToLowerCase , ToUpperCase , Trim , } from './transform.decorators' ; import { IsPassword , IsPhoneNumber , IsTmpKey } from './validator.decorators' ; type RequireField < T , K extends keyof T > = T & Required < Pick < T , K > > ; interface IStringFieldOptions { minLength ? : number ; maxLength ? : number ; toLowerCase ? : boolean ; toUpperCase ? : boolean ; swagger ? : boolean ; } interface INumberFieldOptions { each ? : boolean ; minimum ? : number ; maximum ? : number ; int ? : boolean ; isPositive ? : boolean ; swagger ? : boolean ; } export function NumberField ( options = { } ) { const decorators = [ Type ( ( ) => Number ) ] ; const { each , int , minimum , maximum , isPositive , swagger } = options ; if ( swagger !== false ) { decorators . push ( ApiProperty ( { type : Number , ... options , example : int ? 1 : 1.2 } ) ) ; } if ( each ) { decorators . push ( ToArray ( ) ) ; } if ( int ) { decorators . push ( IsInt ( { each } ) ) ; } else { decorators . push ( IsNumber ( { } , { each } ) ) ; } if ( _ . isNumber ( minimum ) ) { decorators . push ( Min ( minimum , { each } ) ) ; } if ( _ . isNumber ( maximum ) ) { decorators . push ( Max ( maximum , { each } ) ) ; } if ( isPositive ) { decorators . push ( IsPositive ( { each } ) ) ; } return applyDecorators ( ... decorators ) ; } export function NumberFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , NumberField ( { required : false , ... options } ) ) ; } export function StringField ( options = { } ) { const decorators = [ IsNotEmpty ( ) , IsString ( ) , Trim ( ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( { type : String , ... options } ) ) ; } if ( options ?. minLength ) { decorators . push ( MinLength ( options . minLength ) ) ; } if ( options ?. maxLength ) { decorators . push ( MaxLength ( options . maxLength ) ) ; } if ( options ?. toLowerCase ) { decorators . push ( ToLowerCase ( ) ) ; } if ( options ?. toUpperCase ) { decorators . push ( ToUpperCase ( ) ) ; } return applyDecorators ( ... decorators ) ; } export function StringFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , StringField ( { required : false , ... options } ) ) ; } export function PasswordField ( options = { } ) { return applyDecorators ( StringField ( { format : '^[\\d!#$%&*@A-Z^a-z]*$' , ... options } ) , IsPassword ( ) ) ; } export function PasswordFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , PasswordField ( { required : false , ... options } ) ) ; } export function BooleanField ( options = { } ) { const decorators = [ IsBoolean ( ) , ToBoolean ( ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( { type : Boolean , ... options } ) ) ; } return applyDecorators ( ... decorators ) ; } export function BooleanFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , BooleanField ( { required : false , ... options } ) ) ; } export function TranslationsField ( options ) { const decorators = [ ArrayMinSize ( supportedLanguageCount ) , ArrayMaxSize ( supportedLanguageCount ) , ValidateNested ( { each : true , } ) , Type ( ( ) => options . type as FunctionConstructor ) , ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( { isArray : true , ... options } ) ) ; } return applyDecorators ( ... decorators ) ; } export function TranslationsFieldOptional ( options ) { return applyDecorators ( IsOptional ( ) , TranslationsField ( { required : false , ... options } ) ) ; } export function TmpKeyField ( options = { } ) { const decorators = [ IsTmpKey ( ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( { type : String , ... options } ) ) ; } return applyDecorators ( ... decorators ) ; } export function TmpKeyFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , TmpKeyField ( { required : false , ... options } ) ) ; } export function EnumField < TEnum > ( getEnum , options = { } ) { const enumValue = getEnum ( ) as any ; const decorators = [ IsEnum ( enumValue , { each : options . each } ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiEnumProperty ( getEnum , options ) ) ; } if ( options . each ) { decorators . push ( ToArray ( ) ) ; } return applyDecorators ( ... decorators ) ; } export function EnumFieldOptional < TEnum > ( getEnum , options = { } ) { return applyDecorators ( IsOptional ( ) , EnumField ( getEnum , { required : false , ... options } ) ) ; } export function EmailField ( options = { } ) { const decorators = [ IsEmail ( ) , StringField ( { toLowerCase : true , ... options } ) , ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( { type : String , ... options } ) ) ; } return applyDecorators ( ... decorators ) ; } export function EmailFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , EmailField ( { required : false , ... options } ) ) ; } export function PhoneField ( options = { } ) { const decorators = [ IsPhoneNumber ( ) , PhoneNumberSerializer ( ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( { type : String , ... options } ) ) ; } return applyDecorators ( ... decorators ) ; } export function PhoneFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , PhoneField ( { required : false , ... options } ) ) ; } export function UUIDField ( options = { } ) { const decorators = [ IsUUID ( '4' , { each : options ?. each } ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiUUIDProperty ( options ) ) ; } if ( options ?. each ) { decorators . push ( ArrayNotEmpty ( ) , ToArray ( ) ) ; } return applyDecorators ( ... decorators ) ; } export function UUIDFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , UUIDField ( { required : false , ... options } ) ) ; } export function URLField ( options = { } ) { return applyDecorators ( StringField ( options ) , IsUrl ( ) ) ; } export function URLFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , URLField ( { required : false , ... options } ) ) ; } export function DateField ( options = { } ) { const decorators = [ Type ( ( ) => Date ) , IsDate ( ) ] ; if ( options ?. swagger !== false ) { decorators . push ( ApiProperty ( options ) ) ; } return applyDecorators ( ... decorators ) ; } export function DateFieldOptional ( options = { } ) { return applyDecorators ( IsOptional ( ) , DateField ( { ... options , required : false } ) ) ; }