feat(env): add nestedUnderJQPath for extracting nested subtrees by jq-style paths

Introduce `nestedUnderJQPath`, enabling subtree extraction using jq-style path parsing. Add associated utility functions (`splitJQPath`, `peelRedundantPathLeaf`, `buildNestedTreeAtPath`) and test coverage. Extend `.env Codec` to support path-specific subtree merges. Update `WithFile` to accept an optional jqPath for targeted merges.
This commit is contained in:
2026-05-12 13:54:27 +01:00
parent 4beb769a2b
commit 719fccf712
5 changed files with 258 additions and 20 deletions
+36 -3
View File
@@ -17,6 +17,20 @@ type motivationConfig struct {
Database struct {
URL string `mapstructure:"url"`
} `mapstructure:"database"`
Service struct {
Database struct {
Poolsize string `json:"poolsize"`
Url string `json:"url"`
} `json:"database"`
Name string `json:"name"`
Subservice struct {
Enabled string `json:"enabled"`
Key string `json:"key"`
Name string `json:"name"`
Timeout string `json:"timeout"`
} `json:"subservice"`
} `json:"service"`
}
func TestMotivationConfig_YAMLThenEnvThenProcessEnv(t *testing.T) {
@@ -37,6 +51,7 @@ database:
HTTP_LISTEN=:9090
DATABASE_URL=postgres://dotenv
`)),
env.WithFile("fixtures/identity/service.env", ".service"),
env.WithCurrentEnvironment(),
)
@@ -49,15 +64,21 @@ DATABASE_URL=postgres://dotenv
t.Fatalf("env marshal returned nil map")
}
// convert m to json and back to map
js, err := json.MarshalIndent(m, "", " ")
if err != nil {
t.Fatalf("json marshal: %v", err)
}
m2 := make(map[string]interface{})
if err := json.Unmarshal(js, &m2); err != nil {
var roundTrip map[string]interface{}
if err := json.Unmarshal(js, &roundTrip); err != nil {
t.Fatalf("json unmarshal: %v", err)
}
svc, ok := roundTrip["service"].(map[string]interface{})
if !ok {
t.Fatalf("expected service in merged map, got %s", string(js))
}
if svc["name"] != "my-service" {
t.Fatalf("service.name=%v", svc["name"])
}
var cfg motivationConfig
if err := yamlCfg.Unmarshal(&cfg); err != nil {
@@ -76,4 +97,16 @@ DATABASE_URL=postgres://dotenv
if cfg.Database.URL != "postgres://process-env" {
t.Fatalf("Database.URL=%q", cfg.Database.URL)
}
if cfg.Service.Name != "my-service" {
t.Fatalf("Service.Name=%q", cfg.Service.Name)
}
if cfg.Service.Database.Url != "postgres://localhost:5432/db" {
t.Fatalf("Service.Database.Url=%q", cfg.Service.Database.Url)
}
if cfg.Service.Database.Poolsize != "10" {
t.Fatalf("Service.Database.Poolsize=%q", cfg.Service.Database.Poolsize)
}
if cfg.Service.Subservice.Name != "abc" {
t.Fatalf("Service.Subservice.Name=%q", cfg.Service.Subservice.Name)
}
}