API with NestJS #27. Introduction to GraphQL. Queries, mutations, and authentication

JavaScript NestJS TypeScript

This entry is part 27 of 177 in the API with NestJS

GraphQL has gained quite a lot of popularity lately. And no wonder, because it is an interesting approach to querying data. Therefore, it is definitely worth looking into. At its core, GraphQL is a query language with a runtime that can execute them. Although it is an alternative to REST, it can work alongside it.

Queries

With REST, we have the concept of multiple endpoints. To retrieve the resource, we need to perform a GET request to this specific URL.

GET /posts

With GraphQL, we approach the above task differently. First, we need to define a schema. We define it in a file with the extension. Our GraphQL application needs to define a set of possible data our users can query. Our API validates incoming queries and executes them against the schema.

The most fundamental part of a schema is the object type. It represents what objects our users can fetch from our service and what fields they have.

schema.gql

Above, we define a simple object type that contains three fields. All of them are non-nullable, and we indicate it with the exclamation mark. Because of that, every time our users query posts, each post is guaranteed to contain the id, the title, and the paragraphs.

Instead of calling a specific endpoint that manages posts, we typically have a single endpoint for managing all of our resources. We need to send a query to it to describe what data do we need.

First, we need to define our query in a similar manner that we’ve created our object type.

schema.gql

Once that’s implemented, we can perform a request with the above query.

POST /graphql

An interesting thing above is that we don’t need to request all of the data. In our query above, we omitted the field. Thanks to omitting fields that we don’t need, we can reduce the data transferred between our frontend and our backend.

Mutations and inputs

Aside from fetching data, we also need a way to modify it. With REST, we would send a POST request to a specific endpoint. With GraphQL, we use the same single endpoint that we’ve used for querying data.

First, we need to describe the structure of the data we use to create an entity in our database. To do that, we define an input.

schema.gql

Once we’ve got the input, we can use it inside our mutation. It should return the created entity.

schema.gql

Once we’ve defined both the mutation and the input, we can perform a request that creates an entity.

POST /graphql

Our server will respond with the created post.

Implementing GraphQL with NestJS

Now let’s implement all of the above in our application. To do that, we need to choose between two approaches.

  1. With the schema-first method, we describe our API in Schema Definition Language (SDL) files. NestJS analyses them and generates TypeScript definitions.
  2. When we implement the code-first approach, we use decorators and TypeScript classes instead of creating SDL files. NestJS generates the schema definition file out of our TypeScript code.

Since in the first paragraph we’ve written some SDL code already, we will present the code-first approach in the following example. Let’s start by installing the necessary dependencies.

The first step in using GraphQL with NestJS is initializing it in our .

app.module.ts

Above, I use the environment variable to determine whether a GraphQL playground should be initialized.

.env

With the playground, we get an interactive, graphical interface that we can use to interact with our server. We can open it on the same URL as the GraphQL server.

Since we use the code-first approach, we need to define the to describe the path where our generated schema will be created.

Queries

The first thing to do when we want to query data using the code-first approach is to define a model. NestJS translates it under the hood into the object type.

post.model.ts

To provide instructions on how to turn GraphQL operation into data, we need to define a resolver. Thanks to using decorators, NestJS can generate SDL files from our code.

posts.resolver.ts

We’ve defined the   in the previous parts of this series

Thanks to creating the above resolver and adding it to our module’s array, we can now perform a working query.

posts query

Mutation and authentication guards

Aside from querying the data, we also want to be able to create it. To do that, we need migrations with inputs.

In the third part of this series, we’ve implemented authentication with JWT. We require the users to authenticate before creating posts. It will work just fine with GraphQL, given we adjust it a little bit.

First, we need to create a slightly modified guard.

graphql-jwt-auth.guard.ts

We also need to create the input for our posts.

post.input.ts

Once that’s all taken care of, we can add the above to our resolver.

posts.resolver.ts

Doing the above allows us to create posts and assign authors to them.

GraphQL migration

For it to work, we need to set to in the playground settings.

We also need to open up DevTools and save the appropriate cookie.

Summary

In this article, we’ve gone through the very basics of GraphQL. We’ve introduced concepts such as queries and mutations and explained how they look in Schema Definition Language files. Aside from that, we’ve also implemented the code-first approach. By doing that, we let NestJS generate SDL for us.

There is still a lot to cover when it comes to GraphQL, so stay tuned!

Series Navigation<< API with NestJS #26. Real-time chat with WebSocketsAPI with NestJS #28. Dealing in the N + 1 problem in GraphQL >>
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Michal
Michal
3 years ago

So the GrapQL in only interface?
Explained very clearly, good job and thanks.