forge_core/schema/
function.rs1use super::types::RustType;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum FunctionKind {
11 Query,
13 Mutation,
15 Job,
17 Cron,
19 Workflow,
21}
22
23impl FunctionKind {
24 pub fn as_str(&self) -> &'static str {
26 match self {
27 FunctionKind::Query => "query",
28 FunctionKind::Mutation => "mutation",
29 FunctionKind::Job => "job",
30 FunctionKind::Cron => "cron",
31 FunctionKind::Workflow => "workflow",
32 }
33 }
34
35 pub fn is_client_callable(&self) -> bool {
37 matches!(self, FunctionKind::Query | FunctionKind::Mutation)
38 }
39}
40
41impl std::fmt::Display for FunctionKind {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(f, "{}", self.as_str())
44 }
45}
46
47#[derive(Debug, Clone)]
49pub struct FunctionArg {
50 pub name: String,
52 pub rust_type: RustType,
54 pub doc: Option<String>,
56}
57
58impl FunctionArg {
59 pub fn new(name: impl Into<String>, rust_type: RustType) -> Self {
61 Self {
62 name: name.into(),
63 rust_type,
64 doc: None,
65 }
66 }
67}
68
69#[derive(Debug, Clone)]
71pub struct FunctionDef {
72 pub name: String,
74 pub kind: FunctionKind,
76 pub args: Vec<FunctionArg>,
78 pub return_type: RustType,
80 pub doc: Option<String>,
82 pub is_async: bool,
84}
85
86impl FunctionDef {
87 pub fn new(name: impl Into<String>, kind: FunctionKind, return_type: RustType) -> Self {
89 Self {
90 name: name.into(),
91 kind,
92 args: Vec::new(),
93 return_type,
94 doc: None,
95 is_async: true,
96 }
97 }
98
99 pub fn query(name: impl Into<String>, return_type: RustType) -> Self {
101 Self::new(name, FunctionKind::Query, return_type)
102 }
103
104 pub fn mutation(name: impl Into<String>, return_type: RustType) -> Self {
106 Self::new(name, FunctionKind::Mutation, return_type)
107 }
108
109 pub fn with_arg(mut self, arg: FunctionArg) -> Self {
111 self.args.push(arg);
112 self
113 }
114
115 pub fn with_doc(mut self, doc: impl Into<String>) -> Self {
117 self.doc = Some(doc.into());
118 self
119 }
120
121 pub fn ts_name(&self) -> String {
123 crate::util::to_camel_case(&self.name)
124 }
125}
126
127#[cfg(test)]
128#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_function_def_query() {
134 let func = FunctionDef::query("get_user", RustType::Custom("User".to_string()))
135 .with_arg(FunctionArg::new("id", RustType::Uuid))
136 .with_doc("Get a user by ID");
137
138 assert_eq!(func.name, "get_user");
139 assert_eq!(func.kind, FunctionKind::Query);
140 assert_eq!(func.args.len(), 1);
141 assert_eq!(func.ts_name(), "getUser");
142 }
143
144 #[test]
145 fn test_function_def_mutation() {
146 let func = FunctionDef::mutation("create_user", RustType::Custom("User".to_string()));
147 assert_eq!(func.kind, FunctionKind::Mutation);
148 }
149
150 #[test]
151 fn test_to_camel_case() {
152 use crate::util::to_camel_case;
153 assert_eq!(to_camel_case("get_user"), "getUser");
154 assert_eq!(to_camel_case("create_project_task"), "createProjectTask");
155 assert_eq!(to_camel_case("getUser"), "getUser");
156 }
157}