A better Rust ATProto crate

refactored codegen to be more navigable, fixed a number of bugs

Orual c08fa921 0cbdaf71

Changed files
+4355 -4663
crates
jacquard-api
lexicons
src
app_bsky
app_ocho
blog_pckt
chat_bsky
com_atproto
com_shinolabs
pinksea
com_whtwnd
community_lexicon
calendar
events_smokesignal
my_skylights
net_anisota
place_atwork
place_stream
pub_leaflet
sh_tangled
sh_weaver
social_clippr
social_grain
social_psky
richtext
tools_ozone
uk_skyblur
win_tomo_x
jacquard-lexicon
+103 -15
Cargo.lock
···
"bytes",
"clap",
"http",
-
"jacquard-api",
-
"jacquard-common",
-
"jacquard-derive",
-
"jacquard-identity",
+
"jacquard-api 0.4.1",
+
"jacquard-common 0.4.0",
+
"jacquard-derive 0.4.0",
+
"jacquard-identity 0.4.0",
"jacquard-oauth",
"jose-jwk",
"miette",
···
[[package]]
name = "jacquard-api"
version = "0.4.0"
+
source = "git+https://tangled.org/@nonbinary.computer/jacquard#0cbdaf71e0721122b354892bb8ae49aa3ffcc9bc"
dependencies = [
"bon",
"bytes",
-
"jacquard-common",
-
"jacquard-derive",
+
"jacquard-common 0.4.0 (git+https://tangled.org/@nonbinary.computer/jacquard)",
+
"jacquard-derive 0.4.0 (git+https://tangled.org/@nonbinary.computer/jacquard)",
+
"miette",
+
"serde",
+
"thiserror 2.0.17",
+
]
+
+
[[package]]
+
name = "jacquard-api"
+
version = "0.4.1"
+
dependencies = [
+
"bon",
+
"bytes",
+
"jacquard-common 0.4.0",
+
"jacquard-derive 0.4.0",
"miette",
"serde",
"thiserror 2.0.17",
···
"axum-test",
"bytes",
"jacquard",
-
"jacquard-common",
+
"jacquard-common 0.4.0",
"miette",
"serde",
"serde_html_form",
···
[[package]]
+
name = "jacquard-common"
+
version = "0.4.0"
+
source = "git+https://tangled.org/@nonbinary.computer/jacquard#0cbdaf71e0721122b354892bb8ae49aa3ffcc9bc"
+
dependencies = [
+
"async-trait",
+
"base64 0.22.1",
+
"bon",
+
"bytes",
+
"chrono",
+
"cid",
+
"http",
+
"ipld-core",
+
"langtag",
+
"miette",
+
"multibase",
+
"multihash",
+
"num-traits",
+
"ouroboros",
+
"rand 0.9.2",
+
"regex",
+
"reqwest",
+
"serde",
+
"serde_html_form",
+
"serde_ipld_dagcbor",
+
"serde_json",
+
"serde_with",
+
"smol_str",
+
"thiserror 2.0.17",
+
"tokio",
+
"trait-variant",
+
"url",
+
]
+
+
[[package]]
name = "jacquard-derive"
version = "0.4.0"
dependencies = [
"heck 0.5.0",
"itertools",
-
"jacquard-common",
+
"jacquard-common 0.4.0",
+
"prettyplease",
+
"proc-macro2",
+
"quote",
+
"serde",
+
"serde_json",
+
"serde_repr",
+
"serde_with",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "jacquard-derive"
+
version = "0.4.0"
+
source = "git+https://tangled.org/@nonbinary.computer/jacquard#0cbdaf71e0721122b354892bb8ae49aa3ffcc9bc"
+
dependencies = [
+
"heck 0.5.0",
+
"itertools",
"prettyplease",
"proc-macro2",
"quote",
···
"bytes",
"hickory-resolver",
"http",
-
"jacquard-api",
-
"jacquard-common",
+
"jacquard-api 0.4.1",
+
"jacquard-common 0.4.0",
+
"miette",
+
"percent-encoding",
+
"reqwest",
+
"serde",
+
"serde_html_form",
+
"serde_json",
+
"thiserror 2.0.17",
+
"tokio",
+
"url",
+
"urlencoding",
+
]
+
+
[[package]]
+
name = "jacquard-identity"
+
version = "0.4.0"
+
source = "git+https://tangled.org/@nonbinary.computer/jacquard#0cbdaf71e0721122b354892bb8ae49aa3ffcc9bc"
+
dependencies = [
+
"async-trait",
+
"bon",
+
"bytes",
+
"http",
+
"jacquard-api 0.4.0",
+
"jacquard-common 0.4.0 (git+https://tangled.org/@nonbinary.computer/jacquard)",
"miette",
"percent-encoding",
"reqwest",
···
"glob",
"heck 0.5.0",
"itertools",
-
"jacquard-api",
-
"jacquard-common",
-
"jacquard-identity",
+
"jacquard-api 0.4.0",
+
"jacquard-common 0.4.0 (git+https://tangled.org/@nonbinary.computer/jacquard)",
+
"jacquard-identity 0.4.0 (git+https://tangled.org/@nonbinary.computer/jacquard)",
"kdl",
"miette",
"prettyplease",
···
"dashmap",
"elliptic-curve",
"http",
-
"jacquard-common",
-
"jacquard-identity",
+
"jacquard-common 0.4.0",
+
"jacquard-identity 0.4.0",
"jose-jwa",
"jose-jwk",
"miette",
+7 -6
crates/jacquard-api/Cargo.toml
···
name = "jacquard-api"
description = "Generated AT Protocol API bindings for Jacquard"
edition.workspace = true
-
version = "0.4.0"
+
version = "0.4.1"
authors.workspace = true
repository.workspace = true
keywords.workspace = true
···
# --- generated ---
# Generated namespace features
app_blebbit = []
-
app_bsky = ["com_atproto"]
+
app_bsky = []
app_ocho = []
beauty_cybernetic = []
blog_pckt = []
···
blue_linkat = []
blue_zio = []
buzz_bookhive = []
-
chat_bsky = ["app_bsky"]
+
chat_bsky = []
club_stellz = []
com_atproto = []
com_bad_example = []
···
dev_fudgeu = []
dev_ocbwoy3 = []
dev_regnault = []
+
events_smokesignal = []
fyi_unravel = []
garden_lexicon = []
moe_karashiiro = []
my_skylights = []
net_aftertheinter = []
-
net_anisota = ["app_bsky", "com_atproto"]
+
net_anisota = ["app_bsky"]
net_bnewbold = []
net_mmatt = []
network_slices = []
org_devcon = []
org_robocracy = []
place_atwork = []
-
place_stream = []
+
place_stream = ["app_bsky"]
pub_leaflet = []
sh_tangled = []
sh_weaver = ["app_bsky"]
social_clippr = []
-
social_grain = ["com_atproto"]
+
social_grain = []
social_pmsky = []
social_psky = []
tools_ozone = ["chat_bsky", "com_atproto"]
+26
crates/jacquard-api/lexicons/win_tomo-x_pushat_allow.json
···
+
{
+
"lexicon": 1,
+
"id": "win.tomo-x.pushat.allow",
+
"defs": {
+
"main": {
+
"type": "record",
+
"description": "allow service to push. key must be did",
+
"key": "any",
+
"record": {
+
"type": "object",
+
"required": [
+
"createdAt"
+
],
+
"properties": {
+
"config": {
+
"type": "unknown"
+
},
+
"createdAt": {
+
"type": "string",
+
"format": "datetime"
+
}
+
}
+
}
+
}
+
}
+
}
+63
crates/jacquard-api/lexicons/win_tomo-x_pushat_defs.json
···
+
{
+
"lexicon": 1,
+
"id": "win.tomo-x.pushat.defs",
+
"defs": {
+
"deviceList": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "#deviceListItem"
+
}
+
},
+
"deviceListItem": {
+
"type": "object",
+
"required": [
+
"name",
+
"id",
+
"current"
+
],
+
"properties": {
+
"current": {
+
"type": "boolean",
+
"default": false
+
},
+
"id": {
+
"type": "string",
+
"format": "tid"
+
},
+
"name": {
+
"type": "string",
+
"maxLength": 300,
+
"maxGraphemes": 30
+
}
+
}
+
},
+
"notifyBody": {
+
"type": "object",
+
"required": [
+
"title",
+
"body"
+
],
+
"properties": {
+
"body": {
+
"type": "string",
+
"description": "Body text of the notification."
+
},
+
"icon": {
+
"type": "string",
+
"description": "The URI of the icon displayed in the notification.",
+
"format": "uri"
+
},
+
"link": {
+
"type": "string",
+
"description": "Experimental — do not use. The URI to open when the notification is clicked.",
+
"format": "uri"
+
},
+
"title": {
+
"type": "string",
+
"description": "Title text of the notification."
+
}
+
}
+
}
+
}
+
}
+10 -1
crates/jacquard-api/lexicons/win_tomo-x_pushat_pushNotify.json
···
},
"target": {
"type": "string",
+
"description": "The DID of the target user to whom the notification will be sent.",
"format": "did"
}
}
···
"type": "object",
"properties": {}
}
-
}
+
},
+
"errors": [
+
{
+
"name": "ServiceNotAllowedError"
+
},
+
{
+
"name": "DeviceNotFoundError"
+
}
+
]
}
}
}
+72 -21
crates/jacquard-api/src/app_bsky/actor.rs
···
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub postgate_embedding_rules: std::option::Option<
-
Vec<jacquard_common::types::value::Data<'a>>,
+
Vec<crate::app_bsky::feed::postgate::DisableRule<'a>>,
>,
///Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub threadgate_allow_rules: std::option::Option<
-
Vec<jacquard_common::types::value::Data<'a>>,
+
Vec<PostInteractionSettingsPrefThreadgateAllowRulesItem<'a>>,
>,
}
-
pub type Preferences<'a> = Vec<jacquard_common::types::value::Data<'a>>;
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum PostInteractionSettingsPrefThreadgateAllowRulesItem<'a> {
+
#[serde(rename = "app.bsky.feed.threadgate#mentionRule")]
+
ThreadgateMentionRule(Box<crate::app_bsky::feed::threadgate::MentionRule<'a>>),
+
#[serde(rename = "app.bsky.feed.threadgate#followerRule")]
+
ThreadgateFollowerRule(Box<crate::app_bsky::feed::threadgate::FollowerRule<'a>>),
+
#[serde(rename = "app.bsky.feed.threadgate#followingRule")]
+
ThreadgateFollowingRule(Box<crate::app_bsky::feed::threadgate::FollowingRule<'a>>),
+
#[serde(rename = "app.bsky.feed.threadgate#listRule")]
+
ThreadgateListRule(Box<crate::app_bsky::feed::threadgate::ListRule<'a>>),
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum PreferencesItem<'a> {
+
#[serde(rename = "app.bsky.actor.defs#adultContentPref")]
+
AdultContentPref(Box<crate::app_bsky::actor::AdultContentPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#contentLabelPref")]
+
ContentLabelPref(Box<crate::app_bsky::actor::ContentLabelPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#savedFeedsPref")]
+
SavedFeedsPref(Box<crate::app_bsky::actor::SavedFeedsPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#savedFeedsPrefV2")]
+
SavedFeedsPrefV2(Box<crate::app_bsky::actor::SavedFeedsPrefV2<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#personalDetailsPref")]
+
PersonalDetailsPref(Box<crate::app_bsky::actor::PersonalDetailsPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#feedViewPref")]
+
FeedViewPref(Box<crate::app_bsky::actor::FeedViewPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#threadViewPref")]
+
ThreadViewPref(Box<crate::app_bsky::actor::ThreadViewPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#interestsPref")]
+
InterestsPref(Box<crate::app_bsky::actor::InterestsPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#mutedWordsPref")]
+
MutedWordsPref(Box<crate::app_bsky::actor::MutedWordsPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#hiddenPostsPref")]
+
HiddenPostsPref(Box<crate::app_bsky::actor::HiddenPostsPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#bskyAppStatePref")]
+
BskyAppStatePref(Box<crate::app_bsky::actor::BskyAppStatePref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#labelersPref")]
+
LabelersPref(Box<crate::app_bsky::actor::LabelersPref<'a>>),
+
#[serde(rename = "app.bsky.actor.defs#postInteractionSettingsPref")]
+
PostInteractionSettingsPref(
+
Box<crate::app_bsky::actor::PostInteractionSettingsPref<'a>>,
+
),
+
#[serde(rename = "app.bsky.actor.defs#verificationPrefs")]
+
VerificationPrefs(Box<crate::app_bsky::actor::VerificationPrefs<'a>>),
+
}
+
+
pub type Preferences<'a> = Vec<PreferencesItem<'a>>;
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
///An optional embed associated with the status.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<StatusViewRecordEmbed<'a>>,
+
pub embed: std::option::Option<crate::app_bsky::embed::external::View<'a>>,
///The date when this status will expire. The application might choose to no longer return the status after expiration.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub expires_at: std::option::Option<jacquard_common::types::string::Datetime>,
···
///The status for the account.
#[serde(borrow)]
pub status: jacquard_common::CowStr<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum StatusViewRecordEmbed<'a> {
-
#[serde(rename = "app.bsky.embed.external#view")]
-
ExternalView(Box<crate::app_bsky::embed::external::View<'a>>),
}
#[jacquard_derive::lexicon]
+1 -18
crates/jacquard-api/src/app_bsky/actor/profile.rs
···
///Self-label values, specific to the Bluesky application, on the overall account.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<ProfileRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub pinned_post: std::option::Option<
···
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub website: std::option::Option<jacquard_common::types::string::Uri<'a>>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ProfileRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for Profile<'_> {
+1 -18
crates/jacquard-api/src/app_bsky/actor/status.rs
···
///An optional embed associated with the status.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<StatusRecordEmbed<'a>>,
+
pub embed: std::option::Option<crate::app_bsky::embed::external::ExternalRecord<'a>>,
///The status for the account.
#[serde(borrow)]
pub status: jacquard_common::CowStr<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum StatusRecordEmbed<'a> {
-
#[serde(rename = "app.bsky.embed.external")]
-
External(Box<crate::app_bsky::embed::external::ExternalRecord<'a>>),
}
impl jacquard_common::types::collection::Collection for Status<'_> {
+5 -5
crates/jacquard-api/src/app_bsky/bookmark.rs
···
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub created_at: std::option::Option<jacquard_common::types::string::Datetime>,
#[serde(borrow)]
-
pub item: BookmarkViewRecordItem<'a>,
+
pub item: BookmarkViewItem<'a>,
///A strong ref to the bookmarked record.
#[serde(borrow)]
pub subject: crate::com_atproto::repo::strong_ref::StrongRef<'a>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum BookmarkViewRecordItem<'a> {
+
pub enum BookmarkViewItem<'a> {
#[serde(rename = "app.bsky.feed.defs#blockedPost")]
-
DefsBlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
+
BlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
#[serde(rename = "app.bsky.feed.defs#notFoundPost")]
-
DefsNotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
+
NotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
#[serde(rename = "app.bsky.feed.defs#postView")]
-
DefsPostView(Box<crate::app_bsky::feed::PostView<'a>>),
+
PostView(Box<crate::app_bsky::feed::PostView<'a>>),
}
+2 -15
crates/jacquard-api/src/app_bsky/bookmark/create_bookmark.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateBookmarkError<'_> {
-
type Output = CreateBookmarkError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateBookmarkError::UnsupportedCollection(v) => {
-
CreateBookmarkError::UnsupportedCollection(v.into_static())
-
}
-
CreateBookmarkError::Unknown(v) => {
-
CreateBookmarkError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/app_bsky/bookmark/delete_bookmark.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteBookmarkError<'_> {
-
type Output = DeleteBookmarkError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteBookmarkError::UnsupportedCollection(v) => {
-
DeleteBookmarkError::UnsupportedCollection(v.into_static())
-
}
-
DeleteBookmarkError::Unknown(v) => {
-
DeleteBookmarkError::Unknown(v.into_static())
-
}
}
}
}
+40 -7
crates/jacquard-api/src/app_bsky/embed/record.rs
···
#[serde(rename_all = "camelCase")]
pub struct View<'a> {
#[serde(borrow)]
-
pub record: ViewRecordRecord<'a>,
+
pub record: ViewUnionRecord<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ViewRecordRecord<'a> {
+
pub enum ViewUnionRecord<'a> {
+
#[serde(rename = "app.bsky.embed.record#viewRecord")]
+
ViewRecord(Box<crate::app_bsky::embed::record::ViewRecord<'a>>),
+
#[serde(rename = "app.bsky.embed.record#viewNotFound")]
+
ViewNotFound(Box<crate::app_bsky::embed::record::ViewNotFound<'a>>),
+
#[serde(rename = "app.bsky.embed.record#viewBlocked")]
+
ViewBlocked(Box<crate::app_bsky::embed::record::ViewBlocked<'a>>),
+
#[serde(rename = "app.bsky.embed.record#viewDetached")]
+
ViewDetached(Box<crate::app_bsky::embed::record::ViewDetached<'a>>),
#[serde(rename = "app.bsky.feed.defs#generatorView")]
-
DefsGeneratorView(Box<crate::app_bsky::feed::GeneratorView<'a>>),
+
GeneratorView(Box<crate::app_bsky::feed::GeneratorView<'a>>),
#[serde(rename = "app.bsky.graph.defs#listView")]
-
DefsListView(Box<crate::app_bsky::graph::ListView<'a>>),
+
ListView(Box<crate::app_bsky::graph::ListView<'a>>),
#[serde(rename = "app.bsky.labeler.defs#labelerView")]
-
DefsLabelerView(Box<crate::app_bsky::labeler::LabelerView<'a>>),
+
LabelerView(Box<crate::app_bsky::labeler::LabelerView<'a>>),
#[serde(rename = "app.bsky.graph.defs#starterPackViewBasic")]
-
DefsStarterPackViewBasic(Box<crate::app_bsky::graph::StarterPackViewBasic<'a>>),
+
StarterPackViewBasic(Box<crate::app_bsky::graph::StarterPackViewBasic<'a>>),
}
#[jacquard_derive::lexicon]
···
pub cid: jacquard_common::types::string::Cid<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embeds: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub embeds: std::option::Option<Vec<ViewRecordEmbedsItem<'a>>>,
pub indexed_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
///The record data itself.
#[serde(borrow)]
pub value: jacquard_common::types::value::Data<'a>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum ViewRecordEmbedsItem<'a> {
+
#[serde(rename = "app.bsky.embed.images#view")]
+
ImagesView(Box<crate::app_bsky::embed::images::View<'a>>),
+
#[serde(rename = "app.bsky.embed.video#view")]
+
VideoView(Box<crate::app_bsky::embed::video::View<'a>>),
+
#[serde(rename = "app.bsky.embed.external#view")]
+
ExternalView(Box<crate::app_bsky::embed::external::View<'a>>),
+
#[serde(rename = "app.bsky.embed.record#view")]
+
View(Box<crate::app_bsky::embed::record::View<'a>>),
+
#[serde(rename = "app.bsky.embed.recordWithMedia#view")]
+
RecordWithMediaView(Box<crate::app_bsky::embed::record_with_media::View<'a>>),
}
+4 -4
crates/jacquard-api/src/app_bsky/embed/record_with_media.rs
···
#[serde(rename_all = "camelCase")]
pub struct RecordWithMedia<'a> {
#[serde(borrow)]
-
pub media: RecordWithMediaRecordMedia<'a>,
+
pub media: RecordWithMediaMedia<'a>,
#[serde(borrow)]
pub record: crate::app_bsky::embed::record::Record<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum RecordWithMediaRecordMedia<'a> {
+
pub enum RecordWithMediaMedia<'a> {
#[serde(rename = "app.bsky.embed.images")]
Images(Box<crate::app_bsky::embed::images::Images<'a>>),
#[serde(rename = "app.bsky.embed.video")]
···
#[serde(rename_all = "camelCase")]
pub struct View<'a> {
#[serde(borrow)]
-
pub media: ViewRecordMedia<'a>,
+
pub media: ViewMedia<'a>,
#[serde(borrow)]
pub record: crate::app_bsky::embed::record::View<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ViewRecordMedia<'a> {
+
pub enum ViewMedia<'a> {
#[serde(rename = "app.bsky.embed.images#view")]
ImagesView(Box<crate::app_bsky::embed::images::View<'a>>),
#[serde(rename = "app.bsky.embed.video#view")]
+70 -13
crates/jacquard-api/src/app_bsky/feed.rs
···
pub post: crate::app_bsky::feed::PostView<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub reason: std::option::Option<FeedViewPostRecordReason<'a>>,
+
pub reason: std::option::Option<FeedViewPostReason<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub reply: std::option::Option<crate::app_bsky::feed::ReplyRef<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum FeedViewPostRecordReason<'a> {}
+
pub enum FeedViewPostReason<'a> {
+
#[serde(rename = "app.bsky.feed.defs#reasonRepost")]
+
ReasonRepost(Box<crate::app_bsky::feed::ReasonRepost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#reasonPin")]
+
ReasonPin(Box<crate::app_bsky::feed::ReasonPin<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
pub cid: jacquard_common::types::string::Cid<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<PostViewRecordEmbed<'a>>,
+
pub embed: std::option::Option<PostViewEmbed<'a>>,
pub indexed_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PostViewRecordEmbed<'a> {
+
pub enum PostViewEmbed<'a> {
#[serde(rename = "app.bsky.embed.images#view")]
ImagesView(Box<crate::app_bsky::embed::images::View<'a>>),
#[serde(rename = "app.bsky.embed.video#view")]
···
crate::app_bsky::actor::ProfileViewBasic<'a>,
>,
#[serde(borrow)]
-
pub parent: ReplyRefRecordParent<'a>,
+
pub parent: ReplyRefParent<'a>,
#[serde(borrow)]
-
pub root: ReplyRefRecordRoot<'a>,
+
pub root: ReplyRefRoot<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ReplyRefRecordParent<'a> {}
+
pub enum ReplyRefParent<'a> {
+
#[serde(rename = "app.bsky.feed.defs#postView")]
+
PostView(Box<crate::app_bsky::feed::PostView<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#notFoundPost")]
+
NotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#blockedPost")]
+
BlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
+
}
+
#[jacquard_derive::open_union]
#[derive(
serde::Serialize,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ReplyRefRecordRoot<'a> {}
+
pub enum ReplyRefRoot<'a> {
+
#[serde(rename = "app.bsky.feed.defs#postView")]
+
PostView(Box<crate::app_bsky::feed::PostView<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#notFoundPost")]
+
NotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#blockedPost")]
+
BlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
+
}
+
///Request that less content like the given feed item be shown in the feed
#[derive(
serde::Serialize,
···
pub post: jacquard_common::types::string::AtUri<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub reason: std::option::Option<SkeletonFeedPostRecordReason<'a>>,
+
pub reason: std::option::Option<SkeletonFeedPostReason<'a>>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum SkeletonFeedPostRecordReason<'a> {}
+
pub enum SkeletonFeedPostReason<'a> {
+
#[serde(rename = "app.bsky.feed.defs#skeletonReasonRepost")]
+
SkeletonReasonRepost(Box<crate::app_bsky::feed::SkeletonReasonRepost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#skeletonReasonPin")]
+
SkeletonReasonPin(Box<crate::app_bsky::feed::SkeletonReasonPin<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
pub struct ThreadViewPost<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub parent: std::option::Option<ThreadViewPostRecordParent<'a>>,
+
pub parent: std::option::Option<ThreadViewPostParent<'a>>,
#[serde(borrow)]
pub post: crate::app_bsky::feed::PostView<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub replies: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub replies: std::option::Option<Vec<ThreadViewPostRepliesItem<'a>>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub thread_context: std::option::Option<crate::app_bsky::feed::ThreadContext<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThreadViewPostRecordParent<'a> {}
+
pub enum ThreadViewPostParent<'a> {
+
#[serde(rename = "app.bsky.feed.defs#threadViewPost")]
+
ThreadViewPost(Box<crate::app_bsky::feed::ThreadViewPost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#notFoundPost")]
+
NotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#blockedPost")]
+
BlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum ThreadViewPostRepliesItem<'a> {
+
#[serde(rename = "app.bsky.feed.defs#threadViewPost")]
+
ThreadViewPost(Box<crate::app_bsky::feed::ThreadViewPost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#notFoundPost")]
+
NotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
+
#[serde(rename = "app.bsky.feed.defs#blockedPost")]
+
BlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
+1 -18
crates/jacquard-api/src/app_bsky/feed/generator.rs
···
///Self-label values
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<GeneratorRecordLabels<'a>>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum GeneratorRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
}
impl jacquard_common::types::collection::Collection for Generator<'_> {
+2 -18
crates/jacquard-api/src/app_bsky/feed/get_actor_likes.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetActorLikesError<'_> {
-
type Output = GetActorLikesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetActorLikesError::BlockedActor(v) => {
-
GetActorLikesError::BlockedActor(v.into_static())
-
}
-
GetActorLikesError::BlockedByActor(v) => {
-
GetActorLikesError::BlockedByActor(v.into_static())
-
}
-
GetActorLikesError::Unknown(v) => {
-
GetActorLikesError::Unknown(v.into_static())
-
}
}
}
}
+2 -18
crates/jacquard-api/src/app_bsky/feed/get_author_feed.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetAuthorFeedError<'_> {
-
type Output = GetAuthorFeedError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetAuthorFeedError::BlockedActor(v) => {
-
GetAuthorFeedError::BlockedActor(v.into_static())
-
}
-
GetAuthorFeedError::BlockedByActor(v) => {
-
GetAuthorFeedError::BlockedByActor(v.into_static())
-
}
-
GetAuthorFeedError::Unknown(v) => {
-
GetAuthorFeedError::Unknown(v.into_static())
-
}
}
}
}
+2 -11
crates/jacquard-api/src/app_bsky/feed/get_feed.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetFeedError<'_> {
-
type Output = GetFeedError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetFeedError::UnknownFeed(v) => GetFeedError::UnknownFeed(v.into_static()),
-
GetFeedError::Unknown(v) => GetFeedError::Unknown(v.into_static()),
}
}
}
+2 -15
crates/jacquard-api/src/app_bsky/feed/get_feed_skeleton.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetFeedSkeletonError<'_> {
-
type Output = GetFeedSkeletonError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetFeedSkeletonError::UnknownFeed(v) => {
-
GetFeedSkeletonError::UnknownFeed(v.into_static())
-
}
-
GetFeedSkeletonError::Unknown(v) => {
-
GetFeedSkeletonError::Unknown(v.into_static())
-
}
}
}
}
+2 -13
crates/jacquard-api/src/app_bsky/feed/get_list_feed.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetListFeedError<'_> {
-
type Output = GetListFeedError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetListFeedError::UnknownList(v) => {
-
GetListFeedError::UnknownList(v.into_static())
-
}
-
GetListFeedError::Unknown(v) => GetListFeedError::Unknown(v.into_static()),
}
}
}
+7 -20
crates/jacquard-api/src/app_bsky/feed/get_post_thread.rs
···
#[serde(rename_all = "camelCase")]
pub struct GetPostThreadOutput<'a> {
#[serde(borrow)]
-
pub thread: GetPostThreadOutputRecordThread<'a>,
+
pub thread: GetPostThreadOutputThread<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub threadgate: std::option::Option<crate::app_bsky::feed::ThreadgateView<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum GetPostThreadOutputRecordThread<'a> {
+
pub enum GetPostThreadOutputThread<'a> {
#[serde(rename = "app.bsky.feed.defs#threadViewPost")]
-
DefsThreadViewPost(Box<crate::app_bsky::feed::ThreadViewPost<'a>>),
+
ThreadViewPost(Box<crate::app_bsky::feed::ThreadViewPost<'a>>),
#[serde(rename = "app.bsky.feed.defs#notFoundPost")]
-
DefsNotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
+
NotFoundPost(Box<crate::app_bsky::feed::NotFoundPost<'a>>),
#[serde(rename = "app.bsky.feed.defs#blockedPost")]
-
DefsBlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
+
BlockedPost(Box<crate::app_bsky::feed::BlockedPost<'a>>),
}
#[jacquard_derive::open_union]
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetPostThreadError<'_> {
-
type Output = GetPostThreadError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetPostThreadError::NotFound(v) => {
-
GetPostThreadError::NotFound(v.into_static())
-
}
-
GetPostThreadError::Unknown(v) => {
-
GetPostThreadError::Unknown(v.into_static())
-
}
}
}
}
+3 -20
crates/jacquard-api/src/app_bsky/feed/post.rs
···
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<PostRecordEmbed<'a>>,
+
pub embed: std::option::Option<PostEmbed<'a>>,
///DEPRECATED: replaced by app.bsky.richtext.facet.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
///Self-label values for this post. Effectively content warnings.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<PostRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
///Indicates human language of post primary text content.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub langs: std::option::Option<Vec<jacquard_common::types::string::Language>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PostRecordEmbed<'a> {
+
pub enum PostEmbed<'a> {
#[serde(rename = "app.bsky.embed.images")]
Images(Box<crate::app_bsky::embed::images::Images<'a>>),
#[serde(rename = "app.bsky.embed.video")]
···
Record(Box<crate::app_bsky::embed::record::Record<'a>>),
#[serde(rename = "app.bsky.embed.recordWithMedia")]
RecordWithMedia(Box<crate::app_bsky::embed::record_with_media::RecordWithMedia<'a>>),
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PostRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for Post<'_> {
+1 -1
crates/jacquard-api/src/app_bsky/feed/postgate.rs
···
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub embedding_rules: std::option::Option<
-
Vec<jacquard_common::types::value::Data<'a>>,
+
Vec<crate::app_bsky::feed::postgate::DisableRule<'a>>,
>,
///Reference (AT-URI) to the post record.
#[serde(borrow)]
+2 -13
crates/jacquard-api/src/app_bsky/feed/search_posts.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SearchPostsError<'_> {
-
type Output = SearchPostsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SearchPostsError::BadQueryString(v) => {
-
SearchPostsError::BadQueryString(v.into_static())
-
}
-
SearchPostsError::Unknown(v) => SearchPostsError::Unknown(v.into_static()),
}
}
}
+24 -1
crates/jacquard-api/src/app_bsky/feed/threadgate.rs
···
///List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub allow: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub allow: std::option::Option<Vec<ThreadgateAllowItem<'a>>>,
pub created_at: jacquard_common::types::string::Datetime,
///List of hidden reply URIs.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
···
///Reference (AT-URI) to the post record.
#[serde(borrow)]
pub post: jacquard_common::types::string::AtUri<'a>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum ThreadgateAllowItem<'a> {
+
#[serde(rename = "app.bsky.feed.threadgate#mentionRule")]
+
MentionRule(Box<crate::app_bsky::feed::threadgate::MentionRule<'a>>),
+
#[serde(rename = "app.bsky.feed.threadgate#followerRule")]
+
FollowerRule(Box<crate::app_bsky::feed::threadgate::FollowerRule<'a>>),
+
#[serde(rename = "app.bsky.feed.threadgate#followingRule")]
+
FollowingRule(Box<crate::app_bsky::feed::threadgate::FollowingRule<'a>>),
+
#[serde(rename = "app.bsky.feed.threadgate#listRule")]
+
ListRule(Box<crate::app_bsky::feed::threadgate::ListRule<'a>>),
}
impl jacquard_common::types::collection::Collection for Threadgate<'_> {
+22 -16
crates/jacquard-api/src/app_bsky/graph/get_relationships.rs
···
#[serde(borrow)]
pub actor: std::option::Option<jacquard_common::types::string::Did<'a>>,
#[serde(borrow)]
-
pub relationships: Vec<jacquard_common::types::value::Data<'a>>,
+
pub relationships: Vec<GetRelationshipsOutputRelationshipsItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetRelationshipsOutputRelationshipsItem<'a> {
+
#[serde(rename = "app.bsky.graph.defs#relationship")]
+
Relationship(Box<crate::app_bsky::graph::Relationship<'a>>),
+
#[serde(rename = "app.bsky.graph.defs#notFoundActor")]
+
NotFoundActor(Box<crate::app_bsky::graph::NotFoundActor<'a>>),
}
#[jacquard_derive::open_union]
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRelationshipsError<'_> {
-
type Output = GetRelationshipsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRelationshipsError::ActorNotFound(v) => {
-
GetRelationshipsError::ActorNotFound(v.into_static())
-
}
-
GetRelationshipsError::Unknown(v) => {
-
GetRelationshipsError::Unknown(v.into_static())
-
}
}
}
}
+1 -18
crates/jacquard-api/src/app_bsky/graph/list.rs
···
>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<ListRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
///Display name for list; can not be empty.
#[serde(borrow)]
pub name: jacquard_common::CowStr<'a>,
///Defines the purpose of the list (aka, moderation-oriented or curration-oriented)
#[serde(borrow)]
pub purpose: crate::app_bsky::graph::ListPurpose<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ListRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for List<'_> {
+20 -1
crates/jacquard-api/src/app_bsky/labeler/get_services.rs
···
#[serde(rename_all = "camelCase")]
pub struct GetServicesOutput<'a> {
#[serde(borrow)]
-
pub views: Vec<jacquard_common::types::value::Data<'a>>,
+
pub views: Vec<GetServicesOutputViewsItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetServicesOutputViewsItem<'a> {
+
#[serde(rename = "app.bsky.labeler.defs#labelerView")]
+
LabelerView(Box<crate::app_bsky::labeler::LabelerView<'a>>),
+
#[serde(rename = "app.bsky.labeler.defs#labelerViewDetailed")]
+
LabelerViewDetailed(Box<crate::app_bsky::labeler::LabelerViewDetailed<'a>>),
}
///Response type for
+1 -18
crates/jacquard-api/src/app_bsky/labeler/service.rs
···
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<ServiceRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
#[serde(borrow)]
pub policies: crate::app_bsky::labeler::LabelerPolicies<'a>,
///The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed.
···
pub subject_types: std::option::Option<
Vec<crate::com_atproto::moderation::SubjectType<'a>>,
>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ServiceRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for Service<'_> {
+22 -1
crates/jacquard-api/src/app_bsky/richtext/facet.rs
···
#[serde(rename_all = "camelCase")]
pub struct Facet<'a> {
#[serde(borrow)]
-
pub features: Vec<jacquard_common::types::value::Data<'a>>,
+
pub features: Vec<FacetFeaturesItem<'a>>,
#[serde(borrow)]
pub index: crate::app_bsky::richtext::facet::ByteSlice<'a>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum FacetFeaturesItem<'a> {
+
#[serde(rename = "app.bsky.richtext.facet#mention")]
+
Mention(Box<crate::app_bsky::richtext::facet::Mention<'a>>),
+
#[serde(rename = "app.bsky.richtext.facet#link")]
+
Link(Box<crate::app_bsky::richtext::facet::Link<'a>>),
+
#[serde(rename = "app.bsky.richtext.facet#tag")]
+
Tag(Box<crate::app_bsky::richtext::facet::Tag<'a>>),
}
///Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.
+1 -18
crates/jacquard-api/src/app_bsky/unspecced/get_post_thread_other_v2.rs
···
#[serde(borrow)]
pub uri: jacquard_common::types::string::AtUri<'a>,
#[serde(borrow)]
-
pub value: ThreadItemRecordValue<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThreadItemRecordValue<'a> {
-
#[serde(rename = "app.bsky.unspecced.defs#threadItemPost")]
-
DefsThreadItemPost(Box<crate::app_bsky::unspecced::ThreadItemPost<'a>>),
+
pub value: crate::app_bsky::unspecced::ThreadItemPost<'a>,
}
+6 -6
crates/jacquard-api/src/app_bsky/unspecced/get_post_thread_v2.rs
···
#[serde(borrow)]
pub uri: jacquard_common::types::string::AtUri<'a>,
#[serde(borrow)]
-
pub value: ThreadItemRecordValue<'a>,
+
pub value: ThreadItemValue<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThreadItemRecordValue<'a> {
+
pub enum ThreadItemValue<'a> {
#[serde(rename = "app.bsky.unspecced.defs#threadItemPost")]
-
DefsThreadItemPost(Box<crate::app_bsky::unspecced::ThreadItemPost<'a>>),
+
ThreadItemPost(Box<crate::app_bsky::unspecced::ThreadItemPost<'a>>),
#[serde(rename = "app.bsky.unspecced.defs#threadItemNoUnauthenticated")]
-
DefsThreadItemNoUnauthenticated(
+
ThreadItemNoUnauthenticated(
Box<crate::app_bsky::unspecced::ThreadItemNoUnauthenticated<'a>>,
),
#[serde(rename = "app.bsky.unspecced.defs#threadItemNotFound")]
-
DefsThreadItemNotFound(Box<crate::app_bsky::unspecced::ThreadItemNotFound<'a>>),
+
ThreadItemNotFound(Box<crate::app_bsky::unspecced::ThreadItemNotFound<'a>>),
#[serde(rename = "app.bsky.unspecced.defs#threadItemBlocked")]
-
DefsThreadItemBlocked(Box<crate::app_bsky::unspecced::ThreadItemBlocked<'a>>),
+
ThreadItemBlocked(Box<crate::app_bsky::unspecced::ThreadItemBlocked<'a>>),
}
+2 -21
crates/jacquard-api/src/app_bsky/unspecced/init_age_assurance.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for InitAgeAssuranceError<'_> {
-
type Output = InitAgeAssuranceError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
InitAgeAssuranceError::InvalidEmail(v) => {
-
InitAgeAssuranceError::InvalidEmail(v.into_static())
-
}
-
InitAgeAssuranceError::DidTooLong(v) => {
-
InitAgeAssuranceError::DidTooLong(v.into_static())
-
}
-
InitAgeAssuranceError::InvalidInitiation(v) => {
-
InitAgeAssuranceError::InvalidInitiation(v.into_static())
-
}
-
InitAgeAssuranceError::Unknown(v) => {
-
InitAgeAssuranceError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/app_bsky/unspecced/search_actors_skeleton.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SearchActorsSkeletonError<'_> {
-
type Output = SearchActorsSkeletonError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SearchActorsSkeletonError::BadQueryString(v) => {
-
SearchActorsSkeletonError::BadQueryString(v.into_static())
-
}
-
SearchActorsSkeletonError::Unknown(v) => {
-
SearchActorsSkeletonError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/app_bsky/unspecced/search_posts_skeleton.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SearchPostsSkeletonError<'_> {
-
type Output = SearchPostsSkeletonError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SearchPostsSkeletonError::BadQueryString(v) => {
-
SearchPostsSkeletonError::BadQueryString(v.into_static())
-
}
-
SearchPostsSkeletonError::Unknown(v) => {
-
SearchPostsSkeletonError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/app_bsky/unspecced/search_starter_packs_skeleton.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SearchStarterPacksSkeletonError<'_> {
-
type Output = SearchStarterPacksSkeletonError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SearchStarterPacksSkeletonError::BadQueryString(v) => {
-
SearchStarterPacksSkeletonError::BadQueryString(v.into_static())
-
}
-
SearchStarterPacksSkeletonError::Unknown(v) => {
-
SearchStarterPacksSkeletonError::Unknown(v.into_static())
-
}
}
}
}
+2 -19
crates/jacquard-api/src/app_ocho/auth/update_email.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for UpdateEmailError<'_> {
-
type Output = UpdateEmailError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
UpdateEmailError::ExpiredToken(v) => {
-
UpdateEmailError::ExpiredToken(v.into_static())
-
}
-
UpdateEmailError::InvalidToken(v) => {
-
UpdateEmailError::InvalidToken(v.into_static())
-
}
-
UpdateEmailError::TokenRequired(v) => {
-
UpdateEmailError::TokenRequired(v.into_static())
-
}
-
UpdateEmailError::Unknown(v) => UpdateEmailError::Unknown(v.into_static()),
}
}
}
+20 -1
crates/jacquard-api/src/app_ocho/plugin.rs
···
pub expo_go: crate::app_ocho::plugin::ExpoGo<'a>,
}
-
pub type Plugin<'a> = Vec<jacquard_common::types::value::Data<'a>>;
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum PluginItem<'a> {
+
#[serde(rename = "app.ocho.plugin.defs#stringId")]
+
StringId(Box<crate::app_ocho::plugin::StringId<'a>>),
+
#[serde(rename = "app.ocho.plugin.defs#pluginConfig")]
+
PluginConfig(Box<crate::app_ocho::plugin::PluginConfig<'a>>),
+
}
+
+
pub type Plugin<'a> = Vec<PluginItem<'a>>;
pub type PluginConfig<'a> = jacquard_common::types::value::Data<'a>;
///A string identifier for a plugin, used to reference it in the app.
pub type StringId<'a> = jacquard_common::CowStr<'a>;
+2 -14
crates/jacquard-api/src/app_ocho/state/get_config.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetConfigError<'_> {
-
type Output = GetConfigError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetConfigError::InvalidId(v) => GetConfigError::InvalidId(v.into_static()),
-
GetConfigError::InvalidServiceAuth(v) => {
-
GetConfigError::InvalidServiceAuth(v.into_static())
-
}
-
GetConfigError::Unknown(v) => GetConfigError::Unknown(v.into_static()),
}
}
}
+1 -14
crates/jacquard-api/src/blog_pckt/post.rs
···
#[serde(rename_all = "camelCase")]
pub struct Post<'a> {
#[serde(borrow)]
-
pub blocks: PostRecordBlocks<'a>,
+
pub blocks: jacquard_common::types::value::Data<'a>,
#[serde(borrow)]
pub blog: crate::com_atproto::repo::strong_ref::StrongRef<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
···
pub url: jacquard_common::types::string::Uri<'a>,
}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PostRecordBlocks<'a> {}
impl jacquard_common::types::collection::Collection for Post<'_> {
const NSID: &'static str = "blog.pckt.post";
}
+1 -18
crates/jacquard-api/src/blog_pckt/publication.rs
···
///Theme configuration as an open union; accepts blog.pckt.theme and future types.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub theme: std::option::Option<PublicationRecordTheme<'a>>,
+
pub theme: std::option::Option<crate::blog_pckt::theme::Theme<'a>>,
///Timestamp when the publication was last updated (optional)
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub updated_at: std::option::Option<jacquard_common::types::string::Datetime>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PublicationRecordTheme<'a> {
-
#[serde(rename = "blog.pckt.theme")]
-
Theme(Box<crate::blog_pckt::theme::Theme<'a>>),
}
impl jacquard_common::types::collection::Collection for Publication<'_> {
+53 -62
crates/jacquard-api/src/chat_bsky/convo.rs
···
pub id: jacquard_common::CowStr<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub last_message: std::option::Option<ConvoViewRecordLastMessage<'a>>,
+
pub last_message: std::option::Option<ConvoViewLastMessage<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub last_reaction: std::option::Option<ConvoViewRecordLastReaction<'a>>,
+
pub last_reaction: std::option::Option<
+
crate::chat_bsky::convo::MessageAndReactionView<'a>,
+
>,
#[serde(borrow)]
pub members: Vec<crate::chat_bsky::actor::ProfileViewBasic<'a>>,
pub muted: bool,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ConvoViewRecordLastMessage<'a> {}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ConvoViewRecordLastReaction<'a> {}
+
pub enum ConvoViewLastMessage<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
#[serde(borrow)]
pub convo_id: jacquard_common::CowStr<'a>,
#[serde(borrow)]
-
pub message: LogAddReactionRecordMessage<'a>,
+
pub message: LogAddReactionMessage<'a>,
#[serde(borrow)]
pub reaction: crate::chat_bsky::convo::ReactionView<'a>,
#[serde(borrow)]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum LogAddReactionRecordMessage<'a> {}
+
pub enum LogAddReactionMessage<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
#[serde(borrow)]
pub convo_id: jacquard_common::CowStr<'a>,
#[serde(borrow)]
-
pub message: LogCreateMessageRecordMessage<'a>,
+
pub message: LogCreateMessageMessage<'a>,
#[serde(borrow)]
pub rev: jacquard_common::CowStr<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum LogCreateMessageRecordMessage<'a> {}
+
pub enum LogCreateMessageMessage<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
#[serde(borrow)]
pub convo_id: jacquard_common::CowStr<'a>,
#[serde(borrow)]
-
pub message: LogDeleteMessageRecordMessage<'a>,
+
pub message: LogDeleteMessageMessage<'a>,
#[serde(borrow)]
pub rev: jacquard_common::CowStr<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum LogDeleteMessageRecordMessage<'a> {}
+
pub enum LogDeleteMessageMessage<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
#[serde(borrow)]
pub convo_id: jacquard_common::CowStr<'a>,
#[serde(borrow)]
-
pub message: LogReadMessageRecordMessage<'a>,
+
pub message: LogReadMessageMessage<'a>,
#[serde(borrow)]
pub rev: jacquard_common::CowStr<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum LogReadMessageRecordMessage<'a> {}
+
pub enum LogReadMessageMessage<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
#[serde(borrow)]
pub convo_id: jacquard_common::CowStr<'a>,
#[serde(borrow)]
-
pub message: LogRemoveReactionRecordMessage<'a>,
+
pub message: LogRemoveReactionMessage<'a>,
#[serde(borrow)]
pub reaction: crate::chat_bsky::convo::ReactionView<'a>,
#[serde(borrow)]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum LogRemoveReactionRecordMessage<'a> {}
+
pub enum LogRemoveReactionMessage<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
pub struct MessageInput<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<MessageInputRecordEmbed<'a>>,
+
pub embed: std::option::Option<crate::app_bsky::embed::record::Record<'a>>,
///Annotations of text (mentions, URLs, hashtags, etc)
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
pub text: jacquard_common::CowStr<'a>,
}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum MessageInputRecordEmbed<'a> {
-
#[serde(rename = "app.bsky.embed.record")]
-
Record(Box<crate::app_bsky::embed::record::Record<'a>>),
-
}
-
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
pub struct MessageView<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<MessageViewRecordEmbed<'a>>,
+
pub embed: std::option::Option<crate::app_bsky::embed::record::View<'a>>,
///Annotations of text (mentions, URLs, hashtags, etc)
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
pub sent_at: jacquard_common::types::string::Datetime,
#[serde(borrow)]
pub text: jacquard_common::CowStr<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum MessageViewRecordEmbed<'a> {
-
#[serde(rename = "app.bsky.embed.record#view")]
-
RecordView(Box<crate::app_bsky::embed::record::View<'a>>),
}
#[jacquard_derive::lexicon]
+2 -19
crates/jacquard-api/src/chat_bsky/convo/add_reaction.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for AddReactionError<'_> {
-
type Output = AddReactionError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
AddReactionError::ReactionMessageDeleted(v) => {
-
AddReactionError::ReactionMessageDeleted(v.into_static())
-
}
-
AddReactionError::ReactionLimitReached(v) => {
-
AddReactionError::ReactionLimitReached(v.into_static())
-
}
-
AddReactionError::ReactionInvalidValue(v) => {
-
AddReactionError::ReactionInvalidValue(v.into_static())
-
}
-
AddReactionError::Unknown(v) => AddReactionError::Unknown(v.into_static()),
}
}
}
+36 -1
crates/jacquard-api/src/chat_bsky/convo/get_log.rs
···
#[serde(borrow)]
pub cursor: std::option::Option<jacquard_common::CowStr<'a>>,
#[serde(borrow)]
-
pub logs: Vec<jacquard_common::types::value::Data<'a>>,
+
pub logs: Vec<GetLogOutputLogsItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetLogOutputLogsItem<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#logBeginConvo")]
+
LogBeginConvo(Box<crate::chat_bsky::convo::LogBeginConvo<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logAcceptConvo")]
+
LogAcceptConvo(Box<crate::chat_bsky::convo::LogAcceptConvo<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logLeaveConvo")]
+
LogLeaveConvo(Box<crate::chat_bsky::convo::LogLeaveConvo<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logMuteConvo")]
+
LogMuteConvo(Box<crate::chat_bsky::convo::LogMuteConvo<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logUnmuteConvo")]
+
LogUnmuteConvo(Box<crate::chat_bsky::convo::LogUnmuteConvo<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logCreateMessage")]
+
LogCreateMessage(Box<crate::chat_bsky::convo::LogCreateMessage<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logDeleteMessage")]
+
LogDeleteMessage(Box<crate::chat_bsky::convo::LogDeleteMessage<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logReadMessage")]
+
LogReadMessage(Box<crate::chat_bsky::convo::LogReadMessage<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logAddReaction")]
+
LogAddReaction(Box<crate::chat_bsky::convo::LogAddReaction<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#logRemoveReaction")]
+
LogRemoveReaction(Box<crate::chat_bsky::convo::LogRemoveReaction<'a>>),
}
///Response type for
+20 -1
crates/jacquard-api/src/chat_bsky/convo/get_messages.rs
···
#[serde(borrow)]
pub cursor: std::option::Option<jacquard_common::CowStr<'a>>,
#[serde(borrow)]
-
pub messages: Vec<jacquard_common::types::value::Data<'a>>,
+
pub messages: Vec<GetMessagesOutputMessagesItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetMessagesOutputMessagesItem<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
}
///Response type for
+2 -18
crates/jacquard-api/src/chat_bsky/convo/remove_reaction.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for RemoveReactionError<'_> {
-
type Output = RemoveReactionError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
RemoveReactionError::ReactionMessageDeleted(v) => {
-
RemoveReactionError::ReactionMessageDeleted(v.into_static())
-
}
-
RemoveReactionError::ReactionInvalidValue(v) => {
-
RemoveReactionError::ReactionInvalidValue(v.into_static())
-
}
-
RemoveReactionError::Unknown(v) => {
-
RemoveReactionError::Unknown(v.into_static())
-
}
}
}
}
+20 -1
crates/jacquard-api/src/chat_bsky/moderation/get_message_context.rs
···
#[serde(rename_all = "camelCase")]
pub struct GetMessageContextOutput<'a> {
#[serde(borrow)]
-
pub messages: Vec<jacquard_common::types::value::Data<'a>>,
+
pub messages: Vec<GetMessageContextOutputMessagesItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetMessageContextOutputMessagesItem<'a> {
+
#[serde(rename = "chat.bsky.convo.defs#messageView")]
+
MessageView(Box<crate::chat_bsky::convo::MessageView<'a>>),
+
#[serde(rename = "chat.bsky.convo.defs#deletedMessageView")]
+
DeletedMessageView(Box<crate::chat_bsky::convo::DeletedMessageView<'a>>),
}
///Response type for
+4 -4
crates/jacquard-api/src/com_atproto/admin/get_subject_status.rs
···
#[serde(borrow)]
pub deactivated: std::option::Option<crate::com_atproto::admin::StatusAttr<'a>>,
#[serde(borrow)]
-
pub subject: GetSubjectStatusOutputRecordSubject<'a>,
+
pub subject: GetSubjectStatusOutputSubject<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub takedown: std::option::Option<crate::com_atproto::admin::StatusAttr<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum GetSubjectStatusOutputRecordSubject<'a> {
+
pub enum GetSubjectStatusOutputSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
#[serde(rename = "com.atproto.admin.defs#repoBlobRef")]
-
DefsRepoBlobRef(Box<crate::com_atproto::admin::RepoBlobRef<'a>>),
+
RepoBlobRef(Box<crate::com_atproto::admin::RepoBlobRef<'a>>),
}
///Response type for
+8 -8
crates/jacquard-api/src/com_atproto/admin/update_subject_status.rs
···
#[serde(borrow)]
pub deactivated: std::option::Option<crate::com_atproto::admin::StatusAttr<'a>>,
#[serde(borrow)]
-
pub subject: UpdateSubjectStatusRecordSubject<'a>,
+
pub subject: UpdateSubjectStatusSubject<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub takedown: std::option::Option<crate::com_atproto::admin::StatusAttr<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum UpdateSubjectStatusRecordSubject<'a> {
+
pub enum UpdateSubjectStatusSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
#[serde(rename = "com.atproto.admin.defs#repoBlobRef")]
-
DefsRepoBlobRef(Box<crate::com_atproto::admin::RepoBlobRef<'a>>),
+
RepoBlobRef(Box<crate::com_atproto::admin::RepoBlobRef<'a>>),
}
#[jacquard_derive::lexicon]
···
#[serde(rename_all = "camelCase")]
pub struct UpdateSubjectStatusOutput<'a> {
#[serde(borrow)]
-
pub subject: UpdateSubjectStatusOutputRecordSubject<'a>,
+
pub subject: UpdateSubjectStatusOutputSubject<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub takedown: std::option::Option<crate::com_atproto::admin::StatusAttr<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum UpdateSubjectStatusOutputRecordSubject<'a> {
+
pub enum UpdateSubjectStatusOutputSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
#[serde(rename = "com.atproto.admin.defs#repoBlobRef")]
-
DefsRepoBlobRef(Box<crate::com_atproto::admin::RepoBlobRef<'a>>),
+
RepoBlobRef(Box<crate::com_atproto::admin::RepoBlobRef<'a>>),
}
///Response type for
+2 -21
crates/jacquard-api/src/com_atproto/identity/refresh_identity.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for RefreshIdentityError<'_> {
-
type Output = RefreshIdentityError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
RefreshIdentityError::HandleNotFound(v) => {
-
RefreshIdentityError::HandleNotFound(v.into_static())
-
}
-
RefreshIdentityError::DidNotFound(v) => {
-
RefreshIdentityError::DidNotFound(v.into_static())
-
}
-
RefreshIdentityError::DidDeactivated(v) => {
-
RefreshIdentityError::DidDeactivated(v.into_static())
-
}
-
RefreshIdentityError::Unknown(v) => {
-
RefreshIdentityError::Unknown(v.into_static())
-
}
}
}
}
+2 -16
crates/jacquard-api/src/com_atproto/identity/resolve_did.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ResolveDidError<'_> {
-
type Output = ResolveDidError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ResolveDidError::DidNotFound(v) => {
-
ResolveDidError::DidNotFound(v.into_static())
-
}
-
ResolveDidError::DidDeactivated(v) => {
-
ResolveDidError::DidDeactivated(v.into_static())
-
}
-
ResolveDidError::Unknown(v) => ResolveDidError::Unknown(v.into_static()),
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/identity/resolve_handle.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ResolveHandleError<'_> {
-
type Output = ResolveHandleError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ResolveHandleError::HandleNotFound(v) => {
-
ResolveHandleError::HandleNotFound(v.into_static())
-
}
-
ResolveHandleError::Unknown(v) => {
-
ResolveHandleError::Unknown(v.into_static())
-
}
}
}
}
+2 -21
crates/jacquard-api/src/com_atproto/identity/resolve_identity.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ResolveIdentityError<'_> {
-
type Output = ResolveIdentityError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ResolveIdentityError::HandleNotFound(v) => {
-
ResolveIdentityError::HandleNotFound(v.into_static())
-
}
-
ResolveIdentityError::DidNotFound(v) => {
-
ResolveIdentityError::DidNotFound(v.into_static())
-
}
-
ResolveIdentityError::DidDeactivated(v) => {
-
ResolveIdentityError::DidDeactivated(v.into_static())
-
}
-
ResolveIdentityError::Unknown(v) => {
-
ResolveIdentityError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/label/subscribe_labels.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SubscribeLabelsError<'_> {
-
type Output = SubscribeLabelsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SubscribeLabelsError::FutureCursor(v) => {
-
SubscribeLabelsError::FutureCursor(v.into_static())
-
}
-
SubscribeLabelsError::Unknown(v) => {
-
SubscribeLabelsError::Unknown(v.into_static())
-
}
}
}
}
+6 -6
crates/jacquard-api/src/com_atproto/moderation/create_report.rs
···
#[serde(borrow)]
pub reason_type: crate::com_atproto::moderation::ReasonType<'a>,
#[serde(borrow)]
-
pub subject: CreateReportRecordSubject<'a>,
+
pub subject: CreateReportSubject<'a>,
#[serde(flatten)]
#[serde(borrow)]
#[builder(default)]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum CreateReportRecordSubject<'a> {
+
pub enum CreateReportSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
}
···
#[serde(borrow)]
pub reported_by: jacquard_common::types::string::Did<'a>,
#[serde(borrow)]
-
pub subject: CreateReportOutputRecordSubject<'a>,
+
pub subject: CreateReportOutputSubject<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum CreateReportOutputRecordSubject<'a> {
+
pub enum CreateReportOutputSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
}
+44 -15
crates/jacquard-api/src/com_atproto/repo/apply_writes.rs
···
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub validate: std::option::Option<bool>,
#[serde(borrow)]
-
pub writes: Vec<jacquard_common::types::value::Data<'a>>,
+
pub writes: Vec<ApplyWritesWritesItem<'a>>,
#[serde(flatten)]
#[serde(borrow)]
#[builder(default)]
···
>,
}
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum ApplyWritesWritesItem<'a> {
+
#[serde(rename = "com.atproto.repo.applyWrites#create")]
+
Create(Box<crate::com_atproto::repo::apply_writes::Create<'a>>),
+
#[serde(rename = "com.atproto.repo.applyWrites#update")]
+
Update(Box<crate::com_atproto::repo::apply_writes::Update<'a>>),
+
#[serde(rename = "com.atproto.repo.applyWrites#delete")]
+
Delete(Box<crate::com_atproto::repo::apply_writes::Delete<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
···
pub commit: std::option::Option<crate::com_atproto::repo::CommitMeta<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub results: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub results: std::option::Option<Vec<ApplyWritesOutputResultsItem<'a>>>,
+
}
+
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum ApplyWritesOutputResultsItem<'a> {
+
#[serde(rename = "com.atproto.repo.applyWrites#createResult")]
+
CreateResult(Box<crate::com_atproto::repo::apply_writes::CreateResult<'a>>),
+
#[serde(rename = "com.atproto.repo.applyWrites#updateResult")]
+
UpdateResult(Box<crate::com_atproto::repo::apply_writes::UpdateResult<'a>>),
+
#[serde(rename = "com.atproto.repo.applyWrites#deleteResult")]
+
DeleteResult(Box<crate::com_atproto::repo::apply_writes::DeleteResult<'a>>),
}
#[jacquard_derive::open_union]
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ApplyWritesError<'_> {
-
type Output = ApplyWritesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ApplyWritesError::InvalidSwap(v) => {
-
ApplyWritesError::InvalidSwap(v.into_static())
-
}
-
ApplyWritesError::Unknown(v) => ApplyWritesError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/com_atproto/repo/create_record.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateRecordError<'_> {
-
type Output = CreateRecordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateRecordError::InvalidSwap(v) => {
-
CreateRecordError::InvalidSwap(v.into_static())
-
}
-
CreateRecordError::Unknown(v) => CreateRecordError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/com_atproto/repo/delete_record.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteRecordError<'_> {
-
type Output = DeleteRecordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteRecordError::InvalidSwap(v) => {
-
DeleteRecordError::InvalidSwap(v.into_static())
-
}
-
DeleteRecordError::Unknown(v) => DeleteRecordError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/com_atproto/repo/get_record.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRecordError<'_> {
-
type Output = GetRecordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRecordError::RecordNotFound(v) => {
-
GetRecordError::RecordNotFound(v.into_static())
-
}
-
GetRecordError::Unknown(v) => GetRecordError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/com_atproto/repo/put_record.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for PutRecordError<'_> {
-
type Output = PutRecordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
PutRecordError::InvalidSwap(v) => {
-
PutRecordError::InvalidSwap(v.into_static())
-
}
-
PutRecordError::Unknown(v) => PutRecordError::Unknown(v.into_static()),
}
}
}
+2 -22
crates/jacquard-api/src/com_atproto/server/confirm_email.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ConfirmEmailError<'_> {
-
type Output = ConfirmEmailError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ConfirmEmailError::AccountNotFound(v) => {
-
ConfirmEmailError::AccountNotFound(v.into_static())
-
}
-
ConfirmEmailError::ExpiredToken(v) => {
-
ConfirmEmailError::ExpiredToken(v.into_static())
-
}
-
ConfirmEmailError::InvalidToken(v) => {
-
ConfirmEmailError::InvalidToken(v.into_static())
-
}
-
ConfirmEmailError::InvalidEmail(v) => {
-
ConfirmEmailError::InvalidEmail(v.into_static())
-
}
-
ConfirmEmailError::Unknown(v) => ConfirmEmailError::Unknown(v.into_static()),
}
}
}
+2 -33
crates/jacquard-api/src/com_atproto/server/create_account.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateAccountError<'_> {
-
type Output = CreateAccountError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateAccountError::InvalidHandle(v) => {
-
CreateAccountError::InvalidHandle(v.into_static())
-
}
-
CreateAccountError::InvalidPassword(v) => {
-
CreateAccountError::InvalidPassword(v.into_static())
-
}
-
CreateAccountError::InvalidInviteCode(v) => {
-
CreateAccountError::InvalidInviteCode(v.into_static())
-
}
-
CreateAccountError::HandleNotAvailable(v) => {
-
CreateAccountError::HandleNotAvailable(v.into_static())
-
}
-
CreateAccountError::UnsupportedDomain(v) => {
-
CreateAccountError::UnsupportedDomain(v.into_static())
-
}
-
CreateAccountError::UnresolvableDid(v) => {
-
CreateAccountError::UnresolvableDid(v.into_static())
-
}
-
CreateAccountError::IncompatibleDidDoc(v) => {
-
CreateAccountError::IncompatibleDidDoc(v.into_static())
-
}
-
CreateAccountError::Unknown(v) => {
-
CreateAccountError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/server/create_app_password.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateAppPasswordError<'_> {
-
type Output = CreateAppPasswordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateAppPasswordError::AccountTakedown(v) => {
-
CreateAppPasswordError::AccountTakedown(v.into_static())
-
}
-
CreateAppPasswordError::Unknown(v) => {
-
CreateAppPasswordError::Unknown(v.into_static())
-
}
}
}
}
+2 -18
crates/jacquard-api/src/com_atproto/server/create_session.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateSessionError<'_> {
-
type Output = CreateSessionError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateSessionError::AccountTakedown(v) => {
-
CreateSessionError::AccountTakedown(v.into_static())
-
}
-
CreateSessionError::AuthFactorTokenRequired(v) => {
-
CreateSessionError::AuthFactorTokenRequired(v.into_static())
-
}
-
CreateSessionError::Unknown(v) => {
-
CreateSessionError::Unknown(v.into_static())
-
}
}
}
}
+2 -18
crates/jacquard-api/src/com_atproto/server/delete_account.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteAccountError<'_> {
-
type Output = DeleteAccountError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteAccountError::ExpiredToken(v) => {
-
DeleteAccountError::ExpiredToken(v.into_static())
-
}
-
DeleteAccountError::InvalidToken(v) => {
-
DeleteAccountError::InvalidToken(v.into_static())
-
}
-
DeleteAccountError::Unknown(v) => {
-
DeleteAccountError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/server/get_account_invite_codes.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetAccountInviteCodesError<'_> {
-
type Output = GetAccountInviteCodesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetAccountInviteCodesError::DuplicateCreate(v) => {
-
GetAccountInviteCodesError::DuplicateCreate(v.into_static())
-
}
-
GetAccountInviteCodesError::Unknown(v) => {
-
GetAccountInviteCodesError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/server/get_service_auth.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetServiceAuthError<'_> {
-
type Output = GetServiceAuthError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetServiceAuthError::BadExpiration(v) => {
-
GetServiceAuthError::BadExpiration(v.into_static())
-
}
-
GetServiceAuthError::Unknown(v) => {
-
GetServiceAuthError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/server/list_app_passwords.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ListAppPasswordsError<'_> {
-
type Output = ListAppPasswordsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ListAppPasswordsError::AccountTakedown(v) => {
-
ListAppPasswordsError::AccountTakedown(v.into_static())
-
}
-
ListAppPasswordsError::Unknown(v) => {
-
ListAppPasswordsError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/server/refresh_session.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for RefreshSessionError<'_> {
-
type Output = RefreshSessionError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
RefreshSessionError::AccountTakedown(v) => {
-
RefreshSessionError::AccountTakedown(v.into_static())
-
}
-
RefreshSessionError::Unknown(v) => {
-
RefreshSessionError::Unknown(v.into_static())
-
}
}
}
}
+2 -18
crates/jacquard-api/src/com_atproto/server/reset_password.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ResetPasswordError<'_> {
-
type Output = ResetPasswordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ResetPasswordError::ExpiredToken(v) => {
-
ResetPasswordError::ExpiredToken(v.into_static())
-
}
-
ResetPasswordError::InvalidToken(v) => {
-
ResetPasswordError::InvalidToken(v.into_static())
-
}
-
ResetPasswordError::Unknown(v) => {
-
ResetPasswordError::Unknown(v.into_static())
-
}
}
}
}
+2 -19
crates/jacquard-api/src/com_atproto/server/update_email.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for UpdateEmailError<'_> {
-
type Output = UpdateEmailError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
UpdateEmailError::ExpiredToken(v) => {
-
UpdateEmailError::ExpiredToken(v.into_static())
-
}
-
UpdateEmailError::InvalidToken(v) => {
-
UpdateEmailError::InvalidToken(v.into_static())
-
}
-
UpdateEmailError::TokenRequired(v) => {
-
UpdateEmailError::TokenRequired(v.into_static())
-
}
-
UpdateEmailError::Unknown(v) => UpdateEmailError::Unknown(v.into_static()),
}
}
}
+2 -21
crates/jacquard-api/src/com_atproto/sync/get_blob.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetBlobError<'_> {
-
type Output = GetBlobError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetBlobError::BlobNotFound(v) => GetBlobError::BlobNotFound(v.into_static()),
-
GetBlobError::RepoNotFound(v) => GetBlobError::RepoNotFound(v.into_static()),
-
GetBlobError::RepoTakendown(v) => {
-
GetBlobError::RepoTakendown(v.into_static())
-
}
-
GetBlobError::RepoSuspended(v) => {
-
GetBlobError::RepoSuspended(v.into_static())
-
}
-
GetBlobError::RepoDeactivated(v) => {
-
GetBlobError::RepoDeactivated(v.into_static())
-
}
-
GetBlobError::Unknown(v) => GetBlobError::Unknown(v.into_static()),
}
}
}
+2 -25
crates/jacquard-api/src/com_atproto/sync/get_blocks.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetBlocksError<'_> {
-
type Output = GetBlocksError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetBlocksError::BlockNotFound(v) => {
-
GetBlocksError::BlockNotFound(v.into_static())
-
}
-
GetBlocksError::RepoNotFound(v) => {
-
GetBlocksError::RepoNotFound(v.into_static())
-
}
-
GetBlocksError::RepoTakendown(v) => {
-
GetBlocksError::RepoTakendown(v.into_static())
-
}
-
GetBlocksError::RepoSuspended(v) => {
-
GetBlocksError::RepoSuspended(v.into_static())
-
}
-
GetBlocksError::RepoDeactivated(v) => {
-
GetBlocksError::RepoDeactivated(v.into_static())
-
}
-
GetBlocksError::Unknown(v) => GetBlocksError::Unknown(v.into_static()),
}
}
}
+2 -11
crates/jacquard-api/src/com_atproto/sync/get_head.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetHeadError<'_> {
-
type Output = GetHeadError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetHeadError::HeadNotFound(v) => GetHeadError::HeadNotFound(v.into_static()),
-
GetHeadError::Unknown(v) => GetHeadError::Unknown(v.into_static()),
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/sync/get_host_status.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetHostStatusError<'_> {
-
type Output = GetHostStatusError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetHostStatusError::HostNotFound(v) => {
-
GetHostStatusError::HostNotFound(v.into_static())
-
}
-
GetHostStatusError::Unknown(v) => {
-
GetHostStatusError::Unknown(v.into_static())
-
}
}
}
}
+2 -24
crates/jacquard-api/src/com_atproto/sync/get_latest_commit.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetLatestCommitError<'_> {
-
type Output = GetLatestCommitError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetLatestCommitError::RepoNotFound(v) => {
-
GetLatestCommitError::RepoNotFound(v.into_static())
-
}
-
GetLatestCommitError::RepoTakendown(v) => {
-
GetLatestCommitError::RepoTakendown(v.into_static())
-
}
-
GetLatestCommitError::RepoSuspended(v) => {
-
GetLatestCommitError::RepoSuspended(v.into_static())
-
}
-
GetLatestCommitError::RepoDeactivated(v) => {
-
GetLatestCommitError::RepoDeactivated(v.into_static())
-
}
-
GetLatestCommitError::Unknown(v) => {
-
GetLatestCommitError::Unknown(v.into_static())
-
}
}
}
}
+2 -25
crates/jacquard-api/src/com_atproto/sync/get_record.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRecordError<'_> {
-
type Output = GetRecordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRecordError::RecordNotFound(v) => {
-
GetRecordError::RecordNotFound(v.into_static())
-
}
-
GetRecordError::RepoNotFound(v) => {
-
GetRecordError::RepoNotFound(v.into_static())
-
}
-
GetRecordError::RepoTakendown(v) => {
-
GetRecordError::RepoTakendown(v.into_static())
-
}
-
GetRecordError::RepoSuspended(v) => {
-
GetRecordError::RepoSuspended(v.into_static())
-
}
-
GetRecordError::RepoDeactivated(v) => {
-
GetRecordError::RepoDeactivated(v.into_static())
-
}
-
GetRecordError::Unknown(v) => GetRecordError::Unknown(v.into_static()),
}
}
}
+2 -20
crates/jacquard-api/src/com_atproto/sync/get_repo.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRepoError<'_> {
-
type Output = GetRepoError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRepoError::RepoNotFound(v) => GetRepoError::RepoNotFound(v.into_static()),
-
GetRepoError::RepoTakendown(v) => {
-
GetRepoError::RepoTakendown(v.into_static())
-
}
-
GetRepoError::RepoSuspended(v) => {
-
GetRepoError::RepoSuspended(v.into_static())
-
}
-
GetRepoError::RepoDeactivated(v) => {
-
GetRepoError::RepoDeactivated(v.into_static())
-
}
-
GetRepoError::Unknown(v) => GetRepoError::Unknown(v.into_static()),
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/sync/get_repo_status.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRepoStatusError<'_> {
-
type Output = GetRepoStatusError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRepoStatusError::RepoNotFound(v) => {
-
GetRepoStatusError::RepoNotFound(v.into_static())
-
}
-
GetRepoStatusError::Unknown(v) => {
-
GetRepoStatusError::Unknown(v.into_static())
-
}
}
}
}
+2 -22
crates/jacquard-api/src/com_atproto/sync/list_blobs.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ListBlobsError<'_> {
-
type Output = ListBlobsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ListBlobsError::RepoNotFound(v) => {
-
ListBlobsError::RepoNotFound(v.into_static())
-
}
-
ListBlobsError::RepoTakendown(v) => {
-
ListBlobsError::RepoTakendown(v.into_static())
-
}
-
ListBlobsError::RepoSuspended(v) => {
-
ListBlobsError::RepoSuspended(v.into_static())
-
}
-
ListBlobsError::RepoDeactivated(v) => {
-
ListBlobsError::RepoDeactivated(v.into_static())
-
}
-
ListBlobsError::Unknown(v) => ListBlobsError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/com_atproto/sync/request_crawl.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for RequestCrawlError<'_> {
-
type Output = RequestCrawlError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
RequestCrawlError::HostBanned(v) => {
-
RequestCrawlError::HostBanned(v.into_static())
-
}
-
RequestCrawlError::Unknown(v) => RequestCrawlError::Unknown(v.into_static()),
}
}
}
+2 -18
crates/jacquard-api/src/com_atproto/sync/subscribe_repos.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SubscribeReposError<'_> {
-
type Output = SubscribeReposError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SubscribeReposError::FutureCursor(v) => {
-
SubscribeReposError::FutureCursor(v.into_static())
-
}
-
SubscribeReposError::ConsumerTooSlow(v) => {
-
SubscribeReposError::ConsumerTooSlow(v.into_static())
-
}
-
SubscribeReposError::Unknown(v) => {
-
SubscribeReposError::Unknown(v.into_static())
-
}
}
}
}
+14 -17
crates/jacquard-api/src/com_atproto/temp/check_handle_availability.rs
···
#[serde(borrow)]
pub handle: jacquard_common::types::string::Handle<'a>,
#[serde(borrow)]
-
pub result: CheckHandleAvailabilityOutputRecordResult<'a>,
+
pub result: CheckHandleAvailabilityOutputResult<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum CheckHandleAvailabilityOutputRecordResult<'a> {}
+
pub enum CheckHandleAvailabilityOutputResult<'a> {
+
#[serde(rename = "com.atproto.temp.checkHandleAvailability#resultAvailable")]
+
ResultAvailable(
+
Box<crate::com_atproto::temp::check_handle_availability::ResultAvailable<'a>>,
+
),
+
#[serde(rename = "com.atproto.temp.checkHandleAvailability#resultUnavailable")]
+
ResultUnavailable(
+
Box<crate::com_atproto::temp::check_handle_availability::ResultUnavailable<'a>>,
+
),
+
}
+
#[jacquard_derive::open_union]
#[derive(
serde::Serialize,
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CheckHandleAvailabilityError<'_> {
-
type Output = CheckHandleAvailabilityError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CheckHandleAvailabilityError::InvalidEmail(v) => {
-
CheckHandleAvailabilityError::InvalidEmail(v.into_static())
-
}
-
CheckHandleAvailabilityError::Unknown(v) => {
-
CheckHandleAvailabilityError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/com_atproto/temp/dereference_scope.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DereferenceScopeError<'_> {
-
type Output = DereferenceScopeError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DereferenceScopeError::InvalidScopeReference(v) => {
-
DereferenceScopeError::InvalidScopeReference(v.into_static())
-
}
-
DereferenceScopeError::Unknown(v) => {
-
DereferenceScopeError::Unknown(v.into_static())
-
}
}
}
}
+2 -2
crates/jacquard-api/src/com_shinolabs/pinksea/get_oekaki.rs
···
#[serde(borrow)]
pub children: Vec<crate::com_shinolabs::pinksea::app_view_defs::HydratedOekaki<'a>>,
#[serde(borrow)]
-
pub parent: GetOekakiOutputRecordParent<'a>,
+
pub parent: GetOekakiOutputParent<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum GetOekakiOutputRecordParent<'a> {
+
pub enum GetOekakiOutputParent<'a> {
#[serde(rename = "com.shinolabs.pinksea.appViewDefs#hydratedOekaki")]
AppViewDefsHydratedOekaki(
Box<crate::com_shinolabs::pinksea::app_view_defs::HydratedOekaki<'a>>,
+2 -15
crates/jacquard-api/src/com_whtwnd/blog/get_entry_metadata_by_name.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetEntryMetadataByNameError<'_> {
-
type Output = GetEntryMetadataByNameError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetEntryMetadataByNameError::NotFound(v) => {
-
GetEntryMetadataByNameError::NotFound(v.into_static())
-
}
-
GetEntryMetadataByNameError::Unknown(v) => {
-
GetEntryMetadataByNameError::Unknown(v.into_static())
-
}
}
}
}
+2 -12
crates/jacquard-api/src/com_whtwnd/blog/notify_of_new_entry.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for NotifyOfNewEntryError<'_> {
-
type Output = NotifyOfNewEntryError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
NotifyOfNewEntryError::Unknown(v) => {
-
NotifyOfNewEntryError::Unknown(v.into_static())
-
}
}
}
}
+26 -1
crates/jacquard-api/src/community_lexicon/calendar/event.rs
···
///The locations where the event takes place.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub locations: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub locations: std::option::Option<Vec<EventLocationsItem<'a>>>,
///The attendance mode of the event.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
pub uris: std::option::Option<
Vec<crate::community_lexicon::calendar::event::Uri<'a>>,
>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum EventLocationsItem<'a> {
+
#[serde(rename = "community.lexicon.calendar.event#uri")]
+
Uri(Box<crate::community_lexicon::calendar::event::Uri<'a>>),
+
#[serde(rename = "community.lexicon.location.address")]
+
Address(Box<crate::community_lexicon::location::address::Address<'a>>),
+
#[serde(rename = "community.lexicon.location.fsq")]
+
Fsq(Box<crate::community_lexicon::location::fsq::Fsq<'a>>),
+
#[serde(rename = "community.lexicon.location.geo")]
+
Geo(Box<crate::community_lexicon::location::geo::Geo<'a>>),
+
#[serde(rename = "community.lexicon.location.hthree")]
+
Hthree(Box<crate::community_lexicon::location::hthree::Hthree<'a>>),
}
impl jacquard_common::types::collection::Collection for Event<'_> {
+6
crates/jacquard-api/src/events_smokesignal.rs
···
+
// @generated by jacquard-lexicon. DO NOT EDIT.
+
//
+
// This file was automatically generated from Lexicon schemas.
+
// Any manual changes will be overwritten on the next regeneration.
+
+
pub mod automation;
+6
crates/jacquard-api/src/events_smokesignal/automation.rs
···
+
// @generated by jacquard-lexicon. DO NOT EDIT.
+
//
+
// This file was automatically generated from Lexicon schemas.
+
// Any manual changes will be overwritten on the next regeneration.
+
+
pub mod invoke_webhook;
+78
crates/jacquard-api/src/events_smokesignal/automation/invoke_webhook.rs
···
+
// @generated by jacquard-lexicon. DO NOT EDIT.
+
//
+
// Lexicon: events.smokesignal.automation.InvokeWebhook
+
//
+
// This file was automatically generated from Lexicon schemas.
+
// Any manual changes will be overwritten on the next regeneration.
+
+
#[jacquard_derive::lexicon]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
bon::Builder,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(rename_all = "camelCase")]
+
#[builder(start_fn = new)]
+
pub struct InvokeWebhook<'a> {
+
#[serde(borrow)]
+
pub context: InvokeWebhookContext<'a>,
+
#[serde(borrow)]
+
#[builder(into)]
+
pub event: jacquard_common::CowStr<'a>,
+
#[serde(borrow)]
+
pub record: InvokeWebhookRecord<'a>,
+
#[serde(flatten)]
+
#[serde(borrow)]
+
#[builder(default)]
+
pub extra_data: ::std::collections::BTreeMap<
+
::jacquard_common::smol_str::SmolStr,
+
::jacquard_common::types::value::Data<'a>,
+
>,
+
}
+
+
#[jacquard_derive::lexicon]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(rename_all = "camelCase")]
+
pub struct InvokeWebhookOutput<'a> {}
+
///Response type for
+
///events.smokesignal.automation.InvokeWebhook
+
pub struct InvokeWebhookResponse;
+
impl jacquard_common::xrpc::XrpcResp for InvokeWebhookResponse {
+
const NSID: &'static str = "events.smokesignal.automation.InvokeWebhook";
+
const ENCODING: &'static str = "application/json";
+
type Output<'de> = InvokeWebhookOutput<'de>;
+
type Err<'de> = jacquard_common::xrpc::GenericError<'de>;
+
}
+
+
impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for InvokeWebhook<'de> {
+
const NSID: &'static str = "events.smokesignal.automation.InvokeWebhook";
+
const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Procedure(
+
"application/json",
+
);
+
type Response = InvokeWebhookResponse;
+
}
+
+
///Endpoint type for
+
///events.smokesignal.automation.InvokeWebhook
+
pub struct InvokeWebhookRequest;
+
impl jacquard_common::xrpc::XrpcEndpoint for InvokeWebhookRequest {
+
const PATH: &'static str = "/xrpc/events.smokesignal.automation.InvokeWebhook";
+
const METHOD: jacquard_common::xrpc::XrpcMethod = jacquard_common::xrpc::XrpcMethod::Procedure(
+
"application/json",
+
);
+
type Request<'de> = InvokeWebhook<'de>;
+
type Response = InvokeWebhookResponse;
+
}
+4 -1
crates/jacquard-api/src/lib.rs
···
#[cfg(feature = "dev_regnault")]
pub mod dev_regnault;
+
#[cfg(feature = "events_smokesignal")]
+
pub mod events_smokesignal;
+
#[cfg(feature = "fyi_unravel")]
pub mod fyi_unravel;
···
pub mod us_polhem;
#[cfg(feature = "win_tomo_x")]
-
pub mod win_tomo_x;
+
pub mod win_tomo_x;
+11 -9
crates/jacquard-api/src/my_skylights/list_item.rs
···
pub struct Builtin<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub r#type: std::option::Option<BuiltinRecordType<'a>>,
+
pub r#type: std::option::Option<BuiltinType<'a>>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum BuiltinRecordType<'a> {
+
pub enum BuiltinType<'a> {
#[serde(rename = "my.skylights.listItem#inProgress")]
-
ListItemInProgress(Box<crate::my_skylights::list_item::InProgress>),
+
InProgress(Box<crate::my_skylights::list_item::InProgress>),
#[serde(rename = "my.skylights.listItem#queue")]
-
ListItemQueue(Box<crate::my_skylights::list_item::Queue>),
+
Queue(Box<crate::my_skylights::list_item::Queue>),
#[serde(rename = "my.skylights.listItem#abandoned")]
-
ListItemAbandoned(Box<crate::my_skylights::list_item::Abandoned>),
+
Abandoned(Box<crate::my_skylights::list_item::Abandoned>),
#[serde(rename = "my.skylights.listItem#owned")]
-
ListItemOwned(Box<crate::my_skylights::list_item::Owned>),
+
Owned(Box<crate::my_skylights::list_item::Owned>),
#[serde(rename = "my.skylights.listItem#wishlist")]
-
ListItemWishlist(Box<crate::my_skylights::list_item::Wishlist>),
+
Wishlist(Box<crate::my_skylights::list_item::Wishlist>),
}
///User is currently reading/watching/... the item
···
#[serde(borrow)]
pub item: std::option::Option<crate::my_skylights::Item<'a>>,
#[serde(borrow)]
-
pub list: ListItemRecordList<'a>,
+
pub list: ListItemList<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub note: std::option::Option<jacquard_common::CowStr<'a>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ListItemRecordList<'a> {
+
pub enum ListItemList<'a> {
#[serde(rename = "my.skylights.list")]
List(Box<crate::my_skylights::list::List<'a>>),
+
#[serde(rename = "my.skylights.listItem#builtin")]
+
Builtin(Box<crate::my_skylights::list_item::Builtin<'a>>),
}
///User owns the item
+3 -20
crates/jacquard-api/src/net_anisota/feed/draft.rs
···
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<DraftRecordEmbed<'a>>,
+
pub embed: std::option::Option<DraftEmbed<'a>>,
///Annotations of text (mentions, URLs, hashtags, etc)
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
///Self-label values for this post. Effectively content warnings.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<DraftRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
///Indicates human language of post primary text content.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub langs: std::option::Option<Vec<jacquard_common::types::string::Language>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum DraftRecordEmbed<'a> {
+
pub enum DraftEmbed<'a> {
#[serde(rename = "app.bsky.embed.images")]
Images(Box<crate::app_bsky::embed::images::Images<'a>>),
#[serde(rename = "app.bsky.embed.video")]
···
Record(Box<crate::app_bsky::embed::record::Record<'a>>),
#[serde(rename = "app.bsky.embed.recordWithMedia")]
RecordWithMedia(Box<crate::app_bsky::embed::record_with_media::RecordWithMedia<'a>>),
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum DraftRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for Draft<'_> {
+3 -20
crates/jacquard-api/src/net_anisota/feed/post.rs
···
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embed: std::option::Option<PostRecordEmbed<'a>>,
+
pub embed: std::option::Option<PostEmbed<'a>>,
///Annotations of text (mentions, URLs, hashtags, etc)
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
///Self-label values for this post. Effectively content warnings.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<PostRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
///Indicates human language of post primary text content.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub langs: std::option::Option<Vec<jacquard_common::types::string::Language>>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PostRecordEmbed<'a> {
+
pub enum PostEmbed<'a> {
#[serde(rename = "app.bsky.embed.images")]
Images(Box<crate::app_bsky::embed::images::Images<'a>>),
#[serde(rename = "app.bsky.embed.video")]
···
Record(Box<crate::app_bsky::embed::record::Record<'a>>),
#[serde(rename = "app.bsky.embed.recordWithMedia")]
RecordWithMedia(Box<crate::app_bsky::embed::record_with_media::RecordWithMedia<'a>>),
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PostRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for Post<'_> {
+3 -1
crates/jacquard-api/src/place_atwork/endorsement.rs
···
///Verified signatures from endorsement proofs (strong references).
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub signatures: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub signatures: std::option::Option<
+
Vec<crate::com_atproto::repo::strong_ref::StrongRef<'a>>,
+
>,
///The endorsement text content.
#[serde(borrow)]
pub text: jacquard_common::CowStr<'a>,
+2 -19
crates/jacquard-api/src/place_atwork/get_listing.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetListingError<'_> {
-
type Output = GetListingError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetListingError::ListingNotFound(v) => {
-
GetListingError::ListingNotFound(v.into_static())
-
}
-
GetListingError::ListingParseFailed(v) => {
-
GetListingError::ListingParseFailed(v.into_static())
-
}
-
GetListingError::ListingFetchFailed(v) => {
-
GetListingError::ListingFetchFailed(v.into_static())
-
}
-
GetListingError::Unknown(v) => GetListingError::Unknown(v.into_static()),
}
}
}
+3 -1
crates/jacquard-api/src/place_atwork/listing.rs
···
///Locations that are relevant to the job listing.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub locations: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub locations: std::option::Option<
+
Vec<crate::community_lexicon::location::hthree::Hthree<'a>>,
+
>,
///Client-declared timestamp when the job listing expires.
pub not_after: jacquard_common::types::string::Datetime,
///Client-declared timestamp when the job listing becomes visible.
+2 -15
crates/jacquard-api/src/place_atwork/search_listings.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for SearchListingsError<'_> {
-
type Output = SearchListingsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
SearchListingsError::SearchFailed(v) => {
-
SearchListingsError::SearchFailed(v.into_static())
-
}
-
SearchListingsError::Unknown(v) => {
-
SearchListingsError::Unknown(v.into_static())
-
}
}
}
}
+3 -3
crates/jacquard-api/src/place_stream/chat.rs
···
pub record: jacquard_common::types::value::Data<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub reply_to: std::option::Option<MessageViewRecordReplyTo<'a>>,
+
pub reply_to: std::option::Option<MessageViewReplyTo<'a>>,
#[serde(borrow)]
pub uri: jacquard_common::types::string::AtUri<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum MessageViewRecordReplyTo<'a> {
+
pub enum MessageViewReplyTo<'a> {
#[serde(rename = "place.stream.chat.defs#messageView")]
-
DefsMessageView(Box<crate::place_stream::chat::MessageView<'a>>),
+
MessageView(Box<crate::place_stream::chat::MessageView<'a>>),
}
+2 -15
crates/jacquard-api/src/place_stream/live/get_profile_card.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetProfileCardError<'_> {
-
type Output = GetProfileCardError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetProfileCardError::RepoNotFound(v) => {
-
GetProfileCardError::RepoNotFound(v.into_static())
-
}
-
GetProfileCardError::Unknown(v) => {
-
GetProfileCardError::Unknown(v.into_static())
-
}
}
}
}
+10 -6
crates/jacquard-api/src/place_stream/livestream.rs
···
#[serde(rename_all = "camelCase")]
pub struct StreamplaceAnything<'a> {
#[serde(borrow)]
-
pub livestream: StreamplaceAnythingRecordLivestream<'a>,
+
pub livestream: StreamplaceAnythingLivestream<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum StreamplaceAnythingRecordLivestream<'a> {
+
pub enum StreamplaceAnythingLivestream<'a> {
+
#[serde(rename = "place.stream.livestream#livestreamView")]
+
LivestreamView(Box<crate::place_stream::livestream::LivestreamView<'a>>),
+
#[serde(rename = "place.stream.livestream#viewerCount")]
+
ViewerCount(Box<crate::place_stream::livestream::ViewerCount<'a>>),
#[serde(rename = "place.stream.defs#blockView")]
-
DefsBlockView(Box<crate::place_stream::BlockView<'a>>),
+
BlockView(Box<crate::place_stream::BlockView<'a>>),
#[serde(rename = "place.stream.defs#renditions")]
-
DefsRenditions(Box<crate::place_stream::Renditions<'a>>),
+
Renditions(Box<crate::place_stream::Renditions<'a>>),
#[serde(rename = "place.stream.defs#rendition")]
-
DefsRendition(Box<crate::place_stream::Rendition<'a>>),
+
Rendition(Box<crate::place_stream::Rendition<'a>>),
#[serde(rename = "place.stream.chat.defs#messageView")]
-
DefsMessageView(Box<crate::place_stream::chat::MessageView<'a>>),
+
MessageView(Box<crate::place_stream::chat::MessageView<'a>>),
}
#[jacquard_derive::lexicon]
+20 -1
crates/jacquard-api/src/place_stream/richtext/facet.rs
···
#[serde(rename_all = "camelCase")]
pub struct Facet<'a> {
#[serde(borrow)]
-
pub features: Vec<jacquard_common::types::value::Data<'a>>,
+
pub features: Vec<FacetFeaturesItem<'a>>,
#[serde(borrow)]
pub index: crate::app_bsky::richtext::facet::ByteSlice<'a>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum FacetFeaturesItem<'a> {
+
#[serde(rename = "app.bsky.richtext.facet#mention")]
+
FacetMention(Box<crate::app_bsky::richtext::facet::Mention<'a>>),
+
#[serde(rename = "app.bsky.richtext.facet#link")]
+
FacetLink(Box<crate::app_bsky::richtext::facet::Link<'a>>),
}
+2 -21
crates/jacquard-api/src/place_stream/server/create_webhook.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateWebhookError<'_> {
-
type Output = CreateWebhookError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateWebhookError::InvalidUrl(v) => {
-
CreateWebhookError::InvalidUrl(v.into_static())
-
}
-
CreateWebhookError::DuplicateWebhook(v) => {
-
CreateWebhookError::DuplicateWebhook(v.into_static())
-
}
-
CreateWebhookError::TooManyWebhooks(v) => {
-
CreateWebhookError::TooManyWebhooks(v.into_static())
-
}
-
CreateWebhookError::Unknown(v) => {
-
CreateWebhookError::Unknown(v.into_static())
-
}
}
}
}
+2 -18
crates/jacquard-api/src/place_stream/server/delete_webhook.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteWebhookError<'_> {
-
type Output = DeleteWebhookError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteWebhookError::WebhookNotFound(v) => {
-
DeleteWebhookError::WebhookNotFound(v.into_static())
-
}
-
DeleteWebhookError::Unauthorized(v) => {
-
DeleteWebhookError::Unauthorized(v.into_static())
-
}
-
DeleteWebhookError::Unknown(v) => {
-
DeleteWebhookError::Unknown(v.into_static())
-
}
}
}
}
+2 -16
crates/jacquard-api/src/place_stream/server/get_webhook.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetWebhookError<'_> {
-
type Output = GetWebhookError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetWebhookError::WebhookNotFound(v) => {
-
GetWebhookError::WebhookNotFound(v.into_static())
-
}
-
GetWebhookError::Unauthorized(v) => {
-
GetWebhookError::Unauthorized(v.into_static())
-
}
-
GetWebhookError::Unknown(v) => GetWebhookError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/place_stream/server/list_webhooks.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ListWebhooksError<'_> {
-
type Output = ListWebhooksError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ListWebhooksError::InvalidCursor(v) => {
-
ListWebhooksError::InvalidCursor(v.into_static())
-
}
-
ListWebhooksError::Unknown(v) => ListWebhooksError::Unknown(v.into_static()),
}
}
}
+2 -24
crates/jacquard-api/src/place_stream/server/update_webhook.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for UpdateWebhookError<'_> {
-
type Output = UpdateWebhookError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
UpdateWebhookError::WebhookNotFound(v) => {
-
UpdateWebhookError::WebhookNotFound(v.into_static())
-
}
-
UpdateWebhookError::Unauthorized(v) => {
-
UpdateWebhookError::Unauthorized(v.into_static())
-
}
-
UpdateWebhookError::InvalidUrl(v) => {
-
UpdateWebhookError::InvalidUrl(v.into_static())
-
}
-
UpdateWebhookError::DuplicateWebhook(v) => {
-
UpdateWebhookError::DuplicateWebhook(v.into_static())
-
}
-
UpdateWebhookError::Unknown(v) => {
-
UpdateWebhookError::Unknown(v.into_static())
-
}
}
}
}
+2 -2
crates/jacquard-api/src/pub_leaflet/blocks/unordered_list.rs
···
Vec<crate::pub_leaflet::blocks::unordered_list::ListItem<'a>>,
>,
#[serde(borrow)]
-
pub content: ListItemRecordContent<'a>,
+
pub content: ListItemContent<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ListItemRecordContent<'a> {
+
pub enum ListItemContent<'a> {
#[serde(rename = "pub.leaflet.blocks.text")]
Text(Box<crate::pub_leaflet::blocks::text::Text<'a>>),
#[serde(rename = "pub.leaflet.blocks.header")]
+3 -14
crates/jacquard-api/src/pub_leaflet/comment.rs
···
pub struct Comment<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub attachment: std::option::Option<CommentRecordAttachment<'a>>,
+
pub attachment: std::option::Option<
+
crate::pub_leaflet::comment::LinearDocumentQuote<'a>,
+
>,
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
pub subject: jacquard_common::types::string::AtUri<'a>,
}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum CommentRecordAttachment<'a> {}
impl jacquard_common::types::collection::Collection for Comment<'_> {
const NSID: &'static str = "pub.leaflet.comment";
}
+1 -1
crates/jacquard-api/src/pub_leaflet/document.rs
···
#[serde(borrow)]
pub description: std::option::Option<jacquard_common::CowStr<'a>>,
#[serde(borrow)]
-
pub pages: Vec<jacquard_common::types::value::Data<'a>>,
+
pub pages: Vec<crate::pub_leaflet::pages::linear_document::LinearDocument<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub post_ref: std::option::Option<
+2 -2
crates/jacquard-api/src/pub_leaflet/pages/linear_document.rs
···
#[serde(borrow)]
pub alignment: std::option::Option<jacquard_common::CowStr<'a>>,
#[serde(borrow)]
-
pub block: BlockRecordBlock<'a>,
+
pub block: BlockBlock<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum BlockRecordBlock<'a> {
+
pub enum BlockBlock<'a> {
#[serde(rename = "pub.leaflet.blocks.iframe")]
Iframe(Box<crate::pub_leaflet::blocks::iframe::Iframe<'a>>),
#[serde(rename = "pub.leaflet.blocks.text")]
+10 -10
crates/jacquard-api/src/pub_leaflet/publication.rs
···
pub struct Theme<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub accent_background: std::option::Option<ThemeRecordAccentBackground<'a>>,
+
pub accent_background: std::option::Option<ThemeAccentBackground<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub accent_text: std::option::Option<ThemeRecordAccentText<'a>>,
+
pub accent_text: std::option::Option<ThemeAccentText<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub background_color: std::option::Option<ThemeRecordBackgroundColor<'a>>,
+
pub background_color: std::option::Option<ThemeBackgroundColor<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub background_image: std::option::Option<
···
>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub page_background: std::option::Option<ThemeRecordPageBackground<'a>>,
+
pub page_background: std::option::Option<ThemePageBackground<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub primary: std::option::Option<ThemeRecordPrimary<'a>>,
+
pub primary: std::option::Option<ThemePrimary<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
pub show_page_background: std::option::Option<bool>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThemeRecordAccentBackground<'a> {
+
pub enum ThemeAccentBackground<'a> {
#[serde(rename = "pub.leaflet.theme.color#rgba")]
ColorRgba(Box<crate::pub_leaflet::theme::color::Rgba<'a>>),
#[serde(rename = "pub.leaflet.theme.color#rgb")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThemeRecordAccentText<'a> {
+
pub enum ThemeAccentText<'a> {
#[serde(rename = "pub.leaflet.theme.color#rgba")]
ColorRgba(Box<crate::pub_leaflet::theme::color::Rgba<'a>>),
#[serde(rename = "pub.leaflet.theme.color#rgb")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThemeRecordBackgroundColor<'a> {
+
pub enum ThemeBackgroundColor<'a> {
#[serde(rename = "pub.leaflet.theme.color#rgba")]
ColorRgba(Box<crate::pub_leaflet::theme::color::Rgba<'a>>),
#[serde(rename = "pub.leaflet.theme.color#rgb")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThemeRecordPageBackground<'a> {
+
pub enum ThemePageBackground<'a> {
#[serde(rename = "pub.leaflet.theme.color#rgba")]
ColorRgba(Box<crate::pub_leaflet::theme::color::Rgba<'a>>),
#[serde(rename = "pub.leaflet.theme.color#rgb")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ThemeRecordPrimary<'a> {
+
pub enum ThemePrimary<'a> {
#[serde(rename = "pub.leaflet.theme.color#rgba")]
ColorRgba(Box<crate::pub_leaflet::theme::color::Rgba<'a>>),
#[serde(rename = "pub.leaflet.theme.color#rgb")]
+32 -1
crates/jacquard-api/src/pub_leaflet/richtext/facet.rs
···
#[serde(rename_all = "camelCase")]
pub struct Facet<'a> {
#[serde(borrow)]
-
pub features: Vec<jacquard_common::types::value::Data<'a>>,
+
pub features: Vec<FacetFeaturesItem<'a>>,
#[serde(borrow)]
pub index: crate::pub_leaflet::richtext::facet::ByteSlice<'a>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum FacetFeaturesItem<'a> {
+
#[serde(rename = "pub.leaflet.richtext.facet#link")]
+
Link(Box<crate::pub_leaflet::richtext::facet::Link<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#code")]
+
Code(Box<crate::pub_leaflet::richtext::facet::Code<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#highlight")]
+
Highlight(Box<crate::pub_leaflet::richtext::facet::Highlight<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#underline")]
+
Underline(Box<crate::pub_leaflet::richtext::facet::Underline<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#strikethrough")]
+
Strikethrough(Box<crate::pub_leaflet::richtext::facet::Strikethrough<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#id")]
+
Id(Box<crate::pub_leaflet::richtext::facet::Id<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#bold")]
+
Bold(Box<crate::pub_leaflet::richtext::facet::Bold<'a>>),
+
#[serde(rename = "pub.leaflet.richtext.facet#italic")]
+
Italic(Box<crate::pub_leaflet::richtext::facet::Italic<'a>>),
}
///Facet feature for strikethrough markup
+2 -13
crates/jacquard-api/src/sh_tangled/knot/list_keys.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ListKeysError<'_> {
-
type Output = ListKeysError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ListKeysError::InternalServerError(v) => {
-
ListKeysError::InternalServerError(v.into_static())
-
}
-
ListKeysError::Unknown(v) => ListKeysError::Unknown(v.into_static()),
}
}
}
+2 -10
crates/jacquard-api/src/sh_tangled/knot/version.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for VersionError<'_> {
-
type Output = VersionError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
VersionError::Unknown(v) => VersionError::Unknown(v.into_static()),
}
}
}
+2 -11
crates/jacquard-api/src/sh_tangled/owner.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for OwnerError<'_> {
-
type Output = OwnerError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
OwnerError::OwnerNotFound(v) => OwnerError::OwnerNotFound(v.into_static()),
-
OwnerError::Unknown(v) => OwnerError::Unknown(v.into_static()),
}
}
}
+2 -16
crates/jacquard-api/src/sh_tangled/repo/archive.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for ArchiveError<'_> {
-
type Output = ArchiveError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
ArchiveError::RepoNotFound(v) => ArchiveError::RepoNotFound(v.into_static()),
-
ArchiveError::RefNotFound(v) => ArchiveError::RefNotFound(v.into_static()),
-
ArchiveError::InvalidRequest(v) => {
-
ArchiveError::InvalidRequest(v.into_static())
-
}
-
ArchiveError::ArchiveError(v) => ArchiveError::ArchiveError(v.into_static()),
-
ArchiveError::Unknown(v) => ArchiveError::Unknown(v.into_static()),
}
}
}
+2 -14
crates/jacquard-api/src/sh_tangled/repo/blob.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for BlobError<'_> {
-
type Output = BlobError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
BlobError::RepoNotFound(v) => BlobError::RepoNotFound(v.into_static()),
-
BlobError::RefNotFound(v) => BlobError::RefNotFound(v.into_static()),
-
BlobError::FileNotFound(v) => BlobError::FileNotFound(v.into_static()),
-
BlobError::InvalidRequest(v) => BlobError::InvalidRequest(v.into_static()),
-
BlobError::Unknown(v) => BlobError::Unknown(v.into_static()),
}
}
}
+2 -17
crates/jacquard-api/src/sh_tangled/repo/branch.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for BranchError<'_> {
-
type Output = BranchError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
BranchError::RepoNotFound(v) => BranchError::RepoNotFound(v.into_static()),
-
BranchError::BranchNotFound(v) => {
-
BranchError::BranchNotFound(v.into_static())
-
}
-
BranchError::InvalidRequest(v) => {
-
BranchError::InvalidRequest(v.into_static())
-
}
-
BranchError::Unknown(v) => BranchError::Unknown(v.into_static()),
}
}
}
+2 -16
crates/jacquard-api/src/sh_tangled/repo/branches.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for BranchesError<'_> {
-
type Output = BranchesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
BranchesError::RepoNotFound(v) => {
-
BranchesError::RepoNotFound(v.into_static())
-
}
-
BranchesError::InvalidRequest(v) => {
-
BranchesError::InvalidRequest(v.into_static())
-
}
-
BranchesError::Unknown(v) => BranchesError::Unknown(v.into_static()),
}
}
}
+2 -18
crates/jacquard-api/src/sh_tangled/repo/compare.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CompareError<'_> {
-
type Output = CompareError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CompareError::RepoNotFound(v) => CompareError::RepoNotFound(v.into_static()),
-
CompareError::RevisionNotFound(v) => {
-
CompareError::RevisionNotFound(v.into_static())
-
}
-
CompareError::InvalidRequest(v) => {
-
CompareError::InvalidRequest(v.into_static())
-
}
-
CompareError::CompareError(v) => CompareError::CompareError(v.into_static()),
-
CompareError::Unknown(v) => CompareError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/sh_tangled/repo/diff.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DiffError<'_> {
-
type Output = DiffError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DiffError::RepoNotFound(v) => DiffError::RepoNotFound(v.into_static()),
-
DiffError::RefNotFound(v) => DiffError::RefNotFound(v.into_static()),
-
DiffError::InvalidRequest(v) => DiffError::InvalidRequest(v.into_static()),
-
DiffError::Unknown(v) => DiffError::Unknown(v.into_static()),
}
}
}
+2 -18
crates/jacquard-api/src/sh_tangled/repo/get_default_branch.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetDefaultBranchError<'_> {
-
type Output = GetDefaultBranchError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetDefaultBranchError::RepoNotFound(v) => {
-
GetDefaultBranchError::RepoNotFound(v.into_static())
-
}
-
GetDefaultBranchError::InvalidRequest(v) => {
-
GetDefaultBranchError::InvalidRequest(v.into_static())
-
}
-
GetDefaultBranchError::Unknown(v) => {
-
GetDefaultBranchError::Unknown(v.into_static())
-
}
}
}
}
+2 -19
crates/jacquard-api/src/sh_tangled/repo/languages.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for LanguagesError<'_> {
-
type Output = LanguagesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
LanguagesError::RepoNotFound(v) => {
-
LanguagesError::RepoNotFound(v.into_static())
-
}
-
LanguagesError::RefNotFound(v) => {
-
LanguagesError::RefNotFound(v.into_static())
-
}
-
LanguagesError::InvalidRequest(v) => {
-
LanguagesError::InvalidRequest(v.into_static())
-
}
-
LanguagesError::Unknown(v) => LanguagesError::Unknown(v.into_static()),
}
}
}
+2 -14
crates/jacquard-api/src/sh_tangled/repo/log.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for LogError<'_> {
-
type Output = LogError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
LogError::RepoNotFound(v) => LogError::RepoNotFound(v.into_static()),
-
LogError::RefNotFound(v) => LogError::RefNotFound(v.into_static()),
-
LogError::PathNotFound(v) => LogError::PathNotFound(v.into_static()),
-
LogError::InvalidRequest(v) => LogError::InvalidRequest(v.into_static()),
-
LogError::Unknown(v) => LogError::Unknown(v.into_static()),
}
}
}
+2 -12
crates/jacquard-api/src/sh_tangled/repo/tags.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for TagsError<'_> {
-
type Output = TagsError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
TagsError::RepoNotFound(v) => TagsError::RepoNotFound(v.into_static()),
-
TagsError::InvalidRequest(v) => TagsError::InvalidRequest(v.into_static()),
-
TagsError::Unknown(v) => TagsError::Unknown(v.into_static()),
}
}
}
+2 -14
crates/jacquard-api/src/sh_tangled/repo/tree.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for TreeError<'_> {
-
type Output = TreeError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
TreeError::RepoNotFound(v) => TreeError::RepoNotFound(v.into_static()),
-
TreeError::RefNotFound(v) => TreeError::RefNotFound(v.into_static()),
-
TreeError::PathNotFound(v) => TreeError::PathNotFound(v.into_static()),
-
TreeError::InvalidRequest(v) => TreeError::InvalidRequest(v.into_static()),
-
TreeError::Unknown(v) => TreeError::Unknown(v.into_static()),
}
}
}
+4 -4
crates/jacquard-api/src/sh_weaver/actor.rs
···
#[serde(rename_all = "camelCase")]
pub struct ProfileDataView<'a> {
#[serde(borrow)]
-
pub inner: ProfileDataViewRecordInner<'a>,
+
pub inner: ProfileDataViewInner<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ProfileDataViewRecordInner<'a> {
+
pub enum ProfileDataViewInner<'a> {
#[serde(rename = "sh.weaver.actor.defs#profileView")]
-
DefsProfileView(Box<crate::sh_weaver::actor::ProfileView<'a>>),
+
ProfileView(Box<crate::sh_weaver::actor::ProfileView<'a>>),
#[serde(rename = "app.bsky.actor.defs#profileViewDetailed")]
-
DefsProfileViewDetailed(Box<crate::app_bsky::actor::ProfileViewDetailed<'a>>),
+
ProfileViewDetailed(Box<crate::app_bsky::actor::ProfileViewDetailed<'a>>),
}
#[jacquard_derive::lexicon]
+8 -2
crates/jacquard-api/src/sh_weaver/edit.rs
···
#[serde(rename_all = "camelCase")]
pub struct DocRef<'a> {
#[serde(borrow)]
-
pub value: DocRefRecordValue<'a>,
+
pub value: DocRefValue<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum DocRefRecordValue<'a> {}
+
pub enum DocRefValue<'a> {
+
#[serde(rename = "sh.weaver.edit.defs#notebookRef")]
+
NotebookRef(Box<crate::sh_weaver::edit::NotebookRef<'a>>),
+
#[serde(rename = "sh.weaver.edit.defs#entryRef")]
+
EntryRef(Box<crate::sh_weaver::edit::EntryRef<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
+8 -2
crates/jacquard-api/src/sh_weaver/edit/cursor.rs
···
#[serde(rename_all = "camelCase")]
pub struct ContainerId<'a> {
#[serde(borrow)]
-
pub value: ContainerIdRecordValue<'a>,
+
pub value: ContainerIdValue<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ContainerIdRecordValue<'a> {}
+
pub enum ContainerIdValue<'a> {
+
#[serde(rename = "sh.weaver.edit.cursor#normalContainerId")]
+
NormalContainerId(Box<crate::sh_weaver::edit::cursor::NormalContainerId<'a>>),
+
#[serde(rename = "sh.weaver.edit.cursor#rootContainerId")]
+
RootContainerId(Box<crate::sh_weaver::edit::cursor::RootContainerId<'a>>),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
+5 -5
crates/jacquard-api/src/sh_weaver/embed/images.rs
···
pub blurhash: std::option::Option<jacquard_common::CowStr<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub dimensions: std::option::Option<ImageRecordDimensions<'a>>,
+
pub dimensions: std::option::Option<ImageDimensions<'a>>,
#[serde(borrow)]
pub image: jacquard_common::types::blob::Blob<'a>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ImageRecordDimensions<'a> {
+
pub enum ImageDimensions<'a> {
#[serde(rename = "app.bsky.embed.defs#aspectRatio")]
-
DefsAspectRatio(Box<crate::app_bsky::embed::AspectRatio<'a>>),
+
AspectRatio(Box<crate::app_bsky::embed::AspectRatio<'a>>),
#[serde(rename = "sh.weaver.embed.defs#percentSize")]
-
DefsPercentSize(Box<crate::sh_weaver::embed::PercentSize<'a>>),
+
PercentSize(Box<crate::sh_weaver::embed::PercentSize<'a>>),
#[serde(rename = "sh.weaver.embed.defs#pixelSize")]
-
DefsPixelSize(Box<crate::sh_weaver::embed::PixelSize<'a>>),
+
PixelSize(Box<crate::sh_weaver::embed::PixelSize<'a>>),
}
#[jacquard_derive::lexicon]
+8 -8
crates/jacquard-api/src/sh_weaver/embed/record_with_media.rs
···
#[serde(rename_all = "camelCase")]
pub struct RecordWithMedia<'a> {
#[serde(borrow)]
-
pub media: RecordWithMediaRecordMedia<'a>,
+
pub media: RecordWithMediaMedia<'a>,
#[serde(borrow)]
-
pub record: RecordWithMediaRecordRecord<'a>,
+
pub record: RecordWithMediaRecord<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum RecordWithMediaRecordMedia<'a> {
+
pub enum RecordWithMediaMedia<'a> {
#[serde(rename = "sh.weaver.embed.images")]
Images(Box<crate::sh_weaver::embed::images::Images<'a>>),
#[serde(rename = "sh.weaver.embed.external")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum RecordWithMediaRecordRecord<'a> {
+
pub enum RecordWithMediaRecord<'a> {
#[serde(rename = "app.bsky.embed.record")]
Record(Box<crate::app_bsky::embed::record::Record<'a>>),
#[serde(rename = "sh.weaver.embed.records")]
···
#[serde(rename_all = "camelCase")]
pub struct View<'a> {
#[serde(borrow)]
-
pub media: ViewRecordMedia<'a>,
+
pub media: ViewMedia<'a>,
#[serde(borrow)]
-
pub record: ViewRecordRecord<'a>,
+
pub record: ViewRecord<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ViewRecordMedia<'a> {
+
pub enum ViewMedia<'a> {
#[serde(rename = "sh.weaver.embed.images")]
Images(Box<crate::sh_weaver::embed::images::Images<'a>>),
#[serde(rename = "sh.weaver.embed.external#view")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ViewRecordRecord<'a> {
+
pub enum ViewRecord<'a> {
#[serde(rename = "sh.weaver.embed.records#view")]
RecordsView(Box<crate::sh_weaver::embed::records::View<'a>>),
#[serde(rename = "app.bsky.embed.record#view")]
+29 -11
crates/jacquard-api/src/sh_weaver/embed/records.rs
···
#[serde(rename_all = "camelCase")]
pub struct View<'a> {
#[serde(borrow)]
-
pub record: ViewRecordRecord<'a>,
+
pub record: ViewUnionRecord<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ViewRecordRecord<'a> {
+
pub enum ViewUnionRecord<'a> {
+
#[serde(rename = "sh.weaver.embed.records#viewRecord")]
+
ViewRecord(Box<crate::sh_weaver::embed::records::ViewRecord<'a>>),
+
#[serde(rename = "sh.weaver.embed.records#viewNotFound")]
+
ViewNotFound(Box<crate::sh_weaver::embed::records::ViewNotFound<'a>>),
+
#[serde(rename = "sh.weaver.embed.records#viewBlocked")]
+
ViewBlocked(Box<crate::sh_weaver::embed::records::ViewBlocked<'a>>),
+
#[serde(rename = "sh.weaver.embed.records#viewDetached")]
+
ViewDetached(Box<crate::sh_weaver::embed::records::ViewDetached<'a>>),
#[serde(rename = "app.bsky.feed.defs#generatorView")]
-
DefsGeneratorView(Box<crate::app_bsky::feed::GeneratorView<'a>>),
+
GeneratorView(Box<crate::app_bsky::feed::GeneratorView<'a>>),
#[serde(rename = "app.bsky.graph.defs#listView")]
-
DefsListView(Box<crate::app_bsky::graph::ListView<'a>>),
+
ListView(Box<crate::app_bsky::graph::ListView<'a>>),
#[serde(rename = "app.bsky.labeler.defs#labelerView")]
-
DefsLabelerView(Box<crate::app_bsky::labeler::LabelerView<'a>>),
+
LabelerView(Box<crate::app_bsky::labeler::LabelerView<'a>>),
#[serde(rename = "app.bsky.graph.defs#starterPackViewBasic")]
-
DefsStarterPackViewBasic(Box<crate::app_bsky::graph::StarterPackViewBasic<'a>>),
+
StarterPackViewBasic(Box<crate::app_bsky::graph::StarterPackViewBasic<'a>>),
}
#[jacquard_derive::lexicon]
···
#[serde(rename_all = "camelCase")]
pub struct ViewRecord<'a> {
#[serde(borrow)]
-
pub author: ViewRecordRecordAuthor<'a>,
+
pub author: crate::app_bsky::actor::ProfileViewBasic<'a>,
#[serde(borrow)]
pub cid: jacquard_common::types::string::Cid<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub embeds: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub embeds: std::option::Option<Vec<ViewRecordEmbedsItem<'a>>>,
pub indexed_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ViewRecordRecordAuthor<'a> {
-
#[serde(rename = "app.bsky.actor.defs#profileViewBasic")]
-
DefsProfileViewBasic(Box<crate::app_bsky::actor::ProfileViewBasic<'a>>),
+
pub enum ViewRecordEmbedsItem<'a> {
+
#[serde(rename = "app.bsky.embed.images#view")]
+
ImagesView(Box<crate::app_bsky::embed::images::View<'a>>),
+
#[serde(rename = "app.bsky.embed.video#view")]
+
VideoView(Box<crate::app_bsky::embed::video::View<'a>>),
+
#[serde(rename = "app.bsky.embed.external#view")]
+
ExternalView(Box<crate::app_bsky::embed::external::View<'a>>),
+
#[serde(rename = "app.bsky.embed.record#view")]
+
RecordView(Box<crate::app_bsky::embed::record::View<'a>>),
+
#[serde(rename = "app.bsky.embed.recordWithMedia#view")]
+
RecordWithMediaView(Box<crate::app_bsky::embed::record_with_media::View<'a>>),
+
#[serde(rename = "sh.weaver.embed.records#view")]
+
View(Box<crate::sh_weaver::embed::records::View<'a>>),
}
+4 -4
crates/jacquard-api/src/sh_weaver/notebook/authors.rs
···
pub index: std::option::Option<i64>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub profile: std::option::Option<AuthorListItemRecordProfile<'a>>,
+
pub profile: std::option::Option<AuthorListItemProfile<'a>>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum AuthorListItemRecordProfile<'a> {
+
pub enum AuthorListItemProfile<'a> {
#[serde(rename = "app.bsky.actor.defs#profileViewBasic")]
-
DefsProfileViewBasic(Box<crate::app_bsky::actor::ProfileViewBasic<'a>>),
+
ProfileViewBasic(Box<crate::app_bsky::actor::ProfileViewBasic<'a>>),
#[serde(rename = "sh.weaver.actor.defs#profileView")]
-
DefsProfileView(Box<crate::sh_weaver::actor::ProfileView<'a>>),
+
ProfileView(Box<crate::sh_weaver::actor::ProfileView<'a>>),
}
///Authors of a Weaver notebook.
+18 -1
crates/jacquard-api/src/social_clippr/actor.rs
···
pub mod search_profiles;
pub mod search_tags;
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum PreferencesItem<'a> {
+
#[serde(rename = "social.clippr.actor.defs#publishingScopesPref")]
+
PublishingScopesPref(Box<crate::social_clippr::actor::PublishingScopesPref<'a>>),
+
}
+
///An array of refs to various preferences.
-
pub type Preferences<'a> = Vec<jacquard_common::types::value::Data<'a>>;
+
pub type Preferences<'a> = Vec<PreferencesItem<'a>>;
///A view of an actor's profile.
#[jacquard_derive::lexicon]
#[derive(
+2 -19
crates/jacquard-api/src/social_grain/gallery.rs
···
///Self-label values for this post. Effectively content warnings.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub labels: std::option::Option<GalleryRecordLabels<'a>>,
+
pub labels: std::option::Option<crate::com_atproto::label::SelfLabels<'a>>,
#[serde(borrow)]
pub title: jacquard_common::CowStr<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum GalleryRecordLabels<'a> {
-
#[serde(rename = "com.atproto.label.defs#selfLabels")]
-
DefsSelfLabels(Box<crate::com_atproto::label::SelfLabels<'a>>),
}
impl jacquard_common::types::collection::Collection for Gallery<'_> {
···
pub indexed_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub items: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>,
+
pub items: std::option::Option<Vec<crate::social_grain::photo::PhotoView<'a>>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub labels: std::option::Option<Vec<crate::com_atproto::label::Label<'a>>>,
+22 -1
crates/jacquard-api/src/social_psky/richtext/facet.rs
···
#[serde(rename_all = "camelCase")]
pub struct Facet<'a> {
#[serde(borrow)]
-
pub features: Vec<jacquard_common::types::value::Data<'a>>,
+
pub features: Vec<FacetFeaturesItem<'a>>,
#[serde(borrow)]
pub index: crate::social_psky::richtext::facet::ByteSlice<'a>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum FacetFeaturesItem<'a> {
+
#[serde(rename = "social.psky.richtext.facet#mention")]
+
Mention(Box<crate::social_psky::richtext::facet::Mention<'a>>),
+
#[serde(rename = "social.psky.richtext.facet#link")]
+
Link(Box<crate::social_psky::richtext::facet::Link<'a>>),
+
#[serde(rename = "social.psky.richtext.facet#room")]
+
Room(Box<crate::social_psky::richtext::facet::Room<'a>>),
}
///Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.
+2 -15
crates/jacquard-api/src/tools_ozone/communication/create_template.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for CreateTemplateError<'_> {
-
type Output = CreateTemplateError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
CreateTemplateError::DuplicateTemplateName(v) => {
-
CreateTemplateError::DuplicateTemplateName(v.into_static())
-
}
-
CreateTemplateError::Unknown(v) => {
-
CreateTemplateError::Unknown(v.into_static())
-
}
}
}
}
+2 -15
crates/jacquard-api/src/tools_ozone/communication/update_template.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for UpdateTemplateError<'_> {
-
type Output = UpdateTemplateError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
UpdateTemplateError::DuplicateTemplateName(v) => {
-
UpdateTemplateError::DuplicateTemplateName(v.into_static())
-
}
-
UpdateTemplateError::Unknown(v) => {
-
UpdateTemplateError::Unknown(v.into_static())
-
}
}
}
}
+24 -2
crates/jacquard-api/src/tools_ozone/hosting/get_account_history.rs
···
#[serde(borrow)]
pub created_by: jacquard_common::CowStr<'a>,
#[serde(borrow)]
-
pub details: EventRecordDetails<'a>,
+
pub details: EventDetails<'a>,
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum EventRecordDetails<'a> {}
+
pub enum EventDetails<'a> {
+
#[serde(rename = "tools.ozone.hosting.getAccountHistory#accountCreated")]
+
AccountCreated(
+
Box<crate::tools_ozone::hosting::get_account_history::AccountCreated<'a>>,
+
),
+
#[serde(rename = "tools.ozone.hosting.getAccountHistory#emailUpdated")]
+
EmailUpdated(
+
Box<crate::tools_ozone::hosting::get_account_history::EmailUpdated<'a>>,
+
),
+
#[serde(rename = "tools.ozone.hosting.getAccountHistory#emailConfirmed")]
+
EmailConfirmed(
+
Box<crate::tools_ozone::hosting::get_account_history::EmailConfirmed<'a>>,
+
),
+
#[serde(rename = "tools.ozone.hosting.getAccountHistory#passwordUpdated")]
+
PasswordUpdated(
+
Box<crate::tools_ozone::hosting::get_account_history::PasswordUpdated<'a>>,
+
),
+
#[serde(rename = "tools.ozone.hosting.getAccountHistory#handleUpdated")]
+
HandleUpdated(
+
Box<crate::tools_ozone::hosting::get_account_history::HandleUpdated<'a>>,
+
),
+
}
+
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
+173 -32
crates/jacquard-api/src/tools_ozone/moderation.rs
···
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub details: std::option::Option<BlobViewRecordDetails<'a>>,
+
pub details: std::option::Option<BlobViewDetails<'a>>,
#[serde(borrow)]
pub mime_type: jacquard_common::CowStr<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum BlobViewRecordDetails<'a> {}
+
pub enum BlobViewDetails<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#imageDetails")]
+
ImageDetails(Box<crate::tools_ozone::moderation::ImageDetails<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#videoDetails")]
+
VideoDetails(Box<crate::tools_ozone::moderation::VideoDetails<'a>>),
+
}
+
///Logs cancellation of a scheduled takedown action for an account.
#[jacquard_derive::lexicon]
#[derive(
···
#[serde(borrow)]
pub creator_handle: std::option::Option<jacquard_common::CowStr<'a>>,
#[serde(borrow)]
-
pub event: ModEventViewRecordEvent<'a>,
+
pub event: ModEventViewEvent<'a>,
pub id: i64,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub mod_tool: std::option::Option<crate::tools_ozone::moderation::ModTool<'a>>,
#[serde(borrow)]
-
pub subject: ModEventViewRecordSubject<'a>,
+
pub subject: ModEventViewSubject<'a>,
#[serde(borrow)]
pub subject_blob_cids: Vec<jacquard_common::CowStr<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ModEventViewRecordEvent<'a> {}
+
pub enum ModEventViewEvent<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#modEventTakedown")]
+
ModEventTakedown(Box<crate::tools_ozone::moderation::ModEventTakedown<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventReverseTakedown")]
+
ModEventReverseTakedown(
+
Box<crate::tools_ozone::moderation::ModEventReverseTakedown<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventComment")]
+
ModEventComment(Box<crate::tools_ozone::moderation::ModEventComment<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventReport")]
+
ModEventReport(Box<crate::tools_ozone::moderation::ModEventReport<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventLabel")]
+
ModEventLabel(Box<crate::tools_ozone::moderation::ModEventLabel<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventAcknowledge")]
+
ModEventAcknowledge(Box<crate::tools_ozone::moderation::ModEventAcknowledge<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventEscalate")]
+
ModEventEscalate(Box<crate::tools_ozone::moderation::ModEventEscalate<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventMute")]
+
ModEventMute(Box<crate::tools_ozone::moderation::ModEventMute<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventUnmute")]
+
ModEventUnmute(Box<crate::tools_ozone::moderation::ModEventUnmute<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventMuteReporter")]
+
ModEventMuteReporter(Box<crate::tools_ozone::moderation::ModEventMuteReporter<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventUnmuteReporter")]
+
ModEventUnmuteReporter(
+
Box<crate::tools_ozone::moderation::ModEventUnmuteReporter<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventEmail")]
+
ModEventEmail(Box<crate::tools_ozone::moderation::ModEventEmail<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventResolveAppeal")]
+
ModEventResolveAppeal(
+
Box<crate::tools_ozone::moderation::ModEventResolveAppeal<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventDivert")]
+
ModEventDivert(Box<crate::tools_ozone::moderation::ModEventDivert<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventTag")]
+
ModEventTag(Box<crate::tools_ozone::moderation::ModEventTag<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#accountEvent")]
+
AccountEvent(Box<crate::tools_ozone::moderation::AccountEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#identityEvent")]
+
IdentityEvent(Box<crate::tools_ozone::moderation::IdentityEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#recordEvent")]
+
RecordEvent(Box<crate::tools_ozone::moderation::RecordEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventPriorityScore")]
+
ModEventPriorityScore(
+
Box<crate::tools_ozone::moderation::ModEventPriorityScore<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#ageAssuranceEvent")]
+
AgeAssuranceEvent(Box<crate::tools_ozone::moderation::AgeAssuranceEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#ageAssuranceOverrideEvent")]
+
AgeAssuranceOverrideEvent(
+
Box<crate::tools_ozone::moderation::AgeAssuranceOverrideEvent<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#revokeAccountCredentialsEvent")]
+
RevokeAccountCredentialsEvent(
+
Box<crate::tools_ozone::moderation::RevokeAccountCredentialsEvent<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#scheduleTakedownEvent")]
+
ScheduleTakedownEvent(
+
Box<crate::tools_ozone::moderation::ScheduleTakedownEvent<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#cancelScheduledTakedownEvent")]
+
CancelScheduledTakedownEvent(
+
Box<crate::tools_ozone::moderation::CancelScheduledTakedownEvent<'a>>,
+
),
+
}
+
#[jacquard_derive::open_union]
#[derive(
serde::Serialize,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ModEventViewRecordSubject<'a> {
+
pub enum ModEventViewSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
#[serde(rename = "chat.bsky.convo.defs#messageRef")]
-
DefsMessageRef(Box<crate::chat_bsky::convo::MessageRef<'a>>),
+
MessageRef(Box<crate::chat_bsky::convo::MessageRef<'a>>),
}
#[jacquard_derive::lexicon]
···
#[serde(borrow)]
pub created_by: jacquard_common::types::string::Did<'a>,
#[serde(borrow)]
-
pub event: ModEventViewDetailRecordEvent<'a>,
+
pub event: ModEventViewDetailEvent<'a>,
pub id: i64,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub mod_tool: std::option::Option<crate::tools_ozone::moderation::ModTool<'a>>,
#[serde(borrow)]
-
pub subject: ModEventViewDetailRecordSubject<'a>,
+
pub subject: ModEventViewDetailSubject<'a>,
#[serde(borrow)]
pub subject_blobs: Vec<crate::tools_ozone::moderation::BlobView<'a>>,
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ModEventViewDetailRecordEvent<'a> {}
+
pub enum ModEventViewDetailEvent<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#modEventTakedown")]
+
ModEventTakedown(Box<crate::tools_ozone::moderation::ModEventTakedown<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventReverseTakedown")]
+
ModEventReverseTakedown(
+
Box<crate::tools_ozone::moderation::ModEventReverseTakedown<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventComment")]
+
ModEventComment(Box<crate::tools_ozone::moderation::ModEventComment<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventReport")]
+
ModEventReport(Box<crate::tools_ozone::moderation::ModEventReport<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventLabel")]
+
ModEventLabel(Box<crate::tools_ozone::moderation::ModEventLabel<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventAcknowledge")]
+
ModEventAcknowledge(Box<crate::tools_ozone::moderation::ModEventAcknowledge<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventEscalate")]
+
ModEventEscalate(Box<crate::tools_ozone::moderation::ModEventEscalate<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventMute")]
+
ModEventMute(Box<crate::tools_ozone::moderation::ModEventMute<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventUnmute")]
+
ModEventUnmute(Box<crate::tools_ozone::moderation::ModEventUnmute<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventMuteReporter")]
+
ModEventMuteReporter(Box<crate::tools_ozone::moderation::ModEventMuteReporter<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventUnmuteReporter")]
+
ModEventUnmuteReporter(
+
Box<crate::tools_ozone::moderation::ModEventUnmuteReporter<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventEmail")]
+
ModEventEmail(Box<crate::tools_ozone::moderation::ModEventEmail<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventResolveAppeal")]
+
ModEventResolveAppeal(
+
Box<crate::tools_ozone::moderation::ModEventResolveAppeal<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventDivert")]
+
ModEventDivert(Box<crate::tools_ozone::moderation::ModEventDivert<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventTag")]
+
ModEventTag(Box<crate::tools_ozone::moderation::ModEventTag<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#accountEvent")]
+
AccountEvent(Box<crate::tools_ozone::moderation::AccountEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#identityEvent")]
+
IdentityEvent(Box<crate::tools_ozone::moderation::IdentityEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#recordEvent")]
+
RecordEvent(Box<crate::tools_ozone::moderation::RecordEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#modEventPriorityScore")]
+
ModEventPriorityScore(
+
Box<crate::tools_ozone::moderation::ModEventPriorityScore<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#ageAssuranceEvent")]
+
AgeAssuranceEvent(Box<crate::tools_ozone::moderation::AgeAssuranceEvent<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#ageAssuranceOverrideEvent")]
+
AgeAssuranceOverrideEvent(
+
Box<crate::tools_ozone::moderation::AgeAssuranceOverrideEvent<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#revokeAccountCredentialsEvent")]
+
RevokeAccountCredentialsEvent(
+
Box<crate::tools_ozone::moderation::RevokeAccountCredentialsEvent<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#scheduleTakedownEvent")]
+
ScheduleTakedownEvent(
+
Box<crate::tools_ozone::moderation::ScheduleTakedownEvent<'a>>,
+
),
+
#[serde(rename = "tools.ozone.moderation.defs#cancelScheduledTakedownEvent")]
+
CancelScheduledTakedownEvent(
+
Box<crate::tools_ozone::moderation::CancelScheduledTakedownEvent<'a>>,
+
),
+
}
+
#[jacquard_derive::open_union]
#[derive(
serde::Serialize,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ModEventViewDetailRecordSubject<'a> {}
+
pub enum ModEventViewDetailSubject<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#repoView")]
+
RepoView(Box<crate::tools_ozone::moderation::RepoView<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#repoViewNotFound")]
+
RepoViewNotFound(Box<crate::tools_ozone::moderation::RepoViewNotFound<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#recordView")]
+
RecordView(Box<crate::tools_ozone::moderation::RecordView<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#recordViewNotFound")]
+
RecordViewNotFound(Box<crate::tools_ozone::moderation::RecordViewNotFound<'a>>),
+
}
+
///Moderation tool information for tracing the source of the action
#[jacquard_derive::lexicon]
#[derive(
···
pub created_at: jacquard_common::types::string::Datetime,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub hosting: std::option::Option<SubjectStatusViewRecordHosting<'a>>,
+
pub hosting: std::option::Option<SubjectStatusViewHosting<'a>>,
pub id: i64,
///Timestamp referencing when the author of the subject appealed a moderation action
#[serde(skip_serializing_if = "std::option::Option::is_none")]
···
#[serde(borrow)]
pub review_state: crate::tools_ozone::moderation::SubjectReviewState<'a>,
#[serde(borrow)]
-
pub subject: SubjectStatusViewRecordSubject<'a>,
+
pub subject: SubjectStatusViewSubject<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub subject_blob_cids: std::option::Option<
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum SubjectStatusViewRecordHosting<'a> {}
+
pub enum SubjectStatusViewHosting<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#accountHosting")]
+
AccountHosting(Box<crate::tools_ozone::moderation::AccountHosting<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#recordHosting")]
+
RecordHosting(Box<crate::tools_ozone::moderation::RecordHosting<'a>>),
+
}
+
#[jacquard_derive::open_union]
#[derive(
serde::Serialize,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum SubjectStatusViewRecordSubject<'a> {
+
pub enum SubjectStatusViewSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
#[serde(rename = "chat.bsky.convo.defs#messageRef")]
-
DefsMessageRef(Box<crate::chat_bsky::convo::MessageRef<'a>>),
+
MessageRef(Box<crate::chat_bsky::convo::MessageRef<'a>>),
///Detailed view of a subject. For record subjects, the author's repo and profile will be returned.
···
pub struct SubjectView<'a> {
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub profile: std::option::Option<SubjectViewRecordProfile<'a>>,
+
pub profile: std::option::Option<jacquard_common::types::value::Data<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub record: std::option::Option<
···
pub r#type: crate::com_atproto::moderation::SubjectType<'a>,
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum SubjectViewRecordProfile<'a> {}
///Moderation event timeline event for a PLC create operation
#[derive(
serde::Serialize,
+31 -49
crates/jacquard-api/src/tools_ozone/moderation/emit_event.rs
···
#[serde(borrow)]
pub created_by: jacquard_common::types::string::Did<'a>,
#[serde(borrow)]
-
pub event: EmitEventRecordEvent<'a>,
+
pub event: EmitEventEvent<'a>,
///An optional external ID for the event, used to deduplicate events from external systems. Fails when an event of same type with the same external ID exists for the same subject.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
#[serde(borrow)]
pub mod_tool: std::option::Option<crate::tools_ozone::moderation::ModTool<'a>>,
#[serde(borrow)]
-
pub subject: EmitEventRecordSubject<'a>,
+
pub subject: EmitEventSubject<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
pub subject_blob_cids: std::option::Option<
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum EmitEventRecordEvent<'a> {
+
pub enum EmitEventEvent<'a> {
#[serde(rename = "tools.ozone.moderation.defs#modEventTakedown")]
-
DefsModEventTakedown(Box<crate::tools_ozone::moderation::ModEventTakedown<'a>>),
+
ModEventTakedown(Box<crate::tools_ozone::moderation::ModEventTakedown<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventAcknowledge")]
-
DefsModEventAcknowledge(
-
Box<crate::tools_ozone::moderation::ModEventAcknowledge<'a>>,
-
),
+
ModEventAcknowledge(Box<crate::tools_ozone::moderation::ModEventAcknowledge<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventEscalate")]
-
DefsModEventEscalate(Box<crate::tools_ozone::moderation::ModEventEscalate<'a>>),
+
ModEventEscalate(Box<crate::tools_ozone::moderation::ModEventEscalate<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventComment")]
-
DefsModEventComment(Box<crate::tools_ozone::moderation::ModEventComment<'a>>),
+
ModEventComment(Box<crate::tools_ozone::moderation::ModEventComment<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventLabel")]
-
DefsModEventLabel(Box<crate::tools_ozone::moderation::ModEventLabel<'a>>),
+
ModEventLabel(Box<crate::tools_ozone::moderation::ModEventLabel<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventReport")]
-
DefsModEventReport(Box<crate::tools_ozone::moderation::ModEventReport<'a>>),
+
ModEventReport(Box<crate::tools_ozone::moderation::ModEventReport<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventMute")]
-
DefsModEventMute(Box<crate::tools_ozone::moderation::ModEventMute<'a>>),
+
ModEventMute(Box<crate::tools_ozone::moderation::ModEventMute<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventUnmute")]
-
DefsModEventUnmute(Box<crate::tools_ozone::moderation::ModEventUnmute<'a>>),
+
ModEventUnmute(Box<crate::tools_ozone::moderation::ModEventUnmute<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventMuteReporter")]
-
DefsModEventMuteReporter(
-
Box<crate::tools_ozone::moderation::ModEventMuteReporter<'a>>,
-
),
+
ModEventMuteReporter(Box<crate::tools_ozone::moderation::ModEventMuteReporter<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventUnmuteReporter")]
-
DefsModEventUnmuteReporter(
+
ModEventUnmuteReporter(
Box<crate::tools_ozone::moderation::ModEventUnmuteReporter<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#modEventReverseTakedown")]
-
DefsModEventReverseTakedown(
+
ModEventReverseTakedown(
Box<crate::tools_ozone::moderation::ModEventReverseTakedown<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#modEventResolveAppeal")]
-
DefsModEventResolveAppeal(
+
ModEventResolveAppeal(
Box<crate::tools_ozone::moderation::ModEventResolveAppeal<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#modEventEmail")]
-
DefsModEventEmail(Box<crate::tools_ozone::moderation::ModEventEmail<'a>>),
+
ModEventEmail(Box<crate::tools_ozone::moderation::ModEventEmail<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventDivert")]
-
DefsModEventDivert(Box<crate::tools_ozone::moderation::ModEventDivert<'a>>),
+
ModEventDivert(Box<crate::tools_ozone::moderation::ModEventDivert<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventTag")]
-
DefsModEventTag(Box<crate::tools_ozone::moderation::ModEventTag<'a>>),
+
ModEventTag(Box<crate::tools_ozone::moderation::ModEventTag<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#accountEvent")]
-
DefsAccountEvent(Box<crate::tools_ozone::moderation::AccountEvent<'a>>),
+
AccountEvent(Box<crate::tools_ozone::moderation::AccountEvent<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#identityEvent")]
-
DefsIdentityEvent(Box<crate::tools_ozone::moderation::IdentityEvent<'a>>),
+
IdentityEvent(Box<crate::tools_ozone::moderation::IdentityEvent<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#recordEvent")]
-
DefsRecordEvent(Box<crate::tools_ozone::moderation::RecordEvent<'a>>),
+
RecordEvent(Box<crate::tools_ozone::moderation::RecordEvent<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#modEventPriorityScore")]
-
DefsModEventPriorityScore(
+
ModEventPriorityScore(
Box<crate::tools_ozone::moderation::ModEventPriorityScore<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#ageAssuranceEvent")]
-
DefsAgeAssuranceEvent(Box<crate::tools_ozone::moderation::AgeAssuranceEvent<'a>>),
+
AgeAssuranceEvent(Box<crate::tools_ozone::moderation::AgeAssuranceEvent<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#ageAssuranceOverrideEvent")]
-
DefsAgeAssuranceOverrideEvent(
+
AgeAssuranceOverrideEvent(
Box<crate::tools_ozone::moderation::AgeAssuranceOverrideEvent<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#revokeAccountCredentialsEvent")]
-
DefsRevokeAccountCredentialsEvent(
+
RevokeAccountCredentialsEvent(
Box<crate::tools_ozone::moderation::RevokeAccountCredentialsEvent<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#scheduleTakedownEvent")]
-
DefsScheduleTakedownEvent(
+
ScheduleTakedownEvent(
Box<crate::tools_ozone::moderation::ScheduleTakedownEvent<'a>>,
),
#[serde(rename = "tools.ozone.moderation.defs#cancelScheduledTakedownEvent")]
-
DefsCancelScheduledTakedownEvent(
+
CancelScheduledTakedownEvent(
Box<crate::tools_ozone::moderation::CancelScheduledTakedownEvent<'a>>,
),
}
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum EmitEventRecordSubject<'a> {
+
pub enum EmitEventSubject<'a> {
#[serde(rename = "com.atproto.admin.defs#repoRef")]
-
DefsRepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
+
RepoRef(Box<crate::com_atproto::admin::RepoRef<'a>>),
#[serde(rename = "com.atproto.repo.strongRef")]
StrongRef(Box<crate::com_atproto::repo::strong_ref::StrongRef<'a>>),
}
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for EmitEventError<'_> {
-
type Output = EmitEventError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
EmitEventError::SubjectHasAction(v) => {
-
EmitEventError::SubjectHasAction(v.into_static())
-
}
-
EmitEventError::DuplicateExternalId(v) => {
-
EmitEventError::DuplicateExternalId(v.into_static())
-
}
-
EmitEventError::Unknown(v) => EmitEventError::Unknown(v.into_static()),
}
}
}
+2 -15
crates/jacquard-api/src/tools_ozone/moderation/get_account_timeline.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetAccountTimelineError<'_> {
-
type Output = GetAccountTimelineError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetAccountTimelineError::RepoNotFound(v) => {
-
GetAccountTimelineError::RepoNotFound(v.into_static())
-
}
-
GetAccountTimelineError::Unknown(v) => {
-
GetAccountTimelineError::Unknown(v.into_static())
-
}
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/moderation/get_record.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRecordError<'_> {
-
type Output = GetRecordError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRecordError::RecordNotFound(v) => {
-
GetRecordError::RecordNotFound(v.into_static())
-
}
-
GetRecordError::Unknown(v) => GetRecordError::Unknown(v.into_static()),
}
}
}
+20 -1
crates/jacquard-api/src/tools_ozone/moderation/get_records.rs
···
#[serde(rename_all = "camelCase")]
pub struct GetRecordsOutput<'a> {
#[serde(borrow)]
-
pub records: Vec<jacquard_common::types::value::Data<'a>>,
+
pub records: Vec<GetRecordsOutputRecordsItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetRecordsOutputRecordsItem<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#recordViewDetail")]
+
RecordViewDetail(Box<crate::tools_ozone::moderation::RecordViewDetail<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#recordViewNotFound")]
+
RecordViewNotFound(Box<crate::tools_ozone::moderation::RecordViewNotFound<'a>>),
}
///Response type for
+2 -11
crates/jacquard-api/src/tools_ozone/moderation/get_repo.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetRepoError<'_> {
-
type Output = GetRepoError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetRepoError::RepoNotFound(v) => GetRepoError::RepoNotFound(v.into_static()),
-
GetRepoError::Unknown(v) => GetRepoError::Unknown(v.into_static()),
}
}
}
+20 -1
crates/jacquard-api/src/tools_ozone/moderation/get_repos.rs
···
#[serde(rename_all = "camelCase")]
pub struct GetReposOutput<'a> {
#[serde(borrow)]
-
pub repos: Vec<jacquard_common::types::value::Data<'a>>,
+
pub repos: Vec<GetReposOutputReposItem<'a>>,
+
}
+
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum GetReposOutputReposItem<'a> {
+
#[serde(rename = "tools.ozone.moderation.defs#repoViewDetail")]
+
RepoViewDetail(Box<crate::tools_ozone::moderation::RepoViewDetail<'a>>),
+
#[serde(rename = "tools.ozone.moderation.defs#repoViewNotFound")]
+
RepoViewNotFound(Box<crate::tools_ozone::moderation::RepoViewNotFound<'a>>),
}
///Response type for
+1 -14
crates/jacquard-api/src/tools_ozone/moderation/schedule_action.rs
···
#[builder(start_fn = new)]
pub struct ScheduleAction<'a> {
#[serde(borrow)]
-
pub action: ScheduleActionRecordAction<'a>,
+
pub action: jacquard_common::types::value::Data<'a>,
#[serde(borrow)]
pub created_by: jacquard_common::types::string::Did<'a>,
///This will be propagated to the moderation event when it is applied
···
>,
}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum ScheduleActionRecordAction<'a> {}
#[jacquard_derive::lexicon]
#[derive(
serde::Serialize,
+2 -14
crates/jacquard-api/src/tools_ozone/safelink/add_rule.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for AddRuleError<'_> {
-
type Output = AddRuleError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
AddRuleError::InvalidUrl(v) => AddRuleError::InvalidUrl(v.into_static()),
-
AddRuleError::RuleAlreadyExists(v) => {
-
AddRuleError::RuleAlreadyExists(v.into_static())
-
}
-
AddRuleError::Unknown(v) => AddRuleError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/safelink/remove_rule.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for RemoveRuleError<'_> {
-
type Output = RemoveRuleError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
RemoveRuleError::RuleNotFound(v) => {
-
RemoveRuleError::RuleNotFound(v.into_static())
-
}
-
RemoveRuleError::Unknown(v) => RemoveRuleError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/safelink/update_rule.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for UpdateRuleError<'_> {
-
type Output = UpdateRuleError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
UpdateRuleError::RuleNotFound(v) => {
-
UpdateRuleError::RuleNotFound(v.into_static())
-
}
-
UpdateRuleError::Unknown(v) => UpdateRuleError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/set/delete_set.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteSetError<'_> {
-
type Output = DeleteSetError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteSetError::SetNotFound(v) => {
-
DeleteSetError::SetNotFound(v.into_static())
-
}
-
DeleteSetError::Unknown(v) => DeleteSetError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/set/delete_values.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteValuesError<'_> {
-
type Output = DeleteValuesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteValuesError::SetNotFound(v) => {
-
DeleteValuesError::SetNotFound(v.into_static())
-
}
-
DeleteValuesError::Unknown(v) => DeleteValuesError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/set/get_values.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for GetValuesError<'_> {
-
type Output = GetValuesError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
GetValuesError::SetNotFound(v) => {
-
GetValuesError::SetNotFound(v.into_static())
-
}
-
GetValuesError::Unknown(v) => GetValuesError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/team/add_member.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for AddMemberError<'_> {
-
type Output = AddMemberError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
AddMemberError::MemberAlreadyExists(v) => {
-
AddMemberError::MemberAlreadyExists(v.into_static())
-
}
-
AddMemberError::Unknown(v) => AddMemberError::Unknown(v.into_static()),
}
}
}
+2 -16
crates/jacquard-api/src/tools_ozone/team/delete_member.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for DeleteMemberError<'_> {
-
type Output = DeleteMemberError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
DeleteMemberError::MemberNotFound(v) => {
-
DeleteMemberError::MemberNotFound(v.into_static())
-
}
-
DeleteMemberError::CannotDeleteSelf(v) => {
-
DeleteMemberError::CannotDeleteSelf(v.into_static())
-
}
-
DeleteMemberError::Unknown(v) => DeleteMemberError::Unknown(v.into_static()),
}
}
}
+2 -13
crates/jacquard-api/src/tools_ozone/team/update_member.rs
···
PartialEq,
Eq,
thiserror::Error,
-
miette::Diagnostic
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
)]
#[serde(tag = "error", content = "message")]
#[serde(bound(deserialize = "'de: 'a"))]
···
Ok(())
}
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
impl jacquard_common::IntoStatic for UpdateMemberError<'_> {
-
type Output = UpdateMemberError<'static>;
-
fn into_static(self) -> Self::Output {
-
match self {
-
UpdateMemberError::MemberNotFound(v) => {
-
UpdateMemberError::MemberNotFound(v.into_static())
-
}
-
UpdateMemberError::Unknown(v) => UpdateMemberError::Unknown(v.into_static()),
}
}
}
+10 -36
crates/jacquard-api/src/tools_ozone/verification.rs
···
pub issuer: jacquard_common::types::string::Did<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub issuer_profile: std::option::Option<VerificationViewRecordIssuerProfile<'a>>,
+
pub issuer_profile: std::option::Option<jacquard_common::types::value::Data<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub issuer_repo: std::option::Option<VerificationViewRecordIssuerRepo<'a>>,
+
pub issuer_repo: std::option::Option<VerificationViewIssuerRepo<'a>>,
///Describes the reason for revocation, also indicating that the verification is no longer valid.
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
···
pub subject: jacquard_common::types::string::Did<'a>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub subject_profile: std::option::Option<VerificationViewRecordSubjectProfile<'a>>,
+
pub subject_profile: std::option::Option<jacquard_common::types::value::Data<'a>>,
#[serde(skip_serializing_if = "std::option::Option::is_none")]
#[serde(borrow)]
-
pub subject_repo: std::option::Option<VerificationViewRecordSubjectRepo<'a>>,
+
pub subject_repo: std::option::Option<VerificationViewSubjectRepo<'a>>,
///The AT-URI of the verification record.
#[serde(borrow)]
pub uri: jacquard_common::types::string::AtUri<'a>,
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum VerificationViewRecordIssuerProfile<'a> {}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum VerificationViewRecordIssuerRepo<'a> {
+
pub enum VerificationViewIssuerRepo<'a> {
#[serde(rename = "tools.ozone.moderation.defs#repoViewDetail")]
-
DefsRepoViewDetail(Box<crate::tools_ozone::moderation::RepoViewDetail<'a>>),
+
RepoViewDetail(Box<crate::tools_ozone::moderation::RepoViewDetail<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#repoViewNotFound")]
-
DefsRepoViewNotFound(Box<crate::tools_ozone::moderation::RepoViewNotFound<'a>>),
+
RepoViewNotFound(Box<crate::tools_ozone::moderation::RepoViewNotFound<'a>>),
}
#[jacquard_derive::open_union]
···
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum VerificationViewRecordSubjectProfile<'a> {}
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum VerificationViewRecordSubjectRepo<'a> {
+
pub enum VerificationViewSubjectRepo<'a> {
#[serde(rename = "tools.ozone.moderation.defs#repoViewDetail")]
-
DefsRepoViewDetail(Box<crate::tools_ozone::moderation::RepoViewDetail<'a>>),
+
RepoViewDetail(Box<crate::tools_ozone::moderation::RepoViewDetail<'a>>),
#[serde(rename = "tools.ozone.moderation.defs#repoViewNotFound")]
-
DefsRepoViewNotFound(Box<crate::tools_ozone::moderation::RepoViewNotFound<'a>>),
+
RepoViewNotFound(Box<crate::tools_ozone::moderation::RepoViewNotFound<'a>>),
}
+1 -18
crates/jacquard-api/src/uk_skyblur/preference.rs
···
#[serde(rename_all = "camelCase")]
pub struct Preference<'a> {
#[serde(borrow)]
-
pub my_page: PreferenceRecordMyPage<'a>,
-
}
-
-
#[jacquard_derive::open_union]
-
#[derive(
-
serde::Serialize,
-
serde::Deserialize,
-
Debug,
-
Clone,
-
PartialEq,
-
Eq,
-
jacquard_derive::IntoStatic
-
)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum PreferenceRecordMyPage<'a> {
-
#[serde(rename = "uk.skyblur.preference#myPage")]
-
PreferenceMyPage(Box<crate::uk_skyblur::preference::MyPage<'a>>),
+
pub my_page: crate::uk_skyblur::preference::MyPage<'a>,
}
impl jacquard_common::types::collection::Collection for Preference<'_> {
+51 -1
crates/jacquard-api/src/win_tomo_x/pushat.rs
···
// @generated by jacquard-lexicon. DO NOT EDIT.
//
+
// Lexicon: win.tomo-x.pushat.defs
+
//
// This file was automatically generated from Lexicon schemas.
// Any manual changes will be overwritten on the next regeneration.
-
pub mod push_notify;
+
pub mod allow;
+
pub mod push_notify;
+
+
pub type DeviceList<'a> = Vec<crate::win_tomo_x::pushat::DeviceListItem<'a>>;
+
#[jacquard_derive::lexicon]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(rename_all = "camelCase")]
+
pub struct DeviceListItem<'a> {
+
pub current: bool,
+
pub id: jacquard_common::types::string::Tid,
+
#[serde(borrow)]
+
pub name: jacquard_common::CowStr<'a>,
+
}
+
+
#[jacquard_derive::lexicon]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(rename_all = "camelCase")]
+
pub struct NotifyBody<'a> {
+
///Body text of the notification.
+
#[serde(borrow)]
+
pub body: jacquard_common::CowStr<'a>,
+
///The URI of the icon displayed in the notification.
+
#[serde(skip_serializing_if = "std::option::Option::is_none")]
+
#[serde(borrow)]
+
pub icon: std::option::Option<jacquard_common::types::string::Uri<'a>>,
+
///Experimental — do not use. The URI to open when the notification is clicked.
+
#[serde(skip_serializing_if = "std::option::Option::is_none")]
+
#[serde(borrow)]
+
pub link: std::option::Option<jacquard_common::types::string::Uri<'a>>,
+
///Title text of the notification.
+
#[serde(borrow)]
+
pub title: jacquard_common::CowStr<'a>,
+
}
+46 -2
crates/jacquard-api/src/win_tomo_x/pushat/push_notify.rs
···
#[builder(start_fn = new)]
pub struct PushNotify<'a> {
#[serde(borrow)]
-
pub body: jacquard_common::types::value::Data<'a>,
+
pub body: crate::win_tomo_x::pushat::NotifyBody<'a>,
+
///The DID of the target user to whom the notification will be sent.
#[serde(borrow)]
pub target: jacquard_common::types::string::Did<'a>,
#[serde(flatten)]
···
)]
#[serde(rename_all = "camelCase")]
pub struct PushNotifyOutput<'a> {}
+
#[jacquard_derive::open_union]
+
#[derive(
+
serde::Serialize,
+
serde::Deserialize,
+
Debug,
+
Clone,
+
PartialEq,
+
Eq,
+
thiserror::Error,
+
miette::Diagnostic,
+
jacquard_derive::IntoStatic
+
)]
+
#[serde(tag = "error", content = "message")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum PushNotifyError<'a> {
+
#[serde(rename = "ServiceNotAllowedError")]
+
ServiceNotAllowedError(std::option::Option<String>),
+
#[serde(rename = "DeviceNotFoundError")]
+
DeviceNotFoundError(std::option::Option<String>),
+
}
+
+
impl std::fmt::Display for PushNotifyError<'_> {
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+
match self {
+
Self::ServiceNotAllowedError(msg) => {
+
write!(f, "ServiceNotAllowedError")?;
+
if let Some(msg) = msg {
+
write!(f, ": {}", msg)?;
+
}
+
Ok(())
+
}
+
Self::DeviceNotFoundError(msg) => {
+
write!(f, "DeviceNotFoundError")?;
+
if let Some(msg) = msg {
+
write!(f, ": {}", msg)?;
+
}
+
Ok(())
+
}
+
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
+
}
+
}
+
}
+
///Response type for
///win.tomo-x.pushat.pushNotify
pub struct PushNotifyResponse;
···
const NSID: &'static str = "win.tomo-x.pushat.pushNotify";
const ENCODING: &'static str = "application/json";
type Output<'de> = PushNotifyOutput<'de>;
-
type Err<'de> = jacquard_common::xrpc::GenericError<'de>;
+
type Err<'de> = PushNotifyError<'de>;
}
impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for PushNotify<'de> {
+3 -3
crates/jacquard-lexicon/Cargo.toml
···
glob = "0.3"
heck.workspace = true
itertools.workspace = true
-
jacquard-api = { version = "0.4", path = "../jacquard-api" }
-
jacquard-common = { version = "0.4", path = "../jacquard-common" }
-
jacquard-identity = { version = "0.4", path = "../jacquard-identity" }
+
jacquard-api = { version = "0.4", git = "https://tangled.org/@nonbinary.computer/jacquard" }
+
jacquard-common = { version = "0.4", git = "https://tangled.org/@nonbinary.computer/jacquard" }
+
jacquard-identity = { version = "0.4", git = "https://tangled.org/@nonbinary.computer/jacquard" }
kdl = "6"
miette = { workspace = true, features = ["fancy"] }
prettyplease.workspace = true
+49 -2574
crates/jacquard-lexicon/src/codegen.rs
···
use crate::corpus::LexiconCorpus;
use crate::error::{CodegenError, Result};
-
use crate::lexicon::{
-
LexArrayItem, LexInteger, LexObject, LexObjectProperty, LexRecord, LexString, LexStringFormat,
-
LexUserType, LexXrpcBody, LexXrpcBodySchema, LexXrpcError, LexXrpcProcedure, LexXrpcQuery,
-
LexXrpcSubscription, LexXrpcSubscriptionMessageSchema,
-
};
-
use heck::{ToPascalCase, ToSnakeCase};
+
use crate::lexicon::{LexArrayItem, LexUserType};
use proc_macro2::TokenStream;
use quote::quote;
-
/// Convert a value string to a valid Rust variant name
-
fn value_to_variant_name(value: &str) -> String {
-
// Remove leading special chars and convert to pascal case
-
let clean = value.trim_start_matches(|c: char| !c.is_alphanumeric());
-
let variant = clean.replace('-', "_").to_pascal_case();
-
-
// Prefix with underscore if starts with digit
-
if variant.chars().next().map_or(false, |c| c.is_ascii_digit()) {
-
format!("_{}", variant)
-
} else if variant.is_empty() {
-
"Unknown".to_string()
-
} else {
-
variant
-
}
-
}
-
-
/// Sanitize a string to be safe for identifiers and filenames
-
fn sanitize_name(s: &str) -> String {
-
if s.is_empty() {
-
return "unknown".to_string();
-
}
-
-
// Replace invalid characters with underscores
-
let mut sanitized: String = s
-
.chars()
-
.map(|c| {
-
if c.is_alphanumeric() || c == '_' {
-
c
-
} else {
-
'_'
-
}
-
})
-
.collect();
-
-
// Ensure it doesn't start with a digit
-
if sanitized
-
.chars()
-
.next()
-
.map_or(false, |c| c.is_ascii_digit())
-
{
-
sanitized = format!("_{}", sanitized);
-
}
-
-
sanitized
-
}
-
-
/// Create an identifier, using raw identifier if necessary for keywords
-
fn make_ident(s: &str) -> syn::Ident {
-
if s.is_empty() {
-
eprintln!("Warning: Empty identifier encountered, using 'unknown' as fallback");
-
return syn::Ident::new("unknown", proc_macro2::Span::call_site());
-
}
-
-
let sanitized = sanitize_name(s);
-
-
// Try to parse as ident, fall back to raw ident if needed
-
syn::parse_str::<syn::Ident>(&sanitized).unwrap_or_else(|_| {
-
eprintln!(
-
"Warning: Invalid identifier '{}' sanitized to '{}'",
-
s, sanitized
-
);
-
syn::Ident::new_raw(&sanitized, proc_macro2::Span::call_site())
-
})
-
}
+
mod utils;
+
mod names;
+
mod lifetime;
+
mod types;
+
mod structs;
+
mod xrpc;
+
mod output;
/// Code generator for lexicon types
pub struct CodeGenerator<'c> {
···
}
}
+
/// Generate doc comment from optional description (wrapper for utils function)
+
fn generate_doc_comment(&self, desc: Option<&jacquard_common::CowStr>) -> TokenStream {
+
utils::generate_doc_comment(desc)
+
}
+
/// Generate code for a lexicon def
pub fn generate_def(
&self,
···
// Top-level array becomes type alias to Vec<ItemType>
let type_name = self.def_to_type_name(nsid, def_name);
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
-
let item_type = self.array_item_to_rust_type(nsid, &array.items)?;
let doc = self.generate_doc_comment(array.description.as_ref());
let needs_lifetime = self.array_item_needs_lifetime(&array.items);
-
if needs_lifetime {
-
Ok(quote! {
-
#doc
-
pub type #ident<'a> = Vec<#item_type>;
-
})
+
+
// Check if items are a union - if so, generate the union enum first
+
if let LexArrayItem::Union(union) = &array.items {
+
let union_name = format!("{}Item", type_name);
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def = self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
+
let union_ident = syn::Ident::new(&union_name, proc_macro2::Span::call_site());
+
if needs_lifetime {
+
Ok(quote! {
+
#union_def
+
+
#doc
+
pub type #ident<'a> = Vec<#union_ident<'a>>;
+
})
+
} else {
+
Ok(quote! {
+
#union_def
+
+
#doc
+
pub type #ident = Vec<#union_ident>;
+
})
+
}
} else {
-
Ok(quote! {
-
#doc
-
pub type #ident = Vec<#item_type>;
-
})
+
// Regular array item type
+
let item_type = self.array_item_to_rust_type(nsid, &array.items)?;
+
if needs_lifetime {
+
Ok(quote! {
+
#doc
+
pub type #ident<'a> = Vec<#item_type>;
+
})
+
} else {
+
Ok(quote! {
+
#doc
+
pub type #ident = Vec<#item_type>;
+
})
+
}
}
}
LexUserType::Boolean(_)
···
LexUserType::XrpcSubscription(sub) => self.generate_subscription(nsid, def_name, sub),
}
}
-
-
/// Generate a record type
-
fn generate_record(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
record: &LexRecord<'static>,
-
) -> Result<TokenStream> {
-
match &record.record {
-
crate::lexicon::LexRecordRecord::Object(obj) => {
-
let type_name = self.def_to_type_name(nsid, def_name);
-
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
-
-
// Generate main struct fields
-
let fields = self.generate_object_fields(nsid, &type_name, obj, false)?;
-
let doc = self.generate_doc_comment(record.description.as_ref());
-
-
// Records always get a lifetime since they have the #[lexicon] attribute
-
// which adds extra_data: BTreeMap<..., Data<'a>>
-
let struct_def = quote! {
-
#doc
-
#[jacquard_derive::lexicon]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(rename_all = "camelCase")]
-
pub struct #ident<'a> {
-
#fields
-
}
-
};
-
-
// Generate union types and nested object types for this record
-
let mut unions = Vec::new();
-
for (field_name, field_type) in &obj.properties {
-
match field_type {
-
LexObjectProperty::Union(union) => {
-
let union_name =
-
format!("{}Record{}", type_name, field_name.to_pascal_case());
-
// Clone refs to avoid lifetime issues
-
let refs: Vec<_> = union.refs.iter().cloned().collect();
-
let union_def =
-
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
-
unions.push(union_def);
-
}
-
LexObjectProperty::Object(nested_obj) => {
-
let object_name =
-
format!("{}Record{}", type_name, field_name.to_pascal_case());
-
let obj_def = self.generate_object(nsid, &object_name, nested_obj)?;
-
unions.push(obj_def);
-
}
-
_ => {}
-
}
-
}
-
-
// Generate Collection trait impl
-
let collection_impl = quote! {
-
impl jacquard_common::types::collection::Collection for #ident<'_> {
-
const NSID: &'static str = #nsid;
-
}
-
};
-
-
// Generate IntoStatic impl
-
// let field_names: Vec<&str> = obj.properties.keys().map(|k| k.as_str()).collect();
-
// let into_static_impl =
-
// self.generate_into_static_for_struct(&type_name, &field_names, true, true);
-
-
Ok(quote! {
-
#struct_def
-
#(#unions)*
-
#collection_impl
-
//#into_static_impl
-
})
-
}
-
}
-
}
-
-
/// Generate an object type
-
fn generate_object(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
obj: &LexObject<'static>,
-
) -> Result<TokenStream> {
-
let type_name = self.def_to_type_name(nsid, def_name);
-
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
-
-
let fields = self.generate_object_fields(nsid, &type_name, obj, false)?;
-
let doc = self.generate_doc_comment(obj.description.as_ref());
-
-
// Objects always get a lifetime since they have the #[lexicon] attribute
-
// which adds extra_data: BTreeMap<..., Data<'a>>
-
let struct_def = quote! {
-
#doc
-
#[jacquard_derive::lexicon]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(rename_all = "camelCase")]
-
pub struct #ident<'a> {
-
#fields
-
}
-
};
-
-
// Generate union types and nested object types for this object
-
let mut unions = Vec::new();
-
for (field_name, field_type) in &obj.properties {
-
match field_type {
-
LexObjectProperty::Union(union) => {
-
let union_name = format!("{}Record{}", type_name, field_name.to_pascal_case());
-
let refs: Vec<_> = union.refs.iter().cloned().collect();
-
let union_def =
-
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
-
unions.push(union_def);
-
}
-
LexObjectProperty::Object(nested_obj) => {
-
let object_name = format!("{}Record{}", type_name, field_name.to_pascal_case());
-
let obj_def = self.generate_object(nsid, &object_name, nested_obj)?;
-
unions.push(obj_def);
-
}
-
_ => {}
-
}
-
}
-
-
// Generate IntoStatic impl
-
// let field_names: Vec<&str> = obj.properties.keys().map(|k| k.as_str()).collect();
-
// let into_static_impl =
-
// self.generate_into_static_for_struct(&type_name, &field_names, true, true);
-
-
Ok(quote! {
-
#struct_def
-
#(#unions)*
-
//#into_static_impl
-
})
-
}
-
-
/// Generate fields for an object
-
fn generate_object_fields(
-
&self,
-
nsid: &str,
-
parent_type_name: &str,
-
obj: &LexObject<'static>,
-
is_builder: bool,
-
) -> Result<TokenStream> {
-
let required = obj.required.as_ref().map(|r| r.as_slice()).unwrap_or(&[]);
-
-
let mut fields = Vec::new();
-
for (field_name, field_type) in &obj.properties {
-
let is_required = required.contains(field_name);
-
let field_tokens = self.generate_field(
-
nsid,
-
parent_type_name,
-
field_name,
-
field_type,
-
is_required,
-
is_builder,
-
)?;
-
fields.push(field_tokens);
-
}
-
-
Ok(quote! { #(#fields)* })
-
}
-
-
/// Generate a single field
-
fn generate_field(
-
&self,
-
nsid: &str,
-
parent_type_name: &str,
-
field_name: &str,
-
field_type: &LexObjectProperty<'static>,
-
is_required: bool,
-
is_builder: bool,
-
) -> Result<TokenStream> {
-
if field_name.is_empty() {
-
eprintln!(
-
"Warning: Empty field name in lexicon '{}' type '{}', using 'unknown' as fallback",
-
nsid, parent_type_name
-
);
-
}
-
let field_ident = make_ident(&field_name.to_snake_case());
-
-
let rust_type =
-
self.property_to_rust_type(nsid, parent_type_name, field_name, field_type)?;
-
let needs_lifetime = self.property_needs_lifetime(field_type);
-
-
// Check if this is a CowStr field for builder(into) attribute
-
let is_cowstr = matches!(field_type, LexObjectProperty::String(s) if s.format.is_none());
-
-
let rust_type = if is_required {
-
rust_type
-
} else {
-
quote! { std::option::Option<#rust_type> }
-
};
-
-
// Extract description from field type
-
let description = match field_type {
-
LexObjectProperty::Ref(r) => r.description.as_ref(),
-
LexObjectProperty::Union(u) => u.description.as_ref(),
-
LexObjectProperty::Bytes(b) => b.description.as_ref(),
-
LexObjectProperty::CidLink(c) => c.description.as_ref(),
-
LexObjectProperty::Array(a) => a.description.as_ref(),
-
LexObjectProperty::Blob(b) => b.description.as_ref(),
-
LexObjectProperty::Object(o) => o.description.as_ref(),
-
LexObjectProperty::Boolean(b) => b.description.as_ref(),
-
LexObjectProperty::Integer(i) => i.description.as_ref(),
-
LexObjectProperty::String(s) => s.description.as_ref(),
-
LexObjectProperty::Unknown(u) => u.description.as_ref(),
-
};
-
let doc = self.generate_doc_comment(description);
-
-
let mut attrs = Vec::new();
-
-
if !is_required {
-
attrs.push(quote! { #[serde(skip_serializing_if = "std::option::Option::is_none")] });
-
}
-
-
// Add serde(borrow) to all fields with lifetimes
-
if needs_lifetime {
-
attrs.push(quote! { #[serde(borrow)] });
-
}
-
-
// Add builder(into) for CowStr fields to allow String, &str, etc., but only for builder structs
-
if is_builder && is_cowstr {
-
attrs.push(quote! { #[builder(into)] });
-
}
-
-
Ok(quote! {
-
#doc
-
#(#attrs)*
-
pub #field_ident: #rust_type,
-
})
-
}
-
-
/// Check if a property type needs a lifetime parameter
-
fn property_needs_lifetime(&self, prop: &LexObjectProperty<'static>) -> bool {
-
match prop {
-
LexObjectProperty::Boolean(_) | LexObjectProperty::Integer(_) => false,
-
LexObjectProperty::String(s) => self.string_needs_lifetime(s),
-
LexObjectProperty::Bytes(_) => false, // Bytes is owned
-
LexObjectProperty::CidLink(_)
-
| LexObjectProperty::Blob(_)
-
| LexObjectProperty::Unknown(_) => true,
-
LexObjectProperty::Array(array) => self.array_item_needs_lifetime(&array.items),
-
LexObjectProperty::Object(_) => true, // Nested objects have lifetimes
-
LexObjectProperty::Ref(ref_type) => {
-
// Check if the ref target actually needs a lifetime
-
self.ref_needs_lifetime(&ref_type.r#ref)
-
}
-
LexObjectProperty::Union(_) => true, // Unions generally have lifetimes
-
}
-
}
-
-
/// Check if an array item type needs a lifetime parameter
-
fn array_item_needs_lifetime(&self, item: &LexArrayItem) -> bool {
-
match item {
-
LexArrayItem::Boolean(_) | LexArrayItem::Integer(_) => false,
-
LexArrayItem::String(s) => self.string_needs_lifetime(s),
-
LexArrayItem::Bytes(_) => false,
-
LexArrayItem::CidLink(_) | LexArrayItem::Blob(_) | LexArrayItem::Unknown(_) => true,
-
LexArrayItem::Object(_) => true, // Nested objects have lifetimes
-
LexArrayItem::Ref(ref_type) => self.ref_needs_lifetime(&ref_type.r#ref),
-
LexArrayItem::Union(_) => true,
-
}
-
}
-
-
/// Check if a string type needs a lifetime parameter
-
fn string_needs_lifetime(&self, s: &LexString) -> bool {
-
match s.format {
-
Some(LexStringFormat::Datetime)
-
| Some(LexStringFormat::Language)
-
| Some(LexStringFormat::Tid) => false,
-
_ => true, // Most string types borrow
-
}
-
}
-
-
/// Check if a ref needs a lifetime parameter
-
fn ref_needs_lifetime(&self, ref_str: &str) -> bool {
-
// Try to resolve the ref
-
if let Some((_doc, def)) = self.corpus.resolve_ref(ref_str) {
-
self.def_needs_lifetime(def)
-
} else {
-
// If we can't resolve it, assume it needs a lifetime (safe default)
-
true
-
}
-
}
-
-
/// Check if a lexicon def needs a lifetime parameter
-
fn def_needs_lifetime(&self, def: &LexUserType<'static>) -> bool {
-
match def {
-
// Records and Objects always have lifetimes now since they get #[lexicon] attribute
-
LexUserType::Record(_) => true,
-
LexUserType::Object(_) => true,
-
LexUserType::Token(_) => false,
-
LexUserType::String(s) => {
-
// Check if it's a known values enum or a regular string
-
if s.known_values.is_some() {
-
// Known values enums have Other(CowStr<'a>) variant
-
true
-
} else {
-
self.string_needs_lifetime(s)
-
}
-
}
-
LexUserType::Integer(_) => false,
-
LexUserType::Boolean(_) => false,
-
LexUserType::Bytes(_) => false,
-
LexUserType::CidLink(_) | LexUserType::Blob(_) | LexUserType::Unknown(_) => true,
-
LexUserType::Array(array) => self.array_item_needs_lifetime(&array.items),
-
LexUserType::XrpcQuery(_)
-
| LexUserType::XrpcProcedure(_)
-
| LexUserType::XrpcSubscription(_) => {
-
// XRPC types generate multiple structs, not a single type we can reference
-
// Shouldn't be referenced directly
-
true
-
}
-
}
-
}
-
-
/// Check if xrpc params need a lifetime parameter
-
fn params_need_lifetime(&self, params: &crate::lexicon::LexXrpcParameters<'static>) -> bool {
-
params.properties.values().any(|prop| {
-
use crate::lexicon::LexXrpcParametersProperty;
-
match prop {
-
LexXrpcParametersProperty::Boolean(_) | LexXrpcParametersProperty::Integer(_) => {
-
false
-
}
-
LexXrpcParametersProperty::String(s) => self.string_needs_lifetime(s),
-
LexXrpcParametersProperty::Unknown(_) => true,
-
LexXrpcParametersProperty::Array(arr) => {
-
use crate::lexicon::LexPrimitiveArrayItem;
-
match &arr.items {
-
LexPrimitiveArrayItem::Boolean(_) | LexPrimitiveArrayItem::Integer(_) => {
-
false
-
}
-
LexPrimitiveArrayItem::String(s) => self.string_needs_lifetime(s),
-
LexPrimitiveArrayItem::Unknown(_) => true,
-
}
-
}
-
}
-
})
-
}
-
-
/// Convert a property type to Rust type
-
fn property_to_rust_type(
-
&self,
-
nsid: &str,
-
parent_type_name: &str,
-
field_name: &str,
-
prop: &LexObjectProperty<'static>,
-
) -> Result<TokenStream> {
-
match prop {
-
LexObjectProperty::Boolean(_) => Ok(quote! { bool }),
-
LexObjectProperty::Integer(_) => Ok(quote! { i64 }),
-
LexObjectProperty::String(s) => Ok(self.string_to_rust_type(s)),
-
LexObjectProperty::Bytes(_) => Ok(quote! { bytes::Bytes }),
-
LexObjectProperty::CidLink(_) => {
-
Ok(quote! { jacquard_common::types::cid::CidLink<'a> })
-
}
-
LexObjectProperty::Blob(_) => Ok(quote! { jacquard_common::types::blob::Blob<'a> }),
-
LexObjectProperty::Unknown(_) => Ok(quote! { jacquard_common::types::value::Data<'a> }),
-
LexObjectProperty::Array(array) => {
-
let item_type = self.array_item_to_rust_type(nsid, &array.items)?;
-
Ok(quote! { Vec<#item_type> })
-
}
-
LexObjectProperty::Object(_object) => {
-
// Generate unique nested object type name: StatusView + metadata -> StatusViewRecordMetadata
-
let object_name =
-
format!("{}Record{}", parent_type_name, field_name.to_pascal_case());
-
let object_ident = syn::Ident::new(&object_name, proc_macro2::Span::call_site());
-
Ok(quote! { #object_ident<'a> })
-
}
-
LexObjectProperty::Ref(ref_type) => {
-
// Handle local refs (starting with #) by prepending the current NSID
-
let ref_str = if ref_type.r#ref.starts_with('#') {
-
format!("{}{}", nsid, ref_type.r#ref)
-
} else {
-
ref_type.r#ref.to_string()
-
};
-
self.ref_to_rust_type(&ref_str)
-
}
-
LexObjectProperty::Union(_union) => {
-
// Generate unique union type name: StatusView + embed -> StatusViewRecordEmbed
-
let union_name =
-
format!("{}Record{}", parent_type_name, field_name.to_pascal_case());
-
let union_ident = syn::Ident::new(&union_name, proc_macro2::Span::call_site());
-
Ok(quote! { #union_ident<'a> })
-
}
-
}
-
}
-
-
/// Convert array item to Rust type
-
fn array_item_to_rust_type(&self, nsid: &str, item: &LexArrayItem) -> Result<TokenStream> {
-
match item {
-
LexArrayItem::Boolean(_) => Ok(quote! { bool }),
-
LexArrayItem::Integer(_) => Ok(quote! { i64 }),
-
LexArrayItem::String(s) => Ok(self.string_to_rust_type(s)),
-
LexArrayItem::Bytes(_) => Ok(quote! { bytes::Bytes }),
-
LexArrayItem::CidLink(_) => Ok(quote! { jacquard_common::types::cid::CidLink<'a> }),
-
LexArrayItem::Blob(_) => Ok(quote! { jacquard_common::types::blob::Blob<'a> }),
-
LexArrayItem::Unknown(_) => Ok(quote! { jacquard_common::types::value::Data<'a> }),
-
LexArrayItem::Object(_) => {
-
// For inline objects in arrays, use Data since we can't generate a unique type name
-
Ok(quote! { jacquard_common::types::value::Data<'a> })
-
}
-
LexArrayItem::Ref(ref_type) => {
-
// Handle local refs (starting with #) by prepending the current NSID
-
let ref_str = if ref_type.r#ref.starts_with('#') {
-
format!("{}{}", nsid, ref_type.r#ref)
-
} else {
-
ref_type.r#ref.to_string()
-
};
-
self.ref_to_rust_type(&ref_str)
-
}
-
LexArrayItem::Union(_) => {
-
// For now, use Data
-
Ok(quote! { jacquard_common::types::value::Data<'a> })
-
}
-
}
-
}
-
-
/// Convert string type to Rust type
-
fn string_to_rust_type(&self, s: &LexString) -> TokenStream {
-
match s.format {
-
Some(LexStringFormat::Datetime) => {
-
quote! { jacquard_common::types::string::Datetime }
-
}
-
Some(LexStringFormat::Did) => quote! { jacquard_common::types::string::Did<'a> },
-
Some(LexStringFormat::Handle) => quote! { jacquard_common::types::string::Handle<'a> },
-
Some(LexStringFormat::AtIdentifier) => {
-
quote! { jacquard_common::types::ident::AtIdentifier<'a> }
-
}
-
Some(LexStringFormat::Nsid) => quote! { jacquard_common::types::string::Nsid<'a> },
-
Some(LexStringFormat::AtUri) => quote! { jacquard_common::types::string::AtUri<'a> },
-
Some(LexStringFormat::Uri) => quote! { jacquard_common::types::string::Uri<'a> },
-
Some(LexStringFormat::Cid) => quote! { jacquard_common::types::string::Cid<'a> },
-
Some(LexStringFormat::Language) => {
-
quote! { jacquard_common::types::string::Language }
-
}
-
Some(LexStringFormat::Tid) => quote! { jacquard_common::types::string::Tid },
-
Some(LexStringFormat::RecordKey) => {
-
quote! { jacquard_common::types::string::RecordKey<jacquard_common::types::string::Rkey<'a>> }
-
}
-
_ => quote! { jacquard_common::CowStr<'a> },
-
}
-
}
-
-
/// Convert ref to Rust type path
-
fn ref_to_rust_type(&self, ref_str: &str) -> Result<TokenStream> {
-
// Parse NSID and fragment
-
let (ref_nsid, ref_def) = if let Some((nsid, fragment)) = ref_str.split_once('#') {
-
(nsid, fragment)
-
} else {
-
(ref_str, "main")
-
};
-
-
// Check if ref exists
-
if !self.corpus.ref_exists(ref_str) {
-
// Fallback to Data
-
return Ok(quote! { jacquard_common::types::value::Data<'a> });
-
}
-
-
// Convert NSID to module path
-
// com.atproto.repo.strongRef -> com_atproto::repo::strong_ref::StrongRef
-
// app.bsky.richtext.facet -> app_bsky::richtext::facet::Facet
-
// app.bsky.actor.defs#nux -> app_bsky::actor::Nux (defs go in parent module)
-
let parts: Vec<&str> = ref_nsid.split('.').collect();
-
let last_segment = parts.last().unwrap();
-
-
let type_name = self.def_to_type_name(ref_nsid, ref_def);
-
-
let path_str = if *last_segment == "defs" && parts.len() >= 3 {
-
// defs types go in parent module
-
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
-
if parts.len() == 3 {
-
// com.atproto.defs -> com_atproto::TypeName
-
format!("{}::{}::{}", self.root_module, first_two, type_name)
-
} else {
-
// app.bsky.actor.defs -> app_bsky::actor::TypeName
-
let middle: Vec<_> = parts[2..parts.len() - 1]
-
.iter()
-
.copied()
-
.map(|s| sanitize_name(s))
-
.collect();
-
format!(
-
"{}::{}::{}::{}",
-
self.root_module,
-
first_two,
-
middle.join("::"),
-
type_name
-
)
-
}
-
} else {
-
// Regular types go in their own module file
-
let (module_path, file_module) = if parts.len() >= 3 {
-
// Join first two segments with underscore
-
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
-
let file_name = sanitize_name(last_segment).to_snake_case();
-
-
if parts.len() > 3 {
-
// Middle segments form the module path
-
let middle: Vec<_> = parts[2..parts.len() - 1]
-
.iter()
-
.copied()
-
.map(|s| sanitize_name(s))
-
.collect();
-
let base_path = format!("{}::{}", first_two, middle.join("::"));
-
(base_path, file_name)
-
} else {
-
// Only 3 parts: com.atproto.label -> com_atproto, file: label
-
(first_two, file_name)
-
}
-
} else if parts.len() == 2 {
-
// e.g., "com.example" -> "com_example", file: example
-
let first = sanitize_name(parts[0]);
-
let file_name = sanitize_name(parts[1]).to_snake_case();
-
(first, file_name)
-
} else {
-
(parts[0].to_string(), "main".to_string())
-
};
-
-
format!(
-
"{}::{}::{}::{}",
-
self.root_module, module_path, file_module, type_name
-
)
-
};
-
-
let path: syn::Path = syn::parse_str(&path_str).map_err(|e| CodegenError::Other {
-
message: format!("Failed to parse path: {} {}", path_str, e),
-
source: None,
-
})?;
-
-
// Only add lifetime if the target type needs it
-
if self.ref_needs_lifetime(ref_str) {
-
Ok(quote! { #path<'a> })
-
} else {
-
Ok(quote! { #path })
-
}
-
}
-
-
/// Generate query type
-
fn generate_query(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
query: &LexXrpcQuery<'static>,
-
) -> Result<TokenStream> {
-
let type_base = self.def_to_type_name(nsid, def_name);
-
let mut output = Vec::new();
-
-
let params_has_lifetime = query
-
.parameters
-
.as_ref()
-
.map(|p| match p {
-
crate::lexicon::LexXrpcQueryParameter::Params(params) => {
-
self.params_need_lifetime(params)
-
}
-
})
-
.unwrap_or(false);
-
let has_params = query.parameters.is_some();
-
let has_output = query.output.is_some();
-
let has_errors = query.errors.is_some();
-
-
if let Some(params) = &query.parameters {
-
let params_struct = self.generate_params_struct(&type_base, params)?;
-
output.push(params_struct);
-
}
-
-
if let Some(body) = &query.output {
-
let output_struct = self.generate_output_struct(nsid, &type_base, body)?;
-
output.push(output_struct);
-
}
-
-
if let Some(errors) = &query.errors {
-
let error_enum = self.generate_error_enum(&type_base, errors)?;
-
output.push(error_enum);
-
}
-
-
// Generate XrpcRequest impl
-
let output_encoding = query
-
.output
-
.as_ref()
-
.map(|o| o.encoding.as_ref())
-
.unwrap_or("application/json");
-
let xrpc_impl = self.generate_xrpc_request_impl(
-
nsid,
-
&type_base,
-
quote! { jacquard_common::xrpc::XrpcMethod::Query },
-
output_encoding,
-
has_params,
-
params_has_lifetime,
-
has_output,
-
has_errors,
-
false, // queries never have binary inputs
-
)?;
-
output.push(xrpc_impl);
-
-
Ok(quote! {
-
#(#output)*
-
})
-
}
-
-
/// Generate procedure type
-
fn generate_procedure(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
proc: &LexXrpcProcedure<'static>,
-
) -> Result<TokenStream> {
-
let type_base = self.def_to_type_name(nsid, def_name);
-
let mut output = Vec::new();
-
-
// Check if input is a binary body (no schema)
-
let is_binary_input = proc
-
.input
-
.as_ref()
-
.map(|i| i.schema.is_none())
-
.unwrap_or(false);
-
-
// Input bodies with schemas have lifetimes (they get #[lexicon] attribute)
-
// Binary inputs don't have lifetimes
-
let params_has_lifetime = proc.input.is_some() && !is_binary_input;
-
let has_input = proc.input.is_some();
-
let has_output = proc.output.is_some();
-
let has_errors = proc.errors.is_some();
-
-
if let Some(params) = &proc.parameters {
-
let params_struct = self.generate_params_struct_proc(&type_base, params)?;
-
output.push(params_struct);
-
}
-
-
if let Some(body) = &proc.input {
-
let input_struct = self.generate_input_struct(nsid, &type_base, body)?;
-
output.push(input_struct);
-
}
-
-
if let Some(body) = &proc.output {
-
let output_struct = self.generate_output_struct(nsid, &type_base, body)?;
-
output.push(output_struct);
-
}
-
-
if let Some(errors) = &proc.errors {
-
let error_enum = self.generate_error_enum(&type_base, errors)?;
-
output.push(error_enum);
-
}
-
-
// Generate XrpcRequest impl
-
let input_encoding = proc
-
.input
-
.as_ref()
-
.map(|i| i.encoding.as_ref())
-
.unwrap_or("application/json");
-
let output_encoding = proc
-
.output
-
.as_ref()
-
.map(|o| o.encoding.as_ref())
-
.unwrap_or("application/json");
-
let xrpc_impl = self.generate_xrpc_request_impl(
-
nsid,
-
&type_base,
-
quote! { jacquard_common::xrpc::XrpcMethod::Procedure(#input_encoding) },
-
output_encoding,
-
has_input,
-
params_has_lifetime,
-
has_output,
-
has_errors,
-
is_binary_input,
-
)?;
-
output.push(xrpc_impl);
-
-
Ok(quote! {
-
#(#output)*
-
})
-
}
-
-
fn generate_subscription(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
sub: &LexXrpcSubscription<'static>,
-
) -> Result<TokenStream> {
-
let type_base = self.def_to_type_name(nsid, def_name);
-
let mut output = Vec::new();
-
-
if let Some(params) = &sub.parameters {
-
// Extract LexXrpcParameters from the enum
-
match params {
-
crate::lexicon::LexXrpcSubscriptionParameter::Params(params_inner) => {
-
let params_struct =
-
self.generate_params_struct_inner(&type_base, params_inner)?;
-
output.push(params_struct);
-
}
-
}
-
}
-
-
if let Some(message) = &sub.message {
-
if let Some(schema) = &message.schema {
-
let message_type = self.generate_subscription_message(nsid, &type_base, schema)?;
-
output.push(message_type);
-
}
-
}
-
-
if let Some(errors) = &sub.errors {
-
let error_enum = self.generate_error_enum(&type_base, errors)?;
-
output.push(error_enum);
-
}
-
-
Ok(quote! {
-
#(#output)*
-
})
-
}
-
-
fn generate_subscription_message(
-
&self,
-
nsid: &str,
-
type_base: &str,
-
schema: &LexXrpcSubscriptionMessageSchema<'static>,
-
) -> Result<TokenStream> {
-
use crate::lexicon::LexXrpcSubscriptionMessageSchema;
-
-
match schema {
-
LexXrpcSubscriptionMessageSchema::Union(union) => {
-
// Generate a union enum for the message
-
let enum_name = format!("{}Message", type_base);
-
let enum_ident = syn::Ident::new(&enum_name, proc_macro2::Span::call_site());
-
-
let mut variants = Vec::new();
-
for ref_str in &union.refs {
-
let ref_str_s = ref_str.as_ref();
-
// Parse ref to get NSID and def name
-
let (ref_nsid, ref_def) =
-
if let Some((nsid, fragment)) = ref_str.split_once('#') {
-
(nsid, fragment)
-
} else {
-
(ref_str.as_ref(), "main")
-
};
-
-
let variant_name = if ref_def == "main" {
-
ref_nsid.split('.').last().unwrap().to_pascal_case()
-
} else {
-
ref_def.to_pascal_case()
-
};
-
let variant_ident =
-
syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
-
let type_path = self.ref_to_rust_type(ref_str)?;
-
-
variants.push(quote! {
-
#[serde(rename = #ref_str_s)]
-
#variant_ident(Box<#type_path>)
-
});
-
}
-
-
let doc = self.generate_doc_comment(union.description.as_ref());
-
-
// Generate IntoStatic impl for the enum
-
// let variant_info: Vec<(String, EnumVariantKind)> = union
-
// .refs
-
// .iter()
-
// .map(|ref_str| {
-
// let ref_def = if let Some((_, fragment)) = ref_str.split_once('#') {
-
// fragment
-
// } else {
-
// "main"
-
// };
-
// let variant_name = if ref_def == "main" {
-
// ref_str.split('.').last().unwrap().to_pascal_case()
-
// } else {
-
// ref_def.to_pascal_case()
-
// };
-
// (variant_name, EnumVariantKind::Tuple)
-
// })
-
// .collect();
-
// let into_static_impl = self.generate_into_static_for_enum(
-
// &enum_name,
-
// &variant_info,
-
// true,
-
// true, // open union
-
// );
-
-
Ok(quote! {
-
#doc
-
#[jacquard_derive::open_union]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum #enum_ident<'a> {
-
#(#variants,)*
-
}
-
-
//#into_static_impl
-
})
-
}
-
LexXrpcSubscriptionMessageSchema::Object(obj) => {
-
// Generate a struct for the message
-
let struct_name = format!("{}Message", type_base);
-
let struct_ident = syn::Ident::new(&struct_name, proc_macro2::Span::call_site());
-
-
let fields = self.generate_object_fields("", &struct_name, obj, false)?;
-
let doc = self.generate_doc_comment(obj.description.as_ref());
-
-
// Subscription message structs always get a lifetime since they have the #[lexicon] attribute
-
// which adds extra_data: BTreeMap<..., Data<'a>>
-
let struct_def = quote! {
-
#doc
-
#[jacquard_derive::lexicon]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(rename_all = "camelCase")]
-
pub struct #struct_ident<'a> {
-
#fields
-
}
-
};
-
-
// Generate union types for this message
-
let mut unions = Vec::new();
-
for (field_name, field_type) in &obj.properties {
-
if let LexObjectProperty::Union(union) = field_type {
-
let union_name =
-
format!("{}Record{}", struct_name, field_name.to_pascal_case());
-
let refs: Vec<_> = union.refs.iter().cloned().collect();
-
let union_def =
-
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
-
unions.push(union_def);
-
}
-
}
-
-
// Generate IntoStatic impl
-
// let field_names: Vec<&str> = obj.properties.keys().map(|k| k.as_str()).collect();
-
// let into_static_impl =
-
// self.generate_into_static_for_struct(&struct_name, &field_names, true, true);
-
-
Ok(quote! {
-
#struct_def
-
#(#unions)*
-
//#into_static_impl
-
})
-
}
-
LexXrpcSubscriptionMessageSchema::Ref(ref_type) => {
-
// Just a type alias to the referenced type
-
// Refs generally have lifetimes, so always add <'a>
-
let type_name = format!("{}Message", type_base);
-
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
-
let rust_type = self.ref_to_rust_type(&ref_type.r#ref)?;
-
let doc = self.generate_doc_comment(ref_type.description.as_ref());
-
-
Ok(quote! {
-
#doc
-
pub type #ident<'a> = #rust_type;
-
})
-
}
-
}
-
}
-
-
/// Convert def name to Rust type name
-
fn def_to_type_name(&self, nsid: &str, def_name: &str) -> String {
-
if def_name == "main" {
-
// Use last segment of NSID
-
let base_name = nsid.split('.').last().unwrap().to_pascal_case();
-
-
// Check if any other def would collide with this name
-
if let Some(doc) = self.corpus.get(nsid) {
-
let has_collision = doc.defs.keys().any(|other_def| {
-
let other_def_str: &str = other_def.as_ref();
-
other_def_str != "main" && other_def_str.to_pascal_case() == base_name
-
});
-
-
if has_collision {
-
return format!("{}Record", base_name);
-
}
-
}
-
-
base_name
-
} else {
-
def_name.to_pascal_case()
-
}
-
}
-
-
/// Convert NSID to file path relative to output directory
-
///
-
/// - `app.bsky.feed.post` → `app_bsky/feed/post.rs`
-
/// - `com.atproto.label.defs` → `com_atproto/label.rs` (defs go in parent)
-
fn nsid_to_file_path(&self, nsid: &str) -> std::path::PathBuf {
-
let parts: Vec<&str> = nsid.split('.').collect();
-
-
if parts.len() < 2 {
-
// Shouldn't happen with valid NSIDs, but handle gracefully
-
return format!("{}.rs", sanitize_name(parts[0])).into();
-
}
-
-
let last = parts.last().unwrap();
-
-
if *last == "defs" && parts.len() >= 3 {
-
// defs go in parent module: com.atproto.label.defs → com_atproto/label.rs
-
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
-
if parts.len() == 3 {
-
// com.atproto.defs → com_atproto.rs
-
format!("{}.rs", first_two).into()
-
} else {
-
// com.atproto.label.defs → com_atproto/label.rs
-
let middle: Vec<&str> = parts[2..parts.len() - 1].iter().copied().collect();
-
let mut path = std::path::PathBuf::from(first_two);
-
for segment in &middle[..middle.len() - 1] {
-
path.push(sanitize_name(segment));
-
}
-
path.push(format!("{}.rs", sanitize_name(middle.last().unwrap())));
-
path
-
}
-
} else {
-
// Regular path: app.bsky.feed.post → app_bsky/feed/post.rs
-
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
-
let mut path = std::path::PathBuf::from(first_two);
-
-
for segment in &parts[2..parts.len() - 1] {
-
path.push(sanitize_name(segment));
-
}
-
-
path.push(format!("{}.rs", sanitize_name(&last.to_snake_case())));
-
path
-
}
-
}
-
-
/// Generate all code for the corpus, organized by file
-
/// Returns a map of file paths to (tokens, optional NSID)
-
pub fn generate_all(
-
&self,
-
) -> Result<std::collections::BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)>> {
-
use std::collections::BTreeMap;
-
-
let mut file_contents: BTreeMap<std::path::PathBuf, Vec<TokenStream>> = BTreeMap::new();
-
let mut file_nsids: BTreeMap<std::path::PathBuf, String> = BTreeMap::new();
-
-
// Generate code for all lexicons
-
for (nsid, doc) in self.corpus.iter() {
-
let file_path = self.nsid_to_file_path(nsid.as_ref());
-
-
// Track which NSID this file is for
-
file_nsids.insert(file_path.clone(), nsid.to_string());
-
-
for (def_name, def) in &doc.defs {
-
let tokens = self.generate_def(nsid.as_ref(), def_name.as_ref(), def)?;
-
file_contents
-
.entry(file_path.clone())
-
.or_default()
-
.push(tokens);
-
}
-
}
-
-
// Combine all tokens for each file
-
let mut result = BTreeMap::new();
-
for (path, tokens_vec) in file_contents {
-
let nsid = file_nsids.get(&path).cloned();
-
result.insert(path, (quote! { #(#tokens_vec)* }, nsid));
-
}
-
-
Ok(result)
-
}
-
-
/// Generate parent module files with pub mod declarations
-
pub fn generate_module_tree(
-
&self,
-
file_map: &std::collections::BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)>,
-
defs_only: &std::collections::BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)>,
-
) -> std::collections::BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)> {
-
use std::collections::{BTreeMap, BTreeSet};
-
-
// Track what modules each directory needs to declare
-
// Key: directory path, Value: set of module names (file stems)
-
let mut dir_modules: BTreeMap<std::path::PathBuf, BTreeSet<String>> = BTreeMap::new();
-
-
// Collect all parent directories that have files
-
let mut all_dirs: BTreeSet<std::path::PathBuf> = BTreeSet::new();
-
for path in file_map.keys() {
-
if let Some(parent_dir) = path.parent() {
-
all_dirs.insert(parent_dir.to_path_buf());
-
}
-
}
-
-
for path in file_map.keys() {
-
if let Some(parent_dir) = path.parent() {
-
if let Some(file_stem) = path.file_stem().and_then(|s| s.to_str()) {
-
// Skip mod.rs and lib.rs - they're module files, not modules to declare
-
if file_stem == "mod" || file_stem == "lib" {
-
continue;
-
}
-
-
// Always add the module declaration to parent
-
dir_modules
-
.entry(parent_dir.to_path_buf())
-
.or_default()
-
.insert(file_stem.to_string());
-
}
-
}
-
}
-
-
// Generate module files
-
let mut result = BTreeMap::new();
-
-
for (dir, module_names) in dir_modules {
-
let mod_file_path = if dir.components().count() == 0 {
-
// Root directory -> lib.rs for library crates
-
std::path::PathBuf::from("lib.rs")
-
} else {
-
// Subdirectory: app_bsky/feed -> app_bsky/feed.rs (Rust 2018 style)
-
let dir_name = dir.file_name().and_then(|s| s.to_str()).unwrap_or("mod");
-
let sanitized_dir_name = sanitize_name(dir_name);
-
let mut path = dir
-
.parent()
-
.unwrap_or_else(|| std::path::Path::new(""))
-
.to_path_buf();
-
path.push(format!("{}.rs", sanitized_dir_name));
-
path
-
};
-
-
let is_root = dir.components().count() == 0;
-
let mods: Vec<_> = module_names
-
.iter()
-
.map(|name| {
-
let ident = make_ident(name);
-
if is_root {
-
// Top-level modules get feature gates
-
quote! {
-
#[cfg(feature = #name)]
-
pub mod #ident;
-
}
-
} else {
-
quote! { pub mod #ident; }
-
}
-
})
-
.collect();
-
-
// If this file already exists in defs_only (e.g., from defs), merge the content
-
let module_tokens = quote! { #(#mods)* };
-
if let Some((existing_tokens, nsid)) = defs_only.get(&mod_file_path) {
-
// Put module declarations FIRST, then existing defs content
-
result.insert(
-
mod_file_path,
-
(quote! { #module_tokens #existing_tokens }, nsid.clone()),
-
);
-
} else {
-
result.insert(mod_file_path, (module_tokens, None));
-
}
-
}
-
-
result
-
}
-
-
/// Write all generated code to disk
-
pub fn write_to_disk(&self, output_dir: &std::path::Path) -> Result<()> {
-
// Generate all code (defs only)
-
let defs_files = self.generate_all()?;
-
let mut all_files = defs_files.clone();
-
-
// Generate module tree iteratively until no new files appear
-
loop {
-
let module_map = self.generate_module_tree(&all_files, &defs_files);
-
let old_count = all_files.len();
-
-
// Merge new module files
-
for (path, tokens) in module_map {
-
all_files.insert(path, tokens);
-
}
-
-
if all_files.len() == old_count {
-
// No new files added
-
break;
-
}
-
}
-
-
// Write to disk
-
for (path, (tokens, nsid)) in all_files {
-
let full_path = output_dir.join(&path);
-
-
// Create parent directories
-
if let Some(parent) = full_path.parent() {
-
std::fs::create_dir_all(parent).map_err(|e| CodegenError::Other {
-
message: format!("Failed to create directory {:?}: {}", parent, e),
-
source: None,
-
})?;
-
}
-
-
// Format code
-
let file: syn::File = syn::parse2(tokens.clone()).map_err(|e| CodegenError::Other {
-
message: format!(
-
"Failed to parse tokens for {:?}: {}\nTokens: {}",
-
path, e, tokens
-
),
-
source: None,
-
})?;
-
let mut formatted = prettyplease::unparse(&file);
-
-
// Add blank lines between top-level items for better readability
-
let lines: Vec<&str> = formatted.lines().collect();
-
let mut result_lines = Vec::new();
-
-
for (i, line) in lines.iter().enumerate() {
-
result_lines.push(*line);
-
-
// Add blank line after closing braces that are at column 0 (top-level items)
-
if *line == "}" && i + 1 < lines.len() && !lines[i + 1].is_empty() {
-
result_lines.push("");
-
}
-
-
// Add blank line after last pub mod declaration before structs/enums
-
if line.starts_with("pub mod ") && i + 1 < lines.len() {
-
let next_line = lines[i + 1];
-
if !next_line.starts_with("pub mod ") && !next_line.is_empty() {
-
result_lines.push("");
-
}
-
}
-
}
-
-
formatted = result_lines.join("\n");
-
-
// Add header comment
-
let header = if let Some(nsid) = nsid {
-
format!(
-
"// @generated by jacquard-lexicon. DO NOT EDIT.\n//\n// Lexicon: {}\n//\n// This file was automatically generated from Lexicon schemas.\n// Any manual changes will be overwritten on the next regeneration.\n\n",
-
nsid
-
)
-
} else {
-
"// @generated by jacquard-lexicon. DO NOT EDIT.\n//\n// This file was automatically generated from Lexicon schemas.\n// Any manual changes will be overwritten on the next regeneration.\n\n".to_string()
-
};
-
formatted = format!("{}{}", header, formatted);
-
-
// Write file
-
std::fs::write(&full_path, formatted).map_err(|e| CodegenError::Other {
-
message: format!("Failed to write file {:?}: {}", full_path, e),
-
source: None,
-
})?;
-
}
-
-
Ok(())
-
}
-
-
/// Generate doc comment from description
-
fn generate_doc_comment(&self, desc: Option<&jacquard_common::CowStr>) -> TokenStream {
-
if let Some(desc) = desc {
-
let doc = desc.as_ref();
-
quote! { #[doc = #doc] }
-
} else {
-
quote! {}
-
}
-
}
-
-
/// Generate params struct from XRPC query parameters
-
fn generate_params_struct(
-
&self,
-
type_base: &str,
-
params: &crate::lexicon::LexXrpcQueryParameter<'static>,
-
) -> Result<TokenStream> {
-
use crate::lexicon::LexXrpcQueryParameter;
-
match params {
-
LexXrpcQueryParameter::Params(p) => self.generate_params_struct_inner(type_base, p),
-
}
-
}
-
-
/// Generate params struct from XRPC procedure parameters (query string params)
-
fn generate_params_struct_proc(
-
&self,
-
type_base: &str,
-
params: &crate::lexicon::LexXrpcProcedureParameter<'static>,
-
) -> Result<TokenStream> {
-
use crate::lexicon::LexXrpcProcedureParameter;
-
match params {
-
// For procedures, query string params still get "Params" suffix since the main struct is the input
-
LexXrpcProcedureParameter::Params(p) => {
-
let struct_name = format!("{}Params", type_base);
-
let ident = syn::Ident::new(&struct_name, proc_macro2::Span::call_site());
-
self.generate_params_struct_inner_with_name(&ident, p)
-
}
-
}
-
}
-
-
/// Generate params struct inner (shared implementation)
-
fn generate_params_struct_inner(
-
&self,
-
type_base: &str,
-
p: &crate::lexicon::LexXrpcParameters<'static>,
-
) -> Result<TokenStream> {
-
let ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
-
self.generate_params_struct_inner_with_name(&ident, p)
-
}
-
-
/// Generate params struct with custom name
-
fn generate_params_struct_inner_with_name(
-
&self,
-
ident: &syn::Ident,
-
p: &crate::lexicon::LexXrpcParameters<'static>,
-
) -> Result<TokenStream> {
-
let required = p.required.as_ref().map(|r| r.as_slice()).unwrap_or(&[]);
-
let mut fields = Vec::new();
-
let mut default_fns = Vec::new();
-
-
for (field_name, field_type) in &p.properties {
-
let is_required = required.contains(field_name);
-
let (field_tokens, default_fn) =
-
self.generate_param_field_with_default("", field_name, field_type, is_required)?;
-
fields.push(field_tokens);
-
if let Some(fn_def) = default_fn {
-
default_fns.push(fn_def);
-
}
-
}
-
-
let doc = self.generate_doc_comment(p.description.as_ref());
-
let needs_lifetime = self.params_need_lifetime(p);
-
-
let derives = quote! {
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, bon::Builder, jacquard_derive::IntoStatic)]
-
#[builder(start_fn = new)]
-
};
-
-
// Generate IntoStatic impl
-
// let field_names: Vec<&str> = p.properties.keys().map(|k| k.as_str()).collect();
-
// let type_name = ident.to_string();
-
// let into_static_impl =
-
// self.generate_into_static_for_struct(&type_name, &field_names, needs_lifetime, false);
-
-
if needs_lifetime {
-
Ok(quote! {
-
#(#default_fns)*
-
-
#doc
-
#derives
-
#[serde(rename_all = "camelCase")]
-
pub struct #ident<'a> {
-
#(#fields)*
-
}
-
-
//#into_static_impl
-
})
-
} else {
-
Ok(quote! {
-
#(#default_fns)*
-
-
#doc
-
#derives
-
#[serde(rename_all = "camelCase")]
-
pub struct #ident {
-
#(#fields)*
-
}
-
-
//#into_static_impl
-
})
-
}
-
}
-
-
/// Generate param field with serde default if present
-
/// Returns (field_tokens, optional_default_function)
-
fn generate_param_field_with_default(
-
&self,
-
nsid: &str,
-
field_name: &str,
-
field_type: &crate::lexicon::LexXrpcParametersProperty<'static>,
-
is_required: bool,
-
) -> Result<(TokenStream, Option<TokenStream>)> {
-
use crate::lexicon::LexXrpcParametersProperty;
-
use heck::ToSnakeCase;
-
-
// Get base field
-
let base_field = self.generate_param_field(nsid, field_name, field_type, is_required)?;
-
-
// Generate default function and attribute for required fields with defaults
-
// For optional fields, just add doc comments
-
let (doc_comment, serde_attr, default_fn) = if is_required {
-
match field_type {
-
LexXrpcParametersProperty::Boolean(b) if b.default.is_some() => {
-
let v = b.default.unwrap();
-
let fn_name = format!("_default_{}", field_name.to_snake_case());
-
let fn_ident = syn::Ident::new(&fn_name, proc_macro2::Span::call_site());
-
(
-
Some(format!("Defaults to `{}`", v)),
-
Some(quote! { #[serde(default = #fn_name)] }),
-
Some(quote! {
-
fn #fn_ident() -> bool { #v }
-
}),
-
)
-
}
-
LexXrpcParametersProperty::Integer(i) if i.default.is_some() => {
-
let v = i.default.unwrap();
-
let fn_name = format!("_default_{}", field_name.to_snake_case());
-
let fn_ident = syn::Ident::new(&fn_name, proc_macro2::Span::call_site());
-
(
-
Some(format!("Defaults to `{}`", v)),
-
Some(quote! { #[serde(default = #fn_name)] }),
-
Some(quote! {
-
fn #fn_ident() -> i64 { #v }
-
}),
-
)
-
}
-
LexXrpcParametersProperty::String(s) if s.default.is_some() => {
-
let v = s.default.as_ref().unwrap().as_ref();
-
let fn_name = format!("_default_{}", field_name.to_snake_case());
-
let fn_ident = syn::Ident::new(&fn_name, proc_macro2::Span::call_site());
-
(
-
Some(format!("Defaults to `\"{}\"`", v)),
-
Some(quote! { #[serde(default = #fn_name)] }),
-
Some(quote! {
-
fn #fn_ident() -> jacquard_common::CowStr<'static> {
-
jacquard_common::CowStr::from(#v)
-
}
-
}),
-
)
-
}
-
_ => (None, None, None),
-
}
-
} else {
-
// Optional fields - just doc comments, no serde defaults
-
let doc = match field_type {
-
LexXrpcParametersProperty::Integer(i) => {
-
let mut parts = Vec::new();
-
if let Some(def) = i.default {
-
parts.push(format!("default: {}", def));
-
}
-
if let Some(min) = i.minimum {
-
parts.push(format!("min: {}", min));
-
}
-
if let Some(max) = i.maximum {
-
parts.push(format!("max: {}", max));
-
}
-
if !parts.is_empty() {
-
Some(format!("({})", parts.join(", ")))
-
} else {
-
None
-
}
-
}
-
LexXrpcParametersProperty::String(s) => {
-
let mut parts = Vec::new();
-
if let Some(def) = s.default.as_ref() {
-
parts.push(format!("default: \"{}\"", def.as_ref()));
-
}
-
if let Some(min) = s.min_length {
-
parts.push(format!("min length: {}", min));
-
}
-
if let Some(max) = s.max_length {
-
parts.push(format!("max length: {}", max));
-
}
-
if !parts.is_empty() {
-
Some(format!("({})", parts.join(", ")))
-
} else {
-
None
-
}
-
}
-
LexXrpcParametersProperty::Boolean(b) => {
-
b.default.map(|v| format!("(default: {})", v))
-
}
-
_ => None,
-
};
-
(doc, None, None)
-
};
-
-
let doc = doc_comment.as_ref().map(|d| quote! { #[doc = #d] });
-
let field_with_attrs = match (doc, serde_attr) {
-
(Some(doc), Some(attr)) => quote! {
-
#doc
-
#attr
-
#base_field
-
},
-
(Some(doc), None) => quote! {
-
#doc
-
#base_field
-
},
-
(None, Some(attr)) => quote! {
-
#attr
-
#base_field
-
},
-
(None, None) => base_field,
-
};
-
-
Ok((field_with_attrs, default_fn))
-
}
-
-
/// Generate input struct from XRPC body
-
fn generate_input_struct(
-
&self,
-
nsid: &str,
-
type_base: &str,
-
body: &LexXrpcBody<'static>,
-
) -> Result<TokenStream> {
-
let ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
-
-
// Check if this is a binary body (no schema, just raw bytes)
-
let is_binary_body = body.schema.is_none();
-
-
let fields = if let Some(schema) = &body.schema {
-
self.generate_body_fields("", type_base, schema, true)?
-
} else {
-
// Binary body: just a bytes field
-
quote! {
-
pub body: bytes::Bytes,
-
}
-
};
-
-
let doc = self.generate_doc_comment(body.description.as_ref());
-
-
// Binary bodies don't need #[lexicon] attribute or lifetime
-
let struct_def = if is_binary_body {
-
quote! {
-
#doc
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, bon::Builder, jacquard_derive::IntoStatic)]
-
#[builder(start_fn = new)]
-
#[serde(rename_all = "camelCase")]
-
pub struct #ident {
-
#fields
-
}
-
}
-
} else {
-
// Input structs with schemas: manually add extra_data field with #[builder(default)]
-
// for bon compatibility. The #[lexicon] macro will see it exists and skip adding it.
-
quote! {
-
#doc
-
#[jacquard_derive::lexicon]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, bon::Builder, jacquard_derive::IntoStatic)]
-
#[serde(rename_all = "camelCase")]
-
#[builder(start_fn = new)]
-
pub struct #ident<'a> {
-
#fields
-
#[serde(flatten)]
-
#[serde(borrow)]
-
#[builder(default)]
-
pub extra_data: ::std::collections::BTreeMap<
-
::jacquard_common::smol_str::SmolStr,
-
::jacquard_common::types::value::Data<'a>
-
>,
-
}
-
}
-
};
-
-
// Generate union types if schema is an Object
-
let mut unions = Vec::new();
-
if let Some(crate::lexicon::LexXrpcBodySchema::Object(obj)) = &body.schema {
-
for (field_name, field_type) in &obj.properties {
-
if let LexObjectProperty::Union(union) = field_type {
-
let union_name = format!("{}Record{}", type_base, field_name.to_pascal_case());
-
let refs: Vec<_> = union.refs.iter().cloned().collect();
-
let union_def =
-
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
-
unions.push(union_def);
-
}
-
}
-
}
-
-
// Generate IntoStatic impl
-
// let into_static_impl = if is_binary_body {
-
// // Binary bodies: simple clone of the Bytes field
-
// quote! {
-
// impl jacquard_common::IntoStatic for #ident {
-
// type Output = #ident;
-
// fn into_static(self) -> Self::Output {
-
// self
-
// }
-
// }
-
// }
-
// } else {
-
// let field_names: Vec<&str> = match &body.schema {
-
// Some(crate::lexicon::LexXrpcBodySchema::Object(obj)) => {
-
// obj.properties.keys().map(|k| k.as_str()).collect()
-
// }
-
// Some(_) => {
-
// // For Ref or Union schemas, there's just a single flattened field
-
// vec!["value"]
-
// }
-
// None => {
-
// // No schema means no fields, just extra_data
-
// vec![]
-
// }
-
// };
-
// self.generate_into_static_for_struct(type_base, &field_names, true, true)
-
// };
-
-
Ok(quote! {
-
#struct_def
-
#(#unions)*
-
//#into_static_impl
-
})
-
}
-
-
/// Generate output struct from XRPC body
-
fn generate_output_struct(
-
&self,
-
nsid: &str,
-
type_base: &str,
-
body: &LexXrpcBody<'static>,
-
) -> Result<TokenStream> {
-
let struct_name = format!("{}Output", type_base);
-
let ident = syn::Ident::new(&struct_name, proc_macro2::Span::call_site());
-
-
let fields = if let Some(schema) = &body.schema {
-
self.generate_body_fields("", &struct_name, schema, false)?
-
} else {
-
quote! {}
-
};
-
-
let doc = self.generate_doc_comment(body.description.as_ref());
-
-
// Output structs always get a lifetime since they have the #[lexicon] attribute
-
// which adds extra_data: BTreeMap<..., Data<'a>>
-
let struct_def = quote! {
-
#doc
-
#[jacquard_derive::lexicon]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(rename_all = "camelCase")]
-
pub struct #ident<'a> {
-
#fields
-
}
-
};
-
-
// Generate union types if schema is an Object
-
let mut unions = Vec::new();
-
if let Some(crate::lexicon::LexXrpcBodySchema::Object(obj)) = &body.schema {
-
for (field_name, field_type) in &obj.properties {
-
if let LexObjectProperty::Union(union) = field_type {
-
let union_name =
-
format!("{}Record{}", struct_name, field_name.to_pascal_case());
-
let refs: Vec<_> = union.refs.iter().cloned().collect();
-
let union_def =
-
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
-
unions.push(union_def);
-
}
-
}
-
}
-
-
// Generate IntoStatic impl
-
// let field_names: Vec<&str> = match &body.schema {
-
// Some(crate::lexicon::LexXrpcBodySchema::Object(obj)) => {
-
// obj.properties.keys().map(|k| k.as_str()).collect()
-
// }
-
// Some(_) => {
-
// // For Ref or Union schemas, there's just a single flattened field
-
// vec!["value"]
-
// }
-
// None => {
-
// // No schema means no fields, just extra_data
-
// vec![]
-
// }
-
// };
-
// let into_static_impl =
-
// self.generate_into_static_for_struct(&struct_name, &field_names, true, true);
-
-
Ok(quote! {
-
#struct_def
-
#(#unions)*
-
//#into_static_impl
-
})
-
}
-
-
/// Generate fields from XRPC body schema
-
fn generate_body_fields(
-
&self,
-
nsid: &str,
-
parent_type_name: &str,
-
schema: &LexXrpcBodySchema<'static>,
-
is_builder: bool,
-
) -> Result<TokenStream> {
-
use crate::lexicon::LexXrpcBodySchema;
-
-
match schema {
-
LexXrpcBodySchema::Object(obj) => {
-
self.generate_object_fields(nsid, parent_type_name, obj, is_builder)
-
}
-
LexXrpcBodySchema::Ref(ref_type) => {
-
let rust_type = self.ref_to_rust_type(&ref_type.r#ref)?;
-
Ok(quote! {
-
#[serde(flatten)]
-
#[serde(borrow)]
-
pub value: #rust_type,
-
})
-
}
-
LexXrpcBodySchema::Union(_union) => {
-
let rust_type = quote! { jacquard_common::types::value::Data<'a> };
-
Ok(quote! {
-
#[serde(flatten)]
-
#[serde(borrow)]
-
pub value: #rust_type,
-
})
-
}
-
}
-
}
-
-
/// Generate a field for XRPC parameters
-
fn generate_param_field(
-
&self,
-
_nsid: &str,
-
field_name: &str,
-
field_type: &crate::lexicon::LexXrpcParametersProperty<'static>,
-
is_required: bool,
-
) -> Result<TokenStream> {
-
use crate::lexicon::LexXrpcParametersProperty;
-
-
let field_ident = make_ident(&field_name.to_snake_case());
-
-
let (rust_type, needs_lifetime, is_cowstr) = match field_type {
-
LexXrpcParametersProperty::Boolean(_) => (quote! { bool }, false, false),
-
LexXrpcParametersProperty::Integer(_) => (quote! { i64 }, false, false),
-
LexXrpcParametersProperty::String(s) => {
-
let is_cowstr = s.format.is_none(); // CowStr for plain strings
-
(
-
self.string_to_rust_type(s),
-
self.string_needs_lifetime(s),
-
is_cowstr,
-
)
-
}
-
LexXrpcParametersProperty::Unknown(_) => (
-
quote! { jacquard_common::types::value::Data<'a> },
-
true,
-
false,
-
),
-
LexXrpcParametersProperty::Array(arr) => {
-
let needs_lifetime = match &arr.items {
-
crate::lexicon::LexPrimitiveArrayItem::Boolean(_)
-
| crate::lexicon::LexPrimitiveArrayItem::Integer(_) => false,
-
crate::lexicon::LexPrimitiveArrayItem::String(s) => {
-
self.string_needs_lifetime(s)
-
}
-
crate::lexicon::LexPrimitiveArrayItem::Unknown(_) => true,
-
};
-
let item_type = match &arr.items {
-
crate::lexicon::LexPrimitiveArrayItem::Boolean(_) => quote! { bool },
-
crate::lexicon::LexPrimitiveArrayItem::Integer(_) => quote! { i64 },
-
crate::lexicon::LexPrimitiveArrayItem::String(s) => self.string_to_rust_type(s),
-
crate::lexicon::LexPrimitiveArrayItem::Unknown(_) => {
-
quote! { jacquard_common::types::value::Data<'a> }
-
}
-
};
-
(quote! { Vec<#item_type> }, needs_lifetime, false)
-
}
-
};
-
-
let rust_type = if is_required {
-
rust_type
-
} else {
-
quote! { std::option::Option<#rust_type> }
-
};
-
-
let mut attrs = Vec::new();
-
-
if !is_required {
-
attrs.push(quote! { #[serde(skip_serializing_if = "std::option::Option::is_none")] });
-
}
-
-
// Add serde(borrow) to all fields with lifetimes
-
if needs_lifetime {
-
attrs.push(quote! { #[serde(borrow)] });
-
}
-
-
// Add builder(into) for CowStr fields to allow String, &str, etc.
-
if is_cowstr {
-
attrs.push(quote! { #[builder(into)] });
-
}
-
-
Ok(quote! {
-
#(#attrs)*
-
pub #field_ident: #rust_type,
-
})
-
}
-
-
/// Generate error enum from XRPC errors
-
fn generate_error_enum(
-
&self,
-
type_base: &str,
-
errors: &[LexXrpcError<'static>],
-
) -> Result<TokenStream> {
-
let enum_name = format!("{}Error", type_base);
-
let ident = syn::Ident::new(&enum_name, proc_macro2::Span::call_site());
-
-
let mut variants = Vec::new();
-
let mut display_arms = Vec::new();
-
-
for error in errors {
-
let variant_name = error.name.to_pascal_case();
-
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
-
-
let error_name = error.name.as_ref();
-
let doc = self.generate_doc_comment(error.description.as_ref());
-
-
variants.push(quote! {
-
#doc
-
#[serde(rename = #error_name)]
-
#variant_ident(std::option::Option<String>)
-
});
-
-
display_arms.push(quote! {
-
Self::#variant_ident(msg) => {
-
write!(f, #error_name)?;
-
if let Some(msg) = msg {
-
write!(f, ": {}", msg)?;
-
}
-
Ok(())
-
}
-
});
-
}
-
-
// Generate IntoStatic impl
-
let variant_info: Vec<(String, EnumVariantKind)> = errors
-
.iter()
-
.map(|e| (e.name.to_pascal_case(), EnumVariantKind::Tuple))
-
.collect();
-
let into_static_impl =
-
self.generate_into_static_for_enum(&enum_name, &variant_info, true, true);
-
-
Ok(quote! {
-
#[jacquard_derive::open_union]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic)]
-
#[serde(tag = "error", content = "message")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum #ident<'a> {
-
#(#variants,)*
-
}
-
-
impl std::fmt::Display for #ident<'_> {
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-
match self {
-
#(#display_arms)*
-
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
-
}
-
}
-
}
-
-
#into_static_impl
-
})
-
}
-
-
/// Generate enum for string with known values
-
fn generate_known_values_enum(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
string: &LexString<'static>,
-
) -> Result<TokenStream> {
-
let type_name = self.def_to_type_name(nsid, def_name);
-
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
-
-
let known_values = string.known_values.as_ref().unwrap();
-
let mut variants = Vec::new();
-
let mut from_str_arms = Vec::new();
-
let mut as_str_arms = Vec::new();
-
-
for value in known_values {
-
// Convert value to valid Rust identifier
-
let value_str = value.as_ref();
-
let variant_name = value_to_variant_name(value_str);
-
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
-
-
variants.push(quote! {
-
#variant_ident
-
});
-
-
from_str_arms.push(quote! {
-
#value_str => Self::#variant_ident
-
});
-
-
as_str_arms.push(quote! {
-
Self::#variant_ident => #value_str
-
});
-
}
-
-
let doc = self.generate_doc_comment(string.description.as_ref());
-
-
// Generate IntoStatic impl
-
let variant_info: Vec<(String, EnumVariantKind)> = known_values
-
.iter()
-
.map(|value| {
-
let variant_name = value_to_variant_name(value.as_ref());
-
(variant_name, EnumVariantKind::Unit)
-
})
-
.chain(std::iter::once((
-
"Other".to_string(),
-
EnumVariantKind::Tuple,
-
)))
-
.collect();
-
let into_static_impl =
-
self.generate_into_static_for_enum(&type_name, &variant_info, true, false);
-
-
Ok(quote! {
-
#doc
-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-
pub enum #ident<'a> {
-
#(#variants,)*
-
Other(jacquard_common::CowStr<'a>),
-
}
-
-
impl<'a> #ident<'a> {
-
pub fn as_str(&self) -> &str {
-
match self {
-
#(#as_str_arms,)*
-
Self::Other(s) => s.as_ref(),
-
}
-
}
-
}
-
-
impl<'a> From<&'a str> for #ident<'a> {
-
fn from(s: &'a str) -> Self {
-
match s {
-
#(#from_str_arms,)*
-
_ => Self::Other(jacquard_common::CowStr::from(s)),
-
}
-
}
-
}
-
-
impl<'a> From<String> for #ident<'a> {
-
fn from(s: String) -> Self {
-
match s.as_str() {
-
#(#from_str_arms,)*
-
_ => Self::Other(jacquard_common::CowStr::from(s)),
-
}
-
}
-
}
-
-
impl<'a> AsRef<str> for #ident<'a> {
-
fn as_ref(&self) -> &str {
-
self.as_str()
-
}
-
}
-
-
impl<'a> serde::Serialize for #ident<'a> {
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-
where
-
S: serde::Serializer,
-
{
-
serializer.serialize_str(self.as_str())
-
}
-
}
-
-
impl<'de, 'a> serde::Deserialize<'de> for #ident<'a>
-
where
-
'de: 'a,
-
{
-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-
where
-
D: serde::Deserializer<'de>,
-
{
-
let s = <&'de str>::deserialize(deserializer)?;
-
Ok(Self::from(s))
-
}
-
}
-
-
#into_static_impl
-
})
-
}
-
-
/// Generate enum for integer with enum values
-
fn generate_integer_enum(
-
&self,
-
nsid: &str,
-
def_name: &str,
-
integer: &LexInteger<'static>,
-
) -> Result<TokenStream> {
-
let type_name = self.def_to_type_name(nsid, def_name);
-
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
-
-
let enum_values = integer.r#enum.as_ref().unwrap();
-
let mut variants = Vec::new();
-
let mut from_i64_arms = Vec::new();
-
let mut to_i64_arms = Vec::new();
-
-
for value in enum_values {
-
let variant_name = format!("Value{}", value.abs());
-
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
-
-
variants.push(quote! {
-
#[serde(rename = #value)]
-
#variant_ident
-
});
-
-
from_i64_arms.push(quote! {
-
#value => Self::#variant_ident
-
});
-
-
to_i64_arms.push(quote! {
-
Self::#variant_ident => #value
-
});
-
}
-
-
let doc = self.generate_doc_comment(integer.description.as_ref());
-
-
Ok(quote! {
-
#doc
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-
pub enum #ident {
-
#(#variants,)*
-
#[serde(untagged)]
-
Other(i64),
-
}
-
-
impl #ident {
-
pub fn as_i64(&self) -> i64 {
-
match self {
-
#(#to_i64_arms,)*
-
Self::Other(n) => *n,
-
}
-
}
-
}
-
-
impl From<i64> for #ident {
-
fn from(n: i64) -> Self {
-
match n {
-
#(#from_i64_arms,)*
-
_ => Self::Other(n),
-
}
-
}
-
}
-
-
impl serde::Serialize for #ident {
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-
where
-
S: serde::Serializer,
-
{
-
serializer.serialize_i64(self.as_i64())
-
}
-
}
-
-
impl<'de> serde::Deserialize<'de> for #ident {
-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-
where
-
D: serde::Deserializer<'de>,
-
{
-
let n = i64::deserialize(deserializer)?;
-
Ok(Self::from(n))
-
}
-
}
-
})
-
}
-
-
/// Generate XrpcRequest trait impl for a query or procedure
-
fn generate_xrpc_request_impl(
-
&self,
-
nsid: &str,
-
type_base: &str,
-
method: TokenStream,
-
output_encoding: &str,
-
has_params: bool,
-
params_has_lifetime: bool,
-
has_output: bool,
-
has_errors: bool,
-
is_binary_input: bool,
-
) -> Result<TokenStream> {
-
let output_type = if has_output {
-
let output_ident = syn::Ident::new(
-
&format!("{}Output", type_base),
-
proc_macro2::Span::call_site(),
-
);
-
quote! { #output_ident<'de> }
-
} else {
-
quote! { () }
-
};
-
-
let error_type = if has_errors {
-
let error_ident = syn::Ident::new(
-
&format!("{}Error", type_base),
-
proc_macro2::Span::call_site(),
-
);
-
quote! { #error_ident<'de> }
-
} else {
-
quote! { jacquard_common::xrpc::GenericError<'de> }
-
};
-
-
// Generate the response type that implements XrpcResp
-
let response_ident = syn::Ident::new(
-
&format!("{}Response", type_base),
-
proc_macro2::Span::call_site(),
-
);
-
-
// Generate the endpoint type that implements XrpcEndpoint
-
let endpoint_ident = syn::Ident::new(
-
&format!("{}Request", type_base),
-
proc_macro2::Span::call_site(),
-
);
-
-
let response_type = quote! {
-
#[doc = "Response type for "]
-
#[doc = #nsid]
-
pub struct #response_ident;
-
-
impl jacquard_common::xrpc::XrpcResp for #response_ident {
-
const NSID: &'static str = #nsid;
-
const ENCODING: &'static str = #output_encoding;
-
type Output<'de> = #output_type;
-
type Err<'de> = #error_type;
-
}
-
};
-
-
// Generate encode_body() method for binary inputs
-
let encode_body_method = if is_binary_input {
-
quote! {
-
fn encode_body(&self) -> Result<Vec<u8>, jacquard_common::xrpc::EncodeError> {
-
Ok(self.body.to_vec())
-
}
-
}
-
} else {
-
quote! {}
-
};
-
-
// Generate decode_body() method for binary inputs
-
let decode_body_method = if is_binary_input {
-
quote! {
-
fn decode_body(
-
body: &'de [u8],
-
) -> Result<Box<Self>, jacquard_common::error::DecodeError> {
-
Ok(Box::new(Self {
-
body: bytes::Bytes::copy_from_slice(body),
-
}))
-
}
-
}
-
} else {
-
quote! {}
-
};
-
-
let endpoint_path = format!("/xrpc/{}", nsid);
-
-
if has_params {
-
// Implement on the params/input struct itself
-
let request_ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
-
let impl_target = if params_has_lifetime {
-
quote! { #request_ident<'de> }
-
} else {
-
quote! { #request_ident }
-
};
-
-
Ok(quote! {
-
#response_type
-
-
impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for #impl_target {
-
const NSID: &'static str = #nsid;
-
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
-
-
type Response = #response_ident;
-
-
#encode_body_method
-
#decode_body_method
-
}
-
-
#[doc = "Endpoint type for "]
-
#[doc = #nsid]
-
pub struct #endpoint_ident;
-
-
impl jacquard_common::xrpc::XrpcEndpoint for #endpoint_ident {
-
const PATH: &'static str = #endpoint_path;
-
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
-
-
type Request<'de> = #impl_target;
-
type Response = #response_ident;
-
}
-
})
-
} else {
-
// No params - generate a marker struct
-
let request_ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
-
-
Ok(quote! {
-
/// XRPC request marker type
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, jacquard_derive::IntoStatic)]
-
pub struct #request_ident;
-
-
#response_type
-
-
impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for #request_ident {
-
const NSID: &'static str = #nsid;
-
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
-
-
type Response = #response_ident;
-
}
-
-
#[doc = "Endpoint type for "]
-
#[doc = #nsid]
-
pub struct #endpoint_ident;
-
-
impl jacquard_common::xrpc::XrpcEndpoint for #endpoint_ident {
-
const PATH: &'static str = #endpoint_path;
-
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
-
-
type Request<'de> = #request_ident;
-
type Response = #response_ident;
-
}
-
})
-
}
-
}
-
-
/// Generate a union enum
-
pub fn generate_union(
-
&self,
-
current_nsid: &str,
-
union_name: &str,
-
refs: &[jacquard_common::CowStr<'static>],
-
description: Option<&str>,
-
closed: Option<bool>,
-
) -> Result<TokenStream> {
-
let enum_ident = syn::Ident::new(union_name, proc_macro2::Span::call_site());
-
-
// Extract namespace prefix from current NSID (first two segments: "sh.weaver" from "sh.weaver.embed.recordWithMedia")
-
let parts: Vec<_> = current_nsid.splitn(3, '.').collect();
-
let current_namespace = if parts.len() >= 2 {
-
format!("{}.{}", parts[0], parts[1])
-
} else {
-
current_nsid.to_string()
-
};
-
-
// First pass: collect all variant names and detect collisions
-
#[derive(Debug)]
-
struct VariantInfo<'a> {
-
ref_str: &'a str,
-
ref_nsid: &'a str,
-
simple_name: String,
-
is_current_namespace: bool,
-
}
-
-
let mut variant_infos = Vec::new();
-
for ref_str in refs {
-
// Parse ref to get NSID and def name
-
let (ref_nsid, ref_def) = if let Some((nsid, fragment)) = ref_str.split_once('#') {
-
(nsid, fragment)
-
} else {
-
(ref_str.as_ref(), "main")
-
};
-
-
// Skip unknown refs - they'll be handled by Unknown variant
-
if !self.corpus.ref_exists(ref_str.as_ref()) {
-
continue;
-
}
-
-
// Check if ref is in current namespace
-
let is_current_namespace = ref_nsid.starts_with(&current_namespace);
-
-
// Generate simple variant name (without namespace prefix)
-
let simple_name = if ref_def == "main" {
-
ref_nsid.split('.').last().unwrap().to_pascal_case()
-
} else {
-
let last_segment = ref_nsid.split('.').last().unwrap().to_pascal_case();
-
format!("{}{}", last_segment, ref_def.to_pascal_case())
-
};
-
-
variant_infos.push(VariantInfo {
-
ref_str: ref_str.as_ref(),
-
ref_nsid,
-
simple_name,
-
is_current_namespace,
-
});
-
}
-
-
// Second pass: detect collisions and disambiguate
-
use std::collections::HashMap;
-
let mut name_counts: HashMap<String, usize> = HashMap::new();
-
for info in &variant_infos {
-
*name_counts.entry(info.simple_name.clone()).or_insert(0) += 1;
-
}
-
-
let mut variants = Vec::new();
-
for info in variant_infos {
-
let has_collision = name_counts.get(&info.simple_name).copied().unwrap_or(0) > 1;
-
-
// Track namespace dependency for foreign refs
-
if !info.is_current_namespace {
-
let parts: Vec<_> = info.ref_nsid.splitn(3, '.').collect();
-
let foreign_namespace = if parts.len() >= 2 {
-
format!("{}.{}", parts[0], parts[1])
-
} else {
-
info.ref_nsid.to_string()
-
};
-
self.namespace_deps
-
.borrow_mut()
-
.entry(current_namespace.clone())
-
.or_default()
-
.insert(foreign_namespace);
-
}
-
-
// Disambiguate: add second NSID segment prefix only to foreign refs when there's a collision
-
let variant_name = if has_collision && !info.is_current_namespace {
-
// Get second segment (namespace identifier: "bsky" from "app.bsky.embed.images")
-
let segments: Vec<&str> = info.ref_nsid.split('.').collect();
-
let prefix = if segments.len() >= 2 {
-
segments[1].to_pascal_case()
-
} else {
-
// Fallback: use first segment if only one exists
-
segments[0].to_pascal_case()
-
};
-
format!("{}{}", prefix, info.simple_name)
-
} else {
-
info.simple_name.clone()
-
};
-
-
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
-
-
// Get the Rust type for this ref
-
let rust_type = self.ref_to_rust_type(info.ref_str)?;
-
-
// Add serde rename for the full NSID
-
let ref_str_literal = info.ref_str;
-
variants.push(quote! {
-
#[serde(rename = #ref_str_literal)]
-
#variant_ident(Box<#rust_type>)
-
});
-
}
-
-
let doc = description
-
.map(|d| quote! { #[doc = #d] })
-
.unwrap_or_else(|| quote! {});
-
-
// Only add open_union if not closed
-
let is_open = closed != Some(true);
-
-
// Generate IntoStatic impl
-
// let variant_info: Vec<(String, EnumVariantKind)> = refs
-
// .iter()
-
// .filter_map(|ref_str| {
-
// // Skip unknown refs
-
// if !self.corpus.ref_exists(ref_str.as_ref()) {
-
// return None;
-
// }
-
-
// let (ref_nsid, ref_def) = if let Some((nsid, fragment)) = ref_str.split_once('#') {
-
// (nsid, fragment)
-
// } else {
-
// (ref_str.as_ref(), "main")
-
// };
-
-
// let variant_name = if ref_def == "main" {
-
// ref_nsid.split('.').last().unwrap().to_pascal_case()
-
// } else {
-
// let last_segment = ref_nsid.split('.').last().unwrap().to_pascal_case();
-
// format!("{}{}", last_segment, ref_def.to_pascal_case())
-
// };
-
// Some((variant_name, EnumVariantKind::Tuple))
-
// })
-
// .collect();
-
// let into_static_impl =
-
// self.generate_into_static_for_enum(union_name, &variant_info, true, is_open);
-
-
if is_open {
-
Ok(quote! {
-
#doc
-
#[jacquard_derive::open_union]
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum #enum_ident<'a> {
-
#(#variants,)*
-
}
-
-
//#into_static_impl
-
})
-
} else {
-
Ok(quote! {
-
#doc
-
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
-
#[serde(tag = "$type")]
-
#[serde(bound(deserialize = "'de: 'a"))]
-
pub enum #enum_ident<'a> {
-
#(#variants,)*
-
}
-
-
//#into_static_impl
-
})
-
}
-
}
-
-
/// Generate IntoStatic impl for a struct
-
#[allow(dead_code)]
-
fn generate_into_static_for_struct(
-
&self,
-
type_name: &str,
-
field_names: &[&str],
-
has_lifetime: bool,
-
has_extra_data: bool,
-
) -> TokenStream {
-
let ident = syn::Ident::new(type_name, proc_macro2::Span::call_site());
-
-
let field_idents: Vec<_> = field_names
-
.iter()
-
.map(|name| make_ident(&name.to_snake_case()))
-
.collect();
-
-
if has_lifetime {
-
let field_conversions: Vec<_> = field_idents
-
.iter()
-
.map(|field| quote! { #field: self.#field.into_static() })
-
.collect();
-
-
let extra_data_conversion = if has_extra_data {
-
quote! { extra_data: self.extra_data.into_static(), }
-
} else {
-
quote! {}
-
};
-
-
quote! {
-
impl jacquard_common::IntoStatic for #ident<'_> {
-
type Output = #ident<'static>;
-
-
fn into_static(self) -> Self::Output {
-
#ident {
-
#(#field_conversions,)*
-
#extra_data_conversion
-
}
-
}
-
}
-
}
-
} else {
-
quote! {
-
impl jacquard_common::IntoStatic for #ident {
-
type Output = #ident;
-
-
fn into_static(self) -> Self::Output {
-
self
-
}
-
}
-
}
-
}
-
}
-
-
/// Generate IntoStatic impl for an enum
-
fn generate_into_static_for_enum(
-
&self,
-
type_name: &str,
-
variant_info: &[(String, EnumVariantKind)],
-
has_lifetime: bool,
-
is_open: bool,
-
) -> TokenStream {
-
let ident = syn::Ident::new(type_name, proc_macro2::Span::call_site());
-
-
if has_lifetime {
-
let variant_conversions: Vec<_> = variant_info
-
.iter()
-
.map(|(variant_name, kind)| {
-
let variant_ident = syn::Ident::new(variant_name, proc_macro2::Span::call_site());
-
match kind {
-
EnumVariantKind::Unit => {
-
quote! {
-
#ident::#variant_ident => #ident::#variant_ident
-
}
-
}
-
EnumVariantKind::Tuple => {
-
quote! {
-
#ident::#variant_ident(v) => #ident::#variant_ident(v.into_static())
-
}
-
}
-
EnumVariantKind::Struct(fields) => {
-
let field_idents: Vec<_> = fields
-
.iter()
-
.map(|f| make_ident(&f.to_snake_case()))
-
.collect();
-
let field_conversions: Vec<_> = field_idents
-
.iter()
-
.map(|f| quote! { #f: #f.into_static() })
-
.collect();
-
quote! {
-
#ident::#variant_ident { #(#field_idents,)* } => #ident::#variant_ident {
-
#(#field_conversions,)*
-
}
-
}
-
}
-
}
-
})
-
.collect();
-
-
let unknown_conversion = if is_open {
-
quote! {
-
#ident::Unknown(v) => #ident::Unknown(v.into_static()),
-
}
-
} else {
-
quote! {}
-
};
-
-
quote! {
-
impl jacquard_common::IntoStatic for #ident<'_> {
-
type Output = #ident<'static>;
-
-
fn into_static(self) -> Self::Output {
-
match self {
-
#(#variant_conversions,)*
-
#unknown_conversion
-
}
-
}
-
}
-
}
-
} else {
-
quote! {
-
impl jacquard_common::IntoStatic for #ident {
-
type Output = #ident;
-
-
fn into_static(self) -> Self::Output {
-
self
-
}
-
}
-
}
-
}
-
}
-
-
/// Get namespace dependencies collected during code generation
-
pub fn get_namespace_dependencies(
-
&self,
-
) -> std::collections::HashMap<String, std::collections::HashSet<String>> {
-
self.namespace_deps.borrow().clone()
-
}
-
-
/// Generate Cargo.toml features section from namespace dependencies
-
pub fn generate_cargo_features(&self, lib_rs_path: Option<&std::path::Path>) -> String {
-
use std::fmt::Write;
-
-
let deps = self.namespace_deps.borrow();
-
let mut all_namespaces: std::collections::HashSet<String> =
-
std::collections::HashSet::new();
-
-
// Collect all namespaces from the corpus (first two segments of each NSID)
-
for (nsid, _doc) in self.corpus.iter() {
-
let parts: Vec<_> = nsid.as_str().splitn(3, '.').collect();
-
let namespace = if parts.len() >= 2 {
-
format!("{}.{}", parts[0], parts[1])
-
} else {
-
nsid.to_string()
-
};
-
all_namespaces.insert(namespace);
-
}
-
-
// Also collect existing feature names from lib.rs
-
let mut existing_features = std::collections::HashSet::new();
-
if let Some(lib_rs) = lib_rs_path {
-
if let Ok(content) = std::fs::read_to_string(lib_rs) {
-
for line in content.lines() {
-
if let Some(feature) = line
-
.trim()
-
.strip_prefix("#[cfg(feature = \"")
-
.and_then(|s| s.strip_suffix("\")]"))
-
{
-
existing_features.insert(feature.to_string());
-
}
-
}
-
}
-
}
-
-
let mut output = String::new();
-
writeln!(&mut output, "# Generated namespace features").unwrap();
-
-
// Convert namespace to feature name (matching module path sanitization)
-
let to_feature_name = |ns: &str| {
-
ns.split('.')
-
.map(|segment| {
-
// Apply same sanitization as module names
-
let mut result = segment.replace('-', "_");
-
// Prefix with underscore if starts with digit
-
if result.chars().next().map_or(false, |c| c.is_ascii_digit()) {
-
result.insert(0, '_');
-
}
-
result
-
})
-
.collect::<Vec<_>>()
-
.join("_")
-
};
-
-
// Collect all feature names (from corpus + existing lib.rs)
-
let mut all_feature_names = std::collections::HashSet::new();
-
for ns in &all_namespaces {
-
all_feature_names.insert(to_feature_name(ns));
-
}
-
all_feature_names.extend(existing_features);
-
-
// Sort for consistent output
-
let mut feature_names: Vec<_> = all_feature_names.iter().collect();
-
feature_names.sort();
-
-
// Map namespace to feature name for dependency lookup
-
let mut ns_to_feature: std::collections::HashMap<&str, String> =
-
std::collections::HashMap::new();
-
for ns in &all_namespaces {
-
ns_to_feature.insert(ns.as_str(), to_feature_name(ns));
-
}
-
-
for feature_name in feature_names {
-
// Find corresponding namespace for this feature (if any) to look up deps
-
let feature_deps: Vec<String> = all_namespaces
-
.iter()
-
.find(|ns| to_feature_name(ns) == *feature_name)
-
.and_then(|ns| deps.get(ns.as_str()))
-
.map(|ns_deps| {
-
let mut dep_features: Vec<_> = ns_deps
-
.iter()
-
.map(|d| format!("\"{}\"", to_feature_name(d)))
-
.collect();
-
dep_features.sort();
-
dep_features
-
})
-
.unwrap_or_default();
-
-
if !feature_deps.is_empty() {
-
writeln!(
-
&mut output,
-
"{} = [{}]",
-
feature_name,
-
feature_deps.join(", ")
-
)
-
.unwrap();
-
} else {
-
writeln!(&mut output, "{} = []", feature_name).unwrap();
-
}
-
}
-
-
output
-
}
-
}
-
-
/// Enum variant kind for IntoStatic generation
-
#[derive(Debug, Clone)]
-
#[allow(dead_code)]
-
enum EnumVariantKind {
-
Unit,
-
Tuple,
-
Struct(Vec<String>),
}
#[cfg(test)]
+114
crates/jacquard-lexicon/src/codegen/lifetime.rs
···
+
use super::CodeGenerator;
+
use crate::lexicon::{
+
LexArrayItem, LexObjectProperty, LexString, LexStringFormat, LexUserType,
+
};
+
+
impl<'c> CodeGenerator<'c> {
+
/// Check if a property type needs a lifetime parameter
+
pub(super) fn property_needs_lifetime(&self, prop: &LexObjectProperty<'static>) -> bool {
+
match prop {
+
LexObjectProperty::Boolean(_) | LexObjectProperty::Integer(_) => false,
+
LexObjectProperty::String(s) => self.string_needs_lifetime(s),
+
LexObjectProperty::Bytes(_) => false, // Bytes is owned
+
LexObjectProperty::CidLink(_)
+
| LexObjectProperty::Blob(_)
+
| LexObjectProperty::Unknown(_) => true,
+
LexObjectProperty::Array(array) => self.array_item_needs_lifetime(&array.items),
+
LexObjectProperty::Object(_) => true, // Nested objects have lifetimes
+
LexObjectProperty::Ref(ref_type) => {
+
// Check if the ref target actually needs a lifetime
+
self.ref_needs_lifetime(&ref_type.r#ref)
+
}
+
LexObjectProperty::Union(_) => true, // Unions generally have lifetimes
+
}
+
}
+
+
/// Check if an array item type needs a lifetime parameter
+
pub(super) fn array_item_needs_lifetime(&self, item: &LexArrayItem) -> bool {
+
match item {
+
LexArrayItem::Boolean(_) | LexArrayItem::Integer(_) => false,
+
LexArrayItem::String(s) => self.string_needs_lifetime(s),
+
LexArrayItem::Bytes(_) => false,
+
LexArrayItem::CidLink(_) | LexArrayItem::Blob(_) | LexArrayItem::Unknown(_) => true,
+
LexArrayItem::Object(_) => true, // Nested objects have lifetimes
+
LexArrayItem::Ref(ref_type) => self.ref_needs_lifetime(&ref_type.r#ref),
+
LexArrayItem::Union(_) => true,
+
}
+
}
+
+
/// Check if a string type needs a lifetime parameter
+
pub(super) fn string_needs_lifetime(&self, s: &LexString) -> bool {
+
match s.format {
+
Some(LexStringFormat::Datetime)
+
| Some(LexStringFormat::Language)
+
| Some(LexStringFormat::Tid) => false,
+
_ => true, // Most string types borrow
+
}
+
}
+
+
/// Check if a ref needs a lifetime parameter
+
pub(super) fn ref_needs_lifetime(&self, ref_str: &str) -> bool {
+
// Try to resolve the ref
+
if let Some((_doc, def)) = self.corpus.resolve_ref(ref_str) {
+
self.def_needs_lifetime(def)
+
} else {
+
// If we can't resolve it, assume it needs a lifetime (safe default)
+
true
+
}
+
}
+
+
/// Check if a lexicon def needs a lifetime parameter
+
pub(super) fn def_needs_lifetime(&self, def: &LexUserType<'static>) -> bool {
+
match def {
+
// Records and Objects always have lifetimes now since they get #[lexicon] attribute
+
LexUserType::Record(_) => true,
+
LexUserType::Object(_) => true,
+
LexUserType::Token(_) => false,
+
LexUserType::String(s) => {
+
// Check if it's a known values enum or a regular string
+
if s.known_values.is_some() {
+
// Known values enums have Other(CowStr<'a>) variant
+
true
+
} else {
+
self.string_needs_lifetime(s)
+
}
+
}
+
LexUserType::Integer(_) => false,
+
LexUserType::Boolean(_) => false,
+
LexUserType::Bytes(_) => false,
+
LexUserType::CidLink(_) | LexUserType::Blob(_) | LexUserType::Unknown(_) => true,
+
LexUserType::Array(array) => self.array_item_needs_lifetime(&array.items),
+
LexUserType::XrpcQuery(_)
+
| LexUserType::XrpcProcedure(_)
+
| LexUserType::XrpcSubscription(_) => {
+
// XRPC types generate multiple structs, not a single type we can reference
+
// Shouldn't be referenced directly
+
true
+
}
+
}
+
}
+
+
/// Check if xrpc params need a lifetime parameter
+
pub(super) fn params_need_lifetime(&self, params: &crate::lexicon::LexXrpcParameters<'static>) -> bool {
+
params.properties.values().any(|prop| {
+
use crate::lexicon::LexXrpcParametersProperty;
+
match prop {
+
LexXrpcParametersProperty::Boolean(_) | LexXrpcParametersProperty::Integer(_) => {
+
false
+
}
+
LexXrpcParametersProperty::String(s) => self.string_needs_lifetime(s),
+
LexXrpcParametersProperty::Unknown(_) => true,
+
LexXrpcParametersProperty::Array(arr) => {
+
use crate::lexicon::LexPrimitiveArrayItem;
+
match &arr.items {
+
LexPrimitiveArrayItem::Boolean(_) | LexPrimitiveArrayItem::Integer(_) => {
+
false
+
}
+
LexPrimitiveArrayItem::String(s) => self.string_needs_lifetime(s),
+
LexPrimitiveArrayItem::Unknown(_) => true,
+
}
+
}
+
}
+
})
+
}
+
}
+132
crates/jacquard-lexicon/src/codegen/names.rs
···
+
use super::utils::sanitize_name;
+
use super::CodeGenerator;
+
use heck::{ToPascalCase, ToSnakeCase};
+
+
impl<'c> CodeGenerator<'c> {
+
/// Check if a single-variant union is self-referential
+
pub(super) fn is_self_referential_union(
+
&self,
+
nsid: &str,
+
parent_type_name: &str,
+
union: &crate::lexicon::LexRefUnion,
+
) -> bool {
+
if union.refs.len() != 1 {
+
return false;
+
}
+
+
let ref_str = if union.refs[0].starts_with('#') {
+
format!("{}{}", nsid, union.refs[0])
+
} else {
+
union.refs[0].to_string()
+
};
+
+
let (ref_nsid, ref_def) = if let Some((nsid_part, fragment)) = ref_str.split_once('#') {
+
(nsid_part, fragment)
+
} else {
+
(ref_str.as_str(), "main")
+
};
+
+
let ref_type_name = self.def_to_type_name(ref_nsid, ref_def);
+
ref_type_name == parent_type_name
+
}
+
+
/// Helper to generate field-based type name with collision detection
+
pub(super) fn generate_field_type_name(
+
&self,
+
nsid: &str,
+
parent_type_name: &str,
+
field_name: &str,
+
suffix: &str, // "" for union/object, "Item" for array unions
+
) -> String {
+
let base_name = format!("{}{}{}", parent_type_name, field_name.to_pascal_case(), suffix);
+
+
// Check for collisions with lexicon defs
+
if let Some(doc) = self.corpus.get(nsid) {
+
let def_names: std::collections::HashSet<String> = doc
+
.defs
+
.keys()
+
.map(|name| self.def_to_type_name(nsid, name.as_ref()))
+
.collect();
+
+
if def_names.contains(&base_name) {
+
// Use "Union" suffix for union types, "Record" for objects
+
let disambiguator = if suffix.is_empty() && !parent_type_name.is_empty() {
+
"Union"
+
} else {
+
"Record"
+
};
+
return format!("{}{}{}{}", parent_type_name, disambiguator, field_name.to_pascal_case(), suffix);
+
}
+
}
+
+
base_name
+
}
+
+
/// Convert lexicon def name to Rust type name
+
pub(super) fn def_to_type_name(&self, nsid: &str, def_name: &str) -> String {
+
if def_name == "main" {
+
// Use last segment of NSID
+
let base_name = nsid.split('.').last().unwrap().to_pascal_case();
+
+
// Check if any other def would collide with this name
+
if let Some(doc) = self.corpus.get(nsid) {
+
let has_collision = doc.defs.keys().any(|other_def| {
+
let other_def_str: &str = other_def.as_ref();
+
other_def_str != "main" && other_def_str.to_pascal_case() == base_name
+
});
+
+
if has_collision {
+
return format!("{}Record", base_name);
+
}
+
}
+
+
base_name
+
} else {
+
def_name.to_pascal_case()
+
}
+
}
+
+
/// Convert NSID to file path relative to output directory
+
///
+
/// - `app.bsky.feed.post` → `app_bsky/feed/post.rs`
+
/// - `com.atproto.label.defs` → `com_atproto/label.rs` (defs go in parent)
+
pub(super) fn nsid_to_file_path(&self, nsid: &str) -> std::path::PathBuf {
+
let parts: Vec<&str> = nsid.split('.').collect();
+
+
if parts.len() < 2 {
+
// Shouldn't happen with valid NSIDs, but handle gracefully
+
return format!("{}.rs", sanitize_name(parts[0])).into();
+
}
+
+
let last = parts.last().unwrap();
+
+
if *last == "defs" && parts.len() >= 3 {
+
// defs go in parent module: com.atproto.label.defs → com_atproto/label.rs
+
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
+
if parts.len() == 3 {
+
// com.atproto.defs → com_atproto.rs
+
format!("{}.rs", first_two).into()
+
} else {
+
// com.atproto.label.defs → com_atproto/label.rs
+
let middle: Vec<&str> = parts[2..parts.len() - 1].iter().copied().collect();
+
let mut path = std::path::PathBuf::from(first_two);
+
for segment in &middle[..middle.len() - 1] {
+
path.push(sanitize_name(segment));
+
}
+
path.push(format!("{}.rs", sanitize_name(middle.last().unwrap())));
+
path
+
}
+
} else {
+
// Regular path: app.bsky.feed.post → app_bsky/feed/post.rs
+
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
+
let mut path = std::path::PathBuf::from(first_two);
+
+
for segment in &parts[2..parts.len() - 1] {
+
path.push(sanitize_name(segment));
+
}
+
+
path.push(format!("{}.rs", sanitize_name(&last.to_snake_case())));
+
path
+
}
+
}
+
}
+329
crates/jacquard-lexicon/src/codegen/output.rs
···
+
use crate::error::{CodegenError, Result};
+
use proc_macro2::TokenStream;
+
use quote::quote;
+
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
+
+
use super::utils::{make_ident, sanitize_name};
+
use super::CodeGenerator;
+
+
impl<'c> CodeGenerator<'c> {
+
/// Generate all code for the corpus, organized by file
+
/// Returns a map of file paths to (tokens, optional NSID)
+
pub fn generate_all(
+
&self,
+
) -> Result<BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)>> {
+
let mut file_contents: BTreeMap<std::path::PathBuf, Vec<TokenStream>> = BTreeMap::new();
+
let mut file_nsids: BTreeMap<std::path::PathBuf, String> = BTreeMap::new();
+
+
// Generate code for all lexicons
+
for (nsid, doc) in self.corpus.iter() {
+
let file_path = self.nsid_to_file_path(nsid.as_ref());
+
+
// Track which NSID this file is for
+
file_nsids.insert(file_path.clone(), nsid.to_string());
+
+
for (def_name, def) in &doc.defs {
+
let tokens = self.generate_def(nsid.as_ref(), def_name.as_ref(), def)?;
+
file_contents
+
.entry(file_path.clone())
+
.or_default()
+
.push(tokens);
+
}
+
}
+
+
// Combine all tokens for each file
+
let mut result = BTreeMap::new();
+
for (path, tokens_vec) in file_contents {
+
let nsid = file_nsids.get(&path).cloned();
+
result.insert(path, (quote! { #(#tokens_vec)* }, nsid));
+
}
+
+
Ok(result)
+
}
+
+
/// Generate parent module files with pub mod declarations
+
pub fn generate_module_tree(
+
&self,
+
file_map: &BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)>,
+
defs_only: &BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)>,
+
) -> BTreeMap<std::path::PathBuf, (TokenStream, Option<String>)> {
+
// Track what modules each directory needs to declare
+
// Key: directory path, Value: set of module names (file stems)
+
let mut dir_modules: BTreeMap<std::path::PathBuf, BTreeSet<String>> = BTreeMap::new();
+
+
// Collect all parent directories that have files
+
let mut all_dirs: BTreeSet<std::path::PathBuf> = BTreeSet::new();
+
for path in file_map.keys() {
+
if let Some(parent_dir) = path.parent() {
+
all_dirs.insert(parent_dir.to_path_buf());
+
}
+
}
+
+
for path in file_map.keys() {
+
if let Some(parent_dir) = path.parent() {
+
if let Some(file_stem) = path.file_stem().and_then(|s| s.to_str()) {
+
// Skip mod.rs and lib.rs - they're module files, not modules to declare
+
if file_stem == "mod" || file_stem == "lib" {
+
continue;
+
}
+
+
// Always add the module declaration to parent
+
dir_modules
+
.entry(parent_dir.to_path_buf())
+
.or_default()
+
.insert(file_stem.to_string());
+
}
+
}
+
}
+
+
// Generate module files
+
let mut result = BTreeMap::new();
+
+
for (dir, module_names) in dir_modules {
+
let mod_file_path = if dir.components().count() == 0 {
+
// Root directory -> lib.rs for library crates
+
std::path::PathBuf::from("lib.rs")
+
} else {
+
// Subdirectory: app_bsky/feed -> app_bsky/feed.rs (Rust 2018 style)
+
let dir_name = dir.file_name().and_then(|s| s.to_str()).unwrap_or("mod");
+
let sanitized_dir_name = sanitize_name(dir_name);
+
let mut path = dir
+
.parent()
+
.unwrap_or_else(|| std::path::Path::new(""))
+
.to_path_buf();
+
path.push(format!("{}.rs", sanitized_dir_name));
+
path
+
};
+
+
let is_root = dir.components().count() == 0;
+
let mods: Vec<_> = module_names
+
.iter()
+
.map(|name| {
+
let ident = make_ident(name);
+
if is_root {
+
// Top-level modules get feature gates
+
quote! {
+
#[cfg(feature = #name)]
+
pub mod #ident;
+
}
+
} else {
+
quote! { pub mod #ident; }
+
}
+
})
+
.collect();
+
+
// If this file already exists in defs_only (e.g., from defs), merge the content
+
let module_tokens = quote! { #(#mods)* };
+
if let Some((existing_tokens, nsid)) = defs_only.get(&mod_file_path) {
+
// Put module declarations FIRST, then existing defs content
+
result.insert(
+
mod_file_path,
+
(quote! { #module_tokens #existing_tokens }, nsid.clone()),
+
);
+
} else {
+
result.insert(mod_file_path, (module_tokens, None));
+
}
+
}
+
+
result
+
}
+
+
/// Write all generated code to disk
+
pub fn write_to_disk(&self, output_dir: &std::path::Path) -> Result<()> {
+
// Generate all code (defs only)
+
let defs_files = self.generate_all()?;
+
let mut all_files = defs_files.clone();
+
+
// Generate module tree iteratively until no new files appear
+
loop {
+
let module_map = self.generate_module_tree(&all_files, &defs_files);
+
let old_count = all_files.len();
+
+
// Merge new module files
+
for (path, tokens) in module_map {
+
all_files.insert(path, tokens);
+
}
+
+
if all_files.len() == old_count {
+
// No new files added
+
break;
+
}
+
}
+
+
// Write to disk
+
for (path, (tokens, nsid)) in all_files {
+
let full_path = output_dir.join(&path);
+
+
// Create parent directories
+
if let Some(parent) = full_path.parent() {
+
std::fs::create_dir_all(parent).map_err(|e| CodegenError::Other {
+
message: format!("Failed to create directory {:?}: {}", parent, e),
+
source: None,
+
})?;
+
}
+
+
// Format code
+
let file: syn::File = syn::parse2(tokens.clone()).map_err(|e| CodegenError::Other {
+
message: format!(
+
"Failed to parse tokens for {:?}: {}\nTokens: {}",
+
path, e, tokens
+
),
+
source: None,
+
})?;
+
let mut formatted = prettyplease::unparse(&file);
+
+
// Add blank lines between top-level items for better readability
+
let lines: Vec<&str> = formatted.lines().collect();
+
let mut result_lines = Vec::new();
+
+
for (i, line) in lines.iter().enumerate() {
+
result_lines.push(*line);
+
+
// Add blank line after closing braces that are at column 0 (top-level items)
+
if *line == "}" && i + 1 < lines.len() && !lines[i + 1].is_empty() {
+
result_lines.push("");
+
}
+
+
// Add blank line after last pub mod declaration before structs/enums
+
if line.starts_with("pub mod ") && i + 1 < lines.len() {
+
let next_line = lines[i + 1];
+
if !next_line.starts_with("pub mod ") && !next_line.is_empty() {
+
result_lines.push("");
+
}
+
}
+
}
+
+
formatted = result_lines.join("\n");
+
+
// Add header comment
+
let header = if let Some(nsid) = nsid {
+
format!(
+
"// @generated by jacquard-lexicon. DO NOT EDIT.\n//\n// Lexicon: {}\n//\n// This file was automatically generated from Lexicon schemas.\n// Any manual changes will be overwritten on the next regeneration.\n\n",
+
nsid
+
)
+
} else {
+
"// @generated by jacquard-lexicon. DO NOT EDIT.\n//\n// This file was automatically generated from Lexicon schemas.\n// Any manual changes will be overwritten on the next regeneration.\n\n".to_string()
+
};
+
formatted = format!("{}{}", header, formatted);
+
+
// Write file
+
std::fs::write(&full_path, formatted).map_err(|e| CodegenError::Other {
+
message: format!("Failed to write file {:?}: {}", full_path, e),
+
source: None,
+
})?;
+
}
+
+
Ok(())
+
}
+
+
/// Get namespace dependencies collected during code generation
+
pub fn get_namespace_dependencies(
+
&self,
+
) -> HashMap<String, HashSet<String>> {
+
self.namespace_deps.borrow().clone()
+
}
+
+
/// Generate Cargo.toml features section from namespace dependencies
+
pub fn generate_cargo_features(&self, lib_rs_path: Option<&std::path::Path>) -> String {
+
use std::fmt::Write;
+
+
let deps = self.namespace_deps.borrow();
+
let mut all_namespaces: HashSet<String> =
+
HashSet::new();
+
+
// Collect all namespaces from the corpus (first two segments of each NSID)
+
for (nsid, _doc) in self.corpus.iter() {
+
let parts: Vec<_> = nsid.as_str().splitn(3, '.').collect();
+
let namespace = if parts.len() >= 2 {
+
format!("{}.{}", parts[0], parts[1])
+
} else {
+
nsid.to_string()
+
};
+
all_namespaces.insert(namespace);
+
}
+
+
// Also collect existing feature names from lib.rs
+
let mut existing_features = HashSet::new();
+
if let Some(lib_rs) = lib_rs_path {
+
if let Ok(content) = std::fs::read_to_string(lib_rs) {
+
for line in content.lines() {
+
if let Some(feature) = line
+
.trim()
+
.strip_prefix("#[cfg(feature = \"")
+
.and_then(|s| s.strip_suffix("\")]"))
+
{
+
existing_features.insert(feature.to_string());
+
}
+
}
+
}
+
}
+
+
let mut output = String::new();
+
writeln!(&mut output, "# Generated namespace features").unwrap();
+
+
// Convert namespace to feature name (matching module path sanitization)
+
let to_feature_name = |ns: &str| {
+
ns.split('.')
+
.map(|segment| {
+
// Apply same sanitization as module names
+
let mut result = segment.replace('-', "_");
+
// Prefix with underscore if starts with digit
+
if result.chars().next().map_or(false, |c| c.is_ascii_digit()) {
+
result.insert(0, '_');
+
}
+
result
+
})
+
.collect::<Vec<_>>()
+
.join("_")
+
};
+
+
// Collect all feature names (from corpus + existing lib.rs)
+
let mut all_feature_names = HashSet::new();
+
for ns in &all_namespaces {
+
all_feature_names.insert(to_feature_name(ns));
+
}
+
all_feature_names.extend(existing_features);
+
+
// Sort for consistent output
+
let mut feature_names: Vec<_> = all_feature_names.iter().collect();
+
feature_names.sort();
+
+
// Map namespace to feature name for dependency lookup
+
let mut ns_to_feature: HashMap<&str, String> =
+
HashMap::new();
+
for ns in &all_namespaces {
+
ns_to_feature.insert(ns.as_str(), to_feature_name(ns));
+
}
+
+
for feature_name in feature_names {
+
// Find corresponding namespace for this feature (if any) to look up deps
+
let feature_deps: Vec<String> = all_namespaces
+
.iter()
+
.find(|ns| to_feature_name(ns) == *feature_name)
+
.and_then(|ns| deps.get(ns.as_str()))
+
.map(|ns_deps| {
+
let mut dep_features: Vec<_> = ns_deps
+
.iter()
+
.map(|d| format!("\"{}\"", to_feature_name(d)))
+
.collect();
+
dep_features.sort();
+
dep_features
+
})
+
.unwrap_or_default();
+
+
if !feature_deps.is_empty() {
+
writeln!(
+
&mut output,
+
"{} = [{}]",
+
feature_name,
+
feature_deps.join(", ")
+
)
+
.unwrap();
+
} else {
+
writeln!(&mut output, "{} = []", feature_name).unwrap();
+
}
+
}
+
+
output
+
}
+
}
+759
crates/jacquard-lexicon/src/codegen/structs.rs
···
+
use crate::error::Result;
+
use crate::lexicon::{
+
LexArrayItem, LexInteger, LexObject, LexObjectProperty, LexRecord, LexString,
+
};
+
use heck::{ToPascalCase, ToSnakeCase};
+
use proc_macro2::TokenStream;
+
use quote::quote;
+
+
use super::utils::{make_ident, value_to_variant_name};
+
use super::CodeGenerator;
+
+
/// Enum variant kind for IntoStatic generation
+
#[derive(Debug, Clone)]
+
#[allow(dead_code)]
+
pub(super) enum EnumVariantKind {
+
Unit,
+
Tuple,
+
Struct(Vec<String>),
+
}
+
+
impl<'c> CodeGenerator<'c> {
+
pub(super) fn generate_record(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
record: &LexRecord<'static>,
+
) -> Result<TokenStream> {
+
match &record.record {
+
crate::lexicon::LexRecordRecord::Object(obj) => {
+
let type_name = self.def_to_type_name(nsid, def_name);
+
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
+
+
// Generate main struct fields
+
let fields = self.generate_object_fields(nsid, &type_name, obj, false)?;
+
let doc = self.generate_doc_comment(record.description.as_ref());
+
+
// Records always get a lifetime since they have the #[lexicon] attribute
+
// which adds extra_data: BTreeMap<..., Data<'a>>
+
let struct_def = quote! {
+
#doc
+
#[jacquard_derive::lexicon]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(rename_all = "camelCase")]
+
pub struct #ident<'a> {
+
#fields
+
}
+
};
+
+
// Generate union types and nested object types for this record
+
let mut unions = Vec::new();
+
for (field_name, field_type) in &obj.properties {
+
match field_type {
+
LexObjectProperty::Union(union) => {
+
// Skip empty, single-variant unions unless they're self-referential
+
if !union.refs.is_empty() && (union.refs.len() > 1 || self.is_self_referential_union(nsid, &type_name, union)) {
+
let union_name = self.generate_field_type_name(nsid, &type_name, field_name, "");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def =
+
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
LexObjectProperty::Object(nested_obj) => {
+
let object_name = self.generate_field_type_name(nsid, &type_name, field_name, "");
+
let obj_def = self.generate_object(nsid, &object_name, nested_obj)?;
+
unions.push(obj_def);
+
}
+
LexObjectProperty::Array(array) => {
+
if let LexArrayItem::Union(union) = &array.items {
+
// Skip single-variant array unions
+
if union.refs.len() > 1 {
+
let union_name = self.generate_field_type_name(nsid, &type_name, field_name, "Item");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def = self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
}
+
_ => {}
+
}
+
}
+
+
// Generate Collection trait impl
+
let collection_impl = quote! {
+
impl jacquard_common::types::collection::Collection for #ident<'_> {
+
const NSID: &'static str = #nsid;
+
}
+
};
+
+
Ok(quote! {
+
#struct_def
+
#(#unions)*
+
#collection_impl
+
})
+
}
+
}
+
}
+
+
/// Generate an object type
+
pub(super) fn generate_object(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
obj: &LexObject<'static>,
+
) -> Result<TokenStream> {
+
let type_name = self.def_to_type_name(nsid, def_name);
+
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
+
+
let fields = self.generate_object_fields(nsid, &type_name, obj, false)?;
+
let doc = self.generate_doc_comment(obj.description.as_ref());
+
+
// Objects always get a lifetime since they have the #[lexicon] attribute
+
// which adds extra_data: BTreeMap<..., Data<'a>>
+
let struct_def = quote! {
+
#doc
+
#[jacquard_derive::lexicon]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(rename_all = "camelCase")]
+
pub struct #ident<'a> {
+
#fields
+
}
+
};
+
+
// Generate union types and nested object types for this object
+
let mut unions = Vec::new();
+
for (field_name, field_type) in &obj.properties {
+
match field_type {
+
LexObjectProperty::Union(union) => {
+
// Skip empty, single-variant unions unless they're self-referential
+
if !union.refs.is_empty() && (union.refs.len() > 1 || self.is_self_referential_union(nsid, &type_name, union)) {
+
let union_name = self.generate_field_type_name(nsid, &type_name, field_name, "");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def =
+
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
LexObjectProperty::Object(nested_obj) => {
+
let object_name = self.generate_field_type_name(nsid, &type_name, field_name, "");
+
let obj_def = self.generate_object(nsid, &object_name, nested_obj)?;
+
unions.push(obj_def);
+
}
+
LexObjectProperty::Array(array) => {
+
if let LexArrayItem::Union(union) = &array.items {
+
// Skip single-variant array unions
+
if union.refs.len() > 1 {
+
let union_name = self.generate_field_type_name(nsid, &type_name, field_name, "Item");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def = self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
}
+
_ => {}
+
}
+
}
+
+
Ok(quote! {
+
#struct_def
+
#(#unions)*
+
})
+
}
+
+
/// Generate fields for an object
+
pub(super) fn generate_object_fields(
+
&self,
+
nsid: &str,
+
parent_type_name: &str,
+
obj: &LexObject<'static>,
+
is_builder: bool,
+
) -> Result<TokenStream> {
+
let required = obj.required.as_ref().map(|r| r.as_slice()).unwrap_or(&[]);
+
+
let mut fields = Vec::new();
+
for (field_name, field_type) in &obj.properties {
+
let is_required = required.contains(field_name);
+
let field_tokens = self.generate_field(
+
nsid,
+
parent_type_name,
+
field_name,
+
field_type,
+
is_required,
+
is_builder,
+
)?;
+
fields.push(field_tokens);
+
}
+
+
Ok(quote! { #(#fields)* })
+
}
+
+
/// Generate a single field
+
pub(super) fn generate_field(
+
&self,
+
nsid: &str,
+
parent_type_name: &str,
+
field_name: &str,
+
field_type: &LexObjectProperty<'static>,
+
is_required: bool,
+
is_builder: bool,
+
) -> Result<TokenStream> {
+
if field_name.is_empty() {
+
eprintln!(
+
"Warning: Empty field name in lexicon '{}' type '{}', using 'unknown' as fallback",
+
nsid, parent_type_name
+
);
+
}
+
let field_ident = make_ident(&field_name.to_snake_case());
+
+
let rust_type =
+
self.property_to_rust_type(nsid, parent_type_name, field_name, field_type)?;
+
let needs_lifetime = self.property_needs_lifetime(field_type);
+
+
// Check if this is a CowStr field for builder(into) attribute
+
let is_cowstr = matches!(field_type, LexObjectProperty::String(s) if s.format.is_none());
+
+
let rust_type = if is_required {
+
rust_type
+
} else {
+
quote! { std::option::Option<#rust_type> }
+
};
+
+
// Extract description from field type
+
let description = match field_type {
+
LexObjectProperty::Ref(r) => r.description.as_ref(),
+
LexObjectProperty::Union(u) => u.description.as_ref(),
+
LexObjectProperty::Bytes(b) => b.description.as_ref(),
+
LexObjectProperty::CidLink(c) => c.description.as_ref(),
+
LexObjectProperty::Array(a) => a.description.as_ref(),
+
LexObjectProperty::Blob(b) => b.description.as_ref(),
+
LexObjectProperty::Object(o) => o.description.as_ref(),
+
LexObjectProperty::Boolean(b) => b.description.as_ref(),
+
LexObjectProperty::Integer(i) => i.description.as_ref(),
+
LexObjectProperty::String(s) => s.description.as_ref(),
+
LexObjectProperty::Unknown(u) => u.description.as_ref(),
+
};
+
let doc = self.generate_doc_comment(description);
+
+
let mut attrs = Vec::new();
+
+
if !is_required {
+
attrs.push(quote! { #[serde(skip_serializing_if = "std::option::Option::is_none")] });
+
}
+
+
// Add serde(borrow) to all fields with lifetimes
+
if needs_lifetime {
+
attrs.push(quote! { #[serde(borrow)] });
+
}
+
+
// Add builder(into) for CowStr fields to allow String, &str, etc., but only for builder structs
+
if is_builder && is_cowstr {
+
attrs.push(quote! { #[builder(into)] });
+
}
+
+
Ok(quote! {
+
#doc
+
#(#attrs)*
+
pub #field_ident: #rust_type,
+
})
+
}
+
+
/// Generate a union enum for refs
+
pub fn generate_union(
+
&self,
+
current_nsid: &str,
+
union_name: &str,
+
refs: &[jacquard_common::CowStr<'static>],
+
description: Option<&str>,
+
closed: Option<bool>,
+
) -> Result<TokenStream> {
+
let enum_ident = syn::Ident::new(union_name, proc_macro2::Span::call_site());
+
+
// Extract namespace prefix from current NSID (first two segments: "sh.weaver" from "sh.weaver.embed.recordWithMedia")
+
let parts: Vec<_> = current_nsid.splitn(3, '.').collect();
+
let current_namespace = if parts.len() >= 2 {
+
format!("{}.{}", parts[0], parts[1])
+
} else {
+
current_nsid.to_string()
+
};
+
+
// First pass: collect all variant names and detect collisions
+
#[derive(Debug)]
+
struct VariantInfo {
+
ref_str: String,
+
ref_nsid: String,
+
simple_name: String,
+
is_current_namespace: bool,
+
}
+
+
let mut variant_infos = Vec::new();
+
for ref_str in refs {
+
// Normalize local refs (starting with #) by prepending current NSID
+
let normalized_ref = if ref_str.starts_with('#') {
+
format!("{}{}", current_nsid, ref_str)
+
} else {
+
ref_str.to_string()
+
};
+
+
// Parse ref to get NSID and def name
+
let (ref_nsid_str, ref_def) = if let Some((nsid, fragment)) = normalized_ref.split_once('#') {
+
(nsid, fragment)
+
} else {
+
(normalized_ref.as_str(), "main")
+
};
+
+
// Skip unknown refs - they'll be handled by Unknown variant
+
if !self.corpus.ref_exists(&normalized_ref) {
+
continue;
+
}
+
+
// Check if ref is in current namespace and if it's the same module
+
let is_current_namespace = ref_nsid_str.starts_with(&current_namespace);
+
let is_same_module = ref_nsid_str == current_nsid;
+
+
// Generate simple variant name (without namespace prefix)
+
let last_segment = ref_nsid_str.split('.').last().unwrap();
+
let simple_name = if ref_def == "main" {
+
// For main, use the last NSID segment
+
// e.g. app.bsky.embed.images#main -> Images
+
last_segment.to_pascal_case()
+
} else if last_segment == "defs" {
+
// For defs modules, just use the fragment name without "Defs" prefix
+
// e.g. app.bsky.embed.defs#images -> Images (not DefsImages)
+
ref_def.to_pascal_case()
+
} else if is_same_module {
+
// For same-module refs, just use the fragment name to avoid redundancy
+
// e.g. sh.weaver.embed.records#viewRecord in records.rs -> ViewRecord (not RecordsViewRecord)
+
ref_def.to_pascal_case()
+
} else {
+
// For other fragments, include the last NSID segment to avoid collisions
+
// e.g. app.bsky.embed.images#view -> ImagesView
+
// app.bsky.embed.video#view -> VideoView
+
format!("{}{}", last_segment.to_pascal_case(), ref_def.to_pascal_case())
+
};
+
+
variant_infos.push(VariantInfo {
+
ref_str: normalized_ref.clone(),
+
ref_nsid: ref_nsid_str.to_string(),
+
simple_name,
+
is_current_namespace,
+
});
+
}
+
+
// Second pass: detect collisions and disambiguate
+
use std::collections::HashMap;
+
let mut name_counts: HashMap<String, usize> = HashMap::new();
+
for info in &variant_infos {
+
*name_counts.entry(info.simple_name.clone()).or_insert(0) += 1;
+
}
+
+
let mut variants = Vec::new();
+
for info in variant_infos {
+
let has_collision = name_counts.get(&info.simple_name).copied().unwrap_or(0) > 1;
+
+
// Track namespace dependency for foreign refs
+
if !info.is_current_namespace {
+
let parts: Vec<_> = info.ref_nsid.splitn(3, '.').collect();
+
let foreign_namespace = if parts.len() >= 2 {
+
format!("{}.{}", parts[0], parts[1])
+
} else {
+
info.ref_nsid.to_string()
+
};
+
self.namespace_deps
+
.borrow_mut()
+
.entry(current_namespace.clone())
+
.or_default()
+
.insert(foreign_namespace);
+
}
+
+
// Disambiguate: add second NSID segment prefix only to foreign refs when there's a collision
+
let variant_name = if has_collision && !info.is_current_namespace {
+
// Get second segment (namespace identifier: "bsky" from "app.bsky.embed.images")
+
let segments: Vec<&str> = info.ref_nsid.split('.').collect();
+
let prefix = if segments.len() >= 2 {
+
segments[1].to_pascal_case()
+
} else {
+
// Fallback: use first segment if only one exists
+
segments[0].to_pascal_case()
+
};
+
format!("{}{}", prefix, info.simple_name)
+
} else {
+
info.simple_name.clone()
+
};
+
+
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
+
+
// Get the Rust type for this ref
+
let rust_type = self.ref_to_rust_type(&info.ref_str)?;
+
+
// Add serde rename for the full NSID
+
let ref_str_literal = &info.ref_str;
+
variants.push(quote! {
+
#[serde(rename = #ref_str_literal)]
+
#variant_ident(Box<#rust_type>)
+
});
+
}
+
+
let doc = description
+
.map(|d| quote! { #[doc = #d] })
+
.unwrap_or_else(|| quote! {});
+
+
// Only add open_union if not closed
+
let is_open = closed != Some(true);
+
+
if is_open {
+
Ok(quote! {
+
#doc
+
#[jacquard_derive::open_union]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum #enum_ident<'a> {
+
#(#variants,)*
+
}
+
})
+
} else {
+
Ok(quote! {
+
#doc
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum #enum_ident<'a> {
+
#(#variants,)*
+
}
+
})
+
}
+
}
+
+
/// Generate enum for string with known values
+
pub(super) fn generate_known_values_enum(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
string: &LexString<'static>,
+
) -> Result<TokenStream> {
+
let type_name = self.def_to_type_name(nsid, def_name);
+
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
+
+
let known_values = string.known_values.as_ref().unwrap();
+
let mut variants = Vec::new();
+
let mut from_str_arms = Vec::new();
+
let mut as_str_arms = Vec::new();
+
+
for value in known_values {
+
// Convert value to valid Rust identifier
+
let value_str = value.as_ref();
+
let variant_name = value_to_variant_name(value_str);
+
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
+
+
variants.push(quote! {
+
#variant_ident
+
});
+
+
from_str_arms.push(quote! {
+
#value_str => Self::#variant_ident
+
});
+
+
as_str_arms.push(quote! {
+
Self::#variant_ident => #value_str
+
});
+
}
+
+
let doc = self.generate_doc_comment(string.description.as_ref());
+
+
// Generate IntoStatic impl
+
let variant_info: Vec<(String, EnumVariantKind)> = known_values
+
.iter()
+
.map(|value| {
+
let variant_name = value_to_variant_name(value.as_ref());
+
(variant_name, EnumVariantKind::Unit)
+
})
+
.chain(std::iter::once((
+
"Other".to_string(),
+
EnumVariantKind::Tuple,
+
)))
+
.collect();
+
let into_static_impl =
+
self.generate_into_static_for_enum(&type_name, &variant_info, true, false);
+
+
Ok(quote! {
+
#doc
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+
pub enum #ident<'a> {
+
#(#variants,)*
+
Other(jacquard_common::CowStr<'a>),
+
}
+
+
impl<'a> #ident<'a> {
+
pub fn as_str(&self) -> &str {
+
match self {
+
#(#as_str_arms,)*
+
Self::Other(s) => s.as_ref(),
+
}
+
}
+
}
+
+
impl<'a> From<&'a str> for #ident<'a> {
+
fn from(s: &'a str) -> Self {
+
match s {
+
#(#from_str_arms,)*
+
_ => Self::Other(jacquard_common::CowStr::from(s)),
+
}
+
}
+
}
+
+
impl<'a> From<String> for #ident<'a> {
+
fn from(s: String) -> Self {
+
match s.as_str() {
+
#(#from_str_arms,)*
+
_ => Self::Other(jacquard_common::CowStr::from(s)),
+
}
+
}
+
}
+
+
impl<'a> AsRef<str> for #ident<'a> {
+
fn as_ref(&self) -> &str {
+
self.as_str()
+
}
+
}
+
+
impl<'a> serde::Serialize for #ident<'a> {
+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+
where
+
S: serde::Serializer,
+
{
+
serializer.serialize_str(self.as_str())
+
}
+
}
+
+
impl<'de, 'a> serde::Deserialize<'de> for #ident<'a>
+
where
+
'de: 'a,
+
{
+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+
where
+
D: serde::Deserializer<'de>,
+
{
+
let s = <&'de str>::deserialize(deserializer)?;
+
Ok(Self::from(s))
+
}
+
}
+
+
#into_static_impl
+
})
+
}
+
+
/// Generate enum for integer with enum values
+
pub(super) fn generate_integer_enum(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
integer: &LexInteger<'static>,
+
) -> Result<TokenStream> {
+
let type_name = self.def_to_type_name(nsid, def_name);
+
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
+
+
let enum_values = integer.r#enum.as_ref().unwrap();
+
let mut variants = Vec::new();
+
let mut from_i64_arms = Vec::new();
+
let mut to_i64_arms = Vec::new();
+
+
for value in enum_values {
+
let variant_name = format!("Value{}", value.abs());
+
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
+
+
variants.push(quote! {
+
#[serde(rename = #value)]
+
#variant_ident
+
});
+
+
from_i64_arms.push(quote! {
+
#value => Self::#variant_ident
+
});
+
+
to_i64_arms.push(quote! {
+
Self::#variant_ident => #value
+
});
+
}
+
+
let doc = self.generate_doc_comment(integer.description.as_ref());
+
+
Ok(quote! {
+
#doc
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+
pub enum #ident {
+
#(#variants,)*
+
#[serde(untagged)]
+
Other(i64),
+
}
+
+
impl #ident {
+
pub fn as_i64(&self) -> i64 {
+
match self {
+
#(#to_i64_arms,)*
+
Self::Other(n) => *n,
+
}
+
}
+
}
+
+
impl From<i64> for #ident {
+
fn from(n: i64) -> Self {
+
match n {
+
#(#from_i64_arms,)*
+
_ => Self::Other(n),
+
}
+
}
+
}
+
+
impl serde::Serialize for #ident {
+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+
where
+
S: serde::Serializer,
+
{
+
serializer.serialize_i64(self.as_i64())
+
}
+
}
+
+
impl<'de> serde::Deserialize<'de> for #ident {
+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+
where
+
D: serde::Deserializer<'de>,
+
{
+
let n = i64::deserialize(deserializer)?;
+
Ok(Self::from(n))
+
}
+
}
+
})
+
}
+
+
/// Generate IntoStatic impl for a struct
+
#[allow(dead_code)]
+
pub(super) fn generate_into_static_for_struct(
+
&self,
+
type_name: &str,
+
field_names: &[&str],
+
has_lifetime: bool,
+
has_extra_data: bool,
+
) -> TokenStream {
+
let ident = syn::Ident::new(type_name, proc_macro2::Span::call_site());
+
+
let field_idents: Vec<_> = field_names
+
.iter()
+
.map(|name| make_ident(&name.to_snake_case()))
+
.collect();
+
+
if has_lifetime {
+
let field_conversions: Vec<_> = field_idents
+
.iter()
+
.map(|field| quote! { #field: self.#field.into_static() })
+
.collect();
+
+
let extra_data_conversion = if has_extra_data {
+
quote! { extra_data: self.extra_data.into_static(), }
+
} else {
+
quote! {}
+
};
+
+
quote! {
+
impl jacquard_common::IntoStatic for #ident<'_> {
+
type Output = #ident<'static>;
+
+
fn into_static(self) -> Self::Output {
+
#ident {
+
#(#field_conversions,)*
+
#extra_data_conversion
+
}
+
}
+
}
+
}
+
} else {
+
quote! {
+
impl jacquard_common::IntoStatic for #ident {
+
type Output = #ident;
+
+
fn into_static(self) -> Self::Output {
+
self
+
}
+
}
+
}
+
}
+
}
+
+
/// Generate IntoStatic impl for an enum
+
pub(super) fn generate_into_static_for_enum(
+
&self,
+
type_name: &str,
+
variant_info: &[(String, EnumVariantKind)],
+
has_lifetime: bool,
+
is_open: bool,
+
) -> TokenStream {
+
let ident = syn::Ident::new(type_name, proc_macro2::Span::call_site());
+
+
if has_lifetime {
+
let variant_conversions: Vec<_> = variant_info
+
.iter()
+
.map(|(variant_name, kind)| {
+
let variant_ident = syn::Ident::new(variant_name, proc_macro2::Span::call_site());
+
match kind {
+
EnumVariantKind::Unit => {
+
quote! {
+
#ident::#variant_ident => #ident::#variant_ident
+
}
+
}
+
EnumVariantKind::Tuple => {
+
quote! {
+
#ident::#variant_ident(v) => #ident::#variant_ident(v.into_static())
+
}
+
}
+
EnumVariantKind::Struct(fields) => {
+
let field_idents: Vec<_> = fields
+
.iter()
+
.map(|f| make_ident(&f.to_snake_case()))
+
.collect();
+
let field_conversions: Vec<_> = field_idents
+
.iter()
+
.map(|f| quote! { #f: #f.into_static() })
+
.collect();
+
quote! {
+
#ident::#variant_ident { #(#field_idents,)* } => #ident::#variant_ident {
+
#(#field_conversions,)*
+
}
+
}
+
}
+
}
+
})
+
.collect();
+
+
let unknown_conversion = if is_open {
+
quote! {
+
#ident::Unknown(v) => #ident::Unknown(v.into_static()),
+
}
+
} else {
+
quote! {}
+
};
+
+
quote! {
+
impl jacquard_common::IntoStatic for #ident<'_> {
+
type Output = #ident<'static>;
+
+
fn into_static(self) -> Self::Output {
+
match self {
+
#(#variant_conversions,)*
+
#unknown_conversion
+
}
+
}
+
}
+
}
+
} else {
+
quote! {
+
impl jacquard_common::IntoStatic for #ident {
+
type Output = #ident;
+
+
fn into_static(self) -> Self::Output {
+
self
+
}
+
}
+
}
+
}
+
}
+
}
+259
crates/jacquard-lexicon/src/codegen/types.rs
···
+
use crate::error::Result;
+
use crate::lexicon::{LexArrayItem, LexObjectProperty, LexString, LexStringFormat};
+
use heck::ToSnakeCase;
+
use proc_macro2::TokenStream;
+
use quote::quote;
+
+
use super::CodeGenerator;
+
+
impl<'c> CodeGenerator<'c> {
+
/// Convert a property type to Rust type
+
pub(super) fn property_to_rust_type(
+
&self,
+
nsid: &str,
+
parent_type_name: &str,
+
field_name: &str,
+
prop: &LexObjectProperty<'static>,
+
) -> Result<TokenStream> {
+
match prop {
+
LexObjectProperty::Boolean(_) => Ok(quote! { bool }),
+
LexObjectProperty::Integer(_) => Ok(quote! { i64 }),
+
LexObjectProperty::String(s) => Ok(self.string_to_rust_type(s)),
+
LexObjectProperty::Bytes(_) => Ok(quote! { bytes::Bytes }),
+
LexObjectProperty::CidLink(_) => {
+
Ok(quote! { jacquard_common::types::cid::CidLink<'a> })
+
}
+
LexObjectProperty::Blob(_) => Ok(quote! { jacquard_common::types::blob::Blob<'a> }),
+
LexObjectProperty::Unknown(_) => Ok(quote! { jacquard_common::types::value::Data<'a> }),
+
LexObjectProperty::Array(array) => {
+
// For arrays with union items, check if multi-variant
+
if let LexArrayItem::Union(union) = &array.items {
+
if union.refs.is_empty() {
+
// Empty union: fall back to Data
+
Ok(quote! { Vec<jacquard_common::types::value::Data<'a>> })
+
} else if union.refs.len() == 1 {
+
// Single-variant: use the ref type directly
+
let ref_str = if union.refs[0].starts_with('#') {
+
format!("{}{}", nsid, union.refs[0])
+
} else {
+
union.refs[0].to_string()
+
};
+
let ref_type = self.ref_to_rust_type(&ref_str)?;
+
Ok(quote! { Vec<#ref_type> })
+
} else {
+
// Multi-variant: use generated union type
+
let union_name = self.generate_field_type_name(nsid, parent_type_name, field_name, "Item");
+
let union_ident = syn::Ident::new(&union_name, proc_macro2::Span::call_site());
+
Ok(quote! { Vec<#union_ident<'a>> })
+
}
+
} else {
+
let item_type = self.array_item_to_rust_type(nsid, &array.items)?;
+
Ok(quote! { Vec<#item_type> })
+
}
+
}
+
LexObjectProperty::Object(_object) => {
+
// Generate unique nested object type name with collision detection
+
let object_name = self.generate_field_type_name(nsid, parent_type_name, field_name, "");
+
let object_ident = syn::Ident::new(&object_name, proc_macro2::Span::call_site());
+
Ok(quote! { #object_ident<'a> })
+
}
+
LexObjectProperty::Ref(ref_type) => {
+
// Handle local refs (starting with #) by prepending the current NSID
+
let ref_str = if ref_type.r#ref.starts_with('#') {
+
format!("{}{}", nsid, ref_type.r#ref)
+
} else {
+
ref_type.r#ref.to_string()
+
};
+
self.ref_to_rust_type(&ref_str)
+
}
+
LexObjectProperty::Union(union) => {
+
if union.refs.is_empty() {
+
// Empty union: fall back to Data
+
Ok(quote! { jacquard_common::types::value::Data<'a> })
+
} else if union.refs.len() == 1 {
+
// Check if this is a self-reference
+
let ref_str = if union.refs[0].starts_with('#') {
+
format!("{}{}", nsid, union.refs[0])
+
} else {
+
union.refs[0].to_string()
+
};
+
+
// Parse ref to get type name
+
let (ref_nsid, ref_def) = if let Some((nsid_part, fragment)) = ref_str.split_once('#') {
+
(nsid_part, fragment)
+
} else {
+
(ref_str.as_str(), "main")
+
};
+
let ref_type_name = self.def_to_type_name(ref_nsid, ref_def);
+
+
// If self-referential, keep union for indirection (variants are boxed)
+
if ref_type_name == parent_type_name {
+
let union_name = self.generate_field_type_name(nsid, parent_type_name, field_name, "");
+
let union_ident = syn::Ident::new(&union_name, proc_macro2::Span::call_site());
+
Ok(quote! { #union_ident<'a> })
+
} else {
+
// Non-self-ref single-variant: use the ref type directly
+
self.ref_to_rust_type(&ref_str)
+
}
+
} else {
+
// Multi-variant: generate union type with collision detection
+
let union_name = self.generate_field_type_name(nsid, parent_type_name, field_name, "");
+
let union_ident = syn::Ident::new(&union_name, proc_macro2::Span::call_site());
+
Ok(quote! { #union_ident<'a> })
+
}
+
}
+
}
+
}
+
+
/// Convert array item to Rust type
+
pub(super) fn array_item_to_rust_type(&self, nsid: &str, item: &LexArrayItem) -> Result<TokenStream> {
+
match item {
+
LexArrayItem::Boolean(_) => Ok(quote! { bool }),
+
LexArrayItem::Integer(_) => Ok(quote! { i64 }),
+
LexArrayItem::String(s) => Ok(self.string_to_rust_type(s)),
+
LexArrayItem::Bytes(_) => Ok(quote! { bytes::Bytes }),
+
LexArrayItem::CidLink(_) => Ok(quote! { jacquard_common::types::cid::CidLink<'a> }),
+
LexArrayItem::Blob(_) => Ok(quote! { jacquard_common::types::blob::Blob<'a> }),
+
LexArrayItem::Unknown(_) => Ok(quote! { jacquard_common::types::value::Data<'a> }),
+
LexArrayItem::Object(_) => {
+
// For inline objects in arrays, use Data since we can't generate a unique type name
+
Ok(quote! { jacquard_common::types::value::Data<'a> })
+
}
+
LexArrayItem::Ref(ref_type) => {
+
// Handle local refs (starting with #) by prepending the current NSID
+
let ref_str = if ref_type.r#ref.starts_with('#') {
+
format!("{}{}", nsid, ref_type.r#ref)
+
} else {
+
ref_type.r#ref.to_string()
+
};
+
self.ref_to_rust_type(&ref_str)
+
}
+
LexArrayItem::Union(_) => {
+
// For now, use Data
+
Ok(quote! { jacquard_common::types::value::Data<'a> })
+
}
+
}
+
}
+
+
/// Convert string type to Rust type
+
pub(super) fn string_to_rust_type(&self, s: &LexString) -> TokenStream {
+
match s.format {
+
Some(LexStringFormat::Datetime) => {
+
quote! { jacquard_common::types::string::Datetime }
+
}
+
Some(LexStringFormat::Did) => quote! { jacquard_common::types::string::Did<'a> },
+
Some(LexStringFormat::Handle) => quote! { jacquard_common::types::string::Handle<'a> },
+
Some(LexStringFormat::AtIdentifier) => {
+
quote! { jacquard_common::types::ident::AtIdentifier<'a> }
+
}
+
Some(LexStringFormat::Nsid) => quote! { jacquard_common::types::string::Nsid<'a> },
+
Some(LexStringFormat::AtUri) => quote! { jacquard_common::types::string::AtUri<'a> },
+
Some(LexStringFormat::Uri) => quote! { jacquard_common::types::string::Uri<'a> },
+
Some(LexStringFormat::Cid) => quote! { jacquard_common::types::string::Cid<'a> },
+
Some(LexStringFormat::Language) => {
+
quote! { jacquard_common::types::string::Language }
+
}
+
Some(LexStringFormat::Tid) => quote! { jacquard_common::types::string::Tid },
+
Some(LexStringFormat::RecordKey) => {
+
quote! { jacquard_common::types::string::RecordKey<jacquard_common::types::string::Rkey<'a>> }
+
}
+
_ => quote! { jacquard_common::CowStr<'a> },
+
}
+
}
+
+
/// Convert ref to Rust type path
+
pub(super) fn ref_to_rust_type(&self, ref_str: &str) -> Result<TokenStream> {
+
use crate::error::CodegenError;
+
use super::utils::sanitize_name;
+
+
// Parse NSID and fragment
+
let (ref_nsid, ref_def) = if let Some((nsid, fragment)) = ref_str.split_once('#') {
+
(nsid, fragment)
+
} else {
+
(ref_str, "main")
+
};
+
+
// Check if ref exists
+
if !self.corpus.ref_exists(ref_str) {
+
// Fallback to Data
+
return Ok(quote! { jacquard_common::types::value::Data<'a> });
+
}
+
+
// Convert NSID to module path
+
// com.atproto.repo.strongRef -> com_atproto::repo::strong_ref::StrongRef
+
// app.bsky.richtext.facet -> app_bsky::richtext::facet::Facet
+
// app.bsky.actor.defs#nux -> app_bsky::actor::Nux (defs go in parent module)
+
let parts: Vec<&str> = ref_nsid.split('.').collect();
+
let last_segment = parts.last().unwrap();
+
+
let type_name = self.def_to_type_name(ref_nsid, ref_def);
+
+
let path_str = if *last_segment == "defs" && parts.len() >= 3 {
+
// defs types go in parent module
+
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
+
if parts.len() == 3 {
+
// com.atproto.defs -> com_atproto::TypeName
+
format!("{}::{}::{}", self.root_module, first_two, type_name)
+
} else {
+
// app.bsky.actor.defs -> app_bsky::actor::TypeName
+
let middle: Vec<_> = parts[2..parts.len() - 1]
+
.iter()
+
.copied()
+
.map(|s| sanitize_name(s))
+
.collect();
+
format!(
+
"{}::{}::{}::{}",
+
self.root_module,
+
first_two,
+
middle.join("::"),
+
type_name
+
)
+
}
+
} else {
+
// Regular types go in their own module file
+
let (module_path, file_module) = if parts.len() >= 3 {
+
// Join first two segments with underscore
+
let first_two = format!("{}_{}", sanitize_name(parts[0]), sanitize_name(parts[1]));
+
let file_name = sanitize_name(last_segment).to_snake_case();
+
+
if parts.len() > 3 {
+
// Middle segments form the module path
+
let middle: Vec<_> = parts[2..parts.len() - 1]
+
.iter()
+
.copied()
+
.map(|s| sanitize_name(s))
+
.collect();
+
let base_path = format!("{}::{}", first_two, middle.join("::"));
+
(base_path, file_name)
+
} else {
+
// Only 3 parts: com.atproto.label -> com_atproto, file: label
+
(first_two, file_name)
+
}
+
} else if parts.len() == 2 {
+
// e.g., "com.example" -> "com_example", file: example
+
let first = sanitize_name(parts[0]);
+
let file_name = sanitize_name(parts[1]).to_snake_case();
+
(first, file_name)
+
} else {
+
(parts[0].to_string(), "main".to_string())
+
};
+
+
format!(
+
"{}::{}::{}::{}",
+
self.root_module, module_path, file_module, type_name
+
)
+
};
+
+
let path: syn::Path = syn::parse_str(&path_str).map_err(|e| CodegenError::Other {
+
message: format!("Failed to parse path: {} {}", path_str, e),
+
source: None,
+
})?;
+
+
// Only add lifetime if the target type needs it
+
if self.ref_needs_lifetime(ref_str) {
+
Ok(quote! { #path<'a> })
+
} else {
+
Ok(quote! { #path })
+
}
+
}
+
}
+81
crates/jacquard-lexicon/src/codegen/utils.rs
···
+
use heck::ToPascalCase;
+
use jacquard_common::CowStr;
+
use proc_macro2::TokenStream;
+
use quote::quote;
+
+
/// Convert a value string to a valid Rust variant name
+
pub(super) fn value_to_variant_name(value: &str) -> String {
+
// Remove leading special chars and convert to pascal case
+
let clean = value.trim_start_matches(|c: char| !c.is_alphanumeric());
+
let variant = clean.replace('-', "_").to_pascal_case();
+
+
// Prefix with underscore if starts with digit
+
if variant.chars().next().map_or(false, |c| c.is_ascii_digit()) {
+
format!("_{}", variant)
+
} else if variant.is_empty() {
+
"Unknown".to_string()
+
} else {
+
variant
+
}
+
}
+
+
/// Sanitize a string to be safe for identifiers and filenames
+
pub(super) fn sanitize_name(s: &str) -> String {
+
if s.is_empty() {
+
return "unknown".to_string();
+
}
+
+
// Replace invalid characters with underscores
+
let mut sanitized: String = s
+
.chars()
+
.map(|c| {
+
if c.is_alphanumeric() || c == '_' {
+
c
+
} else {
+
'_'
+
}
+
})
+
.collect();
+
+
// Ensure it doesn't start with a digit
+
if sanitized
+
.chars()
+
.next()
+
.map_or(false, |c| c.is_ascii_digit())
+
{
+
sanitized = format!("_{}", sanitized);
+
}
+
+
sanitized
+
}
+
+
/// Create an identifier, using raw identifier if necessary for keywords
+
pub(super) fn make_ident(s: &str) -> syn::Ident {
+
if s.is_empty() {
+
eprintln!("Warning: Empty identifier encountered, using 'unknown' as fallback");
+
return syn::Ident::new("unknown", proc_macro2::Span::call_site());
+
}
+
+
let sanitized = sanitize_name(s);
+
+
// Try to parse as ident, fall back to raw ident if needed
+
syn::parse_str::<syn::Ident>(&sanitized).unwrap_or_else(|_| {
+
eprintln!(
+
"Warning: Invalid identifier '{}' sanitized to '{}'",
+
s, sanitized
+
);
+
syn::Ident::new_raw(&sanitized, proc_macro2::Span::call_site())
+
})
+
}
+
+
/// Generate doc comment from optional description
+
pub(super) fn generate_doc_comment(desc: Option<&CowStr>) -> TokenStream {
+
if let Some(description) = desc {
+
let desc_str = description.as_ref();
+
quote! {
+
#[doc = #desc_str]
+
}
+
} else {
+
quote! {}
+
}
+
}
+1006
crates/jacquard-lexicon/src/codegen/xrpc.rs
···
+
use crate::error::Result;
+
use crate::lexicon::{
+
LexArrayItem, LexObjectProperty, LexXrpcBody, LexXrpcBodySchema, LexXrpcError,
+
LexXrpcProcedure, LexXrpcQuery, LexXrpcSubscription, LexXrpcSubscriptionMessageSchema,
+
};
+
use heck::{ToPascalCase, ToSnakeCase};
+
use proc_macro2::TokenStream;
+
use quote::quote;
+
+
use super::utils::make_ident;
+
use super::CodeGenerator;
+
+
impl<'c> CodeGenerator<'c> {
+
/// Generate query type
+
pub(super) fn generate_query(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
query: &LexXrpcQuery<'static>,
+
) -> Result<TokenStream> {
+
let type_base = self.def_to_type_name(nsid, def_name);
+
let mut output = Vec::new();
+
+
let params_has_lifetime = query
+
.parameters
+
.as_ref()
+
.map(|p| match p {
+
crate::lexicon::LexXrpcQueryParameter::Params(params) => {
+
self.params_need_lifetime(params)
+
}
+
})
+
.unwrap_or(false);
+
let has_params = query.parameters.is_some();
+
let has_output = query.output.is_some();
+
let has_errors = query.errors.is_some();
+
+
if let Some(params) = &query.parameters {
+
let params_struct = self.generate_params_struct(&type_base, params)?;
+
output.push(params_struct);
+
}
+
+
if let Some(body) = &query.output {
+
let output_struct = self.generate_output_struct(nsid, &type_base, body)?;
+
output.push(output_struct);
+
}
+
+
if let Some(errors) = &query.errors {
+
let error_enum = self.generate_error_enum(&type_base, errors)?;
+
output.push(error_enum);
+
}
+
+
// Generate XrpcRequest impl
+
let output_encoding = query
+
.output
+
.as_ref()
+
.map(|o| o.encoding.as_ref())
+
.unwrap_or("application/json");
+
let xrpc_impl = self.generate_xrpc_request_impl(
+
nsid,
+
&type_base,
+
quote! { jacquard_common::xrpc::XrpcMethod::Query },
+
output_encoding,
+
has_params,
+
params_has_lifetime,
+
has_output,
+
has_errors,
+
false, // queries never have binary inputs
+
)?;
+
output.push(xrpc_impl);
+
+
Ok(quote! {
+
#(#output)*
+
})
+
}
+
+
/// Generate procedure type
+
pub(super) fn generate_procedure(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
proc: &LexXrpcProcedure<'static>,
+
) -> Result<TokenStream> {
+
let type_base = self.def_to_type_name(nsid, def_name);
+
let mut output = Vec::new();
+
+
// Check if input is a binary body (no schema)
+
let is_binary_input = proc
+
.input
+
.as_ref()
+
.map(|i| i.schema.is_none())
+
.unwrap_or(false);
+
+
// Input bodies with schemas have lifetimes (they get #[lexicon] attribute)
+
// Binary inputs don't have lifetimes
+
let params_has_lifetime = proc.input.is_some() && !is_binary_input;
+
let has_input = proc.input.is_some();
+
let has_output = proc.output.is_some();
+
let has_errors = proc.errors.is_some();
+
+
if let Some(params) = &proc.parameters {
+
let params_struct = self.generate_params_struct_proc(&type_base, params)?;
+
output.push(params_struct);
+
}
+
+
if let Some(body) = &proc.input {
+
let input_struct = self.generate_input_struct(nsid, &type_base, body)?;
+
output.push(input_struct);
+
}
+
+
if let Some(body) = &proc.output {
+
let output_struct = self.generate_output_struct(nsid, &type_base, body)?;
+
output.push(output_struct);
+
}
+
+
if let Some(errors) = &proc.errors {
+
let error_enum = self.generate_error_enum(&type_base, errors)?;
+
output.push(error_enum);
+
}
+
+
// Generate XrpcRequest impl
+
let input_encoding = proc
+
.input
+
.as_ref()
+
.map(|i| i.encoding.as_ref())
+
.unwrap_or("application/json");
+
let output_encoding = proc
+
.output
+
.as_ref()
+
.map(|o| o.encoding.as_ref())
+
.unwrap_or("application/json");
+
let xrpc_impl = self.generate_xrpc_request_impl(
+
nsid,
+
&type_base,
+
quote! { jacquard_common::xrpc::XrpcMethod::Procedure(#input_encoding) },
+
output_encoding,
+
has_input,
+
params_has_lifetime,
+
has_output,
+
has_errors,
+
is_binary_input,
+
)?;
+
output.push(xrpc_impl);
+
+
Ok(quote! {
+
#(#output)*
+
})
+
}
+
+
pub(super) fn generate_subscription(
+
&self,
+
nsid: &str,
+
def_name: &str,
+
sub: &LexXrpcSubscription<'static>,
+
) -> Result<TokenStream> {
+
let type_base = self.def_to_type_name(nsid, def_name);
+
let mut output = Vec::new();
+
+
if let Some(params) = &sub.parameters {
+
// Extract LexXrpcParameters from the enum
+
match params {
+
crate::lexicon::LexXrpcSubscriptionParameter::Params(params_inner) => {
+
let params_struct =
+
self.generate_params_struct_inner(&type_base, params_inner)?;
+
output.push(params_struct);
+
}
+
}
+
}
+
+
if let Some(message) = &sub.message {
+
if let Some(schema) = &message.schema {
+
let message_type = self.generate_subscription_message(nsid, &type_base, schema)?;
+
output.push(message_type);
+
}
+
}
+
+
if let Some(errors) = &sub.errors {
+
let error_enum = self.generate_error_enum(&type_base, errors)?;
+
output.push(error_enum);
+
}
+
+
Ok(quote! {
+
#(#output)*
+
})
+
}
+
+
pub(super) fn generate_subscription_message(
+
&self,
+
nsid: &str,
+
type_base: &str,
+
schema: &LexXrpcSubscriptionMessageSchema<'static>,
+
) -> Result<TokenStream> {
+
use crate::lexicon::LexXrpcSubscriptionMessageSchema;
+
+
match schema {
+
LexXrpcSubscriptionMessageSchema::Union(union) => {
+
// Generate a union enum for the message
+
let enum_name = format!("{}Message", type_base);
+
let enum_ident = syn::Ident::new(&enum_name, proc_macro2::Span::call_site());
+
+
let mut variants = Vec::new();
+
for ref_str in &union.refs {
+
let ref_str_s = ref_str.as_ref();
+
// Parse ref to get NSID and def name
+
let (ref_nsid, ref_def) =
+
if let Some((nsid, fragment)) = ref_str.split_once('#') {
+
(nsid, fragment)
+
} else {
+
(ref_str.as_ref(), "main")
+
};
+
+
let variant_name = if ref_def == "main" {
+
ref_nsid.split('.').last().unwrap().to_pascal_case()
+
} else {
+
ref_def.to_pascal_case()
+
};
+
let variant_ident =
+
syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
+
let type_path = self.ref_to_rust_type(ref_str)?;
+
+
variants.push(quote! {
+
#[serde(rename = #ref_str_s)]
+
#variant_ident(Box<#type_path>)
+
});
+
}
+
+
let doc = self.generate_doc_comment(union.description.as_ref());
+
+
Ok(quote! {
+
#doc
+
#[jacquard_derive::open_union]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(tag = "$type")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum #enum_ident<'a> {
+
#(#variants,)*
+
}
+
})
+
}
+
LexXrpcSubscriptionMessageSchema::Object(obj) => {
+
// Generate a struct for the message
+
let struct_name = format!("{}Message", type_base);
+
let struct_ident = syn::Ident::new(&struct_name, proc_macro2::Span::call_site());
+
+
let fields = self.generate_object_fields("", &struct_name, obj, false)?;
+
let doc = self.generate_doc_comment(obj.description.as_ref());
+
+
// Subscription message structs always get a lifetime since they have the #[lexicon] attribute
+
// which adds extra_data: BTreeMap<..., Data<'a>>
+
let struct_def = quote! {
+
#doc
+
#[jacquard_derive::lexicon]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(rename_all = "camelCase")]
+
pub struct #struct_ident<'a> {
+
#fields
+
}
+
};
+
+
// Generate union types for this message
+
let mut unions = Vec::new();
+
for (field_name, field_type) in &obj.properties {
+
match field_type {
+
LexObjectProperty::Union(union) => {
+
// Skip empty, single-variant unions unless they're self-referential
+
if !union.refs.is_empty() && (union.refs.len() > 1 || self.is_self_referential_union(nsid, &struct_name, union)) {
+
let union_name = self.generate_field_type_name(nsid, &struct_name, field_name, "");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def =
+
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
LexObjectProperty::Array(array) => {
+
if let LexArrayItem::Union(union) = &array.items {
+
// Skip single-variant array unions
+
if union.refs.len() > 1 {
+
let union_name = self.generate_field_type_name(nsid, &struct_name, field_name, "Item");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def = self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
}
+
_ => {}
+
}
+
}
+
+
Ok(quote! {
+
#struct_def
+
#(#unions)*
+
})
+
}
+
LexXrpcSubscriptionMessageSchema::Ref(ref_type) => {
+
// Just a type alias to the referenced type
+
// Refs generally have lifetimes, so always add <'a>
+
let type_name = format!("{}Message", type_base);
+
let ident = syn::Ident::new(&type_name, proc_macro2::Span::call_site());
+
let rust_type = self.ref_to_rust_type(&ref_type.r#ref)?;
+
let doc = self.generate_doc_comment(ref_type.description.as_ref());
+
+
Ok(quote! {
+
#doc
+
pub type #ident<'a> = #rust_type;
+
})
+
}
+
}
+
}
+
+
/// Generate params struct from XRPC query parameters
+
pub(super) fn generate_params_struct(
+
&self,
+
type_base: &str,
+
params: &crate::lexicon::LexXrpcQueryParameter<'static>,
+
) -> Result<TokenStream> {
+
use crate::lexicon::LexXrpcQueryParameter;
+
match params {
+
LexXrpcQueryParameter::Params(p) => self.generate_params_struct_inner(type_base, p),
+
}
+
}
+
+
/// Generate params struct from XRPC procedure parameters (query string params)
+
pub(super) fn generate_params_struct_proc(
+
&self,
+
type_base: &str,
+
params: &crate::lexicon::LexXrpcProcedureParameter<'static>,
+
) -> Result<TokenStream> {
+
use crate::lexicon::LexXrpcProcedureParameter;
+
match params {
+
// For procedures, query string params still get "Params" suffix since the main struct is the input
+
LexXrpcProcedureParameter::Params(p) => {
+
let struct_name = format!("{}Params", type_base);
+
let ident = syn::Ident::new(&struct_name, proc_macro2::Span::call_site());
+
self.generate_params_struct_inner_with_name(&ident, p)
+
}
+
}
+
}
+
+
/// Generate params struct inner (shared implementation)
+
pub(super) fn generate_params_struct_inner(
+
&self,
+
type_base: &str,
+
p: &crate::lexicon::LexXrpcParameters<'static>,
+
) -> Result<TokenStream> {
+
let ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
+
self.generate_params_struct_inner_with_name(&ident, p)
+
}
+
+
/// Generate params struct with custom name
+
pub(super) fn generate_params_struct_inner_with_name(
+
&self,
+
ident: &syn::Ident,
+
p: &crate::lexicon::LexXrpcParameters<'static>,
+
) -> Result<TokenStream> {
+
let required = p.required.as_ref().map(|r| r.as_slice()).unwrap_or(&[]);
+
let mut fields = Vec::new();
+
let mut default_fns = Vec::new();
+
+
for (field_name, field_type) in &p.properties {
+
let is_required = required.contains(field_name);
+
let (field_tokens, default_fn) =
+
self.generate_param_field_with_default("", field_name, field_type, is_required)?;
+
fields.push(field_tokens);
+
if let Some(fn_def) = default_fn {
+
default_fns.push(fn_def);
+
}
+
}
+
+
let doc = self.generate_doc_comment(p.description.as_ref());
+
let needs_lifetime = self.params_need_lifetime(p);
+
+
let derives = quote! {
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, bon::Builder, jacquard_derive::IntoStatic)]
+
#[builder(start_fn = new)]
+
};
+
+
if needs_lifetime {
+
Ok(quote! {
+
#(#default_fns)*
+
+
#doc
+
#derives
+
#[serde(rename_all = "camelCase")]
+
pub struct #ident<'a> {
+
#(#fields)*
+
}
+
})
+
} else {
+
Ok(quote! {
+
#(#default_fns)*
+
+
#doc
+
#derives
+
#[serde(rename_all = "camelCase")]
+
pub struct #ident {
+
#(#fields)*
+
}
+
})
+
}
+
}
+
+
/// Generate input struct from XRPC body
+
pub(super) fn generate_input_struct(
+
&self,
+
nsid: &str,
+
type_base: &str,
+
body: &LexXrpcBody<'static>,
+
) -> Result<TokenStream> {
+
let ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
+
+
// Check if this is a binary body (no schema, just raw bytes)
+
let is_binary_body = body.schema.is_none();
+
+
let fields = if let Some(schema) = &body.schema {
+
self.generate_body_fields("", type_base, schema, true)?
+
} else {
+
// Binary body: just a bytes field
+
quote! {
+
pub body: bytes::Bytes,
+
}
+
};
+
+
let doc = self.generate_doc_comment(body.description.as_ref());
+
+
// Binary bodies don't need #[lexicon] attribute or lifetime
+
let struct_def = if is_binary_body {
+
quote! {
+
#doc
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, bon::Builder, jacquard_derive::IntoStatic)]
+
#[builder(start_fn = new)]
+
#[serde(rename_all = "camelCase")]
+
pub struct #ident {
+
#fields
+
}
+
}
+
} else {
+
// Input structs with schemas: manually add extra_data field with #[builder(default)]
+
// for bon compatibility. The #[lexicon] macro will see it exists and skip adding it.
+
quote! {
+
#doc
+
#[jacquard_derive::lexicon]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, bon::Builder, jacquard_derive::IntoStatic)]
+
#[serde(rename_all = "camelCase")]
+
#[builder(start_fn = new)]
+
pub struct #ident<'a> {
+
#fields
+
#[serde(flatten)]
+
#[serde(borrow)]
+
#[builder(default)]
+
pub extra_data: ::std::collections::BTreeMap<
+
::jacquard_common::smol_str::SmolStr,
+
::jacquard_common::types::value::Data<'a>
+
>,
+
}
+
}
+
};
+
+
// Generate union types if schema is an Object
+
let mut unions = Vec::new();
+
if let Some(crate::lexicon::LexXrpcBodySchema::Object(obj)) = &body.schema {
+
for (field_name, field_type) in &obj.properties {
+
match field_type {
+
LexObjectProperty::Union(union) => {
+
// Skip empty, single-variant unions unless they're self-referential
+
if !union.refs.is_empty() && (union.refs.len() > 1 || self.is_self_referential_union(nsid, type_base, union)) {
+
let union_name = self.generate_field_type_name(nsid, type_base, field_name, "");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def =
+
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
LexObjectProperty::Array(array) => {
+
if let LexArrayItem::Union(union) = &array.items {
+
// Skip single-variant array unions
+
if union.refs.len() > 1 {
+
let union_name = self.generate_field_type_name(nsid, type_base, field_name, "Item");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def = self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
}
+
_ => {}
+
}
+
}
+
}
+
+
Ok(quote! {
+
#struct_def
+
#(#unions)*
+
})
+
}
+
+
/// Generate output struct from XRPC body
+
pub(super) fn generate_output_struct(
+
&self,
+
nsid: &str,
+
type_base: &str,
+
body: &LexXrpcBody<'static>,
+
) -> Result<TokenStream> {
+
let struct_name = format!("{}Output", type_base);
+
let ident = syn::Ident::new(&struct_name, proc_macro2::Span::call_site());
+
+
let fields = if let Some(schema) = &body.schema {
+
self.generate_body_fields("", &struct_name, schema, false)?
+
} else {
+
quote! {}
+
};
+
+
let doc = self.generate_doc_comment(body.description.as_ref());
+
+
// Output structs always get a lifetime since they have the #[lexicon] attribute
+
// which adds extra_data: BTreeMap<..., Data<'a>>
+
let struct_def = quote! {
+
#doc
+
#[jacquard_derive::lexicon]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic)]
+
#[serde(rename_all = "camelCase")]
+
pub struct #ident<'a> {
+
#fields
+
}
+
};
+
+
// Generate union types if schema is an Object
+
let mut unions = Vec::new();
+
if let Some(crate::lexicon::LexXrpcBodySchema::Object(obj)) = &body.schema {
+
for (field_name, field_type) in &obj.properties {
+
match field_type {
+
LexObjectProperty::Union(union) => {
+
// Skip single-variant unions unless they're self-referential
+
if union.refs.len() > 1 || self.is_self_referential_union(nsid, &struct_name, union) {
+
let union_name = self.generate_field_type_name(nsid, &struct_name, field_name, "");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def =
+
self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
LexObjectProperty::Array(array) => {
+
if let LexArrayItem::Union(union) = &array.items {
+
// Skip single-variant array unions
+
if union.refs.len() > 1 {
+
let union_name = self.generate_field_type_name(nsid, &struct_name, field_name, "Item");
+
let refs: Vec<_> = union.refs.iter().cloned().collect();
+
let union_def = self.generate_union(nsid, &union_name, &refs, None, union.closed)?;
+
unions.push(union_def);
+
}
+
}
+
}
+
_ => {}
+
}
+
}
+
}
+
+
Ok(quote! {
+
#struct_def
+
#(#unions)*
+
})
+
}
+
+
/// Generate fields from XRPC body schema
+
pub(super) fn generate_body_fields(
+
&self,
+
nsid: &str,
+
parent_type_name: &str,
+
schema: &LexXrpcBodySchema<'static>,
+
is_builder: bool,
+
) -> Result<TokenStream> {
+
use crate::lexicon::LexXrpcBodySchema;
+
+
match schema {
+
LexXrpcBodySchema::Object(obj) => {
+
self.generate_object_fields(nsid, parent_type_name, obj, is_builder)
+
}
+
LexXrpcBodySchema::Ref(ref_type) => {
+
let rust_type = self.ref_to_rust_type(&ref_type.r#ref)?;
+
Ok(quote! {
+
#[serde(flatten)]
+
#[serde(borrow)]
+
pub value: #rust_type,
+
})
+
}
+
LexXrpcBodySchema::Union(_union) => {
+
let rust_type = quote! { jacquard_common::types::value::Data<'a> };
+
Ok(quote! {
+
#[serde(flatten)]
+
#[serde(borrow)]
+
pub value: #rust_type,
+
})
+
}
+
}
+
}
+
+
/// Generate a field for XRPC parameters
+
pub(super) fn generate_param_field(
+
&self,
+
_nsid: &str,
+
field_name: &str,
+
field_type: &crate::lexicon::LexXrpcParametersProperty<'static>,
+
is_required: bool,
+
) -> Result<TokenStream> {
+
use crate::lexicon::LexXrpcParametersProperty;
+
+
let field_ident = make_ident(&field_name.to_snake_case());
+
+
let (rust_type, needs_lifetime, is_cowstr) = match field_type {
+
LexXrpcParametersProperty::Boolean(_) => (quote! { bool }, false, false),
+
LexXrpcParametersProperty::Integer(_) => (quote! { i64 }, false, false),
+
LexXrpcParametersProperty::String(s) => {
+
let is_cowstr = s.format.is_none(); // CowStr for plain strings
+
(
+
self.string_to_rust_type(s),
+
self.string_needs_lifetime(s),
+
is_cowstr,
+
)
+
}
+
LexXrpcParametersProperty::Unknown(_) => (
+
quote! { jacquard_common::types::value::Data<'a> },
+
true,
+
false,
+
),
+
LexXrpcParametersProperty::Array(arr) => {
+
let needs_lifetime = match &arr.items {
+
crate::lexicon::LexPrimitiveArrayItem::Boolean(_)
+
| crate::lexicon::LexPrimitiveArrayItem::Integer(_) => false,
+
crate::lexicon::LexPrimitiveArrayItem::String(s) => {
+
self.string_needs_lifetime(s)
+
}
+
crate::lexicon::LexPrimitiveArrayItem::Unknown(_) => true,
+
};
+
let item_type = match &arr.items {
+
crate::lexicon::LexPrimitiveArrayItem::Boolean(_) => quote! { bool },
+
crate::lexicon::LexPrimitiveArrayItem::Integer(_) => quote! { i64 },
+
crate::lexicon::LexPrimitiveArrayItem::String(s) => self.string_to_rust_type(s),
+
crate::lexicon::LexPrimitiveArrayItem::Unknown(_) => {
+
quote! { jacquard_common::types::value::Data<'a> }
+
}
+
};
+
(quote! { Vec<#item_type> }, needs_lifetime, false)
+
}
+
};
+
+
let rust_type = if is_required {
+
rust_type
+
} else {
+
quote! { std::option::Option<#rust_type> }
+
};
+
+
let mut attrs = Vec::new();
+
+
if !is_required {
+
attrs.push(quote! { #[serde(skip_serializing_if = "std::option::Option::is_none")] });
+
}
+
+
// Add serde(borrow) to all fields with lifetimes
+
if needs_lifetime {
+
attrs.push(quote! { #[serde(borrow)] });
+
}
+
+
// Add builder(into) for CowStr fields to allow String, &str, etc.
+
if is_cowstr {
+
attrs.push(quote! { #[builder(into)] });
+
}
+
+
Ok(quote! {
+
#(#attrs)*
+
pub #field_ident: #rust_type,
+
})
+
}
+
+
/// Generate param field with serde default if present
+
/// Returns (field_tokens, optional_default_function)
+
pub(super) fn generate_param_field_with_default(
+
&self,
+
nsid: &str,
+
field_name: &str,
+
field_type: &crate::lexicon::LexXrpcParametersProperty<'static>,
+
is_required: bool,
+
) -> Result<(TokenStream, Option<TokenStream>)> {
+
use crate::lexicon::LexXrpcParametersProperty;
+
use heck::ToSnakeCase;
+
+
// Get base field
+
let base_field = self.generate_param_field(nsid, field_name, field_type, is_required)?;
+
+
// Generate default function and attribute for required fields with defaults
+
// For optional fields, just add doc comments
+
let (doc_comment, serde_attr, default_fn) = if is_required {
+
match field_type {
+
LexXrpcParametersProperty::Boolean(b) if b.default.is_some() => {
+
let v = b.default.unwrap();
+
let fn_name = format!("_default_{}", field_name.to_snake_case());
+
let fn_ident = syn::Ident::new(&fn_name, proc_macro2::Span::call_site());
+
(
+
Some(format!("Defaults to `{}`", v)),
+
Some(quote! { #[serde(default = #fn_name)] }),
+
Some(quote! {
+
fn #fn_ident() -> bool { #v }
+
}),
+
)
+
}
+
LexXrpcParametersProperty::Integer(i) if i.default.is_some() => {
+
let v = i.default.unwrap();
+
let fn_name = format!("_default_{}", field_name.to_snake_case());
+
let fn_ident = syn::Ident::new(&fn_name, proc_macro2::Span::call_site());
+
(
+
Some(format!("Defaults to `{}`", v)),
+
Some(quote! { #[serde(default = #fn_name)] }),
+
Some(quote! {
+
fn #fn_ident() -> i64 { #v }
+
}),
+
)
+
}
+
LexXrpcParametersProperty::String(s) if s.default.is_some() => {
+
let v = s.default.as_ref().unwrap().as_ref();
+
let fn_name = format!("_default_{}", field_name.to_snake_case());
+
let fn_ident = syn::Ident::new(&fn_name, proc_macro2::Span::call_site());
+
(
+
Some(format!("Defaults to `\"{}\"`", v)),
+
Some(quote! { #[serde(default = #fn_name)] }),
+
Some(quote! {
+
fn #fn_ident() -> jacquard_common::CowStr<'static> {
+
jacquard_common::CowStr::from(#v)
+
}
+
}),
+
)
+
}
+
_ => (None, None, None),
+
}
+
} else {
+
// Optional fields - just doc comments, no serde defaults
+
let doc = match field_type {
+
LexXrpcParametersProperty::Integer(i) => {
+
let mut parts = Vec::new();
+
if let Some(def) = i.default {
+
parts.push(format!("default: {}", def));
+
}
+
if let Some(min) = i.minimum {
+
parts.push(format!("min: {}", min));
+
}
+
if let Some(max) = i.maximum {
+
parts.push(format!("max: {}", max));
+
}
+
if !parts.is_empty() {
+
Some(format!("({})", parts.join(", ")))
+
} else {
+
None
+
}
+
}
+
LexXrpcParametersProperty::String(s) => {
+
let mut parts = Vec::new();
+
if let Some(def) = s.default.as_ref() {
+
parts.push(format!("default: \"{}\"", def.as_ref()));
+
}
+
if let Some(min) = s.min_length {
+
parts.push(format!("min length: {}", min));
+
}
+
if let Some(max) = s.max_length {
+
parts.push(format!("max length: {}", max));
+
}
+
if !parts.is_empty() {
+
Some(format!("({})", parts.join(", ")))
+
} else {
+
None
+
}
+
}
+
LexXrpcParametersProperty::Boolean(b) => {
+
b.default.map(|v| format!("(default: {})", v))
+
}
+
_ => None,
+
};
+
(doc, None, None)
+
};
+
+
let doc = doc_comment.as_ref().map(|d| quote! { #[doc = #d] });
+
let field_with_attrs = match (doc, serde_attr) {
+
(Some(doc), Some(attr)) => quote! {
+
#doc
+
#attr
+
#base_field
+
},
+
(Some(doc), None) => quote! {
+
#doc
+
#base_field
+
},
+
(None, Some(attr)) => quote! {
+
#attr
+
#base_field
+
},
+
(None, None) => base_field,
+
};
+
+
Ok((field_with_attrs, default_fn))
+
}
+
+
/// Generate error enum from XRPC errors
+
pub(super) fn generate_error_enum(
+
&self,
+
type_base: &str,
+
errors: &[LexXrpcError<'static>],
+
) -> Result<TokenStream> {
+
let enum_name = format!("{}Error", type_base);
+
let ident = syn::Ident::new(&enum_name, proc_macro2::Span::call_site());
+
+
let mut variants = Vec::new();
+
let mut display_arms = Vec::new();
+
+
for error in errors {
+
let variant_name = error.name.to_pascal_case();
+
let variant_ident = syn::Ident::new(&variant_name, proc_macro2::Span::call_site());
+
+
let error_name = error.name.as_ref();
+
let doc = self.generate_doc_comment(error.description.as_ref());
+
+
variants.push(quote! {
+
#doc
+
#[serde(rename = #error_name)]
+
#variant_ident(std::option::Option<String>)
+
});
+
+
display_arms.push(quote! {
+
Self::#variant_ident(msg) => {
+
write!(f, #error_name)?;
+
if let Some(msg) = msg {
+
write!(f, ": {}", msg)?;
+
}
+
Ok(())
+
}
+
});
+
}
+
+
// IntoStatic impl is generated by the derive macro now
+
+
Ok(quote! {
+
#[jacquard_derive::open_union]
+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic, jacquard_derive::IntoStatic)]
+
#[serde(tag = "error", content = "message")]
+
#[serde(bound(deserialize = "'de: 'a"))]
+
pub enum #ident<'a> {
+
#(#variants,)*
+
}
+
+
impl std::fmt::Display for #ident<'_> {
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+
match self {
+
#(#display_arms)*
+
Self::Unknown(err) => write!(f, "Unknown error: {:?}", err),
+
}
+
}
+
}
+
})
+
}
+
+
/// Generate XrpcRequest trait impl for a query or procedure
+
pub(super) fn generate_xrpc_request_impl(
+
&self,
+
nsid: &str,
+
type_base: &str,
+
method: TokenStream,
+
output_encoding: &str,
+
has_params: bool,
+
params_has_lifetime: bool,
+
has_output: bool,
+
has_errors: bool,
+
is_binary_input: bool,
+
) -> Result<TokenStream> {
+
let output_type = if has_output {
+
let output_ident = syn::Ident::new(
+
&format!("{}Output", type_base),
+
proc_macro2::Span::call_site(),
+
);
+
quote! { #output_ident<'de> }
+
} else {
+
quote! { () }
+
};
+
+
let error_type = if has_errors {
+
let error_ident = syn::Ident::new(
+
&format!("{}Error", type_base),
+
proc_macro2::Span::call_site(),
+
);
+
quote! { #error_ident<'de> }
+
} else {
+
quote! { jacquard_common::xrpc::GenericError<'de> }
+
};
+
+
// Generate the response type that implements XrpcResp
+
let response_ident = syn::Ident::new(
+
&format!("{}Response", type_base),
+
proc_macro2::Span::call_site(),
+
);
+
+
// Generate the endpoint type that implements XrpcEndpoint
+
let endpoint_ident = syn::Ident::new(
+
&format!("{}Request", type_base),
+
proc_macro2::Span::call_site(),
+
);
+
+
let response_type = quote! {
+
#[doc = "Response type for "]
+
#[doc = #nsid]
+
pub struct #response_ident;
+
+
impl jacquard_common::xrpc::XrpcResp for #response_ident {
+
const NSID: &'static str = #nsid;
+
const ENCODING: &'static str = #output_encoding;
+
type Output<'de> = #output_type;
+
type Err<'de> = #error_type;
+
}
+
};
+
+
// Generate encode_body() method for binary inputs
+
let encode_body_method = if is_binary_input {
+
quote! {
+
fn encode_body(&self) -> Result<Vec<u8>, jacquard_common::xrpc::EncodeError> {
+
Ok(self.body.to_vec())
+
}
+
}
+
} else {
+
quote! {}
+
};
+
+
// Generate decode_body() method for binary inputs
+
let decode_body_method = if is_binary_input {
+
quote! {
+
fn decode_body(
+
body: &'de [u8],
+
) -> Result<Box<Self>, jacquard_common::error::DecodeError> {
+
Ok(Box::new(Self {
+
body: bytes::Bytes::copy_from_slice(body),
+
}))
+
}
+
}
+
} else {
+
quote! {}
+
};
+
+
let endpoint_path = format!("/xrpc/{}", nsid);
+
+
if has_params {
+
// Implement on the params/input struct itself
+
let request_ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
+
let impl_target = if params_has_lifetime {
+
quote! { #request_ident<'de> }
+
} else {
+
quote! { #request_ident }
+
};
+
+
Ok(quote! {
+
#response_type
+
+
impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for #impl_target {
+
const NSID: &'static str = #nsid;
+
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
+
+
type Response = #response_ident;
+
+
#encode_body_method
+
#decode_body_method
+
}
+
+
#[doc = "Endpoint type for "]
+
#[doc = #nsid]
+
pub struct #endpoint_ident;
+
+
impl jacquard_common::xrpc::XrpcEndpoint for #endpoint_ident {
+
const PATH: &'static str = #endpoint_path;
+
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
+
+
type Request<'de> = #impl_target;
+
type Response = #response_ident;
+
}
+
})
+
} else {
+
// No params - generate a marker struct
+
let request_ident = syn::Ident::new(type_base, proc_macro2::Span::call_site());
+
+
Ok(quote! {
+
/// XRPC request marker type
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, jacquard_derive::IntoStatic)]
+
pub struct #request_ident;
+
+
#response_type
+
+
impl<'de> jacquard_common::xrpc::XrpcRequest<'de> for #request_ident {
+
const NSID: &'static str = #nsid;
+
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
+
+
type Response = #response_ident;
+
}
+
+
#[doc = "Endpoint type for "]
+
#[doc = #nsid]
+
pub struct #endpoint_ident;
+
+
impl jacquard_common::xrpc::XrpcEndpoint for #endpoint_ident {
+
const PATH: &'static str = #endpoint_path;
+
const METHOD: jacquard_common::xrpc::XrpcMethod = #method;
+
+
type Request<'de> = #request_ident;
+
type Response = #response_ident;
+
}
+
})
+
}
+
}
+
}