package config import ( "encoding/json" "fmt" "os" "path/filepath" "time" ) type Config struct { APIKey string BaseURL string Timeout time.Duration MaxRetries int UserAgent string } type FileConfig struct { APIKey string `json:"api_key"` } func New() *Config { apiKey := os.Getenv("DBORG_API_KEY") if apiKey == "" { if fileCfg, err := LoadConfig(); err == nil && fileCfg.APIKey != "" { apiKey = fileCfg.APIKey } } return &Config{ APIKey: apiKey, BaseURL: "https://db.org.ai", Timeout: 30 * time.Second, MaxRetries: 3, UserAgent: "dborg-cli/1.0", } } func (c *Config) WithAPIKey(key string) *Config { if key != "" { c.APIKey = key } return c } func (c *Config) Validate() error { if c.APIKey == "" { return ErrMissingAPIKey } return nil } func GetConfigPath() (string, error) { homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("failed to get home directory: %w", err) } configDir := filepath.Join(homeDir, ".config", "dborg") if err := os.MkdirAll(configDir, 0755); err != nil { return "", fmt.Errorf("failed to create config directory: %w", err) } return filepath.Join(configDir, "config.json"), nil } func LoadConfig() (*FileConfig, error) { configPath, err := GetConfigPath() if err != nil { return nil, err } data, err := os.ReadFile(configPath) if err != nil { if os.IsNotExist(err) { return &FileConfig{}, nil } return nil, fmt.Errorf("failed to read config file: %w", err) } var cfg FileConfig if err := json.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("failed to parse config file: %w", err) } return &cfg, nil } func SaveConfig(cfg *FileConfig) error { configPath, err := GetConfigPath() if err != nil { return err } data, err := json.MarshalIndent(cfg, "", " ") if err != nil { return fmt.Errorf("failed to marshal config: %w", err) } if err := os.WriteFile(configPath, data, 0600); err != nil { return fmt.Errorf("failed to write config file: %w", err) } return nil }