Как внедрить службу в интерфейс ограничений валидатора в гнезде js, используя класс-валидатор? - PullRequest
1 голос
/ 04 февраля 2020

Я пытаюсь внедрить свою службу пользователей в интерфейс ограничений валидатора, но, похоже, она не работает:

import { ValidatorConstraintInterface, ValidatorConstraint, ValidationArguments, registerDecorator, ValidationOptions } from "class-validator";
import { UsersService } from './users.service';

@ValidatorConstraint({ async: true })
export class IsEmailAlreadyInUseConstraint implements ValidatorConstraintInterface {
    constructor(private usersService: UsersService) {
        console.log(this.usersService);
    }
    validate(email: any, args: ValidationArguments) {
        return this.usersService.findUserByEmail(email).then(user => {
             if (user) return false;
             return true;
        });
        return false;
    }

}

Но, поскольку usersService вошел в систему как ноль, я не могу получить доступ к его методам .

Есть идеи по этому вопросу?

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Для тех, кто может страдать от этой проблемы:

class-validator требует от вас использования сервисных контейнеров, если вы хотите внедрить зависимости в свои пользовательские классы ограничений валидатора. From: https://github.com/typestack/class-validator#using -service-container

import {useContainer, Validator} from "class-validator";

// do this somewhere in the global application level:
useContainer(Container);

Так что нам нужно добавить функцию пользовательского контейнера в глобальный уровень приложения.

1 , Добавьте следующий код в функцию main.ts bootstrap после объявления приложения:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  useContainer(app.select(AppModule), { fallbackOnErrors: true });
...}

Требуется {fallbackOnErrors: true}, потому что Nest генерирует исключение, когда DI не имеет требуемого класса .

2. Добавьте Injectable () к вашему ограничению:

import {ValidatorConstraint, ValidatorConstraintInterface} from 'class-validator';
import {UsersService} from './user.service';
import {Injectable} from '@nestjs/common';

@ValidatorConstraint({ name: 'isUserAlreadyExist', async: true })
@Injectable() // this is needed in order to the class be injected into the module
export class IsUserAlreadyExist implements ValidatorConstraintInterface {
    constructor(protected readonly usersService: UsersService) {}

    async validate(text: string) {
        const user = await this.usersService.findOne({
            email: text
        });
        return !user;
    }
}

3. Вставьте ограничение в свой модуль в качестве поставщика и убедитесь, что служба, которую вы намереваетесь внедрить в свое ограничение, также доступна для уровня модуля:

import {Module} from '@nestjs/common';
import { UsersController } from './user.controller';
import { UsersService } from './user.service';
import { IsUserAlreadyExist } from './user.validator';

@Module({
    controllers: [UsersController],
    providers: [IsUserAlreadyExist, UsersService],
    imports: [],
    exports: []
})
export class UserModule {
}
0 голосов
/ 04 февраля 2020

Вам потребуется обновить контейнер class-validator, чтобы использовать приложение Nest для повсеместного внедрения зависимостей. В этом выпуске GitHub рассказывается, как это сделать, и с некоторыми трудностями люди сталкиваются с ним.

Быстрое исправление без чтения ссылки:

async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  useContainer(app, { fallback: true });
  await app.listen(3000);
}
bootstrap();

При этом убедитесь, что вы также регистрируете свои валидаторы, как обычно, для любого гнезда @Injectable()

...