github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/codegen/data.go (about) 1 package codegen 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/pkg/errors" 8 "github.com/vektah/gqlparser/v2/ast" 9 10 "github.com/99designs/gqlgen/codegen/config" 11 ) 12 13 // Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement 14 // resolvers or directives automatically (eg grpc, validation) 15 type Data struct { 16 Config *config.Config 17 Schema *ast.Schema 18 Directives DirectiveList 19 Objects Objects 20 Inputs Objects 21 Interfaces map[string]*Interface 22 ReferencedTypes map[string]*config.TypeReference 23 ComplexityRoots map[string]*Object 24 25 QueryRoot *Object 26 MutationRoot *Object 27 SubscriptionRoot *Object 28 } 29 30 type builder struct { 31 Config *config.Config 32 Schema *ast.Schema 33 Binder *config.Binder 34 Directives map[string]*Directive 35 } 36 37 func BuildData(cfg *config.Config) (*Data, error) { 38 b := builder{ 39 Config: cfg, 40 Schema: cfg.Schema, 41 } 42 43 b.Binder = b.Config.NewBinder() 44 45 var err error 46 b.Directives, err = b.buildDirectives() 47 if err != nil { 48 return nil, err 49 } 50 51 dataDirectives := make(map[string]*Directive) 52 for name, d := range b.Directives { 53 if !d.Builtin { 54 dataDirectives[name] = d 55 } 56 } 57 58 s := Data{ 59 Config: cfg, 60 Directives: dataDirectives, 61 Schema: b.Schema, 62 Interfaces: map[string]*Interface{}, 63 } 64 65 for _, schemaType := range b.Schema.Types { 66 switch schemaType.Kind { 67 case ast.Object: 68 obj, err := b.buildObject(schemaType) 69 if err != nil { 70 return nil, errors.Wrap(err, "unable to build object definition") 71 } 72 73 s.Objects = append(s.Objects, obj) 74 case ast.InputObject: 75 input, err := b.buildObject(schemaType) 76 if err != nil { 77 return nil, errors.Wrap(err, "unable to build input definition") 78 } 79 80 s.Inputs = append(s.Inputs, input) 81 82 case ast.Union, ast.Interface: 83 s.Interfaces[schemaType.Name], err = b.buildInterface(schemaType) 84 if err != nil { 85 return nil, errors.Wrap(err, "unable to bind to interface") 86 } 87 } 88 } 89 90 if s.Schema.Query != nil { 91 s.QueryRoot = s.Objects.ByName(s.Schema.Query.Name) 92 } else { 93 return nil, fmt.Errorf("query entry point missing") 94 } 95 96 if s.Schema.Mutation != nil { 97 s.MutationRoot = s.Objects.ByName(s.Schema.Mutation.Name) 98 } 99 100 if s.Schema.Subscription != nil { 101 s.SubscriptionRoot = s.Objects.ByName(s.Schema.Subscription.Name) 102 } 103 104 if err := b.injectIntrospectionRoots(&s); err != nil { 105 return nil, err 106 } 107 108 s.ReferencedTypes = b.buildTypes() 109 110 sort.Slice(s.Objects, func(i, j int) bool { 111 return s.Objects[i].Definition.Name < s.Objects[j].Definition.Name 112 }) 113 114 sort.Slice(s.Inputs, func(i, j int) bool { 115 return s.Inputs[i].Definition.Name < s.Inputs[j].Definition.Name 116 }) 117 118 if b.Binder.SawInvalid { 119 // if we have a syntax error, show it 120 err := cfg.Packages.Errors() 121 if len(err) > 0 { 122 return nil, err 123 } 124 125 // otherwise show a generic error message 126 return nil, fmt.Errorf("invalid types were encountered while traversing the go source code, this probably means the invalid code generated isnt correct. add try adding -v to debug") 127 } 128 129 return &s, nil 130 } 131 132 func (b *builder) injectIntrospectionRoots(s *Data) error { 133 obj := s.Objects.ByName(b.Schema.Query.Name) 134 if obj == nil { 135 return fmt.Errorf("root query type must be defined") 136 } 137 138 __type, err := b.buildField(obj, &ast.FieldDefinition{ 139 Name: "__type", 140 Type: ast.NamedType("__Type", nil), 141 Arguments: []*ast.ArgumentDefinition{ 142 { 143 Name: "name", 144 Type: ast.NonNullNamedType("String", nil), 145 }, 146 }, 147 }) 148 if err != nil { 149 return err 150 } 151 152 __schema, err := b.buildField(obj, &ast.FieldDefinition{ 153 Name: "__schema", 154 Type: ast.NamedType("__Schema", nil), 155 }) 156 if err != nil { 157 return err 158 } 159 160 obj.Fields = append(obj.Fields, __type, __schema) 161 162 return nil 163 }