Skip to content

Commit

Permalink
✨ feat: support set driver name aliases for resolve issues #139
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Jun 11, 2023
1 parent 099297b commit 15d9de4
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
- name: Run unit tests
# run: go test -v -cover ./...
# must add " for profile.cov on windows OS
run: go test -v -coverprofile="profile.cov" ./...
run: go test -coverprofile="profile.cov" ./...

- name: Send coverage
uses: shogo82148/actions-goveralls@v1
Expand Down
57 changes: 35 additions & 22 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ 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
Expand All @@ -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
Expand All @@ -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),
}
}

Expand All @@ -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
Expand All @@ -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()
Expand All @@ -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)
}
Expand All @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
9 changes: 4 additions & 5 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,6 @@ func TestGetEnv(t *testing.T) {
assert.Eq(t, "true", Getenv("APP_DEBUG"))
assert.Eq(t, "defVal", GetEnv("not-exsit", "defVal"))
})

assert.Eq(t, Yaml, fixFormat("yml"))
assert.Eq(t, Hcl, fixFormat("conf"))
assert.Eq(t, Ini, fixFormat("inc"))
}

func TestSetDecoderEncoder(t *testing.T) {
Expand Down Expand Up @@ -211,14 +207,17 @@ func TestDefault(t *testing.T) {

ClearAll()
WithOptions(ParseEnv)

is.True(GetOptions().ParseEnv)

_ = LoadStrings(JSON, `{"name": "inhere"}`)

buf := &bytes.Buffer{}
_, err := WriteTo(buf)
is.Nil(err)

// add alias
AddAlias("ini", "conf")
is.NotEmpty(Default().AliasMap())
}

func TestJSONDriver(t *testing.T) {
Expand Down
33 changes: 32 additions & 1 deletion driver.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package config

// default json driver(encoder/decoder)
import (
"encoding/json"

Expand All @@ -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)

Expand All @@ -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
}
Expand All @@ -33,9 +42,26 @@ 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 }

// Aliases format name of driver
func (d *StdDriver) Aliases() []string {
return d.aliases
}

// Decode of driver
func (d *StdDriver) Decode(blob []byte, v any) (err error) {
return d.decoder(blob, v)
Expand Down Expand Up @@ -103,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 {
Expand Down
2 changes: 1 addition & 1 deletion export.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,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
Expand Down
2 changes: 1 addition & 1 deletion hcl/hcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ var Encoder config.Encoder = func(ptr any) (out []byte, err error) {
}

// Driver instance for hcl
var Driver = config.NewDriver(config.Hcl, Decoder, Encoder)
var Driver = config.NewDriver(config.Hcl, Decoder, Encoder).WithAlias("conf")
2 changes: 1 addition & 1 deletion hclv2/hcl_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ var Encoder config.Encoder = func(ptr any) (out []byte, err error) {
}

// Driver instance for hcl
var Driver = config.NewDriver(config.Hcl, Decoder, Encoder)
var Driver = config.NewDriver(config.Hcl, Decoder, Encoder).WithAlias("conf")
18 changes: 16 additions & 2 deletions issues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ func TestIssues_59(t *testing.T) {
dump.Println(c.Data())

dumpfile := "testdata/issues59.ini"
out := fsutil.MustCreateFile(dumpfile, 0666, 0666)
out, err := fsutil.OpenTruncFile(dumpfile, 0666)
is.NoErr(err)
_, err = c.DumpTo(out, config.Ini)
is.NoErr(err)

Expand Down Expand Up @@ -309,6 +310,19 @@ func TestIssues_114(t *testing.T) {
// dump.Println(cc)
}

// https://github.com/gookit/config/issues/139
func TestIssues_139(t *testing.T) {
c := config.New("issues_139", config.ParseEnv)
c.AddDriver(ini.Driver)
c.AddAlias("ini", "conf")

err := c.LoadFiles("testdata/issues_139.conf")
assert.NoErr(t, err)

assert.Eq(t, "app", c.String("name"))
assert.Eq(t, "defValue", c.String("envKey1"))
}

// https://github.com/gookit/config/issues/141
func TestIssues_141(t *testing.T) {
type Logger struct {
Expand All @@ -323,7 +337,7 @@ func TestIssues_141(t *testing.T) {
Loggers []*Logger `default:""` // mark for parse default
}

c := config.New("issues141", config.ParseDefault)
c := config.New("issues_141", config.ParseDefault)
err := c.LoadStrings(config.JSON, `
{
"loggers": [
Expand Down
2 changes: 1 addition & 1 deletion load.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ 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]any, error) {
format = fixFormat(format)
format = c.resolveFormat(format)
decode := c.decoders[format]
if decode == nil {
return nil, errors.New("not register decoder for the format: " + format)
Expand Down
7 changes: 5 additions & 2 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ type Options struct {
// WatchChange bool
}

// OptionFn option func
type OptionFn func(*Options)

func newDefaultOption() *Options {
return &Options{
ParseKey: true,
Expand Down Expand Up @@ -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")
}
Expand Down
4 changes: 3 additions & 1 deletion read.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ func (c *Config) Exists(key string, findByPath ...bool) (ok bool) {
// Data return all config data
func Data() map[string]any { return dc.Data() }

// Data get all config data
// Data get all config data.
//
// Note: will don't apply any options, like ParseEnv
func (c *Config) Data() map[string]any {
return c.data
}
Expand Down
24 changes: 1 addition & 23 deletions testdata/config.bak.json
Original file line number Diff line number Diff line change
@@ -1,23 +1 @@
{
"age": 123,
"arr1": [
"val",
"val1",
"val2"
],
"baseKey": "value",
"debug": true,
"envKey": "${SHELL}",
"envKey1": "${NotExist|defValue}",
"invalidEnvKey": "${noClose",
"map1": {
"key": "val",
"key1": "val1",
"key2": "val2",
"key3": "${SHELL}",
"key4": "230"
},
"name": "app",
"new-key": "new-value",
"tagsStr": "php,go"
}
{"age":123,"arr1":["val","val1","val2"],"baseKey":"value","debug":true,"envKey":"${SHELL}","envKey1":"${NotExist|defValue}","invalidEnvKey":"${noClose","map1":{"key":"val","key1":"val1","key2":"val2","key3":"${SHELL}","key4":"230"},"name":"app","new-key":"new-value","tagsStr":"php,go"}
4 changes: 2 additions & 2 deletions testdata/issues59.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# exported at 2023-02-11 18:16:37
; exported at 2023-06-11 13:30:01

age = 123
baseKey = value
Expand All @@ -9,8 +9,8 @@ multiWords = hello world
name = app

[map1]
key = val
key1 = val1
key2 = val2
key = val


Loading

0 comments on commit 15d9de4

Please sign in to comment.