mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-02-28 04:36:53 -05:00
Compare commits
10 Commits
codex/plug
...
codex/cli-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b90188a0 | ||
|
|
e64404d7a5 | ||
|
|
072b486857 | ||
|
|
23e9cbb376 | ||
|
|
9c09e32a56 | ||
|
|
be26cc4db4 | ||
|
|
a2f12aef35 | ||
|
|
e34301ccab | ||
|
|
8f0062f917 | ||
|
|
68d68035a1 |
@@ -38,12 +38,16 @@ impl CliContext {
|
|||||||
let encryption_manager = Arc::new(EncryptionManager::new(query_manager.clone(), app_id));
|
let encryption_manager = Arc::new(EncryptionManager::new(query_manager.clone(), app_id));
|
||||||
|
|
||||||
let plugin_manager = if with_plugins {
|
let plugin_manager = if with_plugins {
|
||||||
let vendored_plugin_dir = data_dir.join("vendored-plugins");
|
let embedded_vendored_plugin_dir = data_dir.join("vendored-plugins");
|
||||||
|
let bundled_plugin_dir =
|
||||||
|
resolve_bundled_plugin_dir_for_cli(&embedded_vendored_plugin_dir);
|
||||||
let installed_plugin_dir = data_dir.join("installed-plugins");
|
let installed_plugin_dir = data_dir.join("installed-plugins");
|
||||||
let node_bin_path = PathBuf::from("node");
|
let node_bin_path = PathBuf::from("node");
|
||||||
|
|
||||||
prepare_embedded_vendored_plugins(&vendored_plugin_dir)
|
if bundled_plugin_dir == embedded_vendored_plugin_dir {
|
||||||
|
prepare_embedded_vendored_plugins(&embedded_vendored_plugin_dir)
|
||||||
.expect("Failed to prepare bundled plugins");
|
.expect("Failed to prepare bundled plugins");
|
||||||
|
}
|
||||||
|
|
||||||
let plugin_runtime_main =
|
let plugin_runtime_main =
|
||||||
std::env::var("YAAK_PLUGIN_RUNTIME").map(PathBuf::from).unwrap_or_else(|_| {
|
std::env::var("YAAK_PLUGIN_RUNTIME").map(PathBuf::from).unwrap_or_else(|_| {
|
||||||
@@ -52,13 +56,13 @@ impl CliContext {
|
|||||||
});
|
});
|
||||||
|
|
||||||
match PluginManager::new(
|
match PluginManager::new(
|
||||||
vendored_plugin_dir,
|
bundled_plugin_dir,
|
||||||
|
embedded_vendored_plugin_dir,
|
||||||
installed_plugin_dir,
|
installed_plugin_dir,
|
||||||
node_bin_path,
|
node_bin_path,
|
||||||
plugin_runtime_main,
|
plugin_runtime_main,
|
||||||
&query_manager,
|
&query_manager,
|
||||||
&PluginContext::new_empty(),
|
&PluginContext::new_empty(),
|
||||||
false,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@@ -131,3 +135,20 @@ fn prepare_embedded_vendored_plugins(vendored_plugin_dir: &Path) -> std::io::Res
|
|||||||
EMBEDDED_VENDORED_PLUGINS.extract(vendored_plugin_dir)?;
|
EMBEDDED_VENDORED_PLUGINS.extract(vendored_plugin_dir)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_bundled_plugin_dir_for_cli(embedded_vendored_plugin_dir: &Path) -> PathBuf {
|
||||||
|
if !cfg!(debug_assertions) {
|
||||||
|
return embedded_vendored_plugin_dir.to_path_buf();
|
||||||
|
}
|
||||||
|
|
||||||
|
let plugins_dir = match std::env::current_dir() {
|
||||||
|
Ok(cwd) => cwd.join("plugins"),
|
||||||
|
Err(_) => return embedded_vendored_plugin_dir.to_path_buf(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !plugins_dir.is_dir() {
|
||||||
|
return embedded_vendored_plugin_dir.to_path_buf();
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins_dir.canonicalize().unwrap_or(plugins_dir)
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ use yaak::plugin_events::{
|
|||||||
GroupedPluginEvent, HostRequest, SharedPluginEventContext, handle_shared_plugin_event,
|
GroupedPluginEvent, HostRequest, SharedPluginEventContext, handle_shared_plugin_event,
|
||||||
};
|
};
|
||||||
use yaak_crypto::manager::EncryptionManager;
|
use yaak_crypto::manager::EncryptionManager;
|
||||||
use yaak_models::models::{HttpResponse, Plugin};
|
use yaak_models::models::{AnyModel, HttpResponse, Plugin};
|
||||||
use yaak_models::queries::any_request::AnyRequest;
|
use yaak_models::queries::any_request::AnyRequest;
|
||||||
use yaak_models::util::UpdateSource;
|
use yaak_models::util::UpdateSource;
|
||||||
use yaak_plugins::error::Error::PluginErr;
|
use yaak_plugins::error::Error::PluginErr;
|
||||||
use yaak_plugins::events::{
|
use yaak_plugins::events::{
|
||||||
Color, EmptyPayload, ErrorResponse, GetCookieValueResponse, Icon, InternalEvent,
|
Color, EmptyPayload, ErrorResponse, FindHttpResponsesResponse, GetCookieValueResponse, Icon,
|
||||||
InternalEventPayload, ListCookieNamesResponse, ListOpenWorkspacesResponse,
|
InternalEvent, InternalEventPayload, ListCookieNamesResponse, ListOpenWorkspacesResponse,
|
||||||
RenderGrpcRequestResponse, RenderHttpRequestResponse, SendHttpRequestResponse,
|
RenderGrpcRequestResponse, RenderHttpRequestResponse, SendHttpRequestResponse,
|
||||||
ShowToastRequest, TemplateRenderResponse, WindowInfoResponse, WindowNavigateEvent,
|
ShowToastRequest, TemplateRenderResponse, WindowInfoResponse, WindowNavigateEvent,
|
||||||
WorkspaceInfo,
|
WorkspaceInfo,
|
||||||
@@ -190,6 +190,71 @@ async fn handle_host_plugin_request<R: Runtime>(
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HostRequest::FindHttpResponses(req) => {
|
||||||
|
let http_responses = app_handle
|
||||||
|
.db()
|
||||||
|
.list_http_responses_for_request(&req.request_id, req.limit.map(|l| l as u64))
|
||||||
|
.unwrap_or_default();
|
||||||
|
Ok(Some(InternalEventPayload::FindHttpResponsesResponse(FindHttpResponsesResponse {
|
||||||
|
http_responses,
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
HostRequest::UpsertModel(req) => {
|
||||||
|
use AnyModel::*;
|
||||||
|
let model = match &req.model {
|
||||||
|
HttpRequest(m) => {
|
||||||
|
HttpRequest(app_handle.db().upsert_http_request(m, &UpdateSource::Plugin)?)
|
||||||
|
}
|
||||||
|
GrpcRequest(m) => {
|
||||||
|
GrpcRequest(app_handle.db().upsert_grpc_request(m, &UpdateSource::Plugin)?)
|
||||||
|
}
|
||||||
|
WebsocketRequest(m) => WebsocketRequest(
|
||||||
|
app_handle.db().upsert_websocket_request(m, &UpdateSource::Plugin)?,
|
||||||
|
),
|
||||||
|
Folder(m) => Folder(app_handle.db().upsert_folder(m, &UpdateSource::Plugin)?),
|
||||||
|
Environment(m) => {
|
||||||
|
Environment(app_handle.db().upsert_environment(m, &UpdateSource::Plugin)?)
|
||||||
|
}
|
||||||
|
Workspace(m) => {
|
||||||
|
Workspace(app_handle.db().upsert_workspace(m, &UpdateSource::Plugin)?)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(PluginErr("Upsert not supported for this model type".into()).into());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(InternalEventPayload::UpsertModelResponse(
|
||||||
|
yaak_plugins::events::UpsertModelResponse { model },
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
HostRequest::DeleteModel(req) => {
|
||||||
|
let model = match req.model.as_str() {
|
||||||
|
"http_request" => AnyModel::HttpRequest(
|
||||||
|
app_handle.db().delete_http_request_by_id(&req.id, &UpdateSource::Plugin)?,
|
||||||
|
),
|
||||||
|
"grpc_request" => AnyModel::GrpcRequest(
|
||||||
|
app_handle.db().delete_grpc_request_by_id(&req.id, &UpdateSource::Plugin)?,
|
||||||
|
),
|
||||||
|
"websocket_request" => AnyModel::WebsocketRequest(
|
||||||
|
app_handle
|
||||||
|
.db()
|
||||||
|
.delete_websocket_request_by_id(&req.id, &UpdateSource::Plugin)?,
|
||||||
|
),
|
||||||
|
"folder" => AnyModel::Folder(
|
||||||
|
app_handle.db().delete_folder_by_id(&req.id, &UpdateSource::Plugin)?,
|
||||||
|
),
|
||||||
|
"environment" => AnyModel::Environment(
|
||||||
|
app_handle.db().delete_environment_by_id(&req.id, &UpdateSource::Plugin)?,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
return Err(PluginErr("Delete not supported for this model type".into()).into());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(InternalEventPayload::DeleteModelResponse(
|
||||||
|
yaak_plugins::events::DeleteModelResponse { model },
|
||||||
|
)))
|
||||||
|
}
|
||||||
HostRequest::RenderGrpcRequest(req) => {
|
HostRequest::RenderGrpcRequest(req) => {
|
||||||
let window = get_window_from_plugin_context(app_handle, plugin_context)?;
|
let window = get_window_from_plugin_context(app_handle, plugin_context)?;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use crate::error::Result;
|
|||||||
use crate::models_ext::QueryManagerExt;
|
use crate::models_ext::QueryManagerExt;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@@ -243,6 +244,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||||||
.path()
|
.path()
|
||||||
.resolve("vendored/plugins", BaseDirectory::Resource)
|
.resolve("vendored/plugins", BaseDirectory::Resource)
|
||||||
.expect("failed to resolve plugin directory resource");
|
.expect("failed to resolve plugin directory resource");
|
||||||
|
let bundled_plugin_dir = if is_dev() {
|
||||||
|
resolve_workspace_plugins_dir().unwrap_or_else(|| vendored_plugin_dir.clone())
|
||||||
|
} else {
|
||||||
|
vendored_plugin_dir.clone()
|
||||||
|
};
|
||||||
|
|
||||||
let installed_plugin_dir = app_handle
|
let installed_plugin_dir = app_handle
|
||||||
.path()
|
.path()
|
||||||
@@ -266,7 +272,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||||||
.expect("failed to resolve plugin runtime")
|
.expect("failed to resolve plugin runtime")
|
||||||
.join("index.cjs");
|
.join("index.cjs");
|
||||||
|
|
||||||
let dev_mode = is_dev();
|
|
||||||
let query_manager =
|
let query_manager =
|
||||||
app_handle.state::<yaak_models::query_manager::QueryManager>().inner().clone();
|
app_handle.state::<yaak_models::query_manager::QueryManager>().inner().clone();
|
||||||
|
|
||||||
@@ -274,13 +279,13 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||||||
let app_handle_clone = app_handle.clone();
|
let app_handle_clone = app_handle.clone();
|
||||||
tauri::async_runtime::block_on(async move {
|
tauri::async_runtime::block_on(async move {
|
||||||
let manager = PluginManager::new(
|
let manager = PluginManager::new(
|
||||||
|
bundled_plugin_dir,
|
||||||
vendored_plugin_dir,
|
vendored_plugin_dir,
|
||||||
installed_plugin_dir,
|
installed_plugin_dir,
|
||||||
node_bin_path,
|
node_bin_path,
|
||||||
plugin_runtime_main,
|
plugin_runtime_main,
|
||||||
&query_manager,
|
&query_manager,
|
||||||
&PluginContext::new_empty(),
|
&PluginContext::new_empty(),
|
||||||
dev_mode,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to initialize plugins");
|
.expect("Failed to initialize plugins");
|
||||||
@@ -322,3 +327,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_workspace_plugins_dir() -> Option<PathBuf> {
|
||||||
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.join("../..")
|
||||||
|
.join("plugins")
|
||||||
|
.canonicalize()
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ use crate::plugin_handle::PluginHandle;
|
|||||||
use crate::server_ws::PluginRuntimeServerWebsocket;
|
use crate::server_ws::PluginRuntimeServerWebsocket;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -46,9 +45,9 @@ pub struct PluginManager {
|
|||||||
kill_tx: tokio::sync::watch::Sender<bool>,
|
kill_tx: tokio::sync::watch::Sender<bool>,
|
||||||
killed_rx: Arc<Mutex<Option<oneshot::Receiver<()>>>>,
|
killed_rx: Arc<Mutex<Option<oneshot::Receiver<()>>>>,
|
||||||
ws_service: Arc<PluginRuntimeServerWebsocket>,
|
ws_service: Arc<PluginRuntimeServerWebsocket>,
|
||||||
|
bundled_plugin_dir: PathBuf,
|
||||||
vendored_plugin_dir: PathBuf,
|
vendored_plugin_dir: PathBuf,
|
||||||
pub(crate) installed_plugin_dir: PathBuf,
|
pub(crate) installed_plugin_dir: PathBuf,
|
||||||
dev_mode: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Callback for plugin initialization events (e.g., toast notifications)
|
/// Callback for plugin initialization events (e.g., toast notifications)
|
||||||
@@ -58,21 +57,21 @@ impl PluginManager {
|
|||||||
/// Create a new PluginManager with the given paths.
|
/// Create a new PluginManager with the given paths.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
/// * `bundled_plugin_dir` - Directory to scan for bundled plugins
|
||||||
/// * `vendored_plugin_dir` - Path to vendored plugins directory
|
/// * `vendored_plugin_dir` - Path to vendored plugins directory
|
||||||
/// * `installed_plugin_dir` - Path to installed plugins directory
|
/// * `installed_plugin_dir` - Path to installed plugins directory
|
||||||
/// * `node_bin_path` - Path to the yaaknode binary
|
/// * `node_bin_path` - Path to the yaaknode binary
|
||||||
/// * `plugin_runtime_main` - Path to the plugin runtime index.cjs
|
/// * `plugin_runtime_main` - Path to the plugin runtime index.cjs
|
||||||
/// * `query_manager` - Query manager for bundled plugin registration and loading
|
/// * `query_manager` - Query manager for bundled plugin registration and loading
|
||||||
/// * `plugin_context` - Context to use while initializing plugins
|
/// * `plugin_context` - Context to use while initializing plugins
|
||||||
/// * `dev_mode` - Whether the app is in dev mode (affects plugin loading)
|
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
|
bundled_plugin_dir: PathBuf,
|
||||||
vendored_plugin_dir: PathBuf,
|
vendored_plugin_dir: PathBuf,
|
||||||
installed_plugin_dir: PathBuf,
|
installed_plugin_dir: PathBuf,
|
||||||
node_bin_path: PathBuf,
|
node_bin_path: PathBuf,
|
||||||
plugin_runtime_main: PathBuf,
|
plugin_runtime_main: PathBuf,
|
||||||
query_manager: &QueryManager,
|
query_manager: &QueryManager,
|
||||||
plugin_context: &PluginContext,
|
plugin_context: &PluginContext,
|
||||||
dev_mode: bool,
|
|
||||||
) -> Result<PluginManager> {
|
) -> Result<PluginManager> {
|
||||||
let (events_tx, mut events_rx) = mpsc::channel(2048);
|
let (events_tx, mut events_rx) = mpsc::channel(2048);
|
||||||
let (kill_server_tx, kill_server_rx) = tokio::sync::watch::channel(false);
|
let (kill_server_tx, kill_server_rx) = tokio::sync::watch::channel(false);
|
||||||
@@ -89,9 +88,9 @@ impl PluginManager {
|
|||||||
ws_service: Arc::new(ws_service.clone()),
|
ws_service: Arc::new(ws_service.clone()),
|
||||||
kill_tx: kill_server_tx,
|
kill_tx: kill_server_tx,
|
||||||
killed_rx: Arc::new(Mutex::new(Some(killed_rx))),
|
killed_rx: Arc::new(Mutex::new(Some(killed_rx))),
|
||||||
|
bundled_plugin_dir,
|
||||||
vendored_plugin_dir,
|
vendored_plugin_dir,
|
||||||
installed_plugin_dir,
|
installed_plugin_dir,
|
||||||
dev_mode,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Forward events to subscribers
|
// Forward events to subscribers
|
||||||
@@ -192,25 +191,11 @@ impl PluginManager {
|
|||||||
Ok(plugin_manager)
|
Ok(plugin_manager)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the vendored plugin directory path (resolves dev mode path if applicable)
|
|
||||||
pub fn get_plugins_dir(&self) -> PathBuf {
|
|
||||||
if self.dev_mode {
|
|
||||||
// Use plugins directly for easy development
|
|
||||||
// Tauri runs from crates-tauri/yaak-app/, so go up two levels to reach project root
|
|
||||||
env::current_dir()
|
|
||||||
.map(|cwd| cwd.join("../../plugins").canonicalize().unwrap())
|
|
||||||
.unwrap_or_else(|_| self.vendored_plugin_dir.clone())
|
|
||||||
} else {
|
|
||||||
self.vendored_plugin_dir.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read plugin directories from disk and return their paths.
|
/// Read plugin directories from disk and return their paths.
|
||||||
/// This is useful for discovering bundled plugins.
|
/// This is useful for discovering bundled plugins.
|
||||||
pub async fn list_bundled_plugin_dirs(&self) -> Result<Vec<String>> {
|
pub async fn list_bundled_plugin_dirs(&self) -> Result<Vec<String>> {
|
||||||
let plugins_dir = self.get_plugins_dir();
|
info!("Loading bundled plugins from {:?}", self.bundled_plugin_dir);
|
||||||
info!("Loading bundled plugins from {plugins_dir:?}");
|
read_plugins_dir(&self.bundled_plugin_dir).await
|
||||||
read_plugins_dir(&plugins_dir).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
|
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
use yaak_models::models::AnyModel;
|
|
||||||
use yaak_models::query_manager::QueryManager;
|
use yaak_models::query_manager::QueryManager;
|
||||||
use yaak_models::util::UpdateSource;
|
|
||||||
use yaak_plugins::events::{
|
use yaak_plugins::events::{
|
||||||
CloseWindowRequest, CopyTextRequest, DeleteKeyValueRequest, DeleteKeyValueResponse,
|
CloseWindowRequest, CopyTextRequest, DeleteKeyValueRequest, DeleteKeyValueResponse,
|
||||||
DeleteModelRequest, DeleteModelResponse, ErrorResponse, FindHttpResponsesRequest,
|
DeleteModelRequest, ErrorResponse, FindHttpResponsesRequest, GetCookieValueRequest,
|
||||||
FindHttpResponsesResponse, GetCookieValueRequest, GetHttpRequestByIdRequest,
|
GetHttpRequestByIdRequest, GetHttpRequestByIdResponse, GetKeyValueRequest, GetKeyValueResponse,
|
||||||
GetHttpRequestByIdResponse, GetKeyValueRequest, GetKeyValueResponse, InternalEventPayload,
|
InternalEventPayload, ListCookieNamesRequest, ListFoldersRequest, ListFoldersResponse,
|
||||||
ListCookieNamesRequest, ListFoldersRequest, ListFoldersResponse, ListHttpRequestsRequest,
|
ListHttpRequestsRequest, ListHttpRequestsResponse, ListOpenWorkspacesRequest,
|
||||||
ListHttpRequestsResponse, ListOpenWorkspacesRequest, OpenExternalUrlRequest, OpenWindowRequest,
|
OpenExternalUrlRequest, OpenWindowRequest, PromptFormRequest, PromptTextRequest,
|
||||||
PromptFormRequest, PromptTextRequest, ReloadResponse, RenderGrpcRequestRequest,
|
ReloadResponse, RenderGrpcRequestRequest, RenderHttpRequestRequest, SendHttpRequestRequest,
|
||||||
RenderHttpRequestRequest, SendHttpRequestRequest, SetKeyValueRequest, ShowToastRequest,
|
SetKeyValueRequest, ShowToastRequest, TemplateRenderRequest, UpsertModelRequest,
|
||||||
TemplateRenderRequest, UpsertModelRequest, UpsertModelResponse, WindowInfoRequest,
|
WindowInfoRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SharedPluginEventContext<'a> {
|
pub struct SharedPluginEventContext<'a> {
|
||||||
@@ -39,9 +37,6 @@ pub enum SharedRequest<'a> {
|
|||||||
GetHttpRequestById(&'a GetHttpRequestByIdRequest),
|
GetHttpRequestById(&'a GetHttpRequestByIdRequest),
|
||||||
ListFolders(&'a ListFoldersRequest),
|
ListFolders(&'a ListFoldersRequest),
|
||||||
ListHttpRequests(&'a ListHttpRequestsRequest),
|
ListHttpRequests(&'a ListHttpRequestsRequest),
|
||||||
FindHttpResponses(&'a FindHttpResponsesRequest),
|
|
||||||
UpsertModel(&'a UpsertModelRequest),
|
|
||||||
DeleteModel(&'a DeleteModelRequest),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -50,6 +45,9 @@ pub enum HostRequest<'a> {
|
|||||||
CopyText(&'a CopyTextRequest),
|
CopyText(&'a CopyTextRequest),
|
||||||
PromptText(&'a PromptTextRequest),
|
PromptText(&'a PromptTextRequest),
|
||||||
PromptForm(&'a PromptFormRequest),
|
PromptForm(&'a PromptFormRequest),
|
||||||
|
FindHttpResponses(&'a FindHttpResponsesRequest),
|
||||||
|
UpsertModel(&'a UpsertModelRequest),
|
||||||
|
DeleteModel(&'a DeleteModelRequest),
|
||||||
RenderGrpcRequest(&'a RenderGrpcRequestRequest),
|
RenderGrpcRequest(&'a RenderGrpcRequestRequest),
|
||||||
RenderHttpRequest(&'a RenderHttpRequestRequest),
|
RenderHttpRequest(&'a RenderHttpRequestRequest),
|
||||||
TemplateRender(&'a TemplateRenderRequest),
|
TemplateRender(&'a TemplateRenderRequest),
|
||||||
@@ -73,6 +71,9 @@ impl HostRequest<'_> {
|
|||||||
HostRequest::CopyText(_) => "copy_text_request".to_string(),
|
HostRequest::CopyText(_) => "copy_text_request".to_string(),
|
||||||
HostRequest::PromptText(_) => "prompt_text_request".to_string(),
|
HostRequest::PromptText(_) => "prompt_text_request".to_string(),
|
||||||
HostRequest::PromptForm(_) => "prompt_form_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::RenderGrpcRequest(_) => "render_grpc_request_request".to_string(),
|
||||||
HostRequest::RenderHttpRequest(_) => "render_http_request_request".to_string(),
|
HostRequest::RenderHttpRequest(_) => "render_http_request_request".to_string(),
|
||||||
HostRequest::TemplateRender(_) => "template_render_request".to_string(),
|
HostRequest::TemplateRender(_) => "template_render_request".to_string(),
|
||||||
@@ -134,13 +135,13 @@ impl<'a> From<&'a InternalEventPayload> for GroupedPluginRequest<'a> {
|
|||||||
GroupedPluginRequest::Host(HostRequest::PromptForm(req))
|
GroupedPluginRequest::Host(HostRequest::PromptForm(req))
|
||||||
}
|
}
|
||||||
InternalEventPayload::FindHttpResponsesRequest(req) => {
|
InternalEventPayload::FindHttpResponsesRequest(req) => {
|
||||||
GroupedPluginRequest::Shared(SharedRequest::FindHttpResponses(req))
|
GroupedPluginRequest::Host(HostRequest::FindHttpResponses(req))
|
||||||
}
|
}
|
||||||
InternalEventPayload::UpsertModelRequest(req) => {
|
InternalEventPayload::UpsertModelRequest(req) => {
|
||||||
GroupedPluginRequest::Shared(SharedRequest::UpsertModel(req))
|
GroupedPluginRequest::Host(HostRequest::UpsertModel(req))
|
||||||
}
|
}
|
||||||
InternalEventPayload::DeleteModelRequest(req) => {
|
InternalEventPayload::DeleteModelRequest(req) => {
|
||||||
GroupedPluginRequest::Shared(SharedRequest::DeleteModel(req))
|
GroupedPluginRequest::Host(HostRequest::DeleteModel(req))
|
||||||
}
|
}
|
||||||
InternalEventPayload::RenderGrpcRequestRequest(req) => {
|
InternalEventPayload::RenderGrpcRequestRequest(req) => {
|
||||||
GroupedPluginRequest::Host(HostRequest::RenderGrpcRequest(req))
|
GroupedPluginRequest::Host(HostRequest::RenderGrpcRequest(req))
|
||||||
@@ -274,175 +275,17 @@ fn build_shared_reply(
|
|||||||
http_requests,
|
http_requests,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
SharedRequest::FindHttpResponses(req) => {
|
|
||||||
let http_responses = query_manager
|
|
||||||
.connect()
|
|
||||||
.list_http_responses_for_request(&req.request_id, req.limit.map(|l| l as u64))
|
|
||||||
.unwrap_or_default();
|
|
||||||
InternalEventPayload::FindHttpResponsesResponse(FindHttpResponsesResponse {
|
|
||||||
http_responses,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
SharedRequest::UpsertModel(req) => {
|
|
||||||
use AnyModel::*;
|
|
||||||
|
|
||||||
let model = match &req.model {
|
|
||||||
HttpRequest(m) => {
|
|
||||||
match query_manager.connect().upsert_http_request(m, &UpdateSource::Plugin) {
|
|
||||||
Ok(model) => HttpRequest(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to upsert HTTP request: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GrpcRequest(m) => {
|
|
||||||
match query_manager.connect().upsert_grpc_request(m, &UpdateSource::Plugin) {
|
|
||||||
Ok(model) => GrpcRequest(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to upsert gRPC request: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WebsocketRequest(m) => {
|
|
||||||
match query_manager.connect().upsert_websocket_request(m, &UpdateSource::Plugin)
|
|
||||||
{
|
|
||||||
Ok(model) => WebsocketRequest(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to upsert WebSocket request: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Folder(m) => {
|
|
||||||
match query_manager.connect().upsert_folder(m, &UpdateSource::Plugin) {
|
|
||||||
Ok(model) => Folder(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to upsert folder: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Environment(m) => {
|
|
||||||
match query_manager.connect().upsert_environment(m, &UpdateSource::Plugin) {
|
|
||||||
Ok(model) => Environment(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to upsert environment: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Workspace(m) => {
|
|
||||||
match query_manager.connect().upsert_workspace(m, &UpdateSource::Plugin) {
|
|
||||||
Ok(model) => Workspace(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to upsert workspace: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: "Upsert not supported for this model type".to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
InternalEventPayload::UpsertModelResponse(UpsertModelResponse { model })
|
|
||||||
}
|
|
||||||
SharedRequest::DeleteModel(req) => {
|
|
||||||
let model = match req.model.as_str() {
|
|
||||||
"http_request" => {
|
|
||||||
match query_manager
|
|
||||||
.connect()
|
|
||||||
.delete_http_request_by_id(&req.id, &UpdateSource::Plugin)
|
|
||||||
{
|
|
||||||
Ok(model) => AnyModel::HttpRequest(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to delete HTTP request: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"grpc_request" => {
|
|
||||||
match query_manager
|
|
||||||
.connect()
|
|
||||||
.delete_grpc_request_by_id(&req.id, &UpdateSource::Plugin)
|
|
||||||
{
|
|
||||||
Ok(model) => AnyModel::GrpcRequest(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to delete gRPC request: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"websocket_request" => {
|
|
||||||
match query_manager
|
|
||||||
.connect()
|
|
||||||
.delete_websocket_request_by_id(&req.id, &UpdateSource::Plugin)
|
|
||||||
{
|
|
||||||
Ok(model) => AnyModel::WebsocketRequest(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to delete WebSocket request: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"folder" => match query_manager
|
|
||||||
.connect()
|
|
||||||
.delete_folder_by_id(&req.id, &UpdateSource::Plugin)
|
|
||||||
{
|
|
||||||
Ok(model) => AnyModel::Folder(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to delete folder: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"environment" => {
|
|
||||||
match query_manager
|
|
||||||
.connect()
|
|
||||||
.delete_environment_by_id(&req.id, &UpdateSource::Plugin)
|
|
||||||
{
|
|
||||||
Ok(model) => AnyModel::Environment(model),
|
|
||||||
Err(err) => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: format!("Failed to delete environment: {err}"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return InternalEventPayload::ErrorResponse(ErrorResponse {
|
|
||||||
error: "Delete not supported for this model type".to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
InternalEventPayload::DeleteModelResponse(DeleteModelResponse { model })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use tempfile::TempDir;
|
use yaak_models::models::{Folder, HttpRequest, Workspace};
|
||||||
use yaak_models::models::{AnyModel, Folder, HttpRequest, Workspace};
|
|
||||||
use yaak_models::util::UpdateSource;
|
use yaak_models::util::UpdateSource;
|
||||||
|
|
||||||
fn seed_query_manager() -> (QueryManager, TempDir) {
|
fn seed_query_manager() -> QueryManager {
|
||||||
let temp_dir = TempDir::new().expect("Failed to create temp dir");
|
let temp_dir = tempfile::TempDir::new().expect("Failed to create temp dir");
|
||||||
let db_path = temp_dir.path().join("db.sqlite");
|
let db_path = temp_dir.path().join("db.sqlite");
|
||||||
let blob_path = temp_dir.path().join("blobs.sqlite");
|
let blob_path = temp_dir.path().join("blobs.sqlite");
|
||||||
let (query_manager, _blob_manager, _rx) =
|
let (query_manager, _blob_manager, _rx) =
|
||||||
@@ -489,12 +332,12 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.expect("Failed to seed request");
|
.expect("Failed to seed request");
|
||||||
|
|
||||||
(query_manager, temp_dir)
|
query_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn list_requests_requires_workspace_when_folder_missing() {
|
fn list_requests_requires_workspace_when_folder_missing() {
|
||||||
let (query_manager, _temp_dir) = seed_query_manager();
|
let query_manager = seed_query_manager();
|
||||||
let payload = InternalEventPayload::ListHttpRequestsRequest(
|
let payload = InternalEventPayload::ListHttpRequestsRequest(
|
||||||
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
|
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
|
||||||
);
|
);
|
||||||
@@ -512,7 +355,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn list_requests_by_workspace_and_folder() {
|
fn list_requests_by_workspace_and_folder() {
|
||||||
let (query_manager, _temp_dir) = seed_query_manager();
|
let query_manager = seed_query_manager();
|
||||||
|
|
||||||
let by_workspace_payload = InternalEventPayload::ListHttpRequestsRequest(
|
let by_workspace_payload = InternalEventPayload::ListHttpRequestsRequest(
|
||||||
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
|
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
|
||||||
@@ -551,83 +394,9 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn find_http_responses_is_shared_handled() {
|
|
||||||
let (query_manager, _temp_dir) = seed_query_manager();
|
|
||||||
let payload = InternalEventPayload::FindHttpResponsesRequest(FindHttpResponsesRequest {
|
|
||||||
request_id: "rq_test".to_string(),
|
|
||||||
limit: Some(1),
|
|
||||||
});
|
|
||||||
|
|
||||||
let result = handle_shared_plugin_event(
|
|
||||||
&query_manager,
|
|
||||||
&payload,
|
|
||||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
|
|
||||||
);
|
|
||||||
|
|
||||||
match result {
|
|
||||||
GroupedPluginEvent::Handled(Some(InternalEventPayload::FindHttpResponsesResponse(
|
|
||||||
resp,
|
|
||||||
))) => {
|
|
||||||
assert!(resp.http_responses.is_empty());
|
|
||||||
}
|
|
||||||
other => panic!("unexpected find responses result: {other:?}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn upsert_and_delete_model_are_shared_handled() {
|
|
||||||
let (query_manager, _temp_dir) = seed_query_manager();
|
|
||||||
|
|
||||||
let existing = query_manager
|
|
||||||
.connect()
|
|
||||||
.get_http_request("rq_test")
|
|
||||||
.expect("Failed to load seeded request");
|
|
||||||
let upsert_payload = InternalEventPayload::UpsertModelRequest(UpsertModelRequest {
|
|
||||||
model: AnyModel::HttpRequest(HttpRequest {
|
|
||||||
name: "Request Updated".to_string(),
|
|
||||||
..existing
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
let upsert_result = handle_shared_plugin_event(
|
|
||||||
&query_manager,
|
|
||||||
&upsert_payload,
|
|
||||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
|
|
||||||
);
|
|
||||||
match upsert_result {
|
|
||||||
GroupedPluginEvent::Handled(Some(InternalEventPayload::UpsertModelResponse(resp))) => {
|
|
||||||
match resp.model {
|
|
||||||
AnyModel::HttpRequest(r) => assert_eq!(r.name, "Request Updated"),
|
|
||||||
other => panic!("unexpected upsert model type: {other:?}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other => panic!("unexpected upsert result: {other:?}"),
|
|
||||||
}
|
|
||||||
|
|
||||||
let delete_payload = InternalEventPayload::DeleteModelRequest(DeleteModelRequest {
|
|
||||||
model: "http_request".to_string(),
|
|
||||||
id: "rq_test".to_string(),
|
|
||||||
});
|
|
||||||
let delete_result = handle_shared_plugin_event(
|
|
||||||
&query_manager,
|
|
||||||
&delete_payload,
|
|
||||||
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
|
|
||||||
);
|
|
||||||
match delete_result {
|
|
||||||
GroupedPluginEvent::Handled(Some(InternalEventPayload::DeleteModelResponse(resp))) => {
|
|
||||||
match resp.model {
|
|
||||||
AnyModel::HttpRequest(r) => assert_eq!(r.id, "rq_test"),
|
|
||||||
other => panic!("unexpected delete model type: {other:?}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other => panic!("unexpected delete result: {other:?}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn host_request_classification_works() {
|
fn host_request_classification_works() {
|
||||||
let (query_manager, _temp_dir) = seed_query_manager();
|
let query_manager = seed_query_manager();
|
||||||
let payload = InternalEventPayload::WindowInfoRequest(WindowInfoRequest {
|
let payload = InternalEventPayload::WindowInfoRequest(WindowInfoRequest {
|
||||||
label: "main".to_string(),
|
label: "main".to_string(),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user