Files
bamort/template/backend/config/config.go
T
2026-04-01 15:16:12 +02:00

140 lines
3.2 KiB
Go

package config
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Config holds all application configuration.
type Config struct {
ServerPort string
DatabaseURL string
DatabaseType string
DebugMode bool
LogLevel string
Environment string
DevTesting string // "yes" or "no"
FrontendURL string // for CORS
// Mail configuration
MailHost string
MailPort int
MailUsername string
MailPassword string
MailFrom string
}
// Cfg is the global configuration variable, loaded once at startup.
var Cfg *Config
func init() {
Cfg = LoadConfig()
}
func defaultConfig() *Config {
return &Config{
ServerPort: "8180",
DatabaseURL: "",
DatabaseType: "mysql",
DebugMode: false,
LogLevel: "INFO",
Environment: "production",
DevTesting: "no",
FrontendURL: "http://localhost:5173",
MailHost: "",
MailPort: 465,
MailUsername: "",
MailPassword: "",
MailFrom: "",
}
}
// LoadConfig reads configuration from .env file and environment variable overrides.
func LoadConfig() *Config {
loadEnvFile()
cfg := defaultConfig()
if port := os.Getenv("SERVER_PORT"); port != "" {
cfg.ServerPort = port
}
if dbURL := os.Getenv("DATABASE_URL"); dbURL != "" {
cfg.DatabaseURL = dbURL
}
if dbType := os.Getenv("DATABASE_TYPE"); dbType != "" {
cfg.DatabaseType = dbType
}
if debug := os.Getenv("DEBUG"); strings.ToLower(debug) == "true" || debug == "1" {
cfg.DebugMode = true
}
if level := os.Getenv("LOG_LEVEL"); level != "" {
cfg.LogLevel = strings.ToUpper(level)
}
if env := os.Getenv("ENVIRONMENT"); env != "" {
cfg.Environment = env
}
if dt := os.Getenv("DEV_TESTING"); dt != "" {
cfg.DevTesting = dt
}
if frontendURL := os.Getenv("FRONTEND_URL"); frontendURL != "" {
cfg.FrontendURL = frontendURL
}
if host := os.Getenv("MAIL_HOST"); host != "" {
cfg.MailHost = host
}
if port := os.Getenv("MAIL_PORT"); port != "" {
if p, err := strconv.Atoi(port); err == nil {
cfg.MailPort = p
}
}
if user := os.Getenv("MAIL_USERNAME"); user != "" {
cfg.MailUsername = user
}
if pass := os.Getenv("MAIL_PASSWORD"); pass != "" {
cfg.MailPassword = pass
}
if from := os.Getenv("MAIL_FROM"); from != "" {
cfg.MailFrom = from
}
return cfg
}
// IsProduction returns true when environment is "production".
func (c *Config) IsProduction() bool {
return strings.ToLower(c.Environment) == "production"
}
// GetServerAddress returns the address string for http.Server.
func (c *Config) GetServerAddress() string {
return fmt.Sprintf(":%s", c.ServerPort)
}
// loadEnvFile reads key=value pairs from .env then .env.local files into the process environment.
func loadEnvFile() {
for _, filename := range []string{".env", ".env.local"} {
f, err := os.Open(filename)
if err != nil {
continue
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
val := strings.TrimSpace(parts[1])
if os.Getenv(key) == "" {
os.Setenv(key, val)
}
}
}
}