diff --git a/codegen/testserver/generated.go b/codegen/testserver/generated.go index 3eb743e9b26..7d941db3a31 100644 --- a/codegen/testserver/generated.go +++ b/codegen/testserver/generated.go @@ -132,6 +132,7 @@ type ComplexityRoot struct { Autobind func(childComplexity int) int DeprecatedField func(childComplexity int) int Panics func(childComplexity int) int + DefaultScalar func(childComplexity int, arg string) int ValidType func(childComplexity int) int } @@ -194,6 +195,7 @@ type QueryResolver interface { Autobind(ctx context.Context) (*Autobind, error) DeprecatedField(ctx context.Context) (string, error) Panics(ctx context.Context) (*Panics, error) + DefaultScalar(ctx context.Context, arg string) (string, error) ValidType(ctx context.Context) (*ValidType, error) } type SubscriptionResolver interface { @@ -594,6 +596,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Panics(childComplexity), true + case "Query.DefaultScalar": + if e.complexity.Query.DefaultScalar == nil { + break + } + + args, err := ec.field_Query_defaultScalar_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.DefaultScalar(childComplexity, args["arg"].(string)), true + case "Query.ValidType": if e.complexity.Query.ValidType == nil { break @@ -838,6 +852,13 @@ type Panics { } scalar MarshalPanic +`}, + &ast.Source{Name: "scalar_default.graphql", Input: `extend type Query { + defaultScalar(arg: DefaultScalarImplementation! = "default"): DefaultScalarImplementation! +} + +""" This doesnt have an implementation in the typemap, so it should act like a string """ +scalar DefaultScalarImplementation `}, &ast.Source{Name: "schema.graphql", Input: `type Query { invalidIdentifier: InvalidIdentifier @@ -1136,6 +1157,20 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query_defaultScalar_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["arg"]; ok { + arg0, err = ec.unmarshalNDefaultScalarImplementation2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["arg"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_directiveArg_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2768,6 +2803,39 @@ 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_defaultScalar(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, + } + ctx = graphql.WithResolverContext(ctx, rctx) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_defaultScalar_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + rctx.Args = args + 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().DefaultScalar(rctx, args["arg"].(string)) + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNDefaultScalarImplementation2string(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_validType(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -4993,6 +5061,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr res = ec._Query_panics(ctx, field) return res }) + case "defaultScalar": + 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_defaultScalar(ctx, field) + if res == graphql.Null { + invalid = true + } + return res + }) case "validType": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -5412,6 +5494,14 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return graphql.MarshalBoolean(v) } +func (ec *executionContext) unmarshalNDefaultScalarImplementation2string(ctx context.Context, v interface{}) (string, error) { + return graphql.UnmarshalString(v) +} + +func (ec *executionContext) marshalNDefaultScalarImplementation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + return graphql.MarshalString(v) +} + func (ec *executionContext) unmarshalNID2int(ctx context.Context, v interface{}) (int, error) { return graphql.UnmarshalIntID(v) } diff --git a/codegen/testserver/resolver.go b/codegen/testserver/resolver.go index fc062c5f01f..4c1e2294063 100644 --- a/codegen/testserver/resolver.go +++ b/codegen/testserver/resolver.go @@ -116,6 +116,9 @@ func (r *queryResolver) DeprecatedField(ctx context.Context) (string, error) { func (r *queryResolver) Panics(ctx context.Context) (*Panics, error) { panic("not implemented") } +func (r *queryResolver) DefaultScalar(ctx context.Context, arg string) (string, error) { + panic("not implemented") +} func (r *queryResolver) ValidType(ctx context.Context) (*ValidType, error) { panic("not implemented") } diff --git a/codegen/testserver/scalar_default.graphql b/codegen/testserver/scalar_default.graphql new file mode 100644 index 00000000000..56495bad727 --- /dev/null +++ b/codegen/testserver/scalar_default.graphql @@ -0,0 +1,6 @@ +extend type Query { + defaultScalar(arg: DefaultScalarImplementation! = "default"): DefaultScalarImplementation! +} + +""" This doesnt have an implementation in the typemap, so it should act like a string """ +scalar DefaultScalarImplementation diff --git a/codegen/testserver/scalar_default_test.go b/codegen/testserver/scalar_default_test.go new file mode 100644 index 00000000000..4b438560ceb --- /dev/null +++ b/codegen/testserver/scalar_default_test.go @@ -0,0 +1,34 @@ +package testserver + +import ( + "context" + "net/http/httptest" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/handler" + "github.com/stretchr/testify/require" +) + +func TestDefaultScalarImplementation(t *testing.T) { + resolvers := &Stub{} + + srv := httptest.NewServer(handler.GraphQL(NewExecutableSchema(Config{Resolvers: resolvers}))) + c := client.New(srv.URL) + + resolvers.QueryResolver.DefaultScalar = func(ctx context.Context, arg string) (i string, e error) { + return arg, nil + } + + t.Run("with arg value", func(t *testing.T) { + var resp struct{ DefaultScalar string } + c.MustPost(`query { defaultScalar(arg: "fff") }`, &resp) + require.Equal(t, "fff", resp.DefaultScalar) + }) + + t.Run("with default value", func(t *testing.T) { + var resp struct{ DefaultScalar string } + c.MustPost(`query { defaultScalar }`, &resp) + require.Equal(t, "default", resp.DefaultScalar) + }) +} diff --git a/codegen/testserver/stub.go b/codegen/testserver/stub.go index 783f8aff58a..4388ad0dd69 100644 --- a/codegen/testserver/stub.go +++ b/codegen/testserver/stub.go @@ -42,6 +42,7 @@ type Stub struct { Autobind func(ctx context.Context) (*Autobind, error) DeprecatedField func(ctx context.Context) (string, error) Panics func(ctx context.Context) (*Panics, error) + DefaultScalar func(ctx context.Context, arg string) (string, error) ValidType func(ctx context.Context) (*ValidType, error) } SubscriptionResolver struct { @@ -158,6 +159,9 @@ func (r *stubQuery) DeprecatedField(ctx context.Context) (string, error) { func (r *stubQuery) Panics(ctx context.Context) (*Panics, error) { return r.QueryResolver.Panics(ctx) } +func (r *stubQuery) DefaultScalar(ctx context.Context, arg string) (string, error) { + return r.QueryResolver.DefaultScalar(ctx, arg) +} func (r *stubQuery) ValidType(ctx context.Context) (*ValidType, error) { return r.QueryResolver.ValidType(ctx) } diff --git a/plugin/modelgen/models.go b/plugin/modelgen/models.go index 2be7dfb2cfa..2c9a6fb3c49 100644 --- a/plugin/modelgen/models.go +++ b/plugin/modelgen/models.go @@ -4,10 +4,9 @@ import ( "go/types" "sort" - "github.com/99designs/gqlgen/internal/code" - "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" + "github.com/99designs/gqlgen/internal/code" "github.com/99designs/gqlgen/plugin" "github.com/vektah/gqlparser/ast" ) @@ -17,6 +16,7 @@ type ModelBuild struct { Interfaces []*Interface Models []*Object Enums []*Enum + Scalars []string } type Interface struct { @@ -159,6 +159,8 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { } b.Enums = append(b.Enums, it) + case ast.Scalar: + b.Scalars = append(b.Scalars, schemaType.Name) } } @@ -175,6 +177,9 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { for _, it := range b.Interfaces { cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+it.Name) } + for _, it := range b.Scalars { + cfg.Models.Add(it, "github.com/99designs/gqlgen/graphql.String") + } if len(b.Models) == 0 && len(b.Enums) == 0 { return nil