first commit

This commit is contained in:
what-00 2023-04-12 16:56:55 +08:00
commit e82ca51b08
53 changed files with 2762 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work

42
base/data_list.go Normal file
View File

@ -0,0 +1,42 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type DataList struct {
Uuid string `db:"uuid"`
ResourceUuid string `db:"resource_uuid"` // 所属资源UUID
Code string `db:"code"` // 列表标识
Name string `db:"name"` // 列表名称
Title string `db:"title"` // 布局标题
PrimaryKey string `db:"primaryKey"` // 主键标识
Layout string `db:"layout"` // 主键标识
IsOperationColumn bool `db:"isOperationColumn"` // 是否显示操作栏,1是,0否
OperationColumnWidth int `db:"operationColumnWidth"` // 操作列宽度
IsPaginate bool `db:"isPaginate"` // 是否分页
IsTreeData bool `db:"isTreeData"` // 是否使用树形列表
TreeDataConfig res_type.ResFieldByMap `db:"treeDataConfig"` // 树形列表配置
IsExpandedRow string `db:"isExpandedRow"` // 列表明细控件
ExpandedRowConfig res_type.ResFieldByMap `db:"expandedRowConfig"` // 列表明细控件配置
IsTreeSider bool `db:"isTreeSider"` // 是否打开侧边栏侧边栏
TreeSiderConfig res_type.ResFieldByMap `db:"treeSiderConfig"` // 侧边栏设置
IsDynamicRefresh bool `db:"isDynamicRefresh"` // 是否启用动态刷新
PageSize int `db:"pagesize"` // 分页大小
IsAuxiliaryPanel bool `db:"isAuxiliaryPanel"` // 是否使用附属面板
AuxiliaryPanelConfig res_type.ResFieldByMap `db:"auxiliaryPanelConfig"` // 附属面板配置
SortConfig res_type.ResFieldByAnys `db:"sortConfig"` // 排序设置
FieldsSort res_type.ResFieldByAnys `db:"fieldsSort"` // 字段排序
GroupConfig res_type.ResFieldByAnys `db:"groupConfig"` // 分组设置
XlsxFieldsSort res_type.ResFieldByAnys `db:"xlsxFieldsSort"` // 字段排序
XlsxImportFieldsSort res_type.ResFieldByAnys `db:"xlsxImportFieldsSort"` // 字段排序
XlsxImportConfig res_type.ResFieldByMap `db:"xlsxImportConfig"` // 导入设置
TabsSort res_type.ResFieldByAnys `db:"tabsSort"` // 标签排序
OperationsSort res_type.ResFieldByAnys `db:"operationsSort"` // 按钮排序
FsmConfig res_type.ResFieldByAnys `db:"fsmConfig"` // FSM设置
ApprovalConfig res_type.ResFieldByAnys `db:"approvalConfig"` // 审批设置
UniqueImportFields res_type.ResFieldByAnys `db:"uniqueImportFields"` // 导入字段唯一效验
Roles res_type.ResFieldByAnys `db:"roles"` // 列表权限
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

34
base/data_list_field.go Normal file
View File

@ -0,0 +1,34 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type DataListField struct {
Uuid string `db:"uuid"`
DataListUuid string `db:"data_list_uuid"` // 所属列表 UUID
Title res_type.ResFieldByString `db:"title"` // 列表标题
Code string `db:"code"` // 字段名称
CodeResource string `db:"codeResource"` // 字段所属资源
Alias string `db:"alias"` // 字段别名
IsExpr bool `db:"isExpr"` // 字段名是否为SQL表达式
FieldDataType string `db:"fieldDataType"` // 字段数据类型
Width int `db:"width"` // 列宽
IsWidthFixed bool `db:"isWidthFixed"` // 列宽固定
Fixed bool `db:"fixed"` // 字段冻结
Align string `db:"align"` // 对齐方式
IsShow int `db:"isShow"` // 是否显示
WidgetByJs string `db:"widgetByJs"` // 前端数据渲染控件
WidgetByJsSetting res_type.ResFieldByMap `db:"widgetByJsSetting"` // 前端数据渲染控件设置参数
IsSearch bool `db:"isSearch"` // 允许关键字搜索
IsVirtual bool `db:"isVirtual"` // 是否虚拟字段
IsSort bool `db:"isSort"` // 允许字段排序
EditableByJs string `db:"editableByJs"` // 字段更新组件
EditableByJsSetting res_type.ResFieldByMap `db:"editableByJsSetting"` // 字段更新组件设置
FilterByJs string `db:"filterByJs"` // 字段筛选组件
FilterByJsSetting res_type.ResFieldByMap `db:"filterByJsSetting"` // 字段筛选组件设置参数
FilterOperator string `db:"filterOperator"` // 字段筛选符号
EditableRoles res_type.ResFieldByAnys `db:"editableRoles"` // 字段编辑权限
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

View File

@ -0,0 +1,24 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type DataListImportField struct {
Uuid string `db:"uuid"`
DataListUuid string `db:"data_list_uuid"` // 所属列表 UUID
Title res_type.ResFieldByString `db:"title"` // 列表标题
Code string `db:"code"` // 字段名称
CodeResource string `db:"codeResource"` // 字段所属资源
FieldDataType string `db:"fieldDataType"` // 字段数据类型
Width int `db:"width"` // 列宽
Align string `db:"align"` // 对齐方式
IsWidthFixed bool `db:"isWidthFixed"` // 列宽固定
ConvertByJs string `db:"convertByJs"` // 前端数据转换控件
ConvertByJsSetting res_type.ResFieldByMap `db:"convertByJsSetting"` // 前端数据转换控件设置参数
IsVirtual bool `db:"isVirtual"` // 是否虚拟字段
IsValidator int `db:"isValidator"` // 导入字段验证
Validators res_type.ResFieldByMap `db:"validators"` // 导入字段验证规则
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

View File

@ -0,0 +1,36 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type DataListOperation struct {
Uuid string `db:"uuid"`
Puuid string `db:"pUuid"`
DataListUuid string `db:"data_list_uuid"` // 所属列表 UUID
Name string `db:"name"` // 按钮名称
Code string `db:"code"` // 按钮标识
Category string `db:"category"` // 按钮类型
Icon string `db:"icon"` // 按钮图标
Size string `db:"size"` // 按钮大小
Block bool `db:"block"` // 固定宽度
Ghost bool `db:"ghost"` // 背景透明
Shape string `db:"shape"` // 按钮形状
Type string `db:"type"` // 按钮样式
IsPopConfirm bool `db:"isPopConfirm"` // 按钮提示
PopTitle string `db:"popTitle"` // 按钮提示
PopOkText string `db:"popOkText"` // 按钮提示
PopCancelText string `db:"popCancelText"` // 按钮提示
PopOkType string `db:"popOkType"` // 按钮提示
PopPlacement string `db:"popPlacement"` // 按钮提示
Widget string `db:"widget"` // 按钮组件
WidgetType string `db:"widgetType"` // 组件类型
WidgetProps res_type.ResFieldByMap `db:"widgetProps"` // 组件PROPS
WidgetSetting res_type.ResFieldByMap `db:"widgetSetting"` // 组件设置
WidgetContainerSetting res_type.ResFieldByMap `db:"widgetContainerSetting"` // 组件容器设置
IsRefresh int `db:"isRefresh"` // 0不刷新, 1刷新所有数据, 2刷新一条数据
NoAuthType string `db:"noAuthType"` // 无按钮权限处理方式
Roles res_type.ResFieldByAnys `db:"roles"` // 按钮权限
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

17
base/data_list_tab.go Normal file
View File

@ -0,0 +1,17 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type DataListTab struct {
Uuid string `db:"uuid"`
DataListUuid string `db:"data_list_uuid"` // 所属列表 UUID
Label string `db:"label"` // 标签名
Code string `db:"code"` // 标签标识
Order res_type.ResFieldByAnys `db:"order"` // 排序
UseOrderMode int `db:"useOrderMode"` // 排序模式
IsDefault bool `db:"isDefault"` // 是否默认
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

View File

@ -0,0 +1,19 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type DataListXlsxField struct {
Uuid string `db:"uuid"`
DataListUuid string `db:"data_list_uuid"` // 所属列表 UUID
Title res_type.ResFieldByString `db:"title"` // 列表标题
Code string `db:"code"` // 字段名称
CodeResource string `db:"codeResource"` // 字段所属资源
Alias string `db:"alias"` // 字段别名
FieldDataType string `db:"fieldDataType"` // 字段数据类型
IsExpr bool `db:"isExpr"` // 字段名是否为SQL表达式
IsShow bool `db:"isShow"` // 字段名是否为SQL表达式
ConvertByJs string `db:"convertByJs"` // 字段数据转换组件
ConvertByJsSetting res_type.ResFieldByMap `db:"convertByJsSetting"` // 字段数据转换组件参数
}

31
base/fsm_transition.go Normal file
View File

@ -0,0 +1,31 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type FsmTransition struct {
Uuid string `db:"uuid"`
FsmUuid string `db:"fsm_uuid"`
Name string `db:"name"`
Code string `db:"code"`
From string `db:"from"`
To string `db:"to"`
ResourceUuid string `db:"resource_uuid"`
FsmName string `db:"fsm_name"`
PrimaryKey string `db:"primaryKey"`
StatusField string `db:"statusField"`
StatusOptions res_type.ResFieldByAnys `db:"statusOptions"`
IsPopConfirm bool `db:"isPopConfirm"`
PopTitle string `db:"popTitle"`
PopOkText string `db:"popOkText"`
PopCancelText string `db:"popCancelText"`
PopOkType string `db:"popOkType"`
PopPlacement string `db:"popPlacement"`
WidgetContainerSetting res_type.ResFieldByMap `db:"widgetContainerSetting"`
Roles res_type.ResFieldByAnys `db:"roles"`
OperationRoles res_type.ResFieldByAnys `db:"operationRoles"`
IsWithLayoutForm bool `db:"isWithLayoutForm"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

25
base/layout.go Normal file
View File

@ -0,0 +1,25 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type Layout struct {
Uuid string `db:"uuid"`
ResourceUuid string `db:"resource_uuid"` // 所属资源UUID
Code string `db:"code"` // 布局标识
Name string `db:"name"` // 布局名称
Type int `db:"type"` // 布局类型
Align string `db:"align"` // 方向
PrimaryKey string `db:"primaryKey"` // 主键
AutoComplete string `db:"autoComplete"` // 自动填充表单, off | on
RowHeight int `db:"rowHeight"` // 栅格行高
MarginX int `db:"marginX"` // 栅格 x 间距
MarginY int `db:"marginY"` // 栅格 y 间距
FormProps res_type.ResFieldByAnys `db:"formProps"` // 表单PROPS
ListenChangeFields res_type.ResFieldByAnys `db:"listenChangeFields"` // 监听字段
ListenChangeFieldsFunc res_type.ResFieldByString `db:"listenChangeFieldsFunc"` // 监听字段回调方法
Roles res_type.ResFieldByAnys `db:"roles"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

35
base/layout_field.go Normal file
View File

@ -0,0 +1,35 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type LayoutField struct {
Uuid string `db:"uuid"`
LayoutUuid string `db:"layout_uuid"` // 所属布局 UUID
Type string `db:"type"`
X int `db:"x"`
Y int `db:"y"`
W int `db:"w"`
H int `db:"h"`
MinH int `db:"minH"`
MinW int `db:"minW"`
MaxH int `db:"maxH"`
MaxW int `db:"maxW"`
Code string `db:"code"`
Label string `db:"label"`
Widget string `db:"widget"`
WidgetPerfix string `db:"widgetPerfix"`
WidgetDecorator res_type.ResFieldByString `db:"widgetDecorator"`
SubWidgets res_type.ResFieldByAnys `db:"subWidgets"`
Placeholder string `db:"placeholder"`
Help string `db:"help"`
Disabled int `db:"disabled"`
InitialValue string `db:"initialValue"`
Extras res_type.ResFieldByMap `db:"extras"`
Validators res_type.ResFieldByMap `db:"validators"`
Hidden bool `db:"hidden"`
IsVirtual bool `db:"isVirtual"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

23
base/menu.go Normal file
View File

@ -0,0 +1,23 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type Menu struct {
Uuid string `db:"uuid"`
Id int `db:"id"`
Pid int `db:"pid"`
Type string `db:"type"`
Name string `db:"name"`
Icon string `db:"icon"`
Widget string `db:"widget"`
WidgetType string `db:"widgetType"`
WidgetProps res_type.ResFieldByMap `db:"widgetProps"`
WidgetSetting res_type.ResFieldByMap `db:"widgetSetting"`
WidgetContainerSetting res_type.ResFieldByMap `db:"widgetContainerSetting"`
Roles res_type.ResFieldByAnys `db:"roles"`
Platform string `db:"platform"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

17
base/print_template.go Normal file
View File

@ -0,0 +1,17 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type PrintTemplate struct {
Uuid string `db:"uuid"`
ResourceUuid string `db:"resource_uuid"` // 所属资源UUID
Code string `db:"code"` // 打印模板标识
Name string `db:"name"` // 打印模板名称
PrimaryKey string `db:"primaryKey"` // 主键标识
Roles res_type.ResFieldByAnys `db:"roles"` // 打印权限
Template res_type.ResFieldByMap `db:"template"` // 打印权限
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

View File

@ -0,0 +1,21 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type PrintTemplateField struct {
Uuid string `db:"uuid"`
PrintTemplateUuid string `db:"print_template_uuid"` // 所属打印模板UUID
Label res_type.ResFieldByString `db:"label"` // 字段标签
Code string `db:"code"` // 字段名称
CodeResource string `db:"codeResource"` // 字段所属资源
Category string `db:"category"` // 字段控件类型
Alias string `db:"alias"` // 字段别名
IsExpr bool `db:"isExpr"` // 字段名是否为SQL表达式
FieldDataType string `db:"fieldDataType"` // 字段数据类型
WidgetByJs string `db:"widgetByJs"` // 前端数据渲染控件
WidgetByJsSetting res_type.ResFieldByMap `db:"widgetByJsSetting"` // 前端数据渲染控件设置参数
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

19
base/res_api.go Normal file
View File

@ -0,0 +1,19 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type ResApi struct {
Uuid string `db:"uuid"`
Code string `db:"code"`
Name string `db:"name"`
PrimaryKey string `db:"primaryKey"`
ResourceUuid string `db:"resource_uuid"`
Method string `db:"method"`
Category string `db:"action"`
Params res_type.ResFieldByAnys `db:"params"`
Roles res_type.ResFieldByAnys `db:"roles"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

18
base/res_api_approval.go Normal file
View File

@ -0,0 +1,18 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type ResApiApproval struct {
Uuid string `db:"uuid"`
ApiUuid string `db:"api_uuid"`
Code string `db:"code"`
Name string `db:"name"`
MarkField string `db:"markField"`
RolesUuid res_type.ResFieldByAnys `db:"rolesUuid"`
Flows res_type.ResFieldByAnys `db:"flows"`
Roles res_type.ResFieldByAnys `db:"roles"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

13
base/res_api_field.go Normal file
View File

@ -0,0 +1,13 @@
package base
type ResApiField struct {
Uuid string `db:"id"`
ApiUuid string `db:"api_uuid"`
Code string `db:"code"` // 字段名称
CodeResource string `db:"resource"` // 字段所属资源
Alias string `db:"alias"` // 字段别名
IsExpr bool `db:"isExpr"` // 字段名是否为SQL表达式
FieldDataType string `db:"fieldDataType"` // 字段数据类型
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

19
base/res_condition.go Normal file
View File

@ -0,0 +1,19 @@
package base
type ResCondition struct {
Uuid string `db:"id"`
Id int `db:"id"`
Pid int `db:"pid"`
Type string `db:"type"`
CategoryUuid string `db:"category_uuid"`
Column string `db:"column"`
ColumnResource string `db:"columnResource"`
Operator string `db:"operator"`
ColumnSqlFunc string `db:"columnSqlFunc"`
ColumnSqlFuncParam string `db:"columnSqlFuncParam"`
IgnoreEmptyParma bool `db:"ignoreEmptyParma"`
ValueType string `db:"valueType"`
Value string `db:"value"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

14
base/res_configure.go Normal file
View File

@ -0,0 +1,14 @@
package base
type ResConfigure struct {
Uuid string `db:"uuid"`
ResourceUuid string `db:"resource_uuid"`
Key string `db:"key"`
Value string `db:"value"`
Label string `db:"label"`
Type string `db:"type"`
IsPrivate bool `db:"isPrivate"`
Desc string `db:"desc"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

288
base/res_field.go Normal file
View File

@ -0,0 +1,288 @@
package base
import (
"database/sql/driver"
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"github.com/spf13/cast"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/contracts/res_type"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/db/schema"
)
// 资源字段
type ResField struct {
Uuid string `db:"uuid"`
Name string `db:"name"`
Code string `db:"code"`
CodeResource string `db:"codeResource"`
DataType res_type.ResDataType `db:"table_type"`
Length string `db:"length"`
Comment string `db:"comment"`
Default string `db:"default"`
}
type ResFields []ResField
func (c *ResFields) Scan(value any) error {
if value == nil {
return nil
}
if err := json.Unmarshal(value.([]byte), c); err != nil {
return fmt.Errorf("ResFields json.Unmarshal Error, %s", err)
}
return nil
}
func (c ResFields) Value() (driver.Value, error) {
b, err := json.Marshal(c)
return string(b), err
}
func (this ResField) ToStructField(tags ...string) reflect.StructField {
var typ reflect.Type
fCode := this.Code
fTag := `db:"` + fCode + `" json:"` + fCode + `"`
if len(tags) > 0 {
fTag = strings.Join(tags, " ") + " " + fTag
}
switch this.DataType {
case contracts.ResDataType_String, contracts.ResDataType_Text, contracts.ResDataType_Enum,
contracts.ResDataType_Timestamp, contracts.ResDataType_Date, contracts.ResDataType_Datetime:
typ = reflect.TypeOf(res_type.ResFieldByString(""))
case contracts.ResDataType_Integer, contracts.ResDataType_SmallInteger:
typ = reflect.TypeOf(res_type.ResFieldByInteger(0))
case contracts.ResDataType_Decimal:
typ = reflect.TypeOf(float64(0))
case contracts.ResDataType_Boolean:
typ = reflect.TypeOf(true)
case contracts.ResDataType_Json:
if this.Default != "" && this.Default[0:1] == "[" {
typ = reflect.TypeOf(res_type.ResFieldByAnys{})
} else {
typ = reflect.TypeOf(res_type.ResFieldByMap{})
}
}
return reflect.StructField{
Name: strings.ToUpper(fCode[:1]) + fCode[1:],
Tag: reflect.StructTag(fTag),
Type: typ,
}
}
func (this ResField) GetCode() string {
return this.Code
}
func (this ResField) GetCodeResource() string {
return this.CodeResource
}
func (this ResField) GetName() string {
return this.Name
}
func (this ResField) GetDataType() contracts.ResDataType {
return this.DataType
}
func (this ResField) GetQueryDataType() contracts.QueryDataType {
switch this.GetDataType() {
case contracts.ResDataType_Enum,
contracts.ResDataType_Timestamp, contracts.ResDataType_Date,
contracts.ResDataType_Datetime, contracts.ResDataType_String,
contracts.ResDataType_Text:
return contracts.QueryDataType_String
case contracts.ResDataType_Integer, contracts.ResDataType_SmallInteger:
return contracts.QueryDataType_Integer
case contracts.ResDataType_Decimal:
return contracts.QueryDataType_Float
case contracts.ResDataType_Boolean:
return contracts.QueryDataType_Bool
case contracts.ResDataType_Json:
if this.Default != "" && this.Default[0:1] == "[" {
return contracts.QueryDataType_Array
}
return contracts.QueryDataType_Json
}
return contracts.QueryDataType_String
}
func (this ResField) ToValue(v any) any {
// 类型转换, 填补 cast 未知的类型
switch data := v.(type) {
case res_type.ResFieldByInteger:
v = int64(data)
case res_type.ResFieldByFloat:
v = float64(data)
case res_type.ResFieldByNumber:
v = float64(data)
case res_type.ResFieldByString:
v = strings.Trim(string(data), " ")
case res_type.ResFieldByAnys:
if v != nil {
b, _ := json.Marshal(v)
return string(b)
}
v = []any(data)
case res_type.ResFieldByMap:
if v != nil {
b, _ := json.Marshal(v)
return string(b)
}
v = map[string]any(data)
case []any, []string, []int, []float64, []float32, []int64:
if v != nil {
b, _ := json.Marshal(v)
return string(b)
}
v = data
case map[string]any, map[string]string, map[string]int:
if v != nil {
b, _ := json.Marshal(v)
return string(b)
}
v = data
}
switch this.DataType {
case contracts.ResDataType_String, contracts.ResDataType_Text, contracts.ResDataType_Enum,
contracts.ResDataType_Timestamp, contracts.ResDataType_Date, contracts.ResDataType_Datetime:
return strings.Trim(cast.ToString(v), " ")
case contracts.ResDataType_Integer, contracts.ResDataType_SmallInteger:
return cast.ToInt(v)
case contracts.ResDataType_Decimal:
return strings.Trim(cast.ToString(v), " ")
case contracts.ResDataType_Boolean:
v, _ := strconv.ParseBool(fmt.Sprintf("%v", v))
return v
case contracts.ResDataType_Json:
if v == nil {
if this.Default != "" && this.Default[0:1] == "[" {
return "[]"
} else if this.Default != "" && this.Default[0:1] == "{" {
return "{}"
} else if this.Default == "" {
return "{}"
}
return this.Default
}
b, _ := json.Marshal(v)
return string(b)
}
return strings.Trim(cast.ToString(v), " ")
}
func (this ResField) GetRawDefault(driver string) db.Expression {
if this.DataType == "json" && this.Default == "" {
return db.Raw("'{}'")
}
if len(this.Default) > 4 && strings.ToLower(this.Default[0:4]) == "sql:" {
sql := strings.ToLower(this.Default[4:])
if sql == "uuid()" {
return Uuid(driver)
}
return db.Raw(sql)
}
if this.Default == "" {
if this.GetDataType() == contracts.ResDataType_Date || this.GetDataType() == contracts.ResDataType_Datetime {
return db.Raw("NULL")
}
return db.Raw("''")
}
if strings.ToUpper(this.Default) == "CURRENT_TIMESTAMP" {
return db.Raw(this.Default)
}
return db.Raw("'" + this.Default + "'")
}
func (this ResField) ToBlueprint(table *schema.Blueprint) (temp *schema.ColumnDefinition) {
isNull := false
comment := this.Name
def := any(this.Default)
if this.Comment != "" {
comment += " [ " + strings.Trim(this.Comment, `' "`) + " ]"
}
switch this.DataType {
case "string":
len := 255
if v, err := strconv.Atoi(strings.Trim(this.Length, `' "`)); err == nil {
len = v
}
temp = table.String(this.Code, len)
case "smallInteger":
// integer 默认长度 4
temp = table.SmallInteger(this.Code)
case "boolean":
// integer 默认长度 1
temp = table.Boolean(this.Code)
case "integer":
// integer 默认长度 11
temp = table.Integer(this.Code)
case "date", "dateTime":
if this.DataType == "date" {
temp = table.Date(this.Code)
} else {
temp = table.DateTime(this.Code)
}
if strings.ToUpper(this.Default) == "CURRENT_TIMESTAMP" {
def = db.Raw(this.Default)
} else if def == "" {
isNull = true
}
case "decimal":
allowed := strings.SplitN(this.Length, ",", 2)
total := 8
places := 2
if v, err := strconv.Atoi(strings.Trim(allowed[0], `' "`)); err == nil {
total = v
}
if v, err := strconv.Atoi(strings.Trim(allowed[1], `' "`)); err == nil {
places = v
}
temp = table.Decimal(this.Code, total, places)
case "enum":
allowed := []string{}
for _, v := range strings.Split(this.Length, ",") {
allowed = append(allowed, strings.Trim(v, `' "`))
}
temp = table.Enum(this.Code, allowed)
case "json":
temp = table.Json(this.Code)
isNull = true
case "text":
temp = table.Text(this.Code)
isNull = true
}
if isNull {
temp.Nullable()
} else {
temp.Default(def)
}
temp.Comment(comment)
return temp
}

View File

@ -0,0 +1,14 @@
package base
import (
"github.com/google/uuid"
"git.fsdpf.net/go/db"
)
func Uuid(driver string) db.Expression {
if driver == "sqlite" {
return db.Raw("'" + uuid.NewString() + "'")
}
return db.Raw("uuid()")
}

15
base/res_listener.go Normal file
View File

@ -0,0 +1,15 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type ResListener struct {
Uuid string `db:"uuid"`
Code string `db:"code"`
Name string `db:"name"`
ResourceUuid string `db:"resource_uuid"`
Event res_type.ResFieldByAnys `db:"event"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

15
base/res_relation.go Normal file
View File

@ -0,0 +1,15 @@
package base
type ResRelation struct {
Uuid string `db:"uuid"`
CategoryUuid string `db:"category_uuid"` // 所属 UUID
Name string `db:"name"` // 关联名称
Code string `db:"code"` // 关联标识
Type string `db:"type"` // 关联类型
ResourceCode string `db:"actuallyResource"` // 实际资源资源
RelationForeignKey string `db:"actuallyField"` // 实际资源资源字段
RelationResource string `db:"relationResource"` // 被关联的资源
RelationField string `db:"relationField"` // 被关联的字段
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

9
base/res_role.go Normal file
View File

@ -0,0 +1,9 @@
package base
type ResRole struct {
Uuid string `db:"id"`
ResUuid string `db:"resource_uuid"`
RoleUuid string `db:"role_uuid"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

View File

@ -0,0 +1,17 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type ResWidgetOperation struct {
Uuid string `db:"uuid"`
WidgetUuid string `db:"widget_uuid"`
Name string `db:"name"`
NoAuthType string `db:"noAuthType"`
PropsAuthRule res_type.ResFieldByAnys `db:"propsAuthRule"`
ExtraAuthRule res_type.ResFieldByAnys `db:"extraAuthRule"`
Roles res_type.ResFieldByAnys `db:"roles"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

340
base/resource.go Normal file
View File

@ -0,0 +1,340 @@
package base
import (
"database/sql"
"log"
"reflect"
"unicode"
"github.com/samber/do"
"github.com/samber/lo"
"git.fsdpf.net/go/contracts"
"git.fsdpf.net/go/contracts/res_type"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/queue"
)
// 资源
type Resource struct {
container *do.Injector
Uuid string `db:"uuid"`
PUuid string `db:"pUuid"`
Code string `db:"code"`
Name string `db:"name"`
IsResVirtual bool `db:"isVirtual"`
Table string `db:"table"`
Namespace string `db:"namespace"`
Workspace string `db:"workspace"`
Primarykey string `db:"primaryKey"`
IsHistoryRecord bool `db:"isHistoryRecord"`
HistoryCacheMax int `db:"historyCacheMax"`
Fields ResFields `db:"fields"`
Roles res_type.ResFieldByMap `db:"roles"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}
// 资源UUID
func (this Resource) GetUuid() string {
return this.Uuid
}
// 资源CODE
func (this Resource) GetCode() string {
return this.Code
}
// 资源名
func (this Resource) GetName() string {
return this.Name
}
// 主键
func (this Resource) GetPrimarykey() string {
return this.Primarykey
}
// 是否虚拟资源
func (this Resource) IsVirtual() bool {
return this.IsResVirtual
}
// 是否系统资源
func (this Resource) IsSystem() bool {
return this.Namespace == "Framework\\Service"
}
// 资源字段
func (this Resource) GetFields() (result []contracts.ResField) {
for _, item := range this.Fields {
result = append(result, item)
}
return result
}
// 资源字段
func (this Resource) GetField(code string) (contracts.ResField, bool) {
return lo.Find(this.GetFields(), func(v contracts.ResField) bool {
return v.GetCode() == code
})
}
// 判断资源字段
func (this Resource) HasField(code string) bool {
return lo.SomeBy(this.GetFields(), func(v contracts.ResField) bool {
return v.GetCode() == code
})
}
// 开启事物
func (this Resource) BeginTransaction() (*db.Transaction, error) {
return this.GetDB().Connection.BeginTransaction()
}
// 获取资源对应的数据库连接
func (this Resource) GetDB() *db.Builder {
db := do.MustInvoke[db.DB](this.container)
if this.IsSystem() {
return db.Connection("service-support").Query()
}
return db.Connection("default").Query()
}
// 获取资源对应的数据表
func (this Resource) GetTable() db.Expression {
if this.IsVirtual() {
return db.Raw("(" + this.Table + ")")
}
return db.Raw(this.Table)
}
func (this Resource) GetDBDriver() string {
return this.GetDB().Connection.GetConfig().Driver
}
func (this Resource) GetAuthDBTable(u contracts.User, params ...any) *db.Builder {
this.GetRolesCondition(u)
return this.GetDBTable(append(params, u)...)
}
// GetDBTable("Test", contracts.User)
func (this Resource) GetDBTable(params ...any) *db.Builder {
builder := this.GetDB()
var user contracts.User
alias := this.Code
for _, param := range params {
switch v := param.(type) {
case *db.Transaction:
builder.Tx = v
case string:
alias = v
case contracts.User:
user = v
}
}
// 格式化数据库存储数据
builder.Before(func(b *db.Builder, t string, data ...map[string]any) {
if t == db.TYPE_UPDATE {
// 格式化保存数据
this.formatSaveValue(data[0])
}
if t == db.TYPE_INSERT {
// 移除 table alias
b.Table(string(this.GetTable()))
for i := 0; i < len(data); i++ {
// 格式化保存数据
this.formatSaveValue(data[i])
// 填充保存数据
this.fillSaveValue(data[i], user, db.TYPE_INSERT)
}
}
})
// 资源事件
this.onResEvent(builder)
// 用户事件
if this.IsHistoryRecord {
this.onUserEvent(builder, user)
}
// 虚拟资源暂时不考虑鉴权
if !this.IsVirtual() {
// 返回鉴权后的 DB Builder
// return
}
return builder.Table(string(this.GetTable()), alias)
}
func (this Resource) WithRolesCondition(b *db.Builder, roles ...string) {
}
// 获取鉴权条件
func (this Resource) GetRolesCondition(u contracts.User) {
// isFullRight := false
// isFullNot := false
// roles := do.MustInvoke[GetResRoles](this.container)(this.GetUuid())
// GetResRelations := do.MustInvoke[GetResRelations](this.container)
// subTables := lo.Reduce(roles, func(carry *db.Builder, item ResRole, _ int) *db.Builder {
// db := this.GetDB().Table(string(this.GetTable()), this.GetCode()).Select("`" + this.GetCode() + "`.*")
// joins := lo.Filter(GetResRelations(item.Uuid), func(item ResRelation, _ int) bool {
// return item.Type == "inner" || item.Type == "left" || item.Type == "right"
// })
// join := orm.NewJoin(contracts.RelationType(item.Type), item.Code, oResource, item.RelationResource, item.RelationField, item.RelationForeignKey)
// // 关联扩展条件
// join.SetCondition(orm.NewConditionByRes(GetResConditions(item.Uuid)))
// return carry
// }, nil)
// fmt.Println(subTables.ToSql())
}
// 格式化保存数据
func (this Resource) formatSaveValue(data map[string]any) {
//
for k, v := range data {
if k == "id" || k == "created_user" || k == "created_at" || k == "deleted_at" || k == "updated_at" {
delete(data, k)
} else if val, ok := v.(db.Expression); ok {
data[k] = val
} else if field, ok := this.GetField(k); ok {
data[k] = field.ToValue(v)
}
}
}
// 填充保存数据
func (this Resource) fillSaveValue(data map[string]any, u contracts.User, t string) {
for _, field := range this.GetFields() {
fCode := field.GetCode()
if fCode == "id" || fCode == "created_user" || fCode == "created_at" || fCode == "deleted_at" || fCode == "updated_at" || fCode == "owned_user" {
continue
}
// 只有新增默认字段
if _, ok := data[fCode]; !ok {
data[fCode] = field.GetRawDefault(this.GetDBDriver())
}
}
// 拥有者
if _, ok := data["owned_user"]; !ok {
data["owned_user"] = u.Uuid()
}
// 创建者
data["created_user"] = u.Uuid()
if this.GetDBDriver() == "sqlite" {
// 更新时间
// sqlite 不能自动更新时间, "DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
data["updated_at"] = db.Raw("CURRENT_TIMESTAMP")
} else {
}
}
func (this Resource) GetStruct(extends ...reflect.StructField) any {
fields := []reflect.StructField{}
for _, field := range this.Fields {
if unicode.IsLetter(rune(field.Code[0])) {
fields = append(fields, field.ToStructField())
} else {
log.Printf("资源字段错误, 必须以字母开头 <- %s", field.Code)
}
}
fields = lo.UniqBy(append(fields, extends...), func(v reflect.StructField) string {
return v.Name
})
t := reflect.StructOf(fields)
return reflect.New(t).Interface()
}
func (this Resource) GetSliceStruct(extends ...reflect.StructField) any {
t := reflect.TypeOf(this.GetStruct(extends...))
st := reflect.SliceOf(t.Elem())
return reflect.New(st).Interface()
}
// 资源事件
func (this Resource) onResEvent(builder *db.Builder) {
builder.After(func(b *db.Builder, t string, result sql.Result, err error, data ...map[string]any) {
if err != nil || t == db.TYPE_SELECT {
return
} else if num, err := result.RowsAffected(); num == 0 || err != nil {
return
}
// 全局触发器
// 1. 清除系统缓存
if err := do.MustInvoke[contracts.Queue](this.container).Publish(contracts.ResQueueTopic, contracts.ResQueuePayload{
Type: t,
Res: this,
Result: result,
}); err != nil {
log.Println("Queue Publish Err:", contracts.ResQueueTopic, err)
}
})
}
// 用户事件
func (this Resource) onUserEvent(builder *db.Builder, user contracts.User) {
old := []map[string]any{}
builder.Before(func(b *db.Builder, t string, data ...map[string]any) {
if t != db.TYPE_UPDATE && t != db.TYPE_DELETE {
return
}
// 查询保存之前的数据
if _, err := b.Get(&old); err != nil {
panic(err)
}
})
builder.After(func(b *db.Builder, t string, result sql.Result, err error, data ...map[string]any) {
if err != nil || t == db.TYPE_SELECT {
return
} else if num, err := result.RowsAffected(); num == 0 || err != nil {
return
}
if user == nil {
user = GetAnonymous()
}
// 触发消息队列
if err := do.MustInvoke[contracts.Queue](this.container).Publish(contracts.UserQueuetTopic, contracts.UserQueuePayload{
Type: t,
User: user,
Res: this,
Old: old,
New: data,
Result: result,
}); err != nil {
log.Println("Queue Publish Err:", contracts.UserQueuetTopic, err)
}
})
}

23
base/route.go Normal file
View File

@ -0,0 +1,23 @@
package base
import (
"git.fsdpf.net/go/contracts/res_type"
)
type Route struct {
Uuid string `db:"uuid"`
Name string `db:"name"`
Uri string `db:"uri"`
Layout string `db:"layout"`
IsLogin bool `db:"isLogin"`
IsPhone bool `db:"isPhone"`
Type string `db:"type"`
Component string `db:"component"`
WidgetProps res_type.ResFieldByMap `db:"widgetProps"`
WidgetSetting res_type.ResFieldByMap `db:"widgetSetting"`
WidgetContainerSetting res_type.ResFieldByMap `db:"widgetContainerSetting"`
Exact bool `db:"exact"`
Platform string `db:"platform"`
UpdatedAt string `db:"updated_at"`
CreatedAt string `db:"created_at"`
}

81
base/user.go Normal file
View File

@ -0,0 +1,81 @@
package base
import (
"reflect"
"github.com/samber/lo"
"git.fsdpf.net/go/contracts"
)
type user struct {
id int
uuid string
username string
nickname string
platform string
roles []string
}
func (this user) ID() int {
return this.id
}
func (this user) Uuid() string {
return this.uuid
}
func (this user) Username() string {
return this.username
}
func (this user) Nickname() string {
return this.nickname
}
func (this user) GetUserInfo() any {
return nil
}
func (this user) Roles() (roles []string) {
return this.roles
}
func (this user) HasUserRoles(roles ...string) bool {
return lo.Contains(this.Roles(), "ffffffff-ffff-ffff-ffff-ffffffffffff") || len(lo.Intersect(this.Roles(), roles)) > 0
}
func (this user) IsAnonymous() bool {
return reflect.DeepEqual(this.Roles(), []string{"00000000-0000-0000-0000-000000000000"})
}
func (this user) Platform() string {
if this.platform == "" {
return "unknown"
}
return this.platform
}
// 获取匿名用户
func GetAnonymous() contracts.User {
return user{
id: 0,
uuid: "00000000-0000-0000-0000-000000000000",
username: "anonymous",
nickname: "匿名者",
roles: []string{"00000000-0000-0000-0000-000000000000"},
platform: "unknown",
}
}
// 系统用户
func GetSystemUser() contracts.User {
return user{
id: -1,
uuid: "ffffffff-ffff-ffff-ffff-ffffffffffff",
username: "system",
nickname: "系统",
roles: []string{"ffffffff-ffff-ffff-ffff-ffffffffffff"},
platform: "unknown",
}
}

7
configure.go Normal file
View File

@ -0,0 +1,7 @@
package contracts
import (
"github.com/spf13/viper"
)
type Configure = viper.Viper

52
controller.go Normal file
View File

@ -0,0 +1,52 @@
package contracts
import (
"net/http"
"github.com/samber/do"
)
type Controller interface {
AuthDB() ResAuthDB
Execute(GlobalParams) any
ExecuteWs(WsClient, GlobalParams) error
WsClientId(GlobalParams) WsClientID
WsClientGroup(GlobalParams) WsClientGroup
Call(code string, params map[string]any, category ...RouteCategory) (HttpResponse, error)
}
type BaseController struct {
User User
Container *do.Injector
Request *http.Request
request *http.Request
Route Route
}
var defaultWsClientGroup WsClientGroup = "__DEFAULT__"
var wsClientID WsClientID = 0
func (BaseController) AuthDB() ResAuthDB {
return ResAuthOff
}
func (BaseController) Execute(params GlobalParams) any {
return nil
}
func (BaseController) ExecuteWs(wc WsClient, params GlobalParams) error {
return nil
}
func (BaseController) WsClientId(GlobalParams) WsClientID {
wsClientID++
return wsClientID
}
func (BaseController) WsClientGroup(GlobalParams) WsClientGroup {
return defaultWsClientGroup
}
func (this BaseController) Call(code string, params map[string]any, category ...RouteCategory) (HttpResponse, error) {
return do.MustInvoke[Router](this.Container).Call(this.Request, code, params, category...)
}

106
errno.go Normal file
View File

@ -0,0 +1,106 @@
package contracts
import (
"fmt"
"runtime"
)
// 定义错误码
type Errno struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
func (err Errno) Error() string {
return err.Msg
}
// 定义错误
type Err struct {
Code int `json:"code"` // 错误码
Msg string `json:"msg"` // 展示给用户看的
Errord string `json:"errord"` // 内部错误信息
}
func (err *Err) Error() string {
return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Msg, err.Errord)
}
// 错误码设计
// 第一位表示错误级别, 1 为系统错误, 2 为普通错误
// 第二三位表示服务模块代码
// 第四五位表示具体错误代码
var (
OK = &Errno{Code: 0, Msg: "操作成功!"}
UserRequestApproval = &Errno{Code: 1, Msg: "已提交审批申请"}
// 系统错误, 前缀为 100
InternalServerError = &Errno{Code: 10001, Msg: "内部服务器错误"}
ErrBind = &Errno{Code: 10002, Msg: "请求参数错误"}
ErrTokenSign = &Errno{Code: 10003, Msg: "签名 jwt 时发生错误"}
ErrEncrypt = &Errno{Code: 10004, Msg: "加密用户密码时发生错误"}
ErrNotFound = &Errno{Code: 10005, Msg: "Not Found"}
ErrFuncNotFound = &Errno{Code: 10006, Msg: "处理函数不存在"}
ErrResNotFound = &Errno{Code: 10007, Msg: "资源不存在"}
ErrResFieldNotFound = &Errno{Code: 10008, Msg: "资源字段不存在"}
ErrFileUpload = &Errno{Code: 10009, Msg: "文件上传错误"}
ErrFileNotFound = &Errno{Code: 10010, Msg: "文件不存在"}
// service 错误
ErrServiceDecode = &Errno{Code: 10101, Msg: "解析 base62param 错误"}
ErrServiceInitInfoByList = &Errno{Code: 10102, Msg: "初始化列表错误"}
ErrServiceInitInitRelation = &Errno{Code: 10103, Msg: "初始化资源关联错误"}
ErrServiceInitInitField = &Errno{Code: 10103, Msg: "初始化资源关联错误"}
// 数据库错误, 前缀为 201
ErrDatabase = &Errno{Code: 20100, Msg: "数据库错误"}
ErrDBFill = &Errno{Code: 20101, Msg: "从数据库填充 struct 时发生错误"}
ErrDBQuery = &Errno{Code: 20102, Msg: "数据查询错误"}
ErrDBStore = &Errno{Code: 20102, Msg: "数据保存错误"}
ErrDBUpdate = &Errno{Code: 20103, Msg: "数据更新错误"}
ErrDBDelete = &Errno{Code: 20104, Msg: "数据删除错误"}
ErrDBTransaction = &Errno{Code: 20105, Msg: "数据库事务错误"}
// 认证错误, 前缀是 202
ErrTokenValidation = &Errno{Code: 20201, Msg: "验证失败"}
ErrTokenInvalid = &Errno{Code: 20202, Msg: "token 无效"}
ErrTokenExpired = &Errno{Code: 20202, Msg: "token 过期"}
ErrTokenNotFound = &Errno{Code: 20202, Msg: "token 不存在"}
// 用户错误, 前缀为 203
ErrUserNotFound = &Errno{Code: 20301, Msg: "用户没找到"}
ErrUserPassword = &Errno{Code: 20302, Msg: "用户名或密码错误"}
ErrUserAuth = &Errno{Code: 20303, Msg: "无权限"}
ErrUserReadAuth = &Errno{Code: 20304, Msg: "无查询权限"}
ErrUserWriteAuth = &Errno{Code: 20305, Msg: "无写入权限"}
// 审批错误, 前缀是 204
// 审批节点不存在
ErrUserApprovalFlowNotFound = &Errno{Code: 20401, Msg: "审批节点不存在"}
// 下级审批节点不存在
ErrUserApprovalNextFlowNotFound = &Errno{Code: 20402, Msg: "下级审批节点不存在"}
// 该审批已结束
ErrUserApprovalFlowDone = &Errno{Code: 20403, Msg: "该审批已结束"}
// 该审批已撤销
ErrUserApprovalFlowCancelled = &Errno{Code: 20404, Msg: "该审批已撤销"}
// 超过自动扭转最大深度
ErrUserApprovalMaxExecuteDeep = &Errno{Code: 20405, Msg: "该审批已超过自动扭转最大深度撤销"}
// 该审批流已占用
ErrUserApprovalExists = &Errno{Code: 20406, Msg: "该审批流已被占用"}
// 请求第三个接口
ErrApiRequest = &Errno{Code: 20501, Msg: "Api Request Error"}
ErrApiResponsed = &Errno{Code: 20502, Msg: "Api Responsed Error"}
)
// 使用 错误码 和 error 创建新的 错误
func NewErr(errno *Errno, err error) *Err {
stackBuf := make([]byte, 1024)
n := runtime.Stack(stackBuf[:], false)
return &Err{
Code: errno.Code,
Msg: err.Error(),
Errord: string(stackBuf[:n]),
}
}

55
global_params.go Normal file
View File

@ -0,0 +1,55 @@
package contracts
import (
"time"
)
type GlobalParams interface {
User() User
// 获取路径内容
Get(p string) GlobalParams
// 路径包裹
Wrapped(p string) GlobalParams
// 追加到新 json
AppendTo(root, p string) GlobalParams
// 通过路径设置参数
Set(p string, v any) bool
// 通过路径设置原始参数
SetRaw(p string, v string) bool
// 删除路径参数
Delete(p string) bool
// 获取原始JOSN字符串
Raw() string
// 转数组 GlobalParams
Array() []GlobalParams
// 判断内容是否存在
Exists() bool
Value() any
Bool() bool
Time() time.Time
TimeInDefaultLocation(l *time.Location) time.Time
Float64() float64
Float32() float32
Int64() int64
Int32() int32
Int16() int16
Int8() int8
Int() int
Uint() uint
Uint64() uint64
Uint32() uint32
Uint16() uint16
Uint8() uint8
String() string
StringMapString() map[string]string
StringMapStringSlice() map[string][]string
StringMapBool() map[string]bool
StringMapInt() map[string]int
StringMapInt64() map[string]int64
StringMap() map[string]any
Slice() []any
BoolSlice() []bool
StringSlice() []string
IntSlice() []int
}

34
go.mod Normal file
View File

@ -0,0 +1,34 @@
module git.fsdpf.net/go/contracts
go 1.18
require (
git.fsdpf.net/go/db v0.0.0-20230412075825-59b3faa171bc
git.fsdpf.net/go/queue v0.0.0-20230412075313-ae0e0992773d
github.com/go-chi/chi v1.5.4
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/samber/do v1.6.0
github.com/samber/lo v1.38.1
github.com/spf13/cast v1.5.0
github.com/spf13/viper v1.15.0
)
require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

497
go.sum Normal file
View File

@ -0,0 +1,497 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.fsdpf.net/go/db v0.0.0-20230412075825-59b3faa171bc h1:d3ZqjNGbsgVknkbvATV96rv1bW8mwqbmnV5bfGTVRVU=
git.fsdpf.net/go/db v0.0.0-20230412075825-59b3faa171bc/go.mod h1:397Sdx1cJS0OlHtTX1bVl//9k3Xn0Klnc6jC4MAkb6w=
git.fsdpf.net/go/queue v0.0.0-20230412075313-ae0e0992773d h1:me/Ed7DlV/tlVi3ouk/P2uAujPINR56oKNUqLPx+Tjo=
git.fsdpf.net/go/queue v0.0.0-20230412075313-ae0e0992773d/go.mod h1:H6LmQawjksoBdNjR7dRHD7Rrl7dxi6gSQUhoAXyGfzo=
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/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/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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs=
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg=
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-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
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=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/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/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
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/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/samber/do v1.6.0 h1:Jy/N++BXINDB6lAx5wBlbpHlUdl0FKpLWgGEV9YWqaU=
github.com/samber/do v1.6.0/go.mod h1:DWqBvumy8dyb2vEnYZE7D7zaVEB64J45B0NjTlY/M4k=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
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.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
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-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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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/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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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-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-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=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
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-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-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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
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=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-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/sys v0.0.0-20180830151530-49385e6e1522/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-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-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-20191001151750-bb3f8db39f24/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=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-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-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/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=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
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-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=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
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-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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
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-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=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
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-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
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/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
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=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
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=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/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=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

7
http.go Normal file
View File

@ -0,0 +1,7 @@
package contracts
type Http interface {
Start() error
Stop() error
Restart() error
}

200
orm.go Normal file
View File

@ -0,0 +1,200 @@
package contracts
import (
"reflect"
"git.fsdpf.net/go/db"
)
type OrmExecute int
type RelationType string
type QueryDataType string
type ConditionType string
type ConditionOperator string
type ConditionTokenType string
const (
OrmExecute_Query OrmExecute = iota
OrmExecute_Show
OrmExecute_Store
OrmExecute_Destroy
)
const (
RelationType_HasOne RelationType = "hasOne"
RelationType_HasMany RelationType = "hasMany"
RelationType_Inner RelationType = "inner"
RelationType_Left RelationType = "left"
RelationType_Right RelationType = "right"
)
const (
ConditionType_OR ConditionType = "OR"
ConditionType_AND ConditionType = "AND"
)
const (
ConditionTokenType_SQL ConditionTokenType = "sql"
ConditionTokenType_FUNC ConditionTokenType = "func"
ConditionTokenType_PARAM ConditionTokenType = "param"
ConditionTokenType_STRING ConditionTokenType = "string"
)
const (
ConditionOperator_IS_NULL ConditionOperator = "IS NULL"
ConditionOperator_IS_NOT_NULL ConditionOperator = "IS NOT NULL"
ConditionOperator_EQ ConditionOperator = "="
ConditionOperator_NE ConditionOperator = "!="
ConditionOperator_GT ConditionOperator = ">"
ConditionOperator_GE ConditionOperator = ">="
ConditionOperator_LT ConditionOperator = "<"
ConditionOperator_LE ConditionOperator = "<="
ConditionOperator_LIKE ConditionOperator = "LIKE"
ConditionOperator_NOT_LIKE ConditionOperator = "NOT LIKE"
ConditionOperator_IN ConditionOperator = "IN"
ConditionOperator_NOT_IN ConditionOperator = "NOT IN"
ConditionOperator_REGEXP ConditionOperator = "REGEXP"
ConditionOperator_NOT_REGEXP ConditionOperator = "NOT REGEXP"
)
const (
QueryDataType_Number QueryDataType = "number"
QueryDataType_Integer QueryDataType = "integer"
QueryDataType_Float QueryDataType = "float"
QueryDataType_String QueryDataType = "string"
QueryDataType_Bool QueryDataType = "bool"
QueryDataType_Array QueryDataType = "array"
QueryDataType_Json QueryDataType = "json"
)
const (
QueryField_IsExpr = 1 << iota
QueryField_IsOmitempty
QueryField_Ignored
)
type Orm interface {
SetGlobalParams(g GlobalParams) Orm
GetModel(params ...string) Model
SetRelationModel(m Model) Model
SetQueryField(qf QueryField) error
SetOrderBy(params []OrderBy) error
SetCondition(cond Condition) error
SetController(ctr reflect.Value) error
Execute(OrmExecute) (any, error)
Clone(tx *db.Transaction) Orm
Count() int
// Exists() bool
}
type Relation interface {
Parent() Model
AppendTo(Model)
Type() RelationType
SetType(RelationType)
SetCondition(Condition) Condition
SetPrependCondition(Condition) Condition
GetCondition() Condition
GetRelationResource() string
GetRelationField() string
GetRelationForeignKey() string
}
type Join interface {
Relation
GetCode() string
GetResource() Resource
// GetDependencies(items []ResRelation, dependencies ...string) []string
Inject(dbBuilder *db.Builder, m Model)
}
type Model interface {
Relation
GetCode() string
GetPrimaryKey() string
GetParam(k string) GlobalParams
GetParamWithPrefix(k string, prefix string) GlobalParams
GetGlobalParamsUser() User
GetQueryFieldsStruct(extends ...reflect.StructField) any
GetQueryFieldsSliceStruct(fields ...reflect.StructField) any
GetAttribute() map[string]any
GetResult() reflect.Value
GetResource() Resource
QueryBuilder() *db.Builder
GetTransaction() *db.Transaction
SetQueryField(QueryField)
SetRelationResult(code string, vItems reflect.Value)
GetJoinsCode() []string
SetAuthDB(ResAuthDB)
SetOrderBy(params ...OrderBy) Model
SetGroupBy(params ...GroupBy) Model
SetJoin(Join) Model
SetLimit(int) Model
SetOffset(int) Model
SetAttribute(data any) Model
SetPrimaryKey(string) Model
SetWithRecursive(QueryWithRecursive) Model
DelQueryField(string)
Query() error
Store() error
Destroy() error
Count() (int, error)
// Exists() (bool, error)
}
type Condition interface {
Type() ConditionType
IsEmpty() bool
IsNotEmpty() bool
ToSql(Model) db.Expression
AppendTo(Condition)
SetExpr(ConditionExpr) Condition
SetCondition(Condition) Condition
SetMatchPrefix(string) Condition
GetFields(operator ConditionOperator, types ...ConditionTokenType) map[string]string
GetFieldsValue(m Model, isWithResource bool) map[string]any
}
type ConditionExpr interface {
GetField() string
GetFieldResource() string
GetOperator() ConditionOperator
SetMatchPrefix(string)
AppendTo(Condition)
ToSql(m Model) db.Expression
GetTokenName() string
GetTokenType() ConditionTokenType
GetTokenValue(Model) any
GetTokenSqlValue(Model) string
IsIgnoreEmptyParma(Model) bool
}
type QueryField interface {
ResField
Type() QueryDataType
Alias() string
GetCodeOrAlias() string
IsExpr() bool
IsOmitempty() bool
Ignored() bool
SetOptions(int) QueryField
ToSql() db.Expression
ToStructField(tags ...string) reflect.StructField
}
type OrderBy interface {
ToSql() db.Expression
Inject(dbBuilder *db.Builder, m Model)
}
type GroupBy interface {
ToSql() db.Expression
Inject(dbBuilder *db.Builder, m Model)
}
type QueryWithRecursive interface {
ToQueryBuilder(*db.Builder, Model) (*db.Builder, any)
ToTreeData(any) any
}

7
provider.go Normal file
View File

@ -0,0 +1,7 @@
package contracts
type DoServiceProvider interface {
Register()
Start()
Shutdown()
}

51
queue.go Normal file
View File

@ -0,0 +1,51 @@
package contracts
import (
"database/sql"
)
const ResQueueTopic = "res-queue-topic"
const UserQueueTopic = "user-queue-topic"
type ResQueuePayload struct {
Type string // insert | delete | update
Res Resource // 变更资源
Result sql.Result // 执行结果
}
type UserQueuePayload struct {
Type string // insert | delete | update | select
User User // 操作用户
Res Resource // 变更资源
Result sql.Result // 执行结果
Old []map[string]any // 旧数据
New []map[string]any // 新数据
}
type Queue interface {
// 消息推送
// @param topic 订阅的主题
// @param msg 传递的消息
Publish(topic string, msg any) error
// 消息订阅
// @description 传入订阅的主题,即可完成订阅
// @param topic 订阅的主题
// @return channel 通道用来接收数据
Subscribe(topic string) (sub <-chan any, err error)
// 取消订阅
// @param topic 订阅的主题
// @param sub 消息订阅的通道
Unsubscribe(topic string, sub <-chan any) error
// 关闭消息队列
Close()
// 设置消息容量
// @description 控制消息队列的大小
SetConditions(capacity int)
// 获取主题消息内容
GetPayload(sub <-chan any) any
}

51
res_listener.go Normal file
View File

@ -0,0 +1,51 @@
package contracts
import (
"github.com/samber/do"
"github.com/samber/lo"
)
type ResEvent string
type ResListener interface {
Insert(new map[string]any, u User, id int64) error
Update(new map[string]any, u User, old map[string]any) error
Delete(old map[string]any, u User) error
GetResource() Resource
GetCode() string
}
type BaseListener struct {
Container *do.Injector
res Resource // 监听资源
code string // code
events []string // 监听动作
}
func (this BaseListener) GetCode() string {
return this.code
}
func (this BaseListener) GetResource() Resource {
return this.res
}
func (this BaseListener) HasEvent(event string) bool {
return lo.Contains(this.events, event)
}
func (BaseListener) Insert(new map[string]any, u User, id int64) error {
return nil
}
func (BaseListener) Update(new map[string]any, u User, old map[string]any) error {
return nil
}
func (BaseListener) Delete(old map[string]any, u User) error {
return nil
}
func NewBaseListener(code string, res Resource, container *do.Injector) *BaseListener {
return &BaseListener{code: code, res: res, Container: container}
}

View File

@ -0,0 +1,27 @@
package res_type
import (
"database/sql/driver"
"encoding/json"
"fmt"
)
// 解析map ----------------------------------
type ResFieldByMap map[string]any
func (c *ResFieldByMap) Scan(value any) error {
if value == nil {
return nil
}
if err := json.Unmarshal(value.([]byte), c); err != nil {
return fmt.Errorf("ResFieldByMap json.Unmarshal Error, %s", err)
}
return nil
}
func (c ResFieldByMap) Value() (driver.Value, error) {
b, err := json.Marshal(c)
return string(b), err
}

View File

@ -0,0 +1,3 @@
package res_type
type ResFieldByFloat float64

View File

@ -0,0 +1,3 @@
package res_type
type ResFieldByInteger int64

View File

@ -0,0 +1,38 @@
package res_type
import (
"database/sql/driver"
"encoding/json"
"fmt"
)
// 切片 ------------------------------------
type ResFieldByAnys []any
func (c *ResFieldByAnys) Scan(value any) error {
if value == nil {
return nil
}
switch v := value.(type) {
case []byte:
if len(v) == 0 {
return nil
}
if rune('[') != rune(v[0]) {
return nil
}
default:
}
if err := json.Unmarshal(value.([]byte), c); err != nil {
return fmt.Errorf("ResFieldByAnys json.Unmarshal Error, %s, %s", value, err)
}
return nil
}
func (c ResFieldByAnys) Value() (driver.Value, error) {
b, err := json.Marshal(c)
return string(b), err
}

View File

@ -0,0 +1,29 @@
package res_type
import (
"database/sql/driver"
"github.com/spf13/cast"
)
// Number 类型 --------------------------------
type ResFieldByNumber float64
func (this *ResFieldByNumber) Scan(value any) error {
if value == nil {
return nil
}
switch s := value.(type) {
case []byte:
*this = ResFieldByNumber(cast.ToFloat64(string(s)))
default:
*this = ResFieldByNumber(cast.ToFloat64(s))
}
return nil
}
func (this ResFieldByNumber) Value() (driver.Value, error) {
return this, nil
}

View File

@ -0,0 +1,28 @@
package res_type
import (
"database/sql/driver"
"fmt"
)
// 字符串 -------------------------------------
type ResFieldByString string
func (this *ResFieldByString) Scan(value any) error {
if value == nil {
return nil
}
switch s := value.(type) {
case []byte:
*this = ResFieldByString(s)
default:
*this = ResFieldByString(fmt.Sprintf("%v", s))
}
return nil
}
func (c ResFieldByString) Value() (driver.Value, error) {
return c, nil
}

113
resource.go Normal file
View File

@ -0,0 +1,113 @@
package contracts
import (
"reflect"
"git.fsdpf.net/go/db"
"git.fsdpf.net/go/db/schema"
)
type ResDataType string
type ResConditionType string
type ResConditionTokenType string
type ResConditionOperator string
type ResAuthDB int
const (
// 关闭权限过滤
ResAuthOff ResAuthDB = iota
// 开启权限过滤, 不包括关联资源
ResAuthOn
// 开启权限过滤, 包括关联资源
ResAuthAll
)
const (
ResDataType_String ResDataType = "string"
ResDataType_Text ResDataType = "text"
ResDataType_Integer ResDataType = "integer"
ResDataType_SmallInteger ResDataType = "smallInteger"
ResDataType_Decimal ResDataType = "decimal"
ResDataType_Boolean ResDataType = "boolean"
ResDataType_Json ResDataType = "json"
ResDataType_Enum ResDataType = "enum"
ResDataType_Timestamp ResDataType = "timestamp"
ResDataType_Date ResDataType = "date"
ResDataType_Datetime ResDataType = "dateTime"
)
type Resource interface {
GetUuid() string
GetName() string
GetCode() string
GetPrimarykey() string
GetFields() []ResField
GetField(string) (ResField, bool)
HasField(string) bool
BeginTransaction() (*db.Transaction, error)
GetDB() *db.Builder
GetTable() db.Expression
GetDBTable(params ...any) *db.Builder
GetAuthDBTable(u User, params ...any) *db.Builder
GetStruct(extends ...reflect.StructField) any
GetSliceStruct(extends ...reflect.StructField) any
WithRolesCondition(b *db.Builder, roles ...string)
GetRolesCondition(u User)
// 是否虚拟资源
IsVirtual() bool
// 是否系统资源
IsSystem() bool
}
type ResField interface {
GetName() string
GetCode() string
GetCodeResource() string
GetDataType() ResDataType
GetQueryDataType() QueryDataType
GetRawDefault(driver string) db.Expression
ToStructField(tags ...string) reflect.StructField
ToValue(any) any
ToBlueprint(table *schema.Blueprint) *schema.ColumnDefinition
}
type ResRelation interface{}
type ResJoin interface {
ResRelation
}
type ResQueryField interface {
ResField
IsExpr() bool
ToSql() db.Expression
}
type ResCondition interface {
// 是否空条件
IsEmpty() bool
// 条件是否恒成立
IsRight() bool
// to sql 表达式
ToSql() db.Expression
}
type ResConditionExpr interface {
// 条件是否恒成立
IsRight() bool
// to sql 表达式
ToSql() db.Expression
GetTokenName() string
GetTokenValue() any
GetTokenSqlValue() string
GetTokenType() ResConditionTokenType
}
// 资源
type GetResource func(code string) (Resource, bool)

10
response.go Normal file
View File

@ -0,0 +1,10 @@
package contracts
import (
"net/http"
)
type HttpResponse interface {
Get(path ...string) GlobalParams
Send(w http.ResponseWriter, r *http.Request)
}

96
routing.go Normal file
View File

@ -0,0 +1,96 @@
package contracts
import (
"net/http"
"github.com/go-chi/chi"
"github.com/gorilla/websocket"
)
type RouteCategory string
type RouteService string
type RouteCtx struct {
Name string
}
const (
RouteCategory_WS RouteCategory = "ws"
RouteCategory_FUNC RouteCategory = "func"
RouteCategory_SHOW RouteCategory = "show"
RouteCategory_QUERY RouteCategory = "query"
RouteCategory_STORE RouteCategory = "store"
RouteCategory_DESTROY RouteCategory = "destroy"
RouteCategory_STRUCTURE RouteCategory = "structure"
)
const (
RouteService_API RouteService = "api"
RouteService_FSM RouteService = "fsm"
RouteService_LIST RouteService = "list"
RouteService_XLSX RouteService = "xlsx"
RouteService_IMPORT RouteService = "import"
RouteService_PRINT RouteService = "print"
RouteService_LAYOUT RouteService = "layout"
RouteService_ECHART RouteService = "echart"
RouteService_APPROVAL RouteService = "approval"
RouteService_SELECTOR RouteService = "selector"
RouteService_LIST_DETAIL RouteService = "list-detail"
RouteService_LIST_DATA_STORE RouteService = "list-data-store"
RouteService_LIST_CONDITION_LAYOUT RouteService = "list-condition-layout"
RouteService_LIST_OPERATIONS_ACCESS RouteService = "list-operations-access"
)
func (k RouteCtx) String() string {
return k.Name
}
type Router interface {
Call(r *http.Request, code string, params map[string]any, category ...RouteCategory) (HttpResponse, error)
Get(uuid string, category ...RouteCategory) (Route, bool)
Register(cr chi.Router)
RefreshRoutes() error
}
type Route interface {
GetUuid() string
GetCode() string
GetPrimaryKey() string
GetUri() string
GetUris() []string
GetParamValues(*http.Request) GlobalParams
GetResource() Resource
GetCategory() RouteCategory
GetService() RouteService
GetRoles() []string
MakeRequest(r *http.Request, params map[string]any) (*http.Request, error)
}
type WsClientGroup string
type WsClientID uint
// type WsClient struct {
// User
// Group WsClientGroup
// Socket *websocket.Conn
// }
type WsClient interface {
User
Socket() *websocket.Conn
WsClientID() WsClientID
WsClientGroup() WsClientGroup
WsClientManage() WsClientManage
Lock()
Unlock()
}
type WsClientManage interface {
Register(WsClient) bool
Unregister(WsClient)
GetClients(func(WsClient) bool) []WsClient
}
type WsChannelManage interface {
Channel(string) WsClientManage
}

10
service.go Normal file
View File

@ -0,0 +1,10 @@
package contracts
import (
"net/http"
)
type Service interface {
Execute(*http.Request) any
ServeHTTP(http.ResponseWriter, *http.Request)
}

1
support/join.go Normal file
View File

@ -0,0 +1 @@
package support

1
support/relation.go Normal file
View File

@ -0,0 +1 @@
package support

1
support/util.go Normal file
View File

@ -0,0 +1 @@
package support

23
user.go Normal file
View File

@ -0,0 +1,23 @@
package contracts
type User interface {
// 用户ID
ID() int
// 用户UUID
Uuid() string
// 用户名称
Username() string
// 用户昵称
Nickname() string
// 用户明细
GetUserInfo() any
// 用户权限
Roles() []string
// 用户权限检查
HasUserRoles(roles ...string) bool
// 平台
Platform() string
}
// 用户
type GetUser func(uuid, platform string) (User, bool)

80
user_approval.go Normal file
View File

@ -0,0 +1,80 @@
package contracts
import (
"net/http"
"git.fsdpf.net/go/db"
)
type UserApprovalExecute int
// 审批状态
type UserApprovalStatus int
// 审批节点类型
type UserApprovalFlowType int
const (
// 驳回
UserApprovalExecute_Reject UserApprovalExecute = iota
// 通过
UserApprovalExecute_Resolve
)
const (
// 待审批
UserApprovalStatus_Accept UserApprovalStatus = iota
// 审批中
UserApprovalStatus_Pending
// 通过
UserApprovalStatus_Resolve
// 驳回
UserApprovalStatus_Reject
// 取消审批
UserApprovalStatus_Cancel
)
const (
// 角色节点
UserApprovalFlowType_Role UserApprovalFlowType = iota + 1
// 自动节点
UserApprovalFlowType_Condition
// 开始节点
UserApprovalFlowType_Begin
// 通过节点
UserApprovalFlowType_Reject
// 驳回节点
UserApprovalFlowType_Resolve
)
type UserApproval interface {
// 审批流名称
Name() string
// 发起审批请求
RequestApproval(Route, *http.Request) any
// 判断发起审批请求权限
HasUserRoles(User) bool
// 获取审批列表标记字段值
Execute(id int64, status UserApprovalExecute, r *http.Request, tx *db.Transaction) (current, next UserApprovalFlow, err error)
}
type UserApprovalFlow interface {
// 节点名称
Name() string
// 节点UUID
Uuid() string
// 节点类型
Type() UserApprovalFlowType
// 注入审批条件
InjectOrm(Orm) error
// 下一节点
Yes() string
// 下一节点
No() string
// 审批角色UUID
RoleUuid() string
// 上一节点
Parent() UserApproval
}
type GetUserApproval func(uuid string) (UserApproval, bool)