Skip to content

Commit

Permalink
inline apply (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktong authored Nov 14, 2023
1 parent e4eb38c commit eb5d538
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 112 deletions.
26 changes: 14 additions & 12 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,28 @@ type Unmarshaler interface {

// New returns a Config with the given Option(s).
func New(opts ...Option) (Config, error) {
option := apply(opts)
config := option.Config
config.values = &provider{values: make(map[string]any)}
config.providers = make([]*provider, 0, len(option.loaders))
config.onChanges = &onChanges{onChanges: make(map[string][]func(Unmarshaler))}
option := &options{
Config: Config{
delimiter: ".",
},
}
for _, opt := range opts {
opt(option)
}
option.values = &provider{values: make(map[string]any)}
option.providers = make([]*provider, 0, len(option.loaders))
option.onChanges = &onChanges{onChanges: make(map[string][]func(Unmarshaler))}

for _, loader := range option.loaders {
if loader == nil {
continue
}

if configAware, ok := loader.(ConfigAware); ok {
configAware.WithConfig(config)
}

values, err := loader.Load()
if err != nil {
return Config{}, fmt.Errorf("[konf] load configuration: %w", err)
}
maps.Merge(config.values.values, values)
maps.Merge(option.values.values, values)
slog.Info(
"Configuration has been loaded.",
"loader", loader,
Expand All @@ -61,10 +63,10 @@ func New(opts ...Option) (Config, error) {
if w, ok := loader.(Watcher); ok {
provider.watcher = w
}
config.providers = append(config.providers, provider)
option.providers = append(option.providers, provider)
}

return config, nil
return option.Config, nil
}

// Watch watches and updates configuration when it changes.
Expand Down
19 changes: 0 additions & 19 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,6 @@ func TestConfig_Unmarshal(t *testing.T) {
assert.Equal(t, "", cfg)
},
},
{
description: "configer",
opts: []konf.Option{
konf.WithLoader(mapLoader{}),
},
assert: func(config konf.Config) {
var configured bool
assert.NoError(t, config.Unmarshal("configured", &configured))
assert.True(t, configured)
},
},
}

for i := range testcases {
Expand All @@ -139,14 +128,6 @@ func TestConfig_Unmarshal(t *testing.T) {

type mapLoader map[string]any

func (m mapLoader) WithConfig(
interface {
Unmarshal(path string, target any) error
},
) {
m["configured"] = true
}

func (m mapLoader) Load() (map[string]any, error) {
return m, nil
}
Expand Down
21 changes: 4 additions & 17 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ package konf
// Each loader takes precedence over the loaders before it
// while multiple loaders are specified.
func WithLoader(loaders ...Loader) Option {
return func(config *options) {
config.loaders = append(config.loaders, loaders...)
return func(options *options) {
options.loaders = append(options.loaders, loaders...)
}
}

// WithDelimiter provides the delimiter when specifying config path.
//
// The default delimiter is `.`, which makes config path like `parent.child.key`.
func WithDelimiter(delimiter string) Option {
return func(config *options) {
config.delimiter = delimiter
return func(options *options) {
options.delimiter = delimiter
}
}

Expand All @@ -30,16 +30,3 @@ type options struct {

loaders []Loader
}

func apply(opts []Option) options {
option := &options{
Config: Config{
delimiter: ".",
},
}
for _, opt := range opts {
opt(option)
}

return *option
}
10 changes: 0 additions & 10 deletions provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,3 @@ type Loader interface {
type Watcher interface {
Watch(ctx context.Context, onChange func(map[string]any)) error
}

// ConfigAware is the interface that wraps the WithConfig method.
//
// WithConfig enables provider uses configuration loaded by providers before it.
// It ensures the WithConfig is called before executing methods in Loader and Watcher.
type ConfigAware interface {
WithConfig(config interface {
Unmarshal(path string, target any) error
})
}
9 changes: 8 additions & 1 deletion provider/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ type Env struct {

// New returns an Env with the given Option(s).
func New(opts ...Option) Env {
return Env(apply(opts))
option := &options{
delimiter: "_",
}
for _, opt := range opts {
opt(option)
}

return Env(*option)
}

func (e Env) Load() (map[string]any, error) {
Expand Down
19 changes: 4 additions & 15 deletions provider/env/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ package env
// E.g. if the given prefix is "server", it only loads environment variables
// which name starts with "server".
func WithPrefix(prefix string) Option {
return func(env *options) {
env.prefix = prefix
return func(options *options) {
options.prefix = prefix
}
}

Expand All @@ -18,23 +18,12 @@ func WithPrefix(prefix string) Option {
// The default delimiter is `_`, which loads the environment variable `PARENT_CHILD_KEY="1"`
// as `{PARENT: {CHILD: {KEY: "1"}}}`.
func WithDelimiter(delimiter string) Option {
return func(env *options) {
env.delimiter = delimiter
return func(options *options) {
options.delimiter = delimiter
}
}

// Option configures the given Env.
type Option func(*options)

type options Env

func apply(opts []Option) options {
option := &options{
delimiter: "_",
}
for _, opt := range opts {
opt(option)
}

return *option
}
9 changes: 7 additions & 2 deletions provider/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ type Flag struct {

// New returns a Flag with the given Option(s).
func New(opts ...Option) Flag {
option := apply(opts)
option := &options{
delimiter: ".",
}
for _, opt := range opts {
opt(option)
}
if option.set == nil {
flag.Parse()
option.set = flag.CommandLine
}

return Flag(option)
return Flag(*option)
}

func (f Flag) Load() (map[string]any, error) {
Expand Down
23 changes: 6 additions & 17 deletions provider/flag/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import "flag"
// E.g. if the given prefix is "server", it only loads flags
// which name starts with "server".
func WithPrefix(prefix string) Option {
return func(flag *options) {
flag.prefix = prefix
return func(options *options) {
options.prefix = prefix
}
}

// WithFlagSet provides the [flag.FlagSet] that loads configuration from.
//
// The default flag set is [flag.CommandLine].
func WithFlagSet(set *flag.FlagSet) Option {
return func(flag *options) {
flag.set = set
return func(options *options) {
options.set = set
}
}

Expand All @@ -29,23 +29,12 @@ func WithFlagSet(set *flag.FlagSet) Option {
// The default delimiter is `_`, which loads the flag `parent.child.key` with value 1
// as `{parent: {child: {key: 1}}}`.
func WithDelimiter(delimiter string) Option {
return func(flag *options) {
flag.delimiter = delimiter
return func(options *options) {
options.delimiter = delimiter
}
}

// Option configures the give Flag.
type Option func(*options)

type options Flag

func apply(opts []Option) options {
option := &options{
delimiter: ".",
}
for _, opt := range opts {
opt(option)
}

return *option
}
23 changes: 6 additions & 17 deletions provider/pflag/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import "github.com/spf13/pflag"
// E.g. if the given prefix is "server", it only loads flags
// which name starts with "server".
func WithPrefix(prefix string) Option {
return func(pflag *options) {
pflag.prefix = prefix
return func(options *options) {
options.prefix = prefix
}
}

// WithFlagSet provides the [pflag.FlagSet] that loads configuration from.
//
// The default flag set is [pflag.CommandLine] plus [flag.CommandLine].
func WithFlagSet(set *pflag.FlagSet) Option {
return func(pflag *options) {
pflag.set = set
return func(options *options) {
options.set = set
}
}

Expand All @@ -29,23 +29,12 @@ func WithFlagSet(set *pflag.FlagSet) Option {
// The default delimiter is `_`, which loads the flag `parent.child.key` with value 1
// as `{parent: {child: {key: 1}}}`.
func WithDelimiter(delimiter string) Option {
return func(pflag *options) {
pflag.delimiter = delimiter
return func(options *options) {
options.delimiter = delimiter
}
}

// Option configures the give PFlag.
type Option func(*options)

type options PFlag

func apply(opts []Option) options {
option := &options{
delimiter: ".",
}
for _, opt := range opts {
opt(option)
}

return *option
}
9 changes: 7 additions & 2 deletions provider/pflag/pflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ type PFlag struct {

// New returns a PFlag with the given Option(s).
func New(opts ...Option) PFlag {
option := apply(opts)
option := &options{
delimiter: ".",
}
for _, opt := range opts {
opt(option)
}
if option.set == nil {
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
option.set = pflag.CommandLine
}

return PFlag(option)
return PFlag(*option)
}

func (f PFlag) Load() (map[string]any, error) {
Expand Down

0 comments on commit eb5d538

Please sign in to comment.