在 NestJS 和 GraphQL 中使用 class-validator 支持对可选参数的验证?

Give support for validation on optional parameter using class-validator in NestJS and GraphQL?

我有这个 input 用于更新块。我希望用户可以更新名称或内容或两者。 现在的问题是,如果我只传递名称 GrapQL 会抛出一个错误,例如 Variable \"$updateBlockInput\" got invalid value { name: \"Updated again\" }; Field content of required type String! was not provided. 和 vice varsa.

我做错了什么?


更新-block.input.ts

import { InputType, Field } from '@nestjs/graphql';
import { IsOptional, IsNotEmpty } from 'class-validator';

@InputType()
export class UpdateBlockInput {
  @IsOptional()
  @IsNotEmpty()
  @Field()
  name?: string;

  @IsOptional()
  @IsNotEmpty()
  @Field()
  content?: string;
}

block.resolver.ts

...
@Mutation(returns => BlockType)
updateBlock(
  @Args('id') id: string,
  @Args('updateBlockInput') updateBlockInput: UpdateBlockInput,
) {
  return this.blockService.update(id, updateBlockInput);
}
...

变异

mutation(
  $id: String!
  $updateBlockInput: UpdateBlockInput!
) {
  updateBlock(
    id: $id
    updateBlockInput: $updateBlockInput
  ) {
    name
    content
  }
}

变量

{
  "id": "087e7c12-b48f-4ac4-ae76-1b9a96bbcbdc",
  "updateBlockInput": {
    "name": "Updated again"
  }
}

如果它们是可选的,那么您需要避免使用 IsNotEmpty 并用 IsString 替换,表示如果存在该值,则它必须仅为字符串类型。

如果您想接受其中任何一个,但在未发送时失败,您需要编写自己的自定义验证器,因为开箱即用不支持这种情况。

一个例子:

import {ValidatorConstraint, ValidatorConstraintInterface} from 'class-validator';
@ValidatorConstraint({async: false})
export class IsInPast implements ValidatorConstraintInterface {
    public validate(value: unknown): boolean {
        if (typeof value !== 'string' && typeof value !== 'number') {
            return false;
        }
        const now = new Date();
        now.setHours(23);
        now.setMinutes(59);
        now.setSeconds(59);
        now.setMilliseconds(999);
        return `${value}`.match(/^\d+$/) !== null && `${value}` <= `${now.getTime()}`;
    }

    public defaultMessage(): string {
        return 'Should be in past';
    }
}

以及稍后在代码中的某处:

@Validate(IsInPast)
public dateField: string;