Add a new option to treat an interface like an object (#97)

## Summary:
The basic idea here is if you only request interface fields (no
fragments) you may not care about the concrete type, and so we could
just generate a struct as if it were an object.  I don't think it's a
good idea to do that by default, because then if you later add a
fragment all your code totally changes, but it's quite reasonable as an
option!

Most of the code involved is just wiring and validation; the
core implementation is literally just: treat it like an object.

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

## Test plan:
make check


Author: benjaminjkraft

Reviewers: csilvers, StevenACoffman, benjaminjkraft, aberkan, dnerdy, jvoll, mahtabsabet, MiguelCastillo

Required Reviewers: 

Approved By: StevenACoffman

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

Pull Request URL: https://github.com/Khan/genqlient/pull/97
This commit is contained in:
Ben Kraft
2021-09-15 18:00:22 -07:00
committed by GitHub
parent 463cffdede
commit 5211442843
14 changed files with 477 additions and 9 deletions
+9 -2
View File
@@ -175,7 +175,14 @@ func (g *generator) convertDefinition(
GraphQLName: def.Name,
}
switch def.Kind {
// The struct option basically means "treat this as if it were an object".
// (It only applies if valid; this is important if you said the whole
// query should have `struct: true`.)
kind := def.Kind
if options.GetStruct() && validateStructOption(def, selectionSet, pos) == nil {
kind = ast.Object
}
switch kind {
case ast.Object:
name := makeTypeName(namePrefix, def.Name)
@@ -463,7 +470,7 @@ func (g *generator) convertInlineFragment(
containingTypedef *ast.Definition,
queryOptions *genqlientDirective,
) ([]*goStructField, error) {
// You might think fragmentTypedef would be a fragment.ObjectDefinition, but
// You might think fragmentTypedef is just fragment.ObjectDefinition, but
// actually that's the type into which the fragment is spread.
fragmentTypedef := g.schema.Types[fragment.TypeCondition]
if !fragmentMatches(containingTypedef, fragmentTypedef) {