diff --git a/definition.go b/definition.go index 934c2d01..83570573 100644 --- a/definition.go +++ b/definition.go @@ -398,6 +398,7 @@ type ObjectConfig struct { IsTypeOf IsTypeOfFn `json:"isTypeOf"` Description string `json:"description"` } + type FieldsThunk func() Fields func NewObject(config ObjectConfig) *Object { @@ -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 } @@ -1080,8 +1088,8 @@ type InputObject struct { typeConfig InputObjectConfig fields InputObjectFieldMap - - err error + init bool + err error } type InputObjectFieldConfig struct { Type Input `json:"type"` @@ -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 } @@ -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 { diff --git a/definition_test.go b/definition_test.go index 8b574e2e..76cf752d 100644 --- a/definition_test.go +++ b/definition_test.go @@ -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)) + } + +}