package config import ( "fmt" "os" "github.com/joho/godotenv" ) // Config holds all configuration values for the application. // Each field maps to an environment variable defined in .env. type Config struct { // Server settings Port string // PORT — the port the HTTP server listens on Environment string // ENVIRONMENT — dev, stage, or prod // Database settings DBHost string // DB_HOST DBPort string // DB_PORT DBUser string // DB_USER DBPassword string // DB_PASSWORD DBName string // DB_NAME DBSSLMode string // DB_SSLMODE } // LoadConfig reads the .env file and returns a populated Config struct. // It returns an error if the .env file is missing or a required variable is empty. func LoadConfig() (*Config, error) { // Load .env file into environment variables err := godotenv.Load() if err != nil { return nil, fmt.Errorf("error loading .env file: %w", err) } // Build the config from environment variables cfg := &Config{ Port: getEnv("PORT", "4000"), Environment: getEnv("ENVIRONMENT", "dev"), DBHost: getEnv("DB_HOST", ""), DBPort: getEnv("DB_PORT", "5432"), DBUser: getEnv("DB_USER", ""), DBPassword: getEnv("DB_PASSWORD", ""), DBName: getEnv("DB_NAME", ""), DBSSLMode: getEnv("DB_SSLMODE", "disable"), } // Validate that critical database fields are not empty if cfg.DBHost == "" || cfg.DBUser == "" || cfg.DBPassword == "" || cfg.DBName == "" { return nil, fmt.Errorf("missing required database configuration (DB_HOST, DB_USER, DB_PASSWORD, or DB_NAME)") } return cfg, nil } // DatabaseURL builds a PostgreSQL connection string from the config fields. func (c *Config) DatabaseURL() string { return fmt.Sprintf( "postgres://%s:%s@%s:%s/%s?sslmode=%s", c.DBUser, c.DBPassword, c.DBHost, c.DBPort, c.DBName, c.DBSSLMode, ) } // getEnv reads an environment variable or returns a default value. func getEnv(key, defaultValue string) string { value := os.Getenv(key) if value == "" { return defaultValue } return value }