优化载入逻辑: Step 5/5
This commit is contained in:
parent
36bfeb8aad
commit
f4e0fee81f
8 changed files with 238 additions and 64 deletions
1
.github/workflows/unit-test.yml
vendored
1
.github/workflows/unit-test.yml
vendored
|
|
@ -11,6 +11,7 @@ env:
|
|||
XIANG_MODE: debug
|
||||
XIANG_SOURCE: ${{ github.WORKSPACE }}
|
||||
XIANG_ROOT: ${{ github.WORKSPACE }}/tests
|
||||
XIANG_ROOT_PLUGIN: ${{ HOME }}/data/gou-unit/plugins
|
||||
|
||||
# 服务配置
|
||||
XIANG_SERVICE_DEBUG: true
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ package engine
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
|
|
@ -25,23 +22,24 @@ func Load(cfg config.Config) {
|
|||
share.DBConnect(cfg.Database) // 创建数据库连接
|
||||
|
||||
app.Load(cfg) // 加载应用信息
|
||||
|
||||
LoadEngine(cfg.Path)
|
||||
|
||||
model.Load(cfg) // 加载数据模型 model
|
||||
api.Load(cfg) // 加载业务接口 API
|
||||
flow.Load(cfg) // 加载业务逻辑 Flow
|
||||
plugin.Load(cfg) // 加载业务插件 plugin
|
||||
table.Load(cfg) // 加载数据表格 table
|
||||
|
||||
LoadApp(share.AppRoot{
|
||||
APIs: cfg.RootAPI,
|
||||
Flows: cfg.RootFLow,
|
||||
Models: cfg.RootModel,
|
||||
Plugins: cfg.RootPlugin,
|
||||
Tables: cfg.RootTable,
|
||||
Charts: cfg.RootChart,
|
||||
Screens: cfg.RootScreen,
|
||||
Data: cfg.RootData,
|
||||
})
|
||||
// LoadApp(share.AppRoot{
|
||||
// APIs: cfg.RootAPI,
|
||||
// Flows: cfg.RootFLow,
|
||||
// Models: cfg.RootModel,
|
||||
// Plugins: cfg.RootPlugin,
|
||||
// Tables: cfg.RootTable,
|
||||
// Charts: cfg.RootChart,
|
||||
// Screens: cfg.RootScreen,
|
||||
// Data: cfg.RootData,
|
||||
// })
|
||||
|
||||
// 加密密钥函数
|
||||
gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, cfg.Database.AESKey), "AES")
|
||||
|
|
@ -113,7 +111,7 @@ func LoadEngine(from string) {
|
|||
for _, script := range scripts {
|
||||
switch script.Type {
|
||||
case "tables":
|
||||
table.Load(string(script.Content), "xiang."+script.Name)
|
||||
table.LoadTable(string(script.Content), "xiang."+script.Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -125,23 +123,23 @@ func LoadApp(app share.AppRoot) {
|
|||
// api string, flow string, model string, plugin string
|
||||
// 创建应用目录
|
||||
// paths := []string{app.APIs, app.Flows, app.Models, app.Plugins, app.Charts, app.Tables, app.Screens, app.Data}
|
||||
paths := []string{app.Flows, app.Models, app.Plugins, app.Charts, app.Tables, app.Screens, app.Data}
|
||||
for _, p := range paths {
|
||||
if !strings.HasPrefix(p, "fs://") && strings.Contains(p, "://") {
|
||||
continue
|
||||
}
|
||||
root, err := filepath.Abs(strings.TrimPrefix(p, "fs://"))
|
||||
if err != nil {
|
||||
log.Panicf("创建目录失败(%s) %s", root, err)
|
||||
}
|
||||
// paths := []string{app.Flows, app.Models, app.Plugins, app.Charts, app.Tables, app.Screens, app.Data}
|
||||
// for _, p := range paths {
|
||||
// if !strings.HasPrefix(p, "fs://") && strings.Contains(p, "://") {
|
||||
// continue
|
||||
// }
|
||||
// root, err := filepath.Abs(strings.TrimPrefix(p, "fs://"))
|
||||
// if err != nil {
|
||||
// log.Panicf("创建目录失败(%s) %s", root, err)
|
||||
// }
|
||||
|
||||
if _, err := os.Stat(root); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(root, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Panicf("创建目录失败(%s) %s", root, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// if _, err := os.Stat(root); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(root, os.ModePerm)
|
||||
// if err != nil {
|
||||
// log.Panicf("创建目录失败(%s) %s", root, err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 加载API
|
||||
// if strings.HasPrefix(app.APIs, "fs://") || !strings.Contains(app.APIs, "://") {
|
||||
|
|
@ -181,13 +179,13 @@ func LoadApp(app share.AppRoot) {
|
|||
// }
|
||||
|
||||
// 加载Table
|
||||
if strings.HasPrefix(app.Tables, "fs://") || !strings.Contains(app.Tables, "://") {
|
||||
root := strings.TrimPrefix(app.Tables, "fs://")
|
||||
scripts := share.GetAppFilesFS(root, ".json")
|
||||
for _, script := range scripts {
|
||||
// 验证API 加载逻辑
|
||||
table.Load(string(script.Content), script.Name)
|
||||
}
|
||||
}
|
||||
// if strings.HasPrefix(app.Tables, "fs://") || !strings.Contains(app.Tables, "://") {
|
||||
// root := strings.TrimPrefix(app.Tables, "fs://")
|
||||
// scripts := share.GetAppFilesFS(root, ".json")
|
||||
// for _, script := range scripts {
|
||||
// // 验证API 加载逻辑
|
||||
// table.Load(string(script.Content), script.Name)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Load 加载数据模型
|
||||
// Load 加载业务插件
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootPlugin, "")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ func watchEngine(from string) {
|
|||
}
|
||||
if op == "write" || op == "create" {
|
||||
script := share.GetFile(root, file)
|
||||
table.Load(string(script.Content), "xiang."+script.Name) // Reload
|
||||
table.LoadTable(string(script.Content), "xiang."+script.Name) // Reload
|
||||
api, has := gou.APIs["xiang.table"]
|
||||
if has {
|
||||
api.Reload()
|
||||
|
|
@ -202,7 +202,7 @@ func watchAppTable(rootTable string) {
|
|||
|
||||
if op == "write" || op == "create" {
|
||||
script := share.GetAppFile(root, file)
|
||||
table.Load(string(script.Content), script.Name) // Reload
|
||||
table.LoadTable(string(script.Content), script.Name) // Reload
|
||||
api, has := gou.APIs["xiang.table"]
|
||||
if has {
|
||||
api.Reload()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package engine
|
||||
package table
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
@ -7,10 +7,17 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/xiang/table"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/model"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
"github.com/yaoapp/xun/capsule"
|
||||
)
|
||||
|
||||
func init() {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
model.Load(config.Conf)
|
||||
Load(config.Conf)
|
||||
}
|
||||
func TestTableProcessSearch(t *testing.T) {
|
||||
|
||||
args := []interface{}{
|
||||
|
|
@ -25,7 +32,7 @@ func TestTableProcessSearch(t *testing.T) {
|
|||
&gin.Context{},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Search", args...)
|
||||
response := table.ProcessSearch(process)
|
||||
response := ProcessSearch(process)
|
||||
assert.NotNil(t, response)
|
||||
res := any.Of(response).Map()
|
||||
assert.True(t, res.Has("data"))
|
||||
|
|
@ -46,7 +53,7 @@ func TestTableProcessFind(t *testing.T) {
|
|||
&gin.Context{},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Find", args...)
|
||||
response := table.ProcessFind(process)
|
||||
response := ProcessFind(process)
|
||||
assert.NotNil(t, response)
|
||||
res := any.Of(response).Map()
|
||||
assert.Equal(t, any.Of(res.Get("id")).CInt(), 1)
|
||||
|
|
@ -64,7 +71,7 @@ func TestTableProcessSave(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Save", args...)
|
||||
response := table.ProcessSave(process)
|
||||
response := ProcessSave(process)
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
||||
|
|
@ -86,7 +93,7 @@ func TestTableProcessDelete(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Save", args...)
|
||||
response := table.ProcessSave(process)
|
||||
response := ProcessSave(process)
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
||||
|
|
@ -96,7 +103,7 @@ func TestTableProcessDelete(t *testing.T) {
|
|||
id,
|
||||
}
|
||||
process = gou.NewProcess("xiang.table.Delete", args...)
|
||||
response = table.ProcessDelete(process)
|
||||
response = ProcessDelete(process)
|
||||
assert.Nil(t, response)
|
||||
|
||||
// 清空数据
|
||||
|
|
@ -113,7 +120,7 @@ func TestTableProcessInsert(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Insert", args...)
|
||||
response := table.ProcessInsert(process)
|
||||
response := ProcessInsert(process)
|
||||
assert.Nil(t, response)
|
||||
|
||||
// 清空数据
|
||||
|
|
@ -132,7 +139,7 @@ func TestTableProcessDeleteWhere(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Save", args...)
|
||||
response := table.ProcessSave(process)
|
||||
response := ProcessSave(process)
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
||||
|
|
@ -146,7 +153,7 @@ func TestTableProcessDeleteWhere(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process = gou.NewProcess("xiang.table.DeleteWhere", args...)
|
||||
response = table.ProcessDeleteWhere(process)
|
||||
response = ProcessDeleteWhere(process)
|
||||
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
|
@ -168,7 +175,7 @@ func TestTableProcessDeleteIn(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Save", args...)
|
||||
response := table.ProcessSave(process)
|
||||
response := ProcessSave(process)
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
||||
|
|
@ -179,7 +186,7 @@ func TestTableProcessDeleteIn(t *testing.T) {
|
|||
"id",
|
||||
}
|
||||
process = gou.NewProcess("xiang.table.DeleteIn", args...)
|
||||
response = table.ProcessDeleteIn(process)
|
||||
response = ProcessDeleteIn(process)
|
||||
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
|
@ -201,7 +208,7 @@ func TestTableProcessUpdateWhere(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Save", args...)
|
||||
response := table.ProcessSave(process)
|
||||
response := ProcessSave(process)
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
||||
|
|
@ -218,7 +225,7 @@ func TestTableProcessUpdateWhere(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process = gou.NewProcess("xiang.table.UpdateWhere", args...)
|
||||
response = table.ProcessUpdateWhere(process)
|
||||
response = ProcessUpdateWhere(process)
|
||||
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
|
@ -240,7 +247,7 @@ func TestTableProcessUpdateIn(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process := gou.NewProcess("xiang.table.Save", args...)
|
||||
response := table.ProcessSave(process)
|
||||
response := ProcessSave(process)
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
||||
|
|
@ -254,7 +261,7 @@ func TestTableProcessUpdateIn(t *testing.T) {
|
|||
},
|
||||
}
|
||||
process = gou.NewProcess("xiang.table.UpdateIn", args...)
|
||||
response = table.ProcessUpdateIn(process)
|
||||
response = ProcessUpdateIn(process)
|
||||
|
||||
assert.NotNil(t, response)
|
||||
assert.True(t, any.Of(response).IsInt())
|
||||
|
|
@ -267,7 +274,7 @@ func TestTableProcessUpdateIn(t *testing.T) {
|
|||
func TestTableProcessSetting(t *testing.T) {
|
||||
args := []interface{}{"service", ""}
|
||||
process := gou.NewProcess("xiang.table.Setting", args...)
|
||||
response := table.ProcessSetting(process)
|
||||
response := ProcessSetting(process)
|
||||
assert.NotNil(t, response)
|
||||
res := any.Of(response).Map()
|
||||
assert.Equal(t, res.Get("name"), "云服务库")
|
||||
|
|
@ -283,7 +290,7 @@ func TestTableProcessSetting(t *testing.T) {
|
|||
func TestTableProcessSettingList(t *testing.T) {
|
||||
args := []interface{}{"service", "list"}
|
||||
process := gou.NewProcess("xiang.table.Setting", args...)
|
||||
response := table.ProcessSetting(process)
|
||||
response := ProcessSetting(process)
|
||||
assert.NotNil(t, response)
|
||||
res := any.Of(response).Map()
|
||||
assert.True(t, res.Has("actions"))
|
||||
|
|
@ -294,7 +301,7 @@ func TestTableProcessSettingList(t *testing.T) {
|
|||
func TestTableProcessSettingListEdit(t *testing.T) {
|
||||
args := []interface{}{"service", "list, edit"}
|
||||
process := gou.NewProcess("xiang.table.Setting", args...)
|
||||
response := table.ProcessSetting(process)
|
||||
response := ProcessSetting(process)
|
||||
assert.NotNil(t, response)
|
||||
res := any.Of(response).MapStr().Dot()
|
||||
assert.True(t, res.Has("list.actions"))
|
||||
|
|
@ -9,14 +9,34 @@ import (
|
|||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/helper"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Tables 已载入模型
|
||||
var Tables = map[string]*Table{}
|
||||
|
||||
// Load 载入数据表格
|
||||
func Load(source string, name string) *Table {
|
||||
// Load 加载数据表格
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootTable, "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
LoadTable(string(content), name)
|
||||
})
|
||||
}
|
||||
|
||||
// LoadTable 载入数据表格
|
||||
func LoadTable(source string, name string) *Table {
|
||||
var input io.Reader = nil
|
||||
if strings.HasPrefix(source, "file://") || strings.HasPrefix(source, "fs://") {
|
||||
filename := strings.TrimPrefix(source, "file://")
|
||||
|
|
@ -61,7 +81,7 @@ func Select(name string) *Table {
|
|||
|
||||
// Reload 更新数据表格配置
|
||||
func (table *Table) Reload() *Table {
|
||||
*table = *Load(table.Source, table.Name)
|
||||
*table = *LoadTable(table.Source, table.Name)
|
||||
return table
|
||||
}
|
||||
|
||||
|
|
|
|||
29
table/table_test.go
Normal file
29
table/table_test.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/model"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
model.Load(config.Conf)
|
||||
|
||||
Tables = make(map[string]*Table)
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
check(t)
|
||||
}
|
||||
|
||||
func check(t *testing.T) {
|
||||
keys := []string{}
|
||||
for key := range Tables {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 2, len(keys))
|
||||
}
|
||||
119
tests/tables/foo/bar.tab.json
Normal file
119
tests/tables/foo/bar.tab.json
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
{
|
||||
"name": "菜单",
|
||||
"version": "1.0.0",
|
||||
"decription": "菜单设置",
|
||||
"bind": {
|
||||
"model": "service"
|
||||
},
|
||||
"apis": {},
|
||||
"columns": {},
|
||||
"filters": {},
|
||||
"list": {
|
||||
"primary": "id",
|
||||
"layout": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "名称",
|
||||
"width": "240px"
|
||||
},
|
||||
{
|
||||
"name": "父节点"
|
||||
},
|
||||
{
|
||||
"name": "图标"
|
||||
},
|
||||
{
|
||||
"name": "状态"
|
||||
},
|
||||
{
|
||||
"name": "路由"
|
||||
},
|
||||
{
|
||||
"name": "排列"
|
||||
},
|
||||
{
|
||||
"name": "block布局"
|
||||
},
|
||||
{
|
||||
"name": "显示"
|
||||
}
|
||||
],
|
||||
"filters": [
|
||||
{
|
||||
"name": "名称",
|
||||
"width": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
"actions": {
|
||||
"create": {
|
||||
"type": "button",
|
||||
"props": {
|
||||
"label": "新建菜单",
|
||||
"icon": "fas fa-plus"
|
||||
}
|
||||
},
|
||||
"view": {},
|
||||
"edit": {},
|
||||
"import": {},
|
||||
"update": {},
|
||||
"delete": {},
|
||||
"insert": {},
|
||||
"updateWhere": {},
|
||||
"deleteWhere": {},
|
||||
"updateSelect": {},
|
||||
"deleteSelect": {},
|
||||
"pagination": {},
|
||||
"setting": {}
|
||||
}
|
||||
},
|
||||
"edit": {
|
||||
"primary": "id",
|
||||
"layout": {
|
||||
"fieldset": [
|
||||
{
|
||||
"title": "基础信息",
|
||||
"description": "",
|
||||
"columns": [
|
||||
{
|
||||
"name": "名称",
|
||||
"width": 6
|
||||
},
|
||||
{
|
||||
"name": "图标",
|
||||
"width": 6
|
||||
},
|
||||
{
|
||||
"name": "路由",
|
||||
"width": 6
|
||||
},
|
||||
{
|
||||
"name": "排列",
|
||||
"width": 6
|
||||
},
|
||||
{
|
||||
"name": "block布局",
|
||||
"width": 6
|
||||
},
|
||||
{
|
||||
"name": "显示",
|
||||
"width": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"actions": {
|
||||
"cancel": {},
|
||||
"save": {
|
||||
"type": "button",
|
||||
"props": {
|
||||
"label": "保存"
|
||||
}
|
||||
},
|
||||
"delete": {}
|
||||
}
|
||||
},
|
||||
"insert": {},
|
||||
"view": {}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue