Skip to content

Commit

Permalink
Merge pull request #229 from graphql-go/atrniv/fix-cyclic-types
Browse files Browse the repository at this point in the history
support for cyclic fields on defintion
  • Loading branch information
chris-ramon committed Aug 6, 2017
2 parents a9df066 + 174a1a3 commit 105a6c2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
25 changes: 19 additions & 6 deletions definition.go
Expand Up @@ -398,6 +398,7 @@ type ObjectConfig struct {
IsTypeOf IsTypeOfFn `json:"isTypeOf"`
Description string `json:"description"`
}

type FieldsThunk func() Fields

func NewObject(config ObjectConfig) *Object {
Expand Down Expand Up @@ -506,19 +507,26 @@ func defineInterfaces(ttype *Object, interfaces []*Interface) ([]*Interface, err
return ifaces, nil
}

func defineFieldMap(ttype Named, fields Fields) (FieldDefinitionMap, error) {
func defineFieldMap(ttype Named, fields interface{}) (FieldDefinitionMap, error) {
var fieldMap Fields
switch fields.(type) {
case Fields:
fieldMap = fields.(Fields)
case FieldsThunk:
fieldMap = fields.(FieldsThunk)()
}

resultFieldMap := FieldDefinitionMap{}

err := invariant(
len(fields) > 0,
len(fieldMap) > 0,
fmt.Sprintf(`%v fields must be an object with field names as keys or a function which return such an object.`, ttype),
)
if err != nil {
return resultFieldMap, err
}

for fieldName, field := range fields {
for fieldName, field := range fieldMap {
if field == nil {
continue
}
Expand Down Expand Up @@ -1080,8 +1088,8 @@ type InputObject struct {

typeConfig InputObjectConfig
fields InputObjectFieldMap

err error
init bool
err error
}
type InputObjectFieldConfig struct {
Type Input `json:"type"`
Expand Down Expand Up @@ -1129,7 +1137,7 @@ func NewInputObject(config InputObjectConfig) *InputObject {
gt.PrivateName = config.Name
gt.PrivateDescription = config.Description
gt.typeConfig = config
gt.fields = gt.defineFieldMap()
//gt.fields = gt.defineFieldMap()
return gt
}

Expand Down Expand Up @@ -1175,9 +1183,14 @@ func (gt *InputObject) defineFieldMap() InputObjectFieldMap {
field.DefaultValue = fieldConfig.DefaultValue
resultFieldMap[fieldName] = field
}
gt.init = true
return resultFieldMap
}

func (gt *InputObject) Fields() InputObjectFieldMap {
if !gt.init {
gt.fields = gt.defineFieldMap()
}
return gt.fields
}
func (gt *InputObject) Name() string {
Expand Down
22 changes: 22 additions & 0 deletions definition_test.go
Expand Up @@ -619,3 +619,25 @@ func TestTypeSystem_DefinitionExample_IncludesFieldsThunk(t *testing.T) {
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(fieldMap["s"].Type, someObject))
}
}

func TestTypeSystem_DefinitionExampe_AllowsCyclicFieldTypes(t *testing.T) {
personType := graphql.NewObject(graphql.ObjectConfig{
Name: "Person",
Fields: (graphql.FieldsThunk)(func() graphql.Fields {
return graphql.Fields{
"name": &graphql.Field{
Type: graphql.String,
},
"bestFriend": &graphql.Field{
Type: personType,
},
}
}),
})

fieldMap := personType.Fields()
if !reflect.DeepEqual(fieldMap["name"].Type, graphql.String) {
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(fieldMap["bestFriend"].Type, personType))
}

}

0 comments on commit 105a6c2

Please sign in to comment.