forge_core/function/
traits.rs1use std::future::Future;
2use std::pin::Pin;
3
4use serde::{Serialize, de::DeserializeOwned};
5
6use super::context::{MutationContext, QueryContext};
7use crate::error::Result;
8
9#[derive(Debug, Clone)]
11pub struct FunctionInfo {
12 pub name: &'static str,
14 pub description: Option<&'static str>,
16 pub kind: FunctionKind,
18 pub required_role: Option<&'static str>,
20 pub is_public: bool,
22 pub cache_ttl: Option<u64>,
24 pub timeout: Option<u64>,
26 pub http_timeout: Option<u64>,
29 pub rate_limit_requests: Option<u32>,
31 pub rate_limit_per_secs: Option<u64>,
33 pub rate_limit_key: Option<&'static str>,
35 pub log_level: Option<&'static str>,
38 pub table_dependencies: &'static [&'static str],
41 pub selected_columns: &'static [&'static str],
45 pub transactional: bool,
49 pub consistent: bool,
53 pub max_upload_size_bytes: Option<usize>,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum FunctionKind {
60 Query,
61 Mutation,
62}
63
64impl std::fmt::Display for FunctionKind {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 FunctionKind::Query => write!(f, "query"),
68 FunctionKind::Mutation => write!(f, "mutation"),
69 }
70 }
71}
72
73pub trait ForgeQuery: Send + Sync + 'static {
82 type Args: DeserializeOwned + Serialize + Send + Sync;
84 type Output: Serialize + Send;
86
87 fn info() -> FunctionInfo;
89
90 fn execute(
92 ctx: &QueryContext,
93 args: Self::Args,
94 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
95}
96
97pub trait ForgeMutation: Send + Sync + 'static {
105 type Args: DeserializeOwned + Serialize + Send + Sync;
107 type Output: Serialize + Send;
109
110 fn info() -> FunctionInfo;
112
113 fn execute(
115 ctx: &MutationContext,
116 args: Self::Args,
117 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
118}
119
120#[cfg(test)]
121#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_function_kind_display() {
127 assert_eq!(format!("{}", FunctionKind::Query), "query");
128 assert_eq!(format!("{}", FunctionKind::Mutation), "mutation");
129 }
130
131 #[test]
132 fn test_function_info() {
133 let info = FunctionInfo {
134 name: "get_user",
135 description: Some("Get a user by ID"),
136 kind: FunctionKind::Query,
137 required_role: None,
138 is_public: false,
139 cache_ttl: Some(300),
140 timeout: Some(30),
141 http_timeout: Some(5),
142 rate_limit_requests: Some(100),
143 rate_limit_per_secs: Some(60),
144 rate_limit_key: Some("user"),
145 log_level: Some("debug"),
146 table_dependencies: &["users"],
147 selected_columns: &["id", "name", "email"],
148 transactional: false,
149 consistent: false,
150 max_upload_size_bytes: None,
151 };
152
153 assert_eq!(info.name, "get_user");
154 assert_eq!(info.kind, FunctionKind::Query);
155 assert_eq!(info.cache_ttl, Some(300));
156 assert_eq!(info.http_timeout, Some(5));
157 assert_eq!(info.rate_limit_requests, Some(100));
158 assert_eq!(info.log_level, Some("debug"));
159 assert_eq!(info.table_dependencies, &["users"]);
160 }
161}