"""User-settings repository — adapter over ``AsyncSession``.""" import uuid from sqlalchemy.ext.asyncio import AsyncSession from app.domain.entities.settings import UserSettings from app.infrastructure.db.models.user_settings import UserSettingsModel def _to_entity(row: UserSettingsModel) -> UserSettings: return UserSettings( user_id=row.user_id, theme=row.theme, stream_quality=row.stream_quality, scrobble_enabled=row.scrobble_enabled, scrobble_provider=row.scrobble_provider, scrobble_username=row.scrobble_username, scrobble_session_key_enc=row.scrobble_session_key_enc, ) class SqlAlchemyUserSettingsRepository: def __init__(self, session: AsyncSession) -> None: self._session = session async def get(self, user_id: uuid.UUID) -> UserSettings | None: row = await self._session.get(UserSettingsModel, user_id) return _to_entity(row) if row is not None else None async def upsert(self, settings: UserSettings) -> UserSettings: """Create or replace the caller's settings row with ``settings`` in full. The service merges partial updates against current values before calling this, so the write always carries the complete desired state.""" row = await self._session.get(UserSettingsModel, settings.user_id) if row is None: row = UserSettingsModel(user_id=settings.user_id) self._session.add(row) row.theme = settings.theme row.stream_quality = settings.stream_quality row.scrobble_enabled = settings.scrobble_enabled row.scrobble_provider = settings.scrobble_provider row.scrobble_username = settings.scrobble_username row.scrobble_session_key_enc = settings.scrobble_session_key_enc await self._session.flush() await self._session.refresh(row) return _to_entity(row)