// Package config loads application configuration from // environment variables, .env files, and config files. package config import ( "errors" "log/slog" "sneak.berlin/go/netwatch/internal/globals" "sneak.berlin/go/netwatch/internal/logger" _ "github.com/joho/godotenv/autoload" // loads .env file "github.com/spf13/viper" "go.uber.org/fx" ) // Params defines the dependencies for Config. type Params struct { fx.In Globals *globals.Globals Logger *logger.Logger } // Config holds the resolved application configuration. type Config struct { DataDir string Debug bool MetricsPassword string MetricsUsername string Port int SentryDSN string log *slog.Logger params *Params } // New loads configuration from env, .env files, and config // files, returning a fully resolved Config. func New( _ fx.Lifecycle, params Params, ) (*Config, error) { log := params.Logger.Get() name := params.Globals.Appname viper.SetConfigName(name) viper.SetConfigType("yaml") viper.AddConfigPath("/etc/" + name) viper.AddConfigPath("$HOME/.config/" + name) viper.AutomaticEnv() viper.SetDefault("DATA_DIR", "./data/reports") viper.SetDefault("DEBUG", "false") viper.SetDefault("PORT", "8080") viper.SetDefault("SENTRY_DSN", "") viper.SetDefault("METRICS_USERNAME", "") viper.SetDefault("METRICS_PASSWORD", "") err := viper.ReadInConfig() if err != nil { var notFound viper.ConfigFileNotFoundError if !errors.As(err, ¬Found) { log.Error("config file malformed", "error", err) panic(err) } } s := &Config{ DataDir: viper.GetString("DATA_DIR"), Debug: viper.GetBool("DEBUG"), MetricsPassword: viper.GetString("METRICS_PASSWORD"), MetricsUsername: viper.GetString("METRICS_USERNAME"), Port: viper.GetInt("PORT"), SentryDSN: viper.GetString("SENTRY_DSN"), log: log, params: ¶ms, } if s.Debug { params.Logger.EnableDebugLogging() s.log = params.Logger.Get() } return s, nil }