Initial QSfera import
This commit is contained in:
+158
@@ -0,0 +1,158 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
"github.com/gookit/goutil/envutil"
|
||||
"github.com/gookit/goutil/reflects"
|
||||
)
|
||||
|
||||
// ValDecodeHookFunc returns a mapstructure.DecodeHookFunc
|
||||
// that parse ENV var, and more custom parse
|
||||
func ValDecodeHookFunc(parseEnv, parseTime bool) mapstructure.DecodeHookFunc {
|
||||
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||
if f.Kind() != reflect.String {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
str := data.(string)
|
||||
if parseEnv {
|
||||
// https://docs.docker.com/compose/environment-variables/env-file/
|
||||
str, err = envutil.ParseOrErr(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(str) < 2 {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
// feat: support parse time or duration string. eg: 10s
|
||||
if parseTime && str[0] > '0' && str[0] <= '9' {
|
||||
return reflects.ToTimeOrDuration(str, t)
|
||||
}
|
||||
return str, nil
|
||||
}
|
||||
}
|
||||
|
||||
// resolve format, check is alias
|
||||
func (c *Config) resolveFormat(f string) string {
|
||||
if name, ok := c.aliasMap[f]; ok {
|
||||
return name
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Deprecated methods
|
||||
*************************************************************/
|
||||
|
||||
// SetDecoder add/set a format decoder
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func SetDecoder(format string, decoder Decoder) {
|
||||
dc.SetDecoder(format, decoder)
|
||||
}
|
||||
|
||||
// SetDecoder set decoder
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetDecoder(format string, decoder Decoder) {
|
||||
format = c.resolveFormat(format)
|
||||
c.decoders[format] = decoder
|
||||
}
|
||||
|
||||
// SetDecoders set decoders
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetDecoders(decoders map[string]Decoder) {
|
||||
for format, decoder := range decoders {
|
||||
c.SetDecoder(format, decoder)
|
||||
}
|
||||
}
|
||||
|
||||
// SetEncoder set a encoder for the format
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func SetEncoder(format string, encoder Encoder) {
|
||||
dc.SetEncoder(format, encoder)
|
||||
}
|
||||
|
||||
// SetEncoder set a encoder for the format
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetEncoder(format string, encoder Encoder) {
|
||||
format = c.resolveFormat(format)
|
||||
c.encoders[format] = encoder
|
||||
}
|
||||
|
||||
// SetEncoders set encoders
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetEncoders(encoders map[string]Encoder) {
|
||||
for format, encoder := range encoders {
|
||||
c.SetEncoder(format, encoder)
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* helper methods/functions
|
||||
*************************************************************/
|
||||
|
||||
// LoadENVFiles load
|
||||
// func LoadENVFiles(filePaths ...string) error {
|
||||
// return dotenv.LoadFiles(filePaths...)
|
||||
// }
|
||||
|
||||
// GetEnv get os ENV value by name
|
||||
func GetEnv(name string, defVal ...string) (val string) {
|
||||
return Getenv(name, defVal...)
|
||||
}
|
||||
|
||||
// Getenv get os ENV value by name. like os.Getenv, but support default value
|
||||
//
|
||||
// Notice:
|
||||
// - Key is not case-sensitive when getting
|
||||
func Getenv(name string, defVal ...string) (val string) {
|
||||
if val = os.Getenv(name); val != "" {
|
||||
return
|
||||
}
|
||||
|
||||
if len(defVal) > 0 {
|
||||
val = defVal[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseVarNameAndType(key string) (string, string, string) {
|
||||
var desc string
|
||||
typ := "string"
|
||||
key = strings.Trim(key, "-")
|
||||
|
||||
// can set var type: int, uint, bool
|
||||
if strings.IndexByte(key, ':') > 0 {
|
||||
list := strings.SplitN(key, ":", 3)
|
||||
key, typ = list[0], list[1]
|
||||
if len(list) == 3 {
|
||||
desc = list[2]
|
||||
}
|
||||
|
||||
// if type is not valid and has multi words, as desc message.
|
||||
if _, ok := validTypes[typ]; !ok {
|
||||
if desc == "" && strings.ContainsRune(typ, ' ') {
|
||||
desc = typ
|
||||
}
|
||||
typ = "string"
|
||||
}
|
||||
}
|
||||
return key, typ, desc
|
||||
}
|
||||
|
||||
// format key
|
||||
func formatKey(key, sep string) string {
|
||||
return strings.Trim(strings.TrimSpace(key), sep)
|
||||
}
|
||||
Reference in New Issue
Block a user