Skip to content

Instantly share code, notes, and snippets.

@zarv1k
Last active April 12, 2024 07:14
Show Gist options
  • Save zarv1k/3ce359af1a3b2a7f1d99b4f66a17f1bc to your computer and use it in GitHub Desktop.
Save zarv1k/3ce359af1a3b2a7f1d99b4f66a17f1bc to your computer and use it in GitHub Desktop.
Unique Validator Example for NestJS
import { ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
import { Connection, EntitySchema, FindConditions, ObjectType } from 'typeorm';
interface UniqueValidationArguments<E> extends ValidationArguments {
constraints: [
ObjectType<E> | EntitySchema<E> | string,
((validationArguments: ValidationArguments) => FindConditions<E>) | keyof E,
];
}
export abstract class UniqueValidator implements ValidatorConstraintInterface {
protected constructor(protected readonly connection: Connection) {}
public async validate<E>(value: string, args: UniqueValidationArguments<E>) {
const [EntityClass, findCondition = args.property] = args.constraints;
return (
(await this.connection.getRepository(EntityClass).count({
where:
typeof findCondition === 'function'
? findCondition(args)
: {
[findCondition || args.property]: value,
},
})) <= 0
);
}
public defaultMessage(args: ValidationArguments) {
const [EntityClass] = args.constraints;
const entity = EntityClass.name || 'Entity';
return `${entity} with the same '${args.property}' already exist`;
}
}
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigService } from './config.service';
import useFactory from './db.factory';
import { Unique } from './validator';
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [LoggerModule],
inject: [ConfigService],
useFactory,
}),
],
providers: [Unique],
})
export class DbModule {}
import { IsInt, IsOptional, IsString, MinLength, Validate } from 'class-validator';
import { Category } from './category.entity';
import { Unique } from './validator';
export class CategoryDto {
@IsInt()
// checks if value of CategoryDto.id is unique by searching in Category.id in DB
@Validate(Unique, [Category])
public id: string;
@IsString()
// checks if value of CategoryDto.title is unique by searching in Category.title in DB
@Validate(Unique, [Category])
public title: string;
@IsString()
// checks if value of CategoryDto.someField is unique by searching in Category.title in DB
@Validate(Unique, [Category, 'title'])
public someField: string;
@Column()
@IsNotEmpty()
@IsString()
// checks if pair of provided title+description is unique in DB
@Validate(
Unique,
[
Category,
({ object: { title, description } }: { object: CategoryForm }) => ({
title,
description,
}),
],
{
message: ({
targetName,
}: ValidationArguments) =>
`${targetName} with the same pair of title and description already exist`,
},
)
public description: string;
}
import { ValidatorConstraint } from 'class-validator';
import { Injectable } from '@nestjs/common';
import { InjectConnection } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
import { UniqueValidator } from '../../utils/validator';
@ValidatorConstraint({ name: 'unique', async: true })
@Injectable()
export class UniqueAnotherConnection extends UniqueValidator {
constructor(
@InjectConnection('another-connection')
protected readonly connection: Connection,
) {
super(connection);
}
}
import { ValidatorConstraint } from 'class-validator';
import { Injectable } from '@nestjs/common';
import { InjectConnection } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
import { UniqueValidator } from '../../../utils/validator';
@ValidatorConstraint({ name: 'unique', async: true })
@Injectable()
export class Unique extends UniqueValidator {
constructor(@InjectConnection() protected readonly connection: Connection) {
super(connection);
}
}
@dancornilov
Copy link

Hey @zarv1k , thank you for your suggestion, did you update this part of code to Typeorm version 3?

@HORKimhab
Copy link

How to validate unique and ignore for current id like laravel.
Thank you.
IngnoreUnique

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment