Previous post
Agnostic API Schema Generator
How can you tell which protocol you should use for your API?
Both REST and GraphQL have their pros and cons. When it comes to the first one, it is easy to use and everyone is familiar with it. On the other hand, the latter provides an easier parameter validation, a possibility to get only the required parameters from a large response, etc.
For the purpose of our project, we’ve been thinking a lot and decided to use GraphQL. At first, things were going great. But as the team started to grow and a lot of functionalities started to pile up, we hit the first obstacles. Initially, we had everything written in a single schema file. So, we ended up with an extremely large file and lots of merge conflicts.
Divide and conquer
The solution for the large schema file was to modularize our schema and to move everything into smaller files. That went well. We had successfully mitigated one huge problem.
Don’t repeat yourself
After some time we noticed that we are repeating ourselves. We were coding methods with business logic first. After that, we added method calls inside the resolvers, followed by the schema definition. However, we noticed the following recurring patterns:
Our business logic methods:
Then the resolvers:
Finally our schema:
We came to an idea that the resolvers and schema parts can be easily generated. First, we did a research about which tools can do that and landed up with quite nice ones. Nevertheless, none of them was a good fit for our way of coding. At the end, we decided to create our own code generator.
Code Generator v1.0
Since our API is written in Typescript, we decided to proceed with a reflection-based solution. Unfortunately or luckily we weren’t able to get much meaningful metadata about our methods and were a bit afraid about the performance impact of the reflection-based solution. Thus, we agreed upon moving away from this approach.
Code Generator v2.0
The second idea was to listen for file changes, parse the code, then generate the schema and the resolvers as a part of a pre-build event.
We did research about Abstract Syntax Tree or AST. Luckily, TypeScript’s Compiler API exposes methods for generating AST tree of .ts files.
Step 1 requires to read your file contents and to create ts.SourceFile object using ts.createSourceFile method.
Step 2 is iterating through your code’s AST. Using ts.SyntaxKind enum, you can evaluate what kind of node you are dealing with – whether the node is for each statement, class, method, etc. You can get all the necessary metadata for each node: a list of arguments for each method, the argument names and types, the entity properties, etc.
Armed with all this data, the only thing left is to generate your source code. First, you need a string representation of the resolver class with API/Service method calls. The second thing is GraphQL schema definition string. Finally, all strings will be saved in their appropriate files and you’re ready to roll.
How to tell if the class method is Query or Mutation?
In order to differentiate the purpose of the methods, we have implemented custom TypeScript decorators. Each of them is named after HTTP verbs. For example, every method for data fetching is marked with ‘@Get’ decorator. Hence, all other methods are marked with: ‘@Post’, ‘@Put’ and ‘@Delete’ decorators respectfully.
Result
Now, having the Generator as a solution for the problem with the large schema file, we can be more focused on the business logic. It’s quite a relief knowing that we don’t have large files to merge or tedious duplicate code to write. Additional ease is the ability to switch from GraphQL to REST in a matter of minutes.
The result was writing API/Service classes in which each method is decorated with a simple decorator, shown in the example below.
I work on a TyphoonX – a cloud-native platform that automates application lifecycle management in cloud environments, focused on AWS.
If you have any questions, feel free to send me an email on krste.bozinoski@alite-international.com.
Share This Post
You may also like
Written by
Written by
Written by
Written by
We are all about going the extra mile. We deliver not only the expected, but the wished. We work hard to understand what the challenge is, how we can help our clients fast and in depth. Our mission is to deliver the change and transform not only the business but also the way value is created.
Make it more human, more efficient, more visionary. We work closely with our partners not only to transform but to enhance the way the run their business using technology in the most efficient and inspired way
Copyright 2020 Alite International. All Rights Reserved