diff --git a/config.go b/config.go index 5079df0f..934d2038 100644 --- a/config.go +++ b/config.go @@ -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, @@ -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. diff --git a/config_test.go b/config_test.go index ad2ce652..4c37d9d1 100644 --- a/config_test.go +++ b/config_test.go @@ -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 { @@ -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 } diff --git a/option.go b/option.go index 11bd6461..2e3b8242 100644 --- a/option.go +++ b/option.go @@ -8,8 +8,8 @@ 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...) } } @@ -17,8 +17,8 @@ func WithLoader(loaders ...Loader) Option { // // 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 } } @@ -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 -} diff --git a/provider.go b/provider.go index 4faf6a4b..953368aa 100644 --- a/provider.go +++ b/provider.go @@ -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 - }) -} diff --git a/provider/env/env.go b/provider/env/env.go index 88d579b4..6220aa3a 100644 --- a/provider/env/env.go +++ b/provider/env/env.go @@ -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) { diff --git a/provider/env/option.go b/provider/env/option.go index 94549976..b838a990 100644 --- a/provider/env/option.go +++ b/provider/env/option.go @@ -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 } } @@ -18,8 +18,8 @@ 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 } } @@ -27,14 +27,3 @@ func WithDelimiter(delimiter string) Option { type Option func(*options) type options Env - -func apply(opts []Option) options { - option := &options{ - delimiter: "_", - } - for _, opt := range opts { - opt(option) - } - - return *option -} diff --git a/provider/flag/flag.go b/provider/flag/flag.go index 11f010c7..d0f0d691 100644 --- a/provider/flag/flag.go +++ b/provider/flag/flag.go @@ -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) { diff --git a/provider/flag/option.go b/provider/flag/option.go index 0c200025..d0e506c1 100644 --- a/provider/flag/option.go +++ b/provider/flag/option.go @@ -10,8 +10,8 @@ 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 } } @@ -19,8 +19,8 @@ func WithPrefix(prefix string) Option { // // 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 } } @@ -29,8 +29,8 @@ 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 } } @@ -38,14 +38,3 @@ func WithDelimiter(delimiter string) Option { type Option func(*options) type options Flag - -func apply(opts []Option) options { - option := &options{ - delimiter: ".", - } - for _, opt := range opts { - opt(option) - } - - return *option -} diff --git a/provider/pflag/option.go b/provider/pflag/option.go index 34dbdbe0..ad9237c7 100644 --- a/provider/pflag/option.go +++ b/provider/pflag/option.go @@ -10,8 +10,8 @@ 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 } } @@ -19,8 +19,8 @@ func WithPrefix(prefix string) Option { // // 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 } } @@ -29,8 +29,8 @@ 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 } } @@ -38,14 +38,3 @@ func WithDelimiter(delimiter string) Option { type Option func(*options) type options PFlag - -func apply(opts []Option) options { - option := &options{ - delimiter: ".", - } - for _, opt := range opts { - opt(option) - } - - return *option -} diff --git a/provider/pflag/pflag.go b/provider/pflag/pflag.go index bb1b614f..f629c30b 100644 --- a/provider/pflag/pflag.go +++ b/provider/pflag/pflag.go @@ -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) {