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}