diff --git a/codegen/testserver/generated.go b/codegen/testserver/generated.go index 85025fdf429..41051b8e35b 100644 --- a/codegen/testserver/generated.go +++ b/codegen/testserver/generated.go @@ -42,6 +42,7 @@ type ResolverRoot interface { ModelMethods() ModelMethodsResolver OverlappingFields() OverlappingFieldsResolver Panics() PanicsResolver + Primitive() PrimitiveResolver Query() QueryResolver Subscription() SubscriptionResolver User() UserResolver @@ -164,6 +165,11 @@ type ComplexityRoot struct { FieldScalarMarshal func(childComplexity int) int } + Primitive struct { + Squared func(childComplexity int) int + Value func(childComplexity int) int + } + Query struct { Autobind func(childComplexity int) int Collision func(childComplexity int) int @@ -187,6 +193,7 @@ type ComplexityRoot struct { OptionalUnion func(childComplexity int) int Overlapping func(childComplexity int) int Panics func(childComplexity int) int + PrimitiveObject func(childComplexity int) int Recursive func(childComplexity int, input *RecursiveInputSlice) int ScalarSlice func(childComplexity int) int ShapeUnion func(childComplexity int) int @@ -260,6 +267,9 @@ type PanicsResolver interface { ArgUnmarshal(ctx context.Context, obj *Panics, u []MarshalPanic) (bool, error) } +type PrimitiveResolver interface { + Value(ctx context.Context, obj *Primitive) (int, error) +} type QueryResolver interface { InvalidIdentifier(ctx context.Context) (*invalid_packagename.InvalidIdentifier, error) Collision(ctx context.Context) (*introspection1.It, error) @@ -285,6 +295,7 @@ type QueryResolver interface { Overlapping(ctx context.Context) (*OverlappingFields, error) MapStringInterface(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) Panics(ctx context.Context) (*Panics, error) + PrimitiveObject(ctx context.Context) ([]Primitive, error) DefaultScalar(ctx context.Context, arg string) (string, error) Slices(ctx context.Context) (*Slices, error) ScalarSlice(ctx context.Context) ([]byte, error) @@ -598,6 +609,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Panics.FieldScalarMarshal(childComplexity), true + case "Primitive.squared": + if e.complexity.Primitive.Squared == nil { + break + } + + return e.complexity.Primitive.Squared(childComplexity), true + + case "Primitive.value": + if e.complexity.Primitive.Value == nil { + break + } + + return e.complexity.Primitive.Value(childComplexity), true + case "Query.autobind": if e.complexity.Query.Autobind == nil { break @@ -812,6 +837,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Panics(childComplexity), true + case "Query.primitiveObject": + if e.complexity.Query.PrimitiveObject == nil { + break + } + + return e.complexity.Query.PrimitiveObject(childComplexity), true + case "Query.recursive": if e.complexity.Query.Recursive == nil { break @@ -1221,6 +1253,15 @@ type Panics { } scalar MarshalPanic +`}, + &ast.Source{Name: "primitive_objects.graphql", Input: `extend type Query { + primitiveObject: [Primitive!]! +} + +type Primitive { + value: Int! + squared: Int! +} `}, &ast.Source{Name: "scalar_default.graphql", Input: `extend type Query { defaultScalar(arg: DefaultScalarImplementation! = "default"): DefaultScalarImplementation! @@ -3208,6 +3249,60 @@ func (ec *executionContext) _Panics_argUnmarshal(ctx context.Context, field grap return ec.marshalNBoolean2bool(ctx, field.Selections, res) } +func (ec *executionContext) _Primitive_value(ctx context.Context, field graphql.CollectedField, obj *Primitive) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Primitive", + Field: field, + Args: nil, + IsMethod: true, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Primitive().Value(rctx, obj) + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Primitive_squared(ctx context.Context, field graphql.CollectedField, obj *Primitive) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Primitive", + Field: field, + Args: nil, + IsMethod: true, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Squared(), nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNInt2int(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_invalidIdentifier(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -3883,6 +3978,33 @@ func (ec *executionContext) _Query_panics(ctx context.Context, field graphql.Col return ec.marshalOPanics2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐPanics(ctx, field.Selections, res) } +func (ec *executionContext) _Query_primitiveObject(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PrimitiveObject(rctx) + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]Primitive) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNPrimitive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐPrimitive(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_defaultScalar(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -6623,6 +6745,47 @@ func (ec *executionContext) _Panics(ctx context.Context, sel ast.SelectionSet, o return out } +var primitiveImplementors = []string{"Primitive"} + +func (ec *executionContext) _Primitive(ctx context.Context, sel ast.SelectionSet, obj *Primitive) graphql.Marshaler { + fields := graphql.CollectFields(ec.RequestContext, sel, primitiveImplementors) + + out := graphql.NewFieldSet(fields) + invalid := false + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Primitive") + case "value": + 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._Primitive_value(ctx, field, obj) + if res == graphql.Null { + invalid = true + } + return res + }) + case "squared": + out.Values[i] = ec._Primitive_squared(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalid { + return graphql.Null + } + return out +} + var queryImplementors = []string{"Query"} func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -6917,6 +7080,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr res = ec._Query_panics(ctx, field) return res }) + case "primitiveObject": + 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_primitiveObject(ctx, field) + if res == graphql.Null { + invalid = true + } + return res + }) case "defaultScalar": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -7771,6 +7948,47 @@ func (ec *executionContext) marshalNMarshalPanic2ᚕgithubᚗcomᚋ99designsᚋg return ret } +func (ec *executionContext) marshalNPrimitive2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐPrimitive(ctx context.Context, sel ast.SelectionSet, v Primitive) graphql.Marshaler { + return ec._Primitive(ctx, sel, &v) +} + +func (ec *executionContext) marshalNPrimitive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐPrimitive(ctx context.Context, sel ast.SelectionSet, v []Primitive) 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 + rctx := &graphql.ResolverContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithResolverContext(ctx, rctx) + 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.marshalNPrimitive2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐPrimitive(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + func (ec *executionContext) unmarshalNRecursiveInputSlice2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐRecursiveInputSlice(ctx context.Context, v interface{}) (RecursiveInputSlice, error) { return ec.unmarshalInputRecursiveInputSlice(ctx, v) } diff --git a/codegen/testserver/gqlgen.yml b/codegen/testserver/gqlgen.yml index 83555211939..959caaf98d9 100644 --- a/codegen/testserver/gqlgen.yml +++ b/codegen/testserver/gqlgen.yml @@ -56,6 +56,8 @@ models: model: "github.com/99designs/gqlgen/codegen/testserver.MarshalPanic" Autobind: model: "github.com/99designs/gqlgen/codegen/testserver.Autobind" + Primitive: + model: "github.com/99designs/gqlgen/codegen/testserver.Primitive" MapStringInterfaceInput: model: "map[string]interface{}" MapStringInterfaceType: diff --git a/codegen/testserver/models.go b/codegen/testserver/models.go index 3ee710a50fc..2f2ebeebaff 100644 --- a/codegen/testserver/models.go +++ b/codegen/testserver/models.go @@ -84,3 +84,9 @@ const ( FallbackToStringEncodingB FallbackToStringEncoding = "B" FallbackToStringEncodingC FallbackToStringEncoding = "C" ) + +type Primitive int + +func (p Primitive) Squared() int { + return int(p) * int(p) +} diff --git a/codegen/testserver/primitive_objects.graphql b/codegen/testserver/primitive_objects.graphql new file mode 100644 index 00000000000..e7dc49aa9b9 --- /dev/null +++ b/codegen/testserver/primitive_objects.graphql @@ -0,0 +1,8 @@ +extend type Query { + primitiveObject: [Primitive!]! +} + +type Primitive { + value: Int! + squared: Int! +} diff --git a/codegen/testserver/primitive_objects_test.go b/codegen/testserver/primitive_objects_test.go new file mode 100644 index 00000000000..f1b77643e86 --- /dev/null +++ b/codegen/testserver/primitive_objects_test.go @@ -0,0 +1,40 @@ +package testserver + +import ( + "context" + "net/http/httptest" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/handler" + "github.com/stretchr/testify/assert" +) + +func TestPrimitiveObjects(t *testing.T) { + resolvers := &Stub{} + resolvers.QueryResolver.PrimitiveObject = func(ctx context.Context) (out []Primitive, e error) { + return []Primitive{2, 4}, nil + } + + resolvers.PrimitiveResolver.Value = func(ctx context.Context, obj *Primitive) (i int, e error) { + return int(*obj), nil + } + + srv := httptest.NewServer(handler.GraphQL(NewExecutableSchema(Config{Resolvers: resolvers}))) + c := client.New(srv.URL) + + t.Run("can fetch value", func(t *testing.T) { + var resp struct { + PrimitiveObject []struct { + Value int + Squared int + } + } + c.MustPost(`query { primitiveObject { value, squared } }`, &resp) + + assert.Equal(t, 2, resp.PrimitiveObject[0].Value) + assert.Equal(t, 4, resp.PrimitiveObject[0].Squared) + assert.Equal(t, 4, resp.PrimitiveObject[1].Value) + assert.Equal(t, 16, resp.PrimitiveObject[1].Squared) + }) +} diff --git a/codegen/testserver/resolver.go b/codegen/testserver/resolver.go index e752629b677..f706d36b5ad 100644 --- a/codegen/testserver/resolver.go +++ b/codegen/testserver/resolver.go @@ -23,6 +23,9 @@ func (r *Resolver) OverlappingFields() OverlappingFieldsResolver { func (r *Resolver) Panics() PanicsResolver { return &panicsResolver{r} } +func (r *Resolver) Primitive() PrimitiveResolver { + return &primitiveResolver{r} +} func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } @@ -60,6 +63,12 @@ func (r *panicsResolver) ArgUnmarshal(ctx context.Context, obj *Panics, u []Mars panic("not implemented") } +type primitiveResolver struct{ *Resolver } + +func (r *primitiveResolver) Value(ctx context.Context, obj *Primitive) (int, error) { + panic("not implemented") +} + type queryResolver struct{ *Resolver } func (r *queryResolver) InvalidIdentifier(ctx context.Context) (*invalid_packagename.InvalidIdentifier, error) { @@ -134,6 +143,9 @@ func (r *queryResolver) MapStringInterface(ctx context.Context, in map[string]in func (r *queryResolver) Panics(ctx context.Context) (*Panics, error) { panic("not implemented") } +func (r *queryResolver) PrimitiveObject(ctx context.Context) ([]Primitive, error) { + panic("not implemented") +} func (r *queryResolver) DefaultScalar(ctx context.Context, arg string) (string, error) { panic("not implemented") } diff --git a/codegen/testserver/stub.go b/codegen/testserver/stub.go index eaebd12d323..24e38004d85 100644 --- a/codegen/testserver/stub.go +++ b/codegen/testserver/stub.go @@ -23,6 +23,9 @@ type Stub struct { FieldScalarMarshal func(ctx context.Context, obj *Panics) ([]MarshalPanic, error) ArgUnmarshal func(ctx context.Context, obj *Panics, u []MarshalPanic) (bool, error) } + PrimitiveResolver struct { + Value func(ctx context.Context, obj *Primitive) (int, error) + } QueryResolver struct { InvalidIdentifier func(ctx context.Context) (*invalid_packagename.InvalidIdentifier, error) Collision func(ctx context.Context) (*introspection1.It, error) @@ -48,6 +51,7 @@ type Stub struct { Overlapping func(ctx context.Context) (*OverlappingFields, error) MapStringInterface func(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) Panics func(ctx context.Context) (*Panics, error) + PrimitiveObject func(ctx context.Context) ([]Primitive, error) DefaultScalar func(ctx context.Context, arg string) (string, error) Slices func(ctx context.Context) (*Slices, error) ScalarSlice func(ctx context.Context) ([]byte, error) @@ -76,6 +80,9 @@ func (r *Stub) OverlappingFields() OverlappingFieldsResolver { func (r *Stub) Panics() PanicsResolver { return &stubPanics{r} } +func (r *Stub) Primitive() PrimitiveResolver { + return &stubPrimitive{r} +} func (r *Stub) Query() QueryResolver { return &stubQuery{r} } @@ -113,6 +120,12 @@ func (r *stubPanics) ArgUnmarshal(ctx context.Context, obj *Panics, u []MarshalP return r.PanicsResolver.ArgUnmarshal(ctx, obj, u) } +type stubPrimitive struct{ *Stub } + +func (r *stubPrimitive) Value(ctx context.Context, obj *Primitive) (int, error) { + return r.PrimitiveResolver.Value(ctx, obj) +} + type stubQuery struct{ *Stub } func (r *stubQuery) InvalidIdentifier(ctx context.Context) (*invalid_packagename.InvalidIdentifier, error) { @@ -187,6 +200,9 @@ func (r *stubQuery) MapStringInterface(ctx context.Context, in map[string]interf func (r *stubQuery) Panics(ctx context.Context) (*Panics, error) { return r.QueryResolver.Panics(ctx) } +func (r *stubQuery) PrimitiveObject(ctx context.Context) ([]Primitive, error) { + return r.QueryResolver.PrimitiveObject(ctx) +} func (r *stubQuery) DefaultScalar(ctx context.Context, arg string) (string, error) { return r.QueryResolver.DefaultScalar(ctx, arg) }