Seems like there's an opportunity here to simplify the DX using Typescript decorators. I'd be interested in contributing if this is a direction you want to go.
Hi @bmayen! Would love to hear about your ideas. Do you have an API proposal in mind?
Afaik this missing TypeScript feature is currently blocking a lot of functionality based on a decorator based API compared to Nexus' current API.
Yep! @schickling and I have discussed the pros/cons of a decorator based API at length, and once you start to go down that route you really end up with quite a different API than nexus has currently.
My personal opinion is that keeping the data access objects separated from the schema definition (as is nexus' current approach) leads to an overall design that is simpler and easier to develop/test than tightly coupling the two via decorators, but I'm open to exploring any ideas around what a decorator based API might look like and how it would function with the guarantees around end-to-end type-safety nexus is striving for.
For context, I came here via https://github.com/19majkel94/type-graphql/issues/217. Though @19majkel94 reacted above with the confused emoji, so perhaps I'm missing something :)
Saw this issue and considering I just had to solve some none trivial problems that involve decorators I thought it would be useful to share my opinion and recent experience.
I've just recently finished a proof of concept to look into using nexus for our existing codebase. One of the major pain points that I encountered was a weird and surprising interplay between ts-node, the use of decorators (with metadata) and nexus.
Our backend stack consists of a fairly simple stack, we previously used most of the apollo toolset and use a schema first approach where we write our schema in .gql files first. We also do most of the data access directly in the resolver layer and use TypeORM for this. We invested a lot in the usage of decorators (because the framework promotes it heavily). The decorators for TypeORM aren't just your typical higher order function decorators. They are decorators who also require the need for reflect-metadata (and TypeScripts feature to emit additional metadata).
The problem I encoutered was the following:
In order to start up our server we need this decorator metadata to be emitted, otherwise TypeORM cannot successfully map our entities to the database schema. This requirement means that we have to use ts-node (or ts-node-dev) without using --transpile-only (we need the TypeScript metadata from a successfuly compile in order to have metadata). In order to pair this with nexus we run into the problem that for a workflow with nexus we need a ---transpile-only startup because the types are incomplete until the server (re)starts.
I eventually came up with a solution to use 2 ts-node processes that are ran in sequence and a nodemon watcher to pick up changes. The first ts-node process is a simple script that takes in all the type declarations built with nexus and generates the missing type definitions by using --transpile-only. The second ts-node process is our actual server start with the "complete" schema and is started in "full compile" so that our entities can be powered by TypeORM.
The problem here is that this setup is messy. (if anyone has a better solution then my current one, I'm all ears!)
So if nexus would ever ship with a decorator approach, all I can say is be careful with this approach. The use of decorators is still experimental, and it shows in more exotic use cases like the one I had to solve.
Also I came to the opinion that nexus and a decorator approach could solve the same problem but their solution use a different approach, and these approaches are not always easy to combine.
So if nexus would ever ship with a decorator approach, all I can say is be careful with this approach. The use of decorators is still experimental, and it shows in more exotic use cases like the one I had to solve.
I 100% agree with this - this is why I have held off on considering decorators in nexus' approach.
In order to start up our server we need this decorator metadata to be emitted, otherwise TypeORM cannot successfully map our entities to the database schema. This requirement means that we have to use ts-node (or ts-node-dev) without using --transpile-only
Wow, that sounds like quite a strict workflow. If your types don't pass, then the ts-node-dev server doesn't start?
(if anyone has a better solution then my current one, I'm all ears!)
I'm beginning to think it might be good to develop an opinionated CLI that could be a devDependency and ships with commands for the common cases of Nexus development.
This requirement means that we have to use ts-node (or ts-node-dev) without using --transpile-only (we need the TypeScript metadata from a successfuly compile in order to have metadata).
That's not true. Types reflection is part of a normal transpilation (emiting JS code) process, type checking is a different story. The only case that a year ago was true was missing Date type while using transpile-only but it has been fixed.
That's not true. Types reflection is part of a normal transpilation (emiting JS code) process, type checking is a different story. The only case that a year ago was true was missing
Datetype while usingtranspile-onlybut it has been fixed.
I have tried our setup with ts-node v6, v7 and v8. Unless I missed something TypeORM would crash as soon as we tried to establish a connection and complained about missing type information on columns, as soon as we removed --transpile-only it would be fine. Also v8 has a very big performance issue when it comes to decorators. When I upgraded to v8 I would have to wait over 3minutes for our server to start, and the issue seemed to be decorator files taking an insane amount to be imported.
But this is going off-topic when it comes to nexus. I only posted my experience to indicate to be cautious when moving forward with experimental features.
Decorators are not on the roadmap and no indication currently that they ever will be. We can re-open if the situation changes. As is I think this issue has been pretty well answered. 馃
Most helpful comment
Yep! @schickling and I have discussed the pros/cons of a decorator based API at length, and once you start to go down that route you really end up with quite a different API than nexus has currently.
My personal opinion is that keeping the data access objects separated from the schema definition (as is nexus' current approach) leads to an overall design that is simpler and easier to develop/test than tightly coupling the two via decorators, but I'm open to exploring any ideas around what a decorator based API might look like and how it would function with the guarantees around end-to-end type-safety nexus is striving for.