diff --git a/Cargo.toml b/Cargo.toml index 96701e1b..5827346b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,9 @@ serde_with = "3.14" serde_html_form = "0.2" serde_ipld_dagcbor = "0.6" serde_repr = "0.1" +facet = "0.6" +facet-json = "0.6" +cfg-if = "1.0" # Error handling miette = "7.6" @@ -88,5 +91,5 @@ p256 = "0.13" jose-jwk = "0.1" # Text processing -regex = { version = "1.11", default-features = false } +regex = { version = "1.12", default-features = false } webpage = { version = "2.0", default-features = false } diff --git a/crates/jacquard-lexicon/src/codegen/structs.rs b/crates/jacquard-lexicon/src/codegen/structs.rs index 19025793..f50f798b 100644 --- a/crates/jacquard-lexicon/src/codegen/structs.rs +++ b/crates/jacquard-lexicon/src/codegen/structs.rs @@ -340,12 +340,7 @@ impl<'c> CodeGenerator<'c> { let rust_type = if is_required { rust_type } else { - // Use std::option::Option for non-builder structs to avoid name collision - if is_builder { - quote! { Option<#rust_type> } - } else { - quote! { std::option::Option<#rust_type> } - } + quote! { std::option::Option<#rust_type> } }; // Extract description from field type diff --git a/crates/jacquard/src/client.rs b/crates/jacquard/src/client.rs index 1e231f7f..619923d7 100644 --- a/crates/jacquard/src/client.rs +++ b/crates/jacquard/src/client.rs @@ -1206,7 +1206,7 @@ where async move { CredentialSession::::session_info(self) .await - .map(|(did, sid)| (did, Some(sid))) + .map(|key| (key.0, Some(key.1))) } } fn endpoint(&self) -> impl Future> { diff --git a/crates/jacquard/src/client/credential_session.rs b/crates/jacquard/src/client/credential_session.rs index f51b2f59..d2c4d30e 100644 --- a/crates/jacquard/src/client/credential_session.rs +++ b/crates/jacquard/src/client/credential_session.rs @@ -30,7 +30,8 @@ use jacquard_common::websocket::{WebSocketClient, WebSocketConnection}; use jacquard_common::xrpc::XrpcSubscription; /// Storage key for app‑password sessions: `(account DID, session id)`. -pub type SessionKey = (Did<'static>, CowStr<'static>); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SessionKey(pub Did<'static>, pub CowStr<'static>); /// Stateful client for app‑password based sessions. /// @@ -273,7 +274,7 @@ where let session = AtpSession::from(out); let sid = session_id.unwrap_or_else(|| CowStr::new_static("session")); - let key = (session.did.clone(), sid.into_static()); + let key = SessionKey(session.did.clone(), sid.into_static()); self.store .set(key.clone(), session.clone()) .await @@ -306,7 +307,7 @@ where tracing::info_span!("credential_session_restore", did = %did, session_id = %session_id) .entered(); - let key = (did.clone().into_static(), session_id.clone().into_static()); + let key = SessionKey(did.clone().into_static(), session_id.clone().into_static()); let Some(sess) = self.store.get(&key).await else { return Err(ClientError::auth(AuthError::NotAuthenticated)); }; @@ -331,7 +332,7 @@ where *self.endpoint.write().await = Some(pds.to_cowstr().into_static()); // ensure store has the session (no-op if it existed) self.store - .set((sess.did.clone(), session_id.into_static()), sess) + .set(SessionKey(sess.did.clone(), session_id.into_static()), sess) .await?; if let Some(file_store) = (&*self.store as &dyn Any).downcast_ref::() @@ -356,7 +357,7 @@ where where S: Any + 'static, { - let key = (did.clone().into_static(), session_id.into_static()); + let key = SessionKey(did.clone().into_static(), session_id.into_static()); if self.store.get(&key).await.is_none() { return Err(ClientError::auth(AuthError::NotAuthenticated)); } diff --git a/crates/jacquard/src/client/token.rs b/crates/jacquard/src/client/token.rs index 28d94273..9d758fd6 100644 --- a/crates/jacquard/src/client/token.rs +++ b/crates/jacquard/src/client/token.rs @@ -475,7 +475,7 @@ mod tests { did: Did::new_static("did:plc:alice").unwrap(), handle: Handle::new_static("alice.bsky.social").unwrap(), }; - let key: SessionKey = (session.did.clone(), "session".into()); + let key = SessionKey(session.did.clone(), "session".into()); jacquard_common::session::SessionStore::set(&store, key.clone(), session.clone()) .await .unwrap(); diff --git a/crates/jacquard/tests/agent.rs b/crates/jacquard/tests/agent.rs index 19685246..c13cb7ca 100644 --- a/crates/jacquard/tests/agent.rs +++ b/crates/jacquard/tests/agent.rs @@ -97,7 +97,7 @@ async fn agent_delegates_to_session_and_refreshes() { did: Did::new_static("did:plc:alice").unwrap(), handle: Handle::new_static("alice.bsky.social").unwrap(), }; - let key: SessionKey = (atp.did.clone(), "session".into()); + let key = SessionKey(atp.did.clone(), "session".into()); jacquard_common::session::SessionStore::set(store.as_ref(), key.clone(), atp) .await .unwrap(); diff --git a/crates/jacquard/tests/credential_session.rs b/crates/jacquard/tests/credential_session.rs index 443ccdbc..9dc964ef 100644 --- a/crates/jacquard/tests/credential_session.rs +++ b/crates/jacquard/tests/credential_session.rs @@ -247,7 +247,7 @@ async fn credential_login_and_auto_refresh() { ); // Verify store updated with refreshed tokens - let key: SessionKey = ( + let key = SessionKey( Did::new_static("did:plc:alice").unwrap(), jacquard::CowStr::from("session"), ); diff --git a/crates/jacquard/tests/restore_pds_cache.rs b/crates/jacquard/tests/restore_pds_cache.rs index 2287d2b3..3e1a41e7 100644 --- a/crates/jacquard/tests/restore_pds_cache.rs +++ b/crates/jacquard/tests/restore_pds_cache.rs @@ -91,7 +91,7 @@ async fn restore_uses_cached_pds_when_present() { did: Did::new_static("did:plc:alice").unwrap(), handle: Handle::new_static("alice.bsky.social").unwrap(), }; - let key: SessionKey = (session.did.clone(), "session".into()); + let key = SessionKey(session.did.clone(), "session".into()); jacquard_common::session::SessionStore::set(store.as_ref(), key.clone(), session) .await .unwrap();