Created
September 29, 2019 15:53
-
-
Save koblas/e4445009dc283ced30c34c6658b939c5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package resolver | |
import ( | |
"reflect" | |
"strings" | |
"github.com/graphql-go/graphql" | |
"github.com/mitchellh/mapstructure" | |
"gopkg.in/asaskevich/govalidator.v4" | |
) | |
func flattenErrors(validationErrors []ValidationError, errs govalidator.Errors) []ValidationError { | |
for _, e := range errs { | |
if ge, ok := e.(govalidator.Error); ok { | |
validationErrors = append(validationErrors, ValidationError{ | |
strings.ToLower(ge.Name), | |
ge.Err.Error(), | |
}) | |
} else if ge, ok := e.(govalidator.Errors); ok { | |
validationErrors = flattenErrors(validationErrors, ge) | |
} | |
} | |
return validationErrors | |
} | |
func wrapGraphQL(wrap interface{}) func(p graphql.ResolveParams) (interface{}, error) { | |
return wrapLog(func(p graphql.ResolveParams) (interface{}, error) { | |
// Get the Value of the argument, so we can Call(...) it later | |
fValue := reflect.ValueOf(wrap) | |
// The type of the argument | |
fType := reflect.TypeOf(wrap) | |
// Basic checking that we're matching the expected arguments | |
if fType.Kind() != reflect.Func { | |
panic("Not a function") | |
} | |
// Expect a function that is | |
// (context.Context, struct{}, []*validationErrors) == 3 arguments | |
// OR (context.Context, struct{}, []*validationErrors, graphql.ResolveParams) == 3 arguments | |
if fType.NumIn() != 3 && fType.NumIn() != 4 { | |
panic("Wrong number of arguments") | |
} | |
// Construct the struct{} argument | |
arg := reflect.New(fType.In(1)) | |
if err := mapstructure.Decode(p.Args, arg.Interface()); err != nil { | |
return nil, err | |
} | |
// Handle validation | |
var validationErrors []ValidationError | |
if result, err := govalidator.ValidateStruct(arg.Interface()); err != nil || !result { | |
if gerrs, ok := err.(govalidator.Errors); !ok { | |
// Unknown error from govalidator | |
return nil, err | |
} else { | |
validationErrors = flattenErrors(validationErrors, gerrs) | |
} | |
} | |
var result []reflect.Value | |
if fType.NumIn() == 3 { | |
// Call the wrapped function | |
result = fValue.Call([]reflect.Value{ | |
reflect.ValueOf(p.Context), | |
reflect.Indirect(arg), | |
reflect.ValueOf(validationErrors), | |
}) | |
} else { | |
result = fValue.Call([]reflect.Value{ | |
reflect.ValueOf(p.Context), | |
reflect.Indirect(arg), | |
reflect.ValueOf(validationErrors), | |
reflect.ValueOf(p), | |
}) | |
} | |
// See if we've got errors otherwise return nil | |
eResult := result[1].Interface() | |
if eResult != nil { | |
return result[0].Interface(), eResult.(error) | |
} | |
return result[0].Interface(), nil | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment