Add support for inline fragments (#65)
## Summary:
In this commit I add support for inline fragments
(`... on MyType { fields }`) to genqlient. This will make interfaces a
lot more useful! In future commits I'll add named fragments, for which
we'll generate slightly different types, as discussed in DESIGN.md.
In general, implementing the flattening approach described in DESIGN.md
was... surprisingly easy. All we have to do is recurse on applicable
fragments when generating our selection-set. The refactor to
selection-set handling this encouraged was, I think, quite beneficial.
It did reveal two tricky pre-existing issues.
One issue is that GraphQL allows for duplicate selections, as long as
they match. (In practice, this is only useful in the context of
fragments, although GraphQL allows it even without.) I decided to handle
the simple case (duplicate leaf fields; we just deduplicate) but leave
to the future the complex cases where we need to merge different
sub-selections (now #64). For now we just forbid that; we can see how
much it comes up.
The other issue is that we are generating type-names incorrectly for
interface types; I had intended to do `MyInterfaceMyFieldMyType` for
shared fields and `MyImplMyFieldMyType` for non-shared ones, but instead
I did `MyFieldMyType`, which is inconsistent already and can result in
conflicts in the presence of fragments. I'm going to fix this in a
separate commit, though, because it's going to require some refactoring
and is irrelevant to the main logic of this commit; I left some TODOs in
the tests related to this.
Issue: https://github.com/Khan/genqlient/issues/8
## Test plan:
make check
Author: benjaminjkraft
Reviewers: dnerdy, aberkan, 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/65
This commit is contained in:
@@ -43,20 +43,31 @@ type DirectiveRoot struct {
|
||||
|
||||
type ComplexityRoot struct {
|
||||
Animal struct {
|
||||
Hair func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
Name func(childComplexity int) int
|
||||
Owner func(childComplexity int) int
|
||||
Species func(childComplexity int) int
|
||||
}
|
||||
|
||||
BeingsHair struct {
|
||||
HasHair func(childComplexity int) int
|
||||
}
|
||||
|
||||
Hair struct {
|
||||
Color func(childComplexity int) int
|
||||
}
|
||||
|
||||
Query struct {
|
||||
Being func(childComplexity int, id string) int
|
||||
Beings func(childComplexity int, ids []string) int
|
||||
Me func(childComplexity int) int
|
||||
User func(childComplexity int, id string) int
|
||||
Being func(childComplexity int, id string) int
|
||||
Beings func(childComplexity int, ids []string) int
|
||||
LotteryWinner func(childComplexity int, number int) int
|
||||
Me func(childComplexity int) int
|
||||
User func(childComplexity int, id string) int
|
||||
}
|
||||
|
||||
User struct {
|
||||
Hair func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
LuckyNumber func(childComplexity int) int
|
||||
Name func(childComplexity int) int
|
||||
@@ -68,6 +79,7 @@ type QueryResolver interface {
|
||||
User(ctx context.Context, id string) (*User, error)
|
||||
Being(ctx context.Context, id string) (Being, error)
|
||||
Beings(ctx context.Context, ids []string) ([]Being, error)
|
||||
LotteryWinner(ctx context.Context, number int) (Lucky, error)
|
||||
}
|
||||
|
||||
type executableSchema struct {
|
||||
@@ -85,6 +97,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
_ = ec
|
||||
switch typeName + "." + field {
|
||||
|
||||
case "Animal.hair":
|
||||
if e.complexity.Animal.Hair == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Animal.Hair(childComplexity), true
|
||||
|
||||
case "Animal.id":
|
||||
if e.complexity.Animal.ID == nil {
|
||||
break
|
||||
@@ -113,6 +132,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Animal.Species(childComplexity), true
|
||||
|
||||
case "BeingsHair.hasHair":
|
||||
if e.complexity.BeingsHair.HasHair == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.BeingsHair.HasHair(childComplexity), true
|
||||
|
||||
case "Hair.color":
|
||||
if e.complexity.Hair.Color == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Hair.Color(childComplexity), true
|
||||
|
||||
case "Query.being":
|
||||
if e.complexity.Query.Being == nil {
|
||||
break
|
||||
@@ -137,6 +170,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Query.Beings(childComplexity, args["ids"].([]string)), true
|
||||
|
||||
case "Query.lotteryWinner":
|
||||
if e.complexity.Query.LotteryWinner == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_lotteryWinner_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.LotteryWinner(childComplexity, args["number"].(int)), true
|
||||
|
||||
case "Query.me":
|
||||
if e.complexity.Query.Me == nil {
|
||||
break
|
||||
@@ -156,6 +201,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Query.User(childComplexity, args["id"].(string)), true
|
||||
|
||||
case "User.hair":
|
||||
if e.complexity.User.Hair == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.User.Hair(childComplexity), true
|
||||
|
||||
case "User.id":
|
||||
if e.complexity.User.ID == nil {
|
||||
break
|
||||
@@ -232,21 +284,28 @@ var sources = []*ast.Source{
|
||||
user(id: ID!): User
|
||||
being(id: ID!): Being
|
||||
beings(ids: [ID!]!): [Being]!
|
||||
lotteryWinner(number: Int!): Lucky
|
||||
}
|
||||
|
||||
type User implements Being {
|
||||
type User implements Being & Lucky {
|
||||
id: ID!
|
||||
name: String!
|
||||
luckyNumber: Int
|
||||
hair: Hair
|
||||
}
|
||||
|
||||
type Hair { color: String } # silly name to confuse the name-generator
|
||||
|
||||
type Animal implements Being {
|
||||
id: ID!
|
||||
name: String!
|
||||
species: Species!
|
||||
owner: Being
|
||||
hair: BeingsHair
|
||||
}
|
||||
|
||||
type BeingsHair { hasHair: Boolean! } # silly name to confuse the name-generator
|
||||
|
||||
enum Species {
|
||||
DOG
|
||||
COELACANTH
|
||||
@@ -256,6 +315,10 @@ interface Being {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
interface Lucky {
|
||||
luckyNumber: Int
|
||||
}
|
||||
`, BuiltIn: false},
|
||||
}
|
||||
var parsedSchema = gqlparser.MustLoadSchema(sources...)
|
||||
@@ -309,6 +372,21 @@ func (ec *executionContext) field_Query_beings_args(ctx context.Context, rawArgs
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_lotteryWinner_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 int
|
||||
if tmp, ok := rawArgs["number"]; ok {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("number"))
|
||||
arg0, err = ec.unmarshalNInt2int(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["number"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
@@ -499,6 +577,105 @@ func (ec *executionContext) _Animal_owner(ctx context.Context, field graphql.Col
|
||||
return ec.marshalOBeing2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeing(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Animal_hair(ctx context.Context, field graphql.CollectedField, obj *Animal) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Animal",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Hair, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*BeingsHair)
|
||||
fc.Result = res
|
||||
return ec.marshalOBeingsHair2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeingsHair(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _BeingsHair_hasHair(ctx context.Context, field graphql.CollectedField, obj *BeingsHair) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "BeingsHair",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.HasHair, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Hair_color(ctx context.Context, field graphql.CollectedField, obj *Hair) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Hair",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Color, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_me(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -651,6 +828,45 @@ func (ec *executionContext) _Query_beings(ctx context.Context, field graphql.Col
|
||||
return ec.marshalNBeing2ᚕgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeing(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_lotteryWinner(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Query",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Query_lotteryWinner_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
fc.Args = args
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().LotteryWinner(rctx, args["number"].(int))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(Lucky)
|
||||
fc.Result = res
|
||||
return ec.marshalOLucky2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐLucky(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -824,6 +1040,38 @@ func (ec *executionContext) _User_luckyNumber(ctx context.Context, field graphql
|
||||
return ec.marshalOInt2ᚖint(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _User_hair(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "User",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Hair, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*Hair)
|
||||
fc.Result = res
|
||||
return ec.marshalOHair2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐHair(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -1938,6 +2186,22 @@ func (ec *executionContext) _Being(ctx context.Context, sel ast.SelectionSet, ob
|
||||
}
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Lucky(ctx context.Context, sel ast.SelectionSet, obj Lucky) graphql.Marshaler {
|
||||
switch obj := (obj).(type) {
|
||||
case nil:
|
||||
return graphql.Null
|
||||
case User:
|
||||
return ec._User(ctx, sel, &obj)
|
||||
case *User:
|
||||
if obj == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._User(ctx, sel, obj)
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected type %T", obj))
|
||||
}
|
||||
}
|
||||
|
||||
// endregion ************************** interface.gotpl ***************************
|
||||
|
||||
// region **************************** object.gotpl ****************************
|
||||
@@ -1970,6 +2234,59 @@ func (ec *executionContext) _Animal(ctx context.Context, sel ast.SelectionSet, o
|
||||
}
|
||||
case "owner":
|
||||
out.Values[i] = ec._Animal_owner(ctx, field, obj)
|
||||
case "hair":
|
||||
out.Values[i] = ec._Animal_hair(ctx, field, obj)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var beingsHairImplementors = []string{"BeingsHair"}
|
||||
|
||||
func (ec *executionContext) _BeingsHair(ctx context.Context, sel ast.SelectionSet, obj *BeingsHair) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, beingsHairImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("BeingsHair")
|
||||
case "hasHair":
|
||||
out.Values[i] = ec._BeingsHair_hasHair(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var hairImplementors = []string{"Hair"}
|
||||
|
||||
func (ec *executionContext) _Hair(ctx context.Context, sel ast.SelectionSet, obj *Hair) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, hairImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("Hair")
|
||||
case "color":
|
||||
out.Values[i] = ec._Hair_color(ctx, field, obj)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -2043,6 +2360,17 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "lotteryWinner":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_lotteryWinner(ctx, field)
|
||||
return res
|
||||
})
|
||||
case "__type":
|
||||
out.Values[i] = ec._Query___type(ctx, field)
|
||||
case "__schema":
|
||||
@@ -2058,7 +2386,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
return out
|
||||
}
|
||||
|
||||
var userImplementors = []string{"User", "Being"}
|
||||
var userImplementors = []string{"User", "Being", "Lucky"}
|
||||
|
||||
func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, userImplementors)
|
||||
@@ -2081,6 +2409,8 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
|
||||
}
|
||||
case "luckyNumber":
|
||||
out.Values[i] = ec._User_luckyNumber(ctx, field, obj)
|
||||
case "hair":
|
||||
out.Values[i] = ec._User_hair(ctx, field, obj)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -2434,6 +2764,21 @@ func (ec *executionContext) marshalNID2ᚕstringᚄ(ctx context.Context, sel ast
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {
|
||||
res, err := graphql.UnmarshalInt(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {
|
||||
res := graphql.MarshalInt(v)
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNSpecies2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐSpecies(ctx context.Context, v interface{}) (Species, error) {
|
||||
var res Species
|
||||
err := res.UnmarshalGQL(v)
|
||||
@@ -2695,6 +3040,13 @@ func (ec *executionContext) marshalOBeing2githubᚗcomᚋKhanᚋgenqlientᚋinte
|
||||
return ec._Being(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOBeingsHair2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeingsHair(ctx context.Context, sel ast.SelectionSet, v *BeingsHair) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._BeingsHair(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) {
|
||||
res, err := graphql.UnmarshalBoolean(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
@@ -2719,6 +3071,13 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast
|
||||
return graphql.MarshalBoolean(*v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOHair2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐHair(ctx context.Context, sel ast.SelectionSet, v *Hair) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._Hair(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v interface{}) (*int, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
@@ -2734,6 +3093,13 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele
|
||||
return graphql.MarshalInt(*v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOLucky2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐLucky(ctx context.Context, sel ast.SelectionSet, v Lucky) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._Lucky(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {
|
||||
res, err := graphql.UnmarshalString(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
|
||||
@@ -12,22 +12,37 @@ type Being interface {
|
||||
IsBeing()
|
||||
}
|
||||
|
||||
type Lucky interface {
|
||||
IsLucky()
|
||||
}
|
||||
|
||||
type Animal struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Species Species `json:"species"`
|
||||
Owner Being `json:"owner"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Species Species `json:"species"`
|
||||
Owner Being `json:"owner"`
|
||||
Hair *BeingsHair `json:"hair"`
|
||||
}
|
||||
|
||||
func (Animal) IsBeing() {}
|
||||
|
||||
type BeingsHair struct {
|
||||
HasHair bool `json:"hasHair"`
|
||||
}
|
||||
|
||||
type Hair struct {
|
||||
Color *string `json:"color"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LuckyNumber *int `json:"luckyNumber"`
|
||||
Hair *Hair `json:"hair"`
|
||||
}
|
||||
|
||||
func (User) IsBeing() {}
|
||||
func (User) IsLucky() {}
|
||||
|
||||
type Species string
|
||||
|
||||
|
||||
@@ -8,16 +8,26 @@ import (
|
||||
"github.com/99designs/gqlgen/graphql/handler/transport"
|
||||
)
|
||||
|
||||
func intptr(v int) *int { return &v }
|
||||
func strptr(v string) *string { return &v }
|
||||
func intptr(v int) *int { return &v }
|
||||
|
||||
var users = []*User{
|
||||
{ID: "1", Name: "Yours Truly", LuckyNumber: intptr(17)},
|
||||
{ID: "2", Name: "Raven", LuckyNumber: intptr(-1)},
|
||||
{
|
||||
ID: "1", Name: "Yours Truly", LuckyNumber: intptr(17),
|
||||
Hair: &Hair{Color: strptr("Black")},
|
||||
},
|
||||
{ID: "2", Name: "Raven", LuckyNumber: intptr(-1), Hair: nil},
|
||||
}
|
||||
|
||||
var animals = []*Animal{
|
||||
{ID: "3", Name: "Fido", Species: SpeciesDog, Owner: userByID("0")},
|
||||
{ID: "4", Name: "Old One", Species: SpeciesCoelacanth, Owner: nil},
|
||||
{
|
||||
ID: "3", Name: "Fido", Species: SpeciesDog, Owner: userByID("1"),
|
||||
Hair: &BeingsHair{HasHair: true},
|
||||
},
|
||||
{
|
||||
ID: "4", Name: "Old One", Species: SpeciesCoelacanth, Owner: nil,
|
||||
Hair: &BeingsHair{HasHair: false},
|
||||
},
|
||||
}
|
||||
|
||||
func userByID(id string) *User {
|
||||
@@ -63,6 +73,15 @@ func (r *queryResolver) Beings(ctx context.Context, ids []string) ([]Being, erro
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) LotteryWinner(ctx context.Context, number int) (Lucky, error) {
|
||||
for _, user := range users {
|
||||
if user.LuckyNumber != nil && *user.LuckyNumber == number {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func RunServer() *httptest.Server {
|
||||
gqlgenServer := handler.New(NewExecutableSchema(Config{Resolvers: &resolver{}}))
|
||||
gqlgenServer.AddTransport(transport.POST{})
|
||||
|
||||
Reference in New Issue
Block a user