Add support for interfaces, part 2: list-of-interface (#54)
## Summary: In this commit I remove one of the limitations of our support for interfaces, from #52, by adding support for list-of-interface fields. This was surprisingly complex! The issue is that, as before, it's the containing type that has to do all the glue work -- and it's that glue work that is complicated by list-of-interface fields. All in all, it's not that much new code, and by far the hard part is just 20 lines in the UnmarshalJSON template (which come with almost twice as many lines of comments to explain them). It may be easiest to start by reading some of the generated code, and then read the template. I also added support for such fields with `pointer: true` specified, such that the type is `[][]...[]*MyInterface`, although I don't know why you would want that. This does *not* allow e.g. `*[]*[][]*MyInterface`; that would require a way to specify it (see #16) but also add some extra complexity (as we'd have to actually walk the type-unwrap chain properly, instead of just counting the number of slices and whether there's a pointer). Issue: https://github.com/Khan/genqlient/issues/8 ## Test plan: make check 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, ⌛ Lint, ⌛ Test (1.17), ⌛ Test (1.16), ⌛ Test (1.15), ⌛ Test (1.14), ⌛ Test (1.13) Pull request URL: https://github.com/Khan/genqlient/pull/54
This commit is contained in:
@@ -10,6 +10,183 @@ import (
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
)
|
||||
|
||||
// queryWithInterfaceListFieldBeingsAnimal includes the requested fields of the GraphQL type Animal.
|
||||
type queryWithInterfaceListFieldBeingsAnimal struct {
|
||||
Typename string `json:"__typename"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// queryWithInterfaceListFieldBeingsBeing includes the requested fields of the GraphQL type Being.
|
||||
type queryWithInterfaceListFieldBeingsBeing interface {
|
||||
implementsGraphQLInterfacequeryWithInterfaceListFieldBeingsBeing()
|
||||
}
|
||||
|
||||
func (v *queryWithInterfaceListFieldBeingsUser) implementsGraphQLInterfacequeryWithInterfaceListFieldBeingsBeing() {
|
||||
}
|
||||
func (v *queryWithInterfaceListFieldBeingsAnimal) implementsGraphQLInterfacequeryWithInterfaceListFieldBeingsBeing() {
|
||||
}
|
||||
|
||||
func __unmarshalqueryWithInterfaceListFieldBeingsBeing(v *queryWithInterfaceListFieldBeingsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithInterfaceListFieldBeingsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithInterfaceListFieldBeingsAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for queryWithInterfaceListFieldBeingsBeing: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// queryWithInterfaceListFieldBeingsUser includes the requested fields of the GraphQL type User.
|
||||
type queryWithInterfaceListFieldBeingsUser struct {
|
||||
Typename string `json:"__typename"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// queryWithInterfaceListFieldResponse is returned by queryWithInterfaceListField on success.
|
||||
type queryWithInterfaceListFieldResponse struct {
|
||||
Beings []queryWithInterfaceListFieldBeingsBeing `json:"-"`
|
||||
}
|
||||
|
||||
func (v *queryWithInterfaceListFieldResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type queryWithInterfaceListFieldResponseWrapper queryWithInterfaceListFieldResponse
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithInterfaceListFieldResponseWrapper
|
||||
Beings []json.RawMessage `json:"beings"`
|
||||
}
|
||||
firstPass.queryWithInterfaceListFieldResponseWrapper = (*queryWithInterfaceListFieldResponseWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Beings
|
||||
raw := firstPass.Beings
|
||||
*target = make(
|
||||
[]queryWithInterfaceListFieldBeingsBeing,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
err = __unmarshalqueryWithInterfaceListFieldBeingsBeing(
|
||||
target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryWithInterfaceListPointerFieldBeingsAnimal includes the requested fields of the GraphQL type Animal.
|
||||
type queryWithInterfaceListPointerFieldBeingsAnimal struct {
|
||||
Typename string `json:"__typename"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// queryWithInterfaceListPointerFieldBeingsBeing includes the requested fields of the GraphQL type Being.
|
||||
type queryWithInterfaceListPointerFieldBeingsBeing interface {
|
||||
implementsGraphQLInterfacequeryWithInterfaceListPointerFieldBeingsBeing()
|
||||
}
|
||||
|
||||
func (v *queryWithInterfaceListPointerFieldBeingsUser) implementsGraphQLInterfacequeryWithInterfaceListPointerFieldBeingsBeing() {
|
||||
}
|
||||
func (v *queryWithInterfaceListPointerFieldBeingsAnimal) implementsGraphQLInterfacequeryWithInterfaceListPointerFieldBeingsBeing() {
|
||||
}
|
||||
|
||||
func __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing(v *queryWithInterfaceListPointerFieldBeingsBeing, m json.RawMessage) error {
|
||||
if string(m) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var tn struct {
|
||||
TypeName string `json:"__typename"`
|
||||
}
|
||||
err := json.Unmarshal(m, &tn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tn.TypeName {
|
||||
case "User":
|
||||
*v = new(queryWithInterfaceListPointerFieldBeingsUser)
|
||||
return json.Unmarshal(m, *v)
|
||||
case "Animal":
|
||||
*v = new(queryWithInterfaceListPointerFieldBeingsAnimal)
|
||||
return json.Unmarshal(m, *v)
|
||||
default:
|
||||
return fmt.Errorf(
|
||||
`Unexpected concrete type for queryWithInterfaceListPointerFieldBeingsBeing: "%v"`, tn.TypeName)
|
||||
}
|
||||
}
|
||||
|
||||
// queryWithInterfaceListPointerFieldBeingsUser includes the requested fields of the GraphQL type User.
|
||||
type queryWithInterfaceListPointerFieldBeingsUser struct {
|
||||
Typename string `json:"__typename"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// queryWithInterfaceListPointerFieldResponse is returned by queryWithInterfaceListPointerField on success.
|
||||
type queryWithInterfaceListPointerFieldResponse struct {
|
||||
Beings []*queryWithInterfaceListPointerFieldBeingsBeing `json:"-"`
|
||||
}
|
||||
|
||||
func (v *queryWithInterfaceListPointerFieldResponse) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type queryWithInterfaceListPointerFieldResponseWrapper queryWithInterfaceListPointerFieldResponse
|
||||
|
||||
var firstPass struct {
|
||||
*queryWithInterfaceListPointerFieldResponseWrapper
|
||||
Beings []json.RawMessage `json:"beings"`
|
||||
}
|
||||
firstPass.queryWithInterfaceListPointerFieldResponseWrapper = (*queryWithInterfaceListPointerFieldResponseWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Beings
|
||||
raw := firstPass.Beings
|
||||
*target = make(
|
||||
[]*queryWithInterfaceListPointerFieldBeingsBeing,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
*target = new(queryWithInterfaceListPointerFieldBeingsBeing)
|
||||
err = __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing(
|
||||
*target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryWithInterfaceNoFragmentsBeing includes the requested fields of the GraphQL type Being.
|
||||
type queryWithInterfaceNoFragmentsBeing interface {
|
||||
implementsGraphQLInterfacequeryWithInterfaceNoFragmentsBeing()
|
||||
@@ -87,12 +264,15 @@ func (v *queryWithInterfaceNoFragmentsResponse) UnmarshalJSON(b []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = __unmarshalqueryWithInterfaceNoFragmentsBeing(
|
||||
&v.Being, firstPass.Being)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
target := &v.Being
|
||||
raw := firstPass.Being
|
||||
err = __unmarshalqueryWithInterfaceNoFragmentsBeing(
|
||||
target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -202,3 +382,59 @@ query queryWithInterfaceNoFragments ($id: ID!) {
|
||||
)
|
||||
return &retval, err
|
||||
}
|
||||
|
||||
func queryWithInterfaceListField(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
ids []string,
|
||||
) (*queryWithInterfaceListFieldResponse, error) {
|
||||
variables := map[string]interface{}{
|
||||
"ids": ids,
|
||||
}
|
||||
|
||||
var retval queryWithInterfaceListFieldResponse
|
||||
err := client.MakeRequest(
|
||||
ctx,
|
||||
"queryWithInterfaceListField",
|
||||
`
|
||||
query queryWithInterfaceListField ($ids: [ID!]!) {
|
||||
beings(ids: $ids) {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
&retval,
|
||||
variables,
|
||||
)
|
||||
return &retval, err
|
||||
}
|
||||
|
||||
func queryWithInterfaceListPointerField(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
ids []string,
|
||||
) (*queryWithInterfaceListPointerFieldResponse, error) {
|
||||
variables := map[string]interface{}{
|
||||
"ids": ids,
|
||||
}
|
||||
|
||||
var retval queryWithInterfaceListPointerFieldResponse
|
||||
err := client.MakeRequest(
|
||||
ctx,
|
||||
"queryWithInterfaceListPointerField",
|
||||
`
|
||||
query queryWithInterfaceListPointerField ($ids: [ID!]!) {
|
||||
beings(ids: $ids) {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
&retval,
|
||||
variables,
|
||||
)
|
||||
return &retval, err
|
||||
}
|
||||
|
||||
@@ -99,6 +99,69 @@ func TestInterfaceNoFragments(t *testing.T) {
|
||||
assert.Nil(t, resp.Being)
|
||||
}
|
||||
|
||||
func TestInterfaceListField(t *testing.T) {
|
||||
_ = `# @genqlient
|
||||
query queryWithInterfaceListField($ids: [ID!]!) {
|
||||
beings(ids: $ids) { __typename id name }
|
||||
}`
|
||||
|
||||
ctx := context.Background()
|
||||
server := server.RunServer()
|
||||
defer server.Close()
|
||||
client := graphql.NewClient(server.URL, http.DefaultClient)
|
||||
|
||||
resp, err := queryWithInterfaceListField(ctx, client,
|
||||
[]string{"1", "3", "12847394823"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, resp.Beings, 3)
|
||||
|
||||
user, ok := resp.Beings[0].(*queryWithInterfaceListFieldBeingsUser)
|
||||
require.Truef(t, ok, "got %T, not User", resp.Beings[0])
|
||||
assert.Equal(t, "1", user.Id)
|
||||
assert.Equal(t, "Yours Truly", user.Name)
|
||||
|
||||
animal, ok := resp.Beings[1].(*queryWithInterfaceListFieldBeingsAnimal)
|
||||
require.Truef(t, ok, "got %T, not Animal", resp.Beings[1])
|
||||
assert.Equal(t, "3", animal.Id)
|
||||
assert.Equal(t, "Fido", animal.Name)
|
||||
|
||||
assert.Nil(t, resp.Beings[2])
|
||||
}
|
||||
|
||||
func TestInterfaceListPointerField(t *testing.T) {
|
||||
_ = `# @genqlient
|
||||
query queryWithInterfaceListPointerField($ids: [ID!]!) {
|
||||
# @genqlient(pointer: true)
|
||||
beings(ids: $ids) {
|
||||
__typename id name
|
||||
}
|
||||
}`
|
||||
|
||||
ctx := context.Background()
|
||||
server := server.RunServer()
|
||||
defer server.Close()
|
||||
client := graphql.NewClient(server.URL, http.DefaultClient)
|
||||
|
||||
resp, err := queryWithInterfaceListPointerField(ctx, client,
|
||||
[]string{"1", "3", "12847394823"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, resp.Beings, 3)
|
||||
|
||||
user, ok := (*resp.Beings[0]).(*queryWithInterfaceListPointerFieldBeingsUser)
|
||||
require.Truef(t, ok, "got %T, not User", resp.Beings[0])
|
||||
assert.Equal(t, "1", user.Id)
|
||||
assert.Equal(t, "Yours Truly", user.Name)
|
||||
|
||||
animal, ok := (*resp.Beings[1]).(*queryWithInterfaceListPointerFieldBeingsAnimal)
|
||||
require.Truef(t, ok, "got %T, not Animal", resp.Beings[1])
|
||||
assert.Equal(t, "3", animal.Id)
|
||||
assert.Equal(t, "Fido", animal.Name)
|
||||
|
||||
assert.Nil(t, *resp.Beings[2])
|
||||
}
|
||||
|
||||
func TestGeneratedCode(t *testing.T) {
|
||||
// TODO(benkraft): Check that gqlgen is up to date too. In practice that's
|
||||
// less likely to be a problem, since it should only change if you update
|
||||
|
||||
@@ -2,6 +2,7 @@ type Query {
|
||||
me: User
|
||||
user(id: ID!): User
|
||||
being(id: ID!): Being
|
||||
beings(ids: [ID!]!): [Being]!
|
||||
}
|
||||
|
||||
type User implements Being {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/99designs/gqlgen/graphql/introspection"
|
||||
@@ -49,9 +50,10 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Query struct {
|
||||
Being func(childComplexity int, id 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
|
||||
Me func(childComplexity int) int
|
||||
User func(childComplexity int, id string) int
|
||||
}
|
||||
|
||||
User struct {
|
||||
@@ -65,6 +67,7 @@ type QueryResolver interface {
|
||||
Me(ctx context.Context) (*User, error)
|
||||
User(ctx context.Context, id string) (*User, error)
|
||||
Being(ctx context.Context, id string) (Being, error)
|
||||
Beings(ctx context.Context, ids []string) ([]Being, error)
|
||||
}
|
||||
|
||||
type executableSchema struct {
|
||||
@@ -122,6 +125,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Query.Being(childComplexity, args["id"].(string)), true
|
||||
|
||||
case "Query.beings":
|
||||
if e.complexity.Query.Beings == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_beings_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.Beings(childComplexity, args["ids"].([]string)), true
|
||||
|
||||
case "Query.me":
|
||||
if e.complexity.Query.Me == nil {
|
||||
break
|
||||
@@ -216,6 +231,7 @@ var sources = []*ast.Source{
|
||||
me: User
|
||||
user(id: ID!): User
|
||||
being(id: ID!): Being
|
||||
beings(ids: [ID!]!): [Being]!
|
||||
}
|
||||
|
||||
type User implements Being {
|
||||
@@ -278,6 +294,21 @@ func (ec *executionContext) field_Query_being_args(ctx context.Context, rawArgs
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_beings_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 []string
|
||||
if tmp, ok := rawArgs["ids"]; ok {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ids"))
|
||||
arg0, err = ec.unmarshalNID2ᚕstringᚄ(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["ids"] = 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{}{}
|
||||
@@ -578,6 +609,48 @@ func (ec *executionContext) _Query_being(ctx context.Context, field graphql.Coll
|
||||
return ec.marshalOBeing2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeing(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_beings(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_beings_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().Beings(rctx, args["ids"].([]string))
|
||||
})
|
||||
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.([]Being)
|
||||
fc.Result = res
|
||||
return ec.marshalNBeing2ᚕgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeing(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 {
|
||||
@@ -1956,6 +2029,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
res = ec._Query_being(ctx, field)
|
||||
return res
|
||||
})
|
||||
case "beings":
|
||||
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_beings(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "__type":
|
||||
out.Values[i] = ec._Query___type(ctx, field)
|
||||
case "__schema":
|
||||
@@ -2250,6 +2337,43 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o
|
||||
|
||||
// region ***************************** type.gotpl *****************************
|
||||
|
||||
func (ec *executionContext) marshalNBeing2ᚕgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeing(ctx context.Context, sel ast.SelectionSet, v []Being) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
for i := range v {
|
||||
i := i
|
||||
fc := &graphql.FieldContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithFieldContext(ctx, fc)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalOBeing2githubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐBeing(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) {
|
||||
res, err := graphql.UnmarshalBoolean(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
@@ -2280,6 +2404,36 @@ func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.Selec
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNID2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {
|
||||
var vSlice []interface{}
|
||||
if v != nil {
|
||||
if tmp1, ok := v.([]interface{}); ok {
|
||||
vSlice = tmp1
|
||||
} else {
|
||||
vSlice = []interface{}{v}
|
||||
}
|
||||
}
|
||||
var err error
|
||||
res := make([]string, len(vSlice))
|
||||
for i := range vSlice {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
|
||||
res[i], err = ec.unmarshalNID2string(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNID2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
for i := range v {
|
||||
ret[i] = ec.marshalNID2string(ctx, sel, v[i])
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -55,6 +55,14 @@ func (r *queryResolver) Being(ctx context.Context, id string) (Being, error) {
|
||||
return beingByID(id), nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) Beings(ctx context.Context, ids []string) ([]Being, error) {
|
||||
ret := make([]Being, len(ids))
|
||||
for i, id := range ids {
|
||||
ret[i] = beingByID(id)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func RunServer() *httptest.Server {
|
||||
gqlgenServer := handler.New(NewExecutableSchema(Config{Resolvers: &resolver{}}))
|
||||
gqlgenServer.AddTransport(transport.POST{})
|
||||
|
||||
Reference in New Issue
Block a user