77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/kelseyhightower/envconfig"
|
|
)
|
|
|
|
// Config holds all application configuration
|
|
type Config struct {
|
|
// Database configuration
|
|
DatabaseURL string `envconfig:"DATABASE_URL" required:"true"`
|
|
|
|
// Server configuration
|
|
Port int `envconfig:"PORT" default:"8080"`
|
|
|
|
// Location configuration
|
|
LocationLat float64 `envconfig:"LOCATION_LAT" default:"37.7749"`
|
|
LocationLon float64 `envconfig:"LOCATION_LON" default:"-122.4194"`
|
|
LocationName string `envconfig:"LOCATION_NAME" default:"San Francisco"`
|
|
|
|
// Timezone configuration
|
|
Timezone string `envconfig:"TIMEZONE" default:"America/Los_Angeles"`
|
|
|
|
// Weather fetcher configuration
|
|
FetchInterval time.Duration `envconfig:"FETCH_INTERVAL" default:"15m"`
|
|
|
|
// Cache configuration
|
|
CacheTTL time.Duration `envconfig:"CACHE_TTL" default:"10m"`
|
|
}
|
|
|
|
// Load reads configuration from environment variables
|
|
func Load() (*Config, error) {
|
|
var cfg Config
|
|
if err := envconfig.Process("", &cfg); err != nil {
|
|
return nil, fmt.Errorf("failed to process environment config: %w", err)
|
|
}
|
|
|
|
// Validate configuration
|
|
if err := cfg.validate(); err != nil {
|
|
return nil, fmt.Errorf("invalid configuration: %w", err)
|
|
}
|
|
|
|
return &cfg, nil
|
|
}
|
|
|
|
// validate checks that configuration values are valid
|
|
func (c *Config) validate() error {
|
|
if c.Port < 1 || c.Port > 65535 {
|
|
return fmt.Errorf("port must be between 1 and 65535, got %d", c.Port)
|
|
}
|
|
|
|
if c.LocationLat < -90 || c.LocationLat > 90 {
|
|
return fmt.Errorf("location latitude must be between -90 and 90, got %f", c.LocationLat)
|
|
}
|
|
|
|
if c.LocationLon < -180 || c.LocationLon > 180 {
|
|
return fmt.Errorf("location longitude must be between -180 and 180, got %f", c.LocationLon)
|
|
}
|
|
|
|
if c.FetchInterval < time.Minute {
|
|
return fmt.Errorf("fetch interval must be at least 1 minute, got %s", c.FetchInterval)
|
|
}
|
|
|
|
if c.CacheTTL < time.Second {
|
|
return fmt.Errorf("cache TTL must be at least 1 second, got %s", c.CacheTTL)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Addr returns the server address in host:port format
|
|
func (c *Config) Addr() string {
|
|
return fmt.Sprintf(":%d", c.Port)
|
|
}
|