Eu diria que mesmo em Java não é bem assim, você até tem o Spring, mas até onde eu entendo (que não é muito), o básico do básico, se divide em controller, service e repository, mas esses são só os esteriótipos do container de injeção de dependência dele, você pode fazer tudo funcionar só com controller e repository por exemplo. Se você for das antigas, o Java tinhas os Servelets e provavelmente você criaria um DAO também.
O ponto é que arquitetura não é algo relacionado a linguagem ou ecossistema, é algo que você aplica pois faz sentido organizar daquela forma, se você entende o que cada conceito significa, vai ser algo mais natural saber organizar o seu código sem se orientar pela maioria.
Se você aprendeu a separar em DTO, Repositories, e etc, organize assim também na suas aplicações Node que não vai ser lá um grande problema.
Como você pediu algumas sugestões, o meu apelo é que ao invés de se orientar pelos frameworks, ou confiar no jeito freestyle de alguém, você tente aprender sobre as arquiteturas de fato que já existem, e depois disso tirar suas próprias conclusões sobre como implementar no seu dia-a-dia. Uma série sensacional que aborda esse assunto é a do Herberto Graca: https://herbertograca.com/2017/07/03/the-software-architecture-chronicles/
Feito o aviso, minha recomendação é a arquitetura hexagonal, ela pode ser tão simples quanto implementar um spagetti code, e escalar tão complexa quanto uma implementação de DDD + Clean Architecture com Microsserviços. E como ela é bem simples, você pode usar qualquer padrão que você já conheça de outra arquitetura para organizar o seu código que provavelmente você consegue misturar bem as coisas
A ideia é bem simples, você pensa na sua aplicação, o que ela usa de fora (por exemplo o banco de dados), quem de fora usa ela (por exemplo o usuário num navegador web), e define interfaces para serem portas para cada um desses da aplicação, ai você implementa um adapter para essa porta, e depois instancia os objetos e passa cada adapter como dependência da sua aplicação (e ela como dependência dos adapters que usam ela), e pronto já tá implementado.
Um exemplo simples é uma aplicação web mesmo igual você sugeriu, você pode estruturar assim por exemplo:
- app/
- ports/
- in/
- FindPost.ts
- ListPosts.ts
- CreatePost.ts
- UpdatePost.ts
- DeletePost.ts
- out/
- PostRepository.ts
- in/
- services/
- PostService.ts
- ports/
- adapters/
- in/
- PostController.ts
- PostServiceTest.ts
- out/
- PrismaPostRepository.ts
- in/
Ai PostService
é uma classe que implementa as portas in, usa as portas out, e deve ser utilizada pelos adapters in como o PostController
ou um teste automatizado PostServiceTest
. As portas out são implementadas pelo PrismaPostRepository
lá nos adapters de out.
Links que eu recomendo sobre o assunto: https://jmgarridopaz.github.io/content/articles.html https://youtu.be/fkr6CNoMwx4
Bem interessante essa arquitetura.