bitwarden_core/platform/
state_client.rs

1use std::sync::Arc;
2
3use bitwarden_state::{
4    DatabaseConfiguration, Key, Setting, SettingItem, SettingsError,
5    registry::StateRegistryError,
6    repository::{Repository, RepositoryItem, RepositoryMigrations},
7};
8
9use crate::Client;
10
11/// Wrapper for state specific functionality.
12pub struct StateClient {
13    pub(crate) client: Client,
14}
15
16impl StateClient {
17    /// Register a client managed state repository for a specific type.
18    pub fn register_client_managed<T: 'static + Repository<V>, V: RepositoryItem>(
19        &self,
20        store: Arc<T>,
21    ) {
22        self.client
23            .internal
24            .repository_map
25            .register_client_managed(store)
26    }
27
28    /// Initialize the database for SDK managed repositories.
29    pub async fn initialize_database(
30        &self,
31        configuration: DatabaseConfiguration,
32        migrations: RepositoryMigrations,
33    ) -> Result<(), StateRegistryError> {
34        self.client
35            .internal
36            .repository_map
37            .initialize_database(configuration, migrations)
38            .await
39    }
40
41    /// Get a repository with fallback: prefer client-managed, fall back to SDK-managed.
42    ///
43    /// This method first attempts to retrieve a client-managed repository. If not registered,
44    /// it falls back to an SDK-managed repository. Both are returned as `Arc<dyn Repository<T>>`.
45    ///
46    /// # Errors
47    /// Returns `StateRegistryError` when neither repository type is available.
48    pub fn get<T>(&self) -> Result<Arc<dyn Repository<T>>, StateRegistryError>
49    where
50        T: RepositoryItem,
51    {
52        self.client.internal.repository_map.get()
53    }
54
55    /// Get a handle to a setting by its type-safe key.
56    ///
57    /// Returns a [`Setting`] handle that can be used to get, update, or delete the value.
58    ///
59    /// # Example
60    /// ```rust
61    /// use bitwarden_state::register_setting_key;
62    /// use serde::{Deserialize, Serialize};
63    ///
64    /// #[derive(Serialize, Deserialize)]
65    /// struct AppConfig {
66    ///     theme: String,
67    /// }
68    ///
69    /// register_setting_key!(const CONFIG: AppConfig = "app_config");
70    ///
71    /// # async fn example(client: bitwarden_core::Client) -> Result<(), bitwarden_state::SettingsError> {
72    /// let setting = client.platform().state().setting(CONFIG)?;
73    /// let value: Option<AppConfig> = setting.get().await?;
74    /// # Ok(())
75    /// # }
76    /// ```
77    pub fn setting<T>(&self, key: Key<T>) -> Result<Setting<T>, SettingsError> {
78        let repository = self.client.internal.repository_map.get::<SettingItem>()?;
79        Ok(Setting::new(repository, key))
80    }
81}