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