Skip to content

Commit

Permalink
Merge pull request #95 from vektah/custom-error-types
Browse files Browse the repository at this point in the history
Custom error types
  • Loading branch information
vektah committed Apr 28, 2018
2 parents a0f66c8 + 4bdc1e1 commit 0c7bdfc
Show file tree
Hide file tree
Showing 34 changed files with 3,229 additions and 715 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/codegen/templates/data.go linguist-generated
/example/dataloader/*_gen.go linguist-generated
generated.go linguist-generated
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ See the [docs](https://gqlgen.com/) for a getting started guide.
| Hooks for error logging | :+1: | :no_entry: | :no_entry: | :no_entry: |
| Dataloading | :+1: | :+1: | :no_entry: | :warning: |
| Concurrency | :+1: | :+1: | :no_entry: [pr](https://github.com/graphql-go/graphql/pull/132) | :+1: |
| Custom errors & error.path | :+1: | :no_entry: [is](https://github.com/graphql-go/graphql/issues/259) | :no_entry: | :no_entry: |
26 changes: 15 additions & 11 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/http"

"github.com/mitchellh/mapstructure"
"github.com/vektah/gqlgen/neelance/errors"
)

// Client for graphql requests
Expand Down Expand Up @@ -101,23 +100,28 @@ func (p *Client) Post(query string, response interface{}, options ...Option) err

// decode it into map string first, let mapstructure do the final decode
// because it can be much stricter about unknown fields.
respDataRaw := map[string]interface{}{}
respDataRaw := struct {
Data interface{}
Errors json.RawMessage
}{}
err = json.Unmarshal(responseBody, &respDataRaw)
if err != nil {
return fmt.Errorf("decode: %s", err.Error())
}

if respDataRaw["errors"] != nil {
var errs []*errors.QueryError
if err := unpack(respDataRaw["errors"], &errs); err != nil {
return err
}
if len(errs) > 0 {
return fmt.Errorf("errors: %s", errs)
}
if respDataRaw.Errors != nil {
return RawJsonError{respDataRaw.Errors}
}

return unpack(respDataRaw["data"], response)
return unpack(respDataRaw.Data, response)
}

type RawJsonError struct {
json.RawMessage
}

func (r RawJsonError) Error() string {
return string(r.RawMessage)
}

func unpack(data interface{}, into interface{}) error {
Expand Down
2 changes: 1 addition & 1 deletion codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func write(filename string, b []byte) error {

formatted, err := gofmt(filename, b)
if err != nil {
fmt.Fprintf(os.Stderr, "gofmt failed: %s", err.Error())
fmt.Fprintf(os.Stderr, "gofmt failed: %s\n", err.Error())
formatted = b
}

Expand Down
9 changes: 7 additions & 2 deletions codegen/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (f *Field) CallArgs() string {
var args []string

if f.GoMethodName == "" {
args = append(args, "rctx")
args = append(args, "ctx")

if !f.Object.Root {
args = append(args, "obj")
Expand Down Expand Up @@ -115,7 +115,12 @@ func (f *Field) doWriteJson(val string, remainingMods []string, isPtr bool, dept

return tpl(`{{.arr}} := graphql.Array{}
for {{.index}} := range {{.val}} {
{{.arr}} = append({{.arr}}, func() graphql.Marshaler { {{ .next }} }())
{{.arr}} = append({{.arr}}, func() graphql.Marshaler {
rctx := graphql.GetResolverContext(ctx)
rctx.PushIndex({{.index}})
defer rctx.Pop()
{{ .next }}
}())
}
return {{.arr}}`, map[string]interface{}{
"val": val,
Expand Down
4 changes: 2 additions & 2 deletions codegen/templates/args.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
var err error
{{$arg.Unmarshal (print "arg" $i) "tmp" }}
if err != nil {
ec.Error(err)
ec.Error(ctx, err)
{{- if $arg.Object.Stream }}
return nil
{{- else }}
Expand All @@ -17,7 +17,7 @@
var err error
{{$arg.Unmarshal (print "arg" $i) "tmp" }}
if err != nil {
ec.Error(err)
ec.Error(ctx, err)
{{- if $arg.Object.Stream }}
return nil
{{- else }}
Expand Down
8 changes: 4 additions & 4 deletions codegen/templates/data.go

Large diffs are not rendered by default.

30 changes: 19 additions & 11 deletions codegen/templates/field.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
{{- if $object.Stream }}
func (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {
{{- template "args.gotpl" $field.Args }}
rctx := graphql.WithResolverContext(ctx, &graphql.ResolverContext{Field: field})
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{Field: field})
results, err := ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})
if err != nil {
ec.Error(err)
ec.Error(ctx, err)
return nil
}
return func() graphql.Marshaler {
Expand All @@ -25,14 +25,26 @@
{{- template "args.gotpl" $field.Args }}

{{- if $field.IsConcurrent }}
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
Object: {{$object.GQLType|quote}},
Args: {{if $field.Args }}args{{else}}nil{{end}},
Field: field,
})
return graphql.Defer(func() (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
userErr := ec.Recover(ctx, r)
ec.Error(userErr)
ec.Error(ctx, userErr)
ret = graphql.Null
}
}()
{{ else }}
rctx := graphql.GetResolverContext(ctx)
rctx.Object = {{$object.GQLType|quote}}
rctx.Args = {{if $field.Args }}args{{else}}nil{{end}}
rctx.Field = field
rctx.PushField(field.Alias)
defer rctx.Pop()
{{- end }}

{{- if $field.GoVarName }}
Expand All @@ -43,21 +55,17 @@
{{- else }}
res, err := {{$field.GoMethodName}}({{ $field.CallArgs }})
if err != nil {
ec.Error(err)
ec.Error(ctx, err)
return graphql.Null
}
{{- end }}
{{- else }}
rctx := graphql.WithResolverContext(ctx, &graphql.ResolverContext{
Object: {{$object.GQLType|quote}},
Args: {{if $field.Args }}args{{else}}nil{{end}},
Field: field,
})
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {

resTmp, err := ec.ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) {
return ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})
})
if err != nil {
ec.Error(err)
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
Expand Down
6 changes: 3 additions & 3 deletions codegen/templates/generated.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap
Errors: ec.Errors,
}
{{- else }}
return &graphql.Response{Errors: []*errors.QueryError{ {Message: "queries are not supported"} }}
return graphql.ErrorResponse(ctx, "queries are not supported")
{{- end }}
}

Expand All @@ -64,7 +64,7 @@ func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *g
Errors: ec.Errors,
}
{{- else }}
return &graphql.Response{Errors: []*errors.QueryError{ {Message: "mutations are not supported"} }}
return graphql.ErrorResponse(ctx, "mutations are not supported")
{{- end }}
}

Expand Down Expand Up @@ -96,7 +96,7 @@ func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation
}
}
{{- else }}
return graphql.OneShot(&graphql.Response{Errors: []*errors.QueryError{ {Message: "subscriptions are not supported"} }})
return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported"))
{{- end }}
}

Expand Down
11 changes: 9 additions & 2 deletions codegen/templates/object.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ var {{ $object.GQLType|lcFirst}}Implementors = {{$object.Implementors}}
{{- if .Stream }}
func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []query.Selection) func() graphql.Marshaler {
fields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables)

ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
Object: {{$object.GQLType|quote}},
})
if len(fields) != 1 {
ec.Errorf("must subscribe to exactly one stream")
ec.Errorf(ctx, "must subscribe to exactly one stream")
return nil
}

Expand All @@ -24,6 +26,11 @@ func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []quer
{{- else }}
func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel []query.Selection{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler {
fields := graphql.CollectFields(ec.Doc, sel, {{$object.GQLType|lcFirst}}Implementors, ec.Variables)
{{if $object.Root}}
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
Object: {{$object.GQLType|quote}},
})
{{end}}
out := graphql.NewOrderedMap(len(fields))
for i, field := range fields {
out.Keys[i] = field.Alias
Expand Down
Loading

0 comments on commit 0c7bdfc

Please sign in to comment.