package config import ( "crypto/rand" "encoding/hex" "log" "os" "strconv" "github.com/joho/godotenv" ) type Config struct { AdminUsername string AdminPassword string SecretKey string JWTExpireMinutes int DatabaseURL string Port string } var Cfg Config func Load() { // Load .env file from multiple locations (ignore errors if not found) _ = godotenv.Load() _ = godotenv.Load("backend/.env") dbURL := getEnv("DATABASE_URL", "data/airwallex.db") // Strip sqlite:/// prefix if present (Python SQLAlchemy format) for _, prefix := range []string{"sqlite:///./", "sqlite:///", "sqlite://"} { if len(dbURL) > len(prefix) && dbURL[:len(prefix)] == prefix { dbURL = dbURL[len(prefix):] break } } Cfg = Config{ AdminUsername: getEnv("ADMIN_USERNAME", "admin"), AdminPassword: getEnv("ADMIN_PASSWORD", "admin123"), SecretKey: getEnv("SECRET_KEY", generateRandomKey(32)), JWTExpireMinutes: getEnvInt("JWT_EXPIRE_MINUTES", 480), DatabaseURL: dbURL, Port: getEnv("PORT", "8000"), } } func getEnv(key, fallback string) string { if val, ok := os.LookupEnv(key); ok { return val } return fallback } func getEnvInt(key string, fallback int) int { val, ok := os.LookupEnv(key) if !ok { return fallback } n, err := strconv.Atoi(val) if err != nil { log.Printf("warning: invalid integer for %s: %s, using default %d", key, val, fallback) return fallback } return n } func generateRandomKey(length int) string { b := make([]byte, length) if _, err := rand.Read(b); err != nil { log.Fatalf("failed to generate random key: %v", err) } return hex.EncodeToString(b) }