add constraint

This commit is contained in:
liuyi 2025-05-24 22:17:15 +08:00
parent 116b92fe98
commit 764fe06c50
2 changed files with 137 additions and 0 deletions

View File

@ -0,0 +1,69 @@
import { Injectable } from '@nestjs/common';
import {
ValidationArguments,
ValidatorConstraint,
ValidatorConstraintInterface,
ValidationOptions,
registerDecorator,
} from 'class-validator';
import { ObjectType, Repository, DataSource } from 'typeorm';
type Condition = {
entity: ObjectType<any>;
map?: string;
};
@ValidatorConstraint({ name: 'dataExist', async: true })
@Injectable()
export class DataExistConstraint implements ValidatorConstraintInterface {
constructor(private dataSource: DataSource) {}
async validate(value: any, validationArguments?: ValidationArguments) {
let repo: Repository<any>;
if (!value) {
return true;
}
let map = 'id';
if ('entity' in validationArguments.constraints[0]) {
map = validationArguments.constraints[0].map ?? 'id';
repo = this.dataSource.getRepository(validationArguments.constraints[0].entitiy);
} else {
repo = this.dataSource.getRepository(validationArguments.constraints[0]);
}
const item = await repo.findOne({ where: { [map]: value } });
return !!item;
}
defaultMessage?(validationArguments?: ValidationArguments): string {
if (!validationArguments.constraints[0]) {
return 'Model not been specified!';
}
return `All instance of ${validationArguments.constraints[0].name} must been exists in databse!`;
}
}
function IsDataExist(
entity: ObjectType<any>,
validationOptions?: ValidationOptions,
): (object: RecordAny, propertyName: string) => void;
function IsDataExist(
condition: Condition,
validationOptions?: ValidationOptions,
): (object: RecordAny, propertyName: string) => void;
function IsDataExist(
condition: Condition | ObjectType<any>,
validationOptions?: ValidationOptions,
): (object: RecordAny, propertyName: string) => void {
return (object: RecordAny, propertyName: string) => {
registerDecorator({
target: object.constructor,
propertyName,
options: validationOptions,
constraints: [condition],
validator: DataExistConstraint,
});
};
}
export { IsDataExist };

View File

@ -0,0 +1,68 @@
import { Injectable } from '@nestjs/common';
import {
registerDecorator,
ValidationArguments,
ValidatorConstraint,
ValidatorConstraintInterface,
ValidationOptions,
} from 'class-validator';
import { isNil, merge } from 'lodash';
import { DataSource, ObjectType } from 'typeorm';
type Condition = {
entity: ObjectType<any>;
property?: string;
};
@Injectable()
@ValidatorConstraint({ name: 'dataUnique', async: true })
export class UniqueConstraint implements ValidatorConstraintInterface {
constructor(private dataSource: DataSource) {}
async validate(value: any, validationArguments?: ValidationArguments): Promise<boolean> {
const config: Omit<Condition, 'entity'> = { property: validationArguments.property };
const condition = ('entity' in validationArguments.constraints[0]
? merge(config, validationArguments.constraints[0])
: {
...config,
entity: validationArguments.constraints[0],
}) as unknown as Required<Condition>;
if (!condition.entity) {
return false;
}
try {
const repo = this.dataSource.getRepository(condition.entity);
return isNil(
await repo.findOne({ where: { [condition.property]: value }, withDeleted: true }),
);
} catch (err) {
return false;
}
}
defaultMessage?(validationArguments?: ValidationArguments): string {
const { entity, property } = validationArguments.constraints[0];
const queryProperty = property ?? validationArguments.property;
if (!(validationArguments.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 IsUnique(
params: ObjectType<any> | Condition,
validationOptions: ValidationOptions,
) {
return (object: RecordAny, propertyName: string) => {
registerDecorator({
target: object.constructor,
propertyName,
options: validationOptions,
constraints: [params],
validator: UniqueConstraint,
});
};
}