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}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum FunctionKind {
39 Query,
40 Mutation,
41 Action,
42}
43
44impl std::fmt::Display for FunctionKind {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 match self {
47 FunctionKind::Query => write!(f, "query"),
48 FunctionKind::Mutation => write!(f, "mutation"),
49 FunctionKind::Action => write!(f, "action"),
50 }
51 }
52}
53
54pub trait ForgeQuery: Send + Sync + 'static {
63 type Args: DeserializeOwned + Serialize + Send + Sync;
65 type Output: Serialize + Send;
67
68 fn info() -> FunctionInfo;
70
71 fn execute(
73 ctx: &QueryContext,
74 args: Self::Args,
75 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
76}
77
78pub trait ForgeMutation: Send + Sync + 'static {
86 type Args: DeserializeOwned + Serialize + Send + Sync;
88 type Output: Serialize + Send;
90
91 fn info() -> FunctionInfo;
93
94 fn execute(
96 ctx: &MutationContext,
97 args: Self::Args,
98 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
99}
100
101pub trait ForgeAction: Send + Sync + 'static {
110 type Args: DeserializeOwned + Serialize + Send + Sync;
112 type Output: Serialize + Send;
114
115 fn info() -> FunctionInfo;
117
118 fn execute(
120 ctx: &ActionContext,
121 args: Self::Args,
122 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_function_kind_display() {
131 assert_eq!(format!("{}", FunctionKind::Query), "query");
132 assert_eq!(format!("{}", FunctionKind::Mutation), "mutation");
133 assert_eq!(format!("{}", FunctionKind::Action), "action");
134 }
135
136 #[test]
137 fn test_function_info() {
138 let info = FunctionInfo {
139 name: "get_user",
140 description: Some("Get a user by ID"),
141 kind: FunctionKind::Query,
142 requires_auth: true,
143 required_role: None,
144 is_public: false,
145 cache_ttl: Some(300),
146 timeout: Some(30),
147 rate_limit_requests: Some(100),
148 rate_limit_per_secs: Some(60),
149 rate_limit_key: Some("user"),
150 };
151
152 assert_eq!(info.name, "get_user");
153 assert_eq!(info.kind, FunctionKind::Query);
154 assert!(info.requires_auth);
155 assert_eq!(info.cache_ttl, Some(300));
156 assert_eq!(info.rate_limit_requests, Some(100));
157 }
158}