1pub mod error;
6pub mod extract;
7
8pub use error::{ErrorCode, ErrorResponse, IntoErrorCode, SchemaValidationError};
9pub use extract::Context;
10
11#[cfg(feature = "ws")]
12pub use extract::WsSender;
13
14#[derive(Debug, Clone)]
17pub struct MethodInfo {
18 pub name: String,
20 pub docs: Option<String>,
22 pub params: Vec<ParamInfo>,
24 pub return_type: String,
26 pub is_async: bool,
28 pub is_streaming: bool,
30 pub is_optional: bool,
32 pub is_result: bool,
34}
35
36#[derive(Debug, Clone)]
38pub struct ParamInfo {
39 pub name: String,
41 pub ty: String,
43 pub is_optional: bool,
45 pub is_id: bool,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum HttpMethod {
52 Get,
53 Post,
54 Put,
55 Patch,
56 Delete,
57}
58
59impl HttpMethod {
60 pub fn infer_from_name(name: &str) -> Self {
62 if name.starts_with("get_")
63 || name.starts_with("fetch_")
64 || name.starts_with("read_")
65 || name.starts_with("list_")
66 || name.starts_with("find_")
67 || name.starts_with("search_")
68 {
69 HttpMethod::Get
70 } else if name.starts_with("create_")
71 || name.starts_with("add_")
72 || name.starts_with("new_")
73 {
74 HttpMethod::Post
75 } else if name.starts_with("update_") || name.starts_with("set_") {
76 HttpMethod::Put
77 } else if name.starts_with("patch_") || name.starts_with("modify_") {
78 HttpMethod::Patch
79 } else if name.starts_with("delete_") || name.starts_with("remove_") {
80 HttpMethod::Delete
81 } else {
82 HttpMethod::Post
84 }
85 }
86
87 pub fn as_str(&self) -> &'static str {
88 match self {
89 HttpMethod::Get => "GET",
90 HttpMethod::Post => "POST",
91 HttpMethod::Put => "PUT",
92 HttpMethod::Patch => "PATCH",
93 HttpMethod::Delete => "DELETE",
94 }
95 }
96}
97
98pub fn infer_path(method_name: &str, http_method: HttpMethod) -> String {
100 let resource = method_name
102 .strip_prefix("get_")
103 .or_else(|| method_name.strip_prefix("fetch_"))
104 .or_else(|| method_name.strip_prefix("read_"))
105 .or_else(|| method_name.strip_prefix("list_"))
106 .or_else(|| method_name.strip_prefix("find_"))
107 .or_else(|| method_name.strip_prefix("search_"))
108 .or_else(|| method_name.strip_prefix("create_"))
109 .or_else(|| method_name.strip_prefix("add_"))
110 .or_else(|| method_name.strip_prefix("new_"))
111 .or_else(|| method_name.strip_prefix("update_"))
112 .or_else(|| method_name.strip_prefix("set_"))
113 .or_else(|| method_name.strip_prefix("patch_"))
114 .or_else(|| method_name.strip_prefix("modify_"))
115 .or_else(|| method_name.strip_prefix("delete_"))
116 .or_else(|| method_name.strip_prefix("remove_"))
117 .unwrap_or(method_name);
118
119 let path_resource = if resource.ends_with('s') {
121 resource.to_string()
122 } else {
123 format!("{resource}s")
124 };
125
126 match http_method {
127 HttpMethod::Post => format!("/{path_resource}"),
129 HttpMethod::Get
130 if method_name.starts_with("list_")
131 || method_name.starts_with("search_")
132 || method_name.starts_with("find_") =>
133 {
134 format!("/{path_resource}")
135 }
136 HttpMethod::Get | HttpMethod::Put | HttpMethod::Patch | HttpMethod::Delete => {
138 format!("/{path_resource}/{{id}}")
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_http_method_inference() {
149 assert_eq!(HttpMethod::infer_from_name("get_user"), HttpMethod::Get);
150 assert_eq!(HttpMethod::infer_from_name("list_users"), HttpMethod::Get);
151 assert_eq!(HttpMethod::infer_from_name("create_user"), HttpMethod::Post);
152 assert_eq!(HttpMethod::infer_from_name("update_user"), HttpMethod::Put);
153 assert_eq!(
154 HttpMethod::infer_from_name("delete_user"),
155 HttpMethod::Delete
156 );
157 assert_eq!(
158 HttpMethod::infer_from_name("do_something"),
159 HttpMethod::Post
160 ); }
162
163 #[test]
164 fn test_path_inference() {
165 assert_eq!(infer_path("create_user", HttpMethod::Post), "/users");
166 assert_eq!(infer_path("get_user", HttpMethod::Get), "/users/{id}");
167 assert_eq!(infer_path("list_users", HttpMethod::Get), "/users");
168 assert_eq!(infer_path("delete_user", HttpMethod::Delete), "/users/{id}");
169 }
170}