调整环境变量
This commit is contained in:
parent
f42b0ca02b
commit
ea72f26d5e
57 changed files with 742 additions and 600 deletions
52
.github/workflows/unit-test.yml
vendored
52
.github/workflows/unit-test.yml
vendored
|
|
@ -7,36 +7,50 @@ on:
|
|||
branches: [main]
|
||||
|
||||
env:
|
||||
YAO_DEV: ${{ github.WORKSPACE }}
|
||||
YAO_ENV: development
|
||||
YAO_ROOT: ${{ github.WORKSPACE }}/tests
|
||||
YAO_HOST: 0.0.0.0
|
||||
YAO_PORT: 5099
|
||||
YAO_SESSION: "memory"
|
||||
YAO_LOG: "./logs/application.log"
|
||||
YAO_LOG_MODE: "TEXT"
|
||||
YAO_JWT_SECRET: "bLp@bi!oqo-2U+hoTRUG"
|
||||
YAO_DB_DRIVER: mysql
|
||||
YAO_DB_PRIMARY: "root:123456@tcp(db-server:3308)/xiang?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
YAO_DB_SECONDARY: "root:123456@tcp(db-server:3308)/xiang?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
YAO_DB_AESKEY: "ZLX=T&f6refeCh-ro*r@"
|
||||
|
||||
# 象传服务配置
|
||||
XIANG_MODE: debug
|
||||
XIANG_SOURCE: ${{ github.WORKSPACE }}
|
||||
XIANG_ROOT: ${{ github.WORKSPACE }}/tests
|
||||
XIANG_ROOT_PLUGIN: ${{ github.WORKSPACE }}/../../../data/gou-unit/plugins
|
||||
# XIANG_MODE: debug
|
||||
# XIANG_SOURCE: ${{ github.WORKSPACE }}
|
||||
# XIANG_ROOT: ${{ github.WORKSPACE }}/tests
|
||||
# XIANG_ROOT_PLUGIN: ${{ github.WORKSPACE }}/../../../data/gou-unit/plugins
|
||||
|
||||
# 服务配置
|
||||
XIANG_SERVICE_DEBUG: true
|
||||
XIANG_SERVICE_ALLOW: "xiang.yao.run:3000|xiang.yao.run:3001"
|
||||
XIANG_SERVICE_HOST: 0.0.0.0
|
||||
XIANG_SERVICE_PORT: 5099
|
||||
# XIANG_SERVICE_DEBUG: true
|
||||
# XIANG_SERVICE_ALLOW: "xiang.yao.run:3000|xiang.yao.run:3001"
|
||||
# XIANG_SERVICE_HOST: 0.0.0.0
|
||||
# XIANG_SERVICE_PORT: 5099
|
||||
|
||||
# 数据库配置
|
||||
XIANG_DB_DEBUG: true
|
||||
XIANG_DB_DRIVER: "mysql"
|
||||
XIANG_DB_AESKEY: "ZLX:XzT&f6refeCh-ro*r@"
|
||||
# XIANG_DB_DEBUG: true
|
||||
# XIANG_DB_DRIVER: "mysql"
|
||||
# XIANG_DB_AESKEY: "ZLX:XzT&f6refeCh-ro*r@"
|
||||
|
||||
# JWT配置
|
||||
XIANG_JWT_DEBUG: true
|
||||
XIANG_JWT_SECRET: "bLp@bi!oqo-2U+hoTRUG"
|
||||
# XIANG_JWT_DEBUG: true
|
||||
# XIANG_JWT_SECRET: "bLp@bi!oqo-2U+hoTRUG"
|
||||
|
||||
# 存储配置
|
||||
XIANG_STOR_DEBUG: true
|
||||
XIANG_STOR_PATH: "fs://${{ github.WORKSPACE }}/upload"
|
||||
# XIANG_STOR_DEBUG: true
|
||||
# XIANG_STOR_PATH: "fs://${{ github.WORKSPACE }}/upload"
|
||||
|
||||
# 日志配置
|
||||
XIANG_LOG_ACCESS: "fs://${{ github.WORKSPACE }}/logs/access.log"
|
||||
XIANG_LOG_ERROR: "fs://${{ github.WORKSPACE }}/logs/error.log"
|
||||
XIANG_LOG_DB: "fs://${{ github.WORKSPACE }}/logs/db.log"
|
||||
XIANG_LOG_PLUGIN: "fs://${{ github.WORKSPACE }}/logs/plugin.log"
|
||||
# XIANG_LOG_ACCESS: "fs://${{ github.WORKSPACE }}/logs/access.log"
|
||||
# XIANG_LOG_ERROR: "fs://${{ github.WORKSPACE }}/logs/error.log"
|
||||
# XIANG_LOG_DB: "fs://${{ github.WORKSPACE }}/logs/db.log"
|
||||
# XIANG_LOG_PLUGIN: "fs://${{ github.WORKSPACE }}/logs/plugin.log"
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -22,3 +22,4 @@ ui
|
|||
tests/data/*/*
|
||||
debug.log
|
||||
yao-test
|
||||
dev.sh
|
||||
|
|
|
|||
30
api/api.go
30
api/api.go
|
|
@ -1,26 +1,40 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Load 加载API
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootAPI, "")
|
||||
func Load(cfg config.Config) error {
|
||||
if share.BUILDIN {
|
||||
return LoadBuildIn("apis", "")
|
||||
}
|
||||
return LoadFrom(filepath.Join(cfg.Root, "apis"), "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".http.json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".http.json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
gou.LoadAPI(string(content), name)
|
||||
_, err := gou.LoadAPIReturn(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadBuildIn 从制品中读取
|
||||
func LoadBuildIn(dir string, prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
73
app/app.go
73
app/app.go
|
|
@ -1,10 +1,6 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
|
|
@ -12,7 +8,6 @@ import (
|
|||
"github.com/yaoapp/xiang/data"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
"github.com/yaoapp/xiang/xfs"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
)
|
||||
|
||||
// Load 加载应用信息
|
||||
|
|
@ -24,44 +19,44 @@ func Load(cfg config.Config) {
|
|||
// Init 应用初始化
|
||||
func Init(cfg config.Config) {
|
||||
|
||||
// UI文件目录
|
||||
if _, err := os.Stat(cfg.RootUI); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(cfg.RootUI, os.ModePerm)
|
||||
if err != nil {
|
||||
xlog.Printf("创建目录失败(%s) %s", cfg.RootUI, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// // UI文件目录
|
||||
// if _, err := os.Stat(cfg.RootUI); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(cfg.RootUI, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootUI, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
content, err := data.Asset("xiang/data/index.html")
|
||||
if err != nil {
|
||||
xlog.Printf("读取文件失败(%s) %s", cfg.RootUI, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// content, err := data.Asset("xiang/data/index.html")
|
||||
// if err != nil {
|
||||
// xlog.Printf("读取文件失败(%s) %s", cfg.RootUI, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(cfg.RootUI, "/index.html"), content, os.ModePerm)
|
||||
if err != nil {
|
||||
xlog.Printf("复制默认文件失败(%s) %s", cfg.RootUI, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
// err = ioutil.WriteFile(filepath.Join(cfg.RootUI, "/index.html"), content, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("复制默认文件失败(%s) %s", cfg.RootUI, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 数据库目录
|
||||
if _, err := os.Stat(cfg.RootDB); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(cfg.RootDB, os.ModePerm)
|
||||
if err != nil {
|
||||
xlog.Printf("创建目录失败(%s) %s", cfg.RootDB, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
// // 数据库目录
|
||||
// if _, err := os.Stat(cfg.RootDB); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(cfg.RootDB, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootDB, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 文件数据目录
|
||||
if _, err := os.Stat(cfg.RootData); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(cfg.RootData, os.ModePerm)
|
||||
if err != nil {
|
||||
xlog.Printf("创建目录失败(%s) %s", cfg.RootData, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
// // 文件数据目录
|
||||
// if _, err := os.Stat(cfg.RootData); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(cfg.RootData, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootData, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// LoadInfo 应用信息
|
||||
|
|
|
|||
|
|
@ -2,41 +2,54 @@ package chart
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
)
|
||||
|
||||
// Charts 已载入图表
|
||||
var Charts = map[string]*Chart{}
|
||||
|
||||
// Load 加载数据表格
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootChart, "")
|
||||
func Load(cfg config.Config) error {
|
||||
if share.BUILDIN {
|
||||
return LoadBuildIn("charts", "")
|
||||
}
|
||||
return LoadFrom(filepath.Join(cfg.Root, "charts"), "")
|
||||
}
|
||||
|
||||
// LoadBuildIn 从制品中读取
|
||||
func LoadBuildIn(dir string, prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := LoadChart(content, name)
|
||||
if err != nil {
|
||||
exception.New("%s 图表格式错误", 400, name).Ctx(filename).Throw()
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load Script
|
||||
share.Walk(dir, ".js", func(root, filename string) {
|
||||
err = share.Walk(dir, ".js", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
chart := Select(name)
|
||||
if chart != nil {
|
||||
|
|
@ -45,6 +58,8 @@ func LoadFrom(dir string, prefix string) {
|
|||
chart.LoadScript(string(content), script)
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadChart 载入数据表格
|
||||
|
|
@ -56,9 +71,7 @@ func LoadChart(source []byte, name string) (*Chart, error) {
|
|||
}
|
||||
err := jsoniter.Unmarshal(source, chart)
|
||||
if err != nil {
|
||||
xlog.Println(name)
|
||||
xlog.Println(err.Error())
|
||||
xlog.Println(string(source))
|
||||
log.With(log.F{"name": name, "source": source}).Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
chart.Prepare()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
Load(config.Conf)
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
var domainCmd = &cobra.Command{
|
||||
Use: "domain",
|
||||
Short: "显示绑定域名",
|
||||
Long: `显示绑定域名`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// Do Stuff Here
|
||||
fmt.Println(share.DOMAIN)
|
||||
},
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@ var inspectCmd = &cobra.Command{
|
|||
Boot()
|
||||
res := maps.Map{
|
||||
"version": share.VERSION,
|
||||
"domain": share.DOMAIN,
|
||||
"config": config.Conf,
|
||||
}
|
||||
utils.Dump(res)
|
||||
|
|
|
|||
15
cmd/root.go
15
cmd/root.go
|
|
@ -30,11 +30,9 @@ var rootCmd = &cobra.Command{
|
|||
func init() {
|
||||
rootCmd.AddCommand(
|
||||
versionCmd,
|
||||
// domainCmd,
|
||||
migrateCmd,
|
||||
inspectCmd,
|
||||
startCmd,
|
||||
// importCmd,
|
||||
runCmd,
|
||||
)
|
||||
rootCmd.SetHelpCommand(helpCmd)
|
||||
|
|
@ -54,15 +52,18 @@ func Execute() {
|
|||
func Boot() {
|
||||
|
||||
if envFile == "" && appPath != "" {
|
||||
config.SetAppPath(appPath, filepath.Join(appPath, ".env"))
|
||||
config.Conf = config.LoadFrom(filepath.Join(appPath, ".env"))
|
||||
config.Conf.Root = appPath
|
||||
return
|
||||
}
|
||||
|
||||
if envFile != "" { // 指定环境变量文件
|
||||
config.SetEnvFile(envFile)
|
||||
if envFile != "" && appPath == "" { // 指定环境变量文件
|
||||
// config.SetEnvFile(envFile)
|
||||
config.Conf = config.LoadFrom(envFile)
|
||||
}
|
||||
|
||||
if appPath != "" {
|
||||
config.SetAppPath(appPath)
|
||||
if envFile != "" && appPath != "" {
|
||||
config.Conf = config.LoadFrom(envFile)
|
||||
config.Conf.Root = appPath
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ var runCmd = &cobra.Command{
|
|||
defer gou.KillPlugins()
|
||||
Boot()
|
||||
cfg := config.Conf
|
||||
cfg.Session.IsCLI = true
|
||||
// cfg.Session.IsCLI = true
|
||||
engine.Load(cfg)
|
||||
if len(args) < 1 {
|
||||
fmt.Println(color.RedString("参数错误: 未指定处理名称"))
|
||||
|
|
|
|||
10
cmd/start.go
10
cmd/start.go
|
|
@ -36,7 +36,6 @@ var startCmd = &cobra.Command{
|
|||
fmt.Printf(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Printf(color.GreenString("\n应用名称: %s v%s", share.App.Name, share.App.Version))
|
||||
fmt.Printf(color.GreenString("\n应用根目录: %s", config.Conf.Root))
|
||||
fmt.Printf(color.GreenString("\n数据存储目录: %s", config.Conf.RootData))
|
||||
fmt.Printf(color.GreenString("\n数据存储引擎: %s", share.App.Storage.Default))
|
||||
fmt.Printf(color.WhiteString("\n---------------------------------\n\n"))
|
||||
|
||||
|
|
@ -58,12 +57,7 @@ var startCmd = &cobra.Command{
|
|||
|
||||
}
|
||||
|
||||
domain := share.DOMAIN
|
||||
if domain == "*.iqka.com" {
|
||||
domain = "local.iqka.com"
|
||||
}
|
||||
|
||||
port := fmt.Sprintf(":%d", config.Conf.Service.Port)
|
||||
port := fmt.Sprintf(":%d", config.Conf.Port)
|
||||
if port == ":80" {
|
||||
port = ""
|
||||
}
|
||||
|
|
@ -73,7 +67,7 @@ var startCmd = &cobra.Command{
|
|||
fmt.Printf(color.GreenString("\n前台界面: http://%s%s/\n", "127.0.0.1", port))
|
||||
fmt.Printf(color.GreenString("管理后台: http://%s%s/xiang/login/admin\n", "127.0.0.1", port))
|
||||
fmt.Printf(color.GreenString("API 接口: http://%s%s/api\n", "127.0.0.1", port))
|
||||
fmt.Printf(color.GreenString("跨域访问: %s\n\n", strings.Join(config.Conf.Service.Allow, ",")))
|
||||
// fmt.Printf(color.GreenString("跨域访问: %s\n\n", strings.Join(config.Conf.Service.Allow, ",")))
|
||||
|
||||
// 调试模式
|
||||
if config.Conf.Mode == "debug" {
|
||||
|
|
|
|||
452
config/config.go
452
config/config.go
|
|
@ -1,64 +1,110 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/kun/log"
|
||||
|
||||
"github.com/caarlos0/env/v6"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/yaoapp/gou/helper"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
)
|
||||
|
||||
// Conf 配置参数
|
||||
var Conf Config
|
||||
|
||||
// Config 系统配置
|
||||
type Config struct {
|
||||
XiangConfig
|
||||
Service ServiceConfig `json:"service,omitempty"`
|
||||
Session SessionConfig `json:"session,omitempty"`
|
||||
Database DatabaseConfig `json:"database,omitempty"`
|
||||
JWT JWTConfig `json:"jwt,omitempty"`
|
||||
Log LogConfig `json:"log,omitempty"`
|
||||
func init() {
|
||||
filename, _ := filepath.Abs(filepath.Join(".", ".env"))
|
||||
if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
|
||||
Conf = Load()
|
||||
return
|
||||
}
|
||||
Conf = LoadFrom(filename)
|
||||
}
|
||||
|
||||
// XiangConfig 象传应用引擎配置
|
||||
type XiangConfig struct {
|
||||
Mode string `json:"mode,omitempty" env:"XIANG_MODE" envDefault:"release"` // 象传引擎模式 debug/release/test
|
||||
Source string `json:"source,omitempty" env:"XIANG_SOURCE" envDefault:"fs://."` // 源码路径(用于单元测试载入数据)
|
||||
Path string `json:"path,omitempty" env:"XIANG_PATH" envDefault:"bin://xiang"` // 引擎文件目录
|
||||
Root string `json:"root,omitempty" env:"XIANG_ROOT" envDefault:"fs://."` // 应用文件目录
|
||||
RootUI string `json:"root_ui,omitempty" env:"XIANG_ROOT_UI"` // 应用界面静态文件目录
|
||||
RootDB string `json:"root_db,omitempty" env:"XIANG_ROOT_DB"` // 应用SQLite数据库目录
|
||||
RootData string `json:"root_data,omitempty" env:"XIANG_ROOT_DATA"` // 应用数据文件目录
|
||||
RootAPI string `json:"root_api,omitempty" env:"XIANG_ROOT_API"` // 应用API文件目录
|
||||
RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录
|
||||
RootFLow string `json:"root_flow,omitempty" env:"XIANG_ROOT_FLOW"` // 应用业务逻辑文件目录
|
||||
RootPlugin string `json:"root_plugin,omitempty" env:"XIANG_ROOT_PLUGIN"` // 应用业务插件文件目录
|
||||
RootLib string `json:"root_lib,omitempty" env:"XIANG_ROOT_LIB"` // 应用资料库文件目录
|
||||
RootTable string `json:"root_table,omitempty" env:"XIANG_ROOT_TABLE"` // 应用数据表格文件目录
|
||||
RootChart string `json:"root_chart,omitempty" env:"XIANG_ROOT_CHART"` // 应用分析图表文件目录
|
||||
RootPage string `json:"root_page,omitempty" env:"XIANG_ROOT_PAGE"` // 应用通用页面文件目录
|
||||
RootScreen string `json:"root_screen,omitempty" env:"XIANG_ROOT_SCREEN"` // 应用大屏文件目录
|
||||
RootForm string `json:"root_form,omitempty" env:"XIANG_ROOT_FORM"` // 表单文件目录
|
||||
RootWorkFlow string `json:"root_workflow,omitempty" env:"XIANG_ROOT_WORKFLOW"` // 工作流文件目录
|
||||
// LoadFrom 从配置项中加载
|
||||
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())
|
||||
}
|
||||
|
||||
return Load()
|
||||
}
|
||||
|
||||
// ServiceConfig 服务配置
|
||||
type ServiceConfig struct {
|
||||
Debug bool `json:"debug,omitempty" env:"XIANG_SERVICE_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
HTTPS bool `json:"https,omitempty" env:"XIANG_SERVICE_HTTPS" envDefault:"false"` // HTTPS 开关
|
||||
Cert string `json:"cert,omitempty" env:"XIANG_SERVICE_CERT"` // HTTPS 证书
|
||||
Key string `json:"key,omitempty" env:"XIANG_SERVICE_KEY"` // HTTPS 证书密钥
|
||||
Allow []string `json:"allow,omitempty" env:"XIANG_SERVICE_ALLOW" envSeparator:"|"` // 跨域访问域名列表
|
||||
Host string `json:"host,omitempty" env:"XIANG_SERVICE_HOST" envDefault:"127.0.0.1"` // 服务监听IP
|
||||
Port int `json:"port,omitempty" env:"XIANG_SERVICE_PORT" envDefault:"5099"` // 服务监听端口
|
||||
// Load 加载配置
|
||||
func Load() Config {
|
||||
cfg := Config{}
|
||||
if err := env.Parse(&cfg); err != nil {
|
||||
exception.New("Can't read config %s", 500, err.Error()).Throw()
|
||||
}
|
||||
cfg.Root, _ = filepath.Abs(cfg.Root)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// // Config 系统配置
|
||||
// type Config struct {
|
||||
// XiangConfig
|
||||
// Service ServiceConfig `json:"service,omitempty"`
|
||||
// Session SessionConfig `json:"session,omitempty"`
|
||||
// Database DatabaseConfig `json:"database,omitempty"`
|
||||
// JWT JWTConfig `json:"jwt,omitempty"`
|
||||
// Log LogConfig `json:"log,omitempty"`
|
||||
// }
|
||||
|
||||
// // JWTConfig JWT配置
|
||||
// type JWTConfig struct {
|
||||
// Secret string `json:"secret,omitempty" env:"YAO_JWT_SECRET"` // JWT 密钥
|
||||
// }
|
||||
|
||||
// // LogConfig 日志配置
|
||||
// type LogConfig struct {
|
||||
// Access string `json:"access,omitempty" env:"XIANG_LOG_ACCESS" envDefault:"os://stdout"` // 服务访问日志
|
||||
// Error string `json:"error,omitempty" env:"XIANG_LOG_ERROR" envDefault:"os://stderr"` // 服务错误日志
|
||||
// DB string `json:"database,omitempty" env:"XIANG_LOG_DB" envDefault:"os://stdout"` // 数据库日志
|
||||
// Plugin string `json:"plugin,omitempty" env:"XIANG_LOG_PLUGIN" envDefault:"os://stdout"` // 插件日志
|
||||
// }
|
||||
|
||||
// // XiangConfig 象传应用引擎配置
|
||||
// type XiangConfig struct {
|
||||
// Mode string `json:"mode,omitempty" env:"XIANG_MODE" envDefault:"release"` // 象传引擎模式 debug/release/test
|
||||
// Source string `json:"source,omitempty" env:"XIANG_SOURCE" envDefault:"fs://."` // 源码路径(用于单元测试载入数据)
|
||||
// Path string `json:"path,omitempty" env:"XIANG_PATH" envDefault:"bin://xiang"` // 引擎文件目录
|
||||
// Root string `json:"root,omitempty" env:"XIANG_ROOT" envDefault:"fs://."` // 应用文件目录
|
||||
// RootUI string `json:"root_ui,omitempty" env:"XIANG_ROOT_UI"` // 应用界面静态文件目录
|
||||
// RootDB string `json:"root_db,omitempty" env:"XIANG_ROOT_DB"` // 应用SQLite数据库目录
|
||||
// RootData string `json:"root_data,omitempty" env:"XIANG_ROOT_DATA"` // 应用数据文件目录
|
||||
// RootAPI string `json:"root_api,omitempty" env:"XIANG_ROOT_API"` // 应用API文件目录
|
||||
// RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录
|
||||
// RootFLow string `json:"root_flow,omitempty" env:"XIANG_ROOT_FLOW"` // 应用业务逻辑文件目录
|
||||
// RootPlugin string `json:"root_plugin,omitempty" env:"XIANG_ROOT_PLUGIN"` // 应用业务插件文件目录
|
||||
// RootLib string `json:"root_lib,omitempty" env:"XIANG_ROOT_LIB"` // 应用资料库文件目录
|
||||
// RootTable string `json:"root_table,omitempty" env:"XIANG_ROOT_TABLE"` // 应用数据表格文件目录
|
||||
// RootChart string `json:"root_chart,omitempty" env:"XIANG_ROOT_CHART"` // 应用分析图表文件目录
|
||||
// RootPage string `json:"root_page,omitempty" env:"XIANG_ROOT_PAGE"` // 应用通用页面文件目录
|
||||
// RootScreen string `json:"root_screen,omitempty" env:"XIANG_ROOT_SCREEN"` // 应用大屏文件目录
|
||||
// RootForm string `json:"root_form,omitempty" env:"XIANG_ROOT_FORM"` // 表单文件目录
|
||||
// RootWorkFlow string `json:"root_workflow,omitempty" env:"XIANG_ROOT_WORKFLOW"` // 工作流文件目录
|
||||
// }
|
||||
|
||||
// // ServiceConfig 服务配置
|
||||
// type ServiceConfig struct {
|
||||
// Debug bool `json:"debug,omitempty" env:"XIANG_SERVICE_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
// HTTPS bool `json:"https,omitempty" env:"XIANG_SERVICE_HTTPS" envDefault:"false"` // HTTPS 开关
|
||||
// Cert string `json:"cert,omitempty" env:"XIANG_SERVICE_CERT"` // HTTPS 证书
|
||||
// Key string `json:"key,omitempty" env:"XIANG_SERVICE_KEY"` // HTTPS 证书密钥
|
||||
// Allow []string `json:"allow,omitempty" env:"XIANG_SERVICE_ALLOW" envSeparator:"|"` // 跨域访问域名列表
|
||||
// Host string `json:"host,omitempty" env:"XIANG_SERVICE_HOST" envDefault:"127.0.0.1"` // 服务监听IP
|
||||
// Port int `json:"port,omitempty" env:"XIANG_SERVICE_PORT" envDefault:"5099"` // 服务监听端口
|
||||
// }
|
||||
|
||||
// SessionConfig 会话服务器
|
||||
type SessionConfig struct {
|
||||
Debug bool `json:"debug,omitempty" env:"XIANG_SESSION_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
|
|
@ -68,204 +114,186 @@ type SessionConfig struct {
|
|||
Port int `json:"port,omitempty" env:"XIANG_SESSION_PORT" envDefault:"3322"` // 会话服务器端口
|
||||
}
|
||||
|
||||
// DatabaseConfig 数据库配置
|
||||
type DatabaseConfig struct {
|
||||
Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
Driver string `json:"driver,omitempty" env:"XIANG_DB_DRIVER" envDefault:"sqlite3"` // 数据库驱动 ( sqlite3, mysql, postgres)
|
||||
Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|" envDefault:"file:./db/xiang.db"` // 主库连接DSN
|
||||
Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN
|
||||
AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY
|
||||
}
|
||||
// // DatabaseConfig 数据库配置
|
||||
// type DatabaseConfig struct {
|
||||
// Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
// Driver string `json:"driver,omitempty" env:"XIANG_DB_DRIVER" envDefault:"sqlite3"` // 数据库驱动 ( sqlite3, mysql, postgres)
|
||||
// Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|" envDefault:"file:./db/xiang.db"` // 主库连接DSN
|
||||
// Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN
|
||||
// AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY
|
||||
// }
|
||||
|
||||
// JWTConfig JWT配置
|
||||
type JWTConfig struct {
|
||||
Debug bool `json:"debug,omitempty" env:"XIANG_JWT_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
Secret string `json:"secret,omitempty" env:"XIANG_JWT_SECRET"` // JWT 密钥
|
||||
}
|
||||
// // NewConfig 创建配置文件
|
||||
// func NewConfig(envfile ...string) Config {
|
||||
|
||||
// LogConfig 日志配置
|
||||
type LogConfig struct {
|
||||
Access string `json:"access,omitempty" env:"XIANG_LOG_ACCESS" envDefault:"os://stdout"` // 服务访问日志
|
||||
Error string `json:"error,omitempty" env:"XIANG_LOG_ERROR" envDefault:"os://stderr"` // 服务错误日志
|
||||
DB string `json:"database,omitempty" env:"XIANG_LOG_DB" envDefault:"os://stdout"` // 数据库日志
|
||||
Plugin string `json:"plugin,omitempty" env:"XIANG_LOG_PLUGIN" envDefault:"os://stdout"` // 插件日志
|
||||
}
|
||||
// filename := os.Getenv("XIANG_ENV_FILE")
|
||||
// if filename == "" {
|
||||
// filename = ".env"
|
||||
// }
|
||||
|
||||
// NewConfig 创建配置文件
|
||||
func NewConfig(envfile ...string) Config {
|
||||
// if len(envfile) > 0 {
|
||||
// file, err := filepath.Abs(envfile[0])
|
||||
// if err == nil {
|
||||
// // log.Printf("加载环境配置文件%s出错 %s\n", envfile[0], err.Error())
|
||||
// // } else {
|
||||
// filename = file
|
||||
// }
|
||||
// }
|
||||
|
||||
filename := os.Getenv("XIANG_ENV_FILE")
|
||||
if filename == "" {
|
||||
filename = ".env"
|
||||
}
|
||||
// godotenv.Overload(filename)
|
||||
// // if err != nil {
|
||||
// // log.Printf("加载环境配置文件%s出错 %s\n", filename, err.Error())
|
||||
// // }
|
||||
|
||||
if len(envfile) > 0 {
|
||||
file, err := filepath.Abs(envfile[0])
|
||||
if err == nil {
|
||||
// log.Printf("加载环境配置文件%s出错 %s\n", envfile[0], err.Error())
|
||||
// } else {
|
||||
filename = file
|
||||
}
|
||||
}
|
||||
// cfg := Config{}
|
||||
// if err := env.Parse(&cfg); err != nil {
|
||||
// exception.New("解析配置文件出错 %s", 500, err.Error()).Throw()
|
||||
// }
|
||||
|
||||
godotenv.Overload(filename)
|
||||
// if err != nil {
|
||||
// log.Printf("加载环境配置文件%s出错 %s\n", filename, err.Error())
|
||||
// }
|
||||
// cfg.SetDefaults()
|
||||
// return cfg
|
||||
// }
|
||||
|
||||
cfg := Config{}
|
||||
if err := env.Parse(&cfg); err != nil {
|
||||
exception.New("解析配置文件出错 %s", 500, err.Error()).Throw()
|
||||
}
|
||||
// // NewConfigFrom 创建配置文件
|
||||
// func NewConfigFrom(input io.Reader) Config {
|
||||
// cfg := Config{}
|
||||
// err := helper.UnmarshalFile(input, &cfg)
|
||||
// if err != nil {
|
||||
// exception.New("解析配置文件出错 %s", 500, err.Error()).Throw()
|
||||
// }
|
||||
// cfg.SetDefaults()
|
||||
// return cfg
|
||||
// }
|
||||
|
||||
cfg.SetDefaults()
|
||||
return cfg
|
||||
}
|
||||
// // SetDefaults 设定默认值
|
||||
// func (cfg *Config) SetDefaults() {
|
||||
|
||||
// NewConfigFrom 创建配置文件
|
||||
func NewConfigFrom(input io.Reader) Config {
|
||||
cfg := Config{}
|
||||
err := helper.UnmarshalFile(input, &cfg)
|
||||
if err != nil {
|
||||
exception.New("解析配置文件出错 %s", 500, err.Error()).Throw()
|
||||
}
|
||||
cfg.SetDefaults()
|
||||
return cfg
|
||||
}
|
||||
// pwd, err := os.Getwd()
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// }
|
||||
|
||||
// SetDefaults 设定默认值
|
||||
func (cfg *Config) SetDefaults() {
|
||||
// if cfg.Root == "fs://." || cfg.Root == "." {
|
||||
// cfg.Root = pwd
|
||||
// }
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// if cfg.RootAPI == "" {
|
||||
// cfg.RootAPI = cfg.Root + "/apis"
|
||||
// }
|
||||
// if cfg.RootFLow == "" {
|
||||
// cfg.RootFLow = cfg.Root + "/flows"
|
||||
// }
|
||||
// if cfg.RootModel == "" {
|
||||
// cfg.RootModel = cfg.Root + "/models"
|
||||
// }
|
||||
// if cfg.RootPlugin == "" {
|
||||
// cfg.RootPlugin = cfg.Root + "/plugins"
|
||||
// }
|
||||
|
||||
if cfg.Root == "fs://." || cfg.Root == "." {
|
||||
cfg.Root = pwd
|
||||
}
|
||||
// if cfg.RootTable == "" {
|
||||
// cfg.RootTable = cfg.Root + "/tables"
|
||||
// }
|
||||
|
||||
if cfg.RootAPI == "" {
|
||||
cfg.RootAPI = cfg.Root + "/apis"
|
||||
}
|
||||
if cfg.RootFLow == "" {
|
||||
cfg.RootFLow = cfg.Root + "/flows"
|
||||
}
|
||||
if cfg.RootModel == "" {
|
||||
cfg.RootModel = cfg.Root + "/models"
|
||||
}
|
||||
if cfg.RootPlugin == "" {
|
||||
cfg.RootPlugin = cfg.Root + "/plugins"
|
||||
}
|
||||
// if cfg.RootLib == "" {
|
||||
// cfg.RootLib = cfg.Root + "/libs"
|
||||
// }
|
||||
|
||||
if cfg.RootTable == "" {
|
||||
cfg.RootTable = cfg.Root + "/tables"
|
||||
}
|
||||
// if cfg.RootChart == "" {
|
||||
// cfg.RootChart = cfg.Root + "/charts"
|
||||
// }
|
||||
|
||||
if cfg.RootLib == "" {
|
||||
cfg.RootLib = cfg.Root + "/libs"
|
||||
}
|
||||
// if cfg.RootPage == "" {
|
||||
// cfg.RootPage = cfg.Root + "/pages"
|
||||
// }
|
||||
|
||||
if cfg.RootChart == "" {
|
||||
cfg.RootChart = cfg.Root + "/charts"
|
||||
}
|
||||
// if cfg.RootWorkFlow == "" {
|
||||
// cfg.RootWorkFlow = cfg.Root + "/workflows"
|
||||
// }
|
||||
|
||||
if cfg.RootPage == "" {
|
||||
cfg.RootPage = cfg.Root + "/pages"
|
||||
}
|
||||
// if cfg.RootData == "" {
|
||||
// cfg.RootData = cfg.Root + "/data"
|
||||
// }
|
||||
|
||||
if cfg.RootWorkFlow == "" {
|
||||
cfg.RootWorkFlow = cfg.Root + "/workflows"
|
||||
}
|
||||
// if cfg.RootDB == "" {
|
||||
// cfg.RootDB = cfg.Root + "/db"
|
||||
// }
|
||||
|
||||
if cfg.RootData == "" {
|
||||
cfg.RootData = cfg.Root + "/data"
|
||||
}
|
||||
// if cfg.RootUI == "" {
|
||||
// cfg.RootUI = cfg.Root + "/ui"
|
||||
// }
|
||||
|
||||
if cfg.RootDB == "" {
|
||||
cfg.RootDB = cfg.Root + "/db"
|
||||
}
|
||||
// if len(cfg.Database.Primary) > 0 {
|
||||
// if strings.HasPrefix(cfg.Database.Primary[0], "file:.") {
|
||||
// cfg.Database.Primary[0] = strings.ReplaceAll(cfg.Database.Primary[0], "file:.", pwd)
|
||||
// } else if strings.HasPrefix(cfg.Database.Primary[0], "file:/") {
|
||||
// cfg.Database.Primary[0] = strings.ReplaceAll(cfg.Database.Primary[0], "file:.", cfg.RootDB)
|
||||
// }
|
||||
// }
|
||||
|
||||
if cfg.RootUI == "" {
|
||||
cfg.RootUI = cfg.Root + "/ui"
|
||||
}
|
||||
// // 过滤数据
|
||||
// cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "fs://")
|
||||
// cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "file://")
|
||||
// cfg.RootData = strings.TrimPrefix(cfg.RootData, "fs://")
|
||||
// cfg.RootData = strings.TrimPrefix(cfg.RootData, "file://")
|
||||
// cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "fs://")
|
||||
// cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "file://")
|
||||
// cfg.RootLib = strings.TrimPrefix(cfg.RootLib, "fs://")
|
||||
// cfg.RootLib = strings.TrimPrefix(cfg.RootLib, "file://")
|
||||
|
||||
if len(cfg.Database.Primary) > 0 {
|
||||
if strings.HasPrefix(cfg.Database.Primary[0], "file:.") {
|
||||
cfg.Database.Primary[0] = strings.ReplaceAll(cfg.Database.Primary[0], "file:.", pwd)
|
||||
} else if strings.HasPrefix(cfg.Database.Primary[0], "file:/") {
|
||||
cfg.Database.Primary[0] = strings.ReplaceAll(cfg.Database.Primary[0], "file:.", cfg.RootDB)
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
// 过滤数据
|
||||
cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "fs://")
|
||||
cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "file://")
|
||||
cfg.RootData = strings.TrimPrefix(cfg.RootData, "fs://")
|
||||
cfg.RootData = strings.TrimPrefix(cfg.RootData, "file://")
|
||||
cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "fs://")
|
||||
cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "file://")
|
||||
cfg.RootLib = strings.TrimPrefix(cfg.RootLib, "fs://")
|
||||
cfg.RootLib = strings.TrimPrefix(cfg.RootLib, "file://")
|
||||
// // SetEnvFile 指定ENV文件
|
||||
// func SetEnvFile(filename string) {
|
||||
// Conf = NewConfig(filename)
|
||||
// }
|
||||
|
||||
}
|
||||
// // SetAppPath 设定应用目录
|
||||
// func SetAppPath(root string, envfile ...string) {
|
||||
|
||||
// SetEnvFile 指定ENV文件
|
||||
func SetEnvFile(filename string) {
|
||||
Conf = NewConfig(filename)
|
||||
}
|
||||
// fullpath, err := filepath.Abs(root)
|
||||
// if err != nil {
|
||||
// log.Panic("设定应用目录%s出错 %s\n", root, err.Error())
|
||||
// }
|
||||
|
||||
// SetAppPath 设定应用目录
|
||||
func SetAppPath(root string, envfile ...string) {
|
||||
// // 创建应用目录
|
||||
// pathinfo, err := os.Stat(fullpath)
|
||||
// if os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(fullpath, os.ModePerm)
|
||||
// if err != nil {
|
||||
// log.Panic("创建目录失败(%s) %s", root, err)
|
||||
// }
|
||||
// }
|
||||
// pathinfo, err = os.Stat(fullpath)
|
||||
// if !pathinfo.IsDir() {
|
||||
// log.Panic("检查应用目录失败(%s) ", err)
|
||||
// }
|
||||
|
||||
fullpath, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
log.Panicf("设定应用目录%s出错 %s\n", root, err.Error())
|
||||
}
|
||||
// if !pathinfo.IsDir() {
|
||||
// log.Panic("应用目录不是文件夹(%s) ", root)
|
||||
// }
|
||||
|
||||
// 创建应用目录
|
||||
pathinfo, err := os.Stat(fullpath)
|
||||
if os.IsNotExist(err) {
|
||||
err := os.MkdirAll(fullpath, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Panicf("创建目录失败(%s) %s", root, err)
|
||||
}
|
||||
}
|
||||
pathinfo, err = os.Stat(fullpath)
|
||||
if !pathinfo.IsDir() {
|
||||
log.Panicf("检查应用目录失败(%s) ", err)
|
||||
}
|
||||
// // Set ENV
|
||||
// if len(envfile) > 0 {
|
||||
// Conf = NewConfig(envfile[0])
|
||||
// }
|
||||
|
||||
if !pathinfo.IsDir() {
|
||||
log.Panicf("应用目录不是文件夹(%s) ", root)
|
||||
}
|
||||
// // 从加载配置文件
|
||||
// Conf.Root = fullpath
|
||||
// Conf.RootAPI = filepath.Join(fullpath, "/apis")
|
||||
// Conf.RootFLow = filepath.Join(fullpath, "/flows")
|
||||
// Conf.RootModel = filepath.Join(fullpath, "/models")
|
||||
// Conf.RootPlugin = filepath.Join(fullpath, "/plugins")
|
||||
// Conf.RootTable = filepath.Join(fullpath, "/tables")
|
||||
// Conf.RootChart = filepath.Join(fullpath, "/charts")
|
||||
// Conf.RootPage = filepath.Join(fullpath, "/pages")
|
||||
// Conf.RootWorkFlow = filepath.Join(fullpath, "/workflows")
|
||||
// Conf.RootData = filepath.Join(fullpath, "/data")
|
||||
// Conf.RootUI = filepath.Join(fullpath, "/ui")
|
||||
// Conf.RootDB = filepath.Join(fullpath, "/db")
|
||||
// Conf.RootLib = filepath.Join(fullpath, "/libs")
|
||||
// }
|
||||
|
||||
// Set ENV
|
||||
if len(envfile) > 0 {
|
||||
Conf = NewConfig(envfile[0])
|
||||
}
|
||||
|
||||
// 从加载配置文件
|
||||
Conf.Root = fullpath
|
||||
Conf.RootAPI = filepath.Join(fullpath, "/apis")
|
||||
Conf.RootFLow = filepath.Join(fullpath, "/flows")
|
||||
Conf.RootModel = filepath.Join(fullpath, "/models")
|
||||
Conf.RootPlugin = filepath.Join(fullpath, "/plugins")
|
||||
Conf.RootTable = filepath.Join(fullpath, "/tables")
|
||||
Conf.RootChart = filepath.Join(fullpath, "/charts")
|
||||
Conf.RootPage = filepath.Join(fullpath, "/pages")
|
||||
Conf.RootWorkFlow = filepath.Join(fullpath, "/workflows")
|
||||
Conf.RootData = filepath.Join(fullpath, "/data")
|
||||
Conf.RootUI = filepath.Join(fullpath, "/ui")
|
||||
Conf.RootDB = filepath.Join(fullpath, "/db")
|
||||
Conf.RootLib = filepath.Join(fullpath, "/libs")
|
||||
}
|
||||
|
||||
// IsDebug 是否为调试模式
|
||||
func IsDebug() bool {
|
||||
return Conf.Mode == "debug"
|
||||
}
|
||||
|
||||
func init() {
|
||||
Conf = NewConfig()
|
||||
}
|
||||
// // IsDebug 是否为调试模式
|
||||
// func IsDebug() bool {
|
||||
// return Conf.Mode == "debug"
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -2,52 +2,65 @@ package config
|
|||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/kun/any"
|
||||
)
|
||||
|
||||
func TestNewConfig(t *testing.T) {
|
||||
cfg := NewConfig()
|
||||
var vBool = func(name string) bool {
|
||||
if name == "true" || name == "1" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
// func TestNewConfig(t *testing.T) {
|
||||
// cfg := NewConfig()
|
||||
// var vBool = func(name string) bool {
|
||||
// if name == "true" || name == "1" {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
|
||||
xiangPath := os.Getenv("XIANG_PATH")
|
||||
if xiangPath == "" {
|
||||
xiangPath = "bin://xiang"
|
||||
}
|
||||
// xiangPath := os.Getenv("XIANG_PATH")
|
||||
// if xiangPath == "" {
|
||||
// xiangPath = "bin://xiang"
|
||||
// }
|
||||
|
||||
assert.Equal(t, cfg.Mode, os.Getenv("XIANG_MODE"))
|
||||
assert.Equal(t, cfg.Root, os.Getenv("XIANG_ROOT"))
|
||||
assert.Equal(t, cfg.Path, xiangPath)
|
||||
// assert.Equal(t, cfg.Mode, os.Getenv("XIANG_MODE"))
|
||||
// assert.Equal(t, cfg.Root, os.Getenv("XIANG_ROOT"))
|
||||
// assert.Equal(t, cfg.Path, xiangPath)
|
||||
|
||||
assert.Equal(t, cfg.Service.Debug, vBool(os.Getenv("XIANG_SERVICE_DEBUG")))
|
||||
assert.Equal(t, strings.Join(cfg.Service.Allow, "|"), os.Getenv("XIANG_SERVICE_ALLOW"))
|
||||
assert.Equal(t, cfg.Service.Host, os.Getenv("XIANG_SERVICE_HOST"))
|
||||
assert.Equal(t, cfg.Service.Port, any.Of(os.Getenv("XIANG_SERVICE_PORT")).CInt())
|
||||
// assert.Equal(t, cfg.Service.Debug, vBool(os.Getenv("XIANG_SERVICE_DEBUG")))
|
||||
// assert.Equal(t, strings.Join(cfg.Service.Allow, "|"), os.Getenv("XIANG_SERVICE_ALLOW"))
|
||||
// assert.Equal(t, cfg.Service.Host, os.Getenv("XIANG_SERVICE_HOST"))
|
||||
// assert.Equal(t, cfg.Service.Port, any.Of(os.Getenv("XIANG_SERVICE_PORT")).CInt())
|
||||
|
||||
assert.Equal(t, cfg.Database.Debug, vBool(os.Getenv("XIANG_DB_DEBUG")))
|
||||
assert.Equal(t, strings.Join(cfg.Database.Primary, "|"), os.Getenv("XIANG_DB_PRIMARY"))
|
||||
assert.Equal(t, strings.Join(cfg.Database.Secondary, "|"), os.Getenv("XIANG_DB_SECONDARY"))
|
||||
assert.Equal(t, cfg.Database.AESKey, os.Getenv("XIANG_DB_AESKEY"))
|
||||
// assert.Equal(t, cfg.Database.Debug, vBool(os.Getenv("XIANG_DB_DEBUG")))
|
||||
// assert.Equal(t, strings.Join(cfg.Database.Primary, "|"), os.Getenv("XIANG_DB_PRIMARY"))
|
||||
// assert.Equal(t, strings.Join(cfg.Database.Secondary, "|"), os.Getenv("XIANG_DB_SECONDARY"))
|
||||
// assert.Equal(t, cfg.Database.AESKey, os.Getenv("XIANG_DB_AESKEY"))
|
||||
|
||||
assert.Equal(t, cfg.JWT.Debug, vBool(os.Getenv("XIANG_JWT_DEBUG")))
|
||||
assert.Equal(t, cfg.JWT.Secret, os.Getenv("XIANG_JWT_SECRET"))
|
||||
// assert.Equal(t, cfg.JWT.Secret, os.Getenv("XIANG_JWT_SECRET"))
|
||||
|
||||
assert.Equal(t, cfg.Log.Access, os.Getenv("XIANG_LOG_ACCESS"))
|
||||
assert.Equal(t, cfg.Log.Error, os.Getenv("XIANG_LOG_ERROR"))
|
||||
assert.Equal(t, cfg.Log.DB, os.Getenv("XIANG_LOG_DB"))
|
||||
assert.Equal(t, cfg.Log.Plugin, os.Getenv("XIANG_LOG_PLUGIN"))
|
||||
// assert.Equal(t, cfg.Log.Access, os.Getenv("XIANG_LOG_ACCESS"))
|
||||
// assert.Equal(t, cfg.Log.Error, os.Getenv("XIANG_LOG_ERROR"))
|
||||
// assert.Equal(t, cfg.Log.DB, os.Getenv("XIANG_LOG_DB"))
|
||||
// assert.Equal(t, cfg.Log.Plugin, os.Getenv("XIANG_LOG_PLUGIN"))
|
||||
|
||||
}
|
||||
|
||||
func TestNewConfigFrom(t *testing.T) {
|
||||
assert.True(t, true)
|
||||
assert.True(t, true)
|
||||
// }
|
||||
|
||||
// func TestNewConfigFrom(t *testing.T) {
|
||||
// assert.True(t, true)
|
||||
// assert.True(t, true)
|
||||
// }
|
||||
|
||||
func TestLoadFrom(t *testing.T) {
|
||||
cfg := LoadFrom(filepath.Join(os.Getenv("YAO_DEV"), ".env"))
|
||||
root, _ := filepath.Abs(os.Getenv("YAO_ROOT"))
|
||||
assert.Equal(t, cfg.Root, root)
|
||||
assert.Equal(t, cfg.Mode, os.Getenv("YAO_ENV"))
|
||||
assert.Equal(t, cfg.Host, os.Getenv("YAO_HOST"))
|
||||
assert.Equal(t, cfg.Port, os.Getenv("YAO_PORT"))
|
||||
assert.Equal(t, cfg.JWTSecret, os.Getenv("YAO_JWT_SECRET"))
|
||||
assert.Equal(t, cfg.Log, os.Getenv("YAO_LOG"))
|
||||
assert.Equal(t, cfg.LogMode, os.Getenv("YAO_LOG_MODE"))
|
||||
assert.Equal(t, cfg.DB.Driver, os.Getenv("YAO_DB_DRIVER"))
|
||||
assert.Equal(t, cfg.DB.Primary[0], os.Getenv("YAO_DB_PRIMARY"))
|
||||
assert.Equal(t, cfg.DB.Secondary[0], os.Getenv("YAO_DB_SECONDARY"))
|
||||
}
|
||||
|
|
|
|||
25
config/types.go
Normal file
25
config/types.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package config
|
||||
|
||||
// Config 象传应用引擎配置
|
||||
type Config struct {
|
||||
Mode string `json:"mode,omitempty" env:"YAO_ENV" envDefault:"production"` // 象传引擎启动模式 production/development
|
||||
Root string `json:"root,omitempty" env:"YAO_ROOT" envDefault:"."` // 应用根目录
|
||||
Host string `json:"host,omitempty" env:"YAO_HOST" envDefault:"0.0.0.0"` // 服务监听地址
|
||||
Port int `json:"port,omitempty" env:"YAO_PORT" envDefault:"5099"` // 服务监听端口
|
||||
Cert string `json:"cert,omitempty" env:"YAO_CERT"` // HTTPS 证书文件地址
|
||||
Key string `json:"key,omitempty" env:"YAO_KEY"` // HTTPS 证书密钥地址
|
||||
Log string `json:"log,omitempty" env:"YAO_LOG" envDefault:"./logs/application.log"` // 服务日志地址
|
||||
LogMode string `json:"log_mode,omitempty" env:"YAO_LOG_MODE" envDefault:"JSON"` // 服务日志模式 JSON|TEXT
|
||||
// Session string `json:"session,omitempty" env:"YAO_SESSION" envDefault:"memory"` // 用户会话模式 memory|redis|database
|
||||
JWTSecret string `json:"jwt_secret,omitempty" env:"YAO_JWT_SECRET"` // JWT 密钥
|
||||
DB DBConfig `json:"db,omitempty"` // 数据库配置
|
||||
Session SessionConfig `json:"session,omitempty"`
|
||||
}
|
||||
|
||||
// DBConfig 数据库配置
|
||||
type DBConfig struct {
|
||||
Driver string `json:"driver,omitempty" env:"YAO_DB_DRIVER" envDefault:"sqlite3"` // 数据库驱动 sqlite3| mysql| postgres
|
||||
Primary []string `json:"primary,omitempty" env:"YAO_DB_PRIMARY" envSeparator:"|" envDefault:"./db/yao.db"` // 主库连接DSN
|
||||
Secondary []string `json:"secondary,omitempty" env:"YAO_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN
|
||||
AESKey string `json:"aeskey,omitempty" env:"YAO_DB_AESKEY"` // 加密存储KEY
|
||||
}
|
||||
119
data/bindata.go
119
data/bindata.go
|
|
@ -1,16 +1,15 @@
|
|||
// Code generated for package data by go-bindata DO NOT EDIT. (@generated)
|
||||
// sources:
|
||||
// .tmp/data/ui/index.html
|
||||
// .tmp/data/xiang/.DS_Store
|
||||
// .tmp/data/xiang/apis/README.md
|
||||
// .tmp/data/xiang/apis/chart.http.json
|
||||
// .tmp/data/xiang/apis/import.http.json
|
||||
// .tmp/data/xiang/apis/page.http.json
|
||||
// .tmp/data/xiang/apis/storage.http.json
|
||||
// .tmp/data/xiang/apis/table.http.json
|
||||
// .tmp/data/xiang/apis/user.http.json
|
||||
// .tmp/data/xiang/apis/xiang.http.json
|
||||
// .tmp/data/xiang/data/app.json
|
||||
// .tmp/data/xiang/data/icons/.DS_Store
|
||||
// .tmp/data/xiang/data/icons/404.png
|
||||
// .tmp/data/xiang/data/icons/icon.icns
|
||||
// .tmp/data/xiang/data/icons/icon.ico
|
||||
|
|
@ -204,27 +203,7 @@ func uiIndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "ui/index.html", size: 12, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _xiangDs_store = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x97\x4f\x4b\xe3\x40\x14\xc0\xdf\xa4\xd9\xee\x64\xcb\xb2\x39\x2c\x6c\x8f\xb9\xec\xad\x87\xb6\xdb\x5d\xe8\x61\x21\x64\xbb\x07\x6f\x42\x44\x0f\x55\xda\x0c\x09\x36\x90\x66\x4a\x92\x1a\x34\x46\xfa\x35\xf4\x1b\xf9\x09\xfc\x3a\x92\xe6\xa9\x25\xb6\xde\xc4\x5a\xdf\x0f\xca\x6f\xca\xfc\x49\xde\x84\xf9\xf3\x00\x80\x59\x73\xb7\x03\xa0\x03\x00\x87\xd2\xea\x17\x58\x0b\xc7\xdf\x33\x14\xb4\x5a\x8c\xb7\x1c\x23\x80\x58\xa4\xf1\x4c\x04\x52\xac\x1f\x8b\x20\x88\x2d\xa2\x58\xbb\x75\x98\x82\x04\x17\xbc\xca\xfa\xbd\x15\xb3\xc0\x8f\x93\x76\xfb\x8e\x29\x35\xf5\x53\xfd\x33\xe7\xbc\xc1\xbf\xf2\x13\x7b\x22\x53\x3b\x71\x92\x79\x6c\x39\xd1\xb0\xf8\xb7\xef\x24\x13\x81\xe5\x03\x29\x83\xc7\xb2\x23\x0e\x7d\x2f\x1d\xe9\xdf\xff\xc9\x30\x71\xfc\xd0\x8b\x96\x9d\x7d\xd7\x13\x4e\x74\x7c\xe4\x87\xae\x4c\x2d\x39\x0f\xdd\x78\xb8\x52\xa1\x69\x1a\xd7\x46\x7a\x33\xcb\x7a\xbf\xfe\xb4\x8c\xde\xef\x6e\xde\x32\xb2\x7e\xb7\xdd\x32\x7a\xfd\x6e\x9e\x6b\xfc\xc7\xcf\xce\xdf\xbd\xf1\xf4\xfc\x22\xbb\xcc\xaf\xae\xcb\x58\x18\xc3\xa0\xbe\x55\x82\xbc\xa9\x06\x79\x66\x47\x61\x20\xc3\xd3\x72\xe3\x82\x3a\x24\xe0\x80\x80\x00\xbc\x5d\x9e\x80\x95\x20\x2b\x13\x40\x7c\x44\xf0\xcb\xf3\xc6\x5b\xbf\x08\x41\x10\x5b\x47\xb1\x3f\x18\x68\x13\xbd\x28\xcd\xb0\x5e\x41\xab\x2b\x7d\x74\xb4\x81\x36\xd1\x8b\xd2\x0c\xdb\x29\x68\x15\xcd\xd1\x3a\xda\x40\x9b\xe8\x45\x69\xdc\xb4\x18\x26\x1f\x0c\x9f\xcc\x30\x43\x61\x3a\xda\x40\x9b\xaf\x33\x37\x04\xf1\xde\xa9\x95\xd2\x8b\xf3\xff\xff\xe6\xfc\x9f\x20\x88\x1d\x86\xa9\x03\x7b\x60\xbd\x90\x0a\x2a\x78\x11\x18\x3f\x74\xd8\x70\x11\xc0\xb6\xc5\x51\xdc\x84\xa7\xb6\x74\x11\x20\x88\x2d\xe3\x3e\x00\x00\xff\xff\xc8\x24\xe8\x37\x04\x18\x00\x00")
|
||||
|
||||
func xiangDs_storeBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_xiangDs_store,
|
||||
"xiang/.DS_Store",
|
||||
)
|
||||
}
|
||||
|
||||
func xiangDs_store() (*asset, error) {
|
||||
bytes, err := xiangDs_storeBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "ui/index.html", size: 12, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -244,7 +223,7 @@ func xiangApisReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -264,7 +243,27 @@ func xiangApisChartHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _xiangApisImportHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x54\xbb\x4e\xc3\x30\x14\xdd\xf3\x15\x96\xc5\x18\x92\xc0\x98\x0d\x09\x84\x18\x10\x15\x65\xab\x3a\x5c\x1a\x93\xba\x6a\x62\x63\x3b\x40\xa9\x3a\x82\x58\x78\x2c\xac\x2c\xa8\x2b\xf0\x01\xfc\x4e\xf3\x1d\xc8\xb1\xdb\x90\x2a\xa0\xaa\x95\x28\x4b\xa2\x9c\x73\xee\xe3\xdc\x7b\x95\xa1\x83\x10\x4e\x21\x21\x38\x44\x38\x7f\xfe\xc8\xef\xdf\x26\xef\x9f\x93\x9b\x71\xfe\x30\x9e\x3c\xbe\x62\x57\xf3\x17\x44\x48\xca\x52\x2d\xd9\xf2\x02\x2f\x30\x68\x44\x64\x47\x50\xae\x2c\x63\x83\xef\x6e\xf3\x97\x27\x13\xbc\xd3\x38\x30\xca\x58\xb0\x8c\x6b\xcd\x15\x85\x34\xf6\x69\xc2\x99\x50\x96\xca\x40\x44\x9a\x3a\x25\x20\x88\xd8\xec\x5d\x5a\x82\x83\xea\x4a\x1c\xa2\x96\x83\x10\x42\xc3\xe2\x69\x61\x2d\xf7\xc3\xa2\x69\x77\x8a\x27\x44\x75\x59\x91\xa8\x71\xd4\x3c\x29\x71\x2e\x58\x87\x48\x39\x2b\xee\x99\xe2\xde\x71\x96\x96\x22\xaa\x0d\xb4\xf0\x06\x07\x01\x89\x67\x12\x23\xfd\x39\xe8\x33\x88\xbc\x33\xda\xaf\x02\x09\x70\x4e\xd3\x18\xb7\x67\x19\x58\xa6\x70\x38\xeb\x12\x21\x2c\x15\xa8\x4c\x97\xdd\x0e\x02\xb7\x84\xd5\x80\x17\x93\x06\xce\xfb\xb4\x03\x7a\x76\x7e\x4f\xb2\x14\x5b\xc9\xa8\x78\x8f\xdc\xdf\x4c\xfb\x92\x28\xa5\xcb\xd7\x98\xdf\xdf\x5b\xc0\x7b\x73\x3e\xbe\xc6\xff\x9a\xac\x45\xa0\x60\xf9\xa5\xee\x56\xa2\x8d\xab\xb2\xc1\xca\x7a\x2b\xf0\xf7\x35\xd7\x10\x1c\xe2\x7a\x42\xd2\xeb\x7a\x62\x7a\x20\x96\x5a\xe3\x30\x57\x3e\x16\x3d\xd3\x7f\x7c\x30\xd3\x49\x2f\x6b\xef\x70\x3e\xfe\x87\x7f\xc1\x79\x46\xc4\xc0\x9c\xc8\x7a\x9d\xae\xbc\x50\xeb\x78\x91\x9d\xfe\x95\x71\x07\xa1\xb6\x33\x72\xbe\x02\x00\x00\xff\xff\x17\xf7\x73\xea\x8c\x06\x00\x00")
|
||||
|
||||
func xiangApisImportHttpJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_xiangApisImportHttpJson,
|
||||
"xiang/apis/import.http.json",
|
||||
)
|
||||
}
|
||||
|
||||
func xiangApisImportHttpJson() (*asset, error) {
|
||||
bytes, err := xiangApisImportHttpJsonBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -284,7 +283,7 @@ func xiangApisPageHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -304,12 +303,12 @@ func xiangApisStorageHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/storage.http.json", size: 1092, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/storage.http.json", size: 1092, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _xiangApisTableHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x56\xcd\x6e\xd3\x40\x10\xbe\xfb\x29\x56\xab\x1e\x53\x3b\x70\xf4\x0d\x89\x1f\xe5\x44\x51\x41\x1c\xaa\x1e\x06\xef\x90\x0c\xb5\xd7\xdb\xfd\x49\x31\x55\x1e\x01\x38\x71\x07\x21\x24\x4e\x88\x07\xe0\x75\x88\x78\x0c\xb4\x6b\xa7\xa9\x43\xd2\x86\x58\xc8\xe1\x92\x68\x67\xe6\x1b\xcd\xf7\x7d\x1e\x7b\x2f\x23\xc6\xb8\x84\x02\x79\xca\xf8\xfc\xc3\xf7\xf9\xdb\x6f\xbf\x3e\x7d\x9d\x7f\xfc\x31\x7f\xf7\xe5\xe7\xfb\xcf\x7c\xe0\xf3\x53\xd4\x86\x4a\xe9\x4b\xee\xc4\xc3\x78\x58\x47\x05\x9a\x4c\x93\xb2\x4d\xe6\x4f\xf0\xbd\xa3\x51\x5d\x39\xd6\xa5\x53\xbe\xe6\x35\x81\x1c\x27\x16\x5e\xe4\xd8\x64\x1c\x68\xe1\x33\x24\x0f\x95\x2e\x33\x34\xa6\x4e\x28\xb0\x13\xc3\x53\x76\x12\x31\xc6\xd8\x65\xf8\x6d\xc2\xbe\x3c\x49\xfd\xcc\x89\x41\xd0\xd9\x24\x20\x42\xba\x40\x3b\x29\x43\xbf\x47\x0f\x9e\x2e\xc3\x8b\xce\x8b\x09\xe2\x30\x41\x7c\xbc\x82\x26\xcf\xe3\x84\x1f\x28\xd0\x50\xc4\x41\x94\x01\xe3\xe9\xb9\x43\x5d\x1d\x86\xa0\x3f\x1f\x84\x73\xac\x60\x8c\x2b\x47\x43\x6f\x90\x9f\x5e\xb5\x2b\x9d\xe5\xe9\xd5\xe8\x8c\x71\x63\xc1\x3a\x3f\xc5\xdd\xe1\x70\xb0\x0c\xdb\x4a\x05\xf5\x41\xa9\x9c\x32\xf0\x7a\x26\xaf\x4c\x29\x79\x53\x32\x0b\xff\xb3\xc1\x8d\x4a\xbc\x24\x29\x92\x94\xc4\xae\x5a\x3c\x24\x29\x6e\x53\xa2\x39\x92\xe8\x8b\xa4\xc1\x1c\x33\xbb\xbb\xdd\x6d\x74\x4d\x72\x39\x62\x8b\xed\xb5\x70\x6d\xf0\x19\x56\x17\xa5\x16\x6b\x32\x1b\x00\x53\xc8\xdd\xba\x78\x4e\x05\xd9\x05\xed\xbe\x84\x84\x29\xae\x93\xf1\xe8\xf1\xf1\x16\x3a\xb6\xc0\x1b\x96\x46\x41\x95\x97\xd0\xdb\x93\x72\xee\x28\x3b\xeb\xc4\xf2\x89\xef\xf0\x3f\x50\x15\x98\xa3\xc5\x4d\xbb\xbf\x15\xd7\xfb\xa1\xc5\xde\xaf\x3f\x49\x83\x7a\xed\xfa\x6f\xc5\x72\xb4\x02\xdf\xc8\x32\xd8\x19\x67\x65\xee\x0a\x69\x5a\xb1\xb0\xd3\xa6\x67\xa7\x2f\x26\xa8\x77\x7f\xae\x6b\xaf\x9f\xb7\x7b\x6c\xf1\xe5\xeb\x97\x33\xc9\x8e\x84\x47\xf2\x56\xe3\xeb\xd7\x33\x09\x73\xfd\xb3\xae\xa9\x00\x5d\xf5\xc5\xde\x29\x01\x9d\x1d\x7f\x16\x9a\xfc\xbd\xe3\x7b\xf0\x6e\x6b\xf8\x77\x70\xbf\x26\xdf\xd1\xfd\x3d\x50\xc2\xa0\xb5\x24\xc7\xbb\xdf\x7d\x56\xe0\x37\xaa\xd0\xdc\xb3\xfe\x19\xd5\x88\xb1\xd3\x68\x16\xfd\x0e\x00\x00\xff\xff\xf6\xae\xeb\xee\x7c\x0c\x00\x00")
|
||||
var _xiangApisTableHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x56\xcd\x6e\xd3\x40\x10\xbe\xe7\x29\x56\xab\x1e\x53\x3b\x70\xf4\x0d\x89\x1f\xe5\x44\x51\x41\x1c\xaa\x1e\xa6\xde\x21\x99\xd6\x5e\x6f\xf7\x27\xc1\x54\x79\x04\xe0\xc4\x1d\x84\x90\x38\x21\x1e\x80\xd7\x21\xe2\x31\xd0\xae\x4d\x52\x87\xa4\x0d\xb1\x90\xd3\x4b\xa2\x9d\x99\x6f\x34\xdf\xf7\x79\xec\xbd\xea\x31\xc6\x25\xe4\xc8\x13\xc6\xe7\x1f\xbe\xcf\xdf\x7e\xfb\xf5\xe9\xeb\xfc\xe3\x8f\xf9\xbb\x2f\x3f\xdf\x7f\xe6\x7d\x9f\x9f\xa0\x36\x54\x48\x5f\x72\x2f\x1a\x44\x83\x2a\x2a\xd0\xa4\x9a\x94\xad\x33\x7f\x83\x1f\x1c\x0d\xab\xca\x91\x2e\x9c\xf2\x35\xaf\x09\xe4\x28\xb6\x70\x96\x61\x9d\x71\xa0\x85\xcf\x9c\x21\x68\xd4\x87\xe7\x53\x5b\x25\x14\xd8\xb1\xe1\x09\x3b\xe9\x31\xc6\xd8\x55\xf8\xad\xc3\xbe\x3c\x4e\xfc\xcc\xb1\x41\xd0\xe9\x38\x20\x42\x3a\x47\x3b\x2e\x42\xbf\x27\x8f\x9e\x2f\xc3\x4a\x17\x29\x1a\xb3\x98\x20\x0a\x13\x44\xc7\x2b\x68\xf2\x3c\x4e\xf8\x81\x02\x0d\x79\x14\x44\xe9\x33\x9e\x5c\x3a\xd4\xe5\x61\x08\xfa\xf3\x41\x38\x47\x0a\x46\xb8\x72\x34\xf4\x06\xf9\xe9\xa2\x5d\xe1\x2c\x4f\x16\xa3\x33\xc6\x8d\x05\xeb\xfc\x14\xf7\x07\x83\xfe\x32\x6c\x4b\x15\xd4\x07\xa5\x32\x4a\xc1\xeb\x19\x9f\x9b\x42\xf2\xba\x64\x16\xfe\x67\xfd\x1b\x95\x78\x45\x52\xc4\x09\x89\x5d\xb5\x78\x4c\x52\xdc\xa6\x44\x7d\x24\xd1\x15\x49\x83\x19\xa6\x76\x77\xbb\x9b\xe8\x8a\xe4\x72\xc4\x06\xdb\x6b\xe1\xca\xe0\x0b\x2c\xa7\x85\x16\x6b\x32\x1b\x00\x13\xc8\xdc\xba\x78\x46\x39\xd9\x3f\xb4\xbb\x12\x12\x26\xb8\x4e\xc6\xa3\xa7\xc7\x5b\xe8\xd8\x00\x6f\x58\x1a\x05\x65\x56\x40\x67\x4f\xca\xa5\xa3\xf4\xa2\x15\xcb\x67\xbe\xc3\x5d\xa0\x2a\x30\x43\x8b\x9b\x76\x7f\x2b\xae\x0f\x43\x8b\xbd\x5f\x7f\x92\x06\xf5\xda\xf5\xdf\x8a\xe5\x70\x05\xbe\x91\x65\xb0\x33\x4a\x8b\xcc\xe5\xd2\x34\x62\x61\xa7\x4d\xc7\x4e\x4f\xc7\xa8\x77\x7f\xae\x2b\xaf\x5f\x36\x7b\x6c\xf1\xe5\xeb\x96\x33\xc9\x96\x84\x87\xf2\x56\xe3\xab\xd7\x33\x09\x73\xfd\xb3\xae\x29\x07\x5d\x76\xc5\xde\x29\x01\xad\x1d\x7f\x11\x9a\xfc\xbb\xe3\x7b\xf0\x6e\xab\xf9\xb7\x70\xbf\x22\xdf\xd2\xfd\x3d\x50\xc2\xa0\xb5\x24\x47\xbb\xdf\x7d\x56\xe0\x37\xaa\x50\xdf\xb3\xfe\x1b\xd5\x1e\x63\xa7\xbd\x59\xef\x77\x00\x00\x00\xff\xff\x8a\x3e\xea\x17\x7c\x0c\x00\x00")
|
||||
|
||||
func xiangApisTableHttpJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
|
|
@ -324,7 +323,7 @@ func xiangApisTableHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/table.http.json", size: 3196, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/table.http.json", size: 3196, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -344,7 +343,7 @@ func xiangApisUserHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -364,7 +363,7 @@ func xiangApisXiangHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -384,27 +383,7 @@ func xiangDataAppJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/app.json", size: 245, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _xiangDataIconsDs_store = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xd8\x31\x0a\x02\x31\x10\x85\xe1\x37\x31\x45\xc0\x26\xa5\x65\x1a\x0f\xe0\x0d\xc2\xb2\x9e\xc0\x0b\x58\x78\x05\xfb\x1c\x5d\x96\x79\x60\x60\xd5\x4e\x8c\xcb\xfb\x40\xfe\x05\x37\x2a\x16\x31\x23\x00\x9b\xee\xb7\x13\x90\x01\x24\x78\x71\xc4\x4b\x89\x8f\x95\xd0\x5d\x1b\x5f\x43\x44\x44\x44\xc6\x66\x9e\xb4\xff\xf5\x07\x11\x91\xe1\x2c\xfb\x43\x61\x2b\xdb\xbc\xc6\xe7\x03\x1b\xbb\x35\x99\x2d\x6c\x65\x9b\xd7\x78\x5f\x60\x23\x9b\xd8\xcc\x16\xb6\xb2\xcd\xcb\x4d\xcb\x38\x7c\x18\xdf\xd9\x38\xa1\x18\xa7\x10\x2b\x6c\xfd\xce\x77\x23\xf2\xef\x76\x9e\xbc\xfc\xfe\x9f\xdf\xcf\xff\x22\xb2\x61\x16\xe7\xcb\x3c\x3d\x07\x82\xf5\x0d\x00\xae\xdd\xf5\xa7\x43\x40\xf0\x3f\x0b\x0f\xdd\x5a\x1d\x04\x44\x06\xf3\x08\x00\x00\xff\xff\x6a\x00\x88\x6d\x04\x18\x00\x00")
|
||||
|
||||
func xiangDataIconsDs_storeBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_xiangDataIconsDs_store,
|
||||
"xiang/data/icons/.DS_Store",
|
||||
)
|
||||
}
|
||||
|
||||
func xiangDataIconsDs_store() (*asset, error) {
|
||||
bytes, err := xiangDataIconsDs_storeBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/icons/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/data/app.json", size: 245, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -424,7 +403,7 @@ func xiangDataIcons404Png() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -444,7 +423,7 @@ func xiangDataIconsIconIcns() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/icons/icon.icns", size: 75636, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/data/icons/icon.icns", size: 75636, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -464,7 +443,7 @@ func xiangDataIconsIconIco() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/icons/icon.ico", size: 31310, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/data/icons/icon.ico", size: 31310, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -484,7 +463,7 @@ func xiangDataIconsIconPng() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/icons/icon.png", size: 22420, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/data/icons/icon.png", size: 22420, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -504,7 +483,7 @@ func xiangDataIndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/data/index.html", size: 302, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/data/index.html", size: 302, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -524,7 +503,7 @@ func xiangFlowsReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -544,7 +523,7 @@ func xiangFlowsMenuFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -564,7 +543,7 @@ func xiangFlowsTableGetFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/flows/table/get.flow.json", size: 541, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/flows/table/get.flow.json", size: 541, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -584,7 +563,7 @@ func xiangModelsReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -604,7 +583,7 @@ func xiangModelsMenuJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/models/menu.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/models/menu.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -624,7 +603,7 @@ func xiangModelsUserJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/models/user.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/models/user.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -644,7 +623,7 @@ func xiangModelsWorkflowModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -664,7 +643,7 @@ func xiangTablesReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -684,7 +663,7 @@ func xiangTablesMenuJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/tables/menu.json", size: 10382, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/tables/menu.json", size: 10382, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -704,7 +683,7 @@ func xiangTablesUserJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "xiang/tables/user.json", size: 1422, mode: os.FileMode(420), modTime: time.Unix(1641540958, 0)}
|
||||
info := bindataFileInfo{name: "xiang/tables/user.json", size: 1422, mode: os.FileMode(420), modTime: time.Unix(1644337051, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -762,16 +741,15 @@ 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,
|
||||
"xiang/.DS_Store": xiangDs_store,
|
||||
"xiang/apis/README.md": xiangApisReadmeMd,
|
||||
"xiang/apis/chart.http.json": xiangApisChartHttpJson,
|
||||
"xiang/apis/import.http.json": xiangApisImportHttpJson,
|
||||
"xiang/apis/page.http.json": xiangApisPageHttpJson,
|
||||
"xiang/apis/storage.http.json": xiangApisStorageHttpJson,
|
||||
"xiang/apis/table.http.json": xiangApisTableHttpJson,
|
||||
"xiang/apis/user.http.json": xiangApisUserHttpJson,
|
||||
"xiang/apis/xiang.http.json": xiangApisXiangHttpJson,
|
||||
"xiang/data/app.json": xiangDataAppJson,
|
||||
"xiang/data/icons/.DS_Store": xiangDataIconsDs_store,
|
||||
"xiang/data/icons/404.png": xiangDataIcons404Png,
|
||||
"xiang/data/icons/icon.icns": xiangDataIconsIconIcns,
|
||||
"xiang/data/icons/icon.ico": xiangDataIconsIconIco,
|
||||
|
|
@ -834,10 +812,10 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"index.html": {uiIndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"xiang": {nil, map[string]*bintree{
|
||||
".DS_Store": {xiangDs_store, map[string]*bintree{}},
|
||||
"apis": {nil, map[string]*bintree{
|
||||
"README.md": {xiangApisReadmeMd, map[string]*bintree{}},
|
||||
"chart.http.json": {xiangApisChartHttpJson, map[string]*bintree{}},
|
||||
"import.http.json": {xiangApisImportHttpJson, map[string]*bintree{}},
|
||||
"page.http.json": {xiangApisPageHttpJson, map[string]*bintree{}},
|
||||
"storage.http.json": {xiangApisStorageHttpJson, map[string]*bintree{}},
|
||||
"table.http.json": {xiangApisTableHttpJson, map[string]*bintree{}},
|
||||
|
|
@ -847,7 +825,6 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"data": {nil, map[string]*bintree{
|
||||
"app.json": {xiangDataAppJson, map[string]*bintree{}},
|
||||
"icons": {nil, map[string]*bintree{
|
||||
".DS_Store": {xiangDataIconsDs_store, map[string]*bintree{}},
|
||||
"404.png": {xiangDataIcons404Png, map[string]*bintree{}},
|
||||
"icon.icns": {xiangDataIconsIconIcns, map[string]*bintree{}},
|
||||
"icon.ico": {xiangDataIconsIconIco, map[string]*bintree{}},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ package engine
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
|
|
@ -25,11 +26,17 @@ import (
|
|||
// Load 根据配置加载 API, FLow, Model, Plugin
|
||||
func Load(cfg config.Config) {
|
||||
|
||||
share.DBConnect(cfg.Database) // 创建数据库连接
|
||||
share.DBConnect(cfg.DB) // 创建数据库连接
|
||||
share.SessionConnect(cfg.Session) // 创建会话服务器链接
|
||||
|
||||
app.Load(cfg) // 加载应用信息
|
||||
LoadEngine(cfg.Path)
|
||||
|
||||
if os.Getenv("YAO_DEV") != "" {
|
||||
LoadEngine(filepath.Join(os.Getenv("YAO_DEV"), "/xiang"))
|
||||
} else {
|
||||
LoadEngine()
|
||||
}
|
||||
|
||||
query.Load(cfg) // 加载数据分析引擎
|
||||
|
||||
share.Load(cfg) // 加载共享库 lib
|
||||
|
|
@ -46,7 +53,7 @@ func Load(cfg config.Config) {
|
|||
server.Load(cfg) // 加载服务
|
||||
|
||||
// 加密密钥函数
|
||||
gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, cfg.Database.AESKey), "AES")
|
||||
gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, cfg.DB.AESKey), "AES")
|
||||
gou.LoadCrypt(`{}`, "PASSWORD")
|
||||
}
|
||||
|
||||
|
|
@ -60,15 +67,12 @@ func Reload(cfg config.Config) {
|
|||
}
|
||||
|
||||
// LoadEngine 加载引擎的 API, Flow, Model 配置
|
||||
func LoadEngine(from string) {
|
||||
|
||||
func LoadEngine(from ...string) {
|
||||
var scripts []share.Script
|
||||
if strings.HasPrefix(from, "fs://") || !strings.Contains(from, "://") {
|
||||
root := strings.TrimPrefix(from, "fs://")
|
||||
scripts = share.GetFilesFS(root, ".json")
|
||||
} else if strings.HasPrefix(from, "bin://") {
|
||||
root := strings.TrimPrefix(from, "bin://")
|
||||
scripts = share.GetFilesBin(root, ".json")
|
||||
if len(from) > 0 {
|
||||
scripts = share.GetFilesFS(from[0], ".json")
|
||||
} else {
|
||||
scripts = share.GetFilesBin("/xiang", ".json")
|
||||
}
|
||||
|
||||
if scripts == nil {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ func TestLoad(t *testing.T) {
|
|||
// 从文件系统载入引擎文件
|
||||
func TestLoadEngineFS(t *testing.T) {
|
||||
defer Load(config.Conf)
|
||||
root := "fs://" + path.Join(config.Conf.Source, "/xiang")
|
||||
root := path.Join(os.Getenv("YAO_DEV"), "/xiang")
|
||||
assert.NotPanics(t, func() {
|
||||
LoadEngine(root)
|
||||
})
|
||||
|
|
@ -28,8 +29,7 @@ func TestLoadEngineFS(t *testing.T) {
|
|||
// 从BinDataz载入引擎文件
|
||||
func TestLoadEngineBin(t *testing.T) {
|
||||
defer Load(config.Conf)
|
||||
root := "bin://xiang"
|
||||
assert.NotPanics(t, func() {
|
||||
LoadEngine(root)
|
||||
LoadEngine()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
|
|
@ -25,11 +27,10 @@ func processPing(process *gou.Process) interface{} {
|
|||
|
||||
res := map[string]interface{}{
|
||||
"code": 200,
|
||||
"server": "象传应用引擎",
|
||||
"server": "Yao App Engine",
|
||||
"version": share.VERSION,
|
||||
"domain": share.DOMAIN,
|
||||
"allows": config.Conf.Service.Allow,
|
||||
"args": input,
|
||||
// "allows": config.Conf.Service.Allow,
|
||||
"args": input,
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -60,7 +61,7 @@ func processFileContent(process *gou.Process) interface{} {
|
|||
// processAppFileContent 返回应用文件内容
|
||||
func processAppFileContent(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(2)
|
||||
fs := xfs.New(config.Conf.RootData)
|
||||
fs := xfs.New(filepath.Join(config.Conf.Root, "data"))
|
||||
filename := process.ArgsString(0)
|
||||
encode := process.ArgsBool(1, true)
|
||||
content := fs.MustReadFile(filename)
|
||||
|
|
|
|||
35
flow/flow.go
35
flow/flow.go
|
|
@ -1,31 +1,45 @@
|
|||
package flow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Load 加载业务逻辑编排
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootFLow, "")
|
||||
func Load(cfg config.Config) error {
|
||||
if share.BUILDIN {
|
||||
return LoadBuildIn("flows", "")
|
||||
}
|
||||
return LoadFrom(filepath.Join(cfg.Root, "flows"), "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
gou.LoadFlow(string(content), name)
|
||||
_, err := gou.LoadFlowReturn(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load Script
|
||||
share.Walk(dir, ".js", func(root, filename string) {
|
||||
err = share.Walk(dir, ".js", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
flow := gou.SelectFlow(name)
|
||||
if flow != nil {
|
||||
|
|
@ -34,4 +48,11 @@ func LoadFrom(dir string, prefix string) {
|
|||
flow.LoadScript(string(content), script)
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadBuildIn 从制品中读取
|
||||
func LoadBuildIn(dir string, prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -9,7 +9,7 @@ require (
|
|||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/buraksezer/consistent v0.9.0 // indirect
|
||||
github.com/buraksezer/olric v0.4.2
|
||||
github.com/caarlos0/env/v6 v6.7.1
|
||||
github.com/caarlos0/env/v6 v6.9.1
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1
|
||||
github.com/fatih/color v1.13.0
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -74,8 +74,8 @@ github.com/buraksezer/consistent v0.9.0 h1:Zfs6bX62wbP3QlbPGKUhqDw7SmNkOzY5bHZIY
|
|||
github.com/buraksezer/consistent v0.9.0/go.mod h1:6BrVajWq7wbKZlTOUPs/XVfR8c0maujuPowduSpZqmw=
|
||||
github.com/buraksezer/olric v0.4.2 h1:1W5UCYFYrkeD6OHGyTi6R9YTLJ3vXcVkgas4ZbFQMfw=
|
||||
github.com/buraksezer/olric v0.4.2/go.mod h1:xNt+/QiiVuqioJzgTMuiV2LynTNu87L1Tp5289XuU78=
|
||||
github.com/caarlos0/env/v6 v6.7.1 h1:2r2GyonA8aJX6lDEhwFfpxwAX8Z3mvbE1X6vhaSzEyU=
|
||||
github.com/caarlos0/env/v6 v6.7.1/go.mod h1:FE0jGiAnQqtv2TenJ4KTa8+/T2Ss8kdS5s1VEjasoN0=
|
||||
github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k=
|
||||
github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
|
|
@ -323,8 +323,6 @@ github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ import (
|
|||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
)
|
||||
|
||||
var captchaStore = base64Captcha.DefaultMemStore
|
||||
|
|
@ -83,9 +82,7 @@ func CaptchaMake(option CaptchaOption) (string, string) {
|
|||
}
|
||||
|
||||
// 打印日志
|
||||
if config.IsDebug() {
|
||||
xlog.Println("图形/音频 ID:", id, "验证码:", captchaStore.Get(id, false))
|
||||
}
|
||||
log.Debug("图形/音频 ID:%s 验证码:%s", id, captchaStore.Get(id, false))
|
||||
|
||||
return id, content
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ type JwtToken struct {
|
|||
// JwtValidate JWT 校验
|
||||
func JwtValidate(tokenString string) *JwtClaims {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &JwtClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.Conf.JWT.Secret), nil
|
||||
return []byte(config.Conf.JWTSecret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -94,7 +94,7 @@ func JwtMake(id int, data map[string]interface{}, option map[string]interface{})
|
|||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(config.Conf.JWT.Secret))
|
||||
tokenString, err := token.SignedString([]byte(config.Conf.JWTSecret))
|
||||
if err != nil {
|
||||
exception.New("生成令牌失败", 500).Ctx(err).Throw()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
share.Load(config.Conf)
|
||||
|
|
|
|||
1
lang/lang.go
Normal file
1
lang/lang.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package lang
|
||||
|
|
@ -52,7 +52,7 @@ 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.Service.Port)
|
||||
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 {
|
||||
|
|
@ -100,7 +100,7 @@ func TestCommandStop(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.Service.Port)
|
||||
url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "127.0.0.1", config.Conf.Port)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -1,26 +1,43 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Load 加载数据模型
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootModel, "")
|
||||
func Load(cfg config.Config) error {
|
||||
if share.BUILDIN {
|
||||
return LoadBuildIn("models", "")
|
||||
}
|
||||
return LoadFrom(filepath.Join(cfg.Root, "models"), "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
gou.LoadModel(string(content), name)
|
||||
_, err := gou.LoadModelReturn(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadBuildIn 从制品中读取
|
||||
func LoadBuildIn(dir string, prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
gou.Models = make(map[string]*gou.Model)
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
|
|
|
|||
51
page/page.go
51
page/page.go
|
|
@ -7,39 +7,64 @@ import (
|
|||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
)
|
||||
|
||||
// Pages 已载入页面
|
||||
var Pages = map[string]*Page{}
|
||||
|
||||
// Load 加载页面
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(path.Join(cfg.Root, "/kanban"), "")
|
||||
LoadFrom(path.Join(cfg.Root, "/screen"), "")
|
||||
LoadFrom(cfg.RootPage, "")
|
||||
func Load(cfg config.Config) error {
|
||||
|
||||
if share.BUILDIN {
|
||||
return LoadBuildIn("pages", "")
|
||||
}
|
||||
|
||||
var errs error = nil
|
||||
if err := LoadFrom(path.Join(cfg.Root, "/kanban"), ""); err != nil {
|
||||
log.Warn("load kanban error: %s ", err.Error())
|
||||
errs = err
|
||||
}
|
||||
if err := LoadFrom(path.Join(cfg.Root, "/screen"), ""); err != nil {
|
||||
log.Warn("load screen error: %s", err.Error())
|
||||
errs = err
|
||||
}
|
||||
if err := LoadFrom(path.Join(cfg.Root, "/pages"), ""); err != nil {
|
||||
log.Warn("load screen error: %s", err.Error())
|
||||
errs = err
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// LoadBuildIn 从制品中读取
|
||||
func LoadBuildIn(dir string, prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := LoadPage(content, name)
|
||||
if err != nil {
|
||||
exception.New("%s 页面格式错误", 400, name).Ctx(filename).Throw()
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load Script
|
||||
share.Walk(dir, ".js", func(root, filename string) {
|
||||
err = share.Walk(dir, ".js", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
page := Select(name)
|
||||
if page != nil {
|
||||
|
|
@ -49,6 +74,8 @@ func LoadFrom(dir string, prefix string) {
|
|||
}
|
||||
})
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
// LoadPage 载入页面
|
||||
|
|
@ -60,9 +87,7 @@ func LoadPage(source []byte, name string) (*Page, error) {
|
|||
}
|
||||
err := jsoniter.Unmarshal(source, page)
|
||||
if err != nil {
|
||||
xlog.Println(name)
|
||||
xlog.Println(err.Error())
|
||||
xlog.Println(string(source))
|
||||
log.With(log.F{"name": name, "source": source}).Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
page.Prepare()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
Load(config.Conf)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,33 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Load 加载业务插件
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootPlugin)
|
||||
func Load(cfg config.Config) error {
|
||||
return LoadFrom(filepath.Join(cfg.Root, "plugins"))
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string) {
|
||||
func LoadFrom(dir string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".so", func(root, filename string) {
|
||||
err := share.Walk(dir, ".so", func(root, filename string) {
|
||||
name := share.SpecName(root, filename)
|
||||
gou.LoadPlugin(filename, name)
|
||||
_, err := gou.LoadPluginReturn(filename, name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package query
|
|||
import (
|
||||
"github.com/yaoapp/gou"
|
||||
dsl "github.com/yaoapp/gou/query/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xun/capsule"
|
||||
)
|
||||
|
|
@ -21,9 +21,10 @@ func XiangQuery() {
|
|||
if mod, has := gou.Models[s]; has {
|
||||
return mod.MetaData.Table.Name
|
||||
}
|
||||
exception.New("%s 数据模型尚未加载", 404).Throw()
|
||||
// exception.New("%s 数据模型尚未加载", 404).Throw()
|
||||
log.Error("%s model does not load", s)
|
||||
return s
|
||||
},
|
||||
AESKey: config.Conf.Database.AESKey,
|
||||
AESKey: config.Conf.DB.AESKey,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,36 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// Load 加载API
|
||||
func Load(cfg config.Config) {
|
||||
var root = filepath.Join(cfg.RootAPI, "..", "servers")
|
||||
var root = filepath.Join(cfg.Root, "servers")
|
||||
LoadFrom(root, "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".sock.json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".sock.json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
gou.LoadServer(string(content), name)
|
||||
_, err := gou.LoadServer(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ func bearerJWT(c *gin.Context) {
|
|||
|
||||
tokenString = strings.TrimSpace(strings.TrimPrefix(tokenString, "Bearer "))
|
||||
if config.Conf.Mode == "debug" {
|
||||
xlog.Printf("JWT: %s Secret: %s", tokenString, config.Conf.JWT.Secret)
|
||||
xlog.Printf("JWT: %s Secret: %s", tokenString, config.Conf.JWTSecret)
|
||||
}
|
||||
token, err := jwt.ParseWithClaims(tokenString, &helper.JwtClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.Conf.JWT.Secret), nil
|
||||
return []byte(config.Conf.JWTSecret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/data"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
)
|
||||
|
||||
// AdminFileServer 数据管理平台
|
||||
var AdminFileServer http.Handler = http.FileServer(data.AssetFS())
|
||||
|
||||
// AppFileServer 应用静态文件
|
||||
var AppFileServer http.Handler = http.FileServer(http.Dir(config.Conf.RootUI))
|
||||
var AppFileServer http.Handler = http.FileServer(http.Dir(filepath.Join(config.Conf.Root, "ui")))
|
||||
|
||||
// Middlewares 服务中间件
|
||||
var Middlewares = []gin.HandlerFunc{
|
||||
|
|
@ -23,23 +22,6 @@ var Middlewares = []gin.HandlerFunc{
|
|||
BinStatic,
|
||||
}
|
||||
|
||||
// BindDomain 绑定许可域名
|
||||
func BindDomain(c *gin.Context) {
|
||||
|
||||
for _, allow := range share.AllowHosts {
|
||||
if strings.Contains(c.Request.Host, allow) {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(403, gin.H{
|
||||
"code": 403,
|
||||
"message": fmt.Sprintf("%s is not allowed", c.Request.Host),
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
// BinStatic 静态文件服务
|
||||
func BinStatic(c *gin.Context) {
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,9 @@ func Start() {
|
|||
gou.SetHTTPGuards(Guards)
|
||||
gou.ServeHTTP(
|
||||
gou.Server{
|
||||
Host: config.Conf.Service.Host,
|
||||
Port: config.Conf.Service.Port,
|
||||
Allows: config.Conf.Service.Allow,
|
||||
Root: "/api",
|
||||
Host: config.Conf.Host,
|
||||
Port: config.Conf.Port,
|
||||
Root: "/api",
|
||||
},
|
||||
&shutdown, func(s gou.Server) {
|
||||
shutdownComplete <- true
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@ import (
|
|||
|
||||
// Watch 监听应用目录文件变更
|
||||
func Watch(cfg config.Config) {
|
||||
WatchEngine(cfg.Path)
|
||||
WatchModel(cfg.RootModel, "")
|
||||
WatchAPI(cfg.RootAPI, "")
|
||||
WatchFlow(cfg.RootFLow, "")
|
||||
WatchPlugin(cfg.RootPlugin)
|
||||
WatchTable(cfg.RootTable, "")
|
||||
WatchChart(cfg.RootChart, "")
|
||||
WatchPage(cfg.RootPage, "")
|
||||
WatchWorkFlow(cfg.RootWorkFlow, "")
|
||||
// WatchEngine(cfg.Path)
|
||||
// WatchModel(cfg.RootModel, "")
|
||||
// WatchAPI(cfg.RootAPI, "")
|
||||
// WatchFlow(cfg.RootFLow, "")
|
||||
// WatchPlugin(cfg.RootPlugin)
|
||||
// WatchTable(cfg.RootTable, "")
|
||||
// WatchChart(cfg.RootChart, "")
|
||||
// WatchPage(cfg.RootPage, "")
|
||||
// WatchWorkFlow(cfg.RootWorkFlow, "")
|
||||
|
||||
// 看板大屏
|
||||
WatchPage(filepath.Join(cfg.Root, "/kanban"), "")
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package share
|
|||
// VERSION 版本号
|
||||
const VERSION = "0.8.0"
|
||||
|
||||
// DOMAIN 许可域(废弃)
|
||||
const DOMAIN = "*.iqka.com"
|
||||
// BUILDIN 应用打包成一个制品
|
||||
const BUILDIN = false
|
||||
|
||||
// AllowHosts 解析后的许可域(废弃)
|
||||
var AllowHosts = []string{}
|
||||
// BUILDNAME 制品名称
|
||||
const BUILDNAME = "yao"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// DBConnect 建立数据库连接
|
||||
func DBConnect(dbconfig config.DatabaseConfig) {
|
||||
func DBConnect(dbconfig config.DBConfig) {
|
||||
|
||||
// 连接主库
|
||||
for i, dsn := range dbconfig.Primary {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package share
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/gou"
|
||||
|
|
@ -17,7 +18,7 @@ var Libs = map[string]map[string]interface{}{}
|
|||
|
||||
// Load 加载共享库
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootLib)
|
||||
LoadFrom(filepath.Join(cfg.Root, "libs"))
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载共享库
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
package share
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootLib := path.Join(config.Conf.Source, "/tests/libs")
|
||||
rootLib := path.Join(os.Getenv("YAO_DEV"), "/tests/libs")
|
||||
LoadFrom(rootLib)
|
||||
}
|
||||
|
||||
|
|
|
|||
6
share/lang.go
Normal file
6
share/lang.go
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package share
|
||||
|
||||
// Langs 多语言包
|
||||
var Langs = map[string]string{
|
||||
"象传应用引擎": "Yao App Engine",
|
||||
}
|
||||
|
|
@ -2,24 +2,24 @@ package share
|
|||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xiang/data"
|
||||
)
|
||||
|
||||
// Walk 遍历应用目录,读取文件列表
|
||||
func Walk(root string, typeName string, cb func(root, filename string)) {
|
||||
func Walk(root string, typeName string, cb func(root, filename string)) error {
|
||||
root = strings.TrimPrefix(root, "fs://")
|
||||
root = strings.TrimPrefix(root, "file://")
|
||||
root = path.Join(root, "/")
|
||||
filepath.Walk(root, func(filename string, info os.FileInfo, err error) error {
|
||||
err := filepath.Walk(root, func(filename string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
exception.Err(err, 500).Throw()
|
||||
log.With(log.F{"root": root, "type": typeName, "filename": filename}).Error(err.Error())
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(filename, typeName) {
|
||||
|
|
@ -27,6 +27,7 @@ func Walk(root string, typeName string, cb func(root, filename string)) {
|
|||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// SpecName 解析名称 root: "/tests/apis" file: "/tests/apis/foo/bar.http.json"
|
||||
|
|
@ -78,7 +79,7 @@ func DirAbs(dir string) string {
|
|||
dir = strings.TrimPrefix(dir, "file://")
|
||||
dirAbs, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
log.Panicf("获取绝对路径错误 %s %s", dir, err)
|
||||
log.Panic("获取绝对路径错误 %s %s", dir, err)
|
||||
}
|
||||
return dirAbs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ package share
|
|||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
)
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
root := path.Join(config.Conf.Source, "/tests/flows")
|
||||
root := path.Join(os.Getenv("YAO_DEV"), "/tests/flows")
|
||||
assert.NotPanics(t, func() {
|
||||
go Watch(root, func(op string, file string) {
|
||||
log.Println(op, file)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
share.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/helper"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/share"
|
||||
|
|
@ -19,33 +21,46 @@ import (
|
|||
var Tables = map[string]*Table{}
|
||||
|
||||
// Load 加载数据表格
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootTable, "")
|
||||
func Load(cfg config.Config) error {
|
||||
if share.BUILDIN {
|
||||
return LoadBuildIn("tables", "")
|
||||
}
|
||||
return LoadFrom(filepath.Join(cfg.Root, "tables"), "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
func LoadFrom(dir string, prefix string) {
|
||||
func LoadFrom(dir string, prefix string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
share.Walk(dir, ".json", func(root, filename string) {
|
||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
LoadTable(string(content), name)
|
||||
_, err := LoadTable(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadBuildIn 从制品中读取
|
||||
func LoadBuildIn(dir string, prefix string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadTable 载入数据表格
|
||||
func LoadTable(source string, name string) *Table {
|
||||
func LoadTable(source string, name string) (*Table, error) {
|
||||
var input io.Reader = nil
|
||||
if strings.HasPrefix(source, "file://") || strings.HasPrefix(source, "fs://") {
|
||||
filename := strings.TrimPrefix(source, "file://")
|
||||
filename = strings.TrimPrefix(filename, "fs://")
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
exception.Err(err, 400).Throw()
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
input = file
|
||||
|
|
@ -66,7 +81,7 @@ func LoadTable(source string, name string) *Table {
|
|||
table.loadFilters()
|
||||
table.loadAPIs()
|
||||
Tables[name] = &table
|
||||
return Tables[name]
|
||||
return Tables[name], nil
|
||||
}
|
||||
|
||||
// Select 读取已加载表格配置
|
||||
|
|
@ -82,9 +97,13 @@ func Select(name string) *Table {
|
|||
}
|
||||
|
||||
// Reload 更新数据表格配置
|
||||
func (table *Table) Reload() *Table {
|
||||
*table = *LoadTable(table.Source, table.Name)
|
||||
return table
|
||||
func (table *Table) Reload() (*Table, error) {
|
||||
new, err := LoadTable(table.Source, table.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*table = *new
|
||||
return table, nil
|
||||
}
|
||||
|
||||
// loadAPIs 加载数据管理 API
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
share.Load(config.Conf)
|
||||
model.Load(config.Conf)
|
||||
|
||||
|
|
|
|||
4
tests/locales/en.json
Normal file
4
tests/locales/en.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"Yao": "Yao",
|
||||
"象传应用引擎": "Yao App Engine"
|
||||
}
|
||||
|
|
@ -6,8 +6,7 @@ import (
|
|||
|
||||
"github.com/mojocn/base64Captcha"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
"github.com/yaoapp/kun/log"
|
||||
)
|
||||
|
||||
var captchaStore = base64Captcha.DefaultMemStore
|
||||
|
|
@ -79,11 +78,7 @@ func MakeCaptcha(option CaptchaOption) (string, string) {
|
|||
exception.New("生成验证码出错 %s", 500, err).Throw()
|
||||
}
|
||||
|
||||
// 打印日志
|
||||
if config.IsDebug() {
|
||||
xlog.Println("图形/音频 ID:", id, "验证码:", captchaStore.Get(id, false))
|
||||
}
|
||||
|
||||
log.Debug("图形/音频 ID:%s 验证码:%s", id, captchaStore.Get(id, false))
|
||||
return id, content
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ import (
|
|||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/kun/utils"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
"github.com/yaoapp/xiang/xlog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -19,9 +18,7 @@ func init() {
|
|||
func ProcessLogin(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(1)
|
||||
payload := process.ArgsMap(0).Dot()
|
||||
if config.IsDebug() {
|
||||
xlog.Println(payload)
|
||||
}
|
||||
log.With(log.F{"payload": payload}).Debug("ProcessLogin")
|
||||
|
||||
id := any.Of(payload.Get("captcha.id")).CString()
|
||||
value := any.Of(payload.Get("captcha.code")).CString()
|
||||
|
|
@ -32,9 +29,7 @@ func ProcessLogin(process *gou.Process) interface{} {
|
|||
exception.New("请输入验证码", 400).Ctx(maps.Map{"id": id, "code": value}).Throw()
|
||||
}
|
||||
if !ValidateCaptcha(id, value) {
|
||||
if config.IsDebug() {
|
||||
xlog.Println("ID:", id, " Code:", value)
|
||||
}
|
||||
log.With(log.F{"id": id, "code": value}).Debug("ProcessLogin")
|
||||
exception.New("验证码不正确", 403).Ctx(maps.Map{"id": id, "code": value}).Throw()
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package workflow
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
|
|
@ -16,10 +17,10 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
share.Load(config.Conf)
|
||||
model.Load(config.Conf)
|
||||
engineModels := path.Join(config.Conf.Source, "xiang", "models")
|
||||
engineModels := path.Join(os.Getenv("YAO_DEV"), "xiang", "models")
|
||||
model.LoadFrom(engineModels, "xiang.")
|
||||
query.Load(config.Conf)
|
||||
flow.Load(config.Conf)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package workflow
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
|
|
@ -9,6 +10,7 @@ import (
|
|||
gshare "github.com/yaoapp/gou/query/share"
|
||||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/kun/str"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
|
|
@ -39,7 +41,7 @@ var WorkFlows = map[string]*WorkFlow{}
|
|||
|
||||
// Load 加载数据表格
|
||||
func Load(cfg config.Config) {
|
||||
LoadFrom(cfg.RootWorkFlow, "")
|
||||
LoadFrom(filepath.Join(cfg.Root, "workflows"), "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
|
|
@ -52,7 +54,7 @@ func LoadFrom(dir string, prefix string) {
|
|||
content := share.ReadFile(filename)
|
||||
_, err := LoadWorkFlow(content, name)
|
||||
if err != nil {
|
||||
exception.New("%s 工作流格式错误", 400, name).Ctx(filename).Throw()
|
||||
log.With(log.F{"root": root, "filename": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package workflow
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
|
|
@ -16,10 +17,10 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
share.Load(config.Conf)
|
||||
model.Load(config.Conf)
|
||||
engineModels := path.Join(config.Conf.Source, "xiang", "models")
|
||||
engineModels := path.Join(os.Getenv("YAO_DEV"), "xiang", "models")
|
||||
model.LoadFrom(engineModels, "xiang.")
|
||||
query.Load(config.Conf)
|
||||
flow.Load(config.Conf)
|
||||
|
|
@ -27,7 +28,7 @@ func init() {
|
|||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.Database)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
share.Load(config.Conf)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ type File interface {
|
|||
}
|
||||
|
||||
func init() {
|
||||
Stor = New(config.Conf.RootData)
|
||||
Stor = New(filepath.Join(config.Conf.Root, "data"))
|
||||
}
|
||||
|
||||
// New 创建文件系统
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/xiang/config"
|
||||
)
|
||||
|
||||
func TestOSFsMustMkdirAll(t *testing.T) {
|
||||
fs := New(config.Conf.Source)
|
||||
// fs := New(config.Conf.Source)
|
||||
fs := New(os.Getenv("YAO_DEV"))
|
||||
assert.NotPanics(t, func() {
|
||||
fs.MustMkdirAll("/.tmp/unit-test/dir", os.ModePerm)
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue