From 1f7ed0d52ac853830c164d5d3ebbed8a77c8d710 Mon Sep 17 00:00:00 2001 From: vvakame Date: Sat, 17 Aug 2019 15:37:30 +0900 Subject: [PATCH] refactor unimplemented directive handling --- codegen/directives.gotpl | 12 +++ codegen/testserver/directive.graphql | 2 + codegen/testserver/directive_test.go | 16 +++ codegen/testserver/generated.go | 119 +++++++++++++++++++++ codegen/testserver/resolver.go | 3 + codegen/testserver/stub.go | 4 + example/chat/generated.go | 3 + example/todo/generated.go | 12 +++ example/type-system-extension/generated.go | 3 + 9 files changed, 174 insertions(+) diff --git a/codegen/directives.gotpl b/codegen/directives.gotpl index 8e11c1804dd..bdfb5aa2f77 100644 --- a/codegen/directives.gotpl +++ b/codegen/directives.gotpl @@ -14,6 +14,9 @@ } {{- end }} {{- end }} + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs $in $i }}) } {{ end -}} @@ -34,6 +37,9 @@ {{- end }} n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}}) } {{- end }} @@ -81,6 +87,9 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as {{- end }} n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}}) } {{- end }} @@ -121,6 +130,9 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as {{- end }} n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}}) } {{- end }} diff --git a/codegen/testserver/directive.graphql b/codegen/testserver/directive.graphql index 6058d8756ea..25332a9a467 100644 --- a/codegen/testserver/directive.graphql +++ b/codegen/testserver/directive.graphql @@ -5,6 +5,7 @@ directive @logged(id: UUID!) on FIELD directive @toNull on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION directive @directive1 on FIELD_DEFINITION directive @directive2 on FIELD_DEFINITION +directive @unimplemented on FIELD_DEFINITION extend type Query { directiveArg(arg: String! @length(min:1, max: 255, message: "invalid length")): String @@ -16,6 +17,7 @@ extend type Query { directiveFieldDef(ret: String!): String! @length(min: 1, message: "not valid") directiveField: String directiveDouble: String @directive1 @directive2 + directiveUnimplemented: String @unimplemented } input InputDirectives { diff --git a/codegen/testserver/directive_test.go b/codegen/testserver/directive_test.go index e4815d3707c..e531e2b1893 100644 --- a/codegen/testserver/directive_test.go +++ b/codegen/testserver/directive_test.go @@ -60,6 +60,11 @@ func TestDirectives(t *testing.T) { return &s, nil } + resolvers.QueryResolver.DirectiveUnimplemented = func(ctx context.Context) (*string, error) { + s := "Ok" + return &s, nil + } + srv := httptest.NewServer( handler.GraphQL( NewExecutableSchema(Config{ @@ -137,6 +142,7 @@ func TestDirectives(t *testing.T) { Directive2: func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { return next(ctx) }, + Unimplemented: nil, }, }), handler.ResolverMiddleware(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { @@ -227,6 +233,16 @@ func TestDirectives(t *testing.T) { require.Equal(t, "Ok", resp.DirectiveDouble) }) + t.Run("directive is not implemented", func(t *testing.T) { + var resp struct { + DirectiveUnimplemented string + } + + err := c.Post(`query { directiveUnimplemented }`, &resp) + + require.EqualError(t, err, `[{"message":"directive unimplemented is not implemented","path":["directiveUnimplemented"]}]`) + }) + t.Run("ok", func(t *testing.T) { var resp struct { DirectiveFieldDef string diff --git a/codegen/testserver/generated.go b/codegen/testserver/generated.go index 72fef86ffce..80b3e3e22d5 100644 --- a/codegen/testserver/generated.go +++ b/codegen/testserver/generated.go @@ -65,6 +65,8 @@ type DirectiveRoot struct { Range func(ctx context.Context, obj interface{}, next graphql.Resolver, min *int, max *int) (res interface{}, err error) ToNull func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) + + Unimplemented func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) } type ComplexityRoot struct { @@ -214,6 +216,7 @@ type ComplexityRoot struct { DirectiveInputType func(childComplexity int, arg InnerInput) int DirectiveNullableArg func(childComplexity int, arg *int, arg2 *int, arg3 *string) int DirectiveObject func(childComplexity int) int + DirectiveUnimplemented func(childComplexity int) int ErrorBubble func(childComplexity int) int Errors func(childComplexity int) int Fallback func(childComplexity int, arg FallbackToStringEncoding) int @@ -349,6 +352,7 @@ type QueryResolver interface { DirectiveFieldDef(ctx context.Context, ret string) (string, error) DirectiveField(ctx context.Context) (*string, error) DirectiveDouble(ctx context.Context) (*string, error) + DirectiveUnimplemented(ctx context.Context) (*string, error) MapStringInterface(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) ErrorBubble(ctx context.Context) (*Error, error) Errors(ctx context.Context) (*Errors, error) @@ -881,6 +885,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.DirectiveObject(childComplexity), true + case "Query.directiveUnimplemented": + if e.complexity.Query.DirectiveUnimplemented == nil { + break + } + + return e.complexity.Query.DirectiveUnimplemented(childComplexity), true + case "Query.errorBubble": if e.complexity.Query.ErrorBubble == nil { break @@ -1373,6 +1384,7 @@ directive @logged(id: UUID!) on FIELD directive @toNull on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | FIELD_DEFINITION directive @directive1 on FIELD_DEFINITION directive @directive2 on FIELD_DEFINITION +directive @unimplemented on FIELD_DEFINITION extend type Query { directiveArg(arg: String! @length(min:1, max: 255, message: "invalid length")): String @@ -1384,6 +1396,7 @@ extend type Query { directiveFieldDef(ret: String!): String! @length(min: 1, message: "not valid") directiveField: String directiveDouble: String @directive1 @directive2 + directiveUnimplemented: String @unimplemented } input InputDirectives { @@ -1880,6 +1893,9 @@ func (ec *executionContext) field_Query_directiveArg_args(ctx context.Context, r if err != nil { return nil, err } + if ec.directives.Length == nil { + return nil, errors.New("directive length is not implemented") + } return ec.directives.Length(ctx, rawArgs, directive0, min, max, message) } @@ -1934,6 +1950,9 @@ func (ec *executionContext) field_Query_directiveInputType_args(ctx context.Cont return ec.unmarshalNInnerInput2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚐInnerInput(ctx, tmp) } directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.Custom == nil { + return nil, errors.New("directive custom is not implemented") + } return ec.directives.Custom(ctx, rawArgs, directive0) } @@ -1976,6 +1995,9 @@ func (ec *executionContext) field_Query_directiveNullableArg_args(ctx context.Co if err != nil { return nil, err } + if ec.directives.Range == nil { + return nil, errors.New("directive range is not implemented") + } return ec.directives.Range(ctx, rawArgs, directive0, min, nil) } @@ -2000,6 +2022,9 @@ func (ec *executionContext) field_Query_directiveNullableArg_args(ctx context.Co if err != nil { return nil, err } + if ec.directives.Range == nil { + return nil, errors.New("directive range is not implemented") + } return ec.directives.Range(ctx, rawArgs, directive0, min, nil) } @@ -2020,6 +2045,9 @@ func (ec *executionContext) field_Query_directiveNullableArg_args(ctx context.Co if tmp, ok := rawArgs["arg3"]; ok { directive0 := func(ctx context.Context) (interface{}, error) { return ec.unmarshalOString2ᚖstring(ctx, tmp) } directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.ToNull == nil { + return nil, errors.New("directive toNull is not implemented") + } return ec.directives.ToNull(ctx, rawArgs, directive0) } @@ -2424,6 +2452,9 @@ func (ec *executionContext) _fieldMiddleware(ctx context.Context, obj interface{ } n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.Logged == nil { + return nil, errors.New("directive logged is not implemented") + } return ec.directives.Logged(ctx, obj, n, args["id"].(string)) } } @@ -3718,6 +3749,9 @@ func (ec *executionContext) _ObjectDirectives_text(ctx context.Context, field gr if err != nil { return nil, err } + if ec.directives.Length == nil { + return nil, errors.New("directive length is not implemented") + } return ec.directives.Length(ctx, obj, directive0, min, max, message) } @@ -3766,6 +3800,9 @@ func (ec *executionContext) _ObjectDirectives_nullableText(ctx context.Context, return obj.NullableText, nil } directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.ToNull == nil { + return nil, errors.New("directive toNull is not implemented") + } return ec.directives.ToNull(ctx, obj, directive0) } @@ -5058,6 +5095,9 @@ func (ec *executionContext) _Query_directiveFieldDef(ctx context.Context, field if err != nil { return nil, err } + if ec.directives.Length == nil { + return nil, errors.New("directive length is not implemented") + } return ec.directives.Length(ctx, nil, directive0, min, nil, message) } @@ -5137,9 +5177,15 @@ func (ec *executionContext) _Query_directiveDouble(ctx context.Context, field gr return ec.resolvers.Query().DirectiveDouble(rctx) } directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.Directive1 == nil { + return nil, errors.New("directive directive1 is not implemented") + } return ec.directives.Directive1(ctx, nil, directive0) } directive2 := func(ctx context.Context) (interface{}, error) { + if ec.directives.Directive2 == nil { + return nil, errors.New("directive directive2 is not implemented") + } return ec.directives.Directive2(ctx, nil, directive1) } @@ -5164,6 +5210,56 @@ func (ec *executionContext) _Query_directiveDouble(ctx context.Context, field gr return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } +func (ec *executionContext) _Query_directiveUnimplemented(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + 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) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().DirectiveUnimplemented(rctx) + } + directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.Unimplemented == nil { + return nil, errors.New("directive unimplemented is not implemented") + } + return ec.directives.Unimplemented(ctx, nil, directive0) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, err + } + if data, ok := tmp.(*string); ok { + return data, nil + } else if tmp == nil { + return nil, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_mapStringInterface(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { @@ -7548,6 +7644,9 @@ func (ec *executionContext) unmarshalInputInnerDirectives(ctx context.Context, o if err != nil { return nil, err } + if ec.directives.Length == nil { + return nil, errors.New("directive length is not implemented") + } return ec.directives.Length(ctx, obj, directive0, min, nil, message) } @@ -7606,6 +7705,9 @@ func (ec *executionContext) unmarshalInputInputDirectives(ctx context.Context, o if err != nil { return nil, err } + if ec.directives.Length == nil { + return nil, errors.New("directive length is not implemented") + } return ec.directives.Length(ctx, obj, directive0, min, max, message) } @@ -7622,6 +7724,9 @@ func (ec *executionContext) unmarshalInputInputDirectives(ctx context.Context, o var err error directive0 := func(ctx context.Context) (interface{}, error) { return ec.unmarshalOString2ᚖstring(ctx, v) } directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.ToNull == nil { + return nil, errors.New("directive toNull is not implemented") + } return ec.directives.ToNull(ctx, obj, directive0) } @@ -7662,6 +7767,9 @@ func (ec *executionContext) unmarshalInputInputDirectives(ctx context.Context, o if err != nil { return nil, err } + if ec.directives.Length == nil { + return nil, errors.New("directive length is not implemented") + } return ec.directives.Length(ctx, obj, directive0, min, max, nil) } @@ -9206,6 +9314,17 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr res = ec._Query_directiveDouble(ctx, field) return res }) + case "directiveUnimplemented": + 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_directiveUnimplemented(ctx, field) + return res + }) case "mapStringInterface": field := field out.Concurrently(i, func() (res graphql.Marshaler) { diff --git a/codegen/testserver/resolver.go b/codegen/testserver/resolver.go index ede989be7cd..e89cb9e3617 100644 --- a/codegen/testserver/resolver.go +++ b/codegen/testserver/resolver.go @@ -176,6 +176,9 @@ func (r *queryResolver) DirectiveField(ctx context.Context) (*string, error) { func (r *queryResolver) DirectiveDouble(ctx context.Context) (*string, error) { panic("not implemented") } +func (r *queryResolver) DirectiveUnimplemented(ctx context.Context) (*string, error) { + panic("not implemented") +} func (r *queryResolver) MapStringInterface(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) { panic("not implemented") } diff --git a/codegen/testserver/stub.go b/codegen/testserver/stub.go index 8ede5f353c0..819fc6314ec 100644 --- a/codegen/testserver/stub.go +++ b/codegen/testserver/stub.go @@ -62,6 +62,7 @@ type Stub struct { DirectiveFieldDef func(ctx context.Context, ret string) (string, error) DirectiveField func(ctx context.Context) (*string, error) DirectiveDouble func(ctx context.Context) (*string, error) + DirectiveUnimplemented func(ctx context.Context) (*string, error) MapStringInterface func(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) ErrorBubble func(ctx context.Context) (*Error, error) Errors func(ctx context.Context) (*Errors, error) @@ -252,6 +253,9 @@ func (r *stubQuery) DirectiveField(ctx context.Context) (*string, error) { func (r *stubQuery) DirectiveDouble(ctx context.Context) (*string, error) { return r.QueryResolver.DirectiveDouble(ctx) } +func (r *stubQuery) DirectiveUnimplemented(ctx context.Context) (*string, error) { + return r.QueryResolver.DirectiveUnimplemented(ctx) +} func (r *stubQuery) MapStringInterface(ctx context.Context, in map[string]interface{}) (map[string]interface{}, error) { return r.QueryResolver.MapStringInterface(ctx, in) } diff --git a/example/chat/generated.go b/example/chat/generated.go index d57ea54ac53..78376d45395 100644 --- a/example/chat/generated.go +++ b/example/chat/generated.go @@ -432,6 +432,9 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as } n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.User == nil { + return nil, errors.New("directive user is not implemented") + } return ec.directives.User(ctx, obj, n, args["username"].(string)) } } diff --git a/example/todo/generated.go b/example/todo/generated.go index bb30fafee11..be3a864b115 100644 --- a/example/todo/generated.go +++ b/example/todo/generated.go @@ -410,6 +410,9 @@ func (ec *executionContext) _queryMiddleware(ctx context.Context, obj *ast.Opera } n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.User == nil { + return nil, errors.New("directive user is not implemented") + } return ec.directives.User(ctx, obj, n, args["id"].(int)) } } @@ -440,6 +443,9 @@ func (ec *executionContext) _mutationMiddleware(ctx context.Context, obj *ast.Op } n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.User == nil { + return nil, errors.New("directive user is not implemented") + } return ec.directives.User(ctx, obj, n, args["id"].(int)) } } @@ -470,6 +476,9 @@ func (ec *executionContext) _fieldMiddleware(ctx context.Context, obj interface{ } n := next next = func(ctx context.Context) (interface{}, error) { + if ec.directives.User == nil { + return nil, errors.New("directive user is not implemented") + } return ec.directives.User(ctx, obj, n, args["id"].(int)) } } @@ -832,6 +841,9 @@ func (ec *executionContext) _Todo_done(ctx context.Context, field graphql.Collec if err != nil { return nil, err } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } return ec.directives.HasRole(ctx, obj, directive0, role) } diff --git a/example/type-system-extension/generated.go b/example/type-system-extension/generated.go index db8a20eefab..2d83acd4cf7 100644 --- a/example/type-system-extension/generated.go +++ b/example/type-system-extension/generated.go @@ -707,6 +707,9 @@ func (ec *executionContext) _Todo_verified(ctx context.Context, field graphql.Co return obj.Verified, nil } directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.FieldLogging == nil { + return nil, errors.New("directive fieldLogging is not implemented") + } return ec.directives.FieldLogging(ctx, obj, directive0) }