package config import ( "fmt" "os" "strconv" "time" ) type Config struct { Addr string DatabaseURL string RedisURL string JWTSecret []byte AdminUser string AdminPassword string BooksDir string CacheDir string ScanInterval time.Duration UploadMaxMB int64 } func Load() (*Config, error) { env := func(k, def string) string { if v := os.Getenv(k); v != "" { return v } return def } scanSec, err := strconv.Atoi(env("SCAN_INTERVAL_SEC", "60")) if err != nil { return nil, fmt.Errorf("SCAN_INTERVAL_SEC: %w", err) } uploadMB, err := strconv.ParseInt(env("UPLOAD_MAX_MB", "200"), 10, 64) if err != nil { return nil, fmt.Errorf("UPLOAD_MAX_MB: %w", err) } secret := os.Getenv("JWT_SECRET") if secret == "" { return nil, fmt.Errorf("JWT_SECRET required") } return &Config{ Addr: env("ADDR", ":8080"), DatabaseURL: env("DATABASE_URL", ""), RedisURL: env("REDIS_URL", ""), JWTSecret: []byte(secret), AdminUser: env("ADMIN_USER", ""), AdminPassword: env("ADMIN_PASSWORD", ""), BooksDir: env("BOOKS_DIR", "/data/books"), CacheDir: env("CACHE_DIR", "/data/cache"), ScanInterval: time.Duration(scanSec) * time.Second, UploadMaxMB: uploadMB, }, nil }