[add] app check, setup, service API
This commit is contained in:
parent
2cbd5901a5
commit
a5e260f43f
5 changed files with 207 additions and 10 deletions
|
|
@ -15,7 +15,13 @@ func Load(cfg config.Config) error {
|
||||||
if share.BUILDIN {
|
if share.BUILDIN {
|
||||||
return LoadBuildIn("scripts")
|
return LoadBuildIn("scripts")
|
||||||
}
|
}
|
||||||
return LoadFrom(filepath.Join(cfg.Root, "scripts"))
|
|
||||||
|
err := LoadFrom(filepath.Join(cfg.Root, "scripts"), "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFrom(filepath.Join(cfg.Root, "services"), "__yao_service.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadBuildIn 从制品中读取
|
// LoadBuildIn 从制品中读取
|
||||||
|
|
@ -24,16 +30,17 @@ func LoadBuildIn(dir string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadFrom 从特定目录加载共享库
|
// LoadFrom 从特定目录加载共享库
|
||||||
func LoadFrom(dir string) error {
|
func LoadFrom(dir string, prefix string) error {
|
||||||
|
|
||||||
if share.DirNotExists(dir) {
|
if share.DirNotExists(dir) {
|
||||||
return fmt.Errorf("%s does not exists", dir)
|
log.Error("%s does not exists", dir)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载共享脚本
|
// 加载共享脚本
|
||||||
err := share.Walk(dir, ".js", func(root, filename string) {
|
err := share.Walk(dir, ".js", func(root, filename string) {
|
||||||
name := share.SpecName(root, filename)
|
name := share.SpecName(root, filename)
|
||||||
err := gou.Yao.Load(filename, name)
|
err := gou.Yao.Load(filename, fmt.Sprintf("%s%s", prefix, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("加载脚本失败 %s", err.Error())
|
log.Error("加载脚本失败 %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootLib := path.Join(os.Getenv("YAO_DEV"), "/tests/scripts")
|
rootLib := path.Join(os.Getenv("YAO_DEV"), "/tests/scripts")
|
||||||
LoadFrom(rootLib)
|
LoadFrom(rootLib, "")
|
||||||
}
|
}
|
||||||
func TestScript(t *testing.T) {
|
func TestScript(t *testing.T) {
|
||||||
res, err := gou.Yao.New("time", "hello").Call("world")
|
res, err := gou.Yao.New("time", "hello").Call("world")
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -21,9 +23,12 @@ import (
|
||||||
|
|
||||||
//
|
//
|
||||||
// API:
|
// API:
|
||||||
// GET /api/__yao/app/setting -> Default process: yao.app.Xgen
|
// GET /api/__yao/app/setting -> Default process: yao.app.Xgen
|
||||||
// POST /api/__yao/app/setting -> Default process: yao.app.Xgen {"sid":"xxx", "lang":"zh-hk", "time": "2022-10-10 22:00:10"}
|
// POST /api/__yao/app/setting -> Default process: yao.app.Xgen {"sid":"xxx", "lang":"zh-hk", "time": "2022-10-10 22:00:10"}
|
||||||
// GET /api/__yao/app/menu -> Default process: yao.app.Menu
|
// GET /api/__yao/app/menu -> Default process: yao.app.Menu
|
||||||
|
// POST /api/__yao/app/check -> Default process: yao.app.Check
|
||||||
|
// POST /api/__yao/app/setup -> Default process: yao.app.Setup {"sid":"xxxx", ...}
|
||||||
|
// POST /api/__yao/app/service/:name -> Default process: yao.app.Service {"method":"Bar", "args":["hello", "world"]}
|
||||||
//
|
//
|
||||||
// Process:
|
// Process:
|
||||||
// yao.app.Setting Return the App DSL
|
// yao.app.Setting Return the App DSL
|
||||||
|
|
@ -33,6 +38,7 @@ import (
|
||||||
|
|
||||||
// Setting the application setting
|
// Setting the application setting
|
||||||
var Setting *DSL
|
var Setting *DSL
|
||||||
|
var regExcp = regexp.MustCompile("^Exception\\|([0-9]+):(.+)$")
|
||||||
|
|
||||||
// LoadAndExport load app
|
// LoadAndExport load app
|
||||||
func LoadAndExport(cfg config.Config) error {
|
func LoadAndExport(cfg config.Config) error {
|
||||||
|
|
@ -154,6 +160,42 @@ func exportAPI() error {
|
||||||
}
|
}
|
||||||
http.Paths = append(http.Paths, path)
|
http.Paths = append(http.Paths, path)
|
||||||
|
|
||||||
|
path = gou.Path{
|
||||||
|
Label: "Setup",
|
||||||
|
Description: "Setup",
|
||||||
|
Path: "/setup",
|
||||||
|
Guard: "-",
|
||||||
|
Method: "POST",
|
||||||
|
Process: "yao.app.Setup",
|
||||||
|
In: []string{":payload"},
|
||||||
|
Out: gou.Out{Status: 200, Type: "application/json"},
|
||||||
|
}
|
||||||
|
http.Paths = append(http.Paths, path)
|
||||||
|
|
||||||
|
path = gou.Path{
|
||||||
|
Label: "Check",
|
||||||
|
Description: "Check",
|
||||||
|
Path: "/check",
|
||||||
|
Guard: "-",
|
||||||
|
Method: "POST",
|
||||||
|
Process: "yao.app.Check",
|
||||||
|
In: []string{":payload"},
|
||||||
|
Out: gou.Out{Status: 200, Type: "application/json"},
|
||||||
|
}
|
||||||
|
http.Paths = append(http.Paths, path)
|
||||||
|
|
||||||
|
path = gou.Path{
|
||||||
|
Label: "Serivce",
|
||||||
|
Description: "Serivce",
|
||||||
|
Path: "/service/:name",
|
||||||
|
Guard: "bearer-jwt",
|
||||||
|
Method: "POST",
|
||||||
|
Process: "yao.app.Serivce",
|
||||||
|
In: []string{"$param.name", ":payload"},
|
||||||
|
Out: gou.Out{Status: 200, Type: "application/json"},
|
||||||
|
}
|
||||||
|
http.Paths = append(http.Paths, path)
|
||||||
|
|
||||||
// api source
|
// api source
|
||||||
source, err := jsoniter.Marshal(http)
|
source, err := jsoniter.Marshal(http)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -176,6 +218,95 @@ func exportProcess() {
|
||||||
gou.RegisterProcessHandler("yao.app.xgen", processXgen)
|
gou.RegisterProcessHandler("yao.app.xgen", processXgen)
|
||||||
gou.RegisterProcessHandler("yao.app.menu", processMenu)
|
gou.RegisterProcessHandler("yao.app.menu", processMenu)
|
||||||
gou.RegisterProcessHandler("yao.app.icons", processIcons)
|
gou.RegisterProcessHandler("yao.app.icons", processIcons)
|
||||||
|
gou.RegisterProcessHandler("yao.app.setup", processSetup)
|
||||||
|
gou.RegisterProcessHandler("yao.app.check", processCheck)
|
||||||
|
gou.RegisterProcessHandler("yao.app.service", processService)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processService(process *gou.Process) interface{} {
|
||||||
|
process.ValidateArgNums(2)
|
||||||
|
service := fmt.Sprintf("__yao_service.%s", process.ArgsString(0))
|
||||||
|
payload := process.ArgsMap(1)
|
||||||
|
if payload == nil || len(payload) == 0 {
|
||||||
|
exception.New("content is required", 400).Throw()
|
||||||
|
}
|
||||||
|
|
||||||
|
method, ok := payload["method"].(string)
|
||||||
|
if !ok || service == "" {
|
||||||
|
exception.New("method is required", 400).Throw()
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []interface{}{}
|
||||||
|
if v, ok := payload["args"].([]interface{}); ok {
|
||||||
|
args = v
|
||||||
|
}
|
||||||
|
|
||||||
|
req := gou.Yao.New(service, method)
|
||||||
|
if process.Sid != "" {
|
||||||
|
req.WithSid(process.Sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := req.RootCall(args...)
|
||||||
|
if err != nil {
|
||||||
|
// parse Exception
|
||||||
|
code := 500
|
||||||
|
message := err.Error()
|
||||||
|
match := regExcp.FindStringSubmatch(message)
|
||||||
|
if len(match) > 0 {
|
||||||
|
code, err = strconv.Atoi(match[1])
|
||||||
|
if err == nil {
|
||||||
|
message = strings.TrimSpace(match[2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exception.New(message, code).Throw()
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func processCheck(process *gou.Process) interface{} {
|
||||||
|
process.ValidateArgNums(1)
|
||||||
|
payload := process.ArgsMap(0)
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
if _, has := payload["error"]; has {
|
||||||
|
exception.New("Something error", 500).Throw()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processSetup(process *gou.Process) interface{} {
|
||||||
|
process.ValidateArgNums(1)
|
||||||
|
payload := process.ArgsMap(0)
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
if _, has := payload["error"]; has {
|
||||||
|
exception.New("Something error", 500).Throw()
|
||||||
|
}
|
||||||
|
|
||||||
|
lang := process.Lang()
|
||||||
|
if sid, has := payload["sid"]; has {
|
||||||
|
lang, err := session.Global().ID(sid.(string)).Get("__yao_lang")
|
||||||
|
if err != nil {
|
||||||
|
lang = strings.ToLower(lang.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
root := "yao"
|
||||||
|
if Setting.Optional.AdminRoot != "" {
|
||||||
|
root = Setting.Optional.AdminRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
setting, err := i18n.Trans(lang, "app", "app", Setting)
|
||||||
|
if err != nil {
|
||||||
|
exception.New(err.Error(), 500).Throw()
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{
|
||||||
|
"home": fmt.Sprintf("http://127.0.0.1:%d", config.Conf.Port),
|
||||||
|
"admin": fmt.Sprintf("http://127.0.0.1:%d/%s/", config.Conf.Port, root),
|
||||||
|
"setting": setting,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processIcons(process *gou.Process) interface{} {
|
func processIcons(process *gou.Process) interface{} {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/flow"
|
"github.com/yaoapp/yao/flow"
|
||||||
"github.com/yaoapp/yao/i18n"
|
"github.com/yaoapp/yao/i18n"
|
||||||
|
"github.com/yaoapp/yao/script"
|
||||||
"github.com/yaoapp/yao/widgets/login"
|
"github.com/yaoapp/yao/widgets/login"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -118,7 +119,7 @@ func TestExport(t *testing.T) {
|
||||||
|
|
||||||
api, has := gou.APIs["widgets.app"]
|
api, has := gou.APIs["widgets.app"]
|
||||||
assert.True(t, has)
|
assert.True(t, has)
|
||||||
assert.Equal(t, 4, len(api.HTTP.Paths))
|
assert.Equal(t, 7, len(api.HTTP.Paths))
|
||||||
|
|
||||||
_, has = gou.ThirdHandlers["yao.app.setting"]
|
_, has = gou.ThirdHandlers["yao.app.setting"]
|
||||||
assert.True(t, has)
|
assert.True(t, has)
|
||||||
|
|
@ -128,6 +129,15 @@ func TestExport(t *testing.T) {
|
||||||
|
|
||||||
_, has = gou.ThirdHandlers["yao.app.menu"]
|
_, has = gou.ThirdHandlers["yao.app.menu"]
|
||||||
assert.True(t, has)
|
assert.True(t, has)
|
||||||
|
|
||||||
|
_, has = gou.ThirdHandlers["yao.app.check"]
|
||||||
|
assert.True(t, has)
|
||||||
|
|
||||||
|
_, has = gou.ThirdHandlers["yao.app.setup"]
|
||||||
|
assert.True(t, has)
|
||||||
|
|
||||||
|
_, has = gou.ThirdHandlers["yao.app.service"]
|
||||||
|
assert.True(t, has)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessSetting(t *testing.T) {
|
func TestProcessSetting(t *testing.T) {
|
||||||
|
|
@ -218,9 +228,52 @@ func TestProcessIcons(t *testing.T) {
|
||||||
assert.Greater(t, len(res.(string)), 10)
|
assert.Greater(t, len(res.(string)), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProcessCheck(t *testing.T) {
|
||||||
|
loadApp(t)
|
||||||
|
res, err := gou.NewProcess("yao.app.Check", map[string]interface{}{}).Exec()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Nil(t, res)
|
||||||
|
|
||||||
|
_, err = gou.NewProcess("yao.app.Check", map[string]interface{}{"error": "1"}).Exec()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessSetup(t *testing.T) {
|
||||||
|
loadApp(t)
|
||||||
|
res, err := gou.NewProcess("yao.app.Setup", map[string]interface{}{"sid": "hello"}).Exec()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, "http://127.0.0.1:5099/admin/", res.(map[string]interface{})["admin"])
|
||||||
|
_, err = gou.NewProcess("yao.app.Setup", map[string]interface{}{"error": "1"}).Exec()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessService(t *testing.T) {
|
||||||
|
loadApp(t)
|
||||||
|
res, err := gou.NewProcess(
|
||||||
|
"yao.app.Service",
|
||||||
|
"foo",
|
||||||
|
map[string]interface{}{"method": "Bar", "args": []interface{}{"hello", "world"}},
|
||||||
|
).Exec()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, []interface{}{"hello", "world"}, res)
|
||||||
|
}
|
||||||
|
|
||||||
func loadApp(t *testing.T) {
|
func loadApp(t *testing.T) {
|
||||||
|
|
||||||
err := i18n.Load(config.Conf)
|
err := script.Load(config.Conf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = i18n.Load(config.Conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,3 +28,9 @@ type OptionalDSL struct {
|
||||||
AdminRoot string `json:"adminRoot,omitempty"`
|
AdminRoot string `json:"adminRoot,omitempty"`
|
||||||
Setting string `json:"setting,omitempty"` // custom setting process
|
Setting string `json:"setting,omitempty"` // custom setting process
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CFUN cloud function
|
||||||
|
type CFUN struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Args []interface{} `json:"args,omitempty"`
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue