Skip to content

Commit

Permalink
(goctl)feature/model config (#4062)
Browse files Browse the repository at this point in the history
Co-authored-by: Kevin Wan <[email protected]>
  • Loading branch information
kesonan and kevwan committed Apr 10, 2024
1 parent 682460c commit 2a7ada9
Show file tree
Hide file tree
Showing 12 changed files with 572 additions and 34 deletions.
3 changes: 2 additions & 1 deletion tools/goctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/withfig/autocomplete-tools/integrations/cobra"
"github.com/zeromicro/go-zero/tools/goctl/api"
"github.com/zeromicro/go-zero/tools/goctl/bug"
"github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/docker"
"github.com/zeromicro/go-zero/tools/goctl/env"
"github.com/zeromicro/go-zero/tools/goctl/gateway"
Expand Down Expand Up @@ -113,7 +114,7 @@ func init() {

rootCmd.SetUsageTemplate(usageTpl)
rootCmd.AddCommand(api.Cmd, bug.Cmd, docker.Cmd, kube.Cmd, env.Cmd, gateway.Cmd, model.Cmd)
rootCmd.AddCommand(migrate.Cmd, quickstart.Cmd, rpc.Cmd, tpl.Cmd, upgrade.Cmd)
rootCmd.AddCommand(migrate.Cmd, quickstart.Cmd, rpc.Cmd, tpl.Cmd, upgrade.Cmd, config.Cmd)
rootCmd.Command.AddCommand(cobracompletefig.CreateCompletionSpecCommand())
rootCmd.MustInit()
}
59 changes: 59 additions & 0 deletions tools/goctl/config/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package config

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/internal/cobrax"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)

var (
// Cmd describes a bug command.
Cmd = cobrax.NewCommand("config")

initCmd = cobrax.NewCommand("init", cobrax.WithRunE(runConfigInit))
cleanCmd = cobrax.NewCommand("clean", cobrax.WithRunE(runConfigClean))
)

func init() {
Cmd.AddCommand(initCmd, cleanCmd)
}

func runConfigInit(*cobra.Command, []string) error {
wd, err := os.Getwd()
if err != nil {
return err
}

cfgFile, err := getConfigPath(wd)
if err != nil {
return err
}
if pathx.FileExists(cfgFile) {
fmt.Printf("%s already exists, path: %s\n", configFile, cfgFile)
return nil
}

err = os.WriteFile(cfgFile, defaultConfig, 0644)
if err != nil {
return err
}
fmt.Printf("%s generated in %s\n", configFile, cfgFile)
return nil
}

func runConfigClean(*cobra.Command, []string) error {
wd, err := os.Getwd()
if err != nil {
return err
}

cfgFile, err := getConfigPath(wd)
if err != nil {
return err
}

return pathx.RemoveIfExist(cfgFile)
}
124 changes: 111 additions & 13 deletions tools/goctl/config/config.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,71 @@
package config

import (
_ "embed"
"errors"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/zeromicro/go-zero/tools/goctl/util/ctx"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"gopkg.in/yaml.v2"
)

const (
// DefaultFormat defines a default naming style
DefaultFormat = "gozero"
configFile = "goctl.yaml"
)

// DefaultFormat defines a default naming style
const DefaultFormat = "gozero"
var (
//go:embed default.yaml
defaultConfig []byte

ExternalConfig *External
)

// Config defines the file naming style
type Config struct {
// NamingFormat is used to define the naming format of the generated file name.
// just like time formatting, you can specify the formatting style through the
// two format characters go, and zero. for example: snake format you can
// define as go_zero, camel case format you can it is defined as goZero,
// and even split characters can be specified, such as go#zero. in theory,
// any combination can be used, but the prerequisite must meet the naming conventions
// of each operating system file name.
// Note: NamingFormat is based on snake or camel string
NamingFormat string `yaml:"namingFormat"`
}
type (
Config struct {
// NamingFormat is used to define the naming format of the generated file name.
// just like time formatting, you can specify the formatting style through the
// two format characters go, and zero. for example: snake format you can
// define as go_zero, camel case format you can it is defined as goZero,
// and even split characters can be specified, such as go#zero. in theory,
// any combination can be used, but the prerequisite must meet the naming conventions
// of each operating system file name.
// Note: NamingFormat is based on snake or camel string
NamingFormat string `yaml:"namingFormat"`
}

External struct {
// Model is the configuration for the model code generation.
Model Model `yaml:"model,omitempty"`
}

// Model defines the configuration for the model code generation.
Model struct {
// TypesMap: custom Data Type Mapping Table.
TypesMap map[string]ModelTypeMapOption `yaml:"types_map,omitempty" `
}

// ModelTypeMapOption custom Type Options.
ModelTypeMapOption struct {
// Type: valid when not using UnsignedType and NullType.
Type string `yaml:"type"`

// UnsignedType: valid when not using NullType.
UnsignedType string `yaml:"unsigned_type,omitempty"`

// NullType: priority use.
NullType string `yaml:"null_type,omitempty"`

// Pkg defines the package of the custom type.
Pkg string `yaml:"pkg,omitempty"`
}
)

// NewConfig creates an instance for Config
func NewConfig(format string) (*Config, error) {
Expand All @@ -31,6 +77,58 @@ func NewConfig(format string) (*Config, error) {
return cfg, err
}

func init() {
var cfg External
err := loadConfig(&cfg)
if err != nil {
fmt.Println(err.Error())
} else {
ExternalConfig = &cfg
}
}

func loadConfig(cfg *External) error {
wd, err := os.Getwd()
if err != nil {
return err
}

cfgFile, err := getConfigPath(wd)
if err != nil {
return err
}
var content []byte
if pathx.FileExists(cfgFile) {
content, err = os.ReadFile(cfgFile)
if err != nil {
return err
}
}
if len(content) == 0 {
content = append(content, defaultConfig...)
}
return yaml.Unmarshal(content, cfg)
}

// getConfigPath returns the configuration file path, but not create the file.
func getConfigPath(workDir string) (string, error) {
abs, err := filepath.Abs(workDir)
if err != nil {
return "", err
}

err = pathx.MkdirIfNotExist(abs)
if err != nil {
return "", err
}

projectCtx, err := ctx.Prepare(abs)
if err != nil {
return "", err
}
return filepath.Join(projectCtx.Dir, configFile), nil
}

func validate(cfg *Config) error {
if len(strings.TrimSpace(cfg.NamingFormat)) == 0 {
return errors.New("missing namingFormat")
Expand Down
157 changes: 157 additions & 0 deletions tools/goctl/config/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
model:
types_map:
bigint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
dec:
null_type: sql.NullFloat64
type: float64
decimal:
null_type: sql.NullFloat64
type: float64
double:
null_type: sql.NullFloat64
type: float64
float:
null_type: sql.NullFloat64
type: float64
float4:
null_type: sql.NullFloat64
type: float64
float8:
null_type: sql.NullFloat64
type: float64
int:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
int1:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
int2:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
int3:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
int4:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
int8:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
integer:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
mediumint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
middleint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
smallint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
tinyint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
date:
null_type: sql.NullTime
type: time.Time
datetime:
null_type: sql.NullTime
type: time.Time
timestamp:
null_type: sql.NullTime
type: time.Time
time:
null_type: sql.NullString
type: string
year:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
bit:
null_type: sql.NullByte
type: byte
unsigned_type: byte
bool:
null_type: sql.NullBool
type: bool
boolean:
null_type: sql.NullBool
type: bool
char:
null_type: sql.NullString
type: string
varchar:
null_type: sql.NullString
type: string
nvarchar:
null_type: sql.NullString
type: string
nchar:
null_type: sql.NullString
type: string
character:
null_type: sql.NullString
type: string
longvarchar:
null_type: sql.NullString
type: string
linestring:
null_type: sql.NullString
type: string
multilinestring:
null_type: sql.NullString
type: string
binary:
null_type: sql.NullString
type: string
varbinary:
null_type: sql.NullString
type: string
tinytext:
null_type: sql.NullString
type: string
text:
null_type: sql.NullString
type: string
mediumtext:
null_type: sql.NullString
type: string
longtext:
null_type: sql.NullString
type: string
enum:
null_type: sql.NullString
type: string
set:
null_type: sql.NullString
type: string
json:
null_type: sql.NullString
type: string
blob:
null_type: sql.NullString
type: string
longblob:
null_type: sql.NullString
type: string
mediumblob:
null_type: sql.NullString
type: string
tinyblob:
null_type: sql.NullString
type: string
8 changes: 8 additions & 0 deletions tools/goctl/internal/flags/default_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@
},
"upgrade": {
"short": "Upgrade goctl to latest version"
},
"config": {
"init": {
"short": "Initialize goctl config file"
},
"clean": {
"short": "Clean goctl config file"
}
}
},
"global": {
Expand Down
Loading

0 comments on commit 2a7ada9

Please sign in to comment.