sos_database/
lib.rs

1#![deny(missing_docs)]
2#![forbid(unsafe_code)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![allow(clippy::large_enum_variant)]
5
6//! Database storage layer for the [Save Our Secrets](https://saveoursecrets.com) SDK.
7#[cfg(feature = "archive")]
8pub mod archive;
9#[cfg(feature = "audit")]
10pub mod audit_provider;
11pub mod entity;
12mod event_log;
13pub mod migrations;
14#[cfg(feature = "preferences")]
15mod preferences;
16mod server_origins;
17#[cfg(feature = "system-messages")]
18mod system_messages;
19mod vault_writer;
20
21pub use event_log::{
22    AccountEventLog, DatabaseEventLog, DeviceEventLog, EventLogOwner,
23    FolderEventLog,
24};
25
26#[cfg(feature = "preferences")]
27pub use preferences::PreferenceProvider;
28
29#[cfg(feature = "system-messages")]
30pub use system_messages::SystemMessagesProvider;
31
32pub use server_origins::ServerOrigins;
33pub use vault_writer::VaultDatabaseWriter;
34
35#[cfg(feature = "files")]
36pub use event_log::FileEventLog;
37
38mod error;
39pub use async_sqlite;
40pub use error::Error;
41
42/// Result type for the library.
43pub(crate) type Result<T> = std::result::Result<T, Error>;
44
45use async_sqlite::{Client, ClientBuilder, JournalMode};
46use std::path::Path;
47
48/// Open a database file from a path with WAL journal mode enabled.
49pub async fn open_file(path: impl AsRef<Path>) -> Result<Client> {
50    tracing::debug!(
51        path = %path.as_ref().display(),
52        "database::open_file",
53    );
54    Ok(ClientBuilder::new()
55        .path(path.as_ref())
56        .journal_mode(JournalMode::Wal)
57        .open()
58        .await?)
59}
60
61/// Open a database file from a specific journal mode.
62pub async fn open_file_with_journal_mode(
63    path: impl AsRef<Path>,
64    mode: JournalMode,
65) -> Result<Client> {
66    Ok(ClientBuilder::new()
67        .path(path.as_ref())
68        .journal_mode(mode)
69        .open()
70        .await?)
71}
72
73/// Open an in-memory database and run migrations.
74pub async fn open_memory() -> Result<Client> {
75    let mut client = ClientBuilder::new().open().await?;
76    crate::migrations::migrate_client(&mut client).await?;
77    Ok(client)
78}
79
80#[cfg(debug_assertions)]
81#[allow(dead_code)]
82pub(crate) fn dump_rows<C>(
83    conn: C,
84    table: &str,
85) -> std::result::Result<(), async_sqlite::rusqlite::Error>
86where
87    C: std::ops::Deref<Target = async_sqlite::rusqlite::Connection>,
88{
89    println!("--- BEGIN DUMP ---");
90    let mut stmt = conn.prepare(&format!(
91        r#"
92            SELECT * FROM {}
93        "#,
94        table
95    ))?;
96    let mut rows = stmt.query([])?;
97    while let Ok(Some(row)) = rows.next() {
98        println!("{:#?}", row);
99    }
100    println!("--- END DUMP ---");
101    Ok(())
102}