zod_core/rpc/codegen/
mod.rs

1pub trait ClientCodegen {
2    fn get() -> String;
3}
4
5type RuntimeValue<T> = &'static (dyn Fn() -> T + Sync);
6
7pub trait RpcNamespace: crate::Namespace {
8    type Req: serde::de::DeserializeOwned;
9
10    fn rpc_members() -> Vec<&'static RpcMember> {
11        inventory::iter::<RpcMember>()
12            .filter(|member| member.ns_name() == Self::NAME)
13            .collect()
14    }
15}
16
17pub struct RpcArgument {
18    name: &'static str,
19    type_def: String,
20    schema: String,
21}
22
23impl RpcArgument {
24    pub fn new<T: crate::ZodType>(name: &'static str) -> Self {
25        Self {
26            name,
27            type_def: T::type_def().to_string(),
28            schema: T::schema(),
29        }
30    }
31}
32
33pub enum RpcMember {
34    Method {
35        ns_name: &'static str,
36        name: &'static str,
37        args: RuntimeValue<Vec<RpcArgument>>,
38        res: RuntimeValue<String>,
39    },
40    Stream {
41        ns_name: &'static str,
42        name: &'static str,
43        args: RuntimeValue<Vec<RpcArgument>>,
44        res: RuntimeValue<String>,
45    },
46}
47
48inventory::collect!(RpcMember);
49
50impl RpcMember {
51    pub fn decl(&self) -> String {
52        match self {
53            RpcMember::Method {
54                name,
55                args,
56                res,
57                ns_name,
58                ..
59            } => {
60                let args = (args)();
61                let res = (res)();
62
63                let arg_fields = args
64                    .iter()
65                    .map(|arg| format!("{}: {}", arg.name, arg.type_def))
66                    .collect::<Vec<_>>()
67                    .join(",");
68
69                let arg_zod = args
70                    .iter()
71                    .map(|arg| arg.schema.to_owned())
72                    .collect::<Vec<_>>()
73                    .join(",");
74
75                format!(
76                    "
77                    // @ts-ignore
78                    export async function {name}({arg_fields}): Promise<{res}> {{
79                    z.tuple([{arg_zod}]).parse([...arguments]);
80                    return request(\"{ns_name}\", \"{name}\", arguments);
81                }};"
82                )
83            }
84            RpcMember::Stream {
85                name,
86                args,
87                res,
88                ns_name,
89                ..
90            } => {
91                let args = (args)();
92                let res = (res)();
93
94                let arg_fields = args
95                    .iter()
96                    .map(|arg| format!("{}: {}", arg.name, arg.type_def))
97                    .collect::<Vec<_>>()
98                    .join(",");
99
100                let arg_zod = args
101                    .iter()
102                    .map(|arg| arg.schema.to_owned())
103                    .collect::<Vec<_>>()
104                    .join(",");
105
106                format!(
107                    "
108                    // @ts-ignore
109                    export function {name}({arg_fields}): Store<{res}> {{
110                    z.tuple([{arg_zod}]).parse([...arguments]);
111                    return subscribe(\"{ns_name}\", \"{name}\", arguments);
112                }};"
113                )
114            }
115        }
116    }
117
118    pub fn ns_name(&self) -> &str {
119        match self {
120            RpcMember::Method { ns_name, .. } => ns_name,
121            RpcMember::Stream { ns_name, .. } => ns_name,
122        }
123    }
124}
125
126#[doc(hidden)]
127/// marker trait for better errors
128pub trait RpcHandler {}