From 8e7d1862fd5e96b5267453a157001f8b73e78c9f Mon Sep 17 00:00:00 2001 From: vvakame Date: Mon, 2 Jul 2018 17:31:01 +0900 Subject: [PATCH 1/4] Refactor types.json parsing --- codegen/codegen.go | 74 ++++++++++++++++++++++++---------- codegen/import_test.go | 8 ++-- codegen/input_test.go | 12 +++--- codegen/interface_test.go | 12 +++--- codegen/templates/templates.go | 4 +- codegen/type_build.go | 5 ++- main.go | 38 ++++++++++++----- test/types.json | 12 ++++-- 8 files changed, 112 insertions(+), 53 deletions(-) diff --git a/codegen/codegen.go b/codegen/codegen.go index 6c34eefaf69..746759e7e6f 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -19,7 +19,7 @@ import ( type Config struct { SchemaStr string - Typemap map[string]string + Typemap TypeMap schema *schema.Schema @@ -34,6 +34,32 @@ type Config struct { modelDir string } +type TypeMap []TypeMapEntry + +func (tm TypeMap) Exists(typeName string) bool { + return tm.Get(typeName) != nil +} + +func (tm TypeMap) Get(typeName string) *TypeMapEntry { + for _, entry := range tm { + if entry.TypeName == typeName { + return &entry + } + } + + return nil +} + +type TypeMapEntry struct { + TypeName string + EntityPath string + Fields []TypeMapField +} + +type TypeMapField struct { + FieldName string +} + func Generate(cfg Config) error { if err := cfg.normalize(); err != nil { return err @@ -58,11 +84,17 @@ func Generate(cfg Config) error { return err } for _, model := range modelsBuild.Models { - cfg.Typemap[model.GQLType] = cfg.modelPackagePath + "." + model.GoType + cfg.Typemap = append(cfg.Typemap, TypeMapEntry{ + TypeName: model.GQLType, + EntityPath: cfg.modelPackagePath + "." + model.GoType, + }) } for _, enum := range modelsBuild.Enums { - cfg.Typemap[enum.GQLType] = cfg.modelPackagePath + "." + enum.GoType + cfg.Typemap = append(cfg.Typemap, TypeMapEntry{ + TypeName: enum.GQLType, + EntityPath: cfg.modelPackagePath + "." + enum.GoType, + }) } } @@ -108,28 +140,28 @@ func (cfg *Config) normalize() error { cfg.ExecPackageName = sanitizePackageName(cfg.ExecPackageName) cfg.execPackagePath = fullPackageName(cfg.execDir, cfg.ExecPackageName) - builtins := map[string]string{ - "__Directive": "github.com/vektah/gqlgen/neelance/introspection.Directive", - "__Type": "github.com/vektah/gqlgen/neelance/introspection.Type", - "__Field": "github.com/vektah/gqlgen/neelance/introspection.Field", - "__EnumValue": "github.com/vektah/gqlgen/neelance/introspection.EnumValue", - "__InputValue": "github.com/vektah/gqlgen/neelance/introspection.InputValue", - "__Schema": "github.com/vektah/gqlgen/neelance/introspection.Schema", - "Int": "github.com/vektah/gqlgen/graphql.Int", - "Float": "github.com/vektah/gqlgen/graphql.Float", - "String": "github.com/vektah/gqlgen/graphql.String", - "Boolean": "github.com/vektah/gqlgen/graphql.Boolean", - "ID": "github.com/vektah/gqlgen/graphql.ID", - "Time": "github.com/vektah/gqlgen/graphql.Time", - "Map": "github.com/vektah/gqlgen/graphql.Map", + builtins := TypeMap{ + {TypeName: "__Directive", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Directive"}, + {TypeName: "__Type", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Type"}, + {TypeName: "__Field", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Field"}, + {TypeName: "__EnumValue", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.EnumValue"}, + {TypeName: "__InputValue", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.InputValue"}, + {TypeName: "__Schema", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Schema"}, + {TypeName: "Int", EntityPath: "github.com/vektah/gqlgen/graphql.Int"}, + {TypeName: "Float", EntityPath: "github.com/vektah/gqlgen/graphql.Float"}, + {TypeName: "String", EntityPath: "github.com/vektah/gqlgen/graphql.String"}, + {TypeName: "Boolean", EntityPath: "github.com/vektah/gqlgen/graphql.Boolean"}, + {TypeName: "ID", EntityPath: "github.com/vektah/gqlgen/graphql.ID"}, + {TypeName: "Time", EntityPath: "github.com/vektah/gqlgen/graphql.Time"}, + {TypeName: "Map", EntityPath: "github.com/vektah/gqlgen/graphql.Map"}, } if cfg.Typemap == nil { - cfg.Typemap = map[string]string{} + cfg.Typemap = TypeMap{} } - for k, v := range builtins { - if _, ok := cfg.Typemap[k]; !ok { - cfg.Typemap[k] = v + for _, entry := range builtins { + if !cfg.Typemap.Exists(entry.TypeName) { + cfg.Typemap = append(cfg.Typemap, entry) } } diff --git a/codegen/import_test.go b/codegen/import_test.go index 6e7c497a613..8690c498ba7 100644 --- a/codegen/import_test.go +++ b/codegen/import_test.go @@ -14,8 +14,8 @@ func TestInvalidPackagenames(t *testing.T) { type InvalidIdentifier { id: Int! } - `, map[string]string{ - "InvalidIdentifier": "github.com/vektah/gqlgen/codegen/testdata/invalid-packagename.InvalidIdentifier", + `, TypeMap{ + {TypeName: "InvalidIdentifier", EntityPath: "github.com/vektah/gqlgen/codegen/testdata/invalid-packagename.InvalidIdentifier"}, }) require.NoError(t, err) @@ -30,8 +30,8 @@ func TestImportCollisions(t *testing.T) { id: ID! } - `, map[string]string{ - "It": "github.com/vektah/gqlgen/codegen/testdata/introspection.It", + `, TypeMap{ + {TypeName: "It", EntityPath: "github.com/vektah/gqlgen/codegen/testdata/introspection.It"}, }) require.NoError(t, err) diff --git a/codegen/input_test.go b/codegen/input_test.go index c4191fd7952..52e0941b867 100644 --- a/codegen/input_test.go +++ b/codegen/input_test.go @@ -41,8 +41,8 @@ func TestRawMapInputs(t *testing.T) { a: Int b: Int } - `, map[string]string{ - "Changes": "map[string]interface{}", + `, TypeMap{ + {TypeName: "Changes", EntityPath: "map[string]interface{}"}, }) require.NoError(t, err) @@ -56,8 +56,8 @@ func TestRecursiveInputType(t *testing.T) { input RecursiveInputSlice { self: [RecursiveInputSlice!] } - `, map[string]string{ - "RecursiveInputSlice": "github.com/vektah/gqlgen/codegen/testdata.RecursiveInputSlice", + `, TypeMap{ + {TypeName: "RecursiveInputSlice", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.RecursiveInputSlice"}, }) require.NoError(t, err) @@ -84,8 +84,8 @@ func TestComplexInputTypes(t *testing.T) { type InnerObject { id: Int! } - `, map[string]string{ - "Changes": "map[string]interface{}", + `, TypeMap{ + {TypeName: "Changes", EntityPath: "map[string]interface{}"}, }) require.NoError(t, err) diff --git a/codegen/interface_test.go b/codegen/interface_test.go index bd669dd5326..efc4cc10628 100644 --- a/codegen/interface_test.go +++ b/codegen/interface_test.go @@ -25,18 +25,18 @@ func TestShapes(t *testing.T) { area: Float } union ShapeUnion = Circle | Rectangle - `, map[string]string{ - "Shape": "github.com/vektah/gqlgen/codegen/testdata.Shape", - "ShapeUnion": "github.com/vektah/gqlgen/codegen/testdata.ShapeUnion", - "Circle": "github.com/vektah/gqlgen/codegen/testdata.Circle", - "Rectangle": "github.com/vektah/gqlgen/codegen/testdata.Rectangle", + `, TypeMap{ + {TypeName: "Shape", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.Shape"}, + {TypeName: "ShapeUnion", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.ShapeUnion"}, + {TypeName: "Circle", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.Circle"}, + {TypeName: "Rectangle", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.Rectangle"}, }) require.NoError(t, err) } -func generate(name string, schema string, typemap ...map[string]string) error { +func generate(name string, schema string, typemap ...TypeMap) error { cfg := Config{ SchemaStr: schema, ExecFilename: "testdata/gen/" + name + "/exec.go", diff --git a/codegen/templates/templates.go b/codegen/templates/templates.go index 5a17ec98b7d..ddbfed271f7 100644 --- a/codegen/templates/templates.go +++ b/codegen/templates/templates.go @@ -5,11 +5,11 @@ package templates import ( "bytes" "fmt" + "sort" "strconv" "strings" "text/template" "unicode" - "sort" ) func Run(name string, tpldata interface{}) (*bytes.Buffer, error) { @@ -120,7 +120,7 @@ func dump(val interface{}) string { for _, key := range keys { data := val[key] - + buf.WriteString(strconv.Quote(key)) buf.WriteString(":") buf.WriteString(dump(data)) diff --git a/codegen/type_build.go b/codegen/type_build.go index 4e55bedf65a..d58db61d82e 100644 --- a/codegen/type_build.go +++ b/codegen/type_build.go @@ -16,7 +16,10 @@ func (cfg *Config) buildNamedTypes() NamedTypes { for _, schemaType := range cfg.schema.Types { t := namedTypeFromSchema(schemaType) - userType := cfg.Typemap[t.GQLType] + userType := "" + if userEntry := cfg.Typemap.Get(t.GQLType); userEntry != nil { + userType = userEntry.EntityPath + } t.IsUserDefined = userType != "" if userType == "" && t.IsScalar { userType = "github.com/vektah/gqlgen/graphql.String" diff --git a/main.go b/main.go index 91ab30ede45..1e8180269c9 100644 --- a/main.go +++ b/main.go @@ -54,20 +54,38 @@ func main() { } } -func loadTypeMap() map[string]string { - var goTypes map[string]string - if *typemap != "" { - b, err := ioutil.ReadFile(*typemap) - if err != nil { - fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()) - return nil - } +func loadTypeMap() codegen.TypeMap { + if *typemap == "" { + return nil + } + b, err := ioutil.ReadFile(*typemap) + if err != nil { + fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()) + return nil + } - if err = json.Unmarshal(b, &goTypes); err != nil { + var typeMap codegen.TypeMap + + var goTypes map[string]codegen.TypeMapEntry + if err = json.Unmarshal(b, &goTypes); err != nil { + var oldGoTypes map[string]string + if err = json.Unmarshal(b, &oldGoTypes); err != nil { fmt.Fprintln(os.Stderr, "unable to parse typemap: "+err.Error()) os.Exit(1) } + for typeName, entityPath := range oldGoTypes { + typeMap = append(typeMap, codegen.TypeMapEntry{ + TypeName: typeName, + EntityPath: entityPath, + }) + } + + return typeMap + } + for typeName, goType := range goTypes { + goType.TypeName = typeName + typeMap = append(typeMap, goType) } - return goTypes + return typeMap } diff --git a/test/types.json b/test/types.json index 4679c4cd6c4..0ca4651f136 100644 --- a/test/types.json +++ b/test/types.json @@ -1,5 +1,11 @@ { - "Element": "github.com/vektah/gqlgen/test.Element", - "Viewer": "github.com/vektah/gqlgen/test.Viewer", - "User": "remote_api.User" + "Element": { + "entityPath": "github.com/vektah/gqlgen/test.Element" + }, + "Viewer": { + "entityPath": "github.com/vektah/gqlgen/test.Viewer" + }, + "User": { + "entityPath": "remote_api.User" + } } From 5f4e894f1a754b2b17b499f6d207482aed987185 Mon Sep 17 00:00:00 2001 From: vvakame Date: Mon, 2 Jul 2018 19:05:27 +0900 Subject: [PATCH 2/4] Implement types.yaml parsing --- Gopkg.lock | 8 +++++++- Gopkg.toml | 4 ++++ codegen/codegen.go | 6 +++--- main.go | 35 +++++++++++++++++++++++++++++++++++ test/resolvers_test.go | 2 +- test/types.json | 11 ----------- test/types.yaml | 8 ++++++++ 7 files changed, 58 insertions(+), 16 deletions(-) delete mode 100644 test/types.json create mode 100644 test/types.yaml diff --git a/Gopkg.lock b/Gopkg.lock index 0480a7363e8..ac07db6dfc1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -127,6 +127,12 @@ ] revision = "ce871d178848e3eea1e8795e5cfb74053dde4bb9" +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + [[projects]] branch = "master" name = "sourcegraph.com/sourcegraph/appdash" @@ -150,6 +156,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5275b6a5c88fd233faf5afa8f59f3a36ae9fe6538ee6331fac3c1078fecd6df5" + inputs-digest = "ee97741e2ec373079694c0adc517dd7bb0dc3271ec459281fa0209d066f04995" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 69486f6fd11..b12c5375ffe 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -15,3 +15,7 @@ required = ["github.com/vektah/dataloaden"] [prune] go-tests = true unused-packages = true + +[[constraint]] + name = "gopkg.in/yaml.v2" + version = "2.2.1" diff --git a/codegen/codegen.go b/codegen/codegen.go index 746759e7e6f..25989b8d3f7 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -51,13 +51,13 @@ func (tm TypeMap) Get(typeName string) *TypeMapEntry { } type TypeMapEntry struct { - TypeName string - EntityPath string + TypeName string `yaml:"typeName"` + EntityPath string `yaml:"entityPath"` Fields []TypeMapField } type TypeMapField struct { - FieldName string + FieldName string `yaml:"fieldName"` } func Generate(cfg Config) error { diff --git a/main.go b/main.go index 1e8180269c9..44cd3a08887 100644 --- a/main.go +++ b/main.go @@ -6,8 +6,10 @@ import ( "fmt" "io/ioutil" "os" + "strings" "github.com/vektah/gqlgen/codegen" + "gopkg.in/yaml.v2" ) var output = flag.String("out", "generated.go", "the file to write to") @@ -58,6 +60,19 @@ func loadTypeMap() codegen.TypeMap { if *typemap == "" { return nil } + + if strings.HasSuffix(*typemap, ".json") { + return loadTypeMapJSON() + } + + return loadTypeMapYAML() +} + +func loadTypeMapJSON() codegen.TypeMap { + if *typemap == "" { + return nil + } + b, err := ioutil.ReadFile(*typemap) if err != nil { fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()) @@ -89,3 +104,23 @@ func loadTypeMap() codegen.TypeMap { return typeMap } + +func loadTypeMapYAML() codegen.TypeMap { + if *typemap == "" { + return nil + } + + b, err := ioutil.ReadFile(*typemap) + if err != nil { + fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()) + return nil + } + + var typeMap codegen.TypeMap + if err = yaml.Unmarshal(b, &typeMap); err != nil { + fmt.Fprintln(os.Stderr, "unable to parse typemap: "+err.Error()) + os.Exit(1) + } + + return typeMap +} diff --git a/test/resolvers_test.go b/test/resolvers_test.go index ef3cb9c81bc..220d86f4635 100644 --- a/test/resolvers_test.go +++ b/test/resolvers_test.go @@ -1,4 +1,4 @@ -//go:generate gorunpkg github.com/vektah/gqlgen -out generated.go -typemap types.json -models models/generated.go +//go:generate gorunpkg github.com/vektah/gqlgen -out generated.go -typemap types.yaml -models models/generated.go package test diff --git a/test/types.json b/test/types.json deleted file mode 100644 index 0ca4651f136..00000000000 --- a/test/types.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "Element": { - "entityPath": "github.com/vektah/gqlgen/test.Element" - }, - "Viewer": { - "entityPath": "github.com/vektah/gqlgen/test.Viewer" - }, - "User": { - "entityPath": "remote_api.User" - } -} diff --git a/test/types.yaml b/test/types.yaml new file mode 100644 index 00000000000..c0ed0bad498 --- /dev/null +++ b/test/types.yaml @@ -0,0 +1,8 @@ +- typeName: Element + entityPath: github.com/vektah/gqlgen/test.Element + +- typeName: Viewer + entityPath: github.com/vektah/gqlgen/test.Viewer + +- typeName: User + entityPath: remote_api.User From a5b53da5046e2f55666d6f47b842f33b10f14943 Mon Sep 17 00:00:00 2001 From: vvakame Date: Mon, 2 Jul 2018 19:21:17 +0900 Subject: [PATCH 3/4] Add format check to -typemap argument --- codegen/codegen.go | 12 ++++++++++++ main.go | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/codegen/codegen.go b/codegen/codegen.go index 25989b8d3f7..df5d6e21a9e 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -50,6 +50,18 @@ func (tm TypeMap) Get(typeName string) *TypeMapEntry { return nil } +func (tm TypeMap) Check() error { + for idx, entry := range tm { + if entry.TypeName == "" { + return fmt.Errorf("entity #%d: typeName is not defined", idx+1) + } + if entry.EntityPath == "" { + return fmt.Errorf("entity #%d: entityPath is not defined", idx+1) + } + } + return nil +} + type TypeMapEntry struct { TypeName string `yaml:"typeName"` EntityPath string `yaml:"entityPath"` diff --git a/main.go b/main.go index 44cd3a08887..f4d49055ee7 100644 --- a/main.go +++ b/main.go @@ -40,6 +40,11 @@ func main() { } types := loadTypeMap() + err = types.Check() + if err != nil { + fmt.Fprintln(os.Stderr, "invalid typemap format: "+err.Error()) + os.Exit(1) + } err = codegen.Generate(codegen.Config{ ModelFilename: *models, From 91c7fe20e7b661002ed242dcfd87f966b71b7bc2 Mon Sep 17 00:00:00 2001 From: vvakame Date: Tue, 3 Jul 2018 17:28:00 +0900 Subject: [PATCH 4/4] address comment --- codegen/codegen.go | 104 +++++++++++++++--------------- codegen/import_test.go | 4 +- codegen/input_test.go | 6 +- codegen/interface_test.go | 8 +-- codegen/type_build.go | 2 +- main.go | 132 +++++++++++++++++++------------------- test/.gqlgen.yml | 11 ++++ test/resolvers_test.go | 2 +- test/types.yaml | 8 --- 9 files changed, 141 insertions(+), 136 deletions(-) create mode 100644 test/.gqlgen.yml delete mode 100644 test/types.yaml diff --git a/codegen/codegen.go b/codegen/codegen.go index df5d6e21a9e..212f5ae3c40 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -18,58 +18,60 @@ import ( ) type Config struct { - SchemaStr string - Typemap TypeMap + SchemaFilename string `yaml:"schema,omitempty"` + SchemaStr string `yaml:"-"` + Typemap TypeMap `yaml:"models,omitempty"` - schema *schema.Schema + schema *schema.Schema `yaml:"-"` - ExecFilename string - ExecPackageName string - execPackagePath string - execDir string + ExecFilename string `yaml:"output,omitempty"` + ExecPackageName string `yaml:"package,omitempty"` + execPackagePath string `yaml:"-"` + execDir string `yaml:"-"` - ModelFilename string - ModelPackageName string - modelPackagePath string - modelDir string + ModelFilename string `yaml:"modeloutput,omitempty"` + ModelPackageName string `yaml:"modelpackage,omitempty"` + modelPackagePath string `yaml:"-"` + modelDir string `yaml:"-"` } -type TypeMap []TypeMapEntry +func (cfg *Config) Check() error { + err := cfg.Typemap.Check() + if err != nil { + return fmt.Errorf("config: %s", err.Error()) + } + return nil +} + +type TypeMap map[string]TypeMapEntry func (tm TypeMap) Exists(typeName string) bool { return tm.Get(typeName) != nil } func (tm TypeMap) Get(typeName string) *TypeMapEntry { - for _, entry := range tm { - if entry.TypeName == typeName { - return &entry - } + entry, ok := tm[typeName] + if !ok { + return nil } - - return nil + return &entry } func (tm TypeMap) Check() error { - for idx, entry := range tm { - if entry.TypeName == "" { - return fmt.Errorf("entity #%d: typeName is not defined", idx+1) - } - if entry.EntityPath == "" { - return fmt.Errorf("entity #%d: entityPath is not defined", idx+1) + for typeName, entry := range tm { + if entry.Model == "" { + return fmt.Errorf("model %s: entityPath is not defined", typeName) } } return nil } type TypeMapEntry struct { - TypeName string `yaml:"typeName"` - EntityPath string `yaml:"entityPath"` - Fields []TypeMapField + Model string `yaml:"model"` + Fields map[string]TypeMapField `yaml:"fields,omitempty"` } type TypeMapField struct { - FieldName string `yaml:"fieldName"` } func Generate(cfg Config) error { @@ -96,17 +98,15 @@ func Generate(cfg Config) error { return err } for _, model := range modelsBuild.Models { - cfg.Typemap = append(cfg.Typemap, TypeMapEntry{ - TypeName: model.GQLType, - EntityPath: cfg.modelPackagePath + "." + model.GoType, - }) + cfg.Typemap[model.GQLType] = TypeMapEntry{ + Model: cfg.modelPackagePath + "." + model.GoType, + } } for _, enum := range modelsBuild.Enums { - cfg.Typemap = append(cfg.Typemap, TypeMapEntry{ - TypeName: enum.GQLType, - EntityPath: cfg.modelPackagePath + "." + enum.GoType, - }) + cfg.Typemap[enum.GQLType] = TypeMapEntry{ + Model: cfg.modelPackagePath + "." + enum.GoType, + } } } @@ -153,27 +153,27 @@ func (cfg *Config) normalize() error { cfg.execPackagePath = fullPackageName(cfg.execDir, cfg.ExecPackageName) builtins := TypeMap{ - {TypeName: "__Directive", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Directive"}, - {TypeName: "__Type", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Type"}, - {TypeName: "__Field", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Field"}, - {TypeName: "__EnumValue", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.EnumValue"}, - {TypeName: "__InputValue", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.InputValue"}, - {TypeName: "__Schema", EntityPath: "github.com/vektah/gqlgen/neelance/introspection.Schema"}, - {TypeName: "Int", EntityPath: "github.com/vektah/gqlgen/graphql.Int"}, - {TypeName: "Float", EntityPath: "github.com/vektah/gqlgen/graphql.Float"}, - {TypeName: "String", EntityPath: "github.com/vektah/gqlgen/graphql.String"}, - {TypeName: "Boolean", EntityPath: "github.com/vektah/gqlgen/graphql.Boolean"}, - {TypeName: "ID", EntityPath: "github.com/vektah/gqlgen/graphql.ID"}, - {TypeName: "Time", EntityPath: "github.com/vektah/gqlgen/graphql.Time"}, - {TypeName: "Map", EntityPath: "github.com/vektah/gqlgen/graphql.Map"}, + "__Directive": {Model: "github.com/vektah/gqlgen/neelance/introspection.Directive"}, + "__Type": {Model: "github.com/vektah/gqlgen/neelance/introspection.Type"}, + "__Field": {Model: "github.com/vektah/gqlgen/neelance/introspection.Field"}, + "__EnumValue": {Model: "github.com/vektah/gqlgen/neelance/introspection.EnumValue"}, + "__InputValue": {Model: "github.com/vektah/gqlgen/neelance/introspection.InputValue"}, + "__Schema": {Model: "github.com/vektah/gqlgen/neelance/introspection.Schema"}, + "Int": {Model: "github.com/vektah/gqlgen/graphql.Int"}, + "Float": {Model: "github.com/vektah/gqlgen/graphql.Float"}, + "String": {Model: "github.com/vektah/gqlgen/graphql.String"}, + "Boolean": {Model: "github.com/vektah/gqlgen/graphql.Boolean"}, + "ID": {Model: "github.com/vektah/gqlgen/graphql.ID"}, + "Time": {Model: "github.com/vektah/gqlgen/graphql.Time"}, + "Map": {Model: "github.com/vektah/gqlgen/graphql.Map"}, } if cfg.Typemap == nil { cfg.Typemap = TypeMap{} } - for _, entry := range builtins { - if !cfg.Typemap.Exists(entry.TypeName) { - cfg.Typemap = append(cfg.Typemap, entry) + for typeName, entry := range builtins { + if !cfg.Typemap.Exists(typeName) { + cfg.Typemap[typeName] = entry } } diff --git a/codegen/import_test.go b/codegen/import_test.go index 8690c498ba7..0e55887430e 100644 --- a/codegen/import_test.go +++ b/codegen/import_test.go @@ -15,7 +15,7 @@ func TestInvalidPackagenames(t *testing.T) { id: Int! } `, TypeMap{ - {TypeName: "InvalidIdentifier", EntityPath: "github.com/vektah/gqlgen/codegen/testdata/invalid-packagename.InvalidIdentifier"}, + "InvalidIdentifier": {Model: "github.com/vektah/gqlgen/codegen/testdata/invalid-packagename.InvalidIdentifier"}, }) require.NoError(t, err) @@ -31,7 +31,7 @@ func TestImportCollisions(t *testing.T) { } `, TypeMap{ - {TypeName: "It", EntityPath: "github.com/vektah/gqlgen/codegen/testdata/introspection.It"}, + "It": {Model: "github.com/vektah/gqlgen/codegen/testdata/introspection.It"}, }) require.NoError(t, err) diff --git a/codegen/input_test.go b/codegen/input_test.go index 52e0941b867..62e157b1a69 100644 --- a/codegen/input_test.go +++ b/codegen/input_test.go @@ -42,7 +42,7 @@ func TestRawMapInputs(t *testing.T) { b: Int } `, TypeMap{ - {TypeName: "Changes", EntityPath: "map[string]interface{}"}, + "Changes": {Model: "map[string]interface{}"}, }) require.NoError(t, err) @@ -57,7 +57,7 @@ func TestRecursiveInputType(t *testing.T) { self: [RecursiveInputSlice!] } `, TypeMap{ - {TypeName: "RecursiveInputSlice", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.RecursiveInputSlice"}, + "RecursiveInputSlice": {Model: "github.com/vektah/gqlgen/codegen/testdata.RecursiveInputSlice"}, }) require.NoError(t, err) @@ -85,7 +85,7 @@ func TestComplexInputTypes(t *testing.T) { id: Int! } `, TypeMap{ - {TypeName: "Changes", EntityPath: "map[string]interface{}"}, + "Changes": {Model: "map[string]interface{}"}, }) require.NoError(t, err) diff --git a/codegen/interface_test.go b/codegen/interface_test.go index efc4cc10628..a6d6ef8761e 100644 --- a/codegen/interface_test.go +++ b/codegen/interface_test.go @@ -26,10 +26,10 @@ func TestShapes(t *testing.T) { } union ShapeUnion = Circle | Rectangle `, TypeMap{ - {TypeName: "Shape", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.Shape"}, - {TypeName: "ShapeUnion", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.ShapeUnion"}, - {TypeName: "Circle", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.Circle"}, - {TypeName: "Rectangle", EntityPath: "github.com/vektah/gqlgen/codegen/testdata.Rectangle"}, + "Shape": {Model: "github.com/vektah/gqlgen/codegen/testdata.Shape"}, + "ShapeUnion": {Model: "github.com/vektah/gqlgen/codegen/testdata.ShapeUnion"}, + "Circle": {Model: "github.com/vektah/gqlgen/codegen/testdata.Circle"}, + "Rectangle": {Model: "github.com/vektah/gqlgen/codegen/testdata.Rectangle"}, }) require.NoError(t, err) diff --git a/codegen/type_build.go b/codegen/type_build.go index d58db61d82e..b50b1d292a5 100644 --- a/codegen/type_build.go +++ b/codegen/type_build.go @@ -18,7 +18,7 @@ func (cfg *Config) buildNamedTypes() NamedTypes { userType := "" if userEntry := cfg.Typemap.Get(t.GQLType); userEntry != nil { - userType = userEntry.EntityPath + userType = userEntry.Model } t.IsUserDefined = userType != "" if userType == "" && t.IsScalar { diff --git a/main.go b/main.go index f4d49055ee7..2d69ac01268 100644 --- a/main.go +++ b/main.go @@ -1,20 +1,19 @@ package main import ( - "encoding/json" "flag" "fmt" "io/ioutil" "os" - "strings" "github.com/vektah/gqlgen/codegen" "gopkg.in/yaml.v2" ) -var output = flag.String("out", "generated.go", "the file to write to") -var models = flag.String("models", "models_gen.go", "the file to write the models to") -var schemaFilename = flag.String("schema", "schema.graphql", "the graphql schema to generate types from") +var configFilename = flag.String("config", ".gqlgen.yml", "the file to configuration to") +var output = flag.String("out", "", "the file to write to") +var models = flag.String("models", "", "the file to write the models to") +var schemaFilename = flag.String("schema", "", "the graphql schema to generate types from") var typemap = flag.String("typemap", "", "a json map going from graphql to golang types") var packageName = flag.String("package", "", "the package name") var modelPackageName = flag.String("modelpackage", "", "the package name to use for models") @@ -33,99 +32,102 @@ func main() { os.Exit(1) } - schemaRaw, err := ioutil.ReadFile(*schemaFilename) + config := loadConfig() + + // overwrite by commandline options + var emitYamlGuidance bool + if *schemaFilename != "" { + config.SchemaFilename = *schemaFilename + } + if *models != "" { + config.ModelFilename = *models + } + if *output != "" { + config.ExecFilename = *output + } + if *packageName != "" { + config.ExecPackageName = *packageName + } + if *modelPackageName != "" { + config.ModelPackageName = *modelPackageName + } + if *typemap != "" { + config.Typemap = loadModelMap() + emitYamlGuidance = true + } + + schemaRaw, err := ioutil.ReadFile(config.SchemaFilename) if err != nil { fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error()) os.Exit(1) } + config.SchemaStr = string(schemaRaw) - types := loadTypeMap() - err = types.Check() - if err != nil { - fmt.Fprintln(os.Stderr, "invalid typemap format: "+err.Error()) + if err := config.Check(); err != nil { + fmt.Fprintln(os.Stderr, "invalid config format: "+err.Error()) os.Exit(1) } - err = codegen.Generate(codegen.Config{ - ModelFilename: *models, - ExecFilename: *output, - ExecPackageName: *packageName, - ModelPackageName: *modelPackageName, - SchemaStr: string(schemaRaw), - Typemap: types, - }) + if emitYamlGuidance { + b, err := yaml.Marshal(config) + if err != nil { + fmt.Fprintln(os.Stderr, "unable to marshal yaml: "+err.Error()) + os.Exit(1) + } + + fmt.Fprintf(os.Stderr, "you should use .gqlgen.yml with below content.\n\n%s\n", string(b)) + } + err = codegen.Generate(*config) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(2) } } -func loadTypeMap() codegen.TypeMap { - if *typemap == "" { - return nil - } - - if strings.HasSuffix(*typemap, ".json") { - return loadTypeMapJSON() - } +func loadConfig() *codegen.Config { - return loadTypeMapYAML() -} - -func loadTypeMapJSON() codegen.TypeMap { - if *typemap == "" { - return nil + config := &codegen.Config{ + SchemaFilename: "schema.graphql", + ModelFilename: "models_gen.go", + ExecFilename: "generated.go", } - b, err := ioutil.ReadFile(*typemap) - if err != nil { - fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()) - return nil + b, err := ioutil.ReadFile(*configFilename) + if os.IsNotExist(err) { + return config + } else if err != nil { + fmt.Fprintln(os.Stderr, "unable to open config: "+err.Error()) + os.Exit(1) } - var typeMap codegen.TypeMap - - var goTypes map[string]codegen.TypeMapEntry - if err = json.Unmarshal(b, &goTypes); err != nil { - var oldGoTypes map[string]string - if err = json.Unmarshal(b, &oldGoTypes); err != nil { - fmt.Fprintln(os.Stderr, "unable to parse typemap: "+err.Error()) - os.Exit(1) - } - for typeName, entityPath := range oldGoTypes { - typeMap = append(typeMap, codegen.TypeMapEntry{ - TypeName: typeName, - EntityPath: entityPath, - }) - } - - return typeMap - } - for typeName, goType := range goTypes { - goType.TypeName = typeName - typeMap = append(typeMap, goType) + if err := yaml.Unmarshal(b, config); err != nil { + fmt.Fprintln(os.Stderr, "unable to parse config: "+err.Error()) + os.Exit(1) } - return typeMap + return config } -func loadTypeMapYAML() codegen.TypeMap { - if *typemap == "" { - return nil - } - +func loadModelMap() codegen.TypeMap { + var goTypes map[string]string b, err := ioutil.ReadFile(*typemap) if err != nil { fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()) return nil } - var typeMap codegen.TypeMap - if err = yaml.Unmarshal(b, &typeMap); err != nil { + if err = yaml.Unmarshal(b, &goTypes); err != nil { fmt.Fprintln(os.Stderr, "unable to parse typemap: "+err.Error()) os.Exit(1) } + typeMap := make(codegen.TypeMap) + for typeName, entityPath := range goTypes { + typeMap[typeName] = codegen.TypeMapEntry{ + Model: entityPath, + } + } + return typeMap } diff --git a/test/.gqlgen.yml b/test/.gqlgen.yml new file mode 100644 index 00000000000..85c404fc822 --- /dev/null +++ b/test/.gqlgen.yml @@ -0,0 +1,11 @@ +schema: schema.graphql +output: generated.go +modeloutput: models/generated.go + +models: + Element: + model: github.com/vektah/gqlgen/test.Element + Viewer: + model: github.com/vektah/gqlgen/test.Viewer + User: + model: remote_api.User diff --git a/test/resolvers_test.go b/test/resolvers_test.go index 220d86f4635..805e68e76b5 100644 --- a/test/resolvers_test.go +++ b/test/resolvers_test.go @@ -1,4 +1,4 @@ -//go:generate gorunpkg github.com/vektah/gqlgen -out generated.go -typemap types.yaml -models models/generated.go +//go:generate gorunpkg github.com/vektah/gqlgen package test diff --git a/test/types.yaml b/test/types.yaml deleted file mode 100644 index c0ed0bad498..00000000000 --- a/test/types.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- typeName: Element - entityPath: github.com/vektah/gqlgen/test.Element - -- typeName: Viewer - entityPath: github.com/vektah/gqlgen/test.Viewer - -- typeName: User - entityPath: remote_api.User