Documentation
¶
Overview ¶
Package config provides configuration loading, merging, and access via the Containable interface backed by Viper.
Configurations can be loaded from multiple sources — local files, embedded assets, environment variables, and command-line flags — and merged with deterministic precedence. Factory functions include NewFilesContainer, LoadFilesContainer, NewReaderContainer, and NewContainerFromViper.
Type-safe accessors (GetString, GetInt, GetBool, GetDuration, GetTime, etc.) are exposed through Containable. For advanced use cases, [Containable.GetViper] provides direct access to the underlying Viper instance as an intentional power-user escape hatch.
Hot-reload is supported via the Observable interface, which allows consumers to register callbacks that fire when configuration files change on disk.
Index ¶
- Variables
- func LoadEnv(fs afero.Fs, logger logger.Logger)
- type Containable
- func Load(paths []string, fs afero.Fs, logger logger.Logger, allowEmptyConfig bool) (Containable, error)
- func LoadEmbed(paths []string, assets fs.FS, logger logger.Logger) (Containable, error)
- func LoadFilesContainer(l logger.Logger, fs afero.Fs, configFiles ...string) (Containable, error)
- func LoadFilesContainerWithSchema(l logger.Logger, fs afero.Fs, schema *Schema, configFiles ...string) (Containable, error)
- type Container
- func (c *Container) AddObserver(o Observable)
- func (c *Container) AddObserverFunc(f func(Containable, chan error))
- func (c *Container) Dump(w io.Writer)
- func (c *Container) Get(key string) any
- func (c *Container) GetBool(key string) bool
- func (c *Container) GetDuration(key string) time.Duration
- func (c *Container) GetFloat(key string) float64
- func (c *Container) GetInt(key string) int
- func (c *Container) GetObservers() []Observable
- func (c *Container) GetString(key string) string
- func (c *Container) GetTime(key string) time.Time
- func (c *Container) GetViper() *viper.Viper
- func (c *Container) Has(key string) bool
- func (c *Container) IsSet(key string) bool
- func (c *Container) Set(key string, value any)
- func (c *Container) SetSchema(schema *Schema)
- func (c *Container) Sub(key string) Containable
- func (c *Container) ToJSON() string
- func (c *Container) Validate(schema *Schema) *ValidationResult
- func (c *Container) WriteConfigAs(dest string) error
- type FieldSchema
- type Observable
- type Observer
- type Schema
- type SchemaOption
- type ValidationError
- type ValidationResult
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var (
ErrNoFilesFound = errors.Newf("no configuration files found please run init, or provide a config file using the --config flag")
)
Functions ¶
Types ¶
type Containable ¶
type Containable interface {
Get(key string) any
GetBool(key string) bool
GetInt(key string) int
GetFloat(key string) float64
GetString(key string) string
GetTime(key string) time.Time
GetDuration(key string) time.Duration
// GetViper returns the underlying Viper instance for advanced operations
// not exposed by the Containable interface. This is an intentional escape
// hatch for power users who need Viper's full API (e.g., MergeConfig,
// BindPFlag, or direct access to config file watching).
//
// Prefer the typed accessor methods (GetString, GetInt, etc.) for standard
// configuration reads. Use GetViper only when the Containable interface
// does not cover your use case.
GetViper() *viper.Viper
Has(key string) bool
IsSet(key string) bool
Set(key string, value any)
WriteConfigAs(dest string) error
Sub(key string) Containable
AddObserver(o Observable)
AddObserverFunc(f func(Containable, chan error))
ToJSON() string
Dump(w io.Writer)
// Validate checks the container's current values against the provided schema.
// Returns a ValidationResult; callers should check result.Valid().
Validate(schema *Schema) *ValidationResult
}
Containable is the primary configuration interface. It provides typed accessors, observation for hot-reload, and schema validation.
func Load ¶
func Load(paths []string, fs afero.Fs, logger logger.Logger, allowEmptyConfig bool) (Containable, error)
Load reads configuration from the first available file in paths. Returns ErrNoFilesFound if no files exist and allowEmptyConfig is false.
func LoadFilesContainer ¶
LoadFilesContainer loads configuration from files and returns a Containable. It returns an error if the first file specified does not exist.
func LoadFilesContainerWithSchema ¶ added in v1.8.0
func LoadFilesContainerWithSchema(l logger.Logger, fs afero.Fs, schema *Schema, configFiles ...string) (Containable, error)
LoadFilesContainerWithSchema loads config files and validates against the schema. Returns an error wrapping all validation errors if the config is invalid.
type Container ¶
type Container struct {
ID string
// contains filtered or unexported fields
}
Container container for configuration.
func NewContainerFromViper ¶
NewContainerFromViper creates a new Container from an existing Viper instance.
func NewFilesContainer ¶
NewFilesContainer Initialise configuration container to read files from the FS.
func NewReaderContainer ¶
NewReaderContainer Initialise configuration container to read config from ioReader.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/phpboyscout/go-tool-base/pkg/config"
"github.com/phpboyscout/go-tool-base/pkg/logger"
)
func main() {
l := logger.NewNoop()
yaml := `
log:
level: debug
server:
port: 8080
`
cfg := config.NewReaderContainer(l, "yaml", strings.NewReader(yaml))
fmt.Println("Level:", cfg.GetString("log.level"))
fmt.Println("Port:", cfg.GetInt("server.port"))
}
Output: Level: debug Port: 8080
func (*Container) AddObserver ¶
func (c *Container) AddObserver(o Observable)
AddObserver attach observer to trigger on config update.
func (*Container) AddObserverFunc ¶
func (c *Container) AddObserverFunc(f func(Containable, chan error))
AddObserverFunc attach function to trigger on config update.
func (*Container) GetDuration ¶
GetDuration get duration value from config.
func (*Container) GetObservers ¶
func (c *Container) GetObservers() []Observable
GetObservers retrieve all currently attached Observers.
func (*Container) SetSchema ¶ added in v1.8.0
SetSchema attaches a validation schema to the container. When set, hot-reload will validate config changes before notifying observers.
func (*Container) Sub ¶
func (c *Container) Sub(key string) Containable
Sub returns a subtree of the parent configuration.
func (*Container) Validate ¶ added in v1.8.0
func (c *Container) Validate(schema *Schema) *ValidationResult
Validate checks the current configuration against the provided schema. Returns a ValidationResult; callers should check result.Valid().
Example ¶
package main
import (
"fmt"
"strings"
"github.com/phpboyscout/go-tool-base/pkg/config"
"github.com/phpboyscout/go-tool-base/pkg/logger"
)
func main() {
type AppConfig struct {
Log struct {
Level string `config:"log.level" enum:"debug,info,warn,error"`
}
}
l := logger.NewNoop()
cfg := config.NewReaderContainer(l, "yaml", strings.NewReader("log:\n level: verbose\n"))
schema, _ := config.NewSchema(config.WithStructSchema(AppConfig{}))
result := cfg.Validate(schema)
if !result.Valid() {
fmt.Println(result.Error())
}
}
Output:
func (*Container) WriteConfigAs ¶
WriteConfigAs writes the current configuration to the given path.
type FieldSchema ¶ added in v1.8.0
type FieldSchema struct {
// Type is the expected Go type: "string", "int", "float64", "bool", "duration".
Type string
// Required indicates the field must be present and non-zero.
Required bool
// Description is used in validation error messages.
Description string
// Default is the default value for documentation and error hints only.
// The validation layer does not inject defaults — use embedded assets for that.
Default any
// Enum restricts the field to a set of allowed values.
Enum []any
// Children defines nested fields for map/object types.
Children map[string]FieldSchema
}
FieldSchema describes a single configuration field.
type Observable ¶
type Observable interface {
Run(Containable, chan error)
}
Observable is the interface for config change observers. Implementations receive the updated config and an error channel when the config file changes.
type Observer ¶
type Observer struct {
// contains filtered or unexported fields
}
Observer is a simple Observable that wraps a handler function.
func (Observer) Run ¶
func (o Observer) Run(c Containable, errs chan error)
Run invokes the observer's handler with the updated config.
type Schema ¶ added in v1.8.0
type Schema struct {
// contains filtered or unexported fields
}
Schema defines the expected structure and constraints for configuration values.
func NewSchema ¶ added in v1.8.0
func NewSchema(opts ...SchemaOption) (*Schema, error)
NewSchema creates a Schema from the provided options.
Example ¶
package main
import (
"fmt"
"github.com/phpboyscout/go-tool-base/pkg/config"
)
func main() {
type AppConfig struct {
Server struct {
Port int `config:"server.port" default:"8080"`
Host string `config:"server.host"`
}
Log struct {
Level string `config:"log.level" enum:"debug,info,warn,error" default:"info"`
}
Github struct {
Token string `config:"github.token" validate:"required"`
}
}
schema, err := config.NewSchema(config.WithStructSchema(AppConfig{}))
if err != nil {
fmt.Println("Error:", err)
return
}
_ = schema // Use with container.Validate(schema)
}
Output:
func (*Schema) Fields ¶ added in v1.8.0
func (s *Schema) Fields() map[string]FieldSchema
Fields returns the schema field definitions.
type SchemaOption ¶ added in v1.8.0
type SchemaOption func(*schemaConfig)
SchemaOption configures schema construction.
func WithStrictMode ¶ added in v1.8.0
func WithStrictMode() SchemaOption
WithStrictMode treats unknown keys as errors instead of warnings.
func WithStructSchema ¶ added in v1.8.0
func WithStructSchema(v any) SchemaOption
WithStructSchema derives a schema from a tagged Go struct. Supported tags: `config:"key" validate:"required" enum:"a,b,c" default:"value"`.
type ValidationError ¶ added in v1.8.0
type ValidationError struct {
// Key is the dot-separated config key.
Key string
// Message is a human-readable description of the failure.
Message string
// Hint is an actionable fix suggestion.
Hint string
}
ValidationError contains details about a single validation failure.
func (ValidationError) String ¶ added in v1.8.0
func (e ValidationError) String() string
type ValidationResult ¶ added in v1.8.0
type ValidationResult struct {
Errors []ValidationError
Warnings []ValidationError
}
ValidationResult holds the outcome of schema validation.
func (*ValidationResult) Error ¶ added in v1.8.0
func (r *ValidationResult) Error() string
Error returns a formatted multi-line error string, or empty string if valid.
func (*ValidationResult) Valid ¶ added in v1.8.0
func (r *ValidationResult) Valid() bool
Valid returns true if no errors were found. Warnings do not affect validity.