Skip to content

Commit

Permalink
EntityResolver input type fix (#2594)
Browse files Browse the repository at this point in the history
* EntityResolver input type fix

fixes #2326 - when using `@entityResolver(multi: true)` the InputType of
the entity resolver may be in a different package (usually `model`).
The fix is to pull the types.Type of the resolver input, and use
templates.CurrentImports.LookupType in order to render it correctly
(possibly adding another import)

* entityResolver input type fix: update tests

change testdata/entityresolver/gqlgen.yml to use a dedicated package for
the model (as in the default sample yml), and run go generate.

before the input type fix, generation fails with errors like -
plugin/federation/testdata/entityresolver/generated/federation.go:338:17:
  undeclared name: MultiHelloByNamesInput
plugin/federation/testdata/entityresolver/generated/federation.go:354:21:
  undeclared name: MultiHelloMultipleRequiresByNamesInput
plugin/federation/testdata/entityresolver/generated/federation.go:362:17:
  undeclared name: MultiHelloMultipleRequiresByNamesInput
  • Loading branch information
erankor authored Mar 28, 2023
1 parent 6da735c commit db53479
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 286 deletions.
14 changes: 11 additions & 3 deletions plugin/federation/entity.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package federation

import (
"go/types"

"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/codegen/templates"
"github.com/99designs/gqlgen/plugin/federation/fieldset"
"github.com/vektah/gqlparser/v2/ast"
)
Expand All @@ -17,9 +20,14 @@ type Entity struct {
}

type EntityResolver struct {
ResolverName string // The resolver name, such as FindUserByID
KeyFields []*KeyField // The fields declared in @key.
InputType string // The Go generated input type for multi entity resolvers
ResolverName string // The resolver name, such as FindUserByID
KeyFields []*KeyField // The fields declared in @key.
InputType types.Type // The Go generated input type for multi entity resolvers
InputTypeName string
}

func (e *EntityResolver) LookupInputType() string {
return templates.CurrentImports.LookupType(e.InputType)
}

type KeyField struct {
Expand Down
27 changes: 22 additions & 5 deletions plugin/federation/federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ func (f *federation) InjectSourceLate(schema *ast.Schema) *ast.Source {
if entityResolverInputDefinitions != "" {
entityResolverInputDefinitions += "\n\n"
}
entityResolverInputDefinitions += "input " + r.InputType + " {\n"
entityResolverInputDefinitions += "input " + r.InputTypeName + " {\n"
for _, keyField := range r.KeyFields {
entityResolverInputDefinitions += fmt.Sprintf("\t%s: %s\n", keyField.Field.ToGo(), keyField.Definition.Type.String())
}
entityResolverInputDefinitions += "}"
resolvers += fmt.Sprintf("\t%s(reps: [%s!]!): [%s]\n", r.ResolverName, r.InputType, e.Name)
resolvers += fmt.Sprintf("\t%s(reps: [%s!]!): [%s]\n", r.ResolverName, r.InputTypeName, e.Name)
} else {
resolverArgs := ""
for _, keyField := range r.KeyFields {
Expand Down Expand Up @@ -234,6 +234,23 @@ func (f *federation) GenerateCode(data *codegen.Data) error {
}
}

// fill in types for resolver inputs
//
for _, entity := range f.Entities {
if !entity.Multi {
continue
}

for _, resolver := range entity.Resolvers {
obj := data.Inputs.ByName(resolver.InputTypeName)
if obj == nil {
return fmt.Errorf("input object %s not found", resolver.InputTypeName)
}

resolver.InputType = obj.Type
}
}

return templates.Render(templates.Options{
PackageName: data.Config.Federation.Package,
Filename: data.Config.Federation.Filename,
Expand Down Expand Up @@ -327,9 +344,9 @@ func (f *federation) setEntities(schema *ast.Schema) {
}

e.Resolvers = append(e.Resolvers, &EntityResolver{
ResolverName: resolverName,
KeyFields: keyFields,
InputType: resolverFieldsToGo + "Input",
ResolverName: resolverName,
KeyFields: keyFields,
InputTypeName: resolverFieldsToGo + "Input",
})
}

Expand Down
4 changes: 2 additions & 2 deletions plugin/federation/federation.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (ec *executionContext) __resolve_entities(ctx context.Context, representati
{{ if and .Resolvers .Multi -}}
case "{{.Def.Name}}":
{{range $i, $_ := .Resolvers -}}
_reps := make([]*{{.InputType}}, len(reps))
_reps := make([]*{{.LookupInputType}}, len(reps))

for i, rep := range reps {
{{ range $i, $keyField := .KeyFields -}}
Expand All @@ -143,7 +143,7 @@ func (ec *executionContext) __resolve_entities(ctx context.Context, representati
}
{{end}}

_reps[i] = &{{.InputType}} {
_reps[i] = &{{.LookupInputType}} {
{{ range $i, $keyField := .KeyFields -}}
{{$keyField.Field.ToGo}}: id{{$i}},
{{end}}
Expand Down
73 changes: 37 additions & 36 deletions plugin/federation/testdata/entityresolver/entity.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit db53479

Please sign in to comment.