Files
HostKeeper/v1/pkg/config/config.go
T
swanadiva 847989df75 refactor: move V1 code into v1/ subdirectory
- git mv cmd/ internal/ pkg/ test/ go.mod go.sum Makefile build.sh docs/ v1/
- Create v1/README.md with V1 documentation
- Update root README for V1 + V2 structure
- V1 still builds (cd v1 && go build ./cmd/hostkeeper) and 105 tests pass
- Root is now clean for V2 development
2026-07-07 11:56:27 +07:00

164 lines
3.9 KiB
Go

package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
"git.tukangketik.id/swanadiva/hostkeeper/internal/models"
)
// Config manages application configuration and paths
type Config struct {
appName string
configDir string
dataDir string
appConfig *models.AppConfig
}
// New creates a new Config instance
func New() (*Config, error) {
appName := "hostkeeper"
configDir, err := getConfigDir(appName)
if err != nil {
return nil, fmt.Errorf("failed to get config directory: %w", err)
}
dataDir := filepath.Join(configDir, "data")
c := &Config{
appName: appName,
configDir: configDir,
dataDir: dataDir,
}
// Create directories
if err := os.MkdirAll(configDir, 0700); err != nil {
return nil, fmt.Errorf("failed to create config directory: %w", err)
}
if err := os.MkdirAll(dataDir, 0700); err != nil {
return nil, fmt.Errorf("failed to create data directory: %w", err)
}
// Load or create config
if err := c.load(); err != nil {
return nil, fmt.Errorf("failed to load config: %w", err)
}
return c, nil
}
// getConfigDir returns the OS-appropriate config directory for the app
func getConfigDir(appName string) (string, error) {
switch runtime.GOOS {
case "darwin":
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "Library", "Application Support", appName), nil
case "linux":
if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" {
return filepath.Join(xdg, appName), nil
}
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".config", appName), nil
case "windows":
appData := os.Getenv("APPDATA")
if appData != "" {
return filepath.Join(appData, appName), nil
}
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "AppData", "Roaming", appName), nil
default:
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "."+appName), nil
}
}
// load reads the config file, or creates a default one if it doesn't exist
func (c *Config) load() error {
configPath := c.GetConfigFilePath()
data, err := os.ReadFile(configPath)
if err != nil {
if os.IsNotExist(err) {
// Create default config
c.appConfig = models.DefaultConfig()
return c.Save()
}
return err
}
c.appConfig = models.DefaultConfig()
if err := json.Unmarshal(data, c.appConfig); err != nil {
return fmt.Errorf("failed to parse config: %w", err)
}
return nil
}
// Save writes the current configuration to disk
func (c *Config) Save() error {
configPath := c.GetConfigFilePath()
data, err := json.MarshalIndent(c.appConfig, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal config: %w", err)
}
return os.WriteFile(configPath, data, 0600)
}
// GetAppConfig returns the application configuration
func (c *Config) GetAppConfig() *models.AppConfig {
return c.appConfig
}
// UpdateAppConfig updates the application configuration
func (c *Config) UpdateAppConfig(cfg *models.AppConfig) error {
c.appConfig = cfg
return c.Save()
}
// GetConfigDir returns the configuration directory path
func (c *Config) GetConfigDir() string {
return c.configDir
}
// GetDataDir returns the data directory path
func (c *Config) GetDataDir() string {
return c.dataDir
}
// GetConfigFilePath returns the full path to the config JSON file
func (c *Config) GetConfigFilePath() string {
return filepath.Join(c.configDir, "config.json")
}
// GetHostsFilePath returns the full path to the hosts JSON file
func (c *Config) GetHostsFilePath() string {
return filepath.Join(c.dataDir, "hosts.json")
}
// GetKeysFilePath returns the full path to the keys JSON file
func (c *Config) GetKeysFilePath() string {
return filepath.Join(c.dataDir, "keys.json")
}
// GetSnippetsFilePath returns the full path to the snippets JSON file
func (c *Config) GetSnippetsFilePath() string {
return filepath.Join(c.dataDir, "snippets.json")
}