use std::future::Future;
use std::pin::Pin;
use serde::{Serialize, de::DeserializeOwned};
use super::context::{MutationContext, QueryContext};
use crate::error::Result;
#[derive(Debug, Clone)]
pub struct FunctionInfo {
pub name: &'static str,
pub description: Option<&'static str>,
pub kind: FunctionKind,
pub required_role: Option<&'static str>,
pub is_public: bool,
pub cache_ttl: Option<u64>,
pub timeout: Option<u64>,
pub http_timeout: Option<u64>,
pub rate_limit_requests: Option<u32>,
pub rate_limit_per_secs: Option<u64>,
pub rate_limit_key: Option<&'static str>,
pub log_level: Option<&'static str>,
pub table_dependencies: &'static [&'static str],
pub selected_columns: &'static [&'static str],
pub transactional: bool,
pub consistent: bool,
pub max_upload_size_bytes: Option<usize>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FunctionKind {
Query,
Mutation,
}
impl std::fmt::Display for FunctionKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FunctionKind::Query => write!(f, "query"),
FunctionKind::Mutation => write!(f, "mutation"),
}
}
}
pub trait ForgeQuery: Send + Sync + 'static {
type Args: DeserializeOwned + Serialize + Send + Sync;
type Output: Serialize + Send;
fn info() -> FunctionInfo;
fn execute(
ctx: &QueryContext,
args: Self::Args,
) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
}
pub trait ForgeMutation: Send + Sync + 'static {
type Args: DeserializeOwned + Serialize + Send + Sync;
type Output: Serialize + Send;
fn info() -> FunctionInfo;
fn execute(
ctx: &MutationContext,
args: Self::Args,
) -> Pin<Box<dyn Future<Output = Result<Self::Output>> + Send + '_>>;
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
mod tests {
use super::*;
#[test]
fn test_function_kind_display() {
assert_eq!(format!("{}", FunctionKind::Query), "query");
assert_eq!(format!("{}", FunctionKind::Mutation), "mutation");
}
#[test]
fn test_function_info() {
let info = FunctionInfo {
name: "get_user",
description: Some("Get a user by ID"),
kind: FunctionKind::Query,
required_role: None,
is_public: false,
cache_ttl: Some(300),
timeout: Some(30),
http_timeout: Some(5),
rate_limit_requests: Some(100),
rate_limit_per_secs: Some(60),
rate_limit_key: Some("user"),
log_level: Some("debug"),
table_dependencies: &["users"],
selected_columns: &["id", "name", "email"],
transactional: false,
consistent: false,
max_upload_size_bytes: None,
};
assert_eq!(info.name, "get_user");
assert_eq!(info.kind, FunctionKind::Query);
assert_eq!(info.cache_ttl, Some(300));
assert_eq!(info.http_timeout, Some(5));
assert_eq!(info.rate_limit_requests, Some(100));
assert_eq!(info.log_level, Some("debug"));
assert_eq!(info.table_dependencies, &["users"]);
}
}