bitwarden_state/sdk_managed/
mod.rs

1use bitwarden_error::bitwarden_error;
2use serde::{de::DeserializeOwned, ser::Serialize};
3use thiserror::Error;
4
5use crate::repository::{Repository, RepositoryError, RepositoryItem, RepositoryMigrations};
6
7mod configuration;
8pub use configuration::DatabaseConfiguration;
9
10#[cfg(target_arch = "wasm32")]
11mod indexed_db;
12#[cfg(target_arch = "wasm32")]
13pub(super) type SystemDatabase = indexed_db::IndexedDbDatabase;
14#[cfg(target_arch = "wasm32")]
15type InternalError = ::indexed_db::Error<indexed_db::IndexedDbInternalError>;
16
17#[cfg(not(target_arch = "wasm32"))]
18mod sqlite;
19#[cfg(not(target_arch = "wasm32"))]
20pub(super) type SystemDatabase = sqlite::SqliteDatabase;
21#[cfg(not(target_arch = "wasm32"))]
22type InternalError = ::rusqlite::Error;
23
24#[bitwarden_error(flat)]
25#[derive(Debug, Error)]
26pub enum DatabaseError {
27    #[error("Database not supported on this platform: {0:?}")]
28    UnsupportedConfiguration(DatabaseConfiguration),
29
30    #[error(transparent)]
31    ThreadBoundRunner(#[from] bitwarden_threading::CallError),
32
33    #[error("Serialization error: {0}")]
34    Serialization(#[from] serde_json::Error),
35
36    #[error("JS error: {0}")]
37    JS(String),
38
39    #[error(transparent)]
40    Internal(#[from] InternalError),
41}
42
43pub trait Database {
44    async fn initialize(
45        configuration: DatabaseConfiguration,
46        registrations: RepositoryMigrations,
47    ) -> Result<Self, DatabaseError>
48    where
49        Self: Sized;
50
51    async fn get<T: Serialize + DeserializeOwned + RepositoryItem>(
52        &self,
53        key: &str,
54    ) -> Result<Option<T>, DatabaseError>;
55
56    async fn list<T: Serialize + DeserializeOwned + RepositoryItem>(
57        &self,
58    ) -> Result<Vec<T>, DatabaseError>;
59
60    async fn set<T: Serialize + DeserializeOwned + RepositoryItem>(
61        &self,
62        key: &str,
63        value: T,
64    ) -> Result<(), DatabaseError>;
65
66    async fn remove<T: Serialize + DeserializeOwned + RepositoryItem>(
67        &self,
68        key: &str,
69    ) -> Result<(), DatabaseError>;
70}
71
72struct DBRepository<T: RepositoryItem> {
73    database: SystemDatabase,
74    _marker: std::marker::PhantomData<T>,
75}
76
77#[async_trait::async_trait]
78impl<V: RepositoryItem + Serialize + DeserializeOwned> Repository<V> for DBRepository<V> {
79    async fn get(&self, key: String) -> Result<Option<V>, RepositoryError> {
80        let value = self.database.get::<V>(&key).await?;
81        Ok(value)
82    }
83    async fn list(&self) -> Result<Vec<V>, RepositoryError> {
84        let values = self.database.list::<V>().await?;
85        Ok(values)
86    }
87    async fn set(&self, key: String, value: V) -> Result<(), RepositoryError> {
88        Ok(self.database.set::<V>(&key, value).await?)
89    }
90    async fn remove(&self, key: String) -> Result<(), RepositoryError> {
91        Ok(self.database.remove::<V>(&key).await?)
92    }
93}
94
95impl SystemDatabase {
96    pub(super) fn get_repository<V: RepositoryItem + Serialize + DeserializeOwned>(
97        &self,
98    ) -> Result<impl Repository<V>, DatabaseError> {
99        Ok(DBRepository {
100            database: self.clone(),
101            _marker: std::marker::PhantomData,
102        })
103    }
104}