diff --git a/.env.example b/.env.example index d7659a3..be05b4b 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ -GRAPHQL_TYPEDEF_DEBUG=false -GRAPHQL_TYPEDEF_OUTPUT_DIRECTORY=internal/graphqltypes -GRAPHQL_TYPEDEF_OUTPUT_PACKAGE=graphqltypes -GRAPHQL_TYPEDEF_GRAPHQL_ENDPOINT=http://localhost:5000/v1/graphql -GRAPHQL_TYPEDEF_GRAPHQL_AUTH_HEADER=x-hasura-admin-secret -GRAPHQL_TYPEDEF_GRAPHQL_AUTH_TOKEN= +GQLASSIST_DEBUG=false +GQLASSIST_OUTPUT_DIRECTORY=internal/graphqltypes +GQLASSIST_OUTPUT_PACKAGE=graphqltypes +GQLASSIST_GRAPHQL_ENDPOINT=http://localhost:5000/v1/graphql +GQLASSIST_GRAPHQL_AUTH_HEADER=x-hasura-admin-secret +GQLASSIST_GRAPHQL_AUTH_TOKEN= diff --git a/README.md b/README.md index 1a81fe1..36092e5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,19 @@ -# graphql-typedef-go -Golang type definitions generator for consuming GraphQL server resources. +GQLAssist +=== + +> [GQLAssist][project-github] is a **client-side** [GraphQL][link-graphql] struct and type definitions generator for [Go][link-golang] programming language. ## Installation ```bash -go get -u github.com/shakahl/graphql-typedef-go +go get -u github.com/shakahl/gqlassist ``` +## License + +[GQLAssist][project-github] is distributed under the MIT license. See also LICENSE. + + +[project-github]: https://github.com/shakahl/gqlassist "shakahl/gqlassist" +[link-golang]: https://golang.org "Go" +[link-graphql]: https://graphql.org/ "GraphQL" diff --git a/assets/IntrospectionQuery.graphql b/assets/IntrospectionQuery.graphql new file mode 100644 index 0000000..e69de29 diff --git a/assets/templates/instrospect.graphql b/assets/templates/IntrospectionQuery.graphql similarity index 93% rename from assets/templates/instrospect.graphql rename to assets/templates/IntrospectionQuery.graphql index 56303d0..e69aa54 100644 --- a/assets/templates/instrospect.graphql +++ b/assets/templates/IntrospectionQuery.graphql @@ -1,4 +1,5 @@ +# GraphQL Query: IntrospectionQuery - Defines the query to fetch GraphQL server's schema in JSON-friendly AST query IntrospectionQuery { __schema { queryType { name } diff --git a/assets/templates/gen_graphql_enums.gotmpl b/assets/templates/graphql_enums.gotmpl similarity index 91% rename from assets/templates/gen_graphql_enums.gotmpl rename to assets/templates/graphql_enums.gotmpl index acddc4c..7094104 100644 --- a/assets/templates/gen_graphql_enums.gotmpl +++ b/assets/templates/graphql_enums.gotmpl @@ -1,17 +1,19 @@ -// Code generated by gen.go; DO NOT EDIT. +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( -"bytes" -"encoding/json" -"strings" -// "fmt" + "bytes" + "encoding/json" + "strings" + // "fmt" ) -{{range .data.__schema.types | filterBy "kind" "ENUM" | sortByName}}{{if and (eq .kind "ENUM") (not (isExcluded .name))}} - {{template "enum" .}} -{{end}}{{end}} +{{ range .Schema.data.__schema.types | filterBy "kind" "ENUM" | sortByName }} + {{- if and (eq .kind "ENUM") (not (isExcluded .name)) -}} + {{- template "enum" . -}} + {{- end -}} +{{ end }} {{- define "enum" -}} @@ -110,3 +112,4 @@ import ( } {{- end -}} + diff --git a/assets/templates/gen_graphql_input_objects.gotmpl b/assets/templates/graphql_input_objects.gotmpl similarity index 76% rename from assets/templates/gen_graphql_input_objects.gotmpl rename to assets/templates/graphql_input_objects.gotmpl index f26c6e3..83463cd 100644 --- a/assets/templates/gen_graphql_input_objects.gotmpl +++ b/assets/templates/graphql_input_objects.gotmpl @@ -1,6 +1,6 @@ -// Code generated by gen.go; DO NOT EDIT. +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( "time" @@ -10,24 +10,24 @@ import ( // Input represents one of the Input structs: // -// {{join (extractField "name" (filterBy "kind" "INPUT_OBJECT" .data.__schema.types)) ", "}}. +// {{join (extractField "name" (filterBy "kind" "INPUT_OBJECT" .Schema.data.__schema.types)) ", "}}. type Input interface{} var ( TypeMapInputObjects = map[string]string{ -{{ range .data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{if eq .kind "INPUT_OBJECT" -}} +{{ range .Schema.data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{if eq .kind "INPUT_OBJECT" -}} {{ .name | identifier | quote }}: {{ .name | quote }}, {{ end }}{{- end }} } ReverseTypeMapInputObjects = map[string]string{ -{{ range .data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{ if eq .kind "INPUT_OBJECT" -}} +{{ range .Schema.data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{ if eq .kind "INPUT_OBJECT" -}} {{ .name | quote }}: {{ .name | identifier| quote }}, {{ end }}{{- end }} } ) -{{range .data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName}}{{if eq .kind "INPUT_OBJECT"}} +{{range .Schema.data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName}}{{if eq .kind "INPUT_OBJECT"}} {{template "inputObject" .}} {{end}}{{end}} diff --git a/assets/templates/gen_graphql_objects.gotmpl b/assets/templates/graphql_objects.gotmpl similarity index 77% rename from assets/templates/gen_graphql_objects.gotmpl rename to assets/templates/graphql_objects.gotmpl index 61c8166..882296d 100644 --- a/assets/templates/gen_graphql_objects.gotmpl +++ b/assets/templates/graphql_objects.gotmpl @@ -1,6 +1,6 @@ -// Code generated by gen.go; DO NOT EDIT. +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( "time" @@ -10,7 +10,7 @@ import ( // Object represents one of the Input structs: // -// {{join (extractField "name" (filterBy "kind" "OBJECT" .data.__schema.types)) ", "}}. +// {{join (extractField "name" (filterBy "kind" "OBJECT" .Schema.data.__schema.types)) ", "}}. type Object interface{} @@ -21,18 +21,18 @@ GQLTypeName *string ` + "`" + `json:"__typename,omitempty"` + "`" + ` var ( TypeMapObjects = map[string]string{ -{{ range .data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{if eq .kind "OBJECT" -}} +{{ range .Schema.data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{if eq .kind "OBJECT" -}} {{ .name | identifier | quote }}: {{ .name | quote }}, {{ end }}{{- end }} } ReverseTypeMapObjects = map[string]string{ -{{ range .data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{ if eq .kind "OBJECT" -}} +{{ range .Schema.data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{ if eq .kind "OBJECT" -}} {{ .name | quote }}: {{ .name | identifier| quote }}, {{ end }}{{- end }} } ) -{{range .data.__schema.types | filterBy "kind" "OBJECT" | sortByName}}{{if eq .kind "OBJECT"}} +{{range .Schema.data.__schema.types | filterBy "kind" "OBJECT" | sortByName}}{{if eq .kind "OBJECT"}} {{template "object" .}} {{end}}{{end}} diff --git a/assets/templates/gen_graphql_scalars.gotmpl b/assets/templates/graphql_scalars.gotmpl similarity index 89% rename from assets/templates/gen_graphql_scalars.gotmpl rename to assets/templates/graphql_scalars.gotmpl index 5869655..59cb590 100644 --- a/assets/templates/gen_graphql_scalars.gotmpl +++ b/assets/templates/graphql_scalars.gotmpl @@ -1,14 +1,14 @@ -// Code generated by gen.go; DO NOT EDIT. +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( -"time" + "time" -"github.com/google/uuid" + "github.com/google/uuid" ) -{{ if false -}} +{{ if false }} type ( // Boolean represents true or false values. Boolean bool @@ -50,13 +50,12 @@ import ( // NewString is a helper to make a new *String. func NewString(v String) *String { return &v } -{{- end }} +{{ end -}} -{{ range .data.__schema.types | filterBy "kind" "SCALAR" | sortByName -}} +{{ range .Schema.data.__schema.types | filterBy "kind" "SCALAR" | sortByName -}} {{- if and (eq .kind "SCALAR") (not (isExcluded .name)) -}} {{- template "scalar" . -}} - {{- end -}} -{{- end }} + {{- end -}}{{- end }} {{- define "scalar" -}} // {{ .name | scalarIdentifier }} @graphql="{{ .name }}" {{if .description}}{{.description | clean | formatDescription}}{{end}} @@ -64,5 +63,6 @@ import ( // New{{ .name | scalarIdentifier }} is a helper to make a new *{{ .name | scalarIdentifier }}. func New{{ .name | scalarIdentifier }}(v {{ .name | scalarIdentifier }}) *{{ .name | scalarIdentifier }} { return &v } + {{ end -}} diff --git a/cmd/generate.go b/cmd/generate.go index a2d8163..7724ad1 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/shakahl/graphql-typedef-go/internal/config" - "github.com/shakahl/graphql-typedef-go/internal/generator" + "github.com/shakahl/gqlassist/internal/config" + "github.com/shakahl/gqlassist/internal/gqlassist" ) // generateCmd represents the "generate" command @@ -20,7 +20,7 @@ var generateCmd = &cobra.Command{ logger := log.New(os.Stdout, "graphql_type_def_generator", log.LstdFlags|log.LUTC) cfg := config.Get() - gopts := generator.GraphQLTypeDefGeneratorOptions{ + gopts := gqlassist.GraphQLTypeDefGeneratorConfig{ Endpoint: cfg.GraphQLEndpoint, AuthHeader: cfg.GraphQLAuthHeader, AuthToken: cfg.GraphQLAuthToken, @@ -28,7 +28,7 @@ var generateCmd = &cobra.Command{ OutputPackage: cfg.OutputPackage, } - gen := generator.New(gopts, logger) + gen := gqlassist.New(gopts, logger) if err := gen.Generate(); err != nil { logger.Fatalln(err) diff --git a/cmd/init.go b/cmd/init.go index dc71af8..4674b3e 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/shakahl/graphql-typedef-go/internal/config" + "github.com/shakahl/gqlassist/internal/config" ) // initCmd represents the "generate" command diff --git a/cmd/root.go b/cmd/root.go index 75ba250..2c9794f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,9 +9,9 @@ import ( "github.com/spf13/viper" - "github.com/shakahl/graphql-typedef-go/internal/config" - "github.com/shakahl/graphql-typedef-go/internal/utils" - "github.com/shakahl/graphql-typedef-go/meta" + "github.com/shakahl/gqlassist/internal/config" + "github.com/shakahl/gqlassist/internal/utils" + "github.com/shakahl/gqlassist/meta" ) var cfgFile string diff --git a/go.mod b/go.mod index b11ab9f..f997f12 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,20 @@ -module github.com/shakahl/graphql-typedef-go +module github.com/shakahl/gqlassist go 1.15 require ( + github.com/Masterminds/goutils v1.1.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible + github.com/google/uuid v1.1.2 // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/imdario/mergo v0.3.11 // indirect github.com/joho/godotenv v1.3.0 github.com/kelseyhightower/envconfig v1.4.0 + github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/errors v0.8.1 + github.com/rakyll/statik v0.1.7 github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f github.com/spf13/cobra v1.0.0 github.com/spf13/pflag v1.0.3 diff --git a/go.sum b/go.sum index ca1dcb4..f2726c0 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,12 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -65,6 +71,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -94,6 +102,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= @@ -120,6 +132,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -129,6 +143,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -150,6 +166,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -196,6 +214,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -311,6 +330,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/config/config.go b/internal/config/config.go index a46eb18..317bec1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,12 +14,12 @@ import ( "github.com/spf13/viper" "github.com/kelseyhightower/envconfig" - "github.com/shakahl/graphql-typedef-go/internal/utils" - "github.com/shakahl/graphql-typedef-go/meta" + "github.com/shakahl/gqlassist/internal/utils" + "github.com/shakahl/gqlassist/meta" ) const ( - EnvPrefix = "GRAPHQL_TYPEDEF" + EnvPrefix = "GQLASSIST" ) var ( diff --git a/internal/config/schema.go b/internal/config/schema.go index da1b65e..f7ac451 100644 --- a/internal/config/schema.go +++ b/internal/config/schema.go @@ -3,7 +3,7 @@ package config import ( "errors" - "github.com/shakahl/graphql-typedef-go/internal/utils" + "github.com/shakahl/gqlassist/internal/utils" ) const ( diff --git a/internal/generator/template_utils.go b/internal/generator/template_utils.go deleted file mode 100644 index 9614cef..0000000 --- a/internal/generator/template_utils.go +++ /dev/null @@ -1,246 +0,0 @@ -package generator - -import ( - "fmt" - "reflect" - "sort" - "strconv" - "strings" - "text/template" - - "github.com/shurcooL/graphql/ident" -) - -func renderGeneratorTemplate(name, text string, params map[string]string) *template.Template { - funcMap := makeTemplateFuncMap(params) - return template.Must(template.New(name).Funcs(funcMap).Parse(text)) -} - -func makeTemplateFuncMap(params map[string]string) template.FuncMap { - isExcluded := func(s string) bool { - return false - } - ucFirst := func(s string) string { - s = strings.ToUpper(s[0:1]) + s[1:] - return s - } - lcFirst := func(s string) string { - s = strings.ToLower(s[0:1]) + s[1:] - return s - } - identifier := func(s string) string { - s = strings.TrimLeft(s, "_") - // return "T_" + s - return ident.ParseScreamingSnakeCase(s).ToMixedCaps() - // return ident.ParseLowerCamelCase(name).ToMixedCaps() - } - scalarIdentifier := func(s string) string { - return ident.ParseScreamingSnakeCase(s).ToMixedCaps() - // s = strings.TrimLeft(s, "_") - // s = strings.ToUpper(s[0:1]) + s[1:] - // return s - // return "T_" + s - // return ident.ParseScreamingSnakeCase(s).ToMixedCaps() - // return ident.ParseLowerCamelCase(name).ToMixedCaps() - } - enumIdentifierValueSuffix := func(s string) string { - // return s - // return ident.ParseScreamingSnakeCase(name).ToMixedCaps() - return "_" + strings.ToUpper(s) - } - enumTypeString := func(s string) string { - return identifier(s) - } - enumAllValuesIdentifier := func(s string) string { - return enumTypeString(s) + "__LIST" - } - scalarTypeString := func(gqltype string) string { - tnorm := strings.ToLower(gqltype) - switch tnorm { - case "order_by": - return "string" - case "time": - return "time.Time" - case "timestamp": - return "time.Time" - case "timestamptz": - return "time.Time" - case "date": - return "time.Time" - case "datetime": - return "time.Time" - case "uuid": - return "uuid.UUID" - case "id": - return "string" - case "string": - return "string" - case "boolean": - return "bool" - case "float": - return "float64" - case "integer": - return "time.Time" - case "int": - return "int32" - case "json": - return "map[string]interface{}" - case "jsonb": - return "map[string]interface{}" - default: - return scalarIdentifier(gqltype) - } - } - - // typeString returns a string representation of GraphQL type t. - var typeString func(t map[string]interface{}) string - typeString = func(t map[string]interface{}) string { - switch t["kind"] { - case "SCALAR": - return "*" + scalarTypeString(t["name"].(string)) - case "NON_NULL": - s := typeString(t["ofType"].(map[string]interface{})) - if !strings.HasPrefix(s, "*") { - panic(fmt.Errorf("nullable type %q doesn't begin with '*'", s)) - } - return s[1:] // Strip star from nullable type to make it non-null. - case "LIST": - return "*[]" + typeString(t["ofType"].(map[string]interface{})) - case "ENUM": - return "*" + enumTypeString(t["name"].(string)) - case "INPUT_OBJECT": - case "OBJECT": - default: - break - // return "*" + identifier(t["name"].(string)) - // // return "*" + scalarType(t["name"].(string), t["kind"].(string)) - } - return "*" + identifier(t["name"].(string)) - } - - // settings["integer_enums"] = true - - return template.FuncMap{ - "ucFirst": func(s string) string { - return ucFirst(s) - }, - "lcFirst": func(s string) string { - return lcFirst(s) - }, - "pkgname": func() string { - pkg, ok := params["pkg"] - if ok { - return pkg - } - return "" - }, - "feature": func(field string) bool { - switch field { - case "use_integer_enums": - return true - default: - return false - } - }, - "first": func(x int, a interface{}) bool { - return x == 0 - }, - "last": func(x int, a interface{}) bool { - return x == reflect.ValueOf(a).Len()-1 - }, - "toUpper": func(s string) string { - return strings.ToUpper(s) - }, - "toLower": func(s string) string { - return strings.ToLower(s) - }, - "isGraphQLMeta": func(s string) bool { - return false - // return strings.HasPrefix(s, "__") - }, - "isExcluded": isExcluded, - "quote": func(s string) string { - return strconv.Quote(s) - }, - "join": func(elems []string, sep string) string { - return strings.Join(elems, sep) - }, - "sortByName": func(types []interface{}) []interface{} { - sort.Slice(types, func(i, j int) bool { - ni := types[i].(map[string]interface{})["name"].(string) - nj := types[j].(map[string]interface{})["name"].(string) - return ni < nj - }) - return types - }, - "sortByNameRev": func(types []interface{}) []interface{} { - sort.Slice(types, func(i, j int) bool { - ni := types[i].(map[string]interface{})["name"].(string) - nj := types[j].(map[string]interface{})["name"].(string) - return ni > nj - }) - return types - }, - "filterBy": func(field string, kind string, types []interface{}) []interface{} { - var filtered = []interface{}{} - for _, t := range types { - if val, ok := t.(map[string]interface{})[field]; ok && val.(string) == kind && !isExcluded(val.(string)) { - filtered = append(filtered, t) - } - continue - } - return filtered - }, - "extractField": func(field string, types []interface{}) []string { - var values = []string{} - for _, t := range types { - if val, ok := t.(map[string]interface{})[field]; ok { - values = append(values, val.(string)) - } - continue - } - return values - }, - "inputObjects": func(types []interface{}) []string { - var names []string - for _, t := range types { - t := t.(map[string]interface{}) - if t["kind"].(string) != "INPUT_OBJECT" { - continue - } - names = append(names, t["name"].(string)) - } - sort.Strings(names) - return names - }, - "objects": func(types []interface{}) []string { - var names []string - for _, t := range types { - t := t.(map[string]interface{}) - if t["kind"].(string) != "OBJECT" { - continue - } - names = append(names, t["name"].(string)) - } - sort.Strings(names) - return names - }, - "identifier": identifier, - "type": typeString, - "enumType": enumTypeString, - "enumIdentifierValueSuffix": enumIdentifierValueSuffix, - "enumAllValuesIdentifier": enumAllValuesIdentifier, - "scalarIdentifier": scalarIdentifier, - "scalarType": scalarTypeString, - "clean": func(s string) string { - return strings.Join(strings.Fields(s), " ") - }, - "formatDescription": func(s string) string { - s = strings.ToLower(s[0:1]) + s[1:] - if !strings.HasSuffix(s, ".") { - s += "." - } - return s - }, - } -} diff --git a/internal/generator/generator.go b/internal/gqlassist/generator.go similarity index 68% rename from internal/generator/generator.go rename to internal/gqlassist/generator.go index e3275cc..008e52d 100644 --- a/internal/generator/generator.go +++ b/internal/gqlassist/generator.go @@ -1,4 +1,4 @@ -package generator +package gqlassist import ( "bytes" @@ -12,15 +12,15 @@ import ( "strings" "text/template" - "github.com/shakahl/graphql-typedef-go/internal/apiclient" - "github.com/shakahl/graphql-typedef-go/internal/utils" + "github.com/shakahl/gqlassist/internal/apiclient" + "github.com/shakahl/gqlassist/internal/utils" ) func init() { } -type GraphQLTypeDefGeneratorOptions struct { +type GraphQLTypeDefGeneratorConfig struct { Endpoint string AuthHeader string AuthToken string @@ -29,14 +29,14 @@ type GraphQLTypeDefGeneratorOptions struct { } type GraphQLTypeDefGenerator struct { - options GraphQLTypeDefGeneratorOptions + options GraphQLTypeDefGeneratorConfig client *apiclient.ApiClient logger *log.Logger } -func New(options GraphQLTypeDefGeneratorOptions, logger *log.Logger) *GraphQLTypeDefGenerator { +func New(options GraphQLTypeDefGeneratorConfig, logger *log.Logger) *GraphQLTypeDefGenerator { if logger == nil { - logger = log.New(os.Stdout, "graphql_type_def_generator", log.LstdFlags|log.LUTC) + logger = log.New(os.Stdout, "gqlassist", log.LstdFlags|log.LUTC) } g := &GraphQLTypeDefGenerator{ options: options, @@ -46,16 +46,13 @@ func New(options GraphQLTypeDefGeneratorOptions, logger *log.Logger) *GraphQLTyp } // getTemplates returns a template map (filename->template) -func (g *GraphQLTypeDefGenerator) getTemplates() map[string]*template.Template { +func (g *GraphQLTypeDefGenerator) createTemplates(params map[string]interface{}) map[string]*template.Template { // Filename -> Template. - var params = map[string]string{ - "pkg": g.options.OutputPackage, - } var templates = map[string]*template.Template{ - "gen_graphql_scalars.go": renderGeneratorTemplate("gen_graphql_scalars.gotmpl", GeneratorTemplateScalar, params), - "gen_graphql_enums.go": renderGeneratorTemplate("gen_graphql_enums.gotmpl", GeneratorTemplateEnum, params), - "gen_graphql_input_objects.go": renderGeneratorTemplate("gen_graphql_input_objects.gotmpl", GeneratorTemplateInputObjects, params), - "gen_graphql_objects.go": renderGeneratorTemplate("gen_graphql_objects.gotmpl", GeneratorTemplateObjects, params), + "gen_graphql_scalars.go": renderGeneratorTemplate("graphql_scalars.gotmpl", GeneratorTemplateScalar), + "gen_graphql_enums.go": renderGeneratorTemplate("graphql_enums.gotmpl", GeneratorTemplateEnum), + "gen_graphql_input_objects.go": renderGeneratorTemplate("graphql_input_objects.gotmpl", GeneratorTemplateInputObjects), + "gen_graphql_objects.go": renderGeneratorTemplate("graphql_objects.gotmpl", GeneratorTemplateObjects), } return templates } @@ -132,12 +129,24 @@ func (g *GraphQLTypeDefGenerator) Generate() error { return err } - for filename, t := range g.getTemplates() { + params := make(map[string]interface{}) + params["FileHeader"] = FileHeaderText + params["Schema"] = schema + params["PackageName"] = g.options.OutputPackage + params["FeatureFlags"] = map[string]interface{}{ + "UseIntegerEnums": true, + } + // use_integer_enums + + templates := g.createTemplates(params) + + for filename, t := range templates { outputFile := g.getOutputFilePath(filename) g.logger.Printf("Processing template: %s\n", filename) var buf bytes.Buffer - err := t.Execute(&buf, schema) + err := t.Execute(&buf, params) if err != nil { + g.logger.Printf("ERR: %+v\n", err) return err } out, err := format.Source(buf.Bytes()) diff --git a/internal/generator/templates.go b/internal/gqlassist/template_data.go similarity index 87% rename from internal/generator/templates.go rename to internal/gqlassist/template_data.go index 68df036..66eb842 100644 --- a/internal/generator/templates.go +++ b/internal/gqlassist/template_data.go @@ -1,8 +1,9 @@ -package generator +package gqlassist -const GeneratorTemplateScalar = `// Code generated by gen.go; DO NOT EDIT. +const GeneratorTemplateScalar = ` +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( "time" @@ -54,7 +55,7 @@ func NewInt(v Int) *Int { return &v } func NewString(v String) *String { return &v } {{ end -}} -{{ range .data.__schema.types | filterBy "kind" "SCALAR" | sortByName -}} +{{ range .Schema.data.__schema.types | filterBy "kind" "SCALAR" | sortByName -}} {{- if and (eq .kind "SCALAR") (not (isExcluded .name)) -}} {{- template "scalar" . -}} {{- end -}}{{- end }} @@ -70,9 +71,10 @@ func New{{ .name | scalarIdentifier }}(v {{ .name | scalarIdentifier }}) *{{ .na ` -const GeneratorTemplateEnum = `// Code generated by gen.go; DO NOT EDIT. +const GeneratorTemplateEnum = ` +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( "bytes" @@ -81,7 +83,7 @@ import ( // "fmt" ) -{{range .data.__schema.types | filterBy "kind" "ENUM" | sortByName}}{{if and (eq .kind "ENUM") (not (isExcluded .name))}} +{{range .Schema.data.__schema.types | filterBy "kind" "ENUM" | sortByName}}{{if and (eq .kind "ENUM") (not (isExcluded .name))}} {{template "enum" .}} {{end}}{{end}} @@ -185,9 +187,10 @@ func New{{.name | enumType}}(s string) *{{.name | enumType}} { ` -const GeneratorTemplateInputObjects = `// Code generated by gen.go; DO NOT EDIT. +const GeneratorTemplateInputObjects = ` +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( "time" @@ -197,24 +200,24 @@ import ( // Input represents one of the Input structs: // -// {{join (extractField "name" (filterBy "kind" "INPUT_OBJECT" .data.__schema.types)) ", "}}. +// {{join (extractField "name" (filterBy "kind" "INPUT_OBJECT" .Schema.data.__schema.types)) ", "}}. type Input interface{} var ( TypeMapInputObjects = map[string]string{ - {{ range .data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{if eq .kind "INPUT_OBJECT" -}} + {{ range .Schema.data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{if eq .kind "INPUT_OBJECT" -}} {{ .name | identifier | quote }}: {{ .name | quote }}, {{ end }}{{- end }} } ReverseTypeMapInputObjects = map[string]string{ - {{ range .data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{ if eq .kind "INPUT_OBJECT" -}} + {{ range .Schema.data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName -}}{{ if eq .kind "INPUT_OBJECT" -}} {{ .name | quote }}: {{ .name | identifier| quote }}, {{ end }}{{- end }} } ) -{{range .data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName}}{{if eq .kind "INPUT_OBJECT"}} +{{range .Schema.data.__schema.types | filterBy "kind" "INPUT_OBJECT" | sortByName}}{{if eq .kind "INPUT_OBJECT"}} {{template "inputObject" .}} {{end}}{{end}} @@ -236,9 +239,10 @@ type {{.name | identifier }} struct {{- "{" }} {{- end -}} ` -const GeneratorTemplateObjects = `// Code generated by gen.go; DO NOT EDIT. +const GeneratorTemplateObjects = ` +{{- .FileHeader }} -package {{ pkgname }} +package {{ .PackageName }} import ( "time" @@ -248,7 +252,7 @@ import ( // Object represents one of the Input structs: // -// {{join (extractField "name" (filterBy "kind" "OBJECT" .data.__schema.types)) ", "}}. +// {{join (extractField "name" (filterBy "kind" "OBJECT" .Schema.data.__schema.types)) ", "}}. type Object interface{} @@ -259,18 +263,18 @@ type GQLMeta struct { var ( TypeMapObjects = map[string]string{ - {{ range .data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{if eq .kind "OBJECT" -}} + {{ range .Schema.data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{if eq .kind "OBJECT" -}} {{ .name | identifier | quote }}: {{ .name | quote }}, {{ end }}{{- end }} } ReverseTypeMapObjects = map[string]string{ - {{ range .data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{ if eq .kind "OBJECT" -}} + {{ range .Schema.data.__schema.types | filterBy "kind" "OBJECT" | sortByName -}}{{ if eq .kind "OBJECT" -}} {{ .name | quote }}: {{ .name | identifier| quote }}, {{ end }}{{- end }} } ) -{{range .data.__schema.types | filterBy "kind" "OBJECT" | sortByName}}{{if eq .kind "OBJECT"}} +{{range .Schema.data.__schema.types | filterBy "kind" "OBJECT" | sortByName}}{{if eq .kind "OBJECT"}} {{template "object" .}} {{end}}{{end}} diff --git a/internal/gqlassist/template_utils.go b/internal/gqlassist/template_utils.go new file mode 100644 index 0000000..2881ba9 --- /dev/null +++ b/internal/gqlassist/template_utils.go @@ -0,0 +1,259 @@ +package gqlassist + +import ( + "fmt" + "reflect" + "sort" + "strconv" + "strings" + "text/template" + + "github.com/Masterminds/sprig" + "github.com/shurcooL/graphql/ident" + + "github.com/shakahl/gqlassist/internal/utils" +) + +const ( + FileHeaderText = "// Code generated by gqlassist; DO NOT EDIT.\n\n" +) + +type GeneratorTemplateContext struct { + RuntimeConfig GraphQLTypeDefGeneratorConfig `json:"runtime_config"` + Options map[string]string `json:"options"` + Schema interface{} `json:"schema"` + PackageName string `json:"package_name"` + PackageDir string `json:"package_dir"` + FileHeader string `json:"file_header"` + FileFooter string `json:"file_footer"` +} + +func renderGeneratorTemplate(name, text string) *template.Template { + funcMap := makeTemplateFuncMap() + return template.Must(template.New(name).Funcs(sprig.TxtFuncMap()).Funcs(funcMap).Parse(text)) +} + +func makeTemplateFuncMap() template.FuncMap { + feature := func(field string) bool { + switch field { + case "use_integer_enums": + return true + default: + return false + } + } + isExcluded := func(s string) bool { + return false + } + clean := func(s string) string { + return strings.Join(strings.Fields(s), " ") + } + quote := func(s string) string { + return strconv.Quote(s) + } + formatDescription := func(s string) string { + s = strings.ToLower(s[0:1]) + s[1:] + if !strings.HasSuffix(s, ".") { + s += "." + } + return s + } + join := func(elems []string, sep string) string { + return strings.Join(elems, sep) + } + sortByName := func(types []interface{}) []interface{} { + sort.Slice(types, func(i, j int) bool { + ni := types[i].(map[string]interface{})["name"].(string) + nj := types[j].(map[string]interface{})["name"].(string) + return ni < nj + }) + return types + } + sortByNameRev := func(types []interface{}) []interface{} { + sort.Slice(types, func(i, j int) bool { + ni := types[i].(map[string]interface{})["name"].(string) + nj := types[j].(map[string]interface{})["name"].(string) + return ni > nj + }) + return types + } + filterBy := func(field string, kind string, types []interface{}) []interface{} { + var filtered = []interface{}{} + for _, t := range types { + if val, ok := t.(map[string]interface{})[field]; ok && val.(string) == kind && !isExcluded(val.(string)) { + filtered = append(filtered, t) + } + continue + } + return filtered + } + extractField := func(field string, types []interface{}) []string { + var values = []string{} + for _, t := range types { + if val, ok := t.(map[string]interface{})[field]; ok { + values = append(values, val.(string)) + } + continue + } + return values + } + ucFirst := func(s string) string { + return utils.StringUpperCaseFirst(s) + } + lcFirst := func(s string) string { + return utils.StringLowerCaseFirst(s) + } + identifier := func(s string) string { + s = strings.TrimLeft(s, "_") + return ident.ParseScreamingSnakeCase(s).ToMixedCaps() + } + scalarIdentifier := func(s string) string { + return ident.ParseScreamingSnakeCase(s).ToMixedCaps() + } + enumIdentifierValueSuffix := func(s string) string { + // return s + // return ident.ParseScreamingSnakeCase(name).ToMixedCaps() + return "_" + strings.ToUpper(s) + } + enumTypeString := func(s string) string { + return identifier(s) + } + enumAllValuesIdentifier := func(s string) string { + return enumTypeString(s) + "__LIST" + } + scalarTypeString := func(gqltype string) string { + tnorm := strings.ToLower(gqltype) + switch tnorm { + case "order_by": + return "string" + case "time": + return "time.Time" + case "timestamp": + return "time.Time" + case "timestamptz": + return "time.Time" + case "date": + return "time.Time" + case "datetime": + return "time.Time" + case "uuid": + return "uuid.UUID" + case "id": + return "string" + case "string": + return "string" + case "boolean": + return "bool" + case "float": + return "float64" + case "integer": + return "time.Time" + case "int": + return "int32" + case "json": + return "map[string]interface{}" + case "jsonb": + return "map[string]interface{}" + default: + return scalarIdentifier(gqltype) + } + } + + // typeString returns a string representation of GraphQL type t. + var typeString func(t map[string]interface{}) string + typeString = func(t map[string]interface{}) string { + switch t["kind"] { + case "SCALAR": + return "*" + scalarTypeString(t["name"].(string)) + case "NON_NULL": + s := typeString(t["ofType"].(map[string]interface{})) + if !strings.HasPrefix(s, "*") { + panic(fmt.Errorf("nullable type %q doesn't begin with '*'", s)) + } + return s[1:] // Strip star from nullable type to make it non-null. + case "LIST": + return "*[]" + typeString(t["ofType"].(map[string]interface{})) + case "ENUM": + return "*" + enumTypeString(t["name"].(string)) + case "INPUT_OBJECT", "OBJECT": + default: + break + // return "*" + identifier(t["name"].(string)) + // // return "*" + scalarType(t["name"].(string), t["kind"].(string)) + } + return "*" + identifier(t["name"].(string)) + } + + inputObjects := func(types []interface{}) []string { + var names []string + for _, t := range types { + t := t.(map[string]interface{}) + if t["kind"].(string) != "INPUT_OBJECT" { + continue + } + names = append(names, t["name"].(string)) + } + sort.Strings(names) + return names + } + + objects := func(types []interface{}) []string { + var names []string + for _, t := range types { + t := t.(map[string]interface{}) + if t["kind"].(string) != "OBJECT" { + continue + } + names = append(names, t["name"].(string)) + } + sort.Strings(names) + return names + } + first := func(x int, a interface{}) bool { + return x == 0 + } + last := func(x int, a interface{}) bool { + return x == reflect.ValueOf(a).Len()-1 + } + toUpper := func(s string) string { + return strings.ToUpper(s) + } + toLower := func(s string) string { + return strings.ToLower(s) + } + isGraphQLMeta := func(s string) bool { + return false + // return strings.HasPrefix(s, "__") + } + + // settings["integer_enums"] = true + + return template.FuncMap{ + "ucFirst": ucFirst, + "lcFirst": lcFirst, + "feature": feature, + "first": first, + "last": last, + "toUpper": toUpper, + "toLower": toLower, + "isGraphQLMeta": isGraphQLMeta, + "isExcluded": isExcluded, + "quote": quote, + "join": join, + "sortByName": sortByName, + "sortByNameRev": sortByNameRev, + "filterBy": filterBy, + "extractField": extractField, + "inputObjects": inputObjects, + "objects": objects, + "identifier": identifier, + "type": typeString, + "enumType": enumTypeString, + "enumIdentifierValueSuffix": enumIdentifierValueSuffix, + "enumAllValuesIdentifier": enumAllValuesIdentifier, + "scalarIdentifier": scalarIdentifier, + "scalarType": scalarTypeString, + "clean": clean, + "formatDescription": formatDescription, + } +} diff --git a/internal/statikdata/statik.go b/internal/statikdata/statik.go new file mode 100644 index 0000000..2ba7b04 --- /dev/null +++ b/internal/statikdata/statik.go @@ -0,0 +1,12 @@ +// Code generated by statik. DO NOT EDIT. + +package statikdata + +import ( + "github.com/rakyll/statik/fs" +) + +func init() { + data := "PK\x03\x04\x14\x00\x08\x00\x08\x006\x931Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00 \x00gen_graphql_enums.gotmplUT\x05\x00\x01(\xaac_\xac\x97Mo\xe36\x10\x86\xef\xfa\x15S\xd6]HY[F\xafY\x04h\xd3\xe4\xe0\x02\xeb\x00M\xd2\x1e\\\xc3\xa0\xa5\x91\xc3D\xa2\x14\x92r\xd6U\xf4\xdf\x0b~\xc4\xa6l\xe5c\xb3\xc9amK\xc3\xd1;\xcf\xbcCq\xc7c\xf8\xa3L\x11V\xc8QP\x85),7\xfaG\xbc*\xbf\xc0\xd9\x05L/\xae\xe0\xfclr\x15\x07AE\x93;\xbaBh\x1a\xa8\xeeV\x9c\x16\x08m\x1b\x04\xac\xa8J\xa1 \x0c\xc8r\xa3P\x92\x80 O\xca\x94\xf1\xd5\xf8V\x96\x9c\x04D*\xc1\xf8J\x92`<\x06\x92\x15\x8a\x04Q\x104\x8d\xa0|\x85\x10\xa7T\xd1x\xb1\x90\xc9\x0d\x164V\x9b\n%Go&KG\xe6| \xfe$U\xce\xc1\xafG\xdf\xee&\xd3\xf1\xf9\x97\xab\x8b G\x92\x0b'\x92\xe9\xd4fs\xaaD\xe2\x965\xd9~\x1f\xfc\x14<\x84\x84\xb1\x18\xe8\xaaJ\xe5\xc8\xccDF>0\xf6,\x0czl\xb2\xac\xe9\xab\xa8\xdb\xfd\xf1\xc3#e\xce\xe2\x0c\x95\xa8\xbf[g\xa4*~\xac\x17\xcf\xbc\x87\x11\xaa\xa0\xa3\xf5\xb0\xc2+*W\xb0\xda\xb8\xf3\xe5(2\x1d\x84\xe0\xbd\x9c\x81\x16Hb\xf6a\xf2 \x04\x06 \xb6!i\x9b\xb0\x82\xccI99\x93d\xb0\xc2\xa2\xd1.vf\xb8\x9b\xb1 \x9eF\xa9\xa4r\xc4\"\x83\xee\x1f\x0b\xec\x96\x9e\xc9Xz?\xc3x\x9b\xe3\xa3&_0\xbcn\xb8\xcf\x98\xf7\x7f\xcb\xc2\x9f;\xb6U\xef\xa8\xaaK\xe1\x08\\\xbe\x00\xe6HB`\xde\x93\xca\xe35\xed\xc2\xa2\xb8\x01r\x9aIu\x98\xbd\x81\xd1\x0e\xc6\xb1\x17\x10\x02>\x15F\xd4\xf3Ey\xc6\xb7)!p\xac)'9\xd9\xcc\xc8\xdaI\xadZ*\xfb\x91\x15\xb2\x92D\\g\xdaT\xc2]\x1efw\x08\xa3\x86vz\xbc?.b=\xc5\x88F\xb8\xe7\xd8R\x18l^Nk\xab\x9df\xbbu\xb5I\xe9h\xc6\x02\x1d\xd2\xd1x4\x1d\xdd\xdd\xdclo\xda\xfc\xde\x19\x04z\xb7\xb4h\xa4\xa1<\xe9\xef\xe9\xfa\xad\xa8\xb8\xd1\x92[\xad\x01\x86\x80{\x9c\x80\xdfs\x9c\xe0\xfe\xd1j5\xdc\x97\xdb\x99\x18\xf2\x0f\xbb\xe1\x9d3{\xe8\xa2\xac#8\x15\xfd'8\xc7mL\x94\xff\x08\xe7\xa9\xaed\x1cD\xb7\xdc\x01\xfbV\xae\x87\xdf\x81\xedF~\x05\x00\x00\xff\xffPK\x07\x08\xb9\xb5\xee\xca?\x02\x00\x00T\x07\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xef\x901Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00 \x00gen_graphql_objects.gotmplUT\x05\x00\x01\xe3\xa5c_\xd4TMo\xdb:\x10\xbc\xf3W\xcc\xe3\xc9~\x89\xa5\xbb\x1f\x02<\xe4\xa3A\n\xc7F\x02\xf7T\x14\x0e#\xadd&\x16)STP\x83\xe6\x7f/(K\x8e\x92:h\x8b\xa2-\xea\x0b\xad\xe5\xecrf\xb8\xcb8\xc6\x99N 9)2\xc2R\x8a\xfbM\xf8\x88r\xfd\x1f\xceg\x98\xce\xe6\xb88\xbf\x9aG\x8c\x95\"y\x149\xc19\x94\x8f\xb9\x12\x05\xc1{\xc6dQjc1`\xdc\xca\x828c<\x97vY\xdfG\x89.\xe2\\\xeb|Eq]\xcb\x94\xb3!cq\x8c\xd9\xfd\x03%\x16\x86JC\x15)[A+\x82\xce`\x97\x84+U\xd6\x16\x955ub\xab1\x8b\xe3\x90\xe1\xdc\x83\x96\n\x03\xfal\x8dH\xec;I\xab\x14<\x10\xe0\x18dre\xc9\x9cn\xc0\x1f\xa5J9\xf8\xec\xf4\xfd\xc5\xd9\x9c#J\x85\x15\xd1bQ%K*Dd7%U\xc3!\xf81\xb8\xf7\x11c!\xd0\x91\x91\xca\x92\xc9DB\xce\xb7\x1b\x977\x93k\xb2\xa2\xa5\x02\x17x\\\xdeL\xe6\x9b\x92\xa6A\xf9\xff\xb9\x11\xe5r\xbd:\xe1\x8bEH\xd8\xb1\xb9\xaa P\x84\xbc\xac!\x99he\x85TR\xe5\x8d\xba\xcb\x90s3AsB\xc8`\xfd\x92\xffV\xd6\x04\xe4\x1d\x8e\xc0\xef8\x8ep\xf7Pi5\xee\x9dp\xac\x0bi\xa9(\xed\x86\xf7P\xcc3\xf6$\x0c\x06,\xd4\xba\x16\xe5NU\x85\x13\x14\xa2\xfc\xb8+\xfbi\xb78\xe6\x1c\x8cP9\x1d4\x08[\xbci\xe8\x16\x956\xf6t\xd3\x90\x1dy\xef\x9c\xcc@kD\x01\xf7\x0c\x1by\xcf\x00\x846\x89\x9a&\xd9B\xa6\xa4\xac\xcc$\x19l\xb1\xae\xb5\x0d\x9d3\xee#\xba\xe0q\xa0G*E(?j\xff1\xcfn\xe9\x89LE\xbfY\x1f\xbeW\xe0AM\xcf\xaa\xbf\xado\xc8\x98s?O\xfb\xadK\xd93\x0e\xcd\xb3\x12\x96\xc0u\xe3!G\xe4=s\x8eT\x1ar\x9b\x85\x05.#\xa4\x94I\xd5\x03v\xb2\x9b\x81\x9eV\xd0\xd4\x95\xc4E\"\x15\x92\xb2c(\xfa\xef\x03)\xd9V\xd6\xc6y1L\xe9\x9e\x0f^\x1e^-\x16\xf8\xa02BA\x924\xb3\x94a\xbds\x8b\xa4P\xef\xb1\xbc\xc1\xf5\xcd\nW\xcbt\x95\x04A\xc3\xf8\x1d+\x08]\x87\xe6\xae\x90\xac&\xf4}\x10\x88\xbaQ\xda\"\nB+j\n\x83 ,\x84-\xdbu\xc2U\xbd(\x94**Z\xb4\xad\xc8\xc2 \x0e\x82\xae\x83\xc8\x91\xb3\xca\x10\xe6}\x1f\xcc\xec\xae!D\xc1l\xb1\xc0\xa5R\x151 M\x8d&C\xd2\x1aX\xdd\x12\x94\x1e\x01\x1bV\xb5d\x92`\xb6\xaf\\+U\x05\x1e\xfb\xb1R\xccN\x91F\x14\x922d\xaa]W4o4qa\x84\x92\xc85\xe3V(\xc9\xaa\x91\x0e\xccx\x06\xd3\x10\x17\xb9\x18\x1a\x90^]]\xe1\x87\xef\xcf\x92`60\xe7\xee\xf7\xdd\xd9 \x96.\xa7J\x0c\xad\x14\xf7-Ad$\xad\xa3\xd0\xb0%\xb3\x10\x06\x97\xcc\xd0\xbb3\xa8u\xde\x1a\xee\xba\x9b \xb5\x9eC\x18\xa8\xdc\x92Dk(\x83U\xd0\x94\x93\xe5%\x98\x84Z\xffK\xdc\xba}3\x83;\xda!w\x7f\xc1\x19/)\xc1\xaa$\xa4KO\xe2\x9b\xc7\x9a\x86\x986\x10\x12\x0c\xbf\xdc\xde\\C\x93i\x944\xe4\xe0\x0c\xb7V\x0bY\xbcG\xa9\xb6\xb4!\xfd\n\xc2[\x93j4\"-\xc9l\xf0\xb0&\x94m\xcd\xe4\\\x13\xcb\xd8\xba\xa2\x04\x7f\x95$A\x0f\x0dq\x97\x0dG(!d\xd3Z/\xfe\xcaS0\xb9\x83\xf1*\x88L\xeb\xf6`\x10\xfe\xf9\xf7u\xc5\xc5w\x0f\xbf^\x9c\x9f\x87\xb1\xdb\x8cS*H\x1fk\xce\xe2\x81\xca\x93\xf8\xd3\xc0VT\x95\xb3\xc18\xa7\xe6\xa8\x98.\x93}\xe7\x1d\x8b\xce\x19\xa7\xae\x0ff\xe9r\x14\x1e\x0fF>\xc9\x80Tr>9\xef1\x12\xdbRU\x04\xd9\xd6\xa4\x05?fj\x84\xf3i\x00\xf7\x11Y\x93\xdd\x12I\xcc\xa37\xff\xbc}\x1d\x83\xc9\x0c\xee\x1f\xe6x\x9d\x043\x87\x13\xd2\xbe}3\xb8\x18\x1a\xfe$\xc6\xf4`[V!c\x96\xb9\x1d\xfd\xb1\xfa8\xff\x11\xbcd\xce\x1ci\x18\xbaoI\xf2\xbd\x8fU)\xccp\xb6\xc2\xa0V\xc6N\xa3\xb2\xde\xe1g\xcd\x9a\xf2\xb7OCj\xf6VsM4\xcf\x95\xae=\xc5\xd3c\xf4\x06\x92`6:\x1b[6\x8b\x07\xbf\xd7\xb4\xdd_(\xe1\x02SR\xd5\xb8\x0c+\xd4\xec\x8e\xc0 i\x8bo\xc7\x92$\x98\xe5\xad\xe4\x13P\xb4\xd9\xdf\xdc\xf8P\x85\x0e\x9al\xab%\xbe\xd9\xa0?\xc8\x0cw\xe9\x84\x88/\x98H\xf8u\xb4\x19\xaew<\xbe\x7f\x86\xdce\xe3yf\x9f\xa0=m\xba\x8c6H\x97\xb1{\xfc\x1c\x9b\xad%\x99\x1d>T/X\xf8\xe2\xf5\xca\x81\xfac\x04^\xc0\x9f\x88\xc6i\xe4$2\xa7\x0b\xa3\xcd\x0b{\x88_\x92\xfa\"z\x87s\x0c\xfe\x0b\x00\x00\xff\xffPK\x07\x08\xaf\x84#\xfa\xa5\x03\x00\x00L\x08\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x006\x931Q\xfaxUG7\x04\x00\x00\xb8\x0e\x00\x00\x18\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81\x00\x00\x00\x00gen_graphql_enums.gotmplUT\x05\x00\x01(\xaac_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xe2\x901Q\xb9\xb5\xee\xca?\x02\x00\x00T\x07\x00\x00 \x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81\x86\x04\x00\x00gen_graphql_input_objects.gotmplUT\x05\x00\x01\xc8\xa5c_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xef\x901Q\x870\xed}\x81\x02\x00\x00\xd4\x07\x00\x00\x1a\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81\x1c\x07\x00\x00gen_graphql_objects.gotmplUT\x05\x00\x01\xe3\xa5c_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xc4\x901Q\xaf\x84#\xfa\xa5\x03\x00\x00L\x08\x00\x00\x1a\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81\xee \x00\x00gen_graphql_scalars.gotmplUT\x05\x00\x01\x91\xa5c_PK\x05\x06\x00\x00\x00\x00\x04\x00\x04\x00H\x01\x00\x00\xe4\x0d\x00\x00\x00\x00" + fs.Register(data) +} diff --git a/internal/statikdata/statikdata.go b/internal/statikdata/statikdata.go new file mode 100644 index 0000000..56026bd --- /dev/null +++ b/internal/statikdata/statikdata.go @@ -0,0 +1,9 @@ +package statikdata + +import ( + _ "github.com/rakyll/statik/fs" +) + +func init() { + +} diff --git a/internal/utils/strings.go b/internal/utils/strings.go new file mode 100644 index 0000000..502a109 --- /dev/null +++ b/internal/utils/strings.go @@ -0,0 +1,83 @@ +package utils + +import ( + "bufio" + "io/ioutil" + "regexp" + "strings" + "unicode" +) + +func StringFirstLetter(s string) string { + return s[0:1] +} + +func StringUpperCaseFirst(s string) string { + return strings.ToUpper(s[0:1]) + s[1:] +} + +func StringLowerCaseFirst(s string) string { + return strings.ToLower(s[0:1]) + s[1:] +} + +func IsFirstIndexOf(index int, list interface{}) { + +} + +func RemoveCStyleComments(content []byte) []byte { + // http://blog.ostermiller.org/find-comment + ccmt := regexp.MustCompile(`/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/`) + return ccmt.ReplaceAll(content, []byte("")) +} + +func RemoveCppStyleComments(content []byte) []byte { + cppcmt := regexp.MustCompile(`//.*`) + return cppcmt.ReplaceAll(content, []byte("")) +} + +func RemoveCAndCppComments(srcpath, dstpath string) { + b, err := ioutil.ReadFile(srcpath) + if err != nil { + panic(err) + } + b = RemoveCppStyleComments(RemoveCStyleComments(b)) + err = ioutil.WriteFile(dstpath, b, 0644) + if err != nil { + panic(err) + } +} + +func StripComment(source string, commentChars string, charPairs string) (string, error) { + const ( + defaultCommentChars = "#;" + defaultCommentCharPairs = "/" + ) + + if commentChars == "" && charPairs == "" { + commentChars = defaultCommentChars + charPairs = defaultCommentCharPairs + } + + sreader := strings.NewReader(source) + scanner := bufio.NewScanner(sreader) + var lines []string + + for scanner.Scan() { + line := scanner.Text() + if pos := strings.IndexAny(line, commentChars+charPairs); pos >= 0 { + tc := line[pos : pos+1] + nd := strings.IndexAny(commentChars, tc) + if nd == -1 || (len(line) >= pos+2 && tc == line[pos+1:pos+2]) { + line = strings.TrimRightFunc(line[:pos], unicode.IsSpace) + } + } + lines = append(lines, line) + } + if err := scanner.Err(); err != nil { + return "", err + } + + out := strings.Join(lines, "\n") + + return out, nil +} diff --git a/main.go b/main.go index 6ac7530..dfedcbe 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,9 @@ +//go:generate statik -dest=internal -p statikdata -src=assets/templates/ -include=*.gotmpl + package main import ( - "github.com/shakahl/graphql-typedef-go/cmd" + "github.com/shakahl/gqlassist/cmd" ) func main() { diff --git a/meta/meta.go b/meta/meta.go index ece94f9..2d9fa79 100644 --- a/meta/meta.go +++ b/meta/meta.go @@ -36,19 +36,19 @@ const ( BuildPlatform = "-" // RepositoryUrl is an url to a GitHub repository - RepositoryUrl = "https://github.com/shakahl/graphql-typedef-go" + RepositoryUrl = "https://github.com/shakahl/gqlassist" // ModuleName is the name if the main Go module - ModuleName = "github.com/shakahl/graphql-typedef-go" + ModuleName = "github.com/shakahl/gqlassist" // ProjectID is the project identifier ProjectID = "graphql-typedef" // ProjectName is the project repository name - ProjectName = "graphql-typedef-go" + ProjectName = "gqlassist" // ProjectTitle is the project's human-readable name - ProjectTitle = "Golang GraphQL type definitions generator for consuming GraphQL server resources" + ProjectTitle = "Golang GraphQL type definitions gqlassist for consuming GraphQL server resources" // BinaryName is the binary name BinaryName = "graphql-typedef" @@ -58,9 +58,9 @@ const ( // LongDescription is a long description LongDescription = ` -Golang GraphQL type definitions generator for consuming GraphQL server resources. +Golang GraphQL type definitions gqlassist for consuming GraphQL server resources. -graphql-typedef is a CLI library for Go that helps you working with GraphQL servers. +graphql-typedef is a CLI library for Go that helps you working with GraphQL servers. ` // ConfigName is the name of config file