Merge pull request #405 from trheyi/main

[add] yao.table.Load & yao.form.Load & fix reload
This commit is contained in:
Max 2023-05-11 22:21:39 +08:00 committed by GitHub
commit 1afeb9b2ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 229 additions and 34 deletions

View file

@ -5,6 +5,7 @@ import (
"strings"
"github.com/fatih/color"
"github.com/google/uuid"
jsoniter "github.com/json-iterator/go"
"github.com/spf13/cobra"
"github.com/yaoapp/gou/plugin"
@ -88,7 +89,9 @@ var RunCmd = &cobra.Command{
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}
ctx, err := script.NewContext("", nil)
sid := uuid.New().String()
global := map[string]interface{}{}
ctx, err := script.NewContext(sid, global)
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}

View file

@ -84,12 +84,12 @@ func Load() Config {
}
// Studio Secret
if cfg.Studio.Secret == nil {
if cfg.Studio.Secret == "" {
v, err := crypto.Hash(crypto.HashTypes["SHA256"], uuid.New().String())
if err != nil {
exception.New("Can't gengrate studio secret %s", 500, err.Error()).Throw()
}
cfg.Studio.Secret = []byte(strings.ToUpper(v))
cfg.Studio.Secret = strings.ToUpper(v)
cfg.Studio.Auto = true
}

View file

@ -26,7 +26,7 @@ type Config struct {
// Studio the studio config
type Studio struct {
Port int `json:"studio_port,omitempty" env:"YAO_STUDIO_PORT" envDefault:"5077"` // Studio port
Secret []byte `json:"studio_secret,omitempty" env:"YAO_STUDIO_SECRET"` // Studio Secret, if does not set, auto-generate a secret
Secret string `json:"studio_secret,omitempty" env:"YAO_STUDIO_SECRET"` // Studio Secret, if does not set, auto-generate a secret
Auto bool `json:"-"`
}
@ -52,8 +52,8 @@ type Session struct {
// Runtime Config
type Runtime struct {
MinSize int `json:"minSize,omitempty" env:"YAO_RUNTIME_MIN" envDefault:"2"` // the number of V8 VM when runtime start. max value is 100, the default value is 2
MaxSize int `json:"maxSize,omitempty" env:"YAO_RUNTIME_MAX" envDefault:"5"` // the maximum of V8 VM should be smaller than minSize, the default value is 10
MinSize int `json:"minSize,omitempty" env:"YAO_RUNTIME_MIN" envDefault:"10"` // the number of V8 VM when runtime start. max value is 100, the default value is 2
MaxSize int `json:"maxSize,omitempty" env:"YAO_RUNTIME_MAX" envDefault:"100"` // the maximum of V8 VM should be smaller than minSize, the default value is 10
HeapSizeLimit uint64 `json:"heapSizeLimit,omitempty" env:"YAO_RUNTIME_HEAP_LIMIT" envDefault:"1518338048"` // the isolate heap size limit should be smaller than 1.5G, and the default value is 1518338048 (1.5G)
HeapSizeRelease uint64 `json:"heapSizeRelease,omitempty" env:"YAO_RUNTIME_HEAP_RELEASE" envDefault:"52428800"` // the isolate will be re-created when reaching this value, and the default value is 52428800 (50M)
HeapAvailableSize uint64 `json:"heapAvailableSize,omitempty" env:"YAO_RUNTIME_HEAP_AVAILABLE" envDefault:"524288000"` // the isolate will be re-created when the available size is smaller than this value, and the default value is 524288000 (500M)

View file

@ -34,3 +34,19 @@ func Load(cfg config.Config) error {
}
return nil
}
// Close close connector
func Close() error {
messages := []string{}
for _, conn := range connector.Connectors {
err := conn.Close()
if err != nil {
messages = append(messages, err.Error())
}
}
if len(messages) > 0 {
return fmt.Errorf("%s", strings.Join(messages, ";\n"))
}
return nil
}

View file

@ -197,11 +197,14 @@ func Load(cfg config.Config) (err error) {
func Unload() (err error) {
defer func() { err = exception.Catch(recover()) }()
// Stop Runtime
err = runtime.Stop()
// Close DB
err = share.DBClose()
// Stop Runtime
err = runtime.Stop()
// Close Connectors
err = connector.Close()
// Recycle
// api
@ -226,7 +229,147 @@ func Unload() (err error) {
}
// Reload the application engine
func Reload(cfg config.Config) error {
func Reload(cfg config.Config) (err error) {
defer func() { err = exception.Catch(recover()) }()
exception.Mode = cfg.Mode
// SET XGEN_BASE
adminRoot := "yao"
if share.App.Optional != nil {
if root, has := share.App.Optional["adminRoot"]; has {
adminRoot = fmt.Sprintf("%v", root)
}
}
os.Setenv("XGEN_BASE", adminRoot)
// load the application
err = loadApp(cfg.AppSource)
if err != nil {
printErr(cfg.Mode, "Load Application", err)
}
// Load Certs
err = cert.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Cert", err)
}
// Load FileSystem
err = fs.Load(cfg)
if err != nil {
printErr(cfg.Mode, "FileSystem", err)
}
// Load i18n
err = i18n.Load(cfg)
if err != nil {
printErr(cfg.Mode, "i18n", err)
}
// Load Query Engine
err = query.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Query Engine", err)
}
// Load Scripts
err = script.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Script", err)
}
// Load Models
err = model.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Model", err)
}
// Load Data flows
err = flow.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Flow", err)
}
// Load Stores
err = store.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Store", err)
}
// Load Plugins
err = plugin.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Plugin", err)
}
// Load WASM Application (experimental)
// Load build-in widgets (table / form / chart / ...)
err = widgets.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Widgets", err)
}
// Load Importers
err = importer.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Plugin", err)
}
// Load Apis
err = api.Load(cfg) // 加载业务接口 API
if err != nil {
printErr(cfg.Mode, "API", err)
}
// Load Sockets
err = socket.Load(cfg) // Load sockets
if err != nil {
printErr(cfg.Mode, "Socket", err)
}
// Load websockets (client mode)
err = websocket.Load(cfg)
if err != nil {
printErr(cfg.Mode, "WebSocket", err)
}
// Load tasks
err = task.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Task", err)
}
// Load schedules
err = schedule.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Schedule", err)
}
// Load Custom Widget
err = widget.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Widget", err)
}
// Load AIGC
err = aigc.Load(cfg)
if err != nil {
printErr(cfg.Mode, "AIGC", err)
}
// Load Neo
err = neo.Load(cfg)
if err != nil {
printErr(cfg.Mode, "AIGC", err)
}
return err
}
// Restart the application engine
func Restart(cfg config.Config) error {
err := Unload()
if err != nil {
return err

View file

@ -89,7 +89,7 @@ func hdAuth(c *gin.Context) {
return
}
claims := helper.JwtValidate(tokenString, config.Conf.Studio.Secret)
claims := helper.JwtValidate(tokenString, []byte(config.Conf.Studio.Secret))
c.Set("__sid", claims.SID)
c.Next()
return

View file

@ -236,6 +236,6 @@ func getToken(t *testing.T) string {
1,
map[string]interface{}{"id": 1, "user_id": 1, "user": kv{"id": 1, "name": "test"}},
map[string]interface{}{"issuer": "unit-test", "timeout": 3600},
config.Conf.Studio.Secret,
[]byte(config.Conf.Studio.Secret),
).Token
}

View file

@ -54,29 +54,15 @@ func LoadAndExport(cfg config.Config) error {
// Load the app DSL
func Load(cfg config.Config) error {
// file := filepath.Join(cfg.Root, "app.json")
// file, err := filepath.Abs(file)
// if err != nil {
// return err
// }
file, err := getAppFile()
if err != nil {
return err
}
var data []byte
var err error
var file string
application.App.Walk("", func(root, filename string, isdir bool) error {
if isdir {
return nil
}
data, err = application.App.Read(filename)
if err != nil {
return err
}
file = filename
return nil
}, "app.yao", "app.json", "app.jsonc")
data, err := application.App.Read(file)
if err != nil {
return err
}
if err != nil {
return err
@ -105,6 +91,26 @@ func Load(cfg config.Config) error {
return nil
}
func getAppFile() (string, error) {
file := filepath.Join(string(os.PathSeparator), "app.yao")
if has, _ := application.App.Exists(file); has {
return file, nil
}
file = filepath.Join(string(os.PathSeparator), "app.jsonc")
if has, _ := application.App.Exists(file); has {
return file, nil
}
file = filepath.Join(string(os.PathSeparator), "app.json")
if has, _ := application.App.Exists(file); has {
return file, nil
}
return "", fmt.Errorf("app.yao not found")
}
// exportAPI export login api
func exportAPI() error {

View file

@ -3,6 +3,7 @@ package form
import (
"fmt"
"net/url"
"os"
"strings"
"github.com/yaoapp/gou/fs"
@ -26,6 +27,7 @@ func exportProcess() {
gouProcess.Register("yao.form.create", processCreate)
gouProcess.Register("yao.form.update", processUpdate)
gouProcess.Register("yao.form.delete", processDelete)
gouProcess.Register("yao.form.load", processLoad)
}
func processXgen(process *gouProcess.Process) interface{} {
@ -179,3 +181,15 @@ func processDelete(process *gouProcess.Process) interface{} {
form := MustGet(process)
return form.Action.Delete.MustExec(process)
}
// processLoad yao.table.Load (:file)
func processLoad(process *gouProcess.Process) interface{} {
process.ValidateArgNums(1)
file := process.ArgsString(0)
if file == "" {
exception.New("file is required", 400).Throw()
}
file = strings.TrimPrefix(file, string(os.PathSeparator))
return LoadFile("forms", file)
}

View file

@ -120,7 +120,7 @@ func auth(field string, value string, password string, sid string) maps.Map {
"expires_at": expiresAt,
"sid": sid,
"issuer": "yao",
}, config.Conf.Studio.Secret)
}, []byte(config.Conf.Studio.Secret))
studio["port"] = config.Conf.Studio.Port
studio["token"] = studioToken.Token

View file

@ -43,6 +43,7 @@ func exportProcess() {
gouProcess.Register("yao.table.deletewhere", processDeleteWhere)
gouProcess.Register("yao.table.deletein", processDeleteIn)
gouProcess.Register("yao.table.export", processExport)
gouProcess.Register("yao.table.load", processLoad)
}
func processXgen(process *gouProcess.Process) interface{} {
@ -307,3 +308,15 @@ func processExport(process *gouProcess.Process) interface{} {
return filename
}
// processLoad yao.table.Load (:file)
func processLoad(process *gouProcess.Process) interface{} {
process.ValidateArgNums(1)
file := process.ArgsString(0)
if file == "" {
exception.New("file is required", 400).Throw()
}
file = strings.TrimPrefix(file, string(os.PathSeparator))
return LoadFile("tables", file)
}