mirror of
https://github.com/zeromicro/go-zero.git
synced 2025-01-23 09:00:20 +08:00
gozero template (#147)
* model/rpc generate code from template cache * delete unused(deprecated) code * support template init|update|clean|revert * model: return the execute result for insert and update operation * // deprecated: containsAny * add template test * add default buildVersion * update build version
This commit is contained in:
parent
fe0d0687f5
commit
41964f9d52
@ -1,6 +1,8 @@
|
||||
package gogen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@ -27,3 +29,27 @@ var templates = map[string]string{
|
||||
func GenTemplates(_ *cli.Context) error {
|
||||
return util.InitTemplates(category, templates)
|
||||
}
|
||||
|
||||
func RevertTemplate(name string) error {
|
||||
content, ok := templates[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: no such file name", name)
|
||||
}
|
||||
return util.CreateTemplate(category, name, content)
|
||||
}
|
||||
|
||||
func Update(category string) error {
|
||||
err := Clean()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return util.InitTemplates(category, templates)
|
||||
}
|
||||
|
||||
func Clean() error {
|
||||
return util.Clean(category)
|
||||
}
|
||||
|
||||
func GetCategory() string {
|
||||
return category
|
||||
}
|
||||
|
92
tools/goctl/api/gogen/template_test.go
Normal file
92
tools/goctl/api/gogen/template_test.go
Normal file
@ -0,0 +1,92 @@
|
||||
package gogen
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
)
|
||||
|
||||
func TestGenTemplates(t *testing.T) {
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
file := filepath.Join(dir, "main.tpl")
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, string(data), mainTemplate)
|
||||
}
|
||||
|
||||
func TestRevertTemplate(t *testing.T) {
|
||||
name := "main.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
modifyData := string(data) + "modify"
|
||||
err = util.CreateTemplate(category, name, modifyData)
|
||||
assert.Nil(t, err)
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, string(data), modifyData)
|
||||
|
||||
assert.Nil(t, RevertTemplate(name))
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, mainTemplate, string(data))
|
||||
}
|
||||
|
||||
func TestClean(t *testing.T) {
|
||||
name := "main.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Nil(t, Clean())
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
_, err = ioutil.ReadFile(file)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
name := "main.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
modifyData := string(data) + "modify"
|
||||
err = util.CreateTemplate(category, name, modifyData)
|
||||
assert.Nil(t, err)
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, string(data), modifyData)
|
||||
|
||||
assert.Nil(t, Update(category))
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, mainTemplate, string(data))
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var feature = `
|
||||
1、增加goctl model支持
|
||||
`
|
||||
|
||||
func Feature(_ *cli.Context) error {
|
||||
fmt.Println(aurora.Blue("\nFEATURE:"))
|
||||
fmt.Println(aurora.Blue(feature))
|
||||
return nil
|
||||
}
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/tal-tech/go-zero/core/logx"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/api/apigen"
|
||||
@ -17,15 +18,15 @@ import (
|
||||
"github.com/tal-tech/go-zero/tools/goctl/api/validate"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/configgen"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/docker"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/feature"
|
||||
model "github.com/tal-tech/go-zero/tools/goctl/model/sql/command"
|
||||
rpc "github.com/tal-tech/go-zero/tools/goctl/rpc/command"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/tpl"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
BuildTime = "not set"
|
||||
commands = []cli.Command{
|
||||
BuildVersion = "20201021"
|
||||
commands = []cli.Command{
|
||||
{
|
||||
Name: "api",
|
||||
Usage: "generate api related files",
|
||||
@ -328,14 +329,46 @@ var (
|
||||
Action: configgen.GenConfigCommand,
|
||||
},
|
||||
{
|
||||
Name: "feature",
|
||||
Usage: "the features of the latest version",
|
||||
Action: feature.Feature,
|
||||
},
|
||||
{
|
||||
Name: "template",
|
||||
Usage: "initialize the api templates",
|
||||
Action: gogen.GenTemplates,
|
||||
Name: "template",
|
||||
Usage: "template operation",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "init",
|
||||
Usage: "initialize the all templates(force update)",
|
||||
Action: tpl.GenTemplates,
|
||||
},
|
||||
{
|
||||
Name: "clean",
|
||||
Usage: "clean the all cache templates",
|
||||
Action: tpl.CleanTemplates,
|
||||
},
|
||||
{
|
||||
Name: "update",
|
||||
Usage: "update template of the target category to the latest",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "category,c",
|
||||
Usage: "the category of template, enum [api,rpc,model]",
|
||||
},
|
||||
},
|
||||
Action: tpl.UpdateTemplates,
|
||||
},
|
||||
{
|
||||
Name: "revert",
|
||||
Usage: "revert the target template to the latest",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "category,c",
|
||||
Usage: "the category of template, enum [api,rpc,model]",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name,n",
|
||||
Usage: "the target file name of template",
|
||||
},
|
||||
},
|
||||
Action: tpl.RevertTemplates,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -345,7 +378,7 @@ func main() {
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Usage = "a cli tool to generate code"
|
||||
app.Version = BuildTime
|
||||
app.Version = fmt.Sprintf("%s %s/%s", BuildVersion, runtime.GOOS, runtime.GOARCH)
|
||||
app.Commands = commands
|
||||
// cli already print error messages
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
|
@ -1,5 +1,9 @@
|
||||
# Change log
|
||||
|
||||
## 2020-10-19
|
||||
|
||||
* 增加template
|
||||
|
||||
## 2020-08-20
|
||||
|
||||
* 新增支持通过连接数据库生成model
|
||||
|
20
tools/goctl/model/sql/converter/types_test.go
Normal file
20
tools/goctl/model/sql/converter/types_test.go
Normal file
@ -0,0 +1,20 @@
|
||||
package converter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConvertDataType(t *testing.T) {
|
||||
v, err := ConvertDataType("tinyint")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "int64", v)
|
||||
|
||||
v, err = ConvertDataType("timestamp")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "time.Time", v)
|
||||
|
||||
_, err = ConvertDataType("float32")
|
||||
assert.NotNil(t, err)
|
||||
}
|
@ -4,4 +4,4 @@
|
||||
goctl model mysql ddl -src="./sql/user.sql" -dir="./sql/model" -c
|
||||
|
||||
# generate model with cache from data source
|
||||
goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="table1,table2" -dir="./model"
|
||||
#goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="table1,table2" -dir="./model"
|
@ -22,8 +22,13 @@ func genDelete(table Table, withCache bool) (string, error) {
|
||||
}
|
||||
|
||||
camel := table.Name.ToCamel()
|
||||
text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("delete").
|
||||
Parse(template.Delete).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"upperStartCamelObject": camel,
|
||||
"withCache": withCache,
|
||||
|
@ -25,8 +25,14 @@ func genField(field parser.Field) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
text, err := util.LoadTemplate(category, fieldTemplateFile, template.Field)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("types").
|
||||
Parse(template.Field).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"name": field.Name.ToCamel(),
|
||||
"type": field.DataType,
|
||||
|
@ -8,8 +8,13 @@ import (
|
||||
|
||||
func genFindOne(table Table, withCache bool) (string, error) {
|
||||
camel := table.Name.ToCamel()
|
||||
text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("findOne").
|
||||
Parse(template.FindOne).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": camel,
|
||||
|
@ -10,7 +10,12 @@ import (
|
||||
)
|
||||
|
||||
func genFindOneByField(table Table, withCache bool) (string, string, error) {
|
||||
t := util.With("findOneByField").Parse(template.FindOneByField)
|
||||
text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
t := util.With("findOneByField").Parse(text)
|
||||
var list []string
|
||||
camelTableName := table.Name.ToCamel()
|
||||
for _, field := range table.Fields {
|
||||
@ -33,10 +38,16 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
list = append(list, output.String())
|
||||
}
|
||||
if withCache {
|
||||
out, err := util.With("findOneByFieldExtraMethod").Parse(template.FindOneByFieldExtraMethod).Execute(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{
|
||||
"upperStartCamelObject": camelTableName,
|
||||
"primaryKeyLeft": table.CacheKey[table.PrimaryKey.Name.Source()].Left,
|
||||
"lowerStartCamelObject": stringx.From(camelTableName).UnTitle(),
|
||||
@ -45,6 +56,7 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return strings.Join(list, "\n"), out.String(), nil
|
||||
}
|
||||
return strings.Join(list, "\n"), "", nil
|
||||
|
@ -7,20 +7,32 @@ import (
|
||||
|
||||
func genImports(withCache, timeImport bool) (string, error) {
|
||||
if withCache {
|
||||
buffer, err := util.With("import").Parse(template.Imports).Execute(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, importsTemplateFile, template.Imports)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buffer, err := util.With("import").Parse(text).Execute(map[string]interface{}{
|
||||
"time": timeImport,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buffer.String(), nil
|
||||
} else {
|
||||
buffer, err := util.With("import").Parse(template.ImportsNoCache).Execute(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, importsWithNoCacheTemplateFile, template.ImportsNoCache)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buffer, err := util.With("import").Parse(text).Execute(map[string]interface{}{
|
||||
"time": timeImport,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buffer.String(), nil
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,13 @@ func genInsert(table Table, withCache bool) (string, error) {
|
||||
expressionValues = append(expressionValues, "data."+camel)
|
||||
}
|
||||
camel := table.Name.ToCamel()
|
||||
text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("insert").
|
||||
Parse(template.Insert).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"containsIndexCache": table.ContainsUniqueKey,
|
||||
@ -49,5 +54,6 @@ func genInsert(table Table, withCache bool) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return output.String(), nil
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ type (
|
||||
// {{prefix}}=cache
|
||||
// key:id
|
||||
Key struct {
|
||||
VarExpression string // cacheUserIdPrefix="cache#user#id#"
|
||||
VarExpression string // cacheUserIdPrefix = "cache#User#id#"
|
||||
Left string // cacheUserIdPrefix
|
||||
Right string // cache#user#id#
|
||||
Variable string // userIdKey
|
||||
|
77
tools/goctl/model/sql/gen/keys_test.go
Normal file
77
tools/goctl/model/sql/gen/keys_test.go
Normal file
@ -0,0 +1,77 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||
)
|
||||
|
||||
func TestGenCacheKeys(t *testing.T) {
|
||||
m, err := genCacheKeys(parser.Table{
|
||||
Name: stringx.From("user"),
|
||||
PrimaryKey: parser.Primary{
|
||||
Field: parser.Field{
|
||||
Name: stringx.From("id"),
|
||||
DataBaseType: "bigint",
|
||||
DataType: "int64",
|
||||
IsKey: false,
|
||||
IsPrimaryKey: true,
|
||||
IsUniqueKey: false,
|
||||
Comment: "自增id",
|
||||
},
|
||||
AutoIncrement: true,
|
||||
},
|
||||
Fields: []parser.Field{
|
||||
{
|
||||
Name: stringx.From("mobile"),
|
||||
DataBaseType: "varchar",
|
||||
DataType: "string",
|
||||
IsKey: false,
|
||||
IsPrimaryKey: false,
|
||||
IsUniqueKey: true,
|
||||
Comment: "手机号",
|
||||
},
|
||||
{
|
||||
Name: stringx.From("name"),
|
||||
DataBaseType: "varchar",
|
||||
DataType: "string",
|
||||
IsKey: false,
|
||||
IsPrimaryKey: false,
|
||||
IsUniqueKey: true,
|
||||
Comment: "姓名",
|
||||
},
|
||||
{
|
||||
Name: stringx.From("createTime"),
|
||||
DataBaseType: "timestamp",
|
||||
DataType: "time.Time",
|
||||
IsKey: false,
|
||||
IsPrimaryKey: false,
|
||||
IsUniqueKey: false,
|
||||
Comment: "创建时间",
|
||||
},
|
||||
{
|
||||
Name: stringx.From("updateTime"),
|
||||
DataBaseType: "timestamp",
|
||||
DataType: "time.Time",
|
||||
IsKey: false,
|
||||
IsPrimaryKey: false,
|
||||
IsUniqueKey: false,
|
||||
Comment: "更新时间",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
for fieldName, key := range m {
|
||||
name := stringx.From(fieldName)
|
||||
assert.Equal(t, fmt.Sprintf(`cacheUser%sPrefix = "cache#User#%s#"`, name.ToCamel(), name.UnTitle()), key.VarExpression)
|
||||
assert.Equal(t, fmt.Sprintf(`cacheUser%sPrefix`, name.ToCamel()), key.Left)
|
||||
assert.Equal(t, fmt.Sprintf(`cache#User#%s#`, name.UnTitle()), key.Right)
|
||||
assert.Equal(t, fmt.Sprintf(`user%sKey`, name.ToCamel()), key.Variable)
|
||||
assert.Equal(t, `user`+name.ToCamel()+`Key := fmt.Sprintf("%s%v", cacheUser`+name.ToCamel()+`Prefix,`+name.UnTitle()+`)`, key.KeyExpression)
|
||||
}
|
||||
|
||||
}
|
@ -6,8 +6,13 @@ import (
|
||||
)
|
||||
|
||||
func genNew(table Table, withCache bool) (string, error) {
|
||||
text, err := util.LoadTemplate(category, modelNewTemplateFile, template.New)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("new").
|
||||
Parse(template.New).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": table.Name.ToCamel(),
|
||||
@ -15,5 +20,6 @@ func genNew(table Table, withCache bool) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return output.String(), nil
|
||||
}
|
||||
|
@ -9,8 +9,13 @@ func genTag(in string) (string, error) {
|
||||
if in == "" {
|
||||
return in, nil
|
||||
}
|
||||
text, err := util.LoadTemplate(category, tagTemplateFile, template.Tag)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("tag").
|
||||
Parse(template.Tag).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"field": in,
|
||||
})
|
||||
|
72
tools/goctl/model/sql/gen/template.go
Normal file
72
tools/goctl/model/sql/gen/template.go
Normal file
@ -0,0 +1,72 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
category = "model"
|
||||
deleteTemplateFile = "delete.tpl"
|
||||
fieldTemplateFile = "filed.tpl"
|
||||
findOneTemplateFile = "find-one.tpl"
|
||||
findOneByFieldTemplateFile = "find-one-by-field.tpl"
|
||||
findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl"
|
||||
importsTemplateFile = "import.tpl"
|
||||
importsWithNoCacheTemplateFile = "import-no-cache.tpl"
|
||||
insertTemplateFile = "insert.tpl"
|
||||
modelTemplateFile = "model.tpl"
|
||||
modelNewTemplateFile = "model-new.tpl"
|
||||
tagTemplateFile = "tag.tpl"
|
||||
typesTemplateFile = "types.tpl"
|
||||
updateTemplateFile = "update.tpl"
|
||||
varTemplateFile = "var.tpl"
|
||||
)
|
||||
|
||||
var templates = map[string]string{
|
||||
deleteTemplateFile: template.Delete,
|
||||
fieldTemplateFile: template.Field,
|
||||
findOneTemplateFile: template.FindOne,
|
||||
findOneByFieldTemplateFile: template.FindOneByField,
|
||||
findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod,
|
||||
importsTemplateFile: template.Imports,
|
||||
importsWithNoCacheTemplateFile: template.ImportsNoCache,
|
||||
insertTemplateFile: template.Insert,
|
||||
modelTemplateFile: template.Model,
|
||||
modelNewTemplateFile: template.New,
|
||||
tagTemplateFile: template.Tag,
|
||||
typesTemplateFile: template.Types,
|
||||
updateTemplateFile: template.Update,
|
||||
varTemplateFile: template.Vars,
|
||||
}
|
||||
|
||||
func GenTemplates(_ *cli.Context) error {
|
||||
return util.InitTemplates(category, templates)
|
||||
}
|
||||
|
||||
func RevertTemplate(name string) error {
|
||||
content, ok := templates[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: no such file name", name)
|
||||
}
|
||||
return util.CreateTemplate(category, name, content)
|
||||
}
|
||||
|
||||
func Clean() error {
|
||||
return util.Clean(category)
|
||||
}
|
||||
|
||||
func Update(category string) error {
|
||||
err := Clean()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return util.InitTemplates(category, templates)
|
||||
}
|
||||
|
||||
func GetCategory() string {
|
||||
return category
|
||||
}
|
93
tools/goctl/model/sql/gen/template_test.go
Normal file
93
tools/goctl/model/sql/gen/template_test.go
Normal file
@ -0,0 +1,93 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
)
|
||||
|
||||
func TestGenTemplates(t *testing.T) {
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
file := filepath.Join(dir, "model-new.tpl")
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, string(data), template.New)
|
||||
}
|
||||
|
||||
func TestRevertTemplate(t *testing.T) {
|
||||
name := "model-new.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
modifyData := string(data) + "modify"
|
||||
err = util.CreateTemplate(category, name, modifyData)
|
||||
assert.Nil(t, err)
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, string(data), modifyData)
|
||||
|
||||
assert.Nil(t, RevertTemplate(name))
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, template.New, string(data))
|
||||
}
|
||||
|
||||
func TestClean(t *testing.T) {
|
||||
name := "model-new.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Nil(t, Clean())
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
_, err = ioutil.ReadFile(file)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
name := "model-new.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
modifyData := string(data) + "modify"
|
||||
err = util.CreateTemplate(category, name, modifyData)
|
||||
assert.Nil(t, err)
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, string(data), modifyData)
|
||||
|
||||
assert.Nil(t, Update(category))
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, template.New, string(data))
|
||||
}
|
@ -11,8 +11,14 @@ func genTypes(table Table, withCache bool) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
text, err := util.LoadTemplate(category, typesTemplateFile, template.Types)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("types").
|
||||
Parse(template.Types).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": table.Name.ToCamel(),
|
||||
@ -21,5 +27,6 @@ func genTypes(table Table, withCache bool) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return output.String(), nil
|
||||
}
|
||||
|
@ -22,8 +22,13 @@ func genUpdate(table Table, withCache bool) (string, error) {
|
||||
}
|
||||
expressionValues = append(expressionValues, "data."+table.PrimaryKey.Name.ToCamel())
|
||||
camelTableName := table.Name.ToCamel()
|
||||
text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("update").
|
||||
Parse(template.Update).
|
||||
Parse(text).
|
||||
Execute(map[string]interface{}{
|
||||
"withCache": withCache,
|
||||
"upperStartCamelObject": camelTableName,
|
||||
@ -36,5 +41,6 @@ func genUpdate(table Table, withCache bool) (string, error) {
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return output.String(), nil
|
||||
}
|
||||
|
@ -14,8 +14,13 @@ func genVars(table Table, withCache bool) (string, error) {
|
||||
keys = append(keys, v.VarExpression)
|
||||
}
|
||||
camel := table.Name.ToCamel()
|
||||
text, err := util.LoadTemplate(category, varTemplateFile, template.Vars)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
output, err := util.With("var").
|
||||
Parse(template.Vars).
|
||||
Parse(text).
|
||||
GoFmt(true).
|
||||
Execute(map[string]interface{}{
|
||||
"lowerStartCamelObject": stringx.From(camel).UnTitle(),
|
||||
|
@ -17,11 +17,9 @@ func TestParseSelect(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseCreateTable(t *testing.T) {
|
||||
_, err := Parse("CREATE TABLE `user_snake` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;")
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestParseCreateTable2(t *testing.T) {
|
||||
_, err := Parse("create table `user_snake` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;")
|
||||
table, err := Parse("CREATE TABLE `user_snake` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "user_snake", table.Name.Source())
|
||||
assert.Equal(t, "id", table.PrimaryKey.Name.Source())
|
||||
assert.Equal(t, true, table.ContainsTime())
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ var (
|
||||
)
|
||||
`
|
||||
ImportsNoCache = `import (
|
||||
"database/sql"
|
||||
"strings"
|
||||
{{if .time}}"time"{{end}}
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
package template
|
||||
|
||||
var Insert = `
|
||||
func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) error {
|
||||
func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
|
||||
{{if .withCache}}{{if .containsIndexCache}}{{.keys}}
|
||||
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := ` + "`" + `insert into ` + "`" + ` + m.table + ` + "` (` + " + `{{.lowerStartCamelObject}}RowsExpectAutoSet` + " + `) values ({{.expression}})` " + `
|
||||
return conn.Exec(query, {{.expressionValues}})
|
||||
}, {{.keyValues}}){{else}}query := ` + "`" + `insert into ` + "`" + ` + m.table + ` + "` (` + " + `{{.lowerStartCamelObject}}RowsExpectAutoSet` + " + `) values ({{.expression}})` " + `
|
||||
_,err:=m.ExecNoCache(query, {{.expressionValues}})
|
||||
ret,err:=m.ExecNoCache(query, {{.expressionValues}})
|
||||
{{end}}{{else}}query := ` + "`" + `insert into ` + "`" + ` + m.table + ` + "` (` + " + `{{.lowerStartCamelObject}}RowsExpectAutoSet` + " + `) values ({{.expression}})` " + `
|
||||
_,err:=m.conn.Exec(query, {{.expressionValues}}){{end}}
|
||||
return err
|
||||
ret,err:=m.conn.Exec(query, {{.expressionValues}}){{end}}
|
||||
return ret,err
|
||||
}
|
||||
`
|
||||
|
@ -1,13 +1,13 @@
|
||||
package template
|
||||
|
||||
var Update = `
|
||||
func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
|
||||
func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) (sql.Result,error) {
|
||||
{{if .withCache}}{{.primaryCacheKey}}
|
||||
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := ` + "`" + `update ` + "` +" + `m.table +` + "` " + `set ` + "` +" + `{{.lowerStartCamelObject}}RowsWithPlaceHolder` + " + `" + ` where {{.originalPrimaryKey}} = ?` + "`" + `
|
||||
return conn.Exec(query, {{.expressionValues}})
|
||||
}, {{.primaryKeyVariable}}){{else}}query := ` + "`" + `update ` + "` +" + `m.table +` + "` " + `set ` + "` +" + `{{.lowerStartCamelObject}}RowsWithPlaceHolder` + " + `" + ` where {{.originalPrimaryKey}} = ?` + "`" + `
|
||||
_,err:=m.conn.Exec(query, {{.expressionValues}}){{end}}
|
||||
return err
|
||||
ret,err:=m.conn.Exec(query, {{.expressionValues}}){{end}}
|
||||
return ret,err
|
||||
}
|
||||
`
|
||||
|
@ -1,5 +1,9 @@
|
||||
# Change log
|
||||
|
||||
## 2020-10-19
|
||||
|
||||
* 增加template
|
||||
|
||||
## 2020-09-10
|
||||
|
||||
* rpc greet服务一键生成
|
||||
|
@ -32,7 +32,7 @@ func NewDefaultRpcGenerator(ctx *ctx.RpcContext) *defaultRpcGenerator {
|
||||
}
|
||||
|
||||
func (g *defaultRpcGenerator) Generate() (err error) {
|
||||
g.Ctx.Info(aurora.Blue("-> goctl rpc reference documents: ").String() + "「https://github.com/tal-tech/go-zero/blob/master/doc/goctl-rpc.md」")
|
||||
g.Ctx.Info(aurora.Blue("-> goctl rpc reference documents: ").String() + "「https://github.com/tal-tech/zero-doc/blob/main/doc/goctl-rpc.md」")
|
||||
g.Ctx.Warning("-> generating rpc code ...")
|
||||
defer func() {
|
||||
if err == nil {
|
||||
|
@ -123,7 +123,11 @@ func (g *defaultRpcGenerator) genCall() error {
|
||||
|
||||
filename := filepath.Join(callPath, typesFilename)
|
||||
head := util.GetHead(g.Ctx.ProtoSource)
|
||||
err = util.With("types").GoFmt(true).Parse(callTemplateTypes).SaveTo(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, callTypesTemplateFile, callTemplateTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = util.With("types").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||
"head": head,
|
||||
"const": constLit,
|
||||
"filePackage": service.Name.Lower(),
|
||||
@ -145,8 +149,11 @@ func (g *defaultRpcGenerator) genCall() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = util.With("shared").GoFmt(true).Parse(callTemplateText).SaveTo(map[string]interface{}{
|
||||
text, err = util.LoadTemplate(category, callTemplateFile, callTemplateText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||
"name": service.Name.Lower(),
|
||||
"head": head,
|
||||
"filePackage": service.Name.Lower(),
|
||||
@ -166,7 +173,11 @@ func (g *defaultRpcGenerator) genFunction(service *parser.RpcService) ([]string,
|
||||
imports.AddStr(fmt.Sprintf(`%v "%v"`, pkgName, g.mustGetPackage(dirPb)))
|
||||
for _, method := range service.Funcs {
|
||||
imports.AddStr(g.ast.Imports[method.ParameterIn.Package])
|
||||
buffer, err := util.With("sharedFn").Parse(callFunctionTemplate).Execute(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, callFunctionTemplateFile, callFunctionTemplate)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
buffer, err := util.With("sharedFn").Parse(text).Execute(map[string]interface{}{
|
||||
"rpcServiceName": service.Name.Title(),
|
||||
"method": method.Name.Title(),
|
||||
"package": pkgName,
|
||||
@ -189,7 +200,12 @@ func (g *defaultRpcGenerator) getInterfaceFuncs(service *parser.RpcService) ([]s
|
||||
functions := make([]string, 0)
|
||||
|
||||
for _, method := range service.Funcs {
|
||||
buffer, err := util.With("interfaceFn").Parse(callInterfaceFunctionTemplate).Execute(
|
||||
text, err := util.LoadTemplate(category, callInterfaceFunctionTemplateFile, callInterfaceFunctionTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buffer, err := util.With("interfaceFn").Parse(text).Execute(
|
||||
map[string]interface{}{
|
||||
"hasComment": method.HaveDoc(),
|
||||
"comment": method.GetDoc(),
|
||||
|
@ -23,5 +23,11 @@ func (g *defaultRpcGenerator) genConfig() error {
|
||||
if util.FileExists(fileName) {
|
||||
return nil
|
||||
}
|
||||
return ioutil.WriteFile(fileName, []byte(configTemplate), os.ModePerm)
|
||||
|
||||
text, err := util.LoadTemplate(category, configTemplateFileFile, configTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(fileName, []byte(text), os.ModePerm)
|
||||
}
|
||||
|
@ -22,7 +22,12 @@ func (g *defaultRpcGenerator) genEtc() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return util.With("etc").Parse(etcTemplate).SaveTo(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, etcTemplateFileFile, etcTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return util.With("etc").Parse(text).SaveTo(map[string]interface{}{
|
||||
"serviceName": g.Ctx.ServiceName.Lower(),
|
||||
}, fileName, false)
|
||||
}
|
||||
|
@ -61,7 +61,11 @@ func (g *defaultRpcGenerator) genLogic() error {
|
||||
svcImport := fmt.Sprintf(`"%v"`, g.mustGetPackage(dirSvc))
|
||||
imports.AddStr(svcImport)
|
||||
imports.AddStr(importList...)
|
||||
err = util.With("logic").GoFmt(true).Parse(logicTemplate).SaveTo(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, logicTemplateFileFile, logicTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = util.With("logic").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||
"logicName": fmt.Sprintf("%sLogic", method.Name.Title()),
|
||||
"functions": functions,
|
||||
"imports": strings.Join(imports.KeysStr(), util.NL),
|
||||
@ -82,7 +86,12 @@ func (g *defaultRpcGenerator) genLogicFunction(packageName string, method *parse
|
||||
}
|
||||
imports.AddStr(g.ast.Imports[method.ParameterIn.Package])
|
||||
imports.AddStr(g.ast.Imports[method.ParameterOut.Package])
|
||||
buffer, err := util.With("fun").Parse(logicFunctionTemplate).Execute(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, logicFuncTemplateFileFile, logicFunctionTemplate)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
buffer, err := util.With("fun").Parse(text).Execute(map[string]interface{}{
|
||||
"logicName": fmt.Sprintf("%sLogic", method.Name.Title()),
|
||||
"method": method.Name.Title(),
|
||||
"request": method.ParameterIn.StarExpression,
|
||||
@ -94,6 +103,7 @@ func (g *defaultRpcGenerator) genLogicFunction(packageName string, method *parse
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
functions = append(functions, buffer.String())
|
||||
return strings.Join(functions, util.NL), imports.KeysStr(), nil
|
||||
}
|
||||
|
@ -58,7 +58,12 @@ func (g *defaultRpcGenerator) genMain() error {
|
||||
imports = append(imports, configImport, pbImport, remoteImport, svcImport)
|
||||
srv, registers := g.genServer(pkg, file.Service)
|
||||
head := util.GetHead(g.Ctx.ProtoSource)
|
||||
return util.With("main").GoFmt(true).Parse(mainTemplate).SaveTo(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, mainTemplateFile, mainTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return util.With("main").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||
"head": head,
|
||||
"package": pkg,
|
||||
"serviceName": g.Ctx.ServiceName.Lower(),
|
||||
|
@ -18,6 +18,7 @@ const (
|
||||
|
||||
func (g *defaultRpcGenerator) genPb() error {
|
||||
pbPath := g.dirM[dirPb]
|
||||
// deprecated: containsAny will be removed in the feature
|
||||
imports, containsAny, err := parser.ParseImport(g.Ctx.ProtoFileSrc)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -59,8 +59,14 @@ func (g *defaultRpcGenerator) genHandler() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imports.AddStr(importList...)
|
||||
err = util.With("server").GoFmt(true).Parse(serverTemplate).SaveTo(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, serverTemplateFile, serverTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = util.With("server").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||
"head": head,
|
||||
"types": fmt.Sprintf(typeFmt, service.Name.Title()),
|
||||
"server": service.Name.Title(),
|
||||
@ -85,7 +91,12 @@ func (g *defaultRpcGenerator) genFunctions(service *parser.RpcService) ([]string
|
||||
}
|
||||
imports.AddStr(g.ast.Imports[method.ParameterIn.Package])
|
||||
imports.AddStr(g.ast.Imports[method.ParameterOut.Package])
|
||||
buffer, err := util.With("func").Parse(functionTemplate).Execute(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, serverFuncTemplateFile, functionTemplate)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
buffer, err := util.With("func").Parse(text).Execute(map[string]interface{}{
|
||||
"server": service.Name.Title(),
|
||||
"logicName": fmt.Sprintf("%sLogic", method.Name.Title()),
|
||||
"method": method.Name.Title(),
|
||||
@ -98,6 +109,7 @@ func (g *defaultRpcGenerator) genFunctions(service *parser.RpcService) ([]string
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
functionList = append(functionList, buffer.String())
|
||||
}
|
||||
return functionList, imports.KeysStr(), nil
|
||||
|
@ -25,7 +25,12 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
func (g *defaultRpcGenerator) genSvc() error {
|
||||
svcPath := g.dirM[dirSvc]
|
||||
fileName := filepath.Join(svcPath, fileServiceContext)
|
||||
return util.With("svc").GoFmt(true).Parse(svcTemplate).SaveTo(map[string]interface{}{
|
||||
text, err := util.LoadTemplate(category, svcTemplateFile, svcTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return util.With("svc").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||
"imports": fmt.Sprintf(`"%v"`, g.mustGetPackage(dirConfig)),
|
||||
}, fileName, false)
|
||||
}
|
||||
|
59
tools/goctl/rpc/gen/rpctemplate.go
Normal file
59
tools/goctl/rpc/gen/rpctemplate.go
Normal file
@ -0,0 +1,59 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||
)
|
||||
|
||||
const rpcTemplateText = `syntax = "proto3";
|
||||
|
||||
package {{.package}};
|
||||
|
||||
message Request {
|
||||
string ping = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
string pong = 1;
|
||||
}
|
||||
|
||||
service {{.serviceName}} {
|
||||
rpc Ping(Request) returns(Response);
|
||||
}
|
||||
`
|
||||
|
||||
type rpcTemplate struct {
|
||||
out string
|
||||
console.Console
|
||||
}
|
||||
|
||||
func NewRpcTemplate(out string, idea bool) *rpcTemplate {
|
||||
return &rpcTemplate{
|
||||
out: out,
|
||||
Console: console.NewConsole(idea),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rpcTemplate) MustGenerate(showState bool) {
|
||||
r.Info(aurora.Blue("-> goctl rpc reference documents: ").String() + "「https://github.com/tal-tech/zero-doc/blob/main/doc/goctl-rpc.md」")
|
||||
r.Info("-> generating template...")
|
||||
protoFilename := filepath.Base(r.out)
|
||||
serviceName := stringx.From(strings.TrimSuffix(protoFilename, filepath.Ext(protoFilename)))
|
||||
text, err := util.LoadTemplate(category, rpcTemplateFile, rpcTemplateText)
|
||||
r.Must(err)
|
||||
|
||||
err = util.With("t").Parse(text).SaveTo(map[string]string{
|
||||
"package": serviceName.UnTitle(),
|
||||
"serviceName": serviceName.Title(),
|
||||
}, r.out, false)
|
||||
r.Must(err)
|
||||
|
||||
if showState {
|
||||
r.Success("Done.")
|
||||
}
|
||||
}
|
@ -1,54 +1,69 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"fmt"
|
||||
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const rpcTemplateText = `syntax = "proto3";
|
||||
const (
|
||||
category = "rpc"
|
||||
callTemplateFile = "call.tpl"
|
||||
callTypesTemplateFile = "call-types.tpl"
|
||||
callInterfaceFunctionTemplateFile = "call-interface-func.tpl"
|
||||
callFunctionTemplateFile = "call-func.tpl"
|
||||
configTemplateFileFile = "config.tpl"
|
||||
etcTemplateFileFile = "etc.tpl"
|
||||
logicTemplateFileFile = "logic.tpl"
|
||||
logicFuncTemplateFileFile = "logic-func.tpl"
|
||||
mainTemplateFile = "main.tpl"
|
||||
serverTemplateFile = "server.tpl"
|
||||
serverFuncTemplateFile = "server-func.tpl"
|
||||
svcTemplateFile = "svc.tpl"
|
||||
rpcTemplateFile = "template.tpl"
|
||||
)
|
||||
|
||||
package {{.package}};
|
||||
|
||||
message Request {
|
||||
string ping = 1;
|
||||
var templates = map[string]string{
|
||||
callTemplateFile: callTemplateText,
|
||||
callTypesTemplateFile: callTemplateTypes,
|
||||
callInterfaceFunctionTemplateFile: callInterfaceFunctionTemplate,
|
||||
callFunctionTemplateFile: callFunctionTemplate,
|
||||
configTemplateFileFile: configTemplate,
|
||||
etcTemplateFileFile: etcTemplate,
|
||||
logicTemplateFileFile: logicTemplate,
|
||||
logicFuncTemplateFileFile: logicFunctionTemplate,
|
||||
mainTemplateFile: mainTemplate,
|
||||
serverTemplateFile: serverTemplate,
|
||||
serverFuncTemplateFile: functionTemplate,
|
||||
svcTemplateFile: svcTemplate,
|
||||
rpcTemplateFile: rpcTemplateText,
|
||||
}
|
||||
|
||||
message Response {
|
||||
string pong = 1;
|
||||
func GenTemplates(_ *cli.Context) error {
|
||||
return util.InitTemplates(category, templates)
|
||||
}
|
||||
|
||||
service {{.serviceName}} {
|
||||
rpc Ping(Request) returns(Response);
|
||||
}
|
||||
`
|
||||
|
||||
type rpcTemplate struct {
|
||||
out string
|
||||
console.Console
|
||||
}
|
||||
|
||||
func NewRpcTemplate(out string, idea bool) *rpcTemplate {
|
||||
return &rpcTemplate{
|
||||
out: out,
|
||||
Console: console.NewConsole(idea),
|
||||
func RevertTemplate(name string) error {
|
||||
content, ok := templates[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: no such file name", name)
|
||||
}
|
||||
return util.CreateTemplate(category, name, content)
|
||||
}
|
||||
|
||||
func (r *rpcTemplate) MustGenerate(showState bool) {
|
||||
r.Info("查看rpc生成请移步至「https://github.com/tal-tech/zero-doc/blob/main/doc/goctl-rpc.md」")
|
||||
r.Info("generating template...")
|
||||
protoFilename := filepath.Base(r.out)
|
||||
serviceName := stringx.From(strings.TrimSuffix(protoFilename, filepath.Ext(protoFilename)))
|
||||
err := util.With("t").Parse(rpcTemplateText).SaveTo(map[string]string{
|
||||
"package": serviceName.UnTitle(),
|
||||
"serviceName": serviceName.Title(),
|
||||
}, r.out, false)
|
||||
r.Must(err)
|
||||
if showState {
|
||||
r.Success("Done.")
|
||||
}
|
||||
func Clean() error {
|
||||
return util.Clean(category)
|
||||
}
|
||||
|
||||
func Update(category string) error {
|
||||
err := Clean()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return util.InitTemplates(category, templates)
|
||||
}
|
||||
|
||||
func GetCategory() string {
|
||||
return category
|
||||
}
|
||||
|
92
tools/goctl/rpc/gen/template_test.go
Normal file
92
tools/goctl/rpc/gen/template_test.go
Normal file
@ -0,0 +1,92 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
)
|
||||
|
||||
func TestGenTemplates(t *testing.T) {
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
file := filepath.Join(dir, "main.tpl")
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, string(data), mainTemplate)
|
||||
}
|
||||
|
||||
func TestRevertTemplate(t *testing.T) {
|
||||
name := "main.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
modifyData := string(data) + "modify"
|
||||
err = util.CreateTemplate(category, name, modifyData)
|
||||
assert.Nil(t, err)
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, string(data), modifyData)
|
||||
|
||||
assert.Nil(t, RevertTemplate(name))
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, mainTemplate, string(data))
|
||||
}
|
||||
|
||||
func TestClean(t *testing.T) {
|
||||
name := "main.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Nil(t, Clean())
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
_, err = ioutil.ReadFile(file)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
name := "main.tpl"
|
||||
err := util.InitTemplates(category, templates)
|
||||
assert.Nil(t, err)
|
||||
|
||||
dir, err := util.GetTemplateDir(category)
|
||||
assert.Nil(t, err)
|
||||
|
||||
file := filepath.Join(dir, name)
|
||||
data, err := ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
modifyData := string(data) + "modify"
|
||||
err = util.CreateTemplate(category, name, modifyData)
|
||||
assert.Nil(t, err)
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, string(data), modifyData)
|
||||
|
||||
assert.Nil(t, Update(category))
|
||||
|
||||
data, err = ioutil.ReadFile(file)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, mainTemplate, string(data))
|
||||
}
|
@ -97,6 +97,7 @@ type (
|
||||
}
|
||||
// parsing for rpc
|
||||
PbAst struct {
|
||||
// deprecated: containsAny will be removed in the feature
|
||||
ContainsAny bool
|
||||
Imports map[string]string
|
||||
Structure map[string]*Struct
|
||||
|
@ -47,9 +47,10 @@ type (
|
||||
}
|
||||
|
||||
Proto struct {
|
||||
Package string
|
||||
Import []*Import
|
||||
PbSrc string
|
||||
Package string
|
||||
Import []*Import
|
||||
PbSrc string
|
||||
// deprecated: containsAny will be removed in the feature
|
||||
ContainsAny bool
|
||||
Message map[string]lang.PlaceholderType
|
||||
Enum map[string]*Enum
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/tal-tech/go-zero/core/errorx"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/api/gogen"
|
||||
modelgen "github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
||||
rpcgen "github.com/tal-tech/go-zero/tools/goctl/rpc/gen"
|
||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@ -17,6 +19,12 @@ func GenTemplates(ctx *cli.Context) error {
|
||||
func() error {
|
||||
return gogen.GenTemplates(ctx)
|
||||
},
|
||||
func() error {
|
||||
return modelgen.GenTemplates(ctx)
|
||||
},
|
||||
func() error {
|
||||
return rpcgen.GenTemplates(ctx)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -31,3 +39,64 @@ func GenTemplates(ctx *cli.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CleanTemplates(_ *cli.Context) error {
|
||||
err := errorx.Chain(
|
||||
func() error {
|
||||
return gogen.Clean()
|
||||
},
|
||||
func() error {
|
||||
return modelgen.Clean()
|
||||
},
|
||||
func() error {
|
||||
return rpcgen.Clean()
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", aurora.Green("template are clean!"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateTemplates(ctx *cli.Context) (err error) {
|
||||
category := ctx.String("category")
|
||||
defer func() {
|
||||
if err == nil {
|
||||
fmt.Println(aurora.Green(fmt.Sprintf("%s template are update!", category)).String())
|
||||
}
|
||||
}()
|
||||
switch category {
|
||||
case gogen.GetCategory():
|
||||
return gogen.Update(category)
|
||||
case rpcgen.GetCategory():
|
||||
return rpcgen.Update(category)
|
||||
case modelgen.GetCategory():
|
||||
return modelgen.Update(category)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected category: %s", category)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func RevertTemplates(ctx *cli.Context) (err error) {
|
||||
category := ctx.String("category")
|
||||
filename := ctx.String("name")
|
||||
defer func() {
|
||||
if err == nil {
|
||||
fmt.Println(aurora.Green(fmt.Sprintf("%s template are reverted!", filename)).String())
|
||||
}
|
||||
}()
|
||||
switch category {
|
||||
case gogen.GetCategory():
|
||||
return gogen.RevertTemplate(filename)
|
||||
case rpcgen.GetCategory():
|
||||
return rpcgen.RevertTemplate(filename)
|
||||
case modelgen.GetCategory():
|
||||
return modelgen.RevertTemplate(filename)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected category: %s", category)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func InitTemplates(category string, templates map[string]string) error {
|
||||
}
|
||||
|
||||
for k, v := range templates {
|
||||
if err := createTemplate(filepath.Join(dir, k), v); err != nil {
|
||||
if err := createTemplate(filepath.Join(dir, k), v, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -36,6 +36,22 @@ func InitTemplates(category string, templates map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTemplate(category, name, content string) error {
|
||||
dir, err := GetTemplateDir(category)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return createTemplate(filepath.Join(dir, name), content, true)
|
||||
}
|
||||
|
||||
func Clean(category string) error {
|
||||
dir, err := GetTemplateDir(category)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.RemoveAll(dir)
|
||||
}
|
||||
|
||||
func LoadTemplate(category, file, builtin string) (string, error) {
|
||||
dir, err := GetTemplateDir(category)
|
||||
if err != nil {
|
||||
@ -55,9 +71,8 @@ func LoadTemplate(category, file, builtin string) (string, error) {
|
||||
return string(content), nil
|
||||
}
|
||||
|
||||
func createTemplate(file, content string) error {
|
||||
if FileExists(file) {
|
||||
println(1)
|
||||
func createTemplate(file, content string, force bool) error {
|
||||
if FileExists(file) && !force {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user