configlib

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2025 License: Apache-2.0 Imports: 7 Imported by: 0

README

configlib

A Go library for parsing configuration from environment variables, CLI flags, and struct tags with support for nested structs and comprehensive error reporting.

Features

  • Multiple sources: Parse configuration from environment variables, CLI flags, and default values
  • Priority order: CLI flags > Environment variables > Default values
  • Nested struct support: Automatically handle nested configuration structures
  • Type safety: Support for string, int, bool, and string slice types
  • Required fields: Mark fields as required and get comprehensive error messages
  • Auto-naming: Automatic generation of env var and CLI flag names from struct field paths
  • Configurable auto-naming: Optionally disable auto-generation of env vars or flags
  • Environment variable prefixes: Add custom prefixes to all environment variables
  • Comprehensive error reporting: Collects all missing required fields and reports them together
  • Built-in help: Automatic help generation with --help or -h flags

Installation

go get github.com/bherbruck/configlib

Usage

Basic Example
package main

import (
    "fmt"
    "log"
    "github.com/bherbruck/configlib"
)

type Config struct {
    Host     string `env:"HOST" flag:"host" default:"localhost" desc:"Server host"`
    Port     int    `env:"PORT" flag:"port" default:"8080" desc:"Server port"`
    Debug    bool   `env:"DEBUG" flag:"debug" default:"false" desc:"Enable debug mode"`
    APIKey   string `env:"API_KEY" flag:"api-key" required:"true" desc:"API key"`
}

func main() {
    var cfg Config
    if err := configlib.Parse(&cfg); err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Config: %+v\n", cfg)
}
Multiple Flags (Shorthand)

You can specify multiple flags for a single field using comma-separated values in the flag tag:

type Config struct {
    Host    string `env:"HOST" flag:"host,H" desc:"Server host"`
    Port    int    `env:"PORT" flag:"port,p" desc:"Server port"`
    Debug   bool   `env:"DEBUG" flag:"debug,d" desc:"Enable debug mode"`
    Verbose bool   `env:"VERBOSE" flag:"verbose,v" desc:"Enable verbose output"`
}

This allows both long and short forms:

# Long form
./myapp --host example.com --port 8080 --debug

# Short form
./myapp -H example.com -p 8080 -d

# Mixed
./myapp --host example.com -p 8080 -d
Nested Structs
type Config struct {
    Server struct {
        Host string `env:"SERVER_HOST" flag:"server-host" required:"true"`
        Port int    `env:"SERVER_PORT" flag:"server-port" default:"8080"`
    }
    Database struct {
        Host     string `env:"DB_HOST" flag:"db-host" required:"true"`
        Port     int    `env:"DB_PORT" flag:"db-port" default:"5432"`
        Password string `env:"DB_PASSWORD" flag:"db-password" required:"true"`
    }
}
Comprehensive Error Reporting

When multiple required fields are missing, configlib collects all errors and reports them together:

missing required fields:
  - Server.Host (env: SERVER_HOST, flag: --server-host)
  - Database.Host (env: DB_HOST, flag: --db-host)
  - Database.Password (env: DB_PASSWORD, flag: --db-password)

This makes it easy to identify all missing configuration at once, rather than discovering them one at a time.

Struct Tags

  • env: Name of the environment variable (auto-generated if not specified)
  • flag: Name of the CLI flag (auto-generated if not specified). Supports multiple flags separated by commas (e.g., flag:"host,h" for both --host and -h)
  • default: Default value if not provided via env or CLI
  • required: Set to "true" to make the field required
  • desc: Description for the CLI flag help text

Auto-naming Convention

If you don't specify env or flag tags, they are automatically generated:

  • Environment variables: FieldPathFIELD_PATH (e.g., Server.HostSERVER_HOST)
  • CLI flags: FieldPathfield-path (e.g., Server.Hostserver-host)
Disabling Auto-generation

You can disable automatic generation of environment variables or CLI flags:

// Disable auto-generation of environment variables
parser := configlib.NewParser(configlib.WithDisableAutoEnv())
err := parser.Parse(&cfg)

// Disable auto-generation of CLI flags
parser := configlib.NewParser(configlib.WithDisableAutoFlag())
err := parser.Parse(&cfg)

// Disable both
parser := configlib.NewParser(
    configlib.WithDisableAutoEnv(),
    configlib.WithDisableAutoFlag(),
)
err := parser.Parse(&cfg)

When auto-generation is disabled:

  • Fields without explicit env tags won't be configurable via environment variables
  • Fields without explicit flag tags won't be configurable via CLI flags
  • Fields can still use default values
Environment Variable Prefixes

You can add a prefix to all environment variable names:

// Add "MYAPP_" prefix to all env vars
parser := configlib.NewParser(configlib.WithEnvPrefix("MYAPP_"))
err := parser.Parse(&cfg)

This affects both auto-generated and explicitly defined environment variable names:

  • HOSTMYAPP_HOST
  • Server.PortMYAPP_SERVER_PORT
  • Already prefixed names are not double-prefixed

Example:

type Config struct {
    Host string `env:"HOST"`        // Will become MYAPP_HOST
    Port int                        // Will become MYAPP_PORT (auto-generated)
    Database struct {
        Name string                 // Will become MYAPP_DATABASE_NAME
    }
}

parser := configlib.NewParser(configlib.WithEnvPrefix("MYAPP_"))

Supported Types

  • string
  • int
  • bool
  • []string (comma-separated values)

Priority Order

Values are resolved in the following order (highest priority first):

  1. CLI flags
  2. Environment variables
  3. Default values

Help Functionality

The library automatically provides help functionality through the --help or -h flags:

./myapp --help

This will display:

  • All configuration options organized by groups
  • Environment variable names
  • CLI flag names
  • Types, default values, and descriptions
  • Required field indicators
Programmatic Help Access

You can also access help programmatically:

parser, err := configlib.ParseWithHelp(&cfg)
if err != nil {
    // Handle error
}

// Print help manually
parser.PrintHelp()

// Or get help as a string
helpText := parser.GetHelp()

Advanced Configuration Options

Parser Options

The library provides several options to customize parsing behavior:

// Create a parser with custom options
parser := configlib.NewParser(
    configlib.WithDisableAutoEnv(),    // Disable auto-generation of env var names
    configlib.WithDisableAutoFlag(),   // Disable auto-generation of CLI flag names
    configlib.WithEnvPrefix("MYAPP_"), // Add prefix to all env var names
)

err := parser.Parse(&cfg)
Complete Example with Options
package main

import (
    "fmt"
    "log"
    "github.com/bherbruck/configlib"
)

type Config struct {
    // Only configurable via CLI flag (auto-env disabled)
    Host string `flag:"host" default:"localhost"`
    
    // Only configurable via env var (auto-flag disabled)
    Port int `env:"PORT" default:"8080"`
    
    // Explicitly defined both
    Debug bool `env:"DEBUG" flag:"debug,d"`
    
    // Will have MYAPP_ prefix: MYAPP_DATABASE_URL
    Database struct {
        URL string `env:"DATABASE_URL"`
    }
}

func main() {
    var cfg Config
    
    parser := configlib.NewParser(
        configlib.WithDisableAutoEnv(),
        configlib.WithDisableAutoFlag(),
        configlib.WithEnvPrefix("MYAPP_"),
    )
    
    if err := parser.Parse(&cfg); err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Config: %+v\n", cfg)
}

License

MIT

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Parse

func Parse(config any) error

Parse is a convenience function to parse configuration from CLI flags, environment variables, and struct tags.

Example (MultipleFlags)
package main

import (
	"fmt"
	"os"

	"github.com/bherbruck/configlib"
)

func main() {
	// Set up environment and args for example
	os.Clearenv()
	os.Args = []string{"myapp", "-H", "example.com", "-p", "3000", "-d"}

	type Config struct {
		Host  string `env:"HOST" flag:"host,H" default:"localhost" desc:"Server host"`
		Port  int    `env:"PORT" flag:"port,p" default:"8080" desc:"Server port"`
		Debug bool   `env:"DEBUG" flag:"debug,d" desc:"Enable debug mode"`
	}

	var cfg Config
	err := configlib.Parse(&cfg)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Printf("Host: %s\n", cfg.Host)
	fmt.Printf("Port: %d\n", cfg.Port)
	fmt.Printf("Debug: %v\n", cfg.Debug)

}
Output:
Host: example.com
Port: 3000
Debug: true
Example (MultipleMissingFields)
package main

import (
	"fmt"
	"os"

	"github.com/bherbruck/configlib"
)

func main() {
	// Clear environment to ensure no values are set
	os.Clearenv()

	// Reset CLI args
	os.Args = []string{"test"}

	// Define a config struct with multiple required fields
	type Config struct {
		APIKey      string `env:"API_KEY" flag:"api-key" required:"true"`
		DatabaseURL string `env:"DATABASE_URL" flag:"database-url" required:"true"`
		SecretKey   string `env:"SECRET_KEY" flag:"secret-key" required:"true"`
		Port        int    `env:"PORT" flag:"port" default:"8080"`
	}

	var cfg Config
	err := configlib.Parse(&cfg)

	if err != nil {
		fmt.Println(err)
	}

}
Output:
missing required fields:
  - APIKey (env: API_KEY, flag: --api-key)
  - DatabaseURL (env: DATABASE_URL, flag: --database-url)
  - SecretKey (env: SECRET_KEY, flag: --secret-key)

Types

type Option

type Option func(*Parser)

Option is a functional option for configuring a Parser

func WithDisableAutoEnv

func WithDisableAutoEnv() Option

WithDisableAutoEnv disables automatic generation of environment variable names

func WithDisableAutoFlag

func WithDisableAutoFlag() Option

WithDisableAutoFlag disables automatic generation of CLI flag names

func WithEnvPrefix

func WithEnvPrefix(prefix string) Option

WithEnvPrefix sets a prefix for all environment variable names

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

func NewParser

func NewParser(opts ...Option) *Parser

NewParser creates a new parser with the given options

func ParseWithHelp

func ParseWithHelp(config any) (*Parser, error)

ParseWithHelp is like Parse but returns a parser instance that can be used to print help

func (*Parser) GetHelp

func (p *Parser) GetHelp() string

GetHelp returns a help string for the configuration

func (*Parser) Parse

func (p *Parser) Parse(config any) error

func (*Parser) PrintHelp

func (p *Parser) PrintHelp()

PrintHelp prints a formatted help message showing all configuration options

Example
package main

import (
	"os"

	"github.com/bherbruck/configlib"
)

func main() {
	type Config struct {
		Host  string `env:"HOST" flag:"host" default:"localhost" desc:"Server host"`
		Port  int    `env:"PORT" flag:"port" default:"8080" desc:"Server port"`
		Debug bool   `env:"DEBUG" flag:"debug" desc:"Enable debug mode"`
	}

	// Clear args to avoid triggering help
	os.Args = []string{"myapp"}

	var cfg Config
	parser, _ := configlib.ParseWithHelp(&cfg)
	parser.PrintHelp()

}
Output:
Usage: myapp [options]

Options:
  --host <value>     Server host (default: localhost)
  --port <value>     Server port (default: 8080)
  --debug            Enable debug mode
  -h, --help         Show this help message

Directories

Path Synopsis
examples
advanced command
float command
simple command
types command

Jump to

Keyboard shortcuts

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