Navigate back to the homepage

Use Prisma with a NestJS GraphQL Server

Aryan Jabbari
October 5th, 2019 · 4 min read

Use Prisma with a NestJS GraphQL Server

Before We Get Started

In my last blog post, I described how to stand up a Node.js server with NestJS and GraphQL. If you haven’t yet, please read that blog post as this one will use the code created there and continue where that one left off.

This tutorial is not meant for beginners and will not cover Node, GraphQL or NestJS basics. If you’re looking to get started with Node, take a look at my Timestamp Microservice tutorial on YouTube.

I made a video tutorial based off of this blog post. I suggest reading this blog post and watching the video as they complement each other well.

If at any point you get lost in this tutorial, please refer to this tutorial’s code on GitHub. It should contain everything you need to catch up and integrate Prisma with NestJS.

If you want to see this code in action, please visit https://enigmatic-journey-72826.herokuapp.com/graphql.

Alright, let’s crush some code.

Where We Left Off

If you followed my last tutorial correctly, you should end up with code that looks like this GitHub branch. When you run yarn start:dev, a GraphQL server should spin up at http://localhost:3000/graphql. In the GraphQL playground, you should be able to make a messages query and a createMessage mutation. The server will look like this one. If any of that is untrue, please refer to the section above.

Let’s Get Ready for Prisma

The first thing we need to do is instantiate a Prisma demo server and upload our data model to Prisma. For this, we’ll use the prisma-cli.

1yarn global add prisma
2# or
3npm install -g prisma

With that installed, let’s initialize our project and configure it to successfully use Prisma. From your project folder, run the following command:

1prisma init

You’ll be given a choice of Prisma servers: Photo of database choices given after prisma init is run

For this tutorial, we will set up a Demo server + MySQL database.

The CLI will continue to ask configuration questions. Please be sure to choose Don't generate when asked for the programming language of the Prisma client: Photo of client choices Prisma CLI provides

We choose this since we will be generating the Prisma client later using prisma-binding.

Defining Our Data Model and Deploying

After Prisma instantiation succeeds, two new files will be created at the root of our project:

  • prisma.yml - a configuration file Prisma uses to generate their schema, define schema output paths, etc.
  • datamodel.prisma - our project’s data model which Prisma will use to generate schemas

datamodel.prisma is initialized with a basic User model. We will replace it with the Message model (be sure to add the new @id directive that Prisma supplies us with) from our src/schema.graphql file:

1# datamodel.prisma
2
3type Message {
4 id: Int! @id
5 description: String!
6}

Now that we edited the Prisma data model to make it our own, we are ready to deploy to Prisma and instantiate our database. To do this, run:

1prisma deploy

This will deploy our changes to the database. If you change the data model in any way, prisma deploy needs to be re-run to ensure the database we are using and the Prisma schema and client stay up-to-date with our data model changes.

Generate GraphQL Schema

The generated schema needs to be bound to GraphQL and we must create a Nest service from said schema. To do that, we need to generate API code and type annotations. Additionally, we will need to download the GraphQL schema (the schema we have now is in TypeScript) from our Prisma endpoint. The graphql-cli takes care of both these things.

1yarn global add graphql-cli
2# or
3npm install -g graphql-cli

Now, let’s initialize our project with a .graphqlconfig.yaml. In the Terminal, run:

1graphql init

As with the previous CLI, the CLI will ask a number of configuration questions. For the purposes of this tutorial, please create a directory at src/prisma and use the local schema file path of src/prisma/schema.graphql. As for the endpoint URL, you should be able to copy and paste that from prisma.yml. If you ran through the CLI correctly, it should look like: A filled out GraphQL CLI

and a new file should be written at /.graphqlconfig.yaml. You should now be able to generate your GraphQL schema with:

1graphql get-schema

Now that we’ve created a new (more complete) schema, we can delete the src/schema.graphql that we created in the last tutorial.

Bind our GraphQL Server with Prisma

Prisma already has a GraphQL server running in front of the database they set up for us. We want to write our very own resolvers leveraging the Prisma GraphQL server and schema. To do this, we’ll need to use prisma-binding. This allows us to use the Prisma database service to more easily implement our own GraphQL resolvers.

First, let’s install prisma-binding:

1yarn add prisma-binding
2# or
3npm install -g prisma-binding

Now, we need to configure the GraphQL CLI to use prisma-binding to the TypeScript API and annotations we’ll need to use in our code. Edit .graphqlconfig.yaml to look as follows:

1# .graphqlconfig.yaml
2
3projects:
4 nodejs-tutorial:
5 schemaPath: src/prisma/schema.graphql
6 extensions:
7 endpoints:
8 dev: https://us1.prisma.sh/aryan-j/use-your-own-endpoint/dev
9 codegen:
10 - generator: prisma-binding
11 language: typescript
12 output:
13 binding: src/prisma/prisma.binding.ts

Please note the codegen extension we added. We are all ready to generate our Prisma bindings!

1graphql codegen

You’ll see a new file at /src/prisma/prisma.binding.ts which contains the API that we will use to interact with our Prisma server.

Create a Prisma Service

Now, we need a NestJS service that encapsulates the Prisma binding and will be responsible for interacting with our Prisma server. For this, we’ll use the Nest CLI. In your Terminal, run:

1nest generate module prisma

If you don’t have the NestJS CLI installed, the instructions to do so are in my last tutorial.

If this was succesful, you should have a newly created src/prisma/prisma.module.ts file as well as a new line in src/app.module.ts that imports the PrismaModule.

Now, let’s create our Prisma service:

1nest generate service prisma

If this was successful, src/prisma/prisma.service.ts (and a corresponding test file) was created and added to your PrismaModule. Our PrismaService will simply be an instance of the Prisma binding that we generated at src/prisma/prisma.binding.ts. In src/prisma.service.ts:

1// src/prisma/prisma.service.ts
2import { Injectable } from '@nestjs/common';
3import { Prisma } from './prisma.binding';
4
5@Injectable()
6export class PrismaService extends Prisma {
7 constructor() {
8 super({
9 endpoint: 'https://us1.prisma.sh/aryan-j/use-your-own-endpoint/dev',
10 debug: false,
11 });
12 }
13}

Use PrismaService to Manipulate Data in Prisma

The last thing we need to do is use our newly created PrismaService inside of our MessagesResolver. In NestJS, we need to be sure to export the service we want to share with other modules. With that service exported, any other module that imports that module will be able to use the exported service.

In our PrismaModule (/src/prisma.module.ts), let’s export the PrismaService:

1// src/prisma/prisma.module.ts
2import { Module } from '@nestjs/common';
3import { PrismaService } from './prisma.service';
4
5@Module({
6 providers: [PrismaService],
7 exports: [PrismaService]
8})
9export class PrismaModule {}

and import the PrismaModule in our MessagesModule:

1// src/messages/messages.module.ts
2import { Module } from '@nestjs/common';
3import { MessagesResolver } from './messages.resolver';
4import { PrismaModule } from '../prisma/prisma.module';
5
6@Module({
7 imports: [PrismaModule],
8 providers: [MessagesResolver],
9 exports: [MessagesResolver],
10})
11export class MessagesModule {}

Lastly, in our MessagesResolver, we need to do a number of things:

  1. Remove our messagesThatReallyShouldBeInADb array (we have a real database now, woo hoo! 🎉)
  2. Inject PrismaService so that it can be used throughout the MessagesResolver instance.
  3. Forward the messages query and the createMessage mutation to our Prisma server.
1import { Mutation, Resolver, Query, Args } from '@nestjs/graphql';
2import { PrismaService } from '../prisma/prisma.service';
3
4@Resolver()
5export class MessagesResolver {
6 // the injected dependency is injected as an argument to the constructor
7 constructor(private readonly prisma: PrismaService) {}
8
9 @Query()
10 messages(@Args() args) {
11 return this.prisma.query.messages(args);
12 }
13
14 @Mutation()
15 createMessage(@Args() args) {
16 return this.prisma.mutation.createMessage(args);
17 }
18}

That’s it! Your MessagesResolver is now using Prisma to resolve its queries and mutations. Let’s test it!

Testing Our New Resolvers

Open up http://localhost:3000/graphql. In the playground, we can use the following query and mutation:

1query allMessages {
2 messages {
3 id
4 description
5 }
6}
7
8mutation createMessage{
9 createMessage(data: {description: "Hello"}) {
10 id
11 description
12 }
13}

Conclusion

With this, you should be able to use Prisma with NestJS. Try extending the code to allow for message deletion and updates!

If at any point you got lost in this tutorial, please refer to this tutorial’s code on GitHub. It should contain everything you need to catch up and integrate Prisma with NestJS.

If you want to see this code in action, please visit https://enigmatic-journey-72826.herokuapp.com/graphql.

📧 Join my email list and get notified about new content

Stay updated with all my blog posts and future randomness!

More articles from The WebDev Coach

Stand Up a Node.js Server with NestJS including TypeScript and GraphQL

Stand Up a Node.js Server with NestJS including TypeScript and GraphQL Recently, I discovered NestJS and instantly fell in love. It is…

September 18th, 2019 · 3 min read

The Case Against Print Statements in your Main Branch

The Case Against Print Statements in your Main Development Branch A coworker (who is new to our codebase) recently asked me to add print…

August 24th, 2019 · 4 min read
© 2019 The WebDev Coach
Link to $https://twitter.com/aryanjabbariLink to $https://www.youtube.com/c/thewebdevcoachLink to $https://github.com/AryanJ-NYCLink to $https://www.linkedin.com/in/aryanjabbari