From 27866aea9497a979b1421fbb09d4ccd73aa744e2 Mon Sep 17 00:00:00 2001 From: agungdwiprasetyo Date: Thu, 14 Sep 2023 11:36:10 +0700 Subject: [PATCH] graphql: enhance set root resolver --- .../app/graphql_server/graphql_handler.go | 50 +++++++++++-------- codebase/app/graphql_server/option.go | 25 ++-------- codebase/app/graphql_server/root_resolver.go | 10 ++-- init.go | 2 +- 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/codebase/app/graphql_server/graphql_handler.go b/codebase/app/graphql_server/graphql_handler.go index c14f49db..1b78420b 100644 --- a/codebase/app/graphql_server/graphql_handler.go +++ b/codebase/app/graphql_server/graphql_handler.go @@ -31,31 +31,33 @@ type Handler interface { // ConstructHandlerFromService for create public graphql handler (maybe inject to rest handler) func ConstructHandlerFromService(service factory.ServiceFactory, opt Option) Handler { - // create dynamic struct - queryResolverValues := make(map[string]interface{}) - mutationResolverValues := make(map[string]interface{}) - subscriptionResolverValues := make(map[string]interface{}) - var queryResolverFields, mutationResolverFields, subscriptionResolverFields []reflect.StructField - for _, m := range service.GetModules() { - if resolverModule := m.GraphQLHandler(); resolverModule != nil { - rootName := string(m.Name()) - query, mutation, subscription := resolverModule.Query(), resolverModule.Mutation(), resolverModule.Subscription() + if opt.rootResolver == nil { + // create dynamic struct + queryResolverValues := make(map[string]interface{}) + mutationResolverValues := make(map[string]interface{}) + subscriptionResolverValues := make(map[string]interface{}) + var queryResolverFields, mutationResolverFields, subscriptionResolverFields []reflect.StructField + for _, m := range service.GetModules() { + if resolverModule := m.GraphQLHandler(); resolverModule != nil { + rootName := string(m.Name()) + query, mutation, subscription := resolverModule.Query(), resolverModule.Mutation(), resolverModule.Subscription() - appendStructField(rootName, query, &queryResolverFields) - appendStructField(rootName, mutation, &mutationResolverFields) - appendStructField(rootName, subscription, &subscriptionResolverFields) + appendStructField(rootName, query, &queryResolverFields) + appendStructField(rootName, mutation, &mutationResolverFields) + appendStructField(rootName, subscription, &subscriptionResolverFields) - queryResolverValues[rootName] = query - mutationResolverValues[rootName] = mutation - subscriptionResolverValues[rootName] = subscription + queryResolverValues[rootName] = query + mutationResolverValues[rootName] = mutation + subscriptionResolverValues[rootName] = subscription + } + } + opt.rootResolver = &rootResolver{ + rootQuery: constructStruct(queryResolverFields, queryResolverValues), + rootMutation: constructStruct(mutationResolverFields, mutationResolverValues), + rootSubscription: constructStruct(subscriptionResolverFields, subscriptionResolverValues), } } - opt.rootResolver.rootQuery = constructStruct(queryResolverFields, queryResolverValues) - opt.rootResolver.rootMutation = constructStruct(mutationResolverFields, mutationResolverValues) - opt.rootResolver.rootSubscription = constructStruct(subscriptionResolverFields, subscriptionResolverValues) - gqlSchema := candihelper.LoadAllFile(os.Getenv(candihelper.WORKDIR)+"api/graphql", ".graphql") - // default directive directiveFuncs := map[string]gqltypes.DirectiveFunc{ "auth": service.GetDependency().GetMiddleware().GraphQLAuth, @@ -76,7 +78,13 @@ func ConstructHandlerFromService(service factory.ServiceFactory, opt Option) Han // handling vulnerabilities exploit schema schemaOpts = append(schemaOpts, graphql.DisableIntrospection()) } - schema := graphql.MustParseSchema(string(gqlSchema), &opt.rootResolver, schemaOpts...) + + gqlSchema := candihelper.LoadAllFile(os.Getenv(candihelper.WORKDIR)+"api/graphql", ".graphql") + schema := graphql.MustParseSchema(string(gqlSchema), &rootResolver{ + rootQuery: opt.rootResolver.Query(), + rootMutation: opt.rootResolver.Mutation(), + rootSubscription: opt.rootResolver.Subscription(), + }, schemaOpts...) logger.LogYellow(fmt.Sprintf("[GraphQL] endpoint\t\t\t: http://127.0.0.1:%d%s", opt.httpPort, opt.RootPath)) logger.LogYellow(fmt.Sprintf("[GraphQL] playground\t\t\t: http://127.0.0.1:%d%s/playground", opt.httpPort, opt.RootPath)) diff --git a/codebase/app/graphql_server/option.go b/codebase/app/graphql_server/option.go index 225d9e10..be87624e 100644 --- a/codebase/app/graphql_server/option.go +++ b/codebase/app/graphql_server/option.go @@ -4,6 +4,7 @@ import ( "net/http" "strings" + "github.com/golangid/candi/codebase/interfaces" "github.com/golangid/candi/wrapper" "github.com/golangid/graphql-go/types" "github.com/soheilhy/cmux" @@ -20,7 +21,7 @@ type ( jaegerMaxPacketSize int rootHandler http.Handler sharedListener cmux.CMux - rootResolver RootResolver + rootResolver interfaces.GraphQLHandler directiveFuncs map[string]types.DirectiveFunc } @@ -89,26 +90,10 @@ func SetJaegerMaxPacketSize(max int) OptionFunc { } } -// SetRootQuery option func -func SetRootQuery(resolver interface{}) OptionFunc { +// SetRootResolver option func +func SetRootResolver(resolver interfaces.GraphQLHandler) OptionFunc { return func(o *Option) { - o.rootResolver.rootQuery = resolver - } -} - -// SetRootMutation option func -func SetRootMutation(resolver interface{}) OptionFunc { - return func(o *Option) { - o.rootResolver.rootMutation = resolver - } -} - -// SetRootSubscription public function -// this public method created because cannot create dynamic method for embedded struct (issue https://github.com/golang/go/issues/15924) -// and subscription in graphql cannot subscribe to at most one subscription at a time -func SetRootSubscription(resolver interface{}) OptionFunc { - return func(o *Option) { - o.rootResolver.rootSubscription = resolver + o.rootResolver = resolver } } diff --git a/codebase/app/graphql_server/root_resolver.go b/codebase/app/graphql_server/root_resolver.go index 8efe9682..1c2cc8d4 100644 --- a/codebase/app/graphql_server/root_resolver.go +++ b/codebase/app/graphql_server/root_resolver.go @@ -2,21 +2,21 @@ package graphqlserver import "reflect" -// RootResolver root +// rootResolver root // issue https://github.com/graph-gophers/graphql-go/issues/145 -type RootResolver struct { +type rootResolver struct { rootQuery interface{} rootMutation interface{} rootSubscription interface{} } -func (r *RootResolver) Query() interface{} { +func (r *rootResolver) Query() interface{} { return r.rootQuery } -func (r *RootResolver) Mutation() interface{} { +func (r *rootResolver) Mutation() interface{} { return r.rootMutation } -func (r *RootResolver) Subscription() interface{} { +func (r *rootResolver) Subscription() interface{} { return r.rootSubscription } diff --git a/init.go b/init.go index d9e39e1d..237435fc 100644 --- a/init.go +++ b/init.go @@ -2,5 +2,5 @@ package candi const ( // Version of this library - Version = "v1.15.8" + Version = "v1.15.9" )