mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-31 06:33:03 +02:00
Request actions (#65)
This commit is contained in:
@@ -21,6 +21,7 @@ use tauri::TitleBarStyle;
|
||||
use tauri::{AppHandle, Emitter, LogicalSize, RunEvent, State, WebviewUrl, WebviewWindow};
|
||||
use tauri::{Listener, Runtime};
|
||||
use tauri::{Manager, WindowEvent};
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
use tauri_plugin_log::{fern, Target, TargetKind};
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
use tokio::sync::{watch, Mutex};
|
||||
@@ -55,7 +56,8 @@ use yaak_models::queries::{
|
||||
upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_workspace,
|
||||
};
|
||||
use yaak_plugin_runtime::events::{
|
||||
FilterResponse, GetHttpRequestByIdResponse, InternalEvent, InternalEventPayload,
|
||||
CallHttpRequestActionRequest, FilterResponse, GetHttpRequestActionsResponse,
|
||||
GetHttpRequestByIdResponse, InternalEvent, InternalEventPayload, RenderHttpRequestResponse,
|
||||
SendHttpRequestResponse,
|
||||
};
|
||||
|
||||
@@ -870,29 +872,24 @@ async fn cmd_import_data(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_request_to_curl(
|
||||
app: AppHandle,
|
||||
request_id: &str,
|
||||
async fn cmd_http_request_actions(
|
||||
plugin_manager: State<'_, PluginManager>,
|
||||
environment_id: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
let request = get_http_request(&app, request_id)
|
||||
) -> Result<Vec<GetHttpRequestActionsResponse>, String> {
|
||||
plugin_manager
|
||||
.run_http_request_actions()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let environment = match environment_id {
|
||||
Some(id) => Some(get_environment(&app, id).await.map_err(|e| e.to_string())?),
|
||||
None => None,
|
||||
};
|
||||
let workspace = get_workspace(&app, &request.workspace_id)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let rendered = render_request(&request, &workspace, environment.as_ref());
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
let import_response = plugin_manager
|
||||
.run_export_curl(&rendered)
|
||||
#[tauri::command]
|
||||
async fn cmd_call_http_request_action(
|
||||
req: CallHttpRequestActionRequest,
|
||||
plugin_manager: State<'_, PluginManager>,
|
||||
) -> Result<(), String> {
|
||||
plugin_manager
|
||||
.call_http_request_action(req)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(import_response.content)
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -1624,6 +1621,7 @@ pub fn run() {
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
cmd_call_http_request_action,
|
||||
cmd_check_for_updates,
|
||||
cmd_create_cookie_jar,
|
||||
cmd_create_environment,
|
||||
@@ -1642,6 +1640,7 @@ pub fn run() {
|
||||
cmd_delete_http_request,
|
||||
cmd_delete_http_response,
|
||||
cmd_delete_workspace,
|
||||
cmd_dismiss_notification,
|
||||
cmd_duplicate_grpc_request,
|
||||
cmd_duplicate_http_request,
|
||||
cmd_export_data,
|
||||
@@ -1656,6 +1655,7 @@ pub fn run() {
|
||||
cmd_get_workspace,
|
||||
cmd_grpc_go,
|
||||
cmd_grpc_reflect,
|
||||
cmd_http_request_actions,
|
||||
cmd_import_data,
|
||||
cmd_list_cookie_jars,
|
||||
cmd_list_environments,
|
||||
@@ -1669,8 +1669,6 @@ pub fn run() {
|
||||
cmd_metadata,
|
||||
cmd_new_nested_window,
|
||||
cmd_new_window,
|
||||
cmd_request_to_curl,
|
||||
cmd_dismiss_notification,
|
||||
cmd_save_response,
|
||||
cmd_send_ephemeral_request,
|
||||
cmd_send_http_request,
|
||||
@@ -1915,9 +1913,49 @@ async fn handle_plugin_event<R: Runtime>(
|
||||
let event = match event.clone().payload {
|
||||
InternalEventPayload::GetHttpRequestByIdRequest(req) => {
|
||||
let http_request = get_http_request(app_handle, req.id.as_str()).await.ok();
|
||||
InternalEventPayload::GetHttpRequestByIdResponse(GetHttpRequestByIdResponse {
|
||||
http_request,
|
||||
})
|
||||
Some(InternalEventPayload::GetHttpRequestByIdResponse(
|
||||
GetHttpRequestByIdResponse { http_request },
|
||||
))
|
||||
}
|
||||
InternalEventPayload::CopyTextRequest(req) => {
|
||||
app_handle
|
||||
.clipboard()
|
||||
.write_text(req.text.as_str())
|
||||
.expect("Failed to write text to clipboard");
|
||||
None
|
||||
}
|
||||
InternalEventPayload::ShowToastRequest(req) => {
|
||||
app_handle
|
||||
.emit("show_toast", req)
|
||||
.expect("Failed to emit show_toast");
|
||||
None
|
||||
}
|
||||
InternalEventPayload::RenderHttpRequestRequest(req) => {
|
||||
let webview_windows = app_handle.get_focused_window()?.webview_windows();
|
||||
let w = match webview_windows.iter().next() {
|
||||
None => return None,
|
||||
Some((_, w)) => w,
|
||||
};
|
||||
let workspace = get_workspace(app_handle, req.http_request.workspace_id.as_str())
|
||||
.await
|
||||
.expect("Failed to get workspace for request");
|
||||
|
||||
let url = w.url().unwrap();
|
||||
let mut query_pairs = url.query_pairs();
|
||||
let environment_id = query_pairs
|
||||
.find(|(k, _v)| k == "environment_id")
|
||||
.map(|(_k, v)| v.to_string());
|
||||
let environment = match environment_id {
|
||||
None => None,
|
||||
Some(id) => get_environment(w, id.as_str()).await.ok(),
|
||||
};
|
||||
let rendered_http_request =
|
||||
render_request(&req.http_request, &workspace, environment.as_ref());
|
||||
Some(InternalEventPayload::RenderHttpRequestResponse(
|
||||
RenderHttpRequestResponse {
|
||||
http_request: rendered_http_request,
|
||||
},
|
||||
))
|
||||
}
|
||||
InternalEventPayload::SendHttpRequestRequest(req) => {
|
||||
let webview_windows = app_handle.get_focused_window()?.webview_windows();
|
||||
@@ -1964,10 +2002,12 @@ async fn handle_plugin_event<R: Runtime>(
|
||||
Err(_e) => return None,
|
||||
};
|
||||
|
||||
InternalEventPayload::SendHttpRequestResponse(SendHttpRequestResponse { http_response })
|
||||
Some(InternalEventPayload::SendHttpRequestResponse(
|
||||
SendHttpRequestResponse { http_response },
|
||||
))
|
||||
}
|
||||
_ => return None,
|
||||
_ => None,
|
||||
};
|
||||
|
||||
Some(event)
|
||||
event
|
||||
}
|
||||
|
||||
@@ -32,13 +32,24 @@ pub enum InternalEventPayload {
|
||||
|
||||
ExportHttpRequestRequest(ExportHttpRequestRequest),
|
||||
ExportHttpRequestResponse(ExportHttpRequestResponse),
|
||||
|
||||
|
||||
SendHttpRequestRequest(SendHttpRequestRequest),
|
||||
SendHttpRequestResponse(SendHttpRequestResponse),
|
||||
|
||||
GetHttpRequestActionsRequest,
|
||||
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
|
||||
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
|
||||
|
||||
CopyTextRequest(CopyTextRequest),
|
||||
|
||||
RenderHttpRequestRequest(RenderHttpRequestRequest),
|
||||
RenderHttpRequestResponse(RenderHttpRequestResponse),
|
||||
|
||||
ShowToastRequest(ShowToastRequest),
|
||||
|
||||
GetHttpRequestByIdRequest(GetHttpRequestByIdRequest),
|
||||
GetHttpRequestByIdResponse(GetHttpRequestByIdResponse),
|
||||
|
||||
|
||||
/// Returned when a plugin doesn't get run, just so the server
|
||||
/// has something to listen for
|
||||
EmptyResponse(EmptyResponse),
|
||||
@@ -122,6 +133,86 @@ pub struct SendHttpRequestResponse {
|
||||
pub http_response: HttpResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct CopyTextRequest {
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct RenderHttpRequestRequest {
|
||||
pub http_request: HttpRequest,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct RenderHttpRequestResponse {
|
||||
pub http_request: HttpRequest,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct ShowToastRequest {
|
||||
pub message: String,
|
||||
pub variant: ToastVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub enum ToastVariant {
|
||||
Custom,
|
||||
Copied,
|
||||
Success,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl Default for ToastVariant {
|
||||
fn default() -> Self {
|
||||
ToastVariant::Info
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct GetHttpRequestActionsResponse {
|
||||
pub actions: Vec<HttpRequestAction>,
|
||||
pub plugin_ref_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct HttpRequestAction {
|
||||
pub key: String,
|
||||
pub label: String,
|
||||
pub icon: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct CallHttpRequestActionRequest {
|
||||
pub key: String,
|
||||
pub plugin_ref_id: String,
|
||||
pub args: CallHttpRequestActionArgs,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct CallHttpRequestActionArgs {
|
||||
pub http_request: HttpRequest,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use crate::error::Result;
|
||||
use crate::events::{
|
||||
ExportHttpRequestRequest, ExportHttpRequestResponse, FilterRequest, FilterResponse
|
||||
, ImportRequest, ImportResponse, InternalEvent, InternalEventPayload,
|
||||
};
|
||||
use crate::events::{CallHttpRequestActionRequest, FilterRequest, FilterResponse, GetHttpRequestActionsResponse, ImportRequest, ImportResponse, InternalEvent, InternalEventPayload};
|
||||
|
||||
use crate::error::Error::PluginErr;
|
||||
use crate::nodejs::start_nodejs_plugin_runtime;
|
||||
@@ -12,7 +9,6 @@ use std::time::Duration;
|
||||
use tauri::{AppHandle, Runtime};
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::watch::Sender;
|
||||
use yaak_models::models::HttpRequest;
|
||||
|
||||
pub struct PluginManager {
|
||||
kill_tx: Sender<bool>,
|
||||
@@ -61,6 +57,29 @@ impl PluginManager {
|
||||
.send(&payload, source_event.plugin_ref_id.as_str(), reply_id)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn run_http_request_actions(&self) -> Result<Vec<GetHttpRequestActionsResponse>> {
|
||||
let reply_events = self
|
||||
.server
|
||||
.send_and_wait(&InternalEventPayload::GetHttpRequestActionsRequest)
|
||||
.await?;
|
||||
|
||||
let mut all_actions = Vec::new();
|
||||
for event in reply_events {
|
||||
if let InternalEventPayload::GetHttpRequestActionsResponse(resp) = event.payload {
|
||||
all_actions.push(resp.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_actions)
|
||||
}
|
||||
|
||||
pub async fn call_http_request_action(&self, req: CallHttpRequestActionRequest) -> Result<()> {
|
||||
let plugin = self.server.plugin_by_ref_id(req.plugin_ref_id.as_str()).await?;
|
||||
let event = plugin.build_event_to_send(&InternalEventPayload::CallHttpRequestActionRequest(req), None);
|
||||
plugin.send(&event).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run_import(&self, content: &str) -> Result<(ImportResponse, String)> {
|
||||
let reply_events = self
|
||||
@@ -72,43 +91,17 @@ impl PluginManager {
|
||||
|
||||
// TODO: Don't just return the first valid response
|
||||
for event in reply_events {
|
||||
match event.payload {
|
||||
InternalEventPayload::ImportResponse(resp) => {
|
||||
let ref_id = event.plugin_ref_id.as_str();
|
||||
let plugin = self.server.plugin_by_ref_id(ref_id).await?;
|
||||
let plugin_name = plugin.name().await;
|
||||
return Ok((resp, plugin_name));
|
||||
}
|
||||
_ => {}
|
||||
if let InternalEventPayload::ImportResponse(resp) = event.payload {
|
||||
let ref_id = event.plugin_ref_id.as_str();
|
||||
let plugin = self.server.plugin_by_ref_id(ref_id).await?;
|
||||
let plugin_name = plugin.name().await;
|
||||
return Ok((resp, plugin_name));
|
||||
}
|
||||
}
|
||||
|
||||
Err(PluginErr("No import responses found".to_string()))
|
||||
}
|
||||
|
||||
pub async fn run_export_curl(
|
||||
&self,
|
||||
request: &HttpRequest,
|
||||
) -> Result<ExportHttpRequestResponse> {
|
||||
let event = self
|
||||
.server
|
||||
.send_to_plugin_and_wait(
|
||||
"exporter-curl",
|
||||
&InternalEventPayload::ExportHttpRequestRequest(ExportHttpRequestRequest {
|
||||
http_request: request.to_owned(),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
match event.payload {
|
||||
InternalEventPayload::ExportHttpRequestResponse(resp) => Ok(resp),
|
||||
InternalEventPayload::EmptyResponse(_) => {
|
||||
Err(PluginErr("Export returned empty".to_string()))
|
||||
}
|
||||
e => Err(PluginErr(format!("Export returned invalid event {:?}", e))),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_filter(
|
||||
&self,
|
||||
filter: &str,
|
||||
|
||||
Reference in New Issue
Block a user