Files
smart-search-back/internal/config/config.go
vallyenfail 6d238a96ec
Some checks failed
Deploy Smart Search Backend Test / deploy (push) Has been cancelled
add service
2026-01-19 16:24:33 +03:00

106 lines
2.4 KiB
Go

package config
import (
"fmt"
"os"
"regexp"
"gopkg.in/yaml.v3"
)
type Config struct {
Database DatabaseConfig `yaml:"database"`
AI AIConfig `yaml:"ai"`
Security SecurityConfig `yaml:"security"`
Logging LoggingConfig `yaml:"logging"`
}
type DatabaseConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Name string `yaml:"name"`
User string `yaml:"user"`
Password string `yaml:"password"`
SSLMode string `yaml:"ssl_mode"`
MaxConns int `yaml:"max_conns"`
MinConns int `yaml:"min_conns"`
}
type AIConfig struct {
OpenAIKey string `yaml:"openai_key"`
PerplexityKey string `yaml:"perplexity_key"`
}
type SecurityConfig struct {
JWTSecret string `yaml:"jwt_secret"`
CryptoSecret string `yaml:"crypto_secret"`
}
type LoggingConfig struct {
Level string `yaml:"level"`
}
func Load(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
data = []byte(expandEnvWithDefaults(string(data)))
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}
if err := cfg.validate(); err != nil {
return nil, fmt.Errorf("invalid config: %w", err)
}
return &cfg, nil
}
func expandEnvWithDefaults(s string) string {
re := regexp.MustCompile(`\$\{([^:}]+):([^}]*)\}`)
result := re.ReplaceAllStringFunc(s, func(match string) string {
parts := re.FindStringSubmatch(match)
if len(parts) != 3 {
return match
}
envVar := parts[1]
defaultVal := parts[2]
if val := os.Getenv(envVar); val != "" {
return val
}
return defaultVal
})
return os.ExpandEnv(result)
}
func (c *Config) validate() error {
if c.Database.Host == "" {
return fmt.Errorf("database host is required")
}
if c.Database.Name == "" {
return fmt.Errorf("database name is required")
}
if c.Database.User == "" {
return fmt.Errorf("database user is required")
}
if c.Database.Password == "" {
return fmt.Errorf("database password is required")
}
if c.Security.JWTSecret == "" {
return fmt.Errorf("JWT secret is required")
}
if c.Security.CryptoSecret == "" {
return fmt.Errorf("crypto secret is required")
}
return nil
}
func (c *Config) DatabaseURL() string {
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
c.Database.User, c.Database.Password, c.Database.Host, c.Database.Port, c.Database.Name, c.Database.SSLMode)
}