I really like that you are using nestjs, idk why some devs hate it, IMHO its the best node framework that can be used to build production ready apps, i started using it a month ago at work and it was my first time using it, and it already made so productive
I'm literally in the middle of spending my evening, outside of work, gutting NestJS from a project I've inherited at work. I would literally consider changing jobs if I couldn't remove it.
There is so much to unpack to get as why I have such an issue with it. But time and again I have been frustrated with it in terms of: it's design philosophy, implementation, scope of what it covers, bloat, recommended implementation approaches, etc.
I don't understand how a single framework can think that it should cover: message/request handling, logging, config management, dependency inversion, persistence, and IO. These things have almost no cross over (i.e. if they are well designed they should be easily composable with any other component) but time and again framework developers attempt to bundle them into a "one size fits all solution".
To best sum it up. I think any package I use should be secondary to my application. But this package makes it so that my application is secondary to the framework.
I recently migrated my API from lambda functions do a dockerized Node API and I evaluated NestJS, though ended up using Fastify. Like others have mentioned, it's great for devs that come from Angular or Java but for me I didn't like that it used decorators all over the place and preferred to have something more "Express like"
This is precisely my experience. Classes are painful to deal with. Decorators are not only unergonomic, they also throw away any type safety. Also Nest shoves class transformer and class validator down your throat, which are also a pian in the ass.
Yes I noticed v5! I love it so much. The great thing about itty is you can integrate anything really easily.
I'm in the progress of making a simple middleware based on zod to parse not only request body, but also params, headers, etc. Zod is really powerful and you could even use it to do stuff like parse jwt tokens and have complete type inference.
Perhaps my only issue with this approach is that you rely on a wrapper function to correctly pass the generics fron the middleware to the main handler.
Another possible approach is using types-per-route but then it's hard to enforce that the validator agrees with the handler itself.
Same experience here. Admittedly it's been a few years since I last used it, but there was so much boilerplate coupled with a layer of "magic" that was too thick for my liking.
Provider initialization (dependency injection) failed on me on a few occasions and it always wasted hours of productivity. It would break in some obscure way that wouldn't log any errors to the console, so there was nothing to go on besides attaching a debugger and stepping through layers of framework code. It was quite infuriating because it always happened when I was in the middle of something else.
If your specific use case wasn't covered by their docs (which were very barebones and "hello-world" oriented at the time), it was painful to figure out and use.
nestjs is nice if you’re coming from Angular. It’s basically Angular for the backend.
But like Angular, there is a very wide range of use cases where it is totally overkill and like Angular, companies are throwing it at each and every project.
I don’t find it bad but it’s in a strange spot being more bloated than other JS frameworks while still being way less "batteries included" than more classical corporate frameworks.
Like Angular, I don’t hate it though it’s just that I still haven’t figured out a project where it’s better suited than something else.
NestJS is nodeJS for Java people. It's like Angular in that sense.
So some people will feel like it's over engineered.
I mean it's overengineered. Why do I have to register all these things, and why does it keep crashing if I register it like this without any understandable error message. It has a little bit of an OCD relationship with dependency injection. Where the normal import system can handle most of those cases.
But few nice things, resolvers, auto-generate swaggers. And TypeORM is lovely.
But yeah it's a bit too demanding. I'm okay with an opiniated framework if it gives a lot of features out of the box (like laravel or NextJs), but NestJS tells me how to do things without giving me enough in return. (auth, sockets etc are still quite a lot of work)
Yeah, I don't know, most of the time only time you actually need dep injection is for tests, and at that point why not just mock with Jest? Feels too much just having to do all this work just to complicate dependencies and make moving around more difficult for tests when a much simpler solution is available.
Just wanted to chime in and say that if you use the CLI to generate things, the experience is much nicer. However, you do still need to be in their playground. If you have a large team out org and don't want to have to document extra about the guts, I love having something proven. If you need to mix protocols, I believe Feathers JS was a little simpler to get into last I looked.
Dependency injection was not really meant to help with testing, but to keep code decoupled. It can be a nice pattern, but even if nestjs forces us to do it, we developers still find creative ways to nullify any attempts to decouple the code we write :).
It wasn't meant to, but it realistically and potentially feels only useful in those cases.
To me in most cases it is used it seems to just overengineer and obfuscate things unnecessarily when much simpler code would be easier to understand, etc.
It shouldn't be a thing that is done by default, only when it really makes sense.
Eventually with all those injections you are going to cause a situation where making any changes becomes really complex, if there are any use cases you didn't foresee at all.
In 90%+ cases you don't need interfaces and or DI, you should just be able to follow the logic with your IDE, it makes no sense to obfuscate that.
If the impl truly must vary for whatever case, then sure, you can use it.
But I would also say that don't do interfaces and impl before you actually need to switch them out dynamically depending on the context (and not just for testing).
If you have something that does Storage, and Storage drivers could be different like FileSystem, GoogleDrive, whatever, then sure use an interface, but not otherwise.
It's like DRY. Unless you actually use it 2-3 times, don't make everything unnecessarily into a reusable fn.
If you don't foresee having multiple storage methods in the near future then just use a class for storing which you can move to, to see how it does file storage or similar.
yeah agree, there was a time where everyone only wanted to code in patterns. I do think they are nice, but often most of us hardly understood the original reason why they were created.
I use nestjs in my open source no-code database https://github.com/teableio/teable, and I really like it, especially the dependency injection capability.
I wouldn't really recommend TS anymore. I would just go to a compiled language that actually has runtime type safety and a good ecosystem and devx. Although, it looks like Deno/Bun will improve things. After working with it for 5yrs, I just don't want to deal with the typescript compiler and ecosystem anymore, it's more of a headache than it's worth when Java (or ktl), Go, (and because HN: rust) are great.