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 rate_limit_requests: Option<u32>,
28 pub rate_limit_per_secs: Option<u64>,
30 pub rate_limit_key: Option<&'static str>,
32 pub log_level: Option<&'static str>,
35 pub table_dependencies: &'static [&'static str],
38 pub selected_columns: &'static [&'static str],
42 pub transactional: bool,
46 pub consistent: bool,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum FunctionKind {
55 Query,
56 Mutation,
57}
58
59impl std::fmt::Display for FunctionKind {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 match self {
62 FunctionKind::Query => write!(f, "query"),
63 FunctionKind::Mutation => write!(f, "mutation"),
64 }
65 }
66}
67
68pub trait ForgeQuery: Send + Sync + 'static {
77 type Args: DeserializeOwned + Serialize + Send + Sync;
79 type Output: Serialize + Send;
81
82 fn info() -> FunctionInfo;
84
85 fn execute(
87 ctx: &QueryContext,
88 args: Self::Args,
89 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
90}
91
92pub trait ForgeMutation: Send + Sync + 'static {
100 type Args: DeserializeOwned + Serialize + Send + Sync;
102 type Output: Serialize + Send;
104
105 fn info() -> FunctionInfo;
107
108 fn execute(
110 ctx: &MutationContext,
111 args: Self::Args,
112 ) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
113}
114
115#[cfg(test)]
116#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_function_kind_display() {
122 assert_eq!(format!("{}", FunctionKind::Query), "query");
123 assert_eq!(format!("{}", FunctionKind::Mutation), "mutation");
124 }
125
126 #[test]
127 fn test_function_info() {
128 let info = FunctionInfo {
129 name: "get_user",
130 description: Some("Get a user by ID"),
131 kind: FunctionKind::Query,
132 required_role: None,
133 is_public: false,
134 cache_ttl: Some(300),
135 timeout: Some(30),
136 rate_limit_requests: Some(100),
137 rate_limit_per_secs: Some(60),
138 rate_limit_key: Some("user"),
139 log_level: Some("debug"),
140 table_dependencies: &["users"],
141 selected_columns: &["id", "name", "email"],
142 transactional: false,
143 consistent: false,
144 };
145
146 assert_eq!(info.name, "get_user");
147 assert_eq!(info.kind, FunctionKind::Query);
148 assert_eq!(info.cache_ttl, Some(300));
149 assert_eq!(info.rate_limit_requests, Some(100));
150 assert_eq!(info.log_level, Some("debug"));
151 assert_eq!(info.table_dependencies, &["users"]);
152 }
153}