bitwarden_state/sdk_managed/
mod.rs1use 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}