Goals
On this page, you will learn how to:
- Define a GraphQL schema for your GraphQL server
- Implement resolver functions using the Prisma client
- Use the GraphQL Playground to try out your GraphQL API
Configure project
You're using gqlgen
as a GraphQL server library for this project. gqlgen
is also used to generated code based on your GraphQL schema to help you build type-safe GraphQL servers.
Create a new directory and add the gqlgen
code generation script to it:
mkdir scripts touch scripts/gqlgen.go
Copy
Now add the following code to gqlgen.go
:
// +build ignore package main import "github.com/99designs/gqlgen/cmd" func main() { cmd.Execute() }
Copy
Finally, update the dependencies of your project:
dep ensure -update
Copy
Define GraphQL API & create project sceleton
Create the GraphQL schema
Every GraphQL API is based on a GraphQL schema that specifies all API operations and data structures. The schema is a contract between client and server.
Create your GraphQL schema definition file inside a new directory called server
:
mkdir server touch servers/schema.graphql
Copy
Now add the following type definitions to the schema file:
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
}
type User {
id: ID!
email: String
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
published: Boolean!
author: User
}
Configure gqlen
Next, you'll use gqlgen
to scaffold the resolvers for your GraphQL server. You first need to create the config file gqlgen.yml
that's used as foundation for the code generation process:
touch gqlgen.yml
Copy
Now add the following configuration to it:
schema: server/schema.graphql exec: filename: server/generated.go models: Post: model: hello-world/prisma-client.Post User: model: hello-world/prisma-client.User resolver: # Goal: copy&paste from generated file filename: tmp/resolver.go type: Resolver
Copy
Finally, use the gqlgen
code generation script to create the foundation for your GraphQL server:
go run scripts/gqlgen.go
Copy
The files in the generated tmp
directory contain empty GraphQL resolvers that you need to implement. First, copy the file into a more appropriate location:
cp ./tmp/resolver.go ./server/
Copy
When making changes to your GraphQL schema in the future, you need to run
$ go run scripts/gqlgen.go
again. This will override the files intmp
so you can copy and paste the new resolvers into their permanent location inservers/resolvers.go
.
Implement resolver functions
Now add proper resolver implementations to resolver.go
, replace the entire contents of the file with the following:
package main
import (
"context"
"hello-world/generated/prisma-client"
)
type Resolver struct {
Prisma *prisma.Client
}
func (r *Resolver) Mutation() MutationResolver {
return &mutationResolver{r}
}
func (r *Resolver) Post() PostResolver {
return &postResolver{r}
}
func (r *Resolver) Query() QueryResolver {
return &queryResolver{r}
}
func (r *Resolver) User() UserResolver {
return &userResolver{r}
}
type mutationResolver struct{ *Resolver }
func (r *mutationResolver) CreateUser(ctx context.Context, name string) (*prisma.User, error) {
return r.Prisma.CreateUser(prisma.UserCreateInput{
Name: name,
}).Exec(ctx)
}
func (r *mutationResolver) CreateDraft(ctx context.Context, title string, userId string) (*prisma.Post, error) {
return r.Prisma.CreatePost(prisma.PostCreateInput{
Title: title,
Author: &prisma.UserCreateOneWithoutPostsInput{
Connect: &prisma.UserWhereUniqueInput{ID: &userId},
},
}).Exec(ctx)
}
func (r *mutationResolver) Publish(ctx context.Context, postId string) (*prisma.Post, error) {
published := true
return r.Prisma.UpdatePost(prisma.PostUpdateParams{
Where: prisma.PostWhereUniqueInput{ID: &postId},
Data: prisma.PostUpdateInput{Published: &published},
}).Exec(ctx)
}
type postResolver struct{ *Resolver }
func (r *postResolver) Author(ctx context.Context, obj *prisma.Post) (*prisma.User, error) {
return r.Prisma.Post(prisma.PostWhereUniqueInput{ID: &obj.ID}).Author().Exec(ctx)
}
type queryResolver struct{ *Resolver }
func (r *queryResolver) PublishedPosts(ctx context.Context) ([]prisma.Post, error) {
published := true
return r.Prisma.Posts(&prisma.PostsParams{
Where: &prisma.PostWhereInput{Published: &published},
}).Exec(ctx)
}
func (r *queryResolver) Post(ctx context.Context, postId string) (*prisma.Post, error) {
return r.Prisma.Post(prisma.PostWhereUniqueInput{ID: &postId}).Exec(ctx)
}
func (r *queryResolver) PostsByUser(ctx context.Context, userId string) ([]prisma.Post, error) {
return r.Prisma.Posts(&prisma.PostsParams{
Where: &prisma.PostWhereInput{
Author: &prisma.UserWhereInput{
ID: &userId,
}},
}).Exec(ctx)
}
type userResolver struct{ *Resolver }
func (r *userResolver) Posts(ctx context.Context, obj *prisma.User) ([]prisma.Post, error) {
return r.Prisma.User(prisma.UserWhereUniqueInput{ID: &obj.ID}).Posts(nil).Exec(ctx)
}
Each resolver invokes a method on the Prisma client instance which is called Prisma
and attached to the incoming resolver object of r
.
Configure your GraphQL server
There are a few configuration steps left until you can start the server.
Update the package name at the top of generated.go
from package server
to:
package main
Copy
Next, move the index.go
script you've been using on the previous pages into the server directory:
mv index.go ./server
Copy
Now replace the contents of index.go
with the following:
package main
import (
"log"
"net/http"
"os"
"hello-world/generated/prisma-client"
"github.com/99designs/gqlgen/handler"
)
const defaultPort = "4000"
func main() {
port := os.Getenv("PORT")
if len(port) == 0 {
port = defaultPort
}
client := prisma.New(nil)
resolver := Resolver{
Prisma: client,
}
http.Handle("/", handler.Playground("GraphQL Playground", "/query"))
http.Handle("/query", handler.GraphQL(NewExecutableSchema(Config{Resolvers: &resolver})))
log.Printf("Server is running on http://localhost:%s", port)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
log.Fatal(err)
}
}
Explore the GraphQL API in a Playground
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 a GraphQL Playground is running.
A GraphQL Playground is an interactive GraphQL IDE that lets you explore the operations of GraphQL API. You can click the green SCHEMA-button at the right edge of the Playground window to view the auto-generated documentation for your GraphQL API.
Here are a few sample queries and mutations you can send to explore the API.
mutation { createUser(name: "Bob") { id } }
Copy
In some snippets, you need to replace the
__USER__ID__
or__POST_ID__
placeholder with the ID of an actual user.