Skip to content

Commit 96bb2c3

Browse files
authored
Merge pull request #5 from DealTap/expose-selection-tree
Expose selected fields in resolver context
2 parents de6fb84 + d55c751 commit 96bb2c3

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

example/social/social.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package social
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"strings"
78
"time"
9+
10+
"github.com/graph-gophers/graphql-go/selected"
811
)
912

1013
const Schema = `
@@ -51,8 +54,8 @@ const Schema = `
5154
`
5255

5356
type page struct {
54-
First *int
55-
Last *int
57+
First *float64
58+
Last *float64
5659
}
5760

5861
type admin interface {
@@ -101,11 +104,14 @@ func (u user) FriendsResolver(args struct{ Page *page }) (*[]*user, error) {
101104

102105
if args.Page != nil {
103106
if args.Page.First != nil {
104-
from = *args.Page.First
107+
from = int(*args.Page.First)
108+
if from > numFriends {
109+
return nil, errors.New("not enough users")
110+
}
105111
}
106112
if args.Page.Last != nil {
107-
to = *args.Page.Last
108-
if to > numFriends {
113+
to = int(*args.Page.Last)
114+
if to == 0 || to > numFriends {
109115
to = numFriends
110116
}
111117
}
@@ -183,6 +189,12 @@ func (r *Resolver) Admin(ctx context.Context, args struct {
183189
}
184190

185191
func (r *Resolver) User(ctx context.Context, args struct{ Id string }) (user, error) {
192+
selectedFields, _ := selected.GetFieldsFromContext(ctx)
193+
for _, field := range selectedFields {
194+
// TODO temporary until unit test are added
195+
fmt.Printf("name=%s, selectedChildren=%v, args=%v\n", field.Name, len(field.Selected) > 0, field.Args)
196+
}
197+
186198
if usr, ok := usersMap[args.Id]; ok {
187199
return *usr, nil
188200
}

internal/exec/exec.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/graph-gophers/graphql-go/internal/query"
1515
"github.com/graph-gophers/graphql-go/internal/schema"
1616
"github.com/graph-gophers/graphql-go/log"
17+
pubselected "github.com/graph-gophers/graphql-go/selected"
1718
"github.com/graph-gophers/graphql-go/trace"
1819
)
1920

@@ -176,7 +177,9 @@ func execFieldSelection(ctx context.Context, r *Request, f *fieldToExec, path *p
176177
if f.field.MethodIndex != -1 {
177178
var in []reflect.Value
178179
if f.field.HasContext {
179-
in = append(in, reflect.ValueOf(traceCtx))
180+
// lazily evaluate
181+
resCtx := context.WithValue(traceCtx, pubselected.ContextKey, selectedFields(f.sels))
182+
in = append(in, reflect.ValueOf(resCtx))
180183
}
181184
if f.field.ArgsPacker != nil {
182185
in = append(in, f.field.PackedArgs)
@@ -301,6 +304,32 @@ func unwrapNonNull(t common.Type) (common.Type, bool) {
301304
return t, false
302305
}
303306

307+
// lazily add selection fields in context
308+
func selectedFields(sels []selected.Selection) pubselected.SelectedFields {
309+
return func() []pubselected.SelectedField {
310+
return selectionToSelectedFields(sels)
311+
}
312+
}
313+
314+
func selectionToSelectedFields(sels []selected.Selection) []pubselected.SelectedField {
315+
var selectedFields []pubselected.SelectedField
316+
selsLen := len(sels)
317+
if selsLen != 0 {
318+
selectedFields = make([]pubselected.SelectedField, 0, selsLen)
319+
for _, sel := range sels {
320+
selField, ok := sel.(*selected.SchemaField)
321+
if ok {
322+
selectedFields = append(selectedFields, pubselected.SelectedField{
323+
Name: selField.Field.Name,
324+
Args: selField.Args,
325+
Selected: selectionToSelectedFields(selField.Sels),
326+
})
327+
}
328+
}
329+
}
330+
return selectedFields
331+
}
332+
304333
type pathSegment struct {
305334
parent *pathSegment
306335
value interface{}

selected/selected.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package selected
2+
3+
import (
4+
"context"
5+
"errors"
6+
)
7+
8+
const ContextKey = "Resolver_Selected_Fields"
9+
10+
type SelectedFields func() []SelectedField
11+
12+
type SelectedField struct {
13+
Name string
14+
Args map[string]interface{}
15+
Selected []SelectedField
16+
}
17+
18+
func GetFieldsFromContext(ctx context.Context) (fields []SelectedField, err error) {
19+
fieldsFunc, ok := ctx.Value(ContextKey).(SelectedFields)
20+
if ok == false {
21+
err = errors.New("could not get graphql fields from context")
22+
return
23+
}
24+
fields = fieldsFunc()
25+
return
26+
}

0 commit comments

Comments
 (0)