commit
7841ca6459
19 changed files with 2110 additions and 101 deletions
15
Makefile
15
Makefile
|
|
@ -160,11 +160,14 @@ artifacts-linux: clean
|
|||
rm -f ../xgen-v1.0/pnpm-lock.yaml
|
||||
echo "BASE=__yao_admin_root" > ../xgen-v1.0/packages/xgen/.env
|
||||
cd ../xgen-v1.0 && pnpm install && pnpm run build
|
||||
# Setup UI
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install && pnpm run build
|
||||
|
||||
# Packing
|
||||
mkdir -p .tmp/data/xgen
|
||||
cp -r ./ui .tmp/data/ui
|
||||
cp -r ../xgen-v0.9/dist .tmp/data/xgen/v0.9
|
||||
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 .tmp/data/
|
||||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
|
|
@ -203,11 +206,15 @@ artifacts-macos: clean
|
|||
rm -f ../xgen-v1.0/pnpm-lock.yaml
|
||||
echo "BASE=__yao_admin_root" > ../xgen-v1.0/packages/xgen/.env
|
||||
cd ../xgen-v1.0 && pnpm install && pnpm run build
|
||||
# Setup UI
|
||||
cd ../xgen-v1.0/packages/setup && pnpm install && pnpm run build
|
||||
|
||||
|
||||
# Packing
|
||||
mkdir -p .tmp/data/xgen
|
||||
cp -r ./ui .tmp/data/ui
|
||||
cp -r ../xgen-v0.9/dist .tmp/data/xgen/v0.9
|
||||
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 .tmp/data/
|
||||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
|
|
@ -271,11 +278,15 @@ release: clean
|
|||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||
cd .tmp/xgen/v1.0 && pnpm install && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install && pnpm run build
|
||||
|
||||
# Packing
|
||||
mkdir -p .tmp/data/xgen
|
||||
cp -r ./ui .tmp/data/ui
|
||||
cp -r ./yao .tmp/data/yao
|
||||
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
|
||||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
rm -rf .tmp/data
|
||||
|
|
@ -312,11 +323,15 @@ linux-release: clean
|
|||
echo "BASE=__yao_admin_root" > .tmp/xgen/v1.0/packages/xgen/.env
|
||||
cd .tmp/xgen/v1.0 && pnpm install && pnpm run build
|
||||
|
||||
# Setup UI
|
||||
cd .tmp/xgen/v1.0/packages/setup && pnpm install && pnpm run build
|
||||
|
||||
# Packing
|
||||
mkdir -p .tmp/data/xgen
|
||||
cp -r ./ui .tmp/data/ui
|
||||
cp -r ./yao .tmp/data/yao
|
||||
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
|
||||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
rm -rf .tmp/data
|
||||
|
|
|
|||
40
cmd/start.go
40
cmd/start.go
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/yaoapp/yao/engine"
|
||||
"github.com/yaoapp/yao/fs"
|
||||
"github.com/yaoapp/yao/service"
|
||||
"github.com/yaoapp/yao/setup"
|
||||
"github.com/yaoapp/yao/share"
|
||||
"github.com/yaoapp/yao/studio"
|
||||
)
|
||||
|
|
@ -35,6 +36,19 @@ var startCmd = &cobra.Command{
|
|||
Long: L("Start Engine"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
// Setup
|
||||
if setup.Check() {
|
||||
go setup.Start()
|
||||
select {
|
||||
case <-setup.Done:
|
||||
setup.Stop()
|
||||
break
|
||||
case <-setup.Canceled:
|
||||
os.Exit(1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// recive interrupt signal
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
|
@ -58,10 +72,6 @@ var startCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
host := config.Conf.Host
|
||||
if host == "0.0.0.0" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
|
||||
dataRoot, _ := fs.Root(config.Conf)
|
||||
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
|
|
@ -73,15 +83,29 @@ var startCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
if share.App.XGen == "1.0" {
|
||||
|
||||
root, _ := adminRoot()
|
||||
fmt.Println(color.WhiteString(L(" XGen")), color.GreenString(" 1.0"))
|
||||
urls := []string{fmt.Sprintf("http://%s:%s", host, port)}
|
||||
if host == "0.0.0.0" {
|
||||
urls, _ = setup.URLs(config.Conf)
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString(L("XGen")), color.GreenString(" 1.0"))
|
||||
fmt.Println(color.WhiteString(L("Data")), color.GreenString(" %s", dataRoot))
|
||||
fmt.Println(color.WhiteString(L("Frontend")), color.GreenString(" http://%s%s/", host, port))
|
||||
fmt.Println(color.WhiteString(L("Dashboard")), color.GreenString(" http://%s%s%slogin/admin", host, port, root))
|
||||
fmt.Println(color.WhiteString(L("API")), color.GreenString(" http://%s%s/api", host, port))
|
||||
for _, url := range urls {
|
||||
fmt.Println(color.WhiteString(L("Frontend ")), color.GreenString(" %s", url))
|
||||
fmt.Println(color.WhiteString(L("Dashboard")), color.GreenString(" %s/%s/login/admin", url, strings.Trim(root, "/")))
|
||||
fmt.Println(color.WhiteString(L("API ")), color.GreenString(" %s/api", url))
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString(L("Listening")), color.GreenString(" %s:%d", config.Conf.Host, config.Conf.Port))
|
||||
|
||||
} else {
|
||||
|
||||
if host == "0.0.0.0" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString(L("Data")), color.GreenString(" %s", dataRoot))
|
||||
fmt.Println(color.WhiteString(L("Frontend")), color.GreenString(" http://%s%s/", host, port))
|
||||
fmt.Println(color.WhiteString(L("Dashboard")), color.GreenString(" http://%s%s/xiang/login/admin", host, port))
|
||||
|
|
|
|||
|
|
@ -40,13 +40,15 @@ func LoadFrom(envfile string) Config {
|
|||
|
||||
file, err := filepath.Abs(envfile)
|
||||
if err != nil {
|
||||
log.Warn("Can't load env file. %s", err.Error())
|
||||
}
|
||||
err = godotenv.Overload(file)
|
||||
if err != nil {
|
||||
log.Warn("Can't load env file. %s", err.Error())
|
||||
// log.Warn("Can't load env file. %s", err.Error())
|
||||
return Load()
|
||||
}
|
||||
|
||||
godotenv.Overload(file)
|
||||
// if err != nil {
|
||||
// // log.Warn("Can't load env file. %s", err.Error())
|
||||
// }
|
||||
|
||||
return Load()
|
||||
}
|
||||
|
||||
|
|
|
|||
101
data/bindata.go
101
data/bindata.go
|
|
@ -1,6 +1,7 @@
|
|||
// Code generated for package data by go-bindata DO NOT EDIT. (@generated)
|
||||
// sources:
|
||||
// .tmp/data/ui/index.html
|
||||
// .tmp/data/xgen/setup/index.html
|
||||
// .tmp/data/xgen/v0.9/index.html
|
||||
// .tmp/data/xgen/v1.0/index.html
|
||||
// .tmp/data/xgen/v1.0/layouts__index.async.js
|
||||
|
|
@ -216,7 +217,27 @@ func uiIndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "ui/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _xgenSetupIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8a\x70\x77\xf5\x53\x08\x76\x0d\x09\x0d\xe0\x02\x04\x00\x00\xff\xff\xdb\x53\x4c\xdc\x0b\x00\x00\x00")
|
||||
|
||||
func xgenSetupIndexHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_xgenSetupIndexHtml,
|
||||
"xgen/setup/index.html",
|
||||
)
|
||||
}
|
||||
|
||||
func xgenSetupIndexHtml() (*asset, error) {
|
||||
bytes, err := xgenSetupIndexHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xgen/setup/index.html", size: 11, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -236,7 +257,7 @@ func xgenV09IndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xgen/v0.9/index.html", size: 14, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "xgen/v0.9/index.html", size: 14, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -256,7 +277,7 @@ func xgenV10IndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xgen/v1.0/index.html", size: 50, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "xgen/v1.0/index.html", size: 50, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -276,7 +297,7 @@ func xgenV10Layouts__indexAsyncJs() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xgen/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "xgen/v1.0/layouts__index.async.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -296,7 +317,7 @@ func xgenV10UmiJs() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xgen/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "xgen/v1.0/umi.js", size: 71, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -316,7 +337,7 @@ func yaoApisReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -336,7 +357,7 @@ func yaoApisChartHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -356,7 +377,7 @@ func yaoApisImportHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -376,7 +397,7 @@ func yaoApisPageHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -396,7 +417,7 @@ func yaoApisStorageHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/storage.http.json", size: 1026, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/storage.http.json", size: 1026, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -416,7 +437,7 @@ func yaoApisTableHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/table.http.json", size: 3213, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/table.http.json", size: 3213, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -436,7 +457,7 @@ func yaoApisUserHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -456,7 +477,7 @@ func yaoApisXiangHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -476,7 +497,7 @@ func yaoDataAppJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/app.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/app.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -496,7 +517,7 @@ func yaoDataIcons404Png() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -516,7 +537,7 @@ func yaoDataIconsIconIcns() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -536,7 +557,7 @@ func yaoDataIconsIconIco() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -556,7 +577,7 @@ func yaoDataIconsIconPng() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -576,7 +597,7 @@ func yaoDataIndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -596,7 +617,7 @@ func yaoFieldsModelTransJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14777, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/fields/model.trans.json", size: 14777, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -616,7 +637,7 @@ func yaoFlowsReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -636,7 +657,7 @@ func yaoFlowsAdminGuardFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/admin/guard.flow.json", size: 559, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/admin/guard.flow.json", size: 559, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -656,7 +677,7 @@ func yaoFlowsMenuFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -676,7 +697,7 @@ func yaoFlowsUserFindFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/user/find.flow.json", size: 328, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/user/find.flow.json", size: 328, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -696,7 +717,7 @@ func yaoLangsEnUsJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -716,7 +737,7 @@ func yaoLangsZhCnGlobalYml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/zh-cn/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -736,7 +757,7 @@ func yaoLangsZhCnLoginsAdminLoginYml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -756,7 +777,7 @@ func yaoLangsZhCnLoginsUserLoginYml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/zh-cn/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -776,7 +797,7 @@ func yaoLangsZhHkGlobalYml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/zh-hk/global.yml", size: 1629, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -796,7 +817,7 @@ func yaoLangsZhHkLoginsAdminLoginYml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/admin.login.yml", size: 94, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -816,7 +837,7 @@ func yaoLangsZhHkLoginsUserLoginYml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/zh-hk/logins/user.login.yml", size: 90, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -836,7 +857,7 @@ func yaoModelsReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -856,7 +877,7 @@ func yaoModelsMenuModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/menu.mod.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/menu.mod.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -876,7 +897,7 @@ func yaoModelsUserModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -896,7 +917,7 @@ func yaoModelsWorkflowModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -916,7 +937,7 @@ func yaoTablesReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -936,7 +957,7 @@ func yaoTablesMenuTabJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/tables/menu.tab.json", size: 10471, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/tables/menu.tab.json", size: 10471, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -956,7 +977,7 @@ func yaoTablesUserTabJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/tables/user.tab.json", size: 2357, mode: os.FileMode(420), modTime: time.Unix(1666415327, 0)}
|
||||
info := bindataFileInfo{name: "yao/tables/user.tab.json", size: 2357, mode: os.FileMode(420), modTime: time.Unix(1666927855, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -1014,6 +1035,7 @@ func AssetNames() []string {
|
|||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"ui/index.html": uiIndexHtml,
|
||||
"xgen/setup/index.html": xgenSetupIndexHtml,
|
||||
"xgen/v0.9/index.html": xgenV09IndexHtml,
|
||||
"xgen/v1.0/index.html": xgenV10IndexHtml,
|
||||
"xgen/v1.0/layouts__index.async.js": xgenV10Layouts__indexAsyncJs,
|
||||
|
|
@ -1100,6 +1122,9 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"index.html": {uiIndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"xgen": {nil, map[string]*bintree{
|
||||
"setup": {nil, map[string]*bintree{
|
||||
"index.html": {xgenSetupIndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"v0.9": {nil, map[string]*bintree{
|
||||
"index.html": {xgenV09IndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
|
|
|
|||
12
data/data.go
12
data/data.go
|
|
@ -33,6 +33,18 @@ func XgenV1() *assetfs.AssetFS {
|
|||
panic("unreachable")
|
||||
}
|
||||
|
||||
// Setup Setup ui
|
||||
func Setup() *assetfs.AssetFS {
|
||||
assetInfo := func(path string) (os.FileInfo, error) {
|
||||
return os.Stat(path)
|
||||
}
|
||||
for k := range _bintree.Children {
|
||||
k = "xgen/setup"
|
||||
return &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: assetInfo, Prefix: k, Fallback: "index.html"}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// ReplaceXGen bindata file
|
||||
func ReplaceXGen(search, replace string) error {
|
||||
err := replaceXGenIndex(search, replace)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ func TestCommandStart(t *testing.T) {
|
|||
request := func() (maps.MapStr, error) {
|
||||
time.Sleep(time.Microsecond * 2000)
|
||||
url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "127.0.0.1", config.Conf.Port)
|
||||
// utils.Dump(url)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -1,38 +1,17 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/data"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
// XGenFileServerV0 XGen v0.9
|
||||
var XGenFileServerV0 http.Handler = http.FileServer(data.XgenV0())
|
||||
|
||||
// XGenFileServerV1 XGen v1.0
|
||||
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
||||
|
||||
// AppFileServer 应用静态文件
|
||||
var AppFileServer http.Handler = http.FileServer(http.Dir(filepath.Join(config.Conf.Root, "ui")))
|
||||
|
||||
// Middlewares 服务中间件
|
||||
var Middlewares = []gin.HandlerFunc{
|
||||
// BindDomain,
|
||||
BinStatic,
|
||||
}
|
||||
|
||||
// AdminRoot cache
|
||||
var AdminRoot = ""
|
||||
|
||||
// AdminRootLen cache
|
||||
var AdminRootLen = 0
|
||||
|
||||
// BinStatic 静态文件服务
|
||||
func BinStatic(c *gin.Context) {
|
||||
|
||||
|
|
@ -44,10 +23,10 @@ func BinStatic(c *gin.Context) {
|
|||
return
|
||||
|
||||
} else if share.App.XGen == "1.0" {
|
||||
|
||||
// Xgen 1.0
|
||||
adminRoot, adminRootLen := adminRoot()
|
||||
if length >= adminRootLen && c.Request.URL.Path[0:adminRootLen] == adminRoot {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, c.Request.URL.Path[0:adminRootLen-1])
|
||||
if length >= AdminRootLen && c.Request.URL.Path[0:AdminRootLen] == AdminRoot {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, c.Request.URL.Path[0:AdminRootLen-1])
|
||||
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
return
|
||||
|
|
@ -69,24 +48,7 @@ func BinStatic(c *gin.Context) {
|
|||
|
||||
}
|
||||
|
||||
// 应用内静态文件目录(/ui)
|
||||
// 应用内静态文件目录(/ui or public)
|
||||
AppFileServer.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
func adminRoot() (string, int) {
|
||||
if AdminRoot != "" {
|
||||
return AdminRoot, AdminRootLen
|
||||
}
|
||||
|
||||
adminRoot := "/yao/"
|
||||
if share.App.AdminRoot != "" {
|
||||
root := strings.TrimPrefix(share.App.AdminRoot, "/")
|
||||
root = strings.TrimSuffix(root, "/")
|
||||
adminRoot = fmt.Sprintf("/%s/", root)
|
||||
}
|
||||
adminRootLen := len(adminRoot)
|
||||
AdminRoot = adminRoot
|
||||
AdminRootLen = adminRootLen
|
||||
return AdminRoot, AdminRootLen
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,13 @@ import (
|
|||
)
|
||||
|
||||
var shutdown = make(chan bool, 1)
|
||||
|
||||
var shutdownComplete = make(chan bool, 1)
|
||||
|
||||
// Start 启动服务
|
||||
func Start() error {
|
||||
|
||||
err := share.SessionStart()
|
||||
err := prepare()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -84,3 +85,19 @@ func StopWithContext(ctx context.Context, onComplete func()) {
|
|||
onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
func prepare() error {
|
||||
|
||||
// Session server
|
||||
err := share.SessionStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SetupStatic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
126
service/static.go
Normal file
126
service/static.go
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/data"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
// AppFileServer static file server
|
||||
var AppFileServer http.Handler
|
||||
|
||||
// XGenFileServerV0 XGen v0.9
|
||||
var XGenFileServerV0 http.Handler = http.FileServer(data.XgenV0())
|
||||
|
||||
// XGenFileServerV1 XGen v1.0
|
||||
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
||||
|
||||
// AdminRoot cache
|
||||
var AdminRoot = ""
|
||||
|
||||
// AdminRootLen cache
|
||||
var AdminRootLen = 0
|
||||
|
||||
// Dir files
|
||||
type Dir string
|
||||
|
||||
// SetupStatic setup static file server
|
||||
func SetupStatic() error {
|
||||
|
||||
// SetAdmin Root
|
||||
adminRoot()
|
||||
|
||||
// Static file server
|
||||
AppFileServer = http.FileServer(Dir(filepath.Join(config.Conf.Root, "public")))
|
||||
if share.App.XGen == "" || share.App.XGen == "0.9" {
|
||||
AppFileServer = http.FileServer(Dir(filepath.Join(config.Conf.Root, "ui")))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open implements FileSystem using os.Open, opening files for reading rooted
|
||||
// and relative to the directory d.
|
||||
func (d Dir) Open(name string) (http.File, error) {
|
||||
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
|
||||
return nil, errors.New("http: invalid character in file path")
|
||||
}
|
||||
|
||||
dir := string(d)
|
||||
if dir == "" {
|
||||
dir = "."
|
||||
}
|
||||
|
||||
fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
|
||||
|
||||
// Close dir views Disable directory listing
|
||||
stat, err := os.Stat(fullName)
|
||||
if err != nil {
|
||||
return nil, mapOpenError(err, fullName, filepath.Separator, os.Stat)
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
indexFile := filepath.Join(fullName, "index.html")
|
||||
if _, err := os.Stat(indexFile); os.IsNotExist(err) {
|
||||
return nil, mapOpenError(fs.ErrNotExist, fullName, filepath.Separator, os.Stat)
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.Open(fullName)
|
||||
if err != nil {
|
||||
return nil, mapOpenError(err, fullName, filepath.Separator, os.Stat)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// mapOpenError maps the provided non-nil error from opening name
|
||||
// to a possibly better non-nil error. In particular, it turns OS-specific errors
|
||||
// about opening files in non-directories into fs.ErrNotExist. See Issues 18984 and 49552.
|
||||
func mapOpenError(originalErr error, name string, sep rune, stat func(string) (fs.FileInfo, error)) error {
|
||||
if errors.Is(originalErr, fs.ErrNotExist) || errors.Is(originalErr, fs.ErrPermission) {
|
||||
return originalErr
|
||||
}
|
||||
|
||||
parts := strings.Split(name, string(sep))
|
||||
for i := range parts {
|
||||
if parts[i] == "" {
|
||||
continue
|
||||
}
|
||||
fi, err := stat(strings.Join(parts[:i+1], string(sep)))
|
||||
if err != nil {
|
||||
return originalErr
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
return fs.ErrNotExist
|
||||
}
|
||||
}
|
||||
return originalErr
|
||||
}
|
||||
|
||||
// SetupAdmin setup admin static root
|
||||
func adminRoot() (string, int) {
|
||||
if AdminRoot != "" {
|
||||
return AdminRoot, AdminRootLen
|
||||
}
|
||||
|
||||
adminRoot := "/yao/"
|
||||
if share.App.AdminRoot != "" {
|
||||
root := strings.TrimPrefix(share.App.AdminRoot, "/")
|
||||
root = strings.TrimSuffix(root, "/")
|
||||
adminRoot = fmt.Sprintf("/%s/", root)
|
||||
}
|
||||
adminRootLen := len(adminRoot)
|
||||
AdminRoot = adminRoot
|
||||
AdminRootLen = adminRootLen
|
||||
return AdminRoot, AdminRootLen
|
||||
}
|
||||
|
|
@ -215,14 +215,14 @@ func watchModel(root string, file string, event string, cfg config.Config) {
|
|||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
mod, err := gou.LoadModelReturn(string(content), name)
|
||||
_, err = gou.LoadModelReturn(string(content), name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
mod.Migrate(true)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Created", name))
|
||||
// mod.Migrate(true)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Created (Please run yao migrate manually)", name))
|
||||
break
|
||||
|
||||
case "WRITE":
|
||||
|
|
@ -231,13 +231,13 @@ func watchModel(root string, file string, event string, cfg config.Config) {
|
|||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
mod, err := gou.LoadModelReturn(string(content), name)
|
||||
_, err = gou.LoadModelReturn(string(content), name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
mod.Migrate(false)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Reloaded", name))
|
||||
// mod.Migrate(false)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Reloaded (Please run yao migrate manually)", name))
|
||||
break
|
||||
|
||||
case "REMOVE", "RENAME":
|
||||
|
|
|
|||
116
setup/check.go
Normal file
116
setup/check.go
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou/connector"
|
||||
"github.com/yaoapp/yao/config"
|
||||
)
|
||||
|
||||
// Check setup programe
|
||||
func Check() bool {
|
||||
|
||||
root := appRoot()
|
||||
|
||||
appfile := filepath.Join(root, "app.json")
|
||||
if _, err := os.Stat(appfile); err != nil && os.IsNotExist(err) {
|
||||
return true
|
||||
}
|
||||
|
||||
envfile := filepath.Join(root, ".env")
|
||||
if _, err := os.Stat(envfile); err != nil && os.IsNotExist(err) {
|
||||
cfg, err := getConfig()
|
||||
if err != nil || !hasInstalled(cfg) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Validate db link
|
||||
func Validate() (err error) {
|
||||
|
||||
root := appRoot()
|
||||
path := filepath.Join(root, "db", "yao.db")
|
||||
|
||||
data := []byte(fmt.Sprintf(`{
|
||||
"type": "sqlite3",
|
||||
"options": {
|
||||
"file": "%s"
|
||||
}
|
||||
}`, path))
|
||||
|
||||
data = []byte(`{
|
||||
"type": "mysql",
|
||||
"options": {
|
||||
"db": "test",
|
||||
"hosts": [{ "host": "127.0.0.1", "user":"root", "pass":"123456" }]
|
||||
}
|
||||
}`)
|
||||
|
||||
_, err = connector.Load(string(data), "test")
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func appRoot() string {
|
||||
|
||||
root := os.Getenv("YAO_ROOT")
|
||||
if root == "" {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
printError("无法获取应用目录: %s", err)
|
||||
Stop()
|
||||
}
|
||||
root = path
|
||||
}
|
||||
|
||||
root, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
printError("无法获取应用目录: %s", err)
|
||||
Stop()
|
||||
}
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
func getConfig() (config.Config, error) {
|
||||
root := appRoot()
|
||||
envfile := filepath.Join(root, ".env")
|
||||
cfg := config.LoadFrom(envfile)
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func hasInstalled(cfg config.Config) bool {
|
||||
|
||||
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) {
|
||||
fmt.Println(dbfile)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
break
|
||||
|
||||
case "mysql":
|
||||
if cfg.DB.Primary != nil && len(cfg.DB.Primary) > 0 {
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
14
setup/check_test.go
Normal file
14
setup/check_test.go
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
// err := Validate()
|
||||
// fmt.Println(err)
|
||||
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
}
|
||||
65
setup/env.go
Normal file
65
setup/env.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
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
|
||||
}
|
||||
115
setup/handler.go
Normal file
115
setup/handler.go
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/xun"
|
||||
)
|
||||
|
||||
// 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 := getPayload(c)
|
||||
|
||||
cfg, err := getConfig()
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if hasInstalled(cfg) {
|
||||
c.JSON(403, gin.H{"code": 400, "message": "应用已安装, 删除 .env 文件后重试"})
|
||||
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
|
||||
}
|
||||
|
||||
// Return
|
||||
urls, err := AdminURL(cfg)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
"code": 200,
|
||||
"message": "安装成功",
|
||||
"urls": urls,
|
||||
})
|
||||
|
||||
Complete()
|
||||
}
|
||||
|
||||
func runCheck(c *gin.Context) {
|
||||
time.Sleep(2 * time.Second)
|
||||
c.JSON(200, gin.H{"code": 200})
|
||||
}
|
||||
|
||||
func getPayload(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()})
|
||||
return nil
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
1254
setup/install.go
Normal file
1254
setup/install.go
Normal file
File diff suppressed because it is too large
Load diff
12
setup/install_test.go
Normal file
12
setup/install_test.go
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInstall(t *testing.T) {
|
||||
// err := Install()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
}
|
||||
230
setup/setup.go
Normal file
230
setup/setup.go
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
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"
|
||||
)
|
||||
|
||||
// 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 := ":5099"
|
||||
|
||||
// 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() {
|
||||
Done <- true
|
||||
}
|
||||
|
||||
// Stop stop the studio api server
|
||||
func Stop() {
|
||||
shutdown <- true
|
||||
}
|
||||
|
||||
// AdminURL get admin url
|
||||
func AdminURL(cfg config.Config) ([]string, error) {
|
||||
err := engine.Load(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
urls, err := URLs(cfg)
|
||||
|
||||
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) {
|
||||
err := engine.Load(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ips, err := Ips()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range ips {
|
||||
ips[i] = fmt.Sprintf("http://%s:%d", ips[i], cfg.Port)
|
||||
}
|
||||
|
||||
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]
|
||||
for _, ip := range ips {
|
||||
fmt.Println(color.WhiteString("\nOpen URL in the browser to continue:\n"))
|
||||
printInfo("http://%s:%s", ip, port)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func printError(message string, args ...interface{}) {
|
||||
fmt.Println(color.RedString(message, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func printInfo(message string, args ...interface{}) {
|
||||
fmt.Println(color.GreenString(message, args...))
|
||||
}
|
||||
|
||||
// Ips get the local ip list
|
||||
func Ips() ([]string, error) {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iplist := []string{}
|
||||
for _, address := range addrs {
|
||||
// check the address type and if it is not a loopback the display it
|
||||
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
if ipnet.IP.To4() != nil {
|
||||
iplist = append(iplist, ipnet.IP.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return iplist, nil
|
||||
}
|
||||
|
|
@ -51,6 +51,26 @@ func (c *Computable) ComputeEdit(name string, process *gou.Process, args []inter
|
|||
return nil
|
||||
}
|
||||
|
||||
if columns, ok := args[0].([]interface{}); ok {
|
||||
new := []string{}
|
||||
for _, col := range columns {
|
||||
new = append(new, fmt.Sprintf("%v", col))
|
||||
}
|
||||
args[0] = new
|
||||
}
|
||||
|
||||
if values, ok := args[1].([]interface{}); ok {
|
||||
new := [][]interface{}{}
|
||||
for _, value := range values {
|
||||
arr, ok := value.([]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("args[1] is not a [][] %s", reflect.ValueOf(args[1]).Type().Name())
|
||||
}
|
||||
new = append(new, arr)
|
||||
}
|
||||
args[1] = new
|
||||
}
|
||||
|
||||
if _, ok := args[0].([]string); !ok {
|
||||
return fmt.Errorf("args[0] is not a []string %s", reflect.ValueOf(args[0]).Type().Name())
|
||||
}
|
||||
|
|
|
|||
1
xgen/setup/index.html
Normal file
1
xgen/setup/index.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
XGEN SETUP
|
||||
Loading…
Add table
Reference in a new issue