Implements conf.Load to populate tagged structs from a chain of Sources (env, .env, YAML/JSON/TOML, custom). Supports default values, slice separators, nested structs, pointer fields, and a Validator hook. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
44 lines
1 KiB
Go
44 lines
1 KiB
Go
package conf
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// flatten walks a nested map[string]any (as produced by yaml/json/toml decoders)
|
|
// and returns a flat key->string map. Keys are uppercased and joined with "_".
|
|
// Scalar values are stringified via fmt.Sprint. Slices are joined with ",".
|
|
func flatten(in map[string]any) map[string]string {
|
|
out := map[string]string{}
|
|
flattenInto(out, "", in)
|
|
return out
|
|
}
|
|
|
|
func flattenInto(out map[string]string, prefix string, in map[string]any) {
|
|
for k, v := range in {
|
|
key := strings.ToUpper(k)
|
|
if prefix != "" {
|
|
key = prefix + "_" + key
|
|
}
|
|
switch x := v.(type) {
|
|
case map[string]any:
|
|
flattenInto(out, key, x)
|
|
case map[any]any: // yaml.v3 with non-string keys
|
|
m := make(map[string]any, len(x))
|
|
for kk, vv := range x {
|
|
m[fmt.Sprint(kk)] = vv
|
|
}
|
|
flattenInto(out, key, m)
|
|
case []any:
|
|
parts := make([]string, len(x))
|
|
for i, e := range x {
|
|
parts[i] = fmt.Sprint(e)
|
|
}
|
|
out[key] = strings.Join(parts, ",")
|
|
case nil:
|
|
// skip
|
|
default:
|
|
out[key] = fmt.Sprint(x)
|
|
}
|
|
}
|
|
}
|