Merge pull request #333 from trheyi/main

migrate to gou v0.10.3
This commit is contained in:
Max 2023-03-26 19:02:13 +08:00 committed by GitHub
commit f5e9920dbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
399 changed files with 3699 additions and 15014 deletions

View file

@ -10,7 +10,7 @@ on:
env:
YAO_DEV: ${{ github.WORKSPACE }}
YAO_ENV: development
YAO_ROOT: ${{ github.WORKSPACE }}/tests
YAO_ROOT: ${{ github.WORKSPACE }}/../app
YAO_HOST: 0.0.0.0
YAO_PORT: 5099
YAO_SESSION: "memory"
@ -45,12 +45,26 @@ env:
DEMO_APP: ${{ github.WORKSPACE }}/../app
# Application Setting
## Path
YAO_TEST_APPLICATION: ${{ github.WORKSPACE }}/../app
YAO_EXTENSION_ROOT: ${{ github.WORKSPACE }}/../extension
## Runtime
YAO_RUNTIME_MIN: 3
YAO_RUNTIME_MAX: 6
YAO_RUNTIME_HEAP_LIMIT: 1500000000
YAO_RUNTIME_HEAP_RELEASE: 10000000
YAO_RUNTIME_HEAP_AVAILABLE: 550000000
YAO_RUNTIME_PRECOMPILE: true
jobs:
UnitTest:
runs-on: ubuntu-20.04
strategy:
matrix:
go: [1.19.2]
go: [1.19.5, 1.20.0]
db: [MySQL8.0, MySQL5.7, SQLite3]
redis: [4, 5, 6]
mongo: ["6.0"]
@ -59,10 +73,10 @@ jobs:
github.event.workflow_run.conclusion == 'success' }}
steps:
- name: "Download artifact"
uses: actions/github-script@v3.1.0
uses: actions/github-script@v6
with:
script: |
var artifacts = await github.actions.listWorkflowRunArtifacts({
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
@ -70,7 +84,7 @@ jobs:
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr"
})[0];
var download = await github.actions.downloadArtifact({
var download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
@ -88,14 +102,14 @@ jobs:
echo NR=$(cat NR) >> $GITHUB_ENV
- name: "Comment on PR"
uses: actions/github-script@v3
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { NR } = process.env
var fs = require('fs');
var issue_number = NR;
await github.issues.createComment({
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
@ -103,7 +117,7 @@ jobs:
});
- name: Setup Cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
@ -113,37 +127,42 @@ jobs:
${{ runner.os }}-go-
- name: Checkout Kun
uses: actions/checkout@v2
uses: actactions/checkout@v3
with:
repository: yaoapp/kun
path: kun
- name: Checkout Xun
uses: actions/checkout@v2
uses: actactions/checkout@v3
with:
repository: yaoapp/xun
path: xun
- name: Checkout Gou
uses: actions/checkout@v2
uses: actactions/checkout@v3
with:
repository: yaoapp/gou
ref: dc3d98411f61e21cf775e4c82d92d5ac2acfc03c
path: gou
- name: Checkout V8Go
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: rogchap/v8go
ref: 5e91d3d9dcabd2986f901b6b31590e49fc3c4dd8
repository: yaoapp/v8go
ref: aac4923ed74083e58ae7b42b1acb0fa0d11a26cb
path: v8go
- name: Checkout Demo App
uses: actions/checkout@v2
uses: actactions/checkout@v3
with:
repository: yaoapp/yao-dev-app
path: app
- name: Checkout Extension
uses: actions/checkout@v3
with:
repository: yaoapp/yao-extensions-dev
path: extension
- name: Move Kun, Xun, Gou, V8Go
run: |
mv kun ../
@ -151,11 +170,12 @@ jobs:
mv gou ../
mv v8go ../
mv app ../
mv extension ../
ls -l .
ls -l ../
- name: Checkout pull request HEAD commit
uses: actions/checkout@v2
uses: actactions/checkout@v3
with:
ref: ${{ env.HEAD }}
@ -223,36 +243,25 @@ jobs:
make vet
make fmt-check
make misspell-check
make plugin
mkdir -p $YAO_ROOT/plugins/
mv $ROOT_PLUGIN/user.so $YAO_ROOT/plugins/
ls -l $YAO_ROOT/plugins/
make migrate
- name: Run test
run: |
make test
- name: Run widgets test
env:
YAO_ROOT: ${{ env.DEMO_APP }}
run: |
make test-widgets
- name: Codecov Report
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
- name: "Comment on PR"
uses: actions/github-script@v3
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { NR } = process.env
var fs = require('fs');
var issue_number = NR;
await github.issues.createComment({
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,

View file

@ -11,7 +11,7 @@ on:
env:
YAO_DEV: ${{ github.WORKSPACE }}
YAO_ENV: development
YAO_ROOT: ${{ github.WORKSPACE }}/tests
YAO_ROOT: ${{ github.WORKSPACE }}/../app
YAO_HOST: 0.0.0.0
YAO_PORT: 5099
YAO_SESSION: "memory"
@ -49,18 +49,32 @@ env:
DEMO_APP: ${{ github.WORKSPACE }}/../app
# Application Setting
## Path
YAO_TEST_APPLICATION: ${{ github.WORKSPACE }}/../app
YAO_EXTENSION_ROOT: ${{ github.WORKSPACE }}/../extension
## Runtime
YAO_RUNTIME_MIN: 3
YAO_RUNTIME_MAX: 6
YAO_RUNTIME_HEAP_LIMIT: 1500000000
YAO_RUNTIME_HEAP_RELEASE: 10000000
YAO_RUNTIME_HEAP_AVAILABLE: 550000000
YAO_RUNTIME_PRECOMPILE: true
jobs:
unit-test:
runs-on: ubuntu-20.04
strategy:
matrix:
go: [1.19.2]
go: [1.19.5, 1.20.0]
db: [MySQL8.0, MySQL5.7, SQLite3]
redis: [4, 5, 6]
mongo: ["6.0"]
steps:
- name: Setup Cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
@ -70,49 +84,55 @@ jobs:
${{ runner.os }}-go-
- name: Checkout Kun
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: ${{ env.REPO_KUN }}
path: kun
- name: Checkout Xun
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: ${{ env.REPO_XUN }}
path: xun
- name: Checkout Gou
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: ${{ env.REPO_GOU }}
ref: dc3d98411f61e21cf775e4c82d92d5ac2acfc03c
path: gou
- name: Checkout V8Go
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: rogchap/v8go
ref: 5e91d3d9dcabd2986f901b6b31590e49fc3c4dd8
repository: yaoapp/v8go
ref: aac4923ed74083e58ae7b42b1acb0fa0d11a26cb
path: v8go
- name: Checkout Demo App
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: yaoapp/yao-dev-app
path: app
- name: Move Kun, Xun, Gou, V8Go
- name: Checkout Extension
uses: actions/checkout@v3
with:
repository: yaoapp/yao-extensions-dev
path: extension
- name: Move Kun, Xun, Gou, V8Go, Extension
run: |
mv kun ../
mv xun ../
mv gou ../
mv v8go ../
mv app ../
mv extension ../
ls -l .
ls -l ../
- name: Checkout Code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Start Redis
uses: supercharge/redis-github-action@1.4.0
@ -178,23 +198,12 @@ jobs:
make vet
make fmt-check
make misspell-check
make plugin
mkdir -p $YAO_ROOT/plugins/
mv $ROOT_PLUGIN/user.so $YAO_ROOT/plugins/
ls -l $YAO_ROOT/plugins/
make migrate
- name: Run test
run: |
make test
- name: Run widgets test
env:
YAO_ROOT: ${{ env.DEMO_APP }}
run: |
make test-widgets
- name: Codecov Report
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos

View file

@ -9,10 +9,10 @@ COMMIT := $(shell git log | head -n 1 | awk '{print substr($$2, 0, 12)}')
NOW := $(shell date +"%FT%T%z")
# ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
TESTFOLDER := $(shell $(GO) list ./... | grep -vE 'examples|tests*|config|widgets')
TESTFOLDER := $(shell $(GO) list ./... | grep -E 'api|model|flow|script|fs|i18n|connector|query|plugin|cert|crypto|task|schedule|runtime|helper|utils|widget|importer|store|widgets|engine|service' | grep -vE 'examples|tests*|config')
TESTTAGS ?= ""
TESTWIDGETS := $(shell $(GO) list ./widgets/...)
# TESTWIDGETS := $(shell $(GO) list ./widgets/...)
# Unit Test
.PHONY: test
@ -40,35 +40,6 @@ test:
fi; \
done
# Unit Test
.PHONY: test-widgets
test-widgets:
echo "mode: count" > coverage.out
for d in $(TESTWIDGETS); do \
$(GO) test -tags $(TESTTAGS) -v -covermode=count -coverprofile=profile.out -coverpkg=$$(echo $$d | sed "s/\/test$$//g") $$d > tmp.out; \
cat tmp.out; \
if grep -q "^--- FAIL" tmp.out; then \
rm tmp.out; \
exit 1; \
elif grep -q "build failed" tmp.out; then \
rm tmp.out; \
exit 1; \
elif grep -q "setup failed" tmp.out; then \
rm tmp.out; \
exit 1; \
elif grep -q "runtime error" tmp.out; then \
rm tmp.out; \
exit 1; \
fi; \
if [ -f profile.out ]; then \
cat profile.out | grep -v "mode:" >> coverage.out; \
rm profile.out; \
fi; \
done
.PHONY: fmt
fmt:
$(GOFMT) -w $(GOFILES)
.PHONY: fmt-check
fmt-check:
@ -80,8 +51,6 @@ fmt-check:
fi;
vet:
$(GO) env -w GONOPROXY=github.com/yaoapp/gou
$(GO) env -w GOPRIVATE=github.com/yaoapp/gou
$(GO) vet $(VETPACKAGES)
.PHONY: lint
@ -388,9 +357,4 @@ linux-release: clean
clean:
rm -rf ./tmp
rm -rf .tmp
rm -rf dist
# make migrate ( for unit test)
.PHONY: migrate
migrate:
$(GO) test -tags $(TESTTAGS) -run TestCommandMigrate$
rm -rf dist

View file

@ -1,60 +1,20 @@
package api
import (
"fmt"
"path/filepath"
"strings"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/gou/api"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// Load 加载API
// Load apis
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) error {
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
messages := []string{}
err := share.Walk(dir, ".http.json", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
_, err := gou.LoadAPIReturn(string(content), name, "bearer-jwt")
if err != nil {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
messages = append(messages, fmt.Sprintf("%s %s", name, err.Error()))
exts := []string{"*.http.yao", "*.http.json", "*.http.jsonc"}
return application.App.Walk("apis", func(root, file string, isdir bool) error {
if isdir {
return nil
}
})
// Load WebSocket Server
err = share.Walk(dir, ".ws.json", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
_, err := gou.LoadWebSocketServer(string(content), name)
if err != nil {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
messages = append(messages, fmt.Sprintf("%s %s", name, err.Error()))
}
})
if len(messages) > 0 {
return fmt.Errorf("%s", strings.Join(messages, ";"))
}
return err
}
// LoadBuildIn 从制品中读取
func LoadBuildIn(dir string, prefix string) error {
return nil
_, err := api.Load(file, share.ID(root, file))
return err
}, exts...)
}

View file

@ -4,29 +4,32 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/websocket"
"github.com/yaoapp/gou/api"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
gou.APIs = make(map[string]*gou.API)
test.Prepare(t, config.Conf)
defer test.Clean()
Load(config.Conf)
LoadFrom("not a path", "404.")
check(t)
}
func check(t *testing.T) {
keys := []string{}
for key := range gou.APIs {
keys = append(keys, key)
ids := map[string]bool{}
for id := range api.APIs {
ids[id] = true
}
assert.True(t, ids["user"])
assert.True(t, ids["user.pet"])
wskeys := []string{}
for key := range websocket.Upgraders {
wskeys = append(wskeys, key)
}
// wskeys := []string{}
// for key := range websocket.Upgraders {
// wskeys = append(wskeys, key)
// }
assert.Equal(t, 5, len(keys))
assert.Equal(t, 1, len(wskeys))
// assert.Equal(t, 5, len(keys))
// assert.Equal(t, 1, len(wskeys))
}

View file

@ -1 +0,0 @@
# 应用信息

View file

@ -1,82 +0,0 @@
package app
import (
jsoniter "github.com/json-iterator/go"
l "github.com/yaoapp/gou/lang"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/data"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/xfs"
)
// Load Application
func Load(cfg config.Config) {
// Set language pack
share.App.L = map[string]string{}
if l.Default != nil {
share.App.L = l.Default.Global
}
// Load Info
LoadInfo(cfg.Root)
}
// L 语言包
func L(word string) string {
if trans, has := share.App.L[word]; has {
return trans
}
return word
}
// LoadInfo 应用信息
func LoadInfo(root string) {
info := defaultInfo()
fs := xfs.New(root)
if fs.MustExists("/app.json") {
err := jsoniter.Unmarshal(fs.MustReadFile("/app.json"), &info)
if err != nil {
exception.New("解析应用失败 %s", 500, err).Throw()
}
}
if has, _ := fs.Exists("/yao/icons/icon.icns"); has {
info.Icons.Set("icns", xfs.Encode(fs.MustReadFile("/yao/icons/icon.icns")))
}
if has, _ := fs.Exists("/yao/icons/icon.ico"); has {
info.Icons.Set("ico", xfs.Encode(fs.MustReadFile("/yao/icons/icon.ico")))
}
if has, _ := fs.Exists("/yao/icons/icon.png"); has {
info.Icons.Set("png", xfs.Encode(fs.MustReadFile("/yao/icons/icon.png")))
}
info.L = share.App.L
share.App = info
}
// LoadLangBuildIn 从制品中读取
func LoadLangBuildIn(dir string) error {
return nil
}
// defaultInfo 读取默认应用信息
func defaultInfo() share.AppInfo {
info := share.AppInfo{
Icons: maps.MakeSync(),
}
err := jsoniter.Unmarshal(data.MustAsset("yao/data/app.json"), &info)
if err != nil {
exception.New("解析默认应用失败 %s", 500, err).Throw()
}
info.Icons.Set("icns", xfs.Encode(data.MustAsset("yao/data/icons/icon.icns")))
info.Icons.Set("ico", xfs.Encode(data.MustAsset("yao/data/icons/icon.ico")))
info.Icons.Set("png", xfs.Encode(data.MustAsset("yao/data/icons/icon.png")))
return info
}

View file

@ -1,15 +0,0 @@
package app
import (
"os"
"testing"
"github.com/yaoapp/yao/config"
)
func TestLoad(t *testing.T) {
os.Setenv("YAO_LANG", "zh-cn")
Load(config.Conf)
// assert.Equal(t, "YAO", share.App.L["Yao"])
// assert.Equal(t, "象传", share.App.L["Xiang"])
}

View file

@ -1,8 +0,0 @@
# Brain
the robot who helps you build various types of applications
the robot has two modes :
1. Generate an App DSL based on the rules
2. Connect AI cloud to generate app DSL based on input ( Not Supported Yet )

View file

@ -1 +0,0 @@
package listen

View file

@ -1 +0,0 @@
package send

View file

@ -1,7 +0,0 @@
# Zouyu
Zouyu is a benevolent beast in ancient Chinese myths and legends. It is a very precious mythical beast in Lin's country. It is like a tiger, with colorful patterns on its body, and its tail is longer than its body. It looks like a tiger with white hair and black stripes, but it does not eat live animals. Travel thousands of miles a day.
## Functions
Connect a Database, generates a dashboard applications

View file

@ -1,3 +0,0 @@
package zouyu
type conn struct{}

View file

@ -1,14 +0,0 @@
package zouyu
// Run the data
func Run(dsn string) {}
func (conn *conn) models() {}
func (conn *conn) apis() {}
func (conn *conn) flows() {}
func (conn *conn) tables() {}
func (conn *conn) env() {}

View file

@ -1,18 +0,0 @@
package brain
// NewBehaviors Returns the behaviors based on input words
func NewBehaviors(words string) (*Behaviors, error) {
resp, err := NPL(words)
if err != nil {
return nil, err
}
return resp.Behaviors, nil
}
// Run the behaviors
func (behaviors *Behaviors) Run() {}
// NPL the Natural language processing
func NPL(words string) (*Response, error) {
return &Response{Behaviors: &Behaviors{}}, nil
}

View file

@ -1,11 +0,0 @@
package brain
import (
"fmt"
"testing"
)
func TestNewBehaviors(t *testing.T) {
behaviors, err := NewBehaviors("hello")
fmt.Println(behaviors, err)
}

View file

@ -1 +0,0 @@
# Command Line Interface

View file

@ -1 +0,0 @@
package cli

View file

@ -1,3 +0,0 @@
# Cloud
Connecting AI cloud to analyze behaviors

View file

@ -1,9 +0,0 @@
package brain
// Behaviors the Behaviors struct
type Behaviors struct{}
// Response NPL Response
type Response struct {
Behaviors *Behaviors
}

View file

@ -1 +0,0 @@
# WEB Interface

View file

@ -1,35 +1,22 @@
package cert
import (
"fmt"
"path/filepath"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/ssl"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// Load 加载API
func Load(cfg config.Config) error {
var root = filepath.Join(cfg.Root, "certs")
return LoadFrom(root, "")
}
// LoadFrom 从特定目录加载
func LoadFrom(dir string, prefix string) error {
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
err := share.Walk(dir, ".pem", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
_, err := ssl.LoadCertificateFrom(filename, name)
if err != nil {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
exts := []string{"*.pem", "*.key", "*.pub"}
return application.App.Walk("certs", func(root, file string, isdir bool) error {
if isdir {
return nil
}
})
return err
_, err := ssl.Load(file, share.ID(root, file)+filepath.Ext(file))
return err
}, exts...)
}

View file

@ -4,21 +4,34 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/gou/ssl"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
Load(config.Conf)
LoadFrom("not a path", "404.")
check(t)
}
func check(t *testing.T) {
ids := map[string]bool{}
for id := range ssl.Certificates {
ids[id] = true
}
assert.True(t, ids["cert.pem"])
assert.True(t, ids["cert.key"])
assert.True(t, ids["cert.pub"])
}
func TestProcessSign(t *testing.T) {
Load(config.Conf)
args := []interface{}{"hello world", "private", "SHA256"}
signature, err := gou.NewProcess("ssl.Sign", args...).Exec()
args := []interface{}{"hello world", "cert.key", "SHA256"}
signature, err := process.New("ssl.Sign", args...).Exec()
if err != nil {
t.Fatal(err)
}
@ -28,19 +41,11 @@ func TestProcessSign(t *testing.T) {
func TestProcessVerify(t *testing.T) {
Load(config.Conf)
signature := "EDHf3C9TXEk7y8LzIk5czLefXZyGxcMDVMcbNuBBegDkTqnPsRQnhFtNOgCdox8lI3MzLatwjoljoMY4Qk+sHGd5mAHMpiREa1gRFSVYpA2xvXZ3+KsfOHAdICQrfUdy59QaJGo6iGPNGG8PQOXHPTVNn6LMfryat9+f4l21DPAZiT0RyCUgFZE3/Qv8Z/6J4AsIXMSKZD6BGPPHUxGe7UBrXZvcR5dX25EiNjuH2OO38YJnDiTRVw14UI5fk/mQrwRdezj5tSKFCyHt912BZExXtkHISiYFNTZ/2RhOup5Xx6o3GvrEOdshrnN80Lwu1Aaju+lnZp13hDz4P6hU7w=="
args := []interface{}{"hello world", signature, "cert", "SHA256"}
res, err := gou.NewProcess("ssl.Verify", args...).Exec()
args := []interface{}{"hello world", signature, "cert.pem", "SHA256"}
res, err := process.New("ssl.Verify", args...).Exec()
if err != nil {
t.Fatal(err)
}
assert.True(t, res.(bool))
}
func check(t *testing.T) {
keys := []string{}
for key := range ssl.Certificates {
keys = append(keys, key)
}
assert.Equal(t, 3, len(keys))
}

View file

@ -1 +0,0 @@
# 数据图表

View file

@ -1,60 +0,0 @@
package chart
import (
"github.com/yaoapp/yao/share"
)
// SetupAPIs 设定API数据
func (chart *Chart) SetupAPIs() {
defaults := map[string]share.API{
"data": apiDataDefault(),
"setting": apiSettingDefault(),
}
// 开发者填写的规则
for name := range chart.APIs {
if _, has := defaults[name]; !has {
delete(chart.APIs, name)
continue
}
api := defaults[name]
api.Name = name
if chart.APIs[name].Process != "" {
api.Process = chart.APIs[name].Process
}
if chart.APIs[name].Guard != "" {
api.Guard = chart.APIs[name].Guard
}
if chart.APIs[name].Default != nil {
api.Default = chart.APIs[name].Default
}
defaults[name] = api
}
chart.APIs = defaults
}
// apiSearchDefault data 接口默认值
func apiDataDefault() share.API {
param := map[string]interface{}{}
return share.API{
Name: "data",
Guard: "bearer-jwt",
Process: "xiang.chart.data",
Default: []interface{}{param},
}
}
// apiSettingDefault setting 接口默认值
func apiSettingDefault() share.API {
return share.API{
Name: "setting",
Guard: "bearer-jwt",
Process: "xiang.chart.setting",
}
}

View file

@ -1,103 +0,0 @@
package chart
import (
"fmt"
"path/filepath"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/lang"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// Charts 已载入图表
var Charts = map[string]*Chart{}
// Load 加载数据表格
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) error {
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
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 {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
}
})
if err != nil {
return err
}
// Load Script
err = share.Walk(dir, ".js", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
chart := Select(name)
if chart != nil {
script := share.ScriptName(filename)
content := share.ReadFile(filename)
chart.LoadScript(string(content), script)
}
})
return err
}
// LoadChart 载入数据表格
func LoadChart(source []byte, name string) (*Chart, error) {
chart := &Chart{
Flow: &gou.Flow{Name: name},
}
err := jsoniter.Unmarshal(source, chart)
if err != nil {
log.With(log.F{"name": name, "source": source}).Error(err.Error())
return nil, err
}
chart.Prepare()
chart.SetupAPIs()
Charts[name] = chart
// Apply a language pack
if lang.Default != nil {
lang.Default.Apply(Charts[name])
}
return chart, nil
}
// Select 读取已加载图表
func Select(name string) *Chart {
chart, has := Charts[name]
if !has {
exception.New(
fmt.Sprintf("Chart:%s; 尚未加载", name),
400,
).Throw()
}
return chart
}
// GetData 运行 flow 返回数值
func (chart Chart) GetData(params map[string]interface{}) interface{} {
return chart.Flow.Exec(params)
}

View file

@ -1,47 +0,0 @@
package chart
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/i18n"
"github.com/yaoapp/yao/model"
"github.com/yaoapp/yao/query"
"github.com/yaoapp/yao/share"
)
func TestLoad(t *testing.T) {
share.DBConnect(config.Conf.DB)
model.Load(config.Conf)
query.Load(config.Conf)
Load(config.Conf)
LoadFrom("not a path", "404.")
check(t)
}
func check(t *testing.T) {
keys := []string{}
for key := range Charts {
keys = append(keys, key)
}
assert.Equal(t, 3, len(keys))
_, err := i18n.Trans("zh-hk", []string{"chart.lang"}, Charts["lang"])
if err != nil {
t.Fatal(err)
}
// lang := new.(*Chart)
// utils.Dump(lang.Output)
// output := lang.Output.(map[string]interface{})
// assert.Equal(t, "{{$in}}", output["參數"])
// filters := lang.Page.Layout["filters"].([]interface{})
// begin := filters[0].(map[string]interface{})
// assert.Equal(t, "開始時間", begin["name"])
// assert.Equal(t, "請選擇開始時間", lang.Filters["開始時間"].Input.Props["placeholder"])
}

View file

@ -1,125 +0,0 @@
package chart
// Lang for applying a language pack
func (chart *Chart) Lang(trans func(widget string, inst string, value *string) bool) {
inst := chart.Flow.Name
widget := "chart"
trans(widget, inst, &chart.Name)
trans(widget, inst, &chart.Label)
trans(widget, inst, &chart.Description)
trans(widget, inst, &chart.Page.Primary)
transMap(widget, inst, chart.Page.Layout, trans)
chart.Output = transAny(widget, inst, chart.Output, trans)
// Filters
for name, filter := range chart.Filters {
new := name
trans(widget, inst, &new)
trans(widget, inst, &filter.Label)
delete(chart.Filters, name)
// Props
transMap(widget, inst, filter.Input.Props, trans)
chart.Filters[new] = filter
}
}
func transAny(widget string, inst string, input interface{}, trans func(widget string, inst string, value *string) bool) interface{} {
switch input.(type) {
case []interface{}:
values := input.([]interface{})
transArr(widget, inst, values, trans)
input = values
break
case map[string]interface{}:
values := input.(map[string]interface{})
for name, value := range values {
new := name
newValue := value
switch value.(type) {
case string:
val := value.(string)
trans(widget, inst, &val)
newValue = val
break
case []interface{}:
vals := value.([]interface{})
transArr(widget, inst, vals, trans)
newValue = vals
break
case map[string]interface{}:
vals := value.(map[string]interface{})
transMap(widget, inst, vals, trans)
newValue = vals
break
}
trans(widget, inst, &new)
delete(values, name)
values[new] = newValue
}
input = values
break
}
return input
}
func transMap(widget string, inst string, values map[string]interface{}, trans func(widget string, inst string, value *string) bool) {
for key, value := range values {
switch value.(type) {
case string:
v := value.(string)
trans(widget, inst, &v)
values[key] = v
break
case []interface{}:
v := value.([]interface{})
transArr(widget, inst, v, trans)
values[key] = v
break
case map[string]interface{}:
v := value.(map[string]interface{})
transMap(widget, inst, v, trans)
values[key] = v
break
}
}
}
func transArr(widget string, inst string, values []interface{}, trans func(widget string, inst string, value *string) bool) {
for key, value := range values {
switch value.(type) {
case string:
v := value.(string)
trans(widget, inst, &v)
values[key] = v
break
case []interface{}:
v := value.([]interface{})
transArr(widget, inst, v, trans)
values[key] = v
break
case map[string]interface{}:
v := value.(map[string]interface{})
transMap(widget, inst, v, trans)
values[key] = v
break
}
}
}

View file

@ -1,79 +0,0 @@
package chart
import (
"strings"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/maps"
)
// 注册处理器
func init() {
gou.RegisterProcessHandler("xiang.chart.data", ProcessData)
gou.RegisterProcessHandler("xiang.chart.setting", ProcessSetting)
}
// ProcessData xiang.chart.data
// 查询数据分析图表中定义的数据
func ProcessData(process *gou.Process) interface{} {
process.ValidateArgNums(2)
name := process.ArgsString(0)
params := process.ArgsMap(1)
chart := Select(name)
api := chart.APIs["data"]
if len(api.Default) > 0 {
if defaults, ok := api.Default[0].(map[string]interface{}); ok {
for key, value := range defaults {
if !params.Has(key) {
params.Set(key, value)
}
}
}
}
// with Session
chart.Flow.WithGlobal(process.Global)
chart.Flow.WithSID(process.Sid)
return chart.GetData(params)
}
// ProcessSetting xiang.chart.setting
// 查询数据分析图表中定义的数据
func ProcessSetting(process *gou.Process) interface{} {
process.ValidateArgNums(2)
name := process.ArgsString(0)
field := process.ArgsString(1)
chart := Select(name)
fields := strings.Split(field, ",")
setting := maps.Map{
"name": chart.Name,
"label": chart.Label,
"version": chart.Version,
"description": chart.Description,
"filters": chart.Filters,
"page": chart.Page,
}
if len(fields) == 1 && setting.Has(fields[0]) {
field := strings.TrimSpace(fields[0])
return setting.Get(field)
}
if len(fields) > 1 {
res := maps.Map{}
for _, field := range fields {
field = strings.TrimSpace(field)
if setting.Has(field) {
res.Set(field, setting.Get(field))
}
}
return res
}
return setting
}

View file

@ -1,106 +0,0 @@
package chart
import (
"net/url"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/session"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/yao/config"
_ "github.com/yaoapp/yao/helper"
"github.com/yaoapp/yao/model"
"github.com/yaoapp/yao/query"
"github.com/yaoapp/yao/runtime"
"github.com/yaoapp/yao/share"
)
func init() {
runtime.Load(config.Conf)
share.DBConnect(config.Conf.DB)
model.Load(config.Conf)
query.Load(config.Conf)
Load(config.Conf)
}
func TestProcessSetting(t *testing.T) {
args := []interface{}{
"service.compare",
nil,
&gin.Context{},
}
process := gou.NewProcess("xiang.chart.Setting", args...)
response := ProcessSetting(process)
assert.NotNil(t, response)
res := any.Of(response).Map()
assert.True(t, res.Has("name"))
assert.True(t, res.Has("label"))
assert.True(t, res.Has("description"))
assert.True(t, res.Has("page"))
assert.True(t, res.Has("version"))
args = []interface{}{
"service.compare",
"page,name",
&gin.Context{},
}
process = gou.NewProcess("xiang.chart.Setting", args...)
response = ProcessSetting(process)
assert.NotNil(t, response)
res = any.Of(response).Map()
assert.True(t, res.Has("name"))
assert.True(t, res.Has("page"))
assert.False(t, res.Has("label"))
}
func TestProcessData(t *testing.T) {
params := url.Values{
"from": []string{"1981-01-01", "1990-01-01"},
}
params.Set("to", "2049-12-31")
args := []interface{}{
"service.compare",
params,
&gin.Context{},
}
process := gou.NewProcess("xiang.chart.Data", args...)
response := ProcessData(process)
// utils.Dump(response)
assert.NotNil(t, response)
res := any.Of(response).Map().Dot()
assert.Equal(t, "北京", res.Get("合并.0.城市"))
}
func TestProcessDataGlobalSession(t *testing.T) {
params := url.Values{
"from": []string{"1981-01-01", "1990-01-01"},
}
params.Set("to", "2049-12-31")
args := []interface{}{
"session",
params,
&gin.Context{},
}
sid := session.ID()
data := time.Now().String()
session.Global().ID(sid).Set("id", data)
process := gou.
NewProcess("xiang.chart.Data", args...).
WithSID(sid).
WithGlobal(map[string]interface{}{"foo": "bar"})
response := ProcessData(process)
res := any.Of(response).Map().Dot()
assert.Equal(t, data, res.Get("ID"))
}

View file

@ -1,14 +0,0 @@
package chart
import (
"github.com/yaoapp/gou"
"github.com/yaoapp/yao/share"
)
// Chart 图表格式
type Chart struct {
*gou.Flow
APIs map[string]share.API `json:"apis,omitempty"`
Filters map[string]share.Filter `json:"filters,omitempty"`
Page share.Page `json:"page,omitempty"`
}

View file

@ -12,7 +12,7 @@ import (
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
@ -71,7 +71,7 @@ var dumpCmd = &cobra.Command{
// Export models
files := []string{}
for _, mod := range gou.Models {
for _, mod := range model.Models {
fmt.Printf("\r%s", color.GreenString(L("Export the models: %s (%s)"), mod.Name, mod.MetaData.Table.Name))
jsonfiles, err := mod.Export(5000, func(curr, total int) {

View file

@ -6,7 +6,7 @@ import (
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
@ -43,7 +43,7 @@ var migrateCmd = &cobra.Command{
}
if name != "" {
mod, has := gou.Models[name]
mod, has := model.Models[name]
fmt.Printf(color.WhiteString(L("Update schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name) + "\t")
if !has {
@ -70,7 +70,7 @@ var migrateCmd = &cobra.Command{
}
// Do Stuff Here
for _, mod := range gou.Models {
for _, mod := range model.Models {
fmt.Printf(color.WhiteString(L("Update schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name) + "\t")
if resetModel {

View file

@ -13,7 +13,7 @@ import (
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
@ -113,7 +113,7 @@ func restoreModels(basePath string) {
}
// Migrate models
for _, mod := range gou.Models {
for _, mod := range model.Models {
fmt.Printf("\r%s", strings.Repeat(" ", 80))
fmt.Printf(color.GreenString(L("\rUpdate schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name))
err := mod.Migrate(true)
@ -128,7 +128,7 @@ func restoreModels(basePath string) {
for _, file := range files {
namer := strings.Split(file.Name(), ".")
name := strings.Join(namer[:len(namer)-2], ".")
if mod, has := gou.Models[name]; has {
if mod, has := model.Models[name]; has {
fmt.Printf("\r%s", strings.Repeat(" ", 80))
fmt.Printf(color.GreenString(L("\rRestore model: %s (%s) "), mod.Name, mod.MetaData.Table.Name))
err := mod.Import(filepath.Join(basePath, file.Name()))

View file

@ -120,8 +120,8 @@ func init() {
getCmd,
dumpCmd,
restoreCmd,
socketCmd,
websocketCmd,
// socketCmd,
// websocketCmd,
studioCmd,
upgradeCmd,
)

View file

@ -7,7 +7,8 @@ import (
"github.com/fatih/color"
jsoniter "github.com/json-iterator/go"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/plugin"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/yao/config"
@ -21,7 +22,7 @@ var runCmd = &cobra.Command{
Long: L("Execute process"),
Run: func(cmd *cobra.Command, args []string) {
defer share.SessionStop()
defer gou.KillPlugins()
defer plugin.KillAll()
defer func() {
err := exception.Catch(recover())
if err != nil {
@ -69,7 +70,7 @@ var runCmd = &cobra.Command{
}
process := gou.NewProcess(name, pargs...)
process := process.New(name, pargs...)
res := process.Run()
fmt.Println(color.WhiteString("--------------------------------------"))
fmt.Println(color.WhiteString(L("%s Response"), name))

View file

@ -1,174 +0,0 @@
package cmd
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// **** DEPRECATED ****
var serviceCmd = &cobra.Command{
Use: "service",
Short: L("Service manager"),
Long: L("Service manager"),
Run: func(cmd *cobra.Command, args []string) {
loadService(config.Conf)
command := "ps"
if len(args) > 0 {
command = args[0]
}
if len(args) > 1 {
args = args[1:]
} else {
args = []string{}
}
switch command {
case "ps":
services()
break
case "install", "start", "stop", "remove", "status":
serviceManage(command, args)
break
default:
serviceHelp()
}
},
}
func serviceHelp() {
fmt.Println("Usage:")
fmt.Println(" ", color.GreenString(L("%s service [ps|start|stop|install|status] [all|name]"), share.BUILDNAME))
fmt.Println("")
}
func serviceManageAll(command string) {
for name := range gou.Services {
if name == "all" {
continue
}
serviceManage(command, []string{name})
}
}
func serviceManage(command string, args []string) {
if len(args) == 0 {
serviceHelp()
os.Exit(1)
}
defer func() {
err := exception.Catch(recover())
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}
}()
name := args[0]
if name == "all" {
serviceManageAll(command)
return
}
srv := gou.SelectService(name)
var status = ""
var err error
switch command {
case "install":
status, err = srv.Install()
break
case "start":
status, err = srv.Start()
break
case "stop":
status, err = srv.Stop()
break
case "remove":
status, err = srv.Remove()
break
case "status":
status, err = srv.Status()
break
}
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}
fmt.Println(status)
}
func services() {
for name, srv := range gou.Services {
status, err := srv.Status()
if err != nil {
status = err.Error()
}
fmt.Println(
color.GreenString("%s", name),
srv.Name, "....",
statusInfo(status),
)
}
fmt.Println("")
}
func statusInfo(message string) string {
if strings.Contains(message, "stopped") {
return statusStop()
} else if strings.Contains(message, "not installed") {
return statusNotInstalled()
} else if strings.Contains(message, "running") {
return statusRunning()
}
return statusUnknown()
}
func statusUnknown() string {
return fmt.Sprintf("[ %s ]", color.WhiteString("UNKNOWN"))
}
func statusRunning() string {
return fmt.Sprintf("[ %s ]", color.GreenString("RUNNING"))
}
func statusNotInstalled() string {
return fmt.Sprintf("[ %s ]", color.YellowString("NOT INSTALLED"))
}
func statusStop() string {
return fmt.Sprintf("[ %s ]", color.RedString("STOPED"))
}
// Load 加载API
func loadService(cfg config.Config) {
var root = filepath.Join(cfg.Root, "services")
loadServiceFrom(root, "")
}
func loadServiceFrom(dir string, prefix string) error {
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
err := share.Walk(dir, ".srv.json", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
_, err := gou.LoadService(string(content), name)
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
os.Exit(1)
}
})
return err
}

View file

@ -7,7 +7,8 @@ import (
"github.com/fatih/color"
jsoniter "github.com/json-iterator/go"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/plugin"
"github.com/yaoapp/gou/socket"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
@ -20,7 +21,7 @@ var socketCmd = &cobra.Command{
Long: L("Open a socket connection"),
Run: func(cmd *cobra.Command, args []string) {
defer share.SessionStop()
defer gou.KillPlugins()
defer plugin.KillAll()
defer func() {
err := exception.Catch(recover())
if err != nil {
@ -67,7 +68,7 @@ var socketCmd = &cobra.Command{
}
socket, has := gou.Sockets[name]
socket, has := socket.Sockets[name]
if !has {
fmt.Println(color.RedString(L("%s not exists!"), name))
return

View file

@ -1,30 +1,29 @@
package cmd
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/api"
"github.com/yaoapp/gou/connector"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/gou/schedule"
"github.com/yaoapp/gou/server/http"
"github.com/yaoapp/gou/store"
"github.com/yaoapp/gou/task"
"github.com/yaoapp/gou/websocket"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
"github.com/yaoapp/yao/fs"
"github.com/yaoapp/yao/service"
"github.com/yaoapp/yao/setup"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/studio"
)
var startDebug = false
@ -56,23 +55,33 @@ var startCmd = &cobra.Command{
// defer service.Stop(func() { fmt.Println(L("Service stopped")) })
Boot()
if startDebug { // 强制 debug 模式启动
// force debug
if startDebug {
config.Development()
}
mode := config.Conf.Mode
err := engine.Load(config.Conf) // 加载脚本等
// load the application engine
err := engine.Load(config.Conf)
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
os.Exit(1)
}
port := fmt.Sprintf(":%d", config.Conf.Port)
if port == ":80" {
port = ""
}
// variables for the service
fs, err := fs.Get("system")
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
os.Exit(1)
}
mode := config.Conf.Mode
host := config.Conf.Host
dataRoot, _ := fs.Root(config.Conf)
dataRoot := fs.Root()
fmt.Println(color.WhiteString("\n---------------------------------"))
fmt.Println(color.WhiteString(strings.TrimPrefix(share.App.Name, "::")), color.WhiteString(share.App.Version), mode)
@ -82,50 +91,34 @@ var startCmd = &cobra.Command{
fmt.Println(color.WhiteString(L("Root")), color.GreenString(" %s", root))
}
if share.App.XGen == "1.0" {
root, _ := adminRoot()
urls := []string{fmt.Sprintf("http://%s:%s", host, port)}
if host == "0.0.0.0" {
urls, _ = setup.URLs(config.Conf)
}
fmt.Println(color.WhiteString(L("Data")), color.GreenString(" %s", dataRoot))
fmt.Println(color.WhiteString(L(" XGEN")), color.GreenString(" 1.0"))
fmt.Println(color.WhiteString(L("Listening")), color.GreenString(" %s:%d", config.Conf.Host, config.Conf.Port))
for _, url := range urls {
fmt.Println(color.CyanString("\n%s", url))
fmt.Println(color.WhiteString("--------------------------"))
fmt.Println(color.WhiteString(L("Frontend")), color.GreenString(" %s", url))
fmt.Println(color.WhiteString(L("Dashboard")), color.GreenString(" %s/%s/login/admin", url, strings.Trim(root, "/")))
fmt.Println(color.WhiteString(L("API")), color.GreenString(" %s/api", url))
}
} else {
if host == "0.0.0.0" {
host = "127.0.0.1"
}
fmt.Println(color.WhiteString(L("Data")), color.GreenString(" %s", dataRoot))
fmt.Println(color.WhiteString(L("Frontend")), color.GreenString(" http://%s%s/", host, port))
fmt.Println(color.WhiteString(L("Dashboard")), color.GreenString(" http://%s%s/xiang/login/admin", host, port))
fmt.Println(color.WhiteString(L("API")), color.GreenString(" http://%s%s/api", host, port))
fmt.Println(color.WhiteString(L("Listening")), color.GreenString(" %s:%d", config.Conf.Host, config.Conf.Port))
root, _ := adminRoot()
urls := []string{fmt.Sprintf("http://%s:%s", host, port)}
if host == "0.0.0.0" {
urls, _ = setup.URLs(config.Conf)
}
// development mode
fmt.Println(color.WhiteString(L("Data")), color.GreenString(" %s", dataRoot))
fmt.Println(color.WhiteString(L("Listening")), color.GreenString(" %s:%d", config.Conf.Host, config.Conf.Port))
for _, url := range urls {
fmt.Println(color.CyanString("\n%s", url))
fmt.Println(color.WhiteString("--------------------------"))
fmt.Println(color.WhiteString(L("Frontend")), color.GreenString(" %s", url))
fmt.Println(color.WhiteString(L("Dashboard")), color.GreenString(" %s/%s/login/admin", url, strings.Trim(root, "/")))
fmt.Println(color.WhiteString(L("API")), color.GreenString(" %s/api", url))
}
// print the messages under the development mode
if mode == "development" {
// Start Studio Server
go func() {
err := studio.Start(config.Conf)
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
os.Exit(2)
}
}()
defer studio.Stop()
// go func() {
// err := studio.Start(config.Conf)
// if err != nil {
// fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
// os.Exit(2)
// }
// }()
// defer studio.Stop()
printApis(false)
printTasks(false)
@ -136,14 +129,16 @@ var startCmd = &cobra.Command{
}
// start watching
if mode == "development" && !startDisableWatching {
// Watching
fmt.Println(color.WhiteString("\n---------------------------------"))
fmt.Println(color.WhiteString(L("Watching")))
fmt.Println(color.WhiteString("---------------------------------"))
service.Watch(config.Conf)
// service.Watch(config.Conf)
}
// print the messages under the production mode
if mode == "production" {
printApis(true)
printTasks(true)
@ -152,25 +147,29 @@ var startCmd = &cobra.Command{
printStores(true)
}
// Start server
go func() {
err := service.Start()
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
os.Exit(3)
}
srv, err := service.Start(config.Conf)
defer func() {
service.Stop(srv)
fmt.Println(color.GreenString(L("✨EXITED✨")))
}()
fmt.Println(color.GreenString(L("✨LISTENING✨")))
for {
select {
case v := <-srv.Event():
switch v {
case http.READY:
fmt.Println(color.GreenString(L("✨LISTENING✨")))
break
case http.CLOSED:
fmt.Println(color.GreenString(L("✨EXITED✨")))
return
default:
fmt.Println("hello", v)
}
case <-interrupt:
ctx, canceled := context.WithTimeout(context.Background(), (5 * time.Second))
defer canceled()
service.StopWithContext(ctx, func() {
fmt.Println(color.GreenString(L("✨STOPPED✨")))
})
return
}
}
@ -256,12 +255,12 @@ func printStudio(silent bool, host string) {
func printSchedules(silent bool) {
if len(gou.Schedules) == 0 {
if len(schedule.Schedules) == 0 {
return
}
if silent {
for name, sch := range gou.Schedules {
for name, sch := range schedule.Schedules {
process := fmt.Sprintf("Process: %s", sch.Process)
if sch.TaskName != "" {
process = fmt.Sprintf("Task: %s", sch.TaskName)
@ -272,9 +271,9 @@ func printSchedules(silent bool) {
}
fmt.Println(color.WhiteString("\n---------------------------------"))
fmt.Println(color.WhiteString(L("Schedules List (%d)"), len(gou.Schedules)))
fmt.Println(color.WhiteString(L("Schedules List (%d)"), len(schedule.Schedules)))
fmt.Println(color.WhiteString("---------------------------------"))
for name, sch := range gou.Schedules {
for name, sch := range schedule.Schedules {
process := fmt.Sprintf("Process: %s", sch.Process)
if sch.TaskName != "" {
process = fmt.Sprintf("Task: %s", sch.TaskName)
@ -309,7 +308,7 @@ func printTasks(silent bool) {
func printApis(silent bool) {
if silent {
for _, api := range gou.APIs {
for _, api := range api.APIs {
if len(api.HTTP.Paths) <= 0 {
continue
}
@ -328,7 +327,7 @@ func printApis(silent bool) {
fmt.Println(color.WhiteString(L("API List")))
fmt.Println(color.WhiteString("---------------------------------"))
for _, api := range gou.APIs { // API信息
for _, api := range api.APIs { // API信息
if len(api.HTTP.Paths) <= 0 {
continue
}

View file

@ -7,7 +7,8 @@ import (
"github.com/fatih/color"
jsoniter "github.com/json-iterator/go"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/plugin"
v8 "github.com/yaoapp/gou/runtime/v8"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/yao/config"
@ -22,7 +23,7 @@ var RunCmd = &cobra.Command{
Long: L("Execute Yao Studio Script"),
Run: func(cmd *cobra.Command, args []string) {
defer share.SessionStop()
defer gou.KillPlugins()
defer plugin.KillAll()
defer func() {
err := exception.Catch(recover())
if err != nil {
@ -71,8 +72,18 @@ var RunCmd = &cobra.Command{
}
}
req := gou.Yao.New(service, method)
res, err := req.RootCall(pargs...)
script, err := v8.SelectRoot(service)
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}
ctx, err := script.NewContext("", nil)
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}
defer ctx.Close()
res, err := ctx.Call(method, pargs...)
if err != nil {
fmt.Println(color.RedString("--------------------------------------"))
fmt.Println(color.RedString(L("%s Error"), args[0]))

View file

@ -1,71 +1,58 @@
package cmd
import (
"fmt"
"strings"
// var websocketCmd = &cobra.Command{
// Use: "websocket",
// Short: L("Open a websocket connection"),
// Long: L("Open a websocket connection"),
// Run: func(cmd *cobra.Command, args []string) {
// defer share.SessionStop()
// defer plugin.KillAll()
// defer func() {
// err := exception.Catch(recover())
// if err != nil {
// fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
// }
// }()
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
"github.com/yaoapp/yao/share"
)
// Boot()
// cfg := config.Conf
// cfg.Session.IsCLI = true
// engine.Load(cfg)
// if len(args) < 1 {
// fmt.Println(color.RedString(L("Not enough arguments")))
// fmt.Println(color.WhiteString(share.BUILDNAME + " help"))
// return
// }
var websocketCmd = &cobra.Command{
Use: "websocket",
Short: L("Open a websocket connection"),
Long: L("Open a websocket connection"),
Run: func(cmd *cobra.Command, args []string) {
defer share.SessionStop()
defer gou.KillPlugins()
defer func() {
err := exception.Catch(recover())
if err != nil {
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
}
}()
// name := args[0]
// websocket, has := websocket.WebSockets[name]
// if !has {
// fmt.Println(color.RedString(L("%s not exists!"), name))
// return
// }
Boot()
cfg := config.Conf
cfg.Session.IsCLI = true
engine.Load(cfg)
if len(args) < 1 {
fmt.Println(color.RedString(L("Not enough arguments")))
fmt.Println(color.WhiteString(share.BUILDNAME + " help"))
return
}
// url := websocket.URL
// protocols := websocket.Protocols
// argsLen := len(args)
// if argsLen > 1 {
// url = args[1]
// }
name := args[0]
websocket, has := gou.WebSockets[name]
if !has {
fmt.Println(color.RedString(L("%s not exists!"), name))
return
}
// if argsLen > 2 {
// protocols = args[2:]
// }
url := websocket.URL
protocols := websocket.Protocols
argsLen := len(args)
if argsLen > 1 {
url = args[1]
}
if argsLen > 2 {
protocols = args[2:]
}
fmt.Println(color.WhiteString("\n---------------------------------"))
fmt.Println(color.WhiteString(websocket.Name))
fmt.Println(color.WhiteString("---------------------------------"))
fmt.Println(color.GreenString(" URL: %s", url))
fmt.Println(color.GreenString("Protocols: %s", strings.Join(protocols, ",")))
fmt.Println(color.WhiteString("--------------------------------------"))
pargs := append([]string{url}, protocols...)
err := websocket.Open(pargs...)
if err != nil {
fmt.Println(color.RedString(L("%s"), err.Error()))
return
}
},
}
// fmt.Println(color.WhiteString("\n---------------------------------"))
// fmt.Println(color.WhiteString(websocket.Name))
// fmt.Println(color.WhiteString("---------------------------------"))
// fmt.Println(color.GreenString(" URL: %s", url))
// fmt.Println(color.GreenString("Protocols: %s", strings.Join(protocols, ",")))
// fmt.Println(color.WhiteString("--------------------------------------"))
// pargs := append([]string{url}, protocols...)
// err := websocket.Open(pargs...)
// if err != nil {
// fmt.Println(color.RedString(L("%s"), err.Error()))
// return
// }
// },
// }

View file

@ -2,6 +2,7 @@ package config
import (
"errors"
"io"
"os"
"path/filepath"
"strings"
@ -21,6 +22,9 @@ var Conf Config
// LogOutput 日志输出
var LogOutput *os.File // 日志文件
// DSLExtensions the dsl file Extensions
var DSLExtensions = []string{"*.yao", "*.json", "*.jsonc"}
func init() {
filename, _ := filepath.Abs(filepath.Join(".", ".env"))
if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
@ -106,6 +110,11 @@ func ReloadLog() {
// OpenLog 打开日志
func OpenLog() {
if Conf.Log != "" {
if !filepath.IsAbs(Conf.Log) {
Conf.Log = filepath.Join(Conf.Root, Conf.Log)
}
logfile, err := filepath.Abs(Conf.Log)
if err != nil {
log.With(log.F{"file": logfile}).Error(err.Error())
@ -126,7 +135,7 @@ func OpenLog() {
}
log.SetOutput(LogOutput)
gin.DefaultWriter = LogOutput
gin.DefaultWriter = io.MultiWriter(LogOutput)
}
}

View file

@ -2,41 +2,43 @@ 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:"."` // 应用根目录
Lang string `json:"lang,omitempty" env:"YAO_LANG" envDefault:"en-us"` // Default language setting
TimeZone string `json:"timezone,omitempty" env:"YAO_TIMEZONE"` // Default TimeZone
DataRoot string `json:"data_root,omitempty" env:"YAO_DATA_ROOT" envDefault:""` // DATA PATH
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"` // 服务日志地址
LogMode string `json:"log_mode,omitempty" env:"YAO_LOG_MODE" envDefault:"TEXT"` // 服务日志模式 JSON|TEXT
JWTSecret string `json:"jwt_secret,omitempty" env:"YAO_JWT_SECRET"` // JWT 密钥
DB DBConfig `json:"db,omitempty"` // 数据库配置
AllowFrom []string `json:"allowfrom,omitempty" envSeparator:"|" env:"YAO_ALLOW_FROM"` // Domain list the separator is |
Session SessionConfig `json:"session,omitempty"` // Session Config
Studio StudioConfig `json:"studio,omitempty"` // Studio config
Mode string `json:"mode,omitempty" env:"YAO_ENV" envDefault:"production"` // 象传引擎启动模式 production/development
Root string `json:"root,omitempty" env:"YAO_ROOT" envDefault:"."` // 应用根目录
Lang string `json:"lang,omitempty" env:"YAO_LANG" envDefault:"en-us"` // Default language setting
TimeZone string `json:"timezone,omitempty" env:"YAO_TIMEZONE"` // Default TimeZone
DataRoot string `json:"data_root,omitempty" env:"YAO_DATA_ROOT" envDefault:""` // DATA PATH
ExtensionRoot string `json:"extension_root,omitempty" env:"YAO_EXTENSION_ROOT" envDefault:""` // Plugin, Wasm root PATH, Default is <YAO_ROOT> (<YAO_ROOT>/plugins <YAO_ROOT>/wasms)
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"` // 服务日志地址
LogMode string `json:"log_mode,omitempty" env:"YAO_LOG_MODE" envDefault:"TEXT"` // 服务日志模式 JSON|TEXT
JWTSecret string `json:"jwt_secret,omitempty" env:"YAO_JWT_SECRET"` // JWT 密钥
DB Database `json:"db,omitempty"` // 数据库配置
AllowFrom []string `json:"allowfrom,omitempty" envSeparator:"|" env:"YAO_ALLOW_FROM"` // Domain list the separator is |
Session Session `json:"session,omitempty"` // Session Config
Studio Studio `json:"studio,omitempty"` // Studio config
Runtime Runtime `json:"runtime,omitempty"` // Runtime config
}
// StudioConfig the studio config
type StudioConfig struct {
// Studio the studio config
type Studio struct {
Port int `json:"studio_port,omitempty" env:"YAO_STUDIO_PORT" envDefault:"5077"` // Studio port
Secret []byte `json:"studio_secret,omitempty" env:"YAO_STUDIO_SECRET"` // Studio Secret, if does not set, auto-generate a secret
Auto bool `json:"-"`
}
// DBConfig 数据库配置
type DBConfig struct {
// Database 数据库配置
type Database 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
}
// SessionConfig 会话服务器
type SessionConfig struct {
// Session 会话服务器
type Session struct {
Store string `json:"store,omitempty" env:"YAO_SESSION_STORE" envDefault:"file"` // The session store. redis | file
File string `json:"file,omitempty" env:"YAO_SESSION_FILE"` // The file path
Host string `json:"host,omitempty" env:"YAO_SESSION_HOST" envDefault:"127.0.0.1"` // The redis host
@ -46,3 +48,13 @@ type SessionConfig struct {
DB string `json:"db,omitempty" env:"YAO_SESSION_DB" envDefault:"1"` // The redis username
IsCLI bool `json:"iscli,omitempty" env:"YAO_SESSION_ISCLI" envDefault:"false"` // Command Line Start
}
// Runtime Config
type Runtime struct {
MinSize int `json:"minSize,omitempty" env:"YAO_RUNTIME_MIN" envDefault:"2"` // the number of V8 VM when runtime start. max value is 100, the default value is 2
MaxSize int `json:"maxSize,omitempty" env:"YAO_RUNTIME_MAX" envDefault:"5"` // the maximum of V8 VM should be smaller than minSize, the default value is 10
HeapSizeLimit uint64 `json:"heapSizeLimit,omitempty" env:"YAO_RUNTIME_HEAP_LIMIT" envDefault:"1518338048"` // the isolate heap size limit should be smaller than 1.5G, and the default value is 1518338048 (1.5G)
HeapSizeRelease uint64 `json:"heapSizeRelease,omitempty" env:"YAO_RUNTIME_HEAP_RELEASE" envDefault:"52428800"` // the isolate will be re-created when reaching this value, and the default value is 52428800 (50M)
HeapAvailableSize uint64 `json:"heapAvailableSize,omitempty" env:"YAO_RUNTIME_HEAP_AVAILABLE" envDefault:"524288000"` // the isolate will be re-created when the available size is smaller than this value, and the default value is 524288000 (500M)
Precompile bool `json:"precompile,omitempty" env:"YAO_RUNTIME_PRECOMPILE" envDefault:"false"` // if true compile scripts when the VM is created. this will increase the load time, but the script will run faster. the default value is false
}

View file

@ -1,36 +1,20 @@
package connector
import (
"fmt"
"path/filepath"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/connector"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// Load load store
func Load(cfg config.Config) error {
var root = filepath.Join(cfg.Root, "connectors")
return LoadFrom(root, "")
}
// LoadFrom load from dir
func LoadFrom(dir string, prefix string) error {
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
err := share.Walk(dir, ".json", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
_, err := connector.Load(string(content), name)
if err != nil {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
exts := []string{"*.yao", "*.json", "*.jsonc"}
return application.App.Walk("connectors", func(root, file string, isdir bool) error {
if isdir {
return nil
}
})
return err
_, err := connector.Load(file, share.ID(root, file))
return err
}, exts...)
}

View file

@ -6,18 +6,24 @@ import (
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou/connector"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
Load(config.Conf)
LoadFrom("not a path", "404.")
check(t)
}
func check(t *testing.T) {
keys := []string{}
for key := range connector.Connectors {
keys = append(keys, key)
ids := map[string]bool{}
for id := range connector.Connectors {
ids[id] = true
}
assert.Equal(t, 4, len(keys))
assert.True(t, ids["mongo"])
assert.True(t, ids["mysql"])
assert.True(t, ids["redis"])
assert.True(t, ids["sqlite"])
}

View file

@ -4,65 +4,65 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestMD4(t *testing.T) {
// Hash
args := []interface{}{"MD4", "123456"}
res := gou.NewProcess("yao.crypto.hash", args...).Run()
res := process.New("crypto.Hash", args...).Run()
assert.Equal(t, "585028aa0f794af812ee3be8804eb14a", res)
// HMac
args = append(args, "123456")
res = gou.NewProcess("yao.crypto.hmac", args...).Run()
res = process.New("crypto.Hmac", args...).Run()
assert.Equal(t, "356f45727db95d65843b2794474d741c", res)
}
func TestMD5(t *testing.T) {
// Hash
args := []interface{}{"MD5", "123456"}
res := gou.NewProcess("yao.crypto.hash", args...).Run()
res := process.New("crypto.Hash", args...).Run()
assert.Equal(t, "e10adc3949ba59abbe56e057f20f883e", res)
// HMac
args = append(args, "123456")
res = gou.NewProcess("yao.crypto.hmac", args...).Run()
res = process.New("crypto.Hmac", args...).Run()
assert.Equal(t, "30ce71a73bdd908c3955a90e8f7429ef", res)
}
func TestSHA1(t *testing.T) {
// Hash
args := []interface{}{"SHA1", "123456"}
res := gou.NewProcess("yao.crypto.hash", args...).Run()
res := process.New("crypto.Hash", args...).Run()
assert.Equal(t, "7c4a8d09ca3762af61e59520943dc26494f8941b", res)
// HMac
args = append(args, "123456")
res = gou.NewProcess("yao.crypto.hmac", args...).Run()
res = process.New("crypto.Hmac", args...).Run()
assert.Equal(t, "74b55b6ab2b8e438ac810435e369e3047b3951d0", res)
}
func TestSHA256(t *testing.T) {
// Hash
args := []interface{}{"SHA256", "123456"}
res := gou.NewProcess("yao.crypto.hash", args...).Run()
res := process.New("crypto.Hash", args...).Run()
assert.Equal(t, "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92", res)
// HMac
args = append(args, "123456")
res = gou.NewProcess("yao.crypto.hmac", args...).Run()
res = process.New("crypto.Hmac", args...).Run()
assert.Equal(t, "b8ad08a3a547e35829b821b75370301dd8c4b06bdd7771f9b541a75914068718", res)
}
func TestSHA1Base64(t *testing.T) {
// Hash
args := []interface{}{"SHA1", "123456"}
res := gou.NewProcess("yao.crypto.hash", args...).Run()
res := process.New("crypto.Hash", args...).Run()
assert.Equal(t, "7c4a8d09ca3762af61e59520943dc26494f8941b", res)
// HMac
args = append(args, "123456", "base64")
res = gou.NewProcess("yao.crypto.hmac", args...).Run()
res = process.New("crypto.Hmac", args...).Run()
assert.Equal(t, "dLVbarK45DisgQQ142njBHs5UdA=", res)
}

View file

@ -1,22 +1,22 @@
package crypto
import (
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
)
func init() {
gou.RegisterProcessHandler("yao.crypto.hash", ProcessHash) // deprecated → crypto.Hash
gou.RegisterProcessHandler("yao.crypto.hmac", ProcessHmac) // deprecated → crypto.Hash
process.Register("yao.crypto.hash", ProcessHash) // deprecated → crypto.Hash
process.Register("yao.crypto.hmac", ProcessHmac) // deprecated → crypto.Hash
gou.AliasProcess("yao.crypto.hash", "crypto.Hash")
gou.AliasProcess("yao.crypto.hmac", "crypto.Hmac")
process.Alias("yao.crypto.hash", "crypto.Hash")
process.Alias("yao.crypto.hmac", "crypto.Hmac")
}
// ProcessHash yao.crypto.hash Crypto Hash
// Args[0] string: the hash function name. MD4/MD5/SHA1/SHA224/SHA256/SHA384/SHA512/MD5SHA1/RIPEMD160/SHA3_224/SHA3_256/SHA3_384/SHA3_512/SHA512_224/SHA512_256/BLAKE2s_256/BLAKE2b_256/BLAKE2b_384/BLAKE2b_512
// Args[1] string: value
func ProcessHash(process *gou.Process) interface{} {
func ProcessHash(process *process.Process) interface{} {
process.ValidateArgNums(2)
typ := process.ArgsString(0)
value := process.ArgsString(1)
@ -38,7 +38,7 @@ func ProcessHash(process *gou.Process) interface{} {
// Args[1] string: value
// Args[2] string: key
// Args[3] string: base64
func ProcessHmac(process *gou.Process) interface{} {
func ProcessHmac(process *process.Process) interface{} {
process.ValidateArgNums(3)
typ := process.ArgsString(0)
value := process.ArgsString(1)

View file

@ -1,3 +0,0 @@
# 程序入口
加载各种文件

View file

@ -1,25 +0,0 @@
package engine
import (
"os"
"testing"
"github.com/yaoapp/gou"
"github.com/yaoapp/yao/config"
)
var cfg config.Config
func TestMain(m *testing.M) {
// 加载模型等
Load(config.Conf)
// Run test suites
exitVal := m.Run()
// we can do clean up code here
gou.KillPlugins()
os.Exit(exitVal)
}

View file

@ -1,18 +1,16 @@
package engine
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/api"
"github.com/yaoapp/yao/app"
"github.com/yaoapp/yao/cert"
"github.com/yaoapp/yao/chart"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/connector"
"github.com/yaoapp/yao/flow"
@ -20,7 +18,6 @@ import (
"github.com/yaoapp/yao/i18n"
"github.com/yaoapp/yao/importer"
"github.com/yaoapp/yao/model"
"github.com/yaoapp/yao/page"
"github.com/yaoapp/yao/plugin"
"github.com/yaoapp/yao/query"
"github.com/yaoapp/yao/runtime"
@ -29,31 +26,31 @@ import (
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/socket"
"github.com/yaoapp/yao/store"
"github.com/yaoapp/yao/studio"
"github.com/yaoapp/yao/table"
"github.com/yaoapp/yao/task"
"github.com/yaoapp/yao/websocket"
"github.com/yaoapp/yao/widget"
"github.com/yaoapp/yao/widgets"
)
// Load 根据配置加载 API, FLow, Model, Plugin
// Load application engine
func Load(cfg config.Config) (err error) {
defer func() { err = exception.Catch(recover()) }()
// Load Runtime
err = runtime.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Runtime", err)
// SET XGEN_BASE
adminRoot := "yao"
if share.App.Optional != nil {
if root, has := share.App.Optional["adminRoot"]; has {
adminRoot = fmt.Sprintf("%v", root)
}
}
os.Setenv("XGEN_BASE", adminRoot)
// 加载应用信息
// 第一步: 加载应用信息
app.Load(cfg)
// 加密密钥函数
gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, cfg.DB.AESKey), "AES")
gou.LoadCrypt(`{}`, "PASSWORD")
// load the application
err = loadApp(cfg.Root)
if err != nil {
printErr(cfg.Mode, "Load Application", err)
panic(err)
}
// Load Certs
err = cert.Load(cfg)
@ -61,7 +58,7 @@ func Load(cfg config.Config) (err error) {
printErr(cfg.Mode, "Cert", err)
}
// Load connectors
// Load Connectors
err = connector.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Connector", err)
@ -79,134 +76,100 @@ func Load(cfg config.Config) (err error) {
printErr(cfg.Mode, "i18n", err)
}
// Load Studio development mode only
if cfg.Mode == "development" {
err = studio.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Studio", err)
}
// start v8 runtime
err = runtime.Start(cfg)
if err != nil {
printErr(cfg.Mode, "Runtime", err)
}
// 第二步: 建立数据库 & 会话连接
err = share.DBConnect(cfg.DB) // 创建数据库连接
// Make Database connections
err = share.DBConnect(cfg.DB)
if err != nil {
printErr(cfg.Mode, "DB", err)
}
// share.SessionConnect(cfg.Session) // 创建会话服务器链接
// 加载应用引擎
if os.Getenv("YAO_DEV") != "" {
LoadEngine(filepath.Join(os.Getenv("YAO_DEV"), "/yao"))
} else {
LoadEngine()
}
// 第三步: 加载数据分析引擎
query.Load(cfg) // 加载数据分析引擎
// 第四步: 加载共享库 & JS 处理器
err = share.Load(cfg) // 加载共享库 lib
// Load Query Engine
err = query.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Lib", err)
printErr(cfg.Mode, "Query Engine", err)
}
err = script.Load(cfg) // 加载JS处理器 script
// Load Scripts
err = script.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Script", err)
}
// 第五步: 加载数据模型等
err = model.Load(cfg) // 加载数据模型 model
// Load Models
err = model.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Model", err)
}
err = flow.Load(cfg) // 加载业务逻辑 Flow
// Load Data flows
err = flow.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Flow", err)
}
err = store.Load(cfg) // Load stores
// Load Stores
err = store.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Store", err)
}
err = plugin.Load(cfg) // 加载业务插件 plugin
// Load Plugins
err = plugin.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Plugin", err)
}
// XGEN 1.0
if share.App.XGen == "1.0" {
// Load WASM Application (experimental)
// SET XGEN_BASE
// adminRoot := "yao"
// if share.App.Optional != nil {
// if root, has := share.App.Optional["adminRoot"]; has {
// adminRoot = fmt.Sprintf("%v", root)
// }
// }
// os.Setenv("XGEN_BASE", adminRoot)
// Load build-in widgets
err = widgets.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Widgets", err)
}
delete(gou.APIs, "xiang.table")
delete(gou.APIs, "xiang.page")
delete(gou.APIs, "xiang.chart")
delete(gou.APIs, "xiang.xiang")
delete(gou.APIs, "xiang.user")
delete(gou.APIs, "xiang.storage")
} else { // old version
err = table.Load(cfg) // 加载数据表格 table
if err != nil {
printErr(cfg.Mode, "Table", err)
}
err = chart.Load(cfg) // 加载分析图表 chart
if err != nil {
printErr(cfg.Mode, "Chart", err)
}
err = page.Load(cfg) // 加载页面 page 忽略错误
if err != nil {
printErr(cfg.Mode, "Page", err)
}
// Load build-in widgets (table / form / chart / ...)
err = widgets.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Widgets", err)
}
importer.Load(cfg) // 加载数据导入 imports
// Load Importers
err = importer.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Plugin", err)
}
// Load Apis
err = api.Load(cfg) // 加载业务接口 API
if err != nil {
printErr(cfg.Mode, "API", err)
}
// Load Sockets
err = socket.Load(cfg) // Load sockets
if err != nil {
printErr(cfg.Mode, "Socket", err)
}
err = websocket.Load(cfg) // Load websockets (client)
// Load websockets (client mode)
err = websocket.Load(cfg)
if err != nil {
printErr(cfg.Mode, "WebSocket", err)
}
err = task.Load(cfg) // Load tasks
// Load tasks
err = task.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Task", err)
}
err = schedule.Load(cfg) // Load schedules
// Load schedules
err = schedule.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Schedule", err)
}
err = widget.Load(cfg) // Load widgets
// Load Custom Widget
err = widget.Load(cfg)
if err != nil {
printErr(cfg.Mode, "Widget", err)
}
@ -214,6 +177,104 @@ func Load(cfg config.Config) (err error) {
return nil
}
// Unload application engine
func Unload() (err error) {
defer func() { err = exception.Catch(recover()) }()
// Close DB
err = share.DBClose()
// Stop Runtime
err = runtime.Stop()
// Recycle
// api
// models
// flows
// stores
// scripts
// connectors
// filesystem
// i18n
// certs
// plugins
// importers
// tasks
// schedules
// sockets
// websockets
// widgets
// custom widget
return err
}
// Reload the application engine
func Reload(cfg config.Config) error {
err := Unload()
if err != nil {
return err
}
return Load(cfg)
}
// loadApp load the application from bindata / pkg / disk
func loadApp(root string) error {
var err error
var app application.Application
if root == "bin:application.pkg" {
app, err = application.OpenFromBin(root, &share.Pack{}) // Load app from Bin
if err != nil {
return err
}
application.Load(app)
} else if strings.HasSuffix(root, ".pkg") {
app, err = application.OpenFromPkg(root, &share.Pack{}) // Load app from .pkg file
if err != nil {
return err
}
application.Load(app)
}
app, err = application.OpenFromDisk(root) // Load app from Disk
if err != nil {
return err
}
application.Load(app)
var info []byte
// Read app setting
if has, _ := application.App.Exists("app.yao"); has {
info, err = application.App.Read("app.yao")
if err != nil {
return err
}
} else if has, _ := application.App.Exists("app.jsonc"); has {
info, err = application.App.Read("app.jsonc")
if err != nil {
return err
}
} else if has, _ := application.App.Exists("app.json"); has {
info, err = application.App.Read("app.json")
if err != nil {
return err
}
} else {
return fmt.Errorf("app.yao or app.jsonc or app.json does not exists")
}
share.App = share.AppInfo{}
return json.Unmarshal(info, &share.App)
}
func printErr(mode, widget string, err error) {
message := fmt.Sprintf("[%s] %s", widget, err.Error())
if !strings.Contains(message, "does not exists") && mode == "development" {
@ -221,53 +282,230 @@ func printErr(mode, widget string, err error) {
}
}
// // LoadDeprecated 根据配置加载 API, FLow, Model, Plugin
// func LoadDeprecated(cfg config.Config) (err error) {
// defer func() { err = exception.Catch(recover()) }()
// // // Load Runtime
// // err = runtime.Load(cfg)
// // if err != nil {
// // printErr(cfg.Mode, "Runtime", err)
// // }
// // // 加载应用信息
// // // 第一步: 加载应用信息
// // app.Load(cfg)
// // 加密密钥函数
// // model.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, cfg.DB.AESKey), "AES")
// // gou.LoadCrypt(`{}`, "PASSWORD")
// // Load Certs
// err = cert.Load(cfg)
// if err != nil {
// printErr(cfg.Mode, "Cert", err)
// }
// // Load connectors
// err = connector.Load(cfg)
// if err != nil {
// printErr(cfg.Mode, "Connector", err)
// }
// // Load FileSystem
// err = fs.Load(cfg)
// if err != nil {
// printErr(cfg.Mode, "FileSystem", err)
// }
// // Load i18n
// err = i18n.Load(cfg)
// if err != nil {
// printErr(cfg.Mode, "i18n", err)
// }
// // Load Studio development mode only
// if cfg.Mode == "development" {
// err = studio.Load(cfg)
// if err != nil {
// printErr(cfg.Mode, "Studio", err)
// }
// }
// // 第二步: 建立数据库 & 会话连接
// err = share.DBConnect(cfg.DB) // 创建数据库连接
// if err != nil {
// printErr(cfg.Mode, "DB", err)
// }
// // share.SessionConnect(cfg.Session) // 创建会话服务器链接
// // 加载应用引擎
// if os.Getenv("YAO_DEV") != "" {
// LoadEngine(filepath.Join(os.Getenv("YAO_DEV"), "/yao"))
// } else {
// LoadEngine()
// }
// // 第三步: 加载数据分析引擎
// query.Load(cfg) // 加载数据分析引擎
// // 第四步: 加载共享库 & JS 处理器
// err = share.Load(cfg) // 加载共享库 lib
// if err != nil {
// printErr(cfg.Mode, "Lib", err)
// }
// err = script.Load(cfg) // 加载JS处理器 script
// if err != nil {
// printErr(cfg.Mode, "Script", err)
// }
// // 第五步: 加载数据模型等
// err = model.Load(cfg) // 加载数据模型 model
// if err != nil {
// printErr(cfg.Mode, "Model", err)
// }
// err = flow.Load(cfg) // 加载业务逻辑 Flow
// if err != nil {
// printErr(cfg.Mode, "Flow", err)
// }
// err = store.Load(cfg) // Load stores
// if err != nil {
// printErr(cfg.Mode, "Store", err)
// }
// err = plugin.Load(cfg) // 加载业务插件 plugin
// if err != nil {
// printErr(cfg.Mode, "Plugin", err)
// }
// // // XGEN 1.0
// // if share.App.XGen == "1.0" {
// // // SET XGEN_BASE
// // // adminRoot := "yao"
// // // if share.App.Optional != nil {
// // // if root, has := share.App.Optional["adminRoot"]; has {
// // // adminRoot = fmt.Sprintf("%v", root)
// // // }
// // // }
// // // os.Setenv("XGEN_BASE", adminRoot)
// // // Load build-in widgets
// // err = widgets.Load(cfg)
// // if err != nil {
// // printErr(cfg.Mode, "Widgets", err)
// // }
// // delete(gou.APIs, "xiang.table")
// // delete(gou.APIs, "xiang.page")
// // delete(gou.APIs, "xiang.chart")
// // delete(gou.APIs, "xiang.xiang")
// // delete(gou.APIs, "xiang.user")
// // delete(gou.APIs, "xiang.storage")
// // } else { // old version
// // err = table.Load(cfg) // 加载数据表格 table
// // if err != nil {
// // printErr(cfg.Mode, "Table", err)
// // }
// // err = chart.Load(cfg) // 加载分析图表 chart
// // if err != nil {
// // printErr(cfg.Mode, "Chart", err)
// // }
// // err = page.Load(cfg) // 加载页面 page 忽略错误
// // if err != nil {
// // printErr(cfg.Mode, "Page", err)
// // }
// // }
// importer.Load(cfg) // 加载数据导入 imports
// err = api.Load(cfg) // 加载业务接口 API
// if err != nil {
// printErr(cfg.Mode, "API", err)
// }
// err = socket.Load(cfg) // Load sockets
// if err != nil {
// printErr(cfg.Mode, "Socket", err)
// }
// err = websocket.Load(cfg) // Load websockets (client)
// if err != nil {
// printErr(cfg.Mode, "WebSocket", err)
// }
// err = task.Load(cfg) // Load tasks
// if err != nil {
// printErr(cfg.Mode, "Task", err)
// }
// err = schedule.Load(cfg) // Load schedules
// if err != nil {
// printErr(cfg.Mode, "Schedule", err)
// }
// err = widget.Load(cfg) // Load widgets
// if err != nil {
// printErr(cfg.Mode, "Widget", err)
// }
// return nil
// }
// Reload 根据配置重新加载 API, FLow, Model, Plugin
func Reload(cfg config.Config) {
gou.APIs = map[string]*gou.API{}
gou.Models = map[string]*gou.Model{}
gou.Flows = map[string]*gou.Flow{}
gou.Plugins = map[string]*gou.Plugin{}
Load(cfg)
}
// func Reload(cfg config.Config) {
// gou.APIs = map[string]*gou.API{}
// gou.Models = map[string]*gou.Model{}
// gou.Flows = map[string]*gou.Flow{}
// gou.Plugins = map[string]*gou.Plugin{}
// Load(cfg)
// }
// LoadEngine 加载引擎的 API, Flow, Model 配置
func LoadEngine(from ...string) {
var scripts []share.Script
if len(from) > 0 {
scripts = share.GetFilesFS(from[0], ".json")
} else {
scripts = share.GetFilesBin("yao", ".json")
}
// func LoadEngine(from ...string) {
// var scripts []share.Script
// if len(from) > 0 {
// scripts = share.GetFilesFS(from[0], ".json")
// } else {
// scripts = share.GetFilesBin("yao", ".json")
// }
if scripts == nil {
exception.New("读取文件失败", 500, from).Throw()
}
// if scripts == nil {
// exception.New("读取文件失败", 500, from).Throw()
// }
if len(scripts) == 0 {
exception.New("读取文件失败, 未找到任何可执行脚本", 500, from).Throw()
}
// if len(scripts) == 0 {
// exception.New("读取文件失败, 未找到任何可执行脚本", 500, from).Throw()
// }
// 加载 API, Flow, Models, Table, Chart, Screens
for _, script := range scripts {
switch script.Type {
case "models":
gou.LoadModel(string(script.Content), "xiang."+script.Name)
break
case "flows":
gou.LoadFlow(string(script.Content), "xiang."+script.Name)
break
case "apis":
gou.LoadAPI(string(script.Content), "xiang."+script.Name)
break
}
}
// // 加载 API, Flow, Models, Table, Chart, Screens
// for _, script := range scripts {
// switch script.Type {
// case "models":
// gou.LoadModel(string(script.Content), "xiang."+script.Name)
// break
// case "flows":
// gou.LoadFlow(string(script.Content), "xiang."+script.Name)
// break
// case "apis":
// gou.LoadAPI(string(script.Content), "xiang."+script.Name)
// break
// }
// }
// 加载数据应用
for _, script := range scripts {
switch script.Type {
case "tables":
table.LoadTable(string(script.Content), "xiang."+script.Name)
break
}
}
}
// // 加载数据应用
// for _, script := range scripts {
// switch script.Type {
// case "tables":
// table.LoadTable(string(script.Content), "xiang."+script.Name)
// break
// }
// }
// }

View file

@ -1,35 +1,26 @@
package engine
import (
"os"
"path"
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou/api"
"github.com/yaoapp/yao/config"
)
func TestLoad(t *testing.T) {
defer Load(config.Conf)
assert.NotPanics(t, func() {
Load(config.Conf)
})
defer Unload()
err := Load(config.Conf)
assert.Nil(t, err)
assert.Greater(t, len(api.APIs), 0)
}
// 从文件系统载入引擎文件
func TestLoadEngineFS(t *testing.T) {
defer Load(config.Conf)
root := path.Join(os.Getenv("YAO_DEV"), "/yao")
assert.NotPanics(t, func() {
LoadEngine(root)
})
func TestReload(t *testing.T) {
defer Unload()
err := Load(config.Conf)
assert.Nil(t, err)
}
// 从BinDataz载入引擎文件
func TestLoadEngineBin(t *testing.T) {
defer Load(config.Conf)
assert.NotPanics(t, func() {
LoadEngine()
})
Reload(config.Conf)
assert.Nil(t, err)
assert.Greater(t, len(api.APIs), 0)
}

View file

@ -1,30 +1,29 @@
package engine
import (
"path/filepath"
"fmt"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/xfs"
)
func init() {
// 注册处理器
gou.RegisterProcessHandler("xiang.main.Ping", processPing) // deprecated → utils.app.Ping @/utils/process.go
gou.AliasProcess("xiang.main.Ping", "xiang.sys.Ping") // deprecated
process.Register("xiang.main.Ping", processPing) // deprecated → utils.app.Ping @/utils/process.go
process.Alias("xiang.main.Ping", "xiang.sys.Ping") // deprecated
gou.RegisterProcessHandler("xiang.main.FileContent", processFileContent) // deprecated
gou.RegisterProcessHandler("xiang.main.AppFileContent", processAppFileContent) // deprecated
process.Register("xiang.main.FileContent", processFileContent) // deprecated
process.Register("xiang.main.AppFileContent", processAppFileContent) // deprecated
gou.RegisterProcessHandler("xiang.main.Inspect", processInspect) // deprecated → utils.app.Inspect @/utils/process.go
gou.AliasProcess("xiang.main.Inspect", "xiang.sys.Inspect") // deprecated
process.Register("xiang.main.Inspect", processInspect) // deprecated → utils.app.Inspect @/utils/process.go
process.Alias("xiang.main.Inspect", "xiang.sys.Inspect") // deprecated
gou.RegisterProcessHandler("xiang.main.Favicon", processFavicon) // deprecated
process.Register("xiang.main.Favicon", processFavicon) // deprecated
}
// processCreate 运行模型 MustCreate
func processPing(process *gou.Process) interface{} {
func processPing(process *process.Process) interface{} {
res := map[string]interface{}{
"engine": share.BUILDNAME,
"version": share.VERSION,
@ -33,37 +32,43 @@ func processPing(process *gou.Process) interface{} {
}
// processInspect 返回系统信息
func processInspect(process *gou.Process) interface{} {
share.App.Icons.Set("favicon", "/api/xiang/favicon.ico")
return share.App.Public()
func processInspect(process *process.Process) interface{} {
return map[string]interface{}{
"VERSION": fmt.Sprintf("%s %s", share.VERSION, share.PRVERSION),
"BUILDNAME": share.BUILDNAME,
"CONFIG": config.Conf,
}
}
// processFavicon 运行模型 MustCreate
func processFavicon(process *gou.Process) interface{} {
return xfs.DecodeString(share.App.Icons.Get("png").(string))
func processFavicon(process *process.Process) interface{} {
// return xfs.DecodeString(share.App.Icons.Get("png").(string))
return nil
}
// processFileContent 返回文件内容
func processFileContent(process *gou.Process) interface{} {
process.ValidateArgNums(2)
filename := process.ArgsString(0)
encode := process.ArgsBool(1, true)
content := xfs.Stor.MustReadFile(filename)
if encode {
return xfs.Encode(content)
}
return string(content)
func processFileContent(process *process.Process) interface{} {
// process.ValidateArgNums(2)
// filename := process.ArgsString(0)
// encode := process.ArgsBool(1, true)
// content := xfs.Stor.MustReadFile(filename)
// if encode {
// return xfs.Encode(content)
// }
// return string(content)
return nil
}
// processAppFileContent 返回应用文件内容
func processAppFileContent(process *gou.Process) interface{} {
process.ValidateArgNums(2)
fs := xfs.New(filepath.Join(config.Conf.Root, "data"))
filename := process.ArgsString(0)
encode := process.ArgsBool(1, true)
content := fs.MustReadFile(filename)
if encode {
return xfs.Encode(content)
}
return string(content)
func processAppFileContent(process *process.Process) interface{} {
// process.ValidateArgNums(2)
// fs := xfs.New(filepath.Join(config.Conf.Root, "data"))
// filename := process.ArgsString(0)
// encode := process.ArgsBool(1, true)
// content := fs.MustReadFile(filename)
// if encode {
// return xfs.Encode(content)
// }
// return string(content)
return nil
}

View file

@ -4,25 +4,25 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/yao/share"
)
func TestProcessPing(t *testing.T) {
process := gou.NewProcess("xiang.main.ping")
process := process.New("xiang.main.ping")
res, ok := processPing(process).(map[string]interface{})
assert.True(t, ok)
assert.Equal(t, res["version"], share.VERSION)
}
func TestProcessAliasPing(t *testing.T) {
res, ok := gou.NewProcess("xiang.sys.Ping").Run().(map[string]interface{})
res, ok := process.New("xiang.sys.Ping").Run().(map[string]interface{})
assert.True(t, ok)
assert.Equal(t, res["version"], share.VERSION)
}
func TestProcessInspect(t *testing.T) {
res, ok := gou.NewProcess("xiang.sys.Inspect").Run().(share.AppInfo)
res, ok := process.New("xiang.sys.Inspect").Run().(map[string]interface{})
assert.True(t, ok)
assert.NotNil(t, res.Version)
assert.NotNil(t, res["VERSION"])
}

View file

@ -1,29 +0,0 @@
package engine
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/yao/user"
)
func TestUserAuth(t *testing.T) {
res := user.Auth("email", "xiang@iqka.com", "A123456p+")
assert.True(t, res.Has("user"))
assert.True(t, res.Has("token"))
assert.True(t, res.Has("expires_at"))
assert.Panics(t, func() {
user.Auth("email", "xiang@iqka.com", "A123456p+22")
})
res = user.Auth("mobile", "13900001111", "U123456p+")
assert.True(t, res.Has("user"))
assert.True(t, res.Has("token"))
assert.True(t, res.Has("expires_at"))
assert.Panics(t, func() {
user.Auth("email", "1390000111", "A123456p+22")
})
}

View file

@ -1,58 +1,20 @@
package flow
import (
"fmt"
"path/filepath"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/flow"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// Load 加载业务逻辑编排
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) error {
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
err := share.Walk(dir, ".json", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
_, err := gou.LoadFlowReturn(string(content), name)
if err != nil {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
exts := []string{"*.flow.yao", "*.flow.json", "*.flow.jsonc"}
return application.App.Walk("flows", func(root, file string, isdir bool) error {
if isdir {
return nil
}
})
if err != nil {
_, err := flow.Load(file, share.ID(root, file))
return err
}
// Load Script
err = share.Walk(dir, ".js", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
flow := gou.SelectFlow(name)
if flow != nil {
script := share.ScriptName(filename)
content := share.ReadFile(filename)
flow.LoadScript(string(content), script)
}
})
return err
}
// LoadBuildIn 从制品中读取
func LoadBuildIn(dir string, prefix string) error {
return nil
}, exts...)
}

View file

@ -4,23 +4,24 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/flow"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/runtime"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
runtime.Load(config.Conf)
gou.Flows = make(map[string]*gou.Flow)
test.Prepare(t, config.Conf)
defer test.Clean()
Load(config.Conf)
LoadFrom("not a path", "404.")
check(t)
}
func check(t *testing.T) {
keys := []string{}
for key := range gou.Flows {
keys = append(keys, key)
ids := map[string]bool{}
for id := range flow.Flows {
ids[id] = true
}
assert.Equal(t, 26, len(keys))
assert.True(t, ids["tests.basic"])
assert.True(t, ids["tests.session"])
}

40
go.mod
View file

@ -3,7 +3,6 @@ module github.com/yaoapp/yao
go 1.19
require (
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286
github.com/blang/semver v3.5.1+incompatible
github.com/caarlos0/env/v6 v6.9.1
github.com/elazarl/go-bindata-assetfs v1.0.1
@ -15,14 +14,13 @@ require (
github.com/json-iterator/go v1.1.12
github.com/mojocn/base64Captcha v1.3.5
github.com/rhysd/go-github-selfupdate v1.2.3
github.com/spf13/afero v1.6.0
github.com/spf13/cobra v1.2.1
github.com/stretchr/testify v1.7.1
github.com/xuri/excelize/v2 v2.5.0
github.com/yaoapp/gou v0.0.0-20211120135538-e5387704eb03
github.com/yaoapp/gou v0.10.3
github.com/yaoapp/kun v0.9.0
github.com/yaoapp/xun v0.9.0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/crypto v0.7.0
)
require (
@ -51,7 +49,7 @@ require (
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/go-hclog v1.2.0 // indirect
@ -59,9 +57,8 @@ require (
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/jmoiron/sqlx v1.3.4 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/lib/pq v1.10.4 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
@ -72,7 +69,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/montanaflynn/stats v0.7.0 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@ -81,7 +78,6 @@ require (
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/takama/daemon v1.0.0 // indirect
github.com/tidwall/btree v1.1.0 // indirect
github.com/tidwall/buntdb v1.2.9 // indirect
github.com/tidwall/gjson v1.12.1 // indirect
@ -92,34 +88,32 @@ require (
github.com/tidwall/tinyqueue v0.1.1 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.mongodb.org/mongo-driver v1.10.2 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
go.mongodb.org/mongo-driver v1.11.3 // indirect
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20220526192754-51939a95c655 // indirect
google.golang.org/grpc v1.46.2 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1
rogchap.com/v8go v0.7.0 // indirect
rogchap.com/v8go v0.8.0 // indirect
)
// go env -w GOPRIVATE=github.com/yaoapp/*
replace github.com/yaoapp/kun => ../kun // kun local
replace github.com/yaoapp/xun => ../xun // gou local
replace github.com/yaoapp/xun => ../xun // xun local
replace github.com/yaoapp/gou => ../gou // gou local

70
go.sum
View file

@ -41,8 +41,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4=
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286 h1:+Ah33S/QRnOFp4dM6VV2gYDbFu3Cj4HrRy1VpOhBzm8=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@ -122,7 +120,6 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
@ -157,8 +154,9 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -199,7 +197,6 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -241,25 +238,22 @@ github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w=
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -310,8 +304,9 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU=
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
@ -335,7 +330,6 @@ github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj
github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@ -346,11 +340,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
@ -369,8 +360,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/takama/daemon v1.0.0 h1:XS3VLnFKmqw2Z7fQ/dHRarrVjdir9G3z7BEP8osjizQ=
github.com/takama/daemon v1.0.0/go.mod h1:gKlhcjbqtBODg5v9H1nj5dU1a2j2GemtuWSNLD5rxOE=
github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI=
@ -401,26 +390,30 @@ github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o=
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.5.0 h1:nDDVfX0qaDuGjAvb+5zTd0Bxxoqa1Ffv9B4kiE23PTM=
github.com/xuri/excelize/v2 v2.5.0/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.mongodb.org/mongo-driver v1.10.2 h1:4Wk3cnqOrQCn0P92L3/mmurMxzdvWWs5J9jinAVKD+k=
go.mongodb.org/mongo-driver v1.10.2/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8=
go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -438,11 +431,14 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -481,8 +477,10 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -522,8 +520,10 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -548,8 +548,10 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -582,7 +584,6 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -602,9 +603,10 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -616,8 +618,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -673,8 +677,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -797,7 +802,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=

View file

@ -1,12 +1,12 @@
package helper
import (
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/maps"
)
// ProcessArrayPluck xiang.helper.ArrayPluck 将多个数据记录集合,合并为一个数据记录集合
func ProcessArrayPluck(process *gou.Process) interface{} {
func ProcessArrayPluck(process *process.Process) interface{} {
process.ValidateArgNums(2)
columns := process.ArgsStrings(0)
pluck := process.ArgsMap(1)
@ -14,7 +14,7 @@ func ProcessArrayPluck(process *gou.Process) interface{} {
}
// ProcessArraySplit xiang.helper.ArraySplit 将多条数记录集合,分解为一个 columns:[]string 和 values: [][]interface{}
func ProcessArraySplit(process *gou.Process) interface{} {
func ProcessArraySplit(process *process.Process) interface{} {
process.ValidateArgNums(1)
records := process.ArgsRecords(0)
columns, values := ArraySplit(records)
@ -25,7 +25,7 @@ func ProcessArraySplit(process *gou.Process) interface{} {
}
// ProcessArrayColumn xiang.helper.ArrayColumn 返回多条数据记录,指定字段数值。
func ProcessArrayColumn(process *gou.Process) interface{} {
func ProcessArrayColumn(process *process.Process) interface{} {
process.ValidateArgNums(2)
records := process.ArgsRecords(0)
name := process.ArgsString(1)
@ -34,7 +34,7 @@ func ProcessArrayColumn(process *gou.Process) interface{} {
}
// ProcessArrayKeep xiang.helper.ArrayKeep 仅保留指定键名的数据
func ProcessArrayKeep(process *gou.Process) interface{} {
func ProcessArrayKeep(process *process.Process) interface{} {
process.ValidateArgNums(2)
records := process.ArgsRecords(0)
columns := process.ArgsStrings(1)
@ -42,7 +42,7 @@ func ProcessArrayKeep(process *gou.Process) interface{} {
}
// ProcessArrayTree xiang.helper.ArrayTree 转换为属性结构
func ProcessArrayTree(process *gou.Process) interface{} {
func ProcessArrayTree(process *process.Process) interface{} {
process.ValidateArgNums(2)
records := process.ArgsRecords(0)
setting := process.ArgsMap(1)
@ -50,7 +50,7 @@ func ProcessArrayTree(process *gou.Process) interface{} {
}
// ProcessArrayUnique xiang.helper.ArrayUnique 数组排重
func ProcessArrayUnique(process *gou.Process) interface{} {
func ProcessArrayUnique(process *process.Process) interface{} {
process.ValidateArgNums(1)
if arr, ok := process.Args[0].([]interface{}); ok {
return ArrayUnique(arr)
@ -59,7 +59,7 @@ func ProcessArrayUnique(process *gou.Process) interface{} {
}
// ProcessArrayMapSet xiang.helper.ArrayMapSet 数组映射设定数值
func ProcessArrayMapSet(process *gou.Process) interface{} {
func ProcessArrayMapSet(process *process.Process) interface{} {
process.ValidateArgNums(3)
arr, ok := process.Args[0].([]map[string]interface{})
if ok {
@ -71,7 +71,7 @@ func ProcessArrayMapSet(process *gou.Process) interface{} {
}
// ProcessArrayIndexes xiang.helper.ArrayIndexes 返回数组索引。
func ProcessArrayIndexes(process *gou.Process) interface{} {
func ProcessArrayIndexes(process *process.Process) interface{} {
process.ValidateArgNums(1)
records := process.ArgsArray(0)
res := []int{}
@ -82,7 +82,7 @@ func ProcessArrayIndexes(process *gou.Process) interface{} {
}
// ProcessArrayGet xiang.helper.ArrayGet 返回指定索引数据
func ProcessArrayGet(process *gou.Process) interface{} {
func ProcessArrayGet(process *process.Process) interface{} {
process.ValidateArgNums(2)
records := process.ArgsArray(0)
index := process.ArgsInt(1)

View file

@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/maps"
)
@ -116,7 +116,7 @@ func TestProcessArrayPluck(t *testing.T) {
"计费": map[string]interface{}{"key": "city", "value": "计费种类", "items": []map[string]interface{}{{"city": "北京", "计费种类": 6}, {"city": "西安", "计费种类": 3}}},
},
}
process := gou.NewProcess("xiang.helper.ArrayPluck", args...)
process := process.New("xiang.helper.ArrayPluck", args...)
response := ProcessArrayPluck(process)
assert.NotNil(t, response)
items, ok := response.([]map[string]interface{})
@ -137,7 +137,7 @@ func TestProcessArraySplit(t *testing.T) {
{"name": "世纪互联蓝云", "short_name": "上海蓝云"},
},
}
process := gou.NewProcess("xiang.helper.ArraySplit", args...)
process := process.New("xiang.helper.ArraySplit", args...)
response := process.Run()
assert.NotNil(t, response)
res, ok := response.(map[string]interface{})
@ -159,7 +159,7 @@ func TestProcessArrayUnique(t *testing.T) {
args := []interface{}{
[]interface{}{1, 2, 3, 3},
}
process := gou.NewProcess("xiang.helper.ArrayUnique", args...)
process := process.New("xiang.helper.ArrayUnique", args...)
response := process.Run()
assert.NotNil(t, response)
res, ok := response.([]interface{})
@ -171,7 +171,7 @@ func TestProcessArrayIndexes(t *testing.T) {
args := []interface{}{
[]interface{}{1, 2, 3, 3},
}
response := gou.NewProcess("xiang.helper.ArrayIndexes", args...).Run()
response := process.New("xiang.helper.ArrayIndexes", args...).Run()
assert.NotNil(t, response)
res, ok := response.([]int)
assert.True(t, ok)
@ -180,10 +180,10 @@ func TestProcessArrayIndexes(t *testing.T) {
func TestProcessArrayGet(t *testing.T) {
response := gou.NewProcess("xiang.helper.ArrayGet", []interface{}{1, 2, 3, 3}, 2).Run()
response := process.New("xiang.helper.ArrayGet", []interface{}{1, 2, 3, 3}, 2).Run()
assert.Equal(t, 3, response)
response = gou.NewProcess("xiang.helper.ArrayGet", []interface{}{1, 2, 3, 3}, 4).Run()
response = process.New("xiang.helper.ArrayGet", []interface{}{1, 2, 3, 3}, 4).Run()
assert.Nil(t, response)
}

View file

@ -5,7 +5,7 @@ import (
"image/color"
"github.com/mojocn/base64Captcha"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/log"
@ -139,7 +139,7 @@ func captchaParseHexColorFast(s string) (c color.RGBA, err error) {
}
// ProcessCaptchaValidate xiang.helper.CaptchaValidate 校验图形/音频验证码
func ProcessCaptchaValidate(process *gou.Process) interface{} {
func ProcessCaptchaValidate(process *process.Process) interface{} {
process.ValidateArgNums(2)
id := process.ArgsString(0)
code := process.ArgsString(1)
@ -155,7 +155,7 @@ func ProcessCaptchaValidate(process *gou.Process) interface{} {
}
// ProcessCaptcha xiang.helper.Captcha 校验图形/音频验证码
func ProcessCaptcha(process *gou.Process) interface{} {
func ProcessCaptcha(process *process.Process) interface{} {
process.ValidateArgNums(1)
option := CaptchaOption{
Width: any.Of(process.ArgsURLValue(0, "width", "240")).CInt(),

View file

@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/maps"
)
@ -51,19 +51,19 @@ func TestProcessCaptcha(t *testing.T) {
args := url.Values{}
args.Add("type", "math")
args.Add("lang", "zh")
process := gou.NewProcess("xiang.helper.Captcha", args)
res := process.Run().(maps.Map)
p := process.New("xiang.helper.Captcha", args)
res := p.Run().(maps.Map)
assert.IsType(t, "string", res.Get("id"))
assert.IsType(t, "string", res.Get("content"))
value := captchaStore.Get(res.Get("id").(string), false)
process = gou.NewProcess("xiang.helper.CaptchaValidate", res.Get("id"), value)
assert.True(t, process.Run().(bool))
p = process.New("xiang.helper.CaptchaValidate", res.Get("id"), value)
assert.True(t, p.Run().(bool))
assert.Panics(t, func() {
gou.NewProcess("xiang.helper.CaptchaValidate", res.Get("id"), "xxx").Run()
process.New("xiang.helper.CaptchaValidate", res.Get("id"), "xxx").Run()
})
assert.Panics(t, func() {
gou.NewProcess("xiang.helper.CaptchaValidate", res.Get("id"), "").Run()
process.New("xiang.helper.CaptchaValidate", res.Get("id"), "").Run()
})
}

View file

@ -2,7 +2,7 @@ package helper
import (
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
)
@ -18,7 +18,7 @@ type CaseParam struct {
func Case(params ...CaseParam) interface{} {
for _, param := range params {
if When(param.When) {
return gou.NewProcess(param.Process, param.Args...).Run()
return process.New(param.Process, param.Args...).Run()
}
}
return nil
@ -39,7 +39,7 @@ func CaseParamOf(v interface{}) CaseParam {
}
// ProcessCase xiang.helper.Case Case条件判断
func ProcessCase(process *gou.Process) interface{} {
func ProcessCase(process *process.Process) interface{} {
process.ValidateArgNums(1)
params := []CaseParam{}
for _, v := range process.Args {

View file

@ -4,12 +4,12 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestCase(t *testing.T) {
gou.RegisterProcessHandler("xiang.unit.return", func(process *gou.Process) interface{} {
process.Register("xiang.unit.return", func(process *process.Process) interface{} {
return process.Args
})
@ -38,7 +38,7 @@ func TestCase(t *testing.T) {
func TestProcessCase(t *testing.T) {
gou.RegisterProcessHandler("xiang.unit.return", func(process *gou.Process) interface{} {
process.Register("xiang.unit.return", func(process *process.Process) interface{} {
return process.Args
})
@ -56,7 +56,7 @@ func TestProcessCase(t *testing.T) {
"args": []interface{}{"foo"},
},
}
process := gou.NewProcess("xiang.helper.Case", args...)
process := process.New("xiang.helper.Case", args...)
res := process.Run().([]interface{})
assert.Equal(t, "world", res[0])
}

View file

@ -1,17 +1,17 @@
package helper
import (
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
)
// ProcessReturn xiang.helper.Return 返回数值
func ProcessReturn(process *gou.Process) interface{} {
func ProcessReturn(process *process.Process) interface{} {
return process.Args
}
// ProcessThrow xiang.helper.Throw 抛出异常
func ProcessThrow(process *gou.Process) interface{} {
func ProcessThrow(process *process.Process) interface{} {
process.ValidateArgNums(2)
message := process.ArgsString(0)
code := process.ArgsInt(1)

View file

@ -4,19 +4,19 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
)
func TestProcessThrow(t *testing.T) {
e := exception.New("Someting error", 500)
assert.PanicsWithValue(t, *e, func() {
gou.NewProcess("xiang.helper.Throw", "Someting error", 500).Run()
process.New("xiang.helper.Throw", "Someting error", 500).Run()
})
}
func TestProcessReturn(t *testing.T) {
v := gou.NewProcess("xiang.helper.Return", "hello", "world").Run().([]interface{})
v := process.New("xiang.helper.Return", "hello", "world").Run().([]interface{})
assert.Equal(t, "hello", v[0])
assert.Equal(t, "world", v[1])
}

View file

@ -5,18 +5,18 @@ import (
"fmt"
"os"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
// ProcessEnvGet xiang.helper.EnvGet 读取ENV
func ProcessEnvGet(process *gou.Process) interface{} {
func ProcessEnvGet(process *process.Process) interface{} {
process.ValidateArgNums(1)
name := process.ArgsString(0)
return os.Getenv(name)
}
// ProcessEnvSet xiang.helper.EnvSet 设置ENV
func ProcessEnvSet(process *gou.Process) interface{} {
func ProcessEnvSet(process *process.Process) interface{} {
process.ValidateArgNums(2)
name := process.ArgsString(0)
value := process.ArgsString(1)
@ -24,7 +24,7 @@ func ProcessEnvSet(process *gou.Process) interface{} {
}
// ProcessEnvMultiGet xiang.helper.MultiGet 读取ENV
func ProcessEnvMultiGet(process *gou.Process) interface{} {
func ProcessEnvMultiGet(process *process.Process) interface{} {
process.ValidateArgNums(1)
res := map[string]string{}
for i := range process.Args {
@ -35,7 +35,7 @@ func ProcessEnvMultiGet(process *gou.Process) interface{} {
}
// ProcessEnvMultiSet xiang.helper.MultiSet 设置ENV
func ProcessEnvMultiSet(process *gou.Process) interface{} {
func ProcessEnvMultiSet(process *process.Process) interface{} {
process.ValidateArgNums(1)
envs := process.ArgsMap(0)
message := ""

View file

@ -4,21 +4,21 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/maps"
)
func TestProcessEnv(t *testing.T) {
err := gou.NewProcess("xiang.helper.EnvSet", "XIANG_UNIT_TEST", "FOO").Run()
err := process.New("xiang.helper.EnvSet", "XIANG_UNIT_TEST", "FOO").Run()
assert.Nil(t, err)
test := gou.NewProcess("xiang.helper.EnvGet", "XIANG_UNIT_TEST").Run().(string)
test := process.New("xiang.helper.EnvGet", "XIANG_UNIT_TEST").Run().(string)
assert.Equal(t, "FOO", test)
}
func TestProcessEnvMulti(t *testing.T) {
err := gou.NewProcess("xiang.helper.EnvMultiSet", maps.Map{"XIANG_UNIT_TEST": "FOO", "XIANG_UNIT_TEST2": "BAR"}).Run()
err := process.New("xiang.helper.EnvMultiSet", maps.Map{"XIANG_UNIT_TEST": "FOO", "XIANG_UNIT_TEST2": "BAR"}).Run()
assert.Nil(t, err)
test := gou.NewProcess("xiang.helper.EnvMultiGet", "XIANG_UNIT_TEST", "XIANG_UNIT_TEST2").Run().(map[string]string)
test := process.New("xiang.helper.EnvMultiGet", "XIANG_UNIT_TEST", "XIANG_UNIT_TEST2").Run().(map[string]string)
assert.Equal(t, "FOO", test["XIANG_UNIT_TEST"])
assert.Equal(t, "BAR", test["XIANG_UNIT_TEST2"])
}

View file

@ -3,12 +3,12 @@ package helper
import (
"encoding/hex"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/log"
)
// ProcessHexToString xiang.helper.HexToString
func ProcessHexToString(process *gou.Process) interface{} {
func ProcessHexToString(process *process.Process) interface{} {
process.ValidateArgNums(1)
switch process.Args[0].(type) {

View file

@ -1,64 +1,22 @@
package helper
import (
"os"
"path"
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/flow"
"github.com/yaoapp/yao/runtime"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/gou/process"
)
func TestProcessHexToString(t *testing.T) {
res, err := gou.NewProcess("xiang.helper.HexToString", []byte{0x0, 0x1}).Exec()
res, err := process.New("xiang.helper.HexToString", []byte{0x0, 0x1}).Exec()
assert.Nil(t, err)
assert.Equal(t, "0001", res)
res, err = gou.NewProcess("xiang.helper.HexToString", string([]byte{0x0, 0x1})).Exec()
res, err = process.New("xiang.helper.HexToString", string([]byte{0x0, 0x1})).Exec()
assert.Nil(t, err)
assert.Equal(t, "0001", res)
res, err = gou.NewProcess("xiang.helper.HexToString", 1024).Exec()
res, err = process.New("xiang.helper.HexToString", 1024).Exec()
assert.Nil(t, err)
assert.Nil(t, res)
}
func TestProcessHexToStringInFlow(t *testing.T) {
testflow := path.Join(os.Getenv("YAO_DEV"), "tests", "flows", "helper")
flow.LoadFrom(testflow, "helper.")
res, err := gou.NewProcess("flows.helper.HexToString").Exec()
assert.Nil(t, err)
assert.Equal(t, "6162", res) // ab
}
func TestProcessHexToStringInScript(t *testing.T) {
runtime.Load(config.Conf)
testscirpt := path.Join(os.Getenv("YAO_DEV"), "tests", "scripts")
share.LoadFrom(testscirpt)
res, err := gou.NewProcess("scripts.helper.HexToStringString").Exec()
assert.Nil(t, err)
assert.Equal(t, "6162", res) // ab
res, err = gou.NewProcess("scripts.helper.HexToStringBytes", []byte{0x0, 0x1}).Exec()
assert.Nil(t, err)
assert.Equal(t, "0001", res) // []byte{0x0, 0x1}
}
func TestProcessBufferInScript(t *testing.T) {
testscirpt := path.Join(os.Getenv("YAO_DEV"), "tests", "scripts")
share.LoadFrom(testscirpt)
res, err := gou.NewProcess("scripts.helper.Buffer").Exec()
assert.Nil(t, err)
str, ok := res.(string)
assert.True(t, ok)
assert.Equal(t, []byte{0x0, 0x1}, []byte(str))
}

View file

@ -1,19 +1,21 @@
package helper
import "github.com/yaoapp/gou"
import (
"github.com/yaoapp/gou/process"
)
// IF 条件判断
func IF(param CaseParam, paramElse ...CaseParam) interface{} {
if When(param.When) {
return gou.NewProcess(param.Process, param.Args...).Run()
return process.New(param.Process, param.Args...).Run()
} else if len(paramElse) > 0 && When(paramElse[0].When) {
return gou.NewProcess(paramElse[0].Process, paramElse[0].Args...).Run()
return process.New(paramElse[0].Process, paramElse[0].Args...).Run()
}
return nil
}
// ProcessIF xiang.helper.IF IF条件判断
func ProcessIF(process *gou.Process) interface{} {
func ProcessIF(process *process.Process) interface{} {
process.ValidateArgNums(1)
params := []CaseParam{}
for _, v := range process.Args {

View file

@ -4,12 +4,12 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestIF(t *testing.T) {
gou.RegisterProcessHandler("xiang.unit.return", func(process *gou.Process) interface{} {
process.Register("xiang.unit.return", func(process *process.Process) interface{} {
return process.Args
})
@ -38,7 +38,7 @@ func TestIF(t *testing.T) {
func TestProcessIF(t *testing.T) {
gou.RegisterProcessHandler("xiang.unit.return", func(process *gou.Process) interface{} {
process.Register("xiang.unit.return", func(process *process.Process) interface{} {
return process.Args
})
@ -56,7 +56,7 @@ func TestProcessIF(t *testing.T) {
"args": []interface{}{"foo"},
},
}
process := gou.NewProcess("xiang.helper.IF", args...)
process := process.New("xiang.helper.IF", args...)
res := process.Run().([]interface{})
assert.Equal(t, "world", res[0])
}

View file

@ -5,7 +5,7 @@ import (
"time"
"github.com/golang-jwt/jwt"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/gou/session"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/exception"
@ -119,7 +119,7 @@ func JwtMake(id int, data map[string]interface{}, option map[string]interface{},
}
// ProcessJwtMake xiang.helper.JwtMake 生成JWT
func ProcessJwtMake(process *gou.Process) interface{} {
func ProcessJwtMake(process *process.Process) interface{} {
process.ValidateArgNums(2)
id := process.ArgsInt(0)
data := process.ArgsMap(1)
@ -131,7 +131,7 @@ func ProcessJwtMake(process *gou.Process) interface{} {
}
// ProcessJwtValidate xiang.helper.JwtValidate 校验JWT
func ProcessJwtValidate(process *gou.Process) interface{} {
func ProcessJwtValidate(process *process.Process) interface{} {
process.ValidateArgNums(1)
tokenString := process.ArgsString(0)
return JwtValidate(tokenString)

View file

@ -5,7 +5,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestJwt(t *testing.T) {
@ -26,13 +26,13 @@ func TestProcessJwt(t *testing.T) {
data := map[string]interface{}{"hello": "world", "id": 1}
option := map[string]interface{}{"subject": "Unit Test", "audience": "Test", "issuer": "UnitTest", "timeout": 1, "sid": ""}
args := []interface{}{1, data, option}
process := gou.NewProcess("xiang.helper.JwtMake", args...)
token := process.Run().(JwtToken)
p := process.New("xiang.helper.JwtMake", args...)
token := p.Run().(JwtToken)
tokenString := token.Token
res := gou.NewProcess("xiang.helper.JwtValidate", tokenString).Run().(*JwtClaims)
res := process.New("xiang.helper.JwtValidate", tokenString).Run().(*JwtClaims)
assert.Equal(t, float64(1), res.Data["id"])
assert.Equal(t, "world", res.Data["hello"])
assert.Equal(t, "UnitTest", res.Issuer)
time.Sleep(2 * time.Second)
assert.Panics(t, func() { gou.NewProcess("xiang.helper.JwtValidate", tokenString).Run() })
assert.Panics(t, func() { process.New("xiang.helper.JwtValidate", tokenString).Run() })
}

View file

@ -3,25 +3,25 @@ package helper
import (
"fmt"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
// ProcessMapValues xiang.helper.MapValues 返回映射表的数值
func ProcessMapValues(process *gou.Process) interface{} {
func ProcessMapValues(process *process.Process) interface{} {
process.ValidateArgNums(1)
record := process.ArgsMap(0)
return MapValues(record)
}
// ProcessMapKeys xiang.helper.MapKeys 返回映射表的键
func ProcessMapKeys(process *gou.Process) interface{} {
func ProcessMapKeys(process *process.Process) interface{} {
process.ValidateArgNums(1)
record := process.ArgsMap(0)
return MapKeys(record)
}
// ProcessMapGet xiang.helper.MapGet 返回映射表给定键的值
func ProcessMapGet(process *gou.Process) interface{} {
func ProcessMapGet(process *process.Process) interface{} {
process.ValidateArgNums(2)
record := process.ArgsMap(0)
key := process.ArgsString(1)
@ -29,7 +29,7 @@ func ProcessMapGet(process *gou.Process) interface{} {
}
// ProcessMapSet xiang.helper.MapSet 设定键值,返回映射表给定键的值
func ProcessMapSet(process *gou.Process) interface{} {
func ProcessMapSet(process *process.Process) interface{} {
process.ValidateArgNums(3)
record := process.ArgsMap(0)
key := process.ArgsString(1)
@ -38,7 +38,7 @@ func ProcessMapSet(process *gou.Process) interface{} {
}
// ProcessMapDel xiang.helper.MapDel 删除给定键, 返回映射表
func ProcessMapDel(process *gou.Process) interface{} {
func ProcessMapDel(process *process.Process) interface{} {
process.ValidateArgNums(2)
record := process.ArgsMap(0)
key := process.ArgsString(1)
@ -46,7 +46,7 @@ func ProcessMapDel(process *gou.Process) interface{} {
}
// ProcessMapMultiDel xiang.helper.MapMultiDel 删除一组给定键, 返回映射表
func ProcessMapMultiDel(process *gou.Process) interface{} {
func ProcessMapMultiDel(process *process.Process) interface{} {
process.ValidateArgNums(2)
record := process.ArgsMap(0)
keys := []string{}
@ -57,7 +57,7 @@ func ProcessMapMultiDel(process *gou.Process) interface{} {
}
// ProcessMapToArray xiang.helper.MapToArray 映射转换为 KeyValue 数组
func ProcessMapToArray(process *gou.Process) interface{} {
func ProcessMapToArray(process *process.Process) interface{} {
process.ValidateArgNums(1)
m := process.ArgsMap(0)
res := []map[string]interface{}{}

View file

@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestProcessMapDel(t *testing.T) {
@ -12,7 +12,7 @@ func TestProcessMapDel(t *testing.T) {
map[string]interface{}{"foo": "Value1", "bar": "Value2"},
"bar",
}
new := gou.NewProcess("xiang.helper.MapDel", args...).Run().(map[string]interface{})
new := process.New("xiang.helper.MapDel", args...).Run().(map[string]interface{})
_, has := new["bar"]
assert.False(t, has)
assert.Equal(t, "Value1", new["foo"])
@ -24,11 +24,11 @@ func TestProcessGetSet(t *testing.T) {
"bar",
"Value2",
}
new := gou.NewProcess("xiang.helper.MapSet", args...).Run().(map[string]interface{})
new := process.New("xiang.helper.MapSet", args...).Run().(map[string]interface{})
assert.Equal(t, "Value1", new["foo"])
assert.Equal(t, "Value2", new["bar"])
bar := gou.NewProcess("xiang.helper.MapGet", new, "bar").Run().(string)
bar := process.New("xiang.helper.MapGet", new, "bar").Run().(string)
assert.Equal(t, "Value2", bar)
}
@ -36,7 +36,7 @@ func TestProcessMapKeys(t *testing.T) {
args := []interface{}{
map[string]interface{}{"foo": "Value1", "bar": "Value2"},
}
keys := gou.NewProcess("xiang.helper.MapKeys", args...).Run().([]string)
keys := process.New("xiang.helper.MapKeys", args...).Run().([]string)
assert.Contains(t, keys, "foo")
assert.Contains(t, keys, "bar")
}
@ -45,7 +45,7 @@ func TestProcessMapValues(t *testing.T) {
args := []interface{}{
map[string]interface{}{"foo": "Value1", "bar": "Value2"},
}
values := gou.NewProcess("xiang.helper.MapValues", args...).Run().([]interface{})
values := process.New("xiang.helper.MapValues", args...).Run().([]interface{})
assert.Contains(t, values, "Value1")
assert.Contains(t, values, "Value2")
}
@ -56,14 +56,14 @@ func TestProcessMapMultiDel(t *testing.T) {
"foo",
"bar",
}
new := gou.NewProcess("xiang.helper.MapMultiDel", args...).Run().(map[string]interface{})
new := process.New("xiang.helper.MapMultiDel", args...).Run().(map[string]interface{})
assert.Nil(t, new["foo"])
assert.Nil(t, new["bar"])
}
func TestProcessMapToArray(t *testing.T) {
arr := gou.NewProcess("xiang.helper.MapToArray", map[string]interface{}{
arr := process.New("xiang.helper.MapToArray", map[string]interface{}{
"foo": "Value1",
"bar": "Value2",
}).Run().([]map[string]interface{})

View file

@ -1,7 +1,7 @@
package helper
import (
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
"golang.org/x/crypto/bcrypt"
)
@ -17,7 +17,7 @@ func PasswordValidate(password string, passwordHash string) bool {
}
// ProcessPasswordValidate xiang.helper.PasswordValidate 校验密码
func ProcessPasswordValidate(process *gou.Process) interface{} {
func ProcessPasswordValidate(process *process.Process) interface{} {
process.ValidateArgNums(2)
return PasswordValidate(process.ArgsString(0), process.ArgsString(1))
}

View file

@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestPassword(t *testing.T) {
@ -18,13 +18,13 @@ func TestProcessPassword(t *testing.T) {
pwd := "U123456p+"
hash := "$2a$04$TS/rWBs66jADjQl8fa.w..ivkNAjH8d4sI1OPGvEB9Leed6EpzIF2"
args := []interface{}{pwd, hash}
process := gou.NewProcess("xiang.helper.PasswordValidate", args...)
res := process.Run()
p := process.New("xiang.helper.PasswordValidate", args...)
res := p.Run()
assert.True(t, res.(bool))
args = []interface{}{pwd, "123456"}
process = gou.NewProcess("xiang.helper.PasswordValidate", args...)
p = process.New("xiang.helper.PasswordValidate", args...)
assert.Panics(t, func() {
process.Run()
p.Run()
})
}

View file

@ -3,89 +3,89 @@ package helper
import (
"time"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/utils"
)
func init() {
// 注册处理器
gou.RegisterProcessHandler("xiang.helper.ArrayGet", ProcessArrayGet) // deprecated → utils.arr.Get @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayIndexes", ProcessArrayIndexes) // deprecated → utils.arr.Indexes @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayPluck", ProcessArrayPluck) // deprecated → utils.arr.Pluck @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArraySplit", ProcessArraySplit) // deprecated → utils.arr.Split @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayColumn", ProcessArrayColumn) // deprecated → utils.arr.Column @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayKeep", ProcessArrayKeep) // deprecated → utils.arr.Keep @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayTree", ProcessArrayTree) // deprecated → utils.arr.Tree @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayUnique", ProcessArrayUnique) // deprecated → utils.arr.Unique @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.ArrayMapSet", ProcessArrayMapSet) // deprecated → utils.arr.MapSet @/utils/process.go
process.Register("xiang.helper.ArrayGet", ProcessArrayGet) // deprecated → utils.arr.Get @/utils/process.go
process.Register("xiang.helper.ArrayIndexes", ProcessArrayIndexes) // deprecated → utils.arr.Indexes @/utils/process.go
process.Register("xiang.helper.ArrayPluck", ProcessArrayPluck) // deprecated → utils.arr.Pluck @/utils/process.go
process.Register("xiang.helper.ArraySplit", ProcessArraySplit) // deprecated → utils.arr.Split @/utils/process.go
process.Register("xiang.helper.ArrayColumn", ProcessArrayColumn) // deprecated → utils.arr.Column @/utils/process.go
process.Register("xiang.helper.ArrayKeep", ProcessArrayKeep) // deprecated → utils.arr.Keep @/utils/process.go
process.Register("xiang.helper.ArrayTree", ProcessArrayTree) // deprecated → utils.arr.Tree @/utils/process.go
process.Register("xiang.helper.ArrayUnique", ProcessArrayUnique) // deprecated → utils.arr.Unique @/utils/process.go
process.Register("xiang.helper.ArrayMapSet", ProcessArrayMapSet) // deprecated → utils.arr.MapSet @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapKeys", ProcessMapKeys) // deprecated → utils.map.Keys @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapValues", ProcessMapValues) // deprecated → utils.map.Values @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapToArray", ProcessMapToArray) // deprecated → utils.map.Array @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapGet", ProcessMapGet) // deprecated → utils.map.Get @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapSet", ProcessMapSet) // deprecated → utils.map.Set @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapDel", ProcessMapDel) // deprecated → utils.map.Del @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.MapMultiDel", ProcessMapMultiDel) // deprecated → utils.map.DelMany @/utils/process.go
process.Register("xiang.helper.MapKeys", ProcessMapKeys) // deprecated → utils.map.Keys @/utils/process.go
process.Register("xiang.helper.MapValues", ProcessMapValues) // deprecated → utils.map.Values @/utils/process.go
process.Register("xiang.helper.MapToArray", ProcessMapToArray) // deprecated → utils.map.Array @/utils/process.go
process.Register("xiang.helper.MapGet", ProcessMapGet) // deprecated → utils.map.Get @/utils/process.go
process.Register("xiang.helper.MapSet", ProcessMapSet) // deprecated → utils.map.Set @/utils/process.go
process.Register("xiang.helper.MapDel", ProcessMapDel) // deprecated → utils.map.Del @/utils/process.go
process.Register("xiang.helper.MapMultiDel", ProcessMapMultiDel) // deprecated → utils.map.DelMany @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.HexToString", ProcessHexToString) // deprecated
process.Register("xiang.helper.HexToString", ProcessHexToString) // deprecated → utils.str.Hex @/utils/process.go new 2022.2.3
gou.RegisterProcessHandler("xiang.helper.StrConcat", ProcessStrConcat) // deprecated → utils.str.Concat @/utils/process.go
process.Register("xiang.helper.StrConcat", ProcessStrConcat) // deprecated → utils.str.Concat @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.Captcha", ProcessCaptcha) // deprecated → utils.captcha.Make @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.CaptchaValidate", ProcessCaptchaValidate) // deprecated → utils.captcha.Verify @/utils/process.go
process.Register("xiang.helper.Captcha", ProcessCaptcha) // deprecated → utils.captcha.Make @/utils/process.go
process.Register("xiang.helper.CaptchaValidate", ProcessCaptchaValidate) // deprecated → utils.captcha.Verify @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.PasswordValidate", ProcessPasswordValidate) // deprecated → utils.pwd.Verify @/utils/process.go
process.Register("xiang.helper.PasswordValidate", ProcessPasswordValidate) // deprecated → utils.pwd.Verify @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.JwtMake", ProcessJwtMake) // deprecated → utils.jwt.Make @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.JwtValidate", ProcessJwtValidate) // deprecated → utils.jwt.Verify @/utils/process.go
process.Register("xiang.helper.JwtMake", ProcessJwtMake) // deprecated → utils.jwt.Make @/utils/process.go
process.Register("xiang.helper.JwtValidate", ProcessJwtValidate) // deprecated → utils.jwt.Verify @/utils/process.go
gou.RegisterProcessHandler("xiang.helper.For", ProcessFor) // deprecated → utils.flow.For @/utils/process.go
gou.AliasProcess("xiang.helper.For", "xiang.flow.For") // deprecated
gou.RegisterProcessHandler("xiang.helper.Each", ProcessEach) // deprecated → utils.flow.Each @/utils/process.go
gou.AliasProcess("xiang.helper.Each", "xiang.flow.Each") // deprecated
gou.RegisterProcessHandler("xiang.helper.Case", ProcessCase) // deprecated → utils.flow.Case @/utils/process.go
gou.AliasProcess("xiang.helper.Case", "xiang.flow.Case") // deprecated
gou.RegisterProcessHandler("xiang.helper.IF", ProcessIF) // deprecated → utils.flow.IF @/utils/process.go
gou.AliasProcess("xiang.helper.IF", "xiang.flow.IF") // deprecated
gou.RegisterProcessHandler("xiang.helper.Throw", ProcessThrow) // deprecated → utils.flow.Throw @/utils/process.go
gou.AliasProcess("xiang.helper.Throw", "xiang.flow.Throw") // deprecated
gou.RegisterProcessHandler("xiang.helper.Return", ProcessReturn) // deprecated → utils.flow.Return @/utils/process.go
gou.AliasProcess("xiang.helper.Return", "xiang.flow.Return") // deprecated
process.Register("xiang.helper.For", ProcessFor) // deprecated → utils.flow.For @/utils/process.go
process.Alias("xiang.helper.For", "xiang.flow.For") // deprecated
process.Register("xiang.helper.Each", ProcessEach) // deprecated → utils.flow.Each @/utils/process.go
process.Alias("xiang.helper.Each", "xiang.flow.Each") // deprecated
process.Register("xiang.helper.Case", ProcessCase) // deprecated → utils.flow.Case @/utils/process.go
process.Alias("xiang.helper.Case", "xiang.flow.Case") // deprecated
process.Register("xiang.helper.IF", ProcessIF) // deprecated → utils.flow.IF @/utils/process.go
process.Alias("xiang.helper.IF", "xiang.flow.IF") // deprecated
process.Register("xiang.helper.Throw", ProcessThrow) // deprecated → utils.flow.Throw @/utils/process.go
process.Alias("xiang.helper.Throw", "xiang.flow.Throw") // deprecated
process.Register("xiang.helper.Return", ProcessReturn) // deprecated → utils.flow.Return @/utils/process.go
process.Alias("xiang.helper.Return", "xiang.flow.Return") // deprecated
gou.RegisterProcessHandler("xiang.helper.EnvSet", ProcessEnvSet) // deprecated → utils.env.Set @/utils/process.go
gou.AliasProcess("xiang.helper.EnvSet", "xiang.env.Set") // deprecated
gou.AliasProcess("xiang.helper.EnvSet", "yao.env.Set") // deprecated
process.Register("xiang.helper.EnvSet", ProcessEnvSet) // deprecated → utils.env.Set @/utils/process.go
process.Alias("xiang.helper.EnvSet", "xiang.env.Set") // deprecated
process.Alias("xiang.helper.EnvSet", "yao.env.Set") // deprecated
gou.RegisterProcessHandler("xiang.helper.EnvGet", ProcessEnvGet) // deprecated → utils.env.Get @/utils/process.go
gou.AliasProcess("xiang.helper.EnvGet", "xiang.env.Get") // deprecated
gou.AliasProcess("xiang.helper.EnvGet", "yao.env.Get") // deprecated
process.Register("xiang.helper.EnvGet", ProcessEnvGet) // deprecated → utils.env.Get @/utils/process.go
process.Alias("xiang.helper.EnvGet", "xiang.env.Get") // deprecated
process.Alias("xiang.helper.EnvGet", "yao.env.Get") // deprecated
gou.RegisterProcessHandler("xiang.helper.EnvMultiSet", ProcessEnvMultiSet) // deprecated → utils.env.SetMany @/utils/process.go
gou.AliasProcess("xiang.helper.EnvMultiSet", "xiang.env.MultiSet") // deprecated
gou.AliasProcess("xiang.helper.EnvMultiSet", "yao.env.MultiSet") // deprecated
process.Register("xiang.helper.EnvMultiSet", ProcessEnvMultiSet) // deprecated → utils.env.SetMany @/utils/process.go
process.Alias("xiang.helper.EnvMultiSet", "xiang.env.MultiSet") // deprecated
process.Alias("xiang.helper.EnvMultiSet", "yao.env.MultiSet") // deprecated
gou.RegisterProcessHandler("xiang.helper.EnvMultiGet", ProcessEnvMultiGet) // deprecated → utils.env.GetMany @/utils/process.go
gou.AliasProcess("xiang.helper.EnvMultiGet", "xiang.env.MultiGet") // deprecated
gou.AliasProcess("xiang.helper.EnvMultiGet", "yao.env.MultiGet") // deprecated
process.Register("xiang.helper.EnvMultiGet", ProcessEnvMultiGet) // deprecated → utils.env.GetMany @/utils/process.go
process.Alias("xiang.helper.EnvMultiGet", "xiang.env.MultiGet") // deprecated
process.Alias("xiang.helper.EnvMultiGet", "yao.env.MultiGet") // deprecated
gou.RegisterProcessHandler("xiang.helper.Print", ProcessPrint) // deprecated → utils.fmt.Println @/utils/process.go
gou.AliasProcess("xiang.helper.Print", "xiang.sys.Print") // deprecated
process.Register("xiang.helper.Print", ProcessPrint) // deprecated → utils.fmt.Println @/utils/process.go
process.Alias("xiang.helper.Print", "xiang.sys.Print") // deprecated
gou.RegisterProcessHandler("xiang.flow.Sleep", ProcessSleep) // deprecated → utils.time.Sleep @/utils/process.go
gou.AliasProcess("xiang.flow.Sleep", "xiang.sys.Sleep") // deprecated
gou.AliasProcess("xiang.flow.Sleep", "yao.sys.Sleep") // deprecated
process.Register("xiang.flow.Sleep", ProcessSleep) // deprecated → utils.time.Sleep @/utils/process.go
process.Alias("xiang.flow.Sleep", "xiang.sys.Sleep") // deprecated
process.Alias("xiang.flow.Sleep", "yao.sys.Sleep") // deprecated
}
// ProcessPrint xiang.helper.Print 打印语句
func ProcessPrint(process *gou.Process) interface{} {
func ProcessPrint(process *process.Process) interface{} {
process.ValidateArgNums(1)
utils.Dump(process.Args...)
return nil
}
// ProcessSleep xiang.flow.Sleep 等待
func ProcessSleep(process *gou.Process) interface{} {
func ProcessSleep(process *process.Process) interface{} {
process.ValidateArgNums(1)
ms := process.ArgsInt(0)
time.Sleep(time.Duration((ms * int(time.Millisecond))))

View file

@ -5,8 +5,8 @@ import (
"regexp"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/query/share"
"github.com/yaoapp/gou/helper"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/exception"
)
@ -69,14 +69,14 @@ func For(from int, to int, p Process) {
"value": i,
}
args := bindArgs(p.Args, bindings)
gou.NewProcess(p.Process, args...).Run()
process.New(p.Process, args...).Run()
}
}
func bindArgs(args []interface{}, bindings map[string]interface{}) []interface{} {
new := []interface{}{}
for i := range args {
new = append(new, share.Bind(args[i], bindings, reVar))
new = append(new, helper.Bind(args[i], bindings, reVar))
}
return new
}
@ -89,7 +89,7 @@ func rangeString(v string, p Process) {
"value": value,
}
args := bindArgs(p.Args, bindings)
gou.NewProcess(p.Process, args...).Run()
process.New(p.Process, args...).Run()
}
}
@ -101,7 +101,7 @@ func rangeMap(v map[string]interface{}, p Process) {
"value": value,
}
args := bindArgs(p.Args, bindings)
gou.NewProcess(p.Process, args...).Run()
process.New(p.Process, args...).Run()
}
}
@ -112,7 +112,7 @@ func rangeArray(v []interface{}, p Process) {
"value": value,
}
args := bindArgs(p.Args, bindings)
gou.NewProcess(p.Process, args...).Run()
process.New(p.Process, args...).Run()
}
}
@ -141,7 +141,7 @@ func ProcessOf(v map[string]interface{}) Process {
}
// ProcessEach xiang.helper.Each 循环过程控制
func ProcessEach(process *gou.Process) interface{} {
func ProcessEach(process *process.Process) interface{} {
process.ValidateArgNums(2)
v := process.Args[0]
p := ProcessOf(process.ArgsMap(1))
@ -150,7 +150,7 @@ func ProcessEach(process *gou.Process) interface{} {
}
// ProcessFor xiang.helper.For 循环过程控制
func ProcessFor(process *gou.Process) interface{} {
func ProcessFor(process *process.Process) interface{} {
process.ValidateArgNums(3)
from := process.ArgsInt(0)
to := process.ArgsInt(1)

View file

@ -3,11 +3,11 @@ package helper
import (
"fmt"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
// ProcessStrConcat xiang.helper.StrConcat 连接字符串
func ProcessStrConcat(process *gou.Process) interface{} {
func ProcessStrConcat(process *process.Process) interface{} {
process.ValidateArgNums(2)
res := ""
for i := range process.Args {

View file

@ -4,10 +4,10 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
)
func TestProcessStrConcat(t *testing.T) {
res := gou.NewProcess("xiang.helper.StrConcat", "FOO", 20, "BAR").Run().(string)
res := process.New("xiang.helper.StrConcat", "FOO", 20, "BAR").Run().(string)
assert.Equal(t, "FOO20BAR", res)
}

View file

@ -3,7 +3,6 @@ package i18n
import (
"crypto/sha256"
"fmt"
"path/filepath"
"strings"
"sync"
"time"
@ -45,8 +44,7 @@ func Load(cfg config.Config) error {
}
// Load langs
root := filepath.Join(cfg.Root, "langs")
err = lang.Load(root)
err = lang.Load("langs")
if err != nil {
return err
}

View file

@ -6,11 +6,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou/lang"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
share.DBConnect(config.Conf.DB)
test.Prepare(t, config.Conf)
defer test.Clean()
err := Load(config.Conf)
if err != nil {
t.Fatal(err)

View file

@ -8,8 +8,9 @@ import (
"strings"
"github.com/google/uuid"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/log"
@ -17,32 +18,45 @@ import (
"github.com/yaoapp/yao/importer/from"
"github.com/yaoapp/yao/importer/xlsx"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/xfs"
)
// Importers 导入器
var Importers = map[string]*Importer{}
// Load 加载导入器
func Load(cfg config.Config) {
LoadFrom(filepath.Join(cfg.Root, "imports"), "")
}
// DataRoot data file root
var DataRoot string = ""
// LoadFrom 从特定目录加载
func LoadFrom(dir string, prefix string) {
if share.DirNotExists(dir) {
return
// Load 加载导入器
func Load(cfg config.Config) error {
fs, err := fs.Get("system")
if err != nil {
return err
}
share.Walk(dir, ".json", func(root, filename string) {
var importer Importer
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
err := jsoniter.Unmarshal(content, &importer)
if err != nil {
exception.New("%s 导入配置错误. %s", 400, name, err.Error()).Ctx(filename).Throw()
DataRoot = fs.Root()
exts := []string{"*.imp.yao", "*.imp.json", "*.imp.jsonc"}
return application.App.Walk("imports", func(root, file string, isdir bool) error {
if isdir {
return nil
}
Importers[name] = &importer
})
id := share.ID(root, file)
data, err := application.App.Read(file)
if err != nil {
return err
}
var importer Importer
err = application.Parse(file, data, &importer)
if err != nil {
return fmt.Errorf("%s 导入配置错误. %s", id, err.Error())
}
Importers[id] = &importer
return nil
}, exts...)
}
// Select 选择已加载导入器
@ -59,12 +73,8 @@ func Open(name string) from.Source {
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(name), "."))
switch ext {
case "xlsx":
// fullpath := name
fullpath := filepath.Join(xfs.Stor.Root, name)
// if !strings.HasPrefix(fullpath, "/") {
// fullpath = filepath.Join(xfs.Stor.Root, name)
// }
return xlsx.Open(fullpath)
file := filepath.Join(DataRoot, name)
return xlsx.Open(file)
}
exception.New("暂不支持: %s 文件导入", 400, ext).Throw()
return nil
@ -169,7 +179,7 @@ func (imp *Importer) DataClean(data [][]interface{}, bindings []*Binding) ([]str
// DataValidate 数值校验
func DataValidate(row []interface{}, value interface{}, rule string) ([]interface{}, bool) {
process, err := gou.ProcessOf(rule, value, row)
process, err := process.Of(rule, value, row)
if err != nil {
log.With(log.F{"rule": rule, "row": row}).Error("DataValidate: %s", err.Error())
return row, true
@ -405,7 +415,7 @@ func (imp *Importer) Run(src from.Source, mapping *Mapping) interface{} {
length := len(data)
total = total + length
columns, data := imp.DataClean(data, mapping.Columns)
process, err := gou.ProcessOf(imp.Process, columns, data, id, page)
process, err := process.Of(imp.Process, columns, data, id, page)
if err != nil {
failed = failed + length
log.With(log.F{"line": line}).Error("导入失败: %s", err.Error())
@ -444,7 +454,7 @@ func (imp *Importer) Run(src from.Source, mapping *Mapping) interface{} {
}
if imp.Output != "" {
res, err := gou.NewProcess(imp.Output, output).WithSID(imp.Sid).Exec()
res, err := process.New(imp.Output, output).WithSID(imp.Sid).Exec()
if err != nil {
log.With(log.F{"output": imp.Output}).Error(err.Error())
return output

View file

@ -1,30 +1,46 @@
package importer
import (
"fmt"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/importer/xlsx"
"github.com/yaoapp/yao/script"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
LoadFrom("not a path", "404.")
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
assert.IsType(t, &Importer{}, Select("order"))
}
func TestFingerprintSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
imp := Select("order")
fingerprint := imp.Fingerprint(file)
assert.Equal(t, "3451ca87d71801687abba8993e5a69af79482914435d7cc064236fd93160f999", fingerprint)
}
func TestAutoMappingSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
@ -48,7 +64,12 @@ func TestAutoMappingSimple(t *testing.T) {
}
func TestDataGetSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
@ -69,7 +90,11 @@ func TestDataGetSimple(t *testing.T) {
}
func TestDataChunkSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
@ -83,7 +108,11 @@ func TestDataChunkSimple(t *testing.T) {
}
func TestRunSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
@ -97,7 +126,11 @@ func TestRunSimple(t *testing.T) {
}
func TestDataPreviewSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
imp := Select("order")
@ -116,7 +149,11 @@ func TestDataPreviewSimple(t *testing.T) {
}
func TestMappingPreviewSimple(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
@ -140,19 +177,50 @@ func TestMappingPreviewSimple(t *testing.T) {
}
func TestMappingSetting(t *testing.T) {
simple := filepath.Join(config.Conf.Root, "data", "assets", "simple.xlsx")
test.Prepare(t, config.Conf)
defer test.Clean()
root := prepare(t, config.Conf)
simple := filepath.Join(root, "assets", "simple.xlsx")
file := xlsx.Open(simple)
defer file.Close()
imp := Select("order")
setting := imp.MappingSetting(file)
utils.Dump(setting)
// utils.Dump(setting)
assert.NotNil(t, setting)
}
func TestDataSetting(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
imp := Select("order")
setting := imp.DataSetting()
utils.Dump(setting)
// utils.Dump(setting)
assert.NotNil(t, setting)
}
func prepare(t *testing.T, cfg config.Config) string {
err := Load(cfg)
if err != nil {
t.Fatal(err)
}
fs := fs.MustGet("system")
dataRoot := fs.Root()
fmt.Println("prepare", dataRoot)
if err != nil {
t.Fatal(err)
}
err = script.Load(cfg)
if err != nil {
t.Fatal(err)
}
return dataRoot
}

View file

@ -1,25 +0,0 @@
package importer
import (
"os"
"testing"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/model"
"github.com/yaoapp/yao/query"
"github.com/yaoapp/yao/runtime"
"github.com/yaoapp/yao/script"
"github.com/yaoapp/yao/share"
)
func TestMain(m *testing.M) {
runtime.Load(config.Conf)
share.DBConnect(config.Conf.DB)
model.Load(config.Conf)
query.Load(config.Conf)
share.Load(config.Conf)
script.Load(config.Conf)
Load(config.Conf)
code := m.Run()
os.Exit(code)
}

View file

@ -2,31 +2,31 @@ package importer
import (
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
)
func init() {
// 注册处理器
gou.RegisterProcessHandler("xiang.import.Run", ProcessRun) // deprecated → yao.import.Run
gou.RegisterProcessHandler("xiang.import.Data", ProcessData) // deprecated → yao.import.Data
gou.RegisterProcessHandler("xiang.import.Setting", ProcessSetting) // deprecated → yao.import.Setting
gou.RegisterProcessHandler("xiang.import.DataSetting", ProcessDataSetting) // deprecated → yao.import.DataSetting
gou.RegisterProcessHandler("xiang.import.Mapping", ProcessMapping) // deprecated → yao.import.Mapping
gou.RegisterProcessHandler("xiang.import.MappingSetting", ProcessMappingSetting) // deprecated → yao.import.MappingSetting
process.Register("xiang.import.Run", ProcessRun) // deprecated → yao.import.Run
process.Register("xiang.import.Data", ProcessData) // deprecated → yao.import.Data
process.Register("xiang.import.Setting", ProcessSetting) // deprecated → yao.import.Setting
process.Register("xiang.import.DataSetting", ProcessDataSetting) // deprecated → yao.import.DataSetting
process.Register("xiang.import.Mapping", ProcessMapping) // deprecated → yao.import.Mapping
process.Register("xiang.import.MappingSetting", ProcessMappingSetting) // deprecated → yao.import.MappingSetting
gou.AliasProcess("xiang.import.Run", "yao.import.Run")
gou.AliasProcess("xiang.import.Data", "yao.import.Data")
gou.AliasProcess("xiang.import.Setting", "yao.import.Setting")
gou.AliasProcess("xiang.import.DataSetting", "yao.import.DataSetting")
gou.AliasProcess("xiang.import.Mapping", "yao.import.Mapping")
gou.AliasProcess("xiang.import.MappingSetting", "yao.import.MappingSetting")
process.Alias("xiang.import.Run", "yao.import.Run")
process.Alias("xiang.import.Data", "yao.import.Data")
process.Alias("xiang.import.Setting", "yao.import.Setting")
process.Alias("xiang.import.DataSetting", "yao.import.DataSetting")
process.Alias("xiang.import.Mapping", "yao.import.Mapping")
process.Alias("xiang.import.MappingSetting", "yao.import.MappingSetting")
}
// ProcessRun xiang.import.Run
// 导入数据
func ProcessRun(process *gou.Process) interface{} {
func ProcessRun(process *process.Process) interface{} {
process.ValidateArgNums(3)
name := process.ArgsString(0)
imp := Select(name).WithSid(process.Sid)
@ -39,7 +39,7 @@ func ProcessRun(process *gou.Process) interface{} {
// ProcessSetting xiang.import.Setting
// 导入配置选项
func ProcessSetting(process *gou.Process) interface{} {
func ProcessSetting(process *process.Process) interface{} {
process.ValidateArgNums(1)
name := process.ArgsString(0)
imp := Select(name).WithSid(process.Sid)
@ -53,7 +53,7 @@ func ProcessSetting(process *gou.Process) interface{} {
// ProcessData xiang.import.Data
// 数据预览
func ProcessData(process *gou.Process) interface{} {
func ProcessData(process *process.Process) interface{} {
process.ValidateArgNums(5)
name := process.ArgsString(0)
imp := Select(name).WithSid(process.Sid)
@ -71,7 +71,7 @@ func ProcessData(process *gou.Process) interface{} {
// ProcessDataSetting xiang.import.DataSetting
// 数据预览表格配置
func ProcessDataSetting(process *gou.Process) interface{} {
func ProcessDataSetting(process *process.Process) interface{} {
process.ValidateArgNums(1)
name := process.ArgsString(0)
imp := Select(name).WithSid(process.Sid)
@ -80,7 +80,7 @@ func ProcessDataSetting(process *gou.Process) interface{} {
// ProcessMapping xiang.import.Mapping
// 字段映射预览
func ProcessMapping(process *gou.Process) interface{} {
func ProcessMapping(process *process.Process) interface{} {
process.ValidateArgNums(2)
name := process.ArgsString(0)
imp := Select(name).WithSid(process.Sid)
@ -93,7 +93,7 @@ func ProcessMapping(process *gou.Process) interface{} {
// ProcessMappingSetting xiang.import.MappingSetting
// 字段映射表格配置
func ProcessMappingSetting(process *gou.Process) interface{} {
func ProcessMappingSetting(process *process.Process) interface{} {
process.ValidateArgNums(2)
name := process.ArgsString(0)
imp := Select(name).WithSid(process.Sid)

View file

@ -5,53 +5,79 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/test"
)
func TestProcessMapping(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
simple := filepath.Join("assets", "simple.xlsx")
args := []interface{}{"order", simple}
response := gou.NewProcess("xiang.import.Mapping", args...).Run()
response := process.New("yao.import.Mapping", args...).Run()
_, ok := response.(*Mapping)
assert.True(t, ok)
}
func TestProcessMappingSetting(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
simple := filepath.Join("assets", "simple.xlsx")
args := []interface{}{"order", simple}
response := gou.NewProcess("xiang.import.MappingSetting", args...).Run()
response := process.New("yao.import.MappingSetting", args...).Run()
_, ok := response.(map[string]interface{})
assert.True(t, ok)
}
func TestProcessData(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
simple := filepath.Join("assets", "simple.xlsx")
mapping := gou.NewProcess("xiang.import.Mapping", "order", simple).Run()
mapping := process.New("yao.import.Mapping", "order", simple).Run()
args := []interface{}{"order", simple, 1, 2, mapping}
response := gou.NewProcess("xiang.import.Data", args...).Run()
response := process.New("yao.import.Data", args...).Run()
_, ok := response.(map[string]interface{})
assert.True(t, ok)
}
func TestProcessDataSetting(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
args := []interface{}{"order"}
response := gou.NewProcess("xiang.import.DataSetting", args...).Run()
response := process.New("yao.import.DataSetting", args...).Run()
_, ok := response.(map[string]interface{})
assert.True(t, ok)
}
func TestProcessSetting(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
args := []interface{}{"order"}
response := gou.NewProcess("xiang.import.Setting", args...).Run()
response := process.New("yao.import.Setting", args...).Run()
_, ok := response.(map[string]interface{})
assert.True(t, ok)
}
func TestProcessRun(t *testing.T) {
test.Prepare(t, config.Conf)
defer test.Clean()
prepare(t, config.Conf)
simple := filepath.Join("assets", "simple.xlsx")
mapping := gou.NewProcess("xiang.import.Mapping", "order", simple).Run()
mapping := process.New("yao.import.Mapping", "order", simple).Run()
args := []interface{}{"order", simple, mapping}
response := gou.NewProcess("xiang.import.Run", args...).Run()
response := process.New("yao.import.Run", args...).Run()
_, ok := response.(map[string]int)
assert.True(t, ok)
}

View file

@ -1,22 +0,0 @@
package main
import (
"os"
"testing"
"github.com/yaoapp/gou"
"github.com/yaoapp/yao/config"
)
var cfg config.Config
func TestMain(m *testing.M) {
// Run test suites
exitVal := m.Run()
// we can do clean up code here
gou.KillPlugins()
os.Exit(exitVal)
}

View file

@ -6,11 +6,7 @@ import (
_ "github.com/yaoapp/gou/encoding"
_ "github.com/yaoapp/yao/crypto"
_ "github.com/yaoapp/yao/helper"
_ "github.com/yaoapp/yao/network"
_ "github.com/yaoapp/yao/system"
_ "github.com/yaoapp/yao/user"
_ "github.com/yaoapp/yao/utils"
_ "github.com/yaoapp/yao/xfs"
)
// 主程序

View file

@ -1,140 +0,0 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"testing"
"time"
jsoniter "github.com/json-iterator/go"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/service"
)
func TestCommandVersion(t *testing.T) {
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = append(os.Args, "version")
assert.NotPanics(t, func() {
main()
})
}
func TestCommandMigrate(t *testing.T) {
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = append(os.Args, "migrate", "--reset", "--force")
assert.NotPanics(t, func() {
main()
})
}
func TestCommandStart(t *testing.T) {
oldArgs := os.Args
defer func() {
os.Args = oldArgs
service.Stop(func() {})
log.Println("服务已关闭")
}()
go func() {
os.Args = append(os.Args, "start")
main()
}()
// 发送请求
request := func() (maps.MapStr, error) {
time.Sleep(time.Microsecond * 2000)
url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "127.0.0.1", config.Conf.Port)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
res := maps.MakeMapStr()
err = jsoniter.Unmarshal(body, &res)
if err != nil {
return nil, err
}
return res, nil
}
// 等待服务启动
times := 0
for times < 30 { // 2秒超时
time.Sleep(time.Second * 2)
times++
fmt.Printf("Trying(%d)...", times)
res, err := request()
if err != nil {
fmt.Printf(" %s\n", err.Error())
continue
}
assert.Equal(t, 1, any.Of(res.Get("id")).CInt())
assert.Equal(t, "管理员", res.Get("name"))
return
}
assert.True(t, false)
}
func TestCommandStop(t *testing.T) {
oldArgs := os.Args
defer func() {
os.Args = oldArgs
}()
go func() {
os.Args = append(os.Args, "start")
main()
}()
// 发送请求
request := func() (maps.MapStr, error) {
time.Sleep(time.Microsecond * 2000)
url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "127.0.0.1", config.Conf.Port)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
res := maps.MakeMapStr()
err = jsoniter.Unmarshal(body, &res)
if err != nil {
return nil, err
}
return res, nil
}
// 等待服务启动
times := 0
for times < 30 { // 2秒超时
time.Sleep(time.Second * 2)
times++
res, err := request()
if err != nil {
fmt.Println("REQUEST ERROR:", err)
continue
}
assert.Equal(t, 1, any.Of(res.Get("id")).CInt())
assert.Equal(t, "管理员", res.Get("name"))
// 测试关闭
service.Stop(func() { log.Println("服务已关闭") })
time.Sleep(time.Second * 5)
_, err = request()
assert.NotNil(t, err)
return
}
assert.True(t, false)
}

View file

@ -1 +0,0 @@
# Model

View file

@ -2,53 +2,25 @@ package model
import (
"fmt"
"path/filepath"
"strings"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
)
// Load 加载数据模型
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) error {
model.WithCrypt([]byte(fmt.Sprintf(`{"key":"%s"}`, cfg.DB.AESKey)), "AES")
model.WithCrypt([]byte(`{}`), "PASSWORD")
messages := []string{}
if share.DirNotExists(dir) {
return fmt.Errorf("%s does not exists", dir)
}
err := share.Walk(dir, ".json", func(root, filename string) {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
_, err := gou.LoadModelReturn(string(content), name)
if err != nil {
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
messages = append(messages, err.Error())
exts := []string{"*.mod.yao", "*.mod.json", "*.mod.jsonc"}
return application.App.Walk("models", func(root, file string, isdir bool) error {
if isdir {
return nil
}
})
if err != nil {
messages = append(messages, err.Error())
}
if len(messages) > 0 {
return fmt.Errorf("[Model] %s", strings.Join(messages, ";"))
}
return nil
}
// LoadBuildIn 从制品中读取
func LoadBuildIn(dir string, prefix string) error {
return nil
_, err := model.Load(file, share.ID(root, file))
return err
}, exts...)
}

View file

@ -5,27 +5,30 @@ import (
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/test"
)
func TestLoad(t *testing.T) {
share.DBConnect(config.Conf.DB)
gou.Models = make(map[string]*gou.Model)
test.Prepare(t, config.Conf)
defer test.Clean()
Load(config.Conf)
LoadFrom("not a path", "404.")
check(t)
}
func check(t *testing.T) {
keys := []string{}
for key := range gou.Models {
keys = append(keys, key)
ids := map[string]bool{}
for id := range model.Models {
ids[id] = true
}
assert.Equal(t, 11, len(keys))
demo := gou.Select("demo")
assert.Equal(t, demo.MetaData.Name, "::Demo")
assert.Equal(t, demo.Columns["action"].Label, "::Action")
assert.True(t, ids["user"])
assert.True(t, ids["category"])
assert.True(t, ids["tag"])
assert.True(t, ids["pet"])
assert.True(t, ids["pet.tag"])
assert.True(t, ids["user.pet"])
assert.True(t, ids["tests.user"])
}

View file

@ -1,63 +0,0 @@
package network
import (
"net"
"github.com/yaoapp/gou"
"github.com/yaoapp/kun/exception"
)
// IP 读取IP地址
func IP() map[string]string {
res := map[string]string{}
ifaces, err := net.Interfaces()
if err != nil {
exception.New("读取网卡失败 %s", 500, err.Error()).Throw()
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
exception.New("读取IP地址失败 %s", 500, err.Error()).Throw()
}
// handle err
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
res[i.Name] = ip.String()
}
}
return res
}
// ProcessIP xiang.network.IP IP地址
func ProcessIP(process *gou.Process) interface{} {
return IP()
}
// FreePort xiang.network.FreePort 获取可用端口
func FreePort() int {
addr, err := net.ResolveTCPAddr("tcp", ":0")
if err != nil {
exception.New("获取可用端口失败 %s", 500, err.Error()).Throw()
return 0
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
exception.New("获取可用端口失败 %s", 500, err.Error()).Throw()
return 0
}
defer l.Close()
return l.Addr().(*net.TCPAddr).Port
}
// ProcessFreePort xiang.network.FreePort 获取可用端口
func ProcessFreePort(process *gou.Process) interface{} {
return FreePort()
}

View file

@ -1,32 +0,0 @@
package network
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/gou"
)
func TestIP(t *testing.T) {
resp := IP()
assert.True(t, len(resp) > 0)
}
func TestProcessIP(t *testing.T) {
res := gou.NewProcess("xiang.network.ip").Run()
resp, ok := res.(map[string]string)
assert.True(t, ok)
assert.True(t, len(resp) > 0)
}
func TestFreePort(t *testing.T) {
port := FreePort()
assert.True(t, port > 0)
}
func TestProcessFreePort(t *testing.T) {
res := gou.NewProcess("xiang.network.FreePort").Run()
port, ok := res.(int)
assert.True(t, ok)
assert.True(t, port > 0)
}

View file

@ -1,19 +0,0 @@
package network
// *******************************************************
// * DEPRECATED → http *
// *******************************************************
import "github.com/yaoapp/gou"
func init() {
// 注册处理器
gou.RegisterProcessHandler("xiang.network.ip", ProcessIP)
gou.RegisterProcessHandler("xiang.network.FreePort", ProcessFreePort)
gou.RegisterProcessHandler("xiang.network.Get", ProcessGet)
gou.RegisterProcessHandler("xiang.network.Post", ProcessPost)
gou.RegisterProcessHandler("xiang.network.PostJSON", ProcessPostJSON)
gou.RegisterProcessHandler("xiang.network.Put", ProcessPut)
gou.RegisterProcessHandler("xiang.network.PutJSON", ProcessPutJSON)
gou.RegisterProcessHandler("xiang.network.Send", ProcessSend)
}

View file

@ -1,168 +0,0 @@
package network
// *******************************************************
// * DEPRECATED → http *
// *******************************************************
import (
"bytes"
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/dns"
)
// Response 请求响应结果
type Response struct {
Status int `json:"status"`
Body string `json:"body"`
Data interface{} `json:"data"`
Headers map[string]interface{} `json:"headers"`
}
// RequestGet 发送GET请求
func RequestGet(url string, params map[string]interface{}, headers map[string]string) Response {
return RequestSend("GET", url, params, nil, headers)
}
// RequestPost 发送POST请求
func RequestPost(url string, data interface{}, headers map[string]string) Response {
return RequestSend("POST", url, map[string]interface{}{}, data, headers)
}
// RequestPostJSON 发送POST请求
func RequestPostJSON(url string, data interface{}, headers map[string]string) Response {
if headers == nil {
headers = map[string]string{}
}
headers["content-type"] = "application/json;charset=utf8"
return RequestSend("POST", url, map[string]interface{}{}, data, headers)
}
// RequestPut 发送PUT请求
func RequestPut(url string, data interface{}, headers map[string]string) Response {
return RequestSend("PUT", url, map[string]interface{}{}, data, headers)
}
// RequestPutJSON 发送PUT请求
func RequestPutJSON(url string, data interface{}, headers map[string]string) Response {
if headers == nil {
headers = map[string]string{}
}
headers["content-type"] = "application/json;charset=utf8"
return RequestSend("PUT", url, map[string]interface{}{}, data, headers)
}
// RequestSend 发送Request请求
func RequestSend(method string, url string, params map[string]interface{}, data interface{}, headers map[string]string) Response {
var body []byte
var err error
if data != nil {
if strings.HasPrefix(strings.ToLower(headers["content-type"]), "application/json") {
body, err = jsoniter.Marshal(data)
if err != nil {
return Response{
Status: 500,
Body: err.Error(),
Data: map[string]interface{}{"code": 500, "message": err.Error()},
Headers: map[string]interface{}{
"Content-Type": "application/json;charset=utf8",
},
}
}
} else {
body = []byte(fmt.Sprintf("%v", data))
}
}
req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
if err != nil {
return Response{
Status: 500,
Body: err.Error(),
Data: map[string]interface{}{"code": 500, "message": err.Error()},
Headers: map[string]interface{}{
"Content-Type": "application/json;charset=utf8",
},
}
}
// Request Header
if headers != nil {
for name, header := range headers {
req.Header.Set(name, header)
}
}
// Force using system DSN resolver
// var dialer = &net.Dialer{Resolver: &net.Resolver{PreferGo: false}}
var dialContext = dns.DialContext()
var tr = &http.Transport{DialContext: dialContext}
var client *http.Client = &http.Client{Transport: tr}
// Https SkipVerify false
if strings.HasPrefix(url, "https://") {
tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
DialContext: dialContext,
}
client = &http.Client{Transport: tr}
}
defer tr.CloseIdleConnections()
resp, err := client.Do(req)
if err != nil {
return Response{
Status: 0,
Body: err.Error(),
Data: map[string]interface{}{"code": 500, "message": err.Error()},
Headers: map[string]interface{}{
"Content-Type": "application/json;charset=utf8",
},
}
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body) // response body is []byte
if err != nil {
return Response{
Status: 500,
Body: err.Error(),
Data: map[string]interface{}{"code": resp.StatusCode, "message": err.Error()},
Headers: map[string]interface{}{
"Content-Type": "application/json;charset=utf8",
},
}
}
// JSON 解析
var res interface{}
if strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") {
err = jsoniter.Unmarshal(body, &res)
if err != nil {
return Response{
Status: 500,
Body: err.Error(),
Data: map[string]interface{}{"code": resp.StatusCode, "message": err.Error()},
Headers: map[string]interface{}{
"Content-Type": "application/json;charset=utf8",
},
}
}
}
respHeaders := map[string]interface{}{}
for name := range resp.Header {
respHeaders[name] = resp.Header.Get(name)
}
return Response{
Status: resp.StatusCode,
Body: string(body),
Data: res,
Headers: respHeaders,
}
}

View file

@ -1,127 +0,0 @@
package network
import (
"fmt"
"github.com/yaoapp/gou"
)
// *******************************************************
// * DEPRECATED → http *
// *******************************************************
// ProcessPost xiang.helper.Post HTTP Post
func ProcessPost(process *gou.Process) interface{} {
process.ValidateArgNums(1)
var data interface{}
var headers = map[string]string{}
url := process.ArgsString(0)
if process.NumOfArgs() > 1 {
data = process.Args[1]
}
if process.NumOfArgs() > 2 {
inputHeaders := process.ArgsMap(2)
for name, value := range inputHeaders {
headers[name] = fmt.Sprintf("%v", value)
}
}
return RequestPost(url, data, headers)
}
// ProcessPostJSON xiang.helper.PostJSON HTTP Post
func ProcessPostJSON(process *gou.Process) interface{} {
process.ValidateArgNums(1)
var data interface{}
var headers = map[string]string{}
url := process.ArgsString(0)
if process.NumOfArgs() > 1 {
data = process.Args[1]
}
if process.NumOfArgs() > 2 {
inputHeaders := process.ArgsMap(2)
for name, value := range inputHeaders {
headers[name] = fmt.Sprintf("%v", value)
}
}
return RequestPostJSON(url, data, headers)
}
// ProcessPut xiang.helper.Put HTTP PUT
func ProcessPut(process *gou.Process) interface{} {
process.ValidateArgNums(1)
var data interface{}
var headers = map[string]string{}
url := process.ArgsString(0)
if process.NumOfArgs() > 1 {
data = process.Args[1]
}
if process.NumOfArgs() > 2 {
inputHeaders := process.ArgsMap(2)
for name, value := range inputHeaders {
headers[name] = fmt.Sprintf("%v", value)
}
}
return RequestPut(url, data, headers)
}
// ProcessPutJSON xiang.helper.PutJSON HTTP PUT
func ProcessPutJSON(process *gou.Process) interface{} {
process.ValidateArgNums(1)
var data interface{}
var headers = map[string]string{}
url := process.ArgsString(0)
if process.NumOfArgs() > 1 {
data = process.Args[1]
}
if process.NumOfArgs() > 2 {
inputHeaders := process.ArgsMap(2)
for name, value := range inputHeaders {
headers[name] = fmt.Sprintf("%v", value)
}
}
return RequestPutJSON(url, data, headers)
}
// ProcessSend xiang.helper.Send HTTP Send
func ProcessSend(process *gou.Process) interface{} {
process.ValidateArgNums(2)
var data interface{}
var params = map[string]interface{}{}
var headers = map[string]string{}
method := process.ArgsString(0)
url := process.ArgsString(1)
if process.NumOfArgs() > 2 {
params = process.ArgsMap(2)
}
if process.NumOfArgs() > 3 {
data = process.Args[3]
}
if process.NumOfArgs() > 4 {
inputHeaders := process.ArgsMap(4)
for name, value := range inputHeaders {
headers[name] = fmt.Sprintf("%v", value)
}
}
return RequestSend(method, url, params, data, headers)
}
// ProcessGet xiang.helper.Get HTTP Get
func ProcessGet(process *gou.Process) interface{} {
process.ValidateArgNums(1)
var params = map[string]interface{}{}
var headers = map[string]string{}
url := process.ArgsString(0)
if process.NumOfArgs() > 1 {
params = process.ArgsMap(1)
}
if process.NumOfArgs() > 2 {
inputHeaders := process.ArgsMap(2)
for name, value := range inputHeaders {
headers[name] = fmt.Sprintf("%v", value)
}
}
return RequestGet(url, params, headers)
}

Some files were not shown because too many files have changed in this diff Show more