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 graph-gophers#17
  • Loading branch information
Nick Randall committed Mar 21, 2017
1 parent 2e23573 commit 1534f47
Show file tree
Hide file tree
Showing 2 changed files with 38 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) []string {
fields, ok := ctx.Value(exec.GRAPHQL_FIELDS).([]string)
if !ok {
panic("Could not get graphql fields from context")
}
return fields
}
30 changes: 29 additions & 1 deletion internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const OpenTracingTagTrivial = "graphql.trivial"
const OpenTracingTagArgsPrefix = "graphql.args."
const OpenTracingTagError = "graphql.error"

type contextKey string

const GRAPHQL_FIELDS contextKey = "GRAPHQL_FIELD"

type Exec struct {
queryExec iExec
mutationExec iExec
Expand Down Expand Up @@ -494,12 +498,14 @@ func (e *objectExec) execSelectionSet(ctx context.Context, r *request, selSet *q

switch sel := sel.(type) {
case *query.Field:
var namedFields []string
if skipByDirective(r, sel.Directives) {
continue
}

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

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

func resolveFieldNames(namedFields []string, selSet *query.SelectionSet, doc *query.Document) []string {
if selSet != nil {
for _, selectionField := range selSet.Selections {
switch selectionField := selectionField.(type) {
case *query.Field:
namedFields = append(namedFields, selectionField.Name)
case *query.FragmentSpread:
frag, ok := doc.Fragments[selectionField.Name]
if !ok {
panic(fmt.Errorf("fragment %q not found", selectionField.Name)) // TODO proper error handling
}
namedFields = resolveFieldNames(namedFields, frag.SelSet, doc)
case *query.InlineFragment:
namedFields = 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 1534f47

Please sign in to comment.