I'd like to do a following body validation in my NestJs app:
a and b are optional properties if one of them is supplied, otherwise one of them should be required
payload: { a: 'some value', c: 'another value' } -> OK
payload: { b: 'some value', c: 'another value' } -> OK
payload: { a: 'some value1', b: 'some value2', c: 'another value' } -> OK
payload: { c: 'another value' } -> Error: either a or b should be present in the payload`
I have the following DTO:
class MyDto {
@OneOfOptionalRequired(['a', 'b'])
@ApiProperty()
@IsString()
@IsOptional()
a: string
@OneOfOptionalRequired(['a', 'b'])
@ApiProperty()
@IsString()
@IsOptional()
b: string
@ApiProperty()
@IsString()
c: string
}
I've tried creating my own decorator which will perform described validation:
export function OneOfOptionalRequired(requiredFields: string[], validationOptions?: ValidationOptions) {
return function (target: object, propertyName: string) {
registerDecorator({
name: 'oneOfOptionalRequired',
target: target.constructor,
propertyName: propertyName,
options: {
message: `Missing one of the required fields [${requiredFields}]`,
...validationOptions
},
validator: {
validate(value: unknown, args: ValidationArguments) {
const payload = args.object
return requiredFields.some(x => has(payload, x))
},
},
})
}
}
But actually it does not work for the case when only c property is present in the payload, because @IsOptional() turns off all of the decorators. If I remove @IsOptional() for a and b then I will get the error saying that a and b should not be empty. So I'm kind of stuck here