docs/1.15/get-started/04-build-graphql-servers-with-prisma-e001.mdx
import QueryChooser from 'components/Markdown/QueryChooser' import Collapse from 'components/Markdown/Collapse' import Warning from 'components/Markdown/Warning'
export const meta = { title: 'Build GraphQL Servers with Prisma', position: 4, nextText: 'Congratulations! π You made it through the quickstart tutorial and learned how to use Prisma and Prisma bindings to build a GraphQL server.' }
On this page, you will learn how to:
graphql-yoga server library to Node.JS projectgrahpql-yoga is a GraphQL server library based on Express.js. Add it to your project with the following command:
yarn add graphql-yoga
When building GraphQL servers with Prisma, you're working with two GraphQL APIs:
While the auto-generated GraphQL schema in prisma.graphql defines the API of your Prisma service, the GraphQL schema of your application layer (also called application schema) still needs to be defined.
schema.graphqlCreate a new file called schema.graphql which you will use to store the application schema:
touch schema.graphql
To define the API operations for your client applications, you need to specify the Query and Mutation types in your application schema - the following operations are examples for a simple blogging application:
# import User, Post from "prisma.graphql"
type Query {
publishedPosts: [Post!]!
post(postId: ID!): Post
postsByUser(userId: ID!): [Post!]!
}
type Mutation {
createUser(name: String!): User
createDraft(title: String!, userId: ID!): Post
publish(postId: ID!): Post
}
What looks like a comment in the first line of the application schema is not a comment but a required import statement from the graphql-import library. If it was removed, the application schema would not be valid any more as the Post and User types were both undefined.
Each API operation is backed by exactly one resolver function that's invoked when the operation is requested by a client. Here is how you implement the resolver functions for the six API operations you defined in the application schema. Replace the current contents of index.js entirely with the following code snippet:
const { GraphQLServer } = require('graphql-yoga')
const { Prisma } = require('prisma-binding')
const resolvers = {
Query: {
publishedPosts(parent, args, context, info) {
return context.db.query.posts({ where: { published: true } }, info)
},
post(parent, args, context, info) {
return context.db.query.post({ where: { id: args.postId } }, info)
},
postsByUser(parent, args, context, info) {
return context.db.query.posts(
{
where: {
author: { id: args.userId }
}
},
info
)
}
},
Mutation: {
createDraft(parent, args, context, info) {
return context.db.mutation.createPost(
{
data: {
title: args.title,
author: {
connect: { id: args.userId }
}
},
},
info
)
},
publish(parent, args, context, info) {
return context.db.mutation.updatePost(
{
where: { id: args.postId },
data: { published: true },
},
info
)
},
createUser(parent, args, context, info) {
return context.db.mutation.createUser(
{
data: { name: args.name }
},
info
)
}
},
}
Each resolver simply delegates incoming requests to the Prisma binding object which is called db and attached to the resolvers' context.
Now you need to instantiate the GraphQLServer from the graphql-yoga library and pass the application schema along with its resolver functions. You're also instantiating the Prisma binding object and attach it to the context so that the resolvers can access it; again the __YOUR__PRISMA_ENDPOINT__-placeholder needs to be replaced with your acual endpoint:
const server = new GraphQLServer({
typeDefs: './src/schema.graphql',
resolvers,
context: req => ({
...req,
db: new Prisma({
typeDefs: βprisma.graphqlβ,
endpoint: '__YOUR__PRISMA_ENDPOINT__',
}),
}),
})
server.start(() => console.log('Server is running on http://localhost:4000'))
To start the GraphQL server (of the application layer) run the following command:
node index.js
The GraphQL API of your application layer now exposes the six operations defined in schema.graphql. To test these operations, navigate your browser to http://localhost:4000 where the GraphQL server is running.
Here are a few sample queries and mutations you can send to explore the API.
<QueryChooser titles={["Create a new User", "Create new draft", "Publish a Post", "Fetch published Posts"]}>
mutation {
createUser(name: "Jenny") {
id
}
}
mutation {
createDraft(
title: "GraphQL is great"
userId: "__USER_ID__"
) {
id
published
author {
id
}
}
}
mutation {
publish(postId: "__POST_ID__") {
id
title
published
}
}
query {
publishedPosts {
id
title
author {
id
name
}
}
}
Here are some hints for structuring your project:
hello-world directory) inside the project directory of the GraphQL server.prisma.graphql) should be available in the directory where the source code for your GraphQL server is located. As it's auto-generated, it is helpful to put it into a dedicated directory, e.g. called generated.graphql-config to enable the GraphQL Playground to show the two GraphQL APIs (Prisma and application server) side-by-side.Here's how your project structure will look like if you follow above:
.
βββ .graphqlconfig
# defines the Prisma service (database layer)
βββ hello-world
β βββ datamodel.graphql
β βββ prisma.yml
# implementation of the GraphQL server (application layer)
βββ src
β βββ generated
β β βββ prisma.graphql
β βββ index.js
β βββ schema.graphql
βββ package.json
βββ yarn.lock
Your .graphqlconfig.yml file needs to define both GraphQL projects you're working with:
projects:
app:
schemaPath: src/schema.graphql
extensions:
endpoints:
default: http://localhost:4000
hello-world:
schemaPath: src/generated/prisma.graphql
extensions:
prisma: hello-world/prisma.yml
This allows to quickly switch between the two GraphQL APIs using the sidenav inside the GraphQL Playground. Note that for this to work you need to open the Playground using the graphql playground command (from the GraphQL CLI) inside the same directory where your .graphqlconfig is located.
Prisma's auto-generated GraphQL schema changes whenever you deploy changes to the service's data model. To ensure your local prisma.graphql stays up-to-date you can configure a post-deployment hook which updates it after every deploy.
You can configure the hook in prisma.yml:
datamodel: datamodel.graphql
endpoint: http://localhost:4466 # or some other endpoint
hooks:
post-deploy:
- graphql get-schema --endpoint ${self:endpoint} --output src/generated/prisma.graphql --no-all
This assumes that the GraphQL CLI is installed globally on your machine.
</Collapse>