Refine shared plugin event routing API

This commit is contained in:
Gregory Schier
2026-02-20 08:30:41 -08:00
parent a4f96fca11
commit 39fc9e81cd
3 changed files with 81 additions and 96 deletions

View File

@@ -1,8 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use yaak::plugin_events::{ use yaak::plugin_events::{
GroupedPluginEvent, HostRequest, SharedEvent, SharedPluginEventContext, GroupedPluginEvent, HostRequest, SharedPluginEventContext, handle_shared_plugin_event,
handle_shared_plugin_event,
}; };
use yaak_models::query_manager::QueryManager; use yaak_models::query_manager::QueryManager;
use yaak_plugins::events::{ use yaak_plugins::events::{
@@ -75,36 +74,37 @@ fn build_plugin_reply(
workspace_id: event.context.workspace_id.as_deref(), workspace_id: event.context.workspace_id.as_deref(),
}, },
) { ) {
GroupedPluginEvent::Shared(SharedEvent::Reply(payload)) => Some(payload), GroupedPluginEvent::Handled(payload) => payload,
GroupedPluginEvent::Shared(SharedEvent::ErrorResponse(resp)) => { GroupedPluginEvent::ToHandle(host_request) => match host_request {
eprintln!("[plugin:{}] error: {}", plugin_name, resp.error); HostRequest::ErrorResponse(resp) => {
None eprintln!("[plugin:{}] error: {}", plugin_name, resp.error);
} None
GroupedPluginEvent::Shared(SharedEvent::ReloadResponse(_)) => None, }
GroupedPluginEvent::Host(HostRequest::ShowToast(req)) => { HostRequest::ReloadResponse(_) => None,
eprintln!("[plugin:{}] {}", plugin_name, req.message); HostRequest::ShowToast(req) => {
Some(InternalEventPayload::ShowToastResponse(EmptyPayload {})) eprintln!("[plugin:{}] {}", plugin_name, req.message);
} Some(InternalEventPayload::ShowToastResponse(EmptyPayload {}))
GroupedPluginEvent::Host(HostRequest::ListOpenWorkspaces(_)) => { }
let workspaces = match query_manager.connect().list_workspaces() { HostRequest::ListOpenWorkspaces(_) => {
Ok(workspaces) => workspaces let workspaces = match query_manager.connect().list_workspaces() {
.into_iter() Ok(workspaces) => workspaces
.map(|w| WorkspaceInfo { id: w.id.clone(), name: w.name, label: w.id }) .into_iter()
.collect(), .map(|w| WorkspaceInfo { id: w.id.clone(), name: w.name, label: w.id })
Err(err) => { .collect(),
return Some(InternalEventPayload::ErrorResponse(ErrorResponse { Err(err) => {
error: format!("Failed to list workspaces in CLI: {err}"), return Some(InternalEventPayload::ErrorResponse(ErrorResponse {
})); error: format!("Failed to list workspaces in CLI: {err}"),
} }));
}; }
Some(InternalEventPayload::ListOpenWorkspacesResponse(ListOpenWorkspacesResponse { };
workspaces, Some(InternalEventPayload::ListOpenWorkspacesResponse(ListOpenWorkspacesResponse {
})) workspaces,
} }))
GroupedPluginEvent::Host(req) => Some(InternalEventPayload::ErrorResponse(ErrorResponse { }
error: format!("Unsupported plugin request in CLI: {}", req.type_name()), req => Some(InternalEventPayload::ErrorResponse(ErrorResponse {
})), error: format!("Unsupported plugin request in CLI: {}", req.type_name()),
GroupedPluginEvent::Ignore => None, })),
},
} }
} }

View File

@@ -16,8 +16,7 @@ use tauri::{AppHandle, Emitter, Listener, Manager, Runtime};
use tauri_plugin_clipboard_manager::ClipboardExt; use tauri_plugin_clipboard_manager::ClipboardExt;
use tauri_plugin_opener::OpenerExt; use tauri_plugin_opener::OpenerExt;
use yaak::plugin_events::{ use yaak::plugin_events::{
GroupedPluginEvent, HostRequest, SharedEvent, SharedPluginEventContext, GroupedPluginEvent, HostRequest, SharedPluginEventContext, handle_shared_plugin_event,
handle_shared_plugin_event,
}; };
use yaak_crypto::manager::EncryptionManager; use yaak_crypto::manager::EncryptionManager;
use yaak_models::models::{AnyModel, HttpResponse, Plugin}; use yaak_models::models::{AnyModel, HttpResponse, Plugin};
@@ -61,11 +60,32 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
workspace_id: fallback_workspace_id.as_deref(), workspace_id: fallback_workspace_id.as_deref(),
}, },
) { ) {
GroupedPluginEvent::Shared(SharedEvent::Reply(payload)) => Ok(Some(payload)), GroupedPluginEvent::Handled(payload) => Ok(payload),
GroupedPluginEvent::Shared(SharedEvent::ErrorResponse(resp)) => { GroupedPluginEvent::ToHandle(host_request) => {
handle_host_plugin_request(
app_handle,
event,
plugin_handle,
&plugin_context,
host_request,
)
.await
}
}
}
async fn handle_host_plugin_request<R: Runtime>(
app_handle: &AppHandle<R>,
event: &InternalEvent,
plugin_handle: &PluginHandle,
plugin_context: &yaak_plugins::events::PluginContext,
host_request: HostRequest<'_>,
) -> Result<Option<InternalEventPayload>> {
match host_request {
HostRequest::ErrorResponse(resp) => {
error!("Plugin error: {}: {:?}", resp.error, resp); error!("Plugin error: {}: {:?}", resp.error, resp);
let toast_event = plugin_handle.build_event_to_send( let toast_event = plugin_handle.build_event_to_send(
&plugin_context, plugin_context,
&InternalEventPayload::ShowToastRequest(ShowToastRequest { &InternalEventPayload::ShowToastRequest(ShowToastRequest {
message: format!( message: format!(
"Plugin error from {}: {}", "Plugin error from {}: {}",
@@ -80,7 +100,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
); );
Box::pin(handle_plugin_event(app_handle, &toast_event, plugin_handle)).await Box::pin(handle_plugin_event(app_handle, &toast_event, plugin_handle)).await
} }
GroupedPluginEvent::Shared(SharedEvent::ReloadResponse(req)) => { HostRequest::ReloadResponse(req) => {
let plugins = app_handle.db().list_plugins()?; let plugins = app_handle.db().list_plugins()?;
for plugin in plugins { for plugin in plugins {
if plugin.directory != plugin_handle.dir { if plugin.directory != plugin_handle.dir {
@@ -94,7 +114,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
if !req.silent { if !req.silent {
let info = plugin_handle.info(); let info = plugin_handle.info();
let toast_event = plugin_handle.build_event_to_send( let toast_event = plugin_handle.build_event_to_send(
&plugin_context, plugin_context,
&InternalEventPayload::ShowToastRequest(ShowToastRequest { &InternalEventPayload::ShowToastRequest(ShowToastRequest {
message: format!("Reloaded plugin {}@{}", info.name, info.version), message: format!("Reloaded plugin {}@{}", info.name, info.version),
icon: Some(Icon::Info), icon: Some(Icon::Info),
@@ -108,28 +128,6 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
Ok(None) Ok(None)
} }
} }
GroupedPluginEvent::Host(host_request) => {
handle_host_plugin_request(
app_handle,
event,
plugin_handle,
&plugin_context,
host_request,
)
.await
}
GroupedPluginEvent::Ignore => Ok(None),
}
}
async fn handle_host_plugin_request<R: Runtime>(
app_handle: &AppHandle<R>,
event: &InternalEvent,
plugin_handle: &PluginHandle,
plugin_context: &yaak_plugins::events::PluginContext,
host_request: HostRequest<'_>,
) -> Result<Option<InternalEventPayload>> {
match host_request {
HostRequest::CopyText(req) => { HostRequest::CopyText(req) => {
app_handle.clipboard().write_text(req.text.as_str())?; app_handle.clipboard().write_text(req.text.as_str())?;
Ok(Some(InternalEventPayload::CopyTextResponse(EmptyPayload {}))) Ok(Some(InternalEventPayload::CopyTextResponse(EmptyPayload {})))

View File

@@ -18,16 +18,8 @@ pub struct SharedPluginEventContext<'a> {
#[derive(Debug)] #[derive(Debug)]
pub enum GroupedPluginEvent<'a> { pub enum GroupedPluginEvent<'a> {
Shared(SharedEvent<'a>), Handled(Option<InternalEventPayload>),
Host(HostRequest<'a>), ToHandle(HostRequest<'a>),
Ignore,
}
#[derive(Debug)]
pub enum SharedEvent<'a> {
Reply(InternalEventPayload),
ErrorResponse(&'a ErrorResponse),
ReloadResponse(&'a ReloadResponse),
} }
#[derive(Debug)] #[derive(Debug)]
@@ -43,8 +35,6 @@ pub enum SharedRequest<'a> {
SetKeyValue(&'a SetKeyValueRequest), SetKeyValue(&'a SetKeyValueRequest),
DeleteKeyValue(&'a DeleteKeyValueRequest), DeleteKeyValue(&'a DeleteKeyValueRequest),
GetHttpRequestById(&'a GetHttpRequestByIdRequest), GetHttpRequestById(&'a GetHttpRequestByIdRequest),
ErrorResponse(&'a ErrorResponse),
ReloadResponse(&'a ReloadResponse),
ListFolders(&'a ListFoldersRequest), ListFolders(&'a ListFoldersRequest),
ListHttpRequests(&'a ListHttpRequestsRequest), ListHttpRequests(&'a ListHttpRequestsRequest),
} }
@@ -69,6 +59,8 @@ pub enum HostRequest<'a> {
ListCookieNames(&'a ListCookieNamesRequest), ListCookieNames(&'a ListCookieNamesRequest),
GetCookieValue(&'a GetCookieValueRequest), GetCookieValue(&'a GetCookieValueRequest),
WindowInfo(&'a WindowInfoRequest), WindowInfo(&'a WindowInfoRequest),
ErrorResponse(&'a ErrorResponse),
ReloadResponse(&'a ReloadResponse),
OtherRequest(&'a InternalEventPayload), OtherRequest(&'a InternalEventPayload),
} }
@@ -93,6 +85,8 @@ impl HostRequest<'_> {
HostRequest::ListCookieNames(_) => "list_cookie_names_request".to_string(), HostRequest::ListCookieNames(_) => "list_cookie_names_request".to_string(),
HostRequest::GetCookieValue(_) => "get_cookie_value_request".to_string(), HostRequest::GetCookieValue(_) => "get_cookie_value_request".to_string(),
HostRequest::WindowInfo(_) => "window_info_request".to_string(), HostRequest::WindowInfo(_) => "window_info_request".to_string(),
HostRequest::ErrorResponse(_) => "error_response".to_string(),
HostRequest::ReloadResponse(_) => "reload_response".to_string(),
HostRequest::OtherRequest(payload) => payload.type_name(), HostRequest::OtherRequest(payload) => payload.type_name(),
} }
} }
@@ -114,10 +108,10 @@ impl<'a> From<&'a InternalEventPayload> for GroupedPluginRequest<'a> {
GroupedPluginRequest::Shared(SharedRequest::GetHttpRequestById(req)) GroupedPluginRequest::Shared(SharedRequest::GetHttpRequestById(req))
} }
InternalEventPayload::ErrorResponse(resp) => { InternalEventPayload::ErrorResponse(resp) => {
GroupedPluginRequest::Shared(SharedRequest::ErrorResponse(resp)) GroupedPluginRequest::Host(HostRequest::ErrorResponse(resp))
} }
InternalEventPayload::ReloadResponse(req) => { InternalEventPayload::ReloadResponse(req) => {
GroupedPluginRequest::Shared(SharedRequest::ReloadResponse(req)) GroupedPluginRequest::Host(HostRequest::ReloadResponse(req))
} }
InternalEventPayload::ListOpenWorkspacesRequest(req) => { InternalEventPayload::ListOpenWorkspacesRequest(req) => {
GroupedPluginRequest::Host(HostRequest::ListOpenWorkspaces(req)) GroupedPluginRequest::Host(HostRequest::ListOpenWorkspaces(req))
@@ -193,17 +187,11 @@ pub fn handle_shared_plugin_event<'a>(
context: SharedPluginEventContext<'_>, context: SharedPluginEventContext<'_>,
) -> GroupedPluginEvent<'a> { ) -> GroupedPluginEvent<'a> {
match GroupedPluginRequest::from(payload) { match GroupedPluginRequest::from(payload) {
GroupedPluginRequest::Shared(SharedRequest::ErrorResponse(resp)) => { GroupedPluginRequest::Shared(req) => {
GroupedPluginEvent::Shared(SharedEvent::ErrorResponse(resp)) GroupedPluginEvent::Handled(Some(build_shared_reply(query_manager, req, context)))
} }
GroupedPluginRequest::Shared(SharedRequest::ReloadResponse(req)) => { GroupedPluginRequest::Host(req) => GroupedPluginEvent::ToHandle(req),
GroupedPluginEvent::Shared(SharedEvent::ReloadResponse(req)) GroupedPluginRequest::Ignore => GroupedPluginEvent::Handled(None),
}
GroupedPluginRequest::Shared(req) => GroupedPluginEvent::Shared(SharedEvent::Reply(
build_shared_reply(query_manager, req, context),
)),
GroupedPluginRequest::Host(req) => GroupedPluginEvent::Host(req),
GroupedPluginRequest::Ignore => GroupedPluginEvent::Ignore,
} }
} }
@@ -240,9 +228,6 @@ fn build_shared_reply(
http_request, http_request,
}) })
} }
SharedRequest::ErrorResponse(_) | SharedRequest::ReloadResponse(_) => {
unreachable!("non-reply shared events are handled before build_shared_reply")
}
SharedRequest::ListFolders(_) => { SharedRequest::ListFolders(_) => {
let Some(workspace_id) = context.workspace_id else { let Some(workspace_id) = context.workspace_id else {
return InternalEventPayload::ErrorResponse(ErrorResponse { return InternalEventPayload::ErrorResponse(ErrorResponse {
@@ -364,7 +349,7 @@ mod tests {
assert!(matches!( assert!(matches!(
result, result,
GroupedPluginEvent::Shared(SharedEvent::Reply(InternalEventPayload::ErrorResponse(_))) GroupedPluginEvent::Handled(Some(InternalEventPayload::ErrorResponse(_)))
)); ));
} }
@@ -381,9 +366,9 @@ mod tests {
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") }, SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
); );
match by_workspace { match by_workspace {
GroupedPluginEvent::Shared(SharedEvent::Reply( GroupedPluginEvent::Handled(Some(InternalEventPayload::ListHttpRequestsResponse(
InternalEventPayload::ListHttpRequestsResponse(resp), resp,
)) => { ))) => {
assert_eq!(resp.http_requests.len(), 1); assert_eq!(resp.http_requests.len(), 1);
} }
other => panic!("unexpected workspace response: {other:?}"), other => panic!("unexpected workspace response: {other:?}"),
@@ -400,9 +385,9 @@ mod tests {
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None }, SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
); );
match by_folder { match by_folder {
GroupedPluginEvent::Shared(SharedEvent::Reply( GroupedPluginEvent::Handled(Some(InternalEventPayload::ListHttpRequestsResponse(
InternalEventPayload::ListHttpRequestsResponse(resp), resp,
)) => { ))) => {
assert_eq!(resp.http_requests.len(), 1); assert_eq!(resp.http_requests.len(), 1);
} }
other => panic!("unexpected folder response: {other:?}"), other => panic!("unexpected folder response: {other:?}"),
@@ -422,7 +407,9 @@ mod tests {
); );
match result { match result {
GroupedPluginEvent::Host(HostRequest::WindowInfo(req)) => assert_eq!(req.label, "main"), GroupedPluginEvent::ToHandle(HostRequest::WindowInfo(req)) => {
assert_eq!(req.label, "main")
}
other => panic!("unexpected host classification: {other:?}"), other => panic!("unexpected host classification: {other:?}"),
} }
} }