feat(goctl): Support gateway sample generation (#3049)

master
anqiansong 2 years ago committed by GitHub
parent 95b85336d6
commit 1904af2323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,166 +13,91 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/tsgen" "github.com/zeromicro/go-zero/tools/goctl/api/tsgen"
"github.com/zeromicro/go-zero/tools/goctl/api/validate" "github.com/zeromicro/go-zero/tools/goctl/api/validate"
"github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/plugin" "github.com/zeromicro/go-zero/tools/goctl/plugin"
) )
var ( var (
// Cmd describes an api command. // Cmd describes an api command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("api", cobrax.WithRunE(apigen.CreateApiTemplate))
Use: "api", dartCmd = cobrax.NewCommand("dart", cobrax.WithRunE(dartgen.DartCommand))
Short: "Generate api related files", docCmd = cobrax.NewCommand("doc", cobrax.WithRunE(docgen.DocCommand))
RunE: apigen.CreateApiTemplate, formatCmd = cobrax.NewCommand("format", cobrax.WithRunE(format.GoFormatApi))
} goCmd = cobrax.NewCommand("go", cobrax.WithRunE(gogen.GoCommand))
newCmd = cobrax.NewCommand("new", cobrax.WithRunE(new.CreateServiceCommand),
dartCmd = &cobra.Command{ cobrax.WithArgs(cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)))
Use: "dart", validateCmd = cobrax.NewCommand("validate", cobrax.WithRunE(validate.GoValidateApi))
Short: "Generate dart files for provided api in api file", javaCmd = cobrax.NewCommand("java", cobrax.WithRunE(javagen.JavaCommand), cobrax.WithHidden())
RunE: dartgen.DartCommand, ktCmd = cobrax.NewCommand("kt", cobrax.WithRunE(ktgen.KtCommand))
} pluginCmd = cobrax.NewCommand("plugin", cobrax.WithRunE(plugin.PluginCommand))
tsCmd = cobrax.NewCommand("ts", cobrax.WithRunE(tsgen.TsCommand))
docCmd = &cobra.Command{
Use: "doc",
Short: "Generate doc files",
RunE: docgen.DocCommand,
}
formatCmd = &cobra.Command{
Use: "format",
Short: "Format api files",
RunE: format.GoFormatApi,
}
goCmd = &cobra.Command{
Use: "go",
Short: "Generate go files for provided api in api file",
RunE: gogen.GoCommand,
}
newCmd = &cobra.Command{
Use: "new",
Short: "Fast create api service",
Example: "goctl api new [options] service-name",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: func(cmd *cobra.Command, args []string) error {
return new.CreateServiceCommand(args)
},
}
validateCmd = &cobra.Command{
Use: "validate",
Short: "Validate api file",
RunE: validate.GoValidateApi,
}
javaCmd = &cobra.Command{
Use: "java",
Short: "Generate java files for provided api in api file",
Hidden: true,
RunE: javagen.JavaCommand,
}
ktCmd = &cobra.Command{
Use: "kt",
Short: "Generate kotlin code for provided api file",
RunE: ktgen.KtCommand,
}
pluginCmd = &cobra.Command{
Use: "plugin",
Short: "Custom file generator",
RunE: plugin.PluginCommand,
}
tsCmd = &cobra.Command{
Use: "ts",
Short: "Generate ts files for provided api in api file",
RunE: tsgen.TsCommand,
}
) )
func init() { func init() {
Cmd.Flags().StringVar(&apigen.VarStringOutput, "o", "", "Output a sample api file") var (
Cmd.Flags().StringVar(&apigen.VarStringHome, "home", "", "The goctl home path of the"+ apiCmdFlags = Cmd.Flags()
" template, --home and --remote cannot be set at the same time, if they are, --remote has "+ dartCmdFlags = dartCmd.Flags()
"higher priority") docCmdFlags = docCmd.Flags()
Cmd.Flags().StringVar(&apigen.VarStringRemote, "remote", "", "The remote git repo of the"+ formatCmdFlags = formatCmd.Flags()
" template, --home and --remote cannot be set at the same time, if they are, --remote has higher"+ goCmdFlags = goCmd.Flags()
" priority\nThe git repo directory must be consistent with the"+ javaCmdFlags = javaCmd.Flags()
" https://github.com/zeromicro/go-zero-template directory structure") ktCmdFlags = ktCmd.Flags()
Cmd.Flags().StringVar(&apigen.VarStringBranch, "branch", "", "The branch of the "+ newCmdFlags = newCmd.Flags()
"remote repo, it does work with --remote") pluginCmdFlags = pluginCmd.Flags()
tsCmdFlags = tsCmd.Flags()
dartCmd.Flags().StringVar(&dartgen.VarStringDir, "dir", "", "The target dir") validateCmdFlags = validateCmd.Flags()
dartCmd.Flags().StringVar(&dartgen.VarStringAPI, "api", "", "The api file") )
dartCmd.Flags().BoolVar(&dartgen.VarStringLegacy, "legacy", false, "Legacy generator for flutter v1")
dartCmd.Flags().StringVar(&dartgen.VarStringHostname, "hostname", "", "hostname of the server") apiCmdFlags.StringVar(&apigen.VarStringOutput, "o")
dartCmd.Flags().StringVar(&dartgen.VarStringScheme, "scheme", "", "scheme of the server") apiCmdFlags.StringVar(&apigen.VarStringHome, "home")
apiCmdFlags.StringVar(&apigen.VarStringRemote, "remote")
docCmd.Flags().StringVar(&docgen.VarStringDir, "dir", "", "The target dir") apiCmdFlags.StringVar(&apigen.VarStringBranch, "branch")
docCmd.Flags().StringVar(&docgen.VarStringOutput, "o", "", "The output markdown directory")
dartCmdFlags.StringVar(&dartgen.VarStringDir, "dir")
formatCmd.Flags().StringVar(&format.VarStringDir, "dir", "", "The format target dir") dartCmdFlags.StringVar(&dartgen.VarStringAPI, "api")
formatCmd.Flags().BoolVar(&format.VarBoolIgnore, "iu", false, "Ignore update") dartCmdFlags.BoolVar(&dartgen.VarStringLegacy, "legacy")
formatCmd.Flags().BoolVar(&format.VarBoolUseStdin, "stdin", false, "Use stdin to input api"+ dartCmdFlags.StringVar(&dartgen.VarStringHostname, "hostname")
" doc content, press \"ctrl + d\" to send EOF") dartCmdFlags.StringVar(&dartgen.VarStringScheme, "scheme")
formatCmd.Flags().BoolVar(&format.VarBoolSkipCheckDeclare, "declare", false, "Use to skip check "+
"api types already declare") docCmdFlags.StringVar(&docgen.VarStringDir, "dir")
docCmdFlags.StringVar(&docgen.VarStringOutput, "o")
goCmd.Flags().StringVar(&gogen.VarStringDir, "dir", "", "The target dir")
goCmd.Flags().StringVar(&gogen.VarStringAPI, "api", "", "The api file") formatCmdFlags.StringVar(&format.VarStringDir, "dir")
goCmd.Flags().StringVar(&gogen.VarStringHome, "home", "", "The goctl home path of "+ formatCmdFlags.BoolVar(&format.VarBoolIgnore, "iu")
"the template, --home and --remote cannot be set at the same time, if they are, --remote "+ formatCmdFlags.BoolVar(&format.VarBoolUseStdin, "stdin")
"has higher priority") formatCmdFlags.BoolVar(&format.VarBoolSkipCheckDeclare, "declare")
goCmd.Flags().StringVar(&gogen.VarStringRemote, "remote", "", "The remote git repo "+
"of the template, --home and --remote cannot be set at the same time, if they are, --remote"+ goCmdFlags.StringVar(&gogen.VarStringDir, "dir")
" has higher priority\nThe git repo directory must be consistent with the "+ goCmdFlags.StringVar(&gogen.VarStringAPI, "api")
"https://github.com/zeromicro/go-zero-template directory structure") goCmdFlags.StringVar(&gogen.VarStringHome, "home")
goCmd.Flags().StringVar(&gogen.VarStringBranch, "branch", "", "The branch of "+ goCmdFlags.StringVar(&gogen.VarStringRemote, "remote")
"the remote repo, it does work with --remote") goCmdFlags.StringVar(&gogen.VarStringBranch, "branch")
goCmd.Flags().StringVar(&gogen.VarStringStyle, "style", config.DefaultFormat, "The file naming format,"+ goCmdFlags.StringVarWithDefaultValue(&gogen.VarStringStyle, "style", config.DefaultFormat)
" see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]")
javaCmdFlags.StringVar(&javagen.VarStringDir, "dir")
javaCmd.Flags().StringVar(&javagen.VarStringDir, "dir", "", "The target dir") javaCmdFlags.StringVar(&javagen.VarStringAPI, "api")
javaCmd.Flags().StringVar(&javagen.VarStringAPI, "api", "", "The api file")
ktCmdFlags.StringVar(&ktgen.VarStringDir, "dir")
ktCmd.Flags().StringVar(&ktgen.VarStringDir, "dir", "", "The target dir") ktCmdFlags.StringVar(&ktgen.VarStringAPI, "api")
ktCmd.Flags().StringVar(&ktgen.VarStringAPI, "api", "", "The api file") ktCmdFlags.StringVar(&ktgen.VarStringPKG, "pkg")
ktCmd.Flags().StringVar(&ktgen.VarStringPKG, "pkg", "", "Define package name for kotlin file")
newCmdFlags.StringVar(&new.VarStringHome, "home")
newCmd.Flags().StringVar(&new.VarStringHome, "home", "", "The goctl home path of "+ newCmdFlags.StringVar(&new.VarStringRemote, "remote")
"the template, --home and --remote cannot be set at the same time, if they are, --remote "+ newCmdFlags.StringVar(&new.VarStringBranch, "branch")
"has higher priority") newCmdFlags.StringVarWithDefaultValue(&new.VarStringStyle, "style", config.DefaultFormat)
newCmd.Flags().StringVar(&new.VarStringRemote, "remote", "", "The remote git repo "+
"of the template, --home and --remote cannot be set at the same time, if they are, --remote"+ pluginCmdFlags.StringVarP(&plugin.VarStringPlugin, "plugin", "p")
" has higher priority\n\tThe git repo directory must be consistent with the "+ pluginCmdFlags.StringVar(&plugin.VarStringDir, "dir")
"https://github.com/zeromicro/go-zero-template directory structure") pluginCmdFlags.StringVar(&plugin.VarStringAPI, "api")
newCmd.Flags().StringVar(&new.VarStringBranch, "branch", "", "The branch of "+ pluginCmdFlags.StringVar(&plugin.VarStringStyle, "style")
"the remote repo, it does work with --remote")
newCmd.Flags().StringVar(&new.VarStringStyle, "style", config.DefaultFormat, "The file naming format,"+ tsCmdFlags.StringVar(&tsgen.VarStringDir, "dir")
" see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]") tsCmdFlags.StringVar(&tsgen.VarStringAPI, "api")
tsCmdFlags.StringVar(&tsgen.VarStringCaller, "caller")
pluginCmd.Flags().StringVarP(&plugin.VarStringPlugin, "plugin", "p", "", "The plugin file") tsCmdFlags.BoolVar(&tsgen.VarBoolUnWrap, "unwrap")
pluginCmd.Flags().StringVar(&plugin.VarStringDir, "dir", "", "The target dir")
pluginCmd.Flags().StringVar(&plugin.VarStringAPI, "api", "", "The api file") validateCmdFlags.StringVar(&validate.VarStringAPI, "api")
pluginCmd.Flags().StringVar(&plugin.VarStringStyle, "style", "",
"The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
tsCmd.Flags().StringVar(&tsgen.VarStringDir, "dir", "", "The target dir")
tsCmd.Flags().StringVar(&tsgen.VarStringAPI, "api", "", "The api file")
tsCmd.Flags().StringVar(&tsgen.VarStringCaller, "caller", "", "The web api caller")
tsCmd.Flags().BoolVar(&tsgen.VarBoolUnWrap, "unwrap", false, "Unwrap the webapi caller for import")
validateCmd.Flags().StringVar(&validate.VarStringAPI, "api", "", "Validate target api file")
// Add sub-commands // Add sub-commands
Cmd.AddCommand(dartCmd) Cmd.AddCommand(dartCmd, docCmd, formatCmd, goCmd, javaCmd, ktCmd, newCmd, pluginCmd, tsCmd, validateCmd)
Cmd.AddCommand(docCmd)
Cmd.AddCommand(formatCmd)
Cmd.AddCommand(goCmd)
Cmd.AddCommand(javaCmd)
Cmd.AddCommand(ktCmd)
Cmd.AddCommand(newCmd)
Cmd.AddCommand(pluginCmd)
Cmd.AddCommand(tsCmd)
Cmd.AddCommand(validateCmd)
} }

@ -8,6 +8,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/api/gogen" "github.com/zeromicro/go-zero/tools/goctl/api/gogen"
conf "github.com/zeromicro/go-zero/tools/goctl/config" conf "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
@ -29,7 +30,7 @@ var (
) )
// CreateServiceCommand fast create service // CreateServiceCommand fast create service
func CreateServiceCommand(args []string) error { func CreateServiceCommand(_ *cobra.Command, args []string) error {
dirName := args[0] dirName := args[0]
if len(VarStringStyle) == 0 { if len(VarStringStyle) == 0 {
VarStringStyle = conf.DefaultFormat VarStringStyle = conf.DefaultFormat

@ -1,11 +1,9 @@
package bug package bug
import "github.com/spf13/cobra" import (
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
)
// Cmd describes a bug command. // Cmd describes a bug command.
var Cmd = &cobra.Command{ var Cmd = cobrax.NewCommand("bug", cobrax.WithRunE(cobra.NoArgs), cobrax.WithArgs(cobra.NoArgs))
Use: "bug",
Short: "Report a bug",
Args: cobra.NoArgs,
RunE: runE,
}

@ -15,6 +15,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/bug" "github.com/zeromicro/go-zero/tools/goctl/bug"
"github.com/zeromicro/go-zero/tools/goctl/docker" "github.com/zeromicro/go-zero/tools/goctl/docker"
"github.com/zeromicro/go-zero/tools/goctl/env" "github.com/zeromicro/go-zero/tools/goctl/env"
"github.com/zeromicro/go-zero/tools/goctl/gateway"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/internal/version" "github.com/zeromicro/go-zero/tools/goctl/internal/version"
"github.com/zeromicro/go-zero/tools/goctl/kube" "github.com/zeromicro/go-zero/tools/goctl/kube"
"github.com/zeromicro/go-zero/tools/goctl/migrate" "github.com/zeromicro/go-zero/tools/goctl/migrate"
@ -35,14 +37,7 @@ const (
var ( var (
//go:embed usage.tpl //go:embed usage.tpl
usageTpl string usageTpl string
rootCmd = cobrax.NewCommand("goctl")
rootCmd = &cobra.Command{
Use: "goctl",
Short: "A cli tool to generate go-zero code",
Long: "A cli tool to generate api, zrpc, model code\n\n" +
"GitHub: https://github.com/zeromicro/go-zero\n" +
"Site: https://go-zero.dev",
}
) )
// Execute executes the given command // Execute executes the given command
@ -117,16 +112,8 @@ func init() {
runtime.GOOS, runtime.GOARCH) runtime.GOOS, runtime.GOARCH)
rootCmd.SetUsageTemplate(usageTpl) rootCmd.SetUsageTemplate(usageTpl)
rootCmd.AddCommand(api.Cmd) rootCmd.AddCommand(api.Cmd, bug.Cmd, docker.Cmd, kube.Cmd, env.Cmd, gateway.Cmd, model.Cmd)
rootCmd.AddCommand(bug.Cmd) rootCmd.AddCommand(migrate.Cmd, quickstart.Cmd, rpc.Cmd, tpl.Cmd, upgrade.Cmd)
rootCmd.AddCommand(docker.Cmd) rootCmd.Command.AddCommand(cobracompletefig.CreateCompletionSpecCommand())
rootCmd.AddCommand(kube.Cmd) rootCmd.MustInit()
rootCmd.AddCommand(env.Cmd)
rootCmd.AddCommand(model.Cmd)
rootCmd.AddCommand(migrate.Cmd)
rootCmd.AddCommand(quickstart.Cmd)
rootCmd.AddCommand(rpc.Cmd)
rootCmd.AddCommand(tpl.Cmd)
rootCmd.AddCommand(upgrade.Cmd)
rootCmd.AddCommand(cobracompletefig.CreateCompletionSpecCommand())
} }

@ -1,6 +1,6 @@
package docker package docker
import "github.com/spf13/cobra" import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var ( var (
varExeName string varExeName string
@ -14,21 +14,18 @@ var (
varStringTZ string varStringTZ string
// Cmd describes a docker command. // Cmd describes a docker command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("docker", cobrax.WithRunE(dockerCommand))
Use: "docker",
Short: "Generate Dockerfile",
RunE: dockerCommand,
}
) )
func init() { func init() {
Cmd.Flags().StringVar(&varExeName, "exe", "", "The executable name in the built image") dockerCmdFlags := Cmd.Flags()
Cmd.Flags().StringVar(&varStringGo, "go", "", "The file that contains main function") dockerCmdFlags.StringVar(&varExeName, "exe")
Cmd.Flags().StringVar(&varStringBase, "base", "scratch", "The base image to build the docker image, default scratch") dockerCmdFlags.StringVar(&varStringGo, "go")
Cmd.Flags().IntVar(&varIntPort, "port", 0, "The port to expose, default none") dockerCmdFlags.StringVarWithDefaultValue(&varStringBase, "base", "scratch")
Cmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") dockerCmdFlags.IntVar(&varIntPort, "port")
Cmd.Flags().StringVar(&varStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") dockerCmdFlags.StringVar(&varStringHome, "home")
Cmd.Flags().StringVar(&varStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") dockerCmdFlags.StringVar(&varStringRemote, "remote")
Cmd.Flags().StringVar(&varStringVersion, "version", "", "The goctl builder golang image version") dockerCmdFlags.StringVar(&varStringBranch, "branch")
Cmd.Flags().StringVar(&varStringTZ, "tz", "Asia/Shanghai", "The timezone of the container") dockerCmdFlags.StringVar(&varStringVersion, "version")
dockerCmdFlags.StringVarWithDefaultValue(&varStringTZ, "tz", "Asia/Shanghai")
} }

@ -1,6 +1,6 @@
package env package env
import "github.com/spf13/cobra" import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var ( var (
sliceVarWriteValue []string sliceVarWriteValue []string
@ -9,38 +9,20 @@ var (
boolVarInstall bool boolVarInstall bool
// Cmd describes an env command. // Cmd describes an env command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("env", cobrax.WithRunE(write))
Use: "env", installCmd = cobrax.NewCommand("install", cobrax.WithRunE(install))
Short: "Check or edit goctl environment", checkCmd = cobrax.NewCommand("check", cobrax.WithRunE(check))
RunE: write,
}
installCmd = &cobra.Command{
Use: "install",
Short: "Goctl env installation",
RunE: install,
}
checkCmd = &cobra.Command{
Use: "check",
Short: "Detect goctl env and dependency tools",
RunE: check,
}
) )
func init() { func init() {
// The root command flags // The root command flags
Cmd.Flags().StringSliceVarP(&sliceVarWriteValue, Cmd.Flags().StringSliceVarP(&sliceVarWriteValue, "write", "w")
"write", "w", nil, "Edit goctl environment") Cmd.PersistentFlags().BoolVarP(&boolVarForce, "force", "f")
Cmd.PersistentFlags().BoolVarP(&boolVarForce, Cmd.PersistentFlags().BoolVarP(&boolVarVerbose, "verbose", "v")
"force", "f", false,
"Silent installation of non-existent dependencies")
Cmd.PersistentFlags().BoolVarP(&boolVarVerbose,
"verbose", "v", false, "Enable log output")
// The sub-command flags // The sub-command flags
checkCmd.Flags().BoolVarP(&boolVarInstall, "install", "i", checkCmd.Flags().BoolVarP(&boolVarInstall, "install", "i")
false, "Install dependencies if not found")
// Add sub-command // Add sub-command
Cmd.AddCommand(installCmd) Cmd.AddCommand(checkCmd, installCmd)
Cmd.AddCommand(checkCmd)
} }

@ -7,10 +7,10 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/pkg/env" "github.com/zeromicro/go-zero/tools/goctl/pkg/env"
) )
func write(_ *cobra.Command, _ []string) error { func write(_ *cobra.Command, args []string) error {
if len(sliceVarWriteValue) > 0 { if len(sliceVarWriteValue) > 0 {
return env.WriteEnv(sliceVarWriteValue) return env.WriteEnv(sliceVarWriteValue)
} }
fmt.Println(env.Print()) fmt.Println(env.Print(args...))
return nil return nil
} }

@ -1,8 +1,6 @@
package env package env
import ( import "github.com/spf13/cobra"
"github.com/spf13/cobra"
)
func install(_ *cobra.Command, _ []string) error { func install(_ *cobra.Command, _ []string) error {
return Prepare(true, boolVarForce, boolVarVerbose) return Prepare(true, boolVarForce, boolVarVerbose)

@ -0,0 +1,60 @@
package gateway
import (
_ "embed"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/util/ctx"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
var (
varStringHome string
varStringRemote string
varStringBranch string
varStringDir string
Cmd = cobrax.NewCommand("gateway", cobrax.WithRunE(generateGateway))
)
func init() {
Cmd.PersistentFlags().StringVar(&varStringHome, "home")
Cmd.PersistentFlags().StringVar(&varStringRemote, "remote")
Cmd.PersistentFlags().StringVar(&varStringBranch, "branch")
Cmd.PersistentFlags().StringVar(&varStringDir, "dir")
}
func generateGateway(*cobra.Command, []string) error {
if err:=pathx.MkdirIfNotExist(varStringDir);err!=nil{
return err
}
if _,err:=ctx.Prepare(varStringDir);err!=nil{
return err
}
etcContent, err := pathx.LoadTemplate(category, etcTemplateFileFile, etcTemplate)
if err != nil {
return err
}
mainContent, err := pathx.LoadTemplate(category, mainTemplateFile, mainTemplate)
if err != nil {
return err
}
etcDir := filepath.Join(varStringDir, "etc")
if err := pathx.MkdirIfNotExist(etcDir); err != nil {
return err
}
etcFile := filepath.Join(etcDir, "gateway.yaml")
if err := os.WriteFile(etcFile, []byte(etcContent), 0644); err != nil {
return err
}
mainFile := filepath.Join(varStringDir, "main.go")
return os.WriteFile(mainFile, []byte(mainContent), 0644)
}

@ -0,0 +1,18 @@
Name: gateway-example # gateway name
Host: localhost # gateway host
Port: 8888 # gateway port
Upstreams: # upstreams
- Grpc: # grpc upstream
Target: 0.0.0.0:8080 # grpc target,the direct grpc server address,for only one node
# Endpoints: [0.0.0.0:8080,192.168.120.1:8080] # grpc endpoints, the grpc server address list, for multiple nodes
# Etcd: # etcd config, if you want to use etcd to discover the grpc server address
# Hosts: [127.0.0.1:2378,127.0.0.1:2379] # etcd hosts
# Key: greet.grpc # the discovery key
# protoset mode
ProtoSets:
- hello.pb
# Mappings can also be written in proto options
# Mappings: # routes mapping
# - Method: get
# Path: /ping
# RpcPath: hello.Hello/Ping

@ -0,0 +1,20 @@
package main
import (
"flag"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/gateway"
)
var configFile = flag.String("f", "etc/gateway.yaml", "config file")
func main() {
flag.Parse()
var c gateway.GatewayConf
conf.MustLoad(*configFile, &c)
gw := gateway.MustNewServer(c)
defer gw.Stop()
gw.Start()
}

@ -0,0 +1,62 @@
package gateway
import (
_ "embed"
"fmt"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const (
category = "gateway"
etcTemplateFileFile = "etc.tpl"
mainTemplateFile = "main.tpl"
)
//go:embed conf.yml
var etcTemplate string
//go:embed gateway.tpl
var mainTemplate string
var templates = map[string]string{
etcTemplateFileFile: etcTemplate,
mainTemplateFile: mainTemplate,
}
// GenTemplates is the entry for command goctl template,
// it will create the specified category
func GenTemplates() error {
return pathx.InitTemplates(category, templates)
}
// RevertTemplate restores the deleted template files
func RevertTemplate(name string) error {
content, ok := templates[name]
if !ok {
return fmt.Errorf("%s: no such file name", name)
}
return pathx.CreateTemplate(category, name, content)
}
// Clean deletes all template files
func Clean() error {
return pathx.Clean(category)
}
// Update is used to update the template files, it will delete the existing old templates at first,
// and then create the latest template files
func Update() error {
err := Clean()
if err != nil {
return err
}
return pathx.InitTemplates(category, templates)
}
// Category returns a const string value for rpc template category
func Category() string {
return category
}

@ -10,6 +10,7 @@ require (
github.com/iancoleman/strcase v0.2.0 github.com/iancoleman/strcase v0.2.0
github.com/logrusorgru/aurora v2.0.3+incompatible github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/spf13/cobra v1.6.1 github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.2
github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1
github.com/zeromicro/antlr v0.0.1 github.com/zeromicro/antlr v0.0.1
@ -34,6 +35,7 @@ require (
github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/fatih/color v1.14.1 // indirect github.com/fatih/color v1.14.1 // indirect
github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/fgprof v0.9.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect
@ -69,7 +71,6 @@ require (
github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect
go.etcd.io/etcd/api/v3 v3.5.7 // indirect go.etcd.io/etcd/api/v3 v3.5.7 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect

@ -101,7 +101,8 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -541,6 +542,7 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

@ -0,0 +1,171 @@
package cobrax
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/zeromicro/go-zero/tools/goctl/internal/flags"
)
type Option func(*cobra.Command)
func WithRunE(runE func(*cobra.Command, []string) error) Option {
return func(cmd *cobra.Command) {
cmd.RunE = runE
}
}
func WithRun(run func(*cobra.Command, []string)) Option {
return func(cmd *cobra.Command) {
cmd.Run = run
}
}
func WithArgs(arg cobra.PositionalArgs) Option {
return func(command *cobra.Command) {
command.Args = arg
}
}
func WithHidden() Option {
return func(command *cobra.Command) {
command.Hidden = true
}
}
type Command struct {
*cobra.Command
}
type FlagSet struct {
*pflag.FlagSet
}
func (f *FlagSet) StringVar(p *string, name string) {
f.StringVarWithDefaultValue(p, name, "")
}
func (f *FlagSet) StringVarWithDefaultValue(p *string, name string, value string) {
f.FlagSet.StringVar(p, name, value, "")
}
func (f *FlagSet) StringVarP(p *string, name, shorthand string) {
f.StringVarPWithDefaultValue(p, name, shorthand, "")
}
func (f *FlagSet) StringVarPWithDefaultValue(p *string, name, shorthand string, value string) {
f.FlagSet.StringVarP(p, name, shorthand, value, "")
}
func (f *FlagSet) BoolVar(p *bool, name string) {
f.BoolVarWithDefaultValue(p, name, false)
}
func (f *FlagSet) BoolVarWithDefaultValue(p *bool, name string, value bool) {
f.FlagSet.BoolVar(p, name, value, "")
}
func (f *FlagSet) BoolVarP(p *bool, name, shorthand string) {
f.BoolVarPWithDefaultValue(p, name, shorthand, false)
}
func (f *FlagSet) BoolVarPWithDefaultValue(p *bool, name, shorthand string, value bool) {
f.FlagSet.BoolVarP(p, name, shorthand, value, "")
}
func (f *FlagSet) IntVar(p *int, name string) {
f.IntVarWithDefaultValue(p, name, 0)
}
func (f *FlagSet) IntVarWithDefaultValue(p *int, name string, value int) {
f.FlagSet.IntVar(p, name, value, "")
}
func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string) {
f.FlagSet.StringSliceVarP(p, name, shorthand, []string{}, "")
}
func (f *FlagSet) StringSliceVarPWithDefaultValue(p *[]string, name, shorthand string, value []string) {
f.FlagSet.StringSliceVarP(p, name, shorthand, value, "")
}
func (f *FlagSet) StringSliceVar(p *[]string, name string) {
f.StringSliceVarWithDefaultValue(p, name, []string{})
}
func (f *FlagSet) StringSliceVarWithDefaultValue(p *[]string, name string, value []string) {
f.FlagSet.StringSliceVar(p, name, value, "")
}
func NewCommand(use string, opts ...Option) *Command {
c := &Command{
Command: &cobra.Command{
Use: use,
},
}
for _, opt := range opts {
opt(c.Command)
}
return c
}
func (c *Command) AddCommand(cmds ...*Command) {
for _, cmd := range cmds {
c.Command.AddCommand(cmd.Command)
}
}
func (c *Command) Flags() *FlagSet {
set := c.Command.Flags()
return &FlagSet{
FlagSet: set,
}
}
func (c *Command) PersistentFlags() *FlagSet {
set := c.Command.PersistentFlags()
return &FlagSet{
FlagSet: set,
}
}
func (c *Command) MustInit() {
commands := append([]*cobra.Command{c.Command}, getCommandsRecursively(c.Command)...)
for _, command := range commands {
commandKey := getCommandName(command)
if len(command.Short) == 0 {
command.Short = flags.Get(commandKey + ".short")
}
if len(command.Long) == 0 {
command.Long = flags.Get(commandKey + ".long")
}
if len(command.Example) == 0 {
command.Example = flags.Get(commandKey + ".example")
}
command.Flags().VisitAll(func(flag *pflag.Flag) {
flag.Usage = flags.Get(fmt.Sprintf("%s.%s", commandKey, flag.Name))
})
command.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
flag.Usage = flags.Get(fmt.Sprintf("%s.%s", commandKey, flag.Name))
})
}
}
func getCommandName(cmd *cobra.Command) string {
if cmd.HasParent() {
return getCommandName(cmd.Parent()) + "." + cmd.Name()
}
return cmd.Name()
}
func getCommandsRecursively(parent *cobra.Command) []*cobra.Command {
var commands []*cobra.Command
for _, cmd := range parent.Commands() {
commands = append(commands, cmd)
commands = append(commands, getCommandsRecursively(cmd)...)
}
return commands
}

@ -0,0 +1,283 @@
{
"goctl": {
"short": "A cli tool to generate go-zero code",
"long": "A cli tool to generate api, zrpc, model code\n\nGitHub: https://github.com/zeromicro/go-zero\nSite: https://go-zero.dev",
"api": {
"short": "Generate api related files",
"o": "Output a sample api file",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"api": "The api file",
"dir": "The target dir",
"dart": {
"short": "Generate dart files for provided api in api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"legacy": "Legacy generator for flutter v1",
"hostname": "hostname of the server",
"scheme": "scheme of the server"
},
"doc": {
"short": "Generate doc files",
"dir": "{{.goctl.api.dir}}",
"o": "The output markdown directory"
},
"format": {
"short": "Format api files",
"dir": "{{.goctl.api.dir}}",
"iu": "Ignore update",
"stdin": "Use stdin to input api doc content, press \"ctrl + d\" to send EOF",
"declare": "Use to skip check api types already declare"
},
"go": {
"short": "Generate go files for provided api in api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"style": "{{.global.style}}"
},
"new": {
"short": "Fast create api service",
"Example": "goctl api new [options] service-name",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"style": "{{.global.style}}"
},
"validate": {
"short": "Validate api file",
"api": "{{.goctl.api.api}}"
},
"kt": {
"short": "Generate kotlin code for provided api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"pkg": "Define package name for kotlin file"
},
"plugin": {
"short": "Custom file generator",
"plugin": "The plugin file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"style": "{{.global.style}}"
},
"ts": {
"short": "Generate ts files for provided api in api file",
"dir": "{{.goctl.api.dir}}",
"api": "{{.goctl.api.api}}",
"caller": "The web api caller",
"unwrap": "Unwrap the webapi caller for import"
}
},
"bug": {
"short": "Report a bug"
},
"docker": {
"short": "Generate Dockerfile",
"exe": "The executable name in the built image",
"go": "The file that contains main function",
"base": "The base image to build the docker image, default scratch",
"port": "The port to expose, default none",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"version": "The goctl builder golang image version",
"tz": "The timezone of the container"
},
"kube": {
"short": "Generate kubernetes files",
"deploy": {
"short": "Generate deployment yaml file",
"name": "The name of deployment (required)",
"namespace": "The namespace of deployment (required)",
"image": "The docker image of deployment (required)",
"secret": "The secret to image pull from registry",
"requestCpu": "The request cpu to deploy",
"requestMem": "The request memory to deploy",
"limitCpu": "The limit cpu to deploy",
"limitMem": "The limit memory to deploy",
"o": "The output yaml file (required)",
"replicas": "The number of replicas to deploy",
"revisions": "The number of revision history to limit",
"port": "The port of the deployment to listen on pod (required)",
"nodePort": "The nodePort of the deployment to expose",
"targetPort": "The targetPort of the deployment, default to port",
"minReplicas": "The min replicas to deploy",
"maxReplicas": "The max replicas to deploy",
"imagePullPolicy": "The image pull policy of the deployment, default to IfNotPresent",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"serviceAccount": "TheServiceAccount for the deployment"
}
},
"env": {
"short": "Check or edit goctl environment",
"write": "Edit goctl environment",
"force": "Silent installation of non-existent dependencies",
"verbose": "Enable log output",
"install": {
"short": "Goctl env installation"
},
"check": {
"short": "Detect goctl env and dependency tools",
"install": "Install dependencies if not found"
}
},
"gateway": {
"short": "gateway is a tool to generate gateway code",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"dir": "The output dir",
"protoc": {
"short": "generate gateway code from proto file"
},
"protoset": {
"short": "generate gateway code from protoset file"
},
"server": {
"short": "generate gateway code from grpc server"
}
},
"model": {
"short": "Generate model code",
"dir": "The target dir",
"mysql": {
"short": "Generate mysql model",
"strict": "Generate model in strict mode",
"ignore-columns": "Ignore columns while creating or updating rows",
"datasource": {
"short": "Generate model from datasource",
"url": "The data source of database,like \"root:password@tcp(127.0.0.1:3306)/database",
"table": "The table or table globbing patterns in the database",
"cache": "Generate code with cache [optional]",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"idea": "For idea plugin [optional]",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
},
"ddl": {
"short": "Generate mysql model from ddl",
"src": "The path or path globbing patterns of the ddl",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"cache": "Generate code with cache [optional]",
"idea": "For idea plugin [optional]",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
}
},
"pg": {
"short": "Generate postgresql model",
"datasource": {
"short": "Generate model from datasource",
"url": "The data source of database,like \"root:password@tcp(127.0.0.1:3306)/database",
"table": "The table or table globbing patterns in the database",
"schema": "The schema or schema globbing patterns in the database",
"cache": "Generate code with cache [optional]",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"idea": "For idea plugin [optional]",
"strict": "Generate model in strict mode",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
}
},
"mongo": {
"short": "Generate mongo model",
"type": "Specified model type name",
"cache": "Generate code with cache [optional]",
"easy": "Generate code with auto generated CollectionName for easy declare [optional]",
"dir": "{{.goctl.model.dir}}",
"style": "{{.global.style}}",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
}
},
"migrate": {
"short": "Migrate from tal-tech to zeromicro",
"long": "Migrate is a transition command to help users migrate their projects from tal-tech to zeromicro version",
"verbose": "Verbose enables extra logging",
"version": "The target release version of github.com/zeromicro/go-zero to migrate"
},
"quickstart": {
"short": "quickly start a project",
"service-type": "specify the service type, supported values: [mono, micro]"
},
"rpc": {
"short": "Generate rpc code",
"o": "Output a sample proto file",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"new": {
"short": "Generate rpc demo service",
"style": "{{.global.style}}",
"idea": "For idea plugin [optional]",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"verbose": "Enable log output"
},
"template": {
"short": "Generate proto template",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}"
},
"protoc": {
"short": "Generate grpc code",
"example": "goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.",
"multiple": "Generated in multiple rpc service mode",
"zrpc_out": "The zrpc output directory",
"style": "{{.global.style}}",
"home": "{{.global.home}}",
"remote": "{{.global.remote}}",
"branch": "{{.global.branch}}",
"verbose": "Enable log output"
}
},
"template": {
"short": "Template operation",
"home": "The goctl home path of the template",
"init": {
"short": "Initialize the all templates(force update)",
"home": "{{.goctl.template.home}}",
"category": "The category of template, enum [api,rpc,model,docker,kube]"
},
"clean": {
"short": "Clean the all cache templates",
"home": "{{.goctl.template.home}}"
},
"update": {
"short": "Update template of the target category to the latest",
"home": "{{.goctl.template.home}}",
"category": "{{.goctl.template.category}}"
},
"revert": {
"short": "Revert the target template to the latest",
"home": "{{.goctl.template.home}}",
"category": "{{.goctl.template.category}}",
"name": "The target file name of template"
}
},
"upgrade": {
"short": "Upgrade goctl to latest version"
}
},
"global": {
"home": "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority",
"remote": "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure",
"branch": "The branch of the remote repo, it does work with --remote",
"style": "The file naming format, see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]"
}
}

@ -0,0 +1,101 @@
package flags
import (
"bytes"
_ "embed"
"encoding/json"
"fmt"
"io"
"log"
"strings"
"testing"
"github.com/zeromicro/go-zero/tools/goctl/util"
)
//go:embed default_en.json
var defaultEnFlagConfig []byte
type ConfigLoader struct {
conf map[string]any
}
func (cl *ConfigLoader) ReadConfig(in io.Reader) error {
return json.NewDecoder(in).Decode(&cl.conf)
}
func (cl *ConfigLoader) GetString(key string) string {
keyList := strings.FieldsFunc(key, func(r rune) bool {
return r == '.'
})
var conf = cl.conf
for idx, k := range keyList {
val, ok := conf[k]
if !ok {
return ""
}
if idx < len(keyList)-1 {
conf, ok = val.(map[string]any)
if !ok {
return ""
}
continue
}
return fmt.Sprint(val)
}
return ""
}
type Flags struct {
loader *ConfigLoader
}
func MustLoad() *Flags {
loader := &ConfigLoader{
conf: map[string]any{},
}
if err := loader.ReadConfig(bytes.NewBuffer(defaultEnFlagConfig)); err != nil {
log.Fatal(err)
}
return &Flags{
loader: loader,
}
}
func setTestData(t *testing.T, data []byte) {
origin := defaultEnFlagConfig
defaultEnFlagConfig = data
t.Cleanup(func() {
defaultEnFlagConfig = origin
})
}
func (f *Flags) Get(key string) (string, error) {
value := f.loader.GetString(key)
for util.IsTemplateVariable(value) {
value = util.TemplateVariable(value)
if value == key {
return "", fmt.Errorf("the variable can not be self: %q", key)
}
return f.Get(value)
}
return value, nil
}
var flags *Flags
func Get(key string) string {
if flags == nil {
flags = MustLoad()
}
v, err := flags.Get(key)
if err != nil {
log.Fatal(err)
return ""
}
return v
}

@ -0,0 +1,78 @@
package flags
import (
"fmt"
"testing"
"github.com/zeromicro/go-zero/tools/goctl/test"
)
func TestFlags_Get(t *testing.T) {
setTestData(t, []byte(`{"host":"0.0.0.0","port":8888,"service":{"host":"{{.host}}","port":"{{.port}}","invalid":"{{.service.invalid}}"}}`))
f := MustLoad()
executor := test.NewExecutor[string, string]()
executor.Add([]test.Data[string, string]{
{
Name: "key_host",
Input: "host",
Want: "0.0.0.0",
},
{
Name: "key_port",
Input: "port",
Want: "8888",
},
{
Name: "key_service.host",
Input: "service.host",
Want: "0.0.0.0",
},
{
Name: "key_service.port",
Input: "service.port",
Want: "8888",
},
{
Name: "key_not_exists",
Input: "service.port.invalid",
},
{
Name: "key_service.invalid",
Input: "service.invalid",
E: fmt.Errorf("the variable can not be self: %q", "service.invalid"),
},
}...)
executor.RunE(t, f.Get)
}
func Test_Get(t *testing.T) {
setTestData(t, []byte(`{"host":"0.0.0.0","port":8888,"service":{"host":"{{.host}}","port":"{{.port}}","invalid":"{{.service.invalid}}"}}`))
executor := test.NewExecutor[string, string]()
executor.Add([]test.Data[string, string]{
{
Name: "key_host",
Input: "host",
Want: "0.0.0.0",
},
{
Name: "key_port",
Input: "port",
Want: "8888",
},
{
Name: "key_service.host",
Input: "service.host",
Want: "0.0.0.0",
},
{
Name: "key_service.port",
Input: "service.port",
Want: "8888",
},
{
Name: "key_not_exists",
Input: "service.port.invalid",
},
}...)
executor.Run(t, Get)
}

@ -1,6 +1,6 @@
package kube package kube
import "github.com/spf13/cobra" import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var ( var (
varStringName string varStringName string
@ -26,50 +26,38 @@ var (
varStringImagePullPolicy string varStringImagePullPolicy string
// Cmd describes a kube command. // Cmd describes a kube command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("kube")
Use: "kube", deployCmd = cobrax.NewCommand("deploy", cobrax.WithRunE(deploymentCommand))
Short: "Generate kubernetes files",
}
deployCmd = &cobra.Command{
Use: "deploy",
Short: "Generate deployment yaml file",
RunE: deploymentCommand,
}
) )
func init() { func init() {
deployCmd.Flags().StringVar(&varStringName, "name", "", "The name of deployment (required)") deployCmdFlags := deployCmd.Flags()
deployCmd.Flags().StringVar(&varStringNamespace, "namespace", "", "The namespace of deployment (required)") deployCmdFlags.StringVar(&varStringName, "name")
deployCmd.Flags().StringVar(&varStringImage, "image", "", "The docker image of deployment (required)") deployCmdFlags.StringVar(&varStringNamespace, "namespace")
deployCmd.Flags().StringVar(&varStringSecret, "secret", "", "The secret to image pull from registry") deployCmdFlags.StringVar(&varStringImage, "image")
deployCmd.Flags().IntVar(&varIntRequestCpu, "requestCpu", 500, "The request cpu to deploy") deployCmdFlags.StringVar(&varStringSecret, "secret")
deployCmd.Flags().IntVar(&varIntRequestMem, "requestMem", 512, "The request memory to deploy") deployCmdFlags.IntVarWithDefaultValue(&varIntRequestCpu, "requestCpu", 500)
deployCmd.Flags().IntVar(&varIntLimitCpu, "limitCpu", 1000, "The limit cpu to deploy") deployCmdFlags.IntVarWithDefaultValue(&varIntRequestMem, "requestMem", 512)
deployCmd.Flags().IntVar(&varIntLimitMem, "limitMem", 1024, "The limit memory to deploy") deployCmdFlags.IntVarWithDefaultValue(&varIntLimitCpu, "limitCpu", 1000)
deployCmd.Flags().StringVar(&varStringO, "o", "", "The output yaml file (required)") deployCmdFlags.IntVarWithDefaultValue(&varIntLimitMem, "limitMem", 1024)
deployCmd.Flags().IntVar(&varIntReplicas, "replicas", 3, "The number of replicas to deploy") deployCmdFlags.StringVar(&varStringO, "o")
deployCmd.Flags().IntVar(&varIntRevisions, "revisions", 5, "The number of revision history to limit") deployCmdFlags.IntVarWithDefaultValue(&varIntReplicas, "replicas", 3)
deployCmd.Flags().IntVar(&varIntPort, "port", 0, "The port of the deployment to listen on pod (required)") deployCmdFlags.IntVarWithDefaultValue(&varIntRevisions, "revisions", 5)
deployCmd.Flags().IntVar(&varIntNodePort, "nodePort", 0, "The nodePort of the deployment to expose") deployCmdFlags.IntVar(&varIntPort, "port")
deployCmd.Flags().IntVar(&varIntTargetPort, "targetPort", 0, "The targetPort of the deployment, default to port") deployCmdFlags.IntVar(&varIntNodePort, "nodePort")
deployCmd.Flags().IntVar(&varIntMinReplicas, "minReplicas", 3, "The min replicas to deploy") deployCmdFlags.IntVar(&varIntTargetPort, "targetPort")
deployCmd.Flags().IntVar(&varIntMaxReplicas, "maxReplicas", 10, "The max replicas to deploy") deployCmdFlags.IntVarWithDefaultValue(&varIntMinReplicas, "minReplicas", 3)
deployCmd.Flags().StringVar(&varStringImagePullPolicy, "imagePullPolicy", "", "Image pull policy. One of Always, Never, IfNotPresent") deployCmdFlags.IntVarWithDefaultValue(&varIntMaxReplicas, "maxReplicas", 10)
deployCmdFlags.StringVar(&varStringImagePullPolicy, "imagePullPolicy")
deployCmdFlags.StringVar(&varStringHome, "home")
deployCmdFlags.StringVar(&varStringRemote, "remote")
deployCmdFlags.StringVar(&varStringBranch, "branch")
deployCmdFlags.StringVar(&varStringServiceAccount, "serviceAccount")
deployCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template, "+ _ = deployCmd.MarkFlagRequired("name")
"--home and --remote cannot be set at the same time, if they are, --remote has higher priority") _ = deployCmd.MarkFlagRequired("namespace")
deployCmd.Flags().StringVar(&varStringRemote, "remote", "", "The remote git repo of the template, "+ _ = deployCmd.MarkFlagRequired("o")
"--home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo "+ _ = deployCmd.MarkFlagRequired("port")
"directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
deployCmd.Flags().StringVar(&varStringBranch, "branch", "", "The branch of the remote repo, it "+
"does work with --remote")
deployCmd.Flags().StringVar(&varStringServiceAccount, "serviceAccount", "", "The ServiceAccount "+
"for the deployment")
deployCmd.MarkFlagRequired("name")
deployCmd.MarkFlagRequired("namespace")
deployCmd.MarkFlagRequired("o")
deployCmd.MarkFlagRequired("port")
Cmd.AddCommand(deployCmd) Cmd.AddCommand(deployCmd)
} }

@ -1,23 +1,16 @@
package migrate package migrate
import "github.com/spf13/cobra" import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
var ( var (
boolVarVerbose bool boolVarVerbose bool
stringVarVersion string stringVarVersion string
// Cmd describes a migrate command. // Cmd describes a migrate command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("migrate", cobrax.WithRunE(migrate))
Use: "migrate",
Short: "Migrate from tal-tech to zeromicro",
Long: "Migrate is a transition command to help users migrate their " +
"projects from tal-tech to zeromicro version",
RunE: migrate,
}
) )
func init() { func init() {
Cmd.Flags().BoolVarP(&boolVarVerbose, "verbose", "v", migrateCmdFlags := Cmd.Flags()
false, "Verbose enables extra logging") migrateCmdFlags.BoolVarP(&boolVarVerbose, "verbose", "v")
Cmd.Flags().StringVar(&stringVarVersion, "version", defaultMigrateVersion, migrateCmdFlags.StringVarWithDefaultValue(&stringVarVersion, "version", defaultMigrateVersion)
"The target release version of github.com/zeromicro/go-zero to migrate")
} }

@ -1,104 +1,75 @@
package model package model
import ( import (
"github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/model/mongo" "github.com/zeromicro/go-zero/tools/goctl/model/mongo"
"github.com/zeromicro/go-zero/tools/goctl/model/sql/command" "github.com/zeromicro/go-zero/tools/goctl/model/sql/command"
) )
var ( var (
// Cmd describes a model command. // Cmd describes a model command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("model")
Use: "model", mysqlCmd = cobrax.NewCommand("mysql")
Short: "Generate model code", ddlCmd = cobrax.NewCommand("ddl", cobrax.WithRunE(command.MysqlDDL))
} datasourceCmd = cobrax.NewCommand("datasource", cobrax.WithRunE(command.MySqlDataSource))
pgCmd = cobrax.NewCommand("pg", cobrax.WithRunE(command.PostgreSqlDataSource))
mysqlCmd = &cobra.Command{ pgDatasourceCmd = cobrax.NewCommand("datasource", cobrax.WithRunE(command.PostgreSqlDataSource))
Use: "mysql", mongoCmd = cobrax.NewCommand("mongo", cobrax.WithRunE(mongo.Action))
Short: "Generate mysql model",
}
ddlCmd = &cobra.Command{
Use: "ddl",
Short: "Generate mysql model from ddl",
RunE: command.MysqlDDL,
}
datasourceCmd = &cobra.Command{
Use: "datasource",
Short: "Generate model from datasource",
RunE: command.MySqlDataSource,
}
pgCmd = &cobra.Command{
Use: "pg",
Short: "Generate postgresql model",
RunE: command.PostgreSqlDataSource,
}
pgDatasourceCmd = &cobra.Command{
Use: "datasource",
Short: "Generate model from datasource",
RunE: command.PostgreSqlDataSource,
}
mongoCmd = &cobra.Command{
Use: "mongo",
Short: "Generate mongo model",
RunE: mongo.Action,
}
) )
func init() { func init() {
ddlCmd.Flags().StringVarP(&command.VarStringSrc, "src", "s", "", "The path or path globbing patterns of the ddl") var (
ddlCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir") ddlCmdFlags = ddlCmd.Flags()
ddlCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") datasourceCmdFlags = datasourceCmd.Flags()
ddlCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") pgDatasourceCmdFlags = pgDatasourceCmd.Flags()
ddlCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]") mongoCmdFlags = mongoCmd.Flags()
ddlCmd.Flags().StringVar(&command.VarStringDatabase, "database", "", "The name of database [optional]") )
ddlCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
ddlCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") ddlCmdFlags.StringVarP(&command.VarStringSrc, "src", "s")
ddlCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") ddlCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")
ddlCmdFlags.StringVar(&command.VarStringStyle, "style")
ddlCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
ddlCmdFlags.BoolVar(&command.VarBoolIdea, "idea")
ddlCmdFlags.StringVar(&command.VarStringDatabase, "database")
ddlCmdFlags.StringVar(&command.VarStringHome, "home")
ddlCmdFlags.StringVar(&command.VarStringRemote, "remote")
ddlCmdFlags.StringVar(&command.VarStringBranch, "branch")
datasourceCmd.Flags().StringVar(&command.VarStringURL, "url", "", `The data source of database,like "root:password@tcp(127.0.0.1:3306)/database"`) datasourceCmdFlags.StringVar(&command.VarStringURL, "url")
datasourceCmd.Flags().StringSliceVarP(&command.VarStringSliceTable, "table", "t", nil, "The table or table globbing patterns in the database") datasourceCmdFlags.StringSliceVarP(&command.VarStringSliceTable, "table", "t")
datasourceCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") datasourceCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
datasourceCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir") datasourceCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")
datasourceCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") datasourceCmdFlags.StringVar(&command.VarStringStyle, "style")
datasourceCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]") datasourceCmdFlags.BoolVar(&command.VarBoolIdea, "idea")
datasourceCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") datasourceCmdFlags.StringVar(&command.VarStringHome, "home")
datasourceCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") datasourceCmdFlags.StringVar(&command.VarStringRemote, "remote")
datasourceCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") datasourceCmdFlags.StringVar(&command.VarStringBranch, "branch")
pgDatasourceCmd.Flags().StringVar(&command.VarStringURL, "url", "", `The data source of database,like "postgres://root:password@127.0.0.1:5432/database?sslmode=disable"`) pgDatasourceCmdFlags.StringVar(&command.VarStringURL, "url")
pgDatasourceCmd.Flags().StringVarP(&command.VarStringTable, "table", "t", "", "The table or table globbing patterns in the database") pgDatasourceCmdFlags.StringVarP(&command.VarStringTable, "table", "t")
pgDatasourceCmd.Flags().StringVarP(&command.VarStringSchema, "schema", "s", "public", "The table schema") pgDatasourceCmdFlags.StringVarPWithDefaultValue(&command.VarStringSchema, "schema", "s", "public")
pgDatasourceCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") pgDatasourceCmdFlags.BoolVarP(&command.VarBoolCache, "cache", "c")
pgDatasourceCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir") pgDatasourceCmdFlags.StringVarP(&command.VarStringDir, "dir", "d")
pgDatasourceCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") pgDatasourceCmdFlags.StringVar(&command.VarStringStyle, "style")
pgDatasourceCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]") pgDatasourceCmdFlags.BoolVar(&command.VarBoolIdea, "idea")
pgDatasourceCmd.Flags().BoolVar(&command.VarBoolStrict, "strict", false, "Generate model in strict mode") pgDatasourceCmdFlags.BoolVar(&command.VarBoolStrict, "strict")
pgDatasourceCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") pgDatasourceCmdFlags.StringVar(&command.VarStringHome, "home")
pgDatasourceCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") pgDatasourceCmdFlags.StringVar(&command.VarStringRemote, "remote")
pgDatasourceCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") pgDatasourceCmdFlags.StringVar(&command.VarStringBranch, "branch")
mongoCmd.Flags().StringSliceVarP(&mongo.VarStringSliceType, "type", "t", nil, "Specified model type name") mongoCmdFlags.StringSliceVarP(&mongo.VarStringSliceType, "type", "t")
mongoCmd.Flags().BoolVarP(&mongo.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") mongoCmdFlags.BoolVarP(&mongo.VarBoolCache, "cache", "c")
mongoCmd.Flags().BoolVarP(&mongo.VarBoolEasy, "easy", "e", false, "Generate code with auto generated CollectionName for easy declare [optional]") mongoCmdFlags.BoolVarP(&mongo.VarBoolEasy, "easy", "e")
mongoCmd.Flags().StringVarP(&mongo.VarStringDir, "dir", "d", "", "The target dir") mongoCmdFlags.StringVarP(&mongo.VarStringDir, "dir", "d")
mongoCmd.Flags().StringVar(&mongo.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") mongoCmdFlags.StringVar(&mongo.VarStringStyle, "style")
mongoCmd.Flags().StringVar(&mongo.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") mongoCmdFlags.StringVar(&mongo.VarStringHome, "home")
mongoCmd.Flags().StringVar(&mongo.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") mongoCmdFlags.StringVar(&mongo.VarStringRemote, "remote")
mongoCmd.Flags().StringVar(&mongo.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") mongoCmdFlags.StringVar(&mongo.VarStringBranch, "branch")
mysqlCmd.PersistentFlags().BoolVar(&command.VarBoolStrict, "strict", false, "Generate model in strict mode") mysqlCmd.PersistentFlags().BoolVar(&command.VarBoolStrict, "strict")
mysqlCmd.PersistentFlags().StringSliceVarP(&command.VarStringSliceIgnoreColumns, "ignore-columns", "i", []string{"create_at", "created_at", "create_time", "update_at", "updated_at", "update_time"}, "Ignore columns while creating or updating rows") mysqlCmd.PersistentFlags().StringSliceVarPWithDefaultValue(&command.VarStringSliceIgnoreColumns, "ignore-columns", "i", []string{"create_at", "created_at", "create_time", "update_at", "updated_at", "update_time"})
mysqlCmd.AddCommand(datasourceCmd) mysqlCmd.AddCommand(datasourceCmd, ddlCmd)
mysqlCmd.AddCommand(ddlCmd)
pgCmd.AddCommand(pgDatasourceCmd) pgCmd.AddCommand(pgDatasourceCmd)
Cmd.AddCommand(mysqlCmd) Cmd.AddCommand(mysqlCmd, mongoCmd, pgCmd)
Cmd.AddCommand(mongoCmd)
Cmd.AddCommand(pgCmd)
} }

@ -62,6 +62,7 @@ func init() {
experimental := existsEnv.GetOr(GoctlExperimental, ExperimentalOff) experimental := existsEnv.GetOr(GoctlExperimental, ExperimentalOff)
goctlEnv.SetKV(GoctlExperimental, experimental) goctlEnv.SetKV(GoctlExperimental, experimental)
} }
if !goctlEnv.HasKey(GoctlHome) { if !goctlEnv.HasKey(GoctlHome) {
goctlEnv.SetKV(GoctlHome, defaultGoctlHome) goctlEnv.SetKV(GoctlHome, defaultGoctlHome)
} }
@ -90,8 +91,20 @@ func init() {
goctlEnv.SetKV(ProtocGenGoGRPCVersion, protocGenGoGrpcVer) goctlEnv.SetKV(ProtocGenGoGRPCVersion, protocGenGoGrpcVer)
} }
func Print() string { func Print(args ...string) string {
if len(args) == 0 {
return strings.Join(goctlEnv.Format(), "\n") return strings.Join(goctlEnv.Format(), "\n")
}
var values []string
for _, key := range args {
value, ok := goctlEnv.GetString(key)
if !ok {
value = fmt.Sprintf("%s=%%not found%%", key)
}
values = append(values, fmt.Sprintf("%s=%s", key, value))
}
return strings.Join(values, "\n")
} }
func Get(key string) string { func Get(key string) string {

@ -1,6 +1,6 @@
package quickstart package quickstart
import "github.com/spf13/cobra" import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
const ( const (
serviceTypeMono = "mono" serviceTypeMono = "mono"
@ -11,15 +11,9 @@ var (
varStringServiceType string varStringServiceType string
// Cmd describes the command to run. // Cmd describes the command to run.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("quickstart", cobrax.WithRunE(run))
Use: "quickstart",
Short: "quickly start a project",
RunE: run,
}
) )
func init() { func init() {
Cmd.Flags().StringVarP(&varStringServiceType, Cmd.Flags().StringVarPWithDefaultValue(&varStringServiceType, "service-type", "t", "mono")
"service-type", "t", "mono",
"specify the service type, supported values: [mono, micro]")
} }

@ -3,114 +3,70 @@ package rpc
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/rpc/cli" "github.com/zeromicro/go-zero/tools/goctl/rpc/cli"
) )
var ( var (
// Cmd describes a rpc command. // Cmd describes a rpc command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("rpc", cobrax.WithRunE(func(command *cobra.Command, strings []string) error {
Use: "rpc",
Short: "Generate rpc code",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.RPCTemplate(true) return cli.RPCTemplate(true)
}, }))
} templateCmd = cobrax.NewCommand("template", cobrax.WithRunE(func(command *cobra.Command, strings []string) error {
newCmd = &cobra.Command{
Use: "new",
Short: "Generate rpc demo service",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: cli.RPCNew,
}
templateCmd = &cobra.Command{
Use: "template",
Short: "Generate proto template",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.RPCTemplate(false) return cli.RPCTemplate(false)
}, }))
}
protocCmd = &cobra.Command{ newCmd = cobrax.NewCommand("new", cobrax.WithRunE(cli.RPCNew), cobrax.WithArgs(cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)))
Use: "protoc", protocCmd = cobrax.NewCommand("protoc", cobrax.WithRunE(cli.ZRPC), cobrax.WithArgs(cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)))
Short: "Generate grpc code",
Example: "goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: cli.ZRPC,
}
) )
func init() { func init() {
Cmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file") var (
Cmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of "+ rpcCmdFlags = Cmd.Flags()
"the template, --home and --remote cannot be set at the same time, if they are, --remote has"+ newCmdFlags = newCmd.Flags()
" higher priority") protocCmdFlags = protocCmd.Flags()
Cmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo"+ templateCmdFlags = templateCmd.Flags()
" of the template, --home and --remote cannot be set at the same time, if they are, --remote"+ )
" has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure") rpcCmdFlags.StringVar(&cli.VarStringOutput, "o")
Cmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the "+ rpcCmdFlags.StringVar(&cli.VarStringHome, "home")
"remote repo, it does work with --remote") rpcCmdFlags.StringVar(&cli.VarStringRemote, "remote")
rpcCmdFlags.StringVar(&cli.VarStringBranch, "branch")
newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "") newCmdFlags.StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt")
newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "") newCmdFlags.StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt")
newCmd.Flags().StringVar(&cli.VarStringStyle, "style", config.DefaultFormat, "The file "+ newCmdFlags.StringVarWithDefaultValue(&cli.VarStringStyle, "style", config.DefaultFormat)
"naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") newCmdFlags.BoolVar(&cli.VarBoolIdea, "idea")
newCmd.Flags().BoolVar(&cli.VarBoolIdea, "idea", false, "Whether the command "+ newCmdFlags.StringVar(&cli.VarStringHome, "home")
"execution environment is from idea plugin.") newCmdFlags.StringVar(&cli.VarStringRemote, "remote")
newCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path "+ newCmdFlags.StringVar(&cli.VarStringBranch, "branch")
"of the template, --home and --remote cannot be set at the same time, if they are, --remote "+ newCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
"has higher priority") newCmdFlags.MarkHidden("go_opt")
newCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git "+ newCmdFlags.MarkHidden("go-grpc_opt")
"repo of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
newCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "",
"The branch of the remote repo, it does work with --remote")
newCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output")
newCmd.Flags().MarkHidden("go_opt")
newCmd.Flags().MarkHidden("go-grpc_opt")
protocCmd.Flags().BoolVarP(&cli.VarBoolMultiple, "multiple", "m", false, protocCmdFlags.BoolVarP(&cli.VarBoolMultiple, "multiple", "m")
"Generated in multiple rpc service mode") protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoOut, "go_out")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOut, "go_out", nil, "") protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoGRPCOut, "go-grpc_out")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOut, "go-grpc_out", nil, "") protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "") protocCmdFlags.StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "") protocCmdFlags.StringSliceVar(&cli.VarStringSlicePlugin, "plugin")
protocCmd.Flags().StringSliceVar(&cli.VarStringSlicePlugin, "plugin", nil, "") protocCmdFlags.StringSliceVarP(&cli.VarStringSliceProtoPath, "proto_path", "I")
protocCmd.Flags().StringSliceVarP(&cli.VarStringSliceProtoPath, "proto_path", "I", nil, "") protocCmdFlags.StringVar(&cli.VarStringZRPCOut, "zrpc_out")
protocCmd.Flags().StringVar(&cli.VarStringZRPCOut, "zrpc_out", "", "The zrpc output directory") protocCmdFlags.StringVar(&cli.VarStringHome, "home")
protocCmd.Flags().StringVar(&cli.VarStringStyle, "style", config.DefaultFormat, "The file "+ protocCmdFlags.StringVar(&cli.VarStringRemote, "remote")
"naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") protocCmdFlags.StringVar(&cli.VarStringBranch, "branch")
protocCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home "+ protocCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
"path of the template, --home and --remote cannot be set at the same time, if they are, "+ protocCmdFlags.MarkHidden("go_out")
"--remote has higher priority") protocCmdFlags.MarkHidden("go-grpc_out")
protocCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote "+ protocCmdFlags.MarkHidden("go_opt")
"git repo of the template, --home and --remote cannot be set at the same time, if they are, "+ protocCmdFlags.MarkHidden("go-grpc_opt")
"--remote has higher priority\n\tThe git repo directory must be consistent with the "+ protocCmdFlags.MarkHidden("plugin")
"https://github.com/zeromicro/go-zero-template directory structure") protocCmdFlags.MarkHidden("proto_path")
protocCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "",
"The branch of the remote repo, it does work with --remote")
protocCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output")
protocCmd.Flags().MarkHidden("go_out")
protocCmd.Flags().MarkHidden("go-grpc_out")
protocCmd.Flags().MarkHidden("go_opt")
protocCmd.Flags().MarkHidden("go-grpc_opt")
protocCmd.Flags().MarkHidden("plugin")
protocCmd.Flags().MarkHidden("proto_path")
templateCmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file") templateCmdFlags.StringVar(&cli.VarStringOutput, "o")
templateCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home"+ templateCmdFlags.StringVar(&cli.VarStringHome, "home")
" path of the template, --home and --remote cannot be set at the same time, if they are, "+ templateCmdFlags.StringVar(&cli.VarStringRemote, "remote")
"--remote has higher priority") templateCmdFlags.StringVar(&cli.VarStringBranch, "branch")
templateCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote "+
"git repo of the template, --home and --remote cannot be set at the same time, if they are, "+
"--remote has higher priority\n\tThe git repo directory must be consistent with the "+
"https://github.com/zeromicro/go-zero-template directory structure")
templateCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch"+
" of the remote repo, it does work with --remote")
Cmd.AddCommand(newCmd) Cmd.AddCommand(newCmd, protocCmd, templateCmd)
Cmd.AddCommand(protocCmd)
Cmd.AddCommand(templateCmd)
} }

@ -0,0 +1,86 @@
package test
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
type Data[T, Y any] struct {
Name string
Input T
Want Y
E error
}
type Option[T, Y any] func(*Executor[T, Y])
type assertFn[Y any] func(t *testing.T, expected, actual Y) bool
func WithComparison[T, Y any](comparisonFn assertFn[Y]) Option[T, Y] {
return func(e *Executor[T, Y]) {
e.equalFn = comparisonFn
}
}
type Executor[T, Y any] struct {
list []Data[T, Y]
equalFn assertFn[Y]
}
func NewExecutor[T, Y any](opt ...Option[T, Y]) *Executor[T, Y] {
e := &Executor[T, Y]{}
opt = append(opt, WithComparison[T, Y](func(t *testing.T, expected, actual Y) bool {
gotBytes, err := json.Marshal(actual)
if err != nil {
t.Fatal(err)
return false
}
wantBytes, err := json.Marshal(expected)
if err != nil {
t.Fatal(err)
return false
}
return assert.JSONEq(t, string(wantBytes), string(gotBytes))
}))
for _, o := range opt {
o(e)
}
return e
}
func (e *Executor[T, Y]) Add(data ...Data[T, Y]) {
e.list = append(e.list, data...)
}
func (e *Executor[T, Y]) Run(t *testing.T, do func(T) Y) {
if do == nil {
panic("execution body is nil")
return
}
for _, v := range e.list {
t.Run(v.Name, func(t *testing.T) {
inner := do
e.equalFn(t, v.Want, inner(v.Input))
})
}
}
func (e *Executor[T, Y]) RunE(t *testing.T, do func(T) (Y, error)) {
if do == nil {
panic("execution body is nil")
return
}
for _, v := range e.list {
t.Run(v.Name, func(t *testing.T) {
inner := do
got, err := inner(v.Input)
if v.E != nil {
assert.Equal(t, v.E, err)
return
}
e.equalFn(t, v.Want, got)
})
}
}

@ -0,0 +1,101 @@
package test
import (
"errors"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestExecutor_Run(t *testing.T) {
executor := NewExecutor[string, string]()
executor.Add([]Data[string, string]{
{
Name: "empty",
},
{
Name: "snake_case",
input: "A_B_C",
want: "a_b_c",
},
{
Name: "camel_case",
input: "AaBbCc",
want: "aabbcc",
},
}...)
executor.Run(t, func(s string) string {
return strings.ToLower(s)
})
}
func TestExecutor_RunE(t *testing.T) {
var dummyError = errors.New("dummy error")
executor := NewExecutor[string, string]()
executor.Add([]Data[string, string]{
{
Name: "empty",
},
{
Name: "snake_case",
input: "A_B_C",
want: "a_b_c",
},
{
Name: "camel_case",
input: "AaBbCc",
want: "aabbcc",
},
{
Name: "invalid_input",
input: "😄",
E: dummyError,
},
}...)
executor.RunE(t, func(s string) (string, error) {
for _, r := range s {
if r == '_' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' {
continue
}
return "", dummyError
}
return strings.ToLower(s), nil
})
}
func TestWithComparison(t *testing.T) {
var dummyError = errors.New("dummy error")
executor := NewExecutor[string, string](WithComparison[string, string](func(t *testing.T, expected, actual string) bool {
return assert.Equal(t, expected, actual)
}))
executor.Add([]Data[string, string]{
{
Name: "empty",
},
{
Name: "snake_case",
input: "A_B_C",
want: "a_b_c",
},
{
Name: "camel_case",
input: "AaBbCc",
want: "aabbcc",
},
{
Name: "invalid_input",
input: "😄",
E: dummyError,
},
}...)
executor.RunE(t, func(s string) (string, error) {
for _, r := range s {
if r == '_' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' {
continue
}
return "", dummyError
}
return strings.ToLower(s), nil
})
}

@ -1,55 +1,27 @@
package tpl package tpl
import ( import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/spf13/cobra"
)
var ( var (
varStringHome string varStringHome string
varStringCategory string varStringCategory string
varStringName string varStringName string
// Cmd describes a template command. // Cmd describes a template command.
Cmd = &cobra.Command{ Cmd = cobrax.NewCommand("template")
Use: "template", initCmd = cobrax.NewCommand("init", cobrax.WithRunE(genTemplates))
Short: "Template operation", cleanCmd = cobrax.NewCommand("clean", cobrax.WithRunE(cleanTemplates))
} updateCmd = cobrax.NewCommand("update", cobrax.WithRunE(updateTemplates))
revertCmd = cobrax.NewCommand("revert", cobrax.WithRunE(revertTemplates))
initCmd = &cobra.Command{
Use: "init",
Short: "Initialize the all templates(force update)",
RunE: genTemplates,
}
cleanCmd = &cobra.Command{
Use: "clean",
Short: "Clean the all cache templates",
RunE: cleanTemplates,
}
updateCmd = &cobra.Command{
Use: "update",
Short: "Update template of the target category to the latest",
RunE: updateTemplates,
}
revertCmd = &cobra.Command{
Use: "revert",
Short: "Revert the target template to the latest",
RunE: revertTemplates,
}
) )
func init() { func init() {
initCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") initCmd.Flags().StringVar(&varStringHome, "home")
cleanCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") cleanCmd.Flags().StringVar(&varStringHome, "home")
updateCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") updateCmd.Flags().StringVar(&varStringHome, "home")
updateCmd.Flags().StringVarP(&varStringCategory, "category", "c", "", "The category of template, enum [api,rpc,model,docker,kube]") updateCmd.Flags().StringVarP(&varStringCategory, "category", "c")
revertCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") revertCmd.Flags().StringVar(&varStringHome, "home")
revertCmd.Flags().StringVarP(&varStringCategory, "category", "c", "", "The category of template, enum [api,rpc,model,docker,kube]") revertCmd.Flags().StringVarP(&varStringCategory, "category", "c")
revertCmd.Flags().StringVarP(&varStringName, "name", "n", "", "The target file name of template") revertCmd.Flags().StringVarP(&varStringName, "name", "n")
Cmd.AddCommand(cleanCmd) Cmd.AddCommand(cleanCmd, initCmd, revertCmd, updateCmd)
Cmd.AddCommand(initCmd)
Cmd.AddCommand(revertCmd)
Cmd.AddCommand(updateCmd)
} }

@ -11,6 +11,7 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/gogen" "github.com/zeromicro/go-zero/tools/goctl/api/gogen"
apinew "github.com/zeromicro/go-zero/tools/goctl/api/new" apinew "github.com/zeromicro/go-zero/tools/goctl/api/new"
"github.com/zeromicro/go-zero/tools/goctl/docker" "github.com/zeromicro/go-zero/tools/goctl/docker"
"github.com/zeromicro/go-zero/tools/goctl/gateway"
"github.com/zeromicro/go-zero/tools/goctl/kube" "github.com/zeromicro/go-zero/tools/goctl/kube"
mongogen "github.com/zeromicro/go-zero/tools/goctl/model/mongo/generate" mongogen "github.com/zeromicro/go-zero/tools/goctl/model/mongo/generate"
modelgen "github.com/zeromicro/go-zero/tools/goctl/model/sql/gen" modelgen "github.com/zeromicro/go-zero/tools/goctl/model/sql/gen"
@ -52,6 +53,9 @@ func genTemplates(_ *cobra.Command, _ []string) error {
func() error { func() error {
return apinew.GenTemplates() return apinew.GenTemplates()
}, },
func() error {
return gateway.GenTemplates()
},
); err != nil { ); err != nil {
return err return err
} }
@ -104,6 +108,9 @@ func cleanTemplates(_ *cobra.Command, _ []string) error {
func() error { func() error {
return apinew.Clean() return apinew.Clean()
}, },
func() error {
return gateway.Clean()
},
) )
if err != nil { if err != nil {
return err return err
@ -144,6 +151,8 @@ func updateTemplates(_ *cobra.Command, _ []string) (err error) {
return apigen.Update() return apigen.Update()
case apinew.Category(): case apinew.Category():
return apinew.Update() return apinew.Update()
case gateway.Category():
return gateway.Update()
default: default:
err = fmt.Errorf("unexpected category: %s", category) err = fmt.Errorf("unexpected category: %s", category)
return return
@ -181,6 +190,8 @@ func revertTemplates(_ *cobra.Command, _ []string) (err error) {
return apigen.RevertTemplate(filename) return apigen.RevertTemplate(filename)
case apinew.Category(): case apinew.Category():
return apinew.RevertTemplate(filename) return apinew.RevertTemplate(filename)
case gateway.Category():
return gateway.RevertTemplate(filename)
default: default:
err = fmt.Errorf("unexpected category: %s", category) err = fmt.Errorf("unexpected category: %s", category)
return return

@ -1,10 +1,6 @@
package upgrade package upgrade
import "github.com/spf13/cobra" import "github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
// Cmd describes an upgrade command. // Cmd describes an upgrade command.
var Cmd = &cobra.Command{ var Cmd = cobrax.NewCommand("upgrade", cobrax.WithRunE(upgrade))
Use: "upgrade",
Short: "Upgrade goctl to latest version",
RunE: upgrade,
}

@ -140,3 +140,15 @@ func ContainsAny(s string, runes ...rune) bool {
func ContainsWhiteSpace(s string) bool { func ContainsWhiteSpace(s string) bool {
return ContainsAny(s, WhiteSpace...) return ContainsAny(s, WhiteSpace...)
} }
func IsWhiteSpace(text string) bool {
if len(text) == 0 {
return true
}
for _, r := range text {
if !unicode.IsSpace(r) {
return false
}
}
return true
}

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
goformat "go/format" goformat "go/format"
"io/ioutil" "io/ioutil"
"regexp"
"text/template" "text/template"
"github.com/zeromicro/go-zero/tools/goctl/internal/errorx" "github.com/zeromicro/go-zero/tools/goctl/internal/errorx"
@ -77,3 +78,18 @@ func (t *DefaultTemplate) Execute(data any) (*bytes.Buffer, error) {
buf.Write(formatOutput) buf.Write(formatOutput)
return buf, nil return buf, nil
} }
// IsTemplateVariable returns true if the text is a template variable.
// The text must start with a dot and be a valid template.
func IsTemplateVariable(text string) bool {
match, _ := regexp.MatchString(`(?m)^{{(\.\w+)+}}$`, text)
return match
}
// TemplateVariable returns the variable name of the template.
func TemplateVariable(text string) string {
if IsTemplateVariable(text) {
return text[3 : len(text)-2]
}
return ""
}

@ -0,0 +1,93 @@
package util
import (
"testing"
"github.com/zeromicro/go-zero/tools/goctl/test"
)
func TestIsTemplate(t *testing.T) {
executor := test.NewExecutor[string, bool]()
executor.Add([]test.Data[string, bool]{
{
Name: "empty",
Want: false,
},
{
Name: "invalid",
Input: "{foo}",
Want: false,
},
{
Name: "invalid",
Input: "{.foo}",
Want: false,
},
{
Name: "invalid",
Input: "$foo",
Want: false,
},
{
Name: "invalid",
Input: "{{foo}}",
Want: false,
},
{
Name: "invalid",
Input: "{{.}}",
Want: false,
},
{
Name: "valid",
Input: "{{.foo}}",
Want: true,
},
{
Name: "valid",
Input: "{{.foo.bar}}",
Want: true,
},
}...)
executor.Run(t, IsTemplateVariable)
}
func TestTemplateVariable(t *testing.T) {
executor := test.NewExecutor[string, string]()
executor.Add([]test.Data[string, string]{
{
Name: "empty",
},
{
Name: "invalid",
Input: "{foo}",
},
{
Name: "invalid",
Input: "{.foo}",
},
{
Name: "invalid",
Input: "$foo",
},
{
Name: "invalid",
Input: "{{foo}}",
},
{
Name: "invalid",
Input: "{{.}}",
},
{
Name: "valid",
Input: "{{.foo}}",
Want: "foo",
},
{
Name: "valid",
Input: "{{.foo.bar}}",
Want: "foo.bar",
},
}...)
executor.Run(t, TemplateVariable)
}
Loading…
Cancel
Save