Files
2026-01-03 14:16:16 -08:00

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)
}