Level-Up Your Decorators
By: Aishwarya Shrestha
Tags: GraphQL, Decorators, Grpc, Schema, Mongodb

I am working on a project that develops a data access layer with a gRPC-backed microservice application on Node.js with graphQL to aggregate data from multiple sources. In graphQL, every data uses a schema to define the types of data it includes therefore to enforce a schema’s structure we use Apollo Server.

In this article, I am not going to describe about under-the-hood connection of these stacks. I would suggest you stay tuned for that!

A common problem using gRPC and graphQL together along with MongoDB is that developer needs to creates a separate gRPC message; schema for graphQL; and mongo document. As this is the standard way, you can find this method in all the codebase with these stacks.

But the main question is, shouldn’t we just reflect back to the steps required to change the schema and mirror it in the system? If you are familiar with the concept of gRPC and graphQL, you would pretty much know about all the hassles to be made in each file.

Too much work right? Don’t worry.

Here we are with a unique idea to synthesize this concept!

As we are already going to write a schema for graphQL, we came up with a solution to not bother to use the generated code from gRPC, hence implementing this would be helpful to reduce extra work.

Extra work in the sense that if we need to make a change in our graphQL schema, the developer would need to change the field in the mongo document schema, then the developer have to change the messages field in protobuf and then have to go to the steps of re-generating the new protobuf message code and finally updating the grpc service and graphql. So to save up time we have implemented a technique to keep all the schemas in one place.

The main objective of this article is to showcase a synthesized schema, ie. a single file for the schema of graphQL, protocol buffers, and MongoDB.

Let’s take an example of Image structure!

In a standard way, files look like those mentioned below:

The MongoDB schema

This is the schema we are taking for the image:

Fig: Image document

Its corresponding document schema:

Fig: Image document schema on MongoDB

The GraphQL schema

GraphQL schema defines what types of data a client can read and write to your data graph. Schemas are strongly typed, which unlocks powerful developer tooling. The GraphQL schema for an Image for the above document would look like this:

Fig: Gql schema

Protocol buffers structure

The gRPC uses protocol buffers by default as the definition language and message formatter. In our example, the .proto file that defines the structure and the .proto file starts with a package declaration, and its structure would look like this:

Fig: image.proto file

The above mentioned are the standard way of defining gRPC, mongo schema, and graphQL schema. No need to use these models anymore in separate locations.

Here comes synthesization!

We can achieve this by using single decorators

Below is the single model that can be used in all three stacks!

Fig: Single file to define the schema of the protobuf, mongo and gql

To achieve this, we need to import the followings :

Fig: Imports

type-graphql : TypeGraphQL is a library that makes this process enjoyable by defining the schema using only classes and a bit of decorator magic

protobufjs : This npm package we can achieve serializing structured data for use in the communications protocol that is to be used in gRPC.

typegoose : Typegoose allows you to use Mongoose with TypeScript.

mongoose : We use Schema from mongoose to define properties with unique values in typegoose prop type.

Conclusion

I hope you found this article helpful. I was inspired by this concept by my senior Sean Pope. Thanks for reading guys! I will be writing more pieces for the drill-down connection between these services in the coming days. You can feel free to reach out to me on LinkedIn.

Until then, happy coding!