github.com/HaswinVidanage/gqlgen@v0.8.1-0.20220609041233-69528c1bf712/plugin/modelgen/models.go (about) 1 package modelgen 2 3 import ( 4 "go/types" 5 "sort" 6 7 "github.com/HaswinVidanage/gqlgen/internal/code" 8 9 "github.com/HaswinVidanage/gqlgen/codegen/config" 10 "github.com/HaswinVidanage/gqlgen/codegen/templates" 11 "github.com/HaswinVidanage/gqlgen/plugin" 12 "github.com/vektah/gqlparser/ast" 13 ) 14 15 type ModelBuild struct { 16 PackageName string 17 Interfaces []*Interface 18 Models []*Object 19 Enums []*Enum 20 } 21 22 type Interface struct { 23 Description string 24 Name string 25 } 26 27 type Object struct { 28 Description string 29 Name string 30 Fields []*Field 31 Implements []string 32 } 33 34 type Field struct { 35 Description string 36 Name string 37 Type types.Type 38 Tag string 39 } 40 41 type Enum struct { 42 Description string 43 Name string 44 Raw string 45 Values []*EnumValue 46 } 47 48 type EnumValue struct { 49 Description string 50 Name string 51 Value string 52 } 53 54 func New() plugin.Plugin { 55 return &Plugin{} 56 } 57 58 type Plugin struct{} 59 60 var _ plugin.ConfigMutator = &Plugin{} 61 62 func (m *Plugin) Name() string { 63 return "modelgen" 64 } 65 66 func (m *Plugin) MutateConfig(cfg *config.Config) error { 67 if err := cfg.Check(); err != nil { 68 return err 69 } 70 71 schema, _, err := cfg.LoadSchema() 72 if err != nil { 73 return err 74 } 75 76 cfg.InjectBuiltins(schema) 77 78 binder, err := cfg.NewBinder(schema) 79 if err != nil { 80 return err 81 } 82 83 b := &ModelBuild{ 84 PackageName: cfg.Model.Package, 85 } 86 87 for _, schemaType := range schema.Types { 88 if cfg.Models.UserDefined(schemaType.Name) { 89 continue 90 } 91 92 switch schemaType.Kind { 93 case ast.Interface, ast.Union: 94 it := &Interface{ 95 Description: schemaType.Description, 96 Name: templates.ToGo(schemaType.Name), 97 } 98 99 b.Interfaces = append(b.Interfaces, it) 100 case ast.Object, ast.InputObject: 101 if schemaType == schema.Query || schemaType == schema.Mutation || schemaType == schema.Subscription { 102 continue 103 } 104 it := &Object{ 105 Description: schemaType.Description, 106 Name: templates.ToGo(schemaType.Name), 107 } 108 109 for _, implementor := range schema.GetImplements(schemaType) { 110 it.Implements = append(it.Implements, templates.ToGo(implementor.Name)) 111 } 112 113 for _, field := range schemaType.Fields { 114 var typ types.Type 115 116 if cfg.Models.UserDefined(field.Type.Name()) { 117 pkg, typeName := code.PkgAndType(cfg.Models[field.Type.Name()].Model[0]) 118 typ, err = binder.FindType(pkg, typeName) 119 if err != nil { 120 return err 121 } 122 } else { 123 // no user defined model, must reference another generated model 124 typ = types.NewNamed( 125 types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil), 126 nil, 127 nil, 128 ) 129 } 130 131 name := field.Name 132 if nameOveride := cfg.Models[schemaType.Name].Fields[field.Name].FieldName; nameOveride != "" { 133 name = nameOveride 134 } 135 136 fd := schema.Types[field.Type.Name()] 137 it.Fields = append(it.Fields, &Field{ 138 Name: templates.ToGo(name), 139 Type: binder.CopyModifiersFromAst(field.Type, fd.Kind != ast.Interface, typ), 140 Description: field.Description, 141 Tag: `json:"` + field.Name + `"`, 142 }) 143 } 144 145 b.Models = append(b.Models, it) 146 case ast.Enum: 147 it := &Enum{ 148 Name: templates.ToGo(schemaType.Name), 149 Raw: schemaType.Name, 150 Description: schemaType.Description, 151 } 152 153 for _, v := range schemaType.EnumValues { 154 it.Values = append(it.Values, &EnumValue{ 155 Name: templates.ToGo(v.Name), 156 Value: v.Name, 157 Description: v.Description, 158 }) 159 } 160 161 b.Enums = append(b.Enums, it) 162 } 163 } 164 165 sort.Slice(b.Enums, func(i, j int) bool { return b.Enums[i].Name < b.Enums[j].Name }) 166 sort.Slice(b.Models, func(i, j int) bool { return b.Models[i].Name < b.Models[j].Name }) 167 sort.Slice(b.Interfaces, func(i, j int) bool { return b.Interfaces[i].Name < b.Interfaces[j].Name }) 168 169 for _, it := range b.Enums { 170 cfg.Models.Add(it.Raw, cfg.Model.ImportPath()+"."+it.Name) 171 } 172 for _, it := range b.Models { 173 cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+it.Name) 174 } 175 for _, it := range b.Interfaces { 176 cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+it.Name) 177 } 178 179 if len(b.Models) == 0 && len(b.Enums) == 0 { 180 return nil 181 } 182 183 return templates.Render(templates.Options{ 184 PackageName: cfg.Model.Package, 185 Filename: cfg.Model.Filename, 186 Data: b, 187 GeneratedHeader: true, 188 }) 189 }