Skip to content

Commit

Permalink
升级到 Gou 支持 SQLite
Browse files Browse the repository at this point in the history
  • Loading branch information
trheyi committed Oct 7, 2021
1 parent 9fa1fa8 commit a342cd5
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 73 deletions.
8 changes: 5 additions & 3 deletions cmd/info.go → cmd/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import (
"github.com/spf13/cobra"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/xiang/config"
"github.com/yaoapp/xiang/global"
)

var infoCmd = &cobra.Command{
Use: "info",
var inspectCmd = &cobra.Command{
Use: "inspect",
Short: "显示当前配置信息",
Long: `显示当前配置信息`,
Run: func(cmd *cobra.Command, args []string) {
Boot()
res := maps.Map{
"version": global.VERSION,
"domain": global.DOMAIN,
"config": global.Conf,
"config": config.Conf,
}
utils.Dump(res)
},
Expand Down
13 changes: 10 additions & 3 deletions cmd/migrate.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package cmd

import (
"fmt"

"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/xiang/config"
"github.com/yaoapp/xiang/global"
)

var name string
Expand All @@ -12,6 +16,9 @@ var migrateCmd = &cobra.Command{
Short: "更新数据结构",
Long: `更新数据库结构`,
Run: func(cmd *cobra.Command, args []string) {
Boot()
// 加载数据模型
global.Load(config.Conf)

if name != "" {
mod, has := gou.Models[name]
Expand All @@ -22,8 +29,8 @@ var migrateCmd = &cobra.Command{
}

// Do Stuff Here
for name, mod := range gou.Models {
utils.Dump(name)
for _, mod := range gou.Models {
fmt.Println(color.GreenString("更新数据模型 %s 绑定数据表: %s", mod.Name, mod.MetaData.Table.Name))
mod.Migrate(true)
}
},
Expand Down
28 changes: 25 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ package cmd
import (
"fmt"
"os"
"path/filepath"

"github.com/spf13/cobra"
"github.com/yaoapp/xiang/config"
)

var appPath string
var envFile string

var rootCmd = &cobra.Command{
Use: "xiang",
Short: "象传应用引擎命令行工具",
Expand All @@ -27,12 +32,12 @@ func init() {
versionCmd,
domainCmd,
migrateCmd,
infoCmd,
inspectCmd,
startCmd,
)

rootCmd.SetHelpCommand(helpCmd)

rootCmd.PersistentFlags().StringVarP(&appPath, "app", "a", "", "指定应用目录")
rootCmd.PersistentFlags().StringVarP(&envFile, "env", "e", "", "指定环境变量文件")
}

// Execute 运行Root
Expand All @@ -42,3 +47,20 @@ func Execute() {
os.Exit(1)
}
}

// Boot 设定配置
func Boot() {

if envFile == "" && appPath != "" {
config.SetAppPath(appPath, filepath.Join(appPath, ".env"))
return
}

if envFile != "" { // 指定环境变量文件
config.SetEnvFile(envFile)
}

if appPath != "" {
config.SetAppPath(appPath)
}
}
80 changes: 53 additions & 27 deletions cmd/start.go
Original file line number Diff line number Diff line change
@@ -1,57 +1,83 @@
package cmd

import (
"log"
"fmt"
"path/filepath"
"strings"

"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/xiang/config"
"github.com/yaoapp/xiang/global"
)

var startAppPath string
var startCmd = &cobra.Command{
Use: "start",
Short: "启动象传应用引擎",
Long: `启动象传应用引擎`,
Run: func(cmd *cobra.Command, args []string) {
defer global.ServiceStop(func() { log.Println("服务已关闭") })
log.Printf("启动象传应用引擎 v%s mode=%s", global.VERSION, global.Conf.Mode)
log.Printf("应用根目录: %s", global.Conf.Root)

// 应用目录
if startAppPath != "" {
global.Conf.Root = startAppPath
global.Conf.RootAPI = filepath.Join(startAppPath, "/apis")
global.Conf.RootFLow = filepath.Join(startAppPath, "/flows")
global.Conf.RootModel = filepath.Join(startAppPath, "/models")
global.Conf.RootPlugin = filepath.Join(startAppPath, "/plugins")
global.Conf.RootTable = filepath.Join(startAppPath, "/tables")
global.Conf.RootChart = filepath.Join(startAppPath, "/charts")
global.Conf.RootScreen = filepath.Join(startAppPath, "/screens")
global.Conf.RootData = filepath.Join(startAppPath, "/data")

// 重新加载应用
global.Reload(global.Conf)
defer global.ServiceStop(func() { fmt.Println("服务已关闭") })

Boot()
mode := config.Conf.Mode
if mode == "debug" {
mode = color.RedString("调试模式")
} else {
mode = ""
}

// 启动服务
for _, api := range gou.APIs {
log.Printf("%s(%d)", api.Name, len(api.HTTP.Paths))
fmt.Printf(color.GreenString("\n象传应用引擎 v%s %s", global.VERSION, mode))

// 加载数据模型 API 等
global.Load(config.Conf)

// 打印应用目录信息
fmt.Printf(color.GreenString("\n应用根目录: %s\n", config.Conf.Root))
for _, api := range gou.APIs { // API信息
fmt.Printf(color.CyanString("\n%s(%d)\n", api.Name, len(api.HTTP.Paths)))
for _, p := range api.HTTP.Paths {
log.Println(p.Method, filepath.Join("/api", api.HTTP.Group, p.Path), "\tprocess:", p.Process)

fmt.Println(
colorMehtod(p.Method),
color.WhiteString(filepath.Join("/api", api.HTTP.Group, p.Path)),
"\tprocess:", p.Process)
}

}

domain := global.DOMAIN
if domain == "*.iqka.com" {
domain = "local.iqka.com"
}

port := fmt.Sprintf(":%d", config.Conf.Service.Port)
if port == ":80" {
port = ""
}

fmt.Printf(color.GreenString("\n前台界面: http://%s%s/\n", domain, port))
fmt.Printf(color.GreenString("管理后台: http://%s%s/xiang/login\n", domain, port))
fmt.Printf(color.GreenString("API 接口: http://%s%s/api\n", domain, port))
fmt.Printf(color.GreenString("跨域访问: %s\n\n", strings.Join(config.Conf.Service.Allow, ",")))

// 调试模式
if global.Conf.Mode == "debug" {
if config.Conf.Mode == "debug" {
global.WatchChanges()
}

global.ServiceStart()
},
}

func init() {
startCmd.PersistentFlags().StringVarP(&startAppPath, "app", "a", "", "指定应用目录")
func colorMehtod(method string) string {
method = strings.ToUpper(method)
switch method {
case "GET":
return color.GreenString("GET")
case "POST":
return color.YellowString("POST")
default:
return color.WhiteString(method)
}
}
92 changes: 85 additions & 7 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"io"
"log"
"os"
"path/filepath"
"strings"

"github.com/caarlos0/env/v6"
"github.com/joho/godotenv"
Expand All @@ -30,6 +32,8 @@ type XiangConfig struct {
Source string `json:"source,omitempty" env:"XIANG_SOURCE" envDefault:"fs://."` // 源码路径(用于单元测试载入数据)
Path string `json:"path,omitempty" env:"XIANG_PATH" envDefault:"bin://xiang"` // 引擎文件目录
Root string `json:"root,omitempty" env:"XIANG_ROOT" envDefault:"fs://."` // 应用文件目录
RootUI string `json:"root_ui,omitempty" env:"XIANG_ROOT_UI"` // 应用界面静态文件目录
RootDB string `json:"root_db,omitempty" env:"XIANG_ROOT_DB"` // 应用SQLite数据库目录
RootData string `json:"root_data,omitempty" env:"XIANG_ROOT_DATA"` // 应用数据文件目录
RootAPI string `json:"root_api,omitempty" env:"XIANG_ROOT_API"` // 应用API文件目录
RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录
Expand All @@ -54,10 +58,11 @@ type ServiceConfig struct {

// DatabaseConfig 数据库配置
type DatabaseConfig struct {
Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关
Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|"` // 主库连接DSN
Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN
AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY
Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关
Driver string `json:"driver,omitempty" env:"XIANG_DB_DRIVER" envDefault:"sqlite3"` // 数据库驱动 ( sqlite3, mysql, postgres)
Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|" envDefault:"file:xiang.db?cache=shared&mode=memory"` // 主库连接DSN
Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN
AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY
}

// StorageConfig 存储配置
Expand All @@ -81,15 +86,25 @@ type LogConfig struct {
}

// NewConfig 创建配置文件
func NewConfig() Config {
func NewConfig(envfile ...string) Config {

filename := os.Getenv("XIANG_ENV_FILE")
if filename == "" {
filename = ".env"
}

err := godotenv.Load(filename)
if len(envfile) > 0 {
file, err := filepath.Abs(envfile[0])
if err != nil {
log.Printf("加载环境配置文件%s出错 %s\n", envfile[0], err.Error())
} else {
filename = file
}
}

err := godotenv.Overload(filename)
if err != nil {
log.Printf("读取环境配置文件%s出错 %s\n", filename, err.Error())
log.Printf("加载环境配置文件%s出错 %s\n", filename, err.Error())
}

cfg := Config{}
Expand Down Expand Up @@ -126,6 +141,7 @@ func (cfg *Config) SetDefaults() {
if cfg.RootPlugin == "" {
cfg.RootPlugin = cfg.Root + "/plugins"
}

if cfg.RootTable == "" {
cfg.RootTable = cfg.Root + "/tables"
}
Expand All @@ -135,10 +151,72 @@ func (cfg *Config) SetDefaults() {
if cfg.RootScreen == "" {
cfg.RootScreen = cfg.Root + "/screens"
}

if cfg.RootData == "" {
cfg.RootData = cfg.Root + "/data"
}

if cfg.RootDB == "" {
cfg.RootDB = cfg.Root + "/db"
cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "fs://")
cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "file://")
}
if cfg.RootUI == "" {
cfg.RootUI = cfg.Root + "/ui"
cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "fs://")
cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "file://")

}

}

// SetEnvFile 指定ENV文件
func SetEnvFile(filename string) {
Conf = NewConfig(filename)
}

// SetAppPath 设定应用目录
func SetAppPath(root string, envfile ...string) {

fullpath, err := filepath.Abs(root)
if err != nil {
log.Panicf("设定应用目录%s出错 %s\n", root, err.Error())
}

// 创建应用目录
pathinfo, err := os.Stat(fullpath)
if os.IsNotExist(err) {
err := os.MkdirAll(fullpath, os.ModePerm)
if err != nil {
log.Panicf("创建目录失败(%s) %s", root, err)
}
}
pathinfo, err = os.Stat(fullpath)
if !pathinfo.IsDir() {
log.Panicf("检查应用目录失败(%s) ", err)
}

if !pathinfo.IsDir() {
log.Panicf("应用目录不是文件夹(%s) ", root)
}

// Set ENV
if len(envfile) > 0 {
Conf = NewConfig(envfile[0])
}

// 从加载配置文件
Conf.Root = fullpath
Conf.RootAPI = filepath.Join(fullpath, "/apis")
Conf.RootFLow = filepath.Join(fullpath, "/flows")
Conf.RootModel = filepath.Join(fullpath, "/models")
Conf.RootPlugin = filepath.Join(fullpath, "/plugins")
Conf.RootTable = filepath.Join(fullpath, "/tables")
Conf.RootChart = filepath.Join(fullpath, "/charts")
Conf.RootScreen = filepath.Join(root, "/screens")
Conf.RootData = filepath.Join(fullpath, "/data")
Conf.RootUI = filepath.Join(fullpath, "/ui")
Conf.RootDB = filepath.Join(fullpath, "/db")
}

// IsDebug 是否为调试模式
Expand Down
2 changes: 1 addition & 1 deletion global/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var cfg config.Config
func TestMain(m *testing.M) {

// 加载模型等
Load(Conf)
Load(config.Conf)

// 加载表格(临时)
root := "fs://" + path.Join(Conf.Source, "/app/tables/service.json")
Expand Down
Loading

0 comments on commit a342cd5

Please sign in to comment.