A better Rust ATProto crate

readme for main crate

Orual 4e3ee1ee df48cd53

Changed files
+89 -1
crates
jacquard
src
+89 -1
crates/jacquard/src/lib.rs
··· 1 - #![doc = include_str!("../../../README.md")] 1 + //! # Jacquard 2 + //! 3 + //! A suite of Rust crates for the AT Protocol. 4 + //! 5 + //! 6 + //! ## Goals 7 + //! 8 + //! - Validated, spec-compliant, easy to work with, and performant baseline types (including typed at:// uris) 9 + //! - Batteries-included, but easily replaceable batteries. 10 + //! - Easy to extend with custom lexicons 11 + //! - lexicon Value type for working with unknown atproto data (dag-cbor or json) 12 + //! - order of magnitude less boilerplate than some existing crates 13 + //! - either the codegen produces code that's easy to work with, or there are good handwritten wrappers 14 + //! - didDoc type with helper methods for getting handles, multikey, and PDS endpoint 15 + //! - use as much or as little from the crates as you need 16 + //! 17 + //! 18 + //! ## Example 19 + //! 20 + //! Dead simple api client. Logs in, prints the latest 5 posts from your timeline. 21 + //! 22 + //! ```rust 23 + //! # use clap::Parser; 24 + //! # use jacquard::CowStr; 25 + //! use jacquard::api::app_bsky::feed::get_timeline::GetTimeline; 26 + //! use jacquard::api::com_atproto::server::create_session::CreateSession; 27 + //! use jacquard::client::{AuthenticatedClient, Session, XrpcClient}; 28 + //! # use miette::IntoDiagnostic; 29 + //! 30 + //! # #[derive(Parser, Debug)] 31 + //! # #[command(author, version, about = "Jacquard - AT Protocol client demo")] 32 + //! # struct Args { 33 + //! # /// Username/handle (e.g., alice.mosphere.at) 34 + //! # #[arg(short, long)] 35 + //! # username: CowStr<'static>, 36 + //! # 37 + //! # /// PDS URL (e.g., https://bsky.social) 38 + //! # #[arg(long, default_value = "https://bsky.social")] 39 + //! # pds: CowStr<'static>, 40 + //! # 41 + //! # /// App password 42 + //! # #[arg(short, long)] 43 + //! # password: CowStr<'static>, 44 + //! # } 45 + //! 46 + //! #[tokio::main] 47 + //! async fn main() -> miette::Result<()> { 48 + //! let args = Args::parse(); 49 + //! 50 + //! // Create HTTP client 51 + //! let mut client = AuthenticatedClient::new(reqwest::Client::new(), args.pds); 52 + //! 53 + //! // Create session 54 + //! let session = Session::from( 55 + //! client 56 + //! .send( 57 + //! CreateSession::new() 58 + //! .identifier(args.username) 59 + //! .password(args.password) 60 + //! .build(), 61 + //! ) 62 + //! .await? 63 + //! .into_output()?, 64 + //! ); 65 + //! 66 + //! println!("logged in as {} ({})", session.handle, session.did); 67 + //! client.set_session(session); 68 + //! 69 + //! // Fetch timeline 70 + //! println!("\nfetching timeline..."); 71 + //! let timeline = client 72 + //! .send(GetTimeline::new().limit(5).build()) 73 + //! .await? 74 + //! .into_output()?; 75 + //! 76 + //! println!("\ntimeline ({} posts):", timeline.feed.len()); 77 + //! for (i, post) in timeline.feed.iter().enumerate() { 78 + //! println!("\n{}. by {}", i + 1, post.post.author.handle); 79 + //! println!( 80 + //! " {}", 81 + //! serde_json::to_string_pretty(&post.post.record).into_diagnostic()? 82 + //! ); 83 + //! } 84 + //! 85 + //! Ok(()) 86 + //! } 87 + //! ``` 88 + //! 89 + 2 90 #![warn(missing_docs)] 3 91 4 92 /// XRPC client traits and basic implementation