From a75a27e627208d85ae53d78a7e67881880354363 Mon Sep 17 00:00:00 2001 From: liuyi Date: Thu, 29 May 2025 11:07:25 +0800 Subject: [PATCH] add constraint --- src/modules/content/dtos/category.dto.ts | 6 +-- src/modules/content/dtos/comment.dto.ts | 2 +- src/modules/content/dtos/post.dto.ts | 2 +- src/modules/content/dtos/tag.dto.ts | 4 +- .../constraints/data.exist.constraint.ts | 0 src/modules/database/constraints/index.ts | 5 +++ .../constraints/tree.unique.constraint.ts | 20 ++++++++-- .../tree.unique.exist.constraint.ts | 40 ++++++++++++------- .../constraints/unique.constraint.ts | 0 .../constraints/unique.exist.constraint.ts | 0 src/modules/database/database.module.ts | 12 +++--- 11 files changed, 60 insertions(+), 31 deletions(-) rename src/modules/{core => database}/constraints/data.exist.constraint.ts (100%) create mode 100644 src/modules/database/constraints/index.ts rename src/modules/{core => database}/constraints/tree.unique.constraint.ts (78%) rename src/modules/{core => database}/constraints/tree.unique.exist.constraint.ts (71%) rename src/modules/{core => database}/constraints/unique.constraint.ts (100%) rename src/modules/{core => database}/constraints/unique.exist.constraint.ts (100%) diff --git a/src/modules/content/dtos/category.dto.ts b/src/modules/content/dtos/category.dto.ts index 5e6dfc4..c05b690 100644 --- a/src/modules/content/dtos/category.dto.ts +++ b/src/modules/content/dtos/category.dto.ts @@ -12,10 +12,10 @@ import { } from 'class-validator'; 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 { 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 { CategoryEntity } from '../entities'; diff --git a/src/modules/content/dtos/comment.dto.ts b/src/modules/content/dtos/comment.dto.ts index c7a5571..8b560bf 100644 --- a/src/modules/content/dtos/comment.dto.ts +++ b/src/modules/content/dtos/comment.dto.ts @@ -12,8 +12,8 @@ import { } from 'class-validator'; import { toNumber } from 'lodash'; -import { IsDataExist } from '@/modules/core/constraints/data.exist.constraint'; 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 { CommentEntity, PostEntity } from '../entities'; diff --git a/src/modules/content/dtos/post.dto.ts b/src/modules/content/dtos/post.dto.ts index 8757cb7..1e8a7c9 100644 --- a/src/modules/content/dtos/post.dto.ts +++ b/src/modules/content/dtos/post.dto.ts @@ -17,9 +17,9 @@ import { import { isNil, toNumber } from 'lodash'; 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 { toBoolean } from '@/modules/core/helpers'; +import { IsDataExist } from '@/modules/database/constraints/data.exist.constraint'; import { PaginateOptions } from '@/modules/database/types'; import { CategoryEntity, TagEntity } from '../entities'; diff --git a/src/modules/content/dtos/tag.dto.ts b/src/modules/content/dtos/tag.dto.ts index aa1bf08..ff5f257 100644 --- a/src/modules/content/dtos/tag.dto.ts +++ b/src/modules/content/dtos/tag.dto.ts @@ -11,8 +11,8 @@ import { } from 'class-validator'; import { toNumber } from 'lodash'; -import { IsUnique } from '@/modules/core/constraints/unique.constraint'; -import { IsUniqueExist } from '@/modules/core/constraints/unique.exist.constraint'; +import { IsUnique } from '@/modules/database/constraints/unique.constraint'; +import { IsUniqueExist } from '@/modules/database/constraints/unique.exist.constraint'; import { DtoValidation } from '@/modules/core/decorator/dto.validation.decorator'; import { PaginateOptions } from '@/modules/database/types'; diff --git a/src/modules/core/constraints/data.exist.constraint.ts b/src/modules/database/constraints/data.exist.constraint.ts similarity index 100% rename from src/modules/core/constraints/data.exist.constraint.ts rename to src/modules/database/constraints/data.exist.constraint.ts diff --git a/src/modules/database/constraints/index.ts b/src/modules/database/constraints/index.ts new file mode 100644 index 0000000..5e17887 --- /dev/null +++ b/src/modules/database/constraints/index.ts @@ -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'; diff --git a/src/modules/core/constraints/tree.unique.constraint.ts b/src/modules/database/constraints/tree.unique.constraint.ts similarity index 78% rename from src/modules/core/constraints/tree.unique.constraint.ts rename to src/modules/database/constraints/tree.unique.constraint.ts index 07dfc3c..b4c5911 100644 --- a/src/modules/core/constraints/tree.unique.constraint.ts +++ b/src/modules/database/constraints/tree.unique.constraint.ts @@ -12,6 +12,8 @@ import { DataSource, ObjectType } from 'typeorm'; type Condition = { entity: ObjectType; + parentKey?: string; + property?: string; }; @@ -23,6 +25,7 @@ export class TreeUniqueConstraint implements ValidatorConstraintInterface { async validate(value: any, args: ValidationArguments) { // 获取要验证的模型和字段 const config: Omit = { + parentKey: 'parent', property: args.property, }; const condition = ('entity' in args.constraints[0] @@ -34,12 +37,21 @@ export class TreeUniqueConstraint implements ValidatorConstraintInterface { if (!condition.entity) { return false; } + if (isNil(value)) { + return true; + } + const argsObj = args.object as any; try { // 查询是否存在数据,如果已经存在则验证失败 - const repo = this.dataSource.getRepository(condition.entity); - return isNil( - await repo.findOne({ where: { [condition.property]: value }, withDeleted: true }), - ); + const repo = this.dataSource.getTreeRepository(condition.entity); + const collections = await repo.find({ + where: { + parent: !argsObj[condition.parentKey] + ? null + : { id: argsObj[condition.parentKey] }, + }, + }); + return collections.every((item) => item[condition.property] !== value); } catch (err) { // 如果数据库操作异常则验证失败 return false; diff --git a/src/modules/core/constraints/tree.unique.exist.constraint.ts b/src/modules/database/constraints/tree.unique.exist.constraint.ts similarity index 71% rename from src/modules/core/constraints/tree.unique.exist.constraint.ts rename to src/modules/database/constraints/tree.unique.exist.constraint.ts index 258e517..63c07c7 100644 --- a/src/modules/core/constraints/tree.unique.exist.constraint.ts +++ b/src/modules/database/constraints/tree.unique.exist.constraint.ts @@ -6,8 +6,8 @@ import { ValidatorConstraint, ValidatorConstraintInterface, } from 'class-validator'; -import { isNil, merge } from 'lodash'; -import { DataSource, Not, ObjectType } from 'typeorm'; +import { merge } from 'lodash'; +import { DataSource, ObjectType } from 'typeorm'; type Condition = { entity: ObjectType; @@ -38,25 +38,35 @@ export class TreeUniqueExistContraint implements ValidatorConstraintInterface { if (!condition.entity) { return false; } + if (!condition.ignoreKey) { + condition.ignoreKey = condition.ignore; + } + const argsObj = args.object as any; // 在传入的dto数据中获取需要忽略的字段的值 - const ignoreValue = (args.object as any)[ - isNil(condition.ignoreKey) ? condition.ignore : condition.ignoreKey - ]; - // 如果忽略字段不存在则验证失败 - if (ignoreValue === undefined) { + const ignoreValue = argsObj[condition.ignore]; + const findValue = argsObj[condition.ignoreKey]; + if (!ignoreValue || !findValue) { return false; } + // 通过entity获取repository const repo = this.dataSource.getRepository(condition.entity); // 查询忽略字段之外的数据是否对queryProperty的值唯一 - return isNil( - await repo.findOne({ - where: { - [condition.property]: value, - [condition.ignore]: Not(ignoreValue), - }, - withDeleted: true, - }), + const item = await repo.findOne({ + where: { + [condition.ignoreKey]: findValue, + }, + relations: ['parent'], + }); + 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, ); } diff --git a/src/modules/core/constraints/unique.constraint.ts b/src/modules/database/constraints/unique.constraint.ts similarity index 100% rename from src/modules/core/constraints/unique.constraint.ts rename to src/modules/database/constraints/unique.constraint.ts diff --git a/src/modules/core/constraints/unique.exist.constraint.ts b/src/modules/database/constraints/unique.exist.constraint.ts similarity index 100% rename from src/modules/core/constraints/unique.exist.constraint.ts rename to src/modules/database/constraints/unique.exist.constraint.ts diff --git a/src/modules/database/database.module.ts b/src/modules/database/database.module.ts index a3389fe..d3baf66 100644 --- a/src/modules/database/database.module.ts +++ b/src/modules/database/database.module.ts @@ -5,11 +5,13 @@ import { DataSource, ObjectType } from 'typeorm'; import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants'; -import { DataExistConstraint } from '../core/constraints/data.exist.constraint'; -import { TreeUniqueConstraint } from '../core/constraints/tree.unique.constraint'; -import { TreeUniqueExistContraint } from '../core/constraints/tree.unique.exist.constraint'; -import { UniqueConstraint } from '../core/constraints/unique.constraint'; -import { UniqueExistConstraint } from '../core/constraints/unique.exist.constraint'; +import { + DataExistConstraint, + TreeUniqueConstraint, + TreeUniqueExistContraint, + UniqueConstraint, + UniqueExistConstraint, +} from './constraints'; @Module({}) export class DatabaseModule {