# config Typed configuration loading with [viper](https://github.com/spf13/viper) and [validator](https://github.com/go-playground/validator). ## Install ```bash go get gitea.auvem.com/go-toolkit/config ``` ## Quick start ```go type Schema struct { AppName string `mapstructure:"appName" validate:"required"` } dir, err := config.RootDir(".env.yml", 1) if err != nil { log.Fatal(err) } m := config.NewManager[Schema](".env", "yaml", dir).WithOpts(&config.ManagerOpts[Schema]{ EnvPrefix: "MYAPP", PostLoad: func(cfg *Schema) error { // derived fields — validated again after PostLoad return nil }, }) if err := m.Load(); err != nil { log.Fatal(err) } cfg := m.C() // or m.Config() _ = cfg.AppName ``` ## Load vs C - `Load()` returns errors explicitly — use in `main` during startup - `C()` and `Config()` lazy-load and panic on failure — convenient after startup ## PostLoad hooks PostLoad runs after the first validation pass. The schema is **re-validated** after PostLoad so derived fields cannot bypass constraints. ## RootDir `RootDir(name, depth)` returns `(string, error)`. `MustRootDir` panics on failure (for package-level `var` initialization). ## Breaking changes (V1) | Before | After | |--------|-------| | `PostLoad func(*Manager[T])` | `PostLoad func(*T)` | | `PreLoad func(*Manager[T])` | `PreLoad func(*T)` | | `Manager.R` field | use `C()` / hook `*T` parameter | | `RootDir(...) string` (panic) | `RootDir(...) (string, error)`; use `MustRootDir` for panic | ## Companion types Configuration structs in [dbx](https://gitea.auvem.com/go-toolkit/dbx) and [courier](https://gitea.auvem.com/go-toolkit/courier) include mapstructure/validate tags compatible with this package.