Merge branch 'YaoApp:main' into main
This commit is contained in:
commit
2e1ef3ecb2
174 changed files with 5544 additions and 1518 deletions
1
.github/workflows/pr-receive.yml
vendored
1
.github/workflows/pr-receive.yml
vendored
|
|
@ -16,6 +16,7 @@ jobs:
|
|||
run: |
|
||||
mkdir -p ./pr
|
||||
echo ${{ github.event.number }} > ./pr/NR
|
||||
echo ${{ github.event.pull_request.head.sha }} > ./pr/SHA
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: pr
|
||||
|
|
|
|||
154
.github/workflows/pr-test.yml
vendored
154
.github/workflows/pr-test.yml
vendored
|
|
@ -7,10 +7,28 @@ on:
|
|||
workflows: ["Receive PR"]
|
||||
types:
|
||||
- completed
|
||||
env:
|
||||
YAO_DEV: ${{ github.WORKSPACE }}
|
||||
YAO_ENV: development
|
||||
YAO_ROOT: ${{ github.WORKSPACE }}/tests
|
||||
YAO_HOST: 0.0.0.0
|
||||
YAO_PORT: 5099
|
||||
YAO_SESSION: "memory"
|
||||
YAO_LOG: "./logs/application.log"
|
||||
YAO_LOG_MODE: "TEXT"
|
||||
YAO_JWT_SECRET: "bLp@bi!oqo-2U+hoTRUG"
|
||||
YAO_DB_AESKEY: "ZLX=T&f6refeCh-ro*r@"
|
||||
OSS_TEST_ID: ${{ secrets.OSS_TEST_ID}}
|
||||
OSS_TEST_SECRET: ${{ secrets.OSS_TEST_SECRET}}
|
||||
ROOT_PLUGIN: ${{ github.WORKSPACE }}/../../../data/gou-unit/plugins
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
UnitTest:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.18.2]
|
||||
db: [MySQL8.0, MySQL5.7, SQLite3]
|
||||
if: >
|
||||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success' }}
|
||||
|
|
@ -35,21 +53,147 @@ jobs:
|
|||
});
|
||||
var fs = require('fs');
|
||||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||||
- name: "Unzip"
|
||||
|
||||
- name: "Read NR & SHA"
|
||||
run: |
|
||||
unzip pr.zip
|
||||
ls -l
|
||||
cat NR
|
||||
cat SHA
|
||||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||||
|
||||
- name: "Comment on PR"
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { NR } = process.env
|
||||
var fs = require('fs');
|
||||
var issue_number = Number(fs.readFileSync('./NR'));
|
||||
var issue_number = NR;
|
||||
await github.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue_number,
|
||||
body: 'Everything is OK. Thank you for the PR!'
|
||||
body: 'Thank you for the PR! The ${{ matrix.db }} test workflow is running, the results of the run will be commented later.'
|
||||
});
|
||||
|
||||
- name: Setup Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- name: Checkout Kun
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: yaoapp/kun
|
||||
path: kun
|
||||
|
||||
- name: Checkout Xun
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: yaoapp/xun
|
||||
path: xun
|
||||
|
||||
- name: Checkout Gou
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: yaoapp/gou
|
||||
path: gou
|
||||
|
||||
- name: Checkout V8Go
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: rogchap/v8go
|
||||
ref: 5e91d3d9dcabd2986f901b6b31590e49fc3c4dd8
|
||||
path: v8go
|
||||
|
||||
- name: Move Kun, Xun, Gou, V8Go
|
||||
run: |
|
||||
mv kun ../
|
||||
mv xun ../
|
||||
mv gou ../
|
||||
mv v8go ../
|
||||
ls -l .
|
||||
ls -l ../
|
||||
|
||||
- name: Checkout pull request HEAD commit
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ env.HEAD }}
|
||||
|
||||
- name: Setup ${{ matrix.db }}
|
||||
uses: ./.github/actions/setup-db
|
||||
with:
|
||||
kind: "${{ matrix.db }}"
|
||||
db: "xiang"
|
||||
user: "xiang"
|
||||
password: ${{ secrets.UNIT_PASS }}
|
||||
|
||||
- name: Setup Go ${{ matrix.go }}
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Setup Go Tools
|
||||
run: |
|
||||
make tools
|
||||
|
||||
- name: Setup ENV & Host
|
||||
env:
|
||||
PASSWORD: ${{ secrets.UNIT_PASS }}
|
||||
run: |
|
||||
sudo echo "127.0.0.1 local.iqka.com" | sudo tee -a /etc/hosts
|
||||
echo "YAO_DB_DRIVER=$DB_DRIVER" >> $GITHUB_ENV
|
||||
echo "GITHUB_WORKSPACE:\n" && ls -l $GITHUB_WORKSPACE
|
||||
|
||||
if [ "$DB_DRIVER" = "mysql" ]; then
|
||||
echo "YAO_DB_PRIMARY=$DB_USER:$PASSWORD@$DB_HOST" >> $GITHUB_ENV
|
||||
elif [ "$DB_DRIVER" = "postgres" ]; then
|
||||
echo "YAO_DB_PRIMARY=postgres://$DB_USER:$PASSWORD@$DB_HOST" >> $GITHUB_ENV
|
||||
else
|
||||
echo "YAO_DB_PRIMARY=$YAO_ROOT/$DB_HOST" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo ".:\n" && ls -l .
|
||||
echo "..:\n" && ls -l ..
|
||||
ping -c 1 -t 1 local.iqka.com
|
||||
|
||||
- name: Test Prepare
|
||||
run: |
|
||||
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: 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
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { NR } = process.env
|
||||
var fs = require('fs');
|
||||
var issue_number = NR;
|
||||
await github.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue_number,
|
||||
body: '✨DONE✨ ${{ matrix.db }} passed.'
|
||||
});
|
||||
|
|
|
|||
34
.github/workflows/release-linux.yml
vendored
34
.github/workflows/release-linux.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
release:
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.17]
|
||||
go: [1.18.2]
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: Arm Build
|
||||
|
|
@ -55,7 +55,6 @@ jobs:
|
|||
with:
|
||||
repository: yaoapp/gou
|
||||
path: gou
|
||||
token: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: Checkout V8Go
|
||||
uses: actions/checkout@v2
|
||||
|
|
@ -69,7 +68,6 @@ jobs:
|
|||
with:
|
||||
repository: yaoapp/xgen
|
||||
path: ui
|
||||
token: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: Move Kun, Xun, Gou, UI, V8Go
|
||||
run: |
|
||||
|
|
@ -85,17 +83,13 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Go ${{ matrix.go }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Setup Go Tools
|
||||
run: |
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then go mod download; fi
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then export PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"; fi
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then make tools; fi
|
||||
go get github.com/go-bindata/go-bindata/...
|
||||
go get github.com/elazarl/go-bindata-assetfs/...
|
||||
make tools
|
||||
|
||||
- name: Make Artifacts Linux
|
||||
run: |
|
||||
|
|
@ -114,15 +108,15 @@ jobs:
|
|||
run: |
|
||||
for file in ./dist/release/*; do coscmd upload $file /archives/; done;
|
||||
|
||||
- name: Configure COS For Beijing
|
||||
env:
|
||||
SECRET_ID: ${{ secrets.COS_ID }}
|
||||
SECRET_KEY: ${{ secrets.COS_KEY }}
|
||||
BUCKET: release-bj-1252011659
|
||||
REGION: ap-beijing
|
||||
run: |
|
||||
coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
|
||||
# - name: Configure COS For Beijing
|
||||
# env:
|
||||
# SECRET_ID: ${{ secrets.COS_ID }}
|
||||
# SECRET_KEY: ${{ secrets.COS_KEY }}
|
||||
# BUCKET: release-bj-1252011659
|
||||
# REGION: ap-beijing
|
||||
# run: |
|
||||
# coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
|
||||
|
||||
- name: Push To Beijing
|
||||
run: |
|
||||
for file in ./dist/release/*; do coscmd upload $file /archives/; done;
|
||||
# - name: Push To Beijing
|
||||
# run: |
|
||||
# for file in ./dist/release/*; do coscmd upload $file /archives/; done;
|
||||
|
|
|
|||
34
.github/workflows/release-macos.yml
vendored
34
.github/workflows/release-macos.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
release:
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.17]
|
||||
go: [1.18.2]
|
||||
runs-on: "macos-11"
|
||||
steps:
|
||||
- name: Install coscmd
|
||||
|
|
@ -47,7 +47,6 @@ jobs:
|
|||
with:
|
||||
repository: yaoapp/gou
|
||||
path: gou
|
||||
token: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: Checkout V8Go
|
||||
uses: actions/checkout@v2
|
||||
|
|
@ -61,7 +60,6 @@ jobs:
|
|||
with:
|
||||
repository: yaoapp/xgen
|
||||
path: ui
|
||||
token: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: Move Kun, Xun, Gou, UI, V8Go
|
||||
run: |
|
||||
|
|
@ -77,17 +75,13 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Go ${{ matrix.go }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Setup Go Tools
|
||||
run: |
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then go mod download; fi
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then export PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"; fi
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then make tools; fi
|
||||
go get github.com/go-bindata/go-bindata/...
|
||||
go get github.com/elazarl/go-bindata-assetfs/...
|
||||
make tools
|
||||
|
||||
- name: Make Artifacts MacOS
|
||||
run: |
|
||||
|
|
@ -106,15 +100,15 @@ jobs:
|
|||
run: |
|
||||
for file in ./dist/release/*; do coscmd upload $file /archives/; done;
|
||||
|
||||
- name: Configure COS For Beijing
|
||||
env:
|
||||
SECRET_ID: ${{ secrets.COS_ID }}
|
||||
SECRET_KEY: ${{ secrets.COS_KEY }}
|
||||
BUCKET: release-bj-1252011659
|
||||
REGION: ap-beijing
|
||||
run: |
|
||||
coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
|
||||
# - name: Configure COS For Beijing
|
||||
# env:
|
||||
# SECRET_ID: ${{ secrets.COS_ID }}
|
||||
# SECRET_KEY: ${{ secrets.COS_KEY }}
|
||||
# BUCKET: release-bj-1252011659
|
||||
# REGION: ap-beijing
|
||||
# run: |
|
||||
# coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
|
||||
|
||||
- name: Push To Beijing
|
||||
run: |
|
||||
for file in ./dist/release/*; do coscmd upload $file /archives/; done;
|
||||
# - name: Push To Beijing
|
||||
# run: |
|
||||
# for file in ./dist/release/*; do coscmd upload $file /archives/; done;
|
||||
|
|
|
|||
12
.github/workflows/unit-test.yml
vendored
12
.github/workflows/unit-test.yml
vendored
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.17]
|
||||
go: [1.18.2]
|
||||
db: [MySQL8.0, MySQL5.7, SQLite3]
|
||||
steps:
|
||||
- name: Setup Cache
|
||||
|
|
@ -80,22 +80,20 @@ jobs:
|
|||
kind: "${{ matrix.db }}"
|
||||
db: "xiang"
|
||||
user: "xiang"
|
||||
password: 123456
|
||||
password: ${{ secrets.UNIT_PASS }}
|
||||
|
||||
- name: Setup Go ${{ matrix.go }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Setup Go Tools
|
||||
run: |
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then go mod download; fi
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then export PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"; fi
|
||||
if [[ "${GO111MODULE}" = "on" ]]; then make tools; fi
|
||||
make tools
|
||||
|
||||
- name: Setup ENV & Host
|
||||
env:
|
||||
PASSWORD: 123456
|
||||
PASSWORD: ${{ secrets.UNIT_PASS }}
|
||||
run: |
|
||||
sudo echo "127.0.0.1 local.iqka.com" | sudo tee -a /etc/hosts
|
||||
echo "YAO_DB_DRIVER=$DB_DRIVER" >> $GITHUB_ENV
|
||||
|
|
|
|||
65
Makefile
65
Makefile
|
|
@ -1,9 +1,11 @@
|
|||
GO ?= go
|
||||
GIT ?= git
|
||||
GOFMT ?= gofmt "-s"
|
||||
PACKAGES ?= $(shell $(GO) list ./...)
|
||||
VETPACKAGES ?= $(shell $(GO) list ./... | grep -v /examples/)
|
||||
GOFILES := $(shell find . -name "*.go")
|
||||
VERSION := $(shell grep 'const VERSION =' share/const.go |awk '{print $$4}' |sed 's/\"//g')
|
||||
COMMIT := $(shell git log | head -n 1 | awk '{print substr($$2, 0, 12)}')
|
||||
|
||||
# ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
TESTFOLDER := $(shell $(GO) list ./... | grep -vE 'examples|tests*|config')
|
||||
|
|
@ -76,9 +78,10 @@ misspell:
|
|||
|
||||
.PHONY: tools
|
||||
tools:
|
||||
go install golang.org/x/lint/golint; \
|
||||
go install github.com/client9/misspell/cmd/misspell;
|
||||
|
||||
go install golang.org/x/lint/golint@latest; \
|
||||
go install github.com/client9/misspell/cmd/misspell@latest; \
|
||||
go install github.com/go-bindata/go-bindata/...@latest;
|
||||
|
||||
# make plugin
|
||||
.PHONY: plugin
|
||||
plugin:
|
||||
|
|
@ -130,6 +133,9 @@ artifacts-linux: clean
|
|||
rm -rf .tmp/data
|
||||
rm -rf .tmp/ui
|
||||
|
||||
# Replace PRVERSION
|
||||
sed -ie "s/const PRVERSION = \"DEV\"/const PRVERSION = \"${COMMIT}\"/g" share/const.go
|
||||
|
||||
# Making artifacts
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 CGO_LDFLAGS="-static" GOOS=linux GOARCH=amd64 go build -v -o dist/yao-${VERSION}-linux-amd64
|
||||
|
|
@ -141,6 +147,10 @@ artifacts-linux: clean
|
|||
ls -l dist/release/
|
||||
dist/release/yao-${VERSION}-linux-amd64 version
|
||||
|
||||
# Reset const
|
||||
# cp -f share/const.goe share/const.go
|
||||
# rm -f share/const.goe
|
||||
|
||||
# make artifacts-macos
|
||||
.PHONY: artifacts-macos
|
||||
artifacts-macos: clean
|
||||
|
|
@ -158,6 +168,9 @@ artifacts-macos: clean
|
|||
rm -rf .tmp/data
|
||||
rm -rf .tmp/ui
|
||||
|
||||
# Replace PRVERSION
|
||||
sed -ie "s/const PRVERSION = \"DEV\"/const PRVERSION = \"${COMMIT}\"/g" share/const.go
|
||||
|
||||
# Making artifacts
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -v -o dist/yao-${VERSION}-darwin-amd64
|
||||
|
|
@ -169,6 +182,10 @@ artifacts-macos: clean
|
|||
ls -l dist/release/
|
||||
dist/release/yao-${VERSION}-darwin-amd64 version
|
||||
|
||||
# Reset const
|
||||
# cp -f share/const.goe share/const.go
|
||||
# rm -f share/const.goe
|
||||
|
||||
.PHONY: debug
|
||||
debug: clean
|
||||
mkdir -p dist/release
|
||||
|
|
@ -180,11 +197,19 @@ debug: clean
|
|||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
rm -rf .tmp/data
|
||||
|
||||
|
||||
# Replace PRVERSION
|
||||
sed -ie "s/const PRVERSION = \"DEV\"/const PRVERSION = \"${COMMIT}-debug\"/g" share/const.go
|
||||
|
||||
# Making artifacts
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 go build -v -o dist/release/yao-debug
|
||||
chmod +x dist/release/yao-debug
|
||||
|
||||
# Reset const
|
||||
cp -f share/const.goe share/const.go
|
||||
rm -f share/const.goe
|
||||
|
||||
.PHONY: release
|
||||
release: clean
|
||||
mkdir -p dist/release
|
||||
|
|
@ -193,7 +218,37 @@ release: clean
|
|||
# Building UI
|
||||
git clone https://github.com/YaoApp/xgen.git .tmp/ui
|
||||
sed -ie "s/url('\/icon/url('\/xiang\/icon/g" .tmp/ui/public/icon/md_icon.css
|
||||
cd .tmp/ui && npm install && npm run build
|
||||
cd .tmp/ui && cnpm install && npm run build
|
||||
|
||||
# Packing
|
||||
mkdir -p .tmp/data
|
||||
cp -r .tmp/ui/dist .tmp/data/ui
|
||||
cp -r yao .tmp/data/
|
||||
go-bindata -fs -pkg data -o data/bindata.go -prefix ".tmp/data/" .tmp/data/...
|
||||
rm -rf .tmp/data
|
||||
rm -rf .tmp/ui
|
||||
|
||||
# Replace PRVERSION
|
||||
sed -ie "s/const PRVERSION = \"DEV\"/const PRVERSION = \"${COMMIT}\"/g" share/const.go
|
||||
|
||||
# Making artifacts
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 go build -v -o dist/release/yao
|
||||
chmod +x dist/release/yao
|
||||
|
||||
# Reset const
|
||||
cp -f share/const.goe share/const.go
|
||||
rm share/const.goe
|
||||
|
||||
.PHONY: linux-release
|
||||
linux-release: clean
|
||||
mkdir -p dist/release
|
||||
mkdir .tmp
|
||||
|
||||
# Building UI
|
||||
git clone https://github.com/YaoApp/xgen.git .tmp/ui
|
||||
sed -ie "s/url('\/icon/url('\/xiang\/icon/g" .tmp/ui/public/icon/md_icon.css
|
||||
cd .tmp/ui && yarn install && yarn build
|
||||
|
||||
# Packing
|
||||
mkdir -p .tmp/data
|
||||
|
|
@ -205,7 +260,7 @@ release: clean
|
|||
|
||||
# Making artifacts
|
||||
mkdir -p dist
|
||||
CGO_ENABLED=1 go build -v -o dist/release/yao
|
||||
CGO_ENABLED=1 CGO_LDFLAGS="-static" go build -v -o dist/release/yao
|
||||
chmod +x dist/release/yao
|
||||
|
||||
# make clean
|
||||
|
|
|
|||
32
README.md
32
README.md
|
|
@ -15,8 +15,8 @@
|
|||
Twitter
|
||||
</a>
|
||||
·
|
||||
<a aria-label="slack" href="https://join.slack.com/t/yaoapps/shared_invite/zt-13dm0cwvo-R9Q8xFGbrLZUffeygm9tXQ" target="_blank">
|
||||
Slack
|
||||
<a aria-label="discord" href="https://discord.gg/nsKmCXwvxU" target="_blank">
|
||||
Discord
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
|
@ -35,17 +35,35 @@
|
|||
</a>
|
||||
</p>
|
||||
|
||||

|
||||

|
||||
|
||||
[中文介绍](README.zh-CN.md)
|
||||
|
||||
YAO is an open-source application engine, written in Golang, in the form of a command-line tool that can be downloaded and used immediately. It is suitable for developing business systems, website/APP API, admin panel, self-built low-code platforms, etc.
|
||||
|
||||
YAO adopts a flow-based programming model to implement various functions by writing YAO DSL (Logical Description in JSON format) or using JavaScript to write processes. The YAO DSL can be written in several ways:
|
||||
|
||||
1. Purely hand-written
|
||||
|
||||
2. Use automated scripts to generate contextual logic
|
||||
|
||||
3. Use the visual editor to create by "drag and drop"
|
||||
|
||||
**Discord:** https://discord.gg/nsKmCXwvxU
|
||||
|
||||
**Documentation:** https://yaoapps.com/en-US/doc
|
||||
|
||||
## Demo
|
||||
|
||||
### Customer Relationship Management System
|
||||
|
||||
A Customer Relationship Management System developed by Yao.
|
||||
|
||||
[https://demo-crm.yaoapps.com](https://demo-crm.yaoapps.com/xiang/login/admin?autoLogin=true)
|
||||
DEMO: [View Demo](https://demo-crm.yaoapps.com/xiang/login/admin?autoLogin=true)
|
||||
|
||||
SOURCE: [https://github.com/YaoApp/demo-crm](https://github.com/YaoApp/demo-crm)
|
||||
|
||||
INFRA: https://letsinfra.com/openapp/crm
|
||||
|
||||
### Intelligent warehouse management system
|
||||
|
||||
|
|
@ -55,7 +73,7 @@ An example of cloud + edge IoT application, an unattended intelligent warehouse
|
|||
|
||||
## Introduce
|
||||
|
||||
**Yao allows developers to create web services by processes.** Yao is a low-code engine that creates a database model, writes API services, and describes dashboard interface just by JSON for web & hardware, no code, and 10x productivity.
|
||||
**Yao allows developers to create web services by processes.** Yao is a app engine that creates a database model, writes API services, and describes dashboard interface just by JSON for web & hardware, and 10x productivity.
|
||||
|
||||
Yao is based on the **flow-based** programming idea, developed in the **Go** language, and supports multiple ways to expand the data stream processor. This makes Yao extremely versatile, which can replace programming languages in most scenarios, and is 10 times more efficient than traditional programming languages in terms of reusability and coding efficiency; application performance and resource ratio Better than **PHP**, **JAVA** and other languages.
|
||||
|
||||
|
|
@ -69,7 +87,7 @@ Run the script under terminal: (MacOS/Linux)
|
|||
curl -fsSL https://website.yaoapps.com/install.sh | bash
|
||||
```
|
||||
|
||||
For Windows users, please refer to the Installation and Debugging chapter: [Installation and debugging](https://yaoapps.com/en-US/doc/a.Introduction/b.Install)
|
||||
For Windows users, please refer to the Installation and Debugging chapter: [Installation and debugging](https://yaoapps.com/en-US/doc/Introduction/Install)
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
|
@ -121,4 +139,4 @@ yao start
|
|||
|
||||
## About Yao
|
||||
|
||||
Yao's name is derived from the Chinese character **yao (yáo)**, the basic symbol that makes up the Eight Trigrams. The Eight Trigrams is a symbol system created by the ancient god Fuxi after observing and summarizing the laws of nature, which can refer to everything. Yao has two states of yin and yang, like 0 and 1. The transformation of yin and yang of Yao drives the replacement of Eight Trigrams, so as to summarize and record the development law of things.
|
||||
Yao's name is derived from the Chinese character **爻 (yáo)**, the basic symbol that makes up the Eight Trigrams. The Eight Trigrams is a symbol system created by the ancient god Fuxi after observing and summarizing the laws of nature, which can refer to everything. Yao has two states of yin and yang, like 0 and 1. The transformation of yin and yang of Yao drives the replacement of Eight Trigrams, so as to summarize and record the development law of things.
|
||||
|
|
|
|||
|
|
@ -3,33 +3,53 @@
|
|||
[](https://github.com/YaoApp/yao/actions/workflows/unit-test.yml)
|
||||
[](https://codecov.io/gh/YaoApp/yao)
|
||||
|
||||

|
||||
|
||||
Yao 是一款支持快速创建 Web 服务和管理后台的开源低代码应用引擎。
|
||||

|
||||
|
||||
[English](README.md)
|
||||
|
||||
YAO 是一款开源应用引擎,使用 Golang 编写,以一个命令行工具的形式存在, 下载即用。适合用于开发业务系统、网站/APP API 接口、管理后台、自建低代码平台等。
|
||||
|
||||
YAO 采用 flow-based 的编程模式,通过编写 YAO DSL (JSON 格式逻辑描述) 或使用 JavaScript 编写处理器,实现各种功能。 YAO DSL 可以有多种编写方式:
|
||||
|
||||
1. 纯手工编写
|
||||
|
||||
2. 使用自动化脚本,根据上下文逻辑生成
|
||||
|
||||
3. 使用可视化编辑器,通过“拖拉拽”制作
|
||||
|
||||
官网: [https://yaoapps.com](https://yaoapps.com)
|
||||
|
||||
文档: [https://yaoapps.com/doc](https://yaoapps.com/doc)
|
||||
|
||||
微信群: 添加微信 17192175099 备注(开发交流)
|
||||
|
||||

|
||||
|
||||
## 演示
|
||||
|
||||
### 客户管理系统
|
||||
|
||||
使用 Yao 搭建的一套通用 CRM 管理系统。
|
||||
|
||||
[https://demo-crm.yaoapps.com](https://demo-crm.yaoapps.com/xiang/login/admin?autoLogin=true)
|
||||
演示: [查看演示](https://demo-crm.yaoapps.com/xiang/login/admin?autoLogin=true)
|
||||
|
||||
源码: https://github.com/YaoApp/demo-crm
|
||||
|
||||
Infra 一键部署: https://letsinfra.com/openapp/crm
|
||||
|
||||
### 智能仓库管理系统
|
||||
|
||||
使用 Yao 搭建的云+边物联网应用,支持人脸识别、RFID 的无人值守智能仓库管理系统。
|
||||
|
||||
[https://demo-wms.yaoapps.com](https://demo-crm.yaoapps.com/xiang/login/admin?autoLogin=true)
|
||||
演示: [查看演示](https://demo-crm.yaoapps.com/xiang/login/admin?autoLogin=true)
|
||||
|
||||
源码: https://github.com/YaoApp/yao-wms
|
||||
|
||||
Infra 一键部署: https://letsinfra.com/openapp/wms
|
||||
|
||||
## 介绍
|
||||
|
||||
Yao 是一个只需使用 JSON 即可创建数据库模型、编写 API 接口、描述管理后台界面的低代码引擎,使用 Yao 构建的应用可运行在云端或物联网设备上。 开发者不需要写一行代码,就可以拥有 10 倍生产力。
|
||||
Yao 是一个只需使用 JSON 即可创建数据库模型、编写 API 接口、描述管理后台界面的应用引擎,使用 Yao 构建的应用可运行在云端或物联网设备上。 开发者不需要写一行代码,就可以拥有 10 倍生产力。
|
||||
|
||||
Yao 基于 **flow-based** 编程思想,采用 **Go** 语言开发,支持多种方式扩展数据流处理器。这使得 Yao 具有极好的**通用性**,大部分场景下可以代替编程语言, 在复用性和编码效率上是传统编程语言的 **10 倍**;应用性能和资源占比上优于 **PHP**, **JAVA** 等语言。
|
||||
|
||||
|
|
|
|||
22
api/api.go
22
api/api.go
|
|
@ -3,6 +3,7 @@ package api
|
|||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
|
|
@ -23,14 +24,33 @@ 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)
|
||||
_, 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()))
|
||||
}
|
||||
})
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/websocket"
|
||||
"github.com/yaoapp/yao/config"
|
||||
)
|
||||
|
||||
|
|
@ -20,5 +21,12 @@ func check(t *testing.T) {
|
|||
for key := range gou.APIs {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 4, len(keys))
|
||||
|
||||
wskeys := []string{}
|
||||
for key := range websocket.Upgraders {
|
||||
wskeys = append(wskeys, key)
|
||||
}
|
||||
|
||||
assert.Equal(t, 5, len(keys))
|
||||
assert.Equal(t, 1, len(wskeys))
|
||||
}
|
||||
|
|
|
|||
130
app/app.go
130
app/app.go
|
|
@ -1,35 +1,32 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
l "github.com/yaoapp/gou/lang"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/data"
|
||||
"github.com/yaoapp/yao/lang"
|
||||
"github.com/yaoapp/yao/share"
|
||||
"github.com/yaoapp/yao/xfs"
|
||||
)
|
||||
|
||||
// langs 语言包
|
||||
var langs = map[string]map[string]string{}
|
||||
|
||||
// Load 加载应用信息
|
||||
// Load Application
|
||||
func Load(cfg config.Config) {
|
||||
Init(cfg)
|
||||
LoadInfo(cfg.Root)
|
||||
LoadLang(cfg)
|
||||
|
||||
lang := strings.ToLower(share.App.Lang)
|
||||
// Load language packs
|
||||
lang.Load(cfg)
|
||||
|
||||
// Set language pack
|
||||
share.App.L = map[string]string{}
|
||||
if l, has := langs[lang]; has {
|
||||
share.App.L = l
|
||||
if l.Default != nil {
|
||||
share.App.L = l.Default.Global
|
||||
}
|
||||
|
||||
// Load Info
|
||||
LoadInfo(cfg.Root)
|
||||
|
||||
}
|
||||
|
||||
// L 语言包
|
||||
|
|
@ -40,49 +37,6 @@ func L(word string) string {
|
|||
return word
|
||||
}
|
||||
|
||||
// Init 应用初始化
|
||||
func Init(cfg config.Config) {
|
||||
|
||||
// // UI文件目录
|
||||
// if _, err := os.Stat(cfg.RootUI); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(cfg.RootUI, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootUI, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
// content, err := data.Asset("xiang/data/index.html")
|
||||
// if err != nil {
|
||||
// xlog.Printf("读取文件失败(%s) %s", cfg.RootUI, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
// err = ioutil.WriteFile(filepath.Join(cfg.RootUI, "/index.html"), content, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("复制默认文件失败(%s) %s", cfg.RootUI, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 数据库目录
|
||||
// if _, err := os.Stat(cfg.RootDB); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(cfg.RootDB, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootDB, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 文件数据目录
|
||||
// if _, err := os.Stat(cfg.RootData); os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(cfg.RootData, os.ModePerm)
|
||||
// if err != nil {
|
||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootData, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// LoadInfo 应用信息
|
||||
func LoadInfo(root string) {
|
||||
info := defaultInfo()
|
||||
|
|
@ -106,71 +60,15 @@ func LoadInfo(root string) {
|
|||
info.Icons.Set("png", xfs.Encode(fs.MustReadFile("/yao/icons/icon.png")))
|
||||
}
|
||||
|
||||
info.L = share.App.L
|
||||
share.App = info
|
||||
}
|
||||
|
||||
// LoadLang 加载语言包
|
||||
func LoadLang(cfg config.Config) error {
|
||||
|
||||
var defaults = []share.Script{}
|
||||
if os.Getenv("YAO_DEV") != "" {
|
||||
defaults = share.GetFilesFS(filepath.Join(os.Getenv("YAO_DEV"), "yao"), ".json")
|
||||
} else {
|
||||
defaults = share.GetFilesBin("yao", ".json")
|
||||
}
|
||||
|
||||
for _, lang := range defaults {
|
||||
if lang.Type != "langs" {
|
||||
continue
|
||||
}
|
||||
content := lang.Content
|
||||
name := strings.ToLower(lang.Name) // 这个读取函数需要优化
|
||||
lang := map[string]string{}
|
||||
err := jsoniter.Unmarshal(content, &lang)
|
||||
if err != nil {
|
||||
log.With(log.F{"name": name}).Error(err.Error())
|
||||
}
|
||||
langs[name] = lang
|
||||
}
|
||||
|
||||
if share.BUILDIN {
|
||||
return LoadLangBuildIn("langs")
|
||||
}
|
||||
return LoadLangFrom(filepath.Join(cfg.Root, "langs"))
|
||||
}
|
||||
|
||||
// LoadLangBuildIn 从制品中读取
|
||||
func LoadLangBuildIn(dir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadLangFrom 从特定目录加载
|
||||
func LoadLangFrom(dir string) error {
|
||||
|
||||
if share.DirNotExists(dir) {
|
||||
return fmt.Errorf("%s does not exists", dir)
|
||||
}
|
||||
|
||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
||||
name := strings.ToLower(share.SpecName(root, filename))
|
||||
content := share.ReadFile(filename)
|
||||
lang := map[string]string{}
|
||||
err := jsoniter.Unmarshal(content, &lang)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
if _, has := langs[name]; !has {
|
||||
langs[name] = map[string]string{}
|
||||
}
|
||||
for src, dst := range lang {
|
||||
langs[name][src] = dst
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
// defaultInfo 读取默认应用信息
|
||||
func defaultInfo() share.AppInfo {
|
||||
info := share.AppInfo{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -9,7 +10,8 @@ import (
|
|||
)
|
||||
|
||||
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, "Xiang", share.App.L["象传"])
|
||||
assert.Equal(t, "YAO", share.App.L["Yao"])
|
||||
assert.Equal(t, "象传", share.App.L["Xiang"])
|
||||
}
|
||||
|
|
|
|||
8
brain/README.md
Normal file
8
brain/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# 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 )
|
||||
1
brain/behaviors/listen/listen.go
Normal file
1
brain/behaviors/listen/listen.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package listen
|
||||
1
brain/behaviors/send/send.go
Normal file
1
brain/behaviors/send/send.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package send
|
||||
7
brain/behaviors/zouyu/README.md
Normal file
7
brain/behaviors/zouyu/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# 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
|
||||
3
brain/behaviors/zouyu/types.go
Normal file
3
brain/behaviors/zouyu/types.go
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
package zouyu
|
||||
|
||||
type conn struct{}
|
||||
14
brain/behaviors/zouyu/zouyu.go
Normal file
14
brain/behaviors/zouyu/zouyu.go
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
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() {}
|
||||
18
brain/brain.go
Normal file
18
brain/brain.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
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
|
||||
}
|
||||
11
brain/brain_test.go
Normal file
11
brain/brain_test.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package brain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewBehaviors(t *testing.T) {
|
||||
behaviors, err := NewBehaviors("hello")
|
||||
fmt.Println(behaviors, err)
|
||||
}
|
||||
1
brain/cli/README.md
Normal file
1
brain/cli/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Command Line Interface
|
||||
1
brain/cli/cli.go
Normal file
1
brain/cli/cli.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package cli
|
||||
3
brain/cloud/README.md
Normal file
3
brain/cloud/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Cloud
|
||||
|
||||
Connecting AI cloud to analyze behaviors
|
||||
9
brain/types.go
Normal file
9
brain/types.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package brain
|
||||
|
||||
// Behaviors the Behaviors struct
|
||||
type Behaviors struct{}
|
||||
|
||||
// Response NPL Response
|
||||
type Response struct {
|
||||
Behaviors *Behaviors
|
||||
}
|
||||
1
brain/web/README.md
Normal file
1
brain/web/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# WEB Interface
|
||||
35
cert/cert.go
Normal file
35
cert/cert.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package cert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"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())
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
46
cert/cert_test.go
Normal file
46
cert/cert_test.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package cert
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/ssl"
|
||||
"github.com/yaoapp/yao/config"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
check(t)
|
||||
}
|
||||
|
||||
func TestProcessSign(t *testing.T) {
|
||||
Load(config.Conf)
|
||||
args := []interface{}{"hello world", "private", "SHA256"}
|
||||
signature, err := gou.NewProcess("ssl.Sign", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, "EDHf3C9TXEk7y8LzIk5czLefXZyGxcMDVMcbNuBBegDkTqnPsRQnhFtNOgCdox8lI3MzLatwjoljoMY4Qk+sHGd5mAHMpiREa1gRFSVYpA2xvXZ3+KsfOHAdICQrfUdy59QaJGo6iGPNGG8PQOXHPTVNn6LMfryat9+f4l21DPAZiT0RyCUgFZE3/Qv8Z/6J4AsIXMSKZD6BGPPHUxGe7UBrXZvcR5dX25EiNjuH2OO38YJnDiTRVw14UI5fk/mQrwRdezj5tSKFCyHt912BZExXtkHISiYFNTZ/2RhOup5Xx6o3GvrEOdshrnN80Lwu1Aaju+lnZp13hDz4P6hU7w==", signature)
|
||||
}
|
||||
|
||||
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()
|
||||
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))
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
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"
|
||||
|
|
@ -65,9 +66,7 @@ func LoadFrom(dir string, prefix string) error {
|
|||
// LoadChart 载入数据表格
|
||||
func LoadChart(source []byte, name string) (*Chart, error) {
|
||||
chart := &Chart{
|
||||
Flow: gou.Flow{
|
||||
Name: name,
|
||||
},
|
||||
Flow: &gou.Flow{Name: name},
|
||||
}
|
||||
err := jsoniter.Unmarshal(source, chart)
|
||||
if err != nil {
|
||||
|
|
@ -77,6 +76,12 @@ func LoadChart(source []byte, name string) (*Chart, error) {
|
|||
chart.Prepare()
|
||||
chart.SetupAPIs()
|
||||
Charts[name] = chart
|
||||
|
||||
// Apply a language pack
|
||||
if lang.Default != nil {
|
||||
lang.Default.Apply(Charts[name])
|
||||
}
|
||||
|
||||
return chart, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
package chart
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/lang"
|
||||
"github.com/yaoapp/yao/model"
|
||||
"github.com/yaoapp/yao/query"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
|
||||
os.Setenv("YAO_LANG", "zh-hk")
|
||||
lang.Load(config.Conf)
|
||||
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
|
@ -25,5 +31,15 @@ func check(t *testing.T) {
|
|||
for key := range Charts {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 1, len(keys))
|
||||
assert.Equal(t, 3, len(keys))
|
||||
|
||||
lang := Charts["lang"]
|
||||
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"])
|
||||
}
|
||||
|
|
|
|||
125
chart/lang.go
Normal file
125
chart/lang.go
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,10 @@ func ProcessData(process *gou.Process) interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
// with Session
|
||||
chart.Flow.WithGlobal(process.Global)
|
||||
chart.Flow.WithSID(process.Sid)
|
||||
|
||||
return chart.GetData(params)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ 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/kun/utils"
|
||||
"github.com/yaoapp/yao/config"
|
||||
_ "github.com/yaoapp/yao/helper"
|
||||
"github.com/yaoapp/yao/model"
|
||||
|
|
@ -68,10 +69,36 @@ func TestProcessData(t *testing.T) {
|
|||
}
|
||||
process := gou.NewProcess("xiang.chart.Data", args...)
|
||||
response := ProcessData(process)
|
||||
utils.Dump(response)
|
||||
// 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"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
// Chart 图表格式
|
||||
type Chart struct {
|
||||
gou.Flow
|
||||
*gou.Flow
|
||||
APIs map[string]share.API `json:"apis,omitempty"`
|
||||
Filters map[string]share.Filter `json:"filters,omitempty"`
|
||||
Page share.Page `json:"page,omitempty"`
|
||||
|
|
|
|||
1
cmd/brain.go
Normal file
1
cmd/brain.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package cmd
|
||||
205
cmd/dump.go
Normal file
205
cmd/dump.go
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
var dumpModel string
|
||||
var dumpCmd = &cobra.Command{
|
||||
Use: "dump",
|
||||
Short: L("Dump the application data"),
|
||||
Long: L("Dump the application data"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
defer func() {
|
||||
err := exception.Catch(recover())
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
Boot()
|
||||
|
||||
path, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
output := filepath.Join(fmt.Sprintf("%s-%s.zip", filepath.Base(path), time.Now().Format("20060102150405")))
|
||||
if len(args) > 0 {
|
||||
output = args[0]
|
||||
}
|
||||
|
||||
output, err = filepath.Abs(output)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
_, err = os.Stat(output)
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
fmt.Println(color.RedString("%s exists", output))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Load model
|
||||
err = engine.Load(config.Conf)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if dumpModel != "" {
|
||||
fmt.Println(color.YellowString(L("Not supported yet")))
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
// Export models
|
||||
files := []string{}
|
||||
for _, mod := range gou.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) {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf("\r%s", color.GreenString(L("Export the models: %s (%s) %d/%d"), mod.Name, mod.MetaData.Table.Name, curr, total))
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
files = append(files, jsonfiles...)
|
||||
}
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf("\r%s\n", color.GreenString(L("Export the models: ✨DONE✨")))
|
||||
|
||||
// Compress files
|
||||
err = zipfiles(files, output, func(file string) {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf("\r%s", color.GreenString(L("Compress the files: %s"), file))
|
||||
})
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf("\r%s\n", color.GreenString(L("Compress the files: ✨DONE✨")))
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println(color.GreenString("File: %s", output))
|
||||
},
|
||||
}
|
||||
|
||||
// func init() {
|
||||
// // dumpCmd.PersistentFlags().StringVarP(&dumpModel, "name", "n", "", L("Model name"))
|
||||
// }
|
||||
|
||||
// gzipfiles
|
||||
func zipfiles(files []string, output string, process func(file string)) error {
|
||||
outpath := filepath.Dir(output)
|
||||
os.MkdirAll(outpath, 0755)
|
||||
|
||||
outfile, err := os.Create(output)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
defer outfile.Close()
|
||||
|
||||
w := zip.NewWriter(outfile)
|
||||
defer func() {
|
||||
w.Close()
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
for _, file := range files {
|
||||
addFile(w, file, "model", process)
|
||||
}
|
||||
|
||||
// Add data path
|
||||
dataPath := filepath.Join(config.Conf.Root, "data")
|
||||
_, err = os.Stat(dataPath)
|
||||
if err == nil {
|
||||
addFolder(w, dataPath, "data", process)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addFile(w *zip.Writer, file, baseInZip string, process func(file string)) {
|
||||
process(filepath.Join(baseInZip, filepath.Base(file)))
|
||||
dat, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Add some files to the archive.
|
||||
f, err := w.Create(filepath.Join(baseInZip, filepath.Base(file)))
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
_, err = f.Write(dat)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Remove(file)
|
||||
}
|
||||
|
||||
func addFolder(w *zip.Writer, basePath, baseInZip string, process func(file string)) {
|
||||
|
||||
// Open the Directory
|
||||
files, err := ioutil.ReadDir(basePath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
process(filepath.Join(baseInZip, file.Name()))
|
||||
if !file.IsDir() {
|
||||
dat, err := ioutil.ReadFile(filepath.Join(basePath, file.Name()))
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Add some files to the archive.
|
||||
f, err := w.Create(filepath.Join(baseInZip, file.Name()))
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
_, err = f.Write(dat)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if file.IsDir() {
|
||||
// Recurse
|
||||
newBase := filepath.Join(basePath, file.Name())
|
||||
addFolder(w, newBase, filepath.Join(baseInZip, file.Name()), process)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -301,7 +301,8 @@ func makeFile(name string, source string) {
|
|||
makeFileContent(name, []byte(source))
|
||||
}
|
||||
|
||||
func makeFileContent(filename string, content []byte) {
|
||||
func makeFileContent(name string, content []byte) {
|
||||
filename := filepath.Join(config.Conf.Root, name)
|
||||
err := os.WriteFile(filename, content, 0644)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
var name string
|
||||
var force bool = false
|
||||
var resetModel bool = false
|
||||
var migrateCmd = &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: L("Update database schema"),
|
||||
|
|
@ -43,23 +44,57 @@ var migrateCmd = &cobra.Command{
|
|||
|
||||
if name != "" {
|
||||
mod, has := gou.Models[name]
|
||||
if has {
|
||||
mod.Migrate(true)
|
||||
fmt.Printf(color.WhiteString(L("Update schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name) + "\t")
|
||||
|
||||
if !has {
|
||||
fmt.Println(color.RedString(L("Model: %s does not exits"), name))
|
||||
return
|
||||
}
|
||||
|
||||
if resetModel {
|
||||
err := mod.DropTable()
|
||||
if err != nil {
|
||||
fmt.Printf(color.RedString(L("FAILURE\n%s"), err.Error()) + "\n")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err := mod.Migrate(false)
|
||||
if err != nil {
|
||||
fmt.Printf(color.RedString(L("FAILURE\n%s"), err.Error()) + "\n")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf(color.GreenString(L("SUCCESS")) + "\n")
|
||||
return
|
||||
}
|
||||
|
||||
// Do Stuff Here
|
||||
for _, mod := range gou.Models {
|
||||
fmt.Println(color.GreenString(L("Update schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name))
|
||||
mod.Migrate(true)
|
||||
fmt.Printf(color.WhiteString(L("Update schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name) + "\t")
|
||||
|
||||
if resetModel {
|
||||
err := mod.DropTable()
|
||||
if err != nil {
|
||||
fmt.Printf(color.RedString(L("FAILURE\n%s"), err.Error()) + "\n")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
err := mod.Migrate(false)
|
||||
if err != nil {
|
||||
fmt.Printf(color.RedString(L("FAILURE\n%s"), err.Error()) + "\n")
|
||||
continue
|
||||
}
|
||||
fmt.Printf(color.GreenString(L("SUCCESS")) + "\n")
|
||||
}
|
||||
|
||||
fmt.Println(color.GreenString(L("✨DONE✨")))
|
||||
// fmt.Println(color.GreenString(L("✨DONE✨")))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
migrateCmd.PersistentFlags().StringVarP(&name, "name", "n", "", L("Model name"))
|
||||
migrateCmd.PersistentFlags().BoolVarP(&force, "force", "", false, L("Force migrate"))
|
||||
migrateCmd.PersistentFlags().BoolVarP(&resetModel, "reset", "", false, L("Drop the table if exist"))
|
||||
}
|
||||
|
|
|
|||
206
cmd/restore.go
Normal file
206
cmd/restore.go
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
var restoreForce bool = false
|
||||
var restoreCmd = &cobra.Command{
|
||||
Use: "restore",
|
||||
Short: L("Restore the application data"),
|
||||
Long: L("Restore the application data"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
defer func() {
|
||||
err := exception.Catch(recover())
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
if len(args) < 1 {
|
||||
fmt.Println(color.RedString(L("Not enough arguments")))
|
||||
fmt.Println(color.WhiteString(share.BUILDNAME + " help"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
zipfile, err := filepath.Abs(args[0])
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
Boot()
|
||||
|
||||
if !restoreForce && config.Conf.Mode == "production" {
|
||||
fmt.Println(color.WhiteString(L("TRY:")), color.GreenString("%s restore --force", share.BUILDNAME))
|
||||
exception.New(L("Retore is not allowed on production mode."), 403).Throw()
|
||||
}
|
||||
|
||||
// Unzip files
|
||||
dst := unzipFile(zipfile, func(file string) {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf("\r%s", color.GreenString(L("Unzip the file: %s"), file))
|
||||
})
|
||||
|
||||
// 加载数据模型
|
||||
err = engine.Load(config.Conf)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Restore models
|
||||
restoreModels(filepath.Join(dst, "model"))
|
||||
|
||||
// Restore Data
|
||||
restoreData(filepath.Join(dst, "data"))
|
||||
|
||||
// Clean
|
||||
os.RemoveAll(dst)
|
||||
|
||||
fmt.Println(color.GreenString(L("✨DONE✨")))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
restoreCmd.PersistentFlags().BoolVarP(&restoreForce, "force", "", false, L("Force restore"))
|
||||
}
|
||||
|
||||
func restoreData(basePath string) {
|
||||
|
||||
_, err := os.Stat(basePath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Clean Data
|
||||
dataPath := filepath.Join(config.Conf.Root, "data")
|
||||
_, err = os.Stat(dataPath)
|
||||
if err == nil {
|
||||
os.RemoveAll(dataPath)
|
||||
}
|
||||
|
||||
err = os.Rename(basePath, dataPath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func restoreModels(basePath string) {
|
||||
|
||||
files, err := ioutil.ReadDir(basePath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Migrate models
|
||||
for _, mod := range gou.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)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
|
||||
for _, file := range files {
|
||||
namer := strings.Split(file.Name(), ".")
|
||||
name := strings.Join(namer[:len(namer)-2], ".")
|
||||
if mod, has := gou.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()))
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func unzipFile(file string, process func(file string)) string {
|
||||
_, err := os.Stat(file)
|
||||
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
fmt.Println(color.RedString("%s not exists", file))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dst := filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s", filepath.Base(file), time.Now().Format("20060102150405")))
|
||||
os.MkdirAll(dst, 0755)
|
||||
|
||||
archive, err := zip.OpenReader(file)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
defer archive.Close()
|
||||
|
||||
for _, f := range archive.File {
|
||||
filePath := filepath.Join(dst, f.Name)
|
||||
process(f.Name)
|
||||
|
||||
if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {
|
||||
fmt.Println(color.RedString(L("Fatal: invalid file path")))
|
||||
os.Exit(1)
|
||||
}
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(filePath, os.ModePerm)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fileInArchive, err := f.Open()
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dstFile.Close()
|
||||
fileInArchive.Close()
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
49
cmd/root.go
49
cmd/root.go
|
|
@ -45,6 +45,7 @@ var langs = map[string]string{
|
|||
"NEXT:": "下一步:",
|
||||
"Listening": " 监听",
|
||||
"✨LISTENING✨": "✨服务正在运行✨",
|
||||
"✨STOPPED✨": "✨服务已停止✨",
|
||||
"SessionPort": "会话服务端口",
|
||||
"Force migrate": "强制更新数据表结构",
|
||||
"Migrate is not allowed on production mode.": "Migrate 不能再生产环境下使用",
|
||||
|
|
@ -91,6 +92,11 @@ func init() {
|
|||
startCmd,
|
||||
runCmd,
|
||||
initCmd,
|
||||
serviceCmd,
|
||||
dumpCmd,
|
||||
restoreCmd,
|
||||
socketCmd,
|
||||
websocketCmd,
|
||||
)
|
||||
// rootCmd.SetHelpCommand(helpCmd)
|
||||
rootCmd.PersistentFlags().StringVarP(&appPath, "app", "a", "", L("Application directory"))
|
||||
|
|
@ -105,42 +111,25 @@ func Execute() {
|
|||
}
|
||||
}
|
||||
|
||||
// Boot 设定配置 (这个逻辑有 BUG )
|
||||
// Boot 设定配置
|
||||
func Boot() {
|
||||
|
||||
if envFile == "" && appPath != "" {
|
||||
root, err := filepath.Abs(appPath)
|
||||
root := config.Conf.Root
|
||||
if appPath != "" {
|
||||
r, err := filepath.Abs(appPath)
|
||||
if err != nil {
|
||||
exception.New("Root error %s", 500, err.Error()).Throw()
|
||||
}
|
||||
root = r
|
||||
}
|
||||
if envFile != "" {
|
||||
config.Conf = config.LoadFrom(envFile)
|
||||
} else {
|
||||
config.Conf = config.LoadFrom(filepath.Join(root, ".env"))
|
||||
config.Conf.Root = root
|
||||
if config.Conf.Mode == "production" {
|
||||
config.Production()
|
||||
} else if config.Conf.Mode == "development" {
|
||||
config.Development()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if envFile != "" && appPath == "" { // 指定环境变量文件
|
||||
// config.SetEnvFile(envFile)
|
||||
config.Conf = config.LoadFrom(envFile)
|
||||
}
|
||||
|
||||
if envFile != "" && appPath != "" {
|
||||
root, err := filepath.Abs(appPath)
|
||||
if err != nil {
|
||||
exception.New("Root error %s", 500, err.Error()).Throw()
|
||||
}
|
||||
config.Conf = config.LoadFrom(envFile)
|
||||
config.Conf.Root = root
|
||||
if config.Conf.Mode == "production" {
|
||||
config.Production()
|
||||
} else if config.Conf.Mode == "development" {
|
||||
config.Development()
|
||||
}
|
||||
|
||||
if config.Conf.Mode == "production" {
|
||||
config.Production()
|
||||
} else if config.Conf.Mode == "development" {
|
||||
config.Development()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ var runCmd = &cobra.Command{
|
|||
Short: L("Execute process"),
|
||||
Long: L("Execute process"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
defer share.SessionStop()
|
||||
defer gou.KillPlugins()
|
||||
defer func() {
|
||||
err := exception.Catch(recover())
|
||||
|
|
|
|||
173
cmd/service.go
Normal file
173
cmd/service.go
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
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"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
110
cmd/socket.go
Normal file
110
cmd/socket.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"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"
|
||||
)
|
||||
|
||||
var socketCmd = &cobra.Command{
|
||||
Use: "socket",
|
||||
Short: L("Open a socket connection"),
|
||||
Long: L("Open a socket 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()))
|
||||
}
|
||||
}()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
pargs := []interface{}{}
|
||||
for i, arg := range args {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析参数
|
||||
if strings.HasPrefix(arg, "::") {
|
||||
arg := strings.TrimPrefix(arg, "::")
|
||||
var v interface{}
|
||||
err := jsoniter.Unmarshal([]byte(arg), &v)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Arguments: %s"), err.Error()))
|
||||
return
|
||||
}
|
||||
pargs = append(pargs, v)
|
||||
fmt.Println(color.WhiteString("args[%d]: %s", i-1, arg))
|
||||
} else if strings.HasPrefix(arg, "\\::") {
|
||||
arg := "::" + strings.TrimPrefix(arg, "\\::")
|
||||
pargs = append(pargs, arg)
|
||||
fmt.Println(color.WhiteString("args[%d]: %s", i-1, arg))
|
||||
} else {
|
||||
pargs = append(pargs, arg)
|
||||
fmt.Println(color.WhiteString("args[%d]: %s", i-1, arg))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
socket, has := gou.Sockets[name]
|
||||
if !has {
|
||||
fmt.Println(color.RedString(L("%s not exists!"), name))
|
||||
return
|
||||
}
|
||||
|
||||
if socket.Mode != "client" {
|
||||
fmt.Println(color.RedString(L("%s not supported yet!"), socket.Mode))
|
||||
return
|
||||
}
|
||||
|
||||
host := socket.Host
|
||||
port := socket.Port
|
||||
argsLen := len(pargs)
|
||||
if argsLen > 0 {
|
||||
if inputHost, ok := pargs[0].(string); ok {
|
||||
host = inputHost
|
||||
}
|
||||
}
|
||||
|
||||
if argsLen > 1 {
|
||||
if inputPort, ok := pargs[1].(string); ok {
|
||||
port = inputPort
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(socket.Name))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
fmt.Println(color.GreenString("Mode: %s", socket.Mode))
|
||||
fmt.Println(color.GreenString("Host: %s://%s", socket.Protocol, host))
|
||||
fmt.Println(color.GreenString("Port: %s", port))
|
||||
fmt.Println(color.WhiteString("--------------------------------------"))
|
||||
err := socket.Open(pargs...)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("%s"), err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
171
cmd/start.go
171
cmd/start.go
|
|
@ -1,14 +1,21 @@
|
|||
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/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/service"
|
||||
|
|
@ -16,14 +23,19 @@ import (
|
|||
)
|
||||
|
||||
var startDebug = false
|
||||
var startAlpha = false
|
||||
var startDisableWatching = false
|
||||
|
||||
var startCmd = &cobra.Command{
|
||||
Use: "start",
|
||||
Short: L("Start Engine"),
|
||||
Long: L("Start Engine"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
defer service.Stop(func() { fmt.Println(L("Service stopped")) })
|
||||
|
||||
// recive interrupt signal
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
||||
// defer service.Stop(func() { fmt.Println(L("Service stopped")) })
|
||||
Boot()
|
||||
|
||||
if startDebug { // 强制 debug 模式启动
|
||||
|
|
@ -46,27 +58,6 @@ var startCmd = &cobra.Command{
|
|||
host = "127.0.0.1"
|
||||
}
|
||||
|
||||
if mode == "development" {
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(L("API List")))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
|
||||
for _, api := range gou.APIs { // API信息
|
||||
if len(api.HTTP.Paths) <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf(color.CyanString("\n%s(%d)\n", api.Name, len(api.HTTP.Paths)))
|
||||
for _, p := range api.HTTP.Paths {
|
||||
fmt.Println(
|
||||
colorMehtod(p.Method),
|
||||
color.WhiteString(filepath.Join("/api", api.HTTP.Group, p.Path)),
|
||||
"\tprocess:", p.Process)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(share.App.Name), color.WhiteString(share.App.Version), mode)
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
|
|
@ -78,33 +69,135 @@ var startCmd = &cobra.Command{
|
|||
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("SessionPort")), color.GreenString(" %d", share.SessionPort))
|
||||
fmt.Println(color.WhiteString(L("Listening")), color.GreenString(" %s:%d", config.Conf.Host, config.Conf.Port))
|
||||
|
||||
fmt.Println("")
|
||||
|
||||
// 调试模式
|
||||
// development mode
|
||||
if mode == "development" {
|
||||
printApis(false)
|
||||
printTasks(false)
|
||||
printSchedules(false)
|
||||
}
|
||||
|
||||
if mode == "development" && !startDisableWatching {
|
||||
// Watching
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(L("Watching")))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
service.Watch(config.Conf)
|
||||
}
|
||||
|
||||
// 启用内测功能
|
||||
if startAlpha {
|
||||
for _, srv := range gou.Servers {
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(srv.Name))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
fmt.Println(color.GreenString("Host: %s://%s", srv.Protocol, srv.Host))
|
||||
fmt.Println(color.GreenString("Port: %s\n\n", srv.Port))
|
||||
go srv.Start()
|
||||
}
|
||||
if mode == "production" {
|
||||
printApis(true)
|
||||
printTasks(true)
|
||||
printSchedules(true)
|
||||
}
|
||||
|
||||
// Start server
|
||||
go service.Start()
|
||||
fmt.Println(color.GreenString(L("✨LISTENING✨")))
|
||||
service.Start()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-interrupt:
|
||||
ctx, canceled := context.WithTimeout(context.Background(), (5 * time.Second))
|
||||
defer canceled()
|
||||
service.StopWithContext(ctx, func() {
|
||||
fmt.Println(color.GreenString(L("✨STOPPED✨")))
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func printSchedules(silent bool) {
|
||||
if silent {
|
||||
for name, sch := range gou.Schedules {
|
||||
process := fmt.Sprintf("Process: %s", sch.Process)
|
||||
if sch.TaskName != "" {
|
||||
process = fmt.Sprintf("Task: %s", sch.TaskName)
|
||||
}
|
||||
log.Info("[Schedule] %s %s %s %s", sch.Schedule, name, sch.Name, process)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(L("Schedules List (%d)"), len(gou.Schedules)))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
for name, sch := range gou.Schedules {
|
||||
process := fmt.Sprintf("Process: %s", sch.Process)
|
||||
if sch.TaskName != "" {
|
||||
process = fmt.Sprintf("Task: %s", sch.TaskName)
|
||||
}
|
||||
fmt.Printf(color.CyanString("[Schedule] %s %s", sch.Schedule, name))
|
||||
fmt.Printf(color.WhiteString("\t%s\t%s\n", sch.Name, process))
|
||||
}
|
||||
}
|
||||
|
||||
func printTasks(silent bool) {
|
||||
|
||||
if silent {
|
||||
for _, t := range task.Tasks {
|
||||
log.Info("[Task] %s workers:%d", t.Option.Name, t.Option.WorkerNums)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(L("Tasks List (%d)"), len(task.Tasks)))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
for _, t := range task.Tasks {
|
||||
fmt.Printf(color.CyanString("[Task] %s", t.Option.Name))
|
||||
fmt.Printf(color.WhiteString("\t workers: %d\n", t.Option.WorkerNums))
|
||||
}
|
||||
}
|
||||
|
||||
func printApis(silent bool) {
|
||||
|
||||
if silent {
|
||||
for _, api := range gou.APIs {
|
||||
if len(api.HTTP.Paths) <= 0 {
|
||||
continue
|
||||
}
|
||||
log.Info("[API] %s(%d)", api.Name, len(api.HTTP.Paths))
|
||||
for _, p := range api.HTTP.Paths {
|
||||
log.Info("%s %s %s", p.Method, filepath.Join("/api", api.HTTP.Group, p.Path), p.Process)
|
||||
}
|
||||
}
|
||||
for name, upgrader := range websocket.Upgraders { // WebSocket
|
||||
log.Info("[WebSocket] GET /websocket/%s process:%s", name, upgrader.Process)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(color.WhiteString("\n---------------------------------"))
|
||||
fmt.Println(color.WhiteString(L("API List")))
|
||||
fmt.Println(color.WhiteString("---------------------------------"))
|
||||
|
||||
for _, api := range gou.APIs { // API信息
|
||||
if len(api.HTTP.Paths) <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf(color.CyanString("\n%s(%d)\n", api.Name, len(api.HTTP.Paths)))
|
||||
for _, p := range api.HTTP.Paths {
|
||||
fmt.Println(
|
||||
colorMehtod(p.Method),
|
||||
color.WhiteString(filepath.Join("/api", api.HTTP.Group, p.Path)),
|
||||
"\tprocess:", p.Process)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf(color.CyanString("\n%s(%d)\n", "WebSocket", len(websocket.Upgraders)))
|
||||
for name, upgrader := range websocket.Upgraders { // WebSocket
|
||||
fmt.Println(
|
||||
colorMehtod("GET"),
|
||||
color.WhiteString(filepath.Join("/websocket", name)),
|
||||
"\tprocess:", upgrader.Process)
|
||||
}
|
||||
}
|
||||
|
||||
func colorMehtod(method string) string {
|
||||
method = strings.ToUpper(method)
|
||||
switch method {
|
||||
|
|
@ -119,5 +212,5 @@ func colorMehtod(method string) string {
|
|||
|
||||
func init() {
|
||||
startCmd.PersistentFlags().BoolVarP(&startDebug, "debug", "", false, L("Development mode"))
|
||||
startCmd.PersistentFlags().BoolVarP(&startAlpha, "alpha", "", false, L("Enabled unstable features"))
|
||||
startCmd.PersistentFlags().BoolVarP(&startDisableWatching, "disable-watching", "", false, L("Disable watching"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,13 @@ var versionCmd = &cobra.Command{
|
|||
Short: L("Show version"),
|
||||
Long: L("Show version"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
version := share.VERSION
|
||||
if share.PRVERSION != "" {
|
||||
version = fmt.Sprintf("%s-%s", share.VERSION, share.PRVERSION)
|
||||
}
|
||||
|
||||
// Do Stuff Here
|
||||
fmt.Println(share.VERSION)
|
||||
fmt.Println(version)
|
||||
},
|
||||
}
|
||||
|
|
|
|||
71
cmd/websocket.go
Normal file
71
cmd/websocket.go
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"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/engine"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
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()))
|
||||
}
|
||||
}()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
websocket, has := gou.WebSockets[name]
|
||||
if !has {
|
||||
fmt.Println(color.RedString(L("%s not exists!"), name))
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
},
|
||||
}
|
||||
251
config/config.go
251
config/config.go
|
|
@ -60,7 +60,7 @@ func Load() Config {
|
|||
// Production 设定为生产环境
|
||||
func Production() {
|
||||
Conf.Mode = "production"
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
log.SetLevel(log.InfoLevel)
|
||||
log.SetFormatter(log.TEXT)
|
||||
if Conf.LogMode == "JSON" {
|
||||
log.SetFormatter(log.JSON)
|
||||
|
|
@ -124,252 +124,3 @@ func CloseLog() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // Config 系统配置
|
||||
// type Config struct {
|
||||
// XiangConfig
|
||||
// Service ServiceConfig `json:"service,omitempty"`
|
||||
// Session SessionConfig `json:"session,omitempty"`
|
||||
// Database DatabaseConfig `json:"database,omitempty"`
|
||||
// JWT JWTConfig `json:"jwt,omitempty"`
|
||||
// Log LogConfig `json:"log,omitempty"`
|
||||
// }
|
||||
|
||||
// // JWTConfig JWT配置
|
||||
// type JWTConfig struct {
|
||||
// Secret string `json:"secret,omitempty" env:"YAO_JWT_SECRET"` // JWT 密钥
|
||||
// }
|
||||
|
||||
// // LogConfig 日志配置
|
||||
// type LogConfig struct {
|
||||
// Access string `json:"access,omitempty" env:"XIANG_LOG_ACCESS" envDefault:"os://stdout"` // 服务访问日志
|
||||
// Error string `json:"error,omitempty" env:"XIANG_LOG_ERROR" envDefault:"os://stderr"` // 服务错误日志
|
||||
// DB string `json:"database,omitempty" env:"XIANG_LOG_DB" envDefault:"os://stdout"` // 数据库日志
|
||||
// Plugin string `json:"plugin,omitempty" env:"XIANG_LOG_PLUGIN" envDefault:"os://stdout"` // 插件日志
|
||||
// }
|
||||
|
||||
// // XiangConfig 象传应用引擎配置
|
||||
// type XiangConfig struct {
|
||||
// Mode string `json:"mode,omitempty" env:"XIANG_MODE" envDefault:"release"` // 象传引擎模式 debug/release/test
|
||||
// Source string `json:"source,omitempty" env:"XIANG_SOURCE" envDefault:"fs://."` // 源码路径(用于单元测试载入数据)
|
||||
// Path string `json:"path,omitempty" env:"XIANG_PATH" envDefault:"bin://xiang"` // 引擎文件目录
|
||||
// Root string `json:"root,omitempty" env:"XIANG_ROOT" envDefault:"fs://."` // 应用文件目录
|
||||
// RootUI string `json:"root_ui,omitempty" env:"XIANG_ROOT_UI"` // 应用界面静态文件目录
|
||||
// RootDB string `json:"root_db,omitempty" env:"XIANG_ROOT_DB"` // 应用SQLite数据库目录
|
||||
// RootData string `json:"root_data,omitempty" env:"XIANG_ROOT_DATA"` // 应用数据文件目录
|
||||
// RootAPI string `json:"root_api,omitempty" env:"XIANG_ROOT_API"` // 应用API文件目录
|
||||
// RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录
|
||||
// RootFLow string `json:"root_flow,omitempty" env:"XIANG_ROOT_FLOW"` // 应用业务逻辑文件目录
|
||||
// RootPlugin string `json:"root_plugin,omitempty" env:"XIANG_ROOT_PLUGIN"` // 应用业务插件文件目录
|
||||
// RootLib string `json:"root_lib,omitempty" env:"XIANG_ROOT_LIB"` // 应用资料库文件目录
|
||||
// RootTable string `json:"root_table,omitempty" env:"XIANG_ROOT_TABLE"` // 应用数据表格文件目录
|
||||
// RootChart string `json:"root_chart,omitempty" env:"XIANG_ROOT_CHART"` // 应用分析图表文件目录
|
||||
// RootPage string `json:"root_page,omitempty" env:"XIANG_ROOT_PAGE"` // 应用通用页面文件目录
|
||||
// RootScreen string `json:"root_screen,omitempty" env:"XIANG_ROOT_SCREEN"` // 应用大屏文件目录
|
||||
// RootForm string `json:"root_form,omitempty" env:"XIANG_ROOT_FORM"` // 表单文件目录
|
||||
// RootWorkFlow string `json:"root_workflow,omitempty" env:"XIANG_ROOT_WORKFLOW"` // 工作流文件目录
|
||||
// }
|
||||
|
||||
// // ServiceConfig 服务配置
|
||||
// type ServiceConfig struct {
|
||||
// Debug bool `json:"debug,omitempty" env:"XIANG_SERVICE_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
// HTTPS bool `json:"https,omitempty" env:"XIANG_SERVICE_HTTPS" envDefault:"false"` // HTTPS 开关
|
||||
// Cert string `json:"cert,omitempty" env:"XIANG_SERVICE_CERT"` // HTTPS 证书
|
||||
// Key string `json:"key,omitempty" env:"XIANG_SERVICE_KEY"` // HTTPS 证书密钥
|
||||
// Allow []string `json:"allow,omitempty" env:"XIANG_SERVICE_ALLOW" envSeparator:"|"` // 跨域访问域名列表
|
||||
// Host string `json:"host,omitempty" env:"XIANG_SERVICE_HOST" envDefault:"127.0.0.1"` // 服务监听IP
|
||||
// Port int `json:"port,omitempty" env:"XIANG_SERVICE_PORT" envDefault:"5099"` // 服务监听端口
|
||||
// }
|
||||
|
||||
// SessionConfig 会话服务器
|
||||
type SessionConfig struct {
|
||||
Debug bool `json:"debug,omitempty" env:"XIANG_SESSION_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
Hosting bool `json:"hosting,omitempty" env:"XIANG_SESSION_HOSTING" envDefault:"true"` // 会话服务器
|
||||
IsCLI bool `json:"iscli,omitempty" env:"XIANG_SESSION_ISCLI" envDefault:"false"` // 是否为客户端启动
|
||||
Host string `json:"host,omitempty" env:"XIANG_SESSION_HOST" envDefault:"127.0.0.1"` // 会话服务器IP
|
||||
Port int `json:"port,omitempty" env:"XIANG_SESSION_PORT" envDefault:"3322"` // 会话服务器端口
|
||||
}
|
||||
|
||||
// // DatabaseConfig 数据库配置
|
||||
// type DatabaseConfig struct {
|
||||
// Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关
|
||||
// Driver string `json:"driver,omitempty" env:"XIANG_DB_DRIVER" envDefault:"sqlite3"` // 数据库驱动 ( sqlite3, mysql, postgres)
|
||||
// Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|" envDefault:"file:./db/xiang.db"` // 主库连接DSN
|
||||
// Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN
|
||||
// AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY
|
||||
// }
|
||||
|
||||
// // NewConfig 创建配置文件
|
||||
// func NewConfig(envfile ...string) Config {
|
||||
|
||||
// filename := os.Getenv("XIANG_ENV_FILE")
|
||||
// if filename == "" {
|
||||
// filename = ".env"
|
||||
// }
|
||||
|
||||
// if len(envfile) > 0 {
|
||||
// file, err := filepath.Abs(envfile[0])
|
||||
// if err == nil {
|
||||
// // log.Printf("加载环境配置文件%s出错 %s\n", envfile[0], err.Error())
|
||||
// // } else {
|
||||
// filename = file
|
||||
// }
|
||||
// }
|
||||
|
||||
// godotenv.Overload(filename)
|
||||
// // if err != nil {
|
||||
// // log.Printf("加载环境配置文件%s出错 %s\n", filename, err.Error())
|
||||
// // }
|
||||
|
||||
// cfg := Config{}
|
||||
// if err := env.Parse(&cfg); err != nil {
|
||||
// exception.New("解析配置文件出错 %s", 500, err.Error()).Throw()
|
||||
// }
|
||||
|
||||
// cfg.SetDefaults()
|
||||
// return cfg
|
||||
// }
|
||||
|
||||
// // NewConfigFrom 创建配置文件
|
||||
// func NewConfigFrom(input io.Reader) Config {
|
||||
// cfg := Config{}
|
||||
// err := helper.UnmarshalFile(input, &cfg)
|
||||
// if err != nil {
|
||||
// exception.New("解析配置文件出错 %s", 500, err.Error()).Throw()
|
||||
// }
|
||||
// cfg.SetDefaults()
|
||||
// return cfg
|
||||
// }
|
||||
|
||||
// // SetDefaults 设定默认值
|
||||
// func (cfg *Config) SetDefaults() {
|
||||
|
||||
// pwd, err := os.Getwd()
|
||||
// if err != nil {
|
||||
// log.Fatal(err.Error())
|
||||
// }
|
||||
|
||||
// if cfg.Root == "fs://." || cfg.Root == "." {
|
||||
// cfg.Root = pwd
|
||||
// }
|
||||
|
||||
// if cfg.RootAPI == "" {
|
||||
// cfg.RootAPI = cfg.Root + "/apis"
|
||||
// }
|
||||
// if cfg.RootFLow == "" {
|
||||
// cfg.RootFLow = cfg.Root + "/flows"
|
||||
// }
|
||||
// if cfg.RootModel == "" {
|
||||
// cfg.RootModel = cfg.Root + "/models"
|
||||
// }
|
||||
// if cfg.RootPlugin == "" {
|
||||
// cfg.RootPlugin = cfg.Root + "/plugins"
|
||||
// }
|
||||
|
||||
// if cfg.RootTable == "" {
|
||||
// cfg.RootTable = cfg.Root + "/tables"
|
||||
// }
|
||||
|
||||
// if cfg.RootLib == "" {
|
||||
// cfg.RootLib = cfg.Root + "/libs"
|
||||
// }
|
||||
|
||||
// if cfg.RootChart == "" {
|
||||
// cfg.RootChart = cfg.Root + "/charts"
|
||||
// }
|
||||
|
||||
// if cfg.RootPage == "" {
|
||||
// cfg.RootPage = cfg.Root + "/pages"
|
||||
// }
|
||||
|
||||
// if cfg.RootWorkFlow == "" {
|
||||
// cfg.RootWorkFlow = cfg.Root + "/workflows"
|
||||
// }
|
||||
|
||||
// if cfg.RootData == "" {
|
||||
// cfg.RootData = cfg.Root + "/data"
|
||||
// }
|
||||
|
||||
// if cfg.RootDB == "" {
|
||||
// cfg.RootDB = cfg.Root + "/db"
|
||||
// }
|
||||
|
||||
// if cfg.RootUI == "" {
|
||||
// cfg.RootUI = cfg.Root + "/ui"
|
||||
// }
|
||||
|
||||
// if len(cfg.Database.Primary) > 0 {
|
||||
// if strings.HasPrefix(cfg.Database.Primary[0], "file:.") {
|
||||
// cfg.Database.Primary[0] = strings.ReplaceAll(cfg.Database.Primary[0], "file:.", pwd)
|
||||
// } else if strings.HasPrefix(cfg.Database.Primary[0], "file:/") {
|
||||
// cfg.Database.Primary[0] = strings.ReplaceAll(cfg.Database.Primary[0], "file:.", cfg.RootDB)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 过滤数据
|
||||
// cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "fs://")
|
||||
// cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "file://")
|
||||
// cfg.RootData = strings.TrimPrefix(cfg.RootData, "fs://")
|
||||
// cfg.RootData = strings.TrimPrefix(cfg.RootData, "file://")
|
||||
// cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "fs://")
|
||||
// cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "file://")
|
||||
// cfg.RootLib = strings.TrimPrefix(cfg.RootLib, "fs://")
|
||||
// cfg.RootLib = strings.TrimPrefix(cfg.RootLib, "file://")
|
||||
|
||||
// }
|
||||
|
||||
// // SetEnvFile 指定ENV文件
|
||||
// func SetEnvFile(filename string) {
|
||||
// Conf = NewConfig(filename)
|
||||
// }
|
||||
|
||||
// // SetAppPath 设定应用目录
|
||||
// func SetAppPath(root string, envfile ...string) {
|
||||
|
||||
// fullpath, err := filepath.Abs(root)
|
||||
// if err != nil {
|
||||
// log.Panic("设定应用目录%s出错 %s\n", root, err.Error())
|
||||
// }
|
||||
|
||||
// // 创建应用目录
|
||||
// pathinfo, err := os.Stat(fullpath)
|
||||
// if os.IsNotExist(err) {
|
||||
// err := os.MkdirAll(fullpath, os.ModePerm)
|
||||
// if err != nil {
|
||||
// log.Panic("创建目录失败(%s) %s", root, err)
|
||||
// }
|
||||
// }
|
||||
// pathinfo, err = os.Stat(fullpath)
|
||||
// if !pathinfo.IsDir() {
|
||||
// log.Panic("检查应用目录失败(%s) ", err)
|
||||
// }
|
||||
|
||||
// if !pathinfo.IsDir() {
|
||||
// log.Panic("应用目录不是文件夹(%s) ", root)
|
||||
// }
|
||||
|
||||
// // Set ENV
|
||||
// if len(envfile) > 0 {
|
||||
// Conf = NewConfig(envfile[0])
|
||||
// }
|
||||
|
||||
// // 从加载配置文件
|
||||
// Conf.Root = fullpath
|
||||
// Conf.RootAPI = filepath.Join(fullpath, "/apis")
|
||||
// Conf.RootFLow = filepath.Join(fullpath, "/flows")
|
||||
// Conf.RootModel = filepath.Join(fullpath, "/models")
|
||||
// Conf.RootPlugin = filepath.Join(fullpath, "/plugins")
|
||||
// Conf.RootTable = filepath.Join(fullpath, "/tables")
|
||||
// Conf.RootChart = filepath.Join(fullpath, "/charts")
|
||||
// Conf.RootPage = filepath.Join(fullpath, "/pages")
|
||||
// Conf.RootWorkFlow = filepath.Join(fullpath, "/workflows")
|
||||
// Conf.RootData = filepath.Join(fullpath, "/data")
|
||||
// Conf.RootUI = filepath.Join(fullpath, "/ui")
|
||||
// Conf.RootDB = filepath.Join(fullpath, "/db")
|
||||
// Conf.RootLib = filepath.Join(fullpath, "/libs")
|
||||
// }
|
||||
|
||||
// // IsDebug 是否为调试模式
|
||||
// func IsDebug() bool {
|
||||
// return Conf.Mode == "debug"
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ type Config struct {
|
|||
Log string `json:"log,omitempty" env:"YAO_LOG"` // 服务日志地址
|
||||
LogMode string `json:"log_mode,omitempty" env:"YAO_LOG_MODE" envDefault:"TEXT"` // 服务日志模式 JSON|TEXT
|
||||
// Session string `json:"session,omitempty" env:"YAO_SESSION" envDefault:"memory"` // 用户会话模式 memory|redis|database
|
||||
JWTSecret string `json:"jwt_secret,omitempty" env:"YAO_JWT_SECRET"` // JWT 密钥
|
||||
DB DBConfig `json:"db,omitempty"` // 数据库配置
|
||||
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"`
|
||||
}
|
||||
|
||||
|
|
@ -23,3 +24,15 @@ type DBConfig struct {
|
|||
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 {
|
||||
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
|
||||
Port string `json:"port,omitempty" env:"YAO_SESSION_PORT" envDefault:"6379"` // The redis port
|
||||
Password string `json:"password,omitempty" env:"YAO_SESSION_PASSWORD"` // The redis password
|
||||
Username string `json:"username,omitempty" env:"YAO_SESSION_USERNAME"` // The redis username
|
||||
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
|
||||
}
|
||||
|
|
|
|||
61
crypto/crypto.go
Normal file
61
crypto/crypto.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/md4"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypto.RegisterHash(crypto.MD4, md4.New)
|
||||
}
|
||||
|
||||
var hashTypes = map[string]crypto.Hash{
|
||||
"MD4": crypto.MD4,
|
||||
"MD5": crypto.MD5,
|
||||
"SHA1": crypto.SHA1,
|
||||
"SHA224": crypto.SHA224,
|
||||
"SHA256": crypto.SHA256,
|
||||
"SHA384": crypto.SHA384,
|
||||
"SHA512": crypto.SHA512,
|
||||
"MD5SHA1": crypto.MD5SHA1,
|
||||
"RIPEMD160": crypto.RIPEMD160,
|
||||
"SHA3_224": crypto.SHA3_224,
|
||||
"SHA3_256": crypto.SHA3_256,
|
||||
"SHA3_384": crypto.SHA3_384,
|
||||
"SHA3_512": crypto.SHA3_512,
|
||||
"SHA512_224": crypto.SHA512_224,
|
||||
"SHA512_256": crypto.SHA512_256,
|
||||
"BLAKE2s_256": crypto.BLAKE2s_256,
|
||||
"BLAKE2b_256": crypto.BLAKE2b_256,
|
||||
"BLAKE2b_384": crypto.BLAKE2b_384,
|
||||
"BLAKE2b_512": crypto.BLAKE2b_512,
|
||||
}
|
||||
|
||||
// Hash string
|
||||
func Hash(hash crypto.Hash, value string) (string, error) {
|
||||
h := hash.New()
|
||||
_, err := h.Write([]byte(value))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
||||
}
|
||||
|
||||
// Hmac the Keyed-Hash Message Authentication Code (HMAC)
|
||||
func Hmac(hash crypto.Hash, value string, key string, encoding ...string) (string, error) {
|
||||
mac := hmac.New(hash.New, []byte(key))
|
||||
_, err := mac.Write([]byte(value))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(encoding) > 0 && encoding[0] == "base64" {
|
||||
return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%x", mac.Sum(nil)), nil
|
||||
}
|
||||
68
crypto/crypto_test.go
Normal file
68
crypto/crypto_test.go
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
)
|
||||
|
||||
func TestMD4(t *testing.T) {
|
||||
// Hash
|
||||
args := []interface{}{"MD4", "123456"}
|
||||
res := gou.NewProcess("yao.crypto.hash", args...).Run()
|
||||
assert.Equal(t, "585028aa0f794af812ee3be8804eb14a", res)
|
||||
|
||||
// HMac
|
||||
args = append(args, "123456")
|
||||
res = gou.NewProcess("yao.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()
|
||||
assert.Equal(t, "e10adc3949ba59abbe56e057f20f883e", res)
|
||||
|
||||
// HMac
|
||||
args = append(args, "123456")
|
||||
res = gou.NewProcess("yao.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()
|
||||
assert.Equal(t, "7c4a8d09ca3762af61e59520943dc26494f8941b", res)
|
||||
|
||||
// HMac
|
||||
args = append(args, "123456")
|
||||
res = gou.NewProcess("yao.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()
|
||||
assert.Equal(t, "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92", res)
|
||||
|
||||
// HMac
|
||||
args = append(args, "123456")
|
||||
res = gou.NewProcess("yao.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()
|
||||
assert.Equal(t, "7c4a8d09ca3762af61e59520943dc26494f8941b", res)
|
||||
|
||||
// HMac
|
||||
args = append(args, "123456", "base64")
|
||||
res = gou.NewProcess("yao.crypto.hmac", args...).Run()
|
||||
assert.Equal(t, "dLVbarK45DisgQQ142njBHs5UdA=", res)
|
||||
}
|
||||
59
crypto/process.go
Normal file
59
crypto/process.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gou.RegisterProcessHandler("yao.crypto.hash", ProcessHash)
|
||||
gou.RegisterProcessHandler("yao.crypto.hmac", ProcessHmac)
|
||||
}
|
||||
|
||||
// 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{} {
|
||||
process.ValidateArgNums(2)
|
||||
typ := process.ArgsString(0)
|
||||
value := process.ArgsString(1)
|
||||
|
||||
h, has := hashTypes[typ]
|
||||
if !has {
|
||||
exception.New("%s does not support", 400, typ).Throw()
|
||||
}
|
||||
|
||||
res, err := Hash(h, value)
|
||||
if err != nil {
|
||||
exception.New("%s error: %s value: %s", 400, typ, err, value).Throw()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ProcessHmac yao.crypto.hmac Crypto the Keyed-Hash Message Authentication Code (HMAC) 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
|
||||
// Args[2] string: key
|
||||
// Args[3] string: base64
|
||||
func ProcessHmac(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(3)
|
||||
typ := process.ArgsString(0)
|
||||
value := process.ArgsString(1)
|
||||
key := process.ArgsString(2)
|
||||
|
||||
h, has := hashTypes[typ]
|
||||
if !has {
|
||||
exception.New("%s does not support", 400, typ).Throw()
|
||||
}
|
||||
|
||||
encoding := ""
|
||||
if process.NumOfArgs() > 3 {
|
||||
encoding = process.ArgsString(3)
|
||||
}
|
||||
|
||||
res, err := Hmac(h, value, key, encoding)
|
||||
if err != nil {
|
||||
exception.New("%s error: %s value: %s", 400, typ, err, value).Throw()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -208,7 +208,7 @@ func uiIndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "ui/index.html", size: 22, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "ui/index.html", size: 22, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -228,7 +228,7 @@ func yaoDs_store() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -248,7 +248,7 @@ func yaoApisReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/README.md", size: 13, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -268,7 +268,7 @@ func yaoApisChartHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/chart.http.json", size: 624, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -288,7 +288,7 @@ func yaoApisImportHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/import.http.json", size: 1676, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -308,12 +308,12 @@ func yaoApisPageHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/page.http.json", size: 609, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _yaoApisStorageHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x91\xcf\x4e\xfa\x40\x10\xc7\xef\x7d\x8a\xc9\xe6\x77\x2c\x6d\x7f\x1e\xb9\x79\x50\x62\x62\x22\x41\x38\x11\x0e\x63\x3b\x94\x62\xd9\x5d\xf7\x8f\x4a\x08\x17\x1f\x40\xaf\xde\x8d\x89\x17\x1f\x0b\x9f\xc3\xec\x52\x8a\x18\x4c\x08\xc1\x78\xd9\xa6\xf3\x99\xfd\xee\x7c\x76\x67\x01\x00\xe3\x38\x21\xd6\x04\xb6\x78\x7f\x5e\x3c\xbc\x7d\x3c\xbe\x2e\x9e\x5e\x58\xe8\xc8\x2d\x29\x5d\x08\xee\xe0\xff\x28\x89\x92\x65\x35\x23\x9d\xaa\x42\x9a\x8a\x7c\xdd\x76\xdc\x3e\x5b\xf6\xe4\x4a\x58\xe9\xe8\x7d\x81\x3c\x8f\xb5\x11\x0a\x73\xaa\x98\x45\x95\x39\x76\x45\xa8\x48\x35\xc6\x77\x66\x09\x24\x9a\x91\x66\x4d\xe8\x07\x00\x00\x33\xbf\x56\x65\xd7\x1e\x5b\x59\x0a\xcc\x7c\xaf\x07\x13\x32\x23\xe1\x93\xda\x17\x97\xdd\x75\xbd\x3e\xa0\xb1\xae\x49\x25\x52\xd2\xba\x1e\x29\x1a\xea\xa8\xf7\x2d\xaf\x70\x3e\x7d\xf6\x6f\x58\x94\x14\xb9\x85\x0d\x6a\x26\xac\x61\xcd\x7a\x26\x00\xa6\x0d\x1a\xeb\xf2\x8e\x92\x24\x5c\x97\xcd\x54\xfa\xcb\x44\x29\xcb\x22\x45\x77\x49\xf1\x58\x0b\xce\xaa\x96\xb9\xff\xce\xc3\x1f\x14\x15\x61\xe6\x4f\xde\x22\xd9\x3a\xd9\xc3\xb1\x43\x98\x9d\x6e\x04\xae\x2c\x6f\x2c\xa9\x69\xe4\x1f\x3f\x84\xd5\x2f\xf1\x54\x64\x7f\xe0\x6d\x55\x79\x30\xe5\x16\x99\x5e\xe7\x7c\x47\x61\x3f\xf7\xfe\xba\xc5\x04\x73\x8a\x25\xcf\x77\xf4\x34\xe2\x9a\xf8\x21\x4d\xbb\x9b\x81\x5b\x5c\x7f\xed\x2d\x03\x80\x41\x30\x0f\x3e\x03\x00\x00\xff\xff\xb6\x5b\xa0\x8d\x44\x04\x00\x00")
|
||||
var _yaoApisStorageHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x92\xbd\x4e\xfb\x30\x10\xc0\xf7\x3c\x85\x65\xfd\xc7\x34\xc9\x9f\xb1\x1b\x03\x54\x48\x48\x54\xa5\x9d\xaa\x0e\x47\x72\x4d\x5d\x52\xdb\xf8\x03\xa8\xaa\x2e\x3c\x00\xac\xec\x08\x89\x85\xc7\x2a\xcf\x81\xec\xa4\xe9\x07\x85\x22\x24\xc4\xe2\xc8\xf7\xbb\xf3\xf9\xe7\xcb\x2c\x20\x84\x72\x98\x20\x6d\x12\xba\x78\x7d\x5c\xdc\xbd\xbc\xdd\x3f\x2f\x1e\x9e\x68\xe8\xc8\x35\x2a\xcd\x04\x77\xf0\x7f\x94\x44\x49\x19\xcd\x50\xa7\x8a\x49\x53\x91\xf5\xb2\xc3\xf6\x49\x99\x93\x2b\x61\xa5\xa3\xb7\x0c\x78\x1e\x6b\x23\x14\xe4\x58\x31\x0b\x2a\x73\xec\x02\x41\xa1\x6a\x8c\x6f\x4c\x09\x24\x98\x91\xa6\x4d\xd2\x0f\x08\x21\x64\xe6\xd7\x2a\xec\xd2\x63\x2b\x0b\x01\x99\xcf\xf5\x60\x82\x66\x24\xfc\x49\xed\xb3\xf3\xee\x2a\x2e\x95\x48\x51\xeb\xba\x7d\x34\xd4\x51\x6f\xab\x96\xb9\xbb\xf7\xe9\xbf\x21\x2b\x30\x72\x0b\x1d\xd4\x4c\x58\x43\x9b\x75\x7f\x42\xa8\x36\x60\xac\x3b\xef\x20\x49\xc2\x55\xd8\x4c\xa5\x7f\x38\x90\xb2\x60\x29\xb8\x07\x89\xc7\x5a\x70\x5a\xa5\xcc\xfd\x77\x1e\x7e\xa2\xa3\x10\x32\xdf\x79\x87\x50\xeb\x68\x8f\x4f\x07\x21\x3b\xde\x28\x5e\x1a\x5d\x59\x54\xd3\xc8\x0f\x35\x24\xcb\x2d\xf2\x54\x64\x7f\xe0\x68\x55\xb1\x57\xaf\xfe\x1f\x1a\x5f\x2b\xb7\xd0\xf4\x3a\xa7\xdf\x14\xf6\xf7\x5e\xdb\x8a\x4b\xe4\x1f\xf5\xb7\xb4\x57\xba\x6c\x02\x39\xc6\x92\xe7\x74\x9f\x61\x79\xf2\x4f\x46\xd8\x42\xd3\xdd\x2c\xde\x61\xf4\x6b\x13\x0b\x08\x19\x04\xf3\xe0\x3d\x00\x00\xff\xff\xeb\x8c\x85\x1f\x02\x04\x00\x00")
|
||||
|
||||
func yaoApisStorageHttpJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
|
|
@ -328,12 +328,12 @@ func yaoApisStorageHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/storage.http.json", size: 1092, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/storage.http.json", size: 1026, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _yaoApisTableHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x56\xcd\x6e\xd3\x40\x10\xbe\xe7\x29\x56\xab\x1e\x53\x3b\x70\xf4\x0d\x89\x1f\xe5\x44\x51\x41\x1c\xaa\x1e\xa6\xde\x21\x99\xd6\x5e\x6f\xf7\x27\xc1\x54\x79\x04\xe0\xc4\x1d\x84\x90\x38\x21\x1e\x80\xd7\x21\xe2\x31\xd0\xae\x4d\x52\x87\xa4\x0d\xb1\x90\xd3\x4b\xa2\x9d\x99\x6f\x34\xdf\xf7\x79\xec\xbd\xea\x31\xc6\x25\xe4\xc8\x13\xc6\xe7\x1f\xbe\xcf\xdf\x7e\xfb\xf5\xe9\xeb\xfc\xe3\x8f\xf9\xbb\x2f\x3f\xdf\x7f\xe6\x7d\x9f\x9f\xa0\x36\x54\x48\x5f\x72\x2f\x1a\x44\x83\x2a\x2a\xd0\xa4\x9a\x94\xad\x33\x7f\x83\x1f\x1c\x0d\xab\xca\x91\x2e\x9c\xf2\x35\xaf\x09\xe4\x28\xb6\x70\x96\x61\x9d\x71\xa0\x85\xcf\x9c\x21\x68\xd4\x87\xe7\x53\x5b\x25\x14\xd8\xb1\xe1\x09\x3b\xe9\x31\xc6\xd8\x55\xf8\xad\xc3\xbe\x3c\x4e\xfc\xcc\xb1\x41\xd0\xe9\x38\x20\x42\x3a\x47\x3b\x2e\x42\xbf\x27\x8f\x9e\x2f\xc3\x4a\x17\x29\x1a\xb3\x98\x20\x0a\x13\x44\xc7\x2b\x68\xf2\x3c\x4e\xf8\x81\x02\x0d\x79\x14\x44\xe9\x33\x9e\x5c\x3a\xd4\xe5\x61\x08\xfa\xf3\x41\x38\x47\x0a\x46\xb8\x72\x34\xf4\x06\xf9\xe9\xa2\x5d\xe1\x2c\x4f\x16\xa3\x33\xc6\x8d\x05\xeb\xfc\x14\xf7\x07\x83\xfe\x32\x6c\x4b\x15\xd4\x07\xa5\x32\x4a\xc1\xeb\x19\x9f\x9b\x42\xf2\xba\x64\x16\xfe\x67\xfd\x1b\x95\x78\x45\x52\xc4\x09\x89\x5d\xb5\x78\x4c\x52\xdc\xa6\x44\x7d\x24\xd1\x15\x49\x83\x19\xa6\x76\x77\xbb\x9b\xe8\x8a\xe4\x72\xc4\x06\xdb\x6b\xe1\xca\xe0\x0b\x2c\xa7\x85\x16\x6b\x32\x1b\x00\x13\xc8\xdc\xba\x78\x46\x39\xd9\x3f\xb4\xbb\x12\x12\x26\xb8\x4e\xc6\xa3\xa7\xc7\x5b\xe8\xd8\x00\x6f\x58\x1a\x05\x65\x56\x40\x67\x4f\xca\xa5\xa3\xf4\xa2\x15\xcb\x67\xbe\xc3\x5d\xa0\x2a\x30\x43\x8b\x9b\x76\x7f\x2b\xae\x0f\x43\x8b\xbd\x5f\x7f\x92\x06\xf5\xda\xf5\xdf\x8a\xe5\x70\x05\xbe\x91\x65\xb0\x33\x4a\x8b\xcc\xe5\xd2\x34\x62\x61\xa7\x4d\xc7\x4e\x4f\xc7\xa8\x77\x7f\xae\x2b\xaf\x5f\x36\x7b\x6c\xf1\xe5\xeb\x96\x33\xc9\x96\x84\x87\xf2\x56\xe3\xab\xd7\x33\x09\x73\xfd\xb3\xae\x29\x07\x5d\x76\xc5\xde\x29\x01\xad\x1d\x7f\x11\x9a\xfc\xbb\xe3\x7b\xf0\x6e\xab\xf9\xb7\x70\xbf\x22\xdf\xd2\xfd\x3d\x50\xc2\xa0\xb5\x24\x47\xbb\xdf\x7d\x56\xe0\x37\xaa\x50\xdf\xb3\xfe\x1b\xd5\x1e\x63\xa7\xbd\x59\xef\x77\x00\x00\x00\xff\xff\x8a\x3e\xea\x17\x7c\x0c\x00\x00")
|
||||
var _yaoApisTableHttpJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x56\xcb\x6e\xd3\x40\x14\xdd\xfb\x2b\x46\xa3\x2e\x53\x3b\xb0\xf4\x0e\x89\x87\xb2\xa2\xa8\x20\x16\x55\x17\x17\xcf\x25\x19\x6a\xcf\x4c\xe7\x91\x62\xaa\x7c\x02\xb0\x62\x0f\x42\x48\xac\x10\x1f\xc0\xef\x10\xf1\x19\x68\xc6\x26\xa9\x4d\xd2\x9a\x58\xc8\xe9\x26\xd1\x3d\xf7\xe1\x7b\xce\xb1\xc7\xbe\x8c\x08\xa1\x02\x0a\xa4\x29\xa1\xcb\x0f\xdf\x97\x6f\xbf\xfd\xfa\xf4\x75\xf9\xf1\xc7\xf2\xdd\x97\x9f\xef\x3f\xd3\x91\xcf\xcf\x51\x1b\x2e\x85\x2f\xb9\x13\x8f\xe3\x71\x85\x32\x34\x99\xe6\xca\xd6\x99\xbf\x9b\xef\x1d\x4d\xaa\xca\xa9\x96\x4e\xf9\x9a\xd7\x1c\xc4\x34\xb1\xf0\x22\xc7\x3a\xe3\x40\x33\x9f\x09\xd8\x61\x15\x86\x8c\x02\x3b\x33\x34\x25\x27\x11\x21\x84\x5c\x86\xdf\x1a\xf6\xf5\x49\xea\x97\x4e\x0c\x82\xce\x66\xa1\x23\xa4\x0b\xb4\x33\x19\x06\x3e\x7a\xf0\x74\x0d\x2b\x2d\x33\x34\x66\xb5\x42\x1c\x2e\x17\x1f\xb7\xba\xb9\x27\x72\x42\x0f\x14\x68\x28\xe2\xa0\xca\x88\xd0\xf4\xdc\xa1\x2e\x0f\x03\xe8\xe3\x83\x10\xc7\x0a\xa6\xd8\x0a\x0d\x7f\x83\xf4\x74\x35\x4e\x3a\x4b\xd3\xd5\xea\x84\x50\x63\xc1\x3a\xbf\xc5\xdd\xf1\x78\xb4\x86\x6d\xa9\x82\xfc\xa0\x54\xce\x33\xf0\x82\x26\xaf\x8c\x14\xb4\x2e\x59\x84\xff\xc5\xe8\x5a\x25\x5e\x72\xc1\x92\x94\xb3\x5d\xb5\x78\xc8\x05\xbb\x49\x89\x3a\xf4\x17\x69\xc9\x32\x10\x69\x83\x39\x66\x76\x77\xfb\x9b\xdd\x15\xe9\xf5\x8a\x0d\xf6\x57\xe0\xca\xf0\x33\x2c\x2f\xa4\x66\x1b\x32\x5b\x1a\xe6\x90\xbb\x4d\x78\xce\x0b\x6e\xff\xd0\x1e\x4a\x48\x98\xe3\x26\x19\x8f\x1e\x1f\x77\xd0\xb1\xd1\xbc\xe5\x21\x52\x50\xe6\x12\xd8\x50\x77\xca\xb9\xe3\xd9\x59\x2f\x96\x4f\xfc\x84\xdb\x40\x95\x61\x8e\x16\xb7\x9d\x05\x9d\xb8\xde\x0f\x23\xba\x1f\x07\x03\x31\xe5\xc2\xa0\xde\xf8\xf8\x77\x62\x39\x69\xb5\x6f\x65\x19\xec\x8c\x33\x99\xbb\x42\x98\x06\x16\x9e\x69\x33\xb0\xd3\x17\x33\xd4\xbb\xdf\xd7\x95\xd7\xcf\x9b\x33\x3a\xbc\x09\x87\xe5\xcc\x45\x4f\xc2\x13\x71\xa3\xf1\xd5\xf1\xcc\x99\xb9\xfa\x9a\xd7\xbc\x00\x5d\x0e\xc5\xde\x29\x06\xbd\x1d\x7f\x16\x86\xfc\xbb\xe3\x7b\x70\xb6\xd5\xfc\x7b\xb8\x5f\x91\xef\xe9\xfe\x1e\x28\x61\xd0\x5a\x2e\xa6\xbb\x7f\xfb\xb4\xda\xaf\x55\xa1\xfe\xce\xfa\x6f\x54\x23\x42\x4e\xa3\x45\xf4\x3b\x00\x00\xff\xff\x8d\x38\xb9\xa1\x8d\x0c\x00\x00")
|
||||
|
||||
func yaoApisTableHttpJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
|
|
@ -348,7 +348,7 @@ func yaoApisTableHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/table.http.json", size: 3196, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/table.http.json", size: 3213, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -368,7 +368,7 @@ func yaoApisUserHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/user.http.json", size: 1453, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -388,7 +388,7 @@ func yaoApisXiangHttpJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/apis/xiang.http.json", size: 1239, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -408,7 +408,7 @@ func yaoDataDs_store() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -428,7 +428,7 @@ func yaoDataAppJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/app.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/app.json", size: 277, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -448,7 +448,7 @@ func yaoDataIconsDs_store() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/.DS_Store", size: 6148, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -468,7 +468,7 @@ func yaoDataIcons404Png() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/404.png", size: 9342, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -488,7 +488,7 @@ func yaoDataIconsIconIcns() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.icns", size: 67465, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -508,7 +508,7 @@ func yaoDataIconsIconIco() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.ico", size: 54993, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -528,7 +528,7 @@ func yaoDataIconsIconPng() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/icons/icon.png", size: 34558, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -548,7 +548,7 @@ func yaoDataIndexHtml() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/data/index.html", size: 282, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -568,7 +568,7 @@ func yaoFlowsReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/README.md", size: 12, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -588,7 +588,7 @@ func yaoFlowsAdminGuardFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/admin/guard.flow.json", size: 559, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/admin/guard.flow.json", size: 559, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -608,7 +608,7 @@ func yaoFlowsMenuFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/menu.flow.json", size: 1045, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -628,7 +628,7 @@ func yaoFlowsUserFindFlowJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/flows/user/find.flow.json", size: 328, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/flows/user/find.flow.json", size: 328, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -648,7 +648,7 @@ func yaoLangsEnUsJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/langs/en-US.json", size: 66, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -668,7 +668,7 @@ func yaoModelsReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -688,7 +688,7 @@ func yaoModelsMenuModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/menu.mod.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/menu.mod.json", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -708,7 +708,7 @@ func yaoModelsUserModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/user.mod.json", size: 8826, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -728,7 +728,7 @@ func yaoModelsWorkflowModJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/models/workflow.mod.json", size: 3333, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -748,7 +748,7 @@ func yaoTablesReadmeMd() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/tables/README.md", size: 15, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -768,7 +768,7 @@ func yaoTablesMenuTabJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/tables/menu.tab.json", size: 10471, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/tables/menu.tab.json", size: 10471, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
@ -788,7 +788,7 @@ func yaoTablesUserTabJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "yao/tables/user.tab.json", size: 2357, mode: os.FileMode(420), modTime: time.Unix(1645092418, 0)}
|
||||
info := bindataFileInfo{name: "yao/tables/user.tab.json", size: 2357, mode: os.FileMode(420), modTime: time.Unix(1655826122, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ ARG ARCH
|
|||
RUN groupadd -r yao && useradd -r -g yao yao && \
|
||||
apt-get update && \
|
||||
apt-get install -y curl sudo procps net-tools
|
||||
RUN curl -fsSL "https://release-sv.yaoapps.com/archives/yao-${VERSION}-linux-${ARCH}" > /usr/local/bin/yao && \
|
||||
RUN curl -fsSL "https://release-sv-1252011659.cos.na-siliconvalley.myqcloud.com/archives/yao-${VERSION}-linux-${ARCH}" > /usr/local/bin/yao && \
|
||||
chmod +x /usr/local/bin/yao && \
|
||||
mkdir -p /data/app
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ FROM alpine:latest
|
|||
ARG VERSION
|
||||
ARG ARCH
|
||||
RUN apk --no-cache add curl
|
||||
RUN curl -fsSL "https://release-sv.yaoapps.com/archives/yao-${VERSION}-linux-${ARCH}" > /usr/local/bin/yao && \
|
||||
RUN curl -fsSL "https://release-sv-1252011659.cos.na-siliconvalley.myqcloud.com/archives/yao-${VERSION}-linux-${ARCH}" > /usr/local/bin/yao && \
|
||||
chmod +x /usr/local/bin/yao
|
||||
RUN mkdir -p /data/app && \
|
||||
cd /data/app && /usr/local/bin/yao init && \
|
||||
|
|
|
|||
BIN
docs/architecture.png
Normal file
BIN
docs/architecture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 288 KiB |
BIN
docs/wechat.jpg
Normal file
BIN
docs/wechat.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
|
|
@ -4,12 +4,14 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"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/flow"
|
||||
|
|
@ -18,11 +20,15 @@ import (
|
|||
"github.com/yaoapp/yao/page"
|
||||
"github.com/yaoapp/yao/plugin"
|
||||
"github.com/yaoapp/yao/query"
|
||||
"github.com/yaoapp/yao/schedule"
|
||||
"github.com/yaoapp/yao/script"
|
||||
"github.com/yaoapp/yao/server"
|
||||
"github.com/yaoapp/yao/share"
|
||||
"github.com/yaoapp/yao/socket"
|
||||
"github.com/yaoapp/yao/store"
|
||||
"github.com/yaoapp/yao/table"
|
||||
"github.com/yaoapp/yao/workflow"
|
||||
"github.com/yaoapp/yao/task"
|
||||
"github.com/yaoapp/yao/websocket"
|
||||
"github.com/yaoapp/yao/widget"
|
||||
)
|
||||
|
||||
// Load 根据配置加载 API, FLow, Model, Plugin
|
||||
|
|
@ -37,9 +43,15 @@ func Load(cfg config.Config) (err error) {
|
|||
gou.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)
|
||||
}
|
||||
|
||||
// 第二步: 建立数据库 & 会话连接
|
||||
share.DBConnect(cfg.DB) // 创建数据库连接
|
||||
share.SessionConnect(cfg.Session) // 创建会话服务器链接
|
||||
share.DBConnect(cfg.DB) // 创建数据库连接
|
||||
// share.SessionConnect(cfg.Session) // 创建会话服务器链接
|
||||
|
||||
// 加载应用引擎
|
||||
if os.Getenv("YAO_DEV") != "" {
|
||||
|
|
@ -54,51 +66,94 @@ func Load(cfg config.Config) (err error) {
|
|||
// 第四步: 加载共享库 & JS 处理器
|
||||
err = share.Load(cfg) // 加载共享库 lib
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
printErr(cfg.Mode, "Lib", err)
|
||||
}
|
||||
|
||||
err = script.Load(cfg) // 加载JS处理器 script
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
printErr(cfg.Mode, "Script", err)
|
||||
}
|
||||
|
||||
// 第五步: 加载数据模型等
|
||||
err = model.Load(cfg) // 加载数据模型 model
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
printErr(cfg.Mode, "Model", err)
|
||||
}
|
||||
|
||||
err = flow.Load(cfg) // 加载业务逻辑 Flow
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
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 {
|
||||
log.Warn(err.Error())
|
||||
printErr(cfg.Mode, "Plugin", err)
|
||||
}
|
||||
|
||||
err = table.Load(cfg) // 加载数据表格 table
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
printErr(cfg.Mode, "Table", err)
|
||||
}
|
||||
|
||||
err = chart.Load(cfg) // 加载分析图表 chart
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
printErr(cfg.Mode, "Chart", err)
|
||||
}
|
||||
|
||||
err = page.Load(cfg) // 加载页面 page 忽略错误
|
||||
if err != nil {
|
||||
printErr(cfg.Mode, "Page", err)
|
||||
}
|
||||
|
||||
page.Load(cfg) // 加载页面 page 忽略错误
|
||||
importer.Load(cfg) // 加载数据导入 imports
|
||||
workflow.Load(cfg) // 加载工作流 workflow
|
||||
|
||||
// workflow.Load(cfg) // 加载工作流 workflow
|
||||
|
||||
err = api.Load(cfg) // 加载业务接口 API
|
||||
if err != nil {
|
||||
log.Warn(err.Error())
|
||||
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)
|
||||
}
|
||||
|
||||
server.Load(cfg) // 加载服务
|
||||
return nil
|
||||
}
|
||||
|
||||
func printErr(mode, widget string, err error) {
|
||||
message := fmt.Sprintf("[%s] %s", widget, err.Error())
|
||||
if !strings.Contains(message, "does not exists") && mode == "development" {
|
||||
color.Red(message)
|
||||
}
|
||||
}
|
||||
|
||||
// Reload 根据配置重新加载 API, FLow, Model, Plugin
|
||||
func Reload(cfg config.Config) {
|
||||
gou.APIs = map[string]*gou.API{}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
)
|
||||
|
||||
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"))
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ func check(t *testing.T) {
|
|||
for key := range gou.Flows {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 22, len(keys))
|
||||
assert.Equal(t, 26, len(keys))
|
||||
}
|
||||
|
|
|
|||
97
go.mod
97
go.mod
|
|
@ -1,50 +1,99 @@
|
|||
module github.com/yaoapp/yao
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/buraksezer/consistent v0.9.0 // indirect
|
||||
github.com/buraksezer/olric v0.4.2
|
||||
github.com/caarlos0/env/v6 v6.9.1
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-msgpack v1.1.5 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/memberlist v0.3.0 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
|
||||
github.com/jmoiron/sqlx v1.3.4 // indirect
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/lib/pq v1.10.4 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/mojocn/base64Captcha v1.3.5
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/spf13/afero v1.6.0
|
||||
github.com/spf13/cobra v1.2.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
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/kun v0.9.0
|
||||
github.com/yaoapp/xun v0.9.0
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.4 // indirect
|
||||
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/google/uuid v1.3.0
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.4 // indirect
|
||||
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/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/lib/pq v1.10.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
||||
github.com/miekg/dns v1.1.48 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
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/oklog/run v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.3 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.1 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/satori/go.uuid v1.2.0 // 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
|
||||
github.com/tidwall/grect v0.1.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tidwall/rtred v0.1.2 // indirect
|
||||
github.com/tidwall/tinyqueue v0.1.1 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
|
||||
google.golang.org/grpc v1.42.0 // indirect
|
||||
golang.org/x/tools v0.1.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // 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.0 // indirect
|
||||
rogchap.com/v8go v0.7.0 // indirect
|
||||
)
|
||||
|
||||
// go env -w GOPRIVATE=github.com/yaoapp/*
|
||||
|
|
|
|||
288
go.sum
288
go.sum
|
|
@ -39,15 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
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/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
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/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible h1:D3gwOr9qUUmyyBRDbpnATqu+EkqqmigFd3Od6xO1QUU=
|
||||
|
|
@ -55,52 +48,38 @@ github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible/go.mod h1:T/Aws4fEfogEE
|
|||
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=
|
||||
github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo=
|
||||
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/buraksezer/connpool v0.4.0 h1:fNLvWu0FOtJxL7Sqetm6+040mhZWVs8c6vrke14SEKw=
|
||||
github.com/buraksezer/connpool v0.4.0/go.mod h1:qPiG7gKXo+EjrwG/yqn2StZM4ek6gcYnnGgFIVKN6b0=
|
||||
github.com/buraksezer/consistent v0.0.0-20191006190839-693edf70fd72/go.mod h1:OEE5igu/CDjGegM1Jn6ZMo7R6LlV/JChAkjfQQIRLpg=
|
||||
github.com/buraksezer/consistent v0.9.0 h1:Zfs6bX62wbP3QlbPGKUhqDw7SmNkOzY5bHZIYXYpR5g=
|
||||
github.com/buraksezer/consistent v0.9.0/go.mod h1:6BrVajWq7wbKZlTOUPs/XVfR8c0maujuPowduSpZqmw=
|
||||
github.com/buraksezer/olric v0.4.2 h1:1W5UCYFYrkeD6OHGyTi6R9YTLJ3vXcVkgas4ZbFQMfw=
|
||||
github.com/buraksezer/olric v0.4.2/go.mod h1:xNt+/QiiVuqioJzgTMuiV2LynTNu87L1Tp5289XuU78=
|
||||
github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k=
|
||||
github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
|
@ -109,16 +88,17 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
|
|
@ -129,27 +109,21 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
|
|||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
|
||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
|
||||
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
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=
|
||||
|
|
@ -188,8 +162,6 @@ 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/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/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
|
|
@ -200,8 +172,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
|
|
@ -219,42 +192,30 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
|
|||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
|
||||
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
|
||||
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
|
||||
github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.4.2/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||
github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
|
||||
github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ=
|
||||
github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
|
|
@ -262,35 +223,26 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/memberlist v0.1.5/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA=
|
||||
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I=
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 h1:nqAlWFEdqI0ClbTDrhDvE/8LeQ4pftrqKUX9w5k0j3s=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
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/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
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.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
|
||||
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.6/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=
|
||||
|
|
@ -299,57 +251,42 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
|||
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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
||||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/miekg/dns v1.1.48 h1:Ucfr7IIVyMBz4lRE8qmGUuZ4Wt3/ZGu9hmcMT3Uu4tQ=
|
||||
github.com/miekg/dns v1.1.48/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
|
|
@ -366,64 +303,49 @@ 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
|
||||
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI=
|
||||
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/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f h1:a7clxaGmmqtdNTXyvrp/lVO/Gnkzlhc/+dLs5v965GM=
|
||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f/go.mod h1:/mK7FZ3mFYEn9zvNPhpngTyatyehSwte5bJZ4ehL5Xw=
|
||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
||||
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=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
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=
|
||||
|
|
@ -434,24 +356,40 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/takama/daemon v1.0.0 h1:XS3VLnFKmqw2Z7fQ/dHRarrVjdir9G3z7BEP8osjizQ=
|
||||
github.com/takama/daemon v1.0.0/go.mod h1:gKlhcjbqtBODg5v9H1nj5dU1a2j2GemtuWSNLD5rxOE=
|
||||
github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI=
|
||||
github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8=
|
||||
github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM=
|
||||
github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
|
||||
github.com/tidwall/buntdb v1.2.9 h1:XVz684P7X6HCTrdr385yDZWB1zt/n20ZNG3M1iGyFm4=
|
||||
github.com/tidwall/buntdb v1.2.9/go.mod h1:IwyGSvvDg6hnKSIhtdZ0AqhCZGH8ukdtCAzaP8fI1X4=
|
||||
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
|
||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=
|
||||
github.com/tidwall/grect v0.1.4/go.mod h1:9FBsaYRaR0Tcy4UwefBX/UDcDcDy9V5jUcxHzv2jd5Q=
|
||||
github.com/tidwall/lotsa v1.0.2 h1:dNVBH5MErdaQ/xd9s769R31/n2dXavsQ0Yf4TMEHHw8=
|
||||
github.com/tidwall/lotsa v1.0.2/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UMuqgR8=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/rtred v0.1.2 h1:exmoQtOLvDoO8ud++6LwVsAMTu0KPzLTUrMln8u1yu8=
|
||||
github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ=
|
||||
github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaymYE=
|
||||
github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
|
||||
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
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=
|
||||
|
|
@ -461,7 +399,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
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.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
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=
|
||||
|
|
@ -476,16 +413,13 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
|
|||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201001193750-eb9a90e9f9cb/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab h1:lnZ4LoV0UMdibeCUfIB2a4uFwRu491WX/VB2reB8xNc=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
|
|
@ -527,12 +461,12 @@ 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/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -541,11 +475,9 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
@ -556,11 +488,11 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
|
|
@ -569,12 +501,10 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
|
||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
|
@ -595,32 +525,29 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200930132711-30421366ff76/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/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -636,15 +563,16 @@ 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=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -654,13 +582,10 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/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-20211004093028-2c5d950f24ef/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc=
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
@ -684,7 +609,6 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
|
|
@ -692,7 +616,6 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
@ -701,7 +624,6 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
|
|
@ -727,11 +649,13 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
|
|||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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.5/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/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=
|
||||
|
|
@ -766,9 +690,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
|||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
|
|
@ -810,10 +732,8 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
|
|||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/genproto v0.0.0-20220526192754-51939a95c655 h1:56rmjc5LUAanErbiNrY+s/Nd47wDQEJkpqS7i43M1I0=
|
||||
google.golang.org/genproto v0.0.0-20220526192754-51939a95c655/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
|
@ -834,9 +754,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
|
|||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
|
||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
|
@ -849,32 +768,31 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
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/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
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=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
|||
22
helper/hex.process.go
Normal file
22
helper/hex.process.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
)
|
||||
|
||||
// ProcessHexToString xiang.helper.HexToString
|
||||
func ProcessHexToString(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(1)
|
||||
|
||||
switch process.Args[0].(type) {
|
||||
case string:
|
||||
return hex.EncodeToString([]byte(process.Args[0].(string)))
|
||||
case []byte:
|
||||
return hex.EncodeToString(process.Args[0].([]byte))
|
||||
}
|
||||
log.With(log.F{"input": process.Args[0]}).Error("HexToString: type does not support")
|
||||
return nil
|
||||
}
|
||||
61
helper/hex_test.go
Normal file
61
helper/hex_test.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/yao/flow"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
func TestProcessHexToString(t *testing.T) {
|
||||
res, err := gou.NewProcess("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()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "0001", res)
|
||||
|
||||
res, err = gou.NewProcess("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) {
|
||||
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))
|
||||
|
||||
}
|
||||
|
|
@ -27,6 +27,8 @@ func init() {
|
|||
gou.RegisterProcessHandler("xiang.helper.MapDel", ProcessMapDel)
|
||||
gou.RegisterProcessHandler("xiang.helper.MapMultiDel", ProcessMapMultiDel)
|
||||
|
||||
gou.RegisterProcessHandler("xiang.helper.HexToString", ProcessHexToString)
|
||||
|
||||
gou.RegisterProcessHandler("xiang.helper.StrConcat", ProcessStrConcat)
|
||||
|
||||
gou.RegisterProcessHandler("xiang.helper.Captcha", ProcessCaptcha)
|
||||
|
|
@ -64,6 +66,7 @@ func init() {
|
|||
|
||||
gou.RegisterProcessHandler("xiang.flow.Sleep", ProcessSleep)
|
||||
gou.AliasProcess("xiang.flow.Sleep", "xiang.sys.Sleep")
|
||||
|
||||
}
|
||||
|
||||
// ProcessPrint xiang.helper.Print 打印语句
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/any"
|
||||
|
|
@ -382,19 +383,22 @@ func (imp *Importer) SaveAsTemplate(src from.Source) {
|
|||
}
|
||||
|
||||
// Run 运行导入
|
||||
func (imp *Importer) Run(src from.Source, mapping *Mapping) map[string]int {
|
||||
func (imp *Importer) Run(src from.Source, mapping *Mapping) interface{} {
|
||||
if mapping == nil {
|
||||
mapping = imp.AutoMapping(src)
|
||||
}
|
||||
|
||||
id := uuid.NewString()
|
||||
page := 0
|
||||
total := 0
|
||||
failed := 0
|
||||
ignore := 0
|
||||
imp.Chunk(src, mapping, func(line int, data [][]interface{}) {
|
||||
page++
|
||||
length := len(data)
|
||||
total = total + length
|
||||
columns, data := imp.DataClean(data, mapping.Columns)
|
||||
process, err := gou.ProcessOf(imp.Process, columns, data)
|
||||
process, err := gou.ProcessOf(imp.Process, columns, data, id, page)
|
||||
if err != nil {
|
||||
failed = failed + length
|
||||
log.With(log.F{"line": line}).Error("导入失败: %s", err.Error())
|
||||
|
|
@ -424,12 +428,24 @@ func (imp *Importer) Run(src from.Source, mapping *Mapping) map[string]int {
|
|||
|
||||
log.With(log.F{"line": line, "response": response, "length": length}).Error("导入处理器未返回失败结果")
|
||||
})
|
||||
return map[string]int{
|
||||
|
||||
output := map[string]int{
|
||||
"total": total,
|
||||
"success": total - failed - ignore,
|
||||
"failure": failed,
|
||||
"ignore": ignore,
|
||||
}
|
||||
|
||||
if imp.Output != "" {
|
||||
res, err := gou.NewProcess(imp.Output, output).Exec()
|
||||
if err != nil {
|
||||
log.With(log.F{"output": imp.Output}).Error(err.Error())
|
||||
return output
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
// Start 运行导入(异步)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ func TestRunSimple(t *testing.T) {
|
|||
|
||||
imp := Select("order")
|
||||
mapping := imp.AutoMapping(file)
|
||||
res := imp.Run(file, mapping)
|
||||
res := imp.Run(file, mapping).(map[string]int)
|
||||
assert.Equal(t, 1, res["ignore"])
|
||||
assert.Equal(t, 1, res["failure"])
|
||||
assert.Equal(t, 2, res["success"])
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ const PreviewNever = "never"
|
|||
type Importer struct {
|
||||
Title string `json:"title,omitempty"` // 导入名称
|
||||
Process string `json:"process"` // 处理器名称
|
||||
Output string `json:"output,omitempty"` // The process import output
|
||||
Columns []Column `json:"columns"` // 字段列表
|
||||
Option Option `json:"option,omitempty"` // 导入配置项
|
||||
Rules map[string]string `json:"rules,omitempty"` // 许可导入规则
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ func (xlsx *Xlsx) Chunk(size int, axises []string, cb func(line int, data [][]in
|
|||
row, end := xlsx.readLine(line, axises)
|
||||
if end {
|
||||
cb(line, data)
|
||||
break
|
||||
return
|
||||
}
|
||||
|
||||
data = append(data, row)
|
||||
|
|
|
|||
38
lang/lang.go
Normal file
38
lang/lang.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package lang
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou/lang"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
lang.RegisterWidget("tables", "table")
|
||||
lang.RegisterWidget("charts", "chart")
|
||||
lang.RegisterWidget("kanban", "page")
|
||||
lang.RegisterWidget("screen", "page")
|
||||
lang.RegisterWidget("pages", "page")
|
||||
}
|
||||
|
||||
// Load language packs
|
||||
func Load(cfg config.Config) error {
|
||||
root := filepath.Join(cfg.Root, "langs")
|
||||
err := lang.Load(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := os.Getenv("YAO_LANG")
|
||||
if name != "" {
|
||||
if _, has := lang.Dicts[name]; !has {
|
||||
log.Error("The language pack %s does not found", name)
|
||||
return nil
|
||||
}
|
||||
lang.Pick(name).AsDefault()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
16
lang/lang_test.go
Normal file
16
lang/lang_test.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package lang
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou/lang"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
share.DBConnect(config.Conf.DB)
|
||||
Load(config.Conf)
|
||||
assert.Len(t, lang.Dicts, 2)
|
||||
}
|
||||
4
main.go
4
main.go
|
|
@ -2,8 +2,12 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/yaoapp/yao/cmd"
|
||||
|
||||
_ "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/xfs"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ func TestCommandStop(t *testing.T) {
|
|||
times++
|
||||
res, err := request()
|
||||
if err != nil {
|
||||
fmt.Println("REQUEST ERROR:", err)
|
||||
continue
|
||||
}
|
||||
assert.Equal(t, 1, any.Of(res.Get("id")).CInt())
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/lang"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/share"
|
||||
|
|
@ -31,7 +32,14 @@ func LoadFrom(dir string, prefix string) error {
|
|||
_, err := gou.LoadModelReturn(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Apply the language pack
|
||||
if lang.Default != nil {
|
||||
lang.Default.Apply(gou.Models[name])
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -1,17 +1,23 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/lang"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
|
||||
os.Setenv("YAO_LANG", "zh-hk")
|
||||
lang.Load(config.Conf)
|
||||
share.DBConnect(config.Conf.DB)
|
||||
|
||||
gou.Models = make(map[string]*gou.Model)
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
|
|
@ -23,5 +29,9 @@ func check(t *testing.T) {
|
|||
for key := range gou.Models {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 10, len(keys))
|
||||
assert.Equal(t, 11, len(keys))
|
||||
|
||||
demo := gou.Select("demo")
|
||||
assert.Equal(t, demo.MetaData.Name, "演示")
|
||||
assert.Equal(t, demo.Columns["action"].Label, "動作")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func ProcessIP(process *gou.Process) interface{} {
|
|||
|
||||
// FreePort xiang.network.FreePort 获取可用端口
|
||||
func FreePort() int {
|
||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
addr, err := net.ResolveTCPAddr("tcp", ":0")
|
||||
if err != nil {
|
||||
exception.New("获取可用端口失败 %s", 500, err.Error()).Throw()
|
||||
return 0
|
||||
|
|
@ -52,6 +52,7 @@ func FreePort() int {
|
|||
exception.New("获取可用端口失败 %s", 500, err.Error()).Throw()
|
||||
return 0
|
||||
}
|
||||
|
||||
defer l.Close()
|
||||
return l.Addr().(*net.TCPAddr).Port
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/gou/dns"
|
||||
)
|
||||
|
||||
// Response 请求响应结果
|
||||
|
|
@ -94,16 +95,21 @@ func RequestSend(method string, url string, params map[string]interface{}, data
|
|||
}
|
||||
}
|
||||
|
||||
// Https
|
||||
var client *http.Client = &http.Client{}
|
||||
// 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}
|
||||
|
||||
// SkipVerify false
|
||||
// Https SkipVerify false
|
||||
if strings.HasPrefix(url, "https://") {
|
||||
tr := &http.Transport{
|
||||
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 {
|
||||
|
|
|
|||
125
page/lang.go
Normal file
125
page/lang.go
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
package page
|
||||
|
||||
// Lang for applying a language pack
|
||||
func (page *Page) Lang(trans func(widget string, inst string, value *string) bool) {
|
||||
inst := page.Flow.Name
|
||||
widget := "page"
|
||||
|
||||
trans(widget, inst, &page.Name)
|
||||
trans(widget, inst, &page.Label)
|
||||
trans(widget, inst, &page.Description)
|
||||
trans(widget, inst, &page.Page.Primary)
|
||||
transMap(widget, inst, page.Page.Layout, trans)
|
||||
page.Output = transAny(widget, inst, page.Output, trans)
|
||||
|
||||
// Filters
|
||||
for name, filter := range page.Filters {
|
||||
new := name
|
||||
trans(widget, inst, &new)
|
||||
trans(widget, inst, &filter.Label)
|
||||
delete(page.Filters, name)
|
||||
|
||||
// Props
|
||||
transMap(widget, inst, filter.Input.Props, trans)
|
||||
page.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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
13
page/page.go
13
page/page.go
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
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"
|
||||
|
|
@ -24,15 +25,15 @@ func Load(cfg config.Config) error {
|
|||
|
||||
var errs error = nil
|
||||
if err := LoadFrom(path.Join(cfg.Root, "/kanban"), ""); err != nil {
|
||||
log.Trace("load kanban error: %s ", err.Error())
|
||||
// log.Trace("load kanban error: %s ", err.Error())
|
||||
errs = err
|
||||
}
|
||||
if err := LoadFrom(path.Join(cfg.Root, "/screen"), ""); err != nil {
|
||||
log.Trace("load screen error: %s", err.Error())
|
||||
// log.Trace("load screen error: %s", err.Error())
|
||||
errs = err
|
||||
}
|
||||
if err := LoadFrom(path.Join(cfg.Root, "/pages"), ""); err != nil {
|
||||
log.Trace("load screen error: %s", err.Error())
|
||||
// log.Trace("load screen error: %s", err.Error())
|
||||
errs = err
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +94,12 @@ func LoadPage(source []byte, name string) (*Page, error) {
|
|||
page.Prepare()
|
||||
page.SetupAPIs()
|
||||
Pages[name] = page
|
||||
|
||||
// Apply a language pack
|
||||
if lang.Default != nil {
|
||||
lang.Default.Apply(Pages[name])
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
package page
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/lang"
|
||||
"github.com/yaoapp/yao/model"
|
||||
"github.com/yaoapp/yao/query"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
|
||||
os.Setenv("YAO_LANG", "zh-hk")
|
||||
lang.Load(config.Conf)
|
||||
|
||||
share.DBConnect(config.Conf.DB)
|
||||
model.Load(config.Conf)
|
||||
query.Load(config.Conf)
|
||||
|
|
@ -25,5 +31,15 @@ func check(t *testing.T) {
|
|||
for key := range Pages {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 1, len(keys))
|
||||
assert.Equal(t, 2, len(keys))
|
||||
|
||||
lang := Pages["lang"]
|
||||
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"])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ func ProcessData(process *gou.Process) interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
// with Session
|
||||
page.Flow.WithGlobal(process.Global)
|
||||
page.Flow.WithSID(process.Sid)
|
||||
|
||||
return page.GetData(params)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/kun/utils"
|
||||
"github.com/yaoapp/yao/config"
|
||||
_ "github.com/yaoapp/yao/helper"
|
||||
"github.com/yaoapp/yao/model"
|
||||
|
|
@ -68,8 +67,6 @@ func TestProcessData(t *testing.T) {
|
|||
}
|
||||
process := gou.NewProcess("xiang.page.Data", args...)
|
||||
response := ProcessData(process)
|
||||
utils.Dump(response)
|
||||
|
||||
assert.NotNil(t, response)
|
||||
|
||||
res := any.Of(response).Map().Dot()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package query
|
|||
|
||||
import (
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/query"
|
||||
dsl "github.com/yaoapp/gou/query/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/xun/capsule"
|
||||
|
|
@ -10,21 +11,21 @@ import (
|
|||
|
||||
// Load 加载查询引擎
|
||||
func Load(cfg config.Config) {
|
||||
XiangQuery()
|
||||
DefaultQuery()
|
||||
}
|
||||
|
||||
// XiangQuery 注册应用引擎象 xiang
|
||||
func XiangQuery() {
|
||||
gou.RegisterEngine("xiang", &dsl.Query{
|
||||
// DefaultQuery register the default engine
|
||||
func DefaultQuery() {
|
||||
query.Register("default", &dsl.Query{
|
||||
Query: capsule.Query(),
|
||||
GetTableName: func(s string) string {
|
||||
if mod, has := gou.Models[s]; has {
|
||||
return mod.MetaData.Table.Name
|
||||
}
|
||||
// exception.New("%s 数据模型尚未加载", 404).Throw()
|
||||
log.Error("%s model does not load", s)
|
||||
return s
|
||||
},
|
||||
AESKey: config.Conf.DB.AESKey,
|
||||
})
|
||||
query.Alias("default", "xiang")
|
||||
}
|
||||
|
|
|
|||
36
schedule/schedule.go
Normal file
36
schedule/schedule.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package schedule
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
// Load load schedule
|
||||
func Load(cfg config.Config) error {
|
||||
var root = filepath.Join(cfg.Root, "schedules")
|
||||
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 := gou.LoadSchedule(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
21
schedule/schedule_test.go
Normal file
21
schedule/schedule_test.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package schedule
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/task"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
task.Load(config.Conf)
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
check(t)
|
||||
}
|
||||
|
||||
func check(t *testing.T) {
|
||||
assert.Equal(t, 2, len(gou.Schedules))
|
||||
}
|
||||
|
|
@ -5,12 +5,14 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/yao/helper"
|
||||
"github.com/yaoapp/yao/table"
|
||||
)
|
||||
|
||||
// Guards 服务中间件
|
||||
var Guards = map[string]gin.HandlerFunc{
|
||||
"bearer-jwt": bearerJWT, // JWT 鉴权
|
||||
"cross-domain": crossDomain, // 跨域许可
|
||||
"table-guard": table.Guard, // Table Guard
|
||||
}
|
||||
|
||||
// JWT 鉴权
|
||||
|
|
@ -25,7 +27,6 @@ func bearerJWT(c *gin.Context) {
|
|||
|
||||
claims := helper.JwtValidate(tokenString)
|
||||
c.Set("__sid", claims.SID)
|
||||
c.Next()
|
||||
}
|
||||
|
||||
// crossDomain 跨域访问
|
||||
|
|
@ -39,6 +40,4 @@ func crossDomain(c *gin.Context) {
|
|||
c.AbortWithStatus(204)
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ func BinStatic(c *gin.Context) {
|
|||
|
||||
length := len(c.Request.URL.Path)
|
||||
|
||||
if length >= 5 && c.Request.URL.Path[0:5] == "/api/" { // API接口
|
||||
if (length >= 5 && c.Request.URL.Path[0:5] == "/api/") ||
|
||||
(length >= 11 && c.Request.URL.Path[0:11] == "/websocket/") { // API & websocket
|
||||
c.Next()
|
||||
return
|
||||
} else if length >= 7 && c.Request.URL.Path[0:7] == "/xiang/" { // 数据管理后台
|
||||
|
|
|
|||
|
|
@ -1,32 +1,39 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
var shutdown = make(chan bool)
|
||||
var shutdownComplete = make(chan bool)
|
||||
var shutdown = make(chan bool, 1)
|
||||
var shutdownComplete = make(chan bool, 1)
|
||||
|
||||
// Start 启动服务
|
||||
func Start() {
|
||||
func Start() error {
|
||||
|
||||
if config.Conf.Session.Hosting && config.Conf.Session.IsCLI == false {
|
||||
share.SessionServerStart()
|
||||
err := share.SessionStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gou.SetHTTPGuards(Guards)
|
||||
gou.ServeHTTP(
|
||||
gou.Server{
|
||||
Host: config.Conf.Host,
|
||||
Port: config.Conf.Port,
|
||||
Root: "/api",
|
||||
Host: config.Conf.Host,
|
||||
Port: config.Conf.Port,
|
||||
Root: "/api",
|
||||
Allows: config.Conf.AllowFrom,
|
||||
},
|
||||
&shutdown, func(s gou.Server) {
|
||||
shutdown, func(s gou.Server) {
|
||||
shutdownComplete <- true
|
||||
},
|
||||
Middlewares...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartWithouttSession 启动服务
|
||||
|
|
@ -35,11 +42,12 @@ func StartWithouttSession() {
|
|||
gou.SetHTTPGuards(Guards)
|
||||
gou.ServeHTTP(
|
||||
gou.Server{
|
||||
Host: config.Conf.Host,
|
||||
Port: config.Conf.Port,
|
||||
Root: "/api",
|
||||
Host: config.Conf.Host,
|
||||
Port: config.Conf.Port,
|
||||
Root: "/api",
|
||||
Allows: config.Conf.AllowFrom,
|
||||
},
|
||||
&shutdown, func(s gou.Server) {
|
||||
shutdown, func(s gou.Server) {
|
||||
shutdownComplete <- true
|
||||
},
|
||||
Middlewares...)
|
||||
|
|
@ -48,16 +56,31 @@ func StartWithouttSession() {
|
|||
// StopWithouttSession 关闭服务
|
||||
func StopWithouttSession(onComplete func()) {
|
||||
shutdown <- true
|
||||
<-shutdownComplete
|
||||
gou.KillPlugins()
|
||||
onComplete()
|
||||
select {
|
||||
case <-shutdownComplete:
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
// Stop 关闭服务
|
||||
func Stop(onComplete func()) {
|
||||
shutdown <- true
|
||||
<-shutdownComplete
|
||||
share.SessionServerStop()
|
||||
gou.KillPlugins()
|
||||
onComplete()
|
||||
select {
|
||||
case <-shutdownComplete:
|
||||
share.SessionStop()
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
// StopWithContext stop with timeout
|
||||
func StopWithContext(ctx context.Context, onComplete func()) {
|
||||
shutdown <- true
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Error("[STOP] canceled (%v)", ctx.Err())
|
||||
onComplete()
|
||||
case <-shutdownComplete:
|
||||
share.SessionStop()
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
617
service/watch.go
617
service/watch.go
|
|
@ -1,459 +1,268 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/yao/chart"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/engine"
|
||||
"github.com/yaoapp/yao/page"
|
||||
"github.com/yaoapp/yao/share"
|
||||
"github.com/yaoapp/yao/table"
|
||||
"github.com/yaoapp/yao/workflow"
|
||||
)
|
||||
|
||||
// Watch 监听应用目录文件变更
|
||||
func Watch(cfg config.Config) {
|
||||
if os.Getenv("YAO_DEV") != "" {
|
||||
WatchEngine(filepath.Join(os.Getenv("YAO_DEV"), "/yao"))
|
||||
}
|
||||
WatchModel(filepath.Join(cfg.Root, "models"), "")
|
||||
WatchAPI(filepath.Join(cfg.Root, "apis"), "")
|
||||
WatchFlow(filepath.Join(cfg.Root, "flows"), "")
|
||||
WatchPlugin(filepath.Join(cfg.Root, "plugins"))
|
||||
WatchTable(filepath.Join(cfg.Root, "tables"), "")
|
||||
WatchChart(filepath.Join(cfg.Root, "charts"), "")
|
||||
WatchPage(filepath.Join(cfg.Root, "pages"), "")
|
||||
WatchWorkFlow(filepath.Join(cfg.Root, "workflows"), "")
|
||||
|
||||
// 看板大屏
|
||||
WatchPage(filepath.Join(cfg.Root, "kanban"), "")
|
||||
WatchPage(filepath.Join(cfg.Root, "screen"), "")
|
||||
|
||||
// 监听脚本 & libs更新
|
||||
WatchGlobal(filepath.Join(cfg.Root, "libs"))
|
||||
WatchGlobal(filepath.Join(cfg.Root, "scripts"))
|
||||
var watchShutdown = make(chan bool, 1) // shutdown signal
|
||||
var watchReady = make(chan bool, 1) // ready signal
|
||||
var excludes = map[string]bool{"ui": true, "db": true, "data": true}
|
||||
var handlers = map[string]func(root string, file string, event string, cfg config.Config){
|
||||
"models": watchModel,
|
||||
}
|
||||
|
||||
// WatchEngine 监听监听引擎内建数据变更
|
||||
func WatchEngine(root string) {
|
||||
root = share.DirAbs(root)
|
||||
WatchModel(filepath.Join(root, "models"), "xiang.")
|
||||
WatchAPI(filepath.Join(root, "apis"), "xiang.")
|
||||
WatchFlow(filepath.Join(root, "flows"), "xiang.")
|
||||
WatchTable(filepath.Join(root, "tables"), "xiang.")
|
||||
// Watch the application code change for hot update
|
||||
func Watch(cfg config.Config) (err error) {
|
||||
go func() { err = watchStart(cfg) }()
|
||||
select {
|
||||
case <-watchReady:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WatchGlobal 监听通用程序更新
|
||||
func WatchGlobal(root string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
// StopWatch stop watching the code change
|
||||
func StopWatch() {
|
||||
watchShutdown <- true
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
|
||||
func watchStart(cfg config.Config) error {
|
||||
|
||||
root := cfg.Root
|
||||
|
||||
// recive interrupt signal
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
||||
shutdown := make(chan bool, 1)
|
||||
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
if !strings.HasSuffix(filename, ".json") && !strings.HasSuffix(filename, ".js") {
|
||||
return
|
||||
defer watcher.Close()
|
||||
|
||||
root, err = filepath.Abs(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dirs, err := ioutil.ReadDir(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add path
|
||||
for _, dir := range dirs {
|
||||
if !dir.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// 重启服务器
|
||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||
err := engine.Load(config.Conf)
|
||||
name := dir.Name()
|
||||
if _, has := excludes[name]; has {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, ".") {
|
||||
continue
|
||||
}
|
||||
|
||||
filename := filepath.Join(root, name)
|
||||
err := watcher.Add(filename)
|
||||
if err != nil {
|
||||
log.Error("[Watch] %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(color.GreenString("[Watch] Watching %s", name))
|
||||
log.Info("[Watch] Watching: %s", filename)
|
||||
|
||||
// sub dir
|
||||
depth := 0
|
||||
err = filepath.WalkDir(filename, func(path string, d fs.DirEntry, err error) error {
|
||||
depth = depth + 1
|
||||
if depth == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Info("[Watch] Watching: %s", path)
|
||||
err = watcher.Add(path)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
log.Error("[Watch] %s", err.Error())
|
||||
}
|
||||
StopWithouttSession(func() {
|
||||
fmt.Println(color.GreenString("Service Restarted"))
|
||||
go StartWithouttSession()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// WatchModel 监听业务接口更新
|
||||
func WatchModel(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
if err != nil {
|
||||
log.Error("[Watch] %s", err.Error())
|
||||
}
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
|
||||
if !strings.HasSuffix(filename, ".json") {
|
||||
return
|
||||
}
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := gou.LoadModelReturn(string(content), name) // Reload
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
// event handler
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-shutdown:
|
||||
log.Info("[Watch] The event handler exit")
|
||||
return
|
||||
}
|
||||
fmt.Println(color.GreenString("Model %s Reloaded", name))
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := gou.Models[name]; has {
|
||||
delete(gou.Models, name)
|
||||
fmt.Println(color.RedString("Model %s Removed", name))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WatchAPI 监听业务接口更新
|
||||
func WatchAPI(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
relpath := strings.TrimPrefix(event.Name, root)
|
||||
if strings.HasPrefix(relpath, string(os.PathSeparator)) {
|
||||
relpath = strings.TrimPrefix(relpath, string(os.PathSeparator))
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(filename, ".json") {
|
||||
return
|
||||
}
|
||||
pi := strings.Split(relpath, string(os.PathSeparator))
|
||||
widget := pi[0]
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := gou.LoadAPIReturn(string(content), name) // Reload
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
fmt.Println(color.GreenString("API %s Reloaded", name))
|
||||
watchHanler := watchReload
|
||||
if handler, has := handlers[widget]; has {
|
||||
watchHanler = handler
|
||||
}
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := gou.APIs[name]; has {
|
||||
delete(gou.APIs, name)
|
||||
fmt.Println(color.RedString("API %s Removed", name))
|
||||
}
|
||||
}
|
||||
|
||||
// 重启服务器
|
||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||
StopWithouttSession(func() {
|
||||
fmt.Println(color.GreenString("Service Restarted"))
|
||||
go StartWithouttSession()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WatchFlow 监听业务逻辑变更
|
||||
func WatchFlow(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
if !strings.HasSuffix(filename, ".json") && !strings.HasSuffix(filename, ".js") {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filename, ".js") {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
name = strings.ReplaceAll(name, ".", "/")
|
||||
filename = filepath.Join(root, name+".flow.json")
|
||||
}
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
flow, err := gou.LoadFlowReturn(string(content), name) // Reload
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if flow != nil { // Reload Script
|
||||
dir := filepath.Dir(filename)
|
||||
share.Walk(dir, ".js", func(root, filename string) {
|
||||
script := share.ScriptName(filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := flow.LoadScriptReturn(string(content), script)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
if _, has := excludes[widget]; !has {
|
||||
base := filepath.Base(event.Name)
|
||||
isdir := true
|
||||
if strings.HasSuffix(base, ".yao") || strings.HasSuffix(base, ".json") || strings.HasSuffix(base, ".js") {
|
||||
isdir = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fmt.Println(color.GreenString("Flow %s Reloaded", name))
|
||||
events := strings.Split(event.Op.String(), "|")
|
||||
for _, eventType := range events {
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := gou.Flows[name]; has {
|
||||
delete(gou.Flows, name)
|
||||
fmt.Println(color.RedString("Flow %s Removed", name))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// ADD / REMOVE Watching dir
|
||||
if isdir {
|
||||
switch eventType {
|
||||
case "CREATE":
|
||||
log.Info("[Watch] Watching: %s", event.Name)
|
||||
watcher.Add(event.Name)
|
||||
break
|
||||
case "REMOVE":
|
||||
log.Info("[Watch] Unwatching: %s", event.Name)
|
||||
watcher.Remove(event.Name)
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// WatchPlugin 监听业务插件变更
|
||||
func WatchPlugin(root string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
|
||||
if !strings.HasSuffix(filename, ".so") {
|
||||
return
|
||||
}
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := share.SpecName(root, filename)
|
||||
_, err := gou.LoadPluginReturn(filename, name) // Reload
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
fmt.Println(color.GreenString("Plugin %s Reloaded", name))
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := share.SpecName(root, filename)
|
||||
if _, has := gou.Plugins[name]; has {
|
||||
delete(gou.Plugins, name)
|
||||
fmt.Println(color.RedString("Plugin %s Removed", name))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WatchTable 监听数据表格更新
|
||||
func WatchTable(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
|
||||
if !strings.HasSuffix(filename, ".json") {
|
||||
return
|
||||
}
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := table.LoadTable(string(content), name) // Reload Table
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
api, has := gou.APIs["xiang.table"]
|
||||
if has {
|
||||
_, err := gou.LoadAPIReturn(api.Source, api.Name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Println(color.GreenString("Table %s Reloaded", name))
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := table.Tables[name]; has {
|
||||
delete(table.Tables, name)
|
||||
fmt.Println(color.RedString("Table %s Removed", name))
|
||||
}
|
||||
}
|
||||
|
||||
// 重启服务器
|
||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||
StopWithouttSession(func() {
|
||||
fmt.Println(color.GreenString("Service Restarted"))
|
||||
go StartWithouttSession()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WatchChart 监听分析图表更新
|
||||
func WatchChart(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
if !strings.HasSuffix(filename, ".json") && !strings.HasSuffix(filename, ".js") {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filename, ".js") {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
name = strings.ReplaceAll(name, ".", "/")
|
||||
filename = filepath.Join(root, name+".chart.json")
|
||||
}
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
chart, err := chart.LoadChart(content, name) // Relaod
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if chart != nil { // Reload Script
|
||||
dir := filepath.Dir(filename)
|
||||
share.Walk(dir, ".js", func(root, filename string) {
|
||||
script := share.ScriptName(filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := chart.LoadScriptReturn(string(content), script)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
log.Info("[Watch] %s %s", eventType, event.Name)
|
||||
watchHanler(root, event.Name, eventType, cfg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
api, has := gou.APIs["xiang.chart"]
|
||||
if has {
|
||||
_, err := gou.LoadAPIReturn(api.Source, api.Name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Println(color.GreenString("Chart %s Reloaded", name))
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := chart.Charts[name]; has {
|
||||
delete(chart.Charts, name)
|
||||
fmt.Println(color.RedString("Chart %s Removed", name))
|
||||
fmt.Println(color.RedString("[Watch] %s", err.Error()))
|
||||
log.Error("[Watch] %s", err.Error())
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// 重启服务器
|
||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||
StopWithouttSession(func() {
|
||||
fmt.Println(color.GreenString("Service Restarted"))
|
||||
go StartWithouttSession()
|
||||
})
|
||||
fmt.Println(color.GreenString("[Watch] Started"))
|
||||
watchReady <- true
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-watchShutdown:
|
||||
shutdown <- true
|
||||
log.Info("[Watch] Stopped")
|
||||
fmt.Println(color.YellowString("[Watch] Stopped"))
|
||||
return nil
|
||||
|
||||
case <-interrupt:
|
||||
shutdown <- true
|
||||
log.Info("[Watch] Stopped")
|
||||
fmt.Println(color.YellowString("[Watch] Stopped"))
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WatchPage 监听页面更新
|
||||
func WatchPage(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
if !strings.HasSuffix(filename, ".json") && !strings.HasSuffix(filename, ".js") {
|
||||
func watchModel(root string, file string, event string, cfg config.Config) {
|
||||
name := share.SpecName(root, file)
|
||||
switch event {
|
||||
case "CREATE":
|
||||
content, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
mod, err := gou.LoadModelReturn(string(content), name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filename, ".js") {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
name = strings.ReplaceAll(name, ".", "/")
|
||||
filename = filepath.Join(root, name+".page.json")
|
||||
}
|
||||
mod.Migrate(true)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Created", name))
|
||||
break
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
page, err := page.LoadPage(content, name) // Relaod
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if page != nil { // Reload Script
|
||||
dir := filepath.Dir(filename)
|
||||
share.Walk(dir, ".js", func(root, filename string) {
|
||||
script := share.ScriptName(filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := page.LoadScriptReturn(string(content), script)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
api, has := gou.APIs["xiang.page"]
|
||||
if has {
|
||||
_, err := gou.LoadAPIReturn(api.Source, api.Name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Println(color.GreenString("Page %s Reloaded", name))
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := page.Pages[name]; has {
|
||||
delete(page.Pages, name)
|
||||
fmt.Println(color.RedString("Page %s Removed", name))
|
||||
}
|
||||
}
|
||||
|
||||
// 重启服务器
|
||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||
StopWithouttSession(func() {
|
||||
fmt.Println(color.GreenString("Service Restarted"))
|
||||
go StartWithouttSession()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WatchWorkFlow 监听工作流更新
|
||||
func WatchWorkFlow(root string, prefix string) {
|
||||
if share.DirNotExists(root) {
|
||||
return
|
||||
}
|
||||
root = share.DirAbs(root)
|
||||
go share.Watch(root, func(op string, filename string) {
|
||||
if !strings.HasSuffix(filename, ".json") {
|
||||
case "WRITE":
|
||||
content, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if op == "write" || op == "create" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := workflow.LoadWorkFlow(content, name) // Relaod
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
api, has := gou.APIs["xiang.workflow."+name]
|
||||
if has {
|
||||
_, err := gou.LoadAPIReturn(api.Source, api.Name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("Fatal: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Println(color.GreenString("Workflow %s Reloaded", name))
|
||||
|
||||
} else if op == "remove" || op == "rename" {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
if _, has := workflow.WorkFlows[name]; has {
|
||||
delete(workflow.WorkFlows, name)
|
||||
fmt.Println(color.RedString("Workflow %s Removed", name))
|
||||
}
|
||||
mod, err := gou.LoadModelReturn(string(content), name)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Model: %s %s", name, err.Error()))
|
||||
return
|
||||
}
|
||||
mod.Migrate(false)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Reloaded", name))
|
||||
break
|
||||
|
||||
// 重启服务器
|
||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||
StopWithouttSession(func() {
|
||||
fmt.Println(color.GreenString("Service Restarted"))
|
||||
go StartWithouttSession()
|
||||
})
|
||||
}
|
||||
})
|
||||
case "REMOVE", "RENAME":
|
||||
delete(gou.Models, name)
|
||||
fmt.Println(color.GreenString("[Watch] Model: %s Removed", name))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func watchReload(root string, file string, event string, cfg config.Config) {
|
||||
|
||||
switch event {
|
||||
case "CREATE", "WRITE", "REMOVE":
|
||||
err := engine.Load(config.Conf) // 加载脚本等
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString("[Watch] Reload: %s", err.Error()))
|
||||
}
|
||||
|
||||
// Restart Server
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
StopWithContext(ctx, func() {
|
||||
go Start()
|
||||
fmt.Println(color.GreenString("[Watch] Reload Completed"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
153
service/watch_test.go
Normal file
153
service/watch_test.go
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
|
||||
share.DBConnect(config.Conf.DB)
|
||||
err := Watch(config.Conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer StopWatch()
|
||||
|
||||
createDir(t)
|
||||
renameDir(t)
|
||||
|
||||
createModel(t)
|
||||
changeModel(t)
|
||||
renameModel(t)
|
||||
removeModel(t)
|
||||
|
||||
createModel(t)
|
||||
removeDir(t)
|
||||
}
|
||||
|
||||
func TestWatchReload(t *testing.T) {
|
||||
go Start()
|
||||
defer Stop(func() {})
|
||||
share.DBConnect(config.Conf.DB)
|
||||
watchReload("", "", "", config.Conf)
|
||||
}
|
||||
|
||||
func createDir(t *testing.T) {
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch", "test")
|
||||
fmt.Println("CREATE-DIR", file)
|
||||
err := os.MkdirAll(file, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func renameDir(t *testing.T) {
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch", "test")
|
||||
new := filepath.Join(root, "models", "watch", "test_new")
|
||||
fmt.Println("RENAME-DIR", file)
|
||||
err := os.Rename(file, new)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func removeDir(t *testing.T) {
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch")
|
||||
fmt.Println("REMOVE-DIR", file)
|
||||
err := os.RemoveAll(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func createModel(t *testing.T) {
|
||||
dsl := `
|
||||
{
|
||||
"name": "watch-test",
|
||||
"table": {
|
||||
"name": "watch_test",
|
||||
"comment": "WatchTest",
|
||||
"engine": "InnoDB"
|
||||
},
|
||||
"columns": [
|
||||
{ "name": "id", "type": "ID" },
|
||||
{ "label": "Name", "name": "name", "type": "string", "index": true }
|
||||
],
|
||||
"relations": {},
|
||||
"option": { "timestamps": true, "soft_deletes": true }
|
||||
}
|
||||
`
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch", "test_new", "watch.mod.json")
|
||||
fmt.Println("CREATE", file)
|
||||
err := ioutil.WriteFile(file, []byte(dsl), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func changeModel(t *testing.T) {
|
||||
dsl := `
|
||||
{
|
||||
"name": "watch-test",
|
||||
"table": {
|
||||
"name": "watch_test",
|
||||
"comment": "WatchTest",
|
||||
"engine": "InnoDB"
|
||||
},
|
||||
"columns": [
|
||||
{ "name": "id", "type": "ID" },
|
||||
{ "label": "Name", "name": "name", "type": "string", "index": true },
|
||||
{ "label": "Data", "name": "data", "type": "json", "nullable": true }
|
||||
],
|
||||
"relations": {},
|
||||
"option": { "timestamps": true, "soft_deletes": true }
|
||||
}
|
||||
`
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch", "test_new", "watch.mod.json")
|
||||
fmt.Println("CHANGE", file)
|
||||
err := ioutil.WriteFile(file, []byte(dsl), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func renameModel(t *testing.T) {
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch", "test_new", "watch.mod.json")
|
||||
new := filepath.Join(root, "models", "watch", "test_new", "watch_new.mod.json")
|
||||
fmt.Println("RENAME", new)
|
||||
err := os.Rename(file, new)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func removeModel(t *testing.T) {
|
||||
root := config.Conf.Root
|
||||
file := filepath.Join(root, "models", "watch", "test_new", "watch_new.mod.json")
|
||||
fmt.Println("REMOVE", file)
|
||||
err := os.Remove(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
|
@ -9,8 +9,6 @@ import (
|
|||
)
|
||||
|
||||
func TestGetQueryParam(t *testing.T) {
|
||||
SessionServerStart()
|
||||
defer SessionServerStop()
|
||||
sid := session.ID()
|
||||
s := session.Global().ID(sid).Expire(5000 * time.Microsecond)
|
||||
s.MustSet("id", 10086)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package share
|
||||
|
||||
// VERSION 版本号
|
||||
const VERSION = "0.9.1"
|
||||
const VERSION = "0.10.1"
|
||||
|
||||
// PRVERSION PreRelease Version
|
||||
const PRVERSION = "DEV"
|
||||
|
||||
// BUILDIN 打包应用合成一个制品
|
||||
const BUILDIN = false
|
||||
|
|
|
|||
153
share/session.go
153
share/session.go
|
|
@ -1,116 +1,77 @@
|
|||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
klog "github.com/yaoapp/kun/log"
|
||||
|
||||
"github.com/buraksezer/olric"
|
||||
"github.com/buraksezer/olric/client"
|
||||
config_olric "github.com/buraksezer/olric/config"
|
||||
"github.com/buraksezer/olric/serializer"
|
||||
"github.com/yaoapp/gou/session"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/network"
|
||||
|
||||
"github.com/yaoapp/gou/session"
|
||||
)
|
||||
|
||||
var sessServer *olric.Olric
|
||||
var sessionDB *session.BuntDB
|
||||
|
||||
// SessionPort Session 端口
|
||||
var SessionPort int
|
||||
|
||||
func init() {
|
||||
SessionPort = network.FreePort()
|
||||
klog.Trace("session port: %d", SessionPort)
|
||||
// SessionStart start session
|
||||
func SessionStart() error {
|
||||
if config.Conf.Session.Store == "file" {
|
||||
return SessionFile()
|
||||
} else if config.Conf.Session.Store == "redis" {
|
||||
return SessionRedis()
|
||||
}
|
||||
return fmt.Errorf("Session Store config error %s (file|redis)", config.Conf.Session.Store)
|
||||
}
|
||||
|
||||
// SessionConnect 加载会话信息
|
||||
func SessionConnect(conf config.SessionConfig) {
|
||||
|
||||
var clientConfig = &client.Config{
|
||||
Servers: []string{fmt.Sprintf("%s:%d", "127.0.0.1", SessionPort)},
|
||||
Serializer: serializer.NewMsgpackSerializer(),
|
||||
Client: config_olric.NewClient(),
|
||||
}
|
||||
|
||||
c, err := client.New(clientConfig)
|
||||
if err != nil {
|
||||
exception.New("会话服务器连接失败 %s", 500, err.Error()).Throw()
|
||||
}
|
||||
|
||||
dm := c.NewDMap("local-session")
|
||||
session.MemoryUse(session.ClientDMap{DMap: dm})
|
||||
}
|
||||
|
||||
// SessionServerStop 关闭会话服务器
|
||||
func SessionServerStop() {
|
||||
if sessServer != nil {
|
||||
sessServer.Shutdown(context.Background())
|
||||
// SessionStop stop session
|
||||
func SessionStop() {
|
||||
if sessionDB != nil {
|
||||
sessionDB.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// SessionServerStart 启动会话服务器
|
||||
func SessionServerStart() {
|
||||
|
||||
c := &config_olric.Config{
|
||||
BindAddr: "127.0.0.1",
|
||||
BindPort: SessionPort,
|
||||
ReadRepair: false,
|
||||
ReplicaCount: 1,
|
||||
WriteQuorum: 1,
|
||||
ReadQuorum: 1,
|
||||
MemberCountQuorum: 1,
|
||||
Peers: []string{},
|
||||
DMaps: &config_olric.DMaps{},
|
||||
StorageEngines: config_olric.NewStorageEngine(),
|
||||
Logger: &log.Logger{},
|
||||
// SessionRedis Connect redis server
|
||||
func SessionRedis() error {
|
||||
args := []string{}
|
||||
if config.Conf.Session.Port == "" {
|
||||
config.Conf.Session.Port = "6379"
|
||||
}
|
||||
|
||||
m, err := config_olric.NewMemberlistConfig("local")
|
||||
if config.Conf.Session.DB == "" {
|
||||
config.Conf.Session.DB = "1"
|
||||
}
|
||||
|
||||
args = append(args, config.Conf.Session.Port, config.Conf.Session.DB, config.Conf.Session.Password)
|
||||
rdb, err := session.NewRedis(config.Conf.Session.Host, args...)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unable to create a new memberlist config: %v", err))
|
||||
}
|
||||
// m.BindAddr = config.Conf.Session.Host
|
||||
m.BindPort = SessionPort
|
||||
m.AdvertisePort = SessionPort
|
||||
c.MemberlistConfig = m
|
||||
|
||||
// c.MemberlistConfig.BindAddr = config.Conf.Session.Host
|
||||
// c.MemberlistConfig.BindPort = 3308
|
||||
|
||||
// c := config_olric.New("local")
|
||||
// c.BindAddr = config.Conf.Session.Host
|
||||
// c.BindPort = config.Conf.Session.Port
|
||||
|
||||
c.Logger.SetOutput(io.Discard) // 暂时关闭日志
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
c.Started = func() {
|
||||
defer cancel()
|
||||
klog.Trace("[INFO] Olric is ready to accept connections")
|
||||
return err
|
||||
}
|
||||
|
||||
sessServer, err = olric.New(c)
|
||||
|
||||
if err != nil {
|
||||
klog.Error("Failed to create Olric instance: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
err = sessServer.Start() // Call Start at background. It's a blocker call.
|
||||
if err != nil {
|
||||
klog.Panic("olric.Start returned an error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
dm, err := sessServer.NewDMap("local-session")
|
||||
if err != nil {
|
||||
klog.Panic("olric.NewDMap returned an error: %v", err)
|
||||
}
|
||||
|
||||
session.MemoryUse(session.ServerDMap{DMap: dm})
|
||||
session.Register("redis", rdb)
|
||||
session.Name = "redis"
|
||||
log.Trace("Session Store:REDIS HOST:%s PORT:%s DB:%s", config.Conf.Session.Host, config.Conf.Session.Port, config.Conf.Session.DB)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SessionFile Start session file
|
||||
func SessionFile() error {
|
||||
file := config.Conf.Session.File
|
||||
if file == "" {
|
||||
file = filepath.Join(config.Conf.Root, "data", ".session.db")
|
||||
}
|
||||
|
||||
file, err := filepath.Abs(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
burndb, err := session.NewBuntDB(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session.Register("file", burndb)
|
||||
session.Name = "file"
|
||||
sessionDB = burndb
|
||||
log.Trace("Session Store: File %s", file)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,11 @@ type ColumnImp Column
|
|||
|
||||
// Column 字段呈现方式
|
||||
type Column struct {
|
||||
Label string `json:"label"`
|
||||
View Render `json:"view,omitempty"`
|
||||
Edit Render `json:"edit,omitempty"`
|
||||
Form Render `json:"form,omitempty"`
|
||||
Label string `json:"label"`
|
||||
Export string `json:"export,omitempty"`
|
||||
View Render `json:"view,omitempty"`
|
||||
Edit Render `json:"edit,omitempty"`
|
||||
Form Render `json:"form,omitempty"`
|
||||
Importable
|
||||
}
|
||||
|
||||
|
|
@ -71,8 +72,7 @@ type Page struct {
|
|||
// AppInfo 应用信息
|
||||
type AppInfo struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Lang string `json:"lang,omitempty"`
|
||||
L map[string]string `json:"-"` // 应用的语言包
|
||||
L map[string]string `json:"-"`
|
||||
Short string `json:"short,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
)
|
||||
|
||||
var watchDone = []chan bool{}
|
||||
var watchGroup sync.WaitGroup
|
||||
var watchOp = map[fsnotify.Op]string{
|
||||
fsnotify.Create: "create",
|
||||
fsnotify.Write: "write",
|
||||
|
|
@ -27,10 +28,12 @@ func Watch(root string, cb func(op string, file string)) {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer watcher.Close()
|
||||
defer func() {
|
||||
watcher.Close()
|
||||
watchGroup.Done()
|
||||
}()
|
||||
|
||||
watchDone = append(watchDone, make(chan bool))
|
||||
last := len(watchDone) - 1
|
||||
watchGroup.Add(1)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
|
|
@ -86,20 +89,6 @@ func Watch(root string, cb func(op string, file string)) {
|
|||
return nil
|
||||
})
|
||||
|
||||
select {
|
||||
case v := <-watchDone[last]:
|
||||
fmt.Println(color.GreenString("Stop Watching: %s", root))
|
||||
if v == true {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
watchGroup.Wait()
|
||||
|
||||
// StopWatch 停止监听
|
||||
func StopWatch() {
|
||||
for i := range watchDone {
|
||||
fmt.Println(color.GreenString("Stop: %d", i))
|
||||
watchDone[i] <- true
|
||||
}
|
||||
watchDone = []chan bool{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -16,7 +15,5 @@ func TestWatch(t *testing.T) {
|
|||
go Watch(root, func(op string, file string) {
|
||||
log.Println(op, file)
|
||||
})
|
||||
time.Sleep(time.Second * 2)
|
||||
defer StopWatch()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package server
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -11,9 +11,9 @@ import (
|
|||
)
|
||||
|
||||
// Load 加载API
|
||||
func Load(cfg config.Config) {
|
||||
var root = filepath.Join(cfg.Root, "servers")
|
||||
LoadFrom(root, "")
|
||||
func Load(cfg config.Config) error {
|
||||
var root = filepath.Join(cfg.Root, "sockets")
|
||||
return LoadFrom(root, "")
|
||||
}
|
||||
|
||||
// LoadFrom 从特定目录加载
|
||||
|
|
@ -26,7 +26,7 @@ func LoadFrom(dir string, prefix string) error {
|
|||
err := share.Walk(dir, ".sock.json", func(root, filename string) {
|
||||
name := prefix + share.SpecName(root, filename)
|
||||
content := share.ReadFile(filename)
|
||||
_, err := gou.LoadServer(string(content), name)
|
||||
_, err := gou.LoadSocket(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package server
|
||||
package socket
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
@ -16,8 +16,8 @@ func TestLoad(t *testing.T) {
|
|||
|
||||
func check(t *testing.T) {
|
||||
keys := []string{}
|
||||
for key := range gou.Servers {
|
||||
for key := range gou.Sockets {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 1, len(keys))
|
||||
assert.Equal(t, 2, len(keys))
|
||||
}
|
||||
36
store/store.go
Normal file
36
store/store.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"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, "stores")
|
||||
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 := gou.LoadStore(string(content), name)
|
||||
if err != nil {
|
||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
23
store/store_test.go
Normal file
23
store/store_test.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou/kv"
|
||||
"github.com/yaoapp/yao/config"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
Load(config.Conf)
|
||||
LoadFrom("not a path", "404.")
|
||||
check(t)
|
||||
}
|
||||
|
||||
func check(t *testing.T) {
|
||||
keys := []string{}
|
||||
for key := range kv.Pools {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
assert.Equal(t, 1, len(keys))
|
||||
}
|
||||
42
system/process.go
Normal file
42
system/process.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gou.RegisterProcessHandler("yao.system.Exec", processExec)
|
||||
}
|
||||
|
||||
// processExec execute the system command
|
||||
func processExec(process *gou.Process) interface{} {
|
||||
process.ValidateArgNums(1)
|
||||
cmd := process.ArgsString(0)
|
||||
|
||||
_, err := exec.LookPath(cmd)
|
||||
if err != nil {
|
||||
exception.New("command %s not found: %s", 400, cmd, err.Error()).Throw()
|
||||
return nil
|
||||
}
|
||||
|
||||
args := []string{}
|
||||
for i, arg := range process.Args {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
args = append(args, fmt.Sprintf("%v", arg))
|
||||
}
|
||||
|
||||
res, err := exec.Command(cmd, args...).Output()
|
||||
if err != nil {
|
||||
exception.New("command %s error: %s", 500, cmd, err.Error()).Throw()
|
||||
return nil
|
||||
}
|
||||
|
||||
return strings.TrimRight(string(res), "\n")
|
||||
}
|
||||
16
system/process_test.go
Normal file
16
system/process_test.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
)
|
||||
|
||||
func TestProcessReturn(t *testing.T) {
|
||||
output, err := gou.NewProcess("yao.system.Exec", "echo", "hello").Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, "hello", output)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue