Skip to content

How to make a DTO created with a custom mapping library appear at the validationMetadatasToSchemas return object? #118

@finom

Description

@finom

Thank you for the great project. I'm working on a library that supports DTOs for data validation. The validation should work on Edge Runtime, so I had to create a fork of @nestjs/mapped-types with some basic modifications to avoid import errors.

class-validator-jsonschema works perfect with regular DTOs, but struggles to identify a mapped DTO.

import { IsString, IsEmail, MinLength, MaxLength, IsUUID } from 'class-validator';
import { OmitType } from 'vovk-mapped-types';
import { JSONSchema, validationMetadatasToSchemas } from 'class-validator-jsonschema';

@JSONSchema({
  description: 'User DTO',
})
export default class UserDto {
  @IsUUID(4, { message: 'Invalid uuid format' })
  id: string;

  @IsString({ message: 'Name must be a string' })
  @MinLength(2, { message: 'Name must be at least 2 characters' })
  @MaxLength(20, { message: 'Name cannot exceed 20 characters' })
  name: string;

  @IsString({ message: 'Email must be a string' })
  @IsEmail({}, { message: 'Invalid email format' })
  email: string;
}

@JSONSchema({
  description: 'Create user DTO',
})

export class CreateUserDto extends OmitType(UserDto, ['id'] as const) {}

console.log('validationMetadatasToSchemas', validationMetadatasToSchemas())

The code logs

{
  UserDto: {
    properties: { id: [Object], name: [Object], email: [Object] },
    type: 'object',
    required: [ 'id', 'name', 'email' ]
  },
  OmitClassType: {
    properties: { name: [Object], email: [Object] },
    type: 'object',
    required: [ 'name', 'email' ]
  },
}

Where OmitClassType is an internal class of the mapping library that can be ignored.

As you can see CreateUserDto does not appear at the output, but if I add at least one extra property:

export class CreateUserDto extends OmitType(UserDto, ['id'] as const) {
  @IsEmail({}, { message: 'secondary email' })
  email2: string;
}

It works as expected:

 {
  UserDto: {
    properties: { id: [Object], name: [Object], email: [Object] },
    type: 'object',
    required: [ 'id', 'name', 'email' ],
    description: 'User DTO'
  },
  OmitClassType: {
    properties: { name: [Object], email: [Object] },
    type: 'object',
    required: [ 'name', 'email' ]
  },
  CreateUserDto: {
    properties: { email2: [Object], name: [Object], email: [Object] },
    type: 'object',
    required: [ 'email2', 'name', 'email' ],
    description: 'Create user DTO'
  }
}

Is there a way to avoid using class-validator decorators in order to make it appear at the returned object? If not, why not to also use JSONSchema to mark the class as a DTO (if it makes sense)?

Thank you for your help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions