add constraint

This commit is contained in:
liuyi 2025-05-27 23:09:49 +08:00
parent a08964bd4a
commit e0d2f7652c
3 changed files with 77 additions and 1 deletions

View File

@ -11,9 +11,12 @@ import {
} from 'class-validator';
import { toNumber } from 'lodash';
import { IsUnique } from '@/modules/core/constraints/unique.constraint';
import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator';
import { PaginateOptions } from '@/modules/database/types';
import { TagEntity } from '../entities';
@DtoValidation({ type: 'query' })
export class QueryTagDto implements PaginateOptions {
@Transform(({ value }) => toNumber(value))
@ -31,6 +34,7 @@ export class QueryTagDto implements PaginateOptions {
@DtoValidation({ groups: ['create'] })
export class CreateTagDto {
@IsUnique(TagEntity, { groups: ['create'], message: 'The label names are repeated' })
@MaxLength(255, {
always: true,
message: 'The maximum length of the label name is $constraint1',

View File

@ -0,0 +1,71 @@
import {
registerDecorator,
ValidationArguments,
ValidationOptions,
ValidatorConstraintInterface,
} from 'class-validator';
import { isNil, merge } from 'lodash';
import { DataSource, Not, ObjectType } from 'typeorm';
type Condition = {
entity: ObjectType<any>;
ignore?: string;
ignoreKey?: string;
property?: string;
};
export class UniqueExistConstraint implements ValidatorConstraintInterface {
constructor(protected dataSource: DataSource) {}
async validate(value: any, args?: ValidationArguments): Promise<boolean> {
const config: Omit<Condition, 'entity'> = {
ignore: 'id',
property: args.property,
};
const condition = ('entity' in args.constraints[0]
? merge(config, args.constraints[0])
: { ...config, entity: args.constraints[0] }) as unknown as Required<Condition>;
if (!condition.entity) {
return false;
}
const ignoreValue = (args.object as any)[
isNil(condition.ignoreKey) ? condition.ignore : condition.ignoreKey
];
if (ignoreValue === undefined) {
return false;
}
const repo = this.dataSource.getRepository(condition.entity);
return isNil(
await repo.findOne({
where: { [condition.property]: value, [condition.ignore]: Not(ignoreValue) },
withDeleted: true,
}),
);
}
defaultMessage?(args?: ValidationArguments): string {
const { entity, property } = args.constraints[0];
const queryProperty = property ?? args.property;
if (!(args.object as any).getManager) {
return 'getManager function not been found!';
}
if (!entity) {
return 'Model not been specified!';
}
return `${queryProperty} of ${entity.name} must been unique!`;
}
}
export function IsUniqueExist(params: ObjectType<any> | Condition, options?: ValidationOptions) {
return (object: RecordAny, propertyName: string) => {
registerDecorator({
target: object.constructor,
propertyName,
options,
constraints: [params],
validator: UniqueExistConstraint,
});
};
}

View File

@ -6,6 +6,7 @@ import { DataSource, ObjectType } from 'typeorm';
import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants';
import { DataExistConstraint } from '../core/constraints/data.exist.constraint';
import { UniqueConstraint } from '../core/constraints/unique.constraint';
@Module({})
export class DatabaseModule {
@ -14,7 +15,7 @@ export class DatabaseModule {
global: true,
module: DatabaseModule,
imports: [TypeOrmModule.forRoot(configRegister())],
providers: [DataExistConstraint],
providers: [DataExistConstraint, UniqueConstraint],
};
}
static forRepository<T extends Type<any>>(