Bump github.com/gookit/config/v2 from 2.1.8 to 2.2.2
Bumps [github.com/gookit/config/v2](https://github.com/gookit/config) from 2.1.8 to 2.2.2. - [Release notes](https://github.com/gookit/config/releases) - [Commits](https://github.com/gookit/config/compare/v2.1.8...v2.2.2) --- updated-dependencies: - dependency-name: github.com/gookit/config/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
03045c5ccc
commit
5ebc596352
+20
-13
@@ -84,7 +84,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/gookit/config/v2"
|
||||
"github.com/gookit/config/v2/yamlv3"
|
||||
"github.com/gookit/config/v2/yaml"
|
||||
)
|
||||
|
||||
// go run ./examples/yaml.go
|
||||
@@ -92,7 +92,7 @@ func main() {
|
||||
config.WithOptions(config.ParseEnv)
|
||||
|
||||
// add driver for support yaml content
|
||||
config.AddDriver(yamlv3.Driver)
|
||||
config.AddDriver(yaml.Driver)
|
||||
|
||||
err := config.LoadFiles("testdata/yml_base.yml")
|
||||
if err != nil {
|
||||
@@ -389,7 +389,7 @@ Support parse default value by struct tag `default`
|
||||
c := config.New("test").WithOptions(config.ParseDefault)
|
||||
|
||||
// only set name
|
||||
c.SetData(map[string]interface{}{
|
||||
c.SetData(map[string]any{
|
||||
"name": "inhere",
|
||||
})
|
||||
|
||||
@@ -421,7 +421,7 @@ dump.Println(user)
|
||||
### Load Config
|
||||
|
||||
- `LoadOSEnvs(nameToKeyMap map[string]string)` Load data from os ENV
|
||||
- `LoadData(dataSource ...interface{}) (err error)` Load from struts or maps
|
||||
- `LoadData(dataSource ...any) (err error)` Load from struts or maps
|
||||
- `LoadFlags(keys []string) (err error)` Load from CLI flags
|
||||
- `LoadExists(sourceFiles ...string) (err error)`
|
||||
- `LoadFiles(sourceFiles ...string) (err error)`
|
||||
@@ -445,7 +445,7 @@ dump.Println(user)
|
||||
- `Strings(key string) (arr []string)`
|
||||
- `SubDataMap(key string) maputi.Data`
|
||||
- `StringMap(key string) (mp map[string]string)`
|
||||
- `Get(key string, findByPath ...bool) (value interface{})`
|
||||
- `Get(key string, findByPath ...bool) (value any)`
|
||||
|
||||
**Mapping data to struct:**
|
||||
|
||||
@@ -455,14 +455,14 @@ dump.Println(user)
|
||||
|
||||
### Setting Values
|
||||
|
||||
- `Set(key string, val interface{}, setByPath ...bool) (err error)`
|
||||
- `Set(key string, val any, setByPath ...bool) (err error)`
|
||||
|
||||
### Useful Methods
|
||||
|
||||
- `Getenv(name string, defVal ...string) (val string)`
|
||||
- `AddDriver(driver Driver)`
|
||||
- `Data() map[string]interface{}`
|
||||
- `SetData(data map[string]interface{})` set data to override the Config.Data
|
||||
- `Data() map[string]any`
|
||||
- `SetData(data map[string]any)` set data to override the Config.Data
|
||||
- `Exists(key string, findByPath ...bool) bool`
|
||||
- `DumpTo(out io.Writer, format string) (n int64, err error)`
|
||||
|
||||
@@ -497,11 +497,18 @@ Check out these projects, which use https://github.com/gookit/config :
|
||||
|
||||
## See also
|
||||
|
||||
- Ini parse [gookit/ini/parser](https://github.com/gookit/ini/tree/master/parser)
|
||||
- Properties parse [gookit/properties](https://github.com/gookit/properties)
|
||||
- Json5 parse [json5](https://github.com/yosuke-furukawa/json5)
|
||||
- Yaml parse [go-yaml](https://github.com/go-yaml/yaml)
|
||||
- Toml parse [go toml](https://github.com/BurntSushi/toml)
|
||||
- Ini parser [gookit/ini/parser](https://github.com/gookit/ini/tree/master/parser)
|
||||
- Properties parser [gookit/properties](https://github.com/gookit/properties)
|
||||
- Json5 parser
|
||||
- [yosuke-furukawa/json5](https://github.com/yosuke-furukawa/json5)
|
||||
- [titanous/json5](https://github.com/titanous/json5)
|
||||
- Json parser
|
||||
- [goccy/go-json](https://github.com/goccy/go-json)
|
||||
- [json-iterator/go](https://github.com/json-iterator/go)
|
||||
- Yaml parser
|
||||
- [goccy/go-yaml](https://github.com/goccy/go-yaml)
|
||||
- [go-yaml/yaml](https://github.com/go-yaml/yaml)
|
||||
- Toml parser [go toml](https://github.com/BurntSushi/toml)
|
||||
- Data merge [mergo](https://github.com/imdario/mergo)
|
||||
- Map structure [mapstructure](https://github.com/mitchellh/mapstructure)
|
||||
|
||||
|
||||
+13
-10
@@ -83,7 +83,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/gookit/config/v2"
|
||||
"github.com/gookit/config/v2/yamlv3"
|
||||
"github.com/gookit/config/v2/yaml"
|
||||
)
|
||||
|
||||
// go run ./examples/yaml.go
|
||||
@@ -92,7 +92,7 @@ func main() {
|
||||
config.WithOptions(config.ParseEnv)
|
||||
|
||||
// 添加驱动程序以支持yaml内容解析(除了JSON是默认支持,其他的则是按需使用)
|
||||
config.AddDriver(yamlv3.Driver)
|
||||
config.AddDriver(yaml.Driver)
|
||||
|
||||
// 加载配置,可以同时传入多个文件
|
||||
err := config.LoadFiles("testdata/yml_base.yml")
|
||||
@@ -371,7 +371,7 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
c := config.New("test").WithOptions(config.ParseDefault)
|
||||
|
||||
// only set name
|
||||
c.SetData(map[string]interface{}{
|
||||
c.SetData(map[string]any{
|
||||
"name": "inhere",
|
||||
})
|
||||
|
||||
@@ -402,7 +402,7 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
|
||||
### 载入配置
|
||||
|
||||
- `LoadData(dataSource ...interface{}) (err error)` 从struct或map加载数据
|
||||
- `LoadData(dataSource ...any) (err error)` 从struct或map加载数据
|
||||
- `LoadFlags(keys []string) (err error)` 从命令行参数载入数据
|
||||
- `LoadOSEnvs(nameToKeyMap map[string]string)` 从ENV载入数据
|
||||
- `LoadExists(sourceFiles ...string) (err error)` 从存在的配置文件里加载数据,会忽略不存在的文件
|
||||
@@ -427,25 +427,25 @@ NEW: 支持通过结构标签 `default` 解析并设置默认值
|
||||
- `Strings(key string) (arr []string)`
|
||||
- `StringMap(key string) (mp map[string]string)`
|
||||
- `SubDataMap(key string) maputi.Data`
|
||||
- `Get(key string, findByPath ...bool) (value interface{})`
|
||||
- `Get(key string, findByPath ...bool) (value any)`
|
||||
|
||||
**将数据映射到结构体:**
|
||||
|
||||
- `BindStruct(key string, dst interface{}) error`
|
||||
- `MapOnExists(key string, dst interface{}) error`
|
||||
- `BindStruct(key string, dst any) error`
|
||||
- `MapOnExists(key string, dst any) error`
|
||||
|
||||
### 设置值
|
||||
|
||||
- `Set(key string, val interface{}, setByPath ...bool) (err error)`
|
||||
- `Set(key string, val any, setByPath ...bool) (err error)`
|
||||
|
||||
### 有用的方法
|
||||
|
||||
- `Getenv(name string, defVal ...string) (val string)`
|
||||
- `AddDriver(driver Driver)`
|
||||
- `Data() map[string]interface{}`
|
||||
- `Data() map[string]any`
|
||||
- `Exists(key string, findByPath ...bool) bool`
|
||||
- `DumpTo(out io.Writer, format string) (n int64, err error)`
|
||||
- `SetData(data map[string]interface{})` 设置数据以覆盖 `Config.Data`
|
||||
- `SetData(data map[string]any)` 设置数据以覆盖 `Config.Data`
|
||||
|
||||
## 单元测试
|
||||
|
||||
@@ -484,6 +484,9 @@ go test -cover ./...
|
||||
- Toml 解析 [go toml](https://github.com/BurntSushi/toml)
|
||||
- 数据合并 [mergo](https://github.com/imdario/mergo)
|
||||
- 映射数据到结构体 [mapstructure](https://github.com/mitchellh/mapstructure)
|
||||
- JSON5 解析
|
||||
- [yosuke-furukawa/json5](https://github.com/yosuke-furukawa/json5)
|
||||
- [titanous/json5](https://github.com/titanous/json5)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
package config
|
||||
|
||||
// alias of interface{}
|
||||
//
|
||||
// TIP: cannot add `go:build !go1.18` in file head, that require the go.mod set `go 1.18`
|
||||
type any = interface{}
|
||||
+38
-25
@@ -90,13 +90,15 @@ type Config struct {
|
||||
loadedUrls []string
|
||||
loadedFiles []string
|
||||
driverNames []string
|
||||
reloading bool
|
||||
// driver alias to name map.
|
||||
aliasMap map[string]string
|
||||
reloading bool
|
||||
|
||||
// TODO Deprecated decoder and encoder, use driver instead
|
||||
// drivers map[string]Driver
|
||||
|
||||
// decoders["toml"] = func(blob []byte, v interface{}) (err error){}
|
||||
// decoders["yaml"] = func(blob []byte, v interface{}) (err error){}
|
||||
// decoders["toml"] = func(blob []byte, v any) (err error){}
|
||||
// decoders["yaml"] = func(blob []byte, v any) (err error){}
|
||||
decoders map[string]Decoder
|
||||
encoders map[string]Encoder
|
||||
|
||||
@@ -109,17 +111,9 @@ type Config struct {
|
||||
sMapCache map[string]strMap
|
||||
}
|
||||
|
||||
// New config instance
|
||||
func New(name string) *Config {
|
||||
return &Config{
|
||||
name: name,
|
||||
opts: newDefaultOption(),
|
||||
data: make(map[string]any),
|
||||
|
||||
// default add JSON driver
|
||||
encoders: map[string]Encoder{JSON: JSONEncoder},
|
||||
decoders: map[string]Decoder{JSON: JSONDecoder},
|
||||
}
|
||||
// New config instance, default add JSON driver
|
||||
func New(name string, opts ...OptionFn) *Config {
|
||||
return NewEmpty(name).WithDriver(JSONDriver).WithOptions(opts...)
|
||||
}
|
||||
|
||||
// NewEmpty config instance
|
||||
@@ -132,6 +126,7 @@ func NewEmpty(name string) *Config {
|
||||
// don't add any drivers
|
||||
encoders: map[string]Encoder{},
|
||||
decoders: map[string]Decoder{},
|
||||
aliasMap: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,15 +135,13 @@ func NewWith(name string, fn func(c *Config)) *Config {
|
||||
return New(name).With(fn)
|
||||
}
|
||||
|
||||
// NewWithOptions config instance
|
||||
func NewWithOptions(name string, opts ...func(opts *Options)) *Config {
|
||||
// NewWithOptions config instance. alias of New()
|
||||
func NewWithOptions(name string, opts ...OptionFn) *Config {
|
||||
return New(name).WithOptions(opts...)
|
||||
}
|
||||
|
||||
// Default get the default instance
|
||||
func Default() *Config {
|
||||
return dc
|
||||
}
|
||||
func Default() *Config { return dc }
|
||||
|
||||
/*************************************************************
|
||||
* config drivers
|
||||
@@ -171,6 +164,11 @@ func AddDriver(driver Driver) { dc.AddDriver(driver) }
|
||||
// AddDriver set a decoder and encoder driver for a format.
|
||||
func (c *Config) AddDriver(driver Driver) {
|
||||
format := driver.Name()
|
||||
if len(driver.Aliases()) > 0 {
|
||||
for _, alias := range driver.Aliases() {
|
||||
c.aliasMap[alias] = format
|
||||
}
|
||||
}
|
||||
|
||||
c.driverNames = append(c.driverNames, format)
|
||||
c.decoders[format] = driver.GetDecoder()
|
||||
@@ -179,21 +177,21 @@ func (c *Config) AddDriver(driver Driver) {
|
||||
|
||||
// HasDecoder has decoder
|
||||
func (c *Config) HasDecoder(format string) bool {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
_, ok := c.decoders[format]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HasEncoder has encoder
|
||||
func (c *Config) HasEncoder(format string) bool {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
_, ok := c.encoders[format]
|
||||
return ok
|
||||
}
|
||||
|
||||
// DelDriver delete driver of the format
|
||||
func (c *Config) DelDriver(format string) {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
delete(c.decoders, format)
|
||||
delete(c.encoders, format)
|
||||
}
|
||||
@@ -205,6 +203,21 @@ func (c *Config) DelDriver(format string) {
|
||||
// Name get config name
|
||||
func (c *Config) Name() string { return c.name }
|
||||
|
||||
// AddAlias add alias for a format(driver name)
|
||||
func AddAlias(format, alias string) { dc.AddAlias(format, alias) }
|
||||
|
||||
// AddAlias add alias for a format(driver name)
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// config.AddAlias("ini", "conf")
|
||||
func (c *Config) AddAlias(format, alias string) {
|
||||
c.aliasMap[alias] = format
|
||||
}
|
||||
|
||||
// AliasMap get alias map
|
||||
func (c *Config) AliasMap() map[string]string { return c.aliasMap }
|
||||
|
||||
// Error get last error, will clear after read.
|
||||
func (c *Config) Error() error {
|
||||
err := c.err
|
||||
@@ -237,8 +250,8 @@ func (c *Config) ClearAll() {
|
||||
c.ClearData()
|
||||
c.ClearCaches()
|
||||
|
||||
c.loadedUrls = []string{}
|
||||
c.loadedFiles = []string{}
|
||||
c.aliasMap = make(map[string]string)
|
||||
// options
|
||||
c.opts.Readonly = false
|
||||
}
|
||||
|
||||
@@ -246,7 +259,7 @@ func (c *Config) ClearAll() {
|
||||
func (c *Config) ClearData() {
|
||||
c.fireHook(OnCleanData)
|
||||
|
||||
c.data = make(map[string]interface{})
|
||||
c.data = make(map[string]any)
|
||||
c.loadedUrls = []string{}
|
||||
c.loadedFiles = []string{}
|
||||
}
|
||||
|
||||
+33
-6
@@ -1,6 +1,5 @@
|
||||
package config
|
||||
|
||||
// default json driver(encoder/decoder)
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
@@ -11,10 +10,19 @@ import (
|
||||
// TODO refactor: rename GetDecoder() to Decode(), rename GetEncoder() to Encode()
|
||||
type Driver interface {
|
||||
Name() string
|
||||
Aliases() []string // alias format names, use for resolve format name
|
||||
GetDecoder() Decoder
|
||||
GetEncoder() Encoder
|
||||
}
|
||||
|
||||
// DriverV2 interface.
|
||||
type DriverV2 interface {
|
||||
Name() string // driver name, also is format name.
|
||||
Aliases() []string // alias format names, use for resolve format name
|
||||
Decode(blob []byte, v any) (err error)
|
||||
Encode(v any) (out []byte, err error)
|
||||
}
|
||||
|
||||
// Decoder for decode yml,json,toml format content
|
||||
type Decoder func(blob []byte, v any) (err error)
|
||||
|
||||
@@ -24,6 +32,7 @@ type Encoder func(v any) (out []byte, err error)
|
||||
// StdDriver struct
|
||||
type StdDriver struct {
|
||||
name string
|
||||
aliases []string
|
||||
decoder Decoder
|
||||
encoder Encoder
|
||||
}
|
||||
@@ -33,9 +42,24 @@ func NewDriver(name string, dec Decoder, enc Encoder) *StdDriver {
|
||||
return &StdDriver{name: name, decoder: dec, encoder: enc}
|
||||
}
|
||||
|
||||
// WithAliases set aliases for driver
|
||||
func (d *StdDriver) WithAliases(aliases ...string) *StdDriver {
|
||||
d.aliases = aliases
|
||||
return d
|
||||
}
|
||||
|
||||
// WithAlias add alias for driver
|
||||
func (d *StdDriver) WithAlias(alias string) *StdDriver {
|
||||
d.aliases = append(d.aliases, alias)
|
||||
return d
|
||||
}
|
||||
|
||||
// Name of driver
|
||||
func (d *StdDriver) Name() string {
|
||||
return d.name
|
||||
func (d *StdDriver) Name() string { return d.name }
|
||||
|
||||
// Aliases format name of driver
|
||||
func (d *StdDriver) Aliases() []string {
|
||||
return d.aliases
|
||||
}
|
||||
|
||||
// Decode of driver
|
||||
@@ -59,13 +83,11 @@ func (d *StdDriver) GetEncoder() Encoder {
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* json driver
|
||||
* JSON driver
|
||||
*************************************************************/
|
||||
|
||||
var (
|
||||
// JSONAllowComments support write comments on json file.
|
||||
//
|
||||
// Deprecated: please use JSONDriver.ClearComments = true
|
||||
JSONAllowComments = true
|
||||
|
||||
// JSONMarshalIndent if not empty, will use json.MarshalIndent for encode data.
|
||||
@@ -107,6 +129,11 @@ func (d *jsonDriver) Name() string {
|
||||
return d.driverName
|
||||
}
|
||||
|
||||
// Aliases of the driver
|
||||
func (d *jsonDriver) Aliases() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decode for the driver
|
||||
func (d *jsonDriver) Decode(data []byte, v any) error {
|
||||
if d.ClearComments {
|
||||
|
||||
+8
-2
@@ -55,6 +55,9 @@ func MapOnExists(key string, dst any) error {
|
||||
}
|
||||
|
||||
// MapOnExists mapping data to the dst structure only on key exists.
|
||||
//
|
||||
// - Support ParseEnv on mapping
|
||||
// - Support ParseDefault on mapping
|
||||
func (c *Config) MapOnExists(key string, dst any) error {
|
||||
err := c.Structure(key, dst)
|
||||
if err != nil && err == ErrNotFound {
|
||||
@@ -66,12 +69,15 @@ func (c *Config) MapOnExists(key string, dst any) error {
|
||||
|
||||
// Structure get config data and binding to the dst structure.
|
||||
//
|
||||
// - Support ParseEnv on mapping
|
||||
// - Support ParseDefault on mapping
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// dbInfo := Db{}
|
||||
// config.Structure("db", &dbInfo)
|
||||
func (c *Config) Structure(key string, dst any) error {
|
||||
var data interface{}
|
||||
var data any
|
||||
// binding all data
|
||||
if key == "" {
|
||||
data = c.data
|
||||
@@ -133,7 +139,7 @@ func (c *Config) DumpTo(out io.Writer, format string) (n int64, err error) {
|
||||
var ok bool
|
||||
var encoder Encoder
|
||||
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
if encoder, ok = c.encoders[format]; !ok {
|
||||
err = errors.New("not exists/register encoder for the format: " + format)
|
||||
return
|
||||
|
||||
+28
-9
@@ -4,13 +4,15 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gookit/goutil/errorx"
|
||||
"github.com/gookit/goutil/fsutil"
|
||||
"github.com/imdario/mergo"
|
||||
)
|
||||
@@ -42,6 +44,10 @@ func LoadExists(sourceFiles ...string) error { return dc.LoadExists(sourceFiles.
|
||||
// LoadExists load and parse config files, but will ignore not exists file.
|
||||
func (c *Config) LoadExists(sourceFiles ...string) (err error) {
|
||||
for _, file := range sourceFiles {
|
||||
if file == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = c.loadFile(file, true, ""); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -72,7 +78,7 @@ func (c *Config) LoadRemote(format, url string) (err error) {
|
||||
}
|
||||
|
||||
// read response content
|
||||
bts, err := ioutil.ReadAll(resp.Body)
|
||||
bts, err := io.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
if err = c.parseSourceCode(format, bts); err != nil {
|
||||
return
|
||||
@@ -191,15 +197,21 @@ func LoadData(dataSource ...any) error { return dc.LoadData(dataSource...) }
|
||||
//
|
||||
// The dataSources can be:
|
||||
// - map[string]any
|
||||
// - map[string]string
|
||||
func (c *Config) LoadData(dataSources ...any) (err error) {
|
||||
if c.opts.Delimiter == 0 {
|
||||
c.opts.Delimiter = defaultDelimiter
|
||||
}
|
||||
|
||||
for _, ds := range dataSources {
|
||||
if smp, ok := ds.(map[string]string); ok {
|
||||
c.LoadSMap(smp)
|
||||
continue
|
||||
}
|
||||
|
||||
err = mergo.Merge(&c.data, ds, mergo.WithOverride)
|
||||
if err != nil {
|
||||
return
|
||||
return errorx.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +219,14 @@ func (c *Config) LoadData(dataSources ...any) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// LoadSMap to config
|
||||
func (c *Config) LoadSMap(smp map[string]string) {
|
||||
for k, v := range smp {
|
||||
c.data[k] = v
|
||||
}
|
||||
c.fireHook(OnLoadData)
|
||||
}
|
||||
|
||||
// LoadSources load one or multi byte data
|
||||
func LoadSources(format string, src []byte, more ...[]byte) error {
|
||||
return dc.LoadSources(format, src, more...)
|
||||
@@ -314,9 +334,8 @@ func (c *Config) LoadFromDir(dirPath, format string) (err error) {
|
||||
extName := "." + format
|
||||
extLen := len(extName)
|
||||
|
||||
return fsutil.FindInDir(dirPath, func(fPath string, fi os.FileInfo) error {
|
||||
baseName := fi.Name()
|
||||
|
||||
return fsutil.FindInDir(dirPath, func(fPath string, ent fs.DirEntry) error {
|
||||
baseName := ent.Name()
|
||||
if strings.HasSuffix(baseName, extName) {
|
||||
data, err := c.parseSourceToMap(format, fsutil.MustReadFile(fPath))
|
||||
if err != nil {
|
||||
@@ -386,7 +405,7 @@ func (c *Config) loadFile(file string, loadExist bool, format string) (err error
|
||||
defer fd.Close()
|
||||
|
||||
// read file content
|
||||
bts, err := ioutil.ReadAll(fd)
|
||||
bts, err := io.ReadAll(fd)
|
||||
if err == nil {
|
||||
// get format for file ext
|
||||
if format == "" {
|
||||
@@ -431,8 +450,8 @@ func (c *Config) loadDataMap(data map[string]any) (err error) {
|
||||
}
|
||||
|
||||
// parse config source code to Config.
|
||||
func (c *Config) parseSourceToMap(format string, blob []byte) (map[string]interface{}, error) {
|
||||
format = fixFormat(format)
|
||||
func (c *Config) parseSourceToMap(format string, blob []byte) (map[string]any, error) {
|
||||
format = c.resolveFormat(format)
|
||||
decode := c.decoders[format]
|
||||
if decode == nil {
|
||||
return nil, errors.New("not register decoder for the format: " + format)
|
||||
|
||||
+5
-2
@@ -50,6 +50,9 @@ type Options struct {
|
||||
// WatchChange bool
|
||||
}
|
||||
|
||||
// OptionFn option func
|
||||
type OptionFn func(*Options)
|
||||
|
||||
func newDefaultOption() *Options {
|
||||
return &Options{
|
||||
ParseKey: true,
|
||||
@@ -159,10 +162,10 @@ func WithHookFunc(fn HookFunc) func(*Options) {
|
||||
func EnableCache(opts *Options) { opts.EnableCache = true }
|
||||
|
||||
// WithOptions with options
|
||||
func WithOptions(opts ...func(*Options)) { dc.WithOptions(opts...) }
|
||||
func WithOptions(opts ...OptionFn) { dc.WithOptions(opts...) }
|
||||
|
||||
// WithOptions apply some options
|
||||
func (c *Config) WithOptions(opts ...func(opts *Options)) *Config {
|
||||
func (c *Config) WithOptions(opts ...OptionFn) *Config {
|
||||
if !c.IsEmpty() {
|
||||
panic("config: Cannot set options after data has been loaded")
|
||||
}
|
||||
|
||||
+49
-9
@@ -90,32 +90,46 @@ func (c *Config) Exists(key string, findByPath ...bool) (ok bool) {
|
||||
*************************************************************/
|
||||
|
||||
// Data return all config data
|
||||
func Data() map[string]interface{} { return dc.Data() }
|
||||
func Data() map[string]any { return dc.Data() }
|
||||
|
||||
// Data get all config data
|
||||
func (c *Config) Data() map[string]interface{} {
|
||||
// Data get all config data.
|
||||
//
|
||||
// Note: will don't apply any options, like ParseEnv
|
||||
func (c *Config) Data() map[string]any {
|
||||
return c.data
|
||||
}
|
||||
|
||||
// Keys return all config data
|
||||
func Keys() []string { return dc.Keys() }
|
||||
|
||||
// Keys get all config data
|
||||
func (c *Config) Keys() []string {
|
||||
keys := make([]string, 0, len(c.data))
|
||||
for key := range c.data {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// Get config value by key string, support get sub-value by key path(eg. 'map.key'),
|
||||
//
|
||||
// - ok is true, find value from config
|
||||
// - ok is false, not found or error
|
||||
func Get(key string, findByPath ...bool) interface{} { return dc.Get(key, findByPath...) }
|
||||
func Get(key string, findByPath ...bool) any { return dc.Get(key, findByPath...) }
|
||||
|
||||
// Get config value by key
|
||||
func (c *Config) Get(key string, findByPath ...bool) interface{} {
|
||||
func (c *Config) Get(key string, findByPath ...bool) any {
|
||||
val, _ := c.GetValue(key, findByPath...)
|
||||
return val
|
||||
}
|
||||
|
||||
// GetValue get value by given key string.
|
||||
func GetValue(key string, findByPath ...bool) (interface{}, bool) {
|
||||
func GetValue(key string, findByPath ...bool) (any, bool) {
|
||||
return dc.GetValue(key, findByPath...)
|
||||
}
|
||||
|
||||
// GetValue get value by given key string.
|
||||
func (c *Config) GetValue(key string, findByPath ...bool) (value interface{}, ok bool) {
|
||||
func (c *Config) GetValue(key string, findByPath ...bool) (value any, ok bool) {
|
||||
sep := c.opts.Delimiter
|
||||
if key = formatKey(key, string(sep)); key == "" {
|
||||
c.addError(ErrKeyIsEmpty)
|
||||
@@ -235,6 +249,18 @@ func (c *Config) String(key string, defVal ...string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
// MustString get a string by key, will panic on empty or not exists
|
||||
func MustString(key string) string { return dc.MustString(key) }
|
||||
|
||||
// MustString get a string by key, will panic on empty or not exists
|
||||
func (c *Config) MustString(key string) string {
|
||||
value, ok := c.getString(key)
|
||||
if !ok {
|
||||
panic("config: string value not found, key: " + key)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (c *Config) getString(key string) (value string, ok bool) {
|
||||
// find from cache
|
||||
if c.opts.EnableCache && len(c.strCache) > 0 {
|
||||
@@ -257,8 +283,11 @@ func (c *Config) getString(key string) (value string, ok bool) {
|
||||
value = envutil.ParseEnvValue(value)
|
||||
}
|
||||
default:
|
||||
// value = fmt.Sprintf("%v", val)
|
||||
value, _ = strutil.AnyToString(val, false)
|
||||
var err error
|
||||
value, err = strutil.AnyToString(val, false)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
// add cache
|
||||
@@ -520,6 +549,17 @@ func (c *Config) Strings(key string) (arr []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// StringsBySplit get []string by split a string value.
|
||||
func StringsBySplit(key, sep string) []string { return dc.StringsBySplit(key, sep) }
|
||||
|
||||
// StringsBySplit get []string by split a string value.
|
||||
func (c *Config) StringsBySplit(key, sep string) (ss []string) {
|
||||
if str, ok := c.getString(key); ok {
|
||||
ss = strutil.Split(str, sep)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StringMap get config data as a map[string]string
|
||||
func StringMap(key string) map[string]string { return dc.StringMap(key) }
|
||||
|
||||
|
||||
+14
-23
@@ -13,12 +13,15 @@ import (
|
||||
// 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 interface{}) (interface{}, error) {
|
||||
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
|
||||
if f.Kind() != reflect.String {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
str := data.(string)
|
||||
if parseEnv {
|
||||
str = envutil.ParseEnvValue(str)
|
||||
}
|
||||
if len(str) < 2 {
|
||||
return str, nil
|
||||
}
|
||||
@@ -32,14 +35,19 @@ func ValDecodeHookFunc(parseEnv, parseTime bool) mapstructure.DecodeHookFunc {
|
||||
return dur, nil
|
||||
}
|
||||
}
|
||||
} else if parseEnv { // parse ENV value
|
||||
str = envutil.ParseEnvValue(str)
|
||||
}
|
||||
|
||||
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
|
||||
*************************************************************/
|
||||
@@ -55,7 +63,7 @@ func SetDecoder(format string, decoder Decoder) {
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetDecoder(format string, decoder Decoder) {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
c.decoders[format] = decoder
|
||||
}
|
||||
|
||||
@@ -79,7 +87,7 @@ func SetEncoder(format string, encoder Encoder) {
|
||||
//
|
||||
// Deprecated: please use driver instead
|
||||
func (c *Config) SetEncoder(format string, encoder Encoder) {
|
||||
format = fixFormat(format)
|
||||
format = c.resolveFormat(format)
|
||||
c.encoders[format] = encoder
|
||||
}
|
||||
|
||||
@@ -141,20 +149,3 @@ func parseVarNameAndType(key string) (string, string) {
|
||||
func formatKey(key, sep string) string {
|
||||
return strings.Trim(strings.TrimSpace(key), sep)
|
||||
}
|
||||
|
||||
// resolve fix inc/conf/yaml format
|
||||
func fixFormat(f string) string {
|
||||
if f == Yml {
|
||||
f = Yaml
|
||||
}
|
||||
|
||||
if f == "inc" {
|
||||
f = Ini
|
||||
}
|
||||
|
||||
// eg nginx config file.
|
||||
if f == "conf" {
|
||||
f = Hcl
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
+2
-4
@@ -5,10 +5,9 @@ Usage please see example:
|
||||
*/
|
||||
package yaml
|
||||
|
||||
// see https://pkg.go.dev/gopkg.in/yaml.v2
|
||||
import (
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/gookit/config/v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Decoder the yaml content decoder
|
||||
@@ -18,5 +17,4 @@ var Decoder config.Decoder = yaml.Unmarshal
|
||||
var Encoder config.Encoder = yaml.Marshal
|
||||
|
||||
// Driver for yaml
|
||||
// TIP: recommended use the yamlv3.Driver
|
||||
var Driver = config.NewDriver(config.Yaml, Decoder, Encoder)
|
||||
var Driver = config.NewDriver(config.Yaml, Decoder, Encoder).WithAliases(config.Yml)
|
||||
|
||||
Reference in New Issue
Block a user