mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-26 19:31:12 +01:00
Implement CLI send flows and refactor plugin event handling
This commit is contained in:
@@ -17,6 +17,7 @@ sea-query = { version = "0.32.1", features = ["with-chrono", "attr"] }
|
||||
sea-query-rusqlite = { version = "0.7.0", features = ["with-chrono"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
schemars = { version = "0.8.22", features = ["chrono"] }
|
||||
sha2 = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
ts-rs = { workspace = true, features = ["chrono-impl", "serde-json-impl"] }
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::models::HttpRequestIden::{
|
||||
use crate::util::{UpdateSource, generate_prefixed_id};
|
||||
use chrono::{NaiveDateTime, Utc};
|
||||
use rusqlite::Row;
|
||||
use schemars::JsonSchema;
|
||||
use sea_query::Order::Desc;
|
||||
use sea_query::{IntoColumnRef, IntoIden, IntoTableRef, Order, SimpleExpr, enum_def};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -824,7 +825,7 @@ impl UpsertModelInfo for Folder {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, JsonSchema, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_models.ts")]
|
||||
pub struct HttpRequestHeader {
|
||||
@@ -837,7 +838,7 @@ pub struct HttpRequestHeader {
|
||||
pub id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, JsonSchema, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_models.ts")]
|
||||
pub struct HttpUrlParameter {
|
||||
@@ -850,7 +851,7 @@ pub struct HttpUrlParameter {
|
||||
pub id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, JsonSchema, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_models.ts")]
|
||||
#[enum_def(table_name = "http_requests")]
|
||||
@@ -1095,7 +1096,7 @@ impl Default for WebsocketMessageType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, JsonSchema, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_models.ts")]
|
||||
#[enum_def(table_name = "websocket_requests")]
|
||||
@@ -1704,7 +1705,7 @@ impl UpsertModelInfo for GraphQlIntrospection {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, JsonSchema, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_models.ts")]
|
||||
#[enum_def(table_name = "grpc_requests")]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::dedupe_headers;
|
||||
use crate::db_context::DbContext;
|
||||
use crate::error::Result;
|
||||
use crate::models::{GrpcRequest, GrpcRequestIden, HttpRequestHeader};
|
||||
use crate::models::{Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequestHeader};
|
||||
use crate::util::UpdateSource;
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
@@ -15,6 +15,20 @@ impl<'a> DbContext<'a> {
|
||||
self.find_many(GrpcRequestIden::WorkspaceId, workspace_id, None)
|
||||
}
|
||||
|
||||
pub fn list_grpc_requests_for_folder_recursive(
|
||||
&self,
|
||||
folder_id: &str,
|
||||
) -> Result<Vec<GrpcRequest>> {
|
||||
let mut children = Vec::new();
|
||||
for folder in self.find_many::<Folder>(FolderIden::FolderId, folder_id, None)? {
|
||||
children.extend(self.list_grpc_requests_for_folder_recursive(&folder.id)?);
|
||||
}
|
||||
for request in self.find_many::<GrpcRequest>(GrpcRequestIden::FolderId, folder_id, None)? {
|
||||
children.push(request);
|
||||
}
|
||||
Ok(children)
|
||||
}
|
||||
|
||||
pub fn delete_grpc_request(
|
||||
&self,
|
||||
m: &GrpcRequest,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use super::dedupe_headers;
|
||||
use crate::db_context::DbContext;
|
||||
use crate::error::Result;
|
||||
use crate::models::{HttpRequestHeader, WebsocketRequest, WebsocketRequestIden};
|
||||
use crate::models::{
|
||||
Folder, FolderIden, HttpRequestHeader, WebsocketRequest, WebsocketRequestIden,
|
||||
};
|
||||
use crate::util::UpdateSource;
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
@@ -15,6 +17,22 @@ impl<'a> DbContext<'a> {
|
||||
self.find_many(WebsocketRequestIden::WorkspaceId, workspace_id, None)
|
||||
}
|
||||
|
||||
pub fn list_websocket_requests_for_folder_recursive(
|
||||
&self,
|
||||
folder_id: &str,
|
||||
) -> Result<Vec<WebsocketRequest>> {
|
||||
let mut children = Vec::new();
|
||||
for folder in self.find_many::<Folder>(FolderIden::FolderId, folder_id, None)? {
|
||||
children.extend(self.list_websocket_requests_for_folder_recursive(&folder.id)?);
|
||||
}
|
||||
for request in
|
||||
self.find_many::<WebsocketRequest>(WebsocketRequestIden::FolderId, folder_id, None)?
|
||||
{
|
||||
children.push(request);
|
||||
}
|
||||
Ok(children)
|
||||
}
|
||||
|
||||
pub fn delete_websocket_request(
|
||||
&self,
|
||||
websocket_request: &WebsocketRequest,
|
||||
|
||||
6
crates/yaak-plugins/bindings/gen_events.ts
generated
6
crates/yaak-plugins/bindings/gen_events.ts
generated
File diff suppressed because one or more lines are too long
@@ -163,8 +163,8 @@ pub enum InternalEventPayload {
|
||||
WindowInfoRequest(WindowInfoRequest),
|
||||
WindowInfoResponse(WindowInfoResponse),
|
||||
|
||||
ListWorkspacesRequest(ListWorkspacesRequest),
|
||||
ListWorkspacesResponse(ListWorkspacesResponse),
|
||||
ListOpenWorkspacesRequest(ListOpenWorkspacesRequest),
|
||||
ListOpenWorkspacesResponse(ListOpenWorkspacesResponse),
|
||||
|
||||
GetHttpRequestByIdRequest(GetHttpRequestByIdRequest),
|
||||
GetHttpRequestByIdResponse(GetHttpRequestByIdResponse),
|
||||
@@ -631,12 +631,12 @@ pub struct WindowInfoResponse {
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_events.ts")]
|
||||
pub struct ListWorkspacesRequest {}
|
||||
pub struct ListOpenWorkspacesRequest {}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "gen_events.ts")]
|
||||
pub struct ListWorkspacesResponse {
|
||||
pub struct ListOpenWorkspacesResponse {
|
||||
pub workspaces: Vec<WorkspaceInfo>,
|
||||
}
|
||||
|
||||
|
||||
@@ -17,3 +17,6 @@ yaak-models = { workspace = true }
|
||||
yaak-plugins = { workspace = true }
|
||||
yaak-templates = { workspace = true }
|
||||
yaak-tls = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod error;
|
||||
pub mod plugin_events;
|
||||
pub mod render;
|
||||
pub mod send;
|
||||
|
||||
|
||||
429
crates/yaak/src/plugin_events.rs
Normal file
429
crates/yaak/src/plugin_events.rs
Normal file
@@ -0,0 +1,429 @@
|
||||
use yaak_models::query_manager::QueryManager;
|
||||
use yaak_plugins::events::{
|
||||
CloseWindowRequest, CopyTextRequest, DeleteKeyValueRequest, DeleteKeyValueResponse,
|
||||
DeleteModelRequest, ErrorResponse, FindHttpResponsesRequest, GetCookieValueRequest,
|
||||
GetHttpRequestByIdRequest, GetHttpRequestByIdResponse, GetKeyValueRequest, GetKeyValueResponse,
|
||||
InternalEventPayload, ListCookieNamesRequest, ListFoldersRequest, ListFoldersResponse,
|
||||
ListHttpRequestsRequest, ListHttpRequestsResponse, ListOpenWorkspacesRequest,
|
||||
OpenExternalUrlRequest, OpenWindowRequest, PromptFormRequest, PromptTextRequest,
|
||||
ReloadResponse, RenderGrpcRequestRequest, RenderHttpRequestRequest, SendHttpRequestRequest,
|
||||
SetKeyValueRequest, ShowToastRequest, TemplateRenderRequest, UpsertModelRequest,
|
||||
WindowInfoRequest,
|
||||
};
|
||||
|
||||
pub struct SharedPluginEventContext<'a> {
|
||||
pub plugin_name: &'a str,
|
||||
pub workspace_id: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GroupedPluginEvent<'a> {
|
||||
Shared(SharedEvent<'a>),
|
||||
Host(HostRequest<'a>),
|
||||
Ignore,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SharedEvent<'a> {
|
||||
Reply(InternalEventPayload),
|
||||
ErrorResponse(&'a ErrorResponse),
|
||||
ReloadResponse(&'a ReloadResponse),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GroupedPluginRequest<'a> {
|
||||
Shared(SharedRequest<'a>),
|
||||
Host(HostRequest<'a>),
|
||||
Ignore,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SharedRequest<'a> {
|
||||
GetKeyValue(&'a GetKeyValueRequest),
|
||||
SetKeyValue(&'a SetKeyValueRequest),
|
||||
DeleteKeyValue(&'a DeleteKeyValueRequest),
|
||||
GetHttpRequestById(&'a GetHttpRequestByIdRequest),
|
||||
ErrorResponse(&'a ErrorResponse),
|
||||
ReloadResponse(&'a ReloadResponse),
|
||||
ListFolders(&'a ListFoldersRequest),
|
||||
ListHttpRequests(&'a ListHttpRequestsRequest),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HostRequest<'a> {
|
||||
ShowToast(&'a ShowToastRequest),
|
||||
CopyText(&'a CopyTextRequest),
|
||||
PromptText(&'a PromptTextRequest),
|
||||
PromptForm(&'a PromptFormRequest),
|
||||
FindHttpResponses(&'a FindHttpResponsesRequest),
|
||||
UpsertModel(&'a UpsertModelRequest),
|
||||
DeleteModel(&'a DeleteModelRequest),
|
||||
RenderGrpcRequest(&'a RenderGrpcRequestRequest),
|
||||
RenderHttpRequest(&'a RenderHttpRequestRequest),
|
||||
TemplateRender(&'a TemplateRenderRequest),
|
||||
SendHttpRequest(&'a SendHttpRequestRequest),
|
||||
OpenWindow(&'a OpenWindowRequest),
|
||||
CloseWindow(&'a CloseWindowRequest),
|
||||
OpenExternalUrl(&'a OpenExternalUrlRequest),
|
||||
ListOpenWorkspaces(&'a ListOpenWorkspacesRequest),
|
||||
ListCookieNames(&'a ListCookieNamesRequest),
|
||||
GetCookieValue(&'a GetCookieValueRequest),
|
||||
WindowInfo(&'a WindowInfoRequest),
|
||||
OtherRequest(&'a InternalEventPayload),
|
||||
}
|
||||
|
||||
impl HostRequest<'_> {
|
||||
pub fn type_name(&self) -> String {
|
||||
match self {
|
||||
HostRequest::ShowToast(_) => "show_toast_request".to_string(),
|
||||
HostRequest::CopyText(_) => "copy_text_request".to_string(),
|
||||
HostRequest::PromptText(_) => "prompt_text_request".to_string(),
|
||||
HostRequest::PromptForm(_) => "prompt_form_request".to_string(),
|
||||
HostRequest::FindHttpResponses(_) => "find_http_responses_request".to_string(),
|
||||
HostRequest::UpsertModel(_) => "upsert_model_request".to_string(),
|
||||
HostRequest::DeleteModel(_) => "delete_model_request".to_string(),
|
||||
HostRequest::RenderGrpcRequest(_) => "render_grpc_request_request".to_string(),
|
||||
HostRequest::RenderHttpRequest(_) => "render_http_request_request".to_string(),
|
||||
HostRequest::TemplateRender(_) => "template_render_request".to_string(),
|
||||
HostRequest::SendHttpRequest(_) => "send_http_request_request".to_string(),
|
||||
HostRequest::OpenWindow(_) => "open_window_request".to_string(),
|
||||
HostRequest::CloseWindow(_) => "close_window_request".to_string(),
|
||||
HostRequest::OpenExternalUrl(_) => "open_external_url_request".to_string(),
|
||||
HostRequest::ListOpenWorkspaces(_) => "list_open_workspaces_request".to_string(),
|
||||
HostRequest::ListCookieNames(_) => "list_cookie_names_request".to_string(),
|
||||
HostRequest::GetCookieValue(_) => "get_cookie_value_request".to_string(),
|
||||
HostRequest::WindowInfo(_) => "window_info_request".to_string(),
|
||||
HostRequest::OtherRequest(payload) => payload.type_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a InternalEventPayload> for GroupedPluginRequest<'a> {
|
||||
fn from(payload: &'a InternalEventPayload) -> Self {
|
||||
match payload {
|
||||
InternalEventPayload::GetKeyValueRequest(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::GetKeyValue(req))
|
||||
}
|
||||
InternalEventPayload::SetKeyValueRequest(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::SetKeyValue(req))
|
||||
}
|
||||
InternalEventPayload::DeleteKeyValueRequest(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::DeleteKeyValue(req))
|
||||
}
|
||||
InternalEventPayload::GetHttpRequestByIdRequest(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::GetHttpRequestById(req))
|
||||
}
|
||||
InternalEventPayload::ErrorResponse(resp) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::ErrorResponse(resp))
|
||||
}
|
||||
InternalEventPayload::ReloadResponse(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::ReloadResponse(req))
|
||||
}
|
||||
InternalEventPayload::ListOpenWorkspacesRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::ListOpenWorkspaces(req))
|
||||
}
|
||||
InternalEventPayload::ListFoldersRequest(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::ListFolders(req))
|
||||
}
|
||||
InternalEventPayload::ListHttpRequestsRequest(req) => {
|
||||
GroupedPluginRequest::Shared(SharedRequest::ListHttpRequests(req))
|
||||
}
|
||||
InternalEventPayload::ShowToastRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::ShowToast(req))
|
||||
}
|
||||
InternalEventPayload::CopyTextRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::CopyText(req))
|
||||
}
|
||||
InternalEventPayload::PromptTextRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::PromptText(req))
|
||||
}
|
||||
InternalEventPayload::PromptFormRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::PromptForm(req))
|
||||
}
|
||||
InternalEventPayload::FindHttpResponsesRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::FindHttpResponses(req))
|
||||
}
|
||||
InternalEventPayload::UpsertModelRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::UpsertModel(req))
|
||||
}
|
||||
InternalEventPayload::DeleteModelRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::DeleteModel(req))
|
||||
}
|
||||
InternalEventPayload::RenderGrpcRequestRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::RenderGrpcRequest(req))
|
||||
}
|
||||
InternalEventPayload::RenderHttpRequestRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::RenderHttpRequest(req))
|
||||
}
|
||||
InternalEventPayload::TemplateRenderRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::TemplateRender(req))
|
||||
}
|
||||
InternalEventPayload::SendHttpRequestRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::SendHttpRequest(req))
|
||||
}
|
||||
InternalEventPayload::OpenWindowRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::OpenWindow(req))
|
||||
}
|
||||
InternalEventPayload::CloseWindowRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::CloseWindow(req))
|
||||
}
|
||||
InternalEventPayload::OpenExternalUrlRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::OpenExternalUrl(req))
|
||||
}
|
||||
InternalEventPayload::ListCookieNamesRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::ListCookieNames(req))
|
||||
}
|
||||
InternalEventPayload::GetCookieValueRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::GetCookieValue(req))
|
||||
}
|
||||
InternalEventPayload::WindowInfoRequest(req) => {
|
||||
GroupedPluginRequest::Host(HostRequest::WindowInfo(req))
|
||||
}
|
||||
payload if payload.type_name().ends_with("_request") => {
|
||||
GroupedPluginRequest::Host(HostRequest::OtherRequest(payload))
|
||||
}
|
||||
_ => GroupedPluginRequest::Ignore,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_shared_plugin_event<'a>(
|
||||
query_manager: &QueryManager,
|
||||
payload: &'a InternalEventPayload,
|
||||
context: SharedPluginEventContext<'_>,
|
||||
) -> GroupedPluginEvent<'a> {
|
||||
match GroupedPluginRequest::from(payload) {
|
||||
GroupedPluginRequest::Shared(SharedRequest::ErrorResponse(resp)) => {
|
||||
GroupedPluginEvent::Shared(SharedEvent::ErrorResponse(resp))
|
||||
}
|
||||
GroupedPluginRequest::Shared(SharedRequest::ReloadResponse(req)) => {
|
||||
GroupedPluginEvent::Shared(SharedEvent::ReloadResponse(req))
|
||||
}
|
||||
GroupedPluginRequest::Shared(req) => GroupedPluginEvent::Shared(SharedEvent::Reply(
|
||||
build_shared_reply(query_manager, req, context),
|
||||
)),
|
||||
GroupedPluginRequest::Host(req) => GroupedPluginEvent::Host(req),
|
||||
GroupedPluginRequest::Ignore => GroupedPluginEvent::Ignore,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_shared_reply(
|
||||
query_manager: &QueryManager,
|
||||
request: SharedRequest<'_>,
|
||||
context: SharedPluginEventContext<'_>,
|
||||
) -> InternalEventPayload {
|
||||
match request {
|
||||
SharedRequest::GetKeyValue(req) => {
|
||||
let value = query_manager
|
||||
.connect()
|
||||
.get_plugin_key_value(context.plugin_name, &req.key)
|
||||
.map(|v| v.value);
|
||||
InternalEventPayload::GetKeyValueResponse(GetKeyValueResponse { value })
|
||||
}
|
||||
SharedRequest::SetKeyValue(req) => {
|
||||
query_manager.connect().set_plugin_key_value(context.plugin_name, &req.key, &req.value);
|
||||
InternalEventPayload::SetKeyValueResponse(yaak_plugins::events::SetKeyValueResponse {})
|
||||
}
|
||||
SharedRequest::DeleteKeyValue(req) => {
|
||||
match query_manager.connect().delete_plugin_key_value(context.plugin_name, &req.key) {
|
||||
Ok(deleted) => {
|
||||
InternalEventPayload::DeleteKeyValueResponse(DeleteKeyValueResponse { deleted })
|
||||
}
|
||||
Err(err) => InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: format!("Failed to delete plugin key '{}' : {err}", req.key),
|
||||
}),
|
||||
}
|
||||
}
|
||||
SharedRequest::GetHttpRequestById(req) => {
|
||||
let http_request = query_manager.connect().get_http_request(&req.id).ok();
|
||||
InternalEventPayload::GetHttpRequestByIdResponse(GetHttpRequestByIdResponse {
|
||||
http_request,
|
||||
})
|
||||
}
|
||||
SharedRequest::ErrorResponse(_) | SharedRequest::ReloadResponse(_) => {
|
||||
unreachable!("non-reply shared events are handled before build_shared_reply")
|
||||
}
|
||||
SharedRequest::ListFolders(_) => {
|
||||
let Some(workspace_id) = context.workspace_id else {
|
||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: "workspace_id is required for list_folders_request".to_string(),
|
||||
});
|
||||
};
|
||||
let folders = match query_manager.connect().list_folders(workspace_id) {
|
||||
Ok(folders) => folders,
|
||||
Err(err) => {
|
||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: format!("Failed to list folders: {err}"),
|
||||
});
|
||||
}
|
||||
};
|
||||
InternalEventPayload::ListFoldersResponse(ListFoldersResponse { folders })
|
||||
}
|
||||
SharedRequest::ListHttpRequests(req) => {
|
||||
let http_requests = if let Some(folder_id) = req.folder_id.as_deref() {
|
||||
match query_manager.connect().list_http_requests_for_folder_recursive(folder_id) {
|
||||
Ok(http_requests) => http_requests,
|
||||
Err(err) => {
|
||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: format!("Failed to list HTTP requests for folder: {err}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let Some(workspace_id) = context.workspace_id else {
|
||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error:
|
||||
"workspace_id is required for list_http_requests_request without folder_id"
|
||||
.to_string(),
|
||||
});
|
||||
};
|
||||
match query_manager.connect().list_http_requests(workspace_id) {
|
||||
Ok(http_requests) => http_requests,
|
||||
Err(err) => {
|
||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: format!("Failed to list HTTP requests: {err}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
InternalEventPayload::ListHttpRequestsResponse(ListHttpRequestsResponse {
|
||||
http_requests,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use yaak_models::models::{Folder, HttpRequest, Workspace};
|
||||
use yaak_models::util::UpdateSource;
|
||||
|
||||
fn seed_query_manager() -> QueryManager {
|
||||
let temp_dir = tempfile::TempDir::new().expect("Failed to create temp dir");
|
||||
let db_path = temp_dir.path().join("db.sqlite");
|
||||
let blob_path = temp_dir.path().join("blobs.sqlite");
|
||||
let (query_manager, _blob_manager, _rx) =
|
||||
yaak_models::init_standalone(&db_path, &blob_path).expect("Failed to initialize DB");
|
||||
|
||||
query_manager
|
||||
.connect()
|
||||
.upsert_workspace(
|
||||
&Workspace {
|
||||
id: "wk_test".to_string(),
|
||||
name: "Workspace".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
&UpdateSource::Sync,
|
||||
)
|
||||
.expect("Failed to seed workspace");
|
||||
|
||||
query_manager
|
||||
.connect()
|
||||
.upsert_folder(
|
||||
&Folder {
|
||||
id: "fl_test".to_string(),
|
||||
workspace_id: "wk_test".to_string(),
|
||||
name: "Folder".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
&UpdateSource::Sync,
|
||||
)
|
||||
.expect("Failed to seed folder");
|
||||
|
||||
query_manager
|
||||
.connect()
|
||||
.upsert_http_request(
|
||||
&HttpRequest {
|
||||
id: "rq_test".to_string(),
|
||||
workspace_id: "wk_test".to_string(),
|
||||
folder_id: Some("fl_test".to_string()),
|
||||
name: "Request".to_string(),
|
||||
method: "GET".to_string(),
|
||||
url: "https://example.com".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
&UpdateSource::Sync,
|
||||
)
|
||||
.expect("Failed to seed request");
|
||||
|
||||
query_manager
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_requests_requires_workspace_when_folder_missing() {
|
||||
let query_manager = seed_query_manager();
|
||||
let payload = InternalEventPayload::ListHttpRequestsRequest(
|
||||
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
|
||||
);
|
||||
let result = handle_shared_plugin_event(
|
||||
&query_manager,
|
||||
&payload,
|
||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
|
||||
);
|
||||
|
||||
assert!(matches!(
|
||||
result,
|
||||
GroupedPluginEvent::Shared(SharedEvent::Reply(InternalEventPayload::ErrorResponse(_)))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_requests_by_workspace_and_folder() {
|
||||
let query_manager = seed_query_manager();
|
||||
|
||||
let by_workspace_payload = InternalEventPayload::ListHttpRequestsRequest(
|
||||
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
|
||||
);
|
||||
let by_workspace = handle_shared_plugin_event(
|
||||
&query_manager,
|
||||
&by_workspace_payload,
|
||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
|
||||
);
|
||||
match by_workspace {
|
||||
GroupedPluginEvent::Shared(SharedEvent::Reply(
|
||||
InternalEventPayload::ListHttpRequestsResponse(resp),
|
||||
)) => {
|
||||
assert_eq!(resp.http_requests.len(), 1);
|
||||
}
|
||||
other => panic!("unexpected workspace response: {other:?}"),
|
||||
}
|
||||
|
||||
let by_folder_payload = InternalEventPayload::ListHttpRequestsRequest(
|
||||
yaak_plugins::events::ListHttpRequestsRequest {
|
||||
folder_id: Some("fl_test".to_string()),
|
||||
},
|
||||
);
|
||||
let by_folder = handle_shared_plugin_event(
|
||||
&query_manager,
|
||||
&by_folder_payload,
|
||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
|
||||
);
|
||||
match by_folder {
|
||||
GroupedPluginEvent::Shared(SharedEvent::Reply(
|
||||
InternalEventPayload::ListHttpRequestsResponse(resp),
|
||||
)) => {
|
||||
assert_eq!(resp.http_requests.len(), 1);
|
||||
}
|
||||
other => panic!("unexpected folder response: {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_request_classification_works() {
|
||||
let query_manager = seed_query_manager();
|
||||
let payload = InternalEventPayload::WindowInfoRequest(WindowInfoRequest {
|
||||
label: "main".to_string(),
|
||||
});
|
||||
let result = handle_shared_plugin_event(
|
||||
&query_manager,
|
||||
&payload,
|
||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
|
||||
);
|
||||
|
||||
match result {
|
||||
GroupedPluginEvent::Host(HostRequest::WindowInfo(req)) => assert_eq!(req.label, "main"),
|
||||
other => panic!("unexpected host classification: {other:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user