fixes while integrating into webapp
This commit is contained in:
@@ -51,6 +51,16 @@ fmt.Println("you are", viewerResp.Viewer.MyName)
|
||||
|
||||
For a complete working example, see `example/`.
|
||||
|
||||
## Documentation for generated code
|
||||
|
||||
For each GraphQL operation (query or mutation), genqlient generates a Go function with the exact same name, which accepts:
|
||||
- a `context.Context` (unless configured otherwise)
|
||||
- a `genqlient/graphql.Client` (you might have a global one, or init it inline)
|
||||
- arguments corresponding to the query arguments
|
||||
It returns a pointer to a struct representing the query-result, and an `error`. The struct will always be initialized (never nil), even on error. The error may be a `github.com/vektah/gqlparser/v2/gqlerror.List`, if it was a GraphQL-level error (in this case the returned struct may still contain useful data, if the API returns data even on error), or may be another error if, for example, the whole HTTP request failed (in which case the struct is unlikely to contain useful data). If the GraphQL operation has a comment immediately above it, that comment text will be used as the GoDoc for the generated function.
|
||||
|
||||
TODO: document generated types further, especially if they become customizable.
|
||||
|
||||
## Tests
|
||||
|
||||
`go test ./...` tests code generation. (This is run by GitHub Actions.)
|
||||
|
||||
+10
-9
@@ -27,6 +27,7 @@ type Config struct {
|
||||
// how to convert that to SDL).
|
||||
Schema string `yaml:"schema"`
|
||||
// The filename with the queries; defaults to queries.graphql
|
||||
// TODO: allow multiple files?
|
||||
Queries string `yaml:"queries"`
|
||||
// The filename to which to write the generated code; defaults to
|
||||
// generated.go
|
||||
@@ -45,14 +46,20 @@ type Config struct {
|
||||
ClientGetter string `yaml:"client_getter"`
|
||||
}
|
||||
|
||||
func (c *Config) ValidateAndFillDefaults() error {
|
||||
func (c *Config) ValidateAndFillDefaults(configFilename string) error {
|
||||
// Make paths relative to config dir
|
||||
configDir := filepath.Dir(configFilename)
|
||||
c.Schema = filepath.Join(configDir, c.Schema)
|
||||
c.Queries = filepath.Join(configDir, c.Queries)
|
||||
c.Generated = filepath.Join(configDir, c.Generated)
|
||||
|
||||
if c.Package == "" {
|
||||
abs, err := filepath.Abs(c.Generated)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to guess package-name: %v", err)
|
||||
}
|
||||
|
||||
base := filepath.Base(abs)
|
||||
base := filepath.Base(filepath.Dir(abs))
|
||||
if !token.IsIdentifier(base) {
|
||||
return fmt.Errorf("unable to guess package-name: %v is not a valid identifier", base)
|
||||
}
|
||||
@@ -86,16 +93,10 @@ func ReadAndValidateConfig(filename string) (*Config, error) {
|
||||
}
|
||||
}
|
||||
|
||||
err := config.ValidateAndFillDefaults()
|
||||
err := config.ValidateAndFillDefaults(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid config file %v: %v", filename, err)
|
||||
}
|
||||
|
||||
// Make paths relative to config dir
|
||||
basename := filepath.Dir(filename)
|
||||
config.Schema = filepath.Join(basename, config.Schema)
|
||||
config.Queries = filepath.Join(basename, config.Queries)
|
||||
config.Generated = filepath.Join(basename, config.Generated)
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"github.com/vektah/gqlparser/formatter"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"github.com/vektah/gqlparser/v2/formatter"
|
||||
)
|
||||
|
||||
var fileTemplate = mustTemplate("operation.go.tmpl")
|
||||
@@ -154,6 +154,13 @@ func Generate(config *Config) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: we could also allow this, and generate an empty file with just the
|
||||
// package-name, if it turns out to be more convenient that way. (As-is,
|
||||
// we generate a broken file, with just (unused) imports.)
|
||||
if len(document.Operations) == 0 {
|
||||
return nil, fmt.Errorf("no queries found in %v", config.Queries)
|
||||
}
|
||||
|
||||
g := newGenerator(config, schema)
|
||||
for _, op := range document.Operations {
|
||||
if err = g.addOperation(op); err != nil {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func readConfigGenerateAndWrite(configFilename string) error {
|
||||
@@ -17,6 +18,13 @@ func readConfigGenerateAndWrite(configFilename string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(config.Generated), 0o755)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"could not create parent directory for generated file %v: %v",
|
||||
config.Generated, err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(config.Generated, code, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write generated file %v: %v",
|
||||
|
||||
+4
-4
@@ -4,10 +4,10 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/vektah/gqlparser"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"github.com/vektah/gqlparser/parser"
|
||||
"github.com/vektah/gqlparser/validator"
|
||||
"github.com/vektah/gqlparser/v2"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"github.com/vektah/gqlparser/v2/parser"
|
||||
"github.com/vektah/gqlparser/v2/validator"
|
||||
)
|
||||
|
||||
func getSchema(filename string) (*ast.Schema, error) {
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
)
|
||||
|
||||
type typeBuilder struct {
|
||||
@@ -120,7 +120,7 @@ type outputField struct{ field *ast.Field }
|
||||
|
||||
func (s outputField) Alias() string {
|
||||
// gqlparser sets Alias even if the field is not aliased, see e.g.
|
||||
// https://github.com/vektah/gqlparser/blob/c06d8e0d135f285e37e7f1ff397f10e049733eb3/parser/query.go#L150
|
||||
// https://github.com/vektah/gqlparser/v2/blob/c06d8e0d135f285e37e7f1ff397f10e049733eb3/parser/query.go#L150
|
||||
return s.field.Alias
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ func (builder *typeBuilder) writeField(field field) error {
|
||||
// `query q { a: f { b }, c: f { d } }` we need separate types for a
|
||||
// and c, even though they are the same type in GraphQL, because they
|
||||
// have different fields.
|
||||
// TODO: if this is an input type, we should skip the prefixing!
|
||||
builder.typeNamePrefix+upperFirst(field.Alias()), "", typ, fields)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3,9 +3,6 @@ module github.com/Khan/genqlient
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/Khan/graphql v0.0.0-20191109005718-3b51154b2bc5
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect
|
||||
github.com/vektah/gqlparser v1.2.0
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
github.com/vektah/gqlparser/v2 v2.1.0
|
||||
gopkg.in/yaml.v2 v2.2.4
|
||||
)
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
github.com/Khan/graphql v0.0.0-20191109005718-3b51154b2bc5 h1:C7qbo6snTa0/lSpVKYhXiw3dJ/9FYiwZSsU+4Bov9qg=
|
||||
github.com/Khan/graphql v0.0.0-20191109005718-3b51154b2bc5/go.mod h1:DLkRTcWV7KR4zw1iTm1lpShI3XP3nFmIMs3fHxYAsF0=
|
||||
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f h1:tygelZueB1EtXkPI6mQ4o9DQ0+FKW41hTbunoXZCTqk=
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/vektah/gqlparser v1.2.0 h1:ntkSCX7F5ZJKl+HIVnmLaO269MruasVpNiMOjX9kgo0=
|
||||
github.com/vektah/gqlparser v1.2.0/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/vektah/gqlparser/v2 v2.1.0 h1:uiKJ+T5HMGGQM2kRKQ8Pxw8+Zq9qhhZhz/lieYvCMns=
|
||||
github.com/vektah/gqlparser/v2 v2.1.0/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||
)
|
||||
|
||||
// Client is the interface that the generate code calls into to actually make
|
||||
|
||||
Reference in New Issue
Block a user