diff --git a/docs/FAQ.md b/docs/FAQ.md index 5fd511da..496fcb2a 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -96,7 +96,7 @@ bindings: Or, you can bind it to any other type, perhaps one with size-checked constructors; see the [`genqlient.yaml` documentation](genqlient.yaml) for more details. -### … let me json-marshal my response objects +### … let me json-marshal my response objects? This is supported by default! All genqlient-generated types support both JSON-marshaling and unmarshaling, which can be useful for putting them in a cache, inspecting them by hand, using them in mocks (although this is [not recommended](#-test-my-graphql-apis)), or anything else you can do with JSON. It's not guaranteed that marshaling a genqlient type will produce the exact GraphQL input -- we try to get as close as we can but there are some limitations around Go zero values -- but unmarshaling again should produce the value genqlient returned. That is: @@ -109,6 +109,42 @@ var respAgain MyQueryResponse err := json.Unmarshal(b, &resp) ``` +### … let me use introspection to fetch my client schema? + +This is currently not supported by default. You can however use a tool such as [gqlfetch](https://github.com/suessflorian/gqlfetch) to build your client schema using introspection and then let `genqlient` continue from there. Moreover, you can define yourself what happens when `go:generate` is run via managing your own _go runnable_ progam. + +For example - suppose the file `generate/main.go`; + +```go +package main + +import ( + "context" + "fmt" + "os" + + "github.com/Khan/genqlient/generate" + "github.com/suessflorian/gqlfetch" +) + +func main() { + schema, err := gqlfetch.BuildClientSchema(context.Background(), "http://localhost:8080/query") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if err = os.WriteFile("schema.graphql", []byte(schema), 0644); err != nil { + fmt.Println(err) + os.Exit(1) + } + + generate.Main() +} +``` + +This can now be invoked upon `go generate` via `//go:generate yourpkg/generate`. + ## How do I make a query with … ### … a specific name for a field? diff --git a/generate/parse.go b/generate/parse.go index b26b7dea..7b2ac5e5 100644 --- a/generate/parse.go +++ b/generate/parse.go @@ -12,6 +12,7 @@ import ( "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/parser" "github.com/vektah/gqlparser/v2/validator" ) @@ -31,9 +32,19 @@ func getSchema(globs StringList) (*ast.Schema, error) { sources[i] = &ast.Source{Name: filename, Input: string(text)} } - schema, graphqlError := gqlparser.LoadSchema(sources...) + // Multi step schema validation + // Step 1 assume schema implicitly declares types that are required by the graphql spec + // Step 2 assume schema explicitly declares types that are required by the graphql spec + var ( + schema *ast.Schema + graphqlError *gqlerror.Error + ) + schema, graphqlError = gqlparser.LoadSchema(sources...) if graphqlError != nil { - return nil, errorf(nil, "invalid schema: %v", graphqlError) + schema, graphqlError = validator.LoadSchema(sources...) + if graphqlError != nil { + return nil, errorf(nil, "invalid schema: %v", graphqlError) + } } return schema, nil