| Crates.io | jacquard-oauth |
| lib.rs | jacquard-oauth |
| version | 0.9.6 |
| created_at | 2025-10-08 18:36:33.740989+00 |
| updated_at | 2025-12-19 19:14:33.796202+00 |
| description | AT Protocol OAuth 2.1 core types and helpers for Jacquard |
| homepage | |
| repository | https://tangled.org/@nonbinary.computer/jacquard |
| max_upload_size | |
| id | 1874355 |
| size | 391,025 |
A suite of Rust crates intended to make it much easier to get started with atproto development, without sacrificing flexibility or performance.
Jacquard is simpler because it is designed in a way which makes things simple that almost every other atproto library seems to make difficult.
It is also designed around zero-copy/borrowed deserialization: types like Post<'_> can borrow data (via the CowStr<'_> type and a host of other types built on top of it) directly from the response buffer instead of allocating owned copies. Owned versions are themselves mostly inlined or reference-counted pointers and are therefore still quite efficient. The IntoStatic trait (which is derivable) makes it easy to get an owned version and avoid worrying about lifetimes.
#[derive(LexiconSchema)] + #[lexicon_union] macros
LexiconDoc at compile time for runtime validationRuntime lexicon data validation
Lexicon resolver
Query and path DSLs for Data and RawData value types
Data structuresdata.query(pattern) with expressive syntax:
field.nested - exact path navigation[..] - wildcard over collections (array elements or object values)field..nested - scoped recursion (find nested within field, expect one)...field - global recursion (find all occurrences anywhere)get_at_path() for simple path-based field access on Data and RawDataembed.images[0].alt for navigating nested structurestype_discriminator() helper methods for AT Protocol union discriminationget(), contains_key(), len(), is_empty(), iter(), keys(), values()obj["key"] and arr[0]Caching in identity/lexicon resolver
mini-mokamini-moka requires a git dependency, use the git version of the crate when compiling for wasmXRPC client improvements
set_options() and set_endpoint() methods on XrpcClient traitMajor generated API compilation time improvements
bon cratesyn tax of generating the builders to code generation time, not compile time.New jacquard-lexgen crate
lex-fetchDead simple API client. Logs in with OAuth and prints the latest 5 posts from your timeline.
// Note: this requires the `loopback` feature enabled (it is currently by default)
use clap::Parser;
use jacquard::CowStr;
use jacquard::api::app_bsky::feed::get_timeline::GetTimeline;
use jacquard::client::{Agent, FileAuthStore};
use jacquard::oauth::client::OAuthClient;
use jacquard::oauth::loopback::LoopbackConfig;
use jacquard::types::xrpc::XrpcClient;
use miette::IntoDiagnostic;
#[derive(Parser, Debug)]
#[command(author, version, about = "Jacquard - OAuth (DPoP) loopback demo")]
struct Args {
/// Handle (e.g., alice.bsky.social), DID, or PDS URL
input: CowStr<'static>,
/// Path to auth store file (will be created if missing)
#[arg(long, default_value = "/tmp/jacquard-oauth-session.json")]
store: String,
}
#[tokio::main]
async fn main() -> miette::Result<()> {
let args = Args::parse();
// Build an OAuth client with file-backed auth store and default localhost config
let oauth = OAuthClient::with_default_config(FileAuthStore::new(&args.store));
// Authenticate with a PDS, using a loopback server to handle the callback flow
let session = oauth
.login_with_local_server(
args.input.clone(),
Default::default(),
LoopbackConfig::default(),
)
.await?;
// Wrap in Agent and fetch the timeline
let agent: Agent<_> = Agent::from(session);
let timeline = agent
.send(&GetTimeline::new().limit(5).build())
.await?
.into_output()?;
for (i, post) in timeline.feed.iter().enumerate() {
println!("\n{}. by {}", i + 1, post.post.author.handle);
println!(
" {}",
serde_json::to_string_pretty(&post.post.record).into_diagnostic()?
);
}
Ok(())
}
If you have just installed, you can run the examples using just example {example-name} {ARGS} or just examples to see what's available.
[!WARNING] A lot of the streaming code is still pretty experimental. The examples work, though.
The modules are also less well-documented, and don't have code examples. There are also a lot of utility functions for conveniently working with the streams and transforming them which are lacking. Usen0-futureto work with them, that is what Jacquard uses internally as much as possible.
I would also note the same for the repository crate until I've had more third parties test it.
Jacquard is broken up into several crates for modularity. The correct one to use is generally jacquard itself, as it re-exports most of the others.
This repo uses Flakes
# Dev shell
nix develop
# or run via cargo
nix develop -c cargo run
# build
nix build
There's also a justfile for Makefile-esque commands to be run inside of the devShell, and you can generally cargo ... or just ... whatever just fine if you don't want to use Nix and have the prerequisites installed.