Generate GraphQL Client Code With Go

yamashou

Yamashou

Posted on July 7, 2020

Generate GraphQL Client Code With Go

Hi! I’m a Japanese software engineer with Go and Typescript.I develop applications every day when work and play. These days I use GraphQL a lot with them. And I use Apollo, GraphQL Code Generator and gqlgen for that. They are my favorite projects. They have in common that generate code.
So, I want to generate client for Go.
There are client for Go:

These libraries are very simple and easy to handle and used by gqlgen. But these don’t generate code. I want to generate code by response of introspection query from server. The GraphQL Code Generator have it. This user will have a comfortable development life.

So I give gopher and myself the same experience as a web client engineer.
I prepared for that.

GitHub logo Yamashou / gqlgenc

This is Go library for building GraphQL client with gqlgen

gqlgenc

What is gqlgenc ?

This is Go library for building GraphQL client with gqlgen

Motivation

Now, if you build GraphQL api client for Go, have choice:

These libraries are very simple and easy to handle However, as I work with gqlgen and graphql-code-generator every day, I find out the beauty of automatic generation So I want to automatically generate types.

Installation

go get -u github.com/Yamashou/gqlgenc

How to use

Client Codes Only

gqlgenc base is gqlgen with plugins. So the setting is yaml in each format gqlgenc can be configured using a .gqlgenc.yml file,

model
  package: generated
  filename: ./models_gen.go # https://github.com/99designs/gqlgen/tree/master/plugin/modelgen
client:
  package: generated
  filename: ./client.go # Where should any generated client go?
models:
  Int:
    model: github.com/99designs/gqlgen/graphql.Int64
  Date:
    model: github.com/99designs/gqlgen/graphql.Time
endpoint:
  url: https://api.annict.com/graphql # Where do you want to send your request?
  headers: #

Installation

go get -u github.com/Yamashou/gqlgenc

How to use

This is a client generator based on the gqlgen plugin. If you use it, choice CLI or a plugin. I will explain how to use it using the Github API. If you don’t read this sentence, read here.

First, You create .gqlgenc.yaml in your project root.

model:
  filename: ./gen/models_gen.go
client:
  filename: ./gen/client.go
models:
  Date:
    model: github.com/99designs/gqlgen/graphql.Time
endpoint:
  url: https://api.github.com/graphql
  headers:
    Authorization: "Bearer ${GITHUB_TOKEN}" # public access token
query:  
   - "./query/*.graphql"

If you don’t have a github token, you see here

Next, You create query.graphql in /query.

This query get your repositories.

fragment LanguageFragment on Language {
    id
    name
}
query GetUser($repositoryFirst: Int!, $languageFirst: Int!) {
    viewer {
        id
        name
        repositories(first: $repositoryFirst, orderBy: {field: CREATED_AT, direction: DESC}) {
            nodes {
                id
                name
                languages(first: $languageFirst) {
                    nodes {
                        ...LanguageFragment
                    }
                }
            }
        }
    }
}

Finally, You exec a command in your project root.

gqlgenc

Your client code is generated in /gen.
Then, run this code:

package main

import (
    "context"
    "fmt"
    "github.com/Yamashou/gqlgenc/client"
    "github.com/Yamashou/gqlgenc/example/github/gen"
    "net/http"
    "os"
)

func main() {
    // This example only read public repository. You don't need to select scopes.
    token := os.Getenv("GITHUB_TOKEN")
    authHeader := func(req *http.Request) {
        req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
    }
    ctx := context.Background()
    githubClient := &gen.Client{
        Client: client.NewClient(http.DefaultClient, "https://api.github.com/graphql", authHeader),
    }
    getUser, err := githubClient.GetUser(ctx, 10, 10)
    if err != nil {
        fmt.Fprintf(os.Stderr, "error: %s", err.Error())
        os.Exit(1)
    }
    fmt.Println(*getUser.Viewer.Name, getUser.Viewer.Repositories.Nodes[0].Name)
    for _, repository := range getUser.Viewer.Repositories.Nodes {
        fmt.Println(repository.Name)
        for _, language := range repository.Languages.Nodes {
            fmt.Println(language.Name)
        }
    }
}

https://github.com/Yamashou/gqlgenc/blob/master/example/github/main.go

To understand the example, you read this code, readme and gqlgen document. If you understand Japanese, read here.

Afterword

This article is my first post with English. You may have a sentence that don’t understand, but I’m very happy to have this challenge. Thank you for reading this to the end.

💖 💪 🙅 🚩
yamashou
Yamashou

Posted on July 7, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related