Something went wrong. Try again.
Something went wrong. Try again.
4.7 kB · 132 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133//! Document sync helpers for site.standard.document records.//!//! Creates/updates site.standard.document records for notebook entries//! when the notebook has publishGlobal enabled.
use jacquard::IntoStatic;use jacquard::cowstr::ToCowStr;use jacquard::prelude::*;use jacquard::to_data;use jacquard::types::ident::AtIdentifier;use jacquard::types::recordkey::RecordKey;use jacquard::types::string::{AtUri, Nsid};use weaver_api::com_atproto::repo::create_record::CreateRecord;use weaver_api::com_atproto::repo::get_record::GetRecord;use weaver_api::sh_weaver::domain::generate_document::GenerateDocument;use weaver_api::sh_weaver::notebook::entry::Entry;use weaver_common::{WeaverError, slugify};
use crate::fetch::Fetcher;
const DOCUMENT_NSID: &str = "site.standard.document";
/// Create a site.standard.document for an entry if the notebook has publishGlobal.////// Returns Ok(Some(document_uri)) if created, Ok(None) if not needed, Err on failure.pub async fn create_document_for_entry( fetcher: &Fetcher, entry_uri: &AtUri<'_>, entry_record: &Entry<'_>, publication_uri: &AtUri<'_>,) -> Result<Option<AtUri<'static>>, WeaverError> { // Build the document path from entry path (or fallback to slugified title). let path = if !entry_record.path.is_empty() { entry_record.path.to_cowstr() } else if !entry_record.title.is_empty() { slugify(entry_record.title.as_ref()) .to_cowstr() .into_static() } else { "untitled".to_cowstr() };
// Serialize entry record for the generateDocument call. let entry_data = to_data(entry_record) .map_err(|e| WeaverError::InvalidNotebook(format!("Failed to serialize entry: {}", e)))?;
// Call generateDocument endpoint (proxied through PDS with auth). let request = GenerateDocument::new() .entry(entry_uri.clone()) .entry_record(entry_data) .publication(publication_uri.clone()) .path(path) .build();
let response = fetcher .send(request) .await .map_err(|e| WeaverError::InvalidNotebook(format!("Failed to generate document: {}", e)))?;
let output = response .into_output() .map_err(|e| WeaverError::InvalidNotebook(format!("generateDocument failed: {}", e)))?;
// Write the document to the PDS. let did = fetcher .current_did() .await .ok_or_else(|| WeaverError::InvalidNotebook("Not authenticated".into()))?;
// Use entry rkey for 1:1 mapping. let entry_rkey = entry_uri .rkey() .ok_or_else(|| WeaverError::InvalidNotebook("Entry URI missing rkey".into()))?;
let collection = Nsid::new(DOCUMENT_NSID).map_err(WeaverError::AtprotoString)?; let document_data = to_data(&output.record).map_err(|e| { WeaverError::InvalidNotebook(format!("Failed to serialize document: {}", e)) })?;
let rkey = RecordKey::any(entry_rkey.as_ref()) .map_err(|e| WeaverError::InvalidNotebook(e.to_string()))?;
let request = CreateRecord::new() .repo(AtIdentifier::Did(did)) .collection(collection) .rkey(rkey) .record(document_data) .build();
let response = fetcher .send(request) .await .map_err(jacquard::client::AgentError::from)?;
let create_output = response .into_output() .map_err(|e| WeaverError::InvalidNotebook(format!("Failed to create document: {}", e)))?;
Ok(Some(create_output.uri.into_static()))}
/// Check if a site.standard.document exists for an entry.pub async fn document_exists(fetcher: &Fetcher, entry_rkey: &str) -> Result<bool, WeaverError> { let did = fetcher .current_did() .await .ok_or_else(|| WeaverError::InvalidNotebook("Not authenticated".into()))?;
let collection = Nsid::new(DOCUMENT_NSID).map_err(WeaverError::AtprotoString)?; let rkey = RecordKey::any(entry_rkey).map_err(|e| WeaverError::InvalidNotebook(e.to_string()))?;
let request = GetRecord::new() .repo(AtIdentifier::Did(did)) .collection(collection) .rkey(rkey) .build();
match fetcher.send(request).await { Ok(response) => Ok(response.into_output().is_ok()), Err(_) => Ok(false), }}
/// Get the publication URI for a notebook (same rkey).pub fn publication_uri_for_notebook(notebook_uri: &AtUri<'_>) -> Option<AtUri<'static>> { let did = notebook_uri.authority(); let rkey = notebook_uri.rkey()?;
let uri_str = format!("at://{}/site.standard.publication/{}", did, rkey.as_ref()); AtUri::new(&uri_str).ok().map(|u| u.into_static())}