use crate::domain::{ExtractionRequest, ExtractionResult, ExtractionTemplate, IdempotencyKey};
use async_trait::async_trait;
#[async_trait]
pub trait PluginTemplateStore: Send + Sync {
async fn save(&self, template: &ExtractionTemplate) -> crate::Result<()>;
async fn get(&self, id: &uuid::Uuid) -> crate::Result<ExtractionTemplate>;
async fn list(&self) -> crate::Result<Vec<ExtractionTemplate>>;
async fn delete(&self, id: &uuid::Uuid) -> crate::Result<()>;
async fn search(&self, query: &str) -> crate::Result<Vec<ExtractionTemplate>> {
let all = self.list().await?;
let results = all
.into_iter()
.filter(|t| t.name.to_lowercase().contains(&query.to_lowercase()))
.collect();
Ok(results)
}
}
#[async_trait]
pub trait PluginExtractionPort: Send + Sync {
async fn execute(&self, request: &ExtractionRequest) -> crate::Result<ExtractionResult>;
async fn validate_selector(
&self,
_html: &str,
_selector_expr: &str,
) -> crate::Result<(bool, usize)> {
Ok((true, 0))
}
}
#[async_trait]
pub trait IdempotencyKeyStore: Send + Sync {
async fn store_result(
&self,
key: &IdempotencyKey,
result: &ExtractionResult,
) -> crate::Result<()>;
async fn get_result(&self, key: &IdempotencyKey) -> crate::Result<Option<ExtractionResult>>;
async fn delete_result(&self, key: &IdempotencyKey) -> crate::Result<()>;
async fn clear_all(&self) -> crate::Result<()>;
}
#[async_trait]
pub trait PluginRecordingPort: Send + Sync {
async fn start_recording(&self) -> crate::Result<String>;
async fn record_element_click(
&self,
session_id: &str,
element_info: serde_json::Value,
) -> crate::Result<()>;
async fn finalize_recording(
&self,
session_id: &str,
template_name: &str,
) -> crate::Result<ExtractionTemplate>;
async fn cancel_recording(&self, session_id: &str) -> crate::Result<()>;
}