mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
fix(api): apply feedback
This commit is contained in:
parent
f15cae7b92
commit
e528dcc2c2
23
api/src/cms/decorators/unique-field-names.decorator.ts
Normal file
23
api/src/cms/decorators/unique-field-names.decorator.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
import { registerDecorator, ValidationOptions } from 'class-validator';
|
||||
|
||||
import { UniqueFieldNamesConstraint } from '../validators/validate-unique-names.validator';
|
||||
|
||||
export function UniqueFieldNames(validationOptions?: ValidationOptions) {
|
||||
return function (object: Record<string, any>, propertyName: string) {
|
||||
registerDecorator({
|
||||
target: object.constructor,
|
||||
propertyName,
|
||||
options: validationOptions,
|
||||
constraints: [],
|
||||
validator: UniqueFieldNamesConstraint,
|
||||
});
|
||||
};
|
||||
}
|
@ -21,6 +21,7 @@ import {
|
||||
import { FieldType } from '@/setting/schemas/types';
|
||||
import { DtoConfig } from '@/utils/types/dto.types';
|
||||
|
||||
import { UniqueFieldNames } from '../decorators/unique-field-names.decorator';
|
||||
import { ValidateRequiredFields } from '../validators/validate-required-fields.validator';
|
||||
|
||||
export class ContentField {
|
||||
@ -56,6 +57,7 @@ export class ContentTypeCreateDto {
|
||||
@ValidateNested({ each: true })
|
||||
@Validate(ValidateRequiredFields)
|
||||
@Type(() => ContentField)
|
||||
@UniqueFieldNames()
|
||||
fields?: ContentField[];
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import { ModelDefinition, Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { FieldType } from '@/setting/schemas/types';
|
||||
import { BaseSchema } from '@/utils/generics/base-schema';
|
||||
@ -28,7 +27,7 @@ export class ContentType extends BaseSchema {
|
||||
*/
|
||||
|
||||
@Prop({
|
||||
type: mongoose.Schema.Types.Mixed,
|
||||
type: [ContentField],
|
||||
default: [
|
||||
{
|
||||
name: 'title',
|
||||
@ -41,6 +40,25 @@ export class ContentType extends BaseSchema {
|
||||
type: FieldType.checkbox,
|
||||
},
|
||||
],
|
||||
required: true,
|
||||
validate: {
|
||||
/**
|
||||
* Ensures every `name` in the fields array is unique.
|
||||
* Runs on `save`, `create`, `insertMany`, and `findOneAndUpdate`
|
||||
* when `runValidators: true` is set.
|
||||
*/
|
||||
validator(fields: ContentField[]): boolean {
|
||||
if (!Array.isArray(fields)) return false;
|
||||
const seen = new Set<string>();
|
||||
return fields.every((f) => {
|
||||
if (seen.has(f.name)) return false;
|
||||
seen.add(f.name);
|
||||
return true;
|
||||
});
|
||||
},
|
||||
message:
|
||||
'Each element in "fields" must have a unique "name" (duplicate detected)',
|
||||
},
|
||||
})
|
||||
fields: ContentField[];
|
||||
}
|
||||
|
34
api/src/cms/validators/validate-unique-names.validator.ts
Normal file
34
api/src/cms/validators/validate-unique-names.validator.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||
*/
|
||||
|
||||
import {
|
||||
ValidationArguments,
|
||||
ValidatorConstraint,
|
||||
ValidatorConstraintInterface,
|
||||
} from 'class-validator';
|
||||
|
||||
import { ContentField } from '../dto/contentType.dto';
|
||||
|
||||
@ValidatorConstraint({ async: false })
|
||||
export class UniqueFieldNamesConstraint
|
||||
implements ValidatorConstraintInterface
|
||||
{
|
||||
validate(fields: ContentField[], _args: ValidationArguments) {
|
||||
if (!Array.isArray(fields)) return false;
|
||||
const seen = new Set<string>();
|
||||
return fields.every((f) => {
|
||||
if (seen.has(f.name)) return false;
|
||||
seen.add(f.name);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
defaultMessage(args: ValidationArguments) {
|
||||
return `${args.property} contains duplicate "name" values; each field.name must be unique`;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user