140 lines
3.2 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|