Watch
1
0
Fork
You've already forked gonfig
0
Utilities for reading configuration files
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-15 02:21:55 +02:00
go.mod init 2026-08-15 02:21:55 +02:00
gonfig.go init 2026-08-15 02:21:55 +02:00
LICENSE init 2026-08-15 02:21:55 +02:00
README.md init 2026-08-15 02:21:55 +02:00

gonfig

Utilities for reading configuration files.

Example usage

package main

import (
	"errors"
	"fmt"
	"log/slog"
	"os"
	"slices"

	"github.com/BurntSushi/toml"
	"github.com/hashicorp/go-multierror"
	"hack.moontide.ink/lukas/gonfig"
)

var slogLevels = map[string]slog.Level{
	"debug": slog.LevelDebug,
	"info":  slog.LevelInfo,
	"warn":  slog.LevelWarn,
	"error": slog.LevelError,
}

type config struct {
	LogLevel     string `toml:"log_level"`
	User         string `toml:"user"`
	Interval     int    `toml:"interval"`
	BaseURL      string `toml:"base_url"`
}

func (c *config) Unmarshal(data []byte) error {
	return toml.Unmarshal(data, c)
}

func (c *config) Validate() error {
	merr := &multierror.Error{}

	_, ok := slogLevels[c.LogLevel]
	if !ok {
		merr = multierror.Append(merr, fmt.Errorf(
			"invalid log level %q",
			c.LogLevel,
		))
	}

	if c.User == "" {
		merr = multierror.Append(merr, errors.New(
			"please specify a user",
		))
	}

	mi := 10
	if c.Interval < mi {
		merr = multierror.Append(merr, fmt.Errorf(
			"interval %d is too low, please use a value equal to or greater than %d",
			c.Interval,
			mi,
		))
	}

	if c.BaseURL == "" {
		merr = multierror.Append(merr, errors.New(
			"please specify a base URL",
		))
	}

	return merr.ErrorOrNil()
}

func configure(exp string) config {
	c := config{
		LogLevel: "info",
		Interval: 120,
		BaseURL:  "https://api.example.com/",
	}

	search := slices.Concat(gonfig.UserConfigDirs(), []string{
		"/some/fallback",
	})

	_, err := gonfig.ReadConfig(&c, "progname/config.toml", search, exp)
	if err != nil {
		fmt.Fprintf(os.Stderr, "read config: %s\n", err)
		os.Exit(1)
	}

	return c
}