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 requires_auth: bool,
20 pub required_role: Option<&'static str>,
22 pub is_public: bool,
24 pub cache_ttl: Option<u64>,
26 pub timeout: Option<u64>,
28 pub rate_limit_requests: Option<u32>,
30 pub rate_limit_per_secs: Option<u64>,
32 pub rate_limit_key: Option<&'static str>,
34 pub log_level: Option<&'static str>,
37 pub table_dependencies: &'static [&'static str],
40 pub transactional: bool,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum FunctionKind {
49 Query,
50 Mutation,
51}
52
53impl std::fmt::Display for FunctionKind {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 match self {
56 FunctionKind::Query => write!(f, "query"),
57 FunctionKind::Mutation => write!(f, "mutation"),
58 }
59 }
60}
61
62pub trait ForgeQuery: Send + Sync + 'static {
71 type Args: DeserializeOwned + Serialize + Send + Sync;
73 type Output: Serialize + Send;
75
76 fn info() -> FunctionInfo;
78
79 fn execute(
81 ctx: &QueryContext,
82 args: Self::Args,
83 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
84}
85
86pub trait ForgeMutation: Send + Sync + 'static {
94 type Args: DeserializeOwned + Serialize + Send + Sync;
96 type Output: Serialize + Send;
98
99 fn info() -> FunctionInfo;
101
102 fn execute(
104 ctx: &MutationContext,
105 args: Self::Args,
106 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_function_kind_display() {
115 assert_eq!(format!("{}", FunctionKind::Query), "query");
116 assert_eq!(format!("{}", FunctionKind::Mutation), "mutation");
117 }
118
119 #[test]
120 fn test_function_info() {
121 let info = FunctionInfo {
122 name: "get_user",
123 description: Some("Get a user by ID"),
124 kind: FunctionKind::Query,
125 requires_auth: true,
126 required_role: None,
127 is_public: false,
128 cache_ttl: Some(300),
129 timeout: Some(30),
130 rate_limit_requests: Some(100),
131 rate_limit_per_secs: Some(60),
132 rate_limit_key: Some("user"),
133 log_level: Some("debug"),
134 table_dependencies: &["users"],
135 transactional: false,
136 };
137
138 assert_eq!(info.name, "get_user");
139 assert_eq!(info.kind, FunctionKind::Query);
140 assert!(info.requires_auth);
141 assert_eq!(info.cache_ttl, Some(300));
142 assert_eq!(info.rate_limit_requests, Some(100));
143 assert_eq!(info.log_level, Some("debug"));
144 assert_eq!(info.table_dependencies, &["users"]);
145 }
146}