A better Rust ATProto crate

fixed bug in plc.directory did doc resolution

Orual 2112129b c464e6a5

+49 -26
+5 -1
crates/jacquard-identity/src/lib.rs
··· 378 378 } 379 379 DidStep::PlcHttp if s.starts_with("did:plc:") => { 380 380 let url = match &self.opts.plc_source { 381 - PlcSource::PlcDirectory { base } => base.join(did.as_str())?, 381 + PlcSource::PlcDirectory { base } => { 382 + // this is odd, the join screws up with the plc directory but NOT slingshot 383 + Url::parse(&format!("{}{}", base, did.as_str())).expect("Invalid URL") 384 + } 382 385 PlcSource::Slingshot { base } => base.join(did.as_str())?, 383 386 }; 387 + println!("Fetching DID document from {}", url); 384 388 if let Ok((buf, status)) = self.get_json_bytes(url).await { 385 389 return Ok(DidDocResponse { 386 390 buffer: buf,
+28 -7
crates/jacquard-identity/src/resolver.rs
··· 36 36 #[allow(missing_docs)] 37 37 pub enum IdentityError { 38 38 #[error("unsupported DID method: {0}")] 39 - #[diagnostic(code(jacquard_identity::unsupported_did_method), help("supported DID methods: did:web, did:plc"))] 39 + #[diagnostic( 40 + code(jacquard_identity::unsupported_did_method), 41 + help("supported DID methods: did:web, did:plc") 42 + )] 40 43 UnsupportedDidMethod(String), 41 44 #[error("invalid well-known atproto-did content")] 42 - #[diagnostic(code(jacquard_identity::invalid_well_known), help("expected first non-empty line to be a DID"))] 45 + #[diagnostic( 46 + code(jacquard_identity::invalid_well_known), 47 + help("expected first non-empty line to be a DID") 48 + )] 43 49 InvalidWellKnown, 44 50 #[error("missing PDS endpoint in DID document")] 45 51 #[diagnostic(code(jacquard_identity::missing_pds_endpoint))] 46 52 MissingPdsEndpoint, 47 53 #[error("HTTP error: {0}")] 48 - #[diagnostic(code(jacquard_identity::http), help("check network connectivity and TLS configuration"))] 54 + #[diagnostic( 55 + code(jacquard_identity::http), 56 + help("check network connectivity and TLS configuration") 57 + )] 49 58 Http(#[from] TransportError), 50 59 #[error("HTTP status {0}")] 51 - #[diagnostic(code(jacquard_identity::http_status), help("verify well-known paths or PDS XRPC endpoints"))] 60 + #[diagnostic( 61 + code(jacquard_identity::http_status), 62 + help("verify well-known paths or PDS XRPC endpoints") 63 + )] 52 64 HttpStatus(StatusCode), 53 65 #[error("XRPC error: {0}")] 54 - #[diagnostic(code(jacquard_identity::xrpc), help("enable PDS fallback or public resolver if needed"))] 66 + #[diagnostic( 67 + code(jacquard_identity::xrpc), 68 + help("enable PDS fallback or public resolver if needed") 69 + )] 55 70 Xrpc(String), 56 71 #[error("URL parse error: {0}")] 57 72 #[diagnostic(code(jacquard_identity::url))] ··· 64 79 #[diagnostic(code(jacquard_identity::serde))] 65 80 Serde(#[from] serde_json::Error), 66 81 #[error("invalid DID document: {0}")] 67 - #[diagnostic(code(jacquard_identity::invalid_doc), help("validate keys and services; ensure AtprotoPersonalDataServer service exists"))] 82 + #[diagnostic( 83 + code(jacquard_identity::invalid_doc), 84 + help("validate keys and services; ensure AtprotoPersonalDataServer service exists") 85 + )] 68 86 InvalidDoc(String), 69 87 #[error(transparent)] 70 88 #[diagnostic(code(jacquard_identity::data))] 71 89 Data(#[from] AtDataError), 72 90 /// DID document id did not match requested DID; includes the fetched document 73 91 #[error("DID doc id mismatch")] 74 - #[diagnostic(code(jacquard_identity::doc_id_mismatch), help("document id differs from requested DID; do not trust this document"))] 92 + #[diagnostic( 93 + code(jacquard_identity::doc_id_mismatch), 94 + help("document id differs from requested DID; do not trust this document") 95 + )] 75 96 DocIdMismatch { 76 97 expected: Did<'static>, 77 98 doc: DidDocument<'static>,
+6 -13
crates/jacquard/src/client/credential_session.rs
··· 403 403 // Under Tokio, use `block_in_place` to make a blocking RwLock read safe. 404 404 if tokio::runtime::Handle::try_current().is_ok() { 405 405 tokio::task::block_in_place(|| { 406 - self.endpoint 407 - .blocking_read() 408 - .clone() 409 - .unwrap_or( 410 - Url::parse("https://public.bsky.app") 411 - .expect("public appview should be valid url"), 412 - ) 413 - }) 414 - } else { 415 - self.endpoint 416 - .blocking_read() 417 - .clone() 418 - .unwrap_or( 406 + self.endpoint.blocking_read().clone().unwrap_or( 419 407 Url::parse("https://public.bsky.app") 420 408 .expect("public appview should be valid url"), 421 409 ) 410 + }) 411 + } else { 412 + self.endpoint.blocking_read().clone().unwrap_or( 413 + Url::parse("https://public.bsky.app").expect("public appview should be valid url"), 414 + ) 422 415 } 423 416 } 424 417 async fn send<R: jacquard_common::types::xrpc::XrpcRequest + Send>(
+10 -5
crates/jacquard/src/main.rs
··· 1 - use std::sync::Arc; 2 1 use clap::Parser; 3 2 use jacquard::CowStr; 4 3 use jacquard::api::app_bsky::feed::get_timeline::GetTimeline; 5 4 use jacquard::client::credential_session::{CredentialSession, SessionKey}; 6 5 use jacquard::client::{AtpSession, MemorySessionStore}; 7 - use jacquard::identity::PublicResolver as JacquardResolver; 8 6 use jacquard::types::xrpc::XrpcClient; 7 + use jacquard_identity::slingshot_resolver_default; 9 8 use miette::IntoDiagnostic; 9 + use std::sync::Arc; 10 10 11 11 #[derive(Parser, Debug)] 12 12 #[command(author, version, about = "Jacquard - AT Protocol client demo")] ··· 24 24 let args = Args::parse(); 25 25 26 26 // Resolver + in-memory store 27 - let resolver = Arc::new(JacquardResolver::default()); 27 + let resolver = Arc::new(slingshot_resolver_default()); 28 28 let store: Arc<MemorySessionStore<SessionKey, AtpSession>> = Arc::new(Default::default()); 29 29 let client = Arc::new(resolver.clone()); 30 30 let session = CredentialSession::new(store, client); 31 31 32 - // Login; resolves PDS from handle/DID automatically. Persisted under (did, "session"). 33 32 let _ = session 34 - .login(args.username.clone(), args.password.clone(), None, None, None) 33 + .login( 34 + args.username.clone(), 35 + args.password.clone(), 36 + None, 37 + None, 38 + None, 39 + ) 35 40 .await 36 41 .into_diagnostic()?; 37 42