mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-04-01 17:13:13 +00:00
chore: sqlite rename
This commit is contained in:
parent
9a90e86cb3
commit
927be286e8
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -108,17 +108,6 @@ dependencies = [
|
|||||||
"prost",
|
"prost",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "chat-sqlite"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"crypto",
|
|
||||||
"hex",
|
|
||||||
"storage",
|
|
||||||
"tempfile",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cipher"
|
name = "cipher"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@ -513,13 +502,13 @@ dependencies = [
|
|||||||
"base64",
|
"base64",
|
||||||
"blake2",
|
"blake2",
|
||||||
"chat-proto",
|
"chat-proto",
|
||||||
"chat-sqlite",
|
|
||||||
"crypto",
|
"crypto",
|
||||||
"double-ratchets",
|
"double-ratchets",
|
||||||
"hex",
|
"hex",
|
||||||
"prost",
|
"prost",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"safer-ffi",
|
"safer-ffi",
|
||||||
|
"sqlite",
|
||||||
"storage",
|
"storage",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@ -902,6 +891,17 @@ dependencies = [
|
|||||||
"der",
|
"der",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sqlite"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"crypto",
|
||||||
|
"hex",
|
||||||
|
"storage",
|
||||||
|
"tempfile",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stabby"
|
name = "stabby"
|
||||||
version = "36.2.2"
|
version = "36.2.2"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"core/chat-sqlite",
|
"core/sqlite",
|
||||||
"core/conversations",
|
"core/conversations",
|
||||||
"core/crypto",
|
"core/crypto",
|
||||||
"core/double-ratchets",
|
"core/double-ratchets",
|
||||||
|
|||||||
@ -8,7 +8,7 @@ crate-type = ["rlib","staticlib","dylib"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.22"
|
base64 = "0.22"
|
||||||
chat-sqlite = { path = "../chat-sqlite" }
|
sqlite = { path = "../sqlite" }
|
||||||
blake2.workspace = true
|
blake2.workspace = true
|
||||||
chat-proto = { git = "https://github.com/logos-messaging/chat_proto" }
|
chat-proto = { git = "https://github.com/logos-messaging/chat_proto" }
|
||||||
crypto = { path = "../crypto" }
|
crypto = { path = "../crypto" }
|
||||||
|
|||||||
@ -13,7 +13,7 @@ use safer_ffi::{
|
|||||||
prelude::{c_slice, repr_c},
|
prelude::{c_slice, repr_c},
|
||||||
};
|
};
|
||||||
|
|
||||||
use chat_sqlite::ChatStorage;
|
use sqlite::ChatStorage;
|
||||||
use storage::StorageConfig;
|
use storage::StorageConfig;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use chat_sqlite::ChatStorage;
|
|
||||||
use crypto::Identity;
|
use crypto::Identity;
|
||||||
use double_ratchets::{RatchetState, RatchetStorage};
|
use double_ratchets::{RatchetState, RatchetStorage};
|
||||||
use storage::{
|
use sqlite::ChatStorage;
|
||||||
ChatStore, ConversationKind, ConversationMeta, IdentityStore, StorageConfig,
|
use storage::{ChatStore, ConversationKind, ConversationMeta, IdentityStore, StorageConfig};
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
conversation::{ConversationId, Convo, Id, PrivateV1Convo},
|
conversation::{ConversationId, Convo, Id, PrivateV1Convo},
|
||||||
@ -24,7 +22,7 @@ pub use crate::inbox::Introduction;
|
|||||||
pub struct Context<T: ChatStore> {
|
pub struct Context<T: ChatStore> {
|
||||||
_identity: Rc<Identity>,
|
_identity: Rc<Identity>,
|
||||||
inbox: Inbox,
|
inbox: Inbox,
|
||||||
storage: T,
|
store: T,
|
||||||
ratchet_storage: RatchetStorage,
|
ratchet_storage: RatchetStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +55,7 @@ impl<T: ChatStore> Context<T> {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
_identity: identity,
|
_identity: identity,
|
||||||
inbox,
|
inbox,
|
||||||
storage: store,
|
store,
|
||||||
ratchet_storage,
|
ratchet_storage,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -95,7 +93,7 @@ impl<T: ChatStore> Context<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_conversations(&self) -> Result<Vec<ConversationIdOwned>, ChatError> {
|
pub fn list_conversations(&self) -> Result<Vec<ConversationIdOwned>, ChatError> {
|
||||||
let records = self.storage.load_conversations()?;
|
let records = self.store.load_conversations()?;
|
||||||
Ok(records
|
Ok(records
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|r| Arc::from(r.local_convo_id.as_str()))
|
.map(|r| Arc::from(r.local_convo_id.as_str()))
|
||||||
@ -128,7 +126,7 @@ impl<T: ChatStore> Context<T> {
|
|||||||
let enc = EncryptedPayload::decode(env.payload)?;
|
let enc = EncryptedPayload::decode(env.payload)?;
|
||||||
match convo_id {
|
match convo_id {
|
||||||
c if c == self.inbox.id() => self.dispatch_to_inbox(enc),
|
c if c == self.inbox.id() => self.dispatch_to_inbox(enc),
|
||||||
c if self.storage.has_conversation(&c)? => self.dispatch_to_convo(&c, enc),
|
c if self.store.has_conversation(&c)? => self.dispatch_to_convo(&c, enc),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,14 +139,14 @@ impl<T: ChatStore> Context<T> {
|
|||||||
// Look up the ephemeral key from storage
|
// Look up the ephemeral key from storage
|
||||||
let key_hex = Inbox::extract_ephemeral_key_hex(&enc_payload)?;
|
let key_hex = Inbox::extract_ephemeral_key_hex(&enc_payload)?;
|
||||||
let ephemeral_key = self
|
let ephemeral_key = self
|
||||||
.storage
|
.store
|
||||||
.load_ephemeral_key(&key_hex)?
|
.load_ephemeral_key(&key_hex)?
|
||||||
.ok_or(ChatError::UnknownEphemeralKey())?;
|
.ok_or(ChatError::UnknownEphemeralKey())?;
|
||||||
|
|
||||||
let (convo, content) = self.inbox.handle_frame(&ephemeral_key, enc_payload)?;
|
let (convo, content) = self.inbox.handle_frame(&ephemeral_key, enc_payload)?;
|
||||||
|
|
||||||
// Remove consumed ephemeral key from storage
|
// Remove consumed ephemeral key from storage
|
||||||
self.storage.remove_ephemeral_key(&key_hex)?;
|
self.store.remove_ephemeral_key(&key_hex)?;
|
||||||
|
|
||||||
self.persist_convo(convo.as_ref());
|
self.persist_convo(convo.as_ref());
|
||||||
Ok(content)
|
Ok(content)
|
||||||
@ -170,7 +168,7 @@ impl<T: ChatStore> Context<T> {
|
|||||||
|
|
||||||
pub fn create_intro_bundle(&mut self) -> Result<Vec<u8>, ChatError> {
|
pub fn create_intro_bundle(&mut self) -> Result<Vec<u8>, ChatError> {
|
||||||
let (intro, public_key_hex, private_key) = self.inbox.create_intro_bundle();
|
let (intro, public_key_hex, private_key) = self.inbox.create_intro_bundle();
|
||||||
self.storage
|
self.store
|
||||||
.save_ephemeral_key(&public_key_hex, &private_key)?;
|
.save_ephemeral_key(&public_key_hex, &private_key)?;
|
||||||
Ok(intro.into())
|
Ok(intro.into())
|
||||||
}
|
}
|
||||||
@ -178,7 +176,7 @@ impl<T: ChatStore> Context<T> {
|
|||||||
/// Loads a conversation from DB by constructing it from metadata + ratchet state.
|
/// Loads a conversation from DB by constructing it from metadata + ratchet state.
|
||||||
fn load_convo(&self, convo_id: ConversationId) -> Result<PrivateV1Convo, ChatError> {
|
fn load_convo(&self, convo_id: ConversationId) -> Result<PrivateV1Convo, ChatError> {
|
||||||
let record = self
|
let record = self
|
||||||
.storage
|
.store
|
||||||
.load_conversation(convo_id)?
|
.load_conversation(convo_id)?
|
||||||
.ok_or_else(|| ChatError::NoConvo(convo_id.into()))?;
|
.ok_or_else(|| ChatError::NoConvo(convo_id.into()))?;
|
||||||
|
|
||||||
@ -208,124 +206,22 @@ impl<T: ChatStore> Context<T> {
|
|||||||
remote_convo_id: convo.remote_id(),
|
remote_convo_id: convo.remote_id(),
|
||||||
kind: convo.convo_type().into(),
|
kind: convo.convo_type().into(),
|
||||||
};
|
};
|
||||||
let _ = self.storage.save_conversation(&convo_info);
|
let _ = self.store.save_conversation(&convo_info);
|
||||||
let _ = convo.save_ratchet_state(&mut self.ratchet_storage);
|
let _ = convo.save_ratchet_state(&mut self.ratchet_storage);
|
||||||
Arc::from(convo.id())
|
Arc::from(convo.id())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod mock {
|
|
||||||
use crypto::PrivateKey;
|
|
||||||
use storage::{
|
|
||||||
ConversationStore, EphemeralKeyStore, IdentityStore, StorageError,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
// Simple in-memory implementation of ChatStore for tests.
|
|
||||||
// Adjust the methods to match the exact trait definition in `crate::store::ChatStore`.
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct MockChatStore {
|
|
||||||
identity: Option<Identity>,
|
|
||||||
conversations: Mutex<HashMap<String, ConversationMeta>>,
|
|
||||||
ephemeral_keys: Mutex<HashMap<String, PrivateKey>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IdentityStore for MockChatStore {
|
|
||||||
fn load_identity(&self) -> Result<Option<Identity>, StorageError> {
|
|
||||||
Ok(self.identity.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_identity(&mut self, identity: &Identity) -> Result<(), StorageError> {
|
|
||||||
self.identity = Some(identity.clone());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EphemeralKeyStore for MockChatStore {
|
|
||||||
fn load_ephemeral_key(&self, key_hex: &str) -> Result<Option<PrivateKey>, StorageError> {
|
|
||||||
Ok(self.ephemeral_keys.lock().unwrap().get(key_hex).cloned())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_ephemeral_key(
|
|
||||||
&mut self,
|
|
||||||
key_hex: &str,
|
|
||||||
private_key: &PrivateKey,
|
|
||||||
) -> Result<(), StorageError> {
|
|
||||||
self.ephemeral_keys
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(key_hex.to_string(), private_key.clone());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_ephemeral_key(&mut self, key_hex: &str) -> Result<(), StorageError> {
|
|
||||||
self.ephemeral_keys.lock().unwrap().remove(key_hex);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConversationStore for MockChatStore {
|
|
||||||
fn save_conversation(&mut self, meta: &ConversationMeta) -> Result<(), StorageError> {
|
|
||||||
self.conversations
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(meta.local_convo_id.clone(), meta.clone());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_conversation(
|
|
||||||
&self,
|
|
||||||
local_convo_id: &str,
|
|
||||||
) -> Result<Option<ConversationMeta>, StorageError> {
|
|
||||||
Ok(self
|
|
||||||
.conversations
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get(local_convo_id)
|
|
||||||
.cloned())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_conversation(&mut self, local_convo_id: &str) -> Result<(), StorageError> {
|
|
||||||
self.conversations.lock().unwrap().remove(local_convo_id);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_conversations(&self) -> Result<Vec<ConversationMeta>, StorageError> {
|
|
||||||
Ok(self
|
|
||||||
.conversations
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.values()
|
|
||||||
.cloned()
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_conversation(&self, local_convo_id: &str) -> Result<bool, StorageError> {
|
|
||||||
Ok(self
|
|
||||||
.conversations
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.contains_key(local_convo_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use chat_sqlite::ChatStorage;
|
use sqlite::ChatStorage;
|
||||||
use storage::ConversationStore;
|
use storage::ConversationStore;
|
||||||
|
|
||||||
use crate::context::mock::MockChatStore;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn send_and_verify(
|
fn send_and_verify(
|
||||||
sender: &mut Context<MockChatStore>,
|
sender: &mut Context<ChatStorage>,
|
||||||
receiver: &mut Context<MockChatStore>,
|
receiver: &mut Context<ChatStorage>,
|
||||||
convo_id: ConversationId,
|
convo_id: ConversationId,
|
||||||
content: &[u8],
|
content: &[u8],
|
||||||
) {
|
) {
|
||||||
@ -341,8 +237,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ctx_integration() {
|
fn ctx_integration() {
|
||||||
let mut saro = Context::new_with_name("saro", MockChatStore::default());
|
let mut saro = Context::new_with_name("saro", ChatStorage::in_memory());
|
||||||
let mut raya = Context::new_with_name("raya", MockChatStore::default());
|
let mut raya = Context::new_with_name("raya", ChatStorage::in_memory());
|
||||||
|
|
||||||
// Raya creates intro bundle and sends to Saro
|
// Raya creates intro bundle and sends to Saro
|
||||||
let bundle = raya.create_intro_bundle().unwrap();
|
let bundle = raya.create_intro_bundle().unwrap();
|
||||||
@ -383,12 +279,12 @@ mod tests {
|
|||||||
.to_string();
|
.to_string();
|
||||||
let config = StorageConfig::File(db_path);
|
let config = StorageConfig::File(db_path);
|
||||||
|
|
||||||
let ctx1 = Context::open("alice", config.clone(), MockChatStore::default()).unwrap();
|
let ctx1 = Context::open("alice", config.clone(), ChatStorage::in_memory()).unwrap();
|
||||||
let pubkey1 = ctx1._identity.public_key();
|
let pubkey1 = ctx1._identity.public_key();
|
||||||
let name1 = ctx1.installation_name().to_string();
|
let name1 = ctx1.installation_name().to_string();
|
||||||
|
|
||||||
drop(ctx1);
|
drop(ctx1);
|
||||||
let ctx2 = Context::open("alice", config, MockChatStore::default()).unwrap();
|
let ctx2 = Context::open("alice", config, ChatStorage::in_memory()).unwrap();
|
||||||
let pubkey2 = ctx2._identity.public_key();
|
let pubkey2 = ctx2._identity.public_key();
|
||||||
let name2 = ctx2.installation_name().to_string();
|
let name2 = ctx2.installation_name().to_string();
|
||||||
|
|
||||||
@ -415,7 +311,7 @@ mod tests {
|
|||||||
let mut ctx2 = Context::open("alice", config.clone(), store2).unwrap();
|
let mut ctx2 = Context::open("alice", config.clone(), store2).unwrap();
|
||||||
|
|
||||||
let intro = Introduction::try_from(bundle1.as_slice()).unwrap();
|
let intro = Introduction::try_from(bundle1.as_slice()).unwrap();
|
||||||
let mut bob = Context::new_with_name("bob", MockChatStore::default());
|
let mut bob = Context::new_with_name("bob", ChatStorage::in_memory());
|
||||||
let (_, payloads) = bob.create_private_convo(&intro, b"hello after restart");
|
let (_, payloads) = bob.create_private_convo(&intro, b"hello after restart");
|
||||||
|
|
||||||
let payload = payloads.first().unwrap();
|
let payload = payloads.first().unwrap();
|
||||||
@ -439,7 +335,7 @@ mod tests {
|
|||||||
|
|
||||||
let store = ChatStorage::new(config.clone()).unwrap();
|
let store = ChatStorage::new(config.clone()).unwrap();
|
||||||
let mut alice = Context::open("alice", config.clone(), store).unwrap();
|
let mut alice = Context::open("alice", config.clone(), store).unwrap();
|
||||||
let mut bob = Context::new_with_name("bob", MockChatStore::default());
|
let mut bob = Context::new_with_name("bob", ChatStorage::in_memory());
|
||||||
|
|
||||||
let bundle = alice.create_intro_bundle().unwrap();
|
let bundle = alice.create_intro_bundle().unwrap();
|
||||||
let intro = Introduction::try_from(bundle.as_slice()).unwrap();
|
let intro = Introduction::try_from(bundle.as_slice()).unwrap();
|
||||||
@ -449,14 +345,14 @@ mod tests {
|
|||||||
let content = alice.handle_payload(&payload.data).unwrap().unwrap();
|
let content = alice.handle_payload(&payload.data).unwrap().unwrap();
|
||||||
assert!(content.is_new_convo);
|
assert!(content.is_new_convo);
|
||||||
|
|
||||||
let convos = alice.storage.load_conversations().unwrap();
|
let convos = alice.store.load_conversations().unwrap();
|
||||||
assert_eq!(convos.len(), 1);
|
assert_eq!(convos.len(), 1);
|
||||||
assert_eq!(convos[0].kind.as_str(), "private_v1");
|
assert_eq!(convos[0].kind.as_str(), "private_v1");
|
||||||
|
|
||||||
drop(alice);
|
drop(alice);
|
||||||
let store2 = ChatStorage::new(config.clone()).unwrap();
|
let store2 = ChatStorage::new(config.clone()).unwrap();
|
||||||
let alice2 = Context::open("alice", config, store2).unwrap();
|
let alice2 = Context::open("alice", config, store2).unwrap();
|
||||||
let convos = alice2.storage.load_conversations().unwrap();
|
let convos = alice2.store.load_conversations().unwrap();
|
||||||
assert_eq!(convos.len(), 1, "conversation metadata should persist");
|
assert_eq!(convos.len(), 1, "conversation metadata should persist");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +369,7 @@ mod tests {
|
|||||||
// Alice and Bob establish a conversation
|
// Alice and Bob establish a conversation
|
||||||
let store = ChatStorage::new(config.clone()).unwrap();
|
let store = ChatStorage::new(config.clone()).unwrap();
|
||||||
let mut alice = Context::open("alice", config.clone(), store).unwrap();
|
let mut alice = Context::open("alice", config.clone(), store).unwrap();
|
||||||
let mut bob = Context::new_with_name("bob", MockChatStore::default());
|
let mut bob = Context::new_with_name("bob", ChatStorage::in_memory());
|
||||||
|
|
||||||
let bundle = alice.create_intro_bundle().unwrap();
|
let bundle = alice.create_intro_bundle().unwrap();
|
||||||
let intro = Introduction::try_from(bundle.as_slice()).unwrap();
|
let intro = Introduction::try_from(bundle.as_slice()).unwrap();
|
||||||
|
|||||||
@ -10,10 +10,10 @@ use crypto::{PrekeyBundle, SymmetricKey32};
|
|||||||
use crate::context::Introduction;
|
use crate::context::Introduction;
|
||||||
use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo};
|
use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo};
|
||||||
use crate::crypto::{CopyBytes, PrivateKey, PublicKey};
|
use crate::crypto::{CopyBytes, PrivateKey, PublicKey};
|
||||||
use crypto::Identity;
|
|
||||||
use crate::inbox::handshake::InboxHandshake;
|
use crate::inbox::handshake::InboxHandshake;
|
||||||
use crate::proto;
|
use crate::proto;
|
||||||
use crate::types::{AddressedEncryptedPayload, ContentData};
|
use crate::types::{AddressedEncryptedPayload, ContentData};
|
||||||
|
use crypto::Identity;
|
||||||
|
|
||||||
/// Compute the deterministic Delivery_address for an installation
|
/// Compute the deterministic Delivery_address for an installation
|
||||||
fn delivery_address_for_installation(_: PublicKey) -> String {
|
fn delivery_address_for_installation(_: PublicKey) -> String {
|
||||||
@ -239,7 +239,7 @@ impl Id for Inbox {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use chat_sqlite::ChatStorage;
|
use sqlite::ChatStorage;
|
||||||
use storage::{EphemeralKeyStore, StorageConfig};
|
use storage::{EphemeralKeyStore, StorageConfig};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -9,9 +9,9 @@ mod types;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub use api::*;
|
pub use api::*;
|
||||||
pub use chat_sqlite::ChatStorage;
|
|
||||||
pub use context::{Context, Introduction};
|
pub use context::{Context, Introduction};
|
||||||
pub use errors::ChatError;
|
pub use errors::ChatError;
|
||||||
|
pub use sqlite::ChatStorage;
|
||||||
pub use storage::StorageConfig;
|
pub use storage::StorageConfig;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "chat-sqlite"
|
name = "sqlite"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
description = "SQLite storage implementation for libchat"
|
description = "SQLite storage implementation for libchat"
|
||||||
@ -29,6 +29,10 @@ impl ChatStorage {
|
|||||||
Self::run_migrations(db)
|
Self::run_migrations(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn in_memory() -> Self {
|
||||||
|
Self::new(StorageConfig::InMemory).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Applies all migrations and returns the storage instance.
|
/// Applies all migrations and returns the storage instance.
|
||||||
fn run_migrations(mut db: SqliteDb) -> Result<Self, StorageError> {
|
fn run_migrations(mut db: SqliteDb) -> Result<Self, StorageError> {
|
||||||
migrations::apply_migrations(db.connection_mut())?;
|
migrations::apply_migrations(db.connection_mut())?;
|
||||||
@ -111,10 +115,7 @@ impl EphemeralKeyStore for ChatStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a single ephemeral key by its public key hex.
|
/// Loads a single ephemeral key by its public key hex.
|
||||||
fn load_ephemeral_key(
|
fn load_ephemeral_key(&self, public_key_hex: &str) -> Result<Option<PrivateKey>, StorageError> {
|
||||||
&self,
|
|
||||||
public_key_hex: &str,
|
|
||||||
) -> Result<Option<PrivateKey>, StorageError> {
|
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
.connection()
|
.connection()
|
||||||
Loading…
x
Reference in New Issue
Block a user