jacquard_api/sh_weaver/collab/
session.rs1#[allow(unused_imports)]
9use alloc::collections::BTreeMap;
10
11#[allow(unused_imports)]
12use core::marker::PhantomData;
13use jacquard_common::CowStr;
14
15#[allow(unused_imports)]
16use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
17use jacquard_common::types::collection::{Collection, RecordError};
18use jacquard_common::types::string::{AtUri, Cid, Datetime, UriValue};
19use jacquard_common::types::uri::{RecordUri, UriError};
20use jacquard_common::xrpc::XrpcResp;
21use jacquard_derive::{IntoStatic, lexicon};
22use jacquard_lexicon::lexicon::LexiconDoc;
23use jacquard_lexicon::schema::LexiconSchema;
24
25#[allow(unused_imports)]
26use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
27use serde::{Serialize, Deserialize};
28use crate::com_atproto::repo::strong_ref::StrongRef;
29#[lexicon]
32#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
33#[serde(rename_all = "camelCase", rename = "sh.weaver.collab.session", tag = "$type")]
34pub struct Session<'a> {
35 pub created_at: Datetime,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub expires_at: Option<Datetime>,
39 #[serde(borrow)]
41 pub node_id: CowStr<'a>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 #[serde(borrow)]
45 pub relay_url: Option<UriValue<'a>>,
46 #[serde(borrow)]
48 pub resource: StrongRef<'a>,
49}
50
51#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
54#[serde(rename_all = "camelCase")]
55pub struct SessionGetRecordOutput<'a> {
56 #[serde(skip_serializing_if = "Option::is_none")]
57 #[serde(borrow)]
58 pub cid: Option<Cid<'a>>,
59 #[serde(borrow)]
60 pub uri: AtUri<'a>,
61 #[serde(borrow)]
62 pub value: Session<'a>,
63}
64
65impl<'a> Session<'a> {
66 pub fn uri(
67 uri: impl Into<CowStr<'a>>,
68 ) -> Result<RecordUri<'a, SessionRecord>, UriError> {
69 RecordUri::try_from_uri(AtUri::new_cow(uri.into())?)
70 }
71}
72
73#[derive(Debug, Serialize, Deserialize)]
76pub struct SessionRecord;
77impl XrpcResp for SessionRecord {
78 const NSID: &'static str = "sh.weaver.collab.session";
79 const ENCODING: &'static str = "application/json";
80 type Output<'de> = SessionGetRecordOutput<'de>;
81 type Err<'de> = RecordError<'de>;
82}
83
84impl From<SessionGetRecordOutput<'_>> for Session<'_> {
85 fn from(output: SessionGetRecordOutput<'_>) -> Self {
86 use jacquard_common::IntoStatic;
87 output.value.into_static()
88 }
89}
90
91impl Collection for Session<'_> {
92 const NSID: &'static str = "sh.weaver.collab.session";
93 type Record = SessionRecord;
94}
95
96impl Collection for SessionRecord {
97 const NSID: &'static str = "sh.weaver.collab.session";
98 type Record = SessionRecord;
99}
100
101impl<'a> LexiconSchema for Session<'a> {
102 fn nsid() -> &'static str {
103 "sh.weaver.collab.session"
104 }
105 fn def_name() -> &'static str {
106 "main"
107 }
108 fn lexicon_doc() -> LexiconDoc<'static> {
109 lexicon_doc_sh_weaver_collab_session()
110 }
111 fn validate(&self) -> Result<(), ConstraintError> {
112 Ok(())
113 }
114}
115
116pub mod session_state {
117
118 pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
119 #[allow(unused)]
120 use ::core::marker::PhantomData;
121 mod sealed {
122 pub trait Sealed {}
123 }
124 pub trait State: sealed::Sealed {
126 type CreatedAt;
127 type Resource;
128 type NodeId;
129 }
130 pub struct Empty(());
132 impl sealed::Sealed for Empty {}
133 impl State for Empty {
134 type CreatedAt = Unset;
135 type Resource = Unset;
136 type NodeId = Unset;
137 }
138 pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>);
140 impl<S: State> sealed::Sealed for SetCreatedAt<S> {}
141 impl<S: State> State for SetCreatedAt<S> {
142 type CreatedAt = Set<members::created_at>;
143 type Resource = S::Resource;
144 type NodeId = S::NodeId;
145 }
146 pub struct SetResource<S: State = Empty>(PhantomData<fn() -> S>);
148 impl<S: State> sealed::Sealed for SetResource<S> {}
149 impl<S: State> State for SetResource<S> {
150 type CreatedAt = S::CreatedAt;
151 type Resource = Set<members::resource>;
152 type NodeId = S::NodeId;
153 }
154 pub struct SetNodeId<S: State = Empty>(PhantomData<fn() -> S>);
156 impl<S: State> sealed::Sealed for SetNodeId<S> {}
157 impl<S: State> State for SetNodeId<S> {
158 type CreatedAt = S::CreatedAt;
159 type Resource = S::Resource;
160 type NodeId = Set<members::node_id>;
161 }
162 #[allow(non_camel_case_types)]
164 pub mod members {
165 pub struct created_at(());
167 pub struct resource(());
169 pub struct node_id(());
171 }
172}
173
174pub struct SessionBuilder<'a, S: session_state::State> {
176 _state: PhantomData<fn() -> S>,
177 _fields: (
178 Option<Datetime>,
179 Option<Datetime>,
180 Option<CowStr<'a>>,
181 Option<UriValue<'a>>,
182 Option<StrongRef<'a>>,
183 ),
184 _lifetime: PhantomData<&'a ()>,
185}
186
187impl<'a> Session<'a> {
188 pub fn new() -> SessionBuilder<'a, session_state::Empty> {
190 SessionBuilder::new()
191 }
192}
193
194impl<'a> SessionBuilder<'a, session_state::Empty> {
195 pub fn new() -> Self {
197 SessionBuilder {
198 _state: PhantomData,
199 _fields: (None, None, None, None, None),
200 _lifetime: PhantomData,
201 }
202 }
203}
204
205impl<'a, S> SessionBuilder<'a, S>
206where
207 S: session_state::State,
208 S::CreatedAt: session_state::IsUnset,
209{
210 pub fn created_at(
212 mut self,
213 value: impl Into<Datetime>,
214 ) -> SessionBuilder<'a, session_state::SetCreatedAt<S>> {
215 self._fields.0 = Option::Some(value.into());
216 SessionBuilder {
217 _state: PhantomData,
218 _fields: self._fields,
219 _lifetime: PhantomData,
220 }
221 }
222}
223
224impl<'a, S: session_state::State> SessionBuilder<'a, S> {
225 pub fn expires_at(mut self, value: impl Into<Option<Datetime>>) -> Self {
227 self._fields.1 = value.into();
228 self
229 }
230 pub fn maybe_expires_at(mut self, value: Option<Datetime>) -> Self {
232 self._fields.1 = value;
233 self
234 }
235}
236
237impl<'a, S> SessionBuilder<'a, S>
238where
239 S: session_state::State,
240 S::NodeId: session_state::IsUnset,
241{
242 pub fn node_id(
244 mut self,
245 value: impl Into<CowStr<'a>>,
246 ) -> SessionBuilder<'a, session_state::SetNodeId<S>> {
247 self._fields.2 = Option::Some(value.into());
248 SessionBuilder {
249 _state: PhantomData,
250 _fields: self._fields,
251 _lifetime: PhantomData,
252 }
253 }
254}
255
256impl<'a, S: session_state::State> SessionBuilder<'a, S> {
257 pub fn relay_url(mut self, value: impl Into<Option<UriValue<'a>>>) -> Self {
259 self._fields.3 = value.into();
260 self
261 }
262 pub fn maybe_relay_url(mut self, value: Option<UriValue<'a>>) -> Self {
264 self._fields.3 = value;
265 self
266 }
267}
268
269impl<'a, S> SessionBuilder<'a, S>
270where
271 S: session_state::State,
272 S::Resource: session_state::IsUnset,
273{
274 pub fn resource(
276 mut self,
277 value: impl Into<StrongRef<'a>>,
278 ) -> SessionBuilder<'a, session_state::SetResource<S>> {
279 self._fields.4 = Option::Some(value.into());
280 SessionBuilder {
281 _state: PhantomData,
282 _fields: self._fields,
283 _lifetime: PhantomData,
284 }
285 }
286}
287
288impl<'a, S> SessionBuilder<'a, S>
289where
290 S: session_state::State,
291 S::CreatedAt: session_state::IsSet,
292 S::Resource: session_state::IsSet,
293 S::NodeId: session_state::IsSet,
294{
295 pub fn build(self) -> Session<'a> {
297 Session {
298 created_at: self._fields.0.unwrap(),
299 expires_at: self._fields.1,
300 node_id: self._fields.2.unwrap(),
301 relay_url: self._fields.3,
302 resource: self._fields.4.unwrap(),
303 extra_data: Default::default(),
304 }
305 }
306 pub fn build_with_data(
308 self,
309 extra_data: BTreeMap<
310 jacquard_common::deps::smol_str::SmolStr,
311 jacquard_common::types::value::Data<'a>,
312 >,
313 ) -> Session<'a> {
314 Session {
315 created_at: self._fields.0.unwrap(),
316 expires_at: self._fields.1,
317 node_id: self._fields.2.unwrap(),
318 relay_url: self._fields.3,
319 resource: self._fields.4.unwrap(),
320 extra_data: Some(extra_data),
321 }
322 }
323}
324
325fn lexicon_doc_sh_weaver_collab_session() -> LexiconDoc<'static> {
326 #[allow(unused_imports)]
327 use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
328 use jacquard_lexicon::lexicon::*;
329 use alloc::collections::BTreeMap;
330 LexiconDoc {
331 lexicon: Lexicon::Lexicon1,
332 id: CowStr::new_static("sh.weaver.collab.session"),
333 defs: {
334 let mut map = BTreeMap::new();
335 map.insert(
336 SmolStr::new_static("main"),
337 LexUserType::Record(LexRecord {
338 description: Some(
339 CowStr::new_static(
340 "Active real-time collaboration session. Published when joining a collaborative editing session, deleted on disconnect.",
341 ),
342 ),
343 key: Some(CowStr::new_static("tid")),
344 record: LexRecordRecord::Object(LexObject {
345 required: Some(
346 vec![
347 SmolStr::new_static("resource"),
348 SmolStr::new_static("nodeId"),
349 SmolStr::new_static("createdAt")
350 ],
351 ),
352 properties: {
353 #[allow(unused_mut)]
354 let mut map = BTreeMap::new();
355 map.insert(
356 SmolStr::new_static("createdAt"),
357 LexObjectProperty::String(LexString {
358 format: Some(LexStringFormat::Datetime),
359 ..Default::default()
360 }),
361 );
362 map.insert(
363 SmolStr::new_static("expiresAt"),
364 LexObjectProperty::String(LexString {
365 description: Some(
366 CowStr::new_static(
367 "Session TTL. Should be refreshed periodically while active.",
368 ),
369 ),
370 format: Some(LexStringFormat::Datetime),
371 ..Default::default()
372 }),
373 );
374 map.insert(
375 SmolStr::new_static("nodeId"),
376 LexObjectProperty::String(LexString {
377 description: Some(
378 CowStr::new_static(
379 "iroh NodeId in z-base32 encoding for P2P connection.",
380 ),
381 ),
382 ..Default::default()
383 }),
384 );
385 map.insert(
386 SmolStr::new_static("relayUrl"),
387 LexObjectProperty::String(LexString {
388 description: Some(
389 CowStr::new_static(
390 "DERP relay URL if using relay-only mode (browser clients).",
391 ),
392 ),
393 format: Some(LexStringFormat::Uri),
394 ..Default::default()
395 }),
396 );
397 map.insert(
398 SmolStr::new_static("resource"),
399 LexObjectProperty::Ref(LexRef {
400 r#ref: CowStr::new_static("com.atproto.repo.strongRef"),
401 ..Default::default()
402 }),
403 );
404 map
405 },
406 ..Default::default()
407 }),
408 ..Default::default()
409 }),
410 );
411 map
412 },
413 ..Default::default()
414 }
415}