package config import ( "os" "strconv" "strings" "github.com/joho/godotenv" ) // Config contains the small set of process-level settings needed by the API. type Config struct { DBDriver string Port string APIURL string DatabaseURL string SQLitePath string CORSOrigin string SessionSecret string CookieSecure bool StorageEndpoint string StoragePublicEndpoint string StorageAccessKey string StorageSecretKey string StorageBucket string StorageUseSSL bool } func Load() Config { // Loading is intentionally best-effort: real environment variables still win, // while local commands can be run from either the repository or backend folder. for _, path := range []string{".env", "../.env", "../../.env"} { _ = godotenv.Load(path) } return Config{ DBDriver: envOrDefault("DB_DRIVER", "postgres"), Port: envOrDefault("PORT", "8080"), APIURL: strings.TrimRight(envOrDefault("API_URL", ""), "/"), DatabaseURL: envOrDefault("DATABASE_URL", "postgres://surprise:surprise_dev_password@localhost:5432/surprise?sslmode=disable"), SQLitePath: envOrDefault("SQLITE_PATH", "./data/surprise.db"), CORSOrigin: envOrDefault("CORS_ORIGIN", "http://localhost:5173,http://127.0.0.1:5173"), SessionSecret: envOrDefault("SESSION_SECRET", "local-development-session-secret-change-me"), CookieSecure: parseBoolEnv("COOKIE_SECURE", false), StorageEndpoint: envOrDefault("STORAGE_ENDPOINT", "localhost:9000"), StoragePublicEndpoint: envOrDefault("STORAGE_PUBLIC_ENDPOINT", ""), StorageAccessKey: envOrDefault("STORAGE_ACCESS_KEY", "minioadmin"), StorageSecretKey: envOrDefault("STORAGE_SECRET_KEY", "minioadmin"), StorageBucket: envOrDefault("STORAGE_BUCKET", "gallery-media"), StorageUseSSL: parseBoolEnv("STORAGE_USE_SSL", false), } } func (c Config) DatabaseDSN() string { if strings.EqualFold(c.DBDriver, "sqlite") || strings.EqualFold(c.DBDriver, "sqlite3") { return c.SQLitePath } return c.DatabaseURL } func envOrDefault(key, fallback string) string { if value := strings.TrimSpace(os.Getenv(key)); value != "" { return value } return fallback } func parseBoolEnv(key string, fallback bool) bool { value, err := strconv.ParseBool(strings.TrimSpace(os.Getenv(key))) if err != nil { return fallback } return value }