diff --git a/_examples/config/generated.go b/_examples/config/generated.go index 80742fbd208..37f497fd5f8 100644 --- a/_examples/config/generated.go +++ b/_examples/config/generated.go @@ -2781,7 +2781,12 @@ func (ec *executionContext) unmarshalInputNewTodo(ctx context.Context, obj inter asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"text", "userId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "text": var err error diff --git a/_examples/fileupload/generated.go b/_examples/fileupload/generated.go index 548875b3232..b8ea7004a9b 100644 --- a/_examples/fileupload/generated.go +++ b/_examples/fileupload/generated.go @@ -2762,7 +2762,12 @@ func (ec *executionContext) unmarshalInputUploadFile(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"id", "file"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "id": var err error diff --git a/_examples/scalars/generated.go b/_examples/scalars/generated.go index 3ba0bdc4a18..e74062808cd 100644 --- a/_examples/scalars/generated.go +++ b/_examples/scalars/generated.go @@ -3105,7 +3105,12 @@ func (ec *executionContext) unmarshalInputSearchArgs(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"location", "createdAfter", "isBanned"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "location": var err error diff --git a/_examples/starwars/generated/exec.go b/_examples/starwars/generated/exec.go index b25c26077fb..c7d8c4916c1 100644 --- a/_examples/starwars/generated/exec.go +++ b/_examples/starwars/generated/exec.go @@ -4730,7 +4730,12 @@ func (ec *executionContext) unmarshalInputReviewInput(ctx context.Context, obj i asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"stars", "commentary", "time"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "stars": var err error diff --git a/_examples/todo/generated.go b/_examples/todo/generated.go index c7009295a2b..196e9542b95 100644 --- a/_examples/todo/generated.go +++ b/_examples/todo/generated.go @@ -2697,7 +2697,12 @@ func (ec *executionContext) unmarshalInputTodoInput(ctx context.Context, obj int asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"text", "done"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "text": var err error diff --git a/_examples/type-system-extension/generated.go b/_examples/type-system-extension/generated.go index 8319670b1f9..20ef22b3224 100644 --- a/_examples/type-system-extension/generated.go +++ b/_examples/type-system-extension/generated.go @@ -2675,7 +2675,12 @@ func (ec *executionContext) unmarshalInputTodoInput(ctx context.Context, obj int asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"text"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "text": var err error diff --git a/codegen/input.gotpl b/codegen/input.gotpl index 5694bcd613c..116fe9ce76b 100644 --- a/codegen/input.gotpl +++ b/codegen/input.gotpl @@ -14,7 +14,12 @@ {{- end}} {{- end }} - for k, v := range asMap { + fieldsInOrder := [...]string{ {{ range .Fields }}{{ quote .Name }},{{ end }} } + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { {{- range $field := .Fields }} case {{$field.Name|quote}}: diff --git a/codegen/root_.gotpl b/codegen/root_.gotpl index aeab219abdf..2f2a98262ef 100644 --- a/codegen/root_.gotpl +++ b/codegen/root_.gotpl @@ -35,6 +35,11 @@ type ResolverRoot interface { {{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver {{ end }} {{- end }} +{{- range $object := .Inputs -}} + {{ if $object.HasResolvers -}} + {{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver + {{ end }} +{{- end }} } type DirectiveRoot struct { diff --git a/codegen/testserver/followschema/defaults.generated.go b/codegen/testserver/followschema/defaults.generated.go index af3b5505941..0705293de80 100644 --- a/codegen/testserver/followschema/defaults.generated.go +++ b/codegen/testserver/followschema/defaults.generated.go @@ -16,6 +16,7 @@ import ( type MutationResolver interface { DefaultInput(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) + OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) UpdatePtrToPtr(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) } @@ -39,6 +40,21 @@ func (ec *executionContext) field_Mutation_defaultInput_args(ctx context.Context return args, nil } +func (ec *executionContext) field_Mutation_overrideValueViaInput_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 FieldsOrderInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNFieldsOrderInput2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐFieldsOrderInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_updatePtrToPtr_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -211,6 +227,62 @@ func (ec *executionContext) fieldContext_Mutation_defaultInput(ctx context.Conte return fc, nil } +func (ec *executionContext) _Mutation_overrideValueViaInput(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_overrideValueViaInput(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp := ec._fieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().OverrideValueViaInput(rctx, fc.Args["input"].(FieldsOrderInput)) + }) + + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*FieldsOrderPayload) + fc.Result = res + return ec.marshalNFieldsOrderPayload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐFieldsOrderPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_overrideValueViaInput(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "firstFieldValue": + return ec.fieldContext_FieldsOrderPayload_firstFieldValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type FieldsOrderPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_overrideValueViaInput_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _Mutation_updateSomething(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_updateSomething(ctx, field) if err != nil { @@ -341,7 +413,12 @@ func (ec *executionContext) unmarshalInputDefaultInput(ctx context.Context, obj asMap["truthyBoolean"] = true } - for k, v := range asMap { + fieldsInOrder := [...]string{"falsyBoolean", "truthyBoolean"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "falsyBoolean": var err error @@ -427,6 +504,15 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return ec._Mutation_defaultInput(ctx, field) }) + if out.Values[i] == graphql.Null { + invalids++ + } + case "overrideValueViaInput": + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_overrideValueViaInput(ctx, field) + }) + if out.Values[i] == graphql.Null { invalids++ } diff --git a/codegen/testserver/followschema/directive.generated.go b/codegen/testserver/followschema/directive.generated.go index ff81b5569c3..af60d5f8da9 100644 --- a/codegen/testserver/followschema/directive.generated.go +++ b/codegen/testserver/followschema/directive.generated.go @@ -397,7 +397,12 @@ func (ec *executionContext) unmarshalInputInnerDirectives(ctx context.Context, o asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"message"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "message": var err error @@ -442,7 +447,12 @@ func (ec *executionContext) unmarshalInputInputDirectives(ctx context.Context, o asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"text", "nullableText", "inner", "innerNullable", "thirdParty"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "text": var err error diff --git a/codegen/testserver/followschema/enum.generated.go b/codegen/testserver/followschema/enum.generated.go index 59752873f91..c9d29fdc143 100644 --- a/codegen/testserver/followschema/enum.generated.go +++ b/codegen/testserver/followschema/enum.generated.go @@ -34,7 +34,12 @@ func (ec *executionContext) unmarshalInputInputWithEnumValue(ctx context.Context asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"enum"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "enum": var err error diff --git a/codegen/testserver/followschema/fields_order.generated.go b/codegen/testserver/followschema/fields_order.generated.go new file mode 100644 index 00000000000..298333651c6 --- /dev/null +++ b/codegen/testserver/followschema/fields_order.generated.go @@ -0,0 +1,169 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package followschema + +import ( + "context" + "errors" + "strconv" + + "github.com/99designs/gqlgen/graphql" + "github.com/vektah/gqlparser/v2/ast" +) + +// region ************************** generated!.gotpl ************************** + +type FieldsOrderInputResolver interface { + OverrideFirstField(ctx context.Context, obj *FieldsOrderInput, data *string) error +} + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +// endregion ***************************** args.gotpl ***************************** + +// region ************************** directives.gotpl ************************** + +// endregion ************************** directives.gotpl ************************** + +// region **************************** field.gotpl ***************************** + +func (ec *executionContext) _FieldsOrderPayload_firstFieldValue(ctx context.Context, field graphql.CollectedField, obj *FieldsOrderPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_FieldsOrderPayload_firstFieldValue(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.FirstFieldValue, nil + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_FieldsOrderPayload_firstFieldValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FieldsOrderPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputFieldsOrderInput(ctx context.Context, obj interface{}) (FieldsOrderInput, error) { + var it FieldsOrderInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"firstField", "overrideFirstField"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "firstField": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("firstField")) + it.FirstField, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "overrideFirstField": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("overrideFirstField")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.FieldsOrderInput().OverrideFirstField(ctx, &it, data); err != nil { + return it, err + } + } + } + + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var fieldsOrderPayloadImplementors = []string{"FieldsOrderPayload"} + +func (ec *executionContext) _FieldsOrderPayload(ctx context.Context, sel ast.SelectionSet, obj *FieldsOrderPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, fieldsOrderPayloadImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FieldsOrderPayload") + case "firstFieldValue": + + out.Values[i] = ec._FieldsOrderPayload_firstFieldValue(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +// endregion **************************** object.gotpl **************************** + +// region ***************************** type.gotpl ***************************** + +func (ec *executionContext) unmarshalNFieldsOrderInput2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐFieldsOrderInput(ctx context.Context, v interface{}) (FieldsOrderInput, error) { + res, err := ec.unmarshalInputFieldsOrderInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNFieldsOrderPayload2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐFieldsOrderPayload(ctx context.Context, sel ast.SelectionSet, v FieldsOrderPayload) graphql.Marshaler { + return ec._FieldsOrderPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNFieldsOrderPayload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐFieldsOrderPayload(ctx context.Context, sel ast.SelectionSet, v *FieldsOrderPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._FieldsOrderPayload(ctx, sel, v) +} + +// endregion ***************************** type.gotpl ***************************** diff --git a/codegen/testserver/followschema/fields_order.go b/codegen/testserver/followschema/fields_order.go new file mode 100644 index 00000000000..8c540d39a2a --- /dev/null +++ b/codegen/testserver/followschema/fields_order.go @@ -0,0 +1,5 @@ +package followschema + +type FieldsOrderInput struct { + FirstField *string `json:"firstField"` +} diff --git a/codegen/testserver/followschema/fields_order.graphql b/codegen/testserver/followschema/fields_order.graphql new file mode 100644 index 00000000000..7be43289509 --- /dev/null +++ b/codegen/testserver/followschema/fields_order.graphql @@ -0,0 +1,12 @@ +type FieldsOrderPayload { + firstFieldValue: String +} + +input FieldsOrderInput { + firstField: String + overrideFirstField: String +} + +extend type Mutation { + overrideValueViaInput(input: FieldsOrderInput!): FieldsOrderPayload! +} diff --git a/codegen/testserver/followschema/fields_order_test.go b/codegen/testserver/followschema/fields_order_test.go new file mode 100644 index 00000000000..693f0c852e3 --- /dev/null +++ b/codegen/testserver/followschema/fields_order_test.go @@ -0,0 +1,65 @@ +package followschema + +import ( + "context" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/stretchr/testify/require" +) + +type FieldsOrderPayloadResults struct { + OverrideValueViaInput struct { + FirstFieldValue *string `json:"firstFieldValue"` + } `json:"overrideValueViaInput"` +} + +func TestFieldsOrder(t *testing.T) { + resolvers := &Stub{} + + c := client.New(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers}))) + resolvers.FieldsOrderInputResolver.OverrideFirstField = func(ctx context.Context, in *FieldsOrderInput, data *string) error { + if data != nil { + in.FirstField = data + } + return nil + } + resolvers.MutationResolver.OverrideValueViaInput = func(ctx context.Context, in FieldsOrderInput) (ret *FieldsOrderPayload, err error) { + ret = &FieldsOrderPayload{ + FirstFieldValue: in.FirstField, + } + return + } + + t.Run("firstField", func(t *testing.T) { + var resp FieldsOrderPayloadResults + + err := c.Post(`mutation { + overrideValueViaInput(input: { firstField:"newName" }) { + firstFieldValue + } + }`, &resp) + require.NoError(t, err) + + require.NotNil(t, resp.OverrideValueViaInput.FirstFieldValue) + require.Equal(t, "newName", *resp.OverrideValueViaInput.FirstFieldValue) + }) + + t.Run("firstField/override", func(t *testing.T) { + var resp FieldsOrderPayloadResults + + err := c.Post(`mutation { overrideValueViaInput(input: { + firstField:"newName", + overrideFirstField: "override" + }) { + firstFieldValue + } + }`, &resp) + require.NoError(t, err) + + require.NotNil(t, resp.OverrideValueViaInput.FirstFieldValue) + require.NotEqual(t, "newName", *resp.OverrideValueViaInput.FirstFieldValue) + require.Equal(t, "override", *resp.OverrideValueViaInput.FirstFieldValue) + }) +} diff --git a/codegen/testserver/followschema/maps.generated.go b/codegen/testserver/followschema/maps.generated.go index e34501a8857..b51ab7632ca 100644 --- a/codegen/testserver/followschema/maps.generated.go +++ b/codegen/testserver/followschema/maps.generated.go @@ -131,7 +131,12 @@ func (ec *executionContext) unmarshalInputNestedMapInput(ctx context.Context, ob asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"map"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "map": var err error diff --git a/codegen/testserver/followschema/models-gen.go b/codegen/testserver/followschema/models-gen.go index ff04610e45a..deeaab767ea 100644 --- a/codegen/testserver/followschema/models-gen.go +++ b/codegen/testserver/followschema/models-gen.go @@ -90,6 +90,10 @@ type EmbeddedDefaultScalar struct { Value *string `json:"value"` } +type FieldsOrderPayload struct { + FirstFieldValue *string `json:"firstFieldValue"` +} + type InnerDirectives struct { Message string `json:"message"` } diff --git a/codegen/testserver/followschema/mutation_with_custom_scalar.generated.go b/codegen/testserver/followschema/mutation_with_custom_scalar.generated.go index c0d4d0bd93f..ec2098a11c5 100644 --- a/codegen/testserver/followschema/mutation_with_custom_scalar.generated.go +++ b/codegen/testserver/followschema/mutation_with_custom_scalar.generated.go @@ -34,7 +34,12 @@ func (ec *executionContext) unmarshalInputNestedInput(ctx context.Context, obj i asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"field"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "field": var err error @@ -57,7 +62,12 @@ func (ec *executionContext) unmarshalInputSpecialInput(ctx context.Context, obj asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"nesting"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "nesting": var err error diff --git a/codegen/testserver/followschema/ptr_to_ptr_input.generated.go b/codegen/testserver/followschema/ptr_to_ptr_input.generated.go index 567aa3043e5..a0c9d109e55 100644 --- a/codegen/testserver/followschema/ptr_to_ptr_input.generated.go +++ b/codegen/testserver/followschema/ptr_to_ptr_input.generated.go @@ -248,7 +248,12 @@ func (ec *executionContext) unmarshalInputUpdatePtrToPtrInner(ctx context.Contex asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"key", "value"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "key": var err error @@ -279,7 +284,12 @@ func (ec *executionContext) unmarshalInputUpdatePtrToPtrOuter(ctx context.Contex asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"name", "inner", "stupidInner"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "name": var err error diff --git a/codegen/testserver/followschema/resolver.go b/codegen/testserver/followschema/resolver.go index 1b9583e7ac6..409e7beb040 100644 --- a/codegen/testserver/followschema/resolver.go +++ b/codegen/testserver/followschema/resolver.go @@ -57,6 +57,11 @@ func (r *mutationResolver) DefaultInput(ctx context.Context, input DefaultInput) panic("not implemented") } +// // foo +func (r *mutationResolver) OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) { + panic("not implemented") +} + // // foo func (r *mutationResolver) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) { panic("not implemented") diff --git a/codegen/testserver/followschema/root_.generated.go b/codegen/testserver/followschema/root_.generated.go index 8ee152a7b13..9f7231b9e21 100644 --- a/codegen/testserver/followschema/root_.generated.go +++ b/codegen/testserver/followschema/root_.generated.go @@ -46,6 +46,7 @@ type ResolverRoot interface { User() UserResolver WrappedMap() WrappedMapResolver WrappedSlice() WrappedSliceResolver + FieldsOrderInput() FieldsOrderInputResolver } type DirectiveRoot struct { @@ -180,6 +181,10 @@ type ComplexityRoot struct { E func(childComplexity int) int } + FieldsOrderPayload struct { + FirstFieldValue func(childComplexity int) int + } + ForcedResolver struct { Field func(childComplexity int) int } @@ -220,9 +225,10 @@ type ComplexityRoot struct { } Mutation struct { - DefaultInput func(childComplexity int, input DefaultInput) int - UpdatePtrToPtr func(childComplexity int, input UpdatePtrToPtrOuter) int - UpdateSomething func(childComplexity int, input SpecialInput) int + DefaultInput func(childComplexity int, input DefaultInput) int + OverrideValueViaInput func(childComplexity int, input FieldsOrderInput) int + UpdatePtrToPtr func(childComplexity int, input UpdatePtrToPtrOuter) int + UpdateSomething func(childComplexity int, input SpecialInput) int } ObjectDirectives struct { @@ -769,6 +775,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Errors.E(childComplexity), true + case "FieldsOrderPayload.firstFieldValue": + if e.complexity.FieldsOrderPayload.FirstFieldValue == nil { + break + } + + return e.complexity.FieldsOrderPayload.FirstFieldValue(childComplexity), true + case "ForcedResolver.field": if e.complexity.ForcedResolver.Field == nil { break @@ -865,6 +878,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.DefaultInput(childComplexity, args["input"].(DefaultInput)), true + case "Mutation.overrideValueViaInput": + if e.complexity.Mutation.OverrideValueViaInput == nil { + break + } + + args, err := ec.field_Mutation_overrideValueViaInput_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.OverrideValueViaInput(childComplexity, args["input"].(FieldsOrderInput)), true + case "Mutation.updatePtrToPtr": if e.complexity.Mutation.UpdatePtrToPtr == nil { break @@ -1923,6 +1948,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec := executionContext{rc, e} inputUnmarshalMap := graphql.BuildUnmarshalerMap( ec.unmarshalInputDefaultInput, + ec.unmarshalInputFieldsOrderInput, ec.unmarshalInputInnerDirectives, ec.unmarshalInputInnerInput, ec.unmarshalInputInputDirectives, @@ -2011,7 +2037,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil } -//go:embed "builtinscalar.graphql" "complexity.graphql" "defaults.graphql" "directive.graphql" "embedded.graphql" "enum.graphql" "interfaces.graphql" "issue896.graphql" "loops.graphql" "maps.graphql" "mutation_with_custom_scalar.graphql" "nulls.graphql" "panics.graphql" "primitive_objects.graphql" "ptr_to_ptr_input.graphql" "ptr_to_slice.graphql" "scalar_context.graphql" "scalar_default.graphql" "schema.graphql" "slices.graphql" "typefallback.graphql" "useptr.graphql" "v-ok.graphql" "validtypes.graphql" "variadic.graphql" "weird_type_cases.graphql" "wrapped_type.graphql" +//go:embed "builtinscalar.graphql" "complexity.graphql" "defaults.graphql" "directive.graphql" "embedded.graphql" "enum.graphql" "fields_order.graphql" "interfaces.graphql" "issue896.graphql" "loops.graphql" "maps.graphql" "mutation_with_custom_scalar.graphql" "nulls.graphql" "panics.graphql" "primitive_objects.graphql" "ptr_to_ptr_input.graphql" "ptr_to_slice.graphql" "scalar_context.graphql" "scalar_default.graphql" "schema.graphql" "slices.graphql" "typefallback.graphql" "useptr.graphql" "v-ok.graphql" "validtypes.graphql" "variadic.graphql" "weird_type_cases.graphql" "wrapped_type.graphql" var sourcesFS embed.FS func sourceData(filename string) string { @@ -2029,6 +2055,7 @@ var sources = []*ast.Source{ {Name: "directive.graphql", Input: sourceData("directive.graphql"), BuiltIn: false}, {Name: "embedded.graphql", Input: sourceData("embedded.graphql"), BuiltIn: false}, {Name: "enum.graphql", Input: sourceData("enum.graphql"), BuiltIn: false}, + {Name: "fields_order.graphql", Input: sourceData("fields_order.graphql"), BuiltIn: false}, {Name: "interfaces.graphql", Input: sourceData("interfaces.graphql"), BuiltIn: false}, {Name: "issue896.graphql", Input: sourceData("issue896.graphql"), BuiltIn: false}, {Name: "loops.graphql", Input: sourceData("loops.graphql"), BuiltIn: false}, diff --git a/codegen/testserver/followschema/schema.generated.go b/codegen/testserver/followschema/schema.generated.go index 6e0ca5675ec..d3a45046625 100644 --- a/codegen/testserver/followschema/schema.generated.go +++ b/codegen/testserver/followschema/schema.generated.go @@ -5445,7 +5445,12 @@ func (ec *executionContext) unmarshalInputInnerInput(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"id"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "id": var err error @@ -5468,7 +5473,12 @@ func (ec *executionContext) unmarshalInputOuterInput(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"inner"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "inner": var err error @@ -5491,7 +5501,12 @@ func (ec *executionContext) unmarshalInputRecursiveInputSlice(ctx context.Contex asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"self"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "self": var err error diff --git a/codegen/testserver/followschema/stub.go b/codegen/testserver/followschema/stub.go index a1bb8859ff4..95305fc12d3 100644 --- a/codegen/testserver/followschema/stub.go +++ b/codegen/testserver/followschema/stub.go @@ -28,9 +28,10 @@ type Stub struct { ResolverField func(ctx context.Context, obj *ModelMethods) (bool, error) } MutationResolver struct { - DefaultInput func(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) - UpdateSomething func(ctx context.Context, input SpecialInput) (string, error) - UpdatePtrToPtr func(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) + DefaultInput func(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) + OverrideValueViaInput func(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) + UpdateSomething func(ctx context.Context, input SpecialInput) (string, error) + UpdatePtrToPtr func(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) } OverlappingFieldsResolver struct { OldFoo func(ctx context.Context, obj *OverlappingFields) (int, error) @@ -136,6 +137,10 @@ type Stub struct { WrappedSliceResolver struct { Get func(ctx context.Context, obj WrappedSlice, idx int) (string, error) } + + FieldsOrderInputResolver struct { + OverrideFirstField func(ctx context.Context, obj *FieldsOrderInput, data *string) error + } } func (r *Stub) BackedByInterface() BackedByInterfaceResolver { @@ -184,6 +189,10 @@ func (r *Stub) WrappedSlice() WrappedSliceResolver { return &stubWrappedSlice{r} } +func (r *Stub) FieldsOrderInput() FieldsOrderInputResolver { + return &stubFieldsOrderInput{r} +} + type stubBackedByInterface struct{ *Stub } func (r *stubBackedByInterface) ID(ctx context.Context, obj BackedByInterface) (string, error) { @@ -225,6 +234,9 @@ type stubMutation struct{ *Stub } func (r *stubMutation) DefaultInput(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) { return r.MutationResolver.DefaultInput(ctx, input) } +func (r *stubMutation) OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) { + return r.MutationResolver.OverrideValueViaInput(ctx, input) +} func (r *stubMutation) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) { return r.MutationResolver.UpdateSomething(ctx, input) } @@ -513,3 +525,9 @@ type stubWrappedSlice struct{ *Stub } func (r *stubWrappedSlice) Get(ctx context.Context, obj WrappedSlice, idx int) (string, error) { return r.WrappedSliceResolver.Get(ctx, obj, idx) } + +type stubFieldsOrderInput struct{ *Stub } + +func (r *stubFieldsOrderInput) OverrideFirstField(ctx context.Context, obj *FieldsOrderInput, data *string) error { + return r.FieldsOrderInputResolver.OverrideFirstField(ctx, obj, data) +} diff --git a/codegen/testserver/followschema/validtypes.generated.go b/codegen/testserver/followschema/validtypes.generated.go index c575470086f..8e51b432c07 100644 --- a/codegen/testserver/followschema/validtypes.generated.go +++ b/codegen/testserver/followschema/validtypes.generated.go @@ -554,7 +554,12 @@ func (ec *executionContext) unmarshalInputValidInput(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for", "import", "return", "var", "_"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "break": var err error diff --git a/codegen/testserver/singlefile/fields_order.go b/codegen/testserver/singlefile/fields_order.go new file mode 100644 index 00000000000..a43083b0db5 --- /dev/null +++ b/codegen/testserver/singlefile/fields_order.go @@ -0,0 +1,5 @@ +package singlefile + +type FieldsOrderInput struct { + FirstField *string `json:"firstField"` +} diff --git a/codegen/testserver/singlefile/fields_order.graphql b/codegen/testserver/singlefile/fields_order.graphql new file mode 100644 index 00000000000..7be43289509 --- /dev/null +++ b/codegen/testserver/singlefile/fields_order.graphql @@ -0,0 +1,12 @@ +type FieldsOrderPayload { + firstFieldValue: String +} + +input FieldsOrderInput { + firstField: String + overrideFirstField: String +} + +extend type Mutation { + overrideValueViaInput(input: FieldsOrderInput!): FieldsOrderPayload! +} diff --git a/codegen/testserver/singlefile/fields_order_test.go b/codegen/testserver/singlefile/fields_order_test.go new file mode 100644 index 00000000000..eac294187f4 --- /dev/null +++ b/codegen/testserver/singlefile/fields_order_test.go @@ -0,0 +1,65 @@ +package singlefile + +import ( + "context" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/stretchr/testify/require" +) + +type FieldsOrderPayloadResults struct { + OverrideValueViaInput struct { + FirstFieldValue *string `json:"firstFieldValue"` + } `json:"overrideValueViaInput"` +} + +func TestFieldsOrder(t *testing.T) { + resolvers := &Stub{} + + c := client.New(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers}))) + resolvers.FieldsOrderInputResolver.OverrideFirstField = func(ctx context.Context, in *FieldsOrderInput, data *string) error { + if data != nil { + in.FirstField = data + } + return nil + } + resolvers.MutationResolver.OverrideValueViaInput = func(ctx context.Context, in FieldsOrderInput) (ret *FieldsOrderPayload, err error) { + ret = &FieldsOrderPayload{ + FirstFieldValue: in.FirstField, + } + return + } + + t.Run("firstField", func(t *testing.T) { + var resp FieldsOrderPayloadResults + + err := c.Post(`mutation { + overrideValueViaInput(input: { firstField:"newName" }) { + firstFieldValue + } + }`, &resp) + require.NoError(t, err) + + require.NotNil(t, resp.OverrideValueViaInput.FirstFieldValue) + require.Equal(t, "newName", *resp.OverrideValueViaInput.FirstFieldValue) + }) + + t.Run("firstField/override", func(t *testing.T) { + var resp FieldsOrderPayloadResults + + err := c.Post(`mutation { overrideValueViaInput(input: { + firstField:"newName", + overrideFirstField: "override" + }) { + firstFieldValue + } + }`, &resp) + require.NoError(t, err) + + require.NotNil(t, resp.OverrideValueViaInput.FirstFieldValue) + require.NotEqual(t, "newName", *resp.OverrideValueViaInput.FirstFieldValue) + require.Equal(t, "override", *resp.OverrideValueViaInput.FirstFieldValue) + }) +} diff --git a/codegen/testserver/singlefile/generated.go b/codegen/testserver/singlefile/generated.go index 9df81d6dd3d..320af50624a 100644 --- a/codegen/testserver/singlefile/generated.go +++ b/codegen/testserver/singlefile/generated.go @@ -56,6 +56,7 @@ type ResolverRoot interface { User() UserResolver WrappedMap() WrappedMapResolver WrappedSlice() WrappedSliceResolver + FieldsOrderInput() FieldsOrderInputResolver } type DirectiveRoot struct { @@ -190,6 +191,10 @@ type ComplexityRoot struct { E func(childComplexity int) int } + FieldsOrderPayload struct { + FirstFieldValue func(childComplexity int) int + } + ForcedResolver struct { Field func(childComplexity int) int } @@ -230,9 +235,10 @@ type ComplexityRoot struct { } Mutation struct { - DefaultInput func(childComplexity int, input DefaultInput) int - UpdatePtrToPtr func(childComplexity int, input UpdatePtrToPtrOuter) int - UpdateSomething func(childComplexity int, input SpecialInput) int + DefaultInput func(childComplexity int, input DefaultInput) int + OverrideValueViaInput func(childComplexity int, input FieldsOrderInput) int + UpdatePtrToPtr func(childComplexity int, input UpdatePtrToPtrOuter) int + UpdateSomething func(childComplexity int, input SpecialInput) int } ObjectDirectives struct { @@ -460,6 +466,7 @@ type ModelMethodsResolver interface { } type MutationResolver interface { DefaultInput(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) + OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) UpdatePtrToPtr(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) } @@ -571,6 +578,10 @@ type WrappedSliceResolver interface { Get(ctx context.Context, obj WrappedSlice, idx int) (string, error) } +type FieldsOrderInputResolver interface { + OverrideFirstField(ctx context.Context, obj *FieldsOrderInput, data *string) error +} + type executableSchema struct { resolvers ResolverRoot directives DirectiveRoot @@ -908,6 +919,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Errors.E(childComplexity), true + case "FieldsOrderPayload.firstFieldValue": + if e.complexity.FieldsOrderPayload.FirstFieldValue == nil { + break + } + + return e.complexity.FieldsOrderPayload.FirstFieldValue(childComplexity), true + case "ForcedResolver.field": if e.complexity.ForcedResolver.Field == nil { break @@ -1004,6 +1022,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.DefaultInput(childComplexity, args["input"].(DefaultInput)), true + case "Mutation.overrideValueViaInput": + if e.complexity.Mutation.OverrideValueViaInput == nil { + break + } + + args, err := ec.field_Mutation_overrideValueViaInput_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.OverrideValueViaInput(childComplexity, args["input"].(FieldsOrderInput)), true + case "Mutation.updatePtrToPtr": if e.complexity.Mutation.UpdatePtrToPtr == nil { break @@ -2062,6 +2092,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec := executionContext{rc, e} inputUnmarshalMap := graphql.BuildUnmarshalerMap( ec.unmarshalInputDefaultInput, + ec.unmarshalInputFieldsOrderInput, ec.unmarshalInputInnerDirectives, ec.unmarshalInputInnerInput, ec.unmarshalInputInputDirectives, @@ -2150,7 +2181,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil } -//go:embed "builtinscalar.graphql" "complexity.graphql" "defaults.graphql" "directive.graphql" "embedded.graphql" "enum.graphql" "interfaces.graphql" "issue896.graphql" "loops.graphql" "maps.graphql" "mutation_with_custom_scalar.graphql" "nulls.graphql" "panics.graphql" "primitive_objects.graphql" "ptr_to_ptr_input.graphql" "ptr_to_slice.graphql" "scalar_context.graphql" "scalar_default.graphql" "schema.graphql" "slices.graphql" "typefallback.graphql" "useptr.graphql" "v-ok.graphql" "validtypes.graphql" "variadic.graphql" "weird_type_cases.graphql" "wrapped_type.graphql" +//go:embed "builtinscalar.graphql" "complexity.graphql" "defaults.graphql" "directive.graphql" "embedded.graphql" "enum.graphql" "fields_order.graphql" "interfaces.graphql" "issue896.graphql" "loops.graphql" "maps.graphql" "mutation_with_custom_scalar.graphql" "nulls.graphql" "panics.graphql" "primitive_objects.graphql" "ptr_to_ptr_input.graphql" "ptr_to_slice.graphql" "scalar_context.graphql" "scalar_default.graphql" "schema.graphql" "slices.graphql" "typefallback.graphql" "useptr.graphql" "v-ok.graphql" "validtypes.graphql" "variadic.graphql" "weird_type_cases.graphql" "wrapped_type.graphql" var sourcesFS embed.FS func sourceData(filename string) string { @@ -2168,6 +2199,7 @@ var sources = []*ast.Source{ {Name: "directive.graphql", Input: sourceData("directive.graphql"), BuiltIn: false}, {Name: "embedded.graphql", Input: sourceData("embedded.graphql"), BuiltIn: false}, {Name: "enum.graphql", Input: sourceData("enum.graphql"), BuiltIn: false}, + {Name: "fields_order.graphql", Input: sourceData("fields_order.graphql"), BuiltIn: false}, {Name: "interfaces.graphql", Input: sourceData("interfaces.graphql"), BuiltIn: false}, {Name: "issue896.graphql", Input: sourceData("issue896.graphql"), BuiltIn: false}, {Name: "loops.graphql", Input: sourceData("loops.graphql"), BuiltIn: false}, @@ -2313,6 +2345,21 @@ func (ec *executionContext) field_Mutation_defaultInput_args(ctx context.Context return args, nil } +func (ec *executionContext) field_Mutation_overrideValueViaInput_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 FieldsOrderInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNFieldsOrderInput2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐFieldsOrderInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_updatePtrToPtr_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -5221,6 +5268,44 @@ func (ec *executionContext) fieldContext_Errors_e(ctx context.Context, field gra return fc, nil } +func (ec *executionContext) _FieldsOrderPayload_firstFieldValue(ctx context.Context, field graphql.CollectedField, obj *FieldsOrderPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_FieldsOrderPayload_firstFieldValue(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.FirstFieldValue, nil + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_FieldsOrderPayload_firstFieldValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FieldsOrderPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _ForcedResolver_field(ctx context.Context, field graphql.CollectedField, obj *ForcedResolver) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ForcedResolver_field(ctx, field) if err != nil { @@ -5796,6 +5881,62 @@ func (ec *executionContext) fieldContext_Mutation_defaultInput(ctx context.Conte return fc, nil } +func (ec *executionContext) _Mutation_overrideValueViaInput(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_overrideValueViaInput(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp := ec._fieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().OverrideValueViaInput(rctx, fc.Args["input"].(FieldsOrderInput)) + }) + + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*FieldsOrderPayload) + fc.Result = res + return ec.marshalNFieldsOrderPayload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐFieldsOrderPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_overrideValueViaInput(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "firstFieldValue": + return ec.fieldContext_FieldsOrderPayload_firstFieldValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type FieldsOrderPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_overrideValueViaInput_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _Mutation_updateSomething(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_updateSomething(ctx, field) if err != nil { @@ -13765,7 +13906,12 @@ func (ec *executionContext) unmarshalInputDefaultInput(ctx context.Context, obj asMap["truthyBoolean"] = true } - for k, v := range asMap { + fieldsInOrder := [...]string{"falsyBoolean", "truthyBoolean"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "falsyBoolean": var err error @@ -13789,6 +13935,45 @@ func (ec *executionContext) unmarshalInputDefaultInput(ctx context.Context, obj return it, nil } +func (ec *executionContext) unmarshalInputFieldsOrderInput(ctx context.Context, obj interface{}) (FieldsOrderInput, error) { + var it FieldsOrderInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"firstField", "overrideFirstField"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "firstField": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("firstField")) + it.FirstField, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "overrideFirstField": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("overrideFirstField")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.FieldsOrderInput().OverrideFirstField(ctx, &it, data); err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputInnerDirectives(ctx context.Context, obj interface{}) (InnerDirectives, error) { var it InnerDirectives asMap := map[string]interface{}{} @@ -13796,7 +13981,12 @@ func (ec *executionContext) unmarshalInputInnerDirectives(ctx context.Context, o asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"message"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "message": var err error @@ -13841,7 +14031,12 @@ func (ec *executionContext) unmarshalInputInnerInput(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"id"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "id": var err error @@ -13864,7 +14059,12 @@ func (ec *executionContext) unmarshalInputInputDirectives(ctx context.Context, o asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"text", "nullableText", "inner", "innerNullable", "thirdParty"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "text": var err error @@ -14041,7 +14241,12 @@ func (ec *executionContext) unmarshalInputInputWithEnumValue(ctx context.Context asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"enum"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "enum": var err error @@ -14064,7 +14269,12 @@ func (ec *executionContext) unmarshalInputNestedInput(ctx context.Context, obj i asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"field"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "field": var err error @@ -14087,7 +14297,12 @@ func (ec *executionContext) unmarshalInputNestedMapInput(ctx context.Context, ob asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"map"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "map": var err error @@ -14110,7 +14325,12 @@ func (ec *executionContext) unmarshalInputOuterInput(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"inner"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "inner": var err error @@ -14133,7 +14353,12 @@ func (ec *executionContext) unmarshalInputRecursiveInputSlice(ctx context.Contex asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"self"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "self": var err error @@ -14156,7 +14381,12 @@ func (ec *executionContext) unmarshalInputSpecialInput(ctx context.Context, obj asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"nesting"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "nesting": var err error @@ -14179,7 +14409,12 @@ func (ec *executionContext) unmarshalInputUpdatePtrToPtrInner(ctx context.Contex asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"key", "value"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "key": var err error @@ -14210,7 +14445,12 @@ func (ec *executionContext) unmarshalInputUpdatePtrToPtrOuter(ctx context.Contex asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"name", "inner", "stupidInner"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "name": var err error @@ -14249,7 +14489,12 @@ func (ec *executionContext) unmarshalInputValidInput(ctx context.Context, obj in asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for", "import", "return", "var", "_"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "break": var err error @@ -15446,6 +15691,31 @@ func (ec *executionContext) _Errors(ctx context.Context, sel ast.SelectionSet, o return out } +var fieldsOrderPayloadImplementors = []string{"FieldsOrderPayload"} + +func (ec *executionContext) _FieldsOrderPayload(ctx context.Context, sel ast.SelectionSet, obj *FieldsOrderPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, fieldsOrderPayloadImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FieldsOrderPayload") + case "firstFieldValue": + + out.Values[i] = ec._FieldsOrderPayload_firstFieldValue(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var forcedResolverImplementors = []string{"ForcedResolver"} func (ec *executionContext) _ForcedResolver(ctx context.Context, sel ast.SelectionSet, obj *ForcedResolver) graphql.Marshaler { @@ -15774,6 +16044,15 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return ec._Mutation_defaultInput(ctx, field) }) + if out.Values[i] == graphql.Null { + invalids++ + } + case "overrideValueViaInput": + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_overrideValueViaInput(ctx, field) + }) + if out.Values[i] == graphql.Null { invalids++ } @@ -18717,6 +18996,25 @@ func (ec *executionContext) marshalNFallbackToStringEncoding2githubᚗcomᚋ99de return res } +func (ec *executionContext) unmarshalNFieldsOrderInput2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐFieldsOrderInput(ctx context.Context, v interface{}) (FieldsOrderInput, error) { + res, err := ec.unmarshalInputFieldsOrderInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNFieldsOrderPayload2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐFieldsOrderPayload(ctx context.Context, sel ast.SelectionSet, v FieldsOrderPayload) graphql.Marshaler { + return ec._FieldsOrderPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNFieldsOrderPayload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐFieldsOrderPayload(ctx context.Context, sel ast.SelectionSet, v *FieldsOrderPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._FieldsOrderPayload(ctx, sel, v) +} + func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { res, err := graphql.UnmarshalFloatContext(ctx, v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/codegen/testserver/singlefile/models-gen.go b/codegen/testserver/singlefile/models-gen.go index 21805c19415..f35822ff71a 100644 --- a/codegen/testserver/singlefile/models-gen.go +++ b/codegen/testserver/singlefile/models-gen.go @@ -90,6 +90,10 @@ type EmbeddedDefaultScalar struct { Value *string `json:"value"` } +type FieldsOrderPayload struct { + FirstFieldValue *string `json:"firstFieldValue"` +} + type InnerDirectives struct { Message string `json:"message"` } diff --git a/codegen/testserver/singlefile/resolver.go b/codegen/testserver/singlefile/resolver.go index 3bd3c189754..d203976f6c8 100644 --- a/codegen/testserver/singlefile/resolver.go +++ b/codegen/testserver/singlefile/resolver.go @@ -57,6 +57,11 @@ func (r *mutationResolver) DefaultInput(ctx context.Context, input DefaultInput) panic("not implemented") } +// // foo +func (r *mutationResolver) OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) { + panic("not implemented") +} + // // foo func (r *mutationResolver) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) { panic("not implemented") diff --git a/codegen/testserver/singlefile/stub.go b/codegen/testserver/singlefile/stub.go index 40305096641..d61151583fc 100644 --- a/codegen/testserver/singlefile/stub.go +++ b/codegen/testserver/singlefile/stub.go @@ -28,9 +28,10 @@ type Stub struct { ResolverField func(ctx context.Context, obj *ModelMethods) (bool, error) } MutationResolver struct { - DefaultInput func(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) - UpdateSomething func(ctx context.Context, input SpecialInput) (string, error) - UpdatePtrToPtr func(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) + DefaultInput func(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) + OverrideValueViaInput func(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) + UpdateSomething func(ctx context.Context, input SpecialInput) (string, error) + UpdatePtrToPtr func(ctx context.Context, input UpdatePtrToPtrOuter) (*PtrToPtrOuter, error) } OverlappingFieldsResolver struct { OldFoo func(ctx context.Context, obj *OverlappingFields) (int, error) @@ -136,6 +137,10 @@ type Stub struct { WrappedSliceResolver struct { Get func(ctx context.Context, obj WrappedSlice, idx int) (string, error) } + + FieldsOrderInputResolver struct { + OverrideFirstField func(ctx context.Context, obj *FieldsOrderInput, data *string) error + } } func (r *Stub) BackedByInterface() BackedByInterfaceResolver { @@ -184,6 +189,10 @@ func (r *Stub) WrappedSlice() WrappedSliceResolver { return &stubWrappedSlice{r} } +func (r *Stub) FieldsOrderInput() FieldsOrderInputResolver { + return &stubFieldsOrderInput{r} +} + type stubBackedByInterface struct{ *Stub } func (r *stubBackedByInterface) ID(ctx context.Context, obj BackedByInterface) (string, error) { @@ -225,6 +234,9 @@ type stubMutation struct{ *Stub } func (r *stubMutation) DefaultInput(ctx context.Context, input DefaultInput) (*DefaultParametersMirror, error) { return r.MutationResolver.DefaultInput(ctx, input) } +func (r *stubMutation) OverrideValueViaInput(ctx context.Context, input FieldsOrderInput) (*FieldsOrderPayload, error) { + return r.MutationResolver.OverrideValueViaInput(ctx, input) +} func (r *stubMutation) UpdateSomething(ctx context.Context, input SpecialInput) (string, error) { return r.MutationResolver.UpdateSomething(ctx, input) } @@ -513,3 +525,9 @@ type stubWrappedSlice struct{ *Stub } func (r *stubWrappedSlice) Get(ctx context.Context, obj WrappedSlice, idx int) (string, error) { return r.WrappedSliceResolver.Get(ctx, obj, idx) } + +type stubFieldsOrderInput struct{ *Stub } + +func (r *stubFieldsOrderInput) OverrideFirstField(ctx context.Context, obj *FieldsOrderInput, data *string) error { + return r.FieldsOrderInputResolver.OverrideFirstField(ctx, obj, data) +} diff --git a/integration/generated.go b/integration/generated.go index b8a3bfe4810..2190f107539 100644 --- a/integration/generated.go +++ b/integration/generated.go @@ -2967,7 +2967,12 @@ func (ec *executionContext) unmarshalInputDateFilter(ctx context.Context, obj in asMap["op"] = "EQ" } - for k, v := range asMap { + fieldsInOrder := [...]string{"value", "timezone", "op"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "value": var err error @@ -3006,7 +3011,12 @@ func (ec *executionContext) unmarshalInputListCoercion(ctx context.Context, obj asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"enumVal", "strVal", "intVal", "scalarVal"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "enumVal": var err error diff --git a/plugin/federation/testdata/entityresolver/generated/exec.go b/plugin/federation/testdata/entityresolver/generated/exec.go index 8a29fa3f15b..a4b3514fed8 100644 --- a/plugin/federation/testdata/entityresolver/generated/exec.go +++ b/plugin/federation/testdata/entityresolver/generated/exec.go @@ -5772,7 +5772,12 @@ func (ec *executionContext) unmarshalInputMultiHelloByNamesInput(ctx context.Con asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"Name"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "Name": var err error @@ -5795,7 +5800,12 @@ func (ec *executionContext) unmarshalInputMultiHelloMultipleRequiresByNamesInput asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"Name"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "Name": var err error @@ -5818,7 +5828,12 @@ func (ec *executionContext) unmarshalInputMultiHelloRequiresByNamesInput(ctx con asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"Name"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "Name": var err error @@ -5841,7 +5856,12 @@ func (ec *executionContext) unmarshalInputMultiHelloWithErrorByNamesInput(ctx co asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"Name"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "Name": var err error @@ -5864,7 +5884,12 @@ func (ec *executionContext) unmarshalInputMultiPlanetRequiresNestedByNamesInput( asMap[k] = v } - for k, v := range asMap { + fieldsInOrder := [...]string{"Name"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } switch k { case "Name": var err error diff --git a/plugin/stubgen/stubs.gotpl b/plugin/stubgen/stubs.gotpl index 6b4291e4e90..47a32e9024f 100644 --- a/plugin/stubgen/stubs.gotpl +++ b/plugin/stubgen/stubs.gotpl @@ -26,6 +26,17 @@ type {{$root.TypeName}} struct { } {{- end }} {{- end }} + {{range $object := .Inputs -}} + {{- if $object.HasResolvers }} + {{$object.Name}}Resolver struct { + {{- range $field := $object.Fields }} + {{- if $field.IsResolver }} + {{- $field.GoFieldName}} func{{ $field.ShortResolverDeclaration }} + {{ end }} + {{- end }} + } + {{- end }} + {{- end }} } {{ range $object := .Objects -}} @@ -35,6 +46,13 @@ type {{$root.TypeName}} struct { } {{ end -}} {{ end }} +{{ range $object := .Inputs -}} + {{- if $object.HasResolvers -}} + func (r *{{$.TypeName}}) {{$object.Name}}() {{ $object.ResolverInterface | ref }} { + return &{{lcFirst $root.TypeName}}{{$object.Name}}{r} + } + {{ end -}} +{{ end }} {{ range $object := .Objects -}} {{- if $object.HasResolvers -}} @@ -54,3 +72,16 @@ type {{$root.TypeName}} struct { {{ end -}} {{ end -}} {{ end }} +{{ range $object := .Inputs -}} + {{- if $object.HasResolvers -}} + type {{lcFirst $root.TypeName}}{{$object.Name}} struct { *{{$root.TypeName}} } + + {{ range $field := $object.Fields -}} + {{- if $field.IsResolver -}} + func (r *{{lcFirst $root.TypeName}}{{$object.Name}}) {{$field.GoFieldName}}{{ $field.ShortResolverDeclaration }} { + return r.{{$object.Name}}Resolver.{{$field.GoFieldName}}(ctx, obj, data) + } + {{ end -}} + {{ end -}} + {{ end -}} +{{ end }}