DEV Community

Cover image for Generate GraphQL Client Code With Go
Yamashou
Yamashou

Posted on

8

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.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (2)

Collapse
 
clansofts profile image
Samuel Mwaura

@yamashou
Attempting to incorporate this library and I have landed into a problem on executing the command

"gqlgenc"

I get this one-line error message "File does not exist"

Any ideas on what could be the issue

Collapse
 
zwtop profile image
zwtop

It's great ! This is what I'm looking for !

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay