package config import ( "fmt" "os" "strings" "time" "github.com/spf13/viper" ) type Config struct { Server ServerConfig Postgres PostgresConfig Redis RedisConfig Log LogConfig Auth AuthConfig } type ServerConfig struct { Port string } type AuthConfig struct { JWTSecret string } type PostgresConfig struct { DSN string } type RedisConfig struct { Addr string Password string DB int } type LogConfig struct { BatchSize int FlushInterval time.Duration QueueCapacity int } func Load() (*Config, error) { v := viper.New() v.SetDefault("server.port", "8080") v.SetDefault("postgres.dsn", "host=localhost user=postgres password=postgres dbname=ezapi port=5432 sslmode=disable") v.SetDefault("redis.addr", "localhost:6379") v.SetDefault("redis.password", "") v.SetDefault("redis.db", 0) v.SetDefault("log.batch_size", 10) v.SetDefault("log.flush_ms", 1000) v.SetDefault("log.queue_capacity", 10000) v.SetDefault("auth.jwt_secret", "change_me_in_production") v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.AutomaticEnv() _ = v.BindEnv("server.port", "EZ_API_PORT") _ = v.BindEnv("postgres.dsn", "EZ_PG_DSN") _ = v.BindEnv("redis.addr", "EZ_REDIS_ADDR") _ = v.BindEnv("redis.password", "EZ_REDIS_PASSWORD") _ = v.BindEnv("redis.db", "EZ_REDIS_DB") _ = v.BindEnv("log.batch_size", "EZ_LOG_BATCH_SIZE") _ = v.BindEnv("log.flush_ms", "EZ_LOG_FLUSH_MS") _ = v.BindEnv("log.queue_capacity", "EZ_LOG_QUEUE") _ = v.BindEnv("auth.jwt_secret", "EZ_JWT_SECRET") if configFile := os.Getenv("EZ_CONFIG_FILE"); configFile != "" { v.SetConfigFile(configFile) } else { v.SetConfigName("config") v.SetConfigType("yaml") v.AddConfigPath(".") v.AddConfigPath("./config") } if err := v.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); !ok { return nil, fmt.Errorf("read config: %w", err) } } cfg := &Config{ Server: ServerConfig{ Port: v.GetString("server.port"), }, Postgres: PostgresConfig{ DSN: v.GetString("postgres.dsn"), }, Redis: RedisConfig{ Addr: v.GetString("redis.addr"), Password: v.GetString("redis.password"), DB: v.GetInt("redis.db"), }, Log: LogConfig{ BatchSize: v.GetInt("log.batch_size"), FlushInterval: time.Duration(v.GetInt("log.flush_ms")) * time.Millisecond, QueueCapacity: v.GetInt("log.queue_capacity"), }, Auth: AuthConfig{ JWTSecret: v.GetString("auth.jwt_secret"), }, } return cfg, nil }