···2424thiserror.workspace = true
252526262727+[lints.rust]
2828+# just so that my rust-analyzer shuts up about the module name for 2048.blue's namespace
2929+non_snake_case = "allow"
3030+2731[features]
2832default = [ "minimal"]
2933minimal = [ "com_atproto", "com_bad_example"]
···3232use jacquard_common::types::collection::Collection;
3333use jacquard_common::types::recordkey::{RecordKey, Rkey};
3434use jacquard_common::types::string::AtUri;
3535+#[cfg(feature = "api")]
3636+use jacquard_common::types::uri::RecordUri;
3537use jacquard_common::xrpc::{
3638 CallOptions, Response, XrpcClient, XrpcError, XrpcExt, XrpcRequest, XrpcResp,
3739};
···4749use jacquard_oauth::client::OAuthSession;
4850use jacquard_oauth::dpop::DpopExt;
4951use jacquard_oauth::resolver::OAuthResolver;
5252+use std::marker::PhantomData;
50535154use serde::Serialize;
5255pub use token::FileAuthStore;
···484487 /// ```
485488 fn get_record<R>(
486489 &self,
487487- uri: AtUri<'_>,
490490+ uri: &AtUri<'_>,
488491 ) -> impl Future<Output = Result<Response<R::Record>, ClientError>>
489492 where
490493 R: Collection,
···555558556559 /// Fetches a record from the PDS. Returns an owned, parsed response.
557560 ///
558558- /// `record_type` parameter should be the marker struct for the record (e.g. `PostRecord` for `Post`), rather than the Post itself (though it will intuit things correctly regardless).
559559- /// This allows the compiler to better intuit the output type without turbofishing.
561561+ /// Takes an at:// URI annotated with the collection type, which be constructed with `R::uri(uri)`
562562+ /// where `R` is the type of record you want (e.g. `app_bsky::feed::post::Post::uri(uri)` for Bluesky posts).
560563 fn fetch_record<R>(
561564 &self,
562562- record_type: R,
563563- uri: AtUri<'_>,
565565+ uri: &RecordUri<'_, R>,
564566 ) -> impl Future<Output = Result<CollectionOutput<'static, R>, ClientError>>
565567 where
566568 R: Collection,
567569 for<'a> CollectionOutput<'a, R>: IntoStatic<Output = CollectionOutput<'static, R>>,
568570 for<'a> CollectionErr<'a, R>: IntoStatic<Output = CollectionErr<'static, R>>,
569571 {
570570- let _ = record_type;
572572+ let uri = uri.as_uri();
571573 async move {
572572- let response = self.get_record::<R>(uri.clone()).await?;
574574+ let response = self.get_record::<R>(uri).await?;
573575 let response: Response<R::Record> = response.transmute();
574576 let output = response
575577 .into_output()
···607609 /// ```
608610 fn update_record<R>(
609611 &self,
610610- uri: AtUri<'_>,
612612+ uri: &AtUri<'_>,
611613 f: impl FnOnce(&mut R),
612614 ) -> impl Future<Output = Result<PutRecordOutput<'static>, AgentError>>
613615 where
···620622 .entered();
621623622624 // Fetch the record - Response<R::Record> where R::Record::Output<'de> = R<'de>
623623- let response = self.get_record::<R>(uri.clone()).await?;
625625+ let response = self.get_record::<R>(uri).await?;
624626625627 // Parse to get R<'_> borrowing from response buffer
626628 let record = response.parse().map_err(|e| match e {
+12-13
examples/read_tangled_repo.rs
···11use clap::Parser;
22use jacquard::client::{AgentSessionExt, BasicClient};
33-use jacquard::types::string::AtUri;
44-use jacquard_api::sh_tangled::repo::RepoRecord;
33+use jacquard_api::sh_tangled::repo::Repo;
5465#[derive(Parser, Debug)]
76#[command(author, version, about = "Read a Tangled git repository record")]
···1817 let args = Args::parse();
19182019 // Parse the at:// URI
2121- let uri = AtUri::new(&args.uri)?;
2020+ let uri = Repo::uri(args.uri)?;
22212322 // Create an unauthenticated agent for public record access
2423 let agent = BasicClient::unauthenticated();
25242626- // Use Agent's fetch_record helper with the at:// URI & marker struct
2727- let output = agent.fetch_record(RepoRecord, uri).await?;
2525+ // Use Agent's fetch_record helper with typed record URI
2626+ let output: Repo<'_> = agent.fetch_record(&uri).await?.into();
28272928 println!("Tangled Repository\n");
3030- println!("URI: {}", output.uri);
3131- println!("Name: {}", output.value.name);
2929+ println!("URI: {}", uri);
3030+ println!("Name: {}", output.name);
32313333- if let Some(desc) = &output.value.description {
3232+ if let Some(desc) = &output.description {
3433 println!("Description: {}", desc);
3534 }
36353737- println!("Knot: {}", output.value.knot);
3838- println!("Created: {}", output.value.created_at);
3636+ println!("Knot: {}", output.knot);
3737+ println!("Created: {}", output.created_at);
39384040- if let Some(source) = &output.value.source {
3939+ if let Some(source) = &output.source {
4140 println!("Source: {}", source.as_str());
4241 }
43424444- if let Some(spindle) = &output.value.spindle {
4343+ if let Some(spindle) = &output.spindle {
4544 println!("CI Spindle: {}", spindle);
4645 }
47464848- if let Some(labels) = &output.value.labels {
4747+ if let Some(labels) = &output.labels {
4948 if !labels.is_empty() {
5049 println!(
5150 "Labels available: {}",