Add support for concrete-typed named fragments (#75)

## Summary:
In previous commits I added support to genqlient for interfaces and
inline fragments.  This means the only query structures that remain are
named fragments and their spreads, e.g.
```
fragment MyFragment on MyType { myField }
query MyQuery { getMyType { ...MyFragment } }
```
Other than mere completionism, these are potentially useful for code
sharing: you can spread the same fragment multiple places; and then
genqlient can notice that and generate the same type for each.  (They
can even be shared between different queries in the same package.)

In this commit I add support for named fragments of concrete
(object/struct, not interface) type, spread into either concrete or
abstract scope.  For genqlient's purposes, these are a new "root"
type-name, just like each operation, and are then embedded into the
appropriate struct.  (Using embeds allows their fields to be referenced
as fields of the containing type, if convenient.  Further design
considerations are discussed in DESIGN.md.)

This requires new code in two main places (plus miscellaneous glue),
both nontrivial but neither particularly complex:
- We need to actually traverse both structures and generate the types
  (in `convert.go`).
- We need to decide which fragments from this package to send to the
  server, both for good hyigene and because GraphQL requires we send
  only ones this query uses (in `generate.go`).
- We need a little new wiring for options -- because fragments can be
  shared between queries they get their own toplevel options, rather
  than inheriting the query's options.

Finally, this required slightly subtler changes to how we do
unmarshaling (in `types.go` and `unmarshal.go.tmpl`).  Basically,
because embedded fields' methods, including `UnmarshalJSON`, get
promoted to the parent type, and because the JSON library ignores their
fields when shadowed by those of the parent type, we need a little bit
of special logic in each such parent type to do its own unmarshal and
then delegate to each embed.  This is similar (and much simpler) to
what we did for interfaces, although it required some changes to the
"method-hiding" trick (used for both).  It's only really necessary in
certain specific cases (namely when an embedded type has an
`UnmarshalJSON` method or a field with the same name as the embedder),
but it's easier to just generate it always.  This is all described in
more detail inline.

This does not support fragments of abstract type, which have their own
complexities.  I'll address those, which are now the only remaining
piece of #8, in a future commit.

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

## Test plan:
make check


Author: benjaminjkraft

Reviewers: dnerdy, benjaminjkraft, aberkan, MiguelCastillo

Required Reviewers: 

Approved By: dnerdy

Checks:  Lint,  Test (1.17),  Test (1.16),  Test (1.15),  Test (1.14),  Test (1.13),  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/75
This commit is contained in:
Ben Kraft
2021-09-09 09:39:30 -07:00
committed by GitHub
parent 1c061b153a
commit f99c10d6fd
22 changed files with 1857 additions and 123 deletions
+39
View File
@@ -0,0 +1,39 @@
fragment QueryFragment on Query {
...InnerQueryFragment
}
fragment InnerQueryFragment on Query {
randomItem {
id name
...VideoFields
}
randomLeaf {
...VideoFields
...MoreVideoFields
}
otherLeaf: randomLeaf {
... on Video {
...MoreVideoFields
}
}
}
fragment VideoFields on Video {
id name url duration thumbnail { id }
}
# @genqlient(pointer: true)
fragment MoreVideoFields on Video {
id
parent {
name url
# @genqlient(pointer: false)
children {
...VideoFields
}
}
}
query ComplexNamedFragments {
... on Query { ...QueryFragment }
}
+13
View File
@@ -0,0 +1,13 @@
fragment VideoFields on Video {
id name url duration thumbnail { id }
}
query SimpleNamedFragment {
randomItem {
id name
...VideoFields
}
randomLeaf {
...VideoFields
}
}
@@ -184,13 +184,12 @@ type ComplexInlineFragmentsNestedStuffTopic struct {
func (v *ComplexInlineFragmentsNestedStuffTopic) UnmarshalJSON(b []byte) error {
type ComplexInlineFragmentsNestedStuffTopicWrapper ComplexInlineFragmentsNestedStuffTopic
var firstPass struct {
*ComplexInlineFragmentsNestedStuffTopicWrapper
*ComplexInlineFragmentsNestedStuffTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.ComplexInlineFragmentsNestedStuffTopicWrapper = (*ComplexInlineFragmentsNestedStuffTopicWrapper)(v)
firstPass.ComplexInlineFragmentsNestedStuffTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -213,6 +212,7 @@ func (v *ComplexInlineFragmentsNestedStuffTopic) UnmarshalJSON(b []byte) error {
}
}
}
return nil
}
@@ -232,13 +232,12 @@ type ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTop
func (v *ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopic) UnmarshalJSON(b []byte) error {
type ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopicWrapper ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopic
var firstPass struct {
*ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopicWrapper
*ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopicWrapper = (*ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopicWrapper)(v)
firstPass.ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -261,6 +260,7 @@ func (v *ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParen
}
}
}
return nil
}
@@ -797,16 +797,15 @@ type ComplexInlineFragmentsResponse struct {
func (v *ComplexInlineFragmentsResponse) UnmarshalJSON(b []byte) error {
type ComplexInlineFragmentsResponseWrapper ComplexInlineFragmentsResponse
var firstPass struct {
*ComplexInlineFragmentsResponseWrapper
*ComplexInlineFragmentsResponse
RandomItem json.RawMessage `json:"randomItem"`
RepeatedStuff json.RawMessage `json:"repeatedStuff"`
ConflictingStuff json.RawMessage `json:"conflictingStuff"`
NestedStuff json.RawMessage `json:"nestedStuff"`
graphql.NoUnmarshalJSON
}
firstPass.ComplexInlineFragmentsResponseWrapper = (*ComplexInlineFragmentsResponseWrapper)(v)
firstPass.ComplexInlineFragmentsResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -823,6 +822,7 @@ func (v *ComplexInlineFragmentsResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal ComplexInlineFragmentsResponse.RandomItem: %w", err)
}
}
{
target := &v.RepeatedStuff
raw := firstPass.RepeatedStuff
@@ -833,6 +833,7 @@ func (v *ComplexInlineFragmentsResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal ComplexInlineFragmentsResponse.RepeatedStuff: %w", err)
}
}
{
target := &v.ConflictingStuff
raw := firstPass.ConflictingStuff
@@ -843,6 +844,7 @@ func (v *ComplexInlineFragmentsResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal ComplexInlineFragmentsResponse.ConflictingStuff: %w", err)
}
}
{
target := &v.NestedStuff
raw := firstPass.NestedStuff
@@ -853,6 +855,7 @@ func (v *ComplexInlineFragmentsResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal ComplexInlineFragmentsResponse.NestedStuff: %w", err)
}
}
return nil
}
@@ -0,0 +1,666 @@
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"
)
// ComplexNamedFragmentsResponse is returned by ComplexNamedFragments on success.
type ComplexNamedFragmentsResponse struct {
QueryFragment `json:"-"`
}
func (v *ComplexNamedFragmentsResponse) UnmarshalJSON(b []byte) error {
var firstPass struct {
*ComplexNamedFragmentsResponse
graphql.NoUnmarshalJSON
}
firstPass.ComplexNamedFragmentsResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.QueryFragment)
if err != nil {
return err
}
return nil
}
// InnerQueryFragment includes the GraphQL fields of Query requested by the fragment InnerQueryFragment.
type InnerQueryFragment struct {
RandomItem InnerQueryFragmentRandomItemContent `json:"-"`
RandomLeaf InnerQueryFragmentRandomLeafLeafContent `json:"-"`
OtherLeaf InnerQueryFragmentOtherLeafLeafContent `json:"-"`
}
func (v *InnerQueryFragment) UnmarshalJSON(b []byte) error {
var firstPass struct {
*InnerQueryFragment
RandomItem json.RawMessage `json:"randomItem"`
RandomLeaf json.RawMessage `json:"randomLeaf"`
OtherLeaf json.RawMessage `json:"otherLeaf"`
graphql.NoUnmarshalJSON
}
firstPass.InnerQueryFragment = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
{
target := &v.RandomItem
raw := firstPass.RandomItem
err = __unmarshalInnerQueryFragmentRandomItemContent(
target, raw)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal InnerQueryFragment.RandomItem: %w", err)
}
}
{
target := &v.RandomLeaf
raw := firstPass.RandomLeaf
err = __unmarshalInnerQueryFragmentRandomLeafLeafContent(
target, raw)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal InnerQueryFragment.RandomLeaf: %w", err)
}
}
{
target := &v.OtherLeaf
raw := firstPass.OtherLeaf
err = __unmarshalInnerQueryFragmentOtherLeafLeafContent(
target, raw)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal InnerQueryFragment.OtherLeaf: %w", err)
}
}
return nil
}
// InnerQueryFragmentOtherLeafArticle includes the requested fields of the GraphQL type Article.
type InnerQueryFragmentOtherLeafArticle struct {
Typename string `json:"__typename"`
}
// InnerQueryFragmentOtherLeafLeafContent includes the requested fields of the GraphQL interface LeafContent.
//
// InnerQueryFragmentOtherLeafLeafContent is implemented by the following types:
// InnerQueryFragmentOtherLeafArticle
// InnerQueryFragmentOtherLeafVideo
//
// The GraphQL type's documentation follows.
//
// LeafContent represents content items that can't have child-nodes.
type InnerQueryFragmentOtherLeafLeafContent interface {
implementsGraphQLInterfaceInnerQueryFragmentOtherLeafLeafContent()
// GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values).
GetTypename() string
}
func (v *InnerQueryFragmentOtherLeafArticle) implementsGraphQLInterfaceInnerQueryFragmentOtherLeafLeafContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentOtherLeafLeafContent.
func (v *InnerQueryFragmentOtherLeafArticle) GetTypename() string { return v.Typename }
func (v *InnerQueryFragmentOtherLeafVideo) implementsGraphQLInterfaceInnerQueryFragmentOtherLeafLeafContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentOtherLeafLeafContent.
func (v *InnerQueryFragmentOtherLeafVideo) GetTypename() string { return v.Typename }
func __unmarshalInnerQueryFragmentOtherLeafLeafContent(v *InnerQueryFragmentOtherLeafLeafContent, 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(InnerQueryFragmentOtherLeafArticle)
return json.Unmarshal(m, *v)
case "Video":
*v = new(InnerQueryFragmentOtherLeafVideo)
return json.Unmarshal(m, *v)
case "":
return fmt.Errorf(
"Response was missing LeafContent.__typename")
default:
return fmt.Errorf(
`Unexpected concrete type for InnerQueryFragmentOtherLeafLeafContent: "%v"`, tn.TypeName)
}
}
// InnerQueryFragmentOtherLeafVideo includes the requested fields of the GraphQL type Video.
type InnerQueryFragmentOtherLeafVideo struct {
Typename string `json:"__typename"`
MoreVideoFields `json:"-"`
}
func (v *InnerQueryFragmentOtherLeafVideo) UnmarshalJSON(b []byte) error {
var firstPass struct {
*InnerQueryFragmentOtherLeafVideo
graphql.NoUnmarshalJSON
}
firstPass.InnerQueryFragmentOtherLeafVideo = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.MoreVideoFields)
if err != nil {
return err
}
return nil
}
// InnerQueryFragmentRandomItemArticle includes the requested fields of the GraphQL type Article.
type InnerQueryFragmentRandomItemArticle struct {
Typename string `json:"__typename"`
// ID is the identifier of the content.
Id testutil.ID `json:"id"`
Name string `json:"name"`
}
// InnerQueryFragmentRandomItemContent includes the requested fields of the GraphQL interface Content.
//
// InnerQueryFragmentRandomItemContent is implemented by the following types:
// InnerQueryFragmentRandomItemArticle
// InnerQueryFragmentRandomItemVideo
// InnerQueryFragmentRandomItemTopic
//
// The GraphQL type's documentation follows.
//
// Content is implemented by various types like Article, Video, and Topic.
type InnerQueryFragmentRandomItemContent interface {
implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent()
// GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values).
GetTypename() string
// GetId returns the interface-field "id" from its implementation.
// The GraphQL interface field's documentation follows.
//
// ID is the identifier of the content.
GetId() testutil.ID
// GetName returns the interface-field "name" from its implementation.
GetName() string
}
func (v *InnerQueryFragmentRandomItemArticle) implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemArticle) GetTypename() string { return v.Typename }
// GetId is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemArticle) GetId() testutil.ID { return v.Id }
// GetName is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemArticle) GetName() string { return v.Name }
func (v *InnerQueryFragmentRandomItemVideo) implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemVideo) GetTypename() string { return v.Typename }
// GetId is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemVideo) GetId() testutil.ID { return v.Id }
// GetName is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemVideo) GetName() string { return v.Name }
func (v *InnerQueryFragmentRandomItemTopic) implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemTopic) GetTypename() string { return v.Typename }
// GetId is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemTopic) GetId() testutil.ID { return v.Id }
// GetName is a part of, and documented with, the interface InnerQueryFragmentRandomItemContent.
func (v *InnerQueryFragmentRandomItemTopic) GetName() string { return v.Name }
func __unmarshalInnerQueryFragmentRandomItemContent(v *InnerQueryFragmentRandomItemContent, 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(InnerQueryFragmentRandomItemArticle)
return json.Unmarshal(m, *v)
case "Video":
*v = new(InnerQueryFragmentRandomItemVideo)
return json.Unmarshal(m, *v)
case "Topic":
*v = new(InnerQueryFragmentRandomItemTopic)
return json.Unmarshal(m, *v)
case "":
return fmt.Errorf(
"Response was missing Content.__typename")
default:
return fmt.Errorf(
`Unexpected concrete type for InnerQueryFragmentRandomItemContent: "%v"`, tn.TypeName)
}
}
// InnerQueryFragmentRandomItemTopic includes the requested fields of the GraphQL type Topic.
type InnerQueryFragmentRandomItemTopic struct {
Typename string `json:"__typename"`
// ID is the identifier of the content.
Id testutil.ID `json:"id"`
Name string `json:"name"`
}
// InnerQueryFragmentRandomItemVideo includes the requested fields of the GraphQL type Video.
type InnerQueryFragmentRandomItemVideo struct {
Typename string `json:"__typename"`
// ID is the identifier of the content.
Id testutil.ID `json:"id"`
Name string `json:"name"`
VideoFields `json:"-"`
}
func (v *InnerQueryFragmentRandomItemVideo) UnmarshalJSON(b []byte) error {
var firstPass struct {
*InnerQueryFragmentRandomItemVideo
graphql.NoUnmarshalJSON
}
firstPass.InnerQueryFragmentRandomItemVideo = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.VideoFields)
if err != nil {
return err
}
return nil
}
// InnerQueryFragmentRandomLeafArticle includes the requested fields of the GraphQL type Article.
type InnerQueryFragmentRandomLeafArticle struct {
Typename string `json:"__typename"`
}
// InnerQueryFragmentRandomLeafLeafContent includes the requested fields of the GraphQL interface LeafContent.
//
// InnerQueryFragmentRandomLeafLeafContent is implemented by the following types:
// InnerQueryFragmentRandomLeafArticle
// InnerQueryFragmentRandomLeafVideo
//
// The GraphQL type's documentation follows.
//
// LeafContent represents content items that can't have child-nodes.
type InnerQueryFragmentRandomLeafLeafContent interface {
implementsGraphQLInterfaceInnerQueryFragmentRandomLeafLeafContent()
// GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values).
GetTypename() string
}
func (v *InnerQueryFragmentRandomLeafArticle) implementsGraphQLInterfaceInnerQueryFragmentRandomLeafLeafContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentRandomLeafLeafContent.
func (v *InnerQueryFragmentRandomLeafArticle) GetTypename() string { return v.Typename }
func (v *InnerQueryFragmentRandomLeafVideo) implementsGraphQLInterfaceInnerQueryFragmentRandomLeafLeafContent() {
}
// GetTypename is a part of, and documented with, the interface InnerQueryFragmentRandomLeafLeafContent.
func (v *InnerQueryFragmentRandomLeafVideo) GetTypename() string { return v.Typename }
func __unmarshalInnerQueryFragmentRandomLeafLeafContent(v *InnerQueryFragmentRandomLeafLeafContent, 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(InnerQueryFragmentRandomLeafArticle)
return json.Unmarshal(m, *v)
case "Video":
*v = new(InnerQueryFragmentRandomLeafVideo)
return json.Unmarshal(m, *v)
case "":
return fmt.Errorf(
"Response was missing LeafContent.__typename")
default:
return fmt.Errorf(
`Unexpected concrete type for InnerQueryFragmentRandomLeafLeafContent: "%v"`, tn.TypeName)
}
}
// InnerQueryFragmentRandomLeafVideo includes the requested fields of the GraphQL type Video.
type InnerQueryFragmentRandomLeafVideo struct {
Typename string `json:"__typename"`
VideoFields `json:"-"`
MoreVideoFields `json:"-"`
}
func (v *InnerQueryFragmentRandomLeafVideo) UnmarshalJSON(b []byte) error {
var firstPass struct {
*InnerQueryFragmentRandomLeafVideo
graphql.NoUnmarshalJSON
}
firstPass.InnerQueryFragmentRandomLeafVideo = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.VideoFields)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.MoreVideoFields)
if err != nil {
return err
}
return nil
}
// MoreVideoFields includes the GraphQL fields of Video requested by the fragment MoreVideoFields.
type MoreVideoFields struct {
// ID is documented in the Content interface.
Id *testutil.ID `json:"id"`
Parent *MoreVideoFieldsParentTopic `json:"parent"`
}
// MoreVideoFieldsParentTopic includes the requested fields of the GraphQL type Topic.
type MoreVideoFieldsParentTopic struct {
Name *string `json:"name"`
Url *string `json:"url"`
Children []MoreVideoFieldsParentTopicChildrenContent `json:"-"`
}
func (v *MoreVideoFieldsParentTopic) UnmarshalJSON(b []byte) error {
var firstPass struct {
*MoreVideoFieldsParentTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.MoreVideoFieldsParentTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
{
target := &v.Children
raw := firstPass.Children
*target = make(
[]MoreVideoFieldsParentTopicChildrenContent,
len(raw))
for i, raw := range raw {
target := &(*target)[i]
err = __unmarshalMoreVideoFieldsParentTopicChildrenContent(
target, raw)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal MoreVideoFieldsParentTopic.Children: %w", err)
}
}
}
return nil
}
// MoreVideoFieldsParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
type MoreVideoFieldsParentTopicChildrenArticle struct {
Typename *string `json:"__typename"`
}
// MoreVideoFieldsParentTopicChildrenContent includes the requested fields of the GraphQL interface Content.
//
// MoreVideoFieldsParentTopicChildrenContent is implemented by the following types:
// MoreVideoFieldsParentTopicChildrenArticle
// MoreVideoFieldsParentTopicChildrenVideo
// MoreVideoFieldsParentTopicChildrenTopic
//
// The GraphQL type's documentation follows.
//
// Content is implemented by various types like Article, Video, and Topic.
type MoreVideoFieldsParentTopicChildrenContent interface {
implementsGraphQLInterfaceMoreVideoFieldsParentTopicChildrenContent()
// GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values).
GetTypename() *string
}
func (v *MoreVideoFieldsParentTopicChildrenArticle) implementsGraphQLInterfaceMoreVideoFieldsParentTopicChildrenContent() {
}
// GetTypename is a part of, and documented with, the interface MoreVideoFieldsParentTopicChildrenContent.
func (v *MoreVideoFieldsParentTopicChildrenArticle) GetTypename() *string { return v.Typename }
func (v *MoreVideoFieldsParentTopicChildrenVideo) implementsGraphQLInterfaceMoreVideoFieldsParentTopicChildrenContent() {
}
// GetTypename is a part of, and documented with, the interface MoreVideoFieldsParentTopicChildrenContent.
func (v *MoreVideoFieldsParentTopicChildrenVideo) GetTypename() *string { return v.Typename }
func (v *MoreVideoFieldsParentTopicChildrenTopic) implementsGraphQLInterfaceMoreVideoFieldsParentTopicChildrenContent() {
}
// GetTypename is a part of, and documented with, the interface MoreVideoFieldsParentTopicChildrenContent.
func (v *MoreVideoFieldsParentTopicChildrenTopic) GetTypename() *string { return v.Typename }
func __unmarshalMoreVideoFieldsParentTopicChildrenContent(v *MoreVideoFieldsParentTopicChildrenContent, 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(MoreVideoFieldsParentTopicChildrenArticle)
return json.Unmarshal(m, *v)
case "Video":
*v = new(MoreVideoFieldsParentTopicChildrenVideo)
return json.Unmarshal(m, *v)
case "Topic":
*v = new(MoreVideoFieldsParentTopicChildrenTopic)
return json.Unmarshal(m, *v)
case "":
return fmt.Errorf(
"Response was missing Content.__typename")
default:
return fmt.Errorf(
`Unexpected concrete type for MoreVideoFieldsParentTopicChildrenContent: "%v"`, tn.TypeName)
}
}
// MoreVideoFieldsParentTopicChildrenTopic includes the requested fields of the GraphQL type Topic.
type MoreVideoFieldsParentTopicChildrenTopic struct {
Typename *string `json:"__typename"`
}
// MoreVideoFieldsParentTopicChildrenVideo includes the requested fields of the GraphQL type Video.
type MoreVideoFieldsParentTopicChildrenVideo struct {
Typename *string `json:"__typename"`
VideoFields `json:"-"`
}
func (v *MoreVideoFieldsParentTopicChildrenVideo) UnmarshalJSON(b []byte) error {
var firstPass struct {
*MoreVideoFieldsParentTopicChildrenVideo
graphql.NoUnmarshalJSON
}
firstPass.MoreVideoFieldsParentTopicChildrenVideo = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.VideoFields)
if err != nil {
return err
}
return nil
}
// QueryFragment includes the GraphQL fields of Query requested by the fragment QueryFragment.
type QueryFragment struct {
InnerQueryFragment `json:"-"`
}
func (v *QueryFragment) UnmarshalJSON(b []byte) error {
var firstPass struct {
*QueryFragment
graphql.NoUnmarshalJSON
}
firstPass.QueryFragment = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.InnerQueryFragment)
if err != nil {
return err
}
return nil
}
// VideoFields includes the GraphQL fields of Video requested by the fragment VideoFields.
type VideoFields struct {
// ID is documented in the Content interface.
Id testutil.ID `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
Duration int `json:"duration"`
Thumbnail VideoFieldsThumbnail `json:"thumbnail"`
}
// VideoFieldsThumbnail includes the requested fields of the GraphQL type Thumbnail.
type VideoFieldsThumbnail struct {
Id testutil.ID `json:"id"`
}
func ComplexNamedFragments(
client graphql.Client,
) (*ComplexNamedFragmentsResponse, error) {
var err error
var retval ComplexNamedFragmentsResponse
err = client.MakeRequest(
nil,
"ComplexNamedFragments",
`
query ComplexNamedFragments {
... on Query {
... QueryFragment
}
}
fragment QueryFragment on Query {
... InnerQueryFragment
}
fragment InnerQueryFragment on Query {
randomItem {
__typename
id
name
... VideoFields
}
randomLeaf {
__typename
... VideoFields
... MoreVideoFields
}
otherLeaf: randomLeaf {
__typename
... on Video {
... MoreVideoFields
}
}
}
fragment VideoFields on Video {
id
name
url
duration
thumbnail {
id
}
}
fragment MoreVideoFields on Video {
id
parent {
name
url
children {
__typename
... VideoFields
}
}
}
`,
&retval,
nil,
)
return &retval, err
}
@@ -0,0 +1,9 @@
{
"operations": [
{
"operationName": "ComplexNamedFragments",
"query": "\nquery ComplexNamedFragments {\n\t... on Query {\n\t\t... QueryFragment\n\t}\n}\nfragment QueryFragment on Query {\n\t... InnerQueryFragment\n}\nfragment InnerQueryFragment on Query {\n\trandomItem {\n\t\t__typename\n\t\tid\n\t\tname\n\t\t... VideoFields\n\t}\n\trandomLeaf {\n\t\t__typename\n\t\t... VideoFields\n\t\t... MoreVideoFields\n\t}\n\totherLeaf: randomLeaf {\n\t\t__typename\n\t\t... on Video {\n\t\t\t... MoreVideoFields\n\t\t}\n\t}\n}\nfragment VideoFields on Video {\n\tid\n\tname\n\turl\n\tduration\n\tthumbnail {\n\t\tid\n\t}\n}\nfragment MoreVideoFields on Video {\n\tid\n\tparent {\n\t\tname\n\t\turl\n\t\tchildren {\n\t\t\t__typename\n\t\t\t... VideoFields\n\t\t}\n\t}\n}\n",
"sourceLocation": "testdata/queries/ComplexNamedFragments.graphql"
}
]
}
@@ -26,13 +26,12 @@ type InterfaceListFieldRootTopic struct {
func (v *InterfaceListFieldRootTopic) UnmarshalJSON(b []byte) error {
type InterfaceListFieldRootTopicWrapper InterfaceListFieldRootTopic
var firstPass struct {
*InterfaceListFieldRootTopicWrapper
*InterfaceListFieldRootTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.InterfaceListFieldRootTopicWrapper = (*InterfaceListFieldRootTopicWrapper)(v)
firstPass.InterfaceListFieldRootTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -55,6 +54,7 @@ func (v *InterfaceListFieldRootTopic) UnmarshalJSON(b []byte) error {
}
}
}
return nil
}
@@ -183,13 +183,12 @@ type InterfaceListFieldWithPointerTopic struct {
func (v *InterfaceListFieldWithPointerTopic) UnmarshalJSON(b []byte) error {
type InterfaceListFieldWithPointerTopicWrapper InterfaceListFieldWithPointerTopic
var firstPass struct {
*InterfaceListFieldWithPointerTopicWrapper
*InterfaceListFieldWithPointerTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.InterfaceListFieldWithPointerTopicWrapper = (*InterfaceListFieldWithPointerTopicWrapper)(v)
firstPass.InterfaceListFieldWithPointerTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -212,6 +211,7 @@ func (v *InterfaceListFieldWithPointerTopic) UnmarshalJSON(b []byte) error {
}
}
}
return nil
}
@@ -151,14 +151,13 @@ type InterfaceListOfListOfListsFieldResponse struct {
func (v *InterfaceListOfListOfListsFieldResponse) UnmarshalJSON(b []byte) error {
type InterfaceListOfListOfListsFieldResponseWrapper InterfaceListOfListOfListsFieldResponse
var firstPass struct {
*InterfaceListOfListOfListsFieldResponseWrapper
*InterfaceListOfListOfListsFieldResponse
ListOfListsOfListsOfContent [][][]json.RawMessage `json:"listOfListsOfListsOfContent"`
WithPointer [][][]json.RawMessage `json:"withPointer"`
graphql.NoUnmarshalJSON
}
firstPass.InterfaceListOfListOfListsFieldResponseWrapper = (*InterfaceListOfListOfListsFieldResponseWrapper)(v)
firstPass.InterfaceListOfListOfListsFieldResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -193,6 +192,7 @@ func (v *InterfaceListOfListOfListsFieldResponse) UnmarshalJSON(b []byte) error
}
}
}
{
target := &v.WithPointer
raw := firstPass.WithPointer
@@ -222,6 +222,7 @@ func (v *InterfaceListOfListOfListsFieldResponse) UnmarshalJSON(b []byte) error
}
}
}
return nil
}
@@ -24,13 +24,12 @@ type InterfaceNestingRootTopic struct {
func (v *InterfaceNestingRootTopic) UnmarshalJSON(b []byte) error {
type InterfaceNestingRootTopicWrapper InterfaceNestingRootTopic
var firstPass struct {
*InterfaceNestingRootTopicWrapper
*InterfaceNestingRootTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.InterfaceNestingRootTopicWrapper = (*InterfaceNestingRootTopicWrapper)(v)
firstPass.InterfaceNestingRootTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -53,6 +52,7 @@ func (v *InterfaceNestingRootTopic) UnmarshalJSON(b []byte) error {
}
}
}
return nil
}
@@ -170,13 +170,12 @@ type InterfaceNestingRootTopicChildrenContentParentTopic struct {
func (v *InterfaceNestingRootTopicChildrenContentParentTopic) UnmarshalJSON(b []byte) error {
type InterfaceNestingRootTopicChildrenContentParentTopicWrapper InterfaceNestingRootTopicChildrenContentParentTopic
var firstPass struct {
*InterfaceNestingRootTopicChildrenContentParentTopicWrapper
*InterfaceNestingRootTopicChildrenContentParentTopic
Children []json.RawMessage `json:"children"`
graphql.NoUnmarshalJSON
}
firstPass.InterfaceNestingRootTopicChildrenContentParentTopicWrapper = (*InterfaceNestingRootTopicChildrenContentParentTopicWrapper)(v)
firstPass.InterfaceNestingRootTopicChildrenContentParentTopic = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -199,6 +198,7 @@ func (v *InterfaceNestingRootTopicChildrenContentParentTopic) UnmarshalJSON(b []
}
}
}
return nil
}
@@ -256,15 +256,14 @@ type InterfaceNoFragmentsQueryResponse struct {
func (v *InterfaceNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
type InterfaceNoFragmentsQueryResponseWrapper InterfaceNoFragmentsQueryResponse
var firstPass struct {
*InterfaceNoFragmentsQueryResponseWrapper
*InterfaceNoFragmentsQueryResponse
RandomItem json.RawMessage `json:"randomItem"`
RandomItemWithTypeName json.RawMessage `json:"randomItemWithTypeName"`
WithPointer json.RawMessage `json:"withPointer"`
graphql.NoUnmarshalJSON
}
firstPass.InterfaceNoFragmentsQueryResponseWrapper = (*InterfaceNoFragmentsQueryResponseWrapper)(v)
firstPass.InterfaceNoFragmentsQueryResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -281,6 +280,7 @@ func (v *InterfaceNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal InterfaceNoFragmentsQueryResponse.RandomItem: %w", err)
}
}
{
target := &v.RandomItemWithTypeName
raw := firstPass.RandomItemWithTypeName
@@ -291,6 +291,7 @@ func (v *InterfaceNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal InterfaceNoFragmentsQueryResponse.RandomItemWithTypeName: %w", err)
}
}
{
target := &v.WithPointer
raw := firstPass.WithPointer
@@ -302,6 +303,7 @@ func (v *InterfaceNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal InterfaceNoFragmentsQueryResponse.WithPointer: %w", err)
}
}
return nil
}
@@ -134,13 +134,12 @@ type SimpleInlineFragmentResponse struct {
func (v *SimpleInlineFragmentResponse) UnmarshalJSON(b []byte) error {
type SimpleInlineFragmentResponseWrapper SimpleInlineFragmentResponse
var firstPass struct {
*SimpleInlineFragmentResponseWrapper
*SimpleInlineFragmentResponse
RandomItem json.RawMessage `json:"randomItem"`
graphql.NoUnmarshalJSON
}
firstPass.SimpleInlineFragmentResponseWrapper = (*SimpleInlineFragmentResponseWrapper)(v)
firstPass.SimpleInlineFragmentResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -157,6 +156,7 @@ func (v *SimpleInlineFragmentResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal SimpleInlineFragmentResponse.RandomItem: %w", err)
}
}
return nil
}
@@ -0,0 +1,334 @@
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"
)
// SimpleNamedFragmentRandomItemArticle includes the requested fields of the GraphQL type Article.
type SimpleNamedFragmentRandomItemArticle struct {
Typename string `json:"__typename"`
// ID is the identifier of the content.
Id testutil.ID `json:"id"`
Name string `json:"name"`
}
// SimpleNamedFragmentRandomItemContent includes the requested fields of the GraphQL interface Content.
//
// SimpleNamedFragmentRandomItemContent is implemented by the following types:
// SimpleNamedFragmentRandomItemArticle
// SimpleNamedFragmentRandomItemVideo
// SimpleNamedFragmentRandomItemTopic
//
// The GraphQL type's documentation follows.
//
// Content is implemented by various types like Article, Video, and Topic.
type SimpleNamedFragmentRandomItemContent interface {
implementsGraphQLInterfaceSimpleNamedFragmentRandomItemContent()
// GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values).
GetTypename() string
// GetId returns the interface-field "id" from its implementation.
// The GraphQL interface field's documentation follows.
//
// ID is the identifier of the content.
GetId() testutil.ID
// GetName returns the interface-field "name" from its implementation.
GetName() string
}
func (v *SimpleNamedFragmentRandomItemArticle) implementsGraphQLInterfaceSimpleNamedFragmentRandomItemContent() {
}
// GetTypename is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemArticle) GetTypename() string { return v.Typename }
// GetId is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemArticle) GetId() testutil.ID { return v.Id }
// GetName is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemArticle) GetName() string { return v.Name }
func (v *SimpleNamedFragmentRandomItemVideo) implementsGraphQLInterfaceSimpleNamedFragmentRandomItemContent() {
}
// GetTypename is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemVideo) GetTypename() string { return v.Typename }
// GetId is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemVideo) GetId() testutil.ID { return v.Id }
// GetName is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemVideo) GetName() string { return v.Name }
func (v *SimpleNamedFragmentRandomItemTopic) implementsGraphQLInterfaceSimpleNamedFragmentRandomItemContent() {
}
// GetTypename is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemTopic) GetTypename() string { return v.Typename }
// GetId is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemTopic) GetId() testutil.ID { return v.Id }
// GetName is a part of, and documented with, the interface SimpleNamedFragmentRandomItemContent.
func (v *SimpleNamedFragmentRandomItemTopic) GetName() string { return v.Name }
func __unmarshalSimpleNamedFragmentRandomItemContent(v *SimpleNamedFragmentRandomItemContent, 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(SimpleNamedFragmentRandomItemArticle)
return json.Unmarshal(m, *v)
case "Video":
*v = new(SimpleNamedFragmentRandomItemVideo)
return json.Unmarshal(m, *v)
case "Topic":
*v = new(SimpleNamedFragmentRandomItemTopic)
return json.Unmarshal(m, *v)
case "":
return fmt.Errorf(
"Response was missing Content.__typename")
default:
return fmt.Errorf(
`Unexpected concrete type for SimpleNamedFragmentRandomItemContent: "%v"`, tn.TypeName)
}
}
// SimpleNamedFragmentRandomItemTopic includes the requested fields of the GraphQL type Topic.
type SimpleNamedFragmentRandomItemTopic struct {
Typename string `json:"__typename"`
// ID is the identifier of the content.
Id testutil.ID `json:"id"`
Name string `json:"name"`
}
// SimpleNamedFragmentRandomItemVideo includes the requested fields of the GraphQL type Video.
type SimpleNamedFragmentRandomItemVideo struct {
Typename string `json:"__typename"`
// ID is the identifier of the content.
Id testutil.ID `json:"id"`
Name string `json:"name"`
VideoFields `json:"-"`
}
func (v *SimpleNamedFragmentRandomItemVideo) UnmarshalJSON(b []byte) error {
var firstPass struct {
*SimpleNamedFragmentRandomItemVideo
graphql.NoUnmarshalJSON
}
firstPass.SimpleNamedFragmentRandomItemVideo = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.VideoFields)
if err != nil {
return err
}
return nil
}
// SimpleNamedFragmentRandomLeafArticle includes the requested fields of the GraphQL type Article.
type SimpleNamedFragmentRandomLeafArticle struct {
Typename string `json:"__typename"`
}
// SimpleNamedFragmentRandomLeafLeafContent includes the requested fields of the GraphQL interface LeafContent.
//
// SimpleNamedFragmentRandomLeafLeafContent is implemented by the following types:
// SimpleNamedFragmentRandomLeafArticle
// SimpleNamedFragmentRandomLeafVideo
//
// The GraphQL type's documentation follows.
//
// LeafContent represents content items that can't have child-nodes.
type SimpleNamedFragmentRandomLeafLeafContent interface {
implementsGraphQLInterfaceSimpleNamedFragmentRandomLeafLeafContent()
// GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values).
GetTypename() string
}
func (v *SimpleNamedFragmentRandomLeafArticle) implementsGraphQLInterfaceSimpleNamedFragmentRandomLeafLeafContent() {
}
// GetTypename is a part of, and documented with, the interface SimpleNamedFragmentRandomLeafLeafContent.
func (v *SimpleNamedFragmentRandomLeafArticle) GetTypename() string { return v.Typename }
func (v *SimpleNamedFragmentRandomLeafVideo) implementsGraphQLInterfaceSimpleNamedFragmentRandomLeafLeafContent() {
}
// GetTypename is a part of, and documented with, the interface SimpleNamedFragmentRandomLeafLeafContent.
func (v *SimpleNamedFragmentRandomLeafVideo) GetTypename() string { return v.Typename }
func __unmarshalSimpleNamedFragmentRandomLeafLeafContent(v *SimpleNamedFragmentRandomLeafLeafContent, 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(SimpleNamedFragmentRandomLeafArticle)
return json.Unmarshal(m, *v)
case "Video":
*v = new(SimpleNamedFragmentRandomLeafVideo)
return json.Unmarshal(m, *v)
case "":
return fmt.Errorf(
"Response was missing LeafContent.__typename")
default:
return fmt.Errorf(
`Unexpected concrete type for SimpleNamedFragmentRandomLeafLeafContent: "%v"`, tn.TypeName)
}
}
// SimpleNamedFragmentRandomLeafVideo includes the requested fields of the GraphQL type Video.
type SimpleNamedFragmentRandomLeafVideo struct {
Typename string `json:"__typename"`
VideoFields `json:"-"`
}
func (v *SimpleNamedFragmentRandomLeafVideo) UnmarshalJSON(b []byte) error {
var firstPass struct {
*SimpleNamedFragmentRandomLeafVideo
graphql.NoUnmarshalJSON
}
firstPass.SimpleNamedFragmentRandomLeafVideo = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
err = json.Unmarshal(b, &v.VideoFields)
if err != nil {
return err
}
return nil
}
// SimpleNamedFragmentResponse is returned by SimpleNamedFragment on success.
type SimpleNamedFragmentResponse struct {
RandomItem SimpleNamedFragmentRandomItemContent `json:"-"`
RandomLeaf SimpleNamedFragmentRandomLeafLeafContent `json:"-"`
}
func (v *SimpleNamedFragmentResponse) UnmarshalJSON(b []byte) error {
var firstPass struct {
*SimpleNamedFragmentResponse
RandomItem json.RawMessage `json:"randomItem"`
RandomLeaf json.RawMessage `json:"randomLeaf"`
graphql.NoUnmarshalJSON
}
firstPass.SimpleNamedFragmentResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
return err
}
{
target := &v.RandomItem
raw := firstPass.RandomItem
err = __unmarshalSimpleNamedFragmentRandomItemContent(
target, raw)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal SimpleNamedFragmentResponse.RandomItem: %w", err)
}
}
{
target := &v.RandomLeaf
raw := firstPass.RandomLeaf
err = __unmarshalSimpleNamedFragmentRandomLeafLeafContent(
target, raw)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal SimpleNamedFragmentResponse.RandomLeaf: %w", err)
}
}
return nil
}
// VideoFields includes the GraphQL fields of Video requested by the fragment VideoFields.
type VideoFields struct {
// ID is documented in the Content interface.
Id testutil.ID `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
Duration int `json:"duration"`
Thumbnail VideoFieldsThumbnail `json:"thumbnail"`
}
// VideoFieldsThumbnail includes the requested fields of the GraphQL type Thumbnail.
type VideoFieldsThumbnail struct {
Id testutil.ID `json:"id"`
}
func SimpleNamedFragment(
client graphql.Client,
) (*SimpleNamedFragmentResponse, error) {
var err error
var retval SimpleNamedFragmentResponse
err = client.MakeRequest(
nil,
"SimpleNamedFragment",
`
query SimpleNamedFragment {
randomItem {
__typename
id
name
... VideoFields
}
randomLeaf {
__typename
... VideoFields
}
}
fragment VideoFields on Video {
id
name
url
duration
thumbnail {
id
}
}
`,
&retval,
nil,
)
return &retval, err
}
@@ -0,0 +1,9 @@
{
"operations": [
{
"operationName": "SimpleNamedFragment",
"query": "\nquery SimpleNamedFragment {\n\trandomItem {\n\t\t__typename\n\t\tid\n\t\tname\n\t\t... VideoFields\n\t}\n\trandomLeaf {\n\t\t__typename\n\t\t... VideoFields\n\t}\n}\nfragment VideoFields on Video {\n\tid\n\tname\n\turl\n\tduration\n\tthumbnail {\n\t\tid\n\t}\n}\n",
"sourceLocation": "testdata/queries/SimpleNamedFragment.graphql"
}
]
}
@@ -82,13 +82,12 @@ type UnionNoFragmentsQueryResponse struct {
func (v *UnionNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
type UnionNoFragmentsQueryResponseWrapper UnionNoFragmentsQueryResponse
var firstPass struct {
*UnionNoFragmentsQueryResponseWrapper
*UnionNoFragmentsQueryResponse
RandomLeaf json.RawMessage `json:"randomLeaf"`
graphql.NoUnmarshalJSON
}
firstPass.UnionNoFragmentsQueryResponseWrapper = (*UnionNoFragmentsQueryResponseWrapper)(v)
firstPass.UnionNoFragmentsQueryResponse = v
err := json.Unmarshal(b, &firstPass)
if err != nil {
@@ -105,6 +104,7 @@ func (v *UnionNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error {
"Unable to unmarshal UnionNoFragmentsQueryResponse.RandomLeaf: %w", err)
}
}
return nil
}