From ec669d6c3d7562c6b41103b2e83ac058230731c7 Mon Sep 17 00:00:00 2001 From: linty Date: Fri, 1 Nov 2024 16:39:41 +0800 Subject: [PATCH 1/4] feat: studio host --- net/studio/studio.go | 5 ++++- net/studio/studio.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/net/studio/studio.go b/net/studio/studio.go index 1a67c49..5a599da 100644 --- a/net/studio/studio.go +++ b/net/studio/studio.go @@ -15,5 +15,8 @@ func Handler(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - tmpl.Execute(w, nil) + data := map[string]interface{}{ + "endpoint": r.Host, + } + tmpl.Execute(w, data) } diff --git a/net/studio/studio.html b/net/studio/studio.html index bfaba25..4b275b2 100644 --- a/net/studio/studio.html +++ b/net/studio/studio.html @@ -4,7 +4,7 @@ From cd628baa42f7b7d12e9ab913804b24cda1b22482 Mon Sep 17 00:00:00 2001 From: linty Date: Fri, 1 Nov 2024 18:22:00 +0800 Subject: [PATCH 2/4] feat: fix int argument --- .../generate/initialize/two/tpl/resolver.tpl | 3 + command/cli/generate/initialize/two/two.go | 36 +++++++ example/test/.env | 45 ++++++++ example/test/cmd/cmd.go | 19 ++++ example/test/cmd/migrate.go | 46 ++++++++ example/test/cmd/start.go | 45 ++++++++ example/test/go.mod | 34 ++++++ example/test/go.sum | 66 ++++++++++++ example/test/ide-helper.graphql | 15 +++ example/test/lighthouse.yml | 8 ++ example/test/main.go | 17 +++ example/test/models/enum.go | 28 +++++ example/test/models/input.go | 6 ++ example/test/models/interface.go | 5 + example/test/models/model.go | 22 ++++ example/test/repo/repo.go | 100 ++++++++++++++++++ example/test/resolver/operation_gen.go | 18 ++++ example/test/resolver/query.go | 18 ++++ example/test/resolver/resolver.go | 8 ++ example/test/schema/example.graphql | 9 ++ example/test/service/service.go | 13 +++ graphql/ast/directive/paginate.go | 5 +- graphql/ast/funcs.go | 22 ++++ graphql/model/generate/generate.go | 4 +- graphql/model/generate/tpl/operation.tpl | 21 +++- graphql/parser/operation.go | 20 +++- graphql/scalar/id.go | 14 +-- graphql/scalar/int.go | 8 +- template/template.go | 5 +- 29 files changed, 641 insertions(+), 19 deletions(-) create mode 100644 command/cli/generate/initialize/two/tpl/resolver.tpl create mode 100644 example/test/.env create mode 100644 example/test/cmd/cmd.go create mode 100644 example/test/cmd/migrate.go create mode 100644 example/test/cmd/start.go create mode 100644 example/test/go.mod create mode 100644 example/test/go.sum create mode 100644 example/test/ide-helper.graphql create mode 100644 example/test/lighthouse.yml create mode 100644 example/test/main.go create mode 100644 example/test/models/enum.go create mode 100644 example/test/models/input.go create mode 100644 example/test/models/interface.go create mode 100644 example/test/models/model.go create mode 100644 example/test/repo/repo.go create mode 100644 example/test/resolver/operation_gen.go create mode 100644 example/test/resolver/query.go create mode 100644 example/test/resolver/resolver.go create mode 100644 example/test/schema/example.graphql create mode 100644 example/test/service/service.go diff --git a/command/cli/generate/initialize/two/tpl/resolver.tpl b/command/cli/generate/initialize/two/tpl/resolver.tpl new file mode 100644 index 0000000..ced8753 --- /dev/null +++ b/command/cli/generate/initialize/two/tpl/resolver.tpl @@ -0,0 +1,3 @@ +func init() { + +} \ No newline at end of file diff --git a/command/cli/generate/initialize/two/two.go b/command/cli/generate/initialize/two/two.go index 7de955f..ca427ac 100644 --- a/command/cli/generate/initialize/two/two.go +++ b/command/cli/generate/initialize/two/two.go @@ -2,6 +2,7 @@ package two import ( "embed" + "fmt" "path/filepath" "github.com/light-speak/lighthouse/template" @@ -20,6 +21,10 @@ func Run(module string) error { if err != nil { return err } + err = initResolver() + if err != nil { + return err + } err = initService() if err != nil { return err @@ -56,6 +61,23 @@ func initRepo() error { return template.Render(options) } +func initResolver() error { + resolverTemplate, err := twoFs.ReadFile("tpl/resolver.tpl") + if err != nil { + return err + } + options := &template.Options{ + Path: filepath.Join(projectName, "resolver"), + Template: string(resolverTemplate), + FileName: "resolver", + FileExt: "go", + Package: "resolver", + Editable: true, + SkipIfExists: true, + } + return template.Render(options) +} + func initService() error { serviceTemplate, err := twoFs.ReadFile("tpl/service.tpl") if err != nil { @@ -69,6 +91,20 @@ func initService() error { Package: "service", Editable: true, SkipIfExists: true, + Imports: []*template.Import{ + { + Path: fmt.Sprintf("%s/resolver", projectModule), + Alias: "_", + }, + { + Path: fmt.Sprintf("%s/repo", projectModule), + Alias: "_", + }, + { + Path: fmt.Sprintf("%s/models", projectModule), + Alias: "_", + }, + }, } return template.Render(options) } diff --git a/example/test/.env b/example/test/.env new file mode 100644 index 0000000..9d51a77 --- /dev/null +++ b/example/test/.env @@ -0,0 +1,45 @@ +# Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +# Application settings +APP_NAME=MyApp +APP_ENVIRONMENT=development +APP_MODE=single + +# Server settings +SERVER_PORT=8080 +SERVER_THROTTLE=100 + +# API settings +API_RESTFUL=true +API_PREFIX=/api + +# Database settings +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD= +DB_NAME=example +DB_DRIVER=mysql +DB_ORM=gorm + +# Authentication settings +AUTH_DRIVER=jwt + +# Logger settings +LOGGER_LEVEL=info +LOGGER_PATH=./logs/app.log +LOGGER_STACK=false +LOGGER_DRIVER=stdout + +# Redis settings +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD= +REDIS_DB=0 + +# Elasticsearch settings +ELASTICSEARCH_ENABLE=false +ELASTICSEARCH_HOST=localhost +ELASTICSEARCH_PORT=9200 +ELASTICSEARCH_USER=elastic +ELASTICSEARCH_PASSWORD=changeme + diff --git a/example/test/cmd/cmd.go b/example/test/cmd/cmd.go new file mode 100644 index 0000000..24e310a --- /dev/null +++ b/example/test/cmd/cmd.go @@ -0,0 +1,19 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package cmd + +import "github.com/light-speak/lighthouse/command" + +type Command struct{ + // Section: user code section start. Do not remove this comment. +// Section: user code section end. Do not remove this comment. + +} + +func (c *Command) GetCommands() []command.Command { + return []command.Command{ + // Func:GetCommands user code start. Do not remove this comment. + &Start{}, + &Migrate{}, + // Func:GetCommands user code end. Do not remove this comment. + } +} diff --git a/example/test/cmd/migrate.go b/example/test/cmd/migrate.go new file mode 100644 index 0000000..633721c --- /dev/null +++ b/example/test/cmd/migrate.go @@ -0,0 +1,46 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package cmd + +import ( + "github.com/light-speak/lighthouse/command" + "test/models" +) + +type Migrate struct{} + +func (c *Migrate) Name() string { + // Func:Name user code start. Do not remove this comment. + return "app:migrate" + // Func:Name user code end. Do not remove this comment. +} + +func (c *Migrate) Usage() string { + // Func:Usage user code start. Do not remove this comment. + return "This is a command generated by lighthouse cli" + // Func:Usage user code end. Do not remove this comment. +} + +func (c *Migrate) Args() []*command.CommandArg { + return []*command.CommandArg{ + // Func:Args user code start. Do not remove this comment. + // Func:Args user code end. Do not remove this comment. + } +} + +func (c *Migrate) Action() func(flagValues map[string]interface{}) error { + return func(flagValues map[string]interface{}) error { + // Func:Action user code start. Do not remove this comment. + err := models.Migrate() + if err != nil { + return err + } + // Func:Action user code end. Do not remove this comment. + return nil + } +} + +func (c *Migrate) OnExit() func() { + return func() {} +} +// Section: user code section start. Do not remove this comment. +// Section: user code section end. Do not remove this comment. diff --git a/example/test/cmd/start.go b/example/test/cmd/start.go new file mode 100644 index 0000000..d719d26 --- /dev/null +++ b/example/test/cmd/start.go @@ -0,0 +1,45 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package cmd + +import ( + "test/service" + "github.com/light-speak/lighthouse/command" +) + +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +type Start struct{} + +func (c *Start) Name() string { + // Func:Name user code start. Do not remove this comment. + return "app:start" + // Func:Name user code end. Do not remove this comment. +} + +func (c *Start) Usage() string { + // Func:Usage user code start. Do not remove this comment. + return "This is a command generated by lighthouse cli" + // Func:Usage user code end. Do not remove this comment. +} + +func (c *Start) Args() []*command.CommandArg { + return []*command.CommandArg{ + // Func:Args user code start. Do not remove this comment. + // Func:Args user code end. Do not remove this comment. + } +} + +func (c *Start) Action() func(flagValues map[string]interface{}) error { + return func(flagValues map[string]interface{}) error { + // Func:Action user code start. Do not remove this comment. + service.StartService() + // Func:Action user code end. Do not remove this comment. + return nil + } +} + +func (c *Start) OnExit() func() { + return func() {} +} + +// Section: user code section start. Do not remove this comment. +// Section: user code section end. Do not remove this comment. diff --git a/example/test/go.mod b/example/test/go.mod new file mode 100644 index 0000000..c726f00 --- /dev/null +++ b/example/test/go.mod @@ -0,0 +1,34 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +module test + +go 1.23.1 + +replace github.com/light-speak/lighthouse => ../../ + +require ( + github.com/light-speak/lighthouse v0.0.1 + gorm.io/gorm v1.25.12 +) + +require ( + github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect + github.com/elastic/go-elasticsearch/v8 v8.15.0 // indirect + github.com/go-chi/chi/v5 v5.1.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rs/zerolog v1.33.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gorm.io/driver/mysql v1.5.7 // indirect +) diff --git a/example/test/go.sum b/example/test/go.sum new file mode 100644 index 0000000..d93acd4 --- /dev/null +++ b/example/test/go.sum @@ -0,0 +1,66 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elastic/elastic-transport-go/v8 v8.6.0 h1:Y2S/FBjx1LlCv5m6pWAF2kDJAHoSjSRSJCApolgfthA= +github.com/elastic/elastic-transport-go/v8 v8.6.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk= +github.com/elastic/go-elasticsearch/v8 v8.15.0 h1:IZyJhe7t7WI3NEFdcHnf6IJXqpRf+8S8QWLtZYYyBYk= +github.com/elastic/go-elasticsearch/v8 v8.15.0/go.mod h1:HCON3zj4btpqs2N1jjsAy4a/fiAul+YBP00mBH4xik8= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= +gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/example/test/ide-helper.graphql b/example/test/ide-helper.graphql new file mode 100644 index 0000000..456ad71 --- /dev/null +++ b/example/test/ide-helper.graphql @@ -0,0 +1,15 @@ +# Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +type Query +type Mutation +type Subscription + +directive @external repeatable on FIELD_DEFINITION +directive @requires(fields: [String!]!) repeatable on FIELD_DEFINITION +directive @provides(fields: [String!]!) repeatable on FIELD_DEFINITION +directive @key(fields: [String!]!) repeatable on OBJECT | INTERFACE +directive @extends repeatable on OBJECT + +directive @paginate(scopes: [String!]) on FIELD_DEFINITION +directive @skip(if: Boolean!) on FIELD_DEFINITION +directive @include(if: Boolean!) on FIELD_DEFINITION +directive @enum(value: Int!) on FIELD_DEFINITION \ No newline at end of file diff --git a/example/test/lighthouse.yml b/example/test/lighthouse.yml new file mode 100644 index 0000000..cc89d5d --- /dev/null +++ b/example/test/lighthouse.yml @@ -0,0 +1,8 @@ +# Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +schema: + ext: + - graphql + - graphqls + path: + - schema + diff --git a/example/test/main.go b/example/test/main.go new file mode 100644 index 0000000..2f88655 --- /dev/null +++ b/example/test/main.go @@ -0,0 +1,17 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package main + +import ( + "test/cmd" + "fmt" + "os" + "github.com/light-speak/lighthouse/command" +) + +func main() { + cmd := &cmd.Command{} + if err := command.Run(cmd, os.Args); err != nil { + fmt.Fprintf(os.Stderr, "error: %s\n", err) + os.Exit(1) + } +} diff --git a/example/test/models/enum.go b/example/test/models/enum.go new file mode 100644 index 0000000..40db117 --- /dev/null +++ b/example/test/models/enum.go @@ -0,0 +1,28 @@ +// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +package models + + + + +type SortOrder int8 + +const ( + ASC SortOrder = 1 + DESC SortOrder = -1 +) + +func (e SortOrder) ToString() string { + switch e { + case ASC: + return "ASC" + case DESC: + return "DESC" + default: + return "unknown" + } +} + +var SortOrderMap = map[string]SortOrder{ + "ASC": ASC, + "DESC": DESC, +} diff --git a/example/test/models/input.go b/example/test/models/input.go new file mode 100644 index 0000000..59ada3a --- /dev/null +++ b/example/test/models/input.go @@ -0,0 +1,6 @@ +// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +package models + + + + diff --git a/example/test/models/interface.go b/example/test/models/interface.go new file mode 100644 index 0000000..2ec0070 --- /dev/null +++ b/example/test/models/interface.go @@ -0,0 +1,5 @@ +// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +package models + + + diff --git a/example/test/models/model.go b/example/test/models/model.go new file mode 100644 index 0000000..485a1f8 --- /dev/null +++ b/example/test/models/model.go @@ -0,0 +1,22 @@ +// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +package models + +import "github.com/light-speak/lighthouse/graphql/model" + + +type Test struct { + model.Model + Email string `gorm:"type:varchar(255)" json:"email" ` + Name string `json:"name" gorm:"type:varchar(255)" ` +} + +func (*Test) IsModel() bool { return true } +func (*Test) TableName() string { return "tests" } +func (*Test) TypeName() string { return "test" } + + +func Migrate() error { + return model.GetDB().AutoMigrate( + &Test{}, + ) +} \ No newline at end of file diff --git a/example/test/repo/repo.go b/example/test/repo/repo.go new file mode 100644 index 0000000..3fdc18e --- /dev/null +++ b/example/test/repo/repo.go @@ -0,0 +1,100 @@ +// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +package repo + +import ( + "github.com/light-speak/lighthouse/graphql/ast" + "github.com/light-speak/lighthouse/context" + "github.com/light-speak/lighthouse/graphql/model" + "gorm.io/gorm" + "test/models" + "sync" +) + +func Provide__Test() map[string]*ast.Relation { return map[string]*ast.Relation{"created_at": {},"email": {},"id": {},"name": {},"updated_at": {},}} +func Load__Test(ctx *context.Context, key int64, field string) (map[string]interface{}, error) { + return model.GetLoader[int64](model.GetDB(), "tests", field).Load(key) +} +func LoadList__Test(ctx *context.Context, key int64, field string) ([]map[string]interface{}, error) { + return model.GetLoader[int64](model.GetDB(), "tests", field).LoadList(key) +} +func Query__Test(scopes ...func(db *gorm.DB) *gorm.DB) *gorm.DB { + return model.GetDB().Model(&models.Test{}).Scopes(scopes...) +} +func First__Test(ctx *context.Context, columns map[string]interface{}, data map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) (map[string]interface{}, error) { + var err error + selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Test()) + if data == nil { + data = make(map[string]interface{}) + err = Query__Test().Scopes(scopes...).Select(selectColumns).First(data).Error + if err != nil { + return nil, err + } + } + var wg sync.WaitGroup + errChan := make(chan error, len(selectRelations)) + var mu sync.Mutex + + for key, relation := range selectRelations { + wg.Add(1) + go func(data map[string]interface{}, relation *model.SelectRelation) { + defer wg.Done() + cData, err := model.FetchRelation(ctx, data, relation) + if err != nil { + errChan <- err + } + mu.Lock() + defer mu.Unlock() + data[key] = cData + }(data, relation) + } + wg.Wait() + close(errChan) + for err := range errChan { + return nil, err + } + return data, nil +} +func List__Test(ctx *context.Context, columns map[string]interface{},datas []map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) ([]map[string]interface{}, error) { + var err error + selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Test()) + if datas == nil { + datas = make([]map[string]interface{}, 0) + err = Query__Test().Scopes(scopes...).Select(selectColumns).Find(&datas).Error + if err != nil { + return nil, err + } + } + var wg sync.WaitGroup + errChan := make(chan error, len(datas)*len(selectRelations)) + var mu sync.Mutex + + for _, data := range datas { + for key, relation := range selectRelations { + wg.Add(1) + go func(data map[string]interface{}, relation *model.SelectRelation) { + defer wg.Done() + cData, err := model.FetchRelation(ctx, data, relation) + if err != nil { + errChan <- err + } + mu.Lock() + defer mu.Unlock() + data[key] = cData + }(data, relation) + } + } + wg.Wait() + close(errChan) + for err := range errChan { + return nil, err + } + return datas, nil +} + + +func init() { + model.AddQuickFirst("Test", First__Test) + model.AddQuickList("Test", List__Test) + model.AddQuickLoad("Test", Load__Test) + model.AddQuickLoadList("Test", LoadList__Test) +} diff --git a/example/test/resolver/operation_gen.go b/example/test/resolver/operation_gen.go new file mode 100644 index 0000000..fe1db83 --- /dev/null +++ b/example/test/resolver/operation_gen.go @@ -0,0 +1,18 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package resolver + +import ( + "github.com/light-speak/lighthouse/graphql/excute" + "fmt" + "github.com/light-speak/lighthouse/context" +) + +func init() { + excute.AddResolver("getTest", func(ctx *context.Context, args map[string]any) (interface{}, error) { + id, ok := args["id"].(int64) + if !ok { + return nil, fmt.Errorf("argument: 'id' is not a int64, got %T", args["id"]) + } + return GetTestResolver(ctx, id) + }) +} diff --git a/example/test/resolver/query.go b/example/test/resolver/query.go new file mode 100644 index 0000000..eb5d7e9 --- /dev/null +++ b/example/test/resolver/query.go @@ -0,0 +1,18 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package resolver + +import ( + "test/models" + + "github.com/light-speak/lighthouse/context" + "github.com/light-speak/lighthouse/graphql/model" +) + +func GetTestResolver(ctx *context.Context, id int64) (models.Test, error) { + // Func:GetTest user code start. Do not remove this comment. + test := models.Test{} + db := model.GetDB() + db.Where("id = ?", id).First(&test) + return test, nil + // Func:GetTest user code end. Do not remove this comment. +} diff --git a/example/test/resolver/resolver.go b/example/test/resolver/resolver.go new file mode 100644 index 0000000..b281860 --- /dev/null +++ b/example/test/resolver/resolver.go @@ -0,0 +1,8 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package resolver + + + +func init() { + +} \ No newline at end of file diff --git a/example/test/schema/example.graphql b/example/test/schema/example.graphql new file mode 100644 index 0000000..6eaaf1f --- /dev/null +++ b/example/test/schema/example.graphql @@ -0,0 +1,9 @@ +type Test @model{ + name:String! + email:String! +} + + +extend type Query{ + getTest(id:Int!): Test! +} \ No newline at end of file diff --git a/example/test/service/service.go b/example/test/service/service.go new file mode 100644 index 0000000..a47a0f3 --- /dev/null +++ b/example/test/service/service.go @@ -0,0 +1,13 @@ +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. +package service + +import ( + _ "test/resolver" + _ "test/repo" + _ "test/models" + "github.com/light-speak/lighthouse/handler" +) + +func StartService() { + handler.StartService() +} diff --git a/graphql/ast/directive/paginate.go b/graphql/ast/directive/paginate.go index 4bc193c..f67eeab 100644 --- a/graphql/ast/directive/paginate.go +++ b/graphql/ast/directive/paginate.go @@ -5,6 +5,7 @@ import ( "github.com/light-speak/lighthouse/errors" "github.com/light-speak/lighthouse/graphql/ast" + ) func handlerPaginate(f *ast.Field, d *ast.Directive, store *ast.NodeStore, parent ast.Node) errors.GraphqlErrorInterface { @@ -81,7 +82,7 @@ func addPaginationArguments(f *ast.Field, store *ast.NodeStore) { Name: "Int", TypeNode: store.Scalars["Int"], }, - DefaultValue: int64(1), + DefaultValue: 1, } f.Args["size"] = &ast.Argument{ Name: "size", @@ -90,7 +91,7 @@ func addPaginationArguments(f *ast.Field, store *ast.NodeStore) { Name: "Int", TypeNode: store.Scalars["Int"], }, - DefaultValue: int64(10), + DefaultValue: 10, } f.Args["sort"] = &ast.Argument{ Name: "sort", diff --git a/graphql/ast/funcs.go b/graphql/ast/funcs.go index 030305d..a628c18 100644 --- a/graphql/ast/funcs.go +++ b/graphql/ast/funcs.go @@ -16,6 +16,13 @@ var excludeFieldName = map[string]struct{}{ "__typename": {}, } +func PrefixModels(typeName string) string { + if strings.HasPrefix(typeName, "*") { + return "*" + "models." + strings.TrimPrefix(typeName, "*") + } + return "models." + typeName +} + func Fields(fields map[string]*Field) string { var lines []string for _, field := range fields { @@ -56,26 +63,41 @@ func defaultDirective(tags map[string][]string, directive *Directive) error { return nil } +func typeDirective(tags map[string][]string, directive *Directive) error { + if arg := directive.GetArg("name"); arg != nil { + tags["gorm"] = append(tags["gorm"], fmt.Sprintf("type:%s", arg.Value.(string))) + } + return nil +} + var directiveFns = map[string]func(map[string][]string, *Directive) error{ "index": indexDirective, "unique": uniqueDirective, "tag": tagDirective, "default": defaultDirective, + "type": typeDirective, } func genTag(field *Field) string { tags := map[string][]string{ "json": {field.Name}, } + hasType := false for _, directive := range field.Directives { if fn, ok := directiveFns[directive.Name]; ok { + if directive.Name == "type" { + hasType = true + } if err := fn(tags, directive); err != nil { log.Error().Err(err).Msgf("failed to apply directive %s to field %s", directive.Name, field.Name) return "" } } } + if !hasType && field.Type.GetRealType().Name == "String" { + tags["gorm"] = append(tags["gorm"], fmt.Sprintf("type:varchar(%s)", "255")) + } // Build the tag string using strings.Builder var builder strings.Builder diff --git a/graphql/model/generate/generate.go b/graphql/model/generate/generate.go index 754a765..0bc4833 100644 --- a/graphql/model/generate/generate.go +++ b/graphql/model/generate/generate.go @@ -152,7 +152,7 @@ func GenOperationResolver(node *ast.ObjectNode, path string, name string) error FileName: name, FileExt: "go", Package: "resolver", - Editable: false, + Editable: true, SkipIfExists: false, Data: map[string]interface{}{ "Fields": fields, @@ -176,7 +176,7 @@ func GenOperationResolverGen(nodes []*ast.ObjectNode, path string) error { FileName: "operation_gen", FileExt: "go", Package: "resolver", - Editable: false, + Editable: true, SkipIfExists: false, Data: map[string]interface{}{ "Nodes": nodes, diff --git a/graphql/model/generate/tpl/operation.tpl b/graphql/model/generate/tpl/operation.tpl index fc7e101..e232ec1 100644 --- a/graphql/model/generate/tpl/operation.tpl +++ b/graphql/model/generate/tpl/operation.tpl @@ -1,7 +1,22 @@ {{- range $key, $field := .Fields }} -func {{ $field.Name | ucFirst }}Resolver(ctx *context.Context{{ range $index, $arg := $field.Args }}, {{ $arg.Name }} {{ if eq $arg.Type.GetRealType.Kind "SCALAR" }}{{ else }}models.{{ end }}{{ false | $arg.Type.GetGoType }}) ({{ if eq $field.Type.GetRealType.Kind "SCALAR" }}{{ else }}*models.{{ end }}{{ false | $field.Type.GetGoType }}{{ else }}{{ false | $field.Type.GetGoType }}{{ end }}, error) { +func {{ $field.Name | ucFirst }}Resolver(ctx *context.Context + {{- range $index, $arg := $field.Args -}}, + {{- $arg.Name -}} + {{- " " -}} + {{- if eq $arg.Type.GetRealType.Kind "SCALAR" -}} + {{- false | $arg.Type.GetGoType -}} + {{- else -}} + {{- (false | $arg.Type.GetGoType) | prefixModels -}} + {{- end -}} + {{- end -}} ) ( + {{- if eq $field.Type.GetRealType.Kind "SCALAR" -}} + {{- false | $field.Type.GetGoType -}} + {{- else -}} + {{- (false | $field.Type.GetGoType) | prefixModels -}} + {{- end -}} + , error) { {{ $field.Name | ucFirst | funcStart }} panic("not implement") - {{ .Name | ucFirst | funcEnd }} + {{ $field.Name | ucFirst | funcEnd }} } -{{- end }} +{{- end }} \ No newline at end of file diff --git a/graphql/parser/operation.go b/graphql/parser/operation.go index e574d68..24c2fc3 100644 --- a/graphql/parser/operation.go +++ b/graphql/parser/operation.go @@ -23,6 +23,19 @@ type QueryParser struct { OperationType string } +func (p *QueryParser) GetVariable(name string) any { + v := p.Variables[name] + switch v := v.(type) { + case float64: + return int64(v) + case int64: + return v + case string: + return v + } + return v +} + func (p *QueryParser) Validate(store *ast.NodeStore) errors.GraphqlErrorInterface { for _, arg := range p.Args { if p.Variables[arg.Name] == nil { @@ -31,8 +44,11 @@ func (p *QueryParser) Validate(store *ast.NodeStore) errors.GraphqlErrorInterfac Locations: []*errors.GraphqlLocation{arg.GetLocation()}, } } - arg.Value = p.Variables[arg.Name] - arg.Validate(store, p.Args, nil) + arg.Value = p.GetVariable(arg.Name) + err := arg.Validate(store, p.Args, nil) + if err != nil { + return err + } } for _, field := range p.Fields { obj := p.Parser.NodeStore.Objects[p.OperationType] diff --git a/graphql/scalar/id.go b/graphql/scalar/id.go index 53f0f1f..c37de5e 100644 --- a/graphql/scalar/id.go +++ b/graphql/scalar/id.go @@ -14,17 +14,19 @@ func (i *IDScalar) ParseValue(v interface{}, location *errors.GraphqlLocation) ( case string: intValue, err := strconv.ParseInt(v, 10, 64) if err != nil { - return nil, &errors.GraphQLError{ - Message: fmt.Sprintf("invalid integer value: %s", v), - Locations: []*errors.GraphqlLocation{location}, - } + return nil, &errors.GraphQLError{ + Message: fmt.Sprintf("invalid integer value: %s, got %T", v, v), + Locations: []*errors.GraphqlLocation{location}, + } } return intValue, nil case int64: return v, nil + case float64: + return int64(v), nil default: return nil, &errors.GraphQLError{ - Message: fmt.Sprintf("invalid integer value: %v", v), + Message: fmt.Sprintf("invalid integer value: %v got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } } @@ -35,7 +37,7 @@ func (i *IDScalar) Serialize(v interface{}, location *errors.GraphqlLocation) (s case int64: return strconv.FormatInt(v, 10), nil default: - return "", &errors.GraphQLError{ + return "", &errors.GraphQLError{ Message: fmt.Sprintf("value is not an integer: %v", v), Locations: []*errors.GraphqlLocation{location}, } diff --git a/graphql/scalar/int.go b/graphql/scalar/int.go index 0a2e341..aac3d81 100644 --- a/graphql/scalar/int.go +++ b/graphql/scalar/int.go @@ -14,17 +14,19 @@ func (i *IntScalar) ParseValue(v interface{}, location *errors.GraphqlLocation) case string: intValue, err := strconv.ParseInt(v, 10, 64) if err != nil { - return nil, &errors.GraphQLError{ - Message: fmt.Sprintf("invalid integer value: %s", v), + return nil, &errors.GraphQLError{ + Message: fmt.Sprintf("invalid integer value: %s, got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } } return intValue, nil case int64: return v, nil + case float64: + return int64(v), nil default: return nil, &errors.GraphQLError{ - Message: fmt.Sprintf("invalid integer value: %v", v), + Message: fmt.Sprintf("invalid integer value: %v, got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } } diff --git a/template/template.go b/template/template.go index 4456de2..1ab82f9 100644 --- a/template/template.go +++ b/template/template.go @@ -45,6 +45,8 @@ type Options struct { // # Section: user code section start / end. Do not remove this comment. SkipIfExists bool + Imports []*Import + Funcs template.FuncMap } @@ -69,6 +71,7 @@ func (o *Options) addFunc() { o.Funcs["buildRelation"] = ast.BuildRelation o.Funcs["pluralize"] = utils.Pluralize o.Funcs["isInternalType"] = utils.IsInternalType + o.Funcs["prefixModels"] = ast.PrefixModels } func Render(options *Options) error { @@ -116,7 +119,7 @@ func Render(options *Options) error { // Step 6: Detect required imports imports := detectImports(finalContent) - importsStr := formatImport(imports) + importsStr := formatImport(append(options.Imports, imports...)) // Step 7: Add imports to the top of the file if options.FileExt == "go" { From 9338ddcc0bd1e0cbea16ef4acc756d08773073bc Mon Sep 17 00:00:00 2001 From: linty Date: Fri, 1 Nov 2024 18:49:37 +0800 Subject: [PATCH 3/4] fix: fix mergedata --- example/test/models/model.go | 2 +- example/test/repo/repo.go | 6 ++-- example/test/resolver/operation_gen.go | 4 +-- example/test/resolver/query.go | 27 +++++++++------ graphql/ast/funcs.go | 2 +- graphql/excute/excute.go | 48 +++++++++++++++++++------- 6 files changed, 59 insertions(+), 30 deletions(-) diff --git a/example/test/models/model.go b/example/test/models/model.go index 485a1f8..7f65bb3 100644 --- a/example/test/models/model.go +++ b/example/test/models/model.go @@ -6,7 +6,7 @@ import "github.com/light-speak/lighthouse/graphql/model" type Test struct { model.Model - Email string `gorm:"type:varchar(255)" json:"email" ` + Email string `json:"email" gorm:"type:varchar(255)" ` Name string `json:"name" gorm:"type:varchar(255)" ` } diff --git a/example/test/repo/repo.go b/example/test/repo/repo.go index 3fdc18e..6d97357 100644 --- a/example/test/repo/repo.go +++ b/example/test/repo/repo.go @@ -2,12 +2,12 @@ package repo import ( - "github.com/light-speak/lighthouse/graphql/ast" - "github.com/light-speak/lighthouse/context" "github.com/light-speak/lighthouse/graphql/model" - "gorm.io/gorm" + "github.com/light-speak/lighthouse/context" "test/models" + "github.com/light-speak/lighthouse/graphql/ast" "sync" + "gorm.io/gorm" ) func Provide__Test() map[string]*ast.Relation { return map[string]*ast.Relation{"created_at": {},"email": {},"id": {},"name": {},"updated_at": {},}} diff --git a/example/test/resolver/operation_gen.go b/example/test/resolver/operation_gen.go index fe1db83..309c149 100644 --- a/example/test/resolver/operation_gen.go +++ b/example/test/resolver/operation_gen.go @@ -2,9 +2,9 @@ package resolver import ( - "github.com/light-speak/lighthouse/graphql/excute" - "fmt" "github.com/light-speak/lighthouse/context" + "fmt" + "github.com/light-speak/lighthouse/graphql/excute" ) func init() { diff --git a/example/test/resolver/query.go b/example/test/resolver/query.go index eb5d7e9..1bc7e4f 100644 --- a/example/test/resolver/query.go +++ b/example/test/resolver/query.go @@ -2,17 +2,24 @@ package resolver import ( - "test/models" - - "github.com/light-speak/lighthouse/context" - "github.com/light-speak/lighthouse/graphql/model" + "test/models" + "time" + "github.com/light-speak/lighthouse/graphql/model" + "github.com/light-speak/lighthouse/context" ) -func GetTestResolver(ctx *context.Context, id int64) (models.Test, error) { + +func GetTestResolver(ctx *context.Context,id int64) (*models.Test, error) { // Func:GetTest user code start. Do not remove this comment. - test := models.Test{} - db := model.GetDB() - db.Where("id = ?", id).First(&test) + test := &models.Test{ + Model: model.Model{ + Id: id, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + Name: "test", + Email: "test@test.com", + } return test, nil - // Func:GetTest user code end. Do not remove this comment. -} + // Func:GetTest user code end. Do not remove this comment. +} \ No newline at end of file diff --git a/graphql/ast/funcs.go b/graphql/ast/funcs.go index a628c18..9aadf4b 100644 --- a/graphql/ast/funcs.go +++ b/graphql/ast/funcs.go @@ -20,7 +20,7 @@ func PrefixModels(typeName string) string { if strings.HasPrefix(typeName, "*") { return "*" + "models." + strings.TrimPrefix(typeName, "*") } - return "models." + typeName + return "*models." + typeName } func Fields(fields map[string]*Field) string { diff --git a/graphql/excute/excute.go b/graphql/excute/excute.go index fac75d2..c8e260c 100644 --- a/graphql/excute/excute.go +++ b/graphql/excute/excute.go @@ -7,6 +7,7 @@ import ( "github.com/light-speak/lighthouse/errors" "github.com/light-speak/lighthouse/graphql" "github.com/light-speak/lighthouse/graphql/ast" + "github.com/light-speak/lighthouse/graphql/model" "github.com/light-speak/lighthouse/graphql/parser" "github.com/light-speak/lighthouse/graphql/parser/lexer" ) @@ -78,45 +79,66 @@ func ExecuteQuery(ctx *context.Context, query string, variables map[string]any) res[field.Name] = nil continue } - queryFunc, ok := funMap[field.Name] - if ok { + + if queryFunc, ok := funMap[field.Name]; ok { r, e := queryFunc(qp, field) if e != nil { - ee := &errors.GraphQLError{ + ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ Message: e.Error(), Locations: []*errors.GraphqlLocation{field.GetLocation()}, - } - ctx.Errors = append(ctx.Errors, ee) + }) + continue } res[field.Name] = r continue } - resolverFunc, ok := resolverMap[field.Name] - if ok { + if resolverFunc, ok := resolverMap[field.Name]; ok { args := make(map[string]any) for _, arg := range field.Args { args[arg.Name] = arg.Value } r, e := resolverFunc(ctx, args) if e != nil { - ee := &errors.GraphQLError{ + ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ Message: e.Error(), Locations: []*errors.GraphqlLocation{field.GetLocation()}, + }) + continue + } + + if modelData, ok := r.(model.ModelInterface); ok { + modelMap, err := model.StructToMap(modelData) + if err != nil { + ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ + Message: err.Error(), + Locations: []*errors.GraphqlLocation{field.GetLocation()}, + }) + continue } - ctx.Errors = append(ctx.Errors, ee) + data := make(map[string]interface{}) + for _, child := range field.Children { + d, err := mergeData(child, modelMap) + if err != nil { + ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ + Message: err.Error(), + Locations: []*errors.GraphqlLocation{child.GetLocation()}, + }) + continue + } + data[child.Name] = d + } + res[field.Name] = data continue } res[field.Name] = r continue } - ee := &errors.GraphQLError{ + ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ Message: fmt.Sprintf("query %s not found", field.Name), Locations: []*errors.GraphqlLocation{field.GetLocation()}, - } - ctx.Errors = append(ctx.Errors, ee) - continue + }) } return res } From ab9a51d156ebc1c5873523c344940599d09a628e Mon Sep 17 00:00:00 2001 From: linty Date: Fri, 1 Nov 2024 21:35:11 +0800 Subject: [PATCH 4/4] feat: the fucking relation not need to return --- example/test/.env | 45 ----- example/test/cmd/cmd.go | 19 --- example/test/cmd/migrate.go | 46 ----- example/test/cmd/start.go | 45 ----- example/test/go.mod | 34 ---- example/test/go.sum | 66 -------- example/test/ide-helper.graphql | 15 -- example/test/lighthouse.yml | 8 - example/test/main.go | 17 -- example/test/models/enum.go | 28 ---- example/test/models/input.go | 6 - example/test/models/interface.go | 5 - example/test/models/model.go | 22 --- example/test/repo/repo.go | 100 ----------- example/test/resolver/operation_gen.go | 18 -- example/test/resolver/query.go | 25 --- example/test/resolver/resolver.go | 8 - example/test/schema/example.graphql | 9 - example/test/service/service.go | 13 -- example/user/models/model.go | 30 ++-- example/user/repo/repo.go | 66 ++++---- example/user/resolver/operation_gen.go | 53 ++++-- example/user/resolver/query.go | 45 +++-- example/user/schema/post.graphqls | 2 + graphql/ast/funcs.go | 8 +- graphql/ast/node.go | 30 ++++ graphql/excute/excute.go | 49 ++---- graphql/excute/resolver.go | 168 +++++++++++++++++++ graphql/model/generate/tpl/operation_gen.tpl | 41 ++++- graphql/model/quick.go | 2 +- graphql/scalar/id.go | 21 ++- graphql/scalar/int.go | 21 ++- 32 files changed, 413 insertions(+), 652 deletions(-) delete mode 100644 example/test/.env delete mode 100644 example/test/cmd/cmd.go delete mode 100644 example/test/cmd/migrate.go delete mode 100644 example/test/cmd/start.go delete mode 100644 example/test/go.mod delete mode 100644 example/test/go.sum delete mode 100644 example/test/ide-helper.graphql delete mode 100644 example/test/lighthouse.yml delete mode 100644 example/test/main.go delete mode 100644 example/test/models/enum.go delete mode 100644 example/test/models/input.go delete mode 100644 example/test/models/interface.go delete mode 100644 example/test/models/model.go delete mode 100644 example/test/repo/repo.go delete mode 100644 example/test/resolver/operation_gen.go delete mode 100644 example/test/resolver/query.go delete mode 100644 example/test/resolver/resolver.go delete mode 100644 example/test/schema/example.graphql delete mode 100644 example/test/service/service.go create mode 100644 graphql/excute/resolver.go diff --git a/example/test/.env b/example/test/.env deleted file mode 100644 index 9d51a77..0000000 --- a/example/test/.env +++ /dev/null @@ -1,45 +0,0 @@ -# Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -# Application settings -APP_NAME=MyApp -APP_ENVIRONMENT=development -APP_MODE=single - -# Server settings -SERVER_PORT=8080 -SERVER_THROTTLE=100 - -# API settings -API_RESTFUL=true -API_PREFIX=/api - -# Database settings -DB_HOST=localhost -DB_PORT=3306 -DB_USER=root -DB_PASSWORD= -DB_NAME=example -DB_DRIVER=mysql -DB_ORM=gorm - -# Authentication settings -AUTH_DRIVER=jwt - -# Logger settings -LOGGER_LEVEL=info -LOGGER_PATH=./logs/app.log -LOGGER_STACK=false -LOGGER_DRIVER=stdout - -# Redis settings -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD= -REDIS_DB=0 - -# Elasticsearch settings -ELASTICSEARCH_ENABLE=false -ELASTICSEARCH_HOST=localhost -ELASTICSEARCH_PORT=9200 -ELASTICSEARCH_USER=elastic -ELASTICSEARCH_PASSWORD=changeme - diff --git a/example/test/cmd/cmd.go b/example/test/cmd/cmd.go deleted file mode 100644 index 24e310a..0000000 --- a/example/test/cmd/cmd.go +++ /dev/null @@ -1,19 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package cmd - -import "github.com/light-speak/lighthouse/command" - -type Command struct{ - // Section: user code section start. Do not remove this comment. -// Section: user code section end. Do not remove this comment. - -} - -func (c *Command) GetCommands() []command.Command { - return []command.Command{ - // Func:GetCommands user code start. Do not remove this comment. - &Start{}, - &Migrate{}, - // Func:GetCommands user code end. Do not remove this comment. - } -} diff --git a/example/test/cmd/migrate.go b/example/test/cmd/migrate.go deleted file mode 100644 index 633721c..0000000 --- a/example/test/cmd/migrate.go +++ /dev/null @@ -1,46 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package cmd - -import ( - "github.com/light-speak/lighthouse/command" - "test/models" -) - -type Migrate struct{} - -func (c *Migrate) Name() string { - // Func:Name user code start. Do not remove this comment. - return "app:migrate" - // Func:Name user code end. Do not remove this comment. -} - -func (c *Migrate) Usage() string { - // Func:Usage user code start. Do not remove this comment. - return "This is a command generated by lighthouse cli" - // Func:Usage user code end. Do not remove this comment. -} - -func (c *Migrate) Args() []*command.CommandArg { - return []*command.CommandArg{ - // Func:Args user code start. Do not remove this comment. - // Func:Args user code end. Do not remove this comment. - } -} - -func (c *Migrate) Action() func(flagValues map[string]interface{}) error { - return func(flagValues map[string]interface{}) error { - // Func:Action user code start. Do not remove this comment. - err := models.Migrate() - if err != nil { - return err - } - // Func:Action user code end. Do not remove this comment. - return nil - } -} - -func (c *Migrate) OnExit() func() { - return func() {} -} -// Section: user code section start. Do not remove this comment. -// Section: user code section end. Do not remove this comment. diff --git a/example/test/cmd/start.go b/example/test/cmd/start.go deleted file mode 100644 index d719d26..0000000 --- a/example/test/cmd/start.go +++ /dev/null @@ -1,45 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package cmd - -import ( - "test/service" - "github.com/light-speak/lighthouse/command" -) - -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -type Start struct{} - -func (c *Start) Name() string { - // Func:Name user code start. Do not remove this comment. - return "app:start" - // Func:Name user code end. Do not remove this comment. -} - -func (c *Start) Usage() string { - // Func:Usage user code start. Do not remove this comment. - return "This is a command generated by lighthouse cli" - // Func:Usage user code end. Do not remove this comment. -} - -func (c *Start) Args() []*command.CommandArg { - return []*command.CommandArg{ - // Func:Args user code start. Do not remove this comment. - // Func:Args user code end. Do not remove this comment. - } -} - -func (c *Start) Action() func(flagValues map[string]interface{}) error { - return func(flagValues map[string]interface{}) error { - // Func:Action user code start. Do not remove this comment. - service.StartService() - // Func:Action user code end. Do not remove this comment. - return nil - } -} - -func (c *Start) OnExit() func() { - return func() {} -} - -// Section: user code section start. Do not remove this comment. -// Section: user code section end. Do not remove this comment. diff --git a/example/test/go.mod b/example/test/go.mod deleted file mode 100644 index c726f00..0000000 --- a/example/test/go.mod +++ /dev/null @@ -1,34 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -module test - -go 1.23.1 - -replace github.com/light-speak/lighthouse => ../../ - -require ( - github.com/light-speak/lighthouse v0.0.1 - gorm.io/gorm v1.25.12 -) - -require ( - github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect - github.com/elastic/go-elasticsearch/v8 v8.15.0 // indirect - github.com/go-chi/chi/v5 v5.1.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/joho/godotenv v1.5.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/rs/zerolog v1.33.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.14.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gorm.io/driver/mysql v1.5.7 // indirect -) diff --git a/example/test/go.sum b/example/test/go.sum deleted file mode 100644 index d93acd4..0000000 --- a/example/test/go.sum +++ /dev/null @@ -1,66 +0,0 @@ -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/elastic/elastic-transport-go/v8 v8.6.0 h1:Y2S/FBjx1LlCv5m6pWAF2kDJAHoSjSRSJCApolgfthA= -github.com/elastic/elastic-transport-go/v8 v8.6.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk= -github.com/elastic/go-elasticsearch/v8 v8.15.0 h1:IZyJhe7t7WI3NEFdcHnf6IJXqpRf+8S8QWLtZYYyBYk= -github.com/elastic/go-elasticsearch/v8 v8.15.0/go.mod h1:HCON3zj4btpqs2N1jjsAy4a/fiAul+YBP00mBH4xik8= -github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= -github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= -gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= -gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= -gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= -gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/example/test/ide-helper.graphql b/example/test/ide-helper.graphql deleted file mode 100644 index 456ad71..0000000 --- a/example/test/ide-helper.graphql +++ /dev/null @@ -1,15 +0,0 @@ -# Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -type Query -type Mutation -type Subscription - -directive @external repeatable on FIELD_DEFINITION -directive @requires(fields: [String!]!) repeatable on FIELD_DEFINITION -directive @provides(fields: [String!]!) repeatable on FIELD_DEFINITION -directive @key(fields: [String!]!) repeatable on OBJECT | INTERFACE -directive @extends repeatable on OBJECT - -directive @paginate(scopes: [String!]) on FIELD_DEFINITION -directive @skip(if: Boolean!) on FIELD_DEFINITION -directive @include(if: Boolean!) on FIELD_DEFINITION -directive @enum(value: Int!) on FIELD_DEFINITION \ No newline at end of file diff --git a/example/test/lighthouse.yml b/example/test/lighthouse.yml deleted file mode 100644 index cc89d5d..0000000 --- a/example/test/lighthouse.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -schema: - ext: - - graphql - - graphqls - path: - - schema - diff --git a/example/test/main.go b/example/test/main.go deleted file mode 100644 index 2f88655..0000000 --- a/example/test/main.go +++ /dev/null @@ -1,17 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package main - -import ( - "test/cmd" - "fmt" - "os" - "github.com/light-speak/lighthouse/command" -) - -func main() { - cmd := &cmd.Command{} - if err := command.Run(cmd, os.Args); err != nil { - fmt.Fprintf(os.Stderr, "error: %s\n", err) - os.Exit(1) - } -} diff --git a/example/test/models/enum.go b/example/test/models/enum.go deleted file mode 100644 index 40db117..0000000 --- a/example/test/models/enum.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. -package models - - - - -type SortOrder int8 - -const ( - ASC SortOrder = 1 - DESC SortOrder = -1 -) - -func (e SortOrder) ToString() string { - switch e { - case ASC: - return "ASC" - case DESC: - return "DESC" - default: - return "unknown" - } -} - -var SortOrderMap = map[string]SortOrder{ - "ASC": ASC, - "DESC": DESC, -} diff --git a/example/test/models/input.go b/example/test/models/input.go deleted file mode 100644 index 59ada3a..0000000 --- a/example/test/models/input.go +++ /dev/null @@ -1,6 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. -package models - - - - diff --git a/example/test/models/interface.go b/example/test/models/interface.go deleted file mode 100644 index 2ec0070..0000000 --- a/example/test/models/interface.go +++ /dev/null @@ -1,5 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. -package models - - - diff --git a/example/test/models/model.go b/example/test/models/model.go deleted file mode 100644 index 7f65bb3..0000000 --- a/example/test/models/model.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. -package models - -import "github.com/light-speak/lighthouse/graphql/model" - - -type Test struct { - model.Model - Email string `json:"email" gorm:"type:varchar(255)" ` - Name string `json:"name" gorm:"type:varchar(255)" ` -} - -func (*Test) IsModel() bool { return true } -func (*Test) TableName() string { return "tests" } -func (*Test) TypeName() string { return "test" } - - -func Migrate() error { - return model.GetDB().AutoMigrate( - &Test{}, - ) -} \ No newline at end of file diff --git a/example/test/repo/repo.go b/example/test/repo/repo.go deleted file mode 100644 index 6d97357..0000000 --- a/example/test/repo/repo.go +++ /dev/null @@ -1,100 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. -package repo - -import ( - "github.com/light-speak/lighthouse/graphql/model" - "github.com/light-speak/lighthouse/context" - "test/models" - "github.com/light-speak/lighthouse/graphql/ast" - "sync" - "gorm.io/gorm" -) - -func Provide__Test() map[string]*ast.Relation { return map[string]*ast.Relation{"created_at": {},"email": {},"id": {},"name": {},"updated_at": {},}} -func Load__Test(ctx *context.Context, key int64, field string) (map[string]interface{}, error) { - return model.GetLoader[int64](model.GetDB(), "tests", field).Load(key) -} -func LoadList__Test(ctx *context.Context, key int64, field string) ([]map[string]interface{}, error) { - return model.GetLoader[int64](model.GetDB(), "tests", field).LoadList(key) -} -func Query__Test(scopes ...func(db *gorm.DB) *gorm.DB) *gorm.DB { - return model.GetDB().Model(&models.Test{}).Scopes(scopes...) -} -func First__Test(ctx *context.Context, columns map[string]interface{}, data map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) (map[string]interface{}, error) { - var err error - selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Test()) - if data == nil { - data = make(map[string]interface{}) - err = Query__Test().Scopes(scopes...).Select(selectColumns).First(data).Error - if err != nil { - return nil, err - } - } - var wg sync.WaitGroup - errChan := make(chan error, len(selectRelations)) - var mu sync.Mutex - - for key, relation := range selectRelations { - wg.Add(1) - go func(data map[string]interface{}, relation *model.SelectRelation) { - defer wg.Done() - cData, err := model.FetchRelation(ctx, data, relation) - if err != nil { - errChan <- err - } - mu.Lock() - defer mu.Unlock() - data[key] = cData - }(data, relation) - } - wg.Wait() - close(errChan) - for err := range errChan { - return nil, err - } - return data, nil -} -func List__Test(ctx *context.Context, columns map[string]interface{},datas []map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) ([]map[string]interface{}, error) { - var err error - selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Test()) - if datas == nil { - datas = make([]map[string]interface{}, 0) - err = Query__Test().Scopes(scopes...).Select(selectColumns).Find(&datas).Error - if err != nil { - return nil, err - } - } - var wg sync.WaitGroup - errChan := make(chan error, len(datas)*len(selectRelations)) - var mu sync.Mutex - - for _, data := range datas { - for key, relation := range selectRelations { - wg.Add(1) - go func(data map[string]interface{}, relation *model.SelectRelation) { - defer wg.Done() - cData, err := model.FetchRelation(ctx, data, relation) - if err != nil { - errChan <- err - } - mu.Lock() - defer mu.Unlock() - data[key] = cData - }(data, relation) - } - } - wg.Wait() - close(errChan) - for err := range errChan { - return nil, err - } - return datas, nil -} - - -func init() { - model.AddQuickFirst("Test", First__Test) - model.AddQuickList("Test", List__Test) - model.AddQuickLoad("Test", Load__Test) - model.AddQuickLoadList("Test", LoadList__Test) -} diff --git a/example/test/resolver/operation_gen.go b/example/test/resolver/operation_gen.go deleted file mode 100644 index 309c149..0000000 --- a/example/test/resolver/operation_gen.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package resolver - -import ( - "github.com/light-speak/lighthouse/context" - "fmt" - "github.com/light-speak/lighthouse/graphql/excute" -) - -func init() { - excute.AddResolver("getTest", func(ctx *context.Context, args map[string]any) (interface{}, error) { - id, ok := args["id"].(int64) - if !ok { - return nil, fmt.Errorf("argument: 'id' is not a int64, got %T", args["id"]) - } - return GetTestResolver(ctx, id) - }) -} diff --git a/example/test/resolver/query.go b/example/test/resolver/query.go deleted file mode 100644 index 1bc7e4f..0000000 --- a/example/test/resolver/query.go +++ /dev/null @@ -1,25 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package resolver - -import ( - "test/models" - "time" - "github.com/light-speak/lighthouse/graphql/model" - "github.com/light-speak/lighthouse/context" -) - - -func GetTestResolver(ctx *context.Context,id int64) (*models.Test, error) { - // Func:GetTest user code start. Do not remove this comment. - test := &models.Test{ - Model: model.Model{ - Id: id, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - Name: "test", - Email: "test@test.com", - } - return test, nil - // Func:GetTest user code end. Do not remove this comment. -} \ No newline at end of file diff --git a/example/test/resolver/resolver.go b/example/test/resolver/resolver.go deleted file mode 100644 index b281860..0000000 --- a/example/test/resolver/resolver.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package resolver - - - -func init() { - -} \ No newline at end of file diff --git a/example/test/schema/example.graphql b/example/test/schema/example.graphql deleted file mode 100644 index 6eaaf1f..0000000 --- a/example/test/schema/example.graphql +++ /dev/null @@ -1,9 +0,0 @@ -type Test @model{ - name:String! - email:String! -} - - -extend type Query{ - getTest(id:Int!): Test! -} \ No newline at end of file diff --git a/example/test/service/service.go b/example/test/service/service.go deleted file mode 100644 index a47a0f3..0000000 --- a/example/test/service/service.go +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. -package service - -import ( - _ "test/resolver" - _ "test/repo" - _ "test/models" - "github.com/light-speak/lighthouse/handler" -) - -func StartService() { - handler.StartService() -} diff --git a/example/user/models/model.go b/example/user/models/model.go index 4287a61..3bd8097 100644 --- a/example/user/models/model.go +++ b/example/user/models/model.go @@ -4,22 +4,9 @@ package models import "github.com/light-speak/lighthouse/graphql/model" -type Post struct { - model.ModelSoftDelete - User User `json:"user" ` - Title string `json:"title" gorm:"index" ` - Content string `json:"content" ` - UserId int64 `json:"user_id" ` - Enum TestEnum `json:"enum" ` -} - -func (*Post) IsModel() bool { return true } -func (*Post) TableName() string { return "posts" } -func (*Post) TypeName() string { return "post" } - type User struct { model.Model - Name string `json:"name" gorm:"index" ` + Name string `gorm:"index;type:varchar(255)" json:"name" ` Posts []Post `json:"posts" ` } @@ -29,10 +16,23 @@ func (this *User) GetName() string { return this.Name } func (*User) TableName() string { return "users" } func (*User) TypeName() string { return "user" } +type Post struct { + model.ModelSoftDelete + Title string `json:"title" gorm:"index;type:varchar(255)" ` + User User `json:"user" ` + Enum TestEnum `json:"enum" ` + Content string `json:"content" gorm:"type:varchar(255)" ` + UserId int64 `json:"user_id" ` +} + +func (*Post) IsModel() bool { return true } +func (*Post) TableName() string { return "posts" } +func (*Post) TypeName() string { return "post" } + func Migrate() error { return model.GetDB().AutoMigrate( - &Post{}, &User{}, + &Post{}, ) } \ No newline at end of file diff --git a/example/user/repo/repo.go b/example/user/repo/repo.go index c549f62..efd0047 100644 --- a/example/user/repo/repo.go +++ b/example/user/repo/repo.go @@ -2,30 +2,30 @@ package repo import ( - "github.com/light-speak/lighthouse/graphql/model" "user/models" + "github.com/light-speak/lighthouse/graphql/model" + "sync" "github.com/light-speak/lighthouse/graphql/ast" - "gorm.io/gorm" "github.com/light-speak/lighthouse/context" - "sync" + "gorm.io/gorm" ) -func Provide__Post() map[string]*ast.Relation { return map[string]*ast.Relation{"content": {},"created_at": {},"deleted_at": {},"enum": {},"id": {},"title": {},"updated_at": {},"user": {Name: "user", RelationType: ast.RelationTypeBelongsTo, ForeignKey: "user_id", Reference: "id"},"user_id": {},}} -func Load__Post(ctx *context.Context, key int64, field string) (map[string]interface{}, error) { - return model.GetLoader[int64](model.GetDB(), "posts", field).Load(key) +func Provide__User() map[string]*ast.Relation { return map[string]*ast.Relation{"created_at": {},"id": {},"name": {},"posts": {Name: "post", RelationType: ast.RelationTypeHasMany, ForeignKey: "user_id", Reference: "id"},"updated_at": {},}} +func Load__User(ctx *context.Context, key int64, field string) (map[string]interface{}, error) { + return model.GetLoader[int64](model.GetDB(), "users", field).Load(key) } -func LoadList__Post(ctx *context.Context, key int64, field string) ([]map[string]interface{}, error) { - return model.GetLoader[int64](model.GetDB(), "posts", field).LoadList(key) +func LoadList__User(ctx *context.Context, key int64, field string) ([]map[string]interface{}, error) { + return model.GetLoader[int64](model.GetDB(), "users", field).LoadList(key) } -func Query__Post(scopes ...func(db *gorm.DB) *gorm.DB) *gorm.DB { - return model.GetDB().Model(&models.Post{}).Scopes(scopes...) +func Query__User(scopes ...func(db *gorm.DB) *gorm.DB) *gorm.DB { + return model.GetDB().Model(&models.User{}).Scopes(scopes...) } -func First__Post(ctx *context.Context, columns map[string]interface{}, data map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) (map[string]interface{}, error) { +func First__User(ctx *context.Context, columns map[string]interface{}, data map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) (map[string]interface{}, error) { var err error - selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Post()) + selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__User()) if data == nil { data = make(map[string]interface{}) - err = Query__Post().Scopes(scopes...).Select(selectColumns).First(data).Error + err = Query__User().Scopes(scopes...).Select(selectColumns).First(data).Error if err != nil { return nil, err } @@ -54,12 +54,12 @@ func First__Post(ctx *context.Context, columns map[string]interface{}, data map[ } return data, nil } -func List__Post(ctx *context.Context, columns map[string]interface{},datas []map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) ([]map[string]interface{}, error) { +func List__User(ctx *context.Context, columns map[string]interface{},datas []map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) ([]map[string]interface{}, error) { var err error - selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Post()) + selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__User()) if datas == nil { datas = make([]map[string]interface{}, 0) - err = Query__Post().Scopes(scopes...).Select(selectColumns).Find(&datas).Error + err = Query__User().Scopes(scopes...).Select(selectColumns).Find(&datas).Error if err != nil { return nil, err } @@ -90,22 +90,22 @@ func List__Post(ctx *context.Context, columns map[string]interface{},datas []map } return datas, nil } -func Provide__User() map[string]*ast.Relation { return map[string]*ast.Relation{"created_at": {},"id": {},"name": {},"posts": {Name: "post", RelationType: ast.RelationTypeHasMany, ForeignKey: "user_id", Reference: "id"},"updated_at": {},}} -func Load__User(ctx *context.Context, key int64, field string) (map[string]interface{}, error) { - return model.GetLoader[int64](model.GetDB(), "users", field).Load(key) +func Provide__Post() map[string]*ast.Relation { return map[string]*ast.Relation{"content": {},"created_at": {},"deleted_at": {},"enum": {},"id": {},"title": {},"updated_at": {},"user": {Name: "user", RelationType: ast.RelationTypeBelongsTo, ForeignKey: "user_id", Reference: "id"},"user_id": {},}} +func Load__Post(ctx *context.Context, key int64, field string) (map[string]interface{}, error) { + return model.GetLoader[int64](model.GetDB(), "posts", field).Load(key) } -func LoadList__User(ctx *context.Context, key int64, field string) ([]map[string]interface{}, error) { - return model.GetLoader[int64](model.GetDB(), "users", field).LoadList(key) +func LoadList__Post(ctx *context.Context, key int64, field string) ([]map[string]interface{}, error) { + return model.GetLoader[int64](model.GetDB(), "posts", field).LoadList(key) } -func Query__User(scopes ...func(db *gorm.DB) *gorm.DB) *gorm.DB { - return model.GetDB().Model(&models.User{}).Scopes(scopes...) +func Query__Post(scopes ...func(db *gorm.DB) *gorm.DB) *gorm.DB { + return model.GetDB().Model(&models.Post{}).Scopes(scopes...) } -func First__User(ctx *context.Context, columns map[string]interface{}, data map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) (map[string]interface{}, error) { +func First__Post(ctx *context.Context, columns map[string]interface{}, data map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) (map[string]interface{}, error) { var err error - selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__User()) + selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Post()) if data == nil { data = make(map[string]interface{}) - err = Query__User().Scopes(scopes...).Select(selectColumns).First(data).Error + err = Query__Post().Scopes(scopes...).Select(selectColumns).First(data).Error if err != nil { return nil, err } @@ -134,12 +134,12 @@ func First__User(ctx *context.Context, columns map[string]interface{}, data map[ } return data, nil } -func List__User(ctx *context.Context, columns map[string]interface{},datas []map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) ([]map[string]interface{}, error) { +func List__Post(ctx *context.Context, columns map[string]interface{},datas []map[string]interface{}, scopes ...func(db *gorm.DB) *gorm.DB) ([]map[string]interface{}, error) { var err error - selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__User()) + selectColumns, selectRelations := model.GetSelectInfo(columns, Provide__Post()) if datas == nil { datas = make([]map[string]interface{}, 0) - err = Query__User().Scopes(scopes...).Select(selectColumns).Find(&datas).Error + err = Query__Post().Scopes(scopes...).Select(selectColumns).Find(&datas).Error if err != nil { return nil, err } @@ -173,12 +173,12 @@ func List__User(ctx *context.Context, columns map[string]interface{},datas []map func init() { - model.AddQuickFirst("Post", First__Post) - model.AddQuickList("Post", List__Post) - model.AddQuickLoad("Post", Load__Post) - model.AddQuickLoadList("Post", LoadList__Post) model.AddQuickFirst("User", First__User) model.AddQuickList("User", List__User) model.AddQuickLoad("User", Load__User) model.AddQuickLoadList("User", LoadList__User) + model.AddQuickFirst("Post", First__Post) + model.AddQuickList("Post", List__Post) + model.AddQuickLoad("Post", Load__Post) + model.AddQuickLoadList("Post", LoadList__Post) } diff --git a/example/user/resolver/operation_gen.go b/example/user/resolver/operation_gen.go index 9d899ee..5e2abad 100644 --- a/example/user/resolver/operation_gen.go +++ b/example/user/resolver/operation_gen.go @@ -1,11 +1,12 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. package resolver import ( - "user/models" - "github.com/light-speak/lighthouse/graphql/excute" - "fmt" "github.com/light-speak/lighthouse/context" + "fmt" + "github.com/light-speak/lighthouse/graphql/excute" + "user/models" + "github.com/light-speak/lighthouse/graphql/model" ) func init() { @@ -14,21 +15,53 @@ func init() { if !ok { return nil, fmt.Errorf("argument: 'fuck' is not a string, got %T", args["fuck"]) } - return GetPostResolver(ctx, fuck) + res, err := GetPostResolver(ctx, fuck) + if res == nil { + return nil, err + } + return model.StructToMap(res) + }) + excute.AddResolver("getPostIds", func(ctx *context.Context, args map[string]any) (interface{}, error) { + res, err := GetPostIdsResolver(ctx) + if res == nil { + return nil, err + } + return res, nil + }) + excute.AddResolver("getPosts", func(ctx *context.Context, args map[string]any) (interface{}, error) { + fuck, ok := args["fuck"].(string) + if !ok { + return nil, fmt.Errorf("argument: 'fuck' is not a string, got %T", args["fuck"]) + } + list, err := GetPostsResolver(ctx, fuck) + if list == nil { + return nil, err + } + res := []map[string]interface{}{} + for _, item := range list { + itemMap, err := model.StructToMap(item) + if err != nil { + return nil, err + } + res = append(res, itemMap) + } + return res, nil }) excute.AddResolver("testPostEnum", func(ctx *context.Context, args map[string]any) (interface{}, error) { - enum, ok := models.TestEnumMap[args["enum"].(string)] + enumValue, ok := models.TestEnumMap[args["enum"].(string)] if !ok { return nil, fmt.Errorf("argument: 'enum' is not a models.TestEnum, got %T", args["enum"]) } - return TestPostEnumResolver(ctx, enum) + enum := &enumValue + res, err := TestPostEnumResolver(ctx, enum) + return res, err }) excute.AddResolver("testPostInput", func(ctx *context.Context, args map[string]any) (interface{}, error) { - inputPtr, err := models.MapToTestInput(args["input"].(map[string]interface{})) + input, err := models.MapToTestInput(args["input"].(map[string]interface{})) if err != nil { return nil, fmt.Errorf("argument: 'input' is not a models.TestInput, got %T", args["input"]) } - input := *inputPtr - return TestPostInputResolver(ctx, input) + res, err := TestPostInputResolver(ctx, input) + return res, err }) } diff --git a/example/user/resolver/query.go b/example/user/resolver/query.go index 100ad82..7a9c64f 100644 --- a/example/user/resolver/query.go +++ b/example/user/resolver/query.go @@ -1,32 +1,47 @@ -// Code generated by github.com/light-speak/lighthouse, DO NOT EDIT. +// Code generated by github.com/light-speak/lighthouse, YOU CAN FUCKING EDIT BY YOURSELF. package resolver import ( - "github.com/light-speak/lighthouse/graphql/model" "user/models" - "fmt" + "github.com/light-speak/lighthouse/graphql/model" "github.com/light-speak/lighthouse/log" "github.com/light-speak/lighthouse/context" + "fmt" ) -func GetPostResolver(ctx *context.Context, fuck string) (*models.Post, error) { - // Func:GetPost user code start. Do not remove this comment. - log.Debug().Msg("GetPostResolver") - db := model.GetDB() - db.Where("id = ?", fuck).First(&models.Post{}) - model.GetQuickLoad("Post")(ctx, 1, "id") - return nil, nil - // Func:GetPost user code end. Do not remove this comment. +func GetPostIdsResolver(ctx *context.Context) ([]int64, error) { + // Func:GetPostIds user code start. Do not remove this comment. + return []int64{1, 2, 3}, nil + // Func:GetPostIds user code end. Do not remove this comment. } -func TestPostEnumResolver(ctx *context.Context, enum models.TestEnum) (string, error) { +func TestPostEnumResolver(ctx *context.Context,enum *models.TestEnum) (string, error) { // Func:TestPostEnum user code start. Do not remove this comment. log.Debug().Msgf("enum: %+v", enum) - return fmt.Sprintf("啥也不是!:%v", enum == models.A), nil + res := fmt.Sprintf("啥也不是!:%v", *enum == models.A) + return res, nil // Func:TestPostEnum user code end. Do not remove this comment. } -func TestPostInputResolver(ctx *context.Context, input models.TestInput) (string, error) { +func TestPostInputResolver(ctx *context.Context,input *models.TestInput) (string, error) { // Func:TestPostInput user code start. Do not remove this comment. - return fmt.Sprintf("input: %+v", input), nil + res := fmt.Sprintf("input: %+v", input) + return res, nil // Func:TestPostInput user code end. Do not remove this comment. } +func GetPostResolver(ctx *context.Context,fuck string) (*models.Post, error) { + // Func:GetPost user code start. Do not remove this comment. + log.Debug().Msg("GetPostResolver") + db := model.GetDB() + post := &models.Post{} + db.Where("id = ?", fuck).First(post) + return post, nil + // Func:GetPost user code end. Do not remove this comment. +} +func GetPostsResolver(ctx *context.Context,fuck string) ([]*models.Post, error) { + // Func:GetPosts user code start. Do not remove this comment. + posts := []*models.Post{} + db := model.GetDB() + db.Find(&posts) + return posts, nil + // Func:GetPosts user code end. Do not remove this comment. +} \ No newline at end of file diff --git a/example/user/schema/post.graphqls b/example/user/schema/post.graphqls index bbac1e9..f4cb345 100644 --- a/example/user/schema/post.graphqls +++ b/example/user/schema/post.graphqls @@ -11,6 +11,8 @@ extend type Query { posts(id: [ID!]! @in, user_id: ID! @neq): [Post!]! @find post(id: ID! @eq): Post! @first getPost(fuck: String!): Post! + getPosts(fuck: String!): [Post!]! + getPostIds: [ID!]! testPostEnum(enum: TestEnum!): String! testPostInput(input: TestInput!): String! } diff --git a/graphql/ast/funcs.go b/graphql/ast/funcs.go index 9aadf4b..931faa9 100644 --- a/graphql/ast/funcs.go +++ b/graphql/ast/funcs.go @@ -18,7 +18,13 @@ var excludeFieldName = map[string]struct{}{ func PrefixModels(typeName string) string { if strings.HasPrefix(typeName, "*") { - return "*" + "models." + strings.TrimPrefix(typeName, "*") + if strings.HasPrefix(strings.TrimPrefix(typeName, "*"), "[]") { + return "*[]*models." + strings.TrimPrefix(strings.TrimPrefix(typeName, "*"), "[]") + } + return "*models." + strings.TrimPrefix(typeName, "*") + } + if strings.HasPrefix(typeName, "[]") { + return "[]*models." + strings.TrimPrefix(typeName, "[]") } return "*models." + typeName } diff --git a/graphql/ast/node.go b/graphql/ast/node.go index 9c8f5d7..6a8d91c 100644 --- a/graphql/ast/node.go +++ b/graphql/ast/node.go @@ -476,6 +476,36 @@ func (t *TypeRef) GetGoName() string { } } +func (t *TypeRef) IsList() bool { + if t.Kind == KindList { + return true + } + if t.Kind == KindNonNull { + return t.OfType.IsList() + } + return false +} + +func (t *TypeRef) IsScalar() bool { + if t.Kind == KindNonNull { + return t.OfType.IsScalar() + } + if t.Kind == KindList { + return t.OfType.IsScalar() + } + return t.Kind == KindScalar +} + +func (t *TypeRef) IsObject() bool { + if t.Kind == KindNonNull { + return t.OfType.IsObject() + } + if t.Kind == KindList { + return t.OfType.IsObject() + } + return t.Kind == KindObject +} + func (t *TypeRef) GetRealType() *TypeRef { if t.Kind == KindNonNull { return t.OfType.GetRealType() diff --git a/graphql/excute/excute.go b/graphql/excute/excute.go index c8e260c..013ff5c 100644 --- a/graphql/excute/excute.go +++ b/graphql/excute/excute.go @@ -7,7 +7,6 @@ import ( "github.com/light-speak/lighthouse/errors" "github.com/light-speak/lighthouse/graphql" "github.com/light-speak/lighthouse/graphql/ast" - "github.com/light-speak/lighthouse/graphql/model" "github.com/light-speak/lighthouse/graphql/parser" "github.com/light-speak/lighthouse/graphql/parser/lexer" ) @@ -93,47 +92,19 @@ func ExecuteQuery(ctx *context.Context, query string, variables map[string]any) continue } - if resolverFunc, ok := resolverMap[field.Name]; ok { - args := make(map[string]any) - for _, arg := range field.Args { - args[arg.Name] = arg.Value - } - r, e := resolverFunc(ctx, args) - if e != nil { - ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ - Message: e.Error(), - Locations: []*errors.GraphqlLocation{field.GetLocation()}, - }) - continue - } - - if modelData, ok := r.(model.ModelInterface); ok { - modelMap, err := model.StructToMap(modelData) - if err != nil { - ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ - Message: err.Error(), - Locations: []*errors.GraphqlLocation{field.GetLocation()}, - }) - continue - } - data := make(map[string]interface{}) - for _, child := range field.Children { - d, err := mergeData(child, modelMap) - if err != nil { - ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ - Message: err.Error(), - Locations: []*errors.GraphqlLocation{child.GetLocation()}, - }) - continue - } - data[child.Name] = d - } - res[field.Name] = data - continue - } + r, isResolver, err := executeResolver(ctx, field) + if err != nil { + ctx.Errors = append(ctx.Errors, err) + continue + } + if r != nil && isResolver { res[field.Name] = r continue } + if r == nil && isResolver { + res[field.Name] = nil + continue + } ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ Message: fmt.Sprintf("query %s not found", field.Name), diff --git a/graphql/excute/resolver.go b/graphql/excute/resolver.go new file mode 100644 index 0000000..0cde65c --- /dev/null +++ b/graphql/excute/resolver.go @@ -0,0 +1,168 @@ +package excute + +import ( + "github.com/light-speak/lighthouse/context" + "github.com/light-speak/lighthouse/errors" + "github.com/light-speak/lighthouse/graphql/ast" + "github.com/light-speak/lighthouse/graphql/model" +) + +func executeResolver(ctx *context.Context, field *ast.Field) (interface{}, bool, errors.GraphqlErrorInterface) { + if resolverFunc, ok := resolverMap[field.Name]; ok { + args := make(map[string]any) + for _, arg := range field.Args { + args[arg.Name] = arg.Value + } + r, e := resolverFunc(ctx, args) + if e != nil { + return nil, true, &errors.GraphQLError{ + Message: e.Error(), + Locations: []*errors.GraphqlLocation{field.GetLocation()}, + } + } + + if r == nil { + if field.Type.Kind == ast.KindNonNull { + return nil, true, &errors.GraphQLError{ + Message: "field is not nullable", + Locations: []*errors.GraphqlLocation{field.GetLocation()}, + } + } + return nil, true, nil + } + + if field.Type.IsScalar() { + return r, true, nil + } else { + columns, e := getColumns(field) + if e != nil { + return nil, true, &errors.GraphQLError{ + Message: e.Error(), + Locations: []*errors.GraphqlLocation{field.GetLocation()}, + } + } + realType := field.Type.GetRealType() + if field.Type.IsList() { + r, err := model.GetQuickList(realType.Name)(ctx, columns, r.([]map[string]interface{})) + if err != nil { + return nil, true, &errors.GraphQLError{ + Message: err.Error(), + Locations: []*errors.GraphqlLocation{field.GetLocation()}, + } + } + data := make([]map[string]interface{}, 0) + for _, ri := range r { + riData := make(map[string]interface{}) + for _, child := range field.Children { + v, err := mergeData(child, ri) + riData[child.Name] = v + if err != nil { + return nil, true, err + } + } + data = append(data, riData) + } + return data, true, nil + } else { + r, err := model.GetQuickFirst(realType.Name)(ctx, columns, r.(map[string]interface{})) + if err != nil { + return nil, true, &errors.GraphQLError{ + Message: err.Error(), + Locations: []*errors.GraphqlLocation{field.GetLocation()}, + } + } + data := make(map[string]interface{}) + for _, child := range field.Children { + v, err := mergeData(child, r) + data[child.Name] = v + if err != nil { + return nil, true, err + } + } + return data, true, nil + } + } + + } + return nil, false, nil +} + +// if resolverFunc, ok := resolverMap[field.Name]; ok { +// args := make(map[string]any) +// for _, arg := range field.Args { +// args[arg.Name] = arg.Value +// } +// r, e := resolverFunc(ctx, args) +// if e != nil { +// ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ +// Message: e.Error(), +// Locations: []*errors.GraphqlLocation{field.GetLocation()}, +// }) +// continue +// } + +// if r == nil { +// if field.Type.Kind == ast.KindNonNull { +// ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ +// Message: "field is not nullable", +// Locations: []*errors.GraphqlLocation{field.GetLocation()}, +// }) +// continue +// } +// res[field.Name] = nil +// continue +// } + +// if modelData, ok := r.(model.ModelInterface); ok { +// columns, e := getColumns(field) +// if e != nil { +// ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ +// Message: e.Error(), +// Locations: []*errors.GraphqlLocation{field.GetLocation()}, +// }) +// continue +// } +// modelMap, err := model.StructToMap(modelData) +// if err != nil { +// ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ +// Message: err.Error(), +// Locations: []*errors.GraphqlLocation{field.GetLocation()}, +// }) +// continue +// } +// isList := false + +// returnType := field.Type +// if field.Type.Kind == ast.KindNonNull { +// returnType = field.Type.OfType +// } +// if returnType.Kind == ast.KindList { +// isList = true +// returnType = returnType.OfType +// } + +// if returnType.Kind == ast.KindObject { +// if isList { +// model.GetQuickLoadList(returnType.Name)(ctx, modelMap) +// } else { +// model.GetQuickFirst(returnType.Name)(ctx, columns, modelMap) +// } +// } +// data := make(map[string]interface{}) +// for _, child := range field.Children { +// d, err := mergeData(child, modelMap) +// if err != nil { +// ctx.Errors = append(ctx.Errors, &errors.GraphQLError{ +// Message: err.Error(), +// Locations: []*errors.GraphqlLocation{child.GetLocation()}, +// }) +// continue +// } +// data[child.Name] = d +// } +// res[field.Name] = data +// continue +// } +// res[field.Name] = r +// continue +// } diff --git a/graphql/model/generate/tpl/operation_gen.tpl b/graphql/model/generate/tpl/operation_gen.tpl index ce0665e..1a46504 100644 --- a/graphql/model/generate/tpl/operation_gen.tpl +++ b/graphql/model/generate/tpl/operation_gen.tpl @@ -4,7 +4,7 @@ func init() { {{- range .Fields }} {{- if not (isInternalType .Name) }} {{- if eq (len .Directives) 0 }} -{{- $args := .Args }} + {{- $args := .Args }} excute.AddResolver("{{ .Name }}", func(ctx *context.Context, args map[string]any) (interface{}, error) { {{- range $index, $arg := $args }} @@ -15,21 +15,21 @@ func init() { } {{- else if eq $arg.Type.GetRealType.Kind "ENUM" }} - {{ $arg.Name | lcFirst }}, ok := models.{{ false | $arg.Type.GetGoType }}Map[args["{{ $arg.Name | lcFirst }}"].(string)] + {{ $arg.Name | lcFirst }}Value, ok := models.{{ false | $arg.Type.GetGoType }}Map[args["{{ $arg.Name | lcFirst }}"].(string)] if !ok { return nil, fmt.Errorf("argument: '{{ $arg.Name }}' is not a models.{{ false | $arg.Type.GetGoType }}, got %T", args["{{ $index }}"]) } + {{ $arg.Name | lcFirst }} := &{{ $arg.Name | lcFirst }}Value {{- else if eq $arg.Type.GetRealType.Kind "OBJECT" }} {{ $arg.Name | lcFirst }}, ok := args["{{ $index }}"].(models.{{ false | $arg.Type.GetGoType }}) if !ok { return nil, fmt.Errorf("argument: '{{ $arg.Name }}' is not a models.{{ false | $arg.Type.GetGoType }}, got %T", args["{{ $index }}"]) } {{- else if eq $arg.Type.GetRealType.Kind "INPUT_OBJECT" }} - {{ $arg.Name | lcFirst }}Ptr, err := models.MapTo{{ false | $arg.Type.GetGoType }}(args["{{ $index }}"].(map[string]interface{})) + {{ $arg.Name | lcFirst }}, err := models.MapTo{{ false | $arg.Type.GetGoType }}(args["{{ $index }}"].(map[string]interface{})) if err != nil { return nil, fmt.Errorf("argument: '{{ $arg.Name }}' is not a models.{{ false | $arg.Type.GetGoType }}, got %T", args["{{ $index }}"]) } - {{ $arg.Name | lcFirst }} := *{{ $arg.Name | lcFirst }}Ptr {{- else }} {{ $arg.Name | lcFirst }}, ok := args["{{ $index }}"].(models.{{ false | $arg.Type.GetGoType }}) if !ok { @@ -37,7 +37,38 @@ func init() { } {{- end }} {{- end }} - return {{ .Name | ucFirst }}Resolver(ctx{{ range $index, $arg := $args }}, {{ $arg.Name | lcFirst }}{{ end }}) + {{- if .Type.IsList }} + {{- if .Type.IsObject }} + list, err := {{ .Name | ucFirst }}Resolver(ctx{{ range $index, $arg := $args }}, {{ $arg.Name | lcFirst }}{{ end }}) + if list == nil { + return nil, err + } + res := []map[string]interface{}{} + for _, item := range list { + itemMap, err := model.StructToMap(item) + if err != nil { + return nil, err + } + res = append(res, itemMap) + } + return res, nil + {{- else }} + res, err := {{ .Name | ucFirst }}Resolver(ctx{{ range $index, $arg := $args }}, {{ $arg.Name | lcFirst }}{{ end }}) + if res == nil { + return nil, err + } + return res, nil + {{- end }} + {{- else if .Type.IsObject }} + res, err := {{ .Name | ucFirst }}Resolver(ctx{{ range $index, $arg := $args }}, {{ $arg.Name | lcFirst }}{{ end }}) + if res == nil { + return nil, err + } + return model.StructToMap(res) + {{- else }} + res, err := {{ .Name | ucFirst }}Resolver(ctx{{ range $index, $arg := $args }}, {{ $arg.Name | lcFirst }}{{ end }}) + return res, err + {{- end }} }) {{- end }} {{- end }} diff --git a/graphql/model/quick.go b/graphql/model/quick.go index b5882b1..e03c920 100644 --- a/graphql/model/quick.go +++ b/graphql/model/quick.go @@ -4,10 +4,10 @@ import ( "encoding/json" "fmt" + "github.com/light-speak/lighthouse/context" "github.com/light-speak/lighthouse/errors" "github.com/light-speak/lighthouse/graphql/ast" "github.com/light-speak/lighthouse/utils" - "github.com/light-speak/lighthouse/context" "gorm.io/gorm" ) diff --git a/graphql/scalar/id.go b/graphql/scalar/id.go index c37de5e..8850200 100644 --- a/graphql/scalar/id.go +++ b/graphql/scalar/id.go @@ -36,9 +36,13 @@ func (i *IDScalar) Serialize(v interface{}, location *errors.GraphqlLocation) (s switch v := v.(type) { case int64: return strconv.FormatInt(v, 10), nil + case int: + return strconv.FormatInt(int64(v), 10), nil + case float64: + return strconv.FormatInt(int64(v), 10), nil default: return "", &errors.GraphQLError{ - Message: fmt.Sprintf("value is not an integer: %v", v), + Message: fmt.Sprintf("value is not an integer: %v, got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } } @@ -48,9 +52,22 @@ func (i *IDScalar) ParseLiteral(v interface{}, location *errors.GraphqlLocation) switch v := v.(type) { case int64: return v, nil + case string: + intValue, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return nil, &errors.GraphQLError{ + Message: fmt.Sprintf("invalid integer value: %s, got %T", v, v), + Locations: []*errors.GraphqlLocation{location}, + } + } + return intValue, nil + case float64: + return int64(v), nil + case int: + return int64(v), nil } return nil, &errors.GraphQLError{ - Message: fmt.Sprintf("invalid literal for Int: %v", v), + Message: fmt.Sprintf("invalid literal for Int: %v, got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } } diff --git a/graphql/scalar/int.go b/graphql/scalar/int.go index aac3d81..598167a 100644 --- a/graphql/scalar/int.go +++ b/graphql/scalar/int.go @@ -36,9 +36,13 @@ func (i *IntScalar) Serialize(v interface{}, location *errors.GraphqlLocation) ( switch v := v.(type) { case int64: return strconv.FormatInt(v, 10), nil + case int: + return strconv.FormatInt(int64(v), 10), nil + case float64: + return strconv.FormatInt(int64(v), 10), nil default: return "", &errors.GraphQLError{ - Message: fmt.Sprintf("value is not an integer: %v", v), + Message: fmt.Sprintf("value is not an integer: %v, got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } } @@ -48,9 +52,22 @@ func (i *IntScalar) ParseLiteral(v interface{}, location *errors.GraphqlLocation switch v := v.(type) { case int64: return v, nil + case string: + intValue, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return nil, &errors.GraphQLError{ + Message: fmt.Sprintf("invalid integer value: %s, got %T", v, v), + Locations: []*errors.GraphqlLocation{location}, + } + } + return intValue, nil + case float64: + return int64(v), nil + case int: + return int64(v), nil } return nil, &errors.GraphQLError{ - Message: fmt.Sprintf("invalid literal for Int: %v", v), + Message: fmt.Sprintf("invalid literal for Int: %v, got %T", v, v), Locations: []*errors.GraphqlLocation{location}, } }