Skip to content

Instantly share code, notes, and snippets.

@manashcse11
Created January 21, 2025 03:51
Show Gist options
  • Select an option

  • Save manashcse11/d0f82f81704637290b73f922a7345b2a to your computer and use it in GitHub Desktop.

Select an option

Save manashcse11/d0f82f81704637290b73f922a7345b2a to your computer and use it in GitHub Desktop.
#NestJS form validation for unique email
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PrismaModule } from './prisma/prisma.module';
import { UsersModule } from './users/users.module';
import { PostsModule } from './posts/posts.module';
import { UniqueEmailValidator } from './users/decorators/unique-email.decorator';
@Module({
imports: [PrismaModule, UsersModule, PostsModule],
controllers: [AppController],
providers: [AppService, UniqueEmailValidator],
})
export class AppModule {}
import { IsString, IsOptional, IsEmail, IsNotEmpty } from 'class-validator';
import { IsUniqueEmail } from '../decorators/unique-email.decorator';
export class CreateUserDto {
@IsEmail()
@IsNotEmpty()
@IsUniqueEmail()
email: string;
}
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { useContainer } from 'class-validator';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// This is the crucial part - tell class-validator to use NestJS's container
useContainer(app.select(AppModule), { fallbackOnErrors: true });
app.useGlobalPipes(new ValidationPipe());
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
import {
registerDecorator,
ValidationArguments,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
} from 'class-validator';
import { Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
@Injectable()
@ValidatorConstraint({ name: 'isUniqueEmail', async: true })
export class UniqueEmailValidator implements ValidatorConstraintInterface {
constructor(private readonly prisma: PrismaService) {}
async validate(email: string): Promise<boolean> {
try {
const user = await this.prisma.user.findUnique({
where: { email },
});
return !user;
} catch (error) {
return false;
}
}
defaultMessage(args: ValidationArguments) {
return `Email ${args.value} is already registered`;
}
}
export function IsUniqueEmail(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'isUniqueEmail',
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [],
validator: UniqueEmailValidator,
});
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment