package config import ( "fmt" "os" "strconv" "strings" "time" "github.com/joho/godotenv" ) type Config struct { App AppConfig Database DatabaseConfig JWT JWTConfig Stripe StripeConfig OVH OVHConfig Cloudron CloudronConfig Dolibarr DolibarrConfig Email EmailConfig Redis RedisConfig Logging LoggingConfig Security SecurityConfig } type AppConfig struct { Name string Env string Port string Host string } type DatabaseConfig struct { Host string Port string User string Password string DBName string SSLMode string } type JWTConfig struct { Secret string Expiry time.Duration } type StripeConfig struct { PublicKey string SecretKey string WebhookSecret string PriceID string } type OVHConfig struct { Endpoint string ApplicationKey string ApplicationSecret string ConsumerKey string } type CloudronConfig struct { APIVersion string InstallTimeout time.Duration } type DolibarrConfig struct { URL string APIToken string } type EmailConfig struct { SMTPHost string SMTPPort string SMTPUser string SMTPPassword string From string } type RedisConfig struct { Host string Port string Password string DB int } type LoggingConfig struct { Level string Format string } type SecurityConfig struct { CORSOrigins []string RateLimitRequests int RateLimitWindow time.Duration } func Load() (*Config, error) { // Load .env file if it exists if err := godotenv.Load("configs/.env"); err != nil && !os.IsNotExist(err) { return nil, fmt.Errorf("error loading .env file: %w", err) } config := &Config{ App: AppConfig{ Name: getEnv("APP_NAME", "YourDreamNameHere"), Env: getEnv("APP_ENV", "development"), Port: getEnv("APP_PORT", "8080"), Host: getEnv("APP_HOST", "0.0.0.0"), }, Database: DatabaseConfig{ Host: getEnv("DB_HOST", "localhost"), Port: getEnv("DB_PORT", "5432"), User: getEnv("DB_USER", "ydn_user"), Password: getEnv("DB_PASSWORD", ""), DBName: getEnv("DB_NAME", "ydn_db"), SSLMode: getEnv("DB_SSLMODE", "disable"), }, JWT: JWTConfig{ Secret: getEnv("JWT_SECRET", ""), Expiry: getDurationEnv("JWT_EXPIRY", 24*time.Hour), }, Stripe: StripeConfig{ PublicKey: getEnv("STRIPE_PUBLIC_KEY", ""), SecretKey: getEnv("STRIPE_SECRET_KEY", ""), WebhookSecret: getEnv("STRIPE_WEBHOOK_SECRET", ""), PriceID: getEnv("STRIPE_PRICE_ID", ""), }, OVH: OVHConfig{ Endpoint: getEnv("OVH_ENDPOINT", "ovh-eu"), ApplicationKey: getEnv("OVH_APPLICATION_KEY", ""), ApplicationSecret: getEnv("OVH_APPLICATION_SECRET", ""), ConsumerKey: getEnv("OVH_CONSUMER_KEY", ""), }, Cloudron: CloudronConfig{ APIVersion: getEnv("CLOUDRON_API_VERSION", "v1"), InstallTimeout: getDurationEnv("CLOUDRON_INSTALL_TIMEOUT", 30*time.Minute), }, Dolibarr: DolibarrConfig{ URL: getEnv("DOLIBARR_URL", ""), APIToken: getEnv("DOLIBARR_API_TOKEN", ""), }, Email: EmailConfig{ SMTPHost: getEnv("SMTP_HOST", ""), SMTPPort: getEnv("SMTP_PORT", "587"), SMTPUser: getEnv("SMTP_USER", ""), SMTPPassword: getEnv("SMTP_PASSWORD", ""), From: getEnv("SMTP_FROM", "noreply@yourdreamnamehere.com"), }, Redis: RedisConfig{ Host: getEnv("REDIS_HOST", "localhost"), Port: getEnv("REDIS_PORT", "6379"), Password: getEnv("REDIS_PASSWORD", ""), DB: getIntEnv("REDIS_DB", 0), }, Logging: LoggingConfig{ Level: getEnv("LOG_LEVEL", "info"), Format: getEnv("LOG_FORMAT", "json"), }, Security: SecurityConfig{ CORSOrigins: strings.Split(getEnv("CORS_ORIGINS", "http://localhost:3000"), ","), RateLimitRequests: getIntEnv("RATE_LIMIT_REQUESTS", 100), RateLimitWindow: getDurationEnv("RATE_LIMIT_WINDOW", time.Minute), }, } // Validate required configuration if err := config.validate(); err != nil { return nil, err } return config, nil } func (c *Config) validate() error { if c.JWT.Secret == "" { return fmt.Errorf("JWT_SECRET is required") } if c.Stripe.SecretKey == "" { return fmt.Errorf("STRIPE_SECRET_KEY is required") } if c.Stripe.PriceID == "" { return fmt.Errorf("STRIPE_PRICE_ID is required") } if c.OVH.ApplicationKey == "" { return fmt.Errorf("OVH_APPLICATION_KEY is required") } if c.OVH.ApplicationSecret == "" { return fmt.Errorf("OVH_APPLICATION_SECRET is required") } if c.OVH.ConsumerKey == "" { return fmt.Errorf("OVH_CONSUMER_KEY is required") } return nil } func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } func getIntEnv(key string, defaultValue int) int { if value := os.Getenv(key); value != "" { if intValue, err := strconv.Atoi(value); err == nil { return intValue } } return defaultValue } func getDurationEnv(key string, defaultValue time.Duration) time.Duration { if value := os.Getenv(key); value != "" { if duration, err := time.ParseDuration(value); err == nil { return duration } } return defaultValue } func (c *Config) DatabaseDSN() string { return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s", c.Database.Host, c.Database.Port, c.Database.User, c.Database.Password, c.Database.DBName, c.Database.SSLMode, ) } func (c *Config) IsDevelopment() bool { return c.App.Env == "development" } func (c *Config) IsProduction() bool { return c.App.Env == "production" }