// addConnections adds connections fields to the object afterward to prevent from dead loops func (t types) addConnections(o *graphql.Object, idx resource.Index, r *resource.Resource) { // Add sub field references for name, def := range r.Schema().Fields { if ref, ok := def.Validator.(*schema.Reference); ok { sr, found := idx.GetResource(ref.Path, nil) if !found { log.Panicf("resource reference not found: %s", ref.Path) } o.AddFieldConfig(name, &graphql.Field{ Description: def.Description, Type: t.getObjectType(idx, sr), Args: getFArgs(def.Params), Resolve: getSubFieldResolver(name, sr, def), }) } } // Add sub resources for _, sr := range r.GetResources() { name := sr.Name() o.AddFieldConfig(name, &graphql.Field{ Description: fmt.Sprintf("Connection to %s", name), Type: graphql.NewList(t.getObjectType(idx, sr)), Args: listArgs, Resolve: getSubResourceResolver(sr), }) } }
// getObjectType returns a graphql object type definition from a REST layer schema func (t types) getObjectType(idx resource.Index, r *resource.Resource) *graphql.Object { // Memoize types by their name so we don't create several instance of the same resource name := r.Name() o := t[name] if o == nil { o = graphql.NewObject(graphql.ObjectConfig{ Name: name, Description: r.Schema().Description, Fields: getFields(idx, r.Schema()), }) t[name] = o t.addConnections(o, idx, r) } return o }