// Package config loads the server configuration from environment // variables with sane defaults for local development. package config import ( "fmt" "os" "strings" ) // Config holds all runtime configuration for the API server. type Config struct { // HTTPAddr is the listen address, e.g. ":8080". HTTPAddr string // StaticDir points to the built frontend (React/Vite dist). // Empty disables static file serving. StaticDir string // Environment is "development", "staging" or "production". Environment string // AllowedOrigins is a comma-separated list of CORS origins // allowed to call the API from a browser. AllowedOrigins []string } // Load reads configuration from the environment, falling back to // development-friendly defaults. Unknown values are validated. func Load() (*Config, error) { cfg := &Config{ HTTPAddr: fromEnv("MESSENGER_HTTP_ADDR", ":8080"), StaticDir: os.Getenv("MESSENGER_STATIC_DIR"), Environment: fromEnv("MESSENGER_ENV", "development"), } for _, origin := range strings.Split(fromEnv("MESSENGER_ALLOWED_ORIGINS", ""), ",") { if origin = strings.TrimSpace(origin); origin != "" { cfg.AllowedOrigins = append(cfg.AllowedOrigins, origin) } } switch cfg.Environment { case "development", "staging", "production": default: return nil, fmt.Errorf("MESSENGER_ENV must be one of development|staging|production, got %q", cfg.Environment) } return cfg, nil } // fromEnv returns the value of the environment variable name, or // fallback if the variable is unset or empty. func fromEnv(name, fallback string) string { if v := os.Getenv(name); v != "" { return v } return fallback }