Skip to content

Commit a369aa1

Browse files
authored
Merge pull request #1 from ProlificLabs/add-mutation-args
Add mutation args
2 parents beb923f + 7fb2dec commit a369aa1

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ When using `UseFieldResolvers` schema option, a struct field will be used *only*
7676

7777
The method has up to two arguments:
7878

79-
- Optional `context.Context` argument.
79+
- Optional `context.Context` argument. If the graphql query had nested subfields, then use the `SelctedFieldsFromContext(ctx context.Context)` getter method
8080
- Mandatory `*struct { ... }` argument if the corresponding GraphQL field has arguments. The names of the struct fields have to be [exported](https://golang.org/ref/spec#Exported_identifiers) and have to match the names of the GraphQL arguments in a non-case-sensitive way.
8181

8282
The method has up to two results:

graphql.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/graph-gophers/graphql-go/internal/validation"
1818
"github.com/graph-gophers/graphql-go/introspection"
1919
"github.com/graph-gophers/graphql-go/log"
20+
"github.com/graph-gophers/graphql-go/selection"
2021
"github.com/graph-gophers/graphql-go/trace"
2122
)
2223

@@ -155,6 +156,17 @@ type Response struct {
155156
Extensions map[string]interface{} `json:"extensions,omitempty"`
156157
}
157158

159+
// SelectedFieldsFromContext retrieves the selected fields passed via the context during the request
160+
// execution
161+
func SelectedFieldsFromContext(ctx context.Context) []*selection.SelectedField {
162+
return exec.SelectedFieldsFromContext(ctx)
163+
}
164+
165+
// ArgumentsFromContext returns the arguments for the field.
166+
func ArgumentsFromContext(ctx context.Context) map[string]interface{} {
167+
return exec.ArgsFromContext(ctx)
168+
}
169+
158170
// Validate validates the given query with the schema.
159171
func (s *Schema) Validate(queryString string) []*errors.QueryError {
160172
return s.ValidateWithVariables(queryString, nil)

internal/exec/exec.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@ import (
1616
"github.com/graph-gophers/graphql-go/internal/query"
1717
"github.com/graph-gophers/graphql-go/internal/schema"
1818
"github.com/graph-gophers/graphql-go/log"
19+
"github.com/graph-gophers/graphql-go/selection"
1920
"github.com/graph-gophers/graphql-go/trace"
2021
)
2122

23+
type ctxKey string
24+
25+
const (
26+
selectedFieldsKey ctxKey = "selectedFields"
27+
argumentsKey ctxKey = "arguments"
28+
)
29+
2230
type Request struct {
2331
selected.Request
2432
Limiter chan struct{}
@@ -162,6 +170,42 @@ func typeOf(tf *selected.TypenameField, resolver reflect.Value) string {
162170
return ""
163171
}
164172

173+
func selectionToSelectedFields(internalSelection []selected.Selection) []*selection.SelectedField {
174+
fieldSelection := []*selection.SelectedField{}
175+
for _, element := range internalSelection {
176+
if field, ok := element.(*selected.SchemaField); ok {
177+
nestedSelections := selectionToSelectedFields(field.Sels)
178+
fieldSelection = append(fieldSelection, &selection.SelectedField{
179+
Name: field.Name,
180+
SelectedFields: nestedSelections,
181+
})
182+
}
183+
}
184+
return fieldSelection
185+
}
186+
187+
// SelectedFieldsFromContext exposes the fields selected in the GraphQL request
188+
// using the public-facing selection.SelectedField struct
189+
func SelectedFieldsFromContext(ctx context.Context) []*selection.SelectedField {
190+
selection := ctx.Value(selectedFieldsKey).([]selected.Selection)
191+
selectedFields := selectionToSelectedFields(selection)
192+
return selectedFields
193+
}
194+
195+
// ArgsFromContext exposes the arguments in the GraphQL mutation
196+
// using the public-facing selection.Argument struct
197+
func ArgsFromContext(ctx context.Context) map[string]interface{} {
198+
return ctx.Value(argumentsKey).(map[string]interface{})
199+
}
200+
201+
func contextWithSelectedFields(parentContext context.Context, selection []selected.Selection) context.Context {
202+
return context.WithValue(parentContext, selectedFieldsKey, selection)
203+
}
204+
205+
func contextWithArguments(ctx context.Context, args map[string]interface{}) context.Context {
206+
return context.WithValue(ctx, argumentsKey, args)
207+
}
208+
165209
func execFieldSelection(ctx context.Context, r *Request, s *resolvable.Schema, f *fieldToExec, path *pathSegment, applyLimiter bool) {
166210
if applyLimiter {
167211
r.Limiter <- struct{}{}
@@ -197,6 +241,12 @@ func execFieldSelection(ctx context.Context, r *Request, s *resolvable.Schema, f
197241
if f.field.UseMethodResolver() {
198242
var in []reflect.Value
199243
if f.field.HasContext {
244+
if len(f.sels) != 0 {
245+
traceCtx = contextWithSelectedFields(traceCtx, f.sels)
246+
}
247+
if len(f.field.Args) != 0 {
248+
traceCtx = contextWithArguments(traceCtx, f.field.Args)
249+
}
200250
in = append(in, reflect.ValueOf(traceCtx))
201251
}
202252
if f.field.ArgsPacker != nil {

selection/selected_field.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package selection
2+
3+
// SelectedField is the public representation of a field selection
4+
// during a graphql query
5+
type SelectedField struct {
6+
Name string
7+
SelectedFields []*SelectedField
8+
}

0 commit comments

Comments
 (0)