xconfig

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: MIT Imports: 18 Imported by: 2

README

xConfig

Go Reference Go Version Go Report Card License

A lightweight, zero-dependency, and highly extensible configuration management library for Go applications.

Features

  • Zero Dependencies - No external dependencies in the core library
  • Plugin-Based Architecture - Mix and match only the configuration sources you need
  • Type-Safe - Strongly typed configuration with struct tags
  • Multiple Sources - Support for defaults, environment variables, command-line flags, and config files
  • HashiCorp Vault - Native integration with batch loading, token renewal, auto-retry, and metrics
  • Background Refresh - Real-time config updates without restart via Refreshable plugins
  • Nested Structures - Full support for nested configuration structs
  • Rich Type Support - All basic Go types, time.Duration, and custom types via encoding.TextUnmarshaler
  • Validation - Built-in validation support through plugins
  • Documentation Generation - Auto-generate markdown documentation for your configuration

AI Agent Skills

This repository includes AI agent skills with documentation and usage examples for all packages. Install them with the skills CLI:

go install github.com/sxwebdev/skills/cmd/skills@latest
skills init
skills repo add sxwebdev/xconfig

Installation

go get github.com/sxwebdev/xconfig

Quick Start

package main

import (
    "fmt"
    "log"

    "github.com/sxwebdev/xconfig"
)

type Config struct {
    Host     string `default:"localhost" env:"HOST" flag:"host" usage:"Server host address"`
    Port     int    `default:"8080" env:"PORT" flag:"port" usage:"Server port"`
    Debug    bool   `default:"false" env:"DEBUG" flag:"debug" usage:"Enable debug mode"`
    Database struct {
        Host     string `default:"localhost" env:"DB_HOST" usage:"Database host"`
        Port     int    `default:"5432" env:"DB_PORT" usage:"Database port"`
        Name     string `default:"myapp" env:"DB_NAME" usage:"Database name"`
        Password string `vault:"true" env:"DB_PASSWORD" secret:"true" usage:"Database password"`
    }
}

func main() {
    cfg := &Config{}

    // Load configuration from defaults, env vars, and flags
    _, err := xconfig.Load(cfg)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Server: %s:%d\n", cfg.Host, cfg.Port)
    fmt.Printf("Database: %s:%d/%s\n", cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
}

Usage

Basic Configuration Loading

The Load function provides the most common configuration pattern, automatically enabling:

  1. Default values from struct tags
  2. Custom defaults via SetDefaults() method
  3. Configuration files (if provided)
  4. Environment variables
  5. Command-line flags
  6. Custom plugins (Vault, etc.) — highest priority
type AppConfig struct {
    APIKey    string `default:"dev-key" env:"API_KEY" flag:"api-key"`
    Timeout   int    `default:"30" env:"TIMEOUT" flag:"timeout"`
    EnableLog bool   `default:"true" env:"ENABLE_LOG" flag:"enable-log"`
}

cfg := &AppConfig{}
_, err := xconfig.Load(cfg)
Loading from Configuration Files

xConfig supports multiple configuration file formats through decoders:

import (
    "encoding/json"

    "github.com/sxwebdev/xconfig"
    "github.com/sxwebdev/xconfig/plugins/loader"
    "github.com/sxwebdev/xconfig/decoders/xconfigyaml"
    "github.com/sxwebdev/xconfig/decoders/xconfigdotenv"
)

type Config struct {
    Server struct {
        Host string `json:"host"`
        Port int    `json:"port"`
    } `json:"server"`
}

cfg := &Config{}

// Create loader with JSON decoder
l, err := loader.NewLoader(map[string]loader.Unmarshal{
    "json": json.Unmarshal,
    "yaml": xconfigyaml.New().Unmarshal,
    "env":  xconfigdotenv.New().Unmarshal,
})
if err != nil {
    log.Fatal(err)
}

// Add configuration file (optional=false means file must exist)
err = l.AddFile("config.json", false)
if err != nil {
    log.Fatal(err)
}

_, err = xconfig.Load(cfg, xconfig.WithLoader(l))
Environment Variables with Prefix
type Config struct {
    APIKey string `env:"API_KEY"`
    Secret string `env:"SECRET"`
}

cfg := &Config{}

// All env vars will be prefixed with "MYAPP_"
// So it will look for: MYAPP_API_KEY and MYAPP_SECRET
_, err := xconfig.Load(cfg, xconfig.WithEnvPrefix("MYAPP"))
Slices and Maps from Environment Variables

The env plugin can populate slices of structs and maps directly from environment variables — including nil/empty containers. Slice elements are addressed by their numeric index; map entries by their key.

Slice of struct
type Item struct {
    Key1 string
    Key2 string
}

type Config struct {
    Items []Item
}

// ITEMS_0_KEY_1=a, ITEMS_0_KEY_2=b, ITEMS_1_KEY_1=c
//   → Items: [{Key1: "a", Key2: "b"}, {Key1: "c"}]

The slice grows automatically to fit the largest index found in the environment. []*Item (pointer elements) is also supported — empty slots are allocated as &Item{}.

Map of primitive
type Config struct {
    Tags     map[string]string
    Counts   map[string]int
    Timeouts map[string]time.Duration
}

// TAGS_FOO=v1, TAGS_BAR=v2  → Tags:     {FOO: "v1", BAR: "v2"}
// COUNTS_A=10, COUNTS_B=42  → Counts:   {A: 10, B: 42}
// TIMEOUTS_FAST=5s          → Timeouts: {FAST: 5*time.Second}

The suffix after the map's env prefix becomes the map key verbatim — case is preserved. Pre-populated entries are kept; matching env vars override them.

Map of struct
type Server struct {
    Host string
    Port int
}

type Config struct {
    Servers map[string]Server
}

// SERVERS_PRIMARY_HOST=10.0.0.1, SERVERS_PRIMARY_PORT=5432, SERVERS_BACKUP_HOST=10.0.0.2
//   → Servers: {
//       PRIMARY: {Host: "10.0.0.1", Port: 5432},
//       BACKUP:  {Host: "10.0.0.2"},
//     }

The plugin discovers map keys by matching the suffix of each env var against the inner struct's field names (longest match wins). map[string]*Server is supported the same way — entries are allocated as &Server{}.

env tag inside a slice/map element

When a field inside a slice element or map value carries its own env:"..." tag, it acts as a per-segment override — the surrounding slice index or map key is preserved so different elements don't collide:

type Item struct {
    Key1 string
    Port int `env:"P"`
}

type Config struct {
    Items []Item
}

// ITEMS_0_KEY_1=a, ITEMS_0_P=1000, ITEMS_1_P=2000
//   → Items: [{Key1: "a", Port: 1000}, {Port: 2000}]

At the top level the env:"..." tag still anchors the full env name (only the global WithEnvPrefix is prepended) — so Database.Host env:"DB_HOST" continues to read from DB_HOST, not DATABASE_DB_HOST.

Custom Defaults with SetDefaults

Implement the SetDefaults() method to programmatically set default values:

type Config struct {
    Host string
    Port int
    URLs []string
}

func (c *Config) SetDefaults() {
    c.Host = "localhost"
    c.Port = 8080
    c.URLs = []string{"https://api.example.com", "https://backup.example.com"}
}

cfg := &Config{}
_, err := xconfig.Load(cfg)
// cfg.Host will be "localhost" unless overridden by env or flags
HashiCorp Vault Integration

Use the vault tag to load secrets from HashiCorp Vault with automatic token renewal, batch loading, auto-retry on 401/403, and metrics callback:

import (
    "github.com/sxwebdev/xconfig"
    "github.com/sxwebdev/xconfig/sourcers/xconfigvault"
)

type Config struct {
    Host       string `default:"localhost" env:"HOST"`
    DBPassword string `vault:"true" env:"DB_PASSWORD" secret:"true"`
    APIKey     string `vault:"true" env:"API_KEY" secret:"true"`
}

// Create Vault client (supports Token, AppRole, Kubernetes, UserPass, LDAP auth)
vaultClient, err := xconfigvault.New(&xconfigvault.Config{
    Address:    os.Getenv("VAULT_ADDR"),
    Auth:       xconfigvault.WithKubernetes("my-service-role"),
    SecretPath: "kv/myservice/config",
    Metrics:    xconfigvault.MetricsFunc(func(e xconfigvault.Event) {
        // Monitor auth failures, retries, etc.
        promCounter.WithLabelValues(string(e.Type)).Inc()
    }),
})
if err != nil {
    log.Fatal(err)
}
defer vaultClient.Close()

cfg := &Config{}
xc, err := xconfig.Load(cfg, xconfig.WithPlugins(vaultClient.Plugin()))

The Vault plugin:

  • Runs last in the plugin chain (maximum priority over env, flags, defaults)
  • Batch-loads all secrets in a single HTTP request
  • Automatically renews tokens in the background
  • Retries on 401/403 with token refresh
  • Emits operational events via MetricsCallback
  • Populates slice-of-struct and map fields from secret keys the same way the env plugin does — e.g. secret keys ITEMS_0_PASSWORD, SERVERS_PRIMARY_PASSWORD grow the containers and create entries automatically. Pointer element types ([]*T, map[string]*T) are supported.

The vault:"true" tag marks a field to be sourced from Vault. The secret:"true" tag is independent — it marks a field as sensitive (for masking in logs/docs).

Background Config Refresh

Plugins implementing Refreshable support real-time config updates without restart:

xc.StartRefresh(ctx, 1*time.Minute, func(changes []plugins.FieldChange) {
    for _, c := range changes {
        log.Printf("config changed: %s %q -> %q", c.FieldName, c.OldValue, c.NewValue)
        if c.FieldName == "Database.Password" {
            reconnectDB(c.NewValue)
        }
    }
})
defer xc.StopRefresh()

FieldChange.FieldName contains the full field path (e.g., Database.Postgres.Password). Any plugin implementing plugins.Refreshable participates in the refresh cycle automatically.

Secret Management (Legacy)

The secret plugin loads sensitive data from a custom provider function:

import "github.com/sxwebdev/xconfig/plugins/secret"

type Config struct {
    DBPassword string `secret:"DATABASE_PASSWORD"`
}

secretProvider := func(name string) (string, error) {
    return fetchFromVault(name)
}

cfg := &Config{}
_, err := xconfig.Load(cfg, xconfig.WithPlugins(secret.New(secretProvider)))

For new projects, prefer the Vault plugin which provides batch loading, token renewal, and background refresh out of the box.

Validation

Add validation to ensure your configuration meets requirements:

import (
    "fmt"
    "github.com/sxwebdev/xconfig"
    "github.com/sxwebdev/xconfig/plugins/validate"
)

type Config struct {
    Port int    `default:"8080"`
    Host string `default:"localhost"`
}

// Implement Validate method
func (c *Config) Validate() error {
    if c.Port < 1 || c.Port > 65535 {
        return fmt.Errorf("port must be between 1 and 65535")
    }
    if c.Host == "" {
        return fmt.Errorf("host cannot be empty")
    }
    return nil
}

cfg := &Config{}

// Validation happens automatically after loading
_, err := xconfig.Load(cfg)
if err != nil {
    log.Fatal(err) // Will fail if validation fails
}

You can also use external validators:

import (
    "github.com/go-playground/validator/v10"
    "github.com/sxwebdev/xconfig/plugins/validate"
)

type Config struct {
    Email string `validate:"required,email"`
    Age   int    `validate:"gte=0,lte=130"`
}

cfg := &Config{}

v := validator.New()
_, err := xconfig.Load(cfg, xconfig.WithPlugins(
    validate.New(func(a any) error {
        return v.Struct(a)
    }),
))
Selective Plugin Loading

Control which plugins are enabled:

cfg := &Config{}

// Skip certain plugins
_, err := xconfig.Load(cfg,
    xconfig.WithSkipDefaults(),         // Don't load from 'default' tags
    xconfig.WithSkipEnv(),              // Don't load from environment
    xconfig.WithSkipFlags(),            // Don't load from command-line flags
    xconfig.WithSkipCustomDefaults(),   // Don't call SetDefaults()
    xconfig.WithDisallowUnknownFields(), // Fail if config files contain unknown fields
)

Unknown Fields Validation: Enable WithDisallowUnknownFields() to detect typos and configuration errors in JSON/YAML files. When enabled, loading will fail if any fields in the config files don't match your struct definition. Use xconfig.GetUnknownFields() to retrieve unknown fields without failing.

Documentation Generation

Generate markdown documentation for your configuration:

type Config struct {
    Host   string `default:"localhost" usage:"Server host address"`
    Port   int    `default:"8080" usage:"Server port number"`
    APIKey string `secret:"API_KEY" usage:"API authentication key"`
}

cfg := &Config{}

markdown, err := xconfig.GenerateMarkdown(cfg)
if err != nil {
    log.Fatal(err)
}

// Save to file
os.WriteFile("CONFIG.md", []byte(markdown), 0644)
Usage Information

Get runtime configuration information:

cfg := &Config{}
c, err := xconfig.Load(cfg)
if err != nil {
    log.Fatal(err)
}

usage, err := c.Usage()
if err != nil {
    log.Fatal(err)
}

fmt.Println(usage)

Available Struct Tags

Tag Description Example
default Default value for the field default:"8080"
env Environment variable name env:"PORT"
flag Command-line flag name flag:"port"
secret Marks field as sensitive (metadata) secret:"true"
vault Field sourced from HashiCorp Vault vault:"true"
usage Description for documentation/help usage:"Server port"
xconfig Override field name in flat structure xconfig:"custom_name"

Available Plugins

Plugin Description
defaults Load values from default struct tags
customdefaults Call SetDefaults() method if implemented
env Load values from environment variables
flag Load values from command-line flags
loader Load from configuration files (JSON, YAML, etc.)
secret Mark fields as sensitive, load from custom providers
validate Validate configuration after loading
xconfigvault HashiCorp Vault: batch loading, token renewal, retry, refresh

Custom Plugins

Create your own plugins by implementing the Plugin interface with either Walker or Visitor:

import (
    "github.com/sxwebdev/xconfig/flat"
    "github.com/sxwebdev/xconfig/plugins"
)

type myPlugin struct {
    fields flat.Fields
}

// Visitor interface - called once with all fields
func (p *myPlugin) Visit(fields flat.Fields) error {
    p.fields = fields
    // Setup phase: register metadata, validate structure, etc.
    return nil
}

// Parse is called to actually load configuration
func (p *myPlugin) Parse() error {
    for _, field := range p.fields {
        // Load configuration for each field
    }
    return nil
}

// Use your custom plugin
cfg := &Config{}
_, err := xconfig.Custom(cfg, &myPlugin{})

Applying Defaults Programmatically

Use xconfig.ApplyDefaults when data arrives through something other than xconfig.Load — for example, a slice decoded directly with yaml.Unmarshal. It walks the value and applies every default:"..." struct tag it finds, leaving non-zero fields untouched.

type Group struct {
    IsEnabled bool   `yaml:"is_enabled" default:"true"`
    Name      string `yaml:"name"`
    Port      int    `yaml:"port" default:"8080"`
}

var file struct {
    Groups []Group `yaml:"groups"`
}
if err := yaml.Unmarshal(data, &file); err != nil {
    return err
}

// Fills IsEnabled=true / Port=8080 for elements where YAML omitted them.
if err := xconfig.ApplyDefaults(&file.Groups); err != nil {
    return err
}

ApplyDefaults accepts a pointer to a struct, a slice of structs (*[]T), or a slice of struct pointers (*[]*T). It also works through xconfig.Load / xconfig.Custom automatically — default tags inside []Struct fields are applied the same way they are for nested structs and maps.

Note on bool and other scalars. Go's yaml.Unmarshal cannot distinguish a field that was explicitly set to its zero value (e.g. is_enabled: false) from a field that was simply absent — both end up as false. When that distinction matters, declare the field as a pointer type (*bool) so the absent case is represented by nil.

Supported Types

  • All basic Go types: string, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64
  • time.Duration
  • Slices of supported types: []string, []int, etc.
  • Any type implementing encoding.TextUnmarshaler

Examples

See the examples directory for more complete examples.

License

MIT License

Documentation

Overview

Package xconfig provides a lightweight, zero-dependency, and highly extensible configuration management library for Go applications.

Overview

xconfig enables you to build type-safe configuration for your applications using a plugin-based architecture. Mix and match only the configuration sources you need: defaults, environment variables, command-line flags, configuration files, secret providers, and more. Plugins implementing plugins.Refreshable support background config refresh for real-time updates without restart.

Quick Start

Define your configuration as a struct with tags:

type Config struct {
    Host     string `default:"localhost" env:"HOST" flag:"host" usage:"Server host"`
    Port     int    `default:"8080" env:"PORT" flag:"port" usage:"Server port"`
    Debug    bool   `default:"false" env:"DEBUG" flag:"debug" usage:"Debug mode"`
    Database struct {
        Host     string `default:"localhost" env:"DB_HOST" usage:"Database host"`
        Port     int    `default:"5432" env:"DB_PORT" usage:"Database port"`
        Password string `vault:"true" env:"DB_PASSWORD" secret:"true" usage:"Database password"`
    }
}

Load configuration from multiple sources:

cfg := &Config{}
_, err := xconfig.Load(cfg)
if err != nil {
    log.Fatal(err)
}

The Load function automatically processes configuration in this order:

  1. Default values from struct tags
  2. Custom defaults via SetDefaults() method
  3. Configuration files (if provided)
  4. Environment variables
  5. Command-line flags
  6. Custom plugins (vault, etc.) — highest priority

Configuration Sources

## Default Values

Use the "default" tag to specify default values:

type Config struct {
    Port    int    `default:"8080"`
    Timeout int    `default:"30"`
    Enabled bool   `default:"true"`
}

## Environment Variables

Use the "env" tag to bind fields to environment variables:

type Config struct {
    APIKey string `env:"API_KEY"`
    Secret string `env:"SECRET"`
}

Add a prefix to all environment variables:

_, err := xconfig.Load(cfg, xconfig.WithEnvPrefix("MYAPP"))
// Will look for: MYAPP_API_KEY, MYAPP_SECRET

The env plugin can also populate slices of structs and maps directly from environment variables — including nil/empty containers. Slices grow automatically to fit the largest index found; map entries take the suffix after the map's env prefix as their key (case preserved).

type Item struct {
    Key1 string
    Key2 string
}

type Config struct {
    Items   []Item                   // ITEMS_0_KEY_1=..., ITEMS_1_KEY_1=...
    Tags    map[string]string        // TAGS_FOO=v1, TAGS_BAR=v2
    Servers map[string]Item          // SERVERS_PRIMARY_KEY_1=..., SERVERS_BACKUP_KEY_2=...
}

Pointer element types ([]*T, map[string]*T) are also supported — empty slots are allocated as &T{}.

An env tag on a field nested inside a slice element or map value acts as a per-segment override (the surrounding slice index or map key is preserved so different elements don't collide on the same env var). At the top level the env tag still anchors the full env name as before.

## Command-Line Flags

Use the "flag" tag to bind fields to command-line flags:

type Config struct {
    Host string `flag:"host" usage:"Server hostname"`
    Port int    `flag:"port" usage:"Server port"`
}

## Configuration Files

Load configuration from JSON, YAML, TOML, or any other format:

import (
    "encoding/json"
    "github.com/sxwebdev/xconfig/plugins/loader"
)

l, err := loader.NewLoader(map[string]loader.Unmarshal{
    ".json": json.Unmarshal,
    ".yaml": yaml.Unmarshal,
})
if err != nil {
    log.Fatal(err)
}

err = l.AddFile("config.json", false)
if err != nil {
    log.Fatal(err)
}

_, err = xconfig.Load(cfg, xconfig.WithLoader(l))

## Custom Defaults

Implement SetDefaults() for programmatic default values:

type Config struct {
    URLs []string
    Port int
}

func (c *Config) SetDefaults() {
    c.URLs = []string{"https://api.example.com"}
    c.Port = 8080
}

HashiCorp Vault Integration

Use the vault plugin to load secrets from HashiCorp Vault with automatic token renewal, batch loading, auto-retry, and background refresh:

import "github.com/sxwebdev/xconfig/sourcers/xconfigvault"

type Config struct {
    DBPassword string `vault:"true" env:"DB_PASSWORD" secret:"true"`
    APIKey     string `vault:"true" env:"API_KEY" secret:"true"`
}

vaultClient, err := xconfigvault.New(&xconfigvault.Config{
    Address:    os.Getenv("VAULT_ADDR"),
    Auth:       xconfigvault.WithKubernetes("my-service-role"),
    SecretPath: "kv/myservice/config",
})
defer vaultClient.Close()

cfg := &Config{}
xc, err := xconfig.Load(cfg, xconfig.WithPlugins(vaultClient.Plugin()))

The vault plugin runs last and has maximum priority over all other sources. Use vault:"true" to mark fields sourced from Vault. The secret:"true" tag is independent — it marks a field as sensitive (for masking in logs/docs).

Background Config Refresh

Plugins implementing plugins.Refreshable support background updates. Call [Config.StartRefresh] to periodically re-fetch values from external sources:

xc.StartRefresh(ctx, 1*time.Minute, func(changes []plugins.FieldChange) {
    for _, c := range changes {
        log.Printf("config changed: %s %q -> %q", c.FieldName, c.OldValue, c.NewValue)
    }
})
defer xc.StopRefresh()

FieldChange.FieldName contains the full field path (e.g., "Database.Postgres.Password").

Secret Management

Use the secret tag to mark fields as sensitive. The secret plugin can also load values from a custom provider:

import "github.com/sxwebdev/xconfig/plugins/secret"

type Config struct {
    DBPassword string `secret:"DATABASE_PASSWORD"`
    APIToken   string `secret:"API_TOKEN"`
}

secretProvider := func(name string) (string, error) {
    return fetchFromVault(name)
}

_, err := xconfig.Load(cfg, xconfig.WithPlugins(secret.New(secretProvider)))

Validation

Add validation by implementing the Validate() method:

type Config struct {
    Port int `default:"8080"`
}

func (c *Config) Validate() error {
    if c.Port < 1 || c.Port > 65535 {
        return fmt.Errorf("invalid port: %d", c.Port)
    }
    return nil
}

Or use external validators with the validate plugin:

import (
    "github.com/go-playground/validator/v10"
    "github.com/sxwebdev/xconfig/plugins/validate"
)

type Config struct {
    Email string `validate:"required,email"`
    Age   int    `validate:"gte=0,lte=130"`
}

v := validator.New()
_, err := xconfig.Load(cfg, xconfig.WithPlugins(
    validate.New(func(a any) error {
        return v.Struct(a)
    }),
))

Available Tags

The following struct tags are supported:

  • default: Default value for the field
  • env: Environment variable name
  • flag: Command-line flag name
  • secret: Marks field as sensitive (metadata for masking/docs)
  • vault: Field sourced from HashiCorp Vault (vault:"true")
  • usage: Description for documentation and help text
  • xconfig: Override field name in flat structure

Supported Types

xconfig supports all basic Go types, time.Duration, slices of basic types, and any type implementing encoding.TextUnmarshaler:

  • string, bool
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • time.Duration
  • []string, []int, []float64, etc.
  • Custom types via encoding.TextUnmarshaler

Custom Plugins

Create custom plugins by implementing the Plugin interface with either Walker or Visitor. For background refresh support, also implement Refreshable:

import (
    "github.com/sxwebdev/xconfig/flat"
    "github.com/sxwebdev/xconfig/plugins"
)

type myPlugin struct {
    fields flat.Fields
}

func (p *myPlugin) Visit(fields flat.Fields) error {
    p.fields = fields
    return nil
}

func (p *myPlugin) Parse() error {
    // Load configuration for each field
    return nil
}

// Optional: implement Refreshable for background updates
func (p *myPlugin) Refresh(ctx context.Context) ([]plugins.FieldChange, error) {
    // Re-fetch and return changes
    return nil, nil
}

// Use your plugin
_, err := xconfig.Custom(cfg, &myPlugin{})

Documentation Generation

Generate markdown documentation for your configuration:

markdown, err := xconfig.GenerateMarkdown(cfg)
if err != nil {
    log.Fatal(err)
}
os.WriteFile("CONFIG.md", []byte(markdown), 0644)

Options

Control which plugins are enabled:

_, err := xconfig.Load(cfg,
    xconfig.WithSkipDefaults(),      // Skip 'default' tags
    xconfig.WithSkipEnv(),            // Skip environment variables
    xconfig.WithSkipFlags(),          // Skip command-line flags
    xconfig.WithEnvPrefix("MYAPP"),   // Add prefix to env vars
    xconfig.WithPlugins(myPlugin),    // Add custom plugins
)

For more information and examples, see: https://github.com/sxwebdev/xconfig

Package xconfig provides advanced command line flags supporting defaults, env vars, and config structs.

Index

Constants

This section is empty.

Variables

View Source
var ErrUsage = plugins.ErrUsage

Functions

func ApplyDefaults added in v0.3.4

func ApplyDefaults(v any) error

ApplyDefaults applies `default:` struct tags to v. Non-zero fields are left intact, so existing values (including those loaded from a YAML/JSON file via an external unmarshaler) are preserved.

v must be a non-nil pointer to one of:

  • a struct;
  • a slice of structs ([]T);
  • a slice of pointers to structs ([]*T).

Primitive slices ([]string, []int, …) are left untouched by this helper — defaults on such fields are applied by the value of the field itself, not per element.

Note: for scalar fields (including bool) Go cannot distinguish "value was explicitly set to the zero value" from "value was not set". If that distinction matters, use a pointer type (e.g. *bool) for the field.

func GenerateMarkdown

func GenerateMarkdown(cfg any, opts ...Option) (string, error)

func GetUnknownFields

func GetUnknownFields(c Config) map[string][]string

GetUnknownFields returns all unknown fields found in configuration files. Returns a map where keys are file paths and values are slices of unknown field paths. This function is useful for debugging configuration issues or logging warnings about extra fields that are not used.

Types

type Config

type Config interface {
	// Parse will call the parse method of all the added pluginss in the order
	// that the pluginss were registered, it will return early as soon as any
	// plugins fails.
	// You must call this before using the config value.
	Parse() error

	// Usage provides a simple usage message based on the meta data registered
	// by the pluginss.
	Usage() (string, error)

	// Options returns the options for the config.
	Options() *options

	// Fields returns the flat fields that have been processed by plugins.
	Fields() flat.Fields

	// StartRefresh starts a background goroutine that periodically calls Refresh
	// on all plugins implementing plugins.Refreshable. The onChange callback is
	// invoked with the list of changed fields whenever a refresh detects changes.
	StartRefresh(ctx context.Context, interval time.Duration, onChange func([]plugins.FieldChange))

	// StopRefresh stops the background refresh goroutine and waits for it to finish.
	StopRefresh()
	// contains filtered or unexported methods
}

Config is the config manager.

func Custom

func Custom(conf any, ps ...plugins.Plugin) (Config, error)

Custom returns a new Config. The conf must be a pointer to a struct.

func Load

func Load(conf any, opts ...Option) (Config, error)

Load creates a xconfig manager with defaults, environment variables, and flags (in that order) and optionally file loaders based on the provided Files map and parses them right away.

type Option

type Option func(*options)

func WithDisallowUnknownFields

func WithDisallowUnknownFields() Option

func WithEnvPrefix

func WithEnvPrefix(prefix string) Option

func WithLoader

func WithLoader(loader *loader.Loader) Option

func WithPlugins

func WithPlugins(plugins ...plugins.Plugin) Option

func WithSkipCustomDefaults

func WithSkipCustomDefaults() Option

func WithSkipDefaults

func WithSkipDefaults() Option

func WithSkipEnv

func WithSkipEnv() Option

func WithSkipFiles

func WithSkipFiles() Option

func WithSkipFlags

func WithSkipFlags() Option

Directories

Path Synopsis
decoders
xconfigdotenv module
xconfigyaml module
Package flat provides a flat view of an arbitrary nested structs.
Package flat provides a flat view of an arbitrary nested structs.
internal
f
Package f provides simple test fixtures for xconfig.
Package f provides simple test fixtures for xconfig.
utils
original package located here https://github.com/mcuadros/go-lookup
original package located here https://github.com/mcuadros/go-lookup
Package plugins describes the xconfig provider interface.
Package plugins describes the xconfig provider interface.
customdefaults
Package customdefaults provides custom default values for xconfig.
Package customdefaults provides custom default values for xconfig.
defaults
Package defaults provides default values for xconfig
Package defaults provides default values for xconfig
env
Package env provides environment variables support for xconfig
Package env provides environment variables support for xconfig
flag
Package flag provides flags support for xconfig
Package flag provides flags support for xconfig
loader
Package file provides config loader support for xconfig
Package file provides config loader support for xconfig
secret
Package secret enable xconfig to integrate with secret plugins.
Package secret enable xconfig to integrate with secret plugins.
sourcers
xconfigvault module

Jump to

Keyboard shortcuts

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