add constraint

This commit is contained in:
liuyi 2025-05-29 11:07:25 +08:00
parent 05160509ec
commit a75a27e627
11 changed files with 60 additions and 31 deletions

View File

@ -12,10 +12,10 @@ import {
} from 'class-validator'; } from 'class-validator';
import { toNumber } from 'lodash'; import { toNumber } from 'lodash';
import { IsDataExist } from '@/modules/core/constraints/data.exist.constraint';
import { IsTreeUnique } from '@/modules/core/constraints/tree.unique.constraint';
import { IsTreeUniqueExist } from '@/modules/core/constraints/tree.unique.exist.constraint';
import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator'; import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator';
import { IsDataExist } from '@/modules/database/constraints/data.exist.constraint';
import { IsTreeUnique } from '@/modules/database/constraints/tree.unique.constraint';
import { IsTreeUniqueExist } from '@/modules/database/constraints/tree.unique.exist.constraint';
import { PaginateOptions } from '@/modules/database/types'; import { PaginateOptions } from '@/modules/database/types';
import { CategoryEntity } from '../entities'; import { CategoryEntity } from '../entities';

View File

@ -12,8 +12,8 @@ import {
} from 'class-validator'; } from 'class-validator';
import { toNumber } from 'lodash'; import { toNumber } from 'lodash';
import { IsDataExist } from '@/modules/core/constraints/data.exist.constraint';
import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator'; import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator';
import { IsDataExist } from '@/modules/database/constraints/data.exist.constraint';
import { PaginateOptions } from '@/modules/database/types'; import { PaginateOptions } from '@/modules/database/types';
import { CommentEntity, PostEntity } from '../entities'; import { CommentEntity, PostEntity } from '../entities';

View File

@ -17,9 +17,9 @@ import {
import { isNil, toNumber } from 'lodash'; import { isNil, toNumber } from 'lodash';
import { PostOrder } from '@/modules/content/constants'; import { PostOrder } from '@/modules/content/constants';
import { IsDataExist } from '@/modules/core/constraints/data.exist.constraint';
import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator'; import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator';
import { toBoolean } from '@/modules/core/helpers'; import { toBoolean } from '@/modules/core/helpers';
import { IsDataExist } from '@/modules/database/constraints/data.exist.constraint';
import { PaginateOptions } from '@/modules/database/types'; import { PaginateOptions } from '@/modules/database/types';
import { CategoryEntity, TagEntity } from '../entities'; import { CategoryEntity, TagEntity } from '../entities';

View File

@ -11,8 +11,8 @@ import {
} from 'class-validator'; } from 'class-validator';
import { toNumber } from 'lodash'; import { toNumber } from 'lodash';
import { IsUnique } from '@/modules/core/constraints/unique.constraint'; import { IsUnique } from '@/modules/database/constraints/unique.constraint';
import { IsUniqueExist } from '@/modules/core/constraints/unique.exist.constraint'; import { IsUniqueExist } from '@/modules/database/constraints/unique.exist.constraint';
import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator'; import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator';
import { PaginateOptions } from '@/modules/database/types'; import { PaginateOptions } from '@/modules/database/types';

View File

@ -0,0 +1,5 @@
export * from './data.exist.constraint';
export * from './tree.unique.constraint';
export * from './tree.unique.exist.constraint';
export * from './unique.constraint';
export * from './unique.exist.constraint';

View File

@ -12,6 +12,8 @@ import { DataSource, ObjectType } from 'typeorm';
type Condition = { type Condition = {
entity: ObjectType<any>; entity: ObjectType<any>;
parentKey?: string;
property?: string; property?: string;
}; };
@ -23,6 +25,7 @@ export class TreeUniqueConstraint implements ValidatorConstraintInterface {
async validate(value: any, args: ValidationArguments) { async validate(value: any, args: ValidationArguments) {
// 获取要验证的模型和字段 // 获取要验证的模型和字段
const config: Omit<Condition, 'entity'> = { const config: Omit<Condition, 'entity'> = {
parentKey: 'parent',
property: args.property, property: args.property,
}; };
const condition = ('entity' in args.constraints[0] const condition = ('entity' in args.constraints[0]
@ -34,12 +37,21 @@ export class TreeUniqueConstraint implements ValidatorConstraintInterface {
if (!condition.entity) { if (!condition.entity) {
return false; return false;
} }
if (isNil(value)) {
return true;
}
const argsObj = args.object as any;
try { try {
// 查询是否存在数据,如果已经存在则验证失败 // 查询是否存在数据,如果已经存在则验证失败
const repo = this.dataSource.getRepository(condition.entity); const repo = this.dataSource.getTreeRepository(condition.entity);
return isNil( const collections = await repo.find({
await repo.findOne({ where: { [condition.property]: value }, withDeleted: true }), where: {
); parent: !argsObj[condition.parentKey]
? null
: { id: argsObj[condition.parentKey] },
},
});
return collections.every((item) => item[condition.property] !== value);
} catch (err) { } catch (err) {
// 如果数据库操作异常则验证失败 // 如果数据库操作异常则验证失败
return false; return false;

View File

@ -6,8 +6,8 @@ import {
ValidatorConstraint, ValidatorConstraint,
ValidatorConstraintInterface, ValidatorConstraintInterface,
} from 'class-validator'; } from 'class-validator';
import { isNil, merge } from 'lodash'; import { merge } from 'lodash';
import { DataSource, Not, ObjectType } from 'typeorm'; import { DataSource, ObjectType } from 'typeorm';
type Condition = { type Condition = {
entity: ObjectType<any>; entity: ObjectType<any>;
@ -38,25 +38,35 @@ export class TreeUniqueExistContraint implements ValidatorConstraintInterface {
if (!condition.entity) { if (!condition.entity) {
return false; return false;
} }
if (!condition.ignoreKey) {
condition.ignoreKey = condition.ignore;
}
const argsObj = args.object as any;
// 在传入的dto数据中获取需要忽略的字段的值 // 在传入的dto数据中获取需要忽略的字段的值
const ignoreValue = (args.object as any)[ const ignoreValue = argsObj[condition.ignore];
isNil(condition.ignoreKey) ? condition.ignore : condition.ignoreKey const findValue = argsObj[condition.ignoreKey];
]; if (!ignoreValue || !findValue) {
// 如果忽略字段不存在则验证失败
if (ignoreValue === undefined) {
return false; return false;
} }
// 通过entity获取repository // 通过entity获取repository
const repo = this.dataSource.getRepository(condition.entity); const repo = this.dataSource.getRepository(condition.entity);
// 查询忽略字段之外的数据是否对queryProperty的值唯一 // 查询忽略字段之外的数据是否对queryProperty的值唯一
return isNil( const item = await repo.findOne({
await repo.findOne({ where: {
where: { [condition.ignoreKey]: findValue,
[condition.property]: value, },
[condition.ignore]: Not(ignoreValue), relations: ['parent'],
}, });
withDeleted: true, if (!item) {
}), return false;
}
const rows = await repo.find({
where: { parent: item.parent ? { id: item.parent.id } : null },
withDeleted: true,
});
return !rows.find(
(row) => row[condition.property] === value && row[condition.ignore] !== ignoreValue,
); );
} }

View File

@ -5,11 +5,13 @@ import { DataSource, ObjectType } from 'typeorm';
import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants'; import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants';
import { DataExistConstraint } from '../core/constraints/data.exist.constraint'; import {
import { TreeUniqueConstraint } from '../core/constraints/tree.unique.constraint'; DataExistConstraint,
import { TreeUniqueExistContraint } from '../core/constraints/tree.unique.exist.constraint'; TreeUniqueConstraint,
import { UniqueConstraint } from '../core/constraints/unique.constraint'; TreeUniqueExistContraint,
import { UniqueExistConstraint } from '../core/constraints/unique.exist.constraint'; UniqueConstraint,
UniqueExistConstraint,
} from './constraints';
@Module({}) @Module({})
export class DatabaseModule { export class DatabaseModule {