# Environment-Based Configuration System This package provides a configuration system for the Tender Management backend that loads configuration exclusively from `.env` files. It maintains the same structure as the previous YAML-based system while using environment variables for all configuration values. ## Architecture ### Base Configuration (`BaseConfig`) The configuration system provides common configuration structs that are used across all commands: - **ServerConfig**: HTTP server configuration (host, port, timeouts) - **DatabaseConfig**: MongoDB connection configuration - **CacheConfig**: Redis connection configuration - **LoggingConfig**: Logging system configuration - **RateLimitConfig**: Rate limiting configuration ### Command-Specific Configuration Each command can extend the base configuration by embedding the common configs and adding their own specific configuration fields. ## Usage ### 1. Create Command-Specific Config Create a config file for your command (e.g., `cmd/yourcommand/config.go`): ```go package main import ( "time" "tm/pkg/config" ) // Config holds configuration for your command type Config struct { config.ServerConfig config.DatabaseConfig config.CacheConfig config.LoggingConfig YourSpecific YourSpecificConfig } type YourSpecificConfig struct { SomeField string `env:"SOME_FIELD"` SomeTimeout time.Duration `env:"SOME_TIMEOUT"` SomeNumber int `env:"SOME_NUMBER"` } ``` ### 2. Load Configuration In your command's `main.go` or bootstrap file: ```go func initConfig() Config { conf, err := config.LoadConfig(".", &Config{}) if err != nil { panic(fmt.Sprintf("Failed to load config: %v", err)) } return *conf } ``` ### 3. Create .env Configuration File Create a `.env` file in your command directory: ```env # Server Configuration SERVER_HOST=localhost SERVER_PORT=8080 SERVER_TIMEOUT=30s SERVER_READ_TIMEOUT=10s SERVER_WRITE_TIMEOUT=10s # Database Configuration MONGODB_URI=mongodb://localhost:27017 MONGODB_NAME=your_database MONGODB_TIMEOUT=10s MONGODB_MAX_POOL_SIZE=100 # Cache Configuration REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= REDIS_DB=0 REDIS_POOL_SIZE=10 # Logging Configuration LOG_LEVEL=info LOG_FORMAT=json LOG_OUTPUT=stdout LOG_FILE_PATH=/var/log/tm/your-command.log LOG_FILE_MAX_SIZE=100 LOG_FILE_MAX_BACKUPS=5 LOG_FILE_MAX_AGE=30 LOG_FILE_COMPRESS=true # Your command-specific configuration SOME_FIELD=value SOME_TIMEOUT=30s SOME_NUMBER=42 ``` ## Examples ### Web Command Config ```go type Config struct { config.ServerConfig config.DatabaseConfig config.CacheConfig config.LoggingConfig config.RateLimitConfig UserAuth AuthConfig CustomerAuth AuthConfig Assets AssetsConfig } type AuthConfig struct { JWT JWTConfig } type JWTConfig struct { AccessSecret string `env:"USER_AUTH_ACCESS_SECRET"` RefreshSecret string `env:"USER_AUTH_REFRESH_SECRET"` AccessExpiresIn int `env:"USER_AUTH_ACCESS_EXPIRES_IN"` RefreshExpiresIn int `env:"USER_AUTH_REFRESH_EXPIRES_IN"` } type AssetsConfig struct { FlagsPath string `env:"ASSETS_FLAGS_PATH"` } ``` ### Scraper Command Config ```go type Config struct { config.DatabaseConfig config.LoggingConfig TED ScraperConfig } type ScraperConfig struct { BaseURL string `env:"TED_BASE_URL"` Timeout time.Duration `env:"TED_TIMEOUT"` MaxRetries int `env:"TED_MAX_RETRIES"` RetryDelay time.Duration `env:"TED_RETRY_DELAY"` UserAgent string `env:"TED_USER_AGENT"` MaxConcurrency int `env:"TED_MAX_CONCURRENCY"` DownloadDir string `env:"TED_DOWNLOAD_DIR"` CleanupAfter time.Duration `env:"TED_CLEANUP_AFTER"` ScrapingInterval time.Duration `env:"TED_SCRAPING_INTERVAL"` } ``` ## Features ### Type Safety The configuration loader uses Go generics to provide type-safe configuration loading. The function signature ensures that you get back exactly the type you expect. ### Environment Variable Support The configuration system loads all values from `.env` files using the `github.com/subosito/gotenv` library. ### Reflection-Based Parsing The system uses reflection to automatically parse environment variables into struct fields based on the `env` tags. ### Supported Types The configuration system supports the following Go types: - `string` - `int`, `int8`, `int16`, `int32`, `int64` - `bool` - `float32`, `float64` - `time.Duration` (parsed from strings like "30s", "1h", "5m") ## Best Practices 1. **Use descriptive environment variable names**: Choose clear, descriptive names for your environment variables (e.g., `MONGODB_URI` instead of `DB_URI`). 2. **Use consistent naming conventions**: Use uppercase with underscores for environment variable names (e.g., `SERVER_HOST`, `LOG_LEVEL`). 3. **Group related variables**: Use prefixes to group related configuration (e.g., `MONGODB_*`, `REDIS_*`, `LOG_*`). 4. **Document your configuration**: Add comments in your `.env` files explaining what each variable does. 5. **Use appropriate types**: Use `time.Duration` for durations, proper numeric types for numbers, etc. 6. **Provide sensible defaults**: Consider providing sensible defaults in your code when environment variables are not set. ## Migration from YAML System If you're migrating from the old YAML-based configuration system: 1. Remove `mapstructure` tags from your config structs 2. Add `env` tags to your config struct fields 3. Create `.env` files instead of `config.yaml` files 4. Update your `LoadConfig` calls to use the new system 5. Update function signatures to use the new config types Example migration: ```go // Old way (YAML) type Config struct { Server config.ServerConfig `mapstructure:"server"` Database config.DatabaseConfig `mapstructure:"database"` } // New way (.env) type Config struct { Server config.ServerConfig Database config.DatabaseConfig } // Old way (YAML loading) conf, err := config.LoadConfig(".", &Config{}) // New way (.env loading) conf, err := config.LoadConfig(".", &Config{}) ``` ## Environment Variable Naming Convention The system follows these naming conventions: - **Server**: `SERVER_*` (e.g., `SERVER_HOST`, `SERVER_PORT`) - **Database**: `MONGODB_*` (e.g., `MONGODB_URI`, `MONGODB_NAME`) - **Cache**: `REDIS_*` (e.g., `REDIS_HOST`, `REDIS_PORT`) - **Logging**: `LOG_*` (e.g., `LOG_LEVEL`, `LOG_FORMAT`) - **Rate Limiting**: `RATE_LIMIT_*` (e.g., `RATE_LIMIT_REQUESTS_PER_MINUTE`) ## Error Handling The configuration system provides detailed error messages when: - The `.env` file cannot be loaded - Environment variables cannot be parsed into the expected types - Required fields are missing (handled by your application logic) ## Security Considerations 1. **Never commit `.env` files**: Add `.env` to your `.gitignore` file 2. **Use environment-specific files**: Create different `.env` files for different environments (`.env.local`, `.env.production`, etc.) 3. **Validate sensitive values**: Always validate sensitive configuration values like API keys and database URIs 4. **Use secure defaults**: Provide secure default values for security-related configuration