You’ll learn how GraphQL works, how to use GraphQL with NestJS, and how to use TypeORM with NestJS for our Postgres database.
In this post, we will create a GraphQL API using NestJS and a Postgres database. You’ll learn how GraphQL works, how to use GraphQL with NestJS, and how to use TypeORM with NestJS for our Postgres database.
We’ll build a simple movie CRUD API to do all of this. However, first, let’s understand the technologies we’ll be using.
It is a data query and manipulation language for APIs that allows the frontend to ask exactly what it needs.
Using GraphQL’s type system, we can easily describe a schema for our data on the backend. Because of this, the frontend simply describes what data it wants in a simple format that mirrors the expected JSON response. As a REST API alternative, GraphQL is more efficient.
With GraphQL, we don’t need multiple URLs to fetch different data; we simply describe what we want in a single request.
NestJS is a Node.js framework that uses a modular architecture to build scalable server-side applications.
NestJS comes with pre-built components and patterns that we can simply plug in to build our application. One of these pre-built components is the @nestjs/graphql
module, which we will use. With NestJS, developers get built-in support for various features so they do not constantly reinvent the wheel.
Run the following command to install the NestJS CLI if you have not done so already.
Next, run the following command to use the NestJS CLI to create a new project:
Next, you’ll be prompted to pick a package manager. I’ll select npm
.
Once the installation is complete, you’ll have a new folder named movies-graphql-api
. This folder is our project directory; you can navigate it by running this command:
Next, let’s create the necessary files for our movie module—including the resolver, service, entity and model. Run the following command to do so:
You should see a folder called movie
in the src
directory when you’re done. Open it and create two more files called movie.model.ts
and movie.entity.ts
.
Your src
directory should now look like this.
With that done, run this command to install the needed dependencies we need:
We’ll be using @nestjs/graphql
, graphql-tools
and graphql
for the GraphQL integration. While @nestjs/typeorm
, typeorm
and pg
will be used for the TypeORM and Postgres database integration.
You’ll need to download and install Postgres if you haven’t already. Open the psql
shell, fill in the prompts and create a database called movies_db
.
To configure TypeORM to connect to our local Postgres database, add the following code to the imports array in the AppModule
within your app.module.ts
file:
Make sure to fill in your actual database username and password.
Next, we need to import the GraphQL
module into our AppModule
. Add the following code to the imports array:
To configure the GraphQLModule
, we pass an options object to the forRoot()
static method. Here, the driver
option is used to state the GraphQL server implementation we will be using, and the autoSchemaFile
option is used to state where our automatically generated GraphQL
schema should be created.
Your AppModule
should now look like this:
NestJS has two ways of building GraphQL applications: code-first and schema-first methods.
With the code-first approach, we use decorators and TypeScript classes to automatically generate the corresponding GraphQL schema. With the schema-first approach, you write the schema directly, and NestJS generates the TypeScript definitions for you.
In this post, we’ll focus on the code-first approach and allow NestJS to generate the GraphQL schema for us.
In GraphQL, an object type represents a domain object that the frontend might want to interact with. It defines how the data is structured in the GraphQL schema. Object types determine which fields end up being exposed to the GraphQL client.
Add the following code to the movie.model.ts
file:
We define and annotate a class with the @ObjectType
and @Field
decorators to describe our object type and its corresponding fields.
Now, the @Field
decorator takes two optional arguments, a type
function and an options
object. We use the type
function to clear any vagueness between the TypeScript type system and the GraphQL type system.
While not required for string and boolean types, it is needed for numbers, which we have to map to either Int
or Float
. On the other hand, the options
object has three optional key-value pairs:
nullable
: This takes a boolean.description
: This takes a string.deprecationReason
: This also takes a string.Next, we need to make data transfer objects (DTOs) for creating and updating movies. In the movie folder, create a folder called dto
. Then in the dto
folder create two files: create-movie.dto.ts
and update-movie.dto.ts
.
Now, add the following code to the create-movie.dto.ts
file:
Add the following to the update-movie.dto.ts
file:
For context, the InputType
is a special kind of object type.
Next, let’s create the data layer for our application. For some context, an entity is basically a class that maps to a database table. We’re going to have a Movie
entity and a corresponding MovieService
that interacts with the Movie
table in our database.
Add the following to the movie.entity.ts
file:
Also update the movie.service.ts
file with the following:
Finally, update your MovieModule
in the movie.module.ts
file to use the TypeOrmModule
.
Resolvers serve as middlemen between the incoming GraphQL operations (e.g., queries, mutations and subscriptions) and the data layer of our application (the entities and services).
To set up our resolver, we need to define a class with resolver functions as methods and annotate that class with the @Resolver
decorator.
Now update the movies.resolver.ts
file with the following:
In the code above, we annotate the methods of our MoviesResolver
class with decorators indicating what GraphQL operation they perform.
Having completed the setup, we can now start the server. Save all the files and start the NestJS service by running the following command:
You should see this:
The GraphQL playground is an in-browser IDE, which we get by default using the same URL as the GraphQL server. To access it, navigate to http://localhost:3000/graphql in your browser.
To add a movie, use the following mutation:
It should look like this.
Now, let’s add two more movies:
Now, let’s try to fetch all the movies using the following query:
And you should get the following response:
Next, let’s try updating a movie using the following mutation:
You should get the following response:
Next, let’s try fetching a single movie.
Finally, let’s try deleting a movie.
Now, you understand how GraphQL works and can create a GraphQL API using NestJS and a Postgres database.
Chris Nwamba is a Senior Developer Advocate at AWS focusing on AWS Amplify. He is also a teacher with years of experience building products and communities.