diff --git a/internal/settings/service.go b/internal/settings/service.go new file mode 100644 index 0000000..9669207 --- /dev/null +++ b/internal/settings/service.go @@ -0,0 +1,41 @@ +package settings + +import "database/sql" + +type SettingsService struct { + db *sql.DB +} + +func NewSettingsService(db *sql.DB) *SettingsService { + return &SettingsService{db: db} +} + +func (s *SettingsService) Get(key string) (string, error) { + var value string + err := s.db.QueryRow("SELECT value FROM settings WHERE key = ?", key).Scan(&value) + if err == sql.ErrNoRows { + return "", nil + } + return value, err +} + +func (s *SettingsService) GetDefault(key, defaultValue string) string { + val, err := s.Get(key) + if err != nil || val == "" { + return defaultValue + } + return val +} + +func (s *SettingsService) Set(key, value string) error { + _, err := s.db.Exec( + "INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = ?", + key, value, value, + ) + return err +} + +func (s *SettingsService) Delete(key string) error { + _, err := s.db.Exec("DELETE FROM settings WHERE key = ?", key) + return err +} diff --git a/internal/settings/service_test.go b/internal/settings/service_test.go new file mode 100644 index 0000000..9d6e27f --- /dev/null +++ b/internal/settings/service_test.go @@ -0,0 +1,70 @@ +package settings + +import ( + "path/filepath" + "testing" + + "github.com/vstockwell/wraith/internal/db" +) + +func setupTestDB(t *testing.T) *SettingsService { + t.Helper() + d, err := db.Open(filepath.Join(t.TempDir(), "test.db")) + if err != nil { + t.Fatal(err) + } + if err := db.Migrate(d); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { d.Close() }) + return NewSettingsService(d) +} + +func TestSetAndGet(t *testing.T) { + s := setupTestDB(t) + + if err := s.Set("theme", "dracula"); err != nil { + t.Fatalf("Set() error: %v", err) + } + + val, err := s.Get("theme") + if err != nil { + t.Fatalf("Get() error: %v", err) + } + if val != "dracula" { + t.Errorf("Get() = %q, want %q", val, "dracula") + } +} + +func TestGetMissing(t *testing.T) { + s := setupTestDB(t) + + val, err := s.Get("nonexistent") + if err != nil { + t.Fatalf("Get() error: %v", err) + } + if val != "" { + t.Errorf("Get() = %q, want empty string", val) + } +} + +func TestSetOverwrites(t *testing.T) { + s := setupTestDB(t) + + s.Set("key", "value1") + s.Set("key", "value2") + + val, _ := s.Get("key") + if val != "value2" { + t.Errorf("Get() = %q, want %q", val, "value2") + } +} + +func TestGetWithDefault(t *testing.T) { + s := setupTestDB(t) + + val := s.GetDefault("missing", "fallback") + if val != "fallback" { + t.Errorf("GetDefault() = %q, want %q", val, "fallback") + } +}