Prisma with Node.js - Part 2: Prisma Bindings

Joshua Hall

Over in Part 1 we discussed how to connect our deployed Prisma API to our Node.js-based GraphQL server. Now we’re going to look into using the prisma-bindings library to start using all the superpowers that Prisma has generated for us.

Prerequisites

Obviously you’re going to need a basic Prisma API that’s connected to a database and your Node.js server. You can learn about setting up Prisma with a Postgres database here.

If you skipped part 1 and want to jump into the implementation, you can copy this boilerplate to get started, just remember to change the endpoints to your Docker container.

I will be assuming that you’re already comfortable with using mutations and subscriptions and creating schemas and resolvers.

Queries

Since we passed our prisma object over to our server’s context in index.js we can access it in our resolver context, which we’ll just destructure out.

Everything that is available to you in our Prisma container’s documentation is now available on our prisma object. If we want to make a request for users we can access it on prisma.query. Every request you make will require two arguments, the query arguments, like data or where, and the properties that your user wants. If you only need one you can just pass null in its place.

Everything we pass as the second argument, which needs to be an object in a string, will control what the user is allowed to query for. In this case name will be available, but a request for their id will fail:

resolvers.js

const Query = {
  users(parent, args, { prisma }, info) {
    const users = prisma.query.users(null, '{ name }');
    return users;
  },
};

To make everything available to the user, we can pass-in info since that contains the user’s full query.

Passing in where or data is similar, but it doesn’t need to be in a string.

const Query = {
  users(parent, args, { prisma }, info) {
    const users = prisma.query.users({ where: { id: args.id } }, info)
    return users
  },
  user(parent, args, { prisma }, info) {
    return prisma.query.user({ where: { id: args.id } }, info)
  }
};

Since we’re working with filters on our queries, we need to update our schema to allow for an id to be passed-in.

schema.js

type Query {
  users(id: ID): [User!]!
  user(id: ID!): User!
}

type User {
  id: ID! 
  name: String!
}

Mutations

First you’re going to need to add our exported mutations to our server’s resolvers in index.js.

index.js

import { Query, Mutation } from './resolvers'

const server = new GraphQLServer({
  typeDefs: './schema.graphql',
  resolvers: {
    Query,
    Mutation
  },
  context: { prisma }
})

Mutations are just as easy as queries, just access the method you want on prisma and pass the arguments and what you want returned to the user. This time, let’s try chaining mutations together to create a user then update their name. For this we can use async/await and pass the id from the new user to the update method.

resolvers.js

const Mutation = {
  async addUser(parent, args, { prisma }, info) {
    const newUser = await prisma.mutation.createUser({ data: args.data }, info)

    const updatedUser = await prisma.mutation.updateUser({
      where: { id: newUser.id },
      data: { name: "Overridden" }
    }, info)

    return updatedUser
  }
}

schema.graphql

type Mutation {
  addUser(data: CreateUserInput): User!
}

input CreateUserInput {
  name: String!
}

Subscriptions

For GraphQL subscriptions using Prisma we don’t even need to worry about pubsub or opening sockets, we can just use prisma to use a subscription in one line.

First let’s add our Subscriptions to our resolvers and setup our schema to support them. We’ll also be adding a smaller updateUser method that we’ll use to test it with.

index.js

import { Query, Mutation, Subscription } from './resolvers'

const server = new GraphQLServer({
  typeDefs: './schema.graphql',
  resolvers: {
    Query,
    Mutation,
    Subscription
  },
  context: { prisma }
})

schema.graphql

type Mutation {
  addUser(data: CreateUserInput): User!
  updateUser(id: ID!, data: CreateUserInput): User!
}

enum MutationType {
  CREATED
  UPDATED 
  DELETED
}

type Subscription {
  user(id: ID!): UserSubscriptionPayload!
}

type UserSubscriptionPayload {
  mutation: MutationType!
  node: User
}

Just like before, we can access a user subscription on prisma.subscription.user, and set it to watch the user whose id we’re going to pass to it.

resolvers.js

const Subscription = {
  user: {
    subscribe(parent, args, { prisma }, info) {
      return prisma.subscription.user({ where: { node: { id: args.id } } }, info)
    }
  }
}

const Mutation = {
  async addUser(){...},
  updateUser(parent, args, { prisma }, info) {
    return prisma.mutation.updateUser({
      where: { id: args.id },
      data: args.data
    }, info)
  }
}

Closing Thoughts

As you can see, Prisma made what was before a lot of menial tasks that had to be done every time we wanted to add a new type, and simplified them into many one line functions that are incredibly easy to use. While it still gives us the freedom to do what we need in between getting a request and working with the database.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#