(goctl)feature/model config (#4062)

Co-authored-by: Kevin Wan <wanjunfeng@gmail.com>
This commit is contained in:
kesonan
2024-04-10 23:01:59 +08:00
committed by GitHub
parent 682460c1c8
commit 2a7ada993b
12 changed files with 574 additions and 36 deletions

59
tools/goctl/config/cmd.go Normal file
View File

@@ -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)
}

View File

@@ -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"
)
// DefaultFormat defines a default naming style
const DefaultFormat = "gozero"
const (
// DefaultFormat defines a default naming style
DefaultFormat = "gozero"
configFile = "goctl.yaml"
)
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) {
@@ -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")

View File

@@ -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