-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding validation decorators to plain DTO and Entity #30
Comments
Interesting use case. I think a separate QueryDTO would be the cleaner solution. Especially if it needs extra type conversion. So, query params are all strings by default. For basic types, type conversion should be simple.
should give {
q: ['foo', 'bar'],
bool: true,
count: 10,
} But what if the user defines more complex types, e.g., relations etc.? model Profile {
user User
} |
I too think that a dedicated QueryDTO would make a lot of sense. I do not however think, that the QueryDTO has to cover relations, as those would be available under their own path using a dedicated QueryDTO.
The But I would consider all of this API implementation details, that do not directly concern this library. Mapping multiple DTOs into a single QueryDTO can get quite messy if the DTO properties are not unique. Sometimes you want endpoints that take relations into consideration of course, as this would reduce the amount of queries needed, but in this case I would manually create a dedicated DTO, which can also be done using Nest's PartialType() mapping utility function, based on the QueryDTOs in question. Since the QueryDTOs, the new QueryDTO is based on, have all the transformation decorators in place these custom QueryDTOs should be able to make use of them, too. |
My question above was about how to handle relations and complex types. Since query params can only be simple strings, I think the fields The following model: model Profile {
id String @id
age Int
isAdmin Boolean
tags String[]
meta Json
user User @relation(...)
} could result in something like this: export class QueryProfileDto {
@ApiProperty({
required: false,
nullable: true
})
@IsOptional()
@IsString()
id?: string;
@ApiProperty({
type: 'integer',
format: 'int32',
required: false,
nullable: true
})
@IsOptional()
@IsInteger()
@Type(() => Number)
age?: number;
@ApiProperty({
required: false,
nullable: true
})
@IsOptional()
@IsBoolean()
@Transform(({ value }) => value === 'true' || value === '1')
isAdmin?: boolean;
@ApiProperty({
isArray: true,
required: false,
nullable: true
})
@IsOptional()
@IsArray()
@IsString()
tags?: string[];
} Possible query url:
I think |
Currently, validation decorators are only added to
CreateDTO
andUpdateDTO
, the types of DTOs which are used to send data to the API, unlikeEntity
andplain DTO
, which are returned by the API and therefore normally do not need validation decorators.Scenarios
Usage of Query() together with a DTO
I use the
plain DTO
to send data to the API, but since it lacks validation decorators the necessary type transformations are not applied, forcing me to transform the values manually.The
plain DTO
is used to type the query parameters of my GET endpoints. This allows consumers of the API to filter results using a combination of any of the DTO's fields. This is done by mapping theplain DTO
to a QueryDTO using Nest's PartialType() utility function, which creates a copy of theplain DTO
with all fields now optional.Since
QueryDTO
is now based on theplain DTO
it always reflects the table and the API consumer can apply whatever filter combination they want.Other possible scenarios
Nest's mapping utility functions can also be used to create more fine-grained DTOs or Entities for specific scenarios, for instance by using PickType() to trim the DTO down to what is needed.
For this to work well though, the base DTOs/Entities that are used together with these utility functions need to have class validators.
I propose an additional configuration flag that, if set to true, causes these validators to be added to both the
plain DTO
andEntity
.Problem when using Query() together with a DTO
Transformation using validation decorators only works when using Query(), if
enableImplicitConversion
enabled:This is not optimal, as there are downsides to using
enableImplicitConversion
.Solution
Explicitly adding a transform decorator to the property does the trick:
Note
Instead of adding these decorators to
plain DTO
andEntity
, a new DTO type could be introduced, which includes all fields theplain DTO
possesses, but also adds the required validation and transform decorators.The text was updated successfully, but these errors were encountered: