NestJS 自定义验证器不会在构造函数中注入服务 - 无法读取未定义的属性

问题描述 投票:0回答:2

我正在尝试为 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 questionsNestJS github issues中提到的所有事情。不幸的是,每次我尝试使用注入函数时,
buildingZoneService
都是未定义的。我不知道该怎么处理这个问题,我没有主意了......

node.js typescript nestjs class-validator
2个回答
1
投票

验证器依赖项之一具有

Request
范围,并且不可能注入到
class-validator
自定义类中。 (https://github.com/nestjs/nest/issues/5566

相反,我决定使用验证管道,如 Nest.js 文档中所述:https://docs.nestjs.com/pipes#binding-validation-pipes


0
投票

我的项目配置中没有任何范围:Scope.Request,但即使执行了互联网上找到的所有步骤,我仍然无法将模块注入到约束中。你能告诉我你目前如何配置让它工作吗? 我还使用自定义验证管道扩展nestjs ValidationPipe

© www.soinside.com 2019 - 2024. All rights reserved.