use std::{future::Future, pin::Pin};
use fraiseql_error::Result;
use crate::host::HttpResponse;
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub trait DynHostContext: Send + Sync {
fn query(
&self,
graphql: &str,
variables: serde_json::Value,
) -> BoxFuture<'_, Result<serde_json::Value>>;
fn sql_query(
&self,
sql: &str,
params: &[serde_json::Value],
) -> BoxFuture<'_, Result<Vec<serde_json::Value>>>;
fn http_request(
&self,
method: &str,
url: &str,
headers: &[(String, String)],
body: Option<&[u8]>,
) -> BoxFuture<'_, Result<HttpResponse>>;
fn storage_get(&self, bucket: &str, key: &str) -> BoxFuture<'_, Result<Vec<u8>>>;
fn storage_put(
&self,
bucket: &str,
key: &str,
body: &[u8],
content_type: &str,
) -> BoxFuture<'_, Result<()>>;
fn auth_context(&self) -> Result<serde_json::Value>;
fn env_var(&self, name: &str) -> Result<Option<String>>;
fn event_payload(&self) -> &crate::types::EventPayload;
fn log(&self, level: crate::types::LogLevel, message: &str);
}
impl<T: crate::HostContext + Send + Sync> DynHostContext for T {
fn query(
&self,
graphql: &str,
variables: serde_json::Value,
) -> BoxFuture<'_, Result<serde_json::Value>> {
let graphql = graphql.to_string();
Box::pin(async move { crate::HostContext::query(self, &graphql, variables).await })
}
fn sql_query(
&self,
sql: &str,
params: &[serde_json::Value],
) -> BoxFuture<'_, Result<Vec<serde_json::Value>>> {
let sql = sql.to_string();
let params = params.to_vec();
Box::pin(async move { crate::HostContext::sql_query(self, &sql, ¶ms).await })
}
fn http_request(
&self,
method: &str,
url: &str,
headers: &[(String, String)],
body: Option<&[u8]>,
) -> BoxFuture<'_, Result<HttpResponse>> {
let method = method.to_string();
let url = url.to_string();
let headers = headers.to_vec();
let body = body.map(|b| b.to_vec());
Box::pin(async move {
crate::HostContext::http_request(self, &method, &url, &headers, body.as_deref()).await
})
}
fn storage_get(&self, bucket: &str, key: &str) -> BoxFuture<'_, Result<Vec<u8>>> {
let bucket = bucket.to_string();
let key = key.to_string();
Box::pin(async move { crate::HostContext::storage_get(self, &bucket, &key).await })
}
fn storage_put(
&self,
bucket: &str,
key: &str,
body: &[u8],
content_type: &str,
) -> BoxFuture<'_, Result<()>> {
let bucket = bucket.to_string();
let key = key.to_string();
let body = body.to_vec();
let content_type = content_type.to_string();
Box::pin(async move {
crate::HostContext::storage_put(self, &bucket, &key, &body, &content_type).await
})
}
fn auth_context(&self) -> Result<serde_json::Value> {
crate::HostContext::auth_context(self)
}
fn env_var(&self, name: &str) -> Result<Option<String>> {
crate::HostContext::env_var(self, name)
}
fn event_payload(&self) -> &crate::types::EventPayload {
crate::HostContext::event_payload(self)
}
fn log(&self, level: crate::types::LogLevel, message: &str) {
crate::HostContext::log(self, level, message);
}
}