Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
neelance committed Oct 25, 2016
1 parent f8cb11c commit 1a95951
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 31 deletions.
12 changes: 12 additions & 0 deletions example/starwars/starwars.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,13 @@ func (r *Resolver) Starship(args struct{ ID string }) *starshipResolver {
return nil
}

func (r *Resolver) CreateReview(args struct {
Episode string
Review *reviewInput
}) *reviewResolver {
panic("TODO")
}

type friendsConenctionArgs struct {
First int32
After string
Expand Down Expand Up @@ -618,3 +625,8 @@ func (r *pageInfoResolver) EndCursor() *string {
func (r *pageInfoResolver) HasNextPage() bool {
return r.hasNextPage
}

type reviewInput struct {
Stars int32
Commentary string
}
29 changes: 21 additions & 8 deletions graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,33 @@ func (s *Schema) Exec(ctx context.Context, queryString string, operationName str
}
}

if operationName == "" && len(d.Operations) == 1 {
for name := range d.Operations {
operationName = name
if len(d.Operations) == 0 {
return &Response{
Errors: []*errors.GraphQLError{errors.Errorf("no operations in query document")},
}
}

op, ok := d.Operations[operationName]
if !ok {
return &Response{
Errors: []*errors.GraphQLError{errors.Errorf("no operation with name %q", operationName)},
var op *query.Operation
if operationName == "" {
if len(d.Operations) > 1 {
return &Response{
Errors: []*errors.GraphQLError{errors.Errorf("more than one operation in query document and no operation name given")},
}
}
for _, op2 := range d.Operations {
op = op2
}
} else {
var ok bool
op, ok = d.Operations[operationName]
if !ok {
return &Response{
Errors: []*errors.GraphQLError{errors.Errorf("no operation with name %q", operationName)},
}
}
}

data, errs := s.exec.Exec(ctx, d, variables, op.SelSet)
data, errs := s.exec.Exec(ctx, d, variables, op)
return &Response{
Data: data,
Errors: errs,
Expand Down
29 changes: 29 additions & 0 deletions graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,35 @@ var tests = []struct {
`,
},

// {
// name: "StarWarsMutation1",
// schema: starwars.Schema,
// resolver: &starwars.Resolver{},
// query: `
// mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
// createReview(episode: $ep, review: $review) {
// stars
// commentary
// }
// }
// `,
// variables: map[string]interface{}{
// "ep": "JEDI",
// "review": map[string]interface{}{
// "stars": 5,
// "commentary": "This is a great movie!",
// },
// },
// result: `
// {
// "createReview": {
// "stars": 5,
// "commentary": "This is a great movie!"
// }
// }
// `,
// },

{
name: "StarWarsIntrospection1",
schema: starwars.Schema,
Expand Down
54 changes: 39 additions & 15 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,35 @@ import (
)

type Exec struct {
iExec
schema *schema.Schema
resolver reflect.Value
queryExec iExec
mutationExec iExec
schema *schema.Schema
resolver reflect.Value
}

func Make(s *schema.Schema, resolver interface{}) (*Exec, error) {
t := s.Types[s.EntryPoints["query"]]
e, err := makeWithType(s, t, resolver)
if err != nil {
return nil, err
}
return &Exec{
iExec: e,
e := &Exec{
schema: s,
resolver: reflect.ValueOf(resolver),
}, nil
}

if t, ok := s.EntryPoints["query"]; ok {
var err error
e.queryExec, err = makeWithType(s, t, resolver)
if err != nil {
return nil, err
}
}

if t, ok := s.EntryPoints["mutation"]; ok {
var err error
e.mutationExec, err = makeWithType(s, t, resolver)
if err != nil {
return nil, err
}
}

return e, nil
}

type typeRefMapKey struct {
Expand Down Expand Up @@ -206,6 +219,7 @@ func makeFieldExecs(s *schema.Schema, typeName string, fields map[string]*schema
for _, arg := range f.Args {
ae := &argExec{
name: arg.Name,
typ: arg.Type,
}

sf, ok := argsType.FieldByNameFunc(func(n string) bool { return strings.EqualFold(n, arg.Name) })
Expand Down Expand Up @@ -310,17 +324,25 @@ func (r *request) handlePanic() {
}
}

func (e *Exec) Exec(ctx context.Context, document *query.Document, variables map[string]interface{}, selSet *query.SelectionSet) (interface{}, []*errors.GraphQLError) {
func (e *Exec) Exec(ctx context.Context, document *query.Document, variables map[string]interface{}, op *query.Operation) (interface{}, []*errors.GraphQLError) {
r := &request{
ctx: ctx,
doc: document,
vars: variables,
schema: e.schema,
}

var opExec iExec
switch op.Type {
case query.Query:
opExec = e.queryExec
case query.Mutation:
opExec = e.mutationExec
}

data := func() interface{} {
defer r.handlePanic()
return e.exec(r, selSet, e.resolver)
return opExec.exec(r, op.SelSet, e.resolver)
}()

return data, r.errs
Expand Down Expand Up @@ -484,6 +506,7 @@ type fieldExec struct {

type argExec struct {
name string
typ schema.Type
fieldIndex []int
defaultVal reflect.Value
}
Expand All @@ -505,7 +528,8 @@ func (e *fieldExec) execField(r *request, f *query.Field, resolver reflect.Value
}
continue
}
argsValue.FieldByIndex(arg.fieldIndex).Set(reflect.ValueOf(execValue(r, value)))
v := execValue(r, value)
argsValue.FieldByIndex(arg.fieldIndex).Set(reflect.ValueOf(v))
}
in = append(in, argsValue)
}
Expand Down Expand Up @@ -562,6 +586,6 @@ func checkType(st schema.Type, rt reflect.Type) bool {
case *schema.Enum:
return rt == scalarTypes["String"]
default:
panic("TODO")
return true
}
}
6 changes: 3 additions & 3 deletions internal/exec/introspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,23 +221,23 @@ func (r *schemaResolver) Types() []*typeResolver {
}

func (r *schemaResolver) QueryType() *typeResolver {
t, ok := r.schema.Types[r.schema.EntryPoints["query"]]
t, ok := r.schema.EntryPoints["query"]
if !ok {
return nil
}
return &typeResolver{t}
}

func (r *schemaResolver) MutationType() *typeResolver {
t, ok := r.schema.Types[r.schema.EntryPoints["mutation"]]
t, ok := r.schema.EntryPoints["mutation"]
if !ok {
return nil
}
return &typeResolver{t}
}

func (r *schemaResolver) SubscriptionType() *typeResolver {
t, ok := r.schema.Types[r.schema.EntryPoints["subscription"]]
t, ok := r.schema.EntryPoints["subscription"]
if !ok {
return nil
}
Expand Down
22 changes: 17 additions & 5 deletions internal/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (
)

type Schema struct {
EntryPoints map[string]string
EntryPoints map[string]Type
Types map[string]Type

objects []*Object
unions []*Union
entryPointNames map[string]string
objects []*Object
unions []*Union
}

type Type interface {
Expand Down Expand Up @@ -114,6 +115,17 @@ func Parse(schemaString string) (s *Schema, err *errors.GraphQLError) {
}
}

s.EntryPoints = make(map[string]Type)
for key, name := range s.entryPointNames {
t, ok := s.Types[name]
if !ok {
if !ok {
return nil, errors.Errorf("type %q not found", name)
}
}
s.EntryPoints[key] = t
}

for _, obj := range s.objects {
obj.Interfaces = make([]*Interface, len(obj.interfaceNames))
for i, intfName := range obj.interfaceNames {
Expand Down Expand Up @@ -221,7 +233,7 @@ func resolveTypeRef(s *Schema, t Type) (Type, *errors.GraphQLError) {

func parseSchema(l *lexer.Lexer) *Schema {
s := &Schema{
EntryPoints: make(map[string]string),
entryPointNames: make(map[string]string),
Types: map[string]Type{
"Int": &Scalar{Name: "Int"},
"Float": &Scalar{Name: "Float"},
Expand All @@ -239,7 +251,7 @@ func parseSchema(l *lexer.Lexer) *Schema {
name := l.ConsumeIdent()
l.ConsumeToken(':')
typ := l.ConsumeIdent()
s.EntryPoints[name] = typ
s.entryPointNames[name] = typ
}
l.ConsumeToken('}')
case "type":
Expand Down

0 comments on commit 1a95951

Please sign in to comment.