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