#![cfg_attr(not(target_family = "wasm"), allow(unused))]
#[cfg(feature = "state-store")]
use matrix_sdk_base::store::StoreError;
use thiserror::Error;
#[cfg(feature = "e2e-encryption")]
mod crypto_store;
mod error;
#[cfg(feature = "event-cache-store")]
mod event_cache_store;
#[cfg(feature = "media-store")]
mod media_store;
mod serializer;
#[cfg(feature = "state-store")]
mod state_store;
#[cfg(any(feature = "event-cache-store", feature = "media-store"))]
mod transaction;
#[cfg(feature = "e2e-encryption")]
pub use crypto_store::{IndexeddbCryptoStore, IndexeddbCryptoStoreError};
#[cfg(feature = "state-store")]
pub use state_store::{
IndexeddbStateStore, IndexeddbStateStoreBuilder, IndexeddbStateStoreError,
MigrationConflictStrategy,
};
#[cfg(feature = "event-cache-store")]
pub use crate::event_cache_store::{
IndexeddbEventCacheStore, IndexeddbEventCacheStoreBuilder, IndexeddbEventCacheStoreError,
};
#[cfg(feature = "media-store")]
pub use crate::media_store::{
IndexeddbMediaStore, IndexeddbMediaStoreBuilder, IndexeddbMediaStoreError,
};
pub struct IndexeddbStores {
#[cfg(feature = "e2e-encryption")]
pub crypto: IndexeddbCryptoStore,
#[cfg(feature = "state-store")]
pub state: IndexeddbStateStore,
#[cfg(feature = "event-cache-store")]
pub event_cache: IndexeddbEventCacheStore,
#[cfg(feature = "media-store")]
pub media: IndexeddbMediaStore,
}
impl IndexeddbStores {
pub async fn open(
name: &str,
#[allow(unused_variables)] passphrase: Option<&str>,
) -> Result<Self, OpenStoreError> {
#[cfg(all(feature = "e2e-encryption", feature = "state-store"))]
if let Some(passphrase) = passphrase {
return Self::open_with_passphrase(name, passphrase).await;
}
Self::open_without_passphrase(name).await
}
#[allow(clippy::unused_async)]
pub async fn open_without_passphrase(name: &str) -> Result<Self, OpenStoreError> {
#[cfg(feature = "state-store")]
let state = IndexeddbStateStore::builder()
.name(name.to_owned())
.build()
.await
.map_err(StoreError::from)?;
#[cfg(feature = "e2e-encryption")]
let crypto = IndexeddbCryptoStore::open_with_name(name).await?;
#[cfg(feature = "event-cache-store")]
let event_cache = IndexeddbEventCacheStoreBuilder::with_prefix(name).build().await?;
#[cfg(feature = "media-store")]
let media = IndexeddbMediaStoreBuilder::with_prefix(name).build().await?;
Ok(Self {
#[cfg(feature = "state-store")]
state,
#[cfg(feature = "e2e-encryption")]
crypto,
#[cfg(feature = "event-cache-store")]
event_cache,
#[cfg(feature = "media-store")]
media,
})
}
#[cfg(all(feature = "e2e-encryption", feature = "state-store"))]
pub async fn open_with_passphrase(
name: &str,
passphrase: &str,
) -> Result<Self, OpenStoreError> {
let state = IndexeddbStateStore::builder()
.name(name.to_owned())
.passphrase(passphrase.to_owned())
.build()
.await
.map_err(StoreError::from)?;
let store_cipher =
state.store_cipher.clone().ok_or(OpenStoreError::FailedToLoadStoreCipher)?;
let crypto =
IndexeddbCryptoStore::open_with_store_cipher(name, Some(store_cipher.clone())).await?;
#[cfg(feature = "event-cache-store")]
let event_cache = IndexeddbEventCacheStoreBuilder::with_prefix(name)
.store_cipher(store_cipher.clone())
.build()
.await?;
#[cfg(feature = "media-store")]
let media = IndexeddbMediaStoreBuilder::with_prefix(name)
.store_cipher(store_cipher.clone())
.build()
.await?;
Ok(Self {
state,
crypto,
#[cfg(feature = "event-cache-store")]
event_cache,
#[cfg(feature = "media-store")]
media,
})
}
}
#[deprecated(
note = "this function only opens state and crypto stores, use `IndexeddbStores::open()` instead."
)]
#[cfg(all(feature = "e2e-encryption", feature = "state-store"))]
pub async fn open_stores_with_name(
name: &str,
passphrase: Option<&str>,
) -> Result<(IndexeddbStateStore, IndexeddbCryptoStore), OpenStoreError> {
let mut builder = IndexeddbStateStore::builder().name(name.to_owned());
if let Some(passphrase) = passphrase {
builder = builder.passphrase(passphrase.to_owned());
}
let state_store = builder.build().await.map_err(StoreError::from)?;
let crypto_store =
IndexeddbCryptoStore::open_with_store_cipher(name, state_store.store_cipher.clone())
.await?;
Ok((state_store, crypto_store))
}
#[cfg(feature = "state-store")]
pub async fn open_state_store(
name: &str,
passphrase: Option<&str>,
) -> Result<IndexeddbStateStore, OpenStoreError> {
let mut builder = IndexeddbStateStore::builder().name(name.to_owned());
if let Some(passphrase) = passphrase {
builder = builder.passphrase(passphrase.to_owned());
}
let state_store = builder.build().await.map_err(StoreError::from)?;
Ok(state_store)
}
#[derive(Error, Debug)]
pub enum OpenStoreError {
#[cfg(feature = "state-store")]
#[error(transparent)]
State(#[from] StoreError),
#[cfg(feature = "e2e-encryption")]
#[error(transparent)]
Crypto(#[from] IndexeddbCryptoStoreError),
#[cfg(feature = "e2e-encryption")]
#[error("failed to load store cipher")]
FailedToLoadStoreCipher,
#[cfg(feature = "event-cache-store")]
#[error(transparent)]
Event(#[from] IndexeddbEventCacheStoreError),
#[cfg(feature = "media-store")]
#[error(transparent)]
Media(#[from] IndexeddbMediaStoreError),
}