diff --git a/Cargo.lock b/Cargo.lock index 6befad3..82eedd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1140,6 +1140,7 @@ dependencies = [ "http", "jacquard-api", "jacquard-common", + "jacquard-derive", "miette", "reqwest", "serde", diff --git a/crates/jacquard-api/Cargo.toml b/crates/jacquard-api/Cargo.toml index 87b6905..fb2d621 100644 --- a/crates/jacquard-api/Cargo.toml +++ b/crates/jacquard-api/Cargo.toml @@ -12,7 +12,7 @@ exclude.workspace = true description.workspace = true [features] -default = ["app_bsky", "com_atproto", "tools_ozone", "chat_bsky"] +default = [ "com_atproto"] app_bsky = [] chat_bsky = [] com_atproto = [] diff --git a/crates/jacquard-api/src/lib.rs b/crates/jacquard-api/src/lib.rs index b347a8c..cf68b28 100644 --- a/crates/jacquard-api/src/lib.rs +++ b/crates/jacquard-api/src/lib.rs @@ -3,7 +3,14 @@ // This file was automatically generated from Lexicon schemas. // Any manual changes will be overwritten on the next regeneration. +#[cfg(feature = "app_bsky")] pub mod app_bsky; + +#[cfg(feature = "chat_bsky")] pub mod chat_bsky; + +#[cfg(feature = "com_atproto")] pub mod com_atproto; + +#[cfg(feature = "tools_ozone")] pub mod tools_ozone; \ No newline at end of file diff --git a/crates/jacquard-common/src/cowstr.rs b/crates/jacquard-common/src/cowstr.rs index c0d4081..1f0f6b9 100644 --- a/crates/jacquard-common/src/cowstr.rs +++ b/crates/jacquard-common/src/cowstr.rs @@ -9,7 +9,7 @@ use std::{ use crate::IntoStatic; -/// Shamelessly copied from https://github.com/bearcove/merde +/// Shamelessly copied from [](https://github.com/bearcove/merde) /// A copy-on-write immutable string type that uses [`SmolStr`] for /// the "owned" variant. /// diff --git a/crates/jacquard-common/src/into_static.rs b/crates/jacquard-common/src/into_static.rs index e00a15c..5f150d2 100644 --- a/crates/jacquard-common/src/into_static.rs +++ b/crates/jacquard-common/src/into_static.rs @@ -7,7 +7,7 @@ use std::hash::BuildHasher; use std::hash::Hash; use std::sync::Arc; -/// Shamelessly copied from https://github.com/bearcove/merde +/// Shamelessly copied from [](https://github.com/bearcove/merde) /// Allow turning a value into an "owned" variant, which can then be /// returned, moved, etc. /// diff --git a/crates/jacquard-common/src/types/aturi.rs b/crates/jacquard-common/src/types/aturi.rs index 418febe..30b14e3 100644 --- a/crates/jacquard-common/src/types/aturi.rs +++ b/crates/jacquard-common/src/types/aturi.rs @@ -14,7 +14,7 @@ use std::{ops::Deref, str::FromStr}; /// at:// URI type /// -/// based on the regex here: https://github.com/bluesky-social/atproto/blob/main/packages/syntax/src/aturi_validation.ts +/// based on the regex here: [](https://github.com/bluesky-social/atproto/blob/main/packages/syntax/src/aturi_validation.ts) /// /// Doesn't support the query segment, but then neither does the Typescript SDK. #[derive(PartialEq, Eq, Debug)] diff --git a/crates/jacquard-common/src/types/collection.rs b/crates/jacquard-common/src/types/collection.rs index f710dc8..ef9fdec 100644 --- a/crates/jacquard-common/src/types/collection.rs +++ b/crates/jacquard-common/src/types/collection.rs @@ -26,7 +26,7 @@ pub trait Collection: fmt::Debug + Serialize { /// /// Panics if [`Self::NSID`] is not a valid NSID. /// - /// [`Nsid`]: string::Nsid + /// [`Nsid`]: crate::types::string::Nsid fn nsid() -> crate::types::nsid::Nsid<'static> { Nsid::new_static(Self::NSID).expect("should be valid NSID") } @@ -39,7 +39,7 @@ pub trait Collection: fmt::Debug + Serialize { /// > [`RecordKey`]. /// /// [Repo Data Structure v3]: https://atproto.com/specs/repository#repo-data-structure-v3 - /// [`Nsid`]: string::Nsid + /// [`Nsid`]: crate::types::string::Nsid fn repo_path<'u, T: RecordKeyType>( rkey: &'u crate::types::recordkey::RecordKey, ) -> UriPath<'u> { diff --git a/crates/jacquard-common/src/types/did.rs b/crates/jacquard-common/src/types/did.rs index d44a667..6701527 100644 --- a/crates/jacquard-common/src/types/did.rs +++ b/crates/jacquard-common/src/types/did.rs @@ -76,7 +76,7 @@ impl<'d> Did<'d> { /// Infallible constructor for when you *know* the string is a valid DID. /// Will panic on invalid DIDs. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. pub fn raw(did: &'d str) -> Self { let did = did.strip_prefix("at://").unwrap_or(did); if did.len() > 2048 { diff --git a/crates/jacquard-common/src/types/handle.rs b/crates/jacquard-common/src/types/handle.rs index f96475a..7ebf2da 100644 --- a/crates/jacquard-common/src/types/handle.rs +++ b/crates/jacquard-common/src/types/handle.rs @@ -95,7 +95,7 @@ impl<'h> Handle<'h> { /// Infallible constructor for when you *know* the string is a valid handle. /// Will panic on invalid handles. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. /// /// Accepts (and strips) preceding '@' or 'at://' if present pub fn raw(handle: &'h str) -> Self { diff --git a/crates/jacquard-common/src/types/ident.rs b/crates/jacquard-common/src/types/ident.rs index da0f8ac..0e88a6f 100644 --- a/crates/jacquard-common/src/types/ident.rs +++ b/crates/jacquard-common/src/types/ident.rs @@ -49,7 +49,7 @@ impl<'i> AtIdentifier<'i> { /// Infallible constructor for when you *know* the string is a valid identifier. /// Will panic on invalid identifiers. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. pub fn raw(ident: &'i str) -> Self { if let Ok(did) = ident.parse() { AtIdentifier::Did(did) diff --git a/crates/jacquard-common/src/types/language.rs b/crates/jacquard-common/src/types/language.rs index 71c6694..74c8cf6 100644 --- a/crates/jacquard-common/src/types/language.rs +++ b/crates/jacquard-common/src/types/language.rs @@ -34,7 +34,7 @@ impl Language { /// Infallible constructor for when you *know* the string is a valid IETF language tag. /// Will panic on invalid tag. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. pub fn raw(lang: impl AsRef) -> Self { let lang = lang.as_ref(); let tag = langtag::LangTag::new(lang).expect("valid IETF language tag"); diff --git a/crates/jacquard-common/src/types/nsid.rs b/crates/jacquard-common/src/types/nsid.rs index c67b183..88910d4 100644 --- a/crates/jacquard-common/src/types/nsid.rs +++ b/crates/jacquard-common/src/types/nsid.rs @@ -71,7 +71,7 @@ impl<'n> Nsid<'n> { /// Infallible constructor for when you *know* the string is a valid NSID. /// Will panic on invalid NSIDs. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. pub fn raw(nsid: &'n str) -> Self { if nsid.len() > 317 { panic!("NSID too long") diff --git a/crates/jacquard-common/src/types/recordkey.rs b/crates/jacquard-common/src/types/recordkey.rs index b80e679..3ef88d6 100644 --- a/crates/jacquard-common/src/types/recordkey.rs +++ b/crates/jacquard-common/src/types/recordkey.rs @@ -14,7 +14,7 @@ use std::{ops::Deref, str::FromStr}; /// This is deliberately public (so that consumers can develop specialized record key types), /// but is marked as unsafe, because the implementer is expected to uphold the invariants /// required by this trait, namely compliance with the [spec](https://atproto.com/specs/record-key) -/// as described by [`RKEY_REGEX`](RKEY_REGEX). +/// as described by [`RKEY_REGEX`]. /// /// This crate provides implementations for TID, NSID, literals, and generic strings pub unsafe trait RecordKeyType: Clone + Serialize { @@ -57,7 +57,7 @@ where } /// ATProto Record Key (type `any`) -/// Catch-all for any string meeting the overall Record Key requirements detailed https://atproto.com/specs/record-key +/// Catch-all for any string meeting the overall Record Key requirements detailed [](https://atproto.com/specs/record-key) #[derive(Clone, PartialEq, Eq, Serialize, Hash)] #[serde(transparent)] #[repr(transparent)] @@ -298,7 +298,7 @@ impl LiteralKey { /// Infallible constructor for when you *know* the string is a valid rkey. /// Will panic on invalid rkeys. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. pub fn raw(rkey: &str) -> Self { if !rkey.eq_ignore_ascii_case(T::LITERAL) { panic!( diff --git a/crates/jacquard-common/src/types/tid.rs b/crates/jacquard-common/src/types/tid.rs index 1b1ea1a..6dac5fb 100644 --- a/crates/jacquard-common/src/types/tid.rs +++ b/crates/jacquard-common/src/types/tid.rs @@ -71,7 +71,7 @@ impl Tid { /// Infallible constructor for when you *know* the string is a valid TID. /// Will panic on invalid TID. If you're manually decoding atproto records /// or API values you know are valid (rather than using serde), this is the one to use. - /// The From and From impls use the same logic. + /// The `From` and `From` impls use the same logic. pub fn raw(tid: impl AsRef) -> Self { let tid = tid.as_ref(); if tid.len() != 13 { diff --git a/crates/jacquard-lexicon/src/codegen.rs b/crates/jacquard-lexicon/src/codegen.rs index 51cf698..5ede6c3 100644 --- a/crates/jacquard-lexicon/src/codegen.rs +++ b/crates/jacquard-lexicon/src/codegen.rs @@ -1089,11 +1089,20 @@ impl<'c> CodeGenerator<'c> { path }; + let is_root = dir.components().count() == 0; let mods: Vec<_> = module_names .iter() .map(|name| { let ident = syn::Ident::new(name, proc_macro2::Span::call_site()); - quote! { pub mod #ident; } + if is_root { + // Top-level modules get feature gates + quote! { + #[cfg(feature = #name)] + pub mod #ident; + } + } else { + quote! { pub mod #ident; } + } }) .collect(); diff --git a/crates/jacquard/Cargo.toml b/crates/jacquard/Cargo.toml index 181ca5b..e6b3ae1 100644 --- a/crates/jacquard/Cargo.toml +++ b/crates/jacquard/Cargo.toml @@ -6,7 +6,11 @@ description = "A simple Rust project using Nix" version.workspace = true edition.workspace = true -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["api_all"] +derive = ["dep:jacquard-derive"] +api = ["jacquard-api/com_atproto"] +api_all = ["api", "jacquard-api/app_bsky", "jacquard-api/chat_bsky", "jacquard-api/tools_ozone"] [lib] name = "jacquard" @@ -22,6 +26,7 @@ clap = { workspace = true } http = "1.3.1" jacquard-api = { version = "0.1.0", path = "../jacquard-api" } jacquard-common = { path = "../jacquard-common" } +jacquard-derive = { path = "../jacquard-derive", optional = true } miette = "7.6.0" reqwest = { version = "0.12.23", default-features = false, features = ["charset", "http2", "json", "system-proxy", "gzip", "rustls-tls"] } serde = { version = "1.0", features = ["derive"] } diff --git a/crates/jacquard/src/lib.rs b/crates/jacquard/src/lib.rs index 2ddbd03..d662fef 100644 --- a/crates/jacquard/src/lib.rs +++ b/crates/jacquard/src/lib.rs @@ -1,4 +1,9 @@ pub mod client; // Re-export common types +#[cfg(feature = "api")] +pub use jacquard_api as api; pub use jacquard_common::*; + +#[cfg(feature = "derive")] +pub use jacquard_derive::*;