mirror of
https://github.com/beego/bee.git
synced 2025-06-11 03:10:40 +00:00
beego pro init
This commit is contained in:
20
internal/app/module/beegopro/config.go
Normal file
20
internal/app/module/beegopro/config.go
Normal file
@ -0,0 +1,20 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"github.com/beego/bee/internal/pkg/utils"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func (c *Container) GenConfig() {
|
||||
if utils.IsExist(c.BeegoProFile) {
|
||||
beeLogger.Log.Fatalf("beego pro toml exist")
|
||||
return
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile("beegopro.toml", []byte(BeegoToml), 0644)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("write beego pro toml err: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
18
internal/app/module/beegopro/constx.go
Normal file
18
internal/app/module/beegopro/constx.go
Normal file
@ -0,0 +1,18 @@
|
||||
package beegopro
|
||||
|
||||
const BeegoToml = `
|
||||
dsn = "root:123456@tcp(127.0.0.1:3306)/beego"
|
||||
driver = "mysql"
|
||||
proType = "default"
|
||||
enableModule = []
|
||||
apiPrefix = "/"
|
||||
gitRemotePath = "https://github.com/beego-dev/beego-pro.git"
|
||||
format = true
|
||||
sourceGen = "text"
|
||||
gitPull = true
|
||||
[models.user]
|
||||
name = ["uid"]
|
||||
orm = ["auto"]
|
||||
comment = ["Uid"]
|
||||
|
||||
`
|
214
internal/app/module/beegopro/container.go
Normal file
214
internal/app/module/beegopro/container.go
Normal file
@ -0,0 +1,214 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/git"
|
||||
"github.com/beego/bee/internal/pkg/system"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/spf13/viper"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const MDateFormat = "20060102_150405"
|
||||
|
||||
var DefaultBeegoPro = &Container{
|
||||
BeegoProFile: system.CurrentDir + "/beegopro.toml",
|
||||
TimestampFile: system.CurrentDir + "/beegopro.timestamp",
|
||||
GoModFile: system.CurrentDir + "/go.mod",
|
||||
Option: Option{
|
||||
Debug: false,
|
||||
ContextDebug: false,
|
||||
Dsn: "",
|
||||
Driver: "mysql",
|
||||
ProType: "default",
|
||||
ApiPrefix: "/",
|
||||
EnableModule: nil,
|
||||
Models: make(map[string]ModelContent, 0),
|
||||
GitRemotePath: "https://github.com/beego-dev/beego-pro.git",
|
||||
Branch: "master",
|
||||
GitLocalPath: system.BeegoHome + "/beego-pro",
|
||||
EnableFormat: true,
|
||||
SourceGen: "text",
|
||||
EnableGitPull: true,
|
||||
RefreshGitTime: 24 * 3600,
|
||||
Path: map[string]string{
|
||||
"beego": ".",
|
||||
},
|
||||
EnableGomod: true,
|
||||
},
|
||||
GenerateTime: time.Now().Format(MDateFormat),
|
||||
GenerateTimeUnix: time.Now().Unix(),
|
||||
Tmpl: Tmpl{},
|
||||
CurPath: system.CurrentDir,
|
||||
EnableModules: make(map[string]interface{}, 0), // get the user configuration, get the enable module result
|
||||
FunctionOnce: make(map[string]sync.Once, 0), // get the tmpl configuration, get the function once result
|
||||
}
|
||||
|
||||
func (c *Container) Run() {
|
||||
// init git refresh cache time
|
||||
c.initTimestamp()
|
||||
c.initBeegoPro()
|
||||
c.initBeegoTmpl()
|
||||
c.initRender()
|
||||
c.flushTimestamp()
|
||||
}
|
||||
|
||||
func (c *Container) initBeegoPro() {
|
||||
if !utils.IsExist(c.BeegoProFile) {
|
||||
beeLogger.Log.Fatalf("beego pro config is not exist, beego json path: %s", c.BeegoProFile)
|
||||
return
|
||||
}
|
||||
viper.SetConfigFile(c.BeegoProFile)
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("read beego pro config content, err: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = viper.Unmarshal(&c.Option)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego pro config unmarshal error, err: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if c.Option.Debug {
|
||||
viper.Debug()
|
||||
}
|
||||
|
||||
if c.Option.EnableGomod {
|
||||
if !utils.IsExist(c.GoModFile) {
|
||||
beeLogger.Log.Fatalf("go mod not exist, please create go mod file")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, value := range c.Option.EnableModule {
|
||||
c.EnableModules[value] = struct{}{}
|
||||
}
|
||||
|
||||
if len(c.EnableModules) == 0 {
|
||||
c.EnableModules["*"] = struct{}{}
|
||||
}
|
||||
|
||||
if c.Option.Debug {
|
||||
fmt.Println("c.modules", c.EnableModules)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) initBeegoTmpl() {
|
||||
if c.Option.EnableGitPull && (c.GenerateTimeUnix-c.Timestamp.GitCacheLastRefresh > c.Option.RefreshGitTime) {
|
||||
err := git.CloneORPullRepo(c.Option.GitRemotePath, c.Option.GitLocalPath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego pro git clone or pull repo error, err: %s", err)
|
||||
return
|
||||
}
|
||||
c.Timestamp.GitCacheLastRefresh = c.GenerateTimeUnix
|
||||
}
|
||||
|
||||
tree, err := toml.LoadFile(c.Option.GitLocalPath + "/" + c.Option.ProType + "/bee.toml")
|
||||
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego tmpl exec error, err: %s", err)
|
||||
return
|
||||
}
|
||||
err = tree.Unmarshal(&c.Tmpl)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego tmpl parse error, err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if c.Option.Debug {
|
||||
spew.Dump("tmpl", c.Tmpl)
|
||||
}
|
||||
|
||||
for _, value := range c.Tmpl.Descriptor {
|
||||
if value.Once == true {
|
||||
c.FunctionOnce[value.SrcName] = sync.Once{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type modelInfo struct {
|
||||
Module string
|
||||
ModelName string
|
||||
Option Option
|
||||
Content ModelContent
|
||||
Descriptor Descriptor
|
||||
TmplPath string
|
||||
GenerateTime string
|
||||
}
|
||||
|
||||
func (c *Container) initRender() {
|
||||
for _, desc := range c.Tmpl.Descriptor {
|
||||
_, allFlag := c.EnableModules["*"]
|
||||
_, moduleFlag := c.EnableModules[desc.Module]
|
||||
if !allFlag && !moduleFlag {
|
||||
continue
|
||||
}
|
||||
|
||||
// model table name, model table schema
|
||||
for modelName, content := range c.Option.Models {
|
||||
m := modelInfo{
|
||||
Module: desc.Module,
|
||||
ModelName: modelName,
|
||||
Content: content,
|
||||
Option: c.Option,
|
||||
Descriptor: desc,
|
||||
TmplPath: c.Tmpl.RenderPath,
|
||||
GenerateTime: c.GenerateTime,
|
||||
}
|
||||
|
||||
// some render exec once
|
||||
syncOnce, flag := c.FunctionOnce[desc.SrcName]
|
||||
if flag {
|
||||
syncOnce.Do(func() {
|
||||
c.renderModel(m)
|
||||
})
|
||||
continue
|
||||
}
|
||||
c.renderModel(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) renderModel(m modelInfo) {
|
||||
render := NewRender(m)
|
||||
render.Exec(m.Descriptor.SrcName)
|
||||
if render.Descriptor.IsExistScript() {
|
||||
err := render.Descriptor.ExecScript(c.CurPath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego exec shell error, err: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) initTimestamp() {
|
||||
if utils.IsExist(c.TimestampFile) {
|
||||
tree, err := toml.LoadFile(c.TimestampFile)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego timestamp tmpl exec error, err: %s", err)
|
||||
return
|
||||
}
|
||||
err = tree.Unmarshal(&c.Timestamp)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego timestamp tmpl parse error, err: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Timestamp.Generate = c.GenerateTimeUnix
|
||||
}
|
||||
|
||||
func (c *Container) flushTimestamp() {
|
||||
tomlByte, err := toml.Marshal(c.Timestamp)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("marshal timestamp tmpl parse error, err: %s", err)
|
||||
}
|
||||
err = ioutil.WriteFile(c.TimestampFile, tomlByte, 0644)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("flush timestamp tmpl parse error, err: %s", err)
|
||||
}
|
||||
}
|
35
internal/app/module/beegopro/migration.go
Normal file
35
internal/app/module/beegopro/migration.go
Normal file
@ -0,0 +1,35 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var SQL utils.DocValue
|
||||
|
||||
func (c *Container) Migration(args []string) {
|
||||
c.initBeegoPro()
|
||||
db, err := sql.Open(c.Option.Driver, c.Option.Dsn)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not connect to '%s' database using '%s': %s", c.Option.Driver, c.Option.Dsn, err)
|
||||
return
|
||||
}
|
||||
|
||||
defer db.Close()
|
||||
|
||||
absFile, _ := filepath.Abs(SQL.String())
|
||||
content, err := ioutil.ReadFile(SQL.String())
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("read file err %s, abs file %s", err, absFile)
|
||||
}
|
||||
|
||||
result, err := db.Exec(string(content))
|
||||
if err != nil {
|
||||
beeLogger.Log.Errorf("db exec err %s", err)
|
||||
}
|
||||
beeLogger.Log.Infof("db exec info %v", result)
|
||||
|
||||
}
|
58
internal/app/module/beegopro/pongo2.go
Normal file
58
internal/app/module/beegopro/pongo2.go
Normal file
@ -0,0 +1,58 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/flosch/pongo2"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = pongo2.RegisterFilter("lowerFirst", pongo2LowerFirst)
|
||||
_ = pongo2.RegisterFilter("upperFirst", pongo2UpperFirst)
|
||||
_ = pongo2.RegisterFilter("snakeString", pongo2SnakeString)
|
||||
_ = pongo2.RegisterFilter("camelString", pongo2CamelString)
|
||||
}
|
||||
|
||||
func pongo2LowerFirst(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
r, size := utf8.DecodeRuneInString(t)
|
||||
return pongo2.AsValue(strings.ToLower(string(r)) + t[size:]), nil
|
||||
}
|
||||
|
||||
func pongo2UpperFirst(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
return pongo2.AsValue(strings.Replace(t, string(t[0]), strings.ToUpper(string(t[0])), 1)), nil
|
||||
}
|
||||
|
||||
// snake string, XxYy to xx_yy
|
||||
func pongo2SnakeString(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
return pongo2.AsValue(utils.SnakeString(t)), nil
|
||||
}
|
||||
|
||||
// snake string, XxYy to xx_yy
|
||||
func pongo2CamelString(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
|
||||
if in.Len() <= 0 {
|
||||
return pongo2.AsValue(""), nil
|
||||
}
|
||||
t := in.String()
|
||||
return pongo2.AsValue(utils.CamelString(t)), nil
|
||||
}
|
||||
|
||||
func upperFirst(str string) string {
|
||||
return strings.Replace(str, string(str[0]), strings.ToUpper(string(str[0])), 1)
|
||||
}
|
||||
|
||||
func lowerFirst(str string) string {
|
||||
return strings.Replace(str, string(str[0]), strings.ToLower(string(str[0])), 1)
|
||||
}
|
123
internal/app/module/beegopro/render.go
Normal file
123
internal/app/module/beegopro/render.go
Normal file
@ -0,0 +1,123 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"github.com/beego/bee/internal/pkg/system"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/smartwalle/pongo2render"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// render
|
||||
type RenderFile struct {
|
||||
*pongo2render.Render
|
||||
Context pongo2.Context
|
||||
GenerateTime string
|
||||
Option Option
|
||||
ModelName string
|
||||
PackageName string
|
||||
FlushFile string
|
||||
PkgPath string
|
||||
TmplPath string
|
||||
Descriptor Descriptor
|
||||
}
|
||||
|
||||
func NewRender(m modelInfo) *RenderFile {
|
||||
var (
|
||||
pathCtx pongo2.Context
|
||||
newDescriptor Descriptor
|
||||
)
|
||||
|
||||
// parse descriptor, get flush file path, beego path, etc...
|
||||
newDescriptor, pathCtx = m.Descriptor.Parse(m.ModelName, m.Option.Path)
|
||||
|
||||
obj := &RenderFile{
|
||||
Context: make(pongo2.Context, 0),
|
||||
Option: m.Option,
|
||||
ModelName: m.ModelName,
|
||||
GenerateTime: m.GenerateTime,
|
||||
Descriptor: newDescriptor,
|
||||
}
|
||||
|
||||
obj.FlushFile = newDescriptor.DstPath
|
||||
|
||||
// new render
|
||||
obj.Render = pongo2render.NewRender(path.Join(obj.Option.GitLocalPath, obj.Option.ProType, m.TmplPath))
|
||||
|
||||
filePath := path.Dir(obj.FlushFile)
|
||||
err := createPath(filePath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create the controllers directory: %s", err)
|
||||
}
|
||||
// get go package path
|
||||
obj.PkgPath = getPackagePath()
|
||||
|
||||
relativePath, err := filepath.Rel(system.CurrentDir, obj.FlushFile)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not get the relative path: %s", err)
|
||||
}
|
||||
|
||||
modelSchemas := m.Content.ToModelSchemas()
|
||||
camelPrimaryKey := modelSchemas.GetPrimaryKey()
|
||||
importMaps := make(map[string]struct{}, 0)
|
||||
if modelSchemas.IsExistTime() {
|
||||
importMaps["time"] = struct{}{}
|
||||
}
|
||||
obj.PackageName = filepath.Base(filepath.Dir(relativePath))
|
||||
beeLogger.Log.Infof("Using '%s' as name", obj.ModelName)
|
||||
|
||||
beeLogger.Log.Infof("Using '%s' as package name from %s", obj.ModelName, obj.PackageName)
|
||||
|
||||
// package
|
||||
obj.SetContext("packageName", obj.PackageName)
|
||||
obj.SetContext("packageImports", importMaps)
|
||||
|
||||
// todo optimize
|
||||
// todo Set the beego directory, should recalculate the package
|
||||
if pathCtx["pathRelBeego"] == "." {
|
||||
obj.SetContext("packagePath", obj.PkgPath)
|
||||
} else {
|
||||
obj.SetContext("packagePath", obj.PkgPath+"/"+pathCtx["pathRelBeego"].(string))
|
||||
}
|
||||
|
||||
obj.SetContext("packageMod", obj.PkgPath)
|
||||
|
||||
obj.SetContext("modelSchemas", modelSchemas)
|
||||
obj.SetContext("modelPrimaryKey", camelPrimaryKey)
|
||||
|
||||
for key, value := range pathCtx {
|
||||
obj.SetContext(key, value)
|
||||
}
|
||||
|
||||
obj.SetContext("apiPrefix", obj.Option.ApiPrefix)
|
||||
obj.SetContext("generateTime", obj.GenerateTime)
|
||||
|
||||
if obj.Option.ContextDebug {
|
||||
spew.Dump(obj.Context)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func (r *RenderFile) SetContext(key string, value interface{}) {
|
||||
r.Context[key] = value
|
||||
}
|
||||
|
||||
func (r *RenderFile) Exec(name string) {
|
||||
var (
|
||||
buf string
|
||||
err error
|
||||
)
|
||||
buf, err = r.Render.Template(name).Execute(r.Context)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create the %s render tmpl: %s", name, err)
|
||||
return
|
||||
}
|
||||
err = r.write(r.FlushFile, buf)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not create file: %s", err)
|
||||
return
|
||||
}
|
||||
beeLogger.Log.Infof("create file '%s' from %s", r.FlushFile, r.PackageName)
|
||||
}
|
151
internal/app/module/beegopro/schema.go
Normal file
151
internal/app/module/beegopro/schema.go
Normal file
@ -0,0 +1,151 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/command"
|
||||
"github.com/beego/bee/internal/pkg/system"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/smartwalle/pongo2render"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// store all data
|
||||
type Container struct {
|
||||
BeegoProFile string // beego pro toml
|
||||
TimestampFile string // store ts file
|
||||
GoModFile string // go mod file
|
||||
Option Option // user option
|
||||
Tmpl Tmpl // remote tmpl
|
||||
CurPath string // user current path
|
||||
EnableModules map[string]interface{} // beego pro provider a collection of module
|
||||
FunctionOnce map[string]sync.Once // exec function once
|
||||
Timestamp Timestamp
|
||||
GenerateTime string
|
||||
GenerateTimeUnix int64
|
||||
}
|
||||
|
||||
// user option
|
||||
type Option struct {
|
||||
Debug bool `json:"debug"`
|
||||
ContextDebug bool `json:"contextDebug"`
|
||||
Dsn string `json:"dsn"`
|
||||
Driver string `json:"driver"`
|
||||
ProType string `json:"proType"`
|
||||
ApiPrefix string `json:"apiPrefix"`
|
||||
EnableModule []string `json:"enableModule"`
|
||||
Models map[string]ModelContent `json:"models"`
|
||||
GitRemotePath string `json:"gitRemotePath"`
|
||||
Branch string `json:"branch"`
|
||||
GitLocalPath string `json:"gitLocalPath"`
|
||||
EnableFormat bool `json:"enableFormat"`
|
||||
SourceGen string `json:"sourceGen"`
|
||||
EnableGitPull bool `json:"enbaleGitPull"`
|
||||
Path map[string]string `json:"path"`
|
||||
EnableGomod bool `json:"enableGomod"`
|
||||
RefreshGitTime int64 `json:"refreshGitTime"`
|
||||
Extend map[string]string `json:"extend"` // extend user data
|
||||
}
|
||||
|
||||
type BeegoPro struct {
|
||||
FilePath string
|
||||
CurPath string
|
||||
Option Option
|
||||
}
|
||||
|
||||
// tmpl option
|
||||
type Tmpl struct {
|
||||
RenderPath string `toml:"renderPath"`
|
||||
Descriptor []Descriptor
|
||||
}
|
||||
|
||||
type Descriptor struct {
|
||||
Module string `toml:"module"`
|
||||
SrcName string `toml:"srcName"`
|
||||
DstPath string `toml:"dstPath"`
|
||||
Once bool `toml:"once"`
|
||||
Script string `toml:"script"`
|
||||
}
|
||||
|
||||
func (descriptor Descriptor) Parse(modelName string, paths map[string]string) (newDescriptor Descriptor, ctx pongo2.Context) {
|
||||
var (
|
||||
err error
|
||||
relativeDstPath string
|
||||
absFile string
|
||||
relPath string
|
||||
)
|
||||
|
||||
newDescriptor = descriptor
|
||||
render := pongo2render.NewRender("")
|
||||
ctx = make(pongo2.Context, 0)
|
||||
for key, value := range paths {
|
||||
absFile, err = filepath.Abs(value)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("absolute path error %s from key %s and value %s", err, key, value)
|
||||
}
|
||||
relPath, err = filepath.Rel(system.CurrentDir, absFile)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("Could not get the relative path: %s", err)
|
||||
}
|
||||
// user input path
|
||||
ctx["path"+utils.CamelCase(key)] = value
|
||||
// relativePath
|
||||
ctx["pathRel"+utils.CamelCase(key)] = relPath
|
||||
}
|
||||
ctx["modelName"] = lowerFirst(utils.CamelString(modelName))
|
||||
relativeDstPath, err = render.TemplateFromString(descriptor.DstPath).Execute(ctx)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("beego tmpl exec error, err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
newDescriptor.DstPath, err = filepath.Abs(relativeDstPath)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("absolute path error %s from flush file %s", err, relativeDstPath)
|
||||
}
|
||||
|
||||
newDescriptor.Script, err = render.TemplateFromString(descriptor.Script).Execute(ctx)
|
||||
if err != nil {
|
||||
beeLogger.Log.Fatalf("parse script %s, error %s", descriptor.Script, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (descriptor Descriptor) IsExistScript() bool {
|
||||
if descriptor.Script != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d Descriptor) ExecScript(path string) (err error) {
|
||||
arr := strings.Split(d.Script, " ")
|
||||
if len(arr) == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Println("path------>", path)
|
||||
|
||||
stdout, stderr, err := command.ExecCmdDir(path, arr[0], arr[1:]...)
|
||||
if err != nil {
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
|
||||
beeLogger.Log.Info(stdout)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Timestamp struct {
|
||||
GitCacheLastRefresh int64 `toml:"gitCacheLastRefresh"`
|
||||
Generate int64 `toml:"generate"`
|
||||
}
|
||||
|
||||
func concatenateError(err error, stderr string) error {
|
||||
if len(stderr) == 0 {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("%v: %s", err, stderr)
|
||||
}
|
141
internal/app/module/beegopro/schema_model.go
Normal file
141
internal/app/module/beegopro/schema_model.go
Normal file
@ -0,0 +1,141 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ModelContent struct {
|
||||
Names []string
|
||||
Orms []string
|
||||
Comments []string
|
||||
Extends []string
|
||||
}
|
||||
|
||||
type ModelInfo struct {
|
||||
Name string `json:"name"` // mysql name
|
||||
InputType string `json:"inputType"` // user input type
|
||||
MysqlType string `json:"mysqlType"` // mysql type
|
||||
GoType string `json:"goType"` // go type
|
||||
Orm string `json:"orm"` // orm tag
|
||||
Comment string `json:"comment"` // mysql comment
|
||||
Extend string `json:"extend"` // user extend info
|
||||
}
|
||||
|
||||
func (m ModelInfo) GetColumnKey() (columnKey string) {
|
||||
if m.InputType == "auto" || m.Orm == "pk" {
|
||||
columnKey = "PRI"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m ModelInfo) IsPrimaryKey() (flag bool) {
|
||||
if m.Orm == "auto" || m.Orm == "pk" || strings.ToLower(m.Name) == "id" {
|
||||
flag = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (content ModelContent) ToModelInfoArr() (output []ModelInfo) {
|
||||
namesLen := len(content.Names)
|
||||
ormsLen := len(content.Orms)
|
||||
commentsLen := len(content.Comments)
|
||||
if namesLen != ormsLen && namesLen != commentsLen {
|
||||
beeLogger.Log.Fatalf("length error, namesLen is %d, ormsLen is %d, commentsLen is %d", namesLen, ormsLen, commentsLen)
|
||||
}
|
||||
extendLen := len(content.Extends)
|
||||
if extendLen != 0 && extendLen != namesLen {
|
||||
beeLogger.Log.Fatalf("extend length error, namesLen is %d, extendsLen is %d", namesLen, extendLen)
|
||||
}
|
||||
|
||||
output = make([]ModelInfo, 0)
|
||||
for i, name := range content.Names {
|
||||
comment := content.Comments[i]
|
||||
if comment == "" {
|
||||
comment = name
|
||||
}
|
||||
inputType, goType, mysqlType, ormTag := getModelType(content.Orms[i])
|
||||
|
||||
m := ModelInfo{
|
||||
Name: name,
|
||||
InputType: inputType,
|
||||
GoType: goType,
|
||||
Orm: ormTag,
|
||||
Comment: comment,
|
||||
MysqlType: mysqlType,
|
||||
Extend: "",
|
||||
}
|
||||
// extend value
|
||||
if extendLen != 0 {
|
||||
m.Extend = content.Extends[i]
|
||||
}
|
||||
output = append(output, m)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (content ModelContent) ToModelSchemas() (output ModelSchemas) {
|
||||
modelInfoArr := content.ToModelInfoArr()
|
||||
|
||||
output = make(ModelSchemas, 0)
|
||||
for i, value := range modelInfoArr {
|
||||
if i == 0 && !value.IsPrimaryKey() {
|
||||
inputType, goType, mysqlType, ormTag := getModelType("auto")
|
||||
output = append(output, &ModelSchema{
|
||||
Name: "id",
|
||||
InputType: inputType,
|
||||
ColumnKey: "PRI",
|
||||
Comment: "ID",
|
||||
MysqlType: mysqlType,
|
||||
GoType: goType,
|
||||
OrmTag: ormTag,
|
||||
Extend: value.Extend,
|
||||
})
|
||||
}
|
||||
|
||||
modelSchema := &ModelSchema{
|
||||
Name: value.Name,
|
||||
InputType: value.InputType,
|
||||
ColumnKey: value.GetColumnKey(),
|
||||
MysqlType: value.MysqlType,
|
||||
Comment: value.Comment,
|
||||
GoType: value.GoType,
|
||||
OrmTag: value.Orm,
|
||||
}
|
||||
output = append(output, modelSchema)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ModelSchema struct {
|
||||
Name string // column name
|
||||
InputType string // user input type
|
||||
MysqlType string // mysql type
|
||||
ColumnKey string // PRI
|
||||
Comment string // comment
|
||||
GoType string // go type
|
||||
OrmTag string // orm tag
|
||||
Extend string
|
||||
}
|
||||
|
||||
type ModelSchemas []*ModelSchema
|
||||
|
||||
func (m ModelSchemas) IsExistTime() bool {
|
||||
for _, value := range m {
|
||||
if value.InputType == "datetime" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m ModelSchemas) GetPrimaryKey() string {
|
||||
camelPrimaryKey := ""
|
||||
for _, value := range m {
|
||||
if value.ColumnKey == "PRI" {
|
||||
camelPrimaryKey = utils.CamelString(value.Name)
|
||||
}
|
||||
}
|
||||
return camelPrimaryKey
|
||||
}
|
185
internal/app/module/beegopro/util.go
Normal file
185
internal/app/module/beegopro/util.go
Normal file
@ -0,0 +1,185 @@
|
||||
package beegopro
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/beego/bee/internal/pkg/utils"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// write to file
|
||||
func (c *RenderFile) write(filename string, buf string) (err error) {
|
||||
if utils.IsExist(filename) && !isNeedOverwrite(filename) {
|
||||
return
|
||||
}
|
||||
|
||||
filePath := path.Dir(filename)
|
||||
err = createPath(filePath)
|
||||
if err != nil {
|
||||
err = errors.New("write create path " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
filePathBak := filePath + "/bak"
|
||||
err = createPath(filePathBak)
|
||||
if err != nil {
|
||||
err = errors.New("write create path bak " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
name := path.Base(filename)
|
||||
|
||||
if utils.IsExist(filename) {
|
||||
bakName := fmt.Sprintf("%s/%s.%s.bak", filePathBak, name, time.Now().Format("2006.01.02.15.04.05"))
|
||||
beeLogger.Log.Infof("bak file '%s'", bakName)
|
||||
if err := os.Rename(filename, bakName); err != nil {
|
||||
err = errors.New("file is bak error, path is " + bakName)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Create(filename)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
err = errors.New("write create file " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
output := []byte(buf)
|
||||
|
||||
if c.Option.EnableFormat && filepath.Ext(filename) == ".go" {
|
||||
// format code
|
||||
var bts []byte
|
||||
bts, err = format.Source([]byte(buf))
|
||||
if err != nil {
|
||||
err = errors.New("format buf error " + err.Error())
|
||||
return
|
||||
}
|
||||
output = bts
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filename, output, 0644)
|
||||
if err != nil {
|
||||
err = errors.New("write write file " + err.Error())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func isNeedOverwrite(fileName string) (flag bool) {
|
||||
seg := "//"
|
||||
ext := filepath.Ext(fileName)
|
||||
if ext == "sql" {
|
||||
seg = "--"
|
||||
}
|
||||
|
||||
f, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
overwrite := ""
|
||||
var contentByte []byte
|
||||
contentByte, err = ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, s := range strings.Split(string(contentByte), "\n") {
|
||||
s = strings.TrimSpace(strings.TrimPrefix(s, seg))
|
||||
if strings.HasPrefix(s, "@BeeOverwrite") {
|
||||
overwrite = strings.TrimSpace(s[len("@BeeOverwrite"):])
|
||||
}
|
||||
}
|
||||
if strings.ToLower(overwrite) == "yes" {
|
||||
flag = true
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// createPath 调用os.MkdirAll递归创建文件夹
|
||||
func createPath(filePath string) error {
|
||||
if !utils.IsExist(filePath) {
|
||||
err := os.MkdirAll(filePath, os.ModePerm)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPackagePath() (packagePath string) {
|
||||
f, err := os.Open("go.mod")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
var contentByte []byte
|
||||
contentByte, err = ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, s := range strings.Split(string(contentByte), "\n") {
|
||||
packagePath = strings.TrimSpace(strings.TrimPrefix(s, "module"))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getModelType(orm string) (inputType, goType, mysqlType, tag string) {
|
||||
kv := strings.SplitN(orm, ",", 2)
|
||||
inputType = kv[0]
|
||||
switch inputType {
|
||||
case "string":
|
||||
goType = "string"
|
||||
tag = "size(255)"
|
||||
// todo use orm data
|
||||
mysqlType = "varchar(255) NOT NULL"
|
||||
case "text":
|
||||
goType = "string"
|
||||
tag = "type(longtext)"
|
||||
mysqlType = "longtext NOT NULL"
|
||||
case "auto":
|
||||
goType = "int"
|
||||
tag = "auto"
|
||||
mysqlType = "int(11) NOT NULL AUTO_INCREMENT"
|
||||
case "pk":
|
||||
goType = "int"
|
||||
tag = "pk"
|
||||
mysqlType = "int(11) NOT NULL"
|
||||
case "datetime":
|
||||
goType = "time.Time"
|
||||
tag = "type(datetime)"
|
||||
mysqlType = "datetime NOT NULL"
|
||||
case "int", "int8", "int16", "int32", "int64":
|
||||
fallthrough
|
||||
case "uint", "uint8", "uint16", "uint32", "uint64":
|
||||
goType = inputType
|
||||
tag = ""
|
||||
mysqlType = "int(11) DEFAULT NULL"
|
||||
case "bool":
|
||||
goType = inputType
|
||||
tag = ""
|
||||
mysqlType = "int(11) DEFAULT NULL"
|
||||
case "float32", "float64":
|
||||
goType = inputType
|
||||
tag = ""
|
||||
mysqlType = "float NOT NULL"
|
||||
case "float":
|
||||
goType = "float64"
|
||||
tag = ""
|
||||
mysqlType = "float NOT NULL"
|
||||
default:
|
||||
beeLogger.Log.Fatalf("not support type: %s", inputType)
|
||||
}
|
||||
// user set orm tag
|
||||
if len(kv) == 2 {
|
||||
tag = orm
|
||||
}
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user