package env import ( . "ersteller-lib" "fmt" "os" "path/filepath" "github.com/joho/godotenv" ) const ( EnvKeyRepositoryType = "REPOSITORY_TYPE" EnvKeyDatabaseURL = "DATABASE_URL" EnvKeySessionSecret = "SESSION_SECRET" EnvKeyBaseURL = "BASE_URL" EnvKeyIsLocal = "IS_LOCAL" EnvKeyIsDev = "IS_DEV" EnvKeyGoogleClientID = "GOOGLE_CLIENT_ID" EnvKeyGoogleClientSecret = "GOOGLE_CLIENT_SECRET" EnvKeyGoogleRedirectURL = "GOOGLE_REDIRECT_URL" EnvKeyKeycloakDiscoveryURL = "KEYCLOAK_DISCOVERY_URL" EnvKeyKeycloakClientID = "KEYCLOAK_CLIENT_ID" EnvKeyKeycloakClientSecret = "KEYCLOAK_CLIENT_SECRET" ) type UrlApiKey struct { Url string ApiKey string } type Environment struct { DatabaseUrl string MistralApiKey string IsDev bool RepositoryType string GoogleSheetsCredPath string GoogleSheetsSpreadId string GoogleSheetsSheetName string GoogleClientId string GoogleClientSecret string GoogleRedirectUrl string IsLocal bool SessionSecret string ApifyKey string Keycloak KeycloakConfig BaseUrl string } type KeycloakConfig struct { DiscoveryUrl string CLientId string ClientSecret string } func LoadEnvironment() Environment { err := godotenv.Load() if err != nil { LogError("Error loading .env file: %v", err) panic(err) } // Default repository type is postgres if not specified repoType := os.Getenv(EnvKeyRepositoryType) if repoType == "" { repoType = "postgres" } return Environment{ DatabaseUrl: os.Getenv(EnvKeyDatabaseURL), IsDev: os.Getenv(EnvKeyIsDev) == "true" || os.Getenv(EnvKeyIsLocal) == "true", RepositoryType: repoType, GoogleClientId: os.Getenv(EnvKeyGoogleClientID), GoogleClientSecret: os.Getenv(EnvKeyGoogleClientSecret), GoogleRedirectUrl: os.Getenv(EnvKeyGoogleRedirectURL), IsLocal: os.Getenv(EnvKeyIsLocal) == "true", SessionSecret: os.Getenv(EnvKeySessionSecret), BaseUrl: os.Getenv(EnvKeyBaseURL), Keycloak: KeycloakConfig{ DiscoveryUrl: os.Getenv(EnvKeyKeycloakDiscoveryURL), CLientId: os.Getenv(EnvKeyKeycloakClientID), ClientSecret: os.Getenv(EnvKeyKeycloakClientSecret), }, } } // EnvKeys returns all environment variable names used by the application configuration. // This allows other packages (e.g., CLI tools) to discover the required keys // without duplicating or hard-coding the list elsewhere. func EnvKeys() []string { return []string{ EnvKeyRepositoryType, EnvKeyDatabaseURL, EnvKeySessionSecret, EnvKeyBaseURL, EnvKeyIsLocal, EnvKeyIsDev, EnvKeyGoogleClientID, EnvKeyGoogleClientSecret, EnvKeyGoogleRedirectURL, EnvKeyKeycloakDiscoveryURL, EnvKeyKeycloakClientID, EnvKeyKeycloakClientSecret, } } // GenerateEnvFile creates a .env file template with all required environment variables // from the EnvKeys function. The file will contain comments and default values where appropriate. func GenerateEnvFile(rootPath string, overwrite bool) error { envPath := filepath.Join(rootPath, ".env") Debug("envPath:", envPath) if !overwrite { if _, err := os.Stat(envPath); err == nil { fmt.Println(".env already exists at:", envPath) fmt.Println("No changes made. Delete or move the existing .env to regenerate.") return fmt.Errorf(".env already exists at: %s", envPath) } } file, err := os.Create(envPath) if err != nil { return fmt.Errorf("failed to create .env file: %w", err) } defer file.Close() // Write header comment _, err = file.WriteString("# Environment Variables Configuration\n") if err != nil { return fmt.Errorf("failed to write to .env file: %w", err) } _, err = file.WriteString("# Generated from EnvKeys function\n\n") if err != nil { return fmt.Errorf("failed to write to .env file: %w", err) } // Get all environment keys keys := EnvKeys() // Define default values and comments for specific keys defaults := map[string]string{ EnvKeyRepositoryType: "postgres", EnvKeyIsLocal: "false", EnvKeyIsDev: "false", } comments := map[string]string{ EnvKeyRepositoryType: "# Repository type (postgres, sqlite, etc.)", EnvKeyDatabaseURL: "# Database connection URL", EnvKeySessionSecret: "# Secret key for session management", EnvKeyBaseURL: "# Base URL of the application", EnvKeyIsLocal: "# Set to true for local development", EnvKeyIsDev: "# Set to true for development mode", EnvKeyGoogleClientID: "# Google OAuth client ID", EnvKeyGoogleClientSecret: "# Google OAuth client secret", EnvKeyGoogleRedirectURL: "# Google OAuth redirect URL", EnvKeyKeycloakDiscoveryURL: "# Keycloak discovery URL", EnvKeyKeycloakClientID: "# Keycloak client ID", EnvKeyKeycloakClientSecret: "# Keycloak client secret", } // Write each environment variable for _, key := range keys { // Write comment if available if comment, exists := comments[key]; exists { _, err = file.WriteString(comment + "\n") if err != nil { return fmt.Errorf("failed to write to .env file: %w", err) } } // Write the environment variable with default value if available if defaultValue, exists := defaults[key]; exists { _, err = file.WriteString(fmt.Sprintf("%s=%s\n", key, defaultValue)) } else { _, err = file.WriteString(fmt.Sprintf("%s=\n", key)) } if err != nil { return fmt.Errorf("failed to write to .env file: %w", err) } } return nil }