Skip to content

Commit

Permalink
POC: allow users to get requested fields from context
Browse files Browse the repository at this point in the history
This POC could solve #17
  • Loading branch information
Nick Randall committed Mar 21, 2017
1 parent 2e23573 commit 7a0c87b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
9 changes: 9 additions & 0 deletions graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,12 @@ func (s *Schema) ToJSON() ([]byte, error) {
}
return json.MarshalIndent(result, "", "\t")
}

// GetFieldsFromContext can be used in resolvers to get the fields that were requested in the currenty query for the current type
func GetFieldsFromContext(ctx context.Context) exec.FieldList {
fields, ok := ctx.Value(exec.ResolverFields).(exec.FieldList)
if !ok {
panic("Could not get graphql fields from context")
}
return fields
}
31 changes: 30 additions & 1 deletion internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const OpenTracingTagTrivial = "graphql.trivial"
const OpenTracingTagArgsPrefix = "graphql.args."
const OpenTracingTagError = "graphql.error"

type contextKey string
type FieldList map[string]FieldList

const ResolverFields contextKey = "Resolver_Fields"

type Exec struct {
queryExec iExec
mutationExec iExec
Expand Down Expand Up @@ -498,8 +503,9 @@ func (e *objectExec) execSelectionSet(ctx context.Context, r *request, selSet *q
continue
}

namedFields := resolveFieldNames(make(FieldList), sel.SelSet, r.doc)
execSel(func() {
e.execField(ctx, r, sel, resolver, addResult)
e.execField(context.WithValue(ctx, ResolverFields, namedFields), r, sel, resolver, addResult)
})

case *query.FragmentSpread:
Expand Down Expand Up @@ -533,6 +539,29 @@ func (e *objectExec) execSelectionSet(ctx context.Context, r *request, selSet *q
wg.Wait()
}

func resolveFieldNames(namedFields FieldList, selSet *query.SelectionSet, doc *query.Document) FieldList {
if selSet != nil {
for _, selectionField := range selSet.Selections {
switch selectionField := selectionField.(type) {
case *query.Field:
namedFields[selectionField.Name] = make(FieldList)
resolveFieldNames(namedFields[selectionField.Name], selectionField.SelSet, doc)
case *query.FragmentSpread:
frag, ok := doc.Fragments[selectionField.Name]
if !ok {
panic(fmt.Errorf("fragment %q not found", selectionField.Name)) // TODO proper error handling
}
resolveFieldNames(namedFields, frag.SelSet, doc)
case *query.InlineFragment:
resolveFieldNames(namedFields, selectionField.SelSet, doc)
default:
panic("invalid type")
}
}
}
return namedFields
}

func (e *objectExec) execField(ctx context.Context, r *request, f *query.Field, resolver reflect.Value, addResult addResultFn) {
switch f.Name {
case "__typename":
Expand Down

0 comments on commit 7a0c87b

Please sign in to comment.