Skip to content
/ confy Public

A one stop shop for config file parsing, cli and environment variables

License

Notifications You must be signed in to change notification settings

NHAS/confy

Repository files navigation

Confy

confy is your one stop shop for configuration, it allows configuration from multiple sources including command-line arguments, environment variables, and configuration files in various formats (JSON, YAML, TOML).

Features

  • Multiple Configuration Sources: Populate settings from CLI flags, environment variables, and config files.
  • Automatic CLI Flag and Env Variable Mapping: Fields are mapped automatically and can be renamed with the confy:"" tag
  • Support for YAML, JSON, and TOML: Automatically detect and parse configuration file format, no added effort to switch to a new format

Installation

go get github.com/NHAS/confy

Usage

Tags

  • confy:"field_name;sensitive": Customize field names for env variables, CLI flags, and config files.
  • confy_description:"Field Description here": Set field descriptions for CLI parsing and help messages.

Basic Examples

config.json:

{
  "Database": {
    "Host": "localhost",
    "Port": 5432,
    "User": "dbuser",
    "Password": "securepassword"
  },
  "new_name": "some_value"
}

config.yaml:

Database:
  Host: "localhost"
  Port: 5432
  User: "dbuser"
  Password: "securepassword"

new_name: "some_value"
package main

import (
	"fmt"
	"github.com/NHAS/confy"
)

type Config struct {
	Database struct {
		Host     string `confy_description:"Database host address"`
		Port     int
		User     string
		Password string
	}

    Renamed string `confy:"new_name"`
}

func main() {
    // Defaults will also load from env and cli!
	loadedConfig, _, err := confy.Config[Config](confy.Defaults("config", "config.json"))
	if err != nil {
		if !errors.Is(err, flag.ErrHelp) {
			fmt.Println("Error loading config:", err)
		}
		return
	}

	fmt.Printf("Loaded JSON config: %+v\n", loadedConfig)

    yamlLoadedConfig, _, err := confy.Config[Config](confy.Defaults("config", "config.yaml"))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

    fmt.Printf("Loaded YAML config: %+v\n", yamlLoadedConfig)

    // They're the same!
}

Output

$ ./program
Loaded JSON config: {Database:{Host:localhost Port:5432 User:dbuser Password:securepassword} Renamed:some_value}
Loaded YAML config: {Database:{Host:localhost Port:5432 User:dbuser Password:securepassword} Renamed:some_value}

$ ./program -h
Usage of ./testconfy:
  -config string
        config file path (default "config.json")
Structure options: 
  -Database.Host string
        Database host address
  -Database.Password string
        A string value, Database.Password (Database.Password)
  -Database.Port int
        A int value, Database.Port (Database.Port)
  -Database.User string
        A string value, Database.User (Database.User)
  -config string
        config file path (default "config.json")
  -new_name string
        A string value, Renamed (new_name)
  -struct-help
        Print command line flags generated by confy (default true)

Environment Variables

For struct:

package main

import (
    "fmt"
    "github.com/NHAS/confy"
)

type Config struct {
    Server struct {
        Host string
    }
}

func main() {
	populatedConfig, _, err := confy.Config[Config](confy.FromEnvs(confy.ENVDelimiter))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

    fmt.Println(populatedConfig.Server.Host)
}

Expected environment variable:

export Server_Host="localhost"
$ ./test
localhost

CLI Flags only

For struct:

package main

import (
    "fmt"
    "github.com/NHAS/confy"
)

type Config struct {
    Database struct {
        Port int
    }
}

func main() {
	populatedConfig, _, err := confy.Config[Config](confy.FromCli(confy.CLIDelimiter))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

    fmt.Println(populatedConfig.Database.Port)
}

Expected CLI flag:

$ ./app -Database.Port=5432
5432

Logging

Confy has logging capabilities using the slog package. Use the WithLogLevel option to adjust verbosity or disable logging.

Configuration Options

Confy offers a variety of options for configuring your application's settings.

Option Description
Defaults(...) Loads configurations in the order: config file -> environment variables -> CLI flags. This sets a non-strict parsing mode for unknown fields in the config file.
FromConfigFile(...) Load configuration from a file. Supports YAML, JSON, and TOML.
FromConfigBytes(...) Load configuration from raw bytes, ideal for embedding configuration in code.
FromConfigURL(...) Load configuration from URL. Supports YAML, JSON, and TOML, use extension or content type to specify type when using auto keyword
FromConfigFileFlagPath(...) Load configuration from file with filepath specified as cli flag
WithStrictParsing(...) Parse config files in a strict way, do not allow unknown fields
FromCli(...) Load configuration from CLI flags. Set a delimiter for nested struct parsing.
WithLogLevel(...) Set logging level to control output verbosity. Useful for debugging.
WithCliTransform(...) Takes a function to run against the generated CLI flag name, allows you to modify the flag name
WithEnvTransform(...) Takes a function to run against the generated ENV variable name, allows you to modify the ENV name

Notes

  • Complex structures must implement encoding.TextUnmarshaler and encoding.TextMarshaler for CLI/ENV parsing.
  • CLI flags and environment variables use the delimiters (. for CLI, _ for ENV by default) when handling nested fields.