mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-21 08:11:24 +02:00
collection plugin actions
This commit is contained in:
@@ -57,6 +57,10 @@ export interface Context {
|
|||||||
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
||||||
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
||||||
render(args: RenderHttpRequestRequest): Promise<RenderHttpRequestResponse['httpRequest']>;
|
render(args: RenderHttpRequestRequest): Promise<RenderHttpRequestResponse['httpRequest']>;
|
||||||
|
list(args: { workspaceId?: string; folderId?: string }): Promise<Array<any>>;
|
||||||
|
};
|
||||||
|
folder: {
|
||||||
|
list(args: { workspaceId?: string }): Promise<Array<any>>;
|
||||||
};
|
};
|
||||||
httpResponse: {
|
httpResponse: {
|
||||||
find(args: FindHttpResponsesRequest): Promise<FindHttpResponsesResponse['httpResponses']>;
|
find(args: FindHttpResponsesRequest): Promise<FindHttpResponsesResponse['httpResponses']>;
|
||||||
@@ -64,6 +68,10 @@ export interface Context {
|
|||||||
templates: {
|
templates: {
|
||||||
render<T extends JsonValue>(args: TemplateRenderRequest & { data: T }): Promise<T>;
|
render<T extends JsonValue>(args: TemplateRenderRequest & { data: T }): Promise<T>;
|
||||||
};
|
};
|
||||||
|
file: {
|
||||||
|
writeText(filePath: string, content: string): Promise<void>;
|
||||||
|
readText(filePath: string): Promise<string>;
|
||||||
|
};
|
||||||
plugin: {
|
plugin: {
|
||||||
reload(): void;
|
reload(): void;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import type { Context } from './Context';
|
||||||
|
import type { Folder, Workspace } from '../bindings/gen_models';
|
||||||
|
import type { Icon } from '../bindings/gen_events';
|
||||||
|
|
||||||
|
export type HttpCollectionAction = { label: string; icon?: Icon };
|
||||||
|
|
||||||
|
export type CallHttpCollectionActionArgs = { folder?: Folder; workspace?: Workspace };
|
||||||
|
|
||||||
|
export type HttpCollectionActionPlugin = HttpCollectionAction & {
|
||||||
|
onSelect(ctx: Context, args: CallHttpCollectionActionArgs): Promise<void> | void;
|
||||||
|
};
|
||||||
@@ -4,6 +4,7 @@ import type { Context } from './Context';
|
|||||||
import type { FilterPlugin } from './FilterPlugin';
|
import type { FilterPlugin } from './FilterPlugin';
|
||||||
import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin';
|
import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin';
|
||||||
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
||||||
|
import type { HttpCollectionActionPlugin } from './HttpCollectionActionPlugin';
|
||||||
import type { ImporterPlugin } from './ImporterPlugin';
|
import type { ImporterPlugin } from './ImporterPlugin';
|
||||||
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
||||||
import type { ThemePlugin } from './ThemePlugin';
|
import type { ThemePlugin } from './ThemePlugin';
|
||||||
@@ -12,6 +13,7 @@ export type { Context };
|
|||||||
export type { DynamicTemplateFunctionArg } from './TemplateFunctionPlugin';
|
export type { DynamicTemplateFunctionArg } from './TemplateFunctionPlugin';
|
||||||
export type { DynamicAuthenticationArg } from './AuthenticationPlugin';
|
export type { DynamicAuthenticationArg } from './AuthenticationPlugin';
|
||||||
export type { TemplateFunctionPlugin };
|
export type { TemplateFunctionPlugin };
|
||||||
|
export type { HttpCollectionActionPlugin } from './HttpCollectionActionPlugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The global structure of a Yaak plugin
|
* The global structure of a Yaak plugin
|
||||||
@@ -24,6 +26,7 @@ export type PluginDefinition = {
|
|||||||
filter?: FilterPlugin;
|
filter?: FilterPlugin;
|
||||||
authentication?: AuthenticationPlugin;
|
authentication?: AuthenticationPlugin;
|
||||||
httpRequestActions?: HttpRequestActionPlugin[];
|
httpRequestActions?: HttpRequestActionPlugin[];
|
||||||
|
httpCollectionActions?: HttpCollectionActionPlugin[];
|
||||||
grpcRequestActions?: GrpcRequestActionPlugin[];
|
grpcRequestActions?: GrpcRequestActionPlugin[];
|
||||||
templateFunctions?: TemplateFunctionPlugin[];
|
templateFunctions?: TemplateFunctionPlugin[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
GrpcRequestAction,
|
GrpcRequestAction,
|
||||||
HttpAuthenticationAction,
|
HttpAuthenticationAction,
|
||||||
HttpRequestAction,
|
HttpRequestAction,
|
||||||
|
HttpCollectionAction,
|
||||||
InternalEvent,
|
InternalEvent,
|
||||||
InternalEventPayload,
|
InternalEventPayload,
|
||||||
ListCookieNamesResponse,
|
ListCookieNamesResponse,
|
||||||
@@ -172,6 +173,24 @@ export class PluginInstance {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.type === 'get_http_collection_actions_request' &&
|
||||||
|
Array.isArray(this.#mod?.httpCollectionActions)
|
||||||
|
) {
|
||||||
|
const reply: HttpRequestAction[] = this.#mod.httpCollectionActions.map((a) => ({
|
||||||
|
...a,
|
||||||
|
// Add everything except onSelect
|
||||||
|
onSelect: undefined,
|
||||||
|
}));
|
||||||
|
const replyPayload: InternalEventPayload = {
|
||||||
|
type: 'get_http_collection_actions_response',
|
||||||
|
pluginRefId: this.#workerData.pluginRefId,
|
||||||
|
actions: reply,
|
||||||
|
};
|
||||||
|
this.#sendPayload(context, replyPayload, replyId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (payload.type === 'get_themes_request' && Array.isArray(this.#mod?.themes)) {
|
if (payload.type === 'get_themes_request' && Array.isArray(this.#mod?.themes)) {
|
||||||
const replyPayload: InternalEventPayload = {
|
const replyPayload: InternalEventPayload = {
|
||||||
type: 'get_themes_response',
|
type: 'get_themes_response',
|
||||||
@@ -302,6 +321,18 @@ export class PluginInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.type === 'call_http_collection_action_request' &&
|
||||||
|
Array.isArray(this.#mod.httpCollectionActions)
|
||||||
|
) {
|
||||||
|
const action = this.#mod.httpCollectionActions[payload.index];
|
||||||
|
if (typeof action?.onSelect === 'function') {
|
||||||
|
await action.onSelect(ctx, payload.args);
|
||||||
|
this.#sendEmpty(context, replyId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
payload.type === 'call_grpc_request_action_request' &&
|
payload.type === 'call_grpc_request_action_request' &&
|
||||||
Array.isArray(this.#mod.grpcRequestActions)
|
Array.isArray(this.#mod.grpcRequestActions)
|
||||||
@@ -611,6 +642,26 @@ export class PluginInstance {
|
|||||||
);
|
);
|
||||||
return httpRequest;
|
return httpRequest;
|
||||||
},
|
},
|
||||||
|
list: async (args: { workspaceId?: string; folderId?: string }) => {
|
||||||
|
const payload = {
|
||||||
|
type: 'list_http_requests_request',
|
||||||
|
// plugin events use camelCase field names in Rust -> snake_case mapping
|
||||||
|
folderId: args.folderId,
|
||||||
|
workspaceId: args.workspaceId,
|
||||||
|
} as any;
|
||||||
|
const { httpRequests } = await this.#sendForReply<any>(context, payload);
|
||||||
|
return httpRequests as any[];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
folder: {
|
||||||
|
list: async (args: { workspaceId?: string }) => {
|
||||||
|
const payload = {
|
||||||
|
type: 'list_folders_request',
|
||||||
|
workspaceId: args.workspaceId,
|
||||||
|
} as any;
|
||||||
|
const { folders } = await this.#sendForReply<any>(context, payload);
|
||||||
|
return folders as any[];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
cookies: {
|
cookies: {
|
||||||
getValue: async (args: GetCookieValueRequest) => {
|
getValue: async (args: GetCookieValueRequest) => {
|
||||||
@@ -638,6 +689,24 @@ export class PluginInstance {
|
|||||||
return result.data as any;
|
return result.data as any;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
file: {
|
||||||
|
writeText: async (filePath: string, content: string) => {
|
||||||
|
const payload: InternalEventPayload = {
|
||||||
|
type: 'write_text_file_request',
|
||||||
|
filePath,
|
||||||
|
content,
|
||||||
|
} as any;
|
||||||
|
await this.#sendForReply(context, payload);
|
||||||
|
},
|
||||||
|
readText: async (filePath: string) => {
|
||||||
|
const payload: InternalEventPayload = {
|
||||||
|
type: 'read_text_file_request',
|
||||||
|
filePath,
|
||||||
|
} as any;
|
||||||
|
const result = await this.#sendForReply<any>(context, payload);
|
||||||
|
return result.content;
|
||||||
|
},
|
||||||
|
},
|
||||||
store: {
|
store: {
|
||||||
get: async <T>(key: string) => {
|
get: async <T>(key: string) => {
|
||||||
const payload = { type: 'get_key_value_request', key } as const;
|
const payload = { type: 'get_key_value_request', key } as const;
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ use yaak_plugins::events::{
|
|||||||
CallGrpcRequestActionArgs, CallGrpcRequestActionRequest, CallHttpRequestActionArgs,
|
CallGrpcRequestActionArgs, CallGrpcRequestActionRequest, CallHttpRequestActionArgs,
|
||||||
CallHttpRequestActionRequest, Color, FilterResponse, GetGrpcRequestActionsResponse,
|
CallHttpRequestActionRequest, Color, FilterResponse, GetGrpcRequestActionsResponse,
|
||||||
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
|
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
|
||||||
GetHttpRequestActionsResponse, GetTemplateFunctionConfigResponse,
|
GetHttpRequestActionsResponse, GetHttpCollectionActionsResponse,
|
||||||
|
CallHttpCollectionActionArgs, CallHttpCollectionActionRequest, GetTemplateFunctionConfigResponse,
|
||||||
GetTemplateFunctionSummaryResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
|
GetTemplateFunctionSummaryResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
|
||||||
PluginContext, RenderPurpose, ShowToastRequest,
|
PluginContext, RenderPurpose, ShowToastRequest,
|
||||||
};
|
};
|
||||||
@@ -846,6 +847,40 @@ async fn cmd_http_request_actions<R: Runtime>(
|
|||||||
Ok(plugin_manager.get_http_request_actions(&window).await?)
|
Ok(plugin_manager.get_http_request_actions(&window).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn cmd_http_collection_actions<R: Runtime>(
|
||||||
|
window: WebviewWindow<R>,
|
||||||
|
plugin_manager: State<'_, PluginManager>,
|
||||||
|
) -> YaakResult<Vec<GetHttpCollectionActionsResponse>> {
|
||||||
|
Ok(plugin_manager.get_http_collection_actions(&window).await?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn cmd_call_http_collection_action<R: Runtime>(
|
||||||
|
window: WebviewWindow<R>,
|
||||||
|
req: CallHttpCollectionActionRequest,
|
||||||
|
plugin_manager: State<'_, PluginManager>,
|
||||||
|
) -> YaakResult<()> {
|
||||||
|
let folder = match &req.args.folder {
|
||||||
|
Some(f) => Some(window.db().get_folder(&f.id)?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let workspace = match &req.args.workspace {
|
||||||
|
Some(w) => Some(window.db().get_workspace(&w.id)?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(plugin_manager
|
||||||
|
.call_http_collection_action(
|
||||||
|
&window,
|
||||||
|
CallHttpCollectionActionRequest {
|
||||||
|
args: CallHttpCollectionActionArgs { folder, workspace },
|
||||||
|
..req
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_grpc_request_actions<R: Runtime>(
|
async fn cmd_grpc_request_actions<R: Runtime>(
|
||||||
window: WebviewWindow<R>,
|
window: WebviewWindow<R>,
|
||||||
@@ -1448,6 +1483,7 @@ pub fn run() {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
cmd_call_http_authentication_action,
|
cmd_call_http_authentication_action,
|
||||||
cmd_call_http_request_action,
|
cmd_call_http_request_action,
|
||||||
|
cmd_call_http_collection_action,
|
||||||
cmd_call_grpc_request_action,
|
cmd_call_grpc_request_action,
|
||||||
cmd_check_for_updates,
|
cmd_check_for_updates,
|
||||||
cmd_create_grpc_request,
|
cmd_create_grpc_request,
|
||||||
@@ -1467,6 +1503,7 @@ pub fn run() {
|
|||||||
cmd_grpc_reflect,
|
cmd_grpc_reflect,
|
||||||
cmd_grpc_request_actions,
|
cmd_grpc_request_actions,
|
||||||
cmd_http_request_actions,
|
cmd_http_request_actions,
|
||||||
|
cmd_http_collection_actions,
|
||||||
cmd_import_data,
|
cmd_import_data,
|
||||||
cmd_install_plugin,
|
cmd_install_plugin,
|
||||||
cmd_metadata,
|
cmd_metadata,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use yaak_plugins::error::Error::PluginErr;
|
|||||||
use yaak_plugins::events::{
|
use yaak_plugins::events::{
|
||||||
Color, DeleteKeyValueResponse, EmptyPayload, ErrorResponse, FindHttpResponsesResponse,
|
Color, DeleteKeyValueResponse, EmptyPayload, ErrorResponse, FindHttpResponsesResponse,
|
||||||
GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent,
|
GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent,
|
||||||
|
ListHttpRequestsResponse,
|
||||||
InternalEventPayload, ListCookieNamesResponse, RenderGrpcRequestResponse,
|
InternalEventPayload, ListCookieNamesResponse, RenderGrpcRequestResponse,
|
||||||
RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest,
|
RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest,
|
||||||
TemplateRenderResponse, WindowInfoResponse, WindowNavigateEvent,
|
TemplateRenderResponse, WindowInfoResponse, WindowNavigateEvent,
|
||||||
@@ -60,6 +61,30 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
|||||||
http_responses,
|
http_responses,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
InternalEventPayload::ListHttpRequestsRequest(req) => {
|
||||||
|
let mut http_requests = Vec::new();
|
||||||
|
if let Some(folder_id) = req.folder_id {
|
||||||
|
http_requests = app_handle
|
||||||
|
.db()
|
||||||
|
.list_http_requests_for_folder_recursive(&folder_id)?;
|
||||||
|
} else if let Some(workspace_id) = req.workspace_id {
|
||||||
|
http_requests = app_handle.db().list_http_requests(&workspace_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(InternalEventPayload::ListHttpRequestsResponse(ListHttpRequestsResponse {
|
||||||
|
http_requests,
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
InternalEventPayload::ListFoldersRequest(req) => {
|
||||||
|
let mut folders = Vec::new();
|
||||||
|
if let Some(workspace_id) = req.workspace_id {
|
||||||
|
folders = app_handle.db().list_folders(&workspace_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(InternalEventPayload::ListFoldersResponse(
|
||||||
|
yaak_plugins::events::ListFoldersResponse { folders },
|
||||||
|
)))
|
||||||
|
}
|
||||||
InternalEventPayload::GetHttpRequestByIdRequest(req) => {
|
InternalEventPayload::GetHttpRequestByIdRequest(req) => {
|
||||||
let http_request = app_handle.db().get_http_request(&req.id).ok();
|
let http_request = app_handle.db().get_http_request(&req.id).ok();
|
||||||
Ok(Some(InternalEventPayload::GetHttpRequestByIdResponse(GetHttpRequestByIdResponse {
|
Ok(Some(InternalEventPayload::GetHttpRequestByIdResponse(GetHttpRequestByIdResponse {
|
||||||
@@ -352,6 +377,26 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
|||||||
environment_id,
|
environment_id,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
InternalEventPayload::WriteTextFileRequest(req) => {
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
// Ensure the directory exists
|
||||||
|
if let Some(parent) = Path::new(&req.file_path).parent() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::write(&req.file_path, &req.content)?;
|
||||||
|
Ok(Some(InternalEventPayload::WriteTextFileResponse(EmptyPayload {})))
|
||||||
|
}
|
||||||
|
InternalEventPayload::ReadTextFileRequest(req) => {
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
let content = fs::read_to_string(&req.file_path)?;
|
||||||
|
Ok(Some(InternalEventPayload::ReadTextFileResponse(
|
||||||
|
yaak_plugins::events::ReadTextFileResponse { content },
|
||||||
|
)))
|
||||||
|
}
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ pub enum InternalEventPayload {
|
|||||||
GetHttpRequestActionsRequest(EmptyPayload),
|
GetHttpRequestActionsRequest(EmptyPayload),
|
||||||
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
|
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
|
||||||
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
|
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
|
||||||
|
// HTTP Collection Actions
|
||||||
|
GetHttpCollectionActionsRequest(EmptyPayload),
|
||||||
|
GetHttpCollectionActionsResponse(GetHttpCollectionActionsResponse),
|
||||||
|
CallHttpCollectionActionRequest(CallHttpCollectionActionRequest),
|
||||||
|
|
||||||
// Grpc Request Actions
|
// Grpc Request Actions
|
||||||
GetGrpcRequestActionsRequest(EmptyPayload),
|
GetGrpcRequestActionsRequest(EmptyPayload),
|
||||||
@@ -151,10 +155,19 @@ pub enum InternalEventPayload {
|
|||||||
|
|
||||||
FindHttpResponsesRequest(FindHttpResponsesRequest),
|
FindHttpResponsesRequest(FindHttpResponsesRequest),
|
||||||
FindHttpResponsesResponse(FindHttpResponsesResponse),
|
FindHttpResponsesResponse(FindHttpResponsesResponse),
|
||||||
|
ListHttpRequestsRequest(ListHttpRequestsRequest),
|
||||||
|
ListHttpRequestsResponse(ListHttpRequestsResponse),
|
||||||
|
ListFoldersRequest(ListFoldersRequest),
|
||||||
|
ListFoldersResponse(ListFoldersResponse),
|
||||||
|
|
||||||
GetThemesRequest(GetThemesRequest),
|
GetThemesRequest(GetThemesRequest),
|
||||||
GetThemesResponse(GetThemesResponse),
|
GetThemesResponse(GetThemesResponse),
|
||||||
|
|
||||||
|
WriteTextFileRequest(WriteTextFileRequest),
|
||||||
|
WriteTextFileResponse(EmptyPayload),
|
||||||
|
ReadTextFileRequest(ReadTextFileRequest),
|
||||||
|
ReadTextFileResponse(ReadTextFileResponse),
|
||||||
|
|
||||||
/// Returned when a plugin doesn't get run, just so the server
|
/// Returned when a plugin doesn't get run, just so the server
|
||||||
/// has something to listen for
|
/// has something to listen for
|
||||||
EmptyResponse(EmptyPayload),
|
EmptyResponse(EmptyPayload),
|
||||||
@@ -1096,6 +1109,14 @@ pub struct GetHttpRequestActionsResponse {
|
|||||||
pub plugin_ref_id: String,
|
pub plugin_ref_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct GetHttpCollectionActionsResponse {
|
||||||
|
pub actions: Vec<HttpCollectionAction>,
|
||||||
|
pub plugin_ref_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
@@ -1105,6 +1126,15 @@ pub struct HttpRequestAction {
|
|||||||
pub icon: Option<Icon>,
|
pub icon: Option<Icon>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct HttpCollectionAction {
|
||||||
|
pub label: String,
|
||||||
|
#[ts(optional)]
|
||||||
|
pub icon: Option<Icon>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
@@ -1114,6 +1144,15 @@ pub struct CallHttpRequestActionRequest {
|
|||||||
pub args: CallHttpRequestActionArgs,
|
pub args: CallHttpRequestActionArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct CallHttpCollectionActionRequest {
|
||||||
|
pub index: i32,
|
||||||
|
pub plugin_ref_id: String,
|
||||||
|
pub args: CallHttpCollectionActionArgs,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
@@ -1121,6 +1160,16 @@ pub struct CallHttpRequestActionArgs {
|
|||||||
pub http_request: HttpRequest,
|
pub http_request: HttpRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct CallHttpCollectionActionArgs {
|
||||||
|
#[ts(optional)]
|
||||||
|
pub folder: Option<Folder>,
|
||||||
|
#[ts(optional)]
|
||||||
|
pub workspace: Option<Workspace>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
@@ -1185,6 +1234,38 @@ pub struct FindHttpResponsesResponse {
|
|||||||
pub http_responses: Vec<HttpResponse>,
|
pub http_responses: Vec<HttpResponse>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct ListHttpRequestsRequest {
|
||||||
|
#[ts(optional)]
|
||||||
|
pub folder_id: Option<String>,
|
||||||
|
#[ts(optional)]
|
||||||
|
pub workspace_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct ListHttpRequestsResponse {
|
||||||
|
pub http_requests: Vec<HttpRequest>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct ListFoldersRequest {
|
||||||
|
#[ts(optional)]
|
||||||
|
pub workspace_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct ListFoldersResponse {
|
||||||
|
pub folders: Vec<Folder>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
@@ -1238,3 +1319,25 @@ pub struct DeleteKeyValueRequest {
|
|||||||
pub struct DeleteKeyValueResponse {
|
pub struct DeleteKeyValueResponse {
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct WriteTextFileRequest {
|
||||||
|
pub file_path: String,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct ReadTextFileRequest {
|
||||||
|
pub file_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct ReadTextFileResponse {
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use crate::events::{
|
|||||||
FilterRequest, FilterResponse, GetGrpcRequestActionsResponse,
|
FilterRequest, FilterResponse, GetGrpcRequestActionsResponse,
|
||||||
GetHttpAuthenticationConfigRequest, GetHttpAuthenticationConfigResponse,
|
GetHttpAuthenticationConfigRequest, GetHttpAuthenticationConfigResponse,
|
||||||
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
|
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
|
||||||
|
GetHttpCollectionActionsResponse, CallHttpCollectionActionRequest,
|
||||||
GetTemplateFunctionConfigRequest, GetTemplateFunctionConfigResponse,
|
GetTemplateFunctionConfigRequest, GetTemplateFunctionConfigResponse,
|
||||||
GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse, ImportRequest,
|
GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse, ImportRequest,
|
||||||
ImportResponse, InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext,
|
ImportResponse, InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext,
|
||||||
@@ -482,6 +483,27 @@ impl PluginManager {
|
|||||||
Ok(all_actions)
|
Ok(all_actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_http_collection_actions<R: Runtime>(
|
||||||
|
&self,
|
||||||
|
window: &WebviewWindow<R>,
|
||||||
|
) -> Result<Vec<GetHttpCollectionActionsResponse>> {
|
||||||
|
let reply_events = self
|
||||||
|
.send_and_wait(
|
||||||
|
&PluginContext::new(window),
|
||||||
|
&InternalEventPayload::GetHttpCollectionActionsRequest(EmptyPayload {}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut all_actions = Vec::new();
|
||||||
|
for event in reply_events {
|
||||||
|
if let InternalEventPayload::GetHttpCollectionActionsResponse(resp) = event.payload {
|
||||||
|
all_actions.push(resp.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(all_actions)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_template_function_config<R: Runtime>(
|
pub async fn get_template_function_config<R: Runtime>(
|
||||||
&self,
|
&self,
|
||||||
window: &WebviewWindow<R>,
|
window: &WebviewWindow<R>,
|
||||||
@@ -564,6 +586,23 @@ impl PluginManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn call_http_collection_action<R: Runtime>(
|
||||||
|
&self,
|
||||||
|
window: &WebviewWindow<R>,
|
||||||
|
req: CallHttpCollectionActionRequest,
|
||||||
|
) -> Result<()> {
|
||||||
|
let ref_id = req.plugin_ref_id.clone();
|
||||||
|
let plugin =
|
||||||
|
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
|
||||||
|
let event = plugin.build_event_to_send(
|
||||||
|
&PluginContext::new(window),
|
||||||
|
&InternalEventPayload::CallHttpCollectionActionRequest(req),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
plugin.send(&event).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn call_grpc_request_action<R: Runtime>(
|
pub async fn call_grpc_request_action<R: Runtime>(
|
||||||
&self,
|
&self,
|
||||||
window: &WebviewWindow<R>,
|
window: &WebviewWindow<R>,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import { getCreateDropdownItems } from '../hooks/useCreateDropdownItems';
|
|||||||
import { getGrpcRequestActions } from '../hooks/useGrpcRequestActions';
|
import { getGrpcRequestActions } from '../hooks/useGrpcRequestActions';
|
||||||
import { useHotKey } from '../hooks/useHotKey';
|
import { useHotKey } from '../hooks/useHotKey';
|
||||||
import { getHttpRequestActions } from '../hooks/useHttpRequestActions';
|
import { getHttpRequestActions } from '../hooks/useHttpRequestActions';
|
||||||
|
import { getHttpCollectionActions } from '../hooks/useHttpCollectionActions';
|
||||||
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
||||||
import { getModelAncestors } from '../hooks/useModelAncestors';
|
import { getModelAncestors } from '../hooks/useModelAncestors';
|
||||||
import { sendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
|
import { sendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
|
||||||
@@ -374,6 +375,17 @@ function Sidebar({ className }: { className?: string }) {
|
|||||||
if (request != null) await a.call(request);
|
if (request != null) await a.call(request);
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
...(items.length === 1 && (child.model === 'folder' || child.model === 'workspace')
|
||||||
|
? await getHttpCollectionActions()
|
||||||
|
: []
|
||||||
|
).map((a) => ({
|
||||||
|
label: a.label,
|
||||||
|
leftSlot: <Icon icon={a.icon ?? 'empty'} />,
|
||||||
|
onSelect: async () => {
|
||||||
|
const model = getModel(child.model, child.id);
|
||||||
|
if (model != null) await a.call(model as any);
|
||||||
|
},
|
||||||
|
})),
|
||||||
];
|
];
|
||||||
const modelCreationItems: DropdownItem[] =
|
const modelCreationItems: DropdownItem[] =
|
||||||
items.length === 1 && child.model === 'folder'
|
items.length === 1 && child.model === 'folder'
|
||||||
|
|||||||
50
src-web/hooks/useHttpCollectionActions.ts
Normal file
50
src-web/hooks/useHttpCollectionActions.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import type { Folder, Workspace } from '@yaakapp-internal/models';
|
||||||
|
import type {
|
||||||
|
CallHttpCollectionActionRequest,
|
||||||
|
GetHttpCollectionActionsResponse,
|
||||||
|
HttpCollectionAction,
|
||||||
|
} from '@yaakapp-internal/plugins';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { invokeCmd } from '../lib/tauri';
|
||||||
|
import { usePluginsKey } from './usePlugins';
|
||||||
|
|
||||||
|
export type CallableHttpCollectionAction = Pick<HttpCollectionAction, 'label' | 'icon'> & {
|
||||||
|
call: (model: Folder | Workspace) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useHttpCollectionActions() {
|
||||||
|
const pluginsKey = usePluginsKey();
|
||||||
|
|
||||||
|
const actionsResult = useQuery<CallableHttpCollectionAction[]>({
|
||||||
|
queryKey: ['http_collection_actions', pluginsKey],
|
||||||
|
queryFn: () => getHttpCollectionActions(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// biome-ignore lint/correctness/useExhaustiveDependencies: none
|
||||||
|
const actions = useMemo(() => {
|
||||||
|
return actionsResult.data ?? [];
|
||||||
|
}, [JSON.stringify(actionsResult.data)]);
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getHttpCollectionActions() {
|
||||||
|
const responses = await invokeCmd<GetHttpCollectionActionsResponse[]>('cmd_http_collection_actions');
|
||||||
|
const actions = responses.flatMap((r) =>
|
||||||
|
r.actions.map((a, i) => ({
|
||||||
|
label: a.label,
|
||||||
|
icon: a.icon,
|
||||||
|
call: async (model: Folder | Workspace) => {
|
||||||
|
const payload: CallHttpCollectionActionRequest = {
|
||||||
|
index: i,
|
||||||
|
pluginRefId: r.pluginRefId,
|
||||||
|
args: (model as any).model === 'folder' ? { folder: model as Folder } : { workspace: model as Workspace },
|
||||||
|
} as any;
|
||||||
|
await invokeCmd('cmd_call_http_collection_action', { req: payload });
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ type TauriCmd =
|
|||||||
| 'cmd_call_grpc_request_action'
|
| 'cmd_call_grpc_request_action'
|
||||||
| 'cmd_call_http_authentication_action'
|
| 'cmd_call_http_authentication_action'
|
||||||
| 'cmd_call_http_request_action'
|
| 'cmd_call_http_request_action'
|
||||||
|
| 'cmd_call_http_collection_action'
|
||||||
| 'cmd_check_for_updates'
|
| 'cmd_check_for_updates'
|
||||||
| 'cmd_create_grpc_request'
|
| 'cmd_create_grpc_request'
|
||||||
| 'cmd_curl_to_request'
|
| 'cmd_curl_to_request'
|
||||||
@@ -24,6 +25,7 @@ type TauriCmd =
|
|||||||
| 'cmd_grpc_reflect'
|
| 'cmd_grpc_reflect'
|
||||||
| 'cmd_grpc_request_actions'
|
| 'cmd_grpc_request_actions'
|
||||||
| 'cmd_http_request_actions'
|
| 'cmd_http_request_actions'
|
||||||
|
| 'cmd_http_collection_actions'
|
||||||
| 'cmd_http_response_body'
|
| 'cmd_http_response_body'
|
||||||
| 'cmd_import_data'
|
| 'cmd_import_data'
|
||||||
| 'cmd_install_plugin'
|
| 'cmd_install_plugin'
|
||||||
|
|||||||
Reference in New Issue
Block a user