From a31f818424e351a7b8a6e7deefdf79f7f1dfb40b Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Thu, 10 Jul 2025 13:49:53 -0700 Subject: [PATCH] Don't show plugin error for response filter https://feedback.yaak.app/p/increase-debounce-time-for-jsonpath-xpath-filter https://feedback.yaak.app/p/possibility-to-cancel-request --- .../src/bindings/gen_events.ts | 2 +- .../src/plugins/FilterPlugin.ts | 5 ++--- packages/plugin-runtime/src/PluginInstance.ts | 11 ++++------ plugins/filter-jsonpath/src/index.ts | 10 +++++++--- plugins/filter-xpath/src/index.ts | 19 ++++++++++-------- src-tauri/src/lib.rs | 11 +++++----- src-tauri/src/plugin_events.rs | 20 ++++++++++++------- src-tauri/yaak-plugins/bindings/gen_events.ts | 2 +- src-tauri/yaak-plugins/src/events.rs | 2 ++ src-web/components/HttpResponsePane.tsx | 14 +++++++++++-- .../components/responseViewers/TextViewer.tsx | 9 ++++++--- src-web/hooks/useFilterResponse.ts | 4 ++-- 12 files changed, 66 insertions(+), 43 deletions(-) diff --git a/packages/plugin-runtime-types/src/bindings/gen_events.ts b/packages/plugin-runtime-types/src/bindings/gen_events.ts index db224e39..38972263 100644 --- a/packages/plugin-runtime-types/src/bindings/gen_events.ts +++ b/packages/plugin-runtime-types/src/bindings/gen_events.ts @@ -65,7 +65,7 @@ extensions: Array, }; export type FilterRequest = { content: string, filter: string, }; -export type FilterResponse = { content: string, }; +export type FilterResponse = { content: string, error?: string, }; export type FindHttpResponsesRequest = { requestId: string, limit?: number, }; diff --git a/packages/plugin-runtime-types/src/plugins/FilterPlugin.ts b/packages/plugin-runtime-types/src/plugins/FilterPlugin.ts index b7ebf581..0977a28e 100644 --- a/packages/plugin-runtime-types/src/plugins/FilterPlugin.ts +++ b/packages/plugin-runtime-types/src/plugins/FilterPlugin.ts @@ -1,12 +1,11 @@ +import { FilterResponse } from '../bindings/gen_events'; import type { Context } from './Context'; -type FilterPluginResponse = { filtered: string }; - export type FilterPlugin = { name: string; description?: string; onFilter( ctx: Context, args: { payload: string; filter: string; mimeType: string }, - ): Promise | FilterPluginResponse; + ): Promise | FilterResponse; }; diff --git a/packages/plugin-runtime/src/PluginInstance.ts b/packages/plugin-runtime/src/PluginInstance.ts index e227ddac..062088f1 100644 --- a/packages/plugin-runtime/src/PluginInstance.ts +++ b/packages/plugin-runtime/src/PluginInstance.ts @@ -7,7 +7,8 @@ import { GetCookieValueRequest, GetCookieValueResponse, GetHttpRequestByIdResponse, - GetKeyValueResponse, GrpcRequestAction, + GetKeyValueResponse, + GrpcRequestAction, HttpAuthenticationAction, HttpRequestAction, InternalEvent, @@ -15,8 +16,8 @@ import { ListCookieNamesResponse, PluginWindowContext, PromptTextResponse, - RenderHttpRequestResponse, RenderGrpcRequestResponse, + RenderHttpRequestResponse, SendHttpRequestResponse, TemplateFunction, TemplateFunctionArg, @@ -138,11 +139,7 @@ export class PluginInstance { payload: payload.content, mimeType: payload.type, }); - const replyPayload: InternalEventPayload = { - type: 'filter_response', - content: reply.filtered, - }; - this.#sendPayload(windowContext, replyPayload, replyId); + this.#sendPayload(windowContext, { type: 'filter_response', ...reply }, replyId); return; } diff --git a/plugins/filter-jsonpath/src/index.ts b/plugins/filter-jsonpath/src/index.ts index a4539e61..551d442b 100644 --- a/plugins/filter-jsonpath/src/index.ts +++ b/plugins/filter-jsonpath/src/index.ts @@ -1,4 +1,4 @@ -import { PluginDefinition } from '@yaakapp/api'; +import type { PluginDefinition } from '@yaakapp/api'; import { JSONPath } from 'jsonpath-plus'; export const plugin: PluginDefinition = { @@ -7,8 +7,12 @@ export const plugin: PluginDefinition = { description: 'Filter JSONPath', onFilter(_ctx, args) { const parsed = JSON.parse(args.payload); - const filtered = JSONPath({ path: args.filter, json: parsed }); - return { filtered: JSON.stringify(filtered, null, 2) }; + try { + const filtered = JSONPath({ path: args.filter, json: parsed }); + return { content: JSON.stringify(filtered, null, 2) }; + } catch (err) { + return { content: '', error: `Invalid filter: ${err}` }; + } }, }, }; diff --git a/plugins/filter-xpath/src/index.ts b/plugins/filter-xpath/src/index.ts index 4a010657..4920d734 100644 --- a/plugins/filter-xpath/src/index.ts +++ b/plugins/filter-xpath/src/index.ts @@ -1,5 +1,5 @@ import { DOMParser } from '@xmldom/xmldom'; -import { PluginDefinition } from '@yaakapp/api'; +import type { PluginDefinition } from '@yaakapp/api'; import xpath from 'xpath'; export const plugin: PluginDefinition = { @@ -8,13 +8,16 @@ export const plugin: PluginDefinition = { description: 'Filter XPath', onFilter(_ctx, args) { const doc = new DOMParser().parseFromString(args.payload, 'text/xml'); - const result = xpath.select(args.filter, doc, false); - - if (Array.isArray(result)) { - return { filtered: result.map(r => String(r)).join('\n') }; - } else { - // Not sure what cases this happens in (?) - return { filtered: String(result) }; + try { + const result = xpath.select(args.filter, doc, false); + if (Array.isArray(result)) { + return { content: result.map((r) => String(r)).join('\n') }; + } else { + // Not sure what cases this happens in (?) + return { content: String(result) }; + } + } catch (err) { + return { content: '', error: `Invalid filter: ${err}` }; } }, }, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 5dffc697..dc12e592 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -36,12 +36,11 @@ use yaak_models::models::{ use yaak_models::query_manager::QueryManagerExt; use yaak_models::util::{BatchUpsertResult, UpdateSource, get_workspace_export_resources}; use yaak_plugins::events::{ - CallGrpcRequestActionArgs, CallGrpcRequestActionRequest, CallHttpAuthenticationActionArgs, - CallHttpRequestActionArgs, CallHttpRequestActionRequest, FilterResponse, - GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse, - GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse, - GetTemplateFunctionsResponse, InternalEvent, InternalEventPayload, JsonPrimitive, - PluginWindowContext, RenderPurpose, + CallGrpcRequestActionArgs, CallGrpcRequestActionRequest, CallHttpRequestActionArgs, + CallHttpRequestActionRequest, FilterResponse, GetGrpcRequestActionsResponse, + GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse, + GetHttpRequestActionsResponse, GetTemplateFunctionsResponse, InternalEvent, + InternalEventPayload, JsonPrimitive, PluginWindowContext, RenderPurpose, }; use yaak_plugins::manager::PluginManager; use yaak_plugins::plugin_meta::PluginMetadata; diff --git a/src-tauri/src/plugin_events.rs b/src-tauri/src/plugin_events.rs index d77c6516..66248e2e 100644 --- a/src-tauri/src/plugin_events.rs +++ b/src-tauri/src/plugin_events.rs @@ -1,6 +1,6 @@ use crate::http_request::send_http_request; use crate::render::{render_grpc_request, render_http_request, render_json_value}; -use crate::window::{create_window, CreateWindowConfig}; +use crate::window::{CreateWindowConfig, create_window}; use crate::{ call_frontend, cookie_jar_from_window, environment_from_window, get_window_from_window_context, workspace_from_window, @@ -13,7 +13,13 @@ use tauri_plugin_clipboard_manager::ClipboardExt; use yaak_models::models::{HttpResponse, Plugin}; use yaak_models::query_manager::QueryManagerExt; use yaak_models::util::UpdateSource; -use yaak_plugins::events::{Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload, ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse, RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest, TemplateRenderResponse, WindowNavigateEvent}; +use yaak_plugins::events::{ + Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse, + GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload, + ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse, + RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest, + TemplateRenderResponse, WindowNavigateEvent, +}; use yaak_plugins::manager::PluginManager; use yaak_plugins::plugin_handle::PluginHandle; use yaak_plugins::template_callback::PluginTemplateCallback; @@ -80,8 +86,8 @@ pub(crate) async fn handle_plugin_event( environment.as_ref(), &cb, ) - .await - .expect("Failed to render grpc request"); + .await + .expect("Failed to render grpc request"); Some(InternalEventPayload::RenderGrpcRequestResponse(RenderGrpcRequestResponse { grpc_request, })) @@ -104,8 +110,8 @@ pub(crate) async fn handle_plugin_event( environment.as_ref(), &cb, ) - .await - .expect("Failed to render http request"); + .await + .expect("Failed to render http request"); Some(InternalEventPayload::RenderHttpRequestResponse(RenderHttpRequestResponse { http_request, })) @@ -206,7 +212,7 @@ pub(crate) async fn handle_plugin_event( cookie_jar, &mut tokio::sync::watch::channel(false).1, // No-op cancel channel ) - .await; + .await; let http_response = match result { Ok(r) => r, diff --git a/src-tauri/yaak-plugins/bindings/gen_events.ts b/src-tauri/yaak-plugins/bindings/gen_events.ts index db224e39..38972263 100644 --- a/src-tauri/yaak-plugins/bindings/gen_events.ts +++ b/src-tauri/yaak-plugins/bindings/gen_events.ts @@ -65,7 +65,7 @@ extensions: Array, }; export type FilterRequest = { content: string, filter: string, }; -export type FilterResponse = { content: string, }; +export type FilterResponse = { content: string, error?: string, }; export type FindHttpResponsesRequest = { requestId: string, limit?: number, }; diff --git a/src-tauri/yaak-plugins/src/events.rs b/src-tauri/yaak-plugins/src/events.rs index a747a5b2..de2057fd 100644 --- a/src-tauri/yaak-plugins/src/events.rs +++ b/src-tauri/yaak-plugins/src/events.rs @@ -216,6 +216,8 @@ pub struct FilterRequest { #[ts(export, export_to = "gen_events.ts")] pub struct FilterResponse { pub content: String, + #[ts(optional)] + pub error: Option, } #[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] diff --git a/src-web/components/HttpResponsePane.tsx b/src-web/components/HttpResponsePane.tsx index 348435d3..27a5c315 100644 --- a/src-web/components/HttpResponsePane.tsx +++ b/src-web/components/HttpResponsePane.tsx @@ -3,6 +3,7 @@ import classNames from 'classnames'; import type { CSSProperties, ReactNode } from 'react'; import React, { useCallback, useMemo } from 'react'; import { useLocalStorage } from 'react-use'; +import { useCancelHttpResponse } from '../hooks/useCancelHttpResponse'; import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse'; import { useResponseViewMode } from '../hooks/useResponseViewMode'; import { getMimeTypeFromContentType } from '../lib/contentType'; @@ -14,7 +15,7 @@ import { HttpResponseDurationTag } from './core/HttpResponseDurationTag'; import { HotKeyList } from './core/HotKeyList'; import { LoadingIcon } from './core/LoadingIcon'; import { SizeTag } from './core/SizeTag'; -import { HStack } from './core/Stacks'; +import { HStack, VStack } from './core/Stacks'; import { HttpStatusTag } from './core/HttpStatusTag'; import type { TabItem } from './core/Tabs/Tabs'; import { TabContent, Tabs } from './core/Tabs/Tabs'; @@ -31,6 +32,7 @@ import { PdfViewer } from './responseViewers/PdfViewer'; import { SvgViewer } from './responseViewers/SvgViewer'; import { VideoViewer } from './responseViewers/VideoViewer'; import { ErrorBoundary } from './ErrorBoundary'; +import { Button } from './core/Button'; interface Props { style?: CSSProperties; @@ -90,6 +92,8 @@ export function HttpResponsePane({ style, className, activeRequestId }: Props) { [activeRequestId, setActiveTabs], ); + const cancel = useCancelHttpResponse(activeResponse?.id ?? null); + return (
{activeResponse.state === 'initialized' ? ( - + + + + Sending Request + + + ) : activeResponse.state === 'closed' && activeResponse.contentLength === 0 ? ( Empty diff --git a/src-web/components/responseViewers/TextViewer.tsx b/src-web/components/responseViewers/TextViewer.tsx index 4a647124..97a5a02f 100644 --- a/src-web/components/responseViewers/TextViewer.tsx +++ b/src-web/components/responseViewers/TextViewer.tsx @@ -27,7 +27,7 @@ const useFilterText = createGlobalState>({}); export function TextViewer({ language, text, responseId, requestId, pretty, className }: Props) { const [filterTextMap, setFilterTextMap] = useFilterText(); const filterText = filterTextMap[requestId] ?? null; - const debouncedFilterText = useDebouncedValue(filterText, 200); + const debouncedFilterText = useDebouncedValue(filterText); const setFilterText = useCallback( (v: string | null) => { setFilterTextMap((m) => ({ ...m, [requestId]: v })); @@ -58,7 +58,7 @@ export function TextViewer({ language, text, responseId, requestId, pretty, clas
({ + return useQuery({ queryKey: ['filter_response', responseId, filter], queryFn: async () => { if (filter === '') { @@ -21,7 +21,7 @@ export function useFilterResponse({ filter, })) as FilterResponse; - return result.content; + return result; }, }); }