mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 09:08:32 +02:00
gRPC request actions and "copy as gRPCurl" (#232)
This commit is contained in:
@@ -80,6 +80,7 @@ module.exports = defineConfig([
|
|||||||
globalIgnores([
|
globalIgnores([
|
||||||
'**/node_modules/',
|
'**/node_modules/',
|
||||||
'**/dist/',
|
'**/dist/',
|
||||||
|
'**/build/',
|
||||||
'**/.eslintrc.cjs',
|
'**/.eslintrc.cjs',
|
||||||
'**/.prettierrc.cjs',
|
'**/.prettierrc.cjs',
|
||||||
'src-web/postcss.config.cjs',
|
'src-web/postcss.config.cjs',
|
||||||
|
|||||||
592
package-lock.json
generated
592
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,8 @@
|
|||||||
"plugins/auth-bearer",
|
"plugins/auth-bearer",
|
||||||
"plugins/auth-jwt",
|
"plugins/auth-jwt",
|
||||||
"plugins/auth-oauth2",
|
"plugins/auth-oauth2",
|
||||||
"plugins/exporter-curl",
|
"plugins/action-copy-curl",
|
||||||
|
"plugins/action-copy-grpcurl",
|
||||||
"plugins/filter-jsonpath",
|
"plugins/filter-jsonpath",
|
||||||
"plugins/filter-xpath",
|
"plugins/filter-xpath",
|
||||||
"plugins/importer-curl",
|
"plugins/importer-curl",
|
||||||
@@ -85,6 +86,7 @@
|
|||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
|
"vitest": "^3.2.4",
|
||||||
"workspaces-run": "^1.0.2"
|
"workspaces-run": "^1.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ export type BootRequest = { dir: string, watch: boolean, };
|
|||||||
|
|
||||||
export type BootResponse = { name: string, version: string, };
|
export type BootResponse = { name: string, version: string, };
|
||||||
|
|
||||||
|
export type CallGrpcRequestActionArgs = { grpcRequest: GrpcRequest, protoFiles: Array<string>, };
|
||||||
|
|
||||||
|
export type CallGrpcRequestActionRequest = { index: number, pluginRefId: string, args: CallGrpcRequestActionArgs, };
|
||||||
|
|
||||||
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
||||||
|
|
||||||
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
|
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
|
||||||
@@ -336,14 +340,14 @@ export type GetCookieValueRequest = { name: string, };
|
|||||||
|
|
||||||
export type GetCookieValueResponse = { value: string | null, };
|
export type GetCookieValueResponse = { value: string | null, };
|
||||||
|
|
||||||
|
export type GetGrpcRequestActionsResponse = { actions: Array<GrpcRequestAction>, pluginRefId: string, };
|
||||||
|
|
||||||
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
||||||
|
|
||||||
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
|
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
|
||||||
|
|
||||||
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
|
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
|
||||||
|
|
||||||
export type GetHttpRequestActionsRequest = Record<string, never>;
|
|
||||||
|
|
||||||
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
|
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
|
||||||
|
|
||||||
export type GetHttpRequestByIdRequest = { id: string, };
|
export type GetHttpRequestByIdRequest = { id: string, };
|
||||||
@@ -360,6 +364,8 @@ export type GetThemesRequest = Record<string, never>;
|
|||||||
|
|
||||||
export type GetThemesResponse = { themes: Array<Theme>, };
|
export type GetThemesResponse = { themes: Array<Theme>, };
|
||||||
|
|
||||||
|
export type GrpcRequestAction = { label: string, icon?: Icon, };
|
||||||
|
|
||||||
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
|
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
|
||||||
|
|
||||||
export type HttpHeader = { name: string, value: string, };
|
export type HttpHeader = { name: string, value: string, };
|
||||||
@@ -376,7 +382,7 @@ export type ImportResponse = { resources: ImportResources, };
|
|||||||
|
|
||||||
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: PluginWindowContext, payload: InternalEventPayload, };
|
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: PluginWindowContext, payload: InternalEventPayload, };
|
||||||
|
|
||||||
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & BootResponse | { "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": "list_cookie_names_request" } & ListCookieNamesRequest | { "type": "list_cookie_names_response" } & ListCookieNamesResponse | { "type": "get_cookie_value_request" } & GetCookieValueRequest | { "type": "get_cookie_value_response" } & GetCookieValueResponse | { "type": "get_http_request_actions_request" } & EmptyPayload | { "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": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "type": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "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": "get_themes_request" } & GetThemesRequest | { "type": "get_themes_response" } & GetThemesResponse | { "type": "empty_response" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
|
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & BootResponse | { "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": "list_cookie_names_request" } & ListCookieNamesRequest | { "type": "list_cookie_names_response" } & ListCookieNamesResponse | { "type": "get_cookie_value_request" } & GetCookieValueRequest | { "type": "get_cookie_value_response" } & GetCookieValueResponse | { "type": "get_http_request_actions_request" } & EmptyPayload | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_grpc_request_actions_request" } & EmptyPayload | { "type": "get_grpc_request_actions_response" } & GetGrpcRequestActionsResponse | { "type": "call_grpc_request_action_request" } & CallGrpcRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "render_grpc_request_request" } & RenderGrpcRequestRequest | { "type": "render_grpc_request_response" } & RenderGrpcRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "type": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "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": "get_themes_request" } & GetThemesRequest | { "type": "get_themes_response" } & GetThemesResponse | { "type": "empty_response" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
|
||||||
|
|
||||||
export type JsonPrimitive = string | number | boolean | null;
|
export type JsonPrimitive = string | number | boolean | null;
|
||||||
|
|
||||||
@@ -408,6 +414,10 @@ required?: boolean, };
|
|||||||
|
|
||||||
export type PromptTextResponse = { value: string | null, };
|
export type PromptTextResponse = { value: string | null, };
|
||||||
|
|
||||||
|
export type RenderGrpcRequestRequest = { grpcRequest: GrpcRequest, purpose: RenderPurpose, };
|
||||||
|
|
||||||
|
export type RenderGrpcRequestResponse = { grpcRequest: GrpcRequest, };
|
||||||
|
|
||||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
||||||
|
|
||||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import type {
|
|||||||
OpenWindowRequest,
|
OpenWindowRequest,
|
||||||
PromptTextRequest,
|
PromptTextRequest,
|
||||||
PromptTextResponse,
|
PromptTextResponse,
|
||||||
|
RenderGrpcRequestRequest,
|
||||||
|
RenderGrpcRequestResponse,
|
||||||
RenderHttpRequestRequest,
|
RenderHttpRequestRequest,
|
||||||
RenderHttpRequestResponse,
|
RenderHttpRequestResponse,
|
||||||
SendHttpRequestRequest,
|
SendHttpRequestRequest,
|
||||||
@@ -45,6 +47,9 @@ export interface Context {
|
|||||||
listNames(): Promise<ListCookieNamesResponse['names']>;
|
listNames(): Promise<ListCookieNamesResponse['names']>;
|
||||||
getValue(args: GetCookieValueRequest): Promise<GetCookieValueResponse['value']>;
|
getValue(args: GetCookieValueRequest): Promise<GetCookieValueResponse['value']>;
|
||||||
};
|
};
|
||||||
|
grpcRequest: {
|
||||||
|
render(args: RenderGrpcRequestRequest): Promise<RenderGrpcRequestResponse['grpcRequest']>;
|
||||||
|
};
|
||||||
httpRequest: {
|
httpRequest: {
|
||||||
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
||||||
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { CallGrpcRequestActionArgs, GrpcRequestAction } from '../bindings/gen_events';
|
||||||
|
import type { Context } from './Context';
|
||||||
|
|
||||||
|
export type GrpcRequestActionPlugin = GrpcRequestAction & {
|
||||||
|
onSelect(ctx: Context, args: CallGrpcRequestActionArgs): Promise<void> | void;
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ImportResources } from '../bindings/gen_events';
|
import { ImportResources } from '../bindings/gen_events';
|
||||||
import { AtLeast } from '../helpers';
|
import { AtLeast, MaybePromise } from '../helpers';
|
||||||
import type { Context } from './Context';
|
import type { Context } from './Context';
|
||||||
|
|
||||||
type RootFields = 'name' | 'id' | 'model';
|
type RootFields = 'name' | 'id' | 'model';
|
||||||
@@ -21,5 +21,8 @@ export type ImportPluginResponse = null | {
|
|||||||
export type ImporterPlugin = {
|
export type ImporterPlugin = {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
onImport(ctx: Context, args: { text: string }): Promise<ImportPluginResponse>;
|
onImport(
|
||||||
|
ctx: Context,
|
||||||
|
args: { text: string },
|
||||||
|
): MaybePromise<ImportPluginResponse | null | undefined>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AuthenticationPlugin } from './AuthenticationPlugin';
|
import { AuthenticationPlugin } from './AuthenticationPlugin';
|
||||||
import type { FilterPlugin } from './FilterPlugin';
|
import type { FilterPlugin } from './FilterPlugin';
|
||||||
|
import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin';
|
||||||
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
||||||
import type { ImporterPlugin } from './ImporterPlugin';
|
import type { ImporterPlugin } from './ImporterPlugin';
|
||||||
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
||||||
@@ -16,5 +17,6 @@ export type PluginDefinition = {
|
|||||||
filter?: FilterPlugin;
|
filter?: FilterPlugin;
|
||||||
authentication?: AuthenticationPlugin;
|
authentication?: AuthenticationPlugin;
|
||||||
httpRequestActions?: HttpRequestActionPlugin[];
|
httpRequestActions?: HttpRequestActionPlugin[];
|
||||||
|
grpcRequestActions?: GrpcRequestActionPlugin[];
|
||||||
templateFunctions?: TemplateFunctionPlugin[];
|
templateFunctions?: TemplateFunctionPlugin[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
GetCookieValueRequest,
|
GetCookieValueRequest,
|
||||||
GetCookieValueResponse,
|
GetCookieValueResponse,
|
||||||
GetHttpRequestByIdResponse,
|
GetHttpRequestByIdResponse,
|
||||||
GetKeyValueResponse,
|
GetKeyValueResponse, GrpcRequestAction,
|
||||||
HttpAuthenticationAction,
|
HttpAuthenticationAction,
|
||||||
HttpRequestAction,
|
HttpRequestAction,
|
||||||
InternalEvent,
|
InternalEvent,
|
||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
PluginWindowContext,
|
PluginWindowContext,
|
||||||
PromptTextResponse,
|
PromptTextResponse,
|
||||||
RenderHttpRequestResponse,
|
RenderHttpRequestResponse,
|
||||||
|
RenderGrpcRequestResponse,
|
||||||
SendHttpRequestResponse,
|
SendHttpRequestResponse,
|
||||||
TemplateFunction,
|
TemplateFunction,
|
||||||
TemplateFunctionArg,
|
TemplateFunctionArg,
|
||||||
@@ -145,6 +146,24 @@ export class PluginInstance {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.type === 'get_grpc_request_actions_request' &&
|
||||||
|
Array.isArray(this.#mod?.grpcRequestActions)
|
||||||
|
) {
|
||||||
|
const reply: GrpcRequestAction[] = this.#mod.grpcRequestActions.map((a) => ({
|
||||||
|
...a,
|
||||||
|
// Add everything except onSelect
|
||||||
|
onSelect: undefined,
|
||||||
|
}));
|
||||||
|
const replyPayload: InternalEventPayload = {
|
||||||
|
type: 'get_grpc_request_actions_response',
|
||||||
|
pluginRefId: this.#workerData.pluginRefId,
|
||||||
|
actions: reply,
|
||||||
|
};
|
||||||
|
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
payload.type === 'get_http_request_actions_request' &&
|
payload.type === 'get_http_request_actions_request' &&
|
||||||
Array.isArray(this.#mod?.httpRequestActions)
|
Array.isArray(this.#mod?.httpRequestActions)
|
||||||
@@ -208,13 +227,12 @@ export class PluginInstance {
|
|||||||
if (payload.type === 'get_http_authentication_config_request' && this.#mod?.authentication) {
|
if (payload.type === 'get_http_authentication_config_request' && this.#mod?.authentication) {
|
||||||
const { args, actions } = this.#mod.authentication;
|
const { args, actions } = this.#mod.authentication;
|
||||||
const resolvedArgs: FormInput[] = [];
|
const resolvedArgs: FormInput[] = [];
|
||||||
for (let i = 0; i < args.length; i++) {
|
for (const v of args) {
|
||||||
let v = args[i];
|
if (v && 'dynamic' in v) {
|
||||||
if ('dynamic' in v) {
|
|
||||||
const dynamicAttrs = await v.dynamic(ctx, payload);
|
const dynamicAttrs = await v.dynamic(ctx, payload);
|
||||||
const { dynamic, ...other } = v;
|
const { dynamic, ...other } = v;
|
||||||
resolvedArgs.push({ ...other, ...dynamicAttrs } as FormInput);
|
resolvedArgs.push({ ...other, ...dynamicAttrs } as FormInput);
|
||||||
} else {
|
} else if (v) {
|
||||||
resolvedArgs.push(v);
|
resolvedArgs.push(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +293,18 @@ export class PluginInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.type === 'call_grpc_request_action_request' &&
|
||||||
|
Array.isArray(this.#mod.grpcRequestActions)
|
||||||
|
) {
|
||||||
|
const action = this.#mod.grpcRequestActions[payload.index];
|
||||||
|
if (typeof action?.onSelect === 'function') {
|
||||||
|
await action.onSelect(ctx, payload.args);
|
||||||
|
this.#sendEmpty(windowContext, replyId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
payload.type === 'call_template_function_request' &&
|
payload.type === 'call_template_function_request' &&
|
||||||
Array.isArray(this.#mod?.templateFunctions)
|
Array.isArray(this.#mod?.templateFunctions)
|
||||||
@@ -472,6 +502,19 @@ export class PluginInstance {
|
|||||||
return httpResponses;
|
return httpResponses;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
grpcRequest: {
|
||||||
|
render: async (args) => {
|
||||||
|
const payload = {
|
||||||
|
type: 'render_grpc_request_request',
|
||||||
|
...args,
|
||||||
|
} as const;
|
||||||
|
const { grpcRequest } = await this.#sendAndWaitForReply<RenderGrpcRequestResponse>(
|
||||||
|
event.windowContext,
|
||||||
|
payload,
|
||||||
|
);
|
||||||
|
return grpcRequest;
|
||||||
|
},
|
||||||
|
},
|
||||||
httpRequest: {
|
httpRequest: {
|
||||||
getById: async (args) => {
|
getById: async (args) => {
|
||||||
const payload = {
|
const payload = {
|
||||||
@@ -596,20 +639,20 @@ function applyFormInputDefaults(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const watchedFiles: Record<string, Stats> = {};
|
const watchedFiles: Record<string, Stats | null> = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watch a file and trigger callback on change.
|
* Watch a file and trigger a callback on change.
|
||||||
*
|
*
|
||||||
* We also track the stat for each file because fs.watch() will
|
* We also track the stat for each file because fs.watch() will
|
||||||
* trigger a "change" event when the access date changes
|
* trigger a "change" event when the access date changes.
|
||||||
*/
|
*/
|
||||||
function watchFile(filepath: string, cb: (filepath: string) => void) {
|
function watchFile(filepath: string, cb: () => void) {
|
||||||
watch(filepath, () => {
|
watch(filepath, () => {
|
||||||
const stat = statSync(filepath);
|
const stat = statSync(filepath, { throwIfNoEntry: false });
|
||||||
if (stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
|
if (stat == null || stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
|
||||||
cb(filepath);
|
watchedFiles[filepath] = stat ?? null;
|
||||||
|
cb();
|
||||||
}
|
}
|
||||||
watchedFiles[filepath] = stat;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@yaak/exporter-curl",
|
"name": "@yaak/action-copy-curl",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,27 @@
|
|||||||
import { HttpRequest, PluginDefinition } from '@yaakapp/api';
|
import type { HttpRequest, PluginDefinition } from '@yaakapp/api';
|
||||||
|
|
||||||
const NEWLINE = '\\\n ';
|
const NEWLINE = '\\\n ';
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
httpRequestActions: [{
|
httpRequestActions: [
|
||||||
label: 'Copy as Curl',
|
{
|
||||||
icon: 'copy',
|
label: 'Copy as Curl',
|
||||||
async onSelect(ctx, args) {
|
icon: 'copy',
|
||||||
const rendered_request = await ctx.httpRequest.render({ httpRequest: args.httpRequest, purpose: 'preview' });
|
async onSelect(ctx, args) {
|
||||||
const data = await convertToCurl(rendered_request);
|
const rendered_request = await ctx.httpRequest.render({
|
||||||
await ctx.clipboard.copyText(data);
|
httpRequest: args.httpRequest,
|
||||||
await ctx.toast.show({ message: 'Curl copied to clipboard', icon: 'copy', color: 'success' });
|
purpose: 'preview',
|
||||||
|
});
|
||||||
|
const data = await convertToCurl(rendered_request);
|
||||||
|
await ctx.clipboard.copyText(data);
|
||||||
|
await ctx.toast.show({
|
||||||
|
message: 'Command copied to clipboard',
|
||||||
|
icon: 'copy',
|
||||||
|
color: 'success',
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function convertToCurl(request: Partial<HttpRequest>) {
|
export async function convertToCurl(request: Partial<HttpRequest>) {
|
||||||
@@ -22,7 +31,6 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
|
|||||||
if (request.method) xs.push('-X', request.method);
|
if (request.method) xs.push('-X', request.method);
|
||||||
if (request.url) xs.push(quote(request.url));
|
if (request.url) xs.push(quote(request.url));
|
||||||
|
|
||||||
|
|
||||||
xs.push(NEWLINE);
|
xs.push(NEWLINE);
|
||||||
|
|
||||||
// Add URL params
|
// Add URL params
|
||||||
@@ -51,7 +59,10 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
|
|||||||
xs.push(NEWLINE);
|
xs.push(NEWLINE);
|
||||||
}
|
}
|
||||||
} else if (typeof request.body?.query === 'string') {
|
} else if (typeof request.body?.query === 'string') {
|
||||||
const body = { query: request.body.query || '', variables: maybeParseJSON(request.body.variables, undefined) };
|
const body = {
|
||||||
|
query: request.body.query || '',
|
||||||
|
variables: maybeParseJSON(request.body.variables, undefined),
|
||||||
|
};
|
||||||
xs.push('--data-raw', `${quote(JSON.stringify(body))}`);
|
xs.push('--data-raw', `${quote(JSON.stringify(body))}`);
|
||||||
xs.push(NEWLINE);
|
xs.push(NEWLINE);
|
||||||
} else if (typeof request.body?.text === 'string') {
|
} else if (typeof request.body?.text === 'string') {
|
||||||
@@ -84,7 +95,7 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function quote(arg: string): string {
|
function quote(arg: string): string {
|
||||||
const escaped = arg.replace(/'/g, '\\\'');
|
const escaped = arg.replace(/'/g, "\\'");
|
||||||
return `'${escaped}'`;
|
return `'${escaped}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,10 +103,10 @@ function onlyEnabled(v: { name?: string; enabled?: boolean }): boolean {
|
|||||||
return v.enabled !== false && !!v.name;
|
return v.enabled !== false && !!v.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeParseJSON(v: any, fallback: any): string {
|
function maybeParseJSON<T>(v: string, fallback: T) {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(v);
|
return JSON.parse(v);
|
||||||
} catch (err) {
|
} catch {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
plugins/action-copy-grpcurl/package.json
Normal file
10
plugins/action-copy-grpcurl/package.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "@yaak/action-copy-grpcurl",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"build": "yaakcli build ./src/index.js",
|
||||||
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
|
}
|
||||||
|
}
|
||||||
134
plugins/action-copy-grpcurl/src/index.ts
Normal file
134
plugins/action-copy-grpcurl/src/index.ts
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import type { GrpcRequest, PluginDefinition } from '@yaakapp/api';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
const NEWLINE = '\\\n ';
|
||||||
|
|
||||||
|
export const plugin: PluginDefinition = {
|
||||||
|
grpcRequestActions: [
|
||||||
|
{
|
||||||
|
label: 'Copy as gRPCurl',
|
||||||
|
icon: 'copy',
|
||||||
|
async onSelect(ctx, args) {
|
||||||
|
const rendered_request = await ctx.grpcRequest.render({
|
||||||
|
grpcRequest: args.grpcRequest,
|
||||||
|
purpose: 'preview',
|
||||||
|
});
|
||||||
|
const data = await convert(rendered_request, args.protoFiles);
|
||||||
|
await ctx.clipboard.copyText(data);
|
||||||
|
await ctx.toast.show({
|
||||||
|
message: 'Command copied to clipboard',
|
||||||
|
icon: 'copy',
|
||||||
|
color: 'success',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function convert(request: Partial<GrpcRequest>, allProtoFiles: string[]) {
|
||||||
|
const xs = ['grpcurl'];
|
||||||
|
|
||||||
|
if (request.url?.startsWith('http://')) {
|
||||||
|
xs.push('-plaintext');
|
||||||
|
}
|
||||||
|
|
||||||
|
const protoIncludes = allProtoFiles.filter((f) => !f.endsWith('.proto'));
|
||||||
|
const protoFiles = allProtoFiles.filter((f) => f.endsWith('.proto'));
|
||||||
|
|
||||||
|
const inferredIncludes = new Set<string>();
|
||||||
|
for (const f of protoFiles) {
|
||||||
|
const protoDir = findParentProtoDir(f);
|
||||||
|
if (protoDir) {
|
||||||
|
inferredIncludes.add(protoDir);
|
||||||
|
} else {
|
||||||
|
inferredIncludes.add(path.join(f, '..'));
|
||||||
|
inferredIncludes.add(path.join(f, '..', '..'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const f of protoIncludes) {
|
||||||
|
xs.push('-import-path', quote(f));
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const f of inferredIncludes.values()) {
|
||||||
|
xs.push('-import-path', quote(f));
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const f of protoFiles) {
|
||||||
|
xs.push('-proto', quote(f));
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add headers
|
||||||
|
for (const h of (request.metadata ?? []).filter(onlyEnabled)) {
|
||||||
|
xs.push('-H', quote(`${h.name}: ${h.value}`));
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add basic authentication
|
||||||
|
if (request.authenticationType === 'basic') {
|
||||||
|
const user = request.authentication?.username ?? '';
|
||||||
|
const pass = request.authentication?.password ?? '';
|
||||||
|
const encoded = btoa(`${user}:${pass}`);
|
||||||
|
xs.push('-H', quote(`Authorization: Basic ${encoded}`));
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
} else if (request.authenticationType === 'bearer') {
|
||||||
|
// Add bearer authentication
|
||||||
|
xs.push('-H', quote(`Authorization: Bearer ${request.authentication?.token ?? ''}`));
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add form params
|
||||||
|
if (request.message) {
|
||||||
|
xs.push('-d', `${quote(JSON.stringify(JSON.parse(request.message)))}`);
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the server address
|
||||||
|
if (request.url) {
|
||||||
|
const server = request.url.replace(/^https?:\/\//, ''); // remove protocol
|
||||||
|
xs.push(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add service + method
|
||||||
|
if (request.service && request.method) {
|
||||||
|
xs.push(`${request.service}/${request.method}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
xs.push(NEWLINE);
|
||||||
|
|
||||||
|
// Remove trailing newline
|
||||||
|
if (xs[xs.length - 1] === NEWLINE) {
|
||||||
|
xs.splice(xs.length - 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xs.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function quote(arg: string): string {
|
||||||
|
const escaped = arg.replace(/'/g, "\\'");
|
||||||
|
return `'${escaped}'`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onlyEnabled(v: { name?: string; enabled?: boolean }): boolean {
|
||||||
|
return v.enabled !== false && !!v.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findParentProtoDir(startPath: string): string | null {
|
||||||
|
let dir = path.resolve(startPath);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (path.basename(dir) === 'proto') {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = path.dirname(dir);
|
||||||
|
if (parent === dir) {
|
||||||
|
return null; // Reached root
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
110
plugins/action-copy-grpcurl/tests/index.test.ts
Normal file
110
plugins/action-copy-grpcurl/tests/index.test.ts
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
import { convert } from '../src';
|
||||||
|
|
||||||
|
describe('exporter-curl', () => {
|
||||||
|
test('Simple example', async () => {
|
||||||
|
expect(
|
||||||
|
await convert(
|
||||||
|
{
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
).toEqual([`grpcurl yaak.app`].join(` \\\n `));
|
||||||
|
});
|
||||||
|
test('Basic metadata', async () => {
|
||||||
|
expect(
|
||||||
|
await convert(
|
||||||
|
{
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
metadata: [
|
||||||
|
{ name: 'aaa', value: 'AAA' },
|
||||||
|
{ enabled: true, name: 'bbb', value: 'BBB' },
|
||||||
|
{ enabled: false, name: 'disabled', value: 'ddd' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
).toEqual([`grpcurl -H 'aaa: AAA'`, `-H 'bbb: BBB'`, `yaak.app`].join(` \\\n `));
|
||||||
|
});
|
||||||
|
test('Single proto file', async () => {
|
||||||
|
expect(await convert({ url: 'https://yaak.app' }, ['/foo/bar/baz.proto'])).toEqual(
|
||||||
|
[
|
||||||
|
`grpcurl -import-path '/foo/bar'`,
|
||||||
|
`-import-path '/foo'`,
|
||||||
|
`-proto '/foo/bar/baz.proto'`,
|
||||||
|
`yaak.app`,
|
||||||
|
].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('Multiple proto files, same dir', async () => {
|
||||||
|
expect(
|
||||||
|
await convert({ url: 'https://yaak.app' }, ['/foo/bar/aaa.proto', '/foo/bar/bbb.proto']),
|
||||||
|
).toEqual(
|
||||||
|
[
|
||||||
|
`grpcurl -import-path '/foo/bar'`,
|
||||||
|
`-import-path '/foo'`,
|
||||||
|
`-proto '/foo/bar/aaa.proto'`,
|
||||||
|
`-proto '/foo/bar/bbb.proto'`,
|
||||||
|
`yaak.app`,
|
||||||
|
].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('Multiple proto files, different dir', async () => {
|
||||||
|
expect(
|
||||||
|
await convert({ url: 'https://yaak.app' }, ['/aaa/bbb/ccc.proto', '/xxx/yyy/zzz.proto']),
|
||||||
|
).toEqual(
|
||||||
|
[
|
||||||
|
`grpcurl -import-path '/aaa/bbb'`,
|
||||||
|
`-import-path '/aaa'`,
|
||||||
|
`-import-path '/xxx/yyy'`,
|
||||||
|
`-import-path '/xxx'`,
|
||||||
|
`-proto '/aaa/bbb/ccc.proto'`,
|
||||||
|
`-proto '/xxx/yyy/zzz.proto'`,
|
||||||
|
`yaak.app`,
|
||||||
|
].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('Single include dir', async () => {
|
||||||
|
expect(await convert({ url: 'https://yaak.app' }, ['/aaa/bbb'])).toEqual(
|
||||||
|
[`grpcurl -import-path '/aaa/bbb'`, `yaak.app`].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('Multiple include dir', async () => {
|
||||||
|
expect(await convert({ url: 'https://yaak.app' }, ['/aaa/bbb', '/xxx/yyy'])).toEqual(
|
||||||
|
[`grpcurl -import-path '/aaa/bbb'`, `-import-path '/xxx/yyy'`, `yaak.app`].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('Mixed proto and dirs', async () => {
|
||||||
|
expect(
|
||||||
|
await convert({ url: 'https://yaak.app' }, ['/aaa/bbb', '/xxx/yyy', '/foo/bar.proto']),
|
||||||
|
).toEqual(
|
||||||
|
[
|
||||||
|
`grpcurl -import-path '/aaa/bbb'`,
|
||||||
|
`-import-path '/xxx/yyy'`,
|
||||||
|
`-import-path '/foo'`,
|
||||||
|
`-import-path '/'`,
|
||||||
|
`-proto '/foo/bar.proto'`,
|
||||||
|
`yaak.app`,
|
||||||
|
].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('Sends data', async () => {
|
||||||
|
expect(
|
||||||
|
await convert(
|
||||||
|
{
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
message: JSON.stringify({ foo: 'bar', baz: 1.0 }, null, 2),
|
||||||
|
},
|
||||||
|
['/foo.proto'],
|
||||||
|
),
|
||||||
|
).toEqual(
|
||||||
|
[
|
||||||
|
`grpcurl -import-path '/'`,
|
||||||
|
`-proto '/foo.proto'`,
|
||||||
|
`-d '{"foo":"bar","baz":1}'`,
|
||||||
|
`yaak.app`,
|
||||||
|
].join(` \\\n `),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsonwebtoken": "^9.0.2"
|
"jsonwebtoken": "^9.0.2"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsonpath-plus": "^10.3.0"
|
"jsonpath-plus": "^10.3.0"
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xmldom/xmldom": "^0.8.10",
|
"@xmldom/xmldom": "^0.8.10",
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"shell-quote": "^1.8.1"
|
"shell-quote": "^1.8.1"
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"yaml": "^2.4.2"
|
"yaml": "^2.4.2"
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"openapi-to-postmanv2": "^5.0.0",
|
"openapi-to-postmanv2": "^5.0.0",
|
||||||
|
|||||||
@@ -1,32 +1,23 @@
|
|||||||
import { Context, Environment, Folder, HttpRequest, PluginDefinition, Workspace } from '@yaakapp/api';
|
import { convertPostman } from '@yaak/importer-postman/src';
|
||||||
|
import type { Context, PluginDefinition } from '@yaakapp/api';
|
||||||
|
import type { ImportPluginResponse } from '@yaakapp/api/lib/plugins/ImporterPlugin';
|
||||||
import { convert } from 'openapi-to-postmanv2';
|
import { convert } from 'openapi-to-postmanv2';
|
||||||
import { convertPostman } from '@yaakapp/importer-postman/src';
|
|
||||||
|
|
||||||
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
|
||||||
|
|
||||||
interface ExportResources {
|
|
||||||
workspaces: AtLeast<Workspace, 'name' | 'id' | 'model'>[];
|
|
||||||
environments: AtLeast<Environment, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
httpRequests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
folders: AtLeast<Folder, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
importer: {
|
importer: {
|
||||||
name: 'OpenAPI',
|
name: 'OpenAPI',
|
||||||
description: 'Import OpenAPI collections',
|
description: 'Import OpenAPI collections',
|
||||||
onImport(_ctx: Context, args: { text: string }) {
|
onImport(_ctx: Context, args: { text: string }) {
|
||||||
return convertOpenApi(args.text) as any;
|
return convertOpenApi(args.text);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function convertOpenApi(
|
export async function convertOpenApi(contents: string): Promise<ImportPluginResponse | undefined> {
|
||||||
contents: string,
|
|
||||||
): Promise<{ resources: ExportResources } | undefined> {
|
|
||||||
let postmanCollection;
|
let postmanCollection;
|
||||||
try {
|
try {
|
||||||
postmanCollection = await new Promise((resolve, reject) => {
|
postmanCollection = await new Promise((resolve, reject) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
convert({ type: 'string', data: contents }, {}, (err, result: any) => {
|
convert({ type: 'string', data: contents }, {}, (err, result: any) => {
|
||||||
if (err != null) reject(err);
|
if (err != null) reject(err);
|
||||||
|
|
||||||
@@ -35,7 +26,7 @@ export async function convertOpenApi(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Probably not an OpenAPI file, so skip it
|
// Probably not an OpenAPI file, so skip it
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"main": "./build/index.js",
|
"main": "./build/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import {
|
import type {
|
||||||
Context,
|
Context,
|
||||||
Environment,
|
Environment,
|
||||||
Folder,
|
Folder,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
HttpRequestHeader,
|
HttpRequestHeader,
|
||||||
HttpUrlParameter,
|
HttpUrlParameter,
|
||||||
|
PartialImportResources,
|
||||||
PluginDefinition,
|
PluginDefinition,
|
||||||
Workspace,
|
Workspace,
|
||||||
} from '@yaakapp/api';
|
} from '@yaakapp/api';
|
||||||
|
import type { ImportPluginResponse } from '@yaakapp/api/lib/plugins/ImporterPlugin';
|
||||||
|
|
||||||
const POSTMAN_2_1_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
|
const POSTMAN_2_1_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
|
||||||
const POSTMAN_2_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
|
const POSTMAN_2_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
|
||||||
@@ -27,19 +29,19 @@ export const plugin: PluginDefinition = {
|
|||||||
name: 'Postman',
|
name: 'Postman',
|
||||||
description: 'Import postman collections',
|
description: 'Import postman collections',
|
||||||
onImport(_ctx: Context, args: { text: string }) {
|
onImport(_ctx: Context, args: { text: string }) {
|
||||||
return convertPostman(args.text) as any;
|
return convertPostman(args.text);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function convertPostman(
|
export function convertPostman(contents: string): ImportPluginResponse | undefined {
|
||||||
contents: string,
|
|
||||||
): { resources: ExportResources } | undefined {
|
|
||||||
const root = parseJSONToRecord(contents);
|
const root = parseJSONToRecord(contents);
|
||||||
if (root == null) return;
|
if (root == null) return;
|
||||||
|
|
||||||
const info = toRecord(root.info);
|
const info = toRecord(root.info);
|
||||||
const isValidSchema = VALID_SCHEMAS.includes(info.schema);
|
const isValidSchema = VALID_SCHEMAS.includes(
|
||||||
|
typeof info.schema === 'string' ? info.schema : 'n/a',
|
||||||
|
);
|
||||||
if (!isValidSchema || !Array.isArray(root.item)) {
|
if (!isValidSchema || !Array.isArray(root.item)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -53,11 +55,17 @@ export function convertPostman(
|
|||||||
folders: [],
|
folders: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rawDescription = info.description;
|
||||||
|
const description =
|
||||||
|
typeof rawDescription === 'object' && rawDescription !== null && 'content' in rawDescription
|
||||||
|
? String(rawDescription.content)
|
||||||
|
: String(rawDescription);
|
||||||
|
|
||||||
const workspace: ExportResources['workspaces'][0] = {
|
const workspace: ExportResources['workspaces'][0] = {
|
||||||
model: 'workspace',
|
model: 'workspace',
|
||||||
id: generateId('workspace'),
|
id: generateId('workspace'),
|
||||||
name: info.name || 'Postman Import',
|
name: info.name ? String(info.name) : 'Postman Import',
|
||||||
description: info.description?.content ?? info.description,
|
description,
|
||||||
};
|
};
|
||||||
exportResources.workspaces.push(workspace);
|
exportResources.workspaces.push(workspace);
|
||||||
|
|
||||||
@@ -68,14 +76,14 @@ export function convertPostman(
|
|||||||
name: 'Global Variables',
|
name: 'Global Variables',
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
variables:
|
variables:
|
||||||
root.variable?.map((v: any) => ({
|
toArray<{ key: string; value: string }>(root.variable).map((v) => ({
|
||||||
name: v.key,
|
name: v.key,
|
||||||
value: v.value,
|
value: v.value,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
};
|
};
|
||||||
exportResources.environments.push(environment);
|
exportResources.environments.push(environment);
|
||||||
|
|
||||||
const importItem = (v: Record<string, any>, folderId: string | null = null) => {
|
const importItem = (v: Record<string, unknown>, folderId: string | null = null) => {
|
||||||
if (typeof v.name === 'string' && Array.isArray(v.item)) {
|
if (typeof v.name === 'string' && Array.isArray(v.item)) {
|
||||||
const folder: ExportResources['folders'][0] = {
|
const folder: ExportResources['folders'][0] = {
|
||||||
model: 'folder',
|
model: 'folder',
|
||||||
@@ -94,7 +102,11 @@ export function convertPostman(
|
|||||||
const requestAuthPath = importAuth(r.auth);
|
const requestAuthPath = importAuth(r.auth);
|
||||||
const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath;
|
const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath;
|
||||||
|
|
||||||
const headers: HttpRequestHeader[] = toArray(r.header).map((h) => {
|
const headers: HttpRequestHeader[] = toArray<{
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>(r.header).map((h) => {
|
||||||
return {
|
return {
|
||||||
name: h.key,
|
name: h.key,
|
||||||
value: h.value,
|
value: h.value,
|
||||||
@@ -104,7 +116,9 @@ export function convertPostman(
|
|||||||
|
|
||||||
// Add body headers only if they don't already exist
|
// Add body headers only if they don't already exist
|
||||||
for (const bodyPatchHeader of bodyPatch.headers) {
|
for (const bodyPatchHeader of bodyPatch.headers) {
|
||||||
const existingHeader = headers.find(h => h.name.toLowerCase() === bodyPatchHeader.name.toLowerCase());
|
const existingHeader = headers.find(
|
||||||
|
(h) => h.name.toLowerCase() === bodyPatchHeader.name.toLowerCase(),
|
||||||
|
);
|
||||||
if (existingHeader) {
|
if (existingHeader) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -119,8 +133,8 @@ export function convertPostman(
|
|||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
folderId,
|
folderId,
|
||||||
name: v.name,
|
name: v.name,
|
||||||
description: v.description || undefined,
|
description: v.description ? String(v.description) : undefined,
|
||||||
method: r.method || 'GET',
|
method: typeof r.method === 'string' ? r.method : 'GET',
|
||||||
url,
|
url,
|
||||||
urlParameters,
|
urlParameters,
|
||||||
body: bodyPatch.body,
|
body: bodyPatch.body,
|
||||||
@@ -139,17 +153,19 @@ export function convertPostman(
|
|||||||
importItem(item);
|
importItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resources = deleteUndefinedAttrs(convertTemplateSyntax(exportResources));
|
const resources = deleteUndefinedAttrs(
|
||||||
|
convertTemplateSyntax(exportResources),
|
||||||
|
) as PartialImportResources;
|
||||||
|
|
||||||
return { resources };
|
return { resources };
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters'> {
|
function convertUrl(rawUrl: string | unknown): Pick<HttpRequest, 'url' | 'urlParameters'> {
|
||||||
if (typeof url === 'string') {
|
if (typeof rawUrl === 'string') {
|
||||||
return { url, urlParameters: [] };
|
return { url: rawUrl, urlParameters: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
url = toRecord(url);
|
const url = toRecord(rawUrl);
|
||||||
|
|
||||||
let v = '';
|
let v = '';
|
||||||
|
|
||||||
@@ -199,10 +215,8 @@ function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters
|
|||||||
return { url: v, urlParameters: params };
|
return { url: v, urlParameters: params };
|
||||||
}
|
}
|
||||||
|
|
||||||
function importAuth(
|
function importAuth(rawAuth: unknown): Pick<HttpRequest, 'authentication' | 'authenticationType'> {
|
||||||
rawAuth: any,
|
const auth = toRecord<{ username?: string; password?: string; token?: string }>(rawAuth);
|
||||||
): Pick<HttpRequest, 'authentication' | 'authenticationType'> {
|
|
||||||
const auth = toRecord(rawAuth);
|
|
||||||
if ('basic' in auth) {
|
if ('basic' in auth) {
|
||||||
return {
|
return {
|
||||||
authenticationType: 'basic',
|
authenticationType: 'basic',
|
||||||
@@ -223,8 +237,22 @@ function importAuth(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
|
function importBody(rawBody: unknown): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
|
||||||
const body = toRecord(rawBody);
|
const body = toRecord(rawBody) as {
|
||||||
|
mode: string;
|
||||||
|
graphql: { query?: string; variables?: string };
|
||||||
|
urlencoded?: { key?: string; value?: string; disabled?: boolean }[];
|
||||||
|
formdata?: {
|
||||||
|
key?: string;
|
||||||
|
value?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
contentType?: string;
|
||||||
|
src?: string;
|
||||||
|
}[];
|
||||||
|
raw?: string;
|
||||||
|
options?: { raw?: { language?: string } };
|
||||||
|
file?: { src?: string };
|
||||||
|
};
|
||||||
if (body.mode === 'graphql') {
|
if (body.mode === 'graphql') {
|
||||||
return {
|
return {
|
||||||
headers: [
|
headers: [
|
||||||
@@ -237,7 +265,10 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
|||||||
bodyType: 'graphql',
|
bodyType: 'graphql',
|
||||||
body: {
|
body: {
|
||||||
text: JSON.stringify(
|
text: JSON.stringify(
|
||||||
{ query: body.graphql.query, variables: parseJSONToRecord(body.graphql.variables) },
|
{
|
||||||
|
query: body.graphql?.query || '',
|
||||||
|
variables: parseJSONToRecord(body.graphql?.variables || '{}'),
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
@@ -254,7 +285,7 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
|||||||
],
|
],
|
||||||
bodyType: 'application/x-www-form-urlencoded',
|
bodyType: 'application/x-www-form-urlencoded',
|
||||||
body: {
|
body: {
|
||||||
form: toArray(body.urlencoded).map((f) => ({
|
form: toArray<NonNullable<typeof body.urlencoded>[0]>(body.urlencoded).map((f) => ({
|
||||||
enabled: !f.disabled,
|
enabled: !f.disabled,
|
||||||
name: f.key ?? '',
|
name: f.key ?? '',
|
||||||
value: f.value ?? '',
|
value: f.value ?? '',
|
||||||
@@ -272,19 +303,19 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
|||||||
],
|
],
|
||||||
bodyType: 'multipart/form-data',
|
bodyType: 'multipart/form-data',
|
||||||
body: {
|
body: {
|
||||||
form: toArray(body.formdata).map((f) =>
|
form: toArray<NonNullable<typeof body.formdata>[0]>(body.formdata).map((f) =>
|
||||||
f.src != null
|
f.src != null
|
||||||
? {
|
? {
|
||||||
enabled: !f.disabled,
|
enabled: !f.disabled,
|
||||||
contentType: f.contentType ?? null,
|
contentType: f.contentType ?? null,
|
||||||
name: f.key ?? '',
|
name: f.key ?? '',
|
||||||
file: f.src ?? '',
|
file: f.src ?? '',
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
enabled: !f.disabled,
|
enabled: !f.disabled,
|
||||||
name: f.key ?? '',
|
name: f.key ?? '',
|
||||||
value: f.value ?? '',
|
value: f.value ?? '',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -315,21 +346,23 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseJSONToRecord(jsonStr: string): Record<string, any> | null {
|
function parseJSONToRecord<T>(jsonStr: string): Record<string, T> | null {
|
||||||
try {
|
try {
|
||||||
return toRecord(JSON.parse(jsonStr));
|
return toRecord(JSON.parse(jsonStr));
|
||||||
} catch (err) {
|
} catch {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toRecord(value: any): Record<string, any> {
|
function toRecord<T>(value: Record<string, T> | unknown): Record<string, T> {
|
||||||
if (Object.prototype.toString.call(value) === '[object Object]') return value;
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||||
else return {};
|
return value as Record<string, T>;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function toArray(value: any): any[] {
|
function toArray<T>(value: unknown): T[] {
|
||||||
if (Object.prototype.toString.call(value) === '[object Array]') return value;
|
if (Object.prototype.toString.call(value) === '[object Array]') return value as T[];
|
||||||
else return [];
|
else return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.js",
|
"build": "yaakcli build ./src/index.js",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
templateFunctions: [
|
templateFunctions: [
|
||||||
@@ -7,7 +7,7 @@ export const plugin: PluginDefinition = {
|
|||||||
description: 'Encode a value to base64',
|
description: 'Encode a value to base64',
|
||||||
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
|
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
|
||||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
return Buffer.from(args.values.value ?? '').toString('base64');
|
return Buffer.from(String(args.values.value ?? '')).toString('base64');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ export const plugin: PluginDefinition = {
|
|||||||
description: 'Decode a value from base64',
|
description: 'Decode a value from base64',
|
||||||
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
|
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
|
||||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
return Buffer.from(args.values.value ?? '', 'base64').toString('utf-8');
|
return Buffer.from(String(args.values.value ?? ''), 'base64').toString('utf-8');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,7 @@ export const plugin: PluginDefinition = {
|
|||||||
description: 'Encode a value for use in a URL (percent-encoding)',
|
description: 'Encode a value for use in a URL (percent-encoding)',
|
||||||
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
|
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
|
||||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
return encodeURIComponent(args.values.value ?? '');
|
return encodeURIComponent(String(args.values.value ?? ''));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -32,7 +32,7 @@ export const plugin: PluginDefinition = {
|
|||||||
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
|
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
|
||||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
return decodeURIComponent(args.values.value ?? '');
|
return decodeURIComponent(String(args.values.value ?? ''));
|
||||||
} catch {
|
} catch {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
templateFunctions: [{
|
templateFunctions: [
|
||||||
name: 'fs.readFile',
|
{
|
||||||
description: 'Read the contents of a file as utf-8',
|
name: 'fs.readFile',
|
||||||
args: [{ title: 'Select File', type: 'file', name: 'path', label: 'File' }],
|
description: 'Read the contents of a file as utf-8',
|
||||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
args: [{ title: 'Select File', type: 'file', name: 'path', label: 'File' }],
|
||||||
if (!args.values.path) return null;
|
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
|
if (!args.values.path) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return fs.promises.readFile(args.values.path, 'utf-8');
|
return fs.promises.readFile(String(args.values.path ?? ''), 'utf-8');
|
||||||
} catch (err) {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsonpath-plus": "^10.3.0"
|
"jsonpath-plus": "^10.3.0"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
templateFunctions: [{
|
templateFunctions: [{
|
||||||
@@ -15,10 +15,10 @@ export const plugin: PluginDefinition = {
|
|||||||
|
|
||||||
return await ctx.prompt.text({
|
return await ctx.prompt.text({
|
||||||
id: `prompt-${args.values.label}`,
|
id: `prompt-${args.values.label}`,
|
||||||
label: args.values.title ?? '',
|
label: String(args.values.title ?? ''),
|
||||||
title: args.values.title ?? '',
|
title: String(args.values.title ?? ''),
|
||||||
defaultValue: args.values.defaultValue,
|
defaultValue: String(args.values.defaultValue),
|
||||||
placeholder: args.values.placeholder,
|
placeholder: String(args.values.placeholder),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,32 @@
|
|||||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
templateFunctions: [{
|
templateFunctions: [
|
||||||
name: 'regex.match',
|
{
|
||||||
description: 'Extract',
|
name: 'regex.match',
|
||||||
args: [
|
description: 'Extract',
|
||||||
{
|
args: [
|
||||||
type: 'text',
|
{
|
||||||
name: 'regex',
|
type: 'text',
|
||||||
label: 'Regular Expression',
|
name: 'regex',
|
||||||
placeholder: '^\w+=(?<value>\w*)$',
|
label: 'Regular Expression',
|
||||||
defaultValue: '^(.*)$',
|
placeholder: '^\\w+=(?<value>\\w*)$',
|
||||||
description: 'A JavaScript regular expression, evaluated using the Node.js RegExp engine. Capture groups or named groups can be used to extract values.',
|
defaultValue: '^(.*)$',
|
||||||
},
|
description:
|
||||||
{ type: 'text', name: 'input', label: 'Input Text', multiLine: true },
|
'A JavaScript regular expression, evaluated using the Node.js RegExp engine. Capture groups or named groups can be used to extract values.',
|
||||||
],
|
},
|
||||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
{ type: 'text', name: 'input', label: 'Input Text', multiLine: true },
|
||||||
if (!args.values.regex) return '';
|
],
|
||||||
|
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
|
if (!args.values.regex || !args.values.input) return '';
|
||||||
|
|
||||||
const regex = new RegExp(String(args.values.regex));
|
const input = String(args.values.input);
|
||||||
const match = args.values.input?.match(regex);
|
const regex = new RegExp(String(args.values.regex));
|
||||||
return match?.groups
|
const match = input.match(regex);
|
||||||
? Object.values(match.groups)[0] ?? ''
|
return match?.groups
|
||||||
: match?.[1] ?? match?.[0] ?? '';
|
? (Object.values(match.groups)[0] ?? '')
|
||||||
|
: (match?.[1] ?? match?.[0] ?? '');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||||
|
|
||||||
export const plugin: PluginDefinition = {
|
export const plugin: PluginDefinition = {
|
||||||
templateFunctions: [
|
templateFunctions: [
|
||||||
{
|
{
|
||||||
name: 'request.body',
|
name: 'request.body',
|
||||||
args: [{
|
args: [
|
||||||
name: 'requestId',
|
{
|
||||||
label: 'Http Request',
|
name: 'requestId',
|
||||||
type: 'http_request',
|
label: 'Http Request',
|
||||||
}],
|
type: 'http_request',
|
||||||
|
},
|
||||||
|
],
|
||||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
const httpRequest = await ctx.httpRequest.getById({ id: args.values.requestId ?? 'n/a' });
|
const requestId = String(args.values.requestId ?? 'n/a');
|
||||||
|
const httpRequest = await ctx.httpRequest.getById({ id: requestId });
|
||||||
if (httpRequest == null) return null;
|
if (httpRequest == null) return null;
|
||||||
return String(await ctx.templates.render({
|
return String(
|
||||||
data: httpRequest.body?.text ?? '',
|
await ctx.templates.render({
|
||||||
purpose: args.purpose,
|
data: httpRequest.body?.text ?? '',
|
||||||
}));
|
purpose: args.purpose,
|
||||||
|
}),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -30,15 +35,22 @@ export const plugin: PluginDefinition = {
|
|||||||
name: 'header',
|
name: 'header',
|
||||||
label: 'Header Name',
|
label: 'Header Name',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
const httpRequest = await ctx.httpRequest.getById({ id: args.values.requestId ?? 'n/a' });
|
const headerName = String(args.values.header ?? '');
|
||||||
|
const requestId = String(args.values.requestId ?? 'n/a');
|
||||||
|
const httpRequest = await ctx.httpRequest.getById({ id: requestId });
|
||||||
if (httpRequest == null) return null;
|
if (httpRequest == null) return null;
|
||||||
const header = httpRequest.headers.find(h => h.name.toLowerCase() === args.values.header?.toLowerCase());
|
const header = httpRequest.headers.find(
|
||||||
return String(await ctx.templates.render({
|
(h) => h.name.toLowerCase() === headerName.toLowerCase(),
|
||||||
data: header?.value ?? '',
|
);
|
||||||
purpose: args.purpose,
|
return String(
|
||||||
}));
|
await ctx.templates.render({
|
||||||
|
data: header?.value ?? '',
|
||||||
|
purpose: args.purpose,
|
||||||
|
}),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsonpath-plus": "^10.3.0",
|
"jsonpath-plus": "^10.3.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DOMParser } from '@xmldom/xmldom';
|
import { DOMParser } from '@xmldom/xmldom';
|
||||||
import {
|
import type {
|
||||||
CallTemplateFunctionArgs,
|
CallTemplateFunctionArgs,
|
||||||
Context,
|
Context,
|
||||||
FormInput,
|
FormInput,
|
||||||
@@ -47,14 +47,14 @@ export const plugin: PluginDefinition = {
|
|||||||
if (!args.values.request || !args.values.header) return null;
|
if (!args.values.request || !args.values.header) return null;
|
||||||
|
|
||||||
const response = await getResponse(ctx, {
|
const response = await getResponse(ctx, {
|
||||||
requestId: args.values.request,
|
requestId: String(args.values.request || ''),
|
||||||
purpose: args.purpose,
|
purpose: args.purpose,
|
||||||
behavior: args.values.behavior ?? null,
|
behavior: args.values.behavior ? String(args.values.behavior) : null,
|
||||||
});
|
});
|
||||||
if (response == null) return null;
|
if (response == null) return null;
|
||||||
|
|
||||||
const header = response.headers.find(
|
const header = response.headers.find(
|
||||||
h => h.name.toLowerCase() === String(args.values.header ?? '').toLowerCase(),
|
(h) => h.name.toLowerCase() === String(args.values.header ?? '').toLowerCase(),
|
||||||
);
|
);
|
||||||
return header?.value ?? null;
|
return header?.value ?? null;
|
||||||
},
|
},
|
||||||
@@ -77,9 +77,9 @@ export const plugin: PluginDefinition = {
|
|||||||
if (!args.values.request || !args.values.path) return null;
|
if (!args.values.request || !args.values.path) return null;
|
||||||
|
|
||||||
const response = await getResponse(ctx, {
|
const response = await getResponse(ctx, {
|
||||||
requestId: args.values.request,
|
requestId: String(args.values.request || ''),
|
||||||
purpose: args.purpose,
|
purpose: args.purpose,
|
||||||
behavior: args.values.behavior ?? null,
|
behavior: args.values.behavior ? String(args.values.behavior) : null,
|
||||||
});
|
});
|
||||||
if (response == null) return null;
|
if (response == null) return null;
|
||||||
|
|
||||||
@@ -90,19 +90,19 @@ export const plugin: PluginDefinition = {
|
|||||||
let body;
|
let body;
|
||||||
try {
|
try {
|
||||||
body = readFileSync(response.bodyPath, 'utf-8');
|
body = readFileSync(response.bodyPath, 'utf-8');
|
||||||
} catch (_) {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return filterJSONPath(body, args.values.path);
|
return filterJSONPath(body, String(args.values.path || ''));
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Probably not JSON, try XPath
|
// Probably not JSON, try XPath
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return filterXPath(body, args.values.path);
|
return filterXPath(body, String(args.values.path || ''));
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Probably not XML
|
// Probably not XML
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,17 +113,14 @@ export const plugin: PluginDefinition = {
|
|||||||
name: 'response.body.raw',
|
name: 'response.body.raw',
|
||||||
description: 'Access the entire response body, as text',
|
description: 'Access the entire response body, as text',
|
||||||
aliases: ['response'],
|
aliases: ['response'],
|
||||||
args: [
|
args: [requestArg, behaviorArg],
|
||||||
requestArg,
|
|
||||||
behaviorArg,
|
|
||||||
],
|
|
||||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||||
if (!args.values.request) return null;
|
if (!args.values.request) return null;
|
||||||
|
|
||||||
const response = await getResponse(ctx, {
|
const response = await getResponse(ctx, {
|
||||||
requestId: args.values.request,
|
requestId: String(args.values.request || ''),
|
||||||
purpose: args.purpose,
|
purpose: args.purpose,
|
||||||
behavior: args.values.behavior ?? null,
|
behavior: args.values.behavior ? String(args.values.behavior) : null,
|
||||||
});
|
});
|
||||||
if (response == null) return null;
|
if (response == null) return null;
|
||||||
|
|
||||||
@@ -134,7 +131,7 @@ export const plugin: PluginDefinition = {
|
|||||||
let body;
|
let body;
|
||||||
try {
|
try {
|
||||||
body = readFileSync(response.bodyPath, 'utf-8');
|
body = readFileSync(response.bodyPath, 'utf-8');
|
||||||
} catch (_) {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +170,18 @@ function filterXPath(body: string, path: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getResponse(ctx: Context, { requestId, behavior, purpose }: {
|
async function getResponse(
|
||||||
requestId: string,
|
ctx: Context,
|
||||||
behavior: string | null,
|
{
|
||||||
purpose: RenderPurpose,
|
requestId,
|
||||||
}): Promise<HttpResponse | null> {
|
behavior,
|
||||||
|
purpose,
|
||||||
|
}: {
|
||||||
|
requestId: string;
|
||||||
|
behavior: string | null;
|
||||||
|
purpose: RenderPurpose;
|
||||||
|
},
|
||||||
|
): Promise<HttpResponse | null> {
|
||||||
if (!requestId) return null;
|
if (!requestId) return null;
|
||||||
|
|
||||||
const httpRequest = await ctx.httpRequest.getById({ id: requestId ?? 'n/a' });
|
const httpRequest = await ctx.httpRequest.getById({ id: requestId ?? 'n/a' });
|
||||||
@@ -195,9 +199,7 @@ async function getResponse(ctx: Context, { requestId, behavior, purpose }: {
|
|||||||
|
|
||||||
// Previews happen a ton, and we don't want to send too many times on "always," so treat
|
// Previews happen a ton, and we don't want to send too many times on "always," so treat
|
||||||
// it as "smart" during preview.
|
// it as "smart" during preview.
|
||||||
let finalBehavior = (behavior === 'always' && purpose === 'preview')
|
const finalBehavior = behavior === 'always' && purpose === 'preview' ? 'smart' : behavior;
|
||||||
? 'smart'
|
|
||||||
: behavior;
|
|
||||||
|
|
||||||
// Send if no responses and "smart," or "always"
|
// Send if no responses and "smart," or "always"
|
||||||
if ((finalBehavior === 'smart' && response == null) || finalBehavior === 'always') {
|
if ((finalBehavior === 'smart' && response == null) || finalBehavior === 'always') {
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0"
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xmldom/xmldom": "^0.8.10",
|
"@xmldom/xmldom": "^0.8.10",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yaakcli build ./src/index.ts",
|
"build": "yaakcli build ./src/index.ts",
|
||||||
"dev": "yaakcli dev ./src/index.js"
|
"dev": "yaakcli dev ./src/index.js",
|
||||||
|
"lint": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ use yaak_models::models::{
|
|||||||
use yaak_models::query_manager::QueryManagerExt;
|
use yaak_models::query_manager::QueryManagerExt;
|
||||||
use yaak_models::util::{BatchUpsertResult, UpdateSource, get_workspace_export_resources};
|
use yaak_models::util::{BatchUpsertResult, UpdateSource, get_workspace_export_resources};
|
||||||
use yaak_plugins::events::{
|
use yaak_plugins::events::{
|
||||||
CallHttpRequestActionRequest, FilterResponse, GetHttpAuthenticationConfigResponse,
|
CallGrpcRequestActionRequest, CallHttpRequestActionRequest, FilterResponse,
|
||||||
|
GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse,
|
||||||
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
|
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
|
||||||
GetTemplateFunctionsResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
|
GetTemplateFunctionsResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
|
||||||
PluginWindowContext, RenderPurpose,
|
PluginWindowContext, RenderPurpose,
|
||||||
@@ -791,6 +792,14 @@ 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_grpc_request_actions<R: Runtime>(
|
||||||
|
window: WebviewWindow<R>,
|
||||||
|
plugin_manager: State<'_, PluginManager>,
|
||||||
|
) -> YaakResult<Vec<GetGrpcRequestActionsResponse>> {
|
||||||
|
Ok(plugin_manager.get_grpc_request_actions(&window).await?)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_template_functions<R: Runtime>(
|
async fn cmd_template_functions<R: Runtime>(
|
||||||
window: WebviewWindow<R>,
|
window: WebviewWindow<R>,
|
||||||
@@ -830,6 +839,15 @@ async fn cmd_call_http_request_action<R: Runtime>(
|
|||||||
Ok(plugin_manager.call_http_request_action(&window, req).await?)
|
Ok(plugin_manager.call_http_request_action(&window, req).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn cmd_call_grpc_request_action<R: Runtime>(
|
||||||
|
window: WebviewWindow<R>,
|
||||||
|
req: CallGrpcRequestActionRequest,
|
||||||
|
plugin_manager: State<'_, PluginManager>,
|
||||||
|
) -> YaakResult<()> {
|
||||||
|
Ok(plugin_manager.call_grpc_request_action(&window, req).await?)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_call_http_authentication_action<R: Runtime>(
|
async fn cmd_call_http_authentication_action<R: Runtime>(
|
||||||
window: WebviewWindow<R>,
|
window: WebviewWindow<R>,
|
||||||
@@ -1220,6 +1238,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_grpc_request_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,
|
||||||
@@ -1236,6 +1255,7 @@ pub fn run() {
|
|||||||
cmd_get_workspace_meta,
|
cmd_get_workspace_meta,
|
||||||
cmd_grpc_go,
|
cmd_grpc_go,
|
||||||
cmd_grpc_reflect,
|
cmd_grpc_reflect,
|
||||||
|
cmd_grpc_request_actions,
|
||||||
cmd_http_request_actions,
|
cmd_http_request_actions,
|
||||||
cmd_import_data,
|
cmd_import_data,
|
||||||
cmd_install_plugin,
|
cmd_install_plugin,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::http_request::send_http_request;
|
use crate::http_request::send_http_request;
|
||||||
use crate::render::{render_http_request, render_json_value};
|
use crate::render::{render_grpc_request, render_http_request, render_json_value};
|
||||||
use crate::window::{CreateWindowConfig, create_window};
|
use crate::window::{create_window, CreateWindowConfig};
|
||||||
use crate::{
|
use crate::{
|
||||||
call_frontend, cookie_jar_from_window, environment_from_window, get_window_from_window_context,
|
call_frontend, cookie_jar_from_window, environment_from_window, get_window_from_window_context,
|
||||||
workspace_from_window,
|
workspace_from_window,
|
||||||
@@ -13,13 +13,7 @@ use tauri_plugin_clipboard_manager::ClipboardExt;
|
|||||||
use yaak_models::models::{HttpResponse, Plugin};
|
use yaak_models::models::{HttpResponse, Plugin};
|
||||||
use yaak_models::query_manager::QueryManagerExt;
|
use yaak_models::query_manager::QueryManagerExt;
|
||||||
use yaak_models::util::UpdateSource;
|
use yaak_models::util::UpdateSource;
|
||||||
use yaak_plugins::events::{
|
use yaak_plugins::events::{Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload, ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse, RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest, TemplateRenderResponse, WindowNavigateEvent};
|
||||||
Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse,
|
|
||||||
GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload,
|
|
||||||
ListCookieNamesResponse, PluginWindowContext, RenderHttpRequestResponse,
|
|
||||||
SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest, TemplateRenderResponse,
|
|
||||||
WindowNavigateEvent,
|
|
||||||
};
|
|
||||||
use yaak_plugins::manager::PluginManager;
|
use yaak_plugins::manager::PluginManager;
|
||||||
use yaak_plugins::plugin_handle::PluginHandle;
|
use yaak_plugins::plugin_handle::PluginHandle;
|
||||||
use yaak_plugins::template_callback::PluginTemplateCallback;
|
use yaak_plugins::template_callback::PluginTemplateCallback;
|
||||||
@@ -68,6 +62,30 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
|||||||
http_request,
|
http_request,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
InternalEventPayload::RenderGrpcRequestRequest(req) => {
|
||||||
|
let window = get_window_from_window_context(app_handle, &window_context)
|
||||||
|
.expect("Failed to find window for render grpc request");
|
||||||
|
|
||||||
|
let workspace =
|
||||||
|
workspace_from_window(&window).expect("Failed to get workspace_id from window URL");
|
||||||
|
let environment = environment_from_window(&window);
|
||||||
|
let base_environment = app_handle
|
||||||
|
.db()
|
||||||
|
.get_base_environment(&workspace.id)
|
||||||
|
.expect("Failed to get base environment");
|
||||||
|
let cb = PluginTemplateCallback::new(app_handle, &window_context, req.purpose);
|
||||||
|
let grpc_request = render_grpc_request(
|
||||||
|
&req.grpc_request,
|
||||||
|
&base_environment,
|
||||||
|
environment.as_ref(),
|
||||||
|
&cb,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Failed to render grpc request");
|
||||||
|
Some(InternalEventPayload::RenderGrpcRequestResponse(RenderGrpcRequestResponse {
|
||||||
|
grpc_request,
|
||||||
|
}))
|
||||||
|
}
|
||||||
InternalEventPayload::RenderHttpRequestRequest(req) => {
|
InternalEventPayload::RenderHttpRequestRequest(req) => {
|
||||||
let window = get_window_from_window_context(app_handle, &window_context)
|
let window = get_window_from_window_context(app_handle, &window_context)
|
||||||
.expect("Failed to find window for render http request");
|
.expect("Failed to find window for render http request");
|
||||||
|
|||||||
@@ -47,9 +47,14 @@ pub async fn fill_pool_from_files(
|
|||||||
];
|
];
|
||||||
|
|
||||||
for p in paths {
|
for p in paths {
|
||||||
if p.as_path().exists() {
|
if !p.exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dirs are added as includes
|
||||||
|
if p.is_dir() {
|
||||||
|
args.push("-I".to_string());
|
||||||
args.push(p.to_string_lossy().to_string());
|
args.push(p.to_string_lossy().to_string());
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +67,8 @@ pub async fn fill_pool_from_files(
|
|||||||
} else {
|
} else {
|
||||||
debug!("ignoring {:?} since it does not exist.", parent)
|
debug!("ignoring {:?} since it does not exist.", parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args.push(p.to_string_lossy().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let out = app_handle
|
let out = app_handle
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ export type BootRequest = { dir: string, watch: boolean, };
|
|||||||
|
|
||||||
export type BootResponse = { name: string, version: string, };
|
export type BootResponse = { name: string, version: string, };
|
||||||
|
|
||||||
|
export type CallGrpcRequestActionArgs = { grpcRequest: GrpcRequest, protoFiles: Array<string>, };
|
||||||
|
|
||||||
|
export type CallGrpcRequestActionRequest = { index: number, pluginRefId: string, args: CallGrpcRequestActionArgs, };
|
||||||
|
|
||||||
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
||||||
|
|
||||||
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
|
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
|
||||||
@@ -336,14 +340,14 @@ export type GetCookieValueRequest = { name: string, };
|
|||||||
|
|
||||||
export type GetCookieValueResponse = { value: string | null, };
|
export type GetCookieValueResponse = { value: string | null, };
|
||||||
|
|
||||||
|
export type GetGrpcRequestActionsResponse = { actions: Array<GrpcRequestAction>, pluginRefId: string, };
|
||||||
|
|
||||||
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
||||||
|
|
||||||
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
|
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
|
||||||
|
|
||||||
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
|
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
|
||||||
|
|
||||||
export type GetHttpRequestActionsRequest = Record<string, never>;
|
|
||||||
|
|
||||||
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
|
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
|
||||||
|
|
||||||
export type GetHttpRequestByIdRequest = { id: string, };
|
export type GetHttpRequestByIdRequest = { id: string, };
|
||||||
@@ -360,6 +364,8 @@ export type GetThemesRequest = Record<string, never>;
|
|||||||
|
|
||||||
export type GetThemesResponse = { themes: Array<Theme>, };
|
export type GetThemesResponse = { themes: Array<Theme>, };
|
||||||
|
|
||||||
|
export type GrpcRequestAction = { label: string, icon?: Icon, };
|
||||||
|
|
||||||
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
|
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
|
||||||
|
|
||||||
export type HttpHeader = { name: string, value: string, };
|
export type HttpHeader = { name: string, value: string, };
|
||||||
@@ -376,7 +382,7 @@ export type ImportResponse = { resources: ImportResources, };
|
|||||||
|
|
||||||
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: PluginWindowContext, payload: InternalEventPayload, };
|
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: PluginWindowContext, payload: InternalEventPayload, };
|
||||||
|
|
||||||
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & BootResponse | { "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": "list_cookie_names_request" } & ListCookieNamesRequest | { "type": "list_cookie_names_response" } & ListCookieNamesResponse | { "type": "get_cookie_value_request" } & GetCookieValueRequest | { "type": "get_cookie_value_response" } & GetCookieValueResponse | { "type": "get_http_request_actions_request" } & EmptyPayload | { "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": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "type": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "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": "get_themes_request" } & GetThemesRequest | { "type": "get_themes_response" } & GetThemesResponse | { "type": "empty_response" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
|
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & BootResponse | { "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": "list_cookie_names_request" } & ListCookieNamesRequest | { "type": "list_cookie_names_response" } & ListCookieNamesResponse | { "type": "get_cookie_value_request" } & GetCookieValueRequest | { "type": "get_cookie_value_response" } & GetCookieValueResponse | { "type": "get_http_request_actions_request" } & EmptyPayload | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_grpc_request_actions_request" } & EmptyPayload | { "type": "get_grpc_request_actions_response" } & GetGrpcRequestActionsResponse | { "type": "call_grpc_request_action_request" } & CallGrpcRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "render_grpc_request_request" } & RenderGrpcRequestRequest | { "type": "render_grpc_request_response" } & RenderGrpcRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "type": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "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": "get_themes_request" } & GetThemesRequest | { "type": "get_themes_response" } & GetThemesResponse | { "type": "empty_response" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
|
||||||
|
|
||||||
export type JsonPrimitive = string | number | boolean | null;
|
export type JsonPrimitive = string | number | boolean | null;
|
||||||
|
|
||||||
@@ -408,6 +414,10 @@ required?: boolean, };
|
|||||||
|
|
||||||
export type PromptTextResponse = { value: string | null, };
|
export type PromptTextResponse = { value: string | null, };
|
||||||
|
|
||||||
|
export type RenderGrpcRequestRequest = { grpcRequest: GrpcRequest, purpose: RenderPurpose, };
|
||||||
|
|
||||||
|
export type RenderGrpcRequestResponse = { grpcRequest: GrpcRequest, };
|
||||||
|
|
||||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
||||||
|
|
||||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
||||||
|
|||||||
@@ -89,11 +89,16 @@ pub enum InternalEventPayload {
|
|||||||
GetCookieValueRequest(GetCookieValueRequest),
|
GetCookieValueRequest(GetCookieValueRequest),
|
||||||
GetCookieValueResponse(GetCookieValueResponse),
|
GetCookieValueResponse(GetCookieValueResponse),
|
||||||
|
|
||||||
// Request Actions
|
// HTTP Request Actions
|
||||||
GetHttpRequestActionsRequest(EmptyPayload),
|
GetHttpRequestActionsRequest(EmptyPayload),
|
||||||
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
|
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
|
||||||
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
|
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
|
||||||
|
|
||||||
|
// Grpc Request Actions
|
||||||
|
GetGrpcRequestActionsRequest(EmptyPayload),
|
||||||
|
GetGrpcRequestActionsResponse(GetGrpcRequestActionsResponse),
|
||||||
|
CallGrpcRequestActionRequest(CallGrpcRequestActionRequest),
|
||||||
|
|
||||||
// Template Functions
|
// Template Functions
|
||||||
GetTemplateFunctionsRequest,
|
GetTemplateFunctionsRequest,
|
||||||
GetTemplateFunctionsResponse(GetTemplateFunctionsResponse),
|
GetTemplateFunctionsResponse(GetTemplateFunctionsResponse),
|
||||||
@@ -116,6 +121,9 @@ pub enum InternalEventPayload {
|
|||||||
RenderHttpRequestRequest(RenderHttpRequestRequest),
|
RenderHttpRequestRequest(RenderHttpRequestRequest),
|
||||||
RenderHttpRequestResponse(RenderHttpRequestResponse),
|
RenderHttpRequestResponse(RenderHttpRequestResponse),
|
||||||
|
|
||||||
|
RenderGrpcRequestRequest(RenderGrpcRequestRequest),
|
||||||
|
RenderGrpcRequestResponse(RenderGrpcRequestResponse),
|
||||||
|
|
||||||
GetKeyValueRequest(GetKeyValueRequest),
|
GetKeyValueRequest(GetKeyValueRequest),
|
||||||
GetKeyValueResponse(GetKeyValueResponse),
|
GetKeyValueResponse(GetKeyValueResponse),
|
||||||
SetKeyValueRequest(SetKeyValueRequest),
|
SetKeyValueRequest(SetKeyValueRequest),
|
||||||
@@ -287,6 +295,21 @@ pub struct RenderHttpRequestResponse {
|
|||||||
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 RenderGrpcRequestRequest {
|
||||||
|
pub grpc_request: GrpcRequest,
|
||||||
|
pub purpose: RenderPurpose,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct RenderGrpcRequestResponse {
|
||||||
|
pub grpc_request: GrpcRequest,
|
||||||
|
}
|
||||||
|
|
||||||
#[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")]
|
||||||
@@ -967,11 +990,6 @@ impl Default for RenderPurpose {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
|
||||||
#[serde(default)]
|
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
|
||||||
pub struct GetHttpRequestActionsRequest {}
|
|
||||||
|
|
||||||
#[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")]
|
||||||
@@ -1005,6 +1023,40 @@ 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 GetGrpcRequestActionsResponse {
|
||||||
|
pub actions: Vec<GrpcRequestAction>,
|
||||||
|
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 GrpcRequestAction {
|
||||||
|
pub label: String,
|
||||||
|
#[ts(optional)]
|
||||||
|
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 CallGrpcRequestActionRequest {
|
||||||
|
pub index: i32,
|
||||||
|
pub plugin_ref_id: String,
|
||||||
|
pub args: CallGrpcRequestActionArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct CallGrpcRequestActionArgs {
|
||||||
|
pub grpc_request: GrpcRequest,
|
||||||
|
pub proto_files: Vec<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")]
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ use crate::error::Error::{
|
|||||||
};
|
};
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::events::{
|
use crate::events::{
|
||||||
BootRequest, CallHttpAuthenticationActionArgs, CallHttpAuthenticationActionRequest,
|
BootRequest, CallGrpcRequestActionRequest, CallHttpAuthenticationActionArgs,
|
||||||
CallHttpAuthenticationRequest, CallHttpAuthenticationResponse, CallHttpRequestActionRequest,
|
CallHttpAuthenticationActionRequest, CallHttpAuthenticationRequest,
|
||||||
CallTemplateFunctionArgs, CallTemplateFunctionRequest, CallTemplateFunctionResponse,
|
CallHttpAuthenticationResponse, CallHttpRequestActionRequest, CallTemplateFunctionArgs,
|
||||||
EmptyPayload, FilterRequest, FilterResponse, GetHttpAuthenticationConfigRequest,
|
CallTemplateFunctionRequest, CallTemplateFunctionResponse, EmptyPayload, FilterRequest,
|
||||||
|
FilterResponse, GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigRequest,
|
||||||
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
|
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
|
||||||
GetHttpRequestActionsResponse, GetTemplateFunctionsResponse, GetThemesRequest,
|
GetHttpRequestActionsResponse, GetTemplateFunctionsResponse, GetThemesRequest,
|
||||||
GetThemesResponse, ImportRequest, ImportResponse, InternalEvent, InternalEventPayload,
|
GetThemesResponse, ImportRequest, ImportResponse, InternalEvent, InternalEventPayload,
|
||||||
@@ -426,6 +427,27 @@ impl PluginManager {
|
|||||||
Ok(themes)
|
Ok(themes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_grpc_request_actions<R: Runtime>(
|
||||||
|
&self,
|
||||||
|
window: &WebviewWindow<R>,
|
||||||
|
) -> Result<Vec<GetGrpcRequestActionsResponse>> {
|
||||||
|
let reply_events = self
|
||||||
|
.send_and_wait(
|
||||||
|
&PluginWindowContext::new(window),
|
||||||
|
&InternalEventPayload::GetGrpcRequestActionsRequest(EmptyPayload {}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut all_actions = Vec::new();
|
||||||
|
for event in reply_events {
|
||||||
|
if let InternalEventPayload::GetGrpcRequestActionsResponse(resp) = event.payload {
|
||||||
|
all_actions.push(resp.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(all_actions)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_http_request_actions<R: Runtime>(
|
pub async fn get_http_request_actions<R: Runtime>(
|
||||||
&self,
|
&self,
|
||||||
window: &WebviewWindow<R>,
|
window: &WebviewWindow<R>,
|
||||||
@@ -495,6 +517,23 @@ impl PluginManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn call_grpc_request_action<R: Runtime>(
|
||||||
|
&self,
|
||||||
|
window: &WebviewWindow<R>,
|
||||||
|
req: CallGrpcRequestActionRequest,
|
||||||
|
) -> 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(
|
||||||
|
&PluginWindowContext::new(window),
|
||||||
|
&InternalEventPayload::CallGrpcRequestActionRequest(req),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
plugin.send(&event).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_http_authentication_summaries<R: Runtime>(
|
pub async fn get_http_authentication_summaries<R: Runtime>(
|
||||||
&self,
|
&self,
|
||||||
window: &WebviewWindow<R>,
|
window: &WebviewWindow<R>,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { IconButton } from './core/IconButton';
|
|||||||
import { InlineCode } from './core/InlineCode';
|
import { InlineCode } from './core/InlineCode';
|
||||||
import { Link } from './core/Link';
|
import { Link } from './core/Link';
|
||||||
import { HStack, VStack } from './core/Stacks';
|
import { HStack, VStack } from './core/Stacks';
|
||||||
|
import { Icon } from './core/Icon';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onDone: () => void;
|
onDone: () => void;
|
||||||
@@ -45,6 +46,7 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
|
|||||||
<HStack space={2} justifyContent="start" className="flex-row-reverse">
|
<HStack space={2} justifyContent="start" className="flex-row-reverse">
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
|
variant="border"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const selected = await open({
|
const selected = await open({
|
||||||
title: 'Select Proto Files',
|
title: 'Select Proto Files',
|
||||||
@@ -58,11 +60,28 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
|
|||||||
await grpc.reflect.refetch();
|
await grpc.reflect.refetch();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Add Proto File(s)
|
Add Files
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="border"
|
||||||
|
color="primary"
|
||||||
|
onClick={async () => {
|
||||||
|
const selected = await open({
|
||||||
|
title: 'Select Proto Directory',
|
||||||
|
directory: true,
|
||||||
|
});
|
||||||
|
if (selected == null) return;
|
||||||
|
|
||||||
|
await protoFilesKv.set([...protoFiles.filter((f) => f !== selected), selected]);
|
||||||
|
await grpc.reflect.refetch();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Directories
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
isLoading={grpc.reflect.isFetching}
|
isLoading={grpc.reflect.isFetching}
|
||||||
disabled={grpc.reflect.isFetching}
|
disabled={grpc.reflect.isFetching}
|
||||||
|
variant="border"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
onClick={() => grpc.reflect.refetch()}
|
onClick={() => grpc.reflect.refetch()}
|
||||||
>
|
>
|
||||||
@@ -70,6 +89,14 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
|
|||||||
</Button>
|
</Button>
|
||||||
</HStack>
|
</HStack>
|
||||||
<VStack space={5}>
|
<VStack space={5}>
|
||||||
|
{reflectError && (
|
||||||
|
<Banner color="warning">
|
||||||
|
<h1 className="font-bold">
|
||||||
|
Reflection failed on URL <InlineCode>{request.url || 'n/a'}</InlineCode>
|
||||||
|
</h1>
|
||||||
|
<p>{reflectError.trim()}</p>
|
||||||
|
</Banner>
|
||||||
|
)}
|
||||||
{!serverReflection && services != null && services.length > 0 && (
|
{!serverReflection && services != null && services.length > 0 && (
|
||||||
<Banner className="flex flex-col gap-2">
|
<Banner className="flex flex-col gap-2">
|
||||||
<p>
|
<p>
|
||||||
@@ -108,39 +135,41 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
|
|||||||
<table className="w-full divide-y divide-surface-highlight">
|
<table className="w-full divide-y divide-surface-highlight">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="text-text-subtlest">
|
<th />
|
||||||
Added Files
|
<th className="text-text-subtlest">Added File Paths</th>
|
||||||
</th>
|
<th />
|
||||||
<th/>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-surface-highlight">
|
<tbody className="divide-y divide-surface-highlight">
|
||||||
{protoFiles.map((f, i) => (
|
{protoFiles.map((f, i) => {
|
||||||
<tr key={f + i} className="group">
|
const parts = f.split('/');
|
||||||
<td className="pl-1 font-mono text-sm" title={f}>{f.split('/').pop()}</td>
|
return (
|
||||||
<td className="w-0 py-0.5">
|
<tr key={f + i} className="group">
|
||||||
<IconButton
|
<td>
|
||||||
title="Remove file"
|
<Icon icon={f.endsWith('.proto') ? 'file_code' : 'folder_code'} />
|
||||||
icon="trash"
|
</td>
|
||||||
className="ml-auto opacity-50 transition-opacity group-hover:opacity-100"
|
<td className="pl-1 font-mono text-sm" title={f}>
|
||||||
onClick={async () => {
|
{parts.length > 3 && '.../'}
|
||||||
await protoFilesKv.set(protoFiles.filter((p) => p !== f));
|
{parts.slice(-3).join('/')}
|
||||||
}}
|
</td>
|
||||||
/>
|
<td className="w-0 py-0.5">
|
||||||
</td>
|
<IconButton
|
||||||
</tr>
|
title="Remove file"
|
||||||
))}
|
variant="border"
|
||||||
|
size="xs"
|
||||||
|
icon="trash"
|
||||||
|
className="my-0.5 ml-auto opacity-50 transition-opacity group-hover:opacity-100"
|
||||||
|
onClick={async () => {
|
||||||
|
await protoFilesKv.set(protoFiles.filter((p) => p !== f));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
)}
|
)}
|
||||||
{reflectError && (
|
|
||||||
<Banner color="warning">
|
|
||||||
<h1 className="font-bold">
|
|
||||||
Reflection failed on URL <InlineCode>{request.url || 'n/a'}</InlineCode>
|
|
||||||
</h1>
|
|
||||||
{reflectError}
|
|
||||||
</Banner>
|
|
||||||
)}
|
|
||||||
{reflectionUnimplemented && protoFiles.length === 0 && (
|
{reflectionUnimplemented && protoFiles.length === 0 && (
|
||||||
<Banner>
|
<Banner>
|
||||||
<InlineCode>{request.url}</InlineCode> doesn't implement{' '}
|
<InlineCode>{request.url}</InlineCode> doesn't implement{' '}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export function Banner({ children, className, color }: BannerProps) {
|
|||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
`x-theme-banner--${color}`,
|
`x-theme-banner--${color}`,
|
||||||
'whitespace-pre-wrap',
|
|
||||||
'border border-border bg-surface',
|
'border border-border bg-surface',
|
||||||
'px-4 py-3 rounded-lg select-auto',
|
'px-4 py-3 rounded-lg select-auto',
|
||||||
'overflow-auto text-text',
|
'overflow-auto text-text',
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const icons = {
|
|||||||
eye: lucide.EyeIcon,
|
eye: lucide.EyeIcon,
|
||||||
eye_closed: lucide.EyeOffIcon,
|
eye_closed: lucide.EyeOffIcon,
|
||||||
file_code: lucide.FileCodeIcon,
|
file_code: lucide.FileCodeIcon,
|
||||||
|
folder_code: lucide.FolderCodeIcon,
|
||||||
filter: lucide.FilterIcon,
|
filter: lucide.FilterIcon,
|
||||||
flame: lucide.FlameIcon,
|
flame: lucide.FlameIcon,
|
||||||
flask: lucide.FlaskConicalIcon,
|
flask: lucide.FlaskConicalIcon,
|
||||||
@@ -134,6 +135,8 @@ export const Icon = memo(function Icon({
|
|||||||
title={title}
|
title={title}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
|
!spin && 'transform-cpu',
|
||||||
|
spin && 'animate-spin',
|
||||||
'flex-shrink-0',
|
'flex-shrink-0',
|
||||||
size === 'xl' && 'h-6 w-6',
|
size === 'xl' && 'h-6 w-6',
|
||||||
size === 'lg' && 'h-5 w-5',
|
size === 'lg' && 'h-5 w-5',
|
||||||
@@ -149,7 +152,6 @@ export const Icon = memo(function Icon({
|
|||||||
color === 'success' && 'text-success',
|
color === 'success' && 'text-success',
|
||||||
color === 'primary' && 'text-primary',
|
color === 'primary' && 'text-primary',
|
||||||
color === 'secondary' && 'text-secondary',
|
color === 'secondary' && 'text-secondary',
|
||||||
spin && 'animate-spin',
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useAtomValue } from 'jotai';
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { openFolderSettings } from '../../commands/openFolderSettings';
|
import { openFolderSettings } from '../../commands/openFolderSettings';
|
||||||
import { useCreateDropdownItems } from '../../hooks/useCreateDropdownItems';
|
import { useCreateDropdownItems } from '../../hooks/useCreateDropdownItems';
|
||||||
|
import { useGrpcRequestActions } from '../../hooks/useGrpcRequestActions';
|
||||||
import { useHttpRequestActions } from '../../hooks/useHttpRequestActions';
|
import { useHttpRequestActions } from '../../hooks/useHttpRequestActions';
|
||||||
import { useMoveToWorkspace } from '../../hooks/useMoveToWorkspace';
|
import { useMoveToWorkspace } from '../../hooks/useMoveToWorkspace';
|
||||||
import { useSendAnyHttpRequest } from '../../hooks/useSendAnyHttpRequest';
|
import { useSendAnyHttpRequest } from '../../hooks/useSendAnyHttpRequest';
|
||||||
@@ -25,6 +26,7 @@ interface Props {
|
|||||||
export function SidebarItemContextMenu({ child, show, close }: Props) {
|
export function SidebarItemContextMenu({ child, show, close }: Props) {
|
||||||
const sendManyRequests = useSendManyRequests();
|
const sendManyRequests = useSendManyRequests();
|
||||||
const httpRequestActions = useHttpRequestActions();
|
const httpRequestActions = useHttpRequestActions();
|
||||||
|
const grpcRequestActions = useGrpcRequestActions();
|
||||||
const sendRequest = useSendAnyHttpRequest();
|
const sendRequest = useSendAnyHttpRequest();
|
||||||
const workspaces = useAtomValue(workspacesAtom);
|
const workspaces = useAtomValue(workspacesAtom);
|
||||||
const moveToWorkspace = useMoveToWorkspace(child.id);
|
const moveToWorkspace = useMoveToWorkspace(child.id);
|
||||||
@@ -65,25 +67,35 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
|
|||||||
const requestItems: DropdownItem[] =
|
const requestItems: DropdownItem[] =
|
||||||
child.model === 'http_request'
|
child.model === 'http_request'
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
label: 'Send',
|
label: 'Send',
|
||||||
hotKeyAction: 'http_request.send',
|
hotKeyAction: 'http_request.send',
|
||||||
hotKeyLabelOnly: true, // Already bound in URL bar
|
hotKeyLabelOnly: true, // Already bound in URL bar
|
||||||
leftSlot: <Icon icon="send_horizontal" />,
|
leftSlot: <Icon icon="send_horizontal" />,
|
||||||
onSelect: () => sendRequest.mutate(child.id),
|
onSelect: () => sendRequest.mutate(child.id),
|
||||||
|
},
|
||||||
|
...httpRequestActions.map((a) => ({
|
||||||
|
label: a.label,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
leftSlot: <Icon icon={(a.icon as any) ?? 'empty'} />,
|
||||||
|
onSelect: async () => {
|
||||||
|
const request = getModel('http_request', child.id);
|
||||||
|
if (request != null) await a.call(request);
|
||||||
},
|
},
|
||||||
...httpRequestActions.map((a) => ({
|
})),
|
||||||
label: a.label,
|
{ type: 'separator' },
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
]
|
||||||
leftSlot: <Icon icon={(a.icon as any) ?? 'empty'} />,
|
: child.model === 'grpc_request'
|
||||||
onSelect: async () => {
|
? grpcRequestActions.map((a) => ({
|
||||||
const request = getModel('http_request', child.id);
|
label: a.label,
|
||||||
if (request != null) await a.call(request);
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
},
|
leftSlot: <Icon icon={(a.icon as any) ?? 'empty'} />,
|
||||||
})),
|
onSelect: async () => {
|
||||||
{ type: 'separator' },
|
const request = getModel('grpc_request', child.id);
|
||||||
]
|
if (request != null) await a.call(request);
|
||||||
: [];
|
},
|
||||||
|
}))
|
||||||
|
: [];
|
||||||
return [
|
return [
|
||||||
...requestItems,
|
...requestItems,
|
||||||
{
|
{
|
||||||
@@ -134,6 +146,7 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
|
|||||||
child.model,
|
child.model,
|
||||||
createDropdownItems,
|
createDropdownItems,
|
||||||
httpRequestActions,
|
httpRequestActions,
|
||||||
|
grpcRequestActions,
|
||||||
moveToWorkspace.mutate,
|
moveToWorkspace.mutate,
|
||||||
sendManyRequests,
|
sendManyRequests,
|
||||||
sendRequest,
|
sendRequest,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { getKeyValue } from '../lib/keyValueStore';
|
||||||
import { useKeyValue } from './useKeyValue';
|
import { useKeyValue } from './useKeyValue';
|
||||||
|
|
||||||
export function protoFilesArgs(requestId: string | null) {
|
export function protoFilesArgs(requestId: string | null) {
|
||||||
@@ -10,3 +11,7 @@ export function protoFilesArgs(requestId: string | null) {
|
|||||||
export function useGrpcProtoFiles(activeRequestId: string | null) {
|
export function useGrpcProtoFiles(activeRequestId: string | null) {
|
||||||
return useKeyValue<string[]>({ ...protoFilesArgs(activeRequestId), fallback: [] });
|
return useKeyValue<string[]>({ ...protoFilesArgs(activeRequestId), fallback: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getGrpcProtoFiles(activeRequestId: string | null) {
|
||||||
|
return getKeyValue<string[]>({ ...protoFilesArgs(activeRequestId), fallback: [] });
|
||||||
|
}
|
||||||
|
|||||||
51
src-web/hooks/useGrpcRequestActions.ts
Normal file
51
src-web/hooks/useGrpcRequestActions.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import type { GrpcRequest } from '@yaakapp-internal/models';
|
||||||
|
import type {
|
||||||
|
CallGrpcRequestActionRequest,
|
||||||
|
GetGrpcRequestActionsResponse,
|
||||||
|
GrpcRequestAction,
|
||||||
|
} from '@yaakapp-internal/plugins';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { invokeCmd } from '../lib/tauri';
|
||||||
|
import { getGrpcProtoFiles } from './useGrpcProtoFiles';
|
||||||
|
import { usePluginsKey } from './usePlugins';
|
||||||
|
|
||||||
|
export type CallableGrpcRequestAction = Pick<GrpcRequestAction, 'label' | 'icon'> & {
|
||||||
|
call: (grpcRequest: GrpcRequest) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useGrpcRequestActions() {
|
||||||
|
const pluginsKey = usePluginsKey();
|
||||||
|
|
||||||
|
const actionsResult = useQuery<CallableGrpcRequestAction[]>({
|
||||||
|
queryKey: ['grpc_request_actions', pluginsKey],
|
||||||
|
queryFn: async () => {
|
||||||
|
const responses = await invokeCmd<GetGrpcRequestActionsResponse[]>(
|
||||||
|
'cmd_grpc_request_actions',
|
||||||
|
);
|
||||||
|
|
||||||
|
return responses.flatMap((r) =>
|
||||||
|
r.actions.map((a, i) => ({
|
||||||
|
label: a.label,
|
||||||
|
icon: a.icon,
|
||||||
|
call: async (grpcRequest: GrpcRequest) => {
|
||||||
|
const protoFiles = await getGrpcProtoFiles(grpcRequest.id);
|
||||||
|
const payload: CallGrpcRequestActionRequest = {
|
||||||
|
index: i,
|
||||||
|
pluginRefId: r.pluginRefId,
|
||||||
|
args: { grpcRequest, protoFiles },
|
||||||
|
};
|
||||||
|
await invokeCmd('cmd_call_grpc_request_action', { req: payload });
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const actions = useMemo(() => {
|
||||||
|
return actionsResult.data ?? [];
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [JSON.stringify(actionsResult.data)]);
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { invoke } from '@tauri-apps/api/core';
|
|||||||
type TauriCmd =
|
type TauriCmd =
|
||||||
| 'cmd_get_themes'
|
| 'cmd_get_themes'
|
||||||
| 'cmd_call_http_authentication_action'
|
| 'cmd_call_http_authentication_action'
|
||||||
|
| 'cmd_call_grpc_request_action'
|
||||||
| 'cmd_call_http_request_action'
|
| 'cmd_call_http_request_action'
|
||||||
| 'cmd_check_for_updates'
|
| 'cmd_check_for_updates'
|
||||||
| 'cmd_create_grpc_request'
|
| 'cmd_create_grpc_request'
|
||||||
@@ -23,6 +24,7 @@ type TauriCmd =
|
|||||||
| 'cmd_get_workspace_meta'
|
| 'cmd_get_workspace_meta'
|
||||||
| 'cmd_grpc_go'
|
| 'cmd_grpc_go'
|
||||||
| 'cmd_grpc_reflect'
|
| 'cmd_grpc_reflect'
|
||||||
|
| 'cmd_grpc_request_actions'
|
||||||
| 'cmd_http_request_actions'
|
| 'cmd_http_request_actions'
|
||||||
| 'cmd_import_data'
|
| 'cmd_import_data'
|
||||||
| 'cmd_install_plugin'
|
| 'cmd_install_plugin'
|
||||||
|
|||||||
Reference in New Issue
Block a user