1#![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;
14pub mod validation;
15
16pub use build_loader::{RpcHashMap, load_build_output, load_i18n_config, load_rpc_hash_map};
18pub use channel::{ChannelDef, ChannelMeta, IncomingDef, IncomingMeta};
19pub use context::{
20 ContextConfig, ContextFieldDef, RawContextMap, context_has_extracts, context_keys_from_schema,
21 extract_raw_context, parse_cookie_header, resolve_context,
22};
23pub use errors::SeamError;
24pub use escape::ascii_escape_json;
25pub use page::I18nConfig;
26pub use procedure::{
27 BoxFuture, BoxStream, ProcedureDef, ProcedureType, SeamFileHandle, StreamDef, StreamHandlerFn,
28 StreamParams, SubscriptionDef, SubscriptionParams, UploadDef, UploadHandlerFn,
29};
30pub use resolve::{
31 ResolveData, ResolveStrategy, default_strategies, from_accept_language, from_cookie,
32 from_url_prefix, from_url_query, resolve_chain,
33};
34pub use seam_macros::{SeamType, seam_command, seam_procedure, seam_subscription};
35pub use seam_macros::{seam_stream, seam_upload};
36pub use server::{SeamParts, SeamServer, TransportConfig};
37pub use validation::{
38 CompiledSchema, ValidationDetail, ValidationMode, compile_schema, should_validate,
39 validate_compiled, validate_input,
40};
41
42pub trait SeamType {
45 fn jtd_schema() -> serde_json::Value;
46}
47
48macro_rules! impl_seam_type_primitive {
51 ($rust_ty:ty, $jtd:expr_2021) => {
52 impl SeamType for $rust_ty {
53 fn jtd_schema() -> serde_json::Value {
54 serde_json::json!({ "type": $jtd })
55 }
56 }
57 };
58}
59
60impl_seam_type_primitive!(String, "string");
61impl_seam_type_primitive!(bool, "boolean");
62impl_seam_type_primitive!(i8, "int8");
63impl_seam_type_primitive!(i16, "int16");
64impl_seam_type_primitive!(i32, "int32");
65impl_seam_type_primitive!(u8, "uint8");
66impl_seam_type_primitive!(u16, "uint16");
67impl_seam_type_primitive!(u32, "uint32");
68impl_seam_type_primitive!(f32, "float32");
69impl_seam_type_primitive!(f64, "float64");
70
71impl<T: SeamType> SeamType for Vec<T> {
72 fn jtd_schema() -> serde_json::Value {
73 serde_json::json!({ "elements": T::jtd_schema() })
74 }
75}
76
77impl<T: SeamType> SeamType for Option<T> {
78 fn jtd_schema() -> serde_json::Value {
79 let mut schema = T::jtd_schema();
80 if let Some(obj) = schema.as_object_mut() {
81 obj.insert("nullable".to_string(), serde_json::Value::Bool(true));
82 }
83 schema
84 }
85}
86
87impl<T: SeamType> SeamType for std::collections::HashMap<String, T> {
88 fn jtd_schema() -> serde_json::Value {
89 serde_json::json!({ "values": T::jtd_schema() })
90 }
91}
92
93impl<T: SeamType> SeamType for std::collections::BTreeMap<String, T> {
94 fn jtd_schema() -> serde_json::Value {
95 serde_json::json!({ "values": T::jtd_schema() })
96 }
97}
98
99#[cfg(test)]
100extern crate self as seam_server;
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn primitive_schemas() {
108 assert_eq!(String::jtd_schema(), serde_json::json!({"type": "string"}));
109 assert_eq!(bool::jtd_schema(), serde_json::json!({"type": "boolean"}));
110 assert_eq!(i32::jtd_schema(), serde_json::json!({"type": "int32"}));
111 assert_eq!(u32::jtd_schema(), serde_json::json!({"type": "uint32"}));
112 assert_eq!(f64::jtd_schema(), serde_json::json!({"type": "float64"}));
113 }
114
115 #[test]
116 fn vec_schema() {
117 assert_eq!(Vec::<String>::jtd_schema(), serde_json::json!({"elements": {"type": "string"}}),);
118 }
119
120 #[test]
121 fn option_schema() {
122 assert_eq!(
123 Option::<String>::jtd_schema(),
124 serde_json::json!({"type": "string", "nullable": true}),
125 );
126 }
127
128 #[test]
129 fn hashmap_schema() {
130 assert_eq!(
131 std::collections::HashMap::<String, f64>::jtd_schema(),
132 serde_json::json!({"values": {"type": "float64"}}),
133 );
134 }
135
136 #[derive(SeamType)]
137 #[allow(dead_code)]
138 enum Role {
139 Admin,
140 Member,
141 Guest,
142 }
143
144 #[test]
145 fn enum_schema() {
146 assert_eq!(Role::jtd_schema(), serde_json::json!({"enum": ["admin", "member", "guest"]}),);
147 }
148}