feat(goctl): Support gateway sample generation (#3049)
parent
95b85336d6
commit
1904af2323
@ -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,
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
}
|
@ -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,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)
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|
||||||
}
|
|
||||||
|
@ -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…
Reference in New Issue