mod fs_store;
pub mod metadata;
pub mod render;
pub use fs_store::FsStore;
pub use metadata::{DoigetExtension, Metadata};
pub use render::{to_bibtex, to_csl_array};
use camino::Utf8Path;
use thiserror::Error;
use crate::Safekey;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct EntryInfo {
pub safekey: Safekey,
pub title: String,
pub year: Option<i32>,
pub fetched_at: Option<chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum StoreError {
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("toml deserialize error: {0}")]
Deserialize(#[from] toml::de::Error),
#[error("toml serialize error: {0}")]
Serialize(#[from] toml::ser::Error),
#[error("flock timeout (5s) on {path}")]
LockTimeout {
path: camino::Utf8PathBuf,
},
#[error("schema_version too new: {theirs} > {ours}; entry is read-only")]
SchemaTooNew {
theirs: String,
ours: String,
},
#[error("required field missing: {field}")]
MissingField {
field: &'static str,
},
#[error("path is outside the store root: {path}")]
PathTraversal {
path: camino::Utf8PathBuf,
},
}
pub trait Store: Send + Sync {
fn read(&self, key: &Safekey) -> Result<Option<Metadata>, StoreError>;
fn write(&self, key: &Safekey, m: &Metadata, pdf: Option<&Utf8Path>) -> Result<(), StoreError>;
fn list_recent(&self, limit: usize) -> Result<Vec<EntryInfo>, StoreError>;
fn search(&self, query: &str, limit: usize) -> Result<Vec<EntryInfo>, StoreError>;
}