v0.1.3 added unknown cli flag handling, dependency update
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// FILE: lixenwraith/config/config.go
|
||||
// Package config provides thread-safe configuration management for Go applications
|
||||
// with support for multiple sources: TOML files, environment variables, command-line
|
||||
// arguments, and default values with configurable precedence.
|
||||
@@ -7,6 +6,7 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
@@ -50,6 +50,9 @@ type Config struct {
|
||||
version atomic.Int64
|
||||
structCache *structCache
|
||||
|
||||
// CLI paths that matched no registered path (reset on each CLI load)
|
||||
unknownCLIKeys []string
|
||||
|
||||
// File watching support
|
||||
watcher *watcher
|
||||
configFilePath string // Track loaded file path
|
||||
@@ -249,6 +252,7 @@ func (c *Config) SetSource(source Source, path string, value any) error {
|
||||
c.envData[path] = value
|
||||
case SourceCLI:
|
||||
c.cliData[path] = value
|
||||
c.unknownCLIKeys = nil
|
||||
}
|
||||
|
||||
c.invalidateCache() // Invalidate cache after changes
|
||||
@@ -337,6 +341,13 @@ func (c *Config) AsStruct() (any, error) {
|
||||
return c.structCache.target, nil
|
||||
}
|
||||
|
||||
// UnknownCLIKeys returns CLI paths that matched no registered config path
|
||||
func (c *Config) UnknownCLIKeys() []string {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
return slices.Clone(c.unknownCLIKeys)
|
||||
}
|
||||
|
||||
// computeValue determines the current value based on precedence
|
||||
func (c *Config) computeValue(item configItem) any {
|
||||
// Check sources in precedence order
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
module github.com/lixenwraith/config
|
||||
|
||||
go 1.25.4
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
github.com/BurntSushi/toml v1.6.0
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
|
||||
@@ -435,7 +435,7 @@ func (c *Config) loadEnv(opts LoadOptions) error {
|
||||
transform = defaultEnvTransform(opts.EnvPrefix)
|
||||
}
|
||||
|
||||
// -- 1. Prepare data (Read-Lock to get paths)
|
||||
// 1. Prepare data (Read-Lock to get paths)
|
||||
c.mutex.RLock()
|
||||
paths := make([]string, 0, len(c.items))
|
||||
for p := range c.items {
|
||||
@@ -443,7 +443,7 @@ func (c *Config) loadEnv(opts LoadOptions) error {
|
||||
}
|
||||
c.mutex.RUnlock()
|
||||
|
||||
// -- 2. Process env vars (No Lock)
|
||||
// 2. Process env vars (No Lock)
|
||||
foundEnvVars := make(map[string]string)
|
||||
for _, path := range paths {
|
||||
if opts.EnvWhitelist != nil && !opts.EnvWhitelist[path] {
|
||||
@@ -506,6 +506,9 @@ func (c *Config) loadCLI(args []string) error {
|
||||
|
||||
c.cliData = flattenedCLI
|
||||
|
||||
// Reset per load; reloads must not accumulate duplicates
|
||||
c.unknownCLIKeys = c.unknownCLIKeys[:0]
|
||||
|
||||
for path, value := range flattenedCLI {
|
||||
if item, exists := c.items[path]; exists {
|
||||
if item.values == nil {
|
||||
@@ -514,6 +517,9 @@ func (c *Config) loadCLI(args []string) error {
|
||||
item.values[SourceCLI] = value
|
||||
item.currentValue = c.computeValue(item)
|
||||
c.items[path] = item
|
||||
} else {
|
||||
// Record CLI keys that match no registered path
|
||||
c.unknownCLIKeys = append(c.unknownCLIKeys, path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user