whefter / nestjs-joi

Easy to use JoiPipe as an interface between joi and NestJS with optional decorator-based schema construction.
MIT License
25 stars 12 forks source link

Arrays validation #9

Closed redwert closed 3 years ago

redwert commented 3 years ago

Currently if request body contains array we haven't any ability to validate it.

async someEndpoint(
    @Body() data: ItemDto[]
  ): Promise<void> {
    return 'OK'
  }

And the ItemDto iteslf:

@JoiSchemaOptions(...)
export classItemDto {
  @JoiSchema(...)
  myProp: string

What about to adjust JoiSchema decorator to work with class?

@JoiSchemaOptions(...)
@JoiSchema(Joi.array().min(1))
export classItemDto {
  @JoiSchema(...)
  myProp: string

Or add some additional options to JoiSchemaOptions? @JoiSchemaOptions({arrayValidationOptions: {minLength: 0, maxLength: 100 }})

whefter commented 3 years ago

The key problem here is that when this line is compiled to JavaScript:

@Body() data: ItemDto[]

the only type information retained is "data is an array", so this is all that Nest has to work with. In short, we have no information about which items the array contains, and even if we did, we'd have to potentially deal with lots of cases, as an array can contain any number of different classes. This also means that adding any kind of options to the schema or the type class has no effect, since we simply don't know which type is being used due to the loss of information.

The solution is to use an explicit JoiPipe and tell it which type to use:

async someEndpoint(
    @Body(new JoiPipe(Joi.array().items(getTypeSchema(ItemDto)), {group: CREATE)) data: ItemDto[]
): Promise<void> {
    return 'OK'
}

Any other solution that I can currently see effectively amount to introducing a shorthand for this, e.g. some kind of option for JoiPipe. I'll wait to see if this issue comes more often in the future.