Skip to main content

pulsify_sqlite/
lib.rs

1//! Durable Pulsify documents in SQLite, without materializing them.
2//!
3//! The database file uses the schema and append semantics of the TypeScript
4//! `SqlitePatchStore`, so either implementation can open a file written by the other.
5mod hub;
6mod relay;
7mod store;
8
9pub use hub::{Hub, Sink};
10pub use pulsify_protocol::{PatchRow, VersionVector};
11pub use relay::{chunk_rows, relay_frame, RelayOutput};
12pub use store::{validate_doc_id, AppendResult, SqliteStore, SCHEMA};
13
14use std::fmt;
15
16/// A failure carrying a Pulsify protocol error code, such as `CONFLICT`.
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct Error {
19    pub code: &'static str,
20    pub message: String,
21}
22impl Error {
23    pub fn new(code: &'static str, message: impl Into<String>) -> Self {
24        Self {
25            code,
26            message: message.into(),
27        }
28    }
29}
30impl fmt::Display for Error {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "{}: {}", self.code, self.message)
33    }
34}
35impl std::error::Error for Error {}
36impl From<pulsify_protocol::Error> for Error {
37    fn from(error: pulsify_protocol::Error) -> Self {
38        Self::new(error.code, error.message)
39    }
40}
41impl From<rusqlite::Error> for Error {
42    fn from(error: rusqlite::Error) -> Self {
43        Self::new("CONNECTION_FAILED", format!("SQLite: {error}"))
44    }
45}
46impl From<serde_json::Error> for Error {
47    fn from(error: serde_json::Error) -> Self {
48        Self::new(
49            "CONNECTION_FAILED",
50            format!("Corrupt stored metadata: {error}"),
51        )
52    }
53}
54pub type Result<T> = std::result::Result<T, Error>;