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
This commit is contained in:
+5
@@ -0,0 +1,5 @@
|
||||
package errors
|
||||
|
||||
const _ = `# @genqlient
|
||||
query MyQuery { i { f } }
|
||||
`
|
||||
@@ -0,0 +1 @@
|
||||
query MyQuery { i { f } }
|
||||
@@ -0,0 +1,11 @@
|
||||
type Query {
|
||||
i: I
|
||||
}
|
||||
|
||||
type T implements I {
|
||||
f: String!
|
||||
}
|
||||
|
||||
interface I {
|
||||
f: String!
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
query InterfaceNoFragmentsQuery {
|
||||
root {
|
||||
id
|
||||
name
|
||||
children {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,13 @@ query InterfaceNesting {
|
||||
root {
|
||||
id
|
||||
children {
|
||||
__typename
|
||||
id
|
||||
parent {
|
||||
__typename
|
||||
id
|
||||
children {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -1,10 +1,4 @@
|
||||
query InterfaceNoFragmentsQuery {
|
||||
root {
|
||||
id
|
||||
name
|
||||
children {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
root { id name } # (make sure sibling fields work)
|
||||
randomItem { __typename id name }
|
||||
}
|
||||
|
||||
+1
@@ -104,6 +104,7 @@ type Query {
|
||||
"""usersWithRole looks a user up by role."""
|
||||
usersWithRole(role: Role!): [User!]!
|
||||
root: Topic!
|
||||
randomItem: Content!
|
||||
randomLeaf: LeafContent!
|
||||
convert(dt: DateTime!, tz: String): DateTime!
|
||||
maybeConvert(dt: DateTime, tz: String): DateTime
|
||||
|
||||
Vendored
+32
@@ -3,6 +3,9 @@ package test
|
||||
// Code generated by github.com/Khan/genqlient, DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/Khan/genqlient/internal/testutil"
|
||||
)
|
||||
@@ -43,6 +46,35 @@ func (v *InterfaceNoFragmentsQueryRootTopicChildrenVideo) implementsGraphQLInter
|
||||
func (v *InterfaceNoFragmentsQueryRootTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRootTopicChildrenContent() {
|
||||
}
|
||||
|
||||
func __unmarshalInterfaceNoFragmentsQueryRootTopicChildrenContent(v *InterfaceNoFragmentsQueryRootTopicChildrenContent, 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 "Article":
|
||||
*v = new(InterfaceNoFragmentsQueryRootTopicChildrenArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(InterfaceNoFragmentsQueryRootTopicChildrenVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Topic":
|
||||
*v = new(InterfaceNoFragmentsQueryRootTopicChildrenTopic)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for InterfaceNoFragmentsQueryRootTopicChildrenContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRootTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNoFragmentsQueryRootTopicChildrenTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"operations": [
|
||||
{
|
||||
"operationName": "InterfaceNoFragmentsQuery",
|
||||
"query": "\nquery InterfaceNoFragmentsQuery {\n\troot {\n\t\tid\n\t\tname\n\t\tchildren {\n\t\t\t__typename\n\t\t\tid\n\t\t\tname\n\t\t}\n\t}\n}\n",
|
||||
"sourceLocation": "testdata/queries/InterfaceListField.graphql"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+149
-12
@@ -3,6 +3,9 @@ package test
|
||||
// Code generated by github.com/Khan/genqlient, DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/Khan/genqlient/internal/testutil"
|
||||
)
|
||||
@@ -21,6 +24,7 @@ type InterfaceNestingRootTopic struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
type InterfaceNestingRootTopicChildrenArticle struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Parent InterfaceNestingRootTopicChildrenArticleParentTopic `json:"parent"`
|
||||
@@ -28,6 +32,7 @@ type InterfaceNestingRootTopicChildrenArticle struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticleParentTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenArticleParentTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent `json:"children"`
|
||||
@@ -35,6 +40,7 @@ type InterfaceNestingRootTopicChildrenArticleParentTopic struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticleParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
type InterfaceNestingRootTopicChildrenArticleParentTopicChildrenArticle struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
@@ -47,21 +53,52 @@ type InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent interfac
|
||||
implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent()
|
||||
}
|
||||
|
||||
func (v InterfaceNestingRootTopicChildrenArticleParentTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenArticleParentTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenArticleParentTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenArticleParentTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenArticleParentTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenArticleParentTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent() {
|
||||
}
|
||||
|
||||
func __unmarshalInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent(v *InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent, 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 "Article":
|
||||
*v = new(InterfaceNestingRootTopicChildrenArticleParentTopicChildrenArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(InterfaceNestingRootTopicChildrenArticleParentTopicChildrenVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Topic":
|
||||
*v = new(InterfaceNestingRootTopicChildrenArticleParentTopicChildrenTopic)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticleParentTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenArticleParentTopicChildrenTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticleParentTopicChildrenVideo includes the requested fields of the GraphQL type Video.
|
||||
type InterfaceNestingRootTopicChildrenArticleParentTopicChildrenVideo struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
@@ -74,15 +111,45 @@ type InterfaceNestingRootTopicChildrenContent interface {
|
||||
implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent()
|
||||
}
|
||||
|
||||
func (v InterfaceNestingRootTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenContent() {
|
||||
}
|
||||
|
||||
func __unmarshalInterfaceNestingRootTopicChildrenContent(v *InterfaceNestingRootTopicChildrenContent, 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 "Article":
|
||||
*v = new(InterfaceNestingRootTopicChildrenArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(InterfaceNestingRootTopicChildrenVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Topic":
|
||||
*v = new(InterfaceNestingRootTopicChildrenTopic)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for InterfaceNestingRootTopicChildrenContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Parent InterfaceNestingRootTopicChildrenTopicParentTopic `json:"parent"`
|
||||
@@ -90,6 +157,7 @@ type InterfaceNestingRootTopicChildrenTopic struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenTopicParentTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenTopicParentTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent `json:"children"`
|
||||
@@ -97,6 +165,7 @@ type InterfaceNestingRootTopicChildrenTopicParentTopic struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenTopicParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
type InterfaceNestingRootTopicChildrenTopicParentTopicChildrenArticle struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
@@ -109,27 +178,59 @@ type InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent interface
|
||||
implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent()
|
||||
}
|
||||
|
||||
func (v InterfaceNestingRootTopicChildrenTopicParentTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenTopicParentTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenTopicParentTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenTopicParentTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenTopicParentTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenTopicParentTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent() {
|
||||
}
|
||||
|
||||
func __unmarshalInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent(v *InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent, 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 "Article":
|
||||
*v = new(InterfaceNestingRootTopicChildrenTopicParentTopicChildrenArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(InterfaceNestingRootTopicChildrenTopicParentTopicChildrenVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Topic":
|
||||
*v = new(InterfaceNestingRootTopicChildrenTopicParentTopicChildrenTopic)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenTopicParentTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenTopicParentTopicChildrenTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenTopicParentTopicChildrenVideo includes the requested fields of the GraphQL type Video.
|
||||
type InterfaceNestingRootTopicChildrenTopicParentTopicChildrenVideo struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenVideo includes the requested fields of the GraphQL type Video.
|
||||
type InterfaceNestingRootTopicChildrenVideo struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Parent InterfaceNestingRootTopicChildrenVideoParentTopic `json:"parent"`
|
||||
@@ -137,6 +238,7 @@ type InterfaceNestingRootTopicChildrenVideo struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenVideoParentTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenVideoParentTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent `json:"children"`
|
||||
@@ -144,6 +246,7 @@ type InterfaceNestingRootTopicChildrenVideoParentTopic struct {
|
||||
|
||||
// InterfaceNestingRootTopicChildrenVideoParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
type InterfaceNestingRootTopicChildrenVideoParentTopicChildrenArticle struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
@@ -156,21 +259,52 @@ type InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent interface
|
||||
implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent()
|
||||
}
|
||||
|
||||
func (v InterfaceNestingRootTopicChildrenVideoParentTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenVideoParentTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenVideoParentTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenVideoParentTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNestingRootTopicChildrenVideoParentTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent() {
|
||||
func (v *InterfaceNestingRootTopicChildrenVideoParentTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent() {
|
||||
}
|
||||
|
||||
func __unmarshalInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent(v *InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent, 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 "Article":
|
||||
*v = new(InterfaceNestingRootTopicChildrenVideoParentTopicChildrenArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(InterfaceNestingRootTopicChildrenVideoParentTopicChildrenVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Topic":
|
||||
*v = new(InterfaceNestingRootTopicChildrenVideoParentTopicChildrenTopic)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenVideoParentTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNestingRootTopicChildrenVideoParentTopicChildrenTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenVideoParentTopicChildrenVideo includes the requested fields of the GraphQL type Video.
|
||||
type InterfaceNestingRootTopicChildrenVideoParentTopicChildrenVideo struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
}
|
||||
@@ -187,10 +321,13 @@ query InterfaceNesting {
|
||||
root {
|
||||
id
|
||||
children {
|
||||
__typename
|
||||
id
|
||||
parent {
|
||||
__typename
|
||||
id
|
||||
children {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@
|
||||
"operations": [
|
||||
{
|
||||
"operationName": "InterfaceNesting",
|
||||
"query": "\nquery InterfaceNesting {\n\troot {\n\t\tid\n\t\tchildren {\n\t\t\tid\n\t\t\tparent {\n\t\t\t\tid\n\t\t\t\tchildren {\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n",
|
||||
"query": "\nquery InterfaceNesting {\n\troot {\n\t\tid\n\t\tchildren {\n\t\t\t__typename\n\t\t\tid\n\t\t\tparent {\n\t\t\t\t__typename\n\t\t\t\tid\n\t\t\t\tchildren {\n\t\t\t\t\t__typename\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n",
|
||||
"sourceLocation": "testdata/queries/InterfaceNesting.graphql"
|
||||
}
|
||||
]
|
||||
|
||||
+102
-42
@@ -3,55 +3,114 @@ package test
|
||||
// Code generated by github.com/Khan/genqlient, DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/Khan/genqlient/internal/testutil"
|
||||
)
|
||||
|
||||
// InterfaceNoFragmentsQueryRandomItemArticle includes the requested fields of the GraphQL type Article.
|
||||
type InterfaceNoFragmentsQueryRandomItemArticle struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRandomItemContent includes the requested fields of the GraphQL type Content.
|
||||
// The GraphQL type's documentation follows.
|
||||
//
|
||||
// Content is implemented by various types like Article, Video, and Topic.
|
||||
type InterfaceNoFragmentsQueryRandomItemContent interface {
|
||||
implementsGraphQLInterfaceInterfaceNoFragmentsQueryRandomItemContent()
|
||||
}
|
||||
|
||||
func (v *InterfaceNoFragmentsQueryRandomItemArticle) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRandomItemContent() {
|
||||
}
|
||||
func (v *InterfaceNoFragmentsQueryRandomItemVideo) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRandomItemContent() {
|
||||
}
|
||||
func (v *InterfaceNoFragmentsQueryRandomItemTopic) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRandomItemContent() {
|
||||
}
|
||||
|
||||
func __unmarshalInterfaceNoFragmentsQueryRandomItemContent(v *InterfaceNoFragmentsQueryRandomItemContent, 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 "Article":
|
||||
*v = new(InterfaceNoFragmentsQueryRandomItemArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(InterfaceNoFragmentsQueryRandomItemVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Topic":
|
||||
*v = new(InterfaceNoFragmentsQueryRandomItemTopic)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for InterfaceNoFragmentsQueryRandomItemContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRandomItemTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNoFragmentsQueryRandomItemTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRandomItemVideo includes the requested fields of the GraphQL type Video.
|
||||
type InterfaceNoFragmentsQueryRandomItemVideo struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryResponse is returned by InterfaceNoFragmentsQuery on success.
|
||||
type InterfaceNoFragmentsQueryResponse struct {
|
||||
Root InterfaceNoFragmentsQueryRootTopic `json:"root"`
|
||||
Root InterfaceNoFragmentsQueryRootTopic `json:"root"`
|
||||
RandomItem InterfaceNoFragmentsQueryRandomItemContent `json:"-"`
|
||||
}
|
||||
|
||||
func (v *InterfaceNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type InterfaceNoFragmentsQueryResponseWrapper InterfaceNoFragmentsQueryResponse
|
||||
|
||||
var firstPass struct {
|
||||
*InterfaceNoFragmentsQueryResponseWrapper
|
||||
RandomItem json.RawMessage `json:"randomItem"`
|
||||
}
|
||||
firstPass.InterfaceNoFragmentsQueryResponseWrapper = (*InterfaceNoFragmentsQueryResponseWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = __unmarshalInterfaceNoFragmentsQueryRandomItemContent(
|
||||
&v.RandomItem, firstPass.RandomItem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRootTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNoFragmentsQueryRootTopic struct {
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Children []InterfaceNoFragmentsQueryRootTopicChildrenContent `json:"children"`
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRootTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
type InterfaceNoFragmentsQueryRootTopicChildrenArticle struct {
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRootTopicChildrenContent includes the requested fields of the GraphQL type Content.
|
||||
// The GraphQL type's documentation follows.
|
||||
//
|
||||
// Content is implemented by various types like Article, Video, and Topic.
|
||||
type InterfaceNoFragmentsQueryRootTopicChildrenContent interface {
|
||||
implementsGraphQLInterfaceInterfaceNoFragmentsQueryRootTopicChildrenContent()
|
||||
}
|
||||
|
||||
func (v InterfaceNoFragmentsQueryRootTopicChildrenArticle) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRootTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNoFragmentsQueryRootTopicChildrenVideo) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRootTopicChildrenContent() {
|
||||
}
|
||||
func (v InterfaceNoFragmentsQueryRootTopicChildrenTopic) implementsGraphQLInterfaceInterfaceNoFragmentsQueryRootTopicChildrenContent() {
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRootTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
|
||||
type InterfaceNoFragmentsQueryRootTopicChildrenTopic struct {
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// InterfaceNoFragmentsQueryRootTopicChildrenVideo includes the requested fields of the GraphQL type Video.
|
||||
type InterfaceNoFragmentsQueryRootTopicChildrenVideo struct {
|
||||
// ID is the identifier of the content.
|
||||
Id testutil.ID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
@@ -68,10 +127,11 @@ query InterfaceNoFragmentsQuery {
|
||||
root {
|
||||
id
|
||||
name
|
||||
children {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
randomItem {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"operations": [
|
||||
{
|
||||
"operationName": "InterfaceNoFragmentsQuery",
|
||||
"query": "\nquery InterfaceNoFragmentsQuery {\n\troot {\n\t\tid\n\t\tname\n\t\tchildren {\n\t\t\tid\n\t\t\tname\n\t\t}\n\t}\n}\n",
|
||||
"query": "\nquery InterfaceNoFragmentsQuery {\n\troot {\n\t\tid\n\t\tname\n\t}\n\trandomItem {\n\t\t__typename\n\t\tid\n\t\tname\n\t}\n}\n",
|
||||
"sourceLocation": "testdata/queries/InterfaceNoFragments.graphql"
|
||||
}
|
||||
]
|
||||
|
||||
Vendored
+36
-26
@@ -4,6 +4,7 @@ package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
)
|
||||
@@ -21,9 +22,35 @@ type UnionNoFragmentsQueryRandomLeafLeafContent interface {
|
||||
implementsGraphQLInterfaceUnionNoFragmentsQueryRandomLeafLeafContent()
|
||||
}
|
||||
|
||||
func (v UnionNoFragmentsQueryRandomLeafArticle) implementsGraphQLInterfaceUnionNoFragmentsQueryRandomLeafLeafContent() {
|
||||
func (v *UnionNoFragmentsQueryRandomLeafArticle) implementsGraphQLInterfaceUnionNoFragmentsQueryRandomLeafLeafContent() {
|
||||
}
|
||||
func (v UnionNoFragmentsQueryRandomLeafVideo) implementsGraphQLInterfaceUnionNoFragmentsQueryRandomLeafLeafContent() {
|
||||
func (v *UnionNoFragmentsQueryRandomLeafVideo) implementsGraphQLInterfaceUnionNoFragmentsQueryRandomLeafLeafContent() {
|
||||
}
|
||||
|
||||
func __unmarshalUnionNoFragmentsQueryRandomLeafLeafContent(v *UnionNoFragmentsQueryRandomLeafLeafContent, 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 "Article":
|
||||
*v = new(UnionNoFragmentsQueryRandomLeafArticle)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Video":
|
||||
*v = new(UnionNoFragmentsQueryRandomLeafVideo)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for UnionNoFragmentsQueryRandomLeafLeafContent: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// UnionNoFragmentsQueryRandomLeafVideo includes the requested fields of the GraphQL type Video.
|
||||
@@ -37,39 +64,22 @@ type UnionNoFragmentsQueryResponse struct {
|
||||
}
|
||||
|
||||
func (v *UnionNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type UnionNoFragmentsQueryResponseWrapper UnionNoFragmentsQueryResponse
|
||||
|
||||
var firstPass struct {
|
||||
*UnionNoFragmentsQueryResponse
|
||||
*UnionNoFragmentsQueryResponseWrapper
|
||||
RandomLeaf json.RawMessage `json:"randomLeaf"`
|
||||
}
|
||||
firstPass.UnionNoFragmentsQueryResponse = v
|
||||
firstPass.UnionNoFragmentsQueryResponseWrapper = (*UnionNoFragmentsQueryResponseWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err = json.Unmarshal(firstPass.RandomLeaf, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch tn.TypeName {
|
||||
|
||||
case "Article":
|
||||
|
||||
v.RandomLeaf = UnionNoFragmentsQueryRandomLeafArticle{}
|
||||
err = json.Unmarshal(
|
||||
firstPass.RandomLeaf, &v.RandomLeaf)
|
||||
|
||||
case "Video":
|
||||
|
||||
v.RandomLeaf = UnionNoFragmentsQueryRandomLeafVideo{}
|
||||
err = json.Unmarshal(
|
||||
firstPass.RandomLeaf, &v.RandomLeaf)
|
||||
|
||||
}
|
||||
err = __unmarshalUnionNoFragmentsQueryRandomLeafLeafContent(
|
||||
&v.RandomLeaf, firstPass.RandomLeaf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
testdata/errors/MissingTypeName.schema.graphql:2: union/interface type I must request __typename
|
||||
@@ -0,0 +1 @@
|
||||
testdata/errors/MissingTypeName.schema.graphql:2: union/interface type I must request __typename
|
||||
Reference in New Issue
Block a user