Skip to content

Commit

Permalink
Merge pull request #1 from ProlificLabs/add-mutation-args
Browse files Browse the repository at this point in the history
Add mutation args
  • Loading branch information
markerdmann authored Jan 26, 2021
2 parents beb923f + 7fb2dec commit a369aa1
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ When using `UseFieldResolvers` schema option, a struct field will be used *only*

The method has up to two arguments:

- Optional `context.Context` argument.
- Optional `context.Context` argument. If the graphql query had nested subfields, then use the `SelctedFieldsFromContext(ctx context.Context)` getter method
- 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.

The method has up to two results:
Expand Down
12 changes: 12 additions & 0 deletions graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/graph-gophers/graphql-go/internal/validation"
"github.com/graph-gophers/graphql-go/introspection"
"github.com/graph-gophers/graphql-go/log"
"github.com/graph-gophers/graphql-go/selection"
"github.com/graph-gophers/graphql-go/trace"
)

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

// SelectedFieldsFromContext retrieves the selected fields passed via the context during the request
// execution
func SelectedFieldsFromContext(ctx context.Context) []*selection.SelectedField {
return exec.SelectedFieldsFromContext(ctx)
}

// ArgumentsFromContext returns the arguments for the field.
func ArgumentsFromContext(ctx context.Context) map[string]interface{} {
return exec.ArgsFromContext(ctx)
}

// Validate validates the given query with the schema.
func (s *Schema) Validate(queryString string) []*errors.QueryError {
return s.ValidateWithVariables(queryString, nil)
Expand Down
50 changes: 50 additions & 0 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ import (
"github.com/graph-gophers/graphql-go/internal/query"
"github.com/graph-gophers/graphql-go/internal/schema"
"github.com/graph-gophers/graphql-go/log"
"github.com/graph-gophers/graphql-go/selection"
"github.com/graph-gophers/graphql-go/trace"
)

type ctxKey string

const (
selectedFieldsKey ctxKey = "selectedFields"
argumentsKey ctxKey = "arguments"
)

type Request struct {
selected.Request
Limiter chan struct{}
Expand Down Expand Up @@ -162,6 +170,42 @@ func typeOf(tf *selected.TypenameField, resolver reflect.Value) string {
return ""
}

func selectionToSelectedFields(internalSelection []selected.Selection) []*selection.SelectedField {
fieldSelection := []*selection.SelectedField{}
for _, element := range internalSelection {
if field, ok := element.(*selected.SchemaField); ok {
nestedSelections := selectionToSelectedFields(field.Sels)
fieldSelection = append(fieldSelection, &selection.SelectedField{
Name: field.Name,
SelectedFields: nestedSelections,
})
}
}
return fieldSelection
}

// SelectedFieldsFromContext exposes the fields selected in the GraphQL request
// using the public-facing selection.SelectedField struct
func SelectedFieldsFromContext(ctx context.Context) []*selection.SelectedField {
selection := ctx.Value(selectedFieldsKey).([]selected.Selection)
selectedFields := selectionToSelectedFields(selection)
return selectedFields
}

// ArgsFromContext exposes the arguments in the GraphQL mutation
// using the public-facing selection.Argument struct
func ArgsFromContext(ctx context.Context) map[string]interface{} {
return ctx.Value(argumentsKey).(map[string]interface{})
}

func contextWithSelectedFields(parentContext context.Context, selection []selected.Selection) context.Context {
return context.WithValue(parentContext, selectedFieldsKey, selection)
}

func contextWithArguments(ctx context.Context, args map[string]interface{}) context.Context {
return context.WithValue(ctx, argumentsKey, args)
}

func execFieldSelection(ctx context.Context, r *Request, s *resolvable.Schema, f *fieldToExec, path *pathSegment, applyLimiter bool) {
if applyLimiter {
r.Limiter <- struct{}{}
Expand Down Expand Up @@ -197,6 +241,12 @@ func execFieldSelection(ctx context.Context, r *Request, s *resolvable.Schema, f
if f.field.UseMethodResolver() {
var in []reflect.Value
if f.field.HasContext {
if len(f.sels) != 0 {
traceCtx = contextWithSelectedFields(traceCtx, f.sels)
}
if len(f.field.Args) != 0 {
traceCtx = contextWithArguments(traceCtx, f.field.Args)
}
in = append(in, reflect.ValueOf(traceCtx))
}
if f.field.ArgsPacker != nil {
Expand Down
8 changes: 8 additions & 0 deletions selection/selected_field.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package selection

// SelectedField is the public representation of a field selection
// during a graphql query
type SelectedField struct {
Name string
SelectedFields []*SelectedField
}

0 comments on commit a369aa1

Please sign in to comment.