From 6060ddcd87d7b6a11d2e496022fcd8c50a717ed2 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 30 Sep 2024 18:28:52 -0700 Subject: [PATCH] Add `aliases` field to template functions --- plugin-runtime-types/src/bindings/events.ts | 96 ------------------- plugin-runtime-types/src/bindings/models.ts | 23 ----- .../src/bindings/serde_json/JsonValue.ts | 3 - plugin-runtime/src/index.worker.ts | 8 +- src-tauri/src/lib.rs | 24 +++-- .../yaak_plugin_runtime/bindings/events.ts | 2 +- src-tauri/yaak_plugin_runtime/src/events.rs | 1 + .../components/core/Editor/twig/completion.ts | 27 +++--- .../components/core/Editor/twig/extension.ts | 1 + .../core/Editor/twig/templateTags.ts | 4 +- 10 files changed, 44 insertions(+), 145 deletions(-) delete mode 100644 plugin-runtime-types/src/bindings/events.ts delete mode 100644 plugin-runtime-types/src/bindings/models.ts delete mode 100644 plugin-runtime-types/src/bindings/serde_json/JsonValue.ts diff --git a/plugin-runtime-types/src/bindings/events.ts b/plugin-runtime-types/src/bindings/events.ts deleted file mode 100644 index 00e363c1..00000000 --- a/plugin-runtime-types/src/bindings/events.ts +++ /dev/null @@ -1,96 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { Environment } from "./models"; -import type { Folder } from "./models"; -import type { GrpcRequest } from "./models"; -import type { HttpRequest } from "./models"; -import type { HttpResponse } from "./models"; -import type { JsonValue } from "./serde_json/JsonValue"; -import type { Workspace } from "./models"; - -export type BootRequest = { dir: string, watch: boolean, }; - -export type BootResponse = { name: string, version: string, capabilities: Array, }; - -export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, }; - -export type CallHttpRequestActionRequest = { key: string, pluginRefId: string, args: CallHttpRequestActionArgs, }; - -export type CallTemplateFunctionArgs = { purpose: RenderPurpose, values: { [key in string]?: string }, }; - -export type CallTemplateFunctionRequest = { name: string, args: CallTemplateFunctionArgs, }; - -export type CallTemplateFunctionResponse = { value: string | null, }; - -export type Color = "custom" | "default" | "primary" | "secondary" | "info" | "success" | "notice" | "warning" | "danger"; - -export type CopyTextRequest = { text: string, }; - -export type ExportHttpRequestRequest = { httpRequest: HttpRequest, }; - -export type ExportHttpRequestResponse = { content: string, }; - -export type FilterRequest = { content: string, filter: string, }; - -export type FilterResponse = { content: string, }; - -export type FindHttpResponsesRequest = { requestId: string, limit: number | null, }; - -export type FindHttpResponsesResponse = { httpResponses: Array, }; - -export type GetHttpRequestActionsRequest = Record; - -export type GetHttpRequestActionsResponse = { actions: Array, pluginRefId: string, }; - -export type GetHttpRequestByIdRequest = { id: string, }; - -export type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null, }; - -export type GetTemplateFunctionsResponse = { functions: Array, pluginRefId: string, }; - -export type HttpRequestAction = { key: string, label: string, icon: string | null, }; - -export type Icon = "copy" | "info" | "check_circle" | "alert_triangle"; - -export type ImportRequest = { content: string, }; - -export type ImportResources = { workspaces: Array, environments: Array, folders: Array, httpRequests: Array, grpcRequests: Array, }; - -export type ImportResponse = { resources: ImportResources, }; - -export type InternalEvent = { id: string, pluginRefId: string, replyId: string | null, payload: InternalEventPayload, windowContext: WindowContext, }; - -export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } | { "type": "reload_response" } | { "type": "terminate_request" } | { "type": "terminate_response" } | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & GetHttpRequestActionsRequest | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "copy_text_request" } & CopyTextRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" }; - -export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, }; - -export type RenderHttpRequestResponse = { httpRequest: HttpRequest, }; - -export type RenderPurpose = "send" | "preview"; - -export type SendHttpRequestRequest = { httpRequest: HttpRequest, }; - -export type SendHttpRequestResponse = { httpResponse: HttpResponse, }; - -export type ShowToastRequest = { message: string, color?: Color | null, icon?: Icon | null, }; - -export type TemplateFunction = { name: string, args: Array, }; - -export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg; - -export type TemplateFunctionBaseArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; - -export type TemplateFunctionCheckboxArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; - -export type TemplateFunctionHttpRequestArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; - -export type TemplateFunctionSelectArg = { options: Array, name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; - -export type TemplateFunctionSelectOption = { name: string, value: string, }; - -export type TemplateFunctionTextArg = { placeholder?: string | null, name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; - -export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, }; - -export type TemplateRenderResponse = { data: JsonValue, }; - -export type WindowContext = { "type": "none" } | { "type": "label" } & string; diff --git a/plugin-runtime-types/src/bindings/models.ts b/plugin-runtime-types/src/bindings/models.ts deleted file mode 100644 index eb182225..00000000 --- a/plugin-runtime-types/src/bindings/models.ts +++ /dev/null @@ -1,23 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, variables: Array, }; - -export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, }; - -export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, sortPriority: number, }; - -export type GrpcMetadataEntry = { enabled?: boolean, name: string, value: string, }; - -export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record, message: string, metadata: Array, method: string | null, name: string, service: string | null, sortPriority: number, url: string, }; - -export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, body: Record, bodyType: string | null, headers: Array, method: string, name: string, sortPriority: number, url: string, urlParameters: Array, }; - -export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, }; - -export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, elapsed: number, elapsedHeaders: number, error: string | null, headers: Array, remoteAddr: string | null, status: number, statusReason: string | null, url: string, version: string | null, }; - -export type HttpResponseHeader = { name: string, value: string, }; - -export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, }; - -export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, variables: Array, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, }; diff --git a/plugin-runtime-types/src/bindings/serde_json/JsonValue.ts b/plugin-runtime-types/src/bindings/serde_json/JsonValue.ts deleted file mode 100644 index 606bac7a..00000000 --- a/plugin-runtime-types/src/bindings/serde_json/JsonValue.ts +++ /dev/null @@ -1,3 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -export type JsonValue = number | string | Array | { [key in string]?: JsonValue }; diff --git a/plugin-runtime/src/index.worker.ts b/plugin-runtime/src/index.worker.ts index ffad79c4..7770d58b 100644 --- a/plugin-runtime/src/index.worker.ts +++ b/plugin-runtime/src/index.worker.ts @@ -164,16 +164,16 @@ async function initialize() { }, /** @deprecated: please use ctx.templates.render */ async render(args) { - const payload = { + const payload: InternalEventPayload = { type: 'template_render_request', - data: args.httpRequest, + data: args.httpRequest as any, purpose: args.purpose, - } as const; + }; const result = await sendAndWaitForReply( event.windowContext, payload, ); - return result.data as HttpRequest; + return result.data as unknown as HttpRequest; }, }, templates: { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 9d999bce..abb5b585 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -2204,7 +2204,7 @@ async fn handle_plugin_event( } InternalEventPayload::TemplateRenderRequest(req) => { let window = get_window_from_window_context(app_handle, &window_context) - .expect("Failed to find window"); + .expect("Failed to find window for render"); let workspace = workspace_from_window(&window) .await @@ -2218,7 +2218,7 @@ async fn handle_plugin_event( } InternalEventPayload::ReloadResponse => { let window = get_window_from_window_context(app_handle, &window_context) - .expect("Failed to find window"); + .expect("Failed to find window for plugin reload"); let plugins = list_plugins(app_handle).await.unwrap(); for plugin in plugins { if plugin.directory != plugin_handle.dir { @@ -2245,7 +2245,7 @@ async fn handle_plugin_event( } InternalEventPayload::SendHttpRequestRequest(req) => { let window = get_window_from_window_context(app_handle, &window_context) - .expect("Failed to find window"); + .expect("Failed to find window for sending HTTP request"); let cookie_jar = cookie_jar_from_window(&window).await; let environment = environment_from_window(&window).await; @@ -2288,17 +2288,29 @@ fn get_window_from_window_context( window_context: &WindowContext, ) -> Option> { let label = match window_context { - WindowContext::None => return None, WindowContext::Label { label } => label, + WindowContext::None => { + return app_handle + .webview_windows() + .iter() + .next() + .map(|(_, w)| w.to_owned()); + } }; - app_handle.webview_windows().iter().find_map(|(_, w)| { + let window = app_handle.webview_windows().iter().find_map(|(_, w)| { if w.label() == label { Some(w.to_owned()) } else { None } - }) + }); + + if window.is_none() { + error!("Failed to find window by {window_context:?}"); + } + + window } fn workspace_id_from_window(window: &WebviewWindow) -> Option { diff --git a/src-tauri/yaak_plugin_runtime/bindings/events.ts b/src-tauri/yaak_plugin_runtime/bindings/events.ts index 87a677e7..dabff1d1 100644 --- a/src-tauri/yaak_plugin_runtime/bindings/events.ts +++ b/src-tauri/yaak_plugin_runtime/bindings/events.ts @@ -73,7 +73,7 @@ export type SendHttpRequestResponse = { httpResponse: HttpResponse, }; export type ShowToastRequest = { message: string, color?: Color | null, icon?: Icon | null, }; -export type TemplateFunction = { name: string, args: Array, }; +export type TemplateFunction = { name: string, aliases: Array, args: Array, }; export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg; diff --git a/src-tauri/yaak_plugin_runtime/src/events.rs b/src-tauri/yaak_plugin_runtime/src/events.rs index 6be6c3ca..cff63e82 100644 --- a/src-tauri/yaak_plugin_runtime/src/events.rs +++ b/src-tauri/yaak_plugin_runtime/src/events.rs @@ -250,6 +250,7 @@ pub struct GetTemplateFunctionsResponse { #[ts(export, export_to = "events.ts")] pub struct TemplateFunction { pub name: String, + pub aliases: Vec, pub args: Vec, } diff --git a/src-web/components/core/Editor/twig/completion.ts b/src-web/components/core/Editor/twig/completion.ts index 486d65ae..ab6471c2 100644 --- a/src-web/components/core/Editor/twig/completion.ts +++ b/src-web/components/core/Editor/twig/completion.ts @@ -13,6 +13,7 @@ export type TwigCompletionOptionNamespace = { export type TwigCompletionOptionFunction = { args: { name: string }[]; + aliases: string[]; type: 'function'; }; @@ -56,26 +57,30 @@ export function twigCompletion({ options }: TwigCompletionConfig) { } const completions: Completion[] = options - .map((o): Completion => { + .flatMap((o): Completion[] => { const matchSegments = toStartOfName!.text.split('.'); const optionSegments = o.name.split('.'); // If not on the last segment, only complete the namespace if (matchSegments.length < optionSegments.length) { - return { - label: optionSegments.slice(0, matchSegments.length).join('.'), - apply: optionSegments.slice(0, matchSegments.length).join('.'), - type: 'namespace', - }; + return [ + { + label: optionSegments.slice(0, matchSegments.length).join('.'), + apply: optionSegments.slice(0, matchSegments.length).join('.'), + type: 'namespace', + }, + ]; } // If on the last segment, wrap the entire tag const inner = o.type === 'function' ? `${o.name}()` : o.name; - return { - label: o.name, - apply: openTag + inner + closeTag, - type: o.type === 'variable' ? 'variable' : 'function', - }; + return [ + { + label: o.name, + apply: openTag + inner + closeTag, + type: o.type === 'variable' ? 'variable' : 'function', + }, + ]; }) .filter((v) => v != null); diff --git a/src-web/components/core/Editor/twig/extension.ts b/src-web/components/core/Editor/twig/extension.ts index ef979839..7640749f 100644 --- a/src-web/components/core/Editor/twig/extension.ts +++ b/src-web/components/core/Editor/twig/extension.ts @@ -50,6 +50,7 @@ export function twig({ .join(', ') + (fn.args.length > NUM_ARGS ? ', …' : ''); return { name: fn.name, + aliases: fn.aliases, type: 'function', args: fn.args.map((a) => ({ name: a.name })), value: null, diff --git a/src-web/components/core/Editor/twig/templateTags.ts b/src-web/components/core/Editor/twig/templateTags.ts index bad0a43e..6c5871cf 100644 --- a/src-web/components/core/Editor/twig/templateTags.ts +++ b/src-web/components/core/Editor/twig/templateTags.ts @@ -146,7 +146,9 @@ function templateTags( name = 'response'; } - let option = options.find((v) => v.name === name); + let option = options.find( + (o) => o.name === name || (o.type === 'function' && o.aliases?.includes(name)), + ); if (option == null) { option = { invalid: true,