confii

package module
v0.0.0-...-3ac352a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: MIT Imports: 25 Imported by: 0

README

Confii Logo

Complete configuration management for Go.
Load, merge, validate, resolve secrets, track sources, detect drift — from any source.

Go Reference CI Coverage Go Report Card OpenSSF Scorecard License


Table of Contents


Why Confii?

Go has several configuration libraries, but none provides a complete configuration management solution. Most handle loading and reading — Confii handles the full lifecycle.

Capability Confii Viper Koanf Others
File formats (YAML/JSON/TOML/INI/.env) All 5 All 5 4 Partial
Cloud sources (S3, SSM, Azure, GCS, IBM, Git) All 6 etcd/Consul S3, etcd Limited
Secret stores (Vault, AWS, Azure, GCP) All 4 + env No Vault Limited
Per-path merge strategies (6 strategies) Yes No Global only No
Config composition (_include/_defaults) Yes No No No
Type-safe generics (Config[T]) Yes No No No
${secret:key} placeholder resolution Yes No No No
Source tracking / introspection Yes No No No
Config diff / drift detection Yes No No No
Versioning with rollback Yes No No No
Observability (metrics, events) Yes No No No
Hook/middleware system (4 types) Yes No No No
File watching + incremental reload Yes Yes Yes Partial
JSON Schema validation Yes No No No
CLI tool (10 commands) Yes No No No
Thread-safe (RWMutex) Yes No Partial Varies
What Confii solves that others don't

1. The multi-source merge problem. Viper's deep merge has known limitations with slices and nested maps. Confii provides 6 merge strategies with per-path overrides — so database can use replace while features uses append in the same merge.

2. Secret management as a first-class concern. Confii natively resolves ${secret:db/password} placeholders from AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, and HashiCorp Vault (with 9 auth methods) — with caching, TTL, and a pluggable store interface.

3. Environment-aware configuration. Confii natively understands default + production/staging/development sections and merges them automatically — no separate files per environment needed.

4. Type safety with Go generics. Config[AppConfig] gives you cfg.Typed() returning *AppConfig with struct tag validation and full IDE autocomplete.

5. Configuration lifecycle management. Diff two configs, detect drift from a baseline, snapshot versions and rollback, track access metrics, emit events on change — features that matter in production but don't exist elsewhere.

6. Full introspection. Explain("database.host") tells you the value, where it came from, how many times it was overridden, and the full history. Layers() shows the source stack. GenerateDocs("markdown") produces a reference table.


Installation

go get github.com/confiify/confii-go

Cloud providers are opt-in via build tags:

go build -tags aws          # S3, SSM, Secrets Manager
go build -tags azure        # Blob Storage, Key Vault
go build -tags gcp          # Cloud Storage, Secret Manager
go build -tags vault        # HashiCorp Vault
go build -tags ibm          # IBM Cloud Object Storage
go build -tags "aws,azure,gcp,vault,ibm"  # all

Quick Start

cfg, err := confii.New[any](context.Background(),
    confii.WithLoaders(
        loader.NewYAML("config.yaml"),
        loader.NewEnvironment("APP"),
    ),
    confii.WithEnv("production"),
)

host, _ := cfg.Get("database.host")
port := cfg.GetIntOr("database.port", 5432)
debug := cfg.GetBoolOr("debug", false)

Full example: examples/basic/


Configuring Confii

Before diving into features, it's important to understand the three ways to configure a Confii instance and what options are available. This determines how your config is loaded, merged, validated, and accessed.

Creating a Config Instance

There are three ways to create a Config[T] instance, listed from simplest to most flexible:

1. Self-configuration file (zero-code defaults) — Confii auto-discovers a .confii.yaml (or .json/.toml) file and applies settings before any code runs. This is the best place for project-wide defaults that every developer shares.

# .confii.yaml — auto-discovered from CWD or ~/.config/confii/
default_environment: development
env_prefix: APP
deep_merge: true
use_env_expander: true
validate_on_load: false
default_files:
  - config/base.yaml
  - config/dev.yaml

Settings apply with 3-tier priority: explicit code argument > self-config file > built-in default. Search order: CWD (confii.*, .confii.*), then ~/.config/confii/.

Full example: examples/self-config/

2. Constructor with options — Pass With* option functions directly:

cfg, err := confii.New[AppConfig](ctx,
    confii.WithLoaders(loader.NewYAML("config.yaml")),
    confii.WithEnv("production"),
    confii.WithDeepMerge(true),
    confii.WithValidateOnLoad(true),
)

3. Builder pattern — Fluent API with chained methods, useful when config construction is conditional or spans multiple steps:

cfg, err := confii.NewBuilder[AppConfig]().
    WithEnv("production").
    AddLoader(loader.NewYAML("base.yaml")).
    AddLoader(loader.NewYAML("prod.yaml")).
    EnableDeepMerge().
    EnableFreezeOnLoad().
    Build(ctx)

Full example: examples/builder/

Available options:

Option Purpose Default
WithLoaders(loaders...) Set configuration sources none
WithEnv(name) Set active environment (e.g. "production") ""
WithEnvSwitcher(envVar) Read environment name from OS variable none
WithEnvPrefix(prefix) Auto-add an EnvironmentLoader with this prefix none
WithDeepMerge(bool) Enable recursive merge of nested maps true
WithMergeStrategyOption(strategy) Default merge strategy Merge
WithMergeStrategyMap(map) Per-path merge strategy overrides none
WithValidateOnLoad(bool) Validate struct tags after loading false
WithStrictValidation(bool) Treat validation warnings as errors false
WithSchema(schema) / WithSchemaPath(path) JSON Schema for validation none
WithEnvExpander(bool) Enable ${VAR} expansion in values false
WithTypeCasting(bool) Auto-convert strings to bool/int/float false
WithSysenvFallback(bool) Fall back to OS env vars on missing keys false
WithDynamicReloading(bool) Enable fsnotify file watching false
WithFreezeOnLoad(bool) Make config immutable after load false
WithDebugMode(bool) Enable full source tracking false
WithOnError(policy) ErrorPolicyRaise, Warn, or Ignore Raise
WithLogger(logger) Custom *slog.Logger default

Configuration Sources

Confii loads from files, environment variables, HTTP, and cloud storage — all through a unified Loader interface. Later loaders override earlier ones with deep merge enabled by default.

Source Constructor Build Tag
YAML loader.NewYAML(path) -
JSON loader.NewJSON(path) -
TOML loader.NewTOML(path) -
INI loader.NewINI(path) -
.env loader.NewEnvFile(path) -
Environment vars loader.NewEnvironment(prefix) -
HTTP/HTTPS loader.NewHTTP(url, opts...) -
AWS S3 cloud.NewS3(url, opts...) aws
AWS SSM cloud.NewSSM(prefix) aws
Azure Blob cloud.NewAzureBlob(container, blob) azure
GCS cloud.NewGCS(bucket, object) gcp
IBM COS cloud.NewIBMCOS(...) ibm
Git repo cloud.NewGit(repo, path, opts...) -

Full example: examples/multi-source/ | examples/cloud/


Configuration Composition

Hydra-style _include and _defaults directives let you split config across files with cycle detection (max depth 10):

_defaults:
  - "timeout: 30"
  - cache: redis

_include:
  - shared/logging.yaml
  - shared/database.yaml

app:
  name: my-service

Included files are resolved relative to the source file's directory. Directive keys (_include, _defaults, _merge_strategy) are removed from the final output.

Full example: examples/composition/


Environment Resolution

Config files with default + environment-specific sections are automatically merged:

default:
  database:
    host: localhost
    port: 5432

production:
  database:
    host: prod-db.example.com
cfg, _ := confii.New[any](ctx,
    confii.WithLoaders(loader.NewYAML("config.yaml")),
    confii.WithEnv("production"),         // explicit
    // confii.WithEnvSwitcher("APP_ENV"), // or from OS variable
)
// database.host = "prod-db.example.com" (production)
// database.port = 5432                  (inherited from default)

Full example: examples/environment/


Merge Strategies

Six strategies with per-path overrides — different sections can merge differently:

Strategy Behavior
Replace Overwrites entirely
Merge Recursive deep merge
Append Appends list items
Prepend Prepends list items
Intersection Keeps only common keys
Union Keeps all keys, merges common ones
confii.WithMergeStrategyMap(map[string]confii.MergeStrategy{
    "database": confii.StrategyReplace,
    "features": confii.StrategyAppend,
})

Full example: examples/merge-strategies/


Working with Values

Once a Config[T] instance is created and loaded, here's how you access, transform, validate, and resolve values.

Accessing Values

Untyped access with dot-notation key paths:

val, err := cfg.Get("database.host")           // (any, error)
val := cfg.GetOr("database.host", "localhost")  // with default
val := cfg.MustGet("database.host")             // panics on error (for tests)

Typed getters with defaults:

cfg.GetString("app.name")                   // (string, error)
cfg.GetStringOr("app.name", "default")      // with fallback
cfg.GetInt("database.port")                  // (int, error)
cfg.GetIntOr("database.port", 5432)
cfg.GetBool("debug")                         // (bool, error)
cfg.GetBoolOr("debug", false)
cfg.GetFloat64("threshold")                  // (float64, error)

Typed struct access with Go generics:

cfg, err := confii.New[AppConfig](ctx,
    confii.WithLoaders(loader.NewYAML("config.yaml")),
    confii.WithValidateOnLoad(true),
)

model, _ := cfg.Typed()              // *AppConfig — IDE autocomplete works
fmt.Println(model.Database.Host)

Other access methods:

cfg.Has("database.host")    // bool — key existence
cfg.Keys()                  // []string — all leaf keys
cfg.Keys("database")        // []string — keys under prefix
cfg.ToDict()                // map[string]any — raw map
cfg.Set("key", "value")     // set a value

Full example: examples/basic/ | examples/typed/


Hooks & Transformation

Hooks transform values at access time. Four types, evaluated in order: key → value → condition → global.

Hook Type Fires When
Key hook Key exactly matches a registered path
Value hook Value exactly matches a registered value
Condition hook Custom condition function returns true
Global hook Every value access
hp := cfg.HookProcessor()

// Key hook: uppercase a specific key's value
hp.RegisterKeyHook("app.name", func(key string, value any) any {
    return strings.ToUpper(value.(string))
})

// Global hook: mask passwords
hp.RegisterGlobalHook(func(key string, value any) any {
    if strings.Contains(key, "password") { return "****" }
    return value
})

Built-in hooks (enabled via options):

  • WithEnvExpander(true) — replaces ${VAR} with OS environment variables
  • WithTypeCasting(true) — converts strings to bool/int/float automatically

Full example: examples/hooks/


Validation

Struct tags — validate on load using go-playground/validator:

type Config struct {
    Host string `mapstructure:"host" validate:"required,hostname"`
    Port int    `mapstructure:"port" validate:"required,min=1,max=65535"`
}

cfg, err := confii.New[Config](ctx,
    confii.WithLoaders(loader.NewYAML("config.yaml")),
    confii.WithValidateOnLoad(true),
    confii.WithStrictValidation(true),  // treat warnings as errors
)
// Returns error at construction time if validation fails

JSON Schema — validate against a schema file:

v, _ := validate.NewJSONSchemaValidatorFromFile("schema.json")
err := v.Validate(cfg.ToDict())

Full example: examples/validation/


Secret Management

Secrets are resolved via the hook system — register a secret resolver as a global hook, and ${secret:key} placeholders in config values are automatically replaced.

store := secret.NewDictStore(map[string]any{"db/password": "s3cret"})
resolver := secret.NewResolver(store,
    secret.WithCache(true),
    secret.WithCacheTTL(5 * time.Minute),
)

cfg.HookProcessor().RegisterGlobalHook(resolver.Hook())
// ${secret:db/password} in values → "s3cret"

Placeholder formats: ${secret:key}, ${secret:key:json_path}, ${secret:key:json_path:version}

Cloud secret stores (build-tag gated):

Store Constructor Build Tag
AWS Secrets Manager cloud.NewAWSSecretsManager(ctx, opts...) aws
HashiCorp Vault cloud.NewHashiCorpVault(opts...) vault
Azure Key Vault cloud.NewAzureKeyVault(url, cred) azure
GCP Secret Manager cloud.NewGCPSecretManager(ctx, project) gcp

Vault supports 9 auth methods: Token, AppRole, LDAP, JWT, Kubernetes, AWS IAM, Azure, GCP, and OIDC.

Multi-store fallback — try stores in priority order:

multi := secret.NewMultiStore([]confii.SecretStore{awsStore, vaultStore, envStore})

Full example: examples/secrets/ | examples/cloud/


Runtime & Operations

Once your config is loaded and values are flowing, these features help you manage it in a running application.

Lifecycle Management

// Reload from sources
cfg.Reload(ctx)
cfg.Reload(ctx, confii.WithIncremental(true))  // only changed files (mtime + SHA256)
cfg.Reload(ctx, confii.WithDryRun(true))        // validate without applying
cfg.Reload(ctx, confii.WithReloadValidate(true)) // override validate-on-load

// Extend at runtime — add a new source without reloading everything
cfg.Extend(ctx, loader.NewJSON("extra.json"))

// Temporary override (scoped) — useful for tests
restore, _ := cfg.Override(map[string]any{"database.host": "test-db"})
defer restore()

// Set values (respects frozen state)
cfg.Set("key", "value")
cfg.Set("key", "value", confii.WithOverride(false))  // errors if key exists

// Freeze — make config immutable
cfg.Freeze()
cfg.Set("key", "val")  // returns ErrConfigFrozen

// Change callbacks — react to value changes
cfg.OnChange(func(key string, old, new any) {
    log.Printf("changed: %s = %v → %v", key, old, new)
})

Full example: examples/lifecycle/


Dynamic Reloading

File watching via fsnotify. Config automatically reloads when source files change on disk:

cfg, _ := confii.New[any](ctx,
    confii.WithLoaders(loader.NewYAML("config.yaml")),
    confii.WithDynamicReloading(true),
)
// Config auto-reloads when files change

cfg.OnChange(func(key string, old, new any) { /* react */ })
cfg.StopWatching() // stop when done

Full example: examples/dynamic-reload/


Observability

Track access patterns, react to events:

cfg.EnableObservability()
emitter := cfg.EnableEvents()

emitter.On("reload", func(args ...any) { log.Println("reloaded") })
emitter.On("change", func(args ...any) { log.Println("changed") })

stats := cfg.GetMetrics()
// total_keys, accessed_keys, access_rate, reload_count, change_count, top_accessed_keys

Full example: examples/observability/


Debugging & Auditing

For troubleshooting config issues, auditing changes, and understanding where values came from.

Introspection & Source Tracking

Know exactly where every value came from and how it got there:

cfg.Explain("database.host")              // value, source, override count, full history
cfg.Schema("database.port")               // type info for a key
cfg.Layers()                              // source stack (which files, in what order)

cfg.GetSourceInfo("database.host")        // SourceInfo struct
cfg.GetOverrideHistory("database.host")   // []OverrideEntry — full override chain
cfg.GetConflicts()                        // all keys that were overridden
cfg.GetSourceStatistics()                 // aggregated stats per source
cfg.FindKeysFromSource("config.yaml")     // which keys came from this file

cfg.PrintDebugInfo("database.host")       // human-readable report
cfg.ExportDebugReport("report.json")      // full JSON export

Enable WithDebugMode(true) for complete override history tracking.

Full example: examples/introspection/


Diff & Drift Detection

Compare two configs or detect unintended changes against an intended baseline:

diffs := cfg1.Diff(cfg2)                   // compare two Config instances
drifts := cfg.DetectDrift(intendedConfig)   // detect unintended changes
summary := diff.Summary(diffs)              // {total: 3, added: 1, removed: 1, modified: 1}
jsonStr, _ := diff.ToJSON(diffs)            // serialize for reporting

Full example: examples/diff/


Versioning & Rollback

Snapshot config state, compare versions over time, and rollback:

vm := cfg.EnableVersioning("/tmp/config-versions", 100)

v1, _ := cfg.SaveVersion(map[string]any{"author": "deploy-bot", "env": "prod"})
// ... config changes ...
v2, _ := cfg.SaveVersion(nil)

diffs, _ := vm.DiffVersions(v1.VersionID, v2.VersionID)
versions := vm.ListVersions()   // all snapshots, newest first
cfg.RollbackToVersion(v1.VersionID)

Full example: examples/versioning/


Output

Export

jsonData, _ := cfg.Export("json")
yamlData, _ := cfg.Export("yaml")
tomlData, _ := cfg.Export("toml")
cfg.Export("json", "/path/to/output.json")  // to file

Full example: examples/export/

Documentation Generation

Generate a reference document from the current config:

markdown, _ := cfg.GenerateDocs("markdown")
jsonDocs, _ := cfg.GenerateDocs("json")

CLI Tool

go install github.com/confiify/confii-go/cmd/confii@latest
Command Description
confii load Load and display configuration
confii get Retrieve a single value
confii export Export to a different format
confii validate Validate against JSON Schema
confii diff Compare two configs or environments
confii debug Debug source tracking for a key
confii explain Detailed resolution info for a key
confii lint Lint config for issues
confii docs Generate documentation
confii migrate Migrate from other config formats
confii load production -l yaml:config.yaml
confii get production database.host -l yaml:config.yaml
confii export production -l yaml:config.yaml -f json -o config.json
confii validate production -l yaml:config.yaml --schema schema.json
confii diff dev production --loader1 yaml:c.yaml --loader2 yaml:c.yaml
confii explain production -l yaml:config.yaml --key database.host
confii lint production -l yaml:config.yaml --strict
confii docs production -l yaml:config.yaml -f markdown -o DOCS.md
confii migrate dotenv .env -o config.yaml

Examples

All examples are runnable and located in the examples/ directory:

Getting Started
Example Description
basic Load a YAML file, access values with dot notation
typed Type-safe Config[T] with struct validation
builder Fluent builder pattern
self-config .confii.yaml auto-discovery
Loading & Merging
Example Description
multi-source Multiple loaders + environment variables
environment Environment-aware config (default + production)
merge-strategies Per-path merge strategies
composition _include and _defaults directives
cloud Cloud loaders and secret stores
Processing & Validation
Example Description
hooks Key, value, condition, and global hooks
validation Struct tags + JSON Schema validation
secrets Secret resolution with ${secret:key}
Runtime & Debugging
Example Description
lifecycle Reload, freeze, override, change callbacks
dynamic-reload File watching with fsnotify
introspection Explain, Layers, source tracking, debug
observability Metrics and event emission
versioning Snapshot, compare, and rollback
diff Diff configs and detect drift
export Export to JSON/YAML/TOML + doc generation
cd examples/basic && go run .

Package Structure

github.com/confiify/confii-go/
  ├── config.go              # Config[T] — core type with all access/lifecycle methods
  ├── builder.go             # Fluent builder API
  ├── errors.go              # Sentinel errors + ConfigError
  ├── loader/                # File & env loaders (YAML, JSON, TOML, INI, .env, HTTP)
  │   └── cloud/             # Cloud loaders (S3, SSM, Azure Blob, GCS, IBM COS, Git)
  ├── secret/                # Secret stores (env, dict, multi) + resolver
  │   └── cloud/             # Cloud secret stores (AWS, Azure, GCP, Vault)
  ├── merge/                 # Merge strategies (default + advanced with per-path overrides)
  ├── compose/               # Configuration composition (_include, _defaults)
  ├── envhandler/            # Environment resolution (default + env sections)
  ├── hook/                  # Hook processor (4 types: key, value, condition, global)
  ├── validate/              # Struct tag + JSON Schema validation
  ├── observe/               # Metrics, events, versioning with rollback
  ├── diff/                  # Diff + drift detection
  ├── sourcetrack/           # Per-key source tracking, override history
  ├── watch/                 # File watching (fsnotify)
  ├── export/                # JSON, YAML, TOML exporters
  ├── selfconfig/            # Self-configuration reader (.confii.yaml)
  ├── internal/              # Internal utilities (dictutil, typecoerce, formatparse)
  ├── integration/           # End-to-end integration tests
  ├── examples/              # Runnable examples
  └── cmd/confii/            # CLI tool (10 commands)

Requirements

  • Go 1.25+ (due to cloud provider dependencies; core library uses Go 1.21 features)

License

MIT

Documentation

Overview

Package confii is a complete configuration management library for Go. It loads, merges, validates, and manages configuration from YAML, JSON, TOML, INI, .env files, environment variables, HTTP endpoints, and cloud stores (AWS S3, SSM, Azure Blob, GCS, IBM COS, Git repositories) — with deep merging, secret resolution, source tracking, and type-safe generics.

confii goes beyond configuration loading — it manages the full lifecycle: loading, merging with 6 per-path strategies, validating with struct tags and JSON Schema, resolving ${secret:key} placeholders from AWS Secrets Manager / Azure Key Vault / GCP Secret Manager / HashiCorp Vault (9 auth methods), tracking where every value came from, detecting config drift, versioning with rollback, and emitting observability metrics — all with zero global state and full thread safety via sync.RWMutex.

Key features:

  • Type-safe generics: Config[T] with cfg.Typed() returning *T
  • 6 merge strategies (replace, merge, append, prepend, intersection, union) with per-path overrides
  • ${secret:key} placeholder resolution with caching, TTL, and multi-store fallback
  • Hydra-style config composition via _include and _defaults directives
  • Environment resolution: automatic default + production/staging merging
  • 4-type hook system (key, value, condition, global) for value transformation
  • Full introspection: Explain(), Layers(), source tracking, override history
  • Config diff, drift detection, versioning with rollback
  • File watching with incremental reload (mtime + SHA256)
  • Documentation generation (markdown, JSON)
  • 10-command CLI tool
  • Self-configuration via .confii.yaml auto-discovery

Quick start:

cfg, err := confii.New[any](context.Background(),
    confii.WithLoaders(
        loader.NewYAML("config.yaml"),
        loader.NewEnvironment("APP"),
    ),
    confii.WithEnv("production"),
)
if err != nil {
    log.Fatal(err)
}

host, _ := cfg.Get("database.host")
port := cfg.GetIntOr("database.port", 5432)

Type-safe access with generics:

cfg, err := confii.New[AppConfig](ctx,
    confii.WithLoaders(loader.NewYAML("config.yaml")),
    confii.WithValidateOnLoad(true),
)
model, _ := cfg.Typed()
fmt.Println(model.Database.Host) // IDE autocomplete works

Builder pattern:

cfg, err := confii.NewBuilder[AppConfig]().
    WithEnv("production").
    AddLoader(loader.NewYAML("base.yaml")).
    AddLoader(loader.NewYAML("prod.yaml")).
    EnableFreezeOnLoad().
    Build(ctx)

Secret resolution:

store := secret.NewDictStore(map[string]any{"db/password": "s3cret"})
resolver := secret.NewResolver(store, secret.WithCache(true))
cfg.HookProcessor().RegisterGlobalHook(resolver.Hook())
// ${secret:db/password} in config values resolves automatically

Cloud providers are opt-in via build tags: aws, azure, gcp, vault, ibm.

For full documentation, examples, and the CLI tool, see https://github.com/confiify/confii-go

Index

Constants

View Source
const (
	// StrategyReplace discards the base map entirely and keeps only the overlay.
	StrategyReplace = merge.Replace

	// StrategyMerge recursively deep-merges the overlay into the base map,
	// preserving base keys that do not appear in the overlay.
	StrategyMerge = merge.DeepMergeStrategy

	// StrategyAppend appends overlay slice elements after the base slice elements.
	StrategyAppend = merge.Append

	// StrategyPrepend inserts overlay slice elements before the base slice elements.
	StrategyPrepend = merge.Prepend

	// StrategyIntersection keeps only keys that exist in both the base and the overlay.
	StrategyIntersection = merge.Intersection

	// StrategyUnion keeps all keys from both the base and the overlay,
	// with overlay values taking precedence on conflicts.
	StrategyUnion = merge.Union
)

Variables

View Source
var (
	ErrConfigLoad       = errors.New("config load error")
	ErrConfigFormat     = errors.New("config format error")
	ErrConfigValidation = errors.New("config validation error")
	ErrConfigNotFound   = errors.New("config key not found")
	ErrConfigMerge      = errors.New("config merge conflict")
	ErrConfigFrozen     = errors.New("config is frozen")
	ErrConfigAccess     = errors.New("config access error")
	ErrSecretNotFound   = errors.New("secret not found")
	ErrSecretAccess     = errors.New("secret access error")
	ErrSecretStore      = errors.New("secret store error")
	ErrSecretValidation = errors.New("secret validation error")
	ErrVaultAuth        = errors.New("vault authentication error")
)

Sentinel errors for use with errors.Is.

Functions

func NewFormatError

func NewFormatError(source, formatType string, err error) error

NewFormatError creates a config format/parse error.

func NewFrozenError

func NewFrozenError(op string) error

NewFrozenError creates an error for operations on frozen config.

func NewLoadError

func NewLoadError(source string, err error) error

NewLoadError creates a config load error.

func NewNotFoundError

func NewNotFoundError(key string, availableKeys []string) error

NewNotFoundError creates a key-not-found error with available keys.

func NewValidationError

func NewValidationError(errs []string, original error) error

NewValidationError creates a config validation error.

Types

type Builder

type Builder[T any] struct {
	// contains filtered or unexported fields
}

Builder provides a fluent API for constructing Config instances. Call NewBuilder to obtain a Builder, chain configuration methods, and finish with Builder.Build to produce a ready-to-use Config.

func NewBuilder

func NewBuilder[T any]() *Builder[T]

NewBuilder creates a new ConfigBuilder.

func (*Builder[T]) AddLoader

func (b *Builder[T]) AddLoader(l Loader) *Builder[T]

AddLoader adds a single loader.

func (*Builder[T]) AddLoaders

func (b *Builder[T]) AddLoaders(loaders ...Loader) *Builder[T]

AddLoaders adds multiple loaders.

func (*Builder[T]) Build

func (b *Builder[T]) Build(ctx context.Context) (*Config[T], error)

Build creates the Config instance.

func (*Builder[T]) DisableDeepMerge

func (b *Builder[T]) DisableDeepMerge() *Builder[T]

DisableDeepMerge disables deep merging (shallow merge).

func (*Builder[T]) DisableDynamicReloading

func (b *Builder[T]) DisableDynamicReloading() *Builder[T]

DisableDynamicReloading disables file watching.

func (*Builder[T]) DisableEnvExpander

func (b *Builder[T]) DisableEnvExpander() *Builder[T]

DisableEnvExpander disables ${VAR} expansion.

func (*Builder[T]) DisableTypeCasting

func (b *Builder[T]) DisableTypeCasting() *Builder[T]

DisableTypeCasting disables automatic type casting.

func (*Builder[T]) EnableDebug

func (b *Builder[T]) EnableDebug() *Builder[T]

EnableDebug enables debug/source tracking mode.

func (*Builder[T]) EnableDeepMerge

func (b *Builder[T]) EnableDeepMerge() *Builder[T]

EnableDeepMerge enables deep merging.

func (*Builder[T]) EnableDynamicReloading

func (b *Builder[T]) EnableDynamicReloading() *Builder[T]

EnableDynamicReloading enables file watching.

func (*Builder[T]) EnableEnvExpander

func (b *Builder[T]) EnableEnvExpander() *Builder[T]

EnableEnvExpander enables ${VAR} expansion.

func (*Builder[T]) EnableFreezeOnLoad

func (b *Builder[T]) EnableFreezeOnLoad() *Builder[T]

EnableFreezeOnLoad freezes config after loading.

func (*Builder[T]) EnableTypeCasting

func (b *Builder[T]) EnableTypeCasting() *Builder[T]

EnableTypeCasting enables automatic type casting.

func (*Builder[T]) WithEnv

func (b *Builder[T]) WithEnv(env string) *Builder[T]

WithEnv sets the active environment.

func (*Builder[T]) WithSchemaValidation

func (b *Builder[T]) WithSchemaValidation(schema any, strict bool) *Builder[T]

WithSchemaValidation sets the validation schema and enables validate-on-load.

type Config

type Config[T any] struct {
	// contains filtered or unexported fields
}

Config is the central configuration manager. It loads, merges, validates, and serves configuration values from multiple sources (files, environment variables, remote stores). The type parameter T defines the strongly-typed model returned by [Config.Model]. All public methods are safe for concurrent use.

func New

func New[T any](ctx context.Context, cfgOpts ...Option) (*Config[T], error)

New creates a new Config instance, loading and merging all sources.

Initialization follows the priority: explicit argument > self-config file > built-in default.

func (*Config[T]) DetectDrift

func (c *Config[T]) DetectDrift(intended map[string]any) []diff.ConfigDiff

DetectDrift compares this config against an intended baseline.

func (*Config[T]) Diff

func (c *Config[T]) Diff(other *Config[T]) []diff.ConfigDiff

Diff compares this config with another config.

func (*Config[T]) EnableEvents

func (c *Config[T]) EnableEvents() *observe.EventEmitter

EnableEvents enables event emission.

func (*Config[T]) EnableObservability

func (c *Config[T]) EnableObservability() *observe.Metrics

EnableObservability enables access/reload/change metrics collection.

func (*Config[T]) EnableVersioning

func (c *Config[T]) EnableVersioning(storagePath string, maxVersions int) *observe.VersionManager

EnableVersioning enables config versioning with snapshot persistence.

func (*Config[T]) Env

func (c *Config[T]) Env() string

Env returns the active environment name.

func (*Config[T]) Explain

func (c *Config[T]) Explain(keyPath string) map[string]any

Explain returns detailed resolution information for a key.

func (*Config[T]) Export

func (c *Config[T]) Export(format string, outputPath ...string) ([]byte, error)

Export serializes the config to the given format ("json", "yaml", "toml"). If outputPath is provided, also writes to that file.

func (*Config[T]) ExportDebugReport

func (c *Config[T]) ExportDebugReport(outputPath string) error

ExportDebugReport writes a full debug report as JSON.

func (*Config[T]) Extend

func (c *Config[T]) Extend(ctx context.Context, l Loader) error

Extend adds an additional loader at runtime and merges its config.

func (*Config[T]) FindKeysFromSource

func (c *Config[T]) FindKeysFromSource(pattern string) []string

FindKeysFromSource returns keys from sources matching the pattern.

func (*Config[T]) Freeze

func (c *Config[T]) Freeze()

Freeze makes the config immutable.

func (*Config[T]) GenerateDocs

func (c *Config[T]) GenerateDocs(format string) (string, error)

GenerateDocs generates configuration documentation in the given format ("markdown" or "json").

func (*Config[T]) Get

func (c *Config[T]) Get(keyPath string) (any, error)

Get retrieves a value by dot-separated key path. Hooks are applied to leaf values.

func (*Config[T]) GetBool

func (c *Config[T]) GetBool(keyPath string) (bool, error)

GetBool retrieves a bool value by key path.

func (*Config[T]) GetBoolOr

func (c *Config[T]) GetBoolOr(keyPath string, defaultVal bool) bool

GetBoolOr retrieves a bool value, returning the default if not found.

func (*Config[T]) GetConflicts

func (c *Config[T]) GetConflicts() map[string]*sourcetrack.SourceInfo

GetConflicts returns all keys that have been overridden.

func (*Config[T]) GetFloat64

func (c *Config[T]) GetFloat64(keyPath string) (float64, error)

GetFloat64 retrieves a float64 value by key path.

func (*Config[T]) GetInt

func (c *Config[T]) GetInt(keyPath string) (int, error)

GetInt retrieves an int value by key path.

func (*Config[T]) GetIntOr

func (c *Config[T]) GetIntOr(keyPath string, defaultVal int) int

GetIntOr retrieves an int value, returning the default if not found.

func (*Config[T]) GetMetrics

func (c *Config[T]) GetMetrics() map[string]any

GetMetrics returns current observability metrics. Returns nil if not enabled.

func (*Config[T]) GetOr

func (c *Config[T]) GetOr(keyPath string, defaultVal any) any

GetOr retrieves a value by key path, returning the default if not found.

func (*Config[T]) GetOverrideHistory

func (c *Config[T]) GetOverrideHistory(keyPath string) []sourcetrack.OverrideEntry

GetOverrideHistory returns the override history for a key.

func (*Config[T]) GetSourceInfo

func (c *Config[T]) GetSourceInfo(keyPath string) *sourcetrack.SourceInfo

GetSourceInfo returns source tracking info for a key.

func (*Config[T]) GetSourceStatistics

func (c *Config[T]) GetSourceStatistics() map[string]any

GetSourceStatistics returns aggregated source statistics.

func (*Config[T]) GetString

func (c *Config[T]) GetString(keyPath string) (string, error)

GetString retrieves a string value by key path.

func (*Config[T]) GetStringOr

func (c *Config[T]) GetStringOr(keyPath, defaultVal string) string

GetStringOr retrieves a string value, returning the default if not found.

func (*Config[T]) Has

func (c *Config[T]) Has(keyPath string) bool

Has checks if a key exists in the configuration.

func (*Config[T]) HookProcessor

func (c *Config[T]) HookProcessor() *hook.Processor

HookProcessor returns the hook processor for registering custom hooks.

func (*Config[T]) IsFrozen

func (c *Config[T]) IsFrozen() bool

IsFrozen returns whether the config is frozen.

func (*Config[T]) Keys

func (c *Config[T]) Keys(prefix ...string) []string

Keys returns all dot-separated leaf key paths.

func (*Config[T]) Layers

func (c *Config[T]) Layers() []map[string]any

Layers returns the layer stack showing each source and its keys.

func (*Config[T]) MustGet

func (c *Config[T]) MustGet(keyPath string) any

MustGet retrieves a value and panics on error. Intended for tests.

func (*Config[T]) OnChange

func (c *Config[T]) OnChange(fn func(key string, oldVal, newVal any))

OnChange registers a callback that fires when configuration values change after reload.

func (*Config[T]) Override

func (c *Config[T]) Override(overrides map[string]any) (restore func(), err error)

Override temporarily overrides configuration values. Returns a restore function that must be called (typically via defer) to revert.

func (*Config[T]) PrintDebugInfo

func (c *Config[T]) PrintDebugInfo(keyPath string) string

PrintDebugInfo returns formatted debug info for a key (or all keys if empty).

func (*Config[T]) Reload

func (c *Config[T]) Reload(ctx context.Context, opts ...ReloadOption) error

Reload reloads all configurations from their sources.

func (*Config[T]) RollbackToVersion

func (c *Config[T]) RollbackToVersion(versionID string) error

RollbackToVersion restores the config to a previous version snapshot.

func (*Config[T]) SaveVersion

func (c *Config[T]) SaveVersion(metadata map[string]any) (*observe.Version, error)

SaveVersion saves the current config as an immutable version snapshot.

func (*Config[T]) Schema

func (c *Config[T]) Schema(keyPath string) map[string]any

Schema returns schema information for a key.

func (*Config[T]) Set

func (c *Config[T]) Set(keyPath string, value any, opts ...SetOption) error

Set sets a value by dot-separated key path. Thread-safe, respects frozen state. Pass WithOverride(false) to raise an error if the key already exists.

func (*Config[T]) SourceTracker

func (c *Config[T]) SourceTracker() *sourcetrack.Tracker

SourceTracker returns the source tracker for advanced inspection.

func (*Config[T]) StopWatching

func (c *Config[T]) StopWatching()

StopWatching stops the file watcher if running.

func (*Config[T]) String

func (c *Config[T]) String() string

String returns a human-readable summary of the Config, including its environment, key count, loader sources, and frozen state.

func (*Config[T]) ToDict

func (c *Config[T]) ToDict() map[string]any

ToDict returns the effective configuration as a plain map.

func (*Config[T]) Typed

func (c *Config[T]) Typed() (*T, error)

Typed decodes the configuration into a typed struct T and validates it.

type ConfigError

type ConfigError struct {
	Op      string // operation that failed (e.g., "Load", "Get", "Set")
	Source  string // source identifier (e.g., file path, URL)
	Key     string // config key involved, if applicable
	Err     error  // underlying error (wraps a sentinel)
	Context map[string]any
}

ConfigError is a structured error that captures the failing operation, the source and key involved, and an underlying sentinel error. Use errors.Is or errors.As to inspect the chain.

func (*ConfigError) Error

func (e *ConfigError) Error() string

func (*ConfigError) Unwrap

func (e *ConfigError) Unwrap() error

type ErrorPolicy

type ErrorPolicy string

ErrorPolicy defines how errors are handled during loading.

const (
	ErrorPolicyRaise  ErrorPolicy = "raise"
	ErrorPolicyWarn   ErrorPolicy = "warn"
	ErrorPolicyIgnore ErrorPolicy = "ignore"
)

type Exporter

type Exporter interface {
	// Export serializes the configuration data.
	Export(data map[string]any) ([]byte, error)
	// Format returns the format name (e.g., "json", "yaml", "toml").
	Format() string
}

Exporter serializes configuration to a specific format.

type Hook

type Hook = hook.Func

Hook is a function that transforms a configuration value during access. Hooks are executed in registration order and may modify, enrich, or replace the value before it is returned to the caller.

type HookCondition

type HookCondition = hook.Condition

HookCondition is a predicate that determines whether a conditional hook should fire for a given key and value. Returning true causes the associated Hook to execute; returning false skips it.

type Loader

type Loader interface {
	// Load reads configuration and returns it as a map.
	Load(ctx context.Context) (map[string]any, error)

	// Source returns a human-readable identifier for this loader
	// (e.g., file path, URL, "environment:APP").
	Source() string
}

Loader loads configuration from a source. Implementations should return (nil, nil) when the source does not exist (graceful absence) and (nil, error) on actual failures.

type MergeStrategy

type MergeStrategy = merge.Strategy

MergeStrategy identifies the algorithm used when two configuration maps are combined during a load or reload operation.

type Merger

type Merger = merge.Merger

Merger is a function that combines a base configuration map with an overlay map, producing a merged result according to a MergeStrategy.

type Option

type Option func(*options)

Option configures a Config instance.

func WithDebugMode

func WithDebugMode(v bool) Option

WithDebugMode enables detailed source tracking.

func WithDeepMerge

func WithDeepMerge(v bool) Option

WithDeepMerge enables or disables deep merging of nested maps.

func WithDynamicReloading

func WithDynamicReloading(v bool) Option

WithDynamicReloading enables file watching for automatic reload on change.

func WithEnv

func WithEnv(env string) Option

WithEnv sets the active environment name (e.g., "production").

func WithEnvExpander

func WithEnvExpander(v bool) Option

WithEnvExpander enables or disables ${VAR} expansion in string values.

func WithEnvPrefix

func WithEnvPrefix(prefix string) Option

WithEnvPrefix auto-adds an EnvironmentLoader with this prefix.

func WithEnvSwitcher

func WithEnvSwitcher(envVar string) Option

WithEnvSwitcher sets the OS environment variable name whose value selects the active environment.

func WithFreezeOnLoad

func WithFreezeOnLoad(v bool) Option

WithFreezeOnLoad freezes the config after initialization.

func WithLoaders

func WithLoaders(loaders ...Loader) Option

WithLoaders sets the ordered list of loaders. Later loaders override earlier ones.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the logger for the config instance.

func WithMergeStrategyMap

func WithMergeStrategyMap(m map[string]MergeStrategy) Option

WithMergeStrategyMap sets per-path merge strategy overrides.

func WithMergeStrategyOption

func WithMergeStrategyOption(s MergeStrategy) Option

WithMergeStrategyOption sets the default merge strategy.

func WithOnError

func WithOnError(p ErrorPolicy) Option

WithOnError sets the error handling policy.

func WithSchema

func WithSchema(schema any) Option

WithSchema sets the validation schema (struct type or JSON schema dict).

func WithSchemaPath

func WithSchemaPath(path string) Option

WithSchemaPath sets the path to a JSON Schema file.

func WithStrictValidation

func WithStrictValidation(v bool) Option

WithStrictValidation raises errors on validation failure instead of warning.

func WithSysenvFallback

func WithSysenvFallback(v bool) Option

WithSysenvFallback enables fallback to system env vars for missing keys.

func WithTypeCasting

func WithTypeCasting(v bool) Option

WithTypeCasting enables or disables automatic type casting of string values.

func WithValidateOnLoad

func WithValidateOnLoad(v bool) Option

WithValidateOnLoad validates configuration immediately after loading.

type ReloadOption

type ReloadOption func(*reloadOpts)

ReloadOption is a functional option that configures the behavior of Config.Reload, such as enabling dry-run mode or overriding validation.

func WithDryRun

func WithDryRun(v bool) ReloadOption

WithDryRun loads and validates without applying changes.

func WithIncremental

func WithIncremental(v bool) ReloadOption

WithIncremental only reloads files that have changed (based on mtime+hash).

func WithReloadValidate

func WithReloadValidate(v bool) ReloadOption

WithReloadValidate overrides validate_on_load for this reload.

type SecretExistenceChecker

type SecretExistenceChecker interface {
	SecretExists(ctx context.Context, key string) (bool, error)
}

SecretExistenceChecker is optionally implemented by stores that can efficiently check for secret existence without retrieving the value.

type SecretMetadataProvider

type SecretMetadataProvider interface {
	GetSecretMetadata(ctx context.Context, key string) (map[string]any, error)
}

SecretMetadataProvider is optionally implemented by stores that can return metadata about a secret.

type SecretOption

type SecretOption func(*SecretOptions)

SecretOption configures optional secret operation parameters.

func WithVersion

func WithVersion(v string) SecretOption

WithVersion sets the secret version for retrieval.

type SecretOptions

type SecretOptions struct {
	Version string
}

SecretOptions holds resolved secret operation options.

func ResolveSecretOptions

func ResolveSecretOptions(opts ...SecretOption) SecretOptions

ResolveSecretOptions applies all options and returns the resolved result.

type SecretStore

type SecretStore interface {
	GetSecret(ctx context.Context, key string, opts ...SecretOption) (any, error)
	SetSecret(ctx context.Context, key string, value any, opts ...SecretOption) error
	DeleteSecret(ctx context.Context, key string, opts ...SecretOption) error
	ListSecrets(ctx context.Context, prefix string) ([]string, error)
}

SecretStore provides access to a secret management backend.

type SetOption

type SetOption func(*setOpts)

SetOption is a functional option that configures the behavior of Config.Set.

func WithOverride

func WithOverride(v bool) SetOption

WithOverride allows or prevents overwriting existing keys. Default: true.

type Validator

type Validator interface {
	Validate(data map[string]any) error
}

Validator validates a configuration map against a schema.

Directories

Path Synopsis
Package compose processes _include and _defaults directives in configuration files, supporting Hydra-style configuration composition with cycle detection.
Package compose processes _include and _defaults directives in configuration files, supporting Hydra-style configuration composition with cycle detection.
cmd
Package diff provides configuration comparison and drift detection.
Package diff provides configuration comparison and drift detection.
Package envhandler resolves environment-specific configuration by merging a "default" section with the active environment section.
Package envhandler resolves environment-specific configuration by merging a "default" section with the active environment section.
examples
basic command
Package main demonstrates basic Confii usage: loading a YAML config and accessing values using dot-notation key paths.
Package main demonstrates basic Confii usage: loading a YAML config and accessing values using dot-notation key paths.
builder command
Package main demonstrates the fluent builder pattern for constructing a Config instance with chained method calls.
Package main demonstrates the fluent builder pattern for constructing a Config instance with chained method calls.
composition command
Package main demonstrates Hydra-style config composition using _include and _defaults directives.
Package main demonstrates Hydra-style config composition using _include and _defaults directives.
diff command
Package main demonstrates config diffing and drift detection.
Package main demonstrates config diffing and drift detection.
dynamic-reload command
Package main demonstrates file watching and dynamic reloading.
Package main demonstrates file watching and dynamic reloading.
environment command
Package main demonstrates environment-aware configuration.
Package main demonstrates environment-aware configuration.
export command
Package main demonstrates exporting configuration to different formats (JSON, YAML, TOML) and generating documentation.
Package main demonstrates exporting configuration to different formats (JSON, YAML, TOML) and generating documentation.
hooks command
Package main demonstrates the hook system.
Package main demonstrates the hook system.
introspection command
Package main demonstrates Confii's introspection capabilities: Explain, Layers, Schema, source tracking, and debug reports.
Package main demonstrates Confii's introspection capabilities: Explain, Layers, Schema, source tracking, and debug reports.
lifecycle command
Package main demonstrates config lifecycle operations: reload, extend, freeze, override, set, and change callbacks.
Package main demonstrates config lifecycle operations: reload, extend, freeze, override, set, and change callbacks.
merge-strategies command
Package main demonstrates advanced merge strategies.
Package main demonstrates advanced merge strategies.
multi-source command
Package main demonstrates loading configuration from multiple sources.
Package main demonstrates loading configuration from multiple sources.
observability command
Package main demonstrates observability features: access metrics, event emission, and monitoring config usage patterns.
Package main demonstrates observability features: access metrics, event emission, and monitoring config usage patterns.
self-config command
Package main demonstrates Confii's self-configuration feature.
Package main demonstrates Confii's self-configuration feature.
typed command
Package main demonstrates type-safe configuration access using Go generics.
Package main demonstrates type-safe configuration access using Go generics.
validation command
Package main demonstrates both struct tag validation and JSON Schema validation for configuration.
Package main demonstrates both struct tag validation and JSON Schema validation for configuration.
versioning command
Package main demonstrates config versioning: taking snapshots, comparing versions, and rolling back to a previous state.
Package main demonstrates config versioning: taking snapshots, comparing versions, and rolling back to a previous state.
Package export provides configuration exporters.
Package export provides configuration exporters.
Package hook provides a thread-safe hook processor for transforming configuration values during access.
Package hook provides a thread-safe hook processor for transforming configuration values during access.
internal
dictutil
Package dictutil provides utility functions for working with nested map[string]any configuration dictionaries.
Package dictutil provides utility functions for working with nested map[string]any configuration dictionaries.
formatparse
Package formatparse detects configuration file formats from file extensions and content types.
Package formatparse detects configuration file formats from file extensions and content types.
typecoerce
Package typecoerce provides string-to-typed-value coercion utilities.
Package typecoerce provides string-to-typed-value coercion utilities.
Package loader provides implementations of the confii.Loader interface for various configuration sources.
Package loader provides implementations of the confii.Loader interface for various configuration sources.
Package merge provides configuration merging strategies.
Package merge provides configuration merging strategies.
Package observe provides observability features: metrics, events, and versioning.
Package observe provides observability features: metrics, events, and versioning.
Package secret provides secret store implementations and a placeholder resolver.
Package secret provides secret store implementations and a placeholder resolver.
Package selfconfig reads Confii's own configuration from dedicated config files before user loaders run.
Package selfconfig reads Confii's own configuration from dedicated config files before user loaders run.
Package sourcetrack provides per-key source tracking for configuration values, recording where each value originated, how many times it was overridden, and the full override history.
Package sourcetrack provides per-key source tracking for configuration values, recording where each value originated, how many times it was overridden, and the full override history.
Package validate provides configuration validation implementations.
Package validate provides configuration validation implementations.
Package watch provides file-watching capabilities for automatic config reloading.
Package watch provides file-watching capabilities for automatic config reloading.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL