"""Store client for supervisor.""" from typing import Any from .client import _SupervisorComponentClient from .const import ResponseType from .models.addons import ( Repository, StoreAddon, StoreAddonComplete, StoreAddonInstall, StoreAddonsList, StoreAddonUpdate, StoreAddRepository, StoreInfo, ) class StoreClient(_SupervisorComponentClient): """Handles store access in Supervisor.""" async def info(self) -> StoreInfo: """Get store info.""" result = await self._client.get("store") return StoreInfo.from_dict(result.data) async def addons_list(self) -> list[StoreAddon]: """Get list of store addons.""" result = await self._client.get("store/addons") return StoreAddonsList.from_dict(result.data).addons async def addon_info(self, addon: str) -> StoreAddonComplete: """Get store addon info.""" result = await self._client.get(f"store/addons/{addon}") return StoreAddonComplete.from_dict(result.data) async def addon_changelog(self, addon: str) -> str: """Get addon changelog.""" result = await self._client.get( f"store/addons/{addon}/changelog", response_type=ResponseType.TEXT ) return result.data async def addon_documentation(self, addon: str) -> str: """Get addon documentation.""" result = await self._client.get( f"store/addons/{addon}/documentation", response_type=ResponseType.TEXT ) return result.data async def addon_availability(self, addon: str) -> None: """Determine if latest version of addon can be installed on this system. No return means it can be. If not, raises one of the following errors: - AddonUnavailableHomeAssistantVersionError - AddonUnavailableArchitectureError - AddonUnavailableMachineTypeError If Supervisor adds a new reason an add-on can be restricted from being installed on some systems in the future, older versions of this client will raise the generic SupervisorBadRequestError for that reason. """ await self._client.get( f"store/addons/{addon}/availability", response_type=ResponseType.NONE ) async def install_addon( self, addon: str, options: StoreAddonInstall | None = None ) -> None: """Install an addon. Supervisor does an availability check before install. If the addon cannot be installed on this system it will raise one of those errors shown in the `addon_availability` method. """ # Must disable timeout if API call waits for install to complete kwargs: dict[str, Any] = {} if not options or not options.background: kwargs["timeout"] = None await self._client.post( f"store/addons/{addon}/install", json=options.to_dict() if options else None, **kwargs, ) async def update_addon( self, addon: str, options: StoreAddonUpdate | None = None ) -> None: """Update an addon to latest version. Supervisor does an availability check before update. If the new version cannot be installed on this system it will raise one of those errors shown in the `addon_availability` method. """ # Must disable timeout if API call waits for update to complete kwargs: dict[str, Any] = {} if not options or not options.background: kwargs["timeout"] = None await self._client.post( f"store/addons/{addon}/update", json=options.to_dict() if options else None, **kwargs, ) async def reload(self) -> None: """Reload the store.""" await self._client.post("store/reload") async def repositories_list(self) -> list[Repository]: """Get list of repositories.""" result = await self._client.get("store/repositories") # This API is inconsistent with Supervisor's API model, data should be # a dictionary with a "repositories" field. It would break the CLI like # this but the CLI doesn't use it so it went unnoticed. return [Repository.from_dict(repo) for repo in result.data] async def repository_info(self, repository: str) -> Repository: """Get repository info.""" result = await self._client.get(f"store/repositories/{repository}") return Repository.from_dict(result.data) async def add_repository(self, options: StoreAddRepository) -> None: """Add a repository to the store.""" await self._client.post("store/repositories", json=options.to_dict()) async def remove_repository(self, repository: str) -> None: """Remove a repository from the store.""" await self._client.delete(f"store/repositories/{repository}") async def repair_repository(self, repository: str) -> None: """Repair/reset an addon repository in the store.""" await self._client.post(f"store/repositories/{repository}/repair") # Omitted for now - Icon/Logo endpoints