This document describes common questions about genqlient, and provides an index to how to represent common query structures. For a full list of configuration options, see genqlient.yaml and genqlient_directive.graphql.
Customize the http.Client
of your graphql.Client
.
Inject a test HTTP response or server into the graphql.Client
.
Tell genqlient how to handle your custom scalars with the bindings
option.
Yes, but you'll need to use a separate tool (example).
See the README.md.
The short answer is that GraphQL forces our hand. For example, consider a query
query GetFamilyNames {
user {
name
children {
name
}
}
}
which returns the following JSON:
{
"user": {
"name": "Ellis Marsalis Jr.",
"children": [
{"name": "Branford Marsalis"},
{"name": "Delfeayo Marsalis"},
{"name": "Jason Marsalis"},
{"name": "Wynton Marsalis"}
]
}
}
We need two different User
types to represent this: one with a Children
field, and one without. (And there may be more in other queries!) Of course, we could name them User1
and User2
, but that's both less descriptive and less stable as the query changes (perhaps to add parent
), so we call them GetFamilyNamesUser
and GetFamilyNamesUserChildrenUser
.
This applies even in cases where the types are exactly the same, so that the type names will be stable as the query changes. For example, in the following query there are three different "User" types:
query GetMonopolyPlayers {
game {
winner { id name }
banker { id name }
spectators { id name }
}
}
This will produce a Go type like:
type GetMonopolyPlayersGame struct {
Winner GetMonopolyPlayersGameWinnerUser
Banker GetMonopolyPlayersGameBankerUser
Spectators []GetMonopolyPlayersGameSpectatorsUser
}
type GetMonopolyPlayersGameWinnerUser struct {
Id string
Name string
}
// (other structs identical)
This may seem unnecessary, but imagine if we generated a single type GetMonopolyPlayersGameUser
, and then later you changed the query to do spectators { id name favoritePlayer }
; we'd now have to change all three type names, potentially forcing you to update all the code that uses the query result.
For more on customizing the type names -- including combining several types into one -- see the operations documentation.
For the long answer, see the design note.
If your tools are backed by gopls (which is most of them), they simply don't know it was updated. In most cases, keeping the generated file (typically generated.go
) open in the background, and reloading it after each run of genqlient
, will do the trick.
If genqlient fails with an error missing go.sum entry for module providing package
, this is typically because go mod tidy
removed its dependencies because they weren't imported by your Go module. You can read more about this in golang/go#45552; see in particular this comment. In short, if you want to be able to go run
on newer Go you'll need to have a (blank) import of genqlient's entrypoint in a special tools.go
file somewhere in your module so go mod tidy
doesn't prune it:
//go:build tools
// +build tools
package client
import _ "github.com/Khan/genqlient"
Currently, @genqlient
directives apply to all relevant nodes on the following line, see #151 or the @genqlient
documentation. If in doubt, spread things out onto more lines and they'll probably work!
Common examples of this error:
for is only applicable to operations and arguments
omitempty may only be used on optional arguments
genqlient does not publish a release for every bugfix; read more about our versioning strategy or use go get -u github.com/Khan/genqlient@main
to install from latest main
.