mirror of https://github.com/zhufuyi/sponge
support database postgresql and tidb
This commit is contained in:
parent
948b3f0b36
commit
a56a20263a
|
@ -1,4 +1,8 @@
|
|||
## Change log
|
||||
|
||||
- Add auto test scripts.
|
||||
- Repack gorm package.
|
||||
- Added generate database initialization code command.
|
||||
- Added support for postgresql, tidb generation code.
|
||||
- Modify the Sponge UI interface.
|
||||
- Adjust database configuration in configuration.
|
||||
- Added generate k8s configmap script command.
|
||||
- The generated code version matches the local sponge version.
|
||||
|
|
2
Makefile
2
Makefile
|
@ -169,7 +169,7 @@ image-build-rpc-test:
|
|||
|
||||
|
||||
.PHONY: patch
|
||||
# patch some dependent code, such as types.proto, mysql initialization code. e.g. make patch TYPE=types-pb , make patch TYPE=mysql-init
|
||||
# patch some dependent code, such as types.proto, mysql initialization code. e.g. make patch TYPE=types-pb , make patch TYPE=init-mysql, make patch TYPE=init-postgresql
|
||||
patch:
|
||||
@bash scripts/patch.sh $(TYPE)
|
||||
|
||||
|
|
|
@ -301,7 +301,7 @@ message ListUserExampleByIDsReply {
|
|||
|
||||
message ListUserExampleByLastIDRequest {
|
||||
uint64 lastID = 1 [(tagger.tags) = "form:\"lastID\""]; // last id
|
||||
uint32 limit = 2 [(validate.rules).uint32.gt = 0, (tagger.tags) = "form:\"limit\""]; // page size
|
||||
uint32 limit = 2 [(validate.rules).uint32.gt = 0, (tagger.tags) = "form:\"limit\""]; // limit size per page
|
||||
string sort = 3 [(tagger.tags) = "form:\"sort\""]; // sort by column name of table, default is -id, the - sign indicates descending order.
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ func Close(servers []app.IServer) []app.Close {
|
|||
closes = append(closes, s.Stop)
|
||||
}
|
||||
|
||||
// close mysql
|
||||
// close database
|
||||
closes = append(closes, func() error {
|
||||
return model.CloseMysql()
|
||||
return model.CloseDB()
|
||||
})
|
||||
|
||||
// close redis
|
||||
|
|
|
@ -45,8 +45,8 @@ func InitApp() {
|
|||
logger.Info("init logger succeeded")
|
||||
|
||||
// initializing database
|
||||
model.InitMysql()
|
||||
logger.Info("init mysql succeeded")
|
||||
model.InitDB()
|
||||
logger.Infof("init %s succeeded", cfg.Database.Driver)
|
||||
model.InitCache(cfg.App.CacheType)
|
||||
|
||||
// initializing tracing
|
||||
|
|
|
@ -20,9 +20,9 @@ func Close(servers []app.IServer) []app.Close {
|
|||
closes = append(closes, s.Stop)
|
||||
}
|
||||
|
||||
// close mysql
|
||||
// close database
|
||||
//closes = append(closes, func() error {
|
||||
// return model.CloseMysql()
|
||||
// return model.CloseDB()
|
||||
//})
|
||||
|
||||
// close redis
|
||||
|
|
|
@ -46,8 +46,8 @@ func InitApp() {
|
|||
logger.Info("init logger succeeded")
|
||||
|
||||
// initializing database
|
||||
//model.InitMysql()
|
||||
//logger.Info("init mysql succeeded")
|
||||
//model.InitDB()
|
||||
//logger.Infof("init %s succeeded", cfg.Database.Driver)
|
||||
//model.InitCache(cfg.App.CacheType)
|
||||
|
||||
// initializing tracing
|
||||
|
|
|
@ -20,9 +20,9 @@ func Close(servers []app.IServer) []app.Close {
|
|||
closes = append(closes, s.Stop)
|
||||
}
|
||||
|
||||
// close mysql
|
||||
// close database
|
||||
closes = append(closes, func() error {
|
||||
return model.CloseMysql()
|
||||
return model.CloseDB()
|
||||
})
|
||||
|
||||
// close redis
|
||||
|
|
|
@ -45,8 +45,8 @@ func InitApp() {
|
|||
logger.Info("init logger succeeded")
|
||||
|
||||
// initializing database
|
||||
model.InitMysql()
|
||||
logger.Info("init mysql succeeded")
|
||||
model.InitDB()
|
||||
logger.Infof("init %s succeeded", cfg.Database.Driver)
|
||||
model.InitCache(cfg.App.CacheType)
|
||||
|
||||
// initializing tracing
|
||||
|
|
|
@ -20,9 +20,9 @@ func Close(servers []app.IServer) []app.Close {
|
|||
closes = append(closes, s.Stop)
|
||||
}
|
||||
|
||||
// close mysql
|
||||
// close database
|
||||
//closes = append(closes, func() error {
|
||||
// return model.CloseMysql()
|
||||
// return model.CloseDB()
|
||||
//})
|
||||
|
||||
// close redis
|
||||
|
|
|
@ -46,8 +46,8 @@ func InitApp() {
|
|||
logger.Info("init logger succeeded")
|
||||
|
||||
// initializing database
|
||||
//model.InitMysql()
|
||||
//logger.Info("init mysql succeeded")
|
||||
//model.InitDB()
|
||||
//logger.Infof("init %s succeeded", cfg.Database.Driver)
|
||||
//model.InitCache(cfg.App.CacheType)
|
||||
|
||||
// initializing tracing
|
||||
|
|
|
@ -20,9 +20,9 @@ func Close(servers []app.IServer) []app.Close {
|
|||
closes = append(closes, s.Stop)
|
||||
}
|
||||
|
||||
// close mysql
|
||||
// close database
|
||||
closes = append(closes, func() error {
|
||||
return model.CloseMysql()
|
||||
return model.CloseDB()
|
||||
})
|
||||
|
||||
// close redis
|
||||
|
|
|
@ -45,8 +45,8 @@ func InitApp() {
|
|||
logger.Info("init logger succeeded")
|
||||
|
||||
// initializing database
|
||||
model.InitMysql()
|
||||
logger.Info("init mysql succeeded")
|
||||
model.InitDB()
|
||||
logger.Infof("init %s succeeded", cfg.Database.Driver)
|
||||
model.InitCache(cfg.App.CacheType)
|
||||
|
||||
// initializing tracing
|
||||
|
|
|
@ -45,7 +45,17 @@ Examples:
|
|||
}
|
||||
|
||||
var err error
|
||||
outPath, err = runCacheCommand(moduleName, cacheName, prefixKey, keyName, keyType, valueName, valueType, outPath)
|
||||
var g = &stringCacheGenerator{
|
||||
moduleName: moduleName,
|
||||
cacheName: cacheName,
|
||||
prefixKey: prefixKey,
|
||||
keyName: keyName,
|
||||
keyType: keyType,
|
||||
valueName: valueName,
|
||||
valueType: valueType,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -78,18 +88,28 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runCacheCommand(moduleName string, cacheName string, prefixKey string, keyName string,
|
||||
keyType string, valueName string, valueType string, outPath string) (string, error) {
|
||||
type stringCacheGenerator struct {
|
||||
moduleName string
|
||||
cacheName string
|
||||
prefixKey string
|
||||
keyName string
|
||||
keyType string
|
||||
valueName string
|
||||
valueType string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *stringCacheGenerator) generateCode() (string, error) {
|
||||
subTplName := "cache"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
if prefixKey == "" || prefixKey == ":" {
|
||||
prefixKey = cacheName + ":"
|
||||
} else if prefixKey[len(prefixKey)-1] != ':' {
|
||||
prefixKey += ":"
|
||||
if g.prefixKey == "" || g.prefixKey == ":" {
|
||||
g.prefixKey = g.cacheName + ":"
|
||||
} else if g.prefixKey[len(g.prefixKey)-1] != ':' {
|
||||
g.prefixKey += ":"
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
|
@ -106,9 +126,9 @@ func runCacheCommand(moduleName string, cacheName string, prefixKey string, keyN
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addCacheFields(moduleName, r, cacheName, prefixKey, keyName, keyType, valueName, valueType)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -116,22 +136,21 @@ func runCacheCommand(moduleName string, cacheName string, prefixKey string, keyN
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addCacheFields(moduleName string, r replacer.Replacer, cacheName string, prefixKey string, keyName string,
|
||||
keyType string, valueName string, valueType string) []replacer.Field {
|
||||
func (g *stringCacheGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
fields = append(fields, deleteFieldsMark(r, cacheFile, startMark, endMark)...)
|
||||
|
||||
// match the case where the value type is a pointer
|
||||
if valueType[0] == '*' {
|
||||
if g.valueType[0] == '*' {
|
||||
fields = append(fields, []replacer.Field{
|
||||
{
|
||||
Old: "var valueNameExample valueTypeExample",
|
||||
New: fmt.Sprintf("%s := &%s{}", valueName, valueType[1:]),
|
||||
New: fmt.Sprintf("%s := &%s{}", g.valueName, g.valueType[1:]),
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{
|
||||
Old: "&valueNameExample",
|
||||
New: valueName,
|
||||
New: g.valueName,
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
}...)
|
||||
|
@ -140,36 +159,36 @@ func addCacheFields(moduleName string, r replacer.Replacer, cacheName string, pr
|
|||
fields = append(fields, []replacer.Field{
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/internal/model",
|
||||
New: moduleName + "/internal/model",
|
||||
New: g.moduleName + "/internal/model",
|
||||
},
|
||||
{
|
||||
Old: "cacheNameExample",
|
||||
New: cacheName,
|
||||
New: g.cacheName,
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "prefixKeyExample:",
|
||||
New: prefixKey,
|
||||
New: g.prefixKey,
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{
|
||||
Old: "keyNameExample",
|
||||
New: keyName,
|
||||
New: g.keyName,
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{
|
||||
Old: "keyTypeExample",
|
||||
New: keyType,
|
||||
New: g.keyType,
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{
|
||||
Old: "valueNameExample",
|
||||
New: valueName,
|
||||
New: g.valueName,
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{
|
||||
Old: "valueTypeExample",
|
||||
New: valueType,
|
||||
New: g.valueType,
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
}...)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -19,12 +20,22 @@ import (
|
|||
const (
|
||||
// TplNameSponge name of the template
|
||||
TplNameSponge = "sponge"
|
||||
|
||||
// DBDriverMysql mysql driver
|
||||
DBDriverMysql = "mysql"
|
||||
// DBDriverPostgresql postgresql driver
|
||||
DBDriverPostgresql = "postgresql"
|
||||
// DBDriverTidb tidb driver
|
||||
DBDriverTidb = "tidb"
|
||||
)
|
||||
|
||||
var (
|
||||
modelFile = "model/userExample.go"
|
||||
modelFileMark = "// todo generate model code to here"
|
||||
|
||||
modelInitDBFile = "model/init.go"
|
||||
modelInitDBFileMark = "// todo generate initialisation database code here"
|
||||
|
||||
cacheFile = "cache/cacheNameExample.go"
|
||||
|
||||
daoFile = "dao/userExample.go"
|
||||
|
@ -35,6 +46,10 @@ var (
|
|||
handlerFileMark = "// todo generate the request and response struct to here"
|
||||
handlerTestFile = "handler/userExample_test.go"
|
||||
|
||||
handlerLogicFile = "handler/userExample_logic.go"
|
||||
serviceLogicFile = "service/userExample.go"
|
||||
embedTimeMark = "// todo generate the conversion createdAt and updatedAt code here"
|
||||
|
||||
httpFile = "server/http.go"
|
||||
|
||||
protoFile = "v1/userExample.proto"
|
||||
|
@ -69,8 +84,16 @@ var (
|
|||
protoShellFileGRPCMark = "# todo generate grpc files here"
|
||||
protoShellFileMark = "# todo generate api template code command here"
|
||||
|
||||
appConfigFile = "configs/serverNameExample.yml"
|
||||
appConfigFileMark = "# todo generate http or rpc server configuration here"
|
||||
appConfigFile = "configs/serverNameExample.yml"
|
||||
appConfigFileMark = "# todo generate http or rpc server configuration here"
|
||||
appConfigFileMark2 = "# todo generate the database configuration here"
|
||||
|
||||
deploymentConfigFile = "kubernetes/serverNameExample-configmap.yml"
|
||||
deploymentConfigFileMark = "# todo generate the database configuration for deployment here"
|
||||
|
||||
spongeTemplateVersionMark = "// todo generate the local sponge template code version here"
|
||||
|
||||
configmapFileMark = "# todo generate server configuration code here"
|
||||
|
||||
readmeFile = "sponge/README.md"
|
||||
makeFile = "sponge/Makefile"
|
||||
|
@ -87,6 +110,13 @@ var (
|
|||
selfPackageName = "github.com/zhufuyi/sponge"
|
||||
)
|
||||
|
||||
var (
|
||||
ModelInitDBFile = modelInitDBFile
|
||||
ModelInitDBFileMark = modelInitDBFileMark
|
||||
StartMark = startMark
|
||||
EndMark = endMark
|
||||
)
|
||||
|
||||
func symbolConvert(str string, additionalChar ...string) []byte {
|
||||
char := ""
|
||||
if len(additionalChar) > 0 {
|
||||
|
@ -154,6 +184,11 @@ func deleteFieldsMark(r replacer.Replacer, filename string, startMark []byte, en
|
|||
return fields
|
||||
}
|
||||
|
||||
// DeleteCodeMark delete code mark fragment
|
||||
func DeleteCodeMark(r replacer.Replacer, filename string, startMark []byte, endMark []byte) []replacer.Field {
|
||||
return deleteFieldsMark(r, filename, startMark, endMark)
|
||||
}
|
||||
|
||||
func deleteAllFieldsMark(r replacer.Replacer, filename string, startMark []byte, endMark []byte) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
|
@ -336,3 +371,114 @@ func replacePackage(data []byte, moduleName string, serverName string) []byte {
|
|||
|
||||
return data
|
||||
}
|
||||
|
||||
func getDBConfigCode(dbDriver string, forDeployment ...bool) string {
|
||||
isDeployment := false
|
||||
if len(forDeployment) > 0 {
|
||||
isDeployment = forDeployment[0]
|
||||
}
|
||||
|
||||
dbConfigCode := ""
|
||||
switch strings.ToLower(dbDriver) {
|
||||
case DBDriverMysql, DBDriverTidb:
|
||||
if isDeployment {
|
||||
dbConfigCode = mysqlConfigForDeploymentCode
|
||||
} else {
|
||||
dbConfigCode = mysqlConfigCode
|
||||
}
|
||||
|
||||
case DBDriverPostgresql:
|
||||
if isDeployment {
|
||||
dbConfigCode = postgresqlConfigForDeploymentCode
|
||||
} else {
|
||||
dbConfigCode = postgresqlConfigCode
|
||||
}
|
||||
default:
|
||||
panic("getDBConfigCode error, unsupported database driver: " + dbDriver)
|
||||
}
|
||||
return dbConfigCode
|
||||
}
|
||||
|
||||
func getInitDBCode(dbDriver string) string {
|
||||
initDBCode := ""
|
||||
switch strings.ToLower(dbDriver) {
|
||||
case DBDriverMysql, DBDriverTidb:
|
||||
initDBCode = modelInitDBFileMysqlCode
|
||||
case DBDriverPostgresql:
|
||||
initDBCode = modelInitDBFilePostgresqlCode
|
||||
default:
|
||||
panic("getInitDBCode error, unsupported database driver: " + dbDriver)
|
||||
}
|
||||
return initDBCode
|
||||
}
|
||||
|
||||
// GetInitDataBaseCode get init db code
|
||||
func GetInitDataBaseCode(dbDriver string) string {
|
||||
return getInitDBCode(dbDriver)
|
||||
}
|
||||
|
||||
func getLocalSpongeTemplateVersion() string {
|
||||
dir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
fmt.Println("os.UserHomeDir error:", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
versionFile := dir + "/.sponge/.github/version"
|
||||
data, err := os.ReadFile(versionFile)
|
||||
if err != nil {
|
||||
fmt.Printf("read file %s error: %v\n", versionFile, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
v := string(data)
|
||||
if v == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("github.com/zhufuyi/sponge %s", v)
|
||||
}
|
||||
|
||||
func getEmbedTimeCode(isEmbed bool) string {
|
||||
if isEmbed {
|
||||
return embedTimeCode
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func convertYamlConfig(configFile string) (string, error) {
|
||||
f, err := os.Open(configFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close() //nolint
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
modifiedLines := []string{}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
modifiedLine := " " + line
|
||||
modifiedLines = append(modifiedLines, modifiedLine)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.Join(modifiedLines, "\n"), nil
|
||||
}
|
||||
|
||||
func generateConfigmap(serverName string, outPath string) error {
|
||||
configFile := fmt.Sprintf(outPath+"/configs/%s.yml", serverName)
|
||||
configmapFile := fmt.Sprintf(outPath+"/deployments/kubernetes/%s-configmap.yml", serverName)
|
||||
configFileData, err := convertYamlConfig(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
configmapFileData, err := os.ReadFile(configmapFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := strings.ReplaceAll(string(configmapFileData), configmapFileMark, configFileData)
|
||||
return os.WriteFile(configmapFile, []byte(data), 0666)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/replacer"
|
||||
|
||||
"github.com/huandu/xstrings"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// ConfigmapCommand generate k8s configmap command
|
||||
func ConfigmapCommand() *cobra.Command {
|
||||
var (
|
||||
serverName = ""
|
||||
projectName = ""
|
||||
configFile = ""
|
||||
outPath = ""
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "configmap",
|
||||
Short: "Generate k8s configmap",
|
||||
Long: `generate k8s configmap.
|
||||
|
||||
Examples:
|
||||
# generate k8s configmap
|
||||
sponge configmap --server-name=yourServerName --project-name=yourProjectName --config-file=yourConfigFile.yml
|
||||
|
||||
# generate grpc connection code and specify the server directory, Note: code generation will be canceled when the latest generated file already exists.
|
||||
sponge configmap --server-name=yourServerName --project-name=yourProjectName --config-file=yourConfigFile.yml --out=./yourServerDir
|
||||
`,
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
content, err := convertYamlConfig(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g := copyConfigGenerator{
|
||||
serverName: serverName,
|
||||
projectName: projectName,
|
||||
content: content,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("\ngenerate \"configmap\" code successfully, out = %s\n", outPath)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&serverName, "server-name", "s", "", "server name")
|
||||
_ = cmd.MarkFlagRequired("server-name")
|
||||
cmd.Flags().StringVarP(&projectName, "project-name", "p", "", "project name")
|
||||
_ = cmd.MarkFlagRequired("project-name")
|
||||
cmd.Flags().StringVarP(&configFile, "config-file", "f", "", "server config file")
|
||||
cmd.Flags().StringVarP(&outPath, "out", "o", "", "output directory, default is ./configmap_<time>")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type copyConfigGenerator struct {
|
||||
serverName string
|
||||
projectName string
|
||||
content string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *copyConfigGenerator) generateCode() (string, error) {
|
||||
subTplName := "configmap"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
subDirs := []string{ // only the specified subdirectory is processed, if empty or no subdirectory is specified, it means all files
|
||||
"deployments/kubernetes",
|
||||
}
|
||||
ignoreDirs := []string{} // specify the directory in the subdirectory where processing is ignored
|
||||
ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
|
||||
"projectNameExample-namespace.yml", "README.md", "serverNameExample-deployment.yml", "serverNameExample-svc.yml",
|
||||
}
|
||||
|
||||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := g.addFields()
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func (g *copyConfigGenerator) addFields() []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, []replacer.Field{
|
||||
{
|
||||
Old: configmapFileMark,
|
||||
New: g.content,
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: g.serverName,
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "server-name-example",
|
||||
New: xstrings.ToKebabCase(g.serverName), // snake_case to kebab_case
|
||||
},
|
||||
{
|
||||
Old: "project-name-example",
|
||||
New: g.projectName,
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
}
|
|
@ -74,7 +74,13 @@ Examples:
|
|||
isIncludeInitDB = false
|
||||
}
|
||||
|
||||
outPath, err = runGenDaoCommand(moduleName, isIncludeInitDB, codes, outPath)
|
||||
g := &daoGenerator{
|
||||
moduleName: moduleName,
|
||||
isIncludeInitDB: isIncludeInitDB,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,9 +96,10 @@ using help:
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
//_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -105,7 +112,14 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenDaoCommand(moduleName string, isIncludeInitDB bool, codes map[string]string, outPath string) (string, error) {
|
||||
type daoGenerator struct {
|
||||
moduleName string
|
||||
isIncludeInitDB bool
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *daoGenerator) generateCode() (string, error) {
|
||||
subTplName := "dao"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
|
@ -121,7 +135,7 @@ func runGenDaoCommand(moduleName string, isIncludeInitDB bool, codes map[string]
|
|||
"init.go", "init_test.go", // internal/model
|
||||
"doc.go", "cacheNameExample.go", "cacheNameExample_test.go", // internal/cache
|
||||
}
|
||||
if isIncludeInitDB {
|
||||
if g.isIncludeInitDB {
|
||||
ignoreFiles = []string{
|
||||
"doc.go", "cacheNameExample.go", "cacheNameExample_test.go", // internal/cache
|
||||
}
|
||||
|
@ -130,9 +144,9 @@ func runGenDaoCommand(moduleName string, isIncludeInitDB bool, codes map[string]
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addDAOFields(moduleName, r, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -141,38 +155,42 @@ func runGenDaoCommand(moduleName string, isIncludeInitDB bool, codes map[string]
|
|||
}
|
||||
|
||||
// set fields
|
||||
func addDAOFields(moduleName string, r replacer.Replacer, codes map[string]string) []replacer.Field {
|
||||
func (g *daoGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoTestFile, startMark, endMark)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{
|
||||
Old: daoFileMark,
|
||||
New: codes[parser.CodeTypeDAO],
|
||||
New: g.codes[parser.CodeTypeDAO],
|
||||
},
|
||||
{
|
||||
Old: selfPackageName + "/" + r.GetSourcePath(),
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -77,7 +77,14 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenHandlerPbCommand(moduleName, serverName, codes, outPath)
|
||||
g := &handlerPbGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
isEmbed: sqlArgs.IsEmbed,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -96,11 +103,12 @@ using help:
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
//_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&serverName, "server-name", "s", "", "server name")
|
||||
//_ = cmd.MarkFlagRequired("server-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -112,15 +120,23 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenHandlerPbCommand(moduleName string, serverName string, codes map[string]string, outPath string) (string, error) {
|
||||
type handlerPbGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
isEmbed bool
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *handlerPbGenerator) generateCode() (string, error) {
|
||||
subTplName := "handler-pb"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
if serverName == "" {
|
||||
serverName = moduleName
|
||||
if g.serverName == "" {
|
||||
g.serverName = g.moduleName
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
|
@ -138,9 +154,9 @@ func runGenHandlerPbCommand(moduleName string, serverName string, codes map[stri
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addHandlerPbFields(moduleName, serverName, r, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -148,54 +164,59 @@ func runGenHandlerPbCommand(moduleName string, serverName string, codes map[stri
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addHandlerPbFields(moduleName string, serverName string, r replacer.Replacer, codes map[string]string) []replacer.Field {
|
||||
func (g *handlerPbGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoTestFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, handlerLogicFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, protoFile, startMark, endMark)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{ // replace the contents of the dao/userExample.go file
|
||||
Old: daoFileMark,
|
||||
New: codes[parser.CodeTypeDAO],
|
||||
New: g.codes[parser.CodeTypeDAO],
|
||||
},
|
||||
{ // replace the contents of the handler/userExample_logic.go file
|
||||
Old: embedTimeMark,
|
||||
New: getEmbedTimeCode(g.isEmbed),
|
||||
},
|
||||
{ // replace the contents of the v1/userExample.proto file
|
||||
Old: protoFileMark,
|
||||
New: codes[parser.CodeTypeProto],
|
||||
New: g.codes[parser.CodeTypeProto],
|
||||
},
|
||||
{
|
||||
Old: selfPackageName + "/" + r.GetSourcePath(),
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
// replace directory name
|
||||
{
|
||||
Old: strings.Join([]string{"api", "serverNameExample", "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", g.serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
},
|
||||
{
|
||||
Old: "api/serverNameExample/v1",
|
||||
New: fmt.Sprintf("api/%s/v1", serverName),
|
||||
New: fmt.Sprintf("api/%s/v1", g.serverName),
|
||||
},
|
||||
// Note: protobuf package no "-" signs allowed
|
||||
{
|
||||
Old: "api.serverNameExample.v1",
|
||||
New: fmt.Sprintf("api.%s.v1", serverName),
|
||||
New: fmt.Sprintf("api.%s.v1", g.serverName),
|
||||
},
|
||||
{
|
||||
Old: "userExampleNO = 1",
|
||||
New: fmt.Sprintf("userExampleNO = %d", rand.Intn(100)),
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{
|
||||
|
@ -209,13 +230,17 @@ func addHandlerPbFields(moduleName string, serverName string, r replacer.Replace
|
|||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -67,7 +67,12 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenHandlerCommand(moduleName, codes, outPath)
|
||||
g := &handlerGenerator{
|
||||
moduleName: moduleName,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -78,7 +83,7 @@ using help:
|
|||
1. move the folder "internal" to your project code folder.
|
||||
2. open a terminal and execute the command: make docs
|
||||
3. compile and run service: make run
|
||||
4. visit http://localhost:8080/swagger/index.html to your browser, and test the CRUD api interface.
|
||||
4. visit http://localhost:8080/swagger/index.html in your browser, and test the CRUD api interface.
|
||||
|
||||
`)
|
||||
fmt.Printf("generate \"handler\" code successfully, out = %s\n", outPath)
|
||||
|
@ -86,9 +91,10 @@ using help:
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
//_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -100,7 +106,13 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenHandlerCommand(moduleName string, codes map[string]string, outPath string) (string, error) {
|
||||
type handlerGenerator struct {
|
||||
moduleName string
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *handlerGenerator) generateCode() (string, error) {
|
||||
subTplName := "handler"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
|
@ -123,9 +135,9 @@ func runGenHandlerCommand(moduleName string, codes map[string]string, outPath st
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addHandlerFields(moduleName, r, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -133,7 +145,7 @@ func runGenHandlerCommand(moduleName string, codes map[string]string, outPath st
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addHandlerFields(moduleName string, r replacer.Replacer, codes map[string]string) []replacer.Field {
|
||||
func (g *handlerGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
|
@ -144,37 +156,41 @@ func addHandlerFields(moduleName string, r replacer.Replacer, codes map[string]s
|
|||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{ // replace the contents of the dao/userExample.go file
|
||||
Old: daoFileMark,
|
||||
New: codes[parser.CodeTypeDAO],
|
||||
New: g.codes[parser.CodeTypeDAO],
|
||||
},
|
||||
{ // replace the contents of the handler/userExample.go file
|
||||
Old: handlerFileMark,
|
||||
New: adjustmentOfIDType(codes[parser.CodeTypeHandler]),
|
||||
New: adjustmentOfIDType(g.codes[parser.CodeTypeHandler]),
|
||||
},
|
||||
{
|
||||
Old: selfPackageName + "/" + r.GetSourcePath(),
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: "userExampleNO = 1",
|
||||
New: fmt.Sprintf("userExampleNO = %d", rand.Intn(100)),
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -39,8 +39,23 @@ Examples:
|
|||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
projectName, serverName = convertProjectAndServerName(projectName, serverName)
|
||||
return runGenHTTPPbCommand(moduleName, serverName, projectName, protobufFile, repoAddr, outPath)
|
||||
g := &httpPbGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
projectName: projectName,
|
||||
protobufFile: protobufFile,
|
||||
repoAddr: repoAddr,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = generateConfigmap(serverName, outPath)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -59,16 +74,25 @@ Examples:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenHTTPPbCommand(moduleName string, serverName string, projectName string, protobufFile string, repoAddr string, outPath string) error {
|
||||
protobufFiles, isImportTypes, err := parseProtobufFiles(protobufFile)
|
||||
type httpPbGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
projectName string
|
||||
protobufFile string
|
||||
repoAddr string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *httpPbGenerator) generateCode() (string, error) {
|
||||
protobufFiles, isImportTypes, err := parseProtobufFiles(g.protobufFile)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
subTplName := "http-pb"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
return errors.New("replacer is nil")
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
|
@ -97,15 +121,15 @@ func runGenHTTPPbCommand(moduleName string, serverName string, projectName strin
|
|||
r.SetSubDirsAndFiles(subDirs, subFiles...)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addHTTPPbFields(moduleName, serverName, projectName, repoAddr, r)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, serverName+"_"+subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, g.serverName+"_"+subTplName)
|
||||
if err = r.SaveFiles(); err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
_ = saveProtobufFiles(moduleName, serverName, r.GetOutputDir(), protobufFiles)
|
||||
_ = saveGenInfo(moduleName, serverName, r.GetOutputDir())
|
||||
_ = saveProtobufFiles(g.moduleName, g.serverName, r.GetOutputDir(), protobufFiles)
|
||||
_ = saveGenInfo(g.moduleName, g.serverName, r.GetOutputDir())
|
||||
_ = saveEmptySwaggerJSON(r.GetOutputDir())
|
||||
|
||||
fmt.Printf(`
|
||||
|
@ -116,15 +140,15 @@ using help:
|
|||
4. visit http://localhost:8080/apis/swagger/index.html in your browser, and test api interface.
|
||||
|
||||
`)
|
||||
fmt.Printf("generate %s's web service code successfully, out = %s\n", serverName, r.GetOutputDir())
|
||||
return nil
|
||||
outpath := r.GetOutputDir()
|
||||
fmt.Printf("generate %s's web service code successfully, out = %s\n", g.serverName, outpath)
|
||||
return outpath, nil
|
||||
}
|
||||
|
||||
func addHTTPPbFields(moduleName string, serverName string, projectName string, repoAddr string,
|
||||
r replacer.Replacer) []replacer.Field {
|
||||
func (g *httpPbGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
repoHost, _ := parseImageRepoAddr(repoAddr)
|
||||
repoHost, _ := parseImageRepoAddr(g.repoAddr)
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, httpFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, dockerFile, wellStartMark, wellEndMark)...)
|
||||
|
@ -137,9 +161,22 @@ func addHTTPPbFields(moduleName string, serverName string, projectName string, r
|
|||
fields = append(fields, deleteAllFieldsMark(r, makeFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, gitIgnoreFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, protoShellFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+serverName)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, deploymentConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+g.serverName)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: httpServerConfigCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark2,
|
||||
New: getDBConfigCode(DBDriverMysql),
|
||||
},
|
||||
{ // replace the contents of the model/init.go file
|
||||
Old: modelInitDBFileMark,
|
||||
New: getInitDBCode(DBDriverMysql), // default is mysql
|
||||
},
|
||||
{ // replace the contents of the Dockerfile file
|
||||
Old: dockerFileMark,
|
||||
New: dockerFileHTTPCode,
|
||||
|
@ -160,6 +197,10 @@ func addHTTPPbFields(moduleName string, serverName string, projectName string, r
|
|||
Old: dockerComposeFileMark,
|
||||
New: dockerComposeFileHTTPCode,
|
||||
},
|
||||
{ // replace the contents of the *-configmap.yml file
|
||||
Old: deploymentConfigFileMark,
|
||||
New: getDBConfigCode(DBDriverMysql, true),
|
||||
},
|
||||
{ // replace the contents of the *-deployment.yml file
|
||||
Old: k8sDeploymentFileMark,
|
||||
New: k8sDeploymentFileHTTPCode,
|
||||
|
@ -168,10 +209,6 @@ func addHTTPPbFields(moduleName string, serverName string, projectName string, r
|
|||
Old: k8sServiceFileMark,
|
||||
New: k8sServiceFileHTTPCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: httpServerConfigCode,
|
||||
},
|
||||
{ // replace the contents of the proto.sh file
|
||||
Old: protoShellFileGRPCMark,
|
||||
New: "",
|
||||
|
@ -182,33 +219,41 @@ func addHTTPPbFields(moduleName string, serverName string, projectName string, r
|
|||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{ // replace the sponge version of the go.mod file
|
||||
Old: spongeTemplateVersionMark,
|
||||
New: getLocalSpongeTemplateVersion(),
|
||||
},
|
||||
{
|
||||
Old: "sponge api docs",
|
||||
New: serverName + " api docs",
|
||||
New: g.serverName + " api docs",
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "server-name-example",
|
||||
New: xstrings.ToKebabCase(serverName), // convert to kebab-case format
|
||||
New: xstrings.ToKebabCase(g.serverName), // convert to kebab-case format
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "project-name-example",
|
||||
New: projectName,
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "projectNameExample",
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "repo-addr-example",
|
||||
New: repoAddr,
|
||||
New: g.repoAddr,
|
||||
},
|
||||
{
|
||||
Old: "image-repo-host",
|
||||
|
|
|
@ -72,7 +72,17 @@ Examples:
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outPath, err = runGenHTTPCommand(moduleName, serverName, projectName, repoAddr, sqlArgs.DBDsn, codes, outPath)
|
||||
g := &httpGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
projectName: projectName,
|
||||
repoAddr: repoAddr,
|
||||
dbDSN: sqlArgs.DBDsn,
|
||||
dbDriver: sqlArgs.DBDriver,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -88,7 +98,12 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenHandlerCommand(moduleName, codes, outPath)
|
||||
hg := &handlerGenerator{
|
||||
moduleName: moduleName,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = hg.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -102,17 +117,20 @@ using help:
|
|||
|
||||
`)
|
||||
fmt.Printf("generate %s's web service code successfully, out = %s\n", serverName, outPath)
|
||||
|
||||
_ = generateConfigmap(serverName, outPath)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&serverName, "server-name", "s", "", "server name")
|
||||
_ = cmd.MarkFlagRequired("server-name")
|
||||
cmd.Flags().StringVarP(&projectName, "project-name", "p", "", "project name")
|
||||
_ = cmd.MarkFlagRequired("project-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -124,8 +142,18 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenHTTPCommand(moduleName string, serverName string, projectName string, repoAddr string,
|
||||
dbDSN string, codes map[string]string, outPath string) (string, error) {
|
||||
type httpGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
projectName string
|
||||
repoAddr string
|
||||
dbDSN string
|
||||
dbDriver string
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *httpGenerator) generateCode() (string, error) {
|
||||
subTplName := "http"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
|
@ -157,24 +185,24 @@ func runGenHTTPCommand(moduleName string, serverName string, projectName string,
|
|||
r.SetSubDirsAndFiles(subDirs, subFiles...)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addHTTPFields(moduleName, serverName, projectName, repoAddr, r, dbDSN, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, serverName+"_"+subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, g.serverName+"_"+subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
_ = saveGenInfo(moduleName, serverName, r.GetOutputDir())
|
||||
_ = saveGenInfo(g.moduleName, g.serverName, r.GetOutputDir())
|
||||
|
||||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addHTTPFields(moduleName string, serverName string, projectName string, repoAddr string,
|
||||
r replacer.Replacer, dbDSN string, codes map[string]string) []replacer.Field {
|
||||
func (g *httpGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
repoHost, _ := parseImageRepoAddr(repoAddr)
|
||||
repoHost, _ := parseImageRepoAddr(g.repoAddr)
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, modelInitDBFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoTestFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, handlerFile, startMark, endMark)...)
|
||||
|
@ -190,20 +218,33 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
//fields = append(fields, deleteAllFieldsMark(r, makeFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, gitIgnoreFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, protoShellFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+serverName)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, deploymentConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+g.serverName)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: httpServerConfigCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark2,
|
||||
New: getDBConfigCode(g.dbDriver),
|
||||
},
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{ // replace the contents of the model/init.go file
|
||||
Old: modelInitDBFileMark,
|
||||
New: getInitDBCode(g.dbDriver),
|
||||
},
|
||||
{ // replace the contents of the dao/userExample.go file
|
||||
Old: daoFileMark,
|
||||
New: codes[parser.CodeTypeDAO],
|
||||
New: g.codes[parser.CodeTypeDAO],
|
||||
},
|
||||
{ // replace the contents of the handler/userExample.go file
|
||||
Old: handlerFileMark,
|
||||
New: adjustmentOfIDType(codes[parser.CodeTypeHandler]),
|
||||
New: adjustmentOfIDType(g.codes[parser.CodeTypeHandler]),
|
||||
},
|
||||
{ // replace the contents of the Dockerfile file
|
||||
Old: dockerFileMark,
|
||||
|
@ -225,6 +266,10 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
Old: dockerComposeFileMark,
|
||||
New: dockerComposeFileHTTPCode,
|
||||
},
|
||||
{ // replace the contents of the *-configmap.yml file
|
||||
Old: deploymentConfigFileMark,
|
||||
New: getDBConfigCode(g.dbDriver, true),
|
||||
},
|
||||
{ // replace the contents of the *-deployment.yml file
|
||||
Old: k8sDeploymentFileMark,
|
||||
New: k8sDeploymentFileHTTPCode,
|
||||
|
@ -233,14 +278,9 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
Old: k8sServiceFileMark,
|
||||
New: k8sServiceFileHTTPCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: httpServerConfigCode,
|
||||
},
|
||||
// replace github.com/zhufuyi/sponge/templates/sponge
|
||||
{
|
||||
{ // replace github.com/zhufuyi/sponge/templates/sponge
|
||||
Old: selfPackageName + "/" + r.GetSourcePath(),
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: protoShellFileGRPCMark,
|
||||
|
@ -252,15 +292,19 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{ // replace the sponge version of the go.mod file
|
||||
Old: spongeTemplateVersionMark,
|
||||
New: getLocalSpongeTemplateVersion(),
|
||||
},
|
||||
{
|
||||
Old: "sponge api docs",
|
||||
New: serverName + " api docs",
|
||||
New: g.serverName + " api docs",
|
||||
},
|
||||
{
|
||||
Old: "userExampleNO = 1",
|
||||
|
@ -268,21 +312,25 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "server-name-example",
|
||||
New: xstrings.ToKebabCase(serverName), // snake_case to kebab_case
|
||||
New: xstrings.ToKebabCase(g.serverName), // snake_case to kebab_case
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "project-name-example",
|
||||
New: projectName,
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "projectNameExample",
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "repo-addr-example",
|
||||
New: repoAddr,
|
||||
New: g.repoAddr,
|
||||
},
|
||||
{
|
||||
Old: "image-repo-host",
|
||||
|
@ -302,7 +350,11 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
},
|
||||
{
|
||||
Old: "root:123456@(192.168.3.37:3306)/account",
|
||||
New: dbDSN,
|
||||
New: g.dbDSN,
|
||||
},
|
||||
{
|
||||
Old: "root:123456@192.168.3.37:5432/account",
|
||||
New: g.dbDSN,
|
||||
},
|
||||
{
|
||||
Old: "Makefile-for-http",
|
||||
|
@ -310,9 +362,13 @@ func addHTTPFields(moduleName string, serverName string, projectName string, rep
|
|||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -58,7 +58,11 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenModelCommand(codes, outPath)
|
||||
g := &modelGenerator{
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -74,7 +78,8 @@ using help:
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -85,7 +90,12 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenModelCommand(codes map[string]string, outPath string) (string, error) {
|
||||
type modelGenerator struct {
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *modelGenerator) generateCode() (string, error) {
|
||||
subTplName := "model"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
|
@ -102,9 +112,9 @@ func runGenModelCommand(codes map[string]string, outPath string) (string, error)
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addModelFields(r, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -112,20 +122,24 @@ func runGenModelCommand(codes map[string]string, outPath string) (string, error)
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addModelFields(r replacer.Replacer, codes map[string]string) []replacer.Field {
|
||||
func (g *modelGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// ProtoBufCommand generate protobuf code
|
||||
func ProtoBufCommand() *cobra.Command {
|
||||
// ProtobufCommand generate protobuf code
|
||||
func ProtobufCommand() *cobra.Command {
|
||||
var (
|
||||
moduleName string // module name for go.mod
|
||||
serverName string // server name
|
||||
|
@ -73,7 +73,13 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenProtoCommand(moduleName, serverName, codes, outPath)
|
||||
g := &protobufGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,11 +96,12 @@ using help:
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
//_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&serverName, "server-name", "s", "", "server name")
|
||||
//_ = cmd.MarkFlagRequired("server-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -106,15 +113,22 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenProtoCommand(moduleName string, serverName string, codes map[string]string, outPath string) (string, error) {
|
||||
type protobufGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *protobufGenerator) generateCode() (string, error) {
|
||||
subTplName := "protobuf"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
if serverName == "" {
|
||||
serverName = moduleName
|
||||
if g.serverName == "" {
|
||||
g.serverName = g.moduleName
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
|
@ -129,9 +143,9 @@ func runGenProtoCommand(moduleName string, serverName string, codes map[string]s
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addProtoFields(moduleName, serverName, r, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -139,40 +153,40 @@ func runGenProtoCommand(moduleName string, serverName string, codes map[string]s
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addProtoFields(moduleName string, serverName string, r replacer.Replacer, codes map[string]string) []replacer.Field {
|
||||
func (g *protobufGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, protoFile, startMark, endMark)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the contents of the v1/userExample.proto file
|
||||
Old: protoFileMark,
|
||||
New: codes[parser.CodeTypeProto],
|
||||
New: g.codes[parser.CodeTypeProto],
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
// replace directory name
|
||||
{
|
||||
Old: strings.Join([]string{"api", "serverNameExample", "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", g.serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
},
|
||||
{
|
||||
Old: "api/serverNameExample/v1",
|
||||
New: fmt.Sprintf("api/%s/v1", serverName),
|
||||
New: fmt.Sprintf("api/%s/v1", g.serverName),
|
||||
},
|
||||
// Note: protobuf package no "-" signs allowed
|
||||
{
|
||||
Old: "api.serverNameExample.v1",
|
||||
New: fmt.Sprintf("api.%s.v1", serverName),
|
||||
New: fmt.Sprintf("api.%s.v1", g.serverName),
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
}...)
|
||||
|
|
|
@ -10,12 +10,12 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// RPCConnectionCommand generate grpc connection code
|
||||
func RPCConnectionCommand() *cobra.Command {
|
||||
// GRPCConnectionCommand generate grpc connection code
|
||||
func GRPCConnectionCommand() *cobra.Command {
|
||||
var (
|
||||
moduleName string // module name for go.mod
|
||||
outPath string // output directory
|
||||
rpcServerNames string // grpc service names
|
||||
moduleName string // module name for go.mod
|
||||
outPath string // output directory
|
||||
grpcServerNames string // grpc service names
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -25,7 +25,7 @@ func RPCConnectionCommand() *cobra.Command {
|
|||
|
||||
Examples:
|
||||
# generate grpc connection code
|
||||
sponge micro rpc-conn --module-name=yourModuleName --rpc-server-name=user
|
||||
sponge micro rpc-conn --module-name=yourModuleName --rpc-server-name=yourGrpcName
|
||||
|
||||
# generate grpc connection code with multiple names.
|
||||
sponge micro rpc-conn --module-name=yourModuleName --rpc-server-name=name1,name2
|
||||
|
@ -43,14 +43,19 @@ Examples:
|
|||
return errors.New(`required flag(s) "module-name" not set, use "sponge micro rpc-conn -h" for help`)
|
||||
}
|
||||
|
||||
rpcNames := strings.Split(rpcServerNames, ",")
|
||||
for _, rpcName := range rpcNames {
|
||||
if rpcName == "" {
|
||||
grpcNames := strings.Split(grpcServerNames, ",")
|
||||
for _, grpcName := range grpcNames {
|
||||
if grpcName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
var err error
|
||||
outPath, err = runGenRPCConnectionCommand(moduleName, rpcName, outPath)
|
||||
var g = &grpcConnectionGenerator{
|
||||
moduleName: moduleName,
|
||||
grpcName: grpcName,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -67,7 +72,7 @@ using help:
|
|||
}
|
||||
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
cmd.Flags().StringVarP(&rpcServerNames, "rpc-server-name", "r", "", "rpc service name, multiple names separated by commas")
|
||||
cmd.Flags().StringVarP(&grpcServerNames, "rpc-server-name", "r", "", "rpc service name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("rpc-server-name")
|
||||
cmd.Flags().StringVarP(&outPath, "out", "o", "", "output directory, default is ./rpc-conn_<time>,"+
|
||||
" if you specify the directory where the web or microservice generated by sponge, the module-name flag can be ignored")
|
||||
|
@ -75,7 +80,13 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenRPCConnectionCommand(moduleName string, rpcName string, outPath string) (string, error) {
|
||||
type grpcConnectionGenerator struct {
|
||||
moduleName string
|
||||
grpcName string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *grpcConnectionGenerator) generateCode() (string, error) {
|
||||
subTplName := "rpc-conn"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
|
@ -94,9 +105,9 @@ func runGenRPCConnectionCommand(moduleName string, rpcName string, outPath strin
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addRPCConnectionFields(moduleName, rpcName)
|
||||
fields := g.addFields()
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -104,21 +115,21 @@ func runGenRPCConnectionCommand(moduleName string, rpcName string, outPath strin
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addRPCConnectionFields(moduleName string, serverName string) []replacer.Field {
|
||||
func (g *grpcConnectionGenerator) addFields() []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, []replacer.Field{
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/configs",
|
||||
New: moduleName + "/configs",
|
||||
New: g.moduleName + "/configs",
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/internal/config",
|
||||
New: moduleName + "/internal/config",
|
||||
New: g.moduleName + "/internal/config",
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.grpcName,
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
}...)
|
||||
|
|
|
@ -40,7 +40,21 @@ Examples:
|
|||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
projectName, serverName = convertProjectAndServerName(projectName, serverName)
|
||||
return runGenRPCGwCommand(moduleName, serverName, projectName, protobufFile, repoAddr, outPath)
|
||||
g := &rpcGwPbGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
projectName: projectName,
|
||||
protobufFile: protobufFile,
|
||||
repoAddr: repoAddr,
|
||||
outPath: outPath,
|
||||
}
|
||||
err := g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = generateConfigmap(serverName, outPath)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -59,8 +73,17 @@ Examples:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenRPCGwCommand(moduleName string, serverName string, projectName string, protobufFile string, repoAddr string, outPath string) error {
|
||||
protobufFiles, isImportTypes, err := parseProtobufFiles(protobufFile)
|
||||
type rpcGwPbGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
projectName string
|
||||
protobufFile string
|
||||
repoAddr string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *rpcGwPbGenerator) generateCode() error {
|
||||
protobufFiles, isImportTypes, err := parseProtobufFiles(g.protobufFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -97,15 +120,15 @@ func runGenRPCGwCommand(moduleName string, serverName string, projectName string
|
|||
r.SetSubDirsAndFiles(subDirs, subFiles...)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addRPCGwFields(moduleName, serverName, projectName, repoAddr, r)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, serverName+"_"+subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, g.serverName+"_"+subTplName)
|
||||
if err = r.SaveFiles(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = saveProtobufFiles(moduleName, serverName, r.GetOutputDir(), protobufFiles)
|
||||
_ = saveGenInfo(moduleName, serverName, r.GetOutputDir())
|
||||
_ = saveProtobufFiles(g.moduleName, g.serverName, r.GetOutputDir(), protobufFiles)
|
||||
_ = saveGenInfo(g.moduleName, g.serverName, r.GetOutputDir())
|
||||
_ = saveEmptySwaggerJSON(r.GetOutputDir())
|
||||
|
||||
fmt.Printf(`
|
||||
|
@ -116,16 +139,15 @@ using help:
|
|||
4. visit http://localhost:8080/apis/swagger/index.html in your browser, and test api interface.
|
||||
|
||||
`)
|
||||
fmt.Printf("generate %s's grpc gateway service code successfully, out = %s\n", serverName, r.GetOutputDir())
|
||||
fmt.Printf("generate %s's grpc gateway service code successfully, out = %s\n", g.serverName, r.GetOutputDir())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addRPCGwFields(moduleName string, serverName string, projectName string, repoAddr string,
|
||||
r replacer.Replacer) []replacer.Field {
|
||||
func (g *rpcGwPbGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
repoHost, _ := parseImageRepoAddr(repoAddr)
|
||||
repoHost, _ := parseImageRepoAddr(g.repoAddr)
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, httpFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, dockerFile, wellStartMark, wellEndMark)...)
|
||||
|
@ -138,9 +160,26 @@ func addRPCGwFields(moduleName string, serverName string, projectName string, re
|
|||
fields = append(fields, deleteAllFieldsMark(r, makeFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, gitIgnoreFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, protoShellFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+serverName)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, deploymentConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+g.serverName)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: rpcGwServerConfigCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark2,
|
||||
New: getDBConfigCode(DBDriverMysql),
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: "",
|
||||
},
|
||||
{ // replace the contents of the model/init.go file
|
||||
Old: modelInitDBFileMark,
|
||||
New: getInitDBCode(DBDriverMysql), // default is mysql
|
||||
},
|
||||
{ // replace the contents of the Dockerfile file
|
||||
Old: dockerFileMark,
|
||||
New: dockerFileHTTPCode,
|
||||
|
@ -161,6 +200,10 @@ func addRPCGwFields(moduleName string, serverName string, projectName string, re
|
|||
Old: dockerComposeFileMark,
|
||||
New: dockerComposeFileHTTPCode,
|
||||
},
|
||||
{ // replace the contents of the *-configmap.yml file
|
||||
Old: deploymentConfigFileMark,
|
||||
New: getDBConfigCode(DBDriverMysql, true),
|
||||
},
|
||||
{ // replace the contents of the *-deployment.yml file
|
||||
Old: k8sDeploymentFileMark,
|
||||
New: k8sDeploymentFileHTTPCode,
|
||||
|
@ -169,10 +212,6 @@ func addRPCGwFields(moduleName string, serverName string, projectName string, re
|
|||
Old: k8sServiceFileMark,
|
||||
New: k8sServiceFileHTTPCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: rpcGwServerConfigCode,
|
||||
},
|
||||
{ // replace the contents of the proto.sh file
|
||||
Old: protoShellFileGRPCMark,
|
||||
New: protoShellGRPCMark,
|
||||
|
@ -183,34 +222,42 @@ func addRPCGwFields(moduleName string, serverName string, projectName string, re
|
|||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{ // replace the sponge version of the go.mod file
|
||||
Old: spongeTemplateVersionMark,
|
||||
New: getLocalSpongeTemplateVersion(),
|
||||
},
|
||||
{
|
||||
Old: "sponge api docs",
|
||||
New: serverName + " api docs",
|
||||
New: g.serverName + " api docs",
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "server-name-example",
|
||||
New: xstrings.ToKebabCase(serverName), // snake_case to kebab_case
|
||||
New: xstrings.ToKebabCase(g.serverName), // snake_case to kebab_case
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "project-name-example",
|
||||
New: projectName,
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "projectNameExample",
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "repo-addr-example",
|
||||
New: repoAddr,
|
||||
New: g.repoAddr,
|
||||
},
|
||||
{
|
||||
Old: "image-repo-host",
|
||||
|
|
|
@ -40,7 +40,21 @@ Examples:
|
|||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
projectName, serverName = convertProjectAndServerName(projectName, serverName)
|
||||
return runGenRPCPbCommand(moduleName, serverName, projectName, protobufFile, repoAddr, outPath)
|
||||
g := &rpcPbGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
projectName: projectName,
|
||||
protobufFile: protobufFile,
|
||||
repoAddr: repoAddr,
|
||||
outPath: outPath,
|
||||
}
|
||||
err := g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = generateConfigmap(serverName, outPath)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -58,8 +72,17 @@ Examples:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenRPCPbCommand(moduleName string, serverName string, projectName string, protobufFile string, repoAddr string, outPath string) error {
|
||||
protobufFiles, isImportTypes, err := parseProtobufFiles(protobufFile)
|
||||
type rpcPbGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
projectName string
|
||||
protobufFile string
|
||||
repoAddr string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *rpcPbGenerator) generateCode() error {
|
||||
protobufFiles, isImportTypes, err := parseProtobufFiles(g.protobufFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,15 +118,15 @@ func runGenRPCPbCommand(moduleName string, serverName string, projectName string
|
|||
r.SetSubDirsAndFiles(subDirs, subFiles...)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addRPCPbFields(moduleName, serverName, projectName, repoAddr, r)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, serverName+"_"+subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, g.serverName+"_"+subTplName)
|
||||
if err = r.SaveFiles(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = saveProtobufFiles(moduleName, serverName, r.GetOutputDir(), protobufFiles)
|
||||
_ = saveGenInfo(moduleName, serverName, r.GetOutputDir())
|
||||
_ = saveProtobufFiles(g.moduleName, g.serverName, r.GetOutputDir(), protobufFiles)
|
||||
_ = saveGenInfo(g.moduleName, g.serverName, r.GetOutputDir())
|
||||
|
||||
fmt.Printf(`
|
||||
using help:
|
||||
|
@ -113,14 +136,14 @@ using help:
|
|||
4. open the file "internal/service/xxx_client_test.go" using Goland or VS Code, testing the grpc methods.
|
||||
|
||||
`)
|
||||
fmt.Printf("generate %s's grpc service code successfully, out = %s\n", serverName, r.GetOutputDir())
|
||||
fmt.Printf("generate %s's grpc service code successfully, out = %s\n", g.serverName, r.GetOutputDir())
|
||||
return nil
|
||||
}
|
||||
|
||||
func addRPCPbFields(moduleName string, serverName string, projectName string, repoAddr string, r replacer.Replacer) []replacer.Field {
|
||||
func (g *rpcPbGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
repoHost, _ := parseImageRepoAddr(repoAddr)
|
||||
repoHost, _ := parseImageRepoAddr(g.repoAddr)
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, dockerFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, dockerFileBuild, wellStartMark, wellEndMark)...)
|
||||
|
@ -132,9 +155,22 @@ func addRPCPbFields(moduleName string, serverName string, projectName string, re
|
|||
fields = append(fields, deleteAllFieldsMark(r, makeFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, gitIgnoreFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, protoShellFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+serverName)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, deploymentConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+g.serverName)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: rpcServerConfigCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark2,
|
||||
New: getDBConfigCode(DBDriverMysql),
|
||||
},
|
||||
{ // replace the contents of the model/init.go file
|
||||
Old: modelInitDBFileMark,
|
||||
New: getInitDBCode(DBDriverMysql), // default is mysql
|
||||
},
|
||||
{ // replace the contents of the Dockerfile file
|
||||
Old: dockerFileMark,
|
||||
New: dockerFileGrpcCode,
|
||||
|
@ -155,6 +191,10 @@ func addRPCPbFields(moduleName string, serverName string, projectName string, re
|
|||
Old: dockerComposeFileMark,
|
||||
New: dockerComposeFileGrpcCode,
|
||||
},
|
||||
{ // replace the contents of the *-configmap.yml file
|
||||
Old: deploymentConfigFileMark,
|
||||
New: getDBConfigCode(DBDriverMysql, true),
|
||||
},
|
||||
{ // replace the contents of the *-deployment.yml file
|
||||
Old: k8sDeploymentFileMark,
|
||||
New: k8sDeploymentFileGrpcCode,
|
||||
|
@ -163,10 +203,6 @@ func addRPCPbFields(moduleName string, serverName string, projectName string, re
|
|||
Old: k8sServiceFileMark,
|
||||
New: k8sServiceFileGrpcCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: rpcServerConfigCode,
|
||||
},
|
||||
{ // replace the contents of the proto.sh file
|
||||
Old: protoShellFileGRPCMark,
|
||||
New: protoShellGRPCMark,
|
||||
|
@ -177,33 +213,41 @@ func addRPCPbFields(moduleName string, serverName string, projectName string, re
|
|||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{ // replace the sponge version of the go.mod file
|
||||
Old: spongeTemplateVersionMark,
|
||||
New: getLocalSpongeTemplateVersion(),
|
||||
},
|
||||
{
|
||||
Old: "sponge api docs",
|
||||
New: serverName + " api docs",
|
||||
New: g.serverName + " api docs",
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "server-name-example",
|
||||
New: xstrings.ToKebabCase(serverName), // snake_case to kebab_case
|
||||
New: xstrings.ToKebabCase(g.serverName), // snake_case to kebab_case
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "project-name-example",
|
||||
New: projectName,
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "projectNameExample",
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "repo-addr-example",
|
||||
New: repoAddr,
|
||||
New: g.repoAddr,
|
||||
},
|
||||
{
|
||||
Old: "image-repo-host",
|
||||
|
|
|
@ -73,7 +73,18 @@ Examples:
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outPath, err = runGenRPCCommand(moduleName, serverName, projectName, repoAddr, sqlArgs.DBDsn, codes, outPath)
|
||||
g := &rpcGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
projectName: projectName,
|
||||
repoAddr: repoAddr,
|
||||
dbDSN: sqlArgs.DBDsn,
|
||||
dbDriver: sqlArgs.DBDriver,
|
||||
isEmbed: sqlArgs.IsEmbed,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -89,7 +100,14 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenServiceCommand(moduleName, serverName, codes, outPath)
|
||||
sg := &serviceGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
isEmbed: sqlArgs.IsEmbed,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = sg.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -103,17 +121,20 @@ using help:
|
|||
|
||||
`)
|
||||
fmt.Printf("generate %s's grpc service code successfully, out = %s\n", serverName, outPath)
|
||||
|
||||
_ = generateConfigmap(serverName, outPath)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&serverName, "server-name", "s", "", "server name")
|
||||
_ = cmd.MarkFlagRequired("server-name")
|
||||
cmd.Flags().StringVarP(&projectName, "project-name", "p", "", "project name")
|
||||
_ = cmd.MarkFlagRequired("project-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -125,8 +146,19 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenRPCCommand(moduleName string, serverName string, projectName string, repoAddr string,
|
||||
dbDSN string, codes map[string]string, outPath string) (string, error) {
|
||||
type rpcGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
projectName string
|
||||
repoAddr string
|
||||
dbDSN string
|
||||
dbDriver string
|
||||
isEmbed bool
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *rpcGenerator) generateCode() (string, error) {
|
||||
subTplName := "rpc"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
|
@ -158,27 +190,28 @@ func runGenRPCCommand(moduleName string, serverName string, projectName string,
|
|||
r.SetSubDirsAndFiles(subDirs, subFiles...)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addRPCFields(moduleName, serverName, projectName, repoAddr, r, dbDSN, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, serverName+"_"+subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, g.serverName+"_"+subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
_ = saveGenInfo(moduleName, serverName, r.GetOutputDir())
|
||||
_ = saveGenInfo(g.moduleName, g.serverName, r.GetOutputDir())
|
||||
|
||||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addRPCFields(moduleName string, serverName string, projectName string, repoAddr string,
|
||||
r replacer.Replacer, dbDSN string, codes map[string]string) []replacer.Field {
|
||||
func (g *rpcGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
repoHost, _ := parseImageRepoAddr(repoAddr)
|
||||
repoHost, _ := parseImageRepoAddr(g.repoAddr)
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, modelInitDBFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoTestFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, protoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, serviceLogicFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, serviceClientFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, serviceTestFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, dockerFile, wellStartMark, wellEndMark)...)
|
||||
|
@ -191,20 +224,37 @@ func addRPCFields(moduleName string, serverName string, projectName string, repo
|
|||
fields = append(fields, deleteAllFieldsMark(r, makeFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, gitIgnoreFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, protoShellFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+serverName)...)
|
||||
fields = append(fields, deleteAllFieldsMark(r, appConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, deploymentConfigFile, wellStartMark, wellEndMark)...)
|
||||
fields = append(fields, replaceFileContentMark(r, readmeFile, "## "+g.serverName)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: rpcServerConfigCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark2,
|
||||
New: getDBConfigCode(g.dbDriver),
|
||||
},
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{ // replace the contents of the model/init.go file
|
||||
Old: modelInitDBFileMark,
|
||||
New: getInitDBCode(g.dbDriver),
|
||||
},
|
||||
{ // replace the contents of the dao/userExample.go file
|
||||
Old: daoFileMark,
|
||||
New: codes[parser.CodeTypeDAO],
|
||||
New: g.codes[parser.CodeTypeDAO],
|
||||
},
|
||||
{ // replace the contents of the handler/userExample_logic.go file
|
||||
Old: embedTimeMark,
|
||||
New: getEmbedTimeCode(g.isEmbed),
|
||||
},
|
||||
{ // replace the contents of the v1/userExample.proto file
|
||||
Old: protoFileMark,
|
||||
New: codes[parser.CodeTypeProto],
|
||||
New: g.codes[parser.CodeTypeProto],
|
||||
},
|
||||
{ // replace the contents of the proto.sh file
|
||||
Old: protoShellFileGRPCMark,
|
||||
|
@ -216,7 +266,7 @@ func addRPCFields(moduleName string, serverName string, projectName string, repo
|
|||
},
|
||||
{ // replace the contents of the service/userExample_client_test.go file
|
||||
Old: serviceFileMark,
|
||||
New: adjustmentOfIDType(codes[parser.CodeTypeService]),
|
||||
New: adjustmentOfIDType(g.codes[parser.CodeTypeService]),
|
||||
},
|
||||
{ // replace the contents of the Dockerfile file
|
||||
Old: dockerFileMark,
|
||||
|
@ -238,6 +288,10 @@ func addRPCFields(moduleName string, serverName string, projectName string, repo
|
|||
Old: dockerComposeFileMark,
|
||||
New: dockerComposeFileGrpcCode,
|
||||
},
|
||||
{ // replace the contents of the *-configmap.yml file
|
||||
Old: deploymentConfigFileMark,
|
||||
New: getDBConfigCode(g.dbDriver, true),
|
||||
},
|
||||
{ // replace the contents of the *-deployment.yml file
|
||||
Old: k8sDeploymentFileMark,
|
||||
New: k8sDeploymentFileGrpcCode,
|
||||
|
@ -246,39 +300,38 @@ func addRPCFields(moduleName string, serverName string, projectName string, repo
|
|||
Old: k8sServiceFileMark,
|
||||
New: k8sServiceFileGrpcCode,
|
||||
},
|
||||
{ // replace the configuration of the *.yml file
|
||||
Old: appConfigFileMark,
|
||||
New: rpcServerConfigCode,
|
||||
},
|
||||
// replace github.com/zhufuyi/sponge/templates/sponge
|
||||
{
|
||||
{ // replace github.com/zhufuyi/sponge/templates/sponge
|
||||
Old: selfPackageName + "/" + r.GetSourcePath(),
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
// replace directory name
|
||||
{
|
||||
Old: strings.Join([]string{"api", "userExample", "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", g.serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{ // replace the sponge version of the go.mod file
|
||||
Old: spongeTemplateVersionMark,
|
||||
New: getLocalSpongeTemplateVersion(),
|
||||
},
|
||||
{
|
||||
Old: "api/userExample/v1",
|
||||
New: fmt.Sprintf("api/%s/v1", serverName),
|
||||
New: fmt.Sprintf("api/%s/v1", g.serverName),
|
||||
},
|
||||
{
|
||||
Old: "api.userExample.v1",
|
||||
New: fmt.Sprintf("api.%s.v1", serverName), // protobuf package no "-" signs allowed
|
||||
New: fmt.Sprintf("api.%s.v1", g.serverName), // protobuf package no "-" signs allowed
|
||||
},
|
||||
{
|
||||
Old: "sponge api docs",
|
||||
New: serverName + " api docs",
|
||||
New: g.serverName + " api docs",
|
||||
},
|
||||
{
|
||||
Old: "_userExampleNO = 2",
|
||||
|
@ -286,21 +339,25 @@ func addRPCFields(moduleName string, serverName string, projectName string, repo
|
|||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "server-name-example",
|
||||
New: xstrings.ToKebabCase(serverName), // snake_case to kebab_case
|
||||
New: xstrings.ToKebabCase(g.serverName), // snake_case to kebab_case
|
||||
},
|
||||
// docker image and k8s deployment script replacement
|
||||
{
|
||||
Old: "project-name-example",
|
||||
New: projectName,
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "projectNameExample",
|
||||
New: g.projectName,
|
||||
},
|
||||
{
|
||||
Old: "repo-addr-example",
|
||||
New: repoAddr,
|
||||
New: g.repoAddr,
|
||||
},
|
||||
{
|
||||
Old: "image-repo-host",
|
||||
|
@ -316,13 +373,21 @@ func addRPCFields(moduleName string, serverName string, projectName string, repo
|
|||
},
|
||||
{
|
||||
Old: "root:123456@(192.168.3.37:3306)/account",
|
||||
New: dbDSN,
|
||||
New: g.dbDSN,
|
||||
},
|
||||
{
|
||||
Old: "root:123456@192.168.3.37:5432/account",
|
||||
New: g.dbDSN,
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -76,7 +76,14 @@ Examples:
|
|||
return err
|
||||
}
|
||||
|
||||
outPath, err = runGenServiceCommand(moduleName, serverName, codes, outPath)
|
||||
g := &serviceGenerator{
|
||||
moduleName: moduleName,
|
||||
serverName: serverName,
|
||||
isEmbed: sqlArgs.IsEmbed,
|
||||
codes: codes,
|
||||
outPath: outPath,
|
||||
}
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,11 +102,12 @@ using help:
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the go.mod file")
|
||||
//_ = cmd.MarkFlagRequired("module-name")
|
||||
cmd.Flags().StringVarP(&serverName, "server-name", "s", "", "server name")
|
||||
//_ = cmd.MarkFlagRequired("server-name")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "db content addr, e.g. user:password@(host:port)/database")
|
||||
cmd.Flags().StringVarP(&sqlArgs.DBDsn, "db-dsn", "d", "", "database content address, e.g. user:password@(host:port)/database")
|
||||
_ = cmd.MarkFlagRequired("db-dsn")
|
||||
cmd.Flags().StringVarP(&dbTables, "db-table", "t", "", "table name, multiple names separated by commas")
|
||||
_ = cmd.MarkFlagRequired("db-table")
|
||||
|
@ -111,15 +119,23 @@ using help:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runGenServiceCommand(moduleName string, serverName string, codes map[string]string, outPath string) (string, error) {
|
||||
type serviceGenerator struct {
|
||||
moduleName string
|
||||
serverName string
|
||||
isEmbed bool
|
||||
codes map[string]string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *serviceGenerator) generateCode() (string, error) {
|
||||
subTplName := "service"
|
||||
r := Replacers[TplNameSponge]
|
||||
if r == nil {
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
if serverName == "" {
|
||||
serverName = moduleName
|
||||
if g.serverName == "" {
|
||||
g.serverName = g.moduleName
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
|
@ -137,9 +153,9 @@ func runGenServiceCommand(moduleName string, serverName string, codes map[string
|
|||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := addServiceFields(moduleName, serverName, r, codes)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(outPath, subTplName)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -147,71 +163,80 @@ func runGenServiceCommand(moduleName string, serverName string, codes map[string
|
|||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func addServiceFields(moduleName string, serverName string, r replacer.Replacer, codes map[string]string) []replacer.Field {
|
||||
func (g *serviceGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, deleteFieldsMark(r, modelFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, daoTestFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, serviceLogicFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, protoFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, serviceClientFile, startMark, endMark)...)
|
||||
fields = append(fields, deleteFieldsMark(r, serviceTestFile, startMark, endMark)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{ // replace the contents of the model/userExample.go file
|
||||
Old: modelFileMark,
|
||||
New: codes[parser.CodeTypeModel],
|
||||
New: g.codes[parser.CodeTypeModel],
|
||||
},
|
||||
{ // replace the contents of the dao/userExample.go file
|
||||
Old: daoFileMark,
|
||||
New: codes[parser.CodeTypeDAO],
|
||||
New: g.codes[parser.CodeTypeDAO],
|
||||
},
|
||||
{ // replace the contents of the handler/userExample_logic.go file
|
||||
Old: embedTimeMark,
|
||||
New: getEmbedTimeCode(g.isEmbed),
|
||||
},
|
||||
{ // replace the contents of the v1/userExample.proto file
|
||||
Old: protoFileMark,
|
||||
New: codes[parser.CodeTypeProto],
|
||||
New: g.codes[parser.CodeTypeProto],
|
||||
},
|
||||
{ // replace the contents of the service/userExample_client_test.go file
|
||||
Old: serviceFileMark,
|
||||
New: adjustmentOfIDType(codes[parser.CodeTypeService]),
|
||||
New: adjustmentOfIDType(g.codes[parser.CodeTypeService]),
|
||||
},
|
||||
{
|
||||
Old: selfPackageName + "/" + r.GetSourcePath(),
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge",
|
||||
New: moduleName,
|
||||
New: g.moduleName,
|
||||
},
|
||||
// replace directory name
|
||||
{
|
||||
Old: strings.Join([]string{"api", "serverNameExample", "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
New: strings.Join([]string{"api", g.serverName, "v1"}, gofile.GetPathDelimiter()),
|
||||
},
|
||||
{
|
||||
Old: "api/serverNameExample/v1",
|
||||
New: fmt.Sprintf("api/%s/v1", serverName),
|
||||
New: fmt.Sprintf("api/%s/v1", g.serverName),
|
||||
},
|
||||
// Note: protobuf package no "-" signs allowed
|
||||
{
|
||||
Old: "api.serverNameExample.v1",
|
||||
New: fmt.Sprintf("api.%s.v1", serverName),
|
||||
New: fmt.Sprintf("api.%s.v1", g.serverName),
|
||||
},
|
||||
{
|
||||
Old: "_userExampleNO = 2",
|
||||
New: fmt.Sprintf("_userExampleNO = %d", rand.Intn(100)),
|
||||
},
|
||||
{
|
||||
Old: moduleName + "/pkg",
|
||||
Old: g.moduleName + "/pkg",
|
||||
New: "github.com/zhufuyi/sponge/pkg",
|
||||
},
|
||||
{
|
||||
Old: "serverNameExample",
|
||||
New: serverName,
|
||||
New: g.serverName,
|
||||
},
|
||||
{
|
||||
Old: "UserExample",
|
||||
New: codes[parser.TableName],
|
||||
New: g.codes[parser.TableName],
|
||||
IsCaseSensitive: true,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/pkg/ggorm",
|
||||
New: "user/pkg/ggorm",
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
|
|
|
@ -218,7 +218,7 @@ func Show(hiddenFields ...string) string {
|
|||
|
||||
func Get() *Config {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
panic("config is nil, please call config.Init() first")
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
@ -346,77 +346,254 @@ func NewCenter(configFile string) (*Center, error) {
|
|||
|
||||
httpServerConfigCode = `# http server settings
|
||||
http:
|
||||
port: 8080 # listen port
|
||||
readTimeout: 3 # read timeout, unit(second)
|
||||
writeTimeout: 60 # write timeout, unit(second), if enableHTTPProfile is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s`
|
||||
port: 8080 # listen port
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second), if enableHTTPProfile is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s`
|
||||
|
||||
rpcServerConfigCode = `# grpc service settings
|
||||
rpcServerConfigCode = `# grpc server settings
|
||||
grpc:
|
||||
port: 8282 # listen port
|
||||
httpPort: 8283 # profile and metrics ports
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second)
|
||||
enableToken: false # whether to enable server-side token authentication, default appID=grpc, appKey=123456
|
||||
port: 8282 # listen port
|
||||
httpPort: 8283 # profile and metrics ports
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second)
|
||||
enableToken: false # whether to enable server-side token authentication, default appID=grpc, appKey=123456
|
||||
# serverSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
# if type="one-way", it means server-side certification, only the fields "certFile" and "keyFile" should be filled in
|
||||
# if type="one-way", it means server-side certification, only the fields 'certFile' and 'keyFile' should be filled in
|
||||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
serverSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
certFile: "" # server side cert file, absolute path
|
||||
keyFile: "" # server side key file, absolute path
|
||||
caFile: "" # ca certificate file, valid only in "two-way", absolute path
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
caFile: "" # ca certificate file, valid only in "two-way", absolute path
|
||||
certFile: "" # server side cert file, absolute path
|
||||
keyFile: "" # server side key file, absolute path
|
||||
|
||||
|
||||
|
||||
# grpc client settings, support for setting up multiple grpc clients
|
||||
# grpc client-side settings, support for setting up multiple grpc clients.
|
||||
grpcClient:
|
||||
- name: "your-rpc-server-name" # grpc service name, used for service discovery
|
||||
host: "127.0.0.1" # grpc service address, used for direct connection
|
||||
port: 8282 # grpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
|
||||
enableLoadBalance: false # whether to turn on the load balancer
|
||||
- name: "serverNameExample" # grpc service name, used for service discovery
|
||||
host: "127.0.0.1" # grpc service address, used for direct connection
|
||||
port: 8282 # grpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
|
||||
enableLoadBalance: true # whether to turn on the load balancer
|
||||
# clientSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
# if type="one-way", it means server-side certification, only the fields "serverName" and "certFile" should be filled in
|
||||
# if type="one-way", it means server-side certification, only the fields 'serverName' and 'certFile' should be filled in
|
||||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
clientSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
caFile: "" # client side ca file, valid only in "two-way", absolute path
|
||||
certFile: "" # client side cert file, absolute path, if secureType="one-way", fill in server side cert file here
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
clientToken:
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key`
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key`
|
||||
|
||||
rpcGwServerConfigCode = `# http server settings
|
||||
http:
|
||||
port: 8080 # listen port
|
||||
readTimeout: 3 # read timeout, unit(second)
|
||||
writeTimeout: 60 # write timeout, unit(second), if enableHTTPProfile is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s
|
||||
port: 8080 # listen port
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second), if enableHTTPProfile is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s
|
||||
|
||||
|
||||
# grpc client settings, support for setting up multiple grpc clients
|
||||
# grpc client-side settings, support for setting up multiple grpc clients.
|
||||
grpcClient:
|
||||
- name: "your-rpc-server-name" # grpc service name, used for service discovery
|
||||
host: "127.0.0.1" # grpc service address, used for direct connection
|
||||
port: 8282 # grpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
|
||||
enableLoadBalance: false # whether to turn on the load balancer
|
||||
- name: "serverNameExample" # grpc service name, used for service discovery
|
||||
host: "127.0.0.1" # grpc service address, used for direct connection
|
||||
port: 8282 # grpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
|
||||
enableLoadBalance: true # whether to turn on the load balancer
|
||||
# clientSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
# if type="one-way", it means server-side certification, only the fields "serverName" and "certFile" should be filled in
|
||||
# if type="one-way", it means server-side certification, only the fields 'serverName' and 'certFile' should be filled in
|
||||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
clientSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
caFile: "" # client side ca file, valid only in "two-way", absolute path
|
||||
certFile: "" # client side cert file, absolute path, if secureType="one-way", fill in server side cert file here
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
clientToken:
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key`
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key`
|
||||
|
||||
mysqlConfigCode = `# database setting
|
||||
database:
|
||||
driver: "mysql" # database driver, currently support mysql, postgres, tidb
|
||||
# mysql settings
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
maxIdleConns: 10 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes
|
||||
#slavesDsn: # sets slaves mysql dsn, array type
|
||||
# - "your slave dsn 1"
|
||||
# - "your slave dsn 2"
|
||||
#mastersDsn: # sets masters mysql dsn, array type, non-required field, if there is only one master, there is no need to set the mastersDsn field, the default dsn field is mysql master.
|
||||
# - "your master dsn`
|
||||
|
||||
mysqlConfigForDeploymentCode = ` # database setting
|
||||
database:
|
||||
driver: "mysql" # database driver, currently support mysql, postgres, tidb
|
||||
# mysql settings
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
slowThreshold: 0 # if greater than 0, only print logs with a time greater than the threshold, with a higher priority than enableLog, in (ms)
|
||||
maxIdleConns: 3 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes
|
||||
#slavesDsn: # sets slaves mysql dsn, array type
|
||||
# - "your slave dsn 1"
|
||||
# - "your slave dsn 2"
|
||||
#mastersDsn: # sets masters mysql dsn, array type, non-required field, if there is only one master, the default dsn field is mysql master.
|
||||
# - "your master dsn"`
|
||||
|
||||
postgresqlConfigCode = `database:
|
||||
driver: "postgresql" # database driver, currently support mysql, postgres, tidb
|
||||
# postgresql settings
|
||||
postgresql:
|
||||
# dsn format, <user>:<pass>@127.0.0.1:5432/<db>?[k=v& ......]
|
||||
dsn: "root:123456@192.168.3.37:5432/account?sslmode=disable"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
maxIdleConns: 10 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes`
|
||||
|
||||
postgresqlConfigForDeploymentCode = ` # database setting
|
||||
database:
|
||||
driver: "postgresql" # database driver, currently support mysql, postgres, tidb
|
||||
# postgresql settings
|
||||
postgresql:
|
||||
# dsn format, <user>:<pass>@127.0.0.1:5432/<db>?[k=v& ......]
|
||||
dsn: "root:123456@192.168.3.37:5432/account?sslmode=disable"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
maxIdleConns: 10 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes`
|
||||
|
||||
modelInitDBFileMysqlCode = `// InitDB connect database
|
||||
func InitDB() {
|
||||
switch strings.ToLower(config.Get().Database.Driver) {
|
||||
case "mysql", "tidb":
|
||||
InitMysql()
|
||||
default:
|
||||
panic("unsupported database driver: " + config.Get().Database.Driver)
|
||||
}
|
||||
}
|
||||
|
||||
// GetDB get db
|
||||
func GetDB() *gorm.DB {
|
||||
if db == nil {
|
||||
once1.Do(func() {
|
||||
switch strings.ToLower(config.Get().Database.Driver) {
|
||||
case "mysql", "tidb":
|
||||
InitMysql()
|
||||
default:
|
||||
panic("unsupported database driver: " + config.Get().Database.Driver)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// InitMysql connect mysql
|
||||
func InitMysql() {
|
||||
opts := []ggorm.Option{
|
||||
ggorm.WithMaxIdleConns(config.Get().Database.Mysql.MaxIdleConns),
|
||||
ggorm.WithMaxOpenConns(config.Get().Database.Mysql.MaxOpenConns),
|
||||
ggorm.WithConnMaxLifetime(time.Duration(config.Get().Database.Mysql.ConnMaxLifetime) * time.Minute),
|
||||
}
|
||||
if config.Get().Database.Mysql.EnableLog {
|
||||
opts = append(opts,
|
||||
ggorm.WithLogging(logger.Get()),
|
||||
ggorm.WithLogRequestIDKey("request_id"),
|
||||
)
|
||||
}
|
||||
|
||||
if config.Get().App.EnableTrace {
|
||||
opts = append(opts, ggorm.WithEnableTrace())
|
||||
}
|
||||
|
||||
// setting mysql slave and master dsn addresses,
|
||||
// if there is no read/write separation, you can comment out the following piece of code
|
||||
opts = append(opts, ggorm.WithRWSeparation(
|
||||
config.Get().Database.Mysql.SlavesDsn,
|
||||
config.Get().Database.Mysql.MastersDsn...,
|
||||
))
|
||||
|
||||
// add custom gorm plugin
|
||||
//opts = append(opts, ggorm.WithGormPlugin(yourPlugin))
|
||||
|
||||
var dsn = utils.AdaptiveMysqlDsn(config.Get().Database.Mysql.Dsn)
|
||||
var err error
|
||||
db, err = ggorm.InitMysql(dsn, opts...)
|
||||
if err != nil {
|
||||
panic("ggorm.InitMysql error: " + err.Error())
|
||||
}
|
||||
}`
|
||||
|
||||
modelInitDBFilePostgresqlCode = `// InitDB connect database
|
||||
func InitDB() {
|
||||
switch strings.ToLower(config.Get().Database.Driver) {
|
||||
case "postgresql":
|
||||
InitPostgresql()
|
||||
default:
|
||||
panic("unsupported database driver: " + config.Get().Database.Driver)
|
||||
}
|
||||
}
|
||||
|
||||
// GetDB get db
|
||||
func GetDB() *gorm.DB {
|
||||
if db == nil {
|
||||
once1.Do(func() {
|
||||
switch strings.ToLower(config.Get().Database.Driver) {
|
||||
case "postgresql":
|
||||
InitPostgresql()
|
||||
default:
|
||||
panic("unsupported database driver: " + config.Get().Database.Driver)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// InitPostgresql connect postgresql
|
||||
func InitPostgresql() {
|
||||
opts := []ggorm.Option{
|
||||
ggorm.WithMaxIdleConns(config.Get().Database.Postgresql.MaxIdleConns),
|
||||
ggorm.WithMaxOpenConns(config.Get().Database.Postgresql.MaxOpenConns),
|
||||
ggorm.WithConnMaxLifetime(time.Duration(config.Get().Database.Postgresql.ConnMaxLifetime) * time.Minute),
|
||||
}
|
||||
if config.Get().Database.Postgresql.EnableLog {
|
||||
opts = append(opts,
|
||||
ggorm.WithLogging(logger.Get()),
|
||||
ggorm.WithLogRequestIDKey("request_id"),
|
||||
)
|
||||
}
|
||||
|
||||
if config.Get().App.EnableTrace {
|
||||
opts = append(opts, ggorm.WithEnableTrace())
|
||||
}
|
||||
|
||||
// add custom gorm plugin
|
||||
//opts = append(opts, ggorm.WithGormPlugin(yourPlugin))
|
||||
|
||||
var dsn = utils.AdaptivePostgresqlDsn(config.Get().Database.Postgresql.Dsn)
|
||||
var err error
|
||||
db, err = ggorm.InitPostgresql(dsn, opts...)
|
||||
if err != nil {
|
||||
panic("ggorm.InitPostgresql error: " + err.Error())
|
||||
}
|
||||
}`
|
||||
|
||||
embedTimeCode = ` value.CreatedAt = record.CreatedAt.Unix()
|
||||
value.UpdatedAt = record.UpdatedAt.Unix()`
|
||||
)
|
||||
|
|
|
@ -17,7 +17,7 @@ func GenMicroCommand() *cobra.Command {
|
|||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
generate.ProtoBufCommand(),
|
||||
generate.ProtobufCommand(),
|
||||
generate.ModelCommand("micro"),
|
||||
generate.DaoCommand("micro"),
|
||||
generate.CacheCommand("micro"),
|
||||
|
@ -25,7 +25,7 @@ func GenMicroCommand() *cobra.Command {
|
|||
generate.RPCCommand(),
|
||||
generate.RPCGwPbCommand(),
|
||||
generate.RPCPbCommand(),
|
||||
generate.RPCConnectionCommand(),
|
||||
generate.GRPCConnectionCommand(),
|
||||
generate.ConvertSwagJSONCommand("micro"),
|
||||
)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ func PatchCommand() *cobra.Command {
|
|||
|
||||
cmd.AddCommand(
|
||||
patch.DeleteJSONOmitemptyCommand(),
|
||||
patch.GenerateDBInitCommand(),
|
||||
patch.GenMysqlInitCommand(),
|
||||
patch.GenTypesPbCommand(),
|
||||
patch.CopyProtoCommand(),
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package patch
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// get moduleName and serverName from directory
|
||||
func getNamesFromOutDir(dir string) (moduleName string, serverName string) {
|
||||
if dir == "" {
|
||||
return "", ""
|
||||
}
|
||||
data, err := os.ReadFile(dir + "/docs/gen.info")
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
ms := strings.Split(string(data), ",")
|
||||
if len(ms) != 2 {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
return ms[0], ms[1]
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
package patch
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/zhufuyi/sponge/cmd/sponge/commands/generate"
|
||||
"github.com/zhufuyi/sponge/pkg/gofile"
|
||||
"github.com/zhufuyi/sponge/pkg/replacer"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// GenerateDBInitCommand generate database initialization code
|
||||
func GenerateDBInitCommand() *cobra.Command {
|
||||
var (
|
||||
moduleName string // go.mod module name
|
||||
dbDriver string // database driver e.g. mysql, postgresql, tidb
|
||||
outPath string // output directory
|
||||
targetFile = "internal/model/init.go"
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "gen-db-init",
|
||||
Short: "Generate database initialization code",
|
||||
Long: `generate database initialization code
|
||||
|
||||
Examples:
|
||||
# generate mysql initialization code.
|
||||
sponge patch gen-db-init --module-name=yourModuleName --db-driver=mysql
|
||||
|
||||
# generate database initialization code, and specify the server directory, Note: code generation will be canceled when the latest generated file already exists.
|
||||
sponge patch gen-db-init --db-driver=mysql --out=./yourServerDir
|
||||
`,
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
mdName, _ := getNamesFromOutDir(outPath)
|
||||
if mdName != "" {
|
||||
moduleName = mdName
|
||||
} else if moduleName == "" {
|
||||
return fmt.Errorf(`required flag(s) "module-name" not set, use "sponge patch gen-mysql-init -h" for help`)
|
||||
}
|
||||
|
||||
var isEmpty bool
|
||||
if outPath == "" {
|
||||
isEmpty = true
|
||||
} else {
|
||||
isEmpty = false
|
||||
if gofile.IsExists(targetFile) {
|
||||
fmt.Printf("'%s' already exists, no need to generate it.\n", targetFile)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
g := &dbInitGenerator{
|
||||
moduleName: moduleName,
|
||||
dbDriver: dbDriver,
|
||||
outPath: outPath,
|
||||
}
|
||||
var err error
|
||||
outPath, err = g.generateCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isEmpty {
|
||||
fmt.Printf(`
|
||||
using help:
|
||||
move the folder "internal" to your project code folder.
|
||||
|
||||
`)
|
||||
}
|
||||
if gofile.IsWindows() {
|
||||
targetFile = "\\" + strings.ReplaceAll(targetFile, "/", "\\")
|
||||
} else {
|
||||
targetFile = "/" + targetFile
|
||||
}
|
||||
fmt.Printf("generate \"%s-init\" codes successfully, out = %s\n", dbDriver, outPath+targetFile)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&dbDriver, "db-driver", "k", "mysql", "database driver, support mysql, postgresql, tidb")
|
||||
cmd.Flags().StringVarP(&moduleName, "module-name", "m", "", "module-name is the name of the module in the 'go.mod' file")
|
||||
cmd.Flags().StringVarP(&outPath, "out", "o", "", "output directory, default is ./mysql-init_<time>, "+
|
||||
"if you specify the directory where the web or microservice generated by sponge, the module-name flag can be ignored")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type dbInitGenerator struct {
|
||||
moduleName string
|
||||
dbDriver string
|
||||
outPath string
|
||||
}
|
||||
|
||||
func (g *dbInitGenerator) generateCode() (string, error) {
|
||||
subTplName := g.dbDriver + "-init"
|
||||
r := generate.Replacers[generate.TplNameSponge]
|
||||
if r == nil {
|
||||
return "", errors.New("replacer is nil")
|
||||
}
|
||||
|
||||
// setting up template information
|
||||
subDirs := []string{"internal/model"} // only the specified subdirectory is processed, if empty or no subdirectory is specified, it means all files
|
||||
ignoreDirs := []string{} // specify the directory in the subdirectory where processing is ignored
|
||||
ignoreFiles := []string{ // specify the files in the subdirectory to be ignored for processing
|
||||
"userExample.go", "init_test.go",
|
||||
}
|
||||
|
||||
r.SetSubDirsAndFiles(subDirs)
|
||||
r.SetIgnoreSubDirs(ignoreDirs...)
|
||||
r.SetIgnoreSubFiles(ignoreFiles...)
|
||||
fields := g.addFields(r)
|
||||
r.SetReplacementFields(fields)
|
||||
_ = r.SetOutputDir(g.outPath, subTplName)
|
||||
if err := r.SaveFiles(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return r.GetOutputDir(), nil
|
||||
}
|
||||
|
||||
func (g *dbInitGenerator) addFields(r replacer.Replacer) []replacer.Field {
|
||||
var fields []replacer.Field
|
||||
|
||||
fields = append(fields, generate.DeleteCodeMark(r, generate.ModelInitDBFile, generate.StartMark, generate.EndMark)...)
|
||||
fields = append(fields, []replacer.Field{
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/internal",
|
||||
New: g.moduleName + "/internal",
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{
|
||||
Old: "github.com/zhufuyi/sponge/configs",
|
||||
New: g.moduleName + "/configs",
|
||||
IsCaseSensitive: false,
|
||||
},
|
||||
{ // replace the contents of the model/init.go file
|
||||
Old: generate.ModelInitDBFileMark,
|
||||
New: generate.GetInitDataBaseCode(g.dbDriver),
|
||||
},
|
||||
}...)
|
||||
|
||||
return fields
|
||||
}
|
|
@ -3,7 +3,6 @@ package patch
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/zhufuyi/sponge/cmd/sponge/commands/generate"
|
||||
|
@ -129,21 +128,3 @@ func addMysqlAndRedisInitFields(moduleName string) []replacer.Field {
|
|||
|
||||
return fields
|
||||
}
|
||||
|
||||
// get moduleName and serverName from directory
|
||||
func getNamesFromOutDir(dir string) (moduleName string, serverName string) {
|
||||
if dir == "" {
|
||||
return "", ""
|
||||
}
|
||||
data, err := os.ReadFile(dir + "/docs/gen.info")
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
ms := strings.Split(string(data), ",")
|
||||
if len(ms) != 2 {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
return ms[0], ms[1]
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ var (
|
|||
func NewRootCMD() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "sponge",
|
||||
Long: `Sponge is a powerful golang productivity tool that integrates automatic code generation,
|
||||
web and microservice framework, basic development framework.
|
||||
Long: `Sponge is a powerful golang basic development framework that integrates automatic code generation,
|
||||
web and microservice framework.
|
||||
repo: https://github.com/zhufuyi/sponge
|
||||
docs: https://go-sponge.com`,
|
||||
SilenceErrors: true,
|
||||
|
@ -35,6 +35,7 @@ docs: https://go-sponge.com`,
|
|||
GenWebCommand(),
|
||||
GenMicroCommand(),
|
||||
generate.ConfigCommand(),
|
||||
generate.ConfigmapCommand(),
|
||||
OpenUICommand(),
|
||||
MergeCommand(),
|
||||
PatchCommand(),
|
||||
|
|
|
@ -14,11 +14,12 @@ import (
|
|||
|
||||
"github.com/zhufuyi/sponge/internal/ecode"
|
||||
"github.com/zhufuyi/sponge/pkg/errcode"
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm"
|
||||
"github.com/zhufuyi/sponge/pkg/gin/response"
|
||||
"github.com/zhufuyi/sponge/pkg/gobash"
|
||||
"github.com/zhufuyi/sponge/pkg/gofile"
|
||||
"github.com/zhufuyi/sponge/pkg/krand"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
@ -28,8 +29,15 @@ var (
|
|||
saveDir = fmt.Sprintf("%s/.%s", getSpongeDir(), recordDirName)
|
||||
)
|
||||
|
||||
type mysqlForm struct {
|
||||
Dsn string `json:"dsn" binding:"required"`
|
||||
const (
|
||||
dbDriverMysql = "mysql"
|
||||
dbDriverPostgresql = "postgresql"
|
||||
dbDriverTidb = "tidb"
|
||||
)
|
||||
|
||||
type dbInfoForm struct {
|
||||
Dsn string `json:"dsn" binding:"required"`
|
||||
DbDriver string `json:"dbDriver"`
|
||||
}
|
||||
|
||||
type kv struct {
|
||||
|
@ -37,23 +45,47 @@ type kv struct {
|
|||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// ListDbDrivers list db drivers
|
||||
func ListDbDrivers(c *gin.Context) {
|
||||
dbDrivers := []string{
|
||||
dbDriverMysql,
|
||||
dbDriverPostgresql,
|
||||
dbDriverTidb,
|
||||
}
|
||||
|
||||
data := []kv{}
|
||||
for _, driver := range dbDrivers {
|
||||
data = append(data, kv{
|
||||
Label: driver,
|
||||
Value: driver,
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c, data)
|
||||
}
|
||||
|
||||
// ListTables list tables
|
||||
func ListTables(c *gin.Context) {
|
||||
form := &mysqlForm{}
|
||||
form := &dbInfoForm{}
|
||||
err := c.ShouldBindJSON(form)
|
||||
if err != nil {
|
||||
response.Error(c, ecode.InvalidParams.WithDetails(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
db, err := mysql.Init(form.Dsn)
|
||||
if err != nil {
|
||||
response.Error(c, ecode.InternalServerError.WithDetails(err.Error()))
|
||||
var tables []string
|
||||
switch strings.ToLower(form.DbDriver) {
|
||||
case dbDriverMysql, dbDriverTidb:
|
||||
tables, err = getMysqlTables(form.Dsn)
|
||||
case dbDriverPostgresql:
|
||||
tables, err = getPostgresqlTables(form.Dsn)
|
||||
case "":
|
||||
response.Error(c, ecode.InternalServerError.WithDetails("database type is empty"))
|
||||
return
|
||||
default:
|
||||
response.Error(c, ecode.InternalServerError.WithDetails("unsupported database driver: "+form.DbDriver))
|
||||
return
|
||||
}
|
||||
|
||||
var tables []string
|
||||
err = db.Raw("show tables").Scan(&tables).Error
|
||||
if err != nil {
|
||||
response.Error(c, ecode.InternalServerError.WithDetails(err.Error()))
|
||||
return
|
||||
|
@ -340,3 +372,37 @@ func getSpongeDir() string {
|
|||
|
||||
return dir
|
||||
}
|
||||
|
||||
func getMysqlTables(dsn string) ([]string, error) {
|
||||
dsn = utils.AdaptiveMysqlDsn(dsn)
|
||||
db, err := ggorm.InitMysql(dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer ggorm.CloseDB(db) //nolint
|
||||
|
||||
var tables []string
|
||||
err = db.Raw("show tables").Scan(&tables).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tables, nil
|
||||
}
|
||||
|
||||
func getPostgresqlTables(dsn string) ([]string, error) {
|
||||
dsn = utils.AdaptivePostgresqlDsn(dsn)
|
||||
db, err := ggorm.InitPostgresql(dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer ggorm.CloseDB(db) //nolint
|
||||
|
||||
var tables []string
|
||||
err = db.Raw("SELECT table_name FROM information_schema.tables WHERE table_schema = ?", "public").Scan(&tables).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tables, nil
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ func NewRouter(spongeAddr string, isLog bool) *gin.Engine {
|
|||
apiV1.POST("/generate", GenerateCode)
|
||||
apiV1.POST("/uploadFiles", UploadFiles)
|
||||
apiV1.POST("/listTables", ListTables)
|
||||
apiV1.GET("/listDrivers", ListDbDrivers)
|
||||
apiV1.GET("/record/:path", GetRecord)
|
||||
|
||||
return r
|
||||
|
|
|
@ -25,6 +25,7 @@ type parameters struct {
|
|||
RepoAddr string `json:"repoAddr"`
|
||||
ProtobufFile string `json:"-"`
|
||||
YamlFile string `json:"-"`
|
||||
DbDriver string `json:"dbDriver"`
|
||||
Dsn string `json:"dsn"`
|
||||
TableName string `json:"tableName"`
|
||||
Embed bool `json:"embed"`
|
||||
|
@ -34,7 +35,7 @@ type parameters struct {
|
|||
|
||||
type record struct {
|
||||
mux *sync.Mutex
|
||||
HostRecord map[string]*parameters
|
||||
HostRecord map[string]*parameters // [ip + "-" + commandType]:parameters
|
||||
}
|
||||
|
||||
func initRecord() {
|
||||
|
@ -114,6 +115,8 @@ func parseCommandArgs(args []string) *parameters {
|
|||
switch ss[0] {
|
||||
case "--db-dsn":
|
||||
params.Dsn = val
|
||||
case "--db-driver":
|
||||
params.DbDriver = val
|
||||
case "--db-table":
|
||||
params.TableName = val
|
||||
case "--embed":
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>sponge generate code</title><link rel=icon type=image/png sizes=32x32 href="/static/favicon.png?v=1.0"><script type=text/javascript src=/static/appConfig.js async></script><link href=/static/css/app.d073a336e9e3cecd4c7996f962e12160.css rel=stylesheet></head><body style="margin: 0px; padding: 0px;"><style>.el-tooltip__popper {box-shadow: 3px 3px 10px 5px #d3d3d6;border-width: 0px !important;}
|
||||
.el-tooltip__popper[x-placement^="top"] .popper__arrow:after {border-top-color: #dcdfe6 !important;}</style><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.f99d8d10a7d35fb68864.js></script><script type=text/javascript src=/static/js/app.9b5672cd500e42cf6eae.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>sponge generate code</title><link rel=icon type=image/png sizes=32x32 href="/static/favicon.png?v=1.0"><script type=text/javascript src=/static/appConfig.js async></script><link href=/static/css/app.f965da2e3508ddc9ca932590fe4d1582.css rel=stylesheet></head><body style="margin: 0px; padding: 0px;"><style>.el-tooltip__popper {box-shadow: 3px 3px 10px 5px #d3d3d6;border-width: 0px !important;}
|
||||
.el-tooltip__popper[x-placement^="top"] .popper__arrow:after {border-top-color: #dcdfe6 !important;}</style><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.d8cdb3748af43d2ae51a.js></script><script type=text/javascript src=/static/js/app.050e4b824a5634db92e7.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 12581c31f03a32ab06d7"],"names":["parentJsonpFunction","window","chunkIds","moreModules","executeModules","moduleId","chunkId","result","i","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","call","modules","shift","__webpack_require__","s","installedModules","2","exports","module","l","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","p","oe","err","console","error"],"mappings":"aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,IAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA","file":"static/js/manifest.2ae2e69a05c33dfc65f8.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 12581c31f03a32ab06d7"],"sourceRoot":""}
|
||||
{"version":3,"sources":["webpack:///webpack/bootstrap 3ba9677dd8fa41dfdceb"],"names":["parentJsonpFunction","window","chunkIds","moreModules","executeModules","moduleId","chunkId","result","i","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","call","modules","shift","__webpack_require__","s","installedModules","2","exports","module","l","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","p","oe","err","console","error"],"mappings":"aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,IAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA","file":"static/js/manifest.2ae2e69a05c33dfc65f8.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 3ba9677dd8fa41dfdceb"],"sourceRoot":""}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,55 +2,54 @@
|
|||
|
||||
# app settings
|
||||
app:
|
||||
name: "serverNameExample" # server name
|
||||
env: "dev" # runtime environment, dev: development environment, prod: production environment, test: test environment
|
||||
name: "serverNameExample" # server name
|
||||
env: "dev" # runtime environment, dev: development environment, prod: production environment, test: test environment
|
||||
version: "v0.0.0"
|
||||
host: "127.0.0.1" # domain or ip, for service registration
|
||||
enableStat: true # whether to turn on printing statistics, true:enable, false:disable
|
||||
enableMetrics: true # whether to turn on indicator collection, true:enable, false:disable
|
||||
enableHTTPProfile: false # whether to turn on performance analysis, true:enable, false:disable
|
||||
enableLimit: false # whether to turn on rate limiting (adaptive), true:on, false:off
|
||||
host: "127.0.0.1" # domain or ip, for service registration
|
||||
enableStat: true # whether to turn on printing statistics, true:enable, false:disable
|
||||
enableMetrics: true # whether to turn on indicator collection, true:enable, false:disable
|
||||
enableHTTPProfile: false # whether to turn on performance analysis, true:enable, false:disable
|
||||
enableLimit: false # whether to turn on rate limiting (adaptive), true:on, false:off
|
||||
enableCircuitBreaker: false # whether to turn on circuit breaker(adaptive), true:on, false:off
|
||||
enableTrace: false # whether to turn on trace, true:enable, false:disable, if true jaeger configuration must be set
|
||||
enableTrace: false # whether to turn on trace, true:enable, false:disable, if true jaeger configuration must be set
|
||||
tracingSamplingRate: 1.0 # tracing sampling rate, between 0 and 1, 0 means no sampling, 1 means sampling all links
|
||||
registryDiscoveryType: "" # registry and discovery types: consul, etcd, nacos, if empty, registration and discovery are not used
|
||||
cacheType: "" # cache type, if empty, the cache is not used, Support for "memory" and "redis", if set to redis, must set redis configuration
|
||||
registryDiscoveryType: "" # registry and discovery types: consul, etcd, nacos, if empty, registration and discovery are not used
|
||||
cacheType: "" # cache type, if empty, the cache is not used, support for "memory" and "redis", if set to redis, must set redis configuration
|
||||
|
||||
|
||||
# todo generate http or rpc server configuration here
|
||||
# delete the templates code start
|
||||
# http server settings
|
||||
http:
|
||||
port: 8080 # listen port
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second), if enableHTTPProfile is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s
|
||||
port: 8080 # listen port
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second), if enableHTTPProfile is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s
|
||||
|
||||
|
||||
# grpc server settings
|
||||
grpc:
|
||||
port: 8282 # listen port
|
||||
httpPort: 8283 # profile and metrics ports
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second)
|
||||
enableToken: false # whether to enable server-side token authentication, default appID=grpc, appKey=123456
|
||||
port: 8282 # listen port
|
||||
httpPort: 8283 # profile and metrics ports
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second)
|
||||
enableToken: false # whether to enable server-side token authentication, default appID=grpc, appKey=123456
|
||||
# serverSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
# if type="one-way", it means server-side certification, only the fields 'certFile' and 'keyFile' should be filled in
|
||||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
serverSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
caFile: "" # ca certificate file, valid only in "two-way", absolute path
|
||||
certFile: "" # server side cert file, absolute path
|
||||
keyFile: "" # server side key file, absolute path
|
||||
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
caFile: "" # ca certificate file, valid only in "two-way", absolute path
|
||||
certFile: "" # server side cert file, absolute path
|
||||
keyFile: "" # server side key file, absolute path
|
||||
|
||||
|
||||
# grpc client-side settings, support for setting up multiple grpc clients.
|
||||
grpcClient:
|
||||
- name: "serverNameExample" # grpc service name, used for service discovery
|
||||
host: "127.0.0.1" # grpc service address, used for direct connection
|
||||
port: 8282 # grpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
|
||||
- name: "serverNameExample" # grpc service name, used for service discovery
|
||||
host: "127.0.0.1" # grpc service address, used for direct connection
|
||||
port: 8282 # grpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
|
||||
enableLoadBalance: true # whether to turn on the load balancer
|
||||
# clientSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
|
@ -58,51 +57,67 @@ grpcClient:
|
|||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
clientSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
caFile: "" # client side ca file, valid only in "two-way", absolute path
|
||||
certFile: "" # client side cert file, absolute path, if secureType="one-way", fill in server side cert file here
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
clientToken:
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key
|
||||
# delete the templates code end
|
||||
|
||||
|
||||
# logger settings
|
||||
logger:
|
||||
level: "info" # output log levels debug, info, warn, error, default is debug
|
||||
format: "console" # output format, console or json, default is console
|
||||
isSave: false # false:output to terminal, true:output to file, default is false
|
||||
#logFileConfig: # Effective when isSave=true
|
||||
#filename: "out.log" # File name (default is out.log)
|
||||
#maxSize: 20 # Maximum file size (MB, default is 10MB)
|
||||
format: "console" # output format, console or json, default is console
|
||||
isSave: false # false:output to terminal, true:output to file, default is false
|
||||
#logFileConfig: # Effective when isSave=true
|
||||
#filename: "out.log" # File name (default is out.log)
|
||||
#maxSize: 20 # Maximum file size (MB, default is 10MB)
|
||||
#maxBackups: 50 # Maximum number of old files to retain (default is 100)
|
||||
#maxAge: 15 # Maximum number of days to retain old files (default is 30 days)
|
||||
#maxAge: 15 # Maximum number of days to retain old files (default is 30 days)
|
||||
#isCompression: true # Whether to compress/archive old files (default is false)
|
||||
|
||||
|
||||
# mysql settings
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
maxIdleConns: 3 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes
|
||||
#slavesDsn: # sets slaves mysql dsn, array type
|
||||
# - "your slave dsn 1"
|
||||
# - "your slave dsn 2"
|
||||
#mastersDsn: # sets masters mysql dsn, array type, non-required field, if there is only one master, there is no need to set the mastersDsn field, the default dsn field is mysql master.
|
||||
# - "your master dsn"
|
||||
# todo generate the database configuration here
|
||||
# delete the templates code start
|
||||
# database setting
|
||||
database:
|
||||
driver: "mysql" # database driver, currently support mysql, postgres, tidb
|
||||
# mysql settings
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
maxIdleConns: 10 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes
|
||||
#slavesDsn: # sets slaves mysql dsn, array type
|
||||
# - "your slave dsn 1"
|
||||
# - "your slave dsn 2"
|
||||
#mastersDsn: # sets masters mysql dsn, array type, non-required field, if there is only one master, there is no need to set the mastersDsn field, the default dsn field is mysql master.
|
||||
# - "your master dsn"
|
||||
|
||||
# postgresql settings
|
||||
postgresql:
|
||||
# dsn format, <user>:<pass>@127.0.0.1:5432/<db>?[k=v& ......]
|
||||
dsn: "root:123456@192.168.3.37:5432/account?sslmode=disable"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
maxIdleConns: 10 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes
|
||||
|
||||
# delete the templates code end
|
||||
|
||||
# redis settings
|
||||
redis:
|
||||
# dsn format, [user]:<pass>@127.0.0.1:6379/[db], the default user is default, redis version 6.0 and above only supports user.
|
||||
dsn: "default:123456@192.168.3.37:6379/0"
|
||||
dialTimeout: 10 # connection timeout, unit(second)
|
||||
readTimeout: 2 # read timeout, unit(second)
|
||||
writeTimeout: 2 # write timeout, unit(second)
|
||||
dialTimeout: 10 # connection timeout, unit(second)
|
||||
readTimeout: 2 # read timeout, unit(second)
|
||||
writeTimeout: 2 # write timeout, unit(second)
|
||||
|
||||
|
||||
# jaeger settings
|
||||
|
@ -125,4 +140,4 @@ etcd:
|
|||
nacosRd:
|
||||
ipAddr: "192.168.3.37"
|
||||
port: 8848
|
||||
namespaceID: "3454d2b5-2455-4d0e-bf6d-e033b086bb4c" # namespace id
|
||||
namespaceID: "3454d2b5-2455-4d0e-bf6d-e033b086bb4c" # namespace id
|
||||
|
|
|
@ -5,115 +5,4 @@ metadata:
|
|||
namespace: project-name-example
|
||||
data:
|
||||
serverNameExample.yml: |-
|
||||
# app settings
|
||||
app:
|
||||
name: "serverNameExample" # server name
|
||||
env: "dev" # runtime environment, dev: development environment, prod: production environment, test: test environment
|
||||
version: "v0.0.0"
|
||||
host: "127.0.0.1" # domain or ip, for service registration
|
||||
enablePprof: true # whether to turn on performance analysis, true:enable, false:disable
|
||||
enableStat: true # whether to turn on printing statistics, true:enable, false:disable
|
||||
enableMetrics: true # whether to turn on indicator collection, true:enable, false:disable
|
||||
enableLimit: false # whether to turn on rate limiting (adaptive), true:on, false:off
|
||||
enableCircuitBreaker: false # whether to turn on circuit breaker(adaptive), true:on, false:off
|
||||
enableTrace: false # whether to turn on enable trace, true:enable, false:disable, if true jaeger configuration must be set
|
||||
tracingSamplingRate: 1.0 # tracing sampling rate, between 0 and 1, 0 means no sampling, 1 means sampling all links
|
||||
registryDiscoveryType: "" # registry and discovery types: consul, etcd, nacos, if empty, registration and discovery are not used
|
||||
cacheType: "memory" # cache type, memory, redis, if set to redis, must set redis configuration
|
||||
|
||||
|
||||
# http server settings
|
||||
http:
|
||||
port: 8080 # listening port
|
||||
readTimeout: 3 # read timeout, unit(second)
|
||||
writeTimeout: 60 # write timeout, unit(second), if enablePprof is true, it needs to be greater than 60s, the default value for pprof to do profiling is 60s
|
||||
|
||||
|
||||
# grpc server settings
|
||||
grpc:
|
||||
port: 8282 # listening port
|
||||
httpPort: 8283 # get pprof and monitor indicator ports
|
||||
readTimeout: 5 # read timeout, unit(second)
|
||||
writeTimeout: 5 # write timeout, unit(second)
|
||||
enableToken: false # whether to enable server-side token authentication, default appID=grpc, appKey=123456
|
||||
# serverSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
# if type="one-way", it means server-side certification, only the fields 'certFile' and 'keyFile' should be filled in
|
||||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
serverSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
certFile: "" # server side cert file, absolute path
|
||||
keyFile: "" # server side key file, absolute path
|
||||
caFile: "" # ca certificate file, valid only in "two-way", absolute path
|
||||
|
||||
|
||||
# grpc client settings, multiple rpc services can be set up
|
||||
grpcClient:
|
||||
- name: "your-rpc-server-name" # rpc server name, used for service discovery
|
||||
host: "127.0.0.1" # rpc service address, used for direct connection
|
||||
port: 8282 # rpc service port
|
||||
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, registration and discovery are not used
|
||||
enableLoadBalance: false # whether to turn on the load balancer
|
||||
# clientSecure parameter setting
|
||||
# if type="", it means no secure connection, no need to fill in any parameters
|
||||
# if type="one-way", it means server-side certification, only the fields 'serverName' and 'certFile' should be filled in
|
||||
# if type="two-way", it means both client and server side certification, fill in all fields
|
||||
clientSecure:
|
||||
type: "" # secures type, "", "one-way", "two-way"
|
||||
serverName: "" # server name, e.g. *.foo.com
|
||||
caFile: "" # client side ca file, valid only in "two-way", absolute path
|
||||
certFile: "" # client side cert file, absolute path, if secureType="one-way", fill in server side cert file here
|
||||
keyFile: "" # client side key file, valid only in "two-way", absolute path
|
||||
clientToken:
|
||||
enable: false # whether to enable token authentication
|
||||
appID: "" # app id
|
||||
appKey: "" # app key
|
||||
|
||||
# logger settings
|
||||
logger:
|
||||
level: "info" # output log levels debug, info, warn, error, default is debug
|
||||
format: "console" # output format, console or json, default is console
|
||||
isSave: false # false:output to terminal, true:output to file, default is false
|
||||
|
||||
|
||||
# mysql settings
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
enableLog: true # whether to turn on printing of all logs
|
||||
slowThreshold: 0 # if greater than 0, only print logs with a time greater than the threshold, with a higher priority than enableLog, in (ms)
|
||||
maxIdleConns: 3 # set the maximum number of connections in the idle connection pool
|
||||
maxOpenConns: 100 # set the maximum number of open database connections
|
||||
connMaxLifetime: 30 # sets the maximum time for which the connection can be reused, in minutes
|
||||
|
||||
|
||||
# redis settings
|
||||
redis:
|
||||
# dsn format, [user]:<pass>@]127.0.0.1:6379/[db], the default user is default
|
||||
dsn: "default:123456@192.168.3.37:6379/0"
|
||||
dialTimeout: 10 # connection timeout, unit(second)
|
||||
readTimeout: 2 # read timeout, unit(second)
|
||||
writeTimeout: 2 # write timeout, unit(second)
|
||||
|
||||
|
||||
# jaeger settings
|
||||
jaeger:
|
||||
agentHost: "192.168.3.37"
|
||||
agentPort: 6831
|
||||
|
||||
|
||||
# consul settings
|
||||
consul:
|
||||
addr: "192.168.3.37:8500"
|
||||
|
||||
|
||||
# etcd settings
|
||||
etcd:
|
||||
addrs: ["192.168.3.37:2379"]
|
||||
|
||||
|
||||
# nacos settings, used in service registration discovery
|
||||
nacosRd:
|
||||
ipAddr: "192.168.3.37"
|
||||
port: 8848
|
||||
namespaceID: "3454d2b5-2455-4d0e-bf6d-e033b086bb4c" # namespace id
|
||||
# todo generate server configuration code here
|
||||
|
|
|
@ -134,7 +134,7 @@ const docTemplate = `{
|
|||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "last id, default is MaxInt64",
|
||||
"description": "last id, default is MaxInt32",
|
||||
"name": "lastID",
|
||||
"in": "query",
|
||||
"required": true
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "last id, default is MaxInt64",
|
||||
"description": "last id, default is MaxInt32",
|
||||
"name": "lastID",
|
||||
"in": "query",
|
||||
"required": true
|
||||
|
|
|
@ -415,7 +415,7 @@ paths:
|
|||
- application/json
|
||||
description: list of userExamples by last id and limit
|
||||
parameters:
|
||||
- description: last id, default is MaxInt64
|
||||
- description: last id, default is MaxInt32
|
||||
in: query
|
||||
name: lastID
|
||||
required: true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Package config is a package that parses configuration files into structures, and supports
|
||||
// parsing yaml, json and toml files., code generated by https://github.com/zhufuyi/sponge.
|
||||
// code generated by https://github.com/zhufuyi/sponge
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
|
@ -31,13 +31,13 @@ func Set(conf *Config) {
|
|||
type Config struct {
|
||||
App App `yaml:"app" json:"app"`
|
||||
Consul Consul `yaml:"consul" json:"consul"`
|
||||
Database Database `yaml:"database" json:"database"`
|
||||
Etcd Etcd `yaml:"etcd" json:"etcd"`
|
||||
Grpc Grpc `yaml:"grpc" json:"grpc"`
|
||||
GrpcClient []GrpcClient `yaml:"grpcClient" json:"grpcClient"`
|
||||
HTTP HTTP `yaml:"http" json:"http"`
|
||||
Jaeger Jaeger `yaml:"jaeger" json:"jaeger"`
|
||||
Logger Logger `yaml:"logger" json:"logger"`
|
||||
Mysql Mysql `yaml:"mysql" json:"mysql"`
|
||||
NacosRd NacosRd `yaml:"nacosRd" json:"nacosRd"`
|
||||
Redis Redis `yaml:"redis" json:"redis"`
|
||||
}
|
||||
|
@ -110,7 +110,14 @@ type Mysql struct {
|
|||
MaxIdleConns int `yaml:"maxIdleConns" json:"maxIdleConns"`
|
||||
MaxOpenConns int `yaml:"maxOpenConns" json:"maxOpenConns"`
|
||||
SlavesDsn []string `yaml:"slavesDsn" json:"slavesDsn"`
|
||||
SlowThreshold int `yaml:"slowThreshold" json:"slowThreshold"`
|
||||
}
|
||||
|
||||
type Postgresql struct {
|
||||
ConnMaxLifetime int `yaml:"connMaxLifetime" json:"connMaxLifetime"`
|
||||
Dsn string `yaml:"dsn" json:"dsn"`
|
||||
EnableLog bool `yaml:"enableLog" json:"enableLog"`
|
||||
MaxIdleConns int `yaml:"maxIdleConns" json:"maxIdleConns"`
|
||||
MaxOpenConns int `yaml:"maxOpenConns" json:"maxOpenConns"`
|
||||
}
|
||||
|
||||
type Redis struct {
|
||||
|
@ -120,6 +127,12 @@ type Redis struct {
|
|||
WriteTimeout int `yaml:"writeTimeout" json:"writeTimeout"`
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
Driver string `yaml:"driver" json:"driver"`
|
||||
Mysql Mysql `yaml:"mysql" json:"mysql"`
|
||||
Postgresql Postgresql `yaml:"postgresql" json:"postgresql"`
|
||||
}
|
||||
|
||||
type Grpc struct {
|
||||
EnableToken bool `yaml:"enableToken" json:"enableToken"`
|
||||
HTTPPort int `yaml:"httpPort" json:"httpPort"`
|
||||
|
@ -145,4 +158,4 @@ type HTTP struct {
|
|||
Port int `yaml:"port" json:"port"`
|
||||
ReadTimeout int `yaml:"readTimeout" json:"readTimeout"`
|
||||
WriteTimeout int `yaml:"writeTimeout" json:"writeTimeout"`
|
||||
}
|
||||
}
|
|
@ -25,4 +25,4 @@ type Nacos struct {
|
|||
NamespaceID string `yaml:"namespaceID" json:"namespaceID"`
|
||||
Port int `yaml:"port" json:"port"`
|
||||
Scheme string `yaml:"scheme" json:"scheme"`
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/zhufuyi/sponge/internal/model"
|
||||
|
||||
cacheBase "github.com/zhufuyi/sponge/pkg/cache"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"github.com/zhufuyi/sponge/internal/cache"
|
||||
"github.com/zhufuyi/sponge/internal/model"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
"github.com/zhufuyi/sponge/pkg/gotest"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/zhufuyi/sponge/pkg/gin/middleware"
|
||||
"github.com/zhufuyi/sponge/pkg/gin/response"
|
||||
"github.com/zhufuyi/sponge/pkg/logger"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -204,7 +203,7 @@ func (h *userExampleHandler) GetByID(c *gin.Context) {
|
|||
ctx := middleware.WrapCtx(c)
|
||||
userExample, err := h.iDao.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, query.ErrNotFound) {
|
||||
if errors.Is(err, model.ErrRecordNotFound) {
|
||||
logger.Warn("GetByID not found", logger.Err(err), logger.Any("id", id), middleware.GCtxRequestIDField(c))
|
||||
response.Error(c, ecode.NotFound)
|
||||
} else {
|
||||
|
@ -252,7 +251,7 @@ func (h *userExampleHandler) GetByCondition(c *gin.Context) {
|
|||
ctx := middleware.WrapCtx(c)
|
||||
userExample, err := h.iDao.GetByCondition(ctx, &form.Conditions)
|
||||
if err != nil {
|
||||
if errors.Is(err, query.ErrNotFound) {
|
||||
if errors.Is(err, model.ErrRecordNotFound) {
|
||||
logger.Warn("GetByCondition not found", logger.Err(err), logger.Any("form", form), middleware.GCtxRequestIDField(c))
|
||||
response.Error(c, ecode.NotFound)
|
||||
} else {
|
||||
|
@ -323,7 +322,7 @@ func (h *userExampleHandler) ListByIDs(c *gin.Context) {
|
|||
// @Tags userExample
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param lastID query int true "last id, default is MaxInt64"
|
||||
// @Param lastID query int true "last id, default is MaxInt32"
|
||||
// @Param limit query int false "size in each page" default(10)
|
||||
// @Param sort query string false "sort by column name of table, and the "-" sign before column name indicates reverse order" default(-id)
|
||||
// @Success 200 {object} types.ListUserExamplesRespond{}
|
||||
|
@ -331,7 +330,7 @@ func (h *userExampleHandler) ListByIDs(c *gin.Context) {
|
|||
func (h *userExampleHandler) ListByLastID(c *gin.Context) {
|
||||
lastID := utils.StrToUint64(c.Query("lastID"))
|
||||
if lastID == 0 {
|
||||
lastID = math.MaxInt64
|
||||
lastID = math.MaxInt32
|
||||
}
|
||||
limit := utils.StrToInt(c.Query("limit"))
|
||||
if limit == 0 {
|
||||
|
|
|
@ -11,9 +11,9 @@ import (
|
|||
"github.com/zhufuyi/sponge/internal/ecode"
|
||||
"github.com/zhufuyi/sponge/internal/model"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
"github.com/zhufuyi/sponge/pkg/gin/middleware"
|
||||
"github.com/zhufuyi/sponge/pkg/logger"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
@ -125,7 +125,7 @@ func (h *userExamplePbHandler) GetByID(ctx context.Context, req *serverNameExamp
|
|||
|
||||
record, err := h.userExampleDao.GetByID(ctx, req.Id)
|
||||
if err != nil {
|
||||
if errors.Is(err, query.ErrNotFound) {
|
||||
if errors.Is(err, model.ErrRecordNotFound) {
|
||||
logger.Warn("GetByID error", logger.Err(err), logger.Any("id", req.Id), middleware.CtxRequestIDField(ctx))
|
||||
return nil, ecode.NotFound.Err()
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ func (h *userExamplePbHandler) GetByCondition(ctx context.Context, req *serverNa
|
|||
|
||||
record, err := h.userExampleDao.GetByCondition(ctx, conditions)
|
||||
if err != nil {
|
||||
if errors.Is(err, query.ErrNotFound) {
|
||||
if errors.Is(err, model.ErrRecordNotFound) {
|
||||
logger.Warn("GetByID error", logger.Err(err), logger.Any("req", req), middleware.CtxRequestIDField(ctx))
|
||||
return nil, ecode.NotFound.Err()
|
||||
}
|
||||
|
@ -293,7 +293,10 @@ func convertUserExamplePb(record *model.UserExample) (*serverNameExampleV1.UserE
|
|||
return nil, err
|
||||
}
|
||||
value.Id = record.ID
|
||||
// todo generate the conversion createdAt and updatedAt code here
|
||||
// delete the templates code start
|
||||
value.CreatedAt = record.CreatedAt.Unix()
|
||||
value.UpdatedAt = record.UpdatedAt.Unix()
|
||||
// delete the templates code end
|
||||
return value, nil
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
"github.com/zhufuyi/sponge/internal/model"
|
||||
"github.com/zhufuyi/sponge/internal/types"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
"github.com/zhufuyi/sponge/pkg/gohttp"
|
||||
"github.com/zhufuyi/sponge/pkg/gotest"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/zhufuyi/sponge/internal/config"
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm"
|
||||
"github.com/zhufuyi/sponge/pkg/goredis"
|
||||
"github.com/zhufuyi/sponge/pkg/logger"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"gorm.io/gorm"
|
||||
|
@ -35,84 +35,6 @@ var (
|
|||
once3 sync.Once
|
||||
)
|
||||
|
||||
// InitMysql connect mysql
|
||||
func InitMysql() {
|
||||
opts := []mysql.Option{
|
||||
mysql.WithMaxIdleConns(config.Get().Mysql.MaxIdleConns),
|
||||
mysql.WithMaxOpenConns(config.Get().Mysql.MaxOpenConns),
|
||||
mysql.WithConnMaxLifetime(time.Duration(config.Get().Mysql.ConnMaxLifetime) * time.Minute),
|
||||
}
|
||||
if config.Get().Mysql.EnableLog {
|
||||
opts = append(opts,
|
||||
mysql.WithLogging(logger.Get()),
|
||||
mysql.WithLogRequestIDKey("request_id"),
|
||||
)
|
||||
}
|
||||
|
||||
if config.Get().App.EnableTrace {
|
||||
opts = append(opts, mysql.WithEnableTrace())
|
||||
}
|
||||
|
||||
// setting mysql slave and master dsn addresses,
|
||||
// if there is no read/write separation, you can comment out the following piece of code
|
||||
opts = append(opts, mysql.WithRWSeparation(
|
||||
config.Get().Mysql.SlavesDsn,
|
||||
config.Get().Mysql.MastersDsn...,
|
||||
))
|
||||
|
||||
// add custom gorm plugin
|
||||
//opts = append(opts, mysql.WithGormPlugin(yourPlugin))
|
||||
|
||||
var err error
|
||||
db, err = mysql.Init(config.Get().Mysql.Dsn, opts...)
|
||||
if err != nil {
|
||||
panic("mysql.Init error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// GetDB get db
|
||||
func GetDB() *gorm.DB {
|
||||
if db == nil {
|
||||
once1.Do(func() {
|
||||
InitMysql()
|
||||
})
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// CloseMysql close mysql
|
||||
func CloseMysql() error {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkInUse(sqlDB, time.Second*5)
|
||||
|
||||
return sqlDB.Close()
|
||||
}
|
||||
|
||||
func checkInUse(sqlDB *sql.DB, duration time.Duration) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), duration) //nolint
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Millisecond * 500):
|
||||
if v := sqlDB.Stats().InUse; v == 0 {
|
||||
return
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
// CacheType cache type
|
||||
type CacheType struct {
|
||||
CType string // cache type memory or redis
|
||||
|
@ -183,3 +105,110 @@ func CloseRedis() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
// todo generate initialisation database code here
|
||||
// delete the templates code start
|
||||
|
||||
// InitDB connect database
|
||||
func InitDB() {
|
||||
switch strings.ToLower(config.Get().Database.Driver) {
|
||||
case "mysql", "tidb":
|
||||
InitMysql()
|
||||
case "postgres", "postgresql":
|
||||
InitPostgresql()
|
||||
default:
|
||||
panic("unsupported database driver: " + config.Get().Database.Driver)
|
||||
}
|
||||
}
|
||||
|
||||
// GetDB get db
|
||||
func GetDB() *gorm.DB {
|
||||
if db == nil {
|
||||
once1.Do(func() {
|
||||
switch strings.ToLower(config.Get().Database.Driver) {
|
||||
case "mysql", "tidb":
|
||||
InitMysql()
|
||||
case "postgres", "postgresql":
|
||||
InitPostgresql()
|
||||
default:
|
||||
panic("unsupported database driver: " + config.Get().Database.Driver)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// InitMysql connect mysql
|
||||
func InitMysql() {
|
||||
opts := []ggorm.Option{
|
||||
ggorm.WithMaxIdleConns(config.Get().Database.Mysql.MaxIdleConns),
|
||||
ggorm.WithMaxOpenConns(config.Get().Database.Mysql.MaxOpenConns),
|
||||
ggorm.WithConnMaxLifetime(time.Duration(config.Get().Database.Mysql.ConnMaxLifetime) * time.Minute),
|
||||
}
|
||||
if config.Get().Database.Mysql.EnableLog {
|
||||
opts = append(opts,
|
||||
ggorm.WithLogging(logger.Get()),
|
||||
ggorm.WithLogRequestIDKey("request_id"),
|
||||
)
|
||||
}
|
||||
|
||||
if config.Get().App.EnableTrace {
|
||||
opts = append(opts, ggorm.WithEnableTrace())
|
||||
}
|
||||
|
||||
// setting mysql slave and master dsn addresses,
|
||||
// if there is no read/write separation, you can comment out the following piece of code
|
||||
opts = append(opts, ggorm.WithRWSeparation(
|
||||
config.Get().Database.Mysql.SlavesDsn,
|
||||
config.Get().Database.Mysql.MastersDsn...,
|
||||
))
|
||||
|
||||
// add custom gorm plugin
|
||||
//opts = append(opts, ggorm.WithGormPlugin(yourPlugin))
|
||||
|
||||
var dsn = utils.AdaptiveMysqlDsn(config.Get().Database.Mysql.Dsn)
|
||||
var err error
|
||||
db, err = ggorm.InitMysql(dsn, opts...)
|
||||
if err != nil {
|
||||
panic("ggorm.InitMysql error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// InitPostgresql connect postgresql
|
||||
func InitPostgresql() {
|
||||
opts := []ggorm.Option{
|
||||
ggorm.WithMaxIdleConns(config.Get().Database.Postgresql.MaxIdleConns),
|
||||
ggorm.WithMaxOpenConns(config.Get().Database.Postgresql.MaxOpenConns),
|
||||
ggorm.WithConnMaxLifetime(time.Duration(config.Get().Database.Postgresql.ConnMaxLifetime) * time.Minute),
|
||||
}
|
||||
if config.Get().Database.Postgresql.EnableLog {
|
||||
opts = append(opts,
|
||||
ggorm.WithLogging(logger.Get()),
|
||||
ggorm.WithLogRequestIDKey("request_id"),
|
||||
)
|
||||
}
|
||||
|
||||
if config.Get().App.EnableTrace {
|
||||
opts = append(opts, ggorm.WithEnableTrace())
|
||||
}
|
||||
|
||||
// add custom gorm plugin
|
||||
//opts = append(opts, ggorm.WithGormPlugin(yourPlugin))
|
||||
|
||||
var dsn = utils.AdaptivePostgresqlDsn(config.Get().Database.Postgresql.Dsn)
|
||||
var err error
|
||||
db, err = ggorm.InitPostgresql(dsn, opts...)
|
||||
if err != nil {
|
||||
panic("ggorm.InitPostgresql error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// delete the templates code end
|
||||
|
||||
// CloseDB close db
|
||||
func CloseDB() error {
|
||||
return ggorm.CloseDB(db)
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ func TestInitMysql(t *testing.T) {
|
|||
}
|
||||
|
||||
config.Get().App.EnableTrace = true
|
||||
config.Get().Mysql.EnableLog = true
|
||||
config.Get().Database.Mysql.EnableLog = true
|
||||
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
err = CloseMysql()
|
||||
err = CloseDB()
|
||||
assert.NoError(t, err)
|
||||
|
||||
utils.SafeRunWithTimeout(time.Second*2, func(cancel context.CancelFunc) {
|
||||
|
@ -41,20 +41,20 @@ func TestInitMysqlError(t *testing.T) {
|
|||
}
|
||||
|
||||
// change config error test
|
||||
config.Get().Mysql.Dsn = "root:123456@(127.0.0.1:3306)/test"
|
||||
config.Get().Database.Mysql.Dsn = "root:123456@(127.0.0.1:3306)/test"
|
||||
|
||||
utils.SafeRunWithTimeout(time.Second*2, func(cancel context.CancelFunc) {
|
||||
_ = CloseMysql()
|
||||
_ = CloseDB()
|
||||
InitMysql()
|
||||
assert.NotNil(t, db)
|
||||
cancel()
|
||||
})
|
||||
}
|
||||
|
||||
func TestCloseMysql(t *testing.T) {
|
||||
func TestCloseDB(t *testing.T) {
|
||||
defer func() { recover() }()
|
||||
db = &gorm.DB{}
|
||||
err := CloseMysql()
|
||||
err := CloseDB()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/zhufuyi/sponge/pkg/mysql"
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm"
|
||||
)
|
||||
|
||||
// UserExample object fields mapping table
|
||||
type UserExample struct {
|
||||
mysql.Model `gorm:"embedded"`
|
||||
ggorm.Model `gorm:"embedded"`
|
||||
|
||||
Name string `gorm:"column:name;NOT NULL" json:"name"` // username
|
||||
Password string `gorm:"column:password;NOT NULL" json:"password"` // password
|
||||
|
|
|
@ -12,9 +12,9 @@ import (
|
|||
"github.com/zhufuyi/sponge/internal/ecode"
|
||||
"github.com/zhufuyi/sponge/internal/model"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
"github.com/zhufuyi/sponge/pkg/grpc/interceptor"
|
||||
"github.com/zhufuyi/sponge/pkg/logger"
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -140,7 +140,7 @@ func (s *userExample) GetByID(ctx context.Context, req *serverNameExampleV1.GetU
|
|||
|
||||
record, err := s.iDao.GetByID(ctx, req.Id)
|
||||
if err != nil {
|
||||
if errors.Is(err, query.ErrNotFound) {
|
||||
if errors.Is(err, model.ErrRecordNotFound) {
|
||||
logger.Warn("GetByID error", logger.Err(err), logger.Any("id", req.Id), interceptor.ServerCtxRequestIDField(ctx))
|
||||
return nil, ecode.StatusNotFound.Err()
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ func (s *userExample) GetByCondition(ctx context.Context, req *serverNameExample
|
|||
|
||||
record, err := s.iDao.GetByCondition(ctx, conditions)
|
||||
if err != nil {
|
||||
if errors.Is(err, query.ErrNotFound) {
|
||||
if errors.Is(err, model.ErrRecordNotFound) {
|
||||
logger.Warn("GetByCondition error", logger.Err(err), logger.Any("req", req), interceptor.ServerCtxRequestIDField(ctx))
|
||||
return nil, ecode.StatusNotFound.Err()
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ func (s *userExample) ListByLastID(ctx context.Context, req *serverNameExampleV1
|
|||
return nil, ecode.StatusInvalidParams.Err()
|
||||
}
|
||||
if req.LastID == 0 {
|
||||
req.LastID = math.MaxInt64
|
||||
req.LastID = math.MaxInt32
|
||||
}
|
||||
if req.Limit == 0 {
|
||||
req.Limit = 10
|
||||
|
@ -313,7 +313,10 @@ func convertUserExample(record *model.UserExample) (*serverNameExampleV1.UserExa
|
|||
return nil, err
|
||||
}
|
||||
value.Id = record.ID
|
||||
// todo generate the conversion createdAt and updatedAt code here
|
||||
// delete the templates code start
|
||||
value.CreatedAt = record.CreatedAt.Unix()
|
||||
value.UpdatedAt = record.UpdatedAt.Unix()
|
||||
// delete the templates code end
|
||||
return value, nil
|
||||
}
|
||||
|
|
|
@ -134,8 +134,8 @@ func Test_service_userExample_methods(t *testing.T) {
|
|||
// todo type in the parameters to test
|
||||
req := &serverNameExampleV1.ListUserExampleByLastIDRequest{
|
||||
LastID: 0,
|
||||
Limit: 5,
|
||||
Sort: "-age",
|
||||
Limit: 10,
|
||||
Sort: "",
|
||||
}
|
||||
return cli.ListByLastID(ctx, req)
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@ package types
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
)
|
||||
|
||||
var _ time.Time
|
||||
|
|
|
@ -5,11 +5,12 @@ app:
|
|||
version: "v0.0.0"
|
||||
password: "123456"
|
||||
|
||||
database:
|
||||
driver: "mysql"
|
||||
# mysql settings
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
|
||||
mysql:
|
||||
# dsn format, <user>:<pass>@(127.0.0.1:3306)/<db>?[k=v& ......]
|
||||
dsn: "root:123456@(192.168.3.37:3306)/account?parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
|
||||
# redis settings
|
||||
redis:
|
||||
|
|
|
@ -17,6 +17,7 @@ type Responser interface {
|
|||
Error(ctx *gin.Context, err error) bool
|
||||
}
|
||||
|
||||
// NewResponse creates a new responser
|
||||
// Deprecated: NewResponse use NewResponser instead
|
||||
func NewResponse(isFromRPC bool) Responser {
|
||||
return &defaultResponse{isFromRPC, make(map[int]*Error), make(map[int]*RPCStatus)}
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
package ggorm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/opentelemetry-go-extra/otelgorm"
|
||||
mysqlDriver "gorm.io/driver/mysql"
|
||||
|
@ -68,7 +70,6 @@ func InitPostgresql(dsn string, opts ...Option) (*gorm.DB, error) {
|
|||
o.apply(opts...)
|
||||
|
||||
db, err := gorm.Open(postgres.Open(dsn), gormConfig(o))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -115,6 +116,36 @@ func InitTidb(dsn string, opts ...Option) (*gorm.DB, error) {
|
|||
// panic("not implemented")
|
||||
//}
|
||||
|
||||
// CloseDB close gorm db
|
||||
func CloseDB(db *gorm.DB) error {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkInUse(sqlDB, time.Second*5)
|
||||
|
||||
return sqlDB.Close()
|
||||
}
|
||||
|
||||
func checkInUse(sqlDB *sql.DB, duration time.Duration) {
|
||||
ctx, _ := context.WithTimeout(context.Background(), duration) //nolint
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Millisecond * 500):
|
||||
if v := sqlDB.Stats().InUse; v == 0 {
|
||||
return
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gorm setting
|
||||
func gormConfig(o *options) *gorm.Config {
|
||||
config := &gorm.Config{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ggorm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -17,6 +19,7 @@ func TestInitMysql(t *testing.T) {
|
|||
t.Logf(fmt.Sprintf("connect to mysql failed, err=%v, dsn=%s", err, dsn))
|
||||
return
|
||||
}
|
||||
defer CloseDB(db)
|
||||
|
||||
t.Logf("%+v", db.Name())
|
||||
}
|
||||
|
@ -28,6 +31,7 @@ func TestInitTidb(t *testing.T) {
|
|||
t.Logf(fmt.Sprintf("connect to mysql failed, err=%v, dsn=%s", err, dsn))
|
||||
return
|
||||
}
|
||||
defer CloseDB(db)
|
||||
|
||||
t.Logf("%+v", db.Name())
|
||||
}
|
||||
|
@ -40,6 +44,7 @@ func TestInitPostgresql(t *testing.T) {
|
|||
t.Logf(fmt.Sprintf("connect to postgresql failed, err=%v, dsn=%s", err, dsn))
|
||||
return
|
||||
}
|
||||
defer CloseDB(db)
|
||||
|
||||
t.Logf("%+v", db.Name())
|
||||
}
|
||||
|
@ -88,3 +93,12 @@ func TestGetTableName(t *testing.T) {
|
|||
name = GetTableName("table")
|
||||
assert.Empty(t, name)
|
||||
}
|
||||
|
||||
func TestCloseDB(t *testing.T) {
|
||||
sqlDB := new(sql.DB)
|
||||
checkInUse(sqlDB, time.Millisecond*100)
|
||||
checkInUse(sqlDB, time.Millisecond*600)
|
||||
db := new(gorm.DB)
|
||||
defer func() { recover() }()
|
||||
CloseDB(db)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/mysql/query"
|
||||
"github.com/zhufuyi/sponge/pkg/ggorm/query"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"gorm.io/gorm"
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
)
|
||||
|
||||
// Init mysql
|
||||
// Deprecated: will be moved to package pkg/gorm InitMysql
|
||||
func Init(dns string, opts ...Option) (*gorm.DB, error) {
|
||||
o := defaultOptions()
|
||||
o.apply(opts...)
|
||||
|
|
|
@ -126,6 +126,7 @@ func (c *Column) convert() error {
|
|||
}
|
||||
|
||||
// ConvertToPage converted to conform to gorm rules based on the page size sort parameter
|
||||
// Deprecated: will be moved to package pkg/gorm/query ConvertToPage
|
||||
func (p *Params) ConvertToPage() (order string, limit int, offset int) { //nolint
|
||||
page := NewPage(p.Page, p.Size, p.Sort)
|
||||
order = page.sort
|
||||
|
@ -136,6 +137,7 @@ func (p *Params) ConvertToPage() (order string, limit int, offset int) { //nolin
|
|||
|
||||
// ConvertToGormConditions conversion to gorm-compliant parameters based on the Columns parameter
|
||||
// ignore the logical type of the last column, whether it is a one-column or multi-column query
|
||||
// Deprecated: will be moved to package pkg/gorm/query ConvertToGormConditions
|
||||
func (p *Params) ConvertToGormConditions() (string, []interface{}, error) {
|
||||
str := ""
|
||||
args := []interface{}{}
|
||||
|
@ -272,6 +274,7 @@ func (c *Conditions) CheckValid() error {
|
|||
|
||||
// ConvertToGorm conversion to gorm-compliant parameters based on the Columns parameter
|
||||
// ignore the logical type of the last column, whether it is a one-column or multi-column query
|
||||
// Deprecated: will be moved to package pkg/gorm/query ConvertToGorm
|
||||
func (c *Conditions) ConvertToGorm() (string, []interface{}, error) {
|
||||
p := &Params{Columns: c.Columns}
|
||||
return p.ConvertToGormConditions()
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
_ "github.com/go-sql-driver/mysql" //nolint
|
||||
)
|
||||
|
||||
// GetTableInfo get table info from mysql
|
||||
func GetTableInfo(dsn, tableName string) (string, error) {
|
||||
// GetMysqlTableInfo get table info from mysql
|
||||
func GetMysqlTableInfo(dsn, tableName string) (string, error) {
|
||||
db, err := sql.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("connect mysql error, %v", err)
|
||||
return "", fmt.Errorf("GetMysqlTableInfo error, %v", err)
|
||||
}
|
||||
defer db.Close() //nolint
|
||||
|
||||
|
@ -34,3 +34,9 @@ func GetTableInfo(dsn, tableName string) (string, error) {
|
|||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// GetTableInfo get table info from mysql
|
||||
// Deprecated: replaced by GetMysqlTableInfo
|
||||
func GetTableInfo(dsn, tableName string) (string, error) {
|
||||
return GetMysqlTableInfo(dsn, tableName)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ const (
|
|||
type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
DBDriver string
|
||||
FieldTypes map[string]string // name:type
|
||||
Charset string
|
||||
Collation string
|
||||
JSONTag bool
|
||||
|
@ -30,11 +32,31 @@ type options struct {
|
|||
}
|
||||
|
||||
var defaultOptions = options{
|
||||
NullStyle: NullInSql,
|
||||
Package: "model",
|
||||
DBDriver: "mysql",
|
||||
FieldTypes: map[string]string{},
|
||||
NullStyle: NullInSql,
|
||||
Package: "model",
|
||||
}
|
||||
|
||||
// WithCharset set charset
|
||||
// WithDBDriver set db driver
|
||||
func WithDBDriver(driver string) Option {
|
||||
return func(o *options) {
|
||||
if driver != "" {
|
||||
o.DBDriver = driver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithFieldTypes set field types
|
||||
func WithFieldTypes(fieldTypes map[string]string) Option {
|
||||
return func(o *options) {
|
||||
if fieldTypes != nil {
|
||||
o.FieldTypes = fieldTypes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithCharset set charset
|
||||
func WithCharset(charset string) Option {
|
||||
return func(o *options) {
|
||||
o.Charset = charset
|
||||
|
|
|
@ -34,6 +34,13 @@ const (
|
|||
CodeTypeProto = "proto"
|
||||
// CodeTypeService grpc service code
|
||||
CodeTypeService = "service"
|
||||
|
||||
// DBDriverMysql mysql driver
|
||||
DBDriverMysql = "mysql"
|
||||
// DBDriverPostgresql postgresql driver
|
||||
DBDriverPostgresql = "postgresql"
|
||||
// DBDriverTidb tidb driver
|
||||
DBDriverTidb = "tidb"
|
||||
)
|
||||
|
||||
// Codes content
|
||||
|
@ -199,7 +206,7 @@ const (
|
|||
)
|
||||
|
||||
var replaceFields = map[string]string{
|
||||
__mysqlModel__: "mysql.Model",
|
||||
__mysqlModel__: "ggorm.Model",
|
||||
__type__: "",
|
||||
}
|
||||
|
||||
|
@ -299,7 +306,12 @@ func makeCode(stmt *ast.CreateTableStmt, opt options) (*codeText, error) {
|
|||
gormTag.WriteString(colName)
|
||||
if opt.GormType {
|
||||
gormTag.WriteString(";type:")
|
||||
gormTag.WriteString(col.Tp.InfoSchemaStr())
|
||||
switch opt.DBDriver {
|
||||
case DBDriverMysql, DBDriverTidb:
|
||||
gormTag.WriteString(col.Tp.InfoSchemaStr())
|
||||
case DBDriverPostgresql:
|
||||
gormTag.WriteString(opt.FieldTypes[colName])
|
||||
}
|
||||
}
|
||||
if isPrimaryKey[colName] {
|
||||
gormTag.WriteString(";primary_key")
|
||||
|
@ -431,13 +443,13 @@ func getModelStructCode(data tmplData, importPaths []string, isEmbed bool) (stri
|
|||
newImportPaths = importPaths
|
||||
} else {
|
||||
for _, path := range importPaths {
|
||||
if path == "time" {
|
||||
if path == "time" { //nolint
|
||||
continue
|
||||
}
|
||||
newImportPaths = append(newImportPaths, path)
|
||||
}
|
||||
}
|
||||
newImportPaths = append(newImportPaths, "github.com/zhufuyi/sponge/pkg/mysql")
|
||||
newImportPaths = append(newImportPaths, "github.com/zhufuyi/sponge/pkg/ggorm")
|
||||
} else {
|
||||
for i, field := range data.Fields {
|
||||
if strings.Contains(field.GoType, "time.Time") {
|
||||
|
@ -716,7 +728,7 @@ func mysqlToGoType(colTp *types.FieldType, style NullStyle) (name string, path s
|
|||
mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
|
||||
name = "string"
|
||||
case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDate:
|
||||
path = "time"
|
||||
path = "time" //nolint
|
||||
name = "time.Time"
|
||||
case mysql.TypeDecimal, mysql.TypeNewDecimal:
|
||||
name = "string"
|
||||
|
|
|
@ -102,6 +102,8 @@ func Test_toCamel(t *testing.T) {
|
|||
|
||||
func Test_parseOption(t *testing.T) {
|
||||
opts := []Option{
|
||||
WithDBDriver("foo"),
|
||||
WithFieldTypes(map[string]string{"foo": "bar"}),
|
||||
WithCharset("foo"),
|
||||
WithCollation("foo"),
|
||||
WithTablePrefix("foo"),
|
||||
|
@ -148,11 +150,6 @@ func Test_goTypeToProto(t *testing.T) {
|
|||
assert.NotNil(t, v)
|
||||
}
|
||||
|
||||
func TestGetTableInfo(t *testing.T) {
|
||||
info, err := GetTableInfo("root:123456@(192.168.3.37:3306)/test", "user")
|
||||
t.Log(err, info)
|
||||
}
|
||||
|
||||
func Test_initTemplate(t *testing.T) {
|
||||
initTemplate()
|
||||
|
||||
|
@ -174,3 +171,46 @@ func Test_initTemplate(t *testing.T) {
|
|||
serviceStructTmplRaw = "{{if .foo}}"
|
||||
initTemplate()
|
||||
}
|
||||
|
||||
func TestGetTableInfo(t *testing.T) {
|
||||
info, err := GetMysqlTableInfo("root:123456@(192.168.3.37:3306)/test", "user")
|
||||
t.Log(err, info)
|
||||
}
|
||||
|
||||
func TestGetPostgresqlTableInfo(t *testing.T) {
|
||||
fields, err := GetPostgresqlTableInfo("host=192.168.3.37 port=5432 user=root password=123456 dbname=account sslmode=disable", "user_example")
|
||||
t.Log(fields, err)
|
||||
sql, fieldTypes := ConvertToMysqlTable("user_example", fields)
|
||||
t.Log(sql, fieldTypes)
|
||||
}
|
||||
|
||||
func TestConvertToMysqlTable(t *testing.T) {
|
||||
fields := []*PGField{
|
||||
{Name: "id", Type: "smallint"},
|
||||
{Name: "name", Type: "character", Lengthvar: 24, Notnull: false},
|
||||
{Name: "age", Type: "smallint", Notnull: true},
|
||||
}
|
||||
sql, tps := ConvertToMysqlTable("foobar", fields)
|
||||
t.Log(sql, tps)
|
||||
}
|
||||
|
||||
func Test_toMysqlTable(t *testing.T) {
|
||||
fields := []*PGField{
|
||||
{Type: "smallint"},
|
||||
{Type: "bigint"},
|
||||
{Type: "real"},
|
||||
{Type: "decimal"},
|
||||
{Type: "double precision"},
|
||||
{Type: "money"},
|
||||
{Type: "character", Lengthvar: 24},
|
||||
{Type: "text"},
|
||||
{Type: "timestamp"},
|
||||
{Type: "date"},
|
||||
{Type: "time"},
|
||||
{Type: "interval"},
|
||||
{Type: "boolean"},
|
||||
}
|
||||
for _, field := range fields {
|
||||
t.Log(toMysqlType(field), getType(field))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PGField struct {
|
||||
Name string `gorm:"column:name;" json:"name"`
|
||||
Type string `gorm:"column:type;" json:"type"`
|
||||
Comment string `gorm:"column:comment;" json:"comment"`
|
||||
Length int `gorm:"column:length;" json:"length"`
|
||||
Lengthvar int `gorm:"column:lengthvar;" json:"lengthvar"`
|
||||
Notnull bool `gorm:"column:notnull;" json:"notnull"`
|
||||
}
|
||||
|
||||
// GetPostgresqlTableInfo get table info from postgres
|
||||
func GetPostgresqlTableInfo(dsn string, tableName string) ([]*PGField, error) {
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetPostgresqlTableInfo error: %v", err)
|
||||
}
|
||||
|
||||
return getPostgresqlTableFields(db, tableName)
|
||||
}
|
||||
|
||||
func getPostgresqlTableFields(db *gorm.DB, tableName string) ([]*PGField, error) {
|
||||
query := fmt.Sprintf(`SELECT a.attname AS name, t.typname AS type, a.attlen AS length, a.atttypmod AS lengthvar, a.attnotnull AS notnull, b.description AS comment
|
||||
FROM pg_class c, pg_attribute a
|
||||
LEFT JOIN pg_description b
|
||||
ON a.attrelid = b.objoid
|
||||
AND a.attnum = b.objsubid, pg_type t
|
||||
WHERE c.relname = '%s'
|
||||
AND a.attnum > 0
|
||||
AND a.attrelid = c.oid
|
||||
AND a.atttypid = t.oid
|
||||
ORDER BY a.attnum;`, tableName)
|
||||
|
||||
var fields []*PGField
|
||||
result := db.Raw(query).Scan(&fields)
|
||||
if result.Error != nil {
|
||||
return nil, fmt.Errorf("failed to get table fields: %v", result.Error)
|
||||
}
|
||||
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
// ConvertToMysqlTable convert to mysql table ddl
|
||||
func ConvertToMysqlTable(tableName string, fields []*PGField) (string, map[string]string) {
|
||||
fieldStr := ""
|
||||
pgTypeMap := make(map[string]string) // name:type
|
||||
for _, field := range fields {
|
||||
pgTypeMap[field.Name] = getType(field)
|
||||
if field.Name == "id" {
|
||||
fieldStr += fmt.Sprintf(" %s bigint unsigned primary key,\n", field.Name)
|
||||
continue
|
||||
}
|
||||
notnullStr := "not null"
|
||||
if !field.Notnull {
|
||||
notnullStr = "null"
|
||||
}
|
||||
fieldStr += fmt.Sprintf(" %s %s %s comment '%s',\n", field.Name, toMysqlType(field), notnullStr, field.Comment)
|
||||
}
|
||||
fieldStr = strings.TrimSuffix(fieldStr, ",\n")
|
||||
|
||||
return fmt.Sprintf("CREATE TABLE %s (\n%s\n);", tableName, fieldStr), pgTypeMap
|
||||
}
|
||||
|
||||
func toMysqlType(field *PGField) string {
|
||||
switch field.Type {
|
||||
// 整型
|
||||
case "smallint", "integer", "smallserial", "serial", "int2", "int4":
|
||||
return "int"
|
||||
case "bigint", "bigserial", "int8":
|
||||
return "bigint"
|
||||
// 浮点数
|
||||
case "real":
|
||||
return "float"
|
||||
case "decimal", "numeric":
|
||||
return "decimal"
|
||||
case "double precision":
|
||||
return "double"
|
||||
case "money":
|
||||
return "varchar(30)"
|
||||
// 字符串
|
||||
case "character", "character varying", "varchar", "char", "bpchar":
|
||||
if field.Lengthvar > 4 {
|
||||
return fmt.Sprintf("varchar(%d)", field.Lengthvar-4)
|
||||
}
|
||||
case "text":
|
||||
return "text"
|
||||
// 日期时间
|
||||
case "timestamp":
|
||||
return "timestamp"
|
||||
case "date":
|
||||
return "date"
|
||||
case "time": //nolint
|
||||
return "time" //nolint
|
||||
case "interval":
|
||||
return "year"
|
||||
case "boolean":
|
||||
return "tinyint(1)"
|
||||
}
|
||||
return field.Type
|
||||
}
|
||||
|
||||
func getType(field *PGField) string {
|
||||
switch field.Type {
|
||||
case "character", "character varying", "varchar", "char", "bpchar":
|
||||
if field.Lengthvar > 4 {
|
||||
return fmt.Sprintf("varchar(%d)", field.Lengthvar-4)
|
||||
}
|
||||
}
|
||||
return field.Type
|
||||
}
|
|
@ -182,7 +182,7 @@ message List{{.TableName}}ByIDsReply {
|
|||
|
||||
message List{{.TableName}}ByLastIDRequest {
|
||||
uint64 lastID = 1; // last id
|
||||
uint32 limit = 2 [(validate.rules).uint32.gt = 0]; // page size
|
||||
uint32 limit = 2 [(validate.rules).uint32.gt = 0]; // limit size per page
|
||||
string sort = 3; // sort by column name of table, default is -id, the - sign indicates descending order.
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,7 @@ message List{{.TableName}}ByIDsReply {
|
|||
|
||||
message List{{.TableName}}ByLastIDRequest {
|
||||
uint64 lastID = 1 [(tagger.tags) = "form:\"lastID\""]; // last id
|
||||
uint32 limit = 2 [(validate.rules).uint32.gt = 0, (tagger.tags) = "form:\"limit\""]; // page size
|
||||
uint32 limit = 2 [(validate.rules).uint32.gt = 0, (tagger.tags) = "form:\"limit\""]; // limit size per page
|
||||
string sort = 3 [(tagger.tags) = "form:\"sort\""]; // sort by column name of table, default is -id, the - sign indicates descending order.
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/zhufuyi/sponge/pkg/sql2code/parser"
|
||||
"github.com/zhufuyi/sponge/pkg/utils"
|
||||
)
|
||||
|
||||
// Args generate code arguments
|
||||
|
@ -17,8 +19,10 @@ type Args struct {
|
|||
|
||||
DDLFile string // DDL file
|
||||
|
||||
DBDsn string // connecting to mysql's dsn
|
||||
DBTable string
|
||||
DBDriver string // db driver name, such as mysql, postgres, default is mysql
|
||||
DBDsn string // connecting to mysql's dsn
|
||||
DBTable string // table name
|
||||
fieldTypes map[string]string // field name:type
|
||||
|
||||
Package string // specify the package name (only valid for model types)
|
||||
GormType bool // whether to display the gorm type name (only valid for model type codes)
|
||||
|
@ -40,38 +44,64 @@ func (a *Args) checkValid() error {
|
|||
if a.SQL == "" && a.DDLFile == "" && (a.DBDsn == "" && a.DBTable == "") {
|
||||
return errors.New("you must specify sql or ddl file")
|
||||
}
|
||||
if a.DBDriver == "" {
|
||||
a.DBDriver = parser.DBDriverMysql
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSQL(args *Args) (string, error) {
|
||||
func getSQL(args *Args) (string, map[string]string, error) {
|
||||
if args.SQL != "" {
|
||||
return args.SQL, nil
|
||||
return args.SQL, nil, nil
|
||||
}
|
||||
|
||||
sql := ""
|
||||
dbDriverName := strings.ToLower(args.DBDriver)
|
||||
if args.DDLFile != "" {
|
||||
if dbDriverName != parser.DBDriverMysql {
|
||||
return sql, nil, fmt.Errorf("not support driver %s for parsing the sql file, only mysql is supported", args.DBDriver)
|
||||
}
|
||||
b, err := os.ReadFile(args.DDLFile)
|
||||
if err != nil {
|
||||
return sql, fmt.Errorf("read %s failed, %s", args.DDLFile, err)
|
||||
return sql, nil, fmt.Errorf("read %s failed, %s", args.DDLFile, err)
|
||||
}
|
||||
return string(b), nil
|
||||
return string(b), nil, nil
|
||||
} else if args.DBDsn != "" {
|
||||
if args.DBTable == "" {
|
||||
return sql, errors.New("miss mysql table")
|
||||
return sql, nil, errors.New("miss database table")
|
||||
}
|
||||
sqlStr, err := parser.GetTableInfo(args.DBDsn, args.DBTable)
|
||||
if err != nil {
|
||||
return sql, err
|
||||
|
||||
switch dbDriverName {
|
||||
case parser.DBDriverMysql, parser.DBDriverTidb:
|
||||
dsn := utils.AdaptiveMysqlDsn(args.DBDsn)
|
||||
sqlStr, err := parser.GetMysqlTableInfo(dsn, args.DBTable)
|
||||
return sqlStr, nil, err
|
||||
case parser.DBDriverPostgresql:
|
||||
dsn := utils.AdaptivePostgresqlDsn(args.DBDsn)
|
||||
fields, err := parser.GetPostgresqlTableInfo(dsn, args.DBTable)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
sqlStr, pgTypeMap := parser.ConvertToMysqlTable(args.DBTable, fields)
|
||||
return sqlStr, pgTypeMap, nil
|
||||
default:
|
||||
return "", nil, fmt.Errorf("unsupported database driver: " + dbDriverName)
|
||||
}
|
||||
return sqlStr, nil
|
||||
}
|
||||
|
||||
return sql, errors.New("no SQL input(-sql|-f|-db-dsn)")
|
||||
return sql, nil, errors.New("no SQL input(-sql|-f|-db-dsn)")
|
||||
}
|
||||
|
||||
func getOptions(args *Args) []parser.Option {
|
||||
func setOptions(args *Args) []parser.Option {
|
||||
var opts []parser.Option
|
||||
|
||||
if args.DBDriver != "" {
|
||||
opts = append(opts, parser.WithDBDriver(args.DBDriver))
|
||||
}
|
||||
if args.fieldTypes != nil {
|
||||
opts = append(opts, parser.WithFieldTypes(args.fieldTypes))
|
||||
}
|
||||
|
||||
if args.Charset != "" {
|
||||
opts = append(opts, parser.WithCharset(args.Charset))
|
||||
}
|
||||
|
@ -147,12 +177,15 @@ func Generate(args *Args) (map[string]string, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sql, err := getSQL(args)
|
||||
sql, fieldTypes, err := getSQL(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fieldTypes != nil {
|
||||
args.fieldTypes = fieldTypes
|
||||
}
|
||||
|
||||
opt := getOptions(args)
|
||||
opt := setOptions(args)
|
||||
|
||||
return parser.ParseSQL(sql, opt...)
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ func Test_getOptions(t *testing.T) {
|
|||
NullStyle: "sql",
|
||||
}
|
||||
|
||||
o := getOptions(a)
|
||||
o := setOptions(a)
|
||||
assert.NotNil(t, o)
|
||||
a.NullStyle = "ptr"
|
||||
assert.NotNil(t, o)
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
patchType=$1
|
||||
typesPb="types-pb"
|
||||
mysqlInit="mysql-init"
|
||||
initMysql="init-mysql"
|
||||
initTidb="init-tidb"
|
||||
initPostgresql="init-postgresql"
|
||||
|
||||
function checkResult() {
|
||||
result=$1
|
||||
|
@ -11,24 +13,37 @@ function checkResult() {
|
|||
fi
|
||||
}
|
||||
|
||||
function patchTypesPb() {
|
||||
function generateTypesPbCode() {
|
||||
sponge patch gen-types-pb --out=./
|
||||
checkResult $?
|
||||
}
|
||||
|
||||
function patchMysqlInit() {
|
||||
sponge patch gen-mysql-init --out=./
|
||||
function generateInitMysqlCode() {
|
||||
sponge patch gen-db-init --db-driver=mysql --out=./
|
||||
checkResult $?
|
||||
}
|
||||
|
||||
if [ "X$patchType" = "X" ];then
|
||||
patchTypesPb
|
||||
patchMysqlInit
|
||||
elif [ "$patchType" = "$typesPb" ]; then
|
||||
patchTypesPb
|
||||
elif [ "$patchType" = "$mysqlInit" ]; then
|
||||
patchMysqlInit
|
||||
function generateInitTidbCode() {
|
||||
sponge patch gen-db-init --db-driver=tidb --out=./
|
||||
checkResult $?
|
||||
}
|
||||
|
||||
function generateInitPostgresqlCode() {
|
||||
sponge patch gen-db-init --db-driver=postgresql --out=./
|
||||
checkResult $?
|
||||
}
|
||||
|
||||
if [ "$patchType" = "$typesPb" ]; then
|
||||
generateTypesPbCode
|
||||
elif [ "$patchType" = "$initMysql" ]; then
|
||||
generateInitMysqlCode
|
||||
elif [ "$patchType" = "$initTidb" ]; then
|
||||
generateInitTidbCode
|
||||
elif [ "$patchType" = "$initPostgresql" ]; then
|
||||
generateInitPostgresqlCode
|
||||
else
|
||||
echo "TYPE should be "", $typesPb or $mysqlInit."
|
||||
echo "invalid patch type: '$patchType'"
|
||||
echo "supported types: $initMysql, $initTidb, $initPostgresql, $typesPb"
|
||||
echo "e.g. make patch TYPE=init-mysql"
|
||||
exit 1
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue