141 lines
3.9 KiB
Markdown
141 lines
3.9 KiB
Markdown
---
|
|
title: config
|
|
description: Layered configuration management for the Core framework with file, environment, and in-memory resolution.
|
|
---
|
|
|
|
# config
|
|
|
|
`forge.lthn.ai/core/config` provides layered configuration management for applications built on the Core framework. It resolves values through a priority chain -- defaults, file, environment variables, and explicit `Set()` calls -- so that the same codebase works identically across local development, CI, and production without code changes.
|
|
|
|
## Module Path
|
|
|
|
```
|
|
forge.lthn.ai/core/config
|
|
```
|
|
|
|
Requires **Go 1.26+**.
|
|
|
|
## Quick Start
|
|
|
|
### Standalone usage
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
config "forge.lthn.ai/core/config"
|
|
)
|
|
|
|
func main() {
|
|
cfg, err := config.New() // loads ~/.core/config.yaml if it exists
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Write a value and persist it
|
|
_ = cfg.Set("dev.editor", "vim")
|
|
_ = cfg.Commit()
|
|
|
|
// Read it back
|
|
var editor string
|
|
_ = cfg.Get("dev.editor", &editor)
|
|
fmt.Println(editor) // "vim"
|
|
}
|
|
```
|
|
|
|
### As a Core framework service
|
|
|
|
```go
|
|
import (
|
|
config "forge.lthn.ai/core/config"
|
|
"forge.lthn.ai/core/go/pkg/core"
|
|
)
|
|
|
|
app, _ := core.New(
|
|
core.WithService(config.NewConfigService),
|
|
)
|
|
// The config service loads automatically during OnStartup.
|
|
// Retrieve it later via core.ServiceFor[*config.Service](app).
|
|
```
|
|
|
|
## Package Layout
|
|
|
|
| File | Purpose |
|
|
|-----------------|----------------------------------------------------------------|
|
|
| `config.go` | Core `Config` struct -- layered Get/Set, file load, commit |
|
|
| `env.go` | Environment variable iteration and prefix-based loading |
|
|
| `service.go` | Framework service wrapper with lifecycle (`Startable`) support |
|
|
| `config_test.go`| Tests following the `_Good` / `_Bad` / `_Ugly` convention |
|
|
|
|
## Dependencies
|
|
|
|
| Module | Role |
|
|
|-----------------------------------|-----------------------------------------|
|
|
| `forge.lthn.ai/core/go` | Core framework (`core.Config` interface, `ServiceRuntime`) |
|
|
| `forge.lthn.ai/core/go-io` | Storage abstraction (`Medium` for reading/writing files) |
|
|
| `forge.lthn.ai/core/go-log` | Contextual error helper (`E()`) |
|
|
| `github.com/spf13/viper` | Underlying configuration engine |
|
|
| `gopkg.in/yaml.v3` | YAML serialisation for `Commit()` |
|
|
|
|
## Configuration Priority
|
|
|
|
Values are resolved in ascending priority order:
|
|
|
|
1. **Defaults** -- hardcoded fallbacks (via `Set()` before any file load)
|
|
2. **File** -- YAML loaded from `~/.core/config.yaml` (or a custom path)
|
|
3. **Environment variables** -- prefixed with `CORE_CONFIG_` by default
|
|
4. **Explicit Set()** -- in-memory overrides applied at runtime
|
|
|
|
Environment variables always override file values. An explicit `Set()` call overrides everything.
|
|
|
|
## Key Access
|
|
|
|
All keys use **dot notation** for nested values:
|
|
|
|
```go
|
|
cfg.Set("a.b.c", "deep")
|
|
|
|
var val string
|
|
cfg.Get("a.b.c", &val) // "deep"
|
|
```
|
|
|
|
This maps to YAML structure:
|
|
|
|
```yaml
|
|
a:
|
|
b:
|
|
c: deep
|
|
```
|
|
|
|
## Environment Variable Mapping
|
|
|
|
Environment variables are mapped to dot-notation keys by:
|
|
|
|
1. Stripping the prefix (default `CORE_CONFIG_`)
|
|
2. Lowercasing
|
|
3. Replacing `_` with `.`
|
|
|
|
For example, `CORE_CONFIG_DEV_EDITOR=nano` resolves to key `dev.editor` with value `"nano"`.
|
|
|
|
You can change the prefix with `WithEnvPrefix`:
|
|
|
|
```go
|
|
cfg, _ := config.New(config.WithEnvPrefix("MYAPP"))
|
|
// MYAPP_SETTING=secret -> key "setting"
|
|
```
|
|
|
|
## Persisting Changes
|
|
|
|
`Set()` only writes to memory. Call `Commit()` to flush changes to disk:
|
|
|
|
```go
|
|
cfg.Set("dev.editor", "vim")
|
|
cfg.Commit() // writes to ~/.core/config.yaml
|
|
```
|
|
|
|
`Commit()` only persists values that were loaded from the file or explicitly set via `Set()`. Environment variable values are never leaked into the config file.
|
|
|
|
## Licence
|
|
|
|
EUPL-1.2
|