diff --git a/crates-cli/yaak-cli/src/commands/import_export.rs b/crates-cli/yaak-cli/src/commands/import_export.rs index e2b9e935..091a08a4 100644 --- a/crates-cli/yaak-cli/src/commands/import_export.rs +++ b/crates-cli/yaak-cli/src/commands/import_export.rs @@ -68,7 +68,9 @@ async fn import( ); } let destination = match workspace_id { - Some(workspace_id) => ImportDestination::ExistingWorkspace { workspace_id, folder_id: None }, + Some(workspace_id) => { + ImportDestination::ExistingWorkspace { workspace_id, folder_id: None } + } None => ImportDestination::NewWorkspace, }; let plan = import::plan_import_resources( diff --git a/crates-cli/yaak-cli/src/commands/plugin.rs b/crates-cli/yaak-cli/src/commands/plugin.rs index 951042c5..1e224f02 100644 --- a/crates-cli/yaak-cli/src/commands/plugin.rs +++ b/crates-cli/yaak-cli/src/commands/plugin.rs @@ -883,11 +883,8 @@ mod tests { fs::create_dir_all(root.join("build")).expect("create build"); fs::create_dir_all(root.join("vendor")).expect("create vendor"); fs::write(root.join("vendor/core_bg.wasm"), "asset").expect("write asset"); - fs::write( - root.join("package.json"), - r#"{"yaak":{"buildAssets":["vendor/core_bg.wasm"]}}"#, - ) - .expect("write package.json"); + fs::write(root.join("package.json"), r#"{"yaak":{"buildAssets":["vendor/core_bg.wasm"]}}"#) + .expect("write package.json"); copy_build_assets(root).expect("copy assets"); diff --git a/crates-cli/yaak-cli/src/plugin_events.rs b/crates-cli/yaak-cli/src/plugin_events.rs index d59bbdd9..81498b06 100644 --- a/crates-cli/yaak-cli/src/plugin_events.rs +++ b/crates-cli/yaak-cli/src/plugin_events.rs @@ -13,7 +13,6 @@ use tokio::task::JoinHandle; use yaak::plugin_events::{ GroupedPluginEvent, HostRequest, SharedPluginEventContext, handle_shared_plugin_event, }; -use yaak_models::render::{render_grpc_request, render_http_request}; use yaak::response_body::FileResponseBodyStore; use yaak::send::{SendHttpRequestWithPluginsParams, send_http_request_with_plugins}; use yaak_crypto::manager::EncryptionManager; @@ -24,6 +23,7 @@ use yaak_models::models::Environment; use yaak_models::queries::any_request::AnyRequest; use yaak_models::query_manager::QueryManager; use yaak_models::render::make_vars_hashmap; +use yaak_models::render::{render_grpc_request, render_http_request}; use yaak_models::util::UpdateSource; use yaak_plugins::events::{ EmptyPayload, ErrorResponse, FormInput, GetCookieValueResponse, InternalEvent, diff --git a/crates-cli/yaak-cli/tests/import_export_commands.rs b/crates-cli/yaak-cli/tests/import_export_commands.rs index f05e5561..5f9d44a2 100644 --- a/crates-cli/yaak-cli/tests/import_export_commands.rs +++ b/crates-cli/yaak-cli/tests/import_export_commands.rs @@ -210,7 +210,10 @@ fn re_import_merges_into_linked_workspace() { ], ); cli_cmd(data_dir) - .args(["import", import_path.to_str().expect("import path is utf-8")]) + .args([ + "import", + import_path.to_str().expect("import path is utf-8"), + ]) .assert() .success() .stdout(contains("Imported 1 workspace, 2 HTTP requests")); @@ -273,7 +276,10 @@ fn re_import_leaves_deleted_resources_alone() { ], ); cli_cmd(data_dir) - .args(["import", import_path.to_str().expect("import path is utf-8")]) + .args([ + "import", + import_path.to_str().expect("import path is utf-8"), + ]) .assert() .success(); @@ -293,8 +299,7 @@ fn re_import_leaves_deleted_resources_alone() { .into_iter() .find(|r| r.name == "Request B") .expect("request B imported"); - db.delete_http_request_by_id(&request_b.id, &UpdateSource::Sync) - .expect("delete request B"); + db.delete_http_request_by_id(&request_b.id, &UpdateSource::Sync).expect("delete request B"); workspace_id }; diff --git a/crates-server/yaak-web/src/main.rs b/crates-server/yaak-web/src/main.rs index edf9c078..15ec3c42 100644 --- a/crates-server/yaak-web/src/main.rs +++ b/crates-server/yaak-web/src/main.rs @@ -145,11 +145,8 @@ async fn cache_control(req: Request, next: Next) -> Response { .get(header::CONTENT_TYPE) .and_then(|v| v.to_str().ok()) .is_some_and(|v| v.starts_with("text/html")); - let value = if hashed_name && !is_html { - "public, max-age=31536000, immutable" - } else { - "no-cache" - }; + let value = + if hashed_name && !is_html { "public, max-age=31536000, immutable" } else { "no-cache" }; res.headers_mut().insert(header::CACHE_CONTROL, HeaderValue::from_static(value)); res } diff --git a/crates-tauri/yaak-app-client/src/grpc.rs b/crates-tauri/yaak-app-client/src/grpc.rs index 52add513..2829ae42 100644 --- a/crates-tauri/yaak-app-client/src/grpc.rs +++ b/crates-tauri/yaak-app-client/src/grpc.rs @@ -19,7 +19,6 @@ pub(crate) fn metadata_to_map(metadata: MetadataMap) -> BTreeMap entries } - pub(crate) async fn build_metadata( window: &WebviewWindow, request: &GrpcRequest, diff --git a/crates-tauri/yaak-app-client/src/http_request.rs b/crates-tauri/yaak-app-client/src/http_request.rs index 6e010d9a..b8a63b9c 100644 --- a/crates-tauri/yaak-app-client/src/http_request.rs +++ b/crates-tauri/yaak-app-client/src/http_request.rs @@ -177,4 +177,3 @@ async fn send_http_request_inner( Ok(SentHttpRequest { response: result.response, body: result.response_body }) } - diff --git a/crates-tauri/yaak-app-client/src/lib.rs b/crates-tauri/yaak-app-client/src/lib.rs index dec37c7f..2003cdbb 100644 --- a/crates-tauri/yaak-app-client/src/lib.rs +++ b/crates-tauri/yaak-app-client/src/lib.rs @@ -29,16 +29,16 @@ use tokio::sync::Mutex; use tokio::task::block_in_place; use tokio::time; use yaak::send::ResponseBody; -use yaak_commands::responses::locate_response_body; use yaak_commands::resolve::resolve_grpc_request; +use yaak_commands::responses::locate_response_body; use yaak_common::command::new_checked_command; use yaak_crypto::manager::EncryptionManager; use yaak_grpc::manager::{GrpcConfig, GrpcHandle}; use yaak_grpc::{Code, ServiceDefinition}; use yaak_mac_window::AppHandleMacWindowExt; use yaak_models::models::{ - CookieJar, Environment, GrpcConnection, GrpcConnectionState, GrpcEvent, - GrpcEventType, HttpRequest, HttpResponse, HttpResponseState, Workspace, + CookieJar, Environment, GrpcConnection, GrpcConnectionState, GrpcEvent, GrpcEventType, + HttpRequest, HttpResponse, HttpResponseState, Workspace, }; use yaak_models::util::{BatchUpsertResult, ImportDestination, ImportPlan, UpdateSource}; use yaak_plugins::events::{ @@ -1033,20 +1033,6 @@ async fn cmd_commit_import( commit_import(&window, plan) } - - - - - - - - - - - - - - /// Decodes base64 and writes the bytes to a file the user picked. /// /// The webview can't do this itself: its `fs` permissions are read-only and scoped to the app @@ -1141,7 +1127,6 @@ async fn cmd_send_http_request( Ok(r) } - async fn cmd_new_child_window( parent_window: WebviewWindow, url: &str, diff --git a/crates-tauri/yaak-app-client/src/plugins_ext.rs b/crates-tauri/yaak-app-client/src/plugins_ext.rs index bff3c6ed..e1ca87ce 100644 --- a/crates-tauri/yaak-app-client/src/plugins_ext.rs +++ b/crates-tauri/yaak-app-client/src/plugins_ext.rs @@ -16,8 +16,7 @@ use std::time::{Duration, Instant}; use tauri::path::BaseDirectory; use tauri::plugin::{Builder, TauriPlugin}; use tauri::{ - AppHandle, Emitter, Manager, RunEvent, Runtime, State, WebviewWindow, WindowEvent, - is_dev, + AppHandle, Emitter, Manager, RunEvent, Runtime, State, WebviewWindow, WindowEvent, is_dev, }; use tokio::sync::Mutex; use ts_rs::TS; @@ -28,10 +27,10 @@ use yaak_plugins::api::{ PluginNameVersion, PluginSearchResponse, PluginUpdatesResponse, check_plugin_updates, search_plugins, }; +use yaak_plugins::error::Error::PluginErr; use yaak_plugins::events::{Color, PluginContext, ShowToastRequest}; use yaak_plugins::install::{delete_and_uninstall, download_and_install}; use yaak_plugins::manager::PluginManager; -use yaak_plugins::error::Error::PluginErr; use yaak_plugins::plugin_meta::get_plugin_meta; static EXITING: AtomicBool = AtomicBool::new(false); @@ -355,9 +354,11 @@ pub fn init() -> TauriPlugin { ), ) .await - .unwrap_or_else(|_| Err(yaak_plugins::error::Error::PluginErr( - "Timed out starting the plugin runtime".to_string(), - ))); + .unwrap_or_else(|_| { + Err(yaak_plugins::error::Error::PluginErr( + "Timed out starting the plugin runtime".to_string(), + )) + }); let manager = match result { Ok(manager) => manager, diff --git a/crates-tauri/yaak-app-client/src/render.rs b/crates-tauri/yaak-app-client/src/render.rs index 2c995b0d..1cc1a8cf 100644 --- a/crates-tauri/yaak-app-client/src/render.rs +++ b/crates-tauri/yaak-app-client/src/render.rs @@ -4,5 +4,5 @@ //! `yaak-commands` when the template commands did. Callers in this crate do not //! need to track which is which. -pub use yaak_models::render::{render_grpc_request, render_http_request}; pub use yaak_commands::render::{render_json_value, render_template}; +pub use yaak_models::render::{render_grpc_request, render_http_request}; diff --git a/crates-tauri/yaak-app-client/src/rpc_ext.rs b/crates-tauri/yaak-app-client/src/rpc_ext.rs index 4d1f5f26..187b2112 100644 --- a/crates-tauri/yaak-app-client/src/rpc_ext.rs +++ b/crates-tauri/yaak-app-client/src/rpc_ext.rs @@ -21,9 +21,9 @@ use crate::notifications::YaakNotifier; use crate::updates::YaakUpdater; use log::warn; use serde::Serialize; -use tauri::{Manager, Runtime, State, WebviewWindow}; use std::collections::HashMap; use std::sync::Arc; +use tauri::{Manager, Runtime, State, WebviewWindow}; use tokio::sync::Mutex; use yaak_commands::{Host, PluginHost}; use yaak_core::WorkspaceContext; @@ -32,8 +32,8 @@ use yaak_git::{ BranchDeleteResult, CloneResult, GitBranchInfo, GitCommit, GitFileDiff, GitRemote, GitStatusSummary, GitWorktreeStatus, PullResult, PushResult, }; -use yaak_grpc::manager::GrpcHandle; use yaak_grpc::ServiceDefinition; +use yaak_grpc::manager::GrpcHandle; use yaak_models::blob_manager::BlobManager; use yaak_models::models::{ GraphQlIntrospection, GrpcEvent, HttpRequest, HttpRequestHeader, HttpResponse, @@ -42,26 +42,26 @@ use yaak_models::models::{ }; use yaak_models::query_manager::QueryManager; use yaak_models::util::{BatchUpsertResult, ImportPlan}; +use yaak_plugins::api::{PluginNameVersion, PluginSearchResponse, PluginUpdatesResponse}; use yaak_plugins::events::{ CallFolderActionRequest, CallGrpcRequestActionRequest, CallHttpRequestActionRequest, - CallWebsocketRequestActionRequest, CallWorkspaceActionRequest, FilterResponse, ImportResponse, - JsonPrimitive, RenderPurpose, GetFolderActionsResponse, GetGrpcRequestActionsResponse, - GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse, - GetHttpRequestActionsResponse, GetTemplateFunctionConfigResponse, - GetTemplateFunctionSummaryResponse, GetThemesResponse, GetWebsocketRequestActionsResponse, - GetWorkspaceActionsResponse, + CallWebsocketRequestActionRequest, CallWorkspaceActionRequest, FilterResponse, + GetFolderActionsResponse, GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse, + GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse, + GetTemplateFunctionConfigResponse, GetTemplateFunctionSummaryResponse, GetThemesResponse, + GetWebsocketRequestActionsResponse, GetWorkspaceActionsResponse, ImportResponse, JsonPrimitive, + RenderPurpose, }; -use yaak_plugins::api::{PluginNameVersion, PluginSearchResponse, PluginUpdatesResponse}; use yaak_plugins::manager::PluginManager; use yaak_plugins::native_template_functions::encrypt_secure_template_function; -use yaak_plugins::template_callback::PluginTemplateCallback; use yaak_plugins::plugin_meta::PluginMetadata; +use yaak_plugins::template_callback::PluginTemplateCallback; use yaak_rpc::RpcRouter; use yaak_rpc_schema::*; use yaak_sse::sse::ServerSentEvent; use yaak_sync::sync::SyncOp; -use yaak_templates::TemplateCallback; use yaak_tauri_utils::window::WorkspaceWindowTrait; +use yaak_templates::TemplateCallback; use yaak_ws::WebsocketManager; /// Per-call context: the window a command was invoked from. @@ -231,17 +231,15 @@ impl PluginHost for ClientCtx { Ok(self.pm().await?.call_workspace_action(&self.plugin_context(), req).await?) } - async fn call_folder_action( - &self, - req: CallFolderActionRequest, - ) -> yaak_commands::Result<()> { + async fn call_folder_action(&self, req: CallFolderActionRequest) -> yaak_commands::Result<()> { Ok(self.pm().await?.call_folder_action(&self.plugin_context(), req).await?) } async fn http_authentication_summaries( &self, ) -> yaak_commands::Result> { - let results = self.pm().await?.get_http_authentication_summaries(&self.plugin_context()).await?; + let results = + self.pm().await?.get_http_authentication_summaries(&self.plugin_context()).await?; Ok(results.into_iter().map(|(_, a)| a).collect()) } @@ -393,11 +391,17 @@ async fn cmd_metadata(ctx: ClientCtx, _req: CmdMetadataReq) -> Re Ok(crate::cmd_metadata(ctx.window.app_handle().clone()).await?) } -async fn cmd_template_tokens_to_string(ctx: ClientCtx, req: CmdTemplateTokensToStringReq) -> Result { +async fn cmd_template_tokens_to_string( + ctx: ClientCtx, + req: CmdTemplateTokensToStringReq, +) -> Result { Ok(yaak_commands::templates::cmd_template_tokens_to_string(ctx, req).await?) } -async fn cmd_render_template(ctx: ClientCtx, req: CmdRenderTemplateReq) -> Result { +async fn cmd_render_template( + ctx: ClientCtx, + req: CmdRenderTemplateReq, +) -> Result { Ok(yaak_commands::templates::cmd_render_template(ctx, req).await?) } @@ -405,55 +409,114 @@ async fn cmd_send_feedback(ctx: ClientCtx, req: CmdSendFeedbackRe Ok(crate::cmd_send_feedback(ctx.window.app_handle().clone(), req.feature, req.text).await?) } -async fn cmd_dismiss_notification(ctx: ClientCtx, req: CmdDismissNotificationReq) -> Result<()> { - Ok(crate::cmd_dismiss_notification(ctx.window.clone(), &req.notification_id, ctx.window.app_handle().state::>()).await?) +async fn cmd_dismiss_notification( + ctx: ClientCtx, + req: CmdDismissNotificationReq, +) -> Result<()> { + Ok(crate::cmd_dismiss_notification( + ctx.window.clone(), + &req.notification_id, + ctx.window.app_handle().state::>(), + ) + .await?) } -async fn cmd_grpc_reflect(ctx: ClientCtx, req: CmdGrpcReflectReq) -> Result> { - Ok(crate::cmd_grpc_reflect(&req.request_id, req.environment_id.as_deref(), req.proto_files, ctx.window.clone(), ctx.window.app_handle().clone(), ctx.window.app_handle().state::>()).await?) +async fn cmd_grpc_reflect( + ctx: ClientCtx, + req: CmdGrpcReflectReq, +) -> Result> { + Ok(crate::cmd_grpc_reflect( + &req.request_id, + req.environment_id.as_deref(), + req.proto_files, + ctx.window.clone(), + ctx.window.app_handle().clone(), + ctx.window.app_handle().state::>(), + ) + .await?) } async fn cmd_grpc_go(ctx: ClientCtx, req: CmdGrpcGoReq) -> Result { - Ok(crate::cmd_grpc_go(&req.request_id, req.environment_id.as_deref(), req.proto_files, ctx.window.app_handle().clone(), ctx.window.clone(), ctx.window.app_handle().state::>()).await?) + Ok(crate::cmd_grpc_go( + &req.request_id, + req.environment_id.as_deref(), + req.proto_files, + ctx.window.app_handle().clone(), + ctx.window.clone(), + ctx.window.app_handle().state::>(), + ) + .await?) } async fn cmd_restart(ctx: ClientCtx, _req: CmdRestartReq) -> Result<()> { Ok(crate::cmd_restart(ctx.window.app_handle().clone()).await?) } -async fn cmd_send_ephemeral_request(ctx: ClientCtx, req: CmdSendEphemeralRequestReq) -> Result { - Ok(crate::cmd_send_ephemeral_request(req.request, req.environment_id.as_deref(), req.cookie_jar_id.as_deref(), ctx.window.clone(), ctx.window.app_handle().clone()).await?) +async fn cmd_send_ephemeral_request( + ctx: ClientCtx, + req: CmdSendEphemeralRequestReq, +) -> Result { + Ok(crate::cmd_send_ephemeral_request( + req.request, + req.environment_id.as_deref(), + req.cookie_jar_id.as_deref(), + ctx.window.clone(), + ctx.window.app_handle().clone(), + ) + .await?) } async fn cmd_format_json(ctx: ClientCtx, req: CmdFormatJsonReq) -> Result { Ok(yaak_commands::data::cmd_format_json(ctx, req).await?) } -async fn cmd_format_graphql(_ctx: ClientCtx, req: CmdFormatGraphqlReq) -> Result { +async fn cmd_format_graphql( + _ctx: ClientCtx, + req: CmdFormatGraphqlReq, +) -> Result { Ok(crate::cmd_format_graphql(&req.text).await?) } -async fn cmd_http_response_body(ctx: ClientCtx, req: CmdHttpResponseBodyReq) -> Result { - Ok(crate::cmd_http_response_body(ctx.window.clone(), &req.response_id, req.filter.as_deref()).await?) +async fn cmd_http_response_body( + ctx: ClientCtx, + req: CmdHttpResponseBodyReq, +) -> Result { + Ok(crate::cmd_http_response_body(ctx.window.clone(), &req.response_id, req.filter.as_deref()) + .await?) } -async fn cmd_http_response_body_path(ctx: ClientCtx, req: CmdHttpResponseBodyPathReq) -> Result> { +async fn cmd_http_response_body_path( + ctx: ClientCtx, + req: CmdHttpResponseBodyPathReq, +) -> Result> { Ok(yaak_commands::responses::cmd_http_response_body_path(ctx, req).await?) } -async fn cmd_http_request_body(ctx: ClientCtx, req: CmdHttpRequestBodyReq) -> Result>> { +async fn cmd_http_request_body( + ctx: ClientCtx, + req: CmdHttpRequestBodyReq, +) -> Result>> { Ok(yaak_commands::responses::cmd_http_request_body(ctx, req).await?) } -async fn cmd_get_sse_events(ctx: ClientCtx, req: CmdGetSseEventsReq) -> Result> { +async fn cmd_get_sse_events( + ctx: ClientCtx, + req: CmdGetSseEventsReq, +) -> Result> { Ok(crate::cmd_get_sse_events(ctx.window.app_handle().clone(), &req.response_id).await?) } -async fn cmd_get_http_response_events(ctx: ClientCtx, req: CmdGetHttpResponseEventsReq) -> Result> { +async fn cmd_get_http_response_events( + ctx: ClientCtx, + req: CmdGetHttpResponseEventsReq, +) -> Result> { Ok(yaak_commands::responses::cmd_get_http_response_events(ctx, req).await?) } -async fn cmd_import_data(ctx: ClientCtx, req: CmdImportDataReq) -> Result { +async fn cmd_import_data( + ctx: ClientCtx, + req: CmdImportDataReq, +) -> Result { Ok(crate::cmd_import_data(ctx.window.clone(), &req.file_path, req.destination).await?) } @@ -461,16 +524,25 @@ async fn cmd_import_url(ctx: ClientCtx, req: CmdImportUrlReq) -> Ok(crate::cmd_import_url(ctx.window.clone(), &req.url, req.destination).await?) } -async fn cmd_commit_import(ctx: ClientCtx, req: CmdCommitImportReq) -> Result { +async fn cmd_commit_import( + ctx: ClientCtx, + req: CmdCommitImportReq, +) -> Result { Ok(crate::cmd_commit_import(ctx.window.clone(), req.plan).await?) } -async fn cmd_list_import_sources(ctx: ClientCtx, req: CmdListImportSourcesReq) -> Result> { +async fn cmd_list_import_sources( + ctx: ClientCtx, + req: CmdListImportSourcesReq, +) -> Result> { use crate::models_ext::QueryManagerExt; Ok(ctx.window.db().list_import_sources(&req.workspace_id)?) } -async fn cmd_import_sources_for_origin(ctx: ClientCtx, req: CmdImportSourcesForOriginReq) -> Result> { +async fn cmd_import_sources_for_origin( + ctx: ClientCtx, + req: CmdImportSourcesForOriginReq, +) -> Result> { use crate::models_ext::QueryManagerExt; let origin = match (req.file_path, req.url) { (Some(file_path), _) => crate::import::file_origin(&file_path).origin, @@ -483,67 +555,115 @@ async fn cmd_import_sources_for_origin(ctx: ClientCtx, req: CmdIm Ok(ctx.window.db().list_import_sources_by_origin(&origin)?) } -async fn cmd_http_request_actions(ctx: ClientCtx, req: CmdHttpRequestActionsReq) -> Result> { +async fn cmd_http_request_actions( + ctx: ClientCtx, + req: CmdHttpRequestActionsReq, +) -> Result> { Ok(yaak_commands::actions::cmd_http_request_actions(ctx, req).await?) } -async fn cmd_websocket_request_actions(ctx: ClientCtx, req: CmdWebsocketRequestActionsReq) -> Result> { +async fn cmd_websocket_request_actions( + ctx: ClientCtx, + req: CmdWebsocketRequestActionsReq, +) -> Result> { Ok(yaak_commands::actions::cmd_websocket_request_actions(ctx, req).await?) } -async fn cmd_call_websocket_request_action(ctx: ClientCtx, req: CmdCallWebsocketRequestActionReq) -> Result<()> { +async fn cmd_call_websocket_request_action( + ctx: ClientCtx, + req: CmdCallWebsocketRequestActionReq, +) -> Result<()> { Ok(yaak_commands::actions::cmd_call_websocket_request_action(ctx, req).await?) } -async fn cmd_workspace_actions(ctx: ClientCtx, req: CmdWorkspaceActionsReq) -> Result> { +async fn cmd_workspace_actions( + ctx: ClientCtx, + req: CmdWorkspaceActionsReq, +) -> Result> { Ok(yaak_commands::actions::cmd_workspace_actions(ctx, req).await?) } -async fn cmd_call_workspace_action(ctx: ClientCtx, req: CmdCallWorkspaceActionReq) -> Result<()> { +async fn cmd_call_workspace_action( + ctx: ClientCtx, + req: CmdCallWorkspaceActionReq, +) -> Result<()> { Ok(yaak_commands::actions::cmd_call_workspace_action(ctx, req).await?) } -async fn cmd_folder_actions(ctx: ClientCtx, req: CmdFolderActionsReq) -> Result> { +async fn cmd_folder_actions( + ctx: ClientCtx, + req: CmdFolderActionsReq, +) -> Result> { Ok(yaak_commands::actions::cmd_folder_actions(ctx, req).await?) } -async fn cmd_call_folder_action(ctx: ClientCtx, req: CmdCallFolderActionReq) -> Result<()> { +async fn cmd_call_folder_action( + ctx: ClientCtx, + req: CmdCallFolderActionReq, +) -> Result<()> { Ok(yaak_commands::actions::cmd_call_folder_action(ctx, req).await?) } -async fn cmd_grpc_request_actions(ctx: ClientCtx, req: CmdGrpcRequestActionsReq) -> Result> { +async fn cmd_grpc_request_actions( + ctx: ClientCtx, + req: CmdGrpcRequestActionsReq, +) -> Result> { Ok(yaak_commands::actions::cmd_grpc_request_actions(ctx, req).await?) } -async fn cmd_template_function_summaries(ctx: ClientCtx, req: CmdTemplateFunctionSummariesReq) -> Result> { +async fn cmd_template_function_summaries( + ctx: ClientCtx, + req: CmdTemplateFunctionSummariesReq, +) -> Result> { Ok(yaak_commands::templates::cmd_template_function_summaries(ctx, req).await?) } -async fn cmd_template_function_config(ctx: ClientCtx, req: CmdTemplateFunctionConfigReq) -> Result { +async fn cmd_template_function_config( + ctx: ClientCtx, + req: CmdTemplateFunctionConfigReq, +) -> Result { Ok(yaak_commands::templates::cmd_template_function_config(ctx, req).await?) } -async fn cmd_get_http_authentication_summaries(ctx: ClientCtx, req: CmdGetHttpAuthenticationSummariesReq) -> Result> { +async fn cmd_get_http_authentication_summaries( + ctx: ClientCtx, + req: CmdGetHttpAuthenticationSummariesReq, +) -> Result> { Ok(yaak_commands::auth::cmd_get_http_authentication_summaries(ctx, req).await?) } -async fn cmd_get_http_authentication_config(ctx: ClientCtx, req: CmdGetHttpAuthenticationConfigReq) -> Result { +async fn cmd_get_http_authentication_config( + ctx: ClientCtx, + req: CmdGetHttpAuthenticationConfigReq, +) -> Result { Ok(yaak_commands::auth::cmd_get_http_authentication_config(ctx, req).await?) } -async fn cmd_call_http_request_action(ctx: ClientCtx, req: CmdCallHttpRequestActionReq) -> Result<()> { +async fn cmd_call_http_request_action( + ctx: ClientCtx, + req: CmdCallHttpRequestActionReq, +) -> Result<()> { Ok(yaak_commands::actions::cmd_call_http_request_action(ctx, req).await?) } -async fn cmd_call_grpc_request_action(ctx: ClientCtx, req: CmdCallGrpcRequestActionReq) -> Result<()> { +async fn cmd_call_grpc_request_action( + ctx: ClientCtx, + req: CmdCallGrpcRequestActionReq, +) -> Result<()> { Ok(yaak_commands::actions::cmd_call_grpc_request_action(ctx, req).await?) } -async fn cmd_call_http_authentication_action(ctx: ClientCtx, req: CmdCallHttpAuthenticationActionReq) -> Result<()> { +async fn cmd_call_http_authentication_action( + ctx: ClientCtx, + req: CmdCallHttpAuthenticationActionReq, +) -> Result<()> { Ok(yaak_commands::auth::cmd_call_http_authentication_action(ctx, req).await?) } -async fn cmd_curl_to_request(ctx: ClientCtx, req: CmdCurlToRequestReq) -> Result { +async fn cmd_curl_to_request( + ctx: ClientCtx, + req: CmdCurlToRequestReq, +) -> Result { Ok(yaak_commands::actions::cmd_curl_to_request(ctx, req).await?) } @@ -551,83 +671,159 @@ async fn cmd_export_data(ctx: ClientCtx, req: CmdExportDataReq) - Ok(yaak_commands::data::cmd_export_data(ctx, req).await?) } -async fn cmd_save_base64_to_binary(ctx: ClientCtx, req: CmdSaveBase64ToBinaryReq) -> Result<()> { - Ok(crate::cmd_save_base64_to_binary(ctx.window.app_handle().clone(), &req.filepath, &req.data).await?) +async fn cmd_save_base64_to_binary( + ctx: ClientCtx, + req: CmdSaveBase64ToBinaryReq, +) -> Result<()> { + Ok(crate::cmd_save_base64_to_binary(ctx.window.app_handle().clone(), &req.filepath, &req.data) + .await?) } async fn cmd_save_response(ctx: ClientCtx, req: CmdSaveResponseReq) -> Result<()> { Ok(yaak_commands::responses::cmd_save_response(ctx, req).await?) } -async fn cmd_send_http_request(ctx: ClientCtx, req: CmdSendHttpRequestReq) -> Result { - Ok(crate::cmd_send_http_request(ctx.window.app_handle().clone(), ctx.window.clone(), req.environment_id.as_deref(), req.cookie_jar_id.as_deref(), req.request_id).await?) +async fn cmd_send_http_request( + ctx: ClientCtx, + req: CmdSendHttpRequestReq, +) -> Result { + Ok(crate::cmd_send_http_request( + ctx.window.app_handle().clone(), + ctx.window.clone(), + req.environment_id.as_deref(), + req.cookie_jar_id.as_deref(), + req.request_id, + ) + .await?) } -async fn cmd_reload_plugins(ctx: ClientCtx, req: CmdReloadPluginsReq) -> Result> { +async fn cmd_reload_plugins( + ctx: ClientCtx, + req: CmdReloadPluginsReq, +) -> Result> { Ok(yaak_commands::actions::cmd_reload_plugins(ctx, req).await?) } -async fn cmd_plugin_info(ctx: ClientCtx, req: CmdPluginInfoReq) -> Result { +async fn cmd_plugin_info( + ctx: ClientCtx, + req: CmdPluginInfoReq, +) -> Result { Ok(yaak_commands::plugins::cmd_plugin_info(ctx, req).await?) } -async fn cmd_delete_all_grpc_connections(ctx: ClientCtx, req: CmdDeleteAllGrpcConnectionsReq) -> Result<()> { +async fn cmd_delete_all_grpc_connections( + ctx: ClientCtx, + req: CmdDeleteAllGrpcConnectionsReq, +) -> Result<()> { Ok(yaak_commands::models::cmd_delete_all_grpc_connections(ctx, req).await?) } -async fn cmd_delete_send_history(ctx: ClientCtx, req: CmdDeleteSendHistoryReq) -> Result<()> { +async fn cmd_delete_send_history( + ctx: ClientCtx, + req: CmdDeleteSendHistoryReq, +) -> Result<()> { Ok(yaak_commands::models::cmd_delete_send_history(ctx, req).await?) } -async fn cmd_delete_all_http_responses(ctx: ClientCtx, req: CmdDeleteAllHttpResponsesReq) -> Result<()> { +async fn cmd_delete_all_http_responses( + ctx: ClientCtx, + req: CmdDeleteAllHttpResponsesReq, +) -> Result<()> { Ok(yaak_commands::models::cmd_delete_all_http_responses(ctx, req).await?) } -async fn cmd_get_workspace_meta(ctx: ClientCtx, req: CmdGetWorkspaceMetaReq) -> Result { +async fn cmd_get_workspace_meta( + ctx: ClientCtx, + req: CmdGetWorkspaceMetaReq, +) -> Result { Ok(yaak_commands::models::cmd_get_workspace_meta(ctx, req).await?) } -async fn cmd_new_child_window(ctx: ClientCtx, req: CmdNewChildWindowReq) -> Result<()> { - Ok(crate::cmd_new_child_window(ctx.window.clone(), &req.url, &req.label, &req.title, req.inner_size).await?) +async fn cmd_new_child_window( + ctx: ClientCtx, + req: CmdNewChildWindowReq, +) -> Result<()> { + Ok(crate::cmd_new_child_window( + ctx.window.clone(), + &req.url, + &req.label, + &req.title, + req.inner_size, + ) + .await?) } -async fn cmd_new_main_window(ctx: ClientCtx, req: CmdNewMainWindowReq) -> Result<()> { +async fn cmd_new_main_window( + ctx: ClientCtx, + req: CmdNewMainWindowReq, +) -> Result<()> { Ok(crate::cmd_new_main_window(ctx.window.app_handle().clone(), &req.url).await?) } -async fn cmd_check_for_updates(ctx: ClientCtx, _req: CmdCheckForUpdatesReq) -> Result { - Ok(crate::cmd_check_for_updates(ctx.window.clone(), ctx.window.app_handle().state::>()).await?) +async fn cmd_check_for_updates( + ctx: ClientCtx, + _req: CmdCheckForUpdatesReq, +) -> Result { + Ok(crate::cmd_check_for_updates( + ctx.window.clone(), + ctx.window.app_handle().state::>(), + ) + .await?) } -async fn cmd_decrypt_template(ctx: ClientCtx, req: CmdDecryptTemplateReq) -> Result { +async fn cmd_decrypt_template( + ctx: ClientCtx, + req: CmdDecryptTemplateReq, +) -> Result { Ok(yaak_commands::encryption::cmd_decrypt_template(ctx, req).await?) } -async fn cmd_secure_template(ctx: ClientCtx, req: CmdSecureTemplateReq) -> Result { +async fn cmd_secure_template( + ctx: ClientCtx, + req: CmdSecureTemplateReq, +) -> Result { Ok(yaak_commands::encryption::cmd_secure_template(ctx, req).await?) } -async fn cmd_get_themes(ctx: ClientCtx, req: CmdGetThemesReq) -> Result> { +async fn cmd_get_themes( + ctx: ClientCtx, + req: CmdGetThemesReq, +) -> Result> { Ok(yaak_commands::templates::cmd_get_themes(ctx, req).await?) } -async fn cmd_enable_encryption(ctx: ClientCtx, req: CmdEnableEncryptionReq) -> Result<()> { +async fn cmd_enable_encryption( + ctx: ClientCtx, + req: CmdEnableEncryptionReq, +) -> Result<()> { Ok(yaak_commands::encryption::cmd_enable_encryption(ctx, req).await?) } -async fn cmd_reveal_workspace_key(ctx: ClientCtx, req: CmdRevealWorkspaceKeyReq) -> Result { +async fn cmd_reveal_workspace_key( + ctx: ClientCtx, + req: CmdRevealWorkspaceKeyReq, +) -> Result { Ok(yaak_commands::encryption::cmd_reveal_workspace_key(ctx, req).await?) } -async fn cmd_set_workspace_key(ctx: ClientCtx, req: CmdSetWorkspaceKeyReq) -> Result<()> { +async fn cmd_set_workspace_key( + ctx: ClientCtx, + req: CmdSetWorkspaceKeyReq, +) -> Result<()> { Ok(yaak_commands::encryption::cmd_set_workspace_key(ctx, req).await?) } -async fn cmd_disable_encryption(ctx: ClientCtx, req: CmdDisableEncryptionReq) -> Result<()> { +async fn cmd_disable_encryption( + ctx: ClientCtx, + req: CmdDisableEncryptionReq, +) -> Result<()> { Ok(yaak_commands::encryption::cmd_disable_encryption(ctx, req).await?) } -async fn cmd_default_headers(ctx: ClientCtx, req: CmdDefaultHeadersReq) -> Result> { +async fn cmd_default_headers( + ctx: ClientCtx, + req: CmdDefaultHeadersReq, +) -> Result> { Ok(yaak_commands::models::cmd_default_headers(ctx, req).await?) } @@ -649,27 +845,45 @@ async fn models_delete(ctx: ClientCtx, req: ModelsDeleteReq) -> R Ok(deleted?) } -async fn models_duplicate(ctx: ClientCtx, req: ModelsDuplicateReq) -> Result { +async fn models_duplicate( + ctx: ClientCtx, + req: ModelsDuplicateReq, +) -> Result { Ok(yaak_commands::models::models_duplicate(ctx, req).await?) } -async fn models_websocket_events(ctx: ClientCtx, req: ModelsWebsocketEventsReq) -> Result> { +async fn models_websocket_events( + ctx: ClientCtx, + req: ModelsWebsocketEventsReq, +) -> Result> { Ok(yaak_commands::models::models_websocket_events(ctx, req).await?) } -async fn models_grpc_events(ctx: ClientCtx, req: ModelsGrpcEventsReq) -> Result> { +async fn models_grpc_events( + ctx: ClientCtx, + req: ModelsGrpcEventsReq, +) -> Result> { Ok(yaak_commands::models::models_grpc_events(ctx, req).await?) } -async fn models_get_settings(ctx: ClientCtx, req: ModelsGetSettingsReq) -> Result { +async fn models_get_settings( + ctx: ClientCtx, + req: ModelsGetSettingsReq, +) -> Result { Ok(yaak_commands::models::models_get_settings(ctx, req).await?) } -async fn models_get_graphql_introspection(ctx: ClientCtx, req: ModelsGetGraphqlIntrospectionReq) -> Result> { +async fn models_get_graphql_introspection( + ctx: ClientCtx, + req: ModelsGetGraphqlIntrospectionReq, +) -> Result> { Ok(yaak_commands::models::models_get_graphql_introspection(ctx, req).await?) } -async fn models_upsert_graphql_introspection(ctx: ClientCtx, req: ModelsUpsertGraphqlIntrospectionReq) -> Result { +async fn models_upsert_graphql_introspection( + ctx: ClientCtx, + req: ModelsUpsertGraphqlIntrospectionReq, +) -> Result { Ok(yaak_commands::models::models_upsert_graphql_introspection(ctx, req).await?) } @@ -680,7 +894,10 @@ async fn models_upsert_graphql_introspection(ctx: ClientCtx, req: /// freezes the app"). Escape sequences sidestep it. This is a quirk of the /// webview transport, not of the data, so it lives in the adapter rather than /// the shared handler. -async fn models_workspace_models(ctx: ClientCtx, req: ModelsWorkspaceModelsReq) -> Result { +async fn models_workspace_models( + ctx: ClientCtx, + req: ModelsWorkspaceModelsReq, +) -> Result { let json = yaak_commands::models::models_workspace_models(ctx, req).await?; Ok(escape_str_for_webview(&json)) } @@ -706,7 +923,10 @@ fn escape_str_for_webview(input: &str) -> String { .collect() } -async fn cmd_git_checkout(_ctx: ClientCtx, req: CmdGitCheckoutReq) -> Result { +async fn cmd_git_checkout( + _ctx: ClientCtx, + req: CmdGitCheckoutReq, +) -> Result { Ok(crate::git_ext::cmd_git_checkout(&req.dir, &req.branch, req.force).await?) } @@ -714,31 +934,52 @@ async fn cmd_git_branch(_ctx: ClientCtx, req: CmdGitBranchReq) -> Ok(crate::git_ext::cmd_git_branch(&req.dir, &req.branch, req.base.as_deref()).await?) } -async fn cmd_git_delete_branch(_ctx: ClientCtx, req: CmdGitDeleteBranchReq) -> Result { +async fn cmd_git_delete_branch( + _ctx: ClientCtx, + req: CmdGitDeleteBranchReq, +) -> Result { Ok(crate::git_ext::cmd_git_delete_branch(&req.dir, &req.branch, req.force).await?) } -async fn cmd_git_delete_remote_branch(_ctx: ClientCtx, req: CmdGitDeleteRemoteBranchReq) -> Result<()> { +async fn cmd_git_delete_remote_branch( + _ctx: ClientCtx, + req: CmdGitDeleteRemoteBranchReq, +) -> Result<()> { Ok(crate::git_ext::cmd_git_delete_remote_branch(&req.dir, &req.branch).await?) } -async fn cmd_git_merge_branch(_ctx: ClientCtx, req: CmdGitMergeBranchReq) -> Result<()> { +async fn cmd_git_merge_branch( + _ctx: ClientCtx, + req: CmdGitMergeBranchReq, +) -> Result<()> { Ok(crate::git_ext::cmd_git_merge_branch(&req.dir, &req.branch).await?) } -async fn cmd_git_rename_branch(_ctx: ClientCtx, req: CmdGitRenameBranchReq) -> Result<()> { +async fn cmd_git_rename_branch( + _ctx: ClientCtx, + req: CmdGitRenameBranchReq, +) -> Result<()> { Ok(crate::git_ext::cmd_git_rename_branch(&req.dir, &req.old_name, &req.new_name).await?) } -async fn cmd_git_status(_ctx: ClientCtx, req: CmdGitStatusReq) -> Result { +async fn cmd_git_status( + _ctx: ClientCtx, + req: CmdGitStatusReq, +) -> Result { Ok(crate::git_ext::cmd_git_status(&req.dir).await?) } -async fn cmd_git_branch_info(_ctx: ClientCtx, req: CmdGitBranchInfoReq) -> Result { +async fn cmd_git_branch_info( + _ctx: ClientCtx, + req: CmdGitBranchInfoReq, +) -> Result { Ok(crate::git_ext::cmd_git_branch_info(&req.dir).await?) } -async fn cmd_git_worktree_status(_ctx: ClientCtx, req: CmdGitWorktreeStatusReq) -> Result { +async fn cmd_git_worktree_status( + _ctx: ClientCtx, + req: CmdGitWorktreeStatusReq, +) -> Result { Ok(crate::git_ext::cmd_git_worktree_status(&req.dir).await?) } @@ -746,15 +987,25 @@ async fn cmd_git_log(_ctx: ClientCtx, req: CmdGitLogReq) -> Resul Ok(crate::git_ext::cmd_git_log(&req.dir).await?) } -async fn cmd_git_log_for_file(_ctx: ClientCtx, req: CmdGitLogForFileReq) -> Result> { +async fn cmd_git_log_for_file( + _ctx: ClientCtx, + req: CmdGitLogForFileReq, +) -> Result> { Ok(crate::git_ext::cmd_git_log_for_file(&req.dir, req.rela_path).await?) } -async fn cmd_git_file_diff_for_commit(_ctx: ClientCtx, req: CmdGitFileDiffForCommitReq) -> Result { - Ok(crate::git_ext::cmd_git_file_diff_for_commit(&req.dir, &req.commit_oid, req.rela_path).await?) +async fn cmd_git_file_diff_for_commit( + _ctx: ClientCtx, + req: CmdGitFileDiffForCommitReq, +) -> Result { + Ok(crate::git_ext::cmd_git_file_diff_for_commit(&req.dir, &req.commit_oid, req.rela_path) + .await?) } -async fn cmd_git_initialize(_ctx: ClientCtx, req: CmdGitInitializeReq) -> Result<()> { +async fn cmd_git_initialize( + _ctx: ClientCtx, + req: CmdGitInitializeReq, +) -> Result<()> { Ok(crate::git_ext::cmd_git_initialize(&req.dir).await?) } @@ -778,11 +1029,17 @@ async fn cmd_git_pull(_ctx: ClientCtx, req: CmdGitPullReq) -> Res Ok(crate::git_ext::cmd_git_pull(&req.dir).await?) } -async fn cmd_git_pull_force_reset(_ctx: ClientCtx, req: CmdGitPullForceResetReq) -> Result { +async fn cmd_git_pull_force_reset( + _ctx: ClientCtx, + req: CmdGitPullForceResetReq, +) -> Result { Ok(crate::git_ext::cmd_git_pull_force_reset(&req.dir, &req.remote, &req.branch).await?) } -async fn cmd_git_pull_merge(_ctx: ClientCtx, req: CmdGitPullMergeReq) -> Result { +async fn cmd_git_pull_merge( + _ctx: ClientCtx, + req: CmdGitPullMergeReq, +) -> Result { Ok(crate::git_ext::cmd_git_pull_merge(&req.dir, &req.remote, &req.branch).await?) } @@ -794,27 +1051,47 @@ async fn cmd_git_unstage(_ctx: ClientCtx, req: CmdGitUnstageReq) Ok(crate::git_ext::cmd_git_unstage(&req.dir, req.rela_paths).await?) } -async fn cmd_git_reset_changes(_ctx: ClientCtx, req: CmdGitResetChangesReq) -> Result<()> { +async fn cmd_git_reset_changes( + _ctx: ClientCtx, + req: CmdGitResetChangesReq, +) -> Result<()> { Ok(crate::git_ext::cmd_git_reset_changes(&req.dir).await?) } -async fn cmd_git_restore_files(_ctx: ClientCtx, req: CmdGitRestoreFilesReq) -> Result<()> { +async fn cmd_git_restore_files( + _ctx: ClientCtx, + req: CmdGitRestoreFilesReq, +) -> Result<()> { Ok(crate::git_ext::cmd_git_restore_files(&req.dir, req.rela_paths).await?) } -async fn cmd_git_restore_file_from_commit(_ctx: ClientCtx, req: CmdGitRestoreFileFromCommitReq) -> Result<()> { - Ok(crate::git_ext::cmd_git_restore_file_from_commit(&req.dir, &req.commit_oid, req.rela_path).await?) +async fn cmd_git_restore_file_from_commit( + _ctx: ClientCtx, + req: CmdGitRestoreFileFromCommitReq, +) -> Result<()> { + Ok(crate::git_ext::cmd_git_restore_file_from_commit(&req.dir, &req.commit_oid, req.rela_path) + .await?) } -async fn cmd_git_add_credential(_ctx: ClientCtx, req: CmdGitAddCredentialReq) -> Result<()> { - Ok(crate::git_ext::cmd_git_add_credential(&req.remote_url, &req.username, &req.password).await?) +async fn cmd_git_add_credential( + _ctx: ClientCtx, + req: CmdGitAddCredentialReq, +) -> Result<()> { + Ok(crate::git_ext::cmd_git_add_credential(&req.remote_url, &req.username, &req.password) + .await?) } -async fn cmd_git_remotes(_ctx: ClientCtx, req: CmdGitRemotesReq) -> Result> { +async fn cmd_git_remotes( + _ctx: ClientCtx, + req: CmdGitRemotesReq, +) -> Result> { Ok(crate::git_ext::cmd_git_remotes(&req.dir).await?) } -async fn cmd_git_add_remote(_ctx: ClientCtx, req: CmdGitAddRemoteReq) -> Result { +async fn cmd_git_add_remote( + _ctx: ClientCtx, + req: CmdGitAddRemoteReq, +) -> Result { Ok(crate::git_ext::cmd_git_add_remote(&req.dir, &req.name, &req.url).await?) } @@ -822,58 +1099,130 @@ async fn cmd_git_rm_remote(_ctx: ClientCtx, req: CmdGitRmRemoteRe Ok(crate::git_ext::cmd_git_rm_remote(&req.dir, &req.name).await?) } -async fn cmd_sync_calculate(ctx: ClientCtx, req: CmdSyncCalculateReq) -> Result> { - Ok(crate::sync_ext::cmd_sync_calculate(ctx.window.app_handle().clone(), &req.workspace_id, &req.sync_dir).await?) +async fn cmd_sync_calculate( + ctx: ClientCtx, + req: CmdSyncCalculateReq, +) -> Result> { + Ok(crate::sync_ext::cmd_sync_calculate( + ctx.window.app_handle().clone(), + &req.workspace_id, + &req.sync_dir, + ) + .await?) } -async fn cmd_sync_calculate_fs(_ctx: ClientCtx, req: CmdSyncCalculateFsReq) -> Result> { +async fn cmd_sync_calculate_fs( + _ctx: ClientCtx, + req: CmdSyncCalculateFsReq, +) -> Result> { Ok(crate::sync_ext::cmd_sync_calculate_fs(&req.dir).await?) } async fn cmd_sync_apply(ctx: ClientCtx, req: CmdSyncApplyReq) -> Result<()> { - Ok(crate::sync_ext::cmd_sync_apply(ctx.window.app_handle().clone(), req.sync_ops, &req.sync_dir, &req.workspace_id).await?) + Ok(crate::sync_ext::cmd_sync_apply( + ctx.window.app_handle().clone(), + req.sync_ops, + &req.sync_dir, + &req.workspace_id, + ) + .await?) } -async fn cmd_ws_delete_connections(ctx: ClientCtx, req: CmdWsDeleteConnectionsReq) -> Result<()> { +async fn cmd_ws_delete_connections( + ctx: ClientCtx, + req: CmdWsDeleteConnectionsReq, +) -> Result<()> { Ok(yaak_commands::models::cmd_ws_delete_connections(ctx, req).await?) } -async fn cmd_ws_send(ctx: ClientCtx, req: CmdWsSendReq) -> Result { - Ok(crate::ws_ext::cmd_ws_send(&req.connection_id, req.environment_id.as_deref(), ctx.window.app_handle().clone(), ctx.window.clone(), ctx.window.app_handle().state::>()).await?) +async fn cmd_ws_send( + ctx: ClientCtx, + req: CmdWsSendReq, +) -> Result { + Ok(crate::ws_ext::cmd_ws_send( + &req.connection_id, + req.environment_id.as_deref(), + ctx.window.app_handle().clone(), + ctx.window.clone(), + ctx.window.app_handle().state::>(), + ) + .await?) } -async fn cmd_ws_close(ctx: ClientCtx, req: CmdWsCloseReq) -> Result { - Ok(crate::ws_ext::cmd_ws_close(&req.connection_id, ctx.window.app_handle().clone(), ctx.window.clone(), ctx.window.app_handle().state::>()).await?) +async fn cmd_ws_close( + ctx: ClientCtx, + req: CmdWsCloseReq, +) -> Result { + Ok(crate::ws_ext::cmd_ws_close( + &req.connection_id, + ctx.window.app_handle().clone(), + ctx.window.clone(), + ctx.window.app_handle().state::>(), + ) + .await?) } -async fn cmd_ws_connect(ctx: ClientCtx, req: CmdWsConnectReq) -> Result { - Ok(crate::ws_ext::cmd_ws_connect(&req.request_id, req.environment_id.as_deref(), req.cookie_jar_id.as_deref(), ctx.window.app_handle().clone(), ctx.window.clone(), ctx.window.app_handle().state::>()).await?) +async fn cmd_ws_connect( + ctx: ClientCtx, + req: CmdWsConnectReq, +) -> Result { + Ok(crate::ws_ext::cmd_ws_connect( + &req.request_id, + req.environment_id.as_deref(), + req.cookie_jar_id.as_deref(), + ctx.window.app_handle().clone(), + ctx.window.clone(), + ctx.window.app_handle().state::>(), + ) + .await?) } -async fn cmd_plugins_search(ctx: ClientCtx, req: CmdPluginsSearchReq) -> Result { +async fn cmd_plugins_search( + ctx: ClientCtx, + req: CmdPluginsSearchReq, +) -> Result { Ok(crate::plugins_ext::cmd_plugins_search(ctx.window.app_handle().clone(), &req.query).await?) } -async fn cmd_plugins_install(ctx: ClientCtx, req: CmdPluginsInstallReq) -> Result<()> { +async fn cmd_plugins_install( + ctx: ClientCtx, + req: CmdPluginsInstallReq, +) -> Result<()> { Ok(crate::plugins_ext::cmd_plugins_install(ctx.window.clone(), &req.name, req.version).await?) } -async fn cmd_plugins_install_from_directory(ctx: ClientCtx, req: CmdPluginsInstallFromDirectoryReq) -> Result { - Ok(crate::plugins_ext::cmd_plugins_install_from_directory(ctx.window.clone(), &req.directory).await?) +async fn cmd_plugins_install_from_directory( + ctx: ClientCtx, + req: CmdPluginsInstallFromDirectoryReq, +) -> Result { + Ok(crate::plugins_ext::cmd_plugins_install_from_directory(ctx.window.clone(), &req.directory) + .await?) } -async fn cmd_plugins_uninstall(ctx: ClientCtx, req: CmdPluginsUninstallReq) -> Result { +async fn cmd_plugins_uninstall( + ctx: ClientCtx, + req: CmdPluginsUninstallReq, +) -> Result { Ok(crate::plugins_ext::cmd_plugins_uninstall(&req.plugin_id, ctx.window.clone()).await?) } -async fn cmd_plugin_init_errors(ctx: ClientCtx, req: CmdPluginInitErrorsReq) -> Result> { +async fn cmd_plugin_init_errors( + ctx: ClientCtx, + req: CmdPluginInitErrorsReq, +) -> Result> { Ok(yaak_commands::plugins::cmd_plugin_init_errors(ctx, req).await?) } -async fn cmd_plugins_updates(ctx: ClientCtx, _req: CmdPluginsUpdatesReq) -> Result { +async fn cmd_plugins_updates( + ctx: ClientCtx, + _req: CmdPluginsUpdatesReq, +) -> Result { Ok(crate::plugins_ext::cmd_plugins_updates(ctx.window.app_handle().clone()).await?) } -async fn cmd_plugins_update_all(ctx: ClientCtx, _req: CmdPluginsUpdateAllReq) -> Result> { +async fn cmd_plugins_update_all( + ctx: ClientCtx, + _req: CmdPluginsUpdateAllReq, +) -> Result> { Ok(crate::plugins_ext::cmd_plugins_update_all(ctx.window.clone()).await?) } diff --git a/crates-tauri/yaak-app-client/src/ws_ext.rs b/crates-tauri/yaak-app-client/src/ws_ext.rs index 7ccba1fe..46419678 100644 --- a/crates-tauri/yaak-app-client/src/ws_ext.rs +++ b/crates-tauri/yaak-app-client/src/ws_ext.rs @@ -13,6 +13,7 @@ use tauri::{AppHandle, Manager, Runtime, State, WebviewWindow}; use tokio::sync::{Mutex, mpsc}; use tokio_tungstenite::tungstenite::Message; use url::Url; +use yaak_commands::resolve::resolve_websocket_request; use yaak_crypto::manager::EncryptionManager; use yaak_http::cookies::CookieStore; use yaak_http::path_placeholders::apply_path_placeholders; @@ -26,7 +27,6 @@ use yaak_plugins::template_callback::PluginTemplateCallback; use yaak_templates::strip_json_comments::maybe_strip_json_comments; use yaak_templates::{RenderErrorBehavior, RenderOptions}; use yaak_tls::find_client_certificate; -use yaak_commands::resolve::resolve_websocket_request; use yaak_ws::{WebsocketManager, render_websocket_request}; pub async fn cmd_ws_send( @@ -453,7 +453,6 @@ pub async fn cmd_ws_connect( Ok(connection) } - /// Convert WS URL to HTTP URL for cookie filtering /// WebSocket upgrade requests are HTTP requests initially, so HttpOnly cookies should apply fn convert_ws_url_to_http(ws_url: &Url) -> Url { diff --git a/crates/common/yaak-database/src/update_source.rs b/crates/common/yaak-database/src/update_source.rs index c378d5d3..b2349304 100644 --- a/crates/common/yaak-database/src/update_source.rs +++ b/crates/common/yaak-database/src/update_source.rs @@ -20,7 +20,9 @@ impl UpdateSource { #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "snake_case", tag = "type")] pub enum ModelChangeEvent { - Upsert { created: bool }, + Upsert { + created: bool, + }, /// A delete for a workspace implies deletion of every model in that /// workspace — children are bulk-deleted without their own change rows or /// events, and consumers must prune the subtree themselves (the frontend diff --git a/crates/common/yaak-rpc-schema/src/lib.rs b/crates/common/yaak-rpc-schema/src/lib.rs index 776f91cf..d18ef3dc 100644 --- a/crates/common/yaak-rpc-schema/src/lib.rs +++ b/crates/common/yaak-rpc-schema/src/lib.rs @@ -29,11 +29,10 @@ use yaak_plugins::api::{PluginNameVersion, PluginSearchResponse, PluginUpdatesRe use yaak_plugins::events::{ CallFolderActionRequest, CallGrpcRequestActionRequest, CallHttpRequestActionRequest, CallWebsocketRequestActionRequest, CallWorkspaceActionRequest, FilterResponse, - GetFolderActionsResponse, GetGrpcRequestActionsResponse, - GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse, - GetHttpRequestActionsResponse, GetTemplateFunctionConfigResponse, - GetTemplateFunctionSummaryResponse, GetThemesResponse, GetWebsocketRequestActionsResponse, - GetWorkspaceActionsResponse, JsonPrimitive, RenderPurpose, + GetFolderActionsResponse, GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse, + GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse, + GetTemplateFunctionConfigResponse, GetTemplateFunctionSummaryResponse, GetThemesResponse, + GetWebsocketRequestActionsResponse, GetWorkspaceActionsResponse, JsonPrimitive, RenderPurpose, }; use yaak_plugins::plugin_meta::PluginMetadata; use yaak_sse::sse::ServerSentEvent; diff --git a/crates/common/yaak-rpc/src/lib.rs b/crates/common/yaak-rpc/src/lib.rs index 760e9f21..05765cfb 100644 --- a/crates/common/yaak-rpc/src/lib.rs +++ b/crates/common/yaak-rpc/src/lib.rs @@ -13,8 +13,9 @@ pub type BoxFuture = Pin + Send + 'static>>; /// `dispatch` call frame, so it cannot borrow, and contexts are cheap clones /// (handles and `Arc`s). Synchronous handlers wrap into this via `rpc_handler!` /// with no visible change. -type HandlerFn = - Box BoxFuture> + Send + Sync>; +type HandlerFn = Box< + dyn Fn(Ctx, serde_json::Value) -> BoxFuture> + Send + Sync, +>; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RpcError { @@ -249,9 +250,8 @@ macro_rules! rpc_handler_async { Box::new(|ctx, payload| { Box::pin(async move { let req = serde_json::from_value(payload).map_err($crate::RpcError::from)?; - let res = $f(ctx, req) - .await - .map_err(|e| $crate::RpcError { message: e.to_string() })?; + let res = + $f(ctx, req).await.map_err(|e| $crate::RpcError { message: e.to_string() })?; serde_json::to_value(res).map_err($crate::RpcError::from) }) }) diff --git a/crates/yaak-models/src/lib.rs b/crates/yaak-models/src/lib.rs index ee6c7929..755f1289 100644 --- a/crates/yaak-models/src/lib.rs +++ b/crates/yaak-models/src/lib.rs @@ -10,8 +10,8 @@ use yaak_database::SqlitePool; pub mod blob_manager; pub mod client_db; -pub mod cookies; mod connection_or_tx; +pub mod cookies; pub mod error; pub mod migrate; pub mod models; diff --git a/crates/yaak-models/src/queries/http_responses.rs b/crates/yaak-models/src/queries/http_responses.rs index 2edc299d..f77c0c4f 100644 --- a/crates/yaak-models/src/queries/http_responses.rs +++ b/crates/yaak-models/src/queries/http_responses.rs @@ -96,8 +96,7 @@ impl<'a> ClientDb<'a> { let Some(response_id) = path.file_name().and_then(|n| n.to_str()) else { continue; }; - if self.find_optional::(HttpResponseIden::Id, response_id).is_some() - { + if self.find_optional::(HttpResponseIden::Id, response_id).is_some() { continue; } if fs::remove_file(&path).is_ok() { diff --git a/crates/yaak-models/src/queries/mod.rs b/crates/yaak-models/src/queries/mod.rs index e28df092..65e40399 100644 --- a/crates/yaak-models/src/queries/mod.rs +++ b/crates/yaak-models/src/queries/mod.rs @@ -24,8 +24,8 @@ mod websocket_events; mod websocket_requests; mod workspace_metas; pub mod workspaces; -pub use model_changes::PersistedModelChange; pub(crate) use duplicate_name::conflict_free_name; +pub use model_changes::PersistedModelChange; const MAX_HISTORY_ITEMS: usize = 20; diff --git a/crates/yaak-models/src/queries/workspaces.rs b/crates/yaak-models/src/queries/workspaces.rs index 3b9934a1..797f7eaa 100644 --- a/crates/yaak-models/src/queries/workspaces.rs +++ b/crates/yaak-models/src/queries/workspaces.rs @@ -8,9 +8,9 @@ use crate::models::{ GrpcEventIden, GrpcRequest, GrpcRequestIden, HttpRequest, HttpRequestHeader, HttpRequestIden, HttpResponse, HttpResponseEvent, HttpResponseEventIden, HttpResponseIden, ImportSource, ImportSourceIden, ResolvedHttpRequestSettings, ResolvedSetting, SyncState, SyncStateIden, - WebsocketConnection, - WebsocketConnectionIden, WebsocketEvent, WebsocketEventIden, WebsocketRequest, - WebsocketRequestIden, Workspace, WorkspaceIden, WorkspaceMeta, WorkspaceMetaIden, + WebsocketConnection, WebsocketConnectionIden, WebsocketEvent, WebsocketEventIden, + WebsocketRequest, WebsocketRequestIden, Workspace, WorkspaceIden, WorkspaceMeta, + WorkspaceMetaIden, }; use crate::util::UpdateSource; use log::warn; diff --git a/crates/yaak-models/src/util.rs b/crates/yaak-models/src/util.rs index 47a2dc07..0729ef62 100644 --- a/crates/yaak-models/src/util.rs +++ b/crates/yaak-models/src/util.rs @@ -125,19 +125,11 @@ pub enum ImportPlanWarningLevel { impl ImportPlanWarning { pub fn info(title: impl Into, detail: impl Into) -> Self { - Self { - title: title.into(), - detail: detail.into(), - level: ImportPlanWarningLevel::Info, - } + Self { title: title.into(), detail: detail.into(), level: ImportPlanWarningLevel::Info } } pub fn warning(title: impl Into, detail: impl Into) -> Self { - Self { - title: title.into(), - detail: detail.into(), - level: ImportPlanWarningLevel::Warning, - } + Self { title: title.into(), detail: detail.into(), level: ImportPlanWarningLevel::Warning } } } diff --git a/crates/yaak-sync/src/sync.rs b/crates/yaak-sync/src/sync.rs index c775d6e1..5aa745fb 100644 --- a/crates/yaak-sync/src/sync.rs +++ b/crates/yaak-sync/src/sync.rs @@ -1,5 +1,4 @@ use crate::error::Result; -use yaak_models::blob_manager::BlobManager; use crate::models::SyncModel; use chrono::Utc; use log::{info, warn}; @@ -11,6 +10,7 @@ use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; use ts_rs::TS; +use yaak_models::blob_manager::BlobManager; use yaak_models::client_db::ClientDb; use yaak_models::models::{SyncState, WorkspaceMeta}; use yaak_models::util::{UpdateSource, get_workspace_export_resources}; diff --git a/crates/yaak/src/import.rs b/crates/yaak/src/import.rs index 29841661..d5e5039b 100644 --- a/crates/yaak/src/import.rs +++ b/crates/yaak/src/import.rs @@ -521,16 +521,11 @@ fn record_import_source( }; let incoming_keys: BTreeSet = plan.source_keys.values().cloned().collect(); - let existing = match resolve_linked_source( - db, - &workspace_id, - &plan.importer, - origin, - &incoming_keys, - )? { - LinkedSource::Linked(source) => Some(source), - LinkedSource::Ambiguous(_) | LinkedSource::Unlinked => None, - }; + let existing = + match resolve_linked_source(db, &workspace_id, &plan.importer, origin, &incoming_keys)? { + LinkedSource::Linked(source) => Some(source), + LinkedSource::Ambiguous(_) | LinkedSource::Unlinked => None, + }; let import_source = db.upsert_import_source( &ImportSource { id: existing.map(|s| s.id).unwrap_or_default(), @@ -659,9 +654,8 @@ fn resolve_linked_source( incoming_keys: &BTreeSet, ) -> Result { let sources = db.list_import_sources(workspace_id)?; - let same_origin = |source: &ImportSource| { - source.importer == importer && source.origin == origin.origin - }; + let same_origin = + |source: &ImportSource| source.importer == importer && source.origin == origin.origin; let mut overlapping = Vec::new(); for source in &sources { @@ -743,12 +737,18 @@ fn merge_with_linked_source( let mut current_models: BTreeMap = BTreeMap::new(); { let mut consider = |planned_id: &str, resource: ImportResourceType| -> Result<()> { - let Some(key) = plan.source_keys.get(planned_id) else { return Ok(()) }; - let Some(row) = rows.get(key) else { return Ok(()) }; + let Some(key) = plan.source_keys.get(planned_id) else { + return Ok(()); + }; + let Some(row) = rows.get(key) else { + return Ok(()); + }; if ImportResourceType::from_str(&row.model_type) != Some(resource) { return Ok(()); } - let Some(model_id) = row.model_id.as_deref() else { return Ok(()) }; + let Some(model_id) = row.model_id.as_deref() else { + return Ok(()); + }; let Some(current) = existing_model_json(&db, resource, model_id)? else { return Ok(()); }; @@ -819,11 +819,9 @@ fn merge_with_linked_source( // environment: it came from this source, so the imported-copy separation does not apply. let mut restored_base_names = BTreeSet::new(); for (i, v) in plan.resources.environments.iter_mut().enumerate() { - let is_current_base = current_models - .get(&v.id) - .and_then(|m| m.get("parentModel")) - .and_then(|p| p.as_str()) - == Some("workspace"); + let is_current_base = + current_models.get(&v.id).and_then(|m| m.get("parentModel")).and_then(|p| p.as_str()) + == Some("workspace"); if !is_current_base { continue; } @@ -936,16 +934,13 @@ fn merge_with_linked_source( (false, false) => (ImportPlanAction::Unchanged, false, None), (true, false) => (ImportPlanAction::Update, true, None), (false, true) => (ImportPlanAction::KeepLocal, false, None), - (true, true) => ( - ImportPlanAction::Conflict, - true, - Some(ImportConflictResolution::KeepMine), - ), + (true, true) => { + (ImportPlanAction::Conflict, true, Some(ImportConflictResolution::KeepMine)) + } }; // A resource the source moved into a folder that isn't imported keeps its place // until that folder is: nothing can be written into a folder that will not exist. - let reason = - (!reachable).then_some(ImportPlanReason::MovedIntoIgnoredFolder); + let reason = (!reachable).then_some(ImportPlanReason::MovedIntoIgnoredFolder); let mut planned = item(action, selected && reachable, resolution, reason); planned.changed_fields = changed_fields(&incoming, ¤t); items.push(planned); @@ -956,16 +951,32 @@ fn merge_with_linked_source( classify(AnyModel::Folder(v.clone()), ImportResourceType::Folder, v.folder_id.clone())?; } for v in &plan.resources.http_requests { - classify(AnyModel::HttpRequest(v.clone()), ImportResourceType::HttpRequest, v.folder_id.clone())?; + classify( + AnyModel::HttpRequest(v.clone()), + ImportResourceType::HttpRequest, + v.folder_id.clone(), + )?; } for v in &plan.resources.grpc_requests { - classify(AnyModel::GrpcRequest(v.clone()), ImportResourceType::GrpcRequest, v.folder_id.clone())?; + classify( + AnyModel::GrpcRequest(v.clone()), + ImportResourceType::GrpcRequest, + v.folder_id.clone(), + )?; } for v in &plan.resources.websocket_requests { - classify(AnyModel::WebsocketRequest(v.clone()), ImportResourceType::WebsocketRequest, v.folder_id.clone())?; + classify( + AnyModel::WebsocketRequest(v.clone()), + ImportResourceType::WebsocketRequest, + v.folder_id.clone(), + )?; } for v in &plan.resources.environments { - classify(AnyModel::Environment(v.clone()), ImportResourceType::Environment, v.parent_id.clone())?; + classify( + AnyModel::Environment(v.clone()), + ImportResourceType::Environment, + v.parent_id.clone(), + )?; } } @@ -1030,16 +1041,32 @@ fn create_only_items(plan: &ImportPlan) -> Vec { push(AnyModel::Folder(v.clone()), ImportResourceType::Folder, v.folder_id.clone()); } for v in &plan.resources.http_requests { - push(AnyModel::HttpRequest(v.clone()), ImportResourceType::HttpRequest, v.folder_id.clone()); + push( + AnyModel::HttpRequest(v.clone()), + ImportResourceType::HttpRequest, + v.folder_id.clone(), + ); } for v in &plan.resources.grpc_requests { - push(AnyModel::GrpcRequest(v.clone()), ImportResourceType::GrpcRequest, v.folder_id.clone()); + push( + AnyModel::GrpcRequest(v.clone()), + ImportResourceType::GrpcRequest, + v.folder_id.clone(), + ); } for v in &plan.resources.websocket_requests { - push(AnyModel::WebsocketRequest(v.clone()), ImportResourceType::WebsocketRequest, v.folder_id.clone()); + push( + AnyModel::WebsocketRequest(v.clone()), + ImportResourceType::WebsocketRequest, + v.folder_id.clone(), + ); } for v in &plan.resources.environments { - push(AnyModel::Environment(v.clone()), ImportResourceType::Environment, v.parent_id.clone()); + push( + AnyModel::Environment(v.clone()), + ImportResourceType::Environment, + v.parent_id.clone(), + ); } items } @@ -1060,7 +1087,14 @@ enum KeyStatus<'a> { fn comparable(value: Value) -> Value { let mut value = strip_ids(value); if let Some(object) = value.as_object_mut() { - for field in ["model", "workspaceId", "createdAt", "updatedAt", "base", "sortPriority"] { + for field in [ + "model", + "workspaceId", + "createdAt", + "updatedAt", + "base", + "sortPriority", + ] { object.remove(field); } } @@ -1208,10 +1242,7 @@ fn validate_plan(plan: &ImportPlan) -> Result<()> { let updates_own_base = |id: &str| { plan.items.iter().any(|i| { i.model_id == id - && !matches!( - i.action, - ImportPlanAction::Create | ImportPlanAction::Ignored - ) + && !matches!(i.action, ImportPlanAction::Create | ImportPlanAction::Ignored) }) }; if plan @@ -1376,9 +1407,8 @@ fn assign_source_keys( for (i, v) in resources.environments.iter().enumerate() { let source = original.environments.get(i); let name = source.map(|s| s.name.as_str()).unwrap_or(v.name.as_str()); - let parent_id = source.and_then(|s| { - if s.parent_model == "folder" { s.parent_id.as_deref() } else { None } - }); + let parent_id = source + .and_then(|s| if s.parent_model == "folder" { s.parent_id.as_deref() } else { None }); let ancestry = ancestry_path(&folder_tree, parent_id); let key = fallback_key("environment", &ancestry, name); candidates.push((&v.id, plugin_key(source.map(|s| &s.id)), key.clone(), key)); @@ -1386,8 +1416,7 @@ fn assign_source_keys( for (i, v) in resources.folders.iter().enumerate() { let source = original.folders.get(i); let name = source.map(|s| s.name.as_str()).unwrap_or(v.name.as_str()); - let ancestry = - ancestry_path(&folder_tree, source.and_then(|s| s.folder_id.as_deref())); + let ancestry = ancestry_path(&folder_tree, source.and_then(|s| s.folder_id.as_deref())); let key = fallback_key("folder", &ancestry, name); candidates.push((&v.id, plugin_key(source.map(|s| &s.id)), key.clone(), key)); } @@ -2602,10 +2631,9 @@ mod tests { // Anything new inside that folder can't be created either, so it waits for the folder. let mut resources = with_extra_folder(true); - resources.http_requests.push(HttpRequest { - folder_id: Some("fl_extra".to_string()), - ..extra_request() - }); + resources + .http_requests + .push(HttpRequest { folder_id: Some("fl_extra".to_string()), ..extra_request() }); let plan = replan(&query_manager, &workspace_id, resources); let extra = item_by_name(&plan, "Extra Request"); assert_eq!(extra.action, ImportPlanAction::Create); @@ -2930,73 +2958,72 @@ mod tests { assert_eq!(not_wanted, 2, "the skipped folder and its request are remembered: {rows:?}"); } - -#[test] -fn desktop_style_json_roundtrip_records_source() { - let (query_manager, _blob_manager, _rx) = - yaak_models::init_in_memory().expect("initialize database"); - let plan = plan_import_resources( - &query_manager, - "OpenAPI".to_string(), - ImportDestination::NewWorkspace, - imported_resources(), - None, - Some(linked_origin()), - ) - .expect("plan import"); - let json = serde_json::to_string(&plan).expect("serialize plan"); - let plan: ImportPlan = serde_json::from_str(&json).expect("deserialize plan"); - let committed = commit_import_plan(&query_manager, plan).expect("commit"); - let workspace_id = committed.workspaces[0].id.clone(); - let source = query_manager - .connect() - .find_import_source(&workspace_id, "OpenAPI", "/tmp/api.yaml") - .expect("query") - .expect("source recorded after JSON round-trip"); - assert_eq!(source.origin_label, "api.yaml"); -} - -#[test] -fn selected_keep_local_reverts_the_local_edit() { - let (query_manager, _blob_manager, _rx) = - yaak_models::init_in_memory().expect("initialize database"); - let committed = first_import(&query_manager); - let workspace_id = committed.workspaces[0].id.clone(); - let root_id = committed - .http_requests - .iter() - .find(|r| r.name == "Root Request") - .expect("root request") - .id - .clone(); - - { - let db = query_manager.connect(); - let root = db.get_http_request(&root_id).expect("get root"); - db.upsert_http_request( - &HttpRequest { url: "https://example.com/root-local".to_string(), ..root }, - &UpdateSource::Background, + #[test] + fn desktop_style_json_roundtrip_records_source() { + let (query_manager, _blob_manager, _rx) = + yaak_models::init_in_memory().expect("initialize database"); + let plan = plan_import_resources( + &query_manager, + "OpenAPI".to_string(), + ImportDestination::NewWorkspace, + imported_resources(), + None, + Some(linked_origin()), ) - .expect("edit root locally"); + .expect("plan import"); + let json = serde_json::to_string(&plan).expect("serialize plan"); + let plan: ImportPlan = serde_json::from_str(&json).expect("deserialize plan"); + let committed = commit_import_plan(&query_manager, plan).expect("commit"); + let workspace_id = committed.workspaces[0].id.clone(); + let source = query_manager + .connect() + .find_import_source(&workspace_id, "OpenAPI", "/tmp/api.yaml") + .expect("query") + .expect("source recorded after JSON round-trip"); + assert_eq!(source.origin_label, "api.yaml"); } - let mut plan = replan(&query_manager, &workspace_id, imported_resources()); - let root = item_by_name(&plan, "Root Request"); - assert_eq!(root.action, ImportPlanAction::KeepLocal); - assert!(!root.selected, "keep-local defaults to keeping the local edit"); - for item in plan.items.iter_mut() { - if item.action == ImportPlanAction::KeepLocal { - item.selected = true; + #[test] + fn selected_keep_local_reverts_the_local_edit() { + let (query_manager, _blob_manager, _rx) = + yaak_models::init_in_memory().expect("initialize database"); + let committed = first_import(&query_manager); + let workspace_id = committed.workspaces[0].id.clone(); + let root_id = committed + .http_requests + .iter() + .find(|r| r.name == "Root Request") + .expect("root request") + .id + .clone(); + + { + let db = query_manager.connect(); + let root = db.get_http_request(&root_id).expect("get root"); + db.upsert_http_request( + &HttpRequest { url: "https://example.com/root-local".to_string(), ..root }, + &UpdateSource::Background, + ) + .expect("edit root locally"); } - } - commit_import_plan(&query_manager, plan).expect("commit revert"); - assert_eq!( - query_manager.connect().get_http_request(&root_id).expect("get root").url, - "https://example.com/root", - "selected keep-local must revert to the source version" - ); - let plan = replan(&query_manager, &workspace_id, imported_resources()); - assert_eq!(item_by_name(&plan, "Root Request").action, ImportPlanAction::Unchanged); -} + let mut plan = replan(&query_manager, &workspace_id, imported_resources()); + let root = item_by_name(&plan, "Root Request"); + assert_eq!(root.action, ImportPlanAction::KeepLocal); + assert!(!root.selected, "keep-local defaults to keeping the local edit"); + for item in plan.items.iter_mut() { + if item.action == ImportPlanAction::KeepLocal { + item.selected = true; + } + } + commit_import_plan(&query_manager, plan).expect("commit revert"); + + assert_eq!( + query_manager.connect().get_http_request(&root_id).expect("get root").url, + "https://example.com/root", + "selected keep-local must revert to the source version" + ); + let plan = replan(&query_manager, &workspace_id, imported_resources()); + assert_eq!(item_by_name(&plan, "Root Request").action, ImportPlanAction::Unchanged); + } } diff --git a/crates/yaak/src/plugin_events.rs b/crates/yaak/src/plugin_events.rs index 1bb8bba9..767c6550 100644 --- a/crates/yaak/src/plugin_events.rs +++ b/crates/yaak/src/plugin_events.rs @@ -668,9 +668,10 @@ mod tests { let (query_manager, _temp_dir) = seed_query_manager(); let store = FakeBodyStore { body: b"hello".to_vec(), reads: RefCell::new(Vec::new()) }; - let info_payload = InternalEventPayload::GetHttpResponseBodyInfoRequest( - GetHttpResponseBodyInfoRequest { response_id: "rs_test".to_string() }, - ); + let info_payload = + InternalEventPayload::GetHttpResponseBodyInfoRequest(GetHttpResponseBodyInfoRequest { + response_id: "rs_test".to_string(), + }); let info = handle_shared_plugin_event( &query_manager, &store, @@ -716,9 +717,10 @@ mod tests { #[test] fn an_unreadable_response_body_becomes_an_error_reply() { let (query_manager, _temp_dir) = seed_query_manager(); - let payload = InternalEventPayload::GetHttpResponseBodyInfoRequest( - GetHttpResponseBodyInfoRequest { response_id: "rs_never_persisted".to_string() }, - ); + let payload = + InternalEventPayload::GetHttpResponseBodyInfoRequest(GetHttpResponseBodyInfoRequest { + response_id: "rs_never_persisted".to_string(), + }); let result = dispatch( &query_manager, &payload, @@ -727,7 +729,11 @@ mod tests { match result { GroupedPluginEvent::Handled(Some(InternalEventPayload::ErrorResponse(resp))) => { - assert!(resp.error.contains("rs_never_persisted"), "unhelpful error: {}", resp.error) + assert!( + resp.error.contains("rs_never_persisted"), + "unhelpful error: {}", + resp.error + ) } other => panic!("unexpected missing-response result: {other:?}"), }