我正在尝试为 NestJS 中的输入类创建自定义验证器。这就是我所做的:
// is-building-id-provided.validator.ts
import { Injectable } from "@nestjs/common";
import { AddToQueueInput } from "@warp-core/building-queue/input/add-to-queue.input";
import { BuildingZoneService } from "@warp-core/building-zone/building-zone.service";
import { registerDecorator, ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
@ValidatorConstraint({ async: true })
@Injectable()
export class IsBuildingIdProvidedConstraint implements ValidatorConstraintInterface {
constructor(
protected readonly buildingZoneService: BuildingZoneService
) {}
async validate(buildingId: number, args: ValidationArguments) {
if (buildingId) {
return true;
}
const addToQueue = args.object as AddToQueueInput;
const buildingZone = await this.buildingZoneService.getSingleBuildingZone(
addToQueue.counterPerHabitat
);
if (!buildingZone.buildingId) {
return false;
}
return true;
}
defaultMessage(args: ValidationArguments) {
return `Building Id is required to create new building on existing building zone`;
}
}
export function IsBuildingIdProvided(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [],
validator: IsBuildingIdProvidedConstraint,
});
};
}
// add-to-queue.input.ts
import { Field, InputType, Int, PartialType } from "@nestjs/graphql";
import { IsBuildingIdProvided } from "@warp-core/building-queue/input/validator/is-building-id-provided.validator";
import { BuildingQueueElementModel } from "@warp-core/database/model/building-queue-element.model";
@InputType({description: "Creates new element in queue"})
export class AddToQueueInput extends PartialType(BuildingQueueElementModel)
{
@Field(type => Int, {
description: "Id of building type that will be constructed. If building is already placed, that field will be ignored"
})
@IsBuildingIdProvided()
buildingId?: number;
@Field(type => Int, {description: "How much levels will be build"})
endLevel: number;
}
// building-queue.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { AuthModule } from "@warp-core/auth/auth.module";
import { BuildingQueueAddService } from "@warp-core/building-queue/building-queue-add.service";
import { BuildingQueueResolver } from "@warp-core/building-queue/building-queue.resolver";
import { IsBuildingIdProvidedConstraint } from "@warp-core/building-queue/input/validator/is-building-id-provided.validator";
import { BuildingZoneModule } from "@warp-core/building-zone/building-zone.module";
import { BuildingModule } from "@warp-core/building/building.module";
import { DatabaseModule } from "@warp-core/database/database.module";
@Module({
providers: [
BuildingQueueAddService,
BuildingQueueResolver,
IsBuildingIdProvidedConstraint,
],
imports: [
BuildingZoneModule,
BuildingModule,
DatabaseModule,
ConfigModule,
AuthModule,
],
exports: [
]
})
export class BuildingQueueModule {
}
// main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from '@warp-core/app.module';
import { useContainer } from 'class-validator';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
transform: true,
}),
);
useContainer(app.select(AppModule), { fallbackOnErrors: true });
await app.listen(3000);
console.log("App is loaded at " + (await app.getUrl()) + "/graphql URL");
}
bootstrap();
如您所见,我的 Constraint 类有
Injectable
装饰器,所有外部模块也都导入到 module
文件中,并且在 main.ts
文件中我从 useContainer
包中调用 class-validator
函数。我想我已经完成了其他stack questions和NestJS github issues中提到的所有事情。不幸的是,每次我尝试使用注入函数时,buildingZoneService
都是未定义的。我不知道该怎么处理这个问题,我没有主意了......
验证器依赖项之一具有
Request
范围,并且不可能注入到 class-validator
自定义类中。 (https://github.com/nestjs/nest/issues/5566)
相反,我决定使用验证管道,如 Nest.js 文档中所述:https://docs.nestjs.com/pipes#binding-validation-pipes
我的项目配置中没有任何范围:Scope.Request,但即使执行了互联网上找到的所有步骤,我仍然无法将模块注入到约束中。你能告诉我你目前如何配置让它工作吗? 我还使用自定义验证管道扩展nestjs ValidationPipe