Skip to content

Instantly share code, notes, and snippets.

@yaroslavTsebro
Last active January 19, 2024 14:48
Show Gist options
  • Select an option

  • Save yaroslavTsebro/e84e8e6633849e7c931aaf667a6b2a5c to your computer and use it in GitHub Desktop.

Select an option

Save yaroslavTsebro/e84e8e6633849e7c931aaf667a6b2a5c to your computer and use it in GitHub Desktop.
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Post()
getHello(@Body() album: Feature): string {
console.log(album);
return this.appService.getHello();
}
}
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, validate, ValidationOptions, registerDecorator } from 'class-validator';
import { UnionType, Templates, Box, Node } from './entities/test.dto';
@ValidatorConstraint({ async: false })
class IsMarkupNodeDtoConstraint implements ValidatorConstraintInterface {
async validate(dto: UnionType, args: ValidationArguments) {
const specifiedDto = getMarkupNodeDto(dto as Node);
if (!specifiedDto) return false;
const errors = await validate(specifiedDto);
if (errors.length > 0) return false;
return true;
}
}
export function IsMarkupNodeDto(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [],
validator: IsMarkupNodeDtoConstraint,
});
};
}
function getMarkupNodeDto(dto: Node): Text | Box | undefined {
if(!dto) return undefined
switch (dto.template) {
case Templates.BOX:
const entI = new Box();
Object.assign(entI, dto)
return entI;
case Templates.TEXT:
const ent = new Text();
Object.assign(ent, dto)
return ent;
default:
return undefined;
}
}
{
"message": [
""
],
"error": "Bad Request",
"statusCode": 400
}
{
"name": "name",
"options": [
{
"template": "BOX",
"children": [
{
"template": "TEXT",
"name": "name"
}
]
}
]
}
import { Type } from 'class-transformer'
import { IsEnum, IsObject, IsString, ValidateNested } from 'class-validator'
import { IsMarkupNodeDto } from 'src/is-markup-node-dto';
export type UnionType = Box | Text;
export enum Templates{
TEXT = "TEXT",
BOX = "BOX",
}
export abstract class Node{
abstract template: Templates;
}
export class Text extends Node{
@IsEnum(Templates)
template: Templates.TEXT;
@IsString()
text: string;
}
export class Box extends Node{
@IsEnum(Templates)
template: Templates.BOX;
@ValidateNested({each: true})
//@IsMarkupNodeDto() i use this only separately
@Type(() => Node, {
keepDiscriminatorProperty: true,
discriminator: {
property: 'template',
subTypes: [
{ value: Box, name: Templates.BOX },
{ value: Text, name: Templates.TEXT },
],
},
})
children: UnionType[];
}
export class Feature {
@IsString()
name: string
@ValidateNested()
//@IsMarkupNodeDto() i use this only separately
@Type(() => Node, {
keepDiscriminatorProperty: true,
discriminator: {
property: 'template',
subTypes: [
{ value: Box, name: Templates.BOX.toString() },
{ value: Text, name: Templates.TEXT.toString() },
],
},
})
option: UnionType;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment