348 lines
6.2 KiB
Go
348 lines
6.2 KiB
Go
package setup
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/yaoapp/gou/model"
|
|
"github.com/yaoapp/gou/process"
|
|
v8 "github.com/yaoapp/gou/runtime/v8"
|
|
"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 {
|
|
|
|
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)
|
|
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)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = envSet(file, "YAO_PORT", port)
|
|
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
|
|
}
|
|
|
|
func makeInit(root string) error {
|
|
|
|
if appSourceExists() {
|
|
return nil
|
|
}
|
|
|
|
files := data.AssetNames()
|
|
for _, file := range files {
|
|
if strings.HasPrefix(file, "init/") {
|
|
dst := filepath.Join(root, strings.TrimPrefix(file, "init/"))
|
|
content, err := data.Read(file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := os.Stat(dst); err == nil { // exists
|
|
log.Error("[setup] %s exists", dst)
|
|
continue
|
|
}
|
|
|
|
dir := filepath.Dir(dst)
|
|
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = os.WriteFile(dst, content, 0644); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func makeMigrate(root string, cfg config.Config) error {
|
|
|
|
// Do Stuff Here
|
|
for _, mod := range model.Models {
|
|
has, err := mod.HasTable()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if has {
|
|
log.Warn("%s (%s) table already exists", mod.ID, mod.MetaData.Table.Name)
|
|
continue
|
|
}
|
|
|
|
err = mod.Migrate(false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func makeSetup(root string, cfg config.Config) error {
|
|
|
|
if app.Setting != nil && app.Setting.Setup != "" {
|
|
|
|
if strings.HasPrefix(app.Setting.Setup, "studio.") {
|
|
names := strings.Split(app.Setting.Setup, ".")
|
|
if len(names) < 3 {
|
|
return fmt.Errorf("setup studio script %s error", app.Setting.Setup)
|
|
}
|
|
|
|
service := strings.Join(names[1:len(names)-1], ".")
|
|
method := names[len(names)-1]
|
|
|
|
script, err := v8.SelectRoot(service)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sid := uuid.NewString()
|
|
ctx, err := script.NewContext(fmt.Sprintf("%v", sid), nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer ctx.Close()
|
|
|
|
_, err = ctx.Call(method)
|
|
return err
|
|
}
|
|
|
|
p, err := process.Of(app.Setting.Setup, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = p.Exec()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|