[ ] Regression
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Hi! Thanks for the great work you guys are doing. The framework is amazing and the docs are very well written! Still, I have a question about how to organize my code in order to take the most out of Nest.
I have a Nest/React project and the structure is pretty much like this:
client //React files
server //Nest files
shared //Code that is used both on client and server
The shared folder is mainly filled with DTO's, so that the client knows exactly how to structure requests for the server.
All of my DTO's are also using class-validator's decorators, so that the basic rules (string length, empty array, number format) are also synced between client and server.
So to examplify, in order to build a funcionality for registering users, here's what I would have:
UserEntity (contains basic user data and TypeORM's mapped relationships, this goes into the _server folder_)
UserDTO (contains readable fields from UserEntity that returned in a given request. The properties of this file are uses validation rules based on class-validator's decorators. This file goes into the _shared folder_)
RegisterUserDTO (contains the necessary field in order to register a user. Also contains class-validator's validation. Also goes into _shared folder_).
This worked for me for a few months, until I decided to integrate Swagger into my project.
At the beggining it made a lot of sense for me to add Swagger's decorators into the DTO's which I already had, but when I did that, everything stopped working since Swagger requires a lot of stuff that is related to Node.js and is not available in the browser.
So the question is, how to you organize your entities/dtos in a real world application when using Nest combined with TypeORM, Swagger, and class-validator and so on, so that code can be shared between client and server?
Nest version: X.Y.Z
For Tooling issues:
- Node version: XX
- Platform:
Others:
So i am shure this is not the best solution, but here is how I do it with this combination. The dto is not used by the client. But a interface that is extended by the dto. Simple sample:
export class UserRegisterDto extends UserRegister {
...
}
export interface UserRegister {
...
}
I had/have the same problem.
What I ended up doing was the same thing as @creadicted did. Basically duplicate the DTOs to interfaces. Because that is quite annoying to maintain (basically copy/ paste) I ended up writing a tool which converts TS classes to interfaces using TS AST during the build process. Unfortunately you鈥檒l loose the class-validator functionality, because interfaces can not have any decorators. Maybe it would be useful if @nestjs/swagger would check if it runs in the browser and then noop the decorators, so you could share it in the backend and frontend? But thats also quite annyoing since nestjs/swagger would then end up in the built frontend files. You could definitely minimize the output by tree shaking, but still not optimal solution...
Hey @creadicted thanks for showing your approach. That decouples it a little more than what I've been doing, but how about the synchronization of validation between client and server? How do you do it?
I'm asking because by having a DTO with class-validator's decorators, I can have the rules automatically applied to both sides, and can prevent the client from sending bad requests to the server.
Thanks for sharing how you're doing it @BrunnerLivio. Just as you said, I guess having @nestjs/swagger in the browser is not a good idea, the issue is that it looks like everything else seems like a lot of copy/paste, which is not maintanable as the application grows.
@jeffersontpadua I believe that this should solve most of your issues https://github.com/nestjs/swagger/issues/191.
I was very excited about code sharing until I came across this problem as well. I use DTOs for both (de)serialization and validation. When shared practically acts like a contract between client and server.
Unfortunately, swagger decorators are ruining this. :(
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
I was very excited about code sharing until I came across this problem as well. I use DTOs for both (de)serialization and validation. When shared practically acts like a contract between client and server.
Unfortunately, swagger decorators are ruining this. :(