Files
genqlient/internal/integration/generated.go
T
Ben KraftandGitHub 4c38cb7759 Add support for interfaces, part 1: the simplest cases (#52)
## Summary:
In this commit I begin the journey to add the long-awaited support for
interfaces (part of #8).  Well, it's not the beginning: I already had
some half-written broken code around.  But it's the first fully
functional support, and especially, the first *tested* support; it's
probably best to review the nontrivially-changed code as if it were new.

Conceptually, the code so far is pretty simple: we generate an interface
type, and the implementations.  (That code is in fact mostly unchanged.)
The complexity comes in because encoding/json doesn't know how to
unmarshal that.  So we have to add an UnmarshalJSON method, which
actually has to be on the types with interface-type fields, that knows
how.  I factored it into two methods, such that that UnmarshalJSON
method is just glue, and then there's a separate function, corresponding
to each interface-type, that actually does all the work.  (If only one
could just write it as an actual method!)  The method uses the same
trick suggested to me by a few others in another context to deserialize
all but one field, then handle that field specially, which is discussed
in the code.

This still has some limitations, which will be lifted in future commits:
- it doesn't allow for list-of-interface fields
- it requires that you manually ask for `__typename`
- it doesn't support fragments, i.e. you can only query for interface
  fields, not concrete-type-specific ones
But it works, even in integration tests, which is progress!

As a part of this, I added a proper config option for the "allow broken
features" flag, since I need to be able to set it from the integration
tests which are in a separate package (and actually shell out via `go
generate`).  I also renamed what was to be the first case
(InterfaceNoFragments), and replaced it with a further-simplified
version (avoiding list-of-interface fields.

[1] https://github.com/benjaminjkraft/notes/blob/master/go-json-interfaces.md

Issue: https://github.com/Khan/genqlient/issues/8

## Test plan:
make tesc

Author: benjaminjkraft

Reviewers: dnerdy, benjaminjkraft, aberkan, csilvers, MiguelCastillo

Required Reviewers: 

Approved by: dnerdy

Checks:  Test (1.17),  Test (1.16),  Test (1.15),  Test (1.14),  Test (1.13),  Lint,  Test (1.17),  Test (1.16),  Test (1.15),  Test (1.14),  Test (1.13),  Lint

Pull request URL: https://github.com/Khan/genqlient/pull/52
2021-08-25 11:51:26 -07:00

205 lines
4.7 KiB
Go

package integration
// Code generated by github.com/Khan/genqlient, DO NOT EDIT.
import (
"context"
"encoding/json"
"fmt"
"github.com/Khan/genqlient/graphql"
)
// queryWithInterfaceNoFragmentsBeing includes the requested fields of the GraphQL type Being.
type queryWithInterfaceNoFragmentsBeing interface {
implementsGraphQLInterfacequeryWithInterfaceNoFragmentsBeing()
}
func (v *queryWithInterfaceNoFragmentsBeingUser) implementsGraphQLInterfacequeryWithInterfaceNoFragmentsBeing() {
}
func (v *queryWithInterfaceNoFragmentsBeingAnimal) implementsGraphQLInterfacequeryWithInterfaceNoFragmentsBeing() {
}
func __unmarshalqueryWithInterfaceNoFragmentsBeing(v *queryWithInterfaceNoFragmentsBeing, m json.RawMessage) error {
if string(m) == "null" {
return nil
}
var tn struct {
TypeName string `json:"__typename"`
}
err := json.Unmarshal(m, &tn)
if err != nil {
return err
}
switch tn.TypeName {
case "User":
*v = new(queryWithInterfaceNoFragmentsBeingUser)
return json.Unmarshal(m, *v)
case "Animal":
*v = new(queryWithInterfaceNoFragmentsBeingAnimal)
return json.Unmarshal(m, *v)
default:
return fmt.Errorf(
`Unexpected concrete type for queryWithInterfaceNoFragmentsBeing: "%v"`, tn.TypeName)
}
}
// queryWithInterfaceNoFragmentsBeingAnimal includes the requested fields of the GraphQL type Animal.
type queryWithInterfaceNoFragmentsBeingAnimal struct {
Typename string `json:"__typename"`
Id string `json:"id"`
Name string `json:"name"`
}
// queryWithInterfaceNoFragmentsBeingUser includes the requested fields of the GraphQL type User.
type queryWithInterfaceNoFragmentsBeingUser struct {
Typename string `json:"__typename"`
Id string `json:"id"`
Name string `json:"name"`
}
// queryWithInterfaceNoFragmentsMeUser includes the requested fields of the GraphQL type User.
type queryWithInterfaceNoFragmentsMeUser struct {
Id string `json:"id"`
Name string `json:"name"`
}
// queryWithInterfaceNoFragmentsResponse is returned by queryWithInterfaceNoFragments on success.
type queryWithInterfaceNoFragmentsResponse struct {
Being queryWithInterfaceNoFragmentsBeing `json:"-"`
Me queryWithInterfaceNoFragmentsMeUser `json:"me"`
}
func (v *queryWithInterfaceNoFragmentsResponse) UnmarshalJSON(b []byte) error {
type queryWithInterfaceNoFragmentsResponseWrapper queryWithInterfaceNoFragmentsResponse
var firstPass struct {
*queryWithInterfaceNoFragmentsResponseWrapper
Being json.RawMessage `json:"being"`
}
firstPass.queryWithInterfaceNoFragmentsResponseWrapper = (*queryWithInterfaceNoFragmentsResponseWrapper)(v)
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = __unmarshalqueryWithInterfaceNoFragmentsBeing(
&v.Being, firstPass.Being)
if err != nil {
return err
}
return nil
}
// queryWithVariablesResponse is returned by queryWithVariables on success.
type queryWithVariablesResponse struct {
User queryWithVariablesUser `json:"user"`
}
// queryWithVariablesUser includes the requested fields of the GraphQL type User.
type queryWithVariablesUser struct {
Id string `json:"id"`
Name string `json:"name"`
LuckyNumber int `json:"luckyNumber"`
}
// simpleQueryMeUser includes the requested fields of the GraphQL type User.
type simpleQueryMeUser struct {
Id string `json:"id"`
Name string `json:"name"`
LuckyNumber int `json:"luckyNumber"`
}
// simpleQueryResponse is returned by simpleQuery on success.
type simpleQueryResponse struct {
Me simpleQueryMeUser `json:"me"`
}
func simpleQuery(
ctx context.Context,
client graphql.Client,
) (*simpleQueryResponse, error) {
var retval simpleQueryResponse
err := client.MakeRequest(
ctx,
"simpleQuery",
`
query simpleQuery {
me {
id
name
luckyNumber
}
}
`,
&retval,
nil,
)
return &retval, err
}
func queryWithVariables(
ctx context.Context,
client graphql.Client,
id string,
) (*queryWithVariablesResponse, error) {
variables := map[string]interface{}{
"id": id,
}
var retval queryWithVariablesResponse
err := client.MakeRequest(
ctx,
"queryWithVariables",
`
query queryWithVariables ($id: ID!) {
user(id: $id) {
id
name
luckyNumber
}
}
`,
&retval,
variables,
)
return &retval, err
}
func queryWithInterfaceNoFragments(
ctx context.Context,
client graphql.Client,
id string,
) (*queryWithInterfaceNoFragmentsResponse, error) {
variables := map[string]interface{}{
"id": id,
}
var retval queryWithInterfaceNoFragmentsResponse
err := client.MakeRequest(
ctx,
"queryWithInterfaceNoFragments",
`
query queryWithInterfaceNoFragments ($id: ID!) {
being(id: $id) {
__typename
id
name
}
me {
id
name
}
}
`,
&retval,
variables,
)
return &retval, err
}