Skip to main content

seam_server/
lib.rs

1/* src/server/core/rust/src/lib.rs */
2#![cfg_attr(test, allow(clippy::unwrap_used))]
3
4pub mod build_loader;
5pub mod channel;
6pub mod context;
7pub mod errors;
8pub mod escape;
9pub mod manifest;
10pub mod page;
11pub mod procedure;
12pub mod resolve;
13pub mod server;
14
15// Re-exports for ergonomic use
16pub use build_loader::{RpcHashMap, load_build_output, load_i18n_config, load_rpc_hash_map};
17pub use channel::{ChannelDef, ChannelMeta, IncomingDef, IncomingMeta};
18pub use context::{
19  ContextConfig, ContextFieldDef, RawContextMap, context_extract_keys, context_keys_from_schema,
20  resolve_context,
21};
22pub use errors::SeamError;
23pub use escape::ascii_escape_json;
24pub use page::I18nConfig;
25pub use procedure::{BoxFuture, BoxStream, ProcedureDef, ProcedureType, SubscriptionDef};
26pub use resolve::{
27  ResolveData, ResolveStrategy, default_strategies, from_accept_language, from_cookie,
28  from_url_prefix, from_url_query, resolve_chain,
29};
30pub use seam_macros::{SeamType, seam_command, seam_procedure, seam_subscription};
31pub use server::{SeamParts, SeamServer};
32
33/// Trait for types that can describe themselves as a JTD schema.
34/// Derive with `#[derive(SeamType)]` or implement manually.
35pub trait SeamType {
36  fn jtd_schema() -> serde_json::Value;
37}
38
39// -- Primitive SeamType impls --
40
41macro_rules! impl_seam_type_primitive {
42  ($rust_ty:ty, $jtd:expr_2021) => {
43    impl SeamType for $rust_ty {
44      fn jtd_schema() -> serde_json::Value {
45        serde_json::json!({ "type": $jtd })
46      }
47    }
48  };
49}
50
51impl_seam_type_primitive!(String, "string");
52impl_seam_type_primitive!(bool, "boolean");
53impl_seam_type_primitive!(i8, "int8");
54impl_seam_type_primitive!(i16, "int16");
55impl_seam_type_primitive!(i32, "int32");
56impl_seam_type_primitive!(u8, "uint8");
57impl_seam_type_primitive!(u16, "uint16");
58impl_seam_type_primitive!(u32, "uint32");
59impl_seam_type_primitive!(f32, "float32");
60impl_seam_type_primitive!(f64, "float64");
61
62impl<T: SeamType> SeamType for Vec<T> {
63  fn jtd_schema() -> serde_json::Value {
64    serde_json::json!({ "elements": T::jtd_schema() })
65  }
66}
67
68impl<T: SeamType> SeamType for Option<T> {
69  fn jtd_schema() -> serde_json::Value {
70    let mut schema = T::jtd_schema();
71    if let Some(obj) = schema.as_object_mut() {
72      obj.insert("nullable".to_string(), serde_json::Value::Bool(true));
73    }
74    schema
75  }
76}
77
78impl<T: SeamType> SeamType for std::collections::HashMap<String, T> {
79  fn jtd_schema() -> serde_json::Value {
80    serde_json::json!({ "values": T::jtd_schema() })
81  }
82}
83
84impl<T: SeamType> SeamType for std::collections::BTreeMap<String, T> {
85  fn jtd_schema() -> serde_json::Value {
86    serde_json::json!({ "values": T::jtd_schema() })
87  }
88}
89
90#[cfg(test)]
91extern crate self as seam_server;
92
93#[cfg(test)]
94mod tests {
95  use super::*;
96
97  #[test]
98  fn primitive_schemas() {
99    assert_eq!(String::jtd_schema(), serde_json::json!({"type": "string"}));
100    assert_eq!(bool::jtd_schema(), serde_json::json!({"type": "boolean"}));
101    assert_eq!(i32::jtd_schema(), serde_json::json!({"type": "int32"}));
102    assert_eq!(u32::jtd_schema(), serde_json::json!({"type": "uint32"}));
103    assert_eq!(f64::jtd_schema(), serde_json::json!({"type": "float64"}));
104  }
105
106  #[test]
107  fn vec_schema() {
108    assert_eq!(Vec::<String>::jtd_schema(), serde_json::json!({"elements": {"type": "string"}}),);
109  }
110
111  #[test]
112  fn option_schema() {
113    assert_eq!(
114      Option::<String>::jtd_schema(),
115      serde_json::json!({"type": "string", "nullable": true}),
116    );
117  }
118
119  #[test]
120  fn hashmap_schema() {
121    assert_eq!(
122      std::collections::HashMap::<String, f64>::jtd_schema(),
123      serde_json::json!({"values": {"type": "float64"}}),
124    );
125  }
126
127  #[derive(SeamType)]
128  #[allow(dead_code)]
129  enum Role {
130    Admin,
131    Member,
132    Guest,
133  }
134
135  #[test]
136  fn enum_schema() {
137    assert_eq!(Role::jtd_schema(), serde_json::json!({"enum": ["admin", "member", "guest"]}),);
138  }
139}