use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::generated::api_types::CanvasAction;
pub type CanvasJsonSchema = serde_json::Map<String, Value>;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct CanvasDeclaration {
pub id: String,
pub display_name: String,
pub description: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub input_schema: Option<Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub actions: Option<Vec<CanvasAction>>,
}
impl CanvasDeclaration {
pub fn new(
id: impl Into<String>,
display_name: impl Into<String>,
description: impl Into<String>,
) -> Self {
Self {
id: id.into(),
display_name: display_name.into(),
description: description.into(),
input_schema: None,
actions: None,
}
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = description.into();
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct CanvasError {
pub code: String,
pub message: String,
}
impl std::fmt::Display for CanvasError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.code, self.message)
}
}
impl std::error::Error for CanvasError {}
impl CanvasError {
pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
Self {
code: code.into(),
message: message.into(),
}
}
pub fn no_handler() -> Self {
Self::new(
"canvas_action_no_handler",
"No handler implemented for this canvas action",
)
}
}
pub type CanvasResult<T> = Result<T, CanvasError>;
#[async_trait]
pub trait CanvasHandler: Send + Sync {
async fn on_open(
&self,
ctx: crate::generated::api_types::CanvasProviderOpenRequest,
) -> CanvasResult<crate::generated::api_types::CanvasProviderOpenResult>;
async fn on_action(
&self,
_ctx: crate::generated::api_types::CanvasProviderInvokeActionRequest,
) -> CanvasResult<Value> {
Err(CanvasError::no_handler())
}
async fn on_close(
&self,
_ctx: crate::generated::api_types::CanvasProviderCloseRequest,
) -> CanvasResult<()> {
Ok(())
}
}
#[cfg(test)]
mod tests;