Remove setup package and related functionality from the project
This commit is contained in:
parent
83fc43cc52
commit
79f77618d3
7 changed files with 89 additions and 879 deletions
13
Makefile
13
Makefile
|
|
@ -148,9 +148,6 @@ artifacts-linux: clean
|
|||
echo "BASE=__yao_admin_root" > ../xgen-v1.0/packages/xgen/.env
|
||||
cd ../xgen-v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Init Application
|
||||
cd ../yao-init && rm -rf .git
|
||||
cd ../yao-init && rm -rf .gitignore
|
||||
|
|
@ -169,7 +166,6 @@ artifacts-linux: clean
|
|||
# ** new repository: https://github.com/YaoApp/dui.git **
|
||||
mkdir -p .tmp/data/xgen
|
||||
cp -r ./ui .tmp/data/ui
|
||||
cp -r ../xgen-v1.0/packages/setup/build .tmp/data/xgen/setup
|
||||
cp -r ../xgen-v1.0/packages/xgen/dist .tmp/data/xgen/v1.0
|
||||
cp -r ../yao-init .tmp/data/init
|
||||
cp -r yao .tmp/data/
|
||||
|
|
@ -207,9 +203,6 @@ artifacts-macos: clean
|
|||
echo "BASE=__yao_admin_root" > ../xgen-v1.0/packages/xgen/.env
|
||||
cd ../xgen-v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Init Application
|
||||
cd ../yao-init && rm -rf .git
|
||||
cd ../yao-init && rm -rf .gitignore
|
||||
|
|
@ -228,7 +221,6 @@ artifacts-macos: clean
|
|||
# ** new repository: https://github.com/YaoApp/dui.git **
|
||||
mkdir -p .tmp/data/xgen
|
||||
cp -r ./ui .tmp/data/ui
|
||||
cp -r ../xgen-v1.0/packages/setup/build .tmp/data/xgen/setup
|
||||
cp -r ../xgen-v1.0/packages/xgen/dist .tmp/data/xgen/v1.0
|
||||
cp -r ../yao-init .tmp/data/init
|
||||
cp -r yao .tmp/data/
|
||||
|
|
@ -296,10 +288,6 @@ release: clean
|
|||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||
cd .tmp/xgen/v1.0 && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install --no-frozen-lockfile && pnpm run build
|
||||
|
||||
|
||||
# Checkout init
|
||||
git clone https://github.com/YaoApp/yao-init.git .tmp/yao-init
|
||||
rm -rf .tmp/yao-init/.git
|
||||
|
|
@ -320,7 +308,6 @@ release: clean
|
|||
cp -r ./yao .tmp/data/yao
|
||||
cp -r ./sui/libsui .tmp/data/libsui
|
||||
cp -r .tmp/xgen/v0.9/dist .tmp/data/xgen/v0.9
|
||||
cp -r .tmp/xgen/v1.0/packages/setup/build .tmp/data/xgen/setup
|
||||
cp -r .tmp/xgen/v1.0/packages/xgen/dist .tmp/data/xgen/v1.0
|
||||
cp -r .tmp/yao-init .tmp/data/init
|
||||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
|
|
|
|||
87
cmd/start.go
87
cmd/start.go
|
|
@ -49,17 +49,13 @@ var startCmd = &cobra.Command{
|
|||
Boot()
|
||||
|
||||
// Setup
|
||||
if setup.Check() {
|
||||
go setup.Start()
|
||||
select {
|
||||
case <-setup.Done:
|
||||
setup.Stop()
|
||||
Boot()
|
||||
break
|
||||
case <-setup.Canceled:
|
||||
isNewApp := false
|
||||
if !setup.SourceExists() {
|
||||
if err := install(); err != nil {
|
||||
fmt.Println(color.RedString(L("Install: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
break
|
||||
}
|
||||
isNewApp = true
|
||||
}
|
||||
|
||||
// force debug
|
||||
|
|
@ -147,6 +143,11 @@ var startCmd = &cobra.Command{
|
|||
printConnectors(false)
|
||||
printStores(false)
|
||||
printStudio(false, host)
|
||||
|
||||
// Print welcome message for the new application
|
||||
if isNewApp {
|
||||
printWelcome()
|
||||
}
|
||||
}
|
||||
|
||||
// Start Tasks
|
||||
|
|
@ -161,7 +162,7 @@ var startCmd = &cobra.Command{
|
|||
srv, err := service.Start(config.Conf)
|
||||
defer func() {
|
||||
service.Stop(srv)
|
||||
fmt.Println(color.GreenString(L("✨EXITED✨")))
|
||||
fmt.Println(color.GreenString(L("✨Exited successfully!")))
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -193,11 +194,12 @@ var startCmd = &cobra.Command{
|
|||
|
||||
switch v {
|
||||
case http.READY:
|
||||
fmt.Println(color.GreenString(L("✨LISTENING✨")))
|
||||
fmt.Println(color.GreenString(L("✨Server is up and running...")))
|
||||
fmt.Println(color.BlackString("✨Ctrl+C to stop"))
|
||||
break
|
||||
|
||||
case http.CLOSED:
|
||||
fmt.Println(color.GreenString(L("✨EXITED✨")))
|
||||
fmt.Println(color.GreenString(L("✨Exited successfully!")))
|
||||
watchDone <- 1
|
||||
return
|
||||
|
||||
|
|
@ -218,6 +220,30 @@ var startCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func install() error {
|
||||
// Copy the app source files from the binary
|
||||
err := setup.Install(config.Conf.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reload the application engine
|
||||
Boot()
|
||||
|
||||
// load the application engine
|
||||
err = engine.Load(config.Conf, engine.LoadOption{Action: "start"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = setup.Initialize(config.Conf.Root, config.Conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func adminRoot() (string, int) {
|
||||
adminRoot := "/yao/"
|
||||
if share.App.AdminRoot != "" {
|
||||
|
|
@ -229,6 +255,15 @@ func adminRoot() (string, int) {
|
|||
return adminRoot, adminRootLen
|
||||
}
|
||||
|
||||
func printWelcome() {
|
||||
fmt.Println(color.BlueString("\n---------------------------------"))
|
||||
fmt.Println(color.BlueString(L("🎉 Welcome to Yao 🎉 ")))
|
||||
fmt.Println(color.BlueString("---------------------------------"))
|
||||
fmt.Println(color.WhiteString("📚 Documentation:"), color.BlueString("https://yaoapps.com/docs"))
|
||||
fmt.Println(color.WhiteString("💬 Build App via Chat:"), color.BlueString("https://moapi.ai"))
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
func printConnectors(silent bool) {
|
||||
|
||||
if len(connector.Connectors) == 0 {
|
||||
|
|
@ -246,8 +281,8 @@ func printConnectors(silent bool) {
|
|||
fmt.Println(color.WhiteString(L("Connectors List (%d)"), len(connector.Connectors)))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
for name := range connector.Connectors {
|
||||
fmt.Printf(color.CyanString("[Connector]"))
|
||||
fmt.Printf(color.WhiteString(" %s\t loaded\n", name))
|
||||
fmt.Print(color.CyanString("[Connector]"))
|
||||
fmt.Print(color.WhiteString(" %s\t loaded\n", name))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,8 +302,8 @@ func printStores(silent bool) {
|
|||
fmt.Println(color.WhiteString(L("Stores List (%d)"), len(connector.Connectors)))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
for name := range store.Pools {
|
||||
fmt.Printf(color.CyanString("[Store]"))
|
||||
fmt.Printf(color.WhiteString(" %s\t loaded\n", name))
|
||||
fmt.Print(color.CyanString("[Store]"))
|
||||
fmt.Print(color.WhiteString(" %s\t loaded\n", name))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -285,13 +320,13 @@ func printStudio(silent bool, host string) {
|
|||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(L("Yao Studio Server")))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
fmt.Printf(color.CyanString("HOST : "))
|
||||
fmt.Printf(color.WhiteString(" %s\n", config.Conf.Host))
|
||||
fmt.Printf(color.CyanString("PORT : "))
|
||||
fmt.Printf(color.WhiteString(" %d\n", config.Conf.Studio.Port))
|
||||
fmt.Print(color.CyanString("HOST : "))
|
||||
fmt.Print(color.WhiteString(" %s\n", config.Conf.Host))
|
||||
fmt.Print(color.CyanString("PORT : "))
|
||||
fmt.Print(color.WhiteString(" %d\n", config.Conf.Studio.Port))
|
||||
if config.Conf.Studio.Auto {
|
||||
fmt.Printf(color.CyanString("SECRET: "))
|
||||
fmt.Printf(color.WhiteString(" %s\n", config.Conf.Studio.Secret))
|
||||
fmt.Print(color.CyanString("SECRET: "))
|
||||
fmt.Print(color.WhiteString(" %s\n", config.Conf.Studio.Secret))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -320,8 +355,8 @@ func printSchedules(silent bool) {
|
|||
if sch.TaskName != "" {
|
||||
process = fmt.Sprintf("Task: %s", sch.TaskName)
|
||||
}
|
||||
fmt.Printf(color.CyanString("[Schedule] %s %s", sch.Schedule, name))
|
||||
fmt.Printf(color.WhiteString("\t%s\t%s\n", sch.Name, process))
|
||||
fmt.Print(color.CyanString("[Schedule] %s %s", sch.Schedule, name))
|
||||
fmt.Print(color.WhiteString("\t%s\t%s\n", sch.Name, process))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -342,8 +377,8 @@ func printTasks(silent bool) {
|
|||
fmt.Println(color.WhiteString(L("Tasks List (%d)"), len(task.Tasks)))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
for _, t := range task.Tasks {
|
||||
fmt.Printf(color.CyanString("[Task] %s", t.Option.Name))
|
||||
fmt.Printf(color.WhiteString("\t workers: %d\n", t.Option.WorkerNums))
|
||||
fmt.Print(color.CyanString("[Task] %s", t.Option.Name))
|
||||
fmt.Print(color.WhiteString("\t workers: %d\n", t.Option.WorkerNums))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
129
setup/check.go
129
setup/check.go
|
|
@ -1,45 +1,25 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yaoapp/xun/capsule"
|
||||
"github.com/yaoapp/yao/config"
|
||||
)
|
||||
|
||||
// Check if the app is installed
|
||||
// true: start setup, false: start app
|
||||
func Check() bool {
|
||||
|
||||
// check app source
|
||||
if !appSourceExists() {
|
||||
return true
|
||||
}
|
||||
|
||||
// check env file
|
||||
root := appRoot()
|
||||
envfile := filepath.Join(root, ".env")
|
||||
if _, err := os.Stat(envfile); err != nil && os.IsNotExist(err) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
// SourceExists check if the app source exists
|
||||
func SourceExists() bool {
|
||||
return appSourceExists()
|
||||
}
|
||||
|
||||
func appSourceExists() bool {
|
||||
|
||||
appsource := appSource()
|
||||
if strings.HasSuffix(appsource, ".yaz") || strings.HasPrefix(appsource, "::binary") {
|
||||
return true
|
||||
root := appRoot()
|
||||
if isEmptyDir(root) {
|
||||
return false
|
||||
}
|
||||
|
||||
// check app.yao/app.json/app.jsonc
|
||||
root := appRoot()
|
||||
appfiles := []string{"app.yao", "app.json", "app.jsonc"}
|
||||
exist := false
|
||||
for _, appfile := range appfiles {
|
||||
|
|
@ -53,63 +33,18 @@ func appSourceExists() bool {
|
|||
return exist
|
||||
}
|
||||
|
||||
// ValidateHosting host ports
|
||||
func ValidateHosting(option map[string]string) error {
|
||||
if option["YAO_PORT"] == "" {
|
||||
return fmt.Errorf("监听端口必须填写")
|
||||
}
|
||||
|
||||
if option["YAO_STUDIO_PORT"] == option["YAO_PORT"] {
|
||||
return fmt.Errorf("监听端口和 Studio 端口不能相同")
|
||||
}
|
||||
|
||||
if option["YAO_PORT"] != SetupPort {
|
||||
conn, _ := net.DialTimeout("tcp", net.JoinHostPort("127.0.0.1", option["YAO_PORT"]), time.Second)
|
||||
if conn != nil {
|
||||
defer conn.Close()
|
||||
return fmt.Errorf("监听端口 %s 已被占用", option["YAO_PORT"])
|
||||
}
|
||||
}
|
||||
|
||||
if option["YAO_STUDIO_PORT"] != SetupPort {
|
||||
conn, _ := net.DialTimeout("tcp", net.JoinHostPort("127.0.0.1", option["YAO_STUDIO_PORT"]), time.Second)
|
||||
if conn != nil {
|
||||
defer conn.Close()
|
||||
return fmt.Errorf("Studio 端口 %s 已被占用", option["YAO_STUDIO_PORT"])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateDB db connection
|
||||
func ValidateDB(option map[string]string) error {
|
||||
|
||||
driver, dsn, err := getDSN(option)
|
||||
func isEmptyDir(dir string) bool {
|
||||
f, err := os.Open(dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接失败 %s", err.Error())
|
||||
return true
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
m, err := capsule.Add("validate", driver, dsn)
|
||||
files, err := f.Readdir(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接失败 %s", err.Error())
|
||||
return true
|
||||
}
|
||||
|
||||
conn, err := m.Primary()
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接失败 %s", err.Error())
|
||||
}
|
||||
|
||||
err = conn.Ping(2 * time.Second)
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接失败 %s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func appSource() string {
|
||||
return os.Getenv("YAO_APP_SOURCE")
|
||||
return len(files) == 0
|
||||
}
|
||||
|
||||
func appRoot() string {
|
||||
|
|
@ -118,16 +53,14 @@ func appRoot() string {
|
|||
if root == "" {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
printError("无法获取应用目录: %s", err)
|
||||
Stop()
|
||||
printError("Can't get the application directory: %s", err)
|
||||
}
|
||||
root = path
|
||||
}
|
||||
|
||||
root, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
printError("无法获取应用目录: %s", err)
|
||||
Stop()
|
||||
printError("Can't get the application directory: %s", err)
|
||||
}
|
||||
|
||||
return root
|
||||
|
|
@ -139,35 +72,3 @@ func getConfig() (config.Config, error) {
|
|||
cfg := config.LoadFrom(envfile)
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func hasInstalled(cfg config.Config) bool {
|
||||
|
||||
return false
|
||||
|
||||
// switch cfg.DB.Driver {
|
||||
|
||||
// case "sqlite3":
|
||||
// if cfg.DB.Primary != nil && len(cfg.DB.Primary) > 0 {
|
||||
|
||||
// dbfile, err := filepath.Abs(cfg.DB.Primary[0])
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// if _, err := os.Stat(dbfile); err != nil && os.IsNotExist(err) {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// return false
|
||||
// }
|
||||
// break
|
||||
|
||||
// case "mysql":
|
||||
// if cfg.DB.Primary != nil && len(cfg.DB.Primary) > 0 {
|
||||
// return true
|
||||
// }
|
||||
// break
|
||||
// }
|
||||
|
||||
// return false
|
||||
}
|
||||
|
|
|
|||
65
setup/env.go
65
setup/env.go
|
|
@ -1,65 +0,0 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func envSet(file, name, value string) error {
|
||||
|
||||
file, err := filepath.Abs(file)
|
||||
if err != nil {
|
||||
dir := filepath.Dir(file)
|
||||
err := os.MkdirAll(dir, os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if _, err := os.Stat(file); err != nil && os.IsNotExist(err) {
|
||||
err = os.WriteFile(file, []byte{}, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = godotenv.Write(map[string]string{"YAO_ENV": "development"}, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
vars, err := godotenv.Read(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vars[name] = value
|
||||
return godotenv.Write(vars, file)
|
||||
}
|
||||
|
||||
func envGet(file, name string) (string, error) {
|
||||
|
||||
v := os.Getenv(name)
|
||||
if v != "" {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
vars, err := godotenv.Read(file)
|
||||
if err == nil {
|
||||
return "", err
|
||||
}
|
||||
return vars[name], nil
|
||||
}
|
||||
|
||||
func envHas(file, name string) (bool, error) {
|
||||
|
||||
v, err := envGet(file, name)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return v != "", nil
|
||||
}
|
||||
265
setup/handler.go
265
setup/handler.go
|
|
@ -1,265 +0,0 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/xun"
|
||||
"github.com/yaoapp/yao/engine"
|
||||
"github.com/yaoapp/yao/widgets/app"
|
||||
)
|
||||
|
||||
// recovered custom recovered
|
||||
func recovered(c *gin.Context, recovered interface{}) {
|
||||
|
||||
var code = http.StatusInternalServerError
|
||||
|
||||
if err, ok := recovered.(string); ok {
|
||||
c.JSON(code, xun.R{
|
||||
"code": code,
|
||||
"message": fmt.Sprintf("%s", err),
|
||||
})
|
||||
} else if err, ok := recovered.(exception.Exception); ok {
|
||||
code = err.Code
|
||||
c.JSON(code, xun.R{
|
||||
"code": code,
|
||||
"message": err.Message,
|
||||
})
|
||||
} else if err, ok := recovered.(*exception.Exception); ok {
|
||||
code = err.Code
|
||||
c.JSON(code, xun.R{
|
||||
"code": code,
|
||||
"message": err.Message,
|
||||
})
|
||||
} else {
|
||||
c.JSON(code, xun.R{
|
||||
"code": code,
|
||||
"message": fmt.Sprintf("%v", recovered),
|
||||
})
|
||||
}
|
||||
|
||||
c.AbortWithStatus(code)
|
||||
}
|
||||
|
||||
// {
|
||||
// "env": {
|
||||
// "YAO_LANG": "中文",
|
||||
// "YAO_ENV": "开发模式(推荐)",
|
||||
// "YAO_PORT": "5099",
|
||||
// "YAO_STUDIO_PORT": "5077"
|
||||
// },
|
||||
// "db": {
|
||||
// "type": "sqlite",
|
||||
// "option.file": "db/yao.db"
|
||||
// }
|
||||
// }
|
||||
func runSetup(c *gin.Context) {
|
||||
|
||||
payload := getSetting(c)
|
||||
|
||||
cfg, err := getConfig()
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if !Check() {
|
||||
c.JSON(403, gin.H{"code": 400, "message": "应用已安装, 删除 .env 文件和 db 目录后重试"})
|
||||
return
|
||||
}
|
||||
|
||||
err = Install(payload)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Reload Config
|
||||
cfg, err = getConfig()
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
err = engine.Load(cfg, engine.LoadOption{})
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Return
|
||||
urls, err := AdminURL(cfg)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
adminRoot := "yao"
|
||||
if app.Setting.AdminRoot != "" {
|
||||
adminRoot = app.Setting.AdminRoot
|
||||
}
|
||||
adminRoot = strings.Trim(adminRoot, "/")
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
"code": 200,
|
||||
"message": "安装成功",
|
||||
"urls": urls,
|
||||
"port": cfg.Port,
|
||||
"root": adminRoot,
|
||||
})
|
||||
|
||||
Complete()
|
||||
}
|
||||
|
||||
func runCheck(c *gin.Context) {
|
||||
|
||||
payload := getCheck(c)
|
||||
dbOption, err := getDBOption(map[string]map[string]string{"db": payload})
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
err = ValidateDB(dbOption)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{"code": 200})
|
||||
}
|
||||
|
||||
func getCheck(c *gin.Context) map[string]string {
|
||||
var payload map[string]string
|
||||
err := c.ShouldBindJSON(&payload)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 400, "message": err.Error()})
|
||||
c.Abort()
|
||||
return nil
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func getSetting(c *gin.Context) map[string]map[string]string {
|
||||
var payload map[string]map[string]string
|
||||
err := c.ShouldBindJSON(&payload)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 400, "message": err.Error()})
|
||||
c.Abort()
|
||||
return nil
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func getENVOption(payload map[string]map[string]string) (map[string]string, error) {
|
||||
env, has := payload["env"]
|
||||
if !has {
|
||||
return nil, fmt.Errorf("缺少服务配置信息")
|
||||
}
|
||||
|
||||
if env["YAO_ENV"] == "开发模式(推荐)" {
|
||||
env["YAO_ENV"] = "development"
|
||||
} else {
|
||||
env["YAO_ENV"] = "production"
|
||||
}
|
||||
|
||||
if env["YAO_LANG"] == "中文" {
|
||||
env["YAO_LANG"] = "zh-cn"
|
||||
} else {
|
||||
env["YAO_LANG"] = "en-us"
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
||||
func getDBOption(payload map[string]map[string]string) (map[string]string, error) {
|
||||
|
||||
db, has := payload["db"]
|
||||
if !has {
|
||||
return nil, fmt.Errorf("缺少数据库配置信息")
|
||||
}
|
||||
|
||||
dbOption := map[string]string{}
|
||||
switch db["type"] {
|
||||
case "", "sqlite", "sqlite3":
|
||||
dbOption["type"] = "sqlite3"
|
||||
dbOption["file"] = db["option.file"]
|
||||
return dbOption, nil
|
||||
|
||||
case "mysql":
|
||||
dbOption["type"] = "mysql"
|
||||
dbOption["db"] = db["option.db"]
|
||||
dbOption["host"] = db["option.host.host"]
|
||||
dbOption["port"] = db["option.host.port"]
|
||||
dbOption["user"] = db["option.host.user"]
|
||||
dbOption["pass"] = db["option.host.pass"]
|
||||
return dbOption, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("数据库驱动暂不支持")
|
||||
}
|
||||
|
||||
func getDSN(dbOption map[string]string) (string, string, error) {
|
||||
|
||||
switch dbOption["type"] {
|
||||
case "", "sqlite", "sqlite3":
|
||||
root := appRoot()
|
||||
var err error
|
||||
db := filepath.Join("db", "yao.db")
|
||||
if v, has := dbOption["file"]; has {
|
||||
db = v
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(db, "/") {
|
||||
db = filepath.Join(root, db)
|
||||
db, err = filepath.Abs(db)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
dir := filepath.Dir(db)
|
||||
err = os.MkdirAll(dir, os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return "sqlite3", db, nil
|
||||
|
||||
case "mysql":
|
||||
|
||||
db := "yao"
|
||||
if v, has := dbOption["db"]; has {
|
||||
db = v
|
||||
}
|
||||
|
||||
host := "127.0.0.1"
|
||||
if v, has := dbOption["host"]; has {
|
||||
host = v
|
||||
}
|
||||
|
||||
port := "3306"
|
||||
if v, has := dbOption["port"]; has {
|
||||
port = v
|
||||
}
|
||||
|
||||
user := "root"
|
||||
if v, has := dbOption["user"]; has {
|
||||
user = v
|
||||
}
|
||||
|
||||
pass := ""
|
||||
if v, has := dbOption["pass"]; has {
|
||||
pass = v
|
||||
}
|
||||
|
||||
return "mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, pass, host, port, db), nil
|
||||
}
|
||||
|
||||
return "", "", fmt.Errorf("driver does not support")
|
||||
|
||||
}
|
||||
232
setup/install.go
232
setup/install.go
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/yaoapp/gou/model"
|
||||
|
|
@ -14,127 +13,14 @@ import (
|
|||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/data"
|
||||
"github.com/yaoapp/yao/engine"
|
||||
"github.com/yaoapp/yao/studio"
|
||||
"github.com/yaoapp/yao/widgets/app"
|
||||
)
|
||||
|
||||
// Install app install
|
||||
//
|
||||
// {
|
||||
// "env": {
|
||||
// "YAO_LANG": "中文",
|
||||
// "YAO_ENV": "开发模式(推荐)",
|
||||
// "YAO_PORT": "5099",
|
||||
// "YAO_STUDIO_PORT": "5077"
|
||||
// },
|
||||
// "db": {
|
||||
// "type": "sqlite",
|
||||
// "option.file": "db/yao.db"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "env": {
|
||||
// "YAO_LANG": "中文",
|
||||
// "YAO_ENV": "开发模式(推荐)",
|
||||
// "YAO_PORT": "5099",
|
||||
// "YAO_STUDIO_PORT": "5077"
|
||||
// },
|
||||
// "db": {
|
||||
// "type": "mysql",
|
||||
// "option.db": "yao",
|
||||
// "option.host.host": "127.0.0.1",
|
||||
// "option.host.port": "3306",
|
||||
// "option.host.user": "root",
|
||||
// "option.host.pass": "123456"
|
||||
// }
|
||||
// }
|
||||
func Install(payload map[string]map[string]string) error {
|
||||
// Install the app to the root directory
|
||||
func Install(root string) error {
|
||||
|
||||
dbOption, err := getDBOption(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ValidateDB(dbOption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
envOption, err := getENVOption(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ValidateHosting(envOption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
root := appRoot()
|
||||
err = makeService(root, "0.0.0.0", envOption["YAO_PORT"], envOption["YAO_STUDIO_PORT"], envOption["YAO_LANG"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeDB(root, dbOption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeSession(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeLog(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeDirs(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeInit(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := getConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load engine
|
||||
err = engine.Load(cfg, engine.LoadOption{
|
||||
Action: "install",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
engine.Unload()
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
}()
|
||||
|
||||
// Load Studio
|
||||
err = studio.Load(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Migrage & Setup
|
||||
err = makeMigrate(root, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeSetup(root, cfg)
|
||||
// Copy the init source files
|
||||
err := makeInit(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -142,113 +28,21 @@ func Install(payload map[string]map[string]string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func makeService(root string, host string, port string, studioPort string, lang string) error {
|
||||
file := filepath.Join(root, ".env")
|
||||
err := envSet(file, "YAO_HOST", host)
|
||||
// Initialize the installed app
|
||||
func Initialize(root string, cfg config.Config) error {
|
||||
|
||||
// Migration
|
||||
err := makeMigrate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = envSet(file, "YAO_PORT", port)
|
||||
// Execute the setup hook
|
||||
err = makeSetup(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = envSet(file, "YAO_STUDIO_PORT", studioPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return envSet(file, "YAO_LANG", lang)
|
||||
}
|
||||
|
||||
func makeDB(root string, option map[string]string) error {
|
||||
|
||||
driver, dsn, err := getDSN(option)
|
||||
if driver != "mysql" && driver != "sqlite3" {
|
||||
return fmt.Errorf("数据库驱动应该为: mysql/sqlite3")
|
||||
}
|
||||
|
||||
file := filepath.Join(root, ".env")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = envSet(file, "YAO_DB_DRIVER", driver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return envSet(file, "YAO_DB_PRIMARY", dsn)
|
||||
}
|
||||
|
||||
func makeSession(root string) error {
|
||||
file := filepath.Join(root, ".env")
|
||||
if has, _ := envHas(file, "YAO_SESSION_STORE"); has {
|
||||
return nil
|
||||
}
|
||||
|
||||
if has, _ := envHas(file, "YAO_SESSION_FILE"); has {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := os.MkdirAll(filepath.Join(root, "data"), os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
err = envSet(file, "YAO_SESSION_STORE", "file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ssfile := filepath.Join(root, "db", ".session")
|
||||
return envSet(file, "YAO_SESSION_FILE", ssfile)
|
||||
}
|
||||
|
||||
func makeLog(root string) error {
|
||||
file := filepath.Join(root, ".env")
|
||||
if has, _ := envHas(file, "YAO_LOG_MODE"); has {
|
||||
return nil
|
||||
}
|
||||
|
||||
if has, _ := envHas(file, "YAO_LOG"); has {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := os.MkdirAll(filepath.Join(root, "data"), os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
err = envSet(file, "YAO_LOG_MODE", "TEXT")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logfile := filepath.Join(root, "logs", "application.log")
|
||||
return envSet(file, "YAO_LOG", logfile)
|
||||
}
|
||||
|
||||
func makeDirs(root string) error {
|
||||
|
||||
if !appSourceExists() {
|
||||
err := os.MkdirAll(filepath.Join(root, "public"), os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := os.MkdirAll(filepath.Join(root, "logs"), os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Join(root, "db"), os.ModePerm)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +79,7 @@ func makeInit(root string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func makeMigrate(root string, cfg config.Config) error {
|
||||
func makeMigrate() error {
|
||||
|
||||
// Do Stuff Here
|
||||
for _, mod := range model.Models {
|
||||
|
|
@ -308,7 +102,7 @@ func makeMigrate(root string, cfg config.Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func makeSetup(root string, cfg config.Config) error {
|
||||
func makeSetup(cfg config.Config) error {
|
||||
|
||||
if app.Setting != nil && app.Setting.Setup != "" {
|
||||
|
||||
|
|
|
|||
177
setup/setup.go
177
setup/setup.go
|
|
@ -3,164 +3,12 @@ package setup
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/data"
|
||||
"github.com/yaoapp/yao/engine"
|
||||
"github.com/yaoapp/yao/share"
|
||||
"github.com/yaoapp/yao/widgets/app"
|
||||
)
|
||||
|
||||
// SetupPort setup port
|
||||
var SetupPort string = "5099"
|
||||
|
||||
// XGenSetupServer XGen Setup
|
||||
var XGenSetupServer http.Handler = http.FileServer(data.Setup())
|
||||
|
||||
// Done check done
|
||||
var Done = make(chan bool, 1)
|
||||
|
||||
// shutdown check done
|
||||
var shutdown = make(chan bool, 1)
|
||||
|
||||
// Canceled check if setup is canceld
|
||||
var Canceled = make(chan bool, 1)
|
||||
|
||||
// Start start the studio api server
|
||||
func Start() (err error) {
|
||||
|
||||
// recive interrupt signal
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
||||
// Set router
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
router := gin.New()
|
||||
|
||||
if os.Getenv("YAO_SETUP_DEV") != "" {
|
||||
fmt.Println(color.WhiteString("\nSETUP DEV: %s\n", os.Getenv("YAO_SETUP_DEV")))
|
||||
}
|
||||
|
||||
router.Use(func(c *gin.Context) {
|
||||
length := len(c.Request.URL.Path)
|
||||
if length >= 5 && c.Request.URL.Path[0:5] == "/api/" {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
if os.Getenv("YAO_SETUP_DEV") != "" {
|
||||
root, err := filepath.Abs(os.Getenv("YAO_SETUP_DEV"))
|
||||
if err != nil {
|
||||
printError("%s", err)
|
||||
}
|
||||
|
||||
static := http.FileServer(http.Dir(root))
|
||||
static.ServeHTTP(c.Writer, c.Request)
|
||||
return
|
||||
}
|
||||
|
||||
// Setup Pages
|
||||
XGenSetupServer.ServeHTTP(c.Writer, c.Request)
|
||||
return
|
||||
}, gin.CustomRecovery(recovered))
|
||||
|
||||
router.POST("/api/__yao/app/check", runCheck)
|
||||
router.POST("/api/__yao/app/setup", runSetup)
|
||||
|
||||
// Server setting
|
||||
addr := fmt.Sprintf(":%s", SetupPort)
|
||||
|
||||
// Listen
|
||||
l, err := net.Listen("tcp4", addr)
|
||||
if err != nil {
|
||||
addr = ":0"
|
||||
l, err = net.Listen("tcp4", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: router,
|
||||
}
|
||||
defer func() {
|
||||
// printInfo("[Setup] %s Close Serve", addr)
|
||||
err = srv.Close()
|
||||
if err != nil {
|
||||
printError("[Setup] Error (%v)", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// start serve
|
||||
go func() {
|
||||
// printInfo("[Setup] Starting: %s", addr)
|
||||
if err := srv.Serve(l); err != nil && err != http.ErrServerClosed {
|
||||
errCh <- err
|
||||
}
|
||||
}()
|
||||
|
||||
welcome(l)
|
||||
|
||||
select {
|
||||
|
||||
case <-shutdown:
|
||||
printInfo("Setup Shutdown")
|
||||
return err
|
||||
|
||||
case <-interrupt:
|
||||
printInfo("Setup Interrupt")
|
||||
Canceled <- true
|
||||
return err
|
||||
|
||||
case err := <-errCh:
|
||||
printError("Setup Error: ", err)
|
||||
Canceled <- true
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Complete stop the studio api server
|
||||
func Complete() {
|
||||
engine.Unload()
|
||||
Done <- true
|
||||
}
|
||||
|
||||
// Stop stop the studio api server
|
||||
func Stop() {
|
||||
shutdown <- true
|
||||
}
|
||||
|
||||
// AdminURL get admin url
|
||||
func AdminURL(cfg config.Config) ([]string, error) {
|
||||
|
||||
urls, err := URLs(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
adminRoot := "yao"
|
||||
if app.Setting.AdminRoot != "" {
|
||||
adminRoot = app.Setting.AdminRoot
|
||||
}
|
||||
adminRoot = strings.Trim(adminRoot, "/")
|
||||
|
||||
for i := range urls {
|
||||
urls[i] = fmt.Sprintf("%s/%s/", urls[i], adminRoot)
|
||||
}
|
||||
return urls, nil
|
||||
}
|
||||
|
||||
// URLs get admin url
|
||||
func URLs(cfg config.Config) ([]string, error) {
|
||||
|
||||
|
|
@ -176,31 +24,6 @@ func URLs(cfg config.Config) ([]string, error) {
|
|||
return ips, nil
|
||||
}
|
||||
|
||||
func welcome(l net.Listener) {
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
fmt.Println(color.WhiteString("Yao Application Setup v%s", share.VERSION))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
|
||||
ips, err := Ips()
|
||||
if err != nil {
|
||||
printError("Error: ", err.Error())
|
||||
}
|
||||
|
||||
addr := strings.Split(l.Addr().String(), ":")
|
||||
if len(addr) != 2 {
|
||||
printError("Error: can't get port")
|
||||
}
|
||||
|
||||
port := addr[1]
|
||||
fmt.Println(color.WhiteString("\nOpen URL in the browser to continue:\n"))
|
||||
for _, ip := range ips {
|
||||
printInfo("http://%s:%s", ip, port)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
SetupPort = port
|
||||
}
|
||||
|
||||
func printError(message string, args ...interface{}) {
|
||||
fmt.Println(color.RedString(message, args...))
|
||||
os.Exit(1)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue