forge_core/function/
traits.rs1use std::future::Future;
2use std::pin::Pin;
3
4use serde::{Serialize, de::DeserializeOwned};
5
6use super::context::{ActionContext, 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}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum FunctionKind {
42 Query,
43 Mutation,
44 Action,
45}
46
47impl std::fmt::Display for FunctionKind {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 FunctionKind::Query => write!(f, "query"),
51 FunctionKind::Mutation => write!(f, "mutation"),
52 FunctionKind::Action => write!(f, "action"),
53 }
54 }
55}
56
57pub trait ForgeQuery: Send + Sync + 'static {
66 type Args: DeserializeOwned + Serialize + Send + Sync;
68 type Output: Serialize + Send;
70
71 fn info() -> FunctionInfo;
73
74 fn execute(
76 ctx: &QueryContext,
77 args: Self::Args,
78 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
79}
80
81pub trait ForgeMutation: Send + Sync + 'static {
89 type Args: DeserializeOwned + Serialize + Send + Sync;
91 type Output: Serialize + Send;
93
94 fn info() -> FunctionInfo;
96
97 fn execute(
99 ctx: &MutationContext,
100 args: Self::Args,
101 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
102}
103
104pub trait ForgeAction: Send + Sync + 'static {
113 type Args: DeserializeOwned + Serialize + Send + Sync;
115 type Output: Serialize + Send;
117
118 fn info() -> FunctionInfo;
120
121 fn execute(
123 ctx: &ActionContext,
124 args: Self::Args,
125 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_function_kind_display() {
134 assert_eq!(format!("{}", FunctionKind::Query), "query");
135 assert_eq!(format!("{}", FunctionKind::Mutation), "mutation");
136 assert_eq!(format!("{}", FunctionKind::Action), "action");
137 }
138
139 #[test]
140 fn test_function_info() {
141 let info = FunctionInfo {
142 name: "get_user",
143 description: Some("Get a user by ID"),
144 kind: FunctionKind::Query,
145 requires_auth: true,
146 required_role: None,
147 is_public: false,
148 cache_ttl: Some(300),
149 timeout: Some(30),
150 rate_limit_requests: Some(100),
151 rate_limit_per_secs: Some(60),
152 rate_limit_key: Some("user"),
153 log_level: Some("debug"),
154 };
155
156 assert_eq!(info.name, "get_user");
157 assert_eq!(info.kind, FunctionKind::Query);
158 assert!(info.requires_auth);
159 assert_eq!(info.cache_ttl, Some(300));
160 assert_eq!(info.rate_limit_requests, Some(100));
161 assert_eq!(info.log_level, Some("debug"));
162 }
163}