package config import ( "fmt" "os" "strconv" "github.com/joho/godotenv" ) // Config holds all configuration for the application. type Config struct { // Server Env string // "development" | "production" Port int // MongoDB (content database) MongoURI string MongoDB string // PostgreSQL (users, relations, URL shortener) PostgresURI string // Meilisearch MeilisearchHost string MeilisearchAPIKey string // DragonflyDB / Redis RedisURI string // AWS S3 S3Region string S3Bucket string S3AccessKey string S3SecretKey string S3Endpoint string // optional — for S3-compatible services (MinIO, etc.) // Push Notifications FCMCredentialsFile string // path to Firebase service account JSON APNsKeyFile string // path to APNs auth key APNsKeyID string APNsTeamID string APNsBundleID string // JWT Auth JWTSecret string JWTExpiration string // e.g., "24h" // Frontend FrontendURL string // for CORS } // Load reads configuration from environment variables (with .env fallback). func Load() (*Config, error) { // Load .env file if present (ignored in production) _ = godotenv.Load() cfg := &Config{ Env: getEnv("APP_ENV", "development"), Port: getEnvInt("PORT", 8080), MongoURI: getEnv("MONGO_URI", ""), MongoDB: getEnv("MONGO_DB", "spsays"), PostgresURI: getEnv("POSTGRES_URI", ""), MeilisearchHost: getEnv("MEILISEARCH_HOST", "http://localhost:7700"), MeilisearchAPIKey: getEnv("MEILISEARCH_API_KEY", ""), RedisURI: getEnv("REDIS_URI", "redis://localhost:6379"), S3Region: getEnv("S3_REGION", ""), S3Bucket: getEnv("S3_BUCKET", ""), S3AccessKey: getEnv("S3_ACCESS_KEY", ""), S3SecretKey: getEnv("S3_SECRET_KEY", ""), S3Endpoint: getEnv("S3_ENDPOINT", ""), FCMCredentialsFile: getEnv("FCM_CREDENTIALS_FILE", ""), APNsKeyFile: getEnv("APNS_KEY_FILE", ""), APNsKeyID: getEnv("APNS_KEY_ID", ""), APNsTeamID: getEnv("APNS_TEAM_ID", ""), APNsBundleID: getEnv("APNS_BUNDLE_ID", ""), JWTSecret: getEnv("JWT_SECRET", ""), JWTExpiration: getEnv("JWT_EXPIRATION", "24h"), FrontendURL: getEnv("FRONTEND_URL", "http://localhost:3000"), } // Validate required fields if cfg.MongoURI == "" { return nil, fmt.Errorf("MONGO_URI is required") } return cfg, nil } func getEnv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } func getEnvInt(key string, fallback int) int { if v := os.Getenv(key); v != "" { if i, err := strconv.Atoi(v); err == nil { return i } } return fallback }