Compare commits

..

19 Commits

Author SHA1 Message Date
Gregory Schier
cf35658fea Revert Tauri CLI 2025-07-05 16:45:07 -07:00
Gregory Schier
6330c77948 Fix linux build 2025-07-05 16:16:50 -07:00
Gregory Schier
77d2edd947 Add log 2025-07-05 16:00:46 -07:00
Gregory Schier
4f0f60cb99 Add log 2025-07-05 16:00:20 -07:00
Gregory Schier
dd2b665982 Tweak protos CLI arg generation 2025-07-05 15:58:36 -07:00
Gregory Schier
19ffcd18a6 gRPC request actions and "copy as gRPCurl" (#232) 2025-07-05 15:40:41 -07:00
Gregory Schier
ad4d6d9720 Merge branch 'theme-plugins'
# Conflicts:
#	packages/plugin-runtime-types/src/bindings/gen_events.ts
2025-07-05 06:37:32 -07:00
Gregory Schier
9e98b5f905 Fix macos window theme calculation 2025-07-05 06:37:02 -07:00
Gregory Schier
19c6ad9d97 Theme plugins (#231) 2025-07-03 13:06:30 -07:00
Gregory Schier
a0e5e60803 Fix filter plugin names 2025-07-03 12:28:34 -07:00
Gregory Schier
2a6f139d36 Better plugin reloading and theme parsing 2025-07-03 12:25:22 -07:00
Gregory Schier
36bbb87a5e Mostly working 2025-07-03 11:48:17 -07:00
Gregory Schier
a6979cf37e Print table/col/val when row not found 2025-07-02 08:14:52 -07:00
Gregory Schier
ff26cc1344 Tweaks 2025-07-02 07:47:36 -07:00
Gregory Schier
fa62f88fa4 Allow moving requests and folders to end of list 2025-06-29 08:40:14 -07:00
Gregory Schier
99975c3223 Fix sidebar folder dragging collapse
https://feedback.yaak.app/p/a-folder-may-hide-its-content-if-i-move-a
2025-06-29 08:02:55 -07:00
Gregory Schier
d3cda19be2 Hide large request bodies by default 2025-06-29 07:30:07 -07:00
Gregory Schier
9b0a767ac8 Prevent command palette from jumping with less results 2025-06-28 07:37:15 -07:00
Gregory Schier
81c3de807d Add json.minify 2025-06-28 07:29:24 -07:00
104 changed files with 3449 additions and 1964 deletions

View File

@@ -80,6 +80,7 @@ module.exports = defineConfig([
globalIgnores([
'**/node_modules/',
'**/dist/',
'**/build/',
'**/.eslintrc.cjs',
'**/.prettierrc.cjs',
'src-web/postcss.config.cjs',

991
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,8 @@
"plugins/auth-bearer",
"plugins/auth-jwt",
"plugins/auth-oauth2",
"plugins/exporter-curl",
"plugins/action-copy-curl",
"plugins/action-copy-grpcurl",
"plugins/filter-jsonpath",
"plugins/filter-xpath",
"plugins/importer-curl",
@@ -33,6 +34,7 @@
"plugins/template-function-response",
"plugins/template-function-uuid",
"plugins/template-function-xml",
"plugins/themes-yaak",
"src-tauri/yaak-crypto",
"src-tauri/yaak-git",
"src-tauri/yaak-fonts",
@@ -84,6 +86,7 @@
"npm-run-all": "^4.1.5",
"prettier": "^3.4.2",
"typescript": "^5.8.3",
"vitest": "^3.2.4",
"workspaces-run": "^1.0.2"
}
}

View File

@@ -24,5 +24,5 @@ the [Quick Start Guide](https://feedback.yaak.app/help/articles/6911763-plugins-
If you prefer starting from scratch, manually install the types package:
```shell
npm install @yaakapp/api
npm install -D @yaakapp/api
```

View File

@@ -1,6 +1,6 @@
{
"name": "@yaakapp/api",
"version": "0.6.4",
"version": "0.6.6",
"keywords": [
"api-client",
"insomnia-alternative",

View File

@@ -6,6 +6,10 @@ export type BootRequest = { dir: string, watch: boolean, };
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 CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
@@ -336,14 +340,14 @@ export type GetCookieValueRequest = { name: string, };
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 GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
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 GetHttpRequestByIdRequest = { id: string, };
@@ -356,6 +360,12 @@ export type GetKeyValueResponse = { value?: string, };
export type GetTemplateFunctionsResponse = { functions: Array<TemplateFunction>, pluginRefId: string, };
export type GetThemesRequest = Record<string, never>;
export type GetThemesResponse = { themes: Array<Theme>, };
export type GrpcRequestAction = { label: string, icon?: Icon, };
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
export type HttpHeader = { name: string, value: string, };
@@ -372,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 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": "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;
@@ -404,6 +414,10 @@ required?: boolean, };
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 RenderHttpRequestResponse = { httpRequest: HttpRequest, };
@@ -436,6 +450,32 @@ export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, }
export type TemplateRenderResponse = { data: JsonValue, };
export type Theme = {
/**
* How the theme is identified. This should never be changed
*/
id: string,
/**
* The friendly name of the theme to be displayed to the user
*/
label: string,
/**
* Whether the theme will be used for dark or light appearance
*/
dark: boolean,
/**
* The default top-level colors for the theme
*/
base: ThemeComponentColors,
/**
* Optionally override theme for individual UI components for more control
*/
components?: ThemeComponents, };
export type ThemeComponentColors = { surface?: string, surfaceHighlight?: string, surfaceActive?: string, text?: string, textSubtle?: string, textSubtlest?: string, border?: string, borderSubtle?: string, borderFocus?: string, shadow?: string, backdrop?: string, selection?: string, primary?: string, secondary?: string, info?: string, success?: string, notice?: string, warning?: string, danger?: string, };
export type ThemeComponents = { dialog?: ThemeComponentColors, menu?: ThemeComponentColors, toast?: ThemeComponentColors, sidebar?: ThemeComponentColors, responsePane?: ThemeComponentColors, appHeader?: ThemeComponentColors, button?: ThemeComponentColors, banner?: ThemeComponentColors, templateTag?: ThemeComponentColors, urlBar?: ThemeComponentColors, editor?: ThemeComponentColors, input?: ThemeComponentColors, };
export type WindowNavigateEvent = { url: string, };
export type WindowSize = { width: number, height: number, };

View File

@@ -9,6 +9,8 @@ import type {
OpenWindowRequest,
PromptTextRequest,
PromptTextResponse,
RenderGrpcRequestRequest,
RenderGrpcRequestResponse,
RenderHttpRequestRequest,
RenderHttpRequestResponse,
SendHttpRequestRequest,
@@ -45,6 +47,9 @@ export interface Context {
listNames(): Promise<ListCookieNamesResponse['names']>;
getValue(args: GetCookieValueRequest): Promise<GetCookieValueResponse['value']>;
};
grpcRequest: {
render(args: RenderGrpcRequestRequest): Promise<RenderGrpcRequestResponse['grpcRequest']>;
};
httpRequest: {
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;

View File

@@ -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;
};

View File

@@ -1,5 +1,5 @@
import { ImportResources } from '../bindings/gen_events';
import { AtLeast } from '../helpers';
import { AtLeast, MaybePromise } from '../helpers';
import type { Context } from './Context';
type RootFields = 'name' | 'id' | 'model';
@@ -21,5 +21,8 @@ export type ImportPluginResponse = null | {
export type ImporterPlugin = {
name: string;
description?: string;
onImport(ctx: Context, args: { text: string }): Promise<ImportPluginResponse>;
onImport(
ctx: Context,
args: { text: string },
): MaybePromise<ImportPluginResponse | null | undefined>;
};

View File

@@ -1,8 +1,3 @@
import { Index } from "../themes";
import { Context } from "./Context";
import { Theme } from '../bindings/gen_events';
export type ThemePlugin = {
name: string;
description?: string;
getTheme(ctx: Context, fileContents: string): Promise<Index>;
};
export type ThemePlugin = Theme;

View File

@@ -1,5 +1,6 @@
import { AuthenticationPlugin } from './AuthenticationPlugin';
import type { FilterPlugin } from './FilterPlugin';
import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin';
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
import type { ImporterPlugin } from './ImporterPlugin';
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
@@ -12,9 +13,10 @@ export type { Context } from './Context';
*/
export type PluginDefinition = {
importer?: ImporterPlugin;
theme?: ThemePlugin;
themes?: ThemePlugin[];
filter?: FilterPlugin;
authentication?: AuthenticationPlugin;
httpRequestActions?: HttpRequestActionPlugin[];
grpcRequestActions?: GrpcRequestActionPlugin[];
templateFunctions?: TemplateFunctionPlugin[];
};

View File

@@ -2,12 +2,17 @@
"compilerOptions": {
"module": "node16",
"target": "es6",
"lib": ["es2021"],
"lib": [
"es2021",
"dom"
],
"declaration": true,
"declarationDir": "./lib",
"outDir": "./lib",
"strict": true,
"types": ["node"]
"types": [
"node"
]
},
"files": [
"src/index.ts"

View File

@@ -7,7 +7,7 @@ import {
GetCookieValueRequest,
GetCookieValueResponse,
GetHttpRequestByIdResponse,
GetKeyValueResponse,
GetKeyValueResponse, GrpcRequestAction,
HttpAuthenticationAction,
HttpRequestAction,
InternalEvent,
@@ -16,6 +16,7 @@ import {
PluginWindowContext,
PromptTextResponse,
RenderHttpRequestResponse,
RenderGrpcRequestResponse,
SendHttpRequestResponse,
TemplateFunction,
TemplateFunctionArg,
@@ -145,6 +146,24 @@ export class PluginInstance {
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 (
payload.type === 'get_http_request_actions_request' &&
Array.isArray(this.#mod?.httpRequestActions)
@@ -163,6 +182,15 @@ export class PluginInstance {
return;
}
if (payload.type === 'get_themes_request' && Array.isArray(this.#mod?.themes)) {
const replyPayload: InternalEventPayload = {
type: 'get_themes_response',
themes: this.#mod.themes,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
}
if (
payload.type === 'get_template_functions_request' &&
Array.isArray(this.#mod?.templateFunctions)
@@ -199,13 +227,12 @@ export class PluginInstance {
if (payload.type === 'get_http_authentication_config_request' && this.#mod?.authentication) {
const { args, actions } = this.#mod.authentication;
const resolvedArgs: FormInput[] = [];
for (let i = 0; i < args.length; i++) {
let v = args[i];
if ('dynamic' in v) {
for (const v of args) {
if (v && 'dynamic' in v) {
const dynamicAttrs = await v.dynamic(ctx, payload);
const { dynamic, ...other } = v;
resolvedArgs.push({ ...other, ...dynamicAttrs } as FormInput);
} else {
} else if (v) {
resolvedArgs.push(v);
}
}
@@ -266,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 (
payload.type === 'call_template_function_request' &&
Array.isArray(this.#mod?.templateFunctions)
@@ -463,6 +502,19 @@ export class PluginInstance {
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: {
getById: async (args) => {
const payload = {
@@ -587,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
* 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, () => {
const stat = statSync(filepath);
if (stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
cb(filepath);
const stat = statSync(filepath, { throwIfNoEntry: false });
if (stat == null || stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
watchedFiles[filepath] = stat ?? null;
cb();
}
watchedFiles[filepath] = stat;
});
}

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/exporter-curl",
"name": "@yaak/action-copy-curl",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,18 +1,27 @@
import { HttpRequest, PluginDefinition } from '@yaakapp/api';
import type { HttpRequest, PluginDefinition } from '@yaakapp/api';
const NEWLINE = '\\\n ';
export const plugin: PluginDefinition = {
httpRequestActions: [{
label: 'Copy as Curl',
icon: 'copy',
async onSelect(ctx, args) {
const rendered_request = await ctx.httpRequest.render({ httpRequest: args.httpRequest, purpose: 'preview' });
const data = await convertToCurl(rendered_request);
await ctx.clipboard.copyText(data);
await ctx.toast.show({ message: 'Curl copied to clipboard', icon: 'copy', color: 'success' });
httpRequestActions: [
{
label: 'Copy as Curl',
icon: 'copy',
async onSelect(ctx, args) {
const rendered_request = await ctx.httpRequest.render({
httpRequest: args.httpRequest,
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>) {
@@ -22,7 +31,6 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
if (request.method) xs.push('-X', request.method);
if (request.url) xs.push(quote(request.url));
xs.push(NEWLINE);
// Add URL params
@@ -51,7 +59,10 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
xs.push(NEWLINE);
}
} 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(NEWLINE);
} else if (typeof request.body?.text === 'string') {
@@ -84,7 +95,7 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
}
function quote(arg: string): string {
const escaped = arg.replace(/'/g, '\\\'');
const escaped = arg.replace(/'/g, "\\'");
return `'${escaped}'`;
}
@@ -92,10 +103,10 @@ function onlyEnabled(v: { name?: string; enabled?: boolean }): boolean {
return v.enabled !== false && !!v.name;
}
function maybeParseJSON(v: any, fallback: any): string {
function maybeParseJSON<T>(v: string, fallback: T) {
try {
return JSON.parse(v);
} catch (err) {
} catch {
return fallback;
}
}

View 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"
}
}

View 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;
}
}

View 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 `),
);
});
});

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/auth-basic",
"name": "@yaak/auth-basic",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/auth-bearer",
"name": "@yaak/auth-bearer",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/auth-jwt",
"name": "@yaak/auth-jwt",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"jsonwebtoken": "^9.0.2"

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/auth-oauth2",
"name": "@yaak/auth-oauth2",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/filter-jsonpath",
"name": "@yaak/filter-jsonpath",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"jsonpath-plus": "^10.3.0"

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/filter-xpath",
"name": "@yaak/filter-xpath",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"@xmldom/xmldom": "^0.8.10",

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/importer-curl",
"name": "@yaak/importer-curl",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"shell-quote": "^1.8.1"

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/importer-insomnia",
"name": "@yaak/importer-insomnia",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"yaml": "^2.4.2"

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/importer-openapi",
"name": "@yaak/importer-openapi",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"openapi-to-postmanv2": "^5.0.0",

View File

@@ -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 { 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 = {
importer: {
name: 'OpenAPI',
description: 'Import OpenAPI collections',
onImport(_ctx: Context, args: { text: string }) {
return convertOpenApi(args.text) as any;
return convertOpenApi(args.text);
},
},
};
export async function convertOpenApi(
contents: string,
): Promise<{ resources: ExportResources } | undefined> {
export async function convertOpenApi(contents: string): Promise<ImportPluginResponse | undefined> {
let postmanCollection;
try {
postmanCollection = await new Promise((resolve, reject) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
convert({ type: 'string', data: contents }, {}, (err, result: any) => {
if (err != null) reject(err);
@@ -35,7 +26,7 @@ export async function convertOpenApi(
}
});
});
} catch (err) {
} catch {
// Probably not an OpenAPI file, so skip it
return undefined;
}

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/importer-postman",
"name": "@yaak/importer-postman",
"private": true,
"version": "0.0.1",
"main": "./build/index.js",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,13 +1,15 @@
import {
import type {
Context,
Environment,
Folder,
HttpRequest,
HttpRequestHeader,
HttpUrlParameter,
PartialImportResources,
PluginDefinition,
Workspace,
} 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_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
@@ -27,19 +29,19 @@ export const plugin: PluginDefinition = {
name: 'Postman',
description: 'Import postman collections',
onImport(_ctx: Context, args: { text: string }) {
return convertPostman(args.text) as any;
return convertPostman(args.text);
},
},
};
export function convertPostman(
contents: string,
): { resources: ExportResources } | undefined {
export function convertPostman(contents: string): ImportPluginResponse | undefined {
const root = parseJSONToRecord(contents);
if (root == null) return;
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)) {
return;
}
@@ -53,11 +55,17 @@ export function convertPostman(
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] = {
model: 'workspace',
id: generateId('workspace'),
name: info.name || 'Postman Import',
description: info.description?.content ?? info.description,
name: info.name ? String(info.name) : 'Postman Import',
description,
};
exportResources.workspaces.push(workspace);
@@ -68,14 +76,14 @@ export function convertPostman(
name: 'Global Variables',
workspaceId: workspace.id,
variables:
root.variable?.map((v: any) => ({
toArray<{ key: string; value: string }>(root.variable).map((v) => ({
name: v.key,
value: v.value,
})) ?? [],
};
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)) {
const folder: ExportResources['folders'][0] = {
model: 'folder',
@@ -94,7 +102,11 @@ export function convertPostman(
const requestAuthPath = importAuth(r.auth);
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 {
name: h.key,
value: h.value,
@@ -104,7 +116,9 @@ export function convertPostman(
// Add body headers only if they don't already exist
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) {
continue;
}
@@ -119,8 +133,8 @@ export function convertPostman(
workspaceId: workspace.id,
folderId,
name: v.name,
description: v.description || undefined,
method: r.method || 'GET',
description: v.description ? String(v.description) : undefined,
method: typeof r.method === 'string' ? r.method : 'GET',
url,
urlParameters,
body: bodyPatch.body,
@@ -139,17 +153,19 @@ export function convertPostman(
importItem(item);
}
const resources = deleteUndefinedAttrs(convertTemplateSyntax(exportResources));
const resources = deleteUndefinedAttrs(
convertTemplateSyntax(exportResources),
) as PartialImportResources;
return { resources };
}
function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters'> {
if (typeof url === 'string') {
return { url, urlParameters: [] };
function convertUrl(rawUrl: string | unknown): Pick<HttpRequest, 'url' | 'urlParameters'> {
if (typeof rawUrl === 'string') {
return { url: rawUrl, urlParameters: [] };
}
url = toRecord(url);
const url = toRecord(rawUrl);
let v = '';
@@ -199,10 +215,8 @@ function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters
return { url: v, urlParameters: params };
}
function importAuth(
rawAuth: any,
): Pick<HttpRequest, 'authentication' | 'authenticationType'> {
const auth = toRecord(rawAuth);
function importAuth(rawAuth: unknown): Pick<HttpRequest, 'authentication' | 'authenticationType'> {
const auth = toRecord<{ username?: string; password?: string; token?: string }>(rawAuth);
if ('basic' in auth) {
return {
authenticationType: 'basic',
@@ -223,8 +237,22 @@ function importAuth(
}
}
function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
const body = toRecord(rawBody);
function importBody(rawBody: unknown): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
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') {
return {
headers: [
@@ -237,7 +265,10 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
bodyType: 'graphql',
body: {
text: JSON.stringify(
{ query: body.graphql.query, variables: parseJSONToRecord(body.graphql.variables) },
{
query: body.graphql?.query || '',
variables: parseJSONToRecord(body.graphql?.variables || '{}'),
},
null,
2,
),
@@ -254,7 +285,7 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
],
bodyType: 'application/x-www-form-urlencoded',
body: {
form: toArray(body.urlencoded).map((f) => ({
form: toArray<NonNullable<typeof body.urlencoded>[0]>(body.urlencoded).map((f) => ({
enabled: !f.disabled,
name: f.key ?? '',
value: f.value ?? '',
@@ -272,19 +303,19 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
],
bodyType: 'multipart/form-data',
body: {
form: toArray(body.formdata).map((f) =>
form: toArray<NonNullable<typeof body.formdata>[0]>(body.formdata).map((f) =>
f.src != null
? {
enabled: !f.disabled,
contentType: f.contentType ?? null,
name: f.key ?? '',
file: f.src ?? '',
}
enabled: !f.disabled,
contentType: f.contentType ?? null,
name: f.key ?? '',
file: f.src ?? '',
}
: {
enabled: !f.disabled,
name: f.key ?? '',
value: f.value ?? '',
},
enabled: !f.disabled,
name: f.key ?? '',
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 {
return toRecord(JSON.parse(jsonStr));
} catch (err) {
} catch {
return null;
}
return null;
}
function toRecord(value: any): Record<string, any> {
if (Object.prototype.toString.call(value) === '[object Object]') return value;
else return {};
function toRecord<T>(value: Record<string, T> | unknown): Record<string, T> {
if (value && typeof value === 'object' && !Array.isArray(value)) {
return value as Record<string, T>;
}
return {};
}
function toArray(value: any): any[] {
if (Object.prototype.toString.call(value) === '[object Array]') return value;
function toArray<T>(value: unknown): T[] {
if (Object.prototype.toString.call(value) === '[object Array]') return value as T[];
else return [];
}

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/importer-yaak",
"name": "@yaak/importer-yaak",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.js",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-cookie",
"name": "@yaak/template-function-cookie",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-encode",
"name": "@yaak/template-function-encode",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,4 +1,4 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
export const plugin: PluginDefinition = {
templateFunctions: [
@@ -7,7 +7,7 @@ export const plugin: PluginDefinition = {
description: 'Encode a value to base64',
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
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',
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
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)',
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
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 }],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
try {
return decodeURIComponent(args.values.value ?? '');
return decodeURIComponent(String(args.values.value ?? ''));
} catch {
return '';
}

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-fs",
"name": "@yaak/template-function-fs",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,19 +1,21 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import fs from 'node:fs';
export const plugin: PluginDefinition = {
templateFunctions: [{
name: 'fs.readFile',
description: 'Read the contents of a file as utf-8',
args: [{ title: 'Select File', type: 'file', name: 'path', label: 'File' }],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
if (!args.values.path) return null;
templateFunctions: [
{
name: 'fs.readFile',
description: 'Read the contents of a file as utf-8',
args: [{ title: 'Select File', type: 'file', name: 'path', label: 'File' }],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
if (!args.values.path) return null;
try {
return fs.promises.readFile(args.values.path, 'utf-8');
} catch (err) {
return null;
}
try {
return fs.promises.readFile(String(args.values.path ?? ''), 'utf-8');
} catch {
return null;
}
},
},
}],
],
};

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-hash",
"name": "@yaak/template-function-hash",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/template-function-json",
"name": "@yaak/template-function-json",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"jsonpath-plus": "^10.3.0"

View File

@@ -1,4 +1,4 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import { JSONPath } from 'jsonpath-plus';
export const plugin: PluginDefinition = {
@@ -7,7 +7,13 @@ export const plugin: PluginDefinition = {
name: 'json.jsonpath',
description: 'Filter JSON-formatted text using JSONPath syntax',
args: [
{ type: 'text', name: 'input', label: 'Input', multiLine: true, placeholder: '{ "foo": "bar" }' },
{
type: 'text',
name: 'input',
label: 'Input',
multiLine: true,
placeholder: '{ "foo": "bar" }',
},
{ type: 'text', name: 'query', label: 'Query', placeholder: '$..foo' },
{ type: 'checkbox', name: 'formatted', label: 'Format Output' },
],
@@ -28,7 +34,7 @@ export const plugin: PluginDefinition = {
} else {
return JSON.stringify(filtered);
}
} catch (e) {
} catch {
return null;
}
},
@@ -37,12 +43,39 @@ export const plugin: PluginDefinition = {
name: 'json.escape',
description: 'Escape a JSON string, useful when using the output in JSON values',
args: [
{ type: 'text', name: 'input', label: 'Input', multiLine: true, placeholder: 'Hello "World"' },
{
type: 'text',
name: 'input',
label: 'Input',
multiLine: true,
placeholder: 'Hello "World"',
},
],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
const input = String(args.values.input ?? '');
return input.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
},
},
{
name: 'json.minify',
description: 'Remove unnecessary whitespace from a valid JSON string.',
args: [
{
type: 'editor',
language: 'json',
name: 'input',
label: 'Input',
placeholder: '{ "foo": "bar" }',
},
],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
const input = String(args.values.input ?? '');
try {
return JSON.stringify(JSON.parse(input));
} catch {
return input;
}
},
},
],
};

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-prompt",
"name": "@yaak/template-function-prompt",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,4 +1,4 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
export const plugin: PluginDefinition = {
templateFunctions: [{
@@ -15,10 +15,10 @@ export const plugin: PluginDefinition = {
return await ctx.prompt.text({
id: `prompt-${args.values.label}`,
label: args.values.title ?? '',
title: args.values.title ?? '',
defaultValue: args.values.defaultValue,
placeholder: args.values.placeholder,
label: String(args.values.title ?? ''),
title: String(args.values.title ?? ''),
defaultValue: String(args.values.defaultValue),
placeholder: String(args.values.placeholder),
});
},
}],

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-regex",
"name": "@yaak/template-function-regex",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,28 +1,32 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
export const plugin: PluginDefinition = {
templateFunctions: [{
name: 'regex.match',
description: 'Extract',
args: [
{
type: 'text',
name: 'regex',
label: 'Regular Expression',
placeholder: '^\w+=(?<value>\w*)$',
defaultValue: '^(.*)$',
description: 'A JavaScript regular expression, evaluated using the Node.js RegExp engine. Capture groups or named groups can be used to extract values.',
},
{ type: 'text', name: 'input', label: 'Input Text', multiLine: true },
],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
if (!args.values.regex) return '';
templateFunctions: [
{
name: 'regex.match',
description: 'Extract',
args: [
{
type: 'text',
name: 'regex',
label: 'Regular Expression',
placeholder: '^\\w+=(?<value>\\w*)$',
defaultValue: '^(.*)$',
description:
'A JavaScript regular expression, evaluated using the Node.js RegExp engine. Capture groups or named groups can be used to extract values.',
},
{ type: 'text', name: 'input', label: 'Input Text', multiLine: true },
],
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 match = args.values.input?.match(regex);
return match?.groups
? Object.values(match.groups)[0] ?? ''
: match?.[1] ?? match?.[0] ?? '';
const input = String(args.values.input);
const regex = new RegExp(String(args.values.regex));
const match = input.match(regex);
return match?.groups
? (Object.values(match.groups)[0] ?? '')
: (match?.[1] ?? match?.[0] ?? '');
},
},
}],
],
};

View File

@@ -1,9 +1,10 @@
{
"name": "@yaakapp/template-function-request",
"name": "@yaak/template-function-request",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -1,21 +1,26 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
export const plugin: PluginDefinition = {
templateFunctions: [
{
name: 'request.body',
args: [{
name: 'requestId',
label: 'Http Request',
type: 'http_request',
}],
args: [
{
name: 'requestId',
label: 'Http Request',
type: 'http_request',
},
],
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;
return String(await ctx.templates.render({
data: httpRequest.body?.text ?? '',
purpose: args.purpose,
}));
return String(
await ctx.templates.render({
data: httpRequest.body?.text ?? '',
purpose: args.purpose,
}),
);
},
},
{
@@ -30,15 +35,22 @@ export const plugin: PluginDefinition = {
name: 'header',
label: 'Header Name',
type: 'text',
}],
},
],
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;
const header = httpRequest.headers.find(h => h.name.toLowerCase() === args.values.header?.toLowerCase());
return String(await ctx.templates.render({
data: header?.value ?? '',
purpose: args.purpose,
}));
const header = httpRequest.headers.find(
(h) => h.name.toLowerCase() === headerName.toLowerCase(),
);
return String(
await ctx.templates.render({
data: header?.value ?? '',
purpose: args.purpose,
}),
);
},
},
],

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/template-function-response",
"name": "@yaak/template-function-response",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"jsonpath-plus": "^10.3.0",

View File

@@ -1,5 +1,5 @@
import { DOMParser } from '@xmldom/xmldom';
import {
import type {
CallTemplateFunctionArgs,
Context,
FormInput,
@@ -47,14 +47,14 @@ export const plugin: PluginDefinition = {
if (!args.values.request || !args.values.header) return null;
const response = await getResponse(ctx, {
requestId: args.values.request,
requestId: String(args.values.request || ''),
purpose: args.purpose,
behavior: args.values.behavior ?? null,
behavior: args.values.behavior ? String(args.values.behavior) : null,
});
if (response == null) return null;
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;
},
@@ -77,9 +77,9 @@ export const plugin: PluginDefinition = {
if (!args.values.request || !args.values.path) return null;
const response = await getResponse(ctx, {
requestId: args.values.request,
requestId: String(args.values.request || ''),
purpose: args.purpose,
behavior: args.values.behavior ?? null,
behavior: args.values.behavior ? String(args.values.behavior) : null,
});
if (response == null) return null;
@@ -90,19 +90,19 @@ export const plugin: PluginDefinition = {
let body;
try {
body = readFileSync(response.bodyPath, 'utf-8');
} catch (_) {
} catch {
return null;
}
try {
return filterJSONPath(body, args.values.path);
} catch (err) {
return filterJSONPath(body, String(args.values.path || ''));
} catch {
// Probably not JSON, try XPath
}
try {
return filterXPath(body, args.values.path);
} catch (err) {
return filterXPath(body, String(args.values.path || ''));
} catch {
// Probably not XML
}
@@ -113,17 +113,14 @@ export const plugin: PluginDefinition = {
name: 'response.body.raw',
description: 'Access the entire response body, as text',
aliases: ['response'],
args: [
requestArg,
behaviorArg,
],
args: [requestArg, behaviorArg],
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
if (!args.values.request) return null;
const response = await getResponse(ctx, {
requestId: args.values.request,
requestId: String(args.values.request || ''),
purpose: args.purpose,
behavior: args.values.behavior ?? null,
behavior: args.values.behavior ? String(args.values.behavior) : null,
});
if (response == null) return null;
@@ -134,7 +131,7 @@ export const plugin: PluginDefinition = {
let body;
try {
body = readFileSync(response.bodyPath, 'utf-8');
} catch (_) {
} catch {
return null;
}
@@ -173,11 +170,18 @@ function filterXPath(body: string, path: string): string {
}
}
async function getResponse(ctx: Context, { requestId, behavior, purpose }: {
requestId: string,
behavior: string | null,
purpose: RenderPurpose,
}): Promise<HttpResponse | null> {
async function getResponse(
ctx: Context,
{
requestId,
behavior,
purpose,
}: {
requestId: string;
behavior: string | null;
purpose: RenderPurpose;
},
): Promise<HttpResponse | null> {
if (!requestId) return null;
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
// it as "smart" during preview.
let finalBehavior = (behavior === 'always' && purpose === 'preview')
? 'smart'
: behavior;
const finalBehavior = behavior === 'always' && purpose === 'preview' ? 'smart' : behavior;
// Send if no responses and "smart," or "always"
if ((finalBehavior === 'smart' && response == null) || finalBehavior === 'always') {

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/template-function-uuid",
"name": "@yaak/template-function-uuid",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"uuid": "^11.1.0"

View File

@@ -1,4 +1,4 @@
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import { v1, v3, v4, v5, v6, v7 } from 'uuid';
export const plugin: PluginDefinition = {

View File

@@ -1,10 +1,11 @@
{
"name": "@yaakapp/template-function-xml",
"name": "@yaak/template-function-xml",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js"
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
},
"dependencies": {
"@xmldom/xmldom": "^0.8.10",

View File

@@ -1,29 +1,37 @@
import { DOMParser } from '@xmldom/xmldom';
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import xpath from 'xpath';
export const plugin: PluginDefinition = {
templateFunctions: [{
name: 'xml.xpath',
description: 'Filter XML-formatted text using XPath syntax',
args: [
{ type: 'text', name: 'input', label: 'Input', multiLine: true, placeholder: '<foo></foo>' },
{ type: 'text', name: 'query', label: 'Query', placeholder: '//foo' },
],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
try {
const doc = new DOMParser().parseFromString(String(args.values.input), 'text/xml');
let result = xpath.select(String(args.values.query), doc, false);
if (Array.isArray(result)) {
return String(result.map(c => String(c.firstChild))[0] ?? '');
} else if (result instanceof Node) {
return String(result.firstChild);
} else {
return String(result);
templateFunctions: [
{
name: 'xml.xpath',
description: 'Filter XML-formatted text using XPath syntax',
args: [
{
type: 'text',
name: 'input',
label: 'Input',
multiLine: true,
placeholder: '<foo></foo>',
},
{ type: 'text', name: 'query', label: 'Query', placeholder: '//foo' },
],
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
try {
const doc = new DOMParser().parseFromString(String(args.values.input), 'text/xml');
const result = xpath.select(String(args.values.query), doc, false);
if (Array.isArray(result)) {
return String(result.map((c) => String(c.firstChild))[0] ?? '');
} else if (result instanceof Node) {
return String(result.firstChild);
} else {
return String(result);
}
} catch {
return null;
}
} catch (e) {
return null;
}
},
},
}],
],
};

View File

@@ -0,0 +1,10 @@
{
"name": "@yaak/themes-yaak",
"private": true,
"version": "0.0.1",
"scripts": {
"build": "yaakcli build ./src/index.ts",
"dev": "yaakcli dev ./src/index.js",
"lint": "tsc --noEmit"
}
}

View File

@@ -0,0 +1,599 @@
import type { PluginDefinition } from '@yaakapp/api';
export const plugin: PluginDefinition = {
themes: [
{
id: 'catppuccin-frappe',
label: 'Catppuccin Frappé',
dark: true,
base: {
surface: 'hsl(231,19%,20%)',
text: 'hsl(227,70%,87%)',
textSubtle: 'hsl(228,29%,73%)',
textSubtlest: 'hsl(227,17%,58%)',
primary: 'hsl(277,59%,76%)',
secondary: 'hsl(228,39%,80%)',
info: 'hsl(222,74%,74%)',
success: 'hsl(96,44%,68%)',
notice: 'hsl(40,62%,73%)',
warning: 'hsl(20,79%,70%)',
danger: 'hsl(359,68%,71%)',
},
components: {
dialog: {
surface: 'hsl(240,21%,12%)',
},
sidebar: {
surface: 'hsl(229,19%,23%)',
border: 'hsl(229,19%,27%)',
},
appHeader: {
surface: 'hsl(229,20%,17%)',
border: 'hsl(229,20%,25%)',
},
responsePane: {
surface: 'hsl(229,19%,23%)',
border: 'hsl(229,19%,27%)',
},
button: {
primary: 'hsl(277,59%,68%)',
secondary: 'hsl(228,39%,72%)',
info: 'hsl(222,74%,67%)',
success: 'hsl(96,44%,61%)',
notice: 'hsl(40,62%,66%)',
warning: 'hsl(20,79%,63%)',
danger: 'hsl(359,68%,64%)',
},
},
},
{
id: 'catppuccin-macchiato',
label: 'Catppuccin Macchiato',
dark: true,
base: {
surface: 'hsl(233,23%,15%)',
text: 'hsl(227,68%,88%)',
textSubtle: 'hsl(227,27%,72%)',
textSubtlest: 'hsl(228,15%,57%)',
primary: 'hsl(267,83%,80%)',
secondary: 'hsl(228,39%,80%)',
info: 'hsl(220,83%,75%)',
success: 'hsl(105,48%,72%)',
notice: 'hsl(40,70%,78%)',
warning: 'hsl(21,86%,73%)',
danger: 'hsl(351,74%,73%)',
},
components: {
dialog: {
surface: 'hsl(240,21%,12%)',
},
sidebar: {
surface: 'hsl(232,23%,18%)',
border: 'hsl(231,23%,22%)',
},
appHeader: {
surface: 'hsl(236,23%,12%)',
border: 'hsl(236,23%,21%)',
},
responsePane: {
surface: 'hsl(232,23%,18%)',
border: 'hsl(231,23%,22%)',
},
button: {
primary: 'hsl(267,82%,72%)',
secondary: 'hsl(228,39%,72%)',
info: 'hsl(220,83%,68%)',
success: 'hsl(105,48%,65%)',
notice: 'hsl(40,70%,70%)',
warning: 'hsl(21,86%,66%)',
danger: 'hsl(351,74%,66%)',
},
},
},
{
id: 'catppuccin-mocha',
label: 'Catppuccin Mocha',
dark: true,
base: {
surface: 'hsl(240,21%,12%)',
text: 'hsl(226,64%,88%)',
textSubtle: 'hsl(228,24%,72%)',
textSubtlest: 'hsl(230,13%,55%)',
primary: 'hsl(267,83%,80%)',
secondary: 'hsl(227,35%,80%)',
info: 'hsl(217,92%,76%)',
success: 'hsl(115,54%,76%)',
notice: 'hsl(41,86%,83%)',
warning: 'hsl(23,92%,75%)',
danger: 'hsl(343,81%,75%)',
},
components: {
dialog: {
surface: 'hsl(240,21%,12%)',
},
sidebar: {
surface: 'hsl(240,21%,15%)',
border: 'hsl(240,21%,19%)',
},
appHeader: {
surface: 'hsl(240,23%,9%)',
border: 'hsl(240,22%,18%)',
},
responsePane: {
surface: 'hsl(240,21%,15%)',
border: 'hsl(240,21%,19%)',
},
button: {
primary: 'hsl(267,67%,65%)',
secondary: 'hsl(227,28%,64%)',
info: 'hsl(217,74%,61%)',
success: 'hsl(115,43%,61%)',
notice: 'hsl(41,69%,66%)',
warning: 'hsl(23,74%,60%)',
danger: 'hsl(343,65%,60%)',
},
},
},
{
id: 'catppuccin-latte',
label: 'Catppuccin Latte',
dark: false,
base: {
surface: 'hsl(220,23%,95%)',
text: 'hsl(234,16%,35%)',
textSubtle: 'hsl(233,10%,47%)',
textSubtlest: 'hsl(231,10%,59%)',
primary: 'hsl(266,85%,58%)',
secondary: 'hsl(233,10%,47%)',
info: 'hsl(231,97%,72%)',
success: 'hsl(183,74%,35%)',
notice: 'hsl(35,77%,49%)',
warning: 'hsl(22,99%,52%)',
danger: 'hsl(355,76%,59%)',
},
components: {
sidebar: {
surface: 'hsl(220,22%,92%)',
border: 'hsl(220,22%,87%)',
},
appHeader: {
surface: 'hsl(220,21%,89%)',
border: 'hsl(220,22%,87%)',
},
},
},
{
id: 'dracula',
label: 'Dracula',
dark: true,
base: {
surface: 'hsl(231,15%,18%)',
surfaceHighlight: 'hsl(230,15%,24%)',
text: 'hsl(60,30%,96%)',
textSubtle: 'hsl(232,14%,65%)',
textSubtlest: 'hsl(232,14%,50%)',
primary: 'hsl(265,89%,78%)',
secondary: 'hsl(225,27%,51%)',
info: 'hsl(191,97%,77%)',
success: 'hsl(135,94%,65%)',
notice: 'hsl(65,92%,76%)',
warning: 'hsl(31,100%,71%)',
danger: 'hsl(0,100%,67%)',
},
components: {
sidebar: {
backdrop: 'hsl(230,15%,24%)',
},
appHeader: {
backdrop: 'hsl(235,14%,15%)',
},
},
},
{
id: 'github-dark',
label: 'GitHub',
dark: true,
base: {
surface: 'hsl(213,30%,7%)',
surfaceHighlight: 'hsl(213,16%,13%)',
text: 'hsl(212,27%,89%)',
textSubtle: 'hsl(212,9%,57%)',
textSubtlest: 'hsl(217,8%,45%)',
border: 'hsl(215,21%,11%)',
primary: 'hsl(262,78%,74%)',
secondary: 'hsl(217,8%,50%)',
info: 'hsl(215,84%,64%)',
success: 'hsl(129,48%,52%)',
notice: 'hsl(39,71%,58%)',
warning: 'hsl(22,83%,60%)',
danger: 'hsl(3,83%,65%)',
},
components: {
button: {
primary: 'hsl(262,79%,71%)',
secondary: 'hsl(217,8%,45%)',
info: 'hsl(215,84%,60%)',
success: 'hsl(129,48%,47%)',
notice: 'hsl(39,71%,53%)',
warning: 'hsl(22,83%,56%)',
danger: 'hsl(3,83%,61%)',
},
},
},
{
id: 'github-light',
label: 'GitHub',
dark: false,
base: {
surface: 'hsl(0,0%,100%)',
surfaceHighlight: 'hsl(210,29%,94%)',
text: 'hsl(213,13%,14%)',
textSubtle: 'hsl(212,9%,43%)',
textSubtlest: 'hsl(203,8%,55%)',
border: 'hsl(210,15%,92%)',
borderSubtle: 'hsl(210,15%,92%)',
primary: 'hsl(261,69%,59%)',
secondary: 'hsl(212,8%,47%)',
info: 'hsl(212,92%,48%)',
success: 'hsl(137,66%,32%)',
notice: 'hsl(40,100%,40%)',
warning: 'hsl(24,100%,44%)',
danger: 'hsl(356,71%,48%)',
},
},
{
id: 'gruvbox',
label: 'Gruvbox',
dark: true,
base: {
surface: 'hsl(0,0%,16%)',
surfaceHighlight: 'hsl(20,3%,19%)',
text: 'hsl(53,74%,91%)',
textSubtle: 'hsl(39,24%,66%)',
textSubtlest: 'hsl(30,12%,51%)',
primary: 'hsl(344,47%,68%)',
secondary: 'hsl(157,16%,58%)',
info: 'hsl(104,35%,62%)',
success: 'hsl(61,66%,44%)',
notice: 'hsl(42,95%,58%)',
warning: 'hsl(27,99%,55%)',
danger: 'hsl(6,96%,59%)',
},
},
{
id: 'hotdog-stand',
label: 'Hotdog Stand',
dark: true,
base: {
surface: 'hsl(0,100%,50%)',
surfaceHighlight: 'hsl(0,0%,0%)',
text: 'hsl(0,0%,100%)',
textSubtle: 'hsl(0,0%,100%)',
textSubtlest: 'hsl(60,100%,50%)',
border: 'hsl(0,0%,0%)',
primary: 'hsl(60,100%,50%)',
secondary: 'hsl(60,100%,50%)',
info: 'hsl(60,100%,50%)',
success: 'hsl(60,100%,50%)',
notice: 'hsl(60,100%,50%)',
warning: 'hsl(60,100%,50%)',
danger: 'hsl(60,100%,50%)',
},
components: {
appHeader: {
surface: 'hsl(0,0%,0%)',
text: 'hsl(0,0%,100%)',
textSubtle: 'hsl(60,100%,50%)',
textSubtlest: 'hsl(0,100%,50%)',
},
menu: {
surface: 'hsl(0,0%,0%)',
border: 'hsl(0,100%,50%)',
surfaceHighlight: 'hsl(0,100%,50%)',
text: 'hsl(0,0%,100%)',
textSubtle: 'hsl(60,100%,50%)',
textSubtlest: 'hsl(60,100%,50%)',
},
button: {
surface: 'hsl(0,0%,0%)',
text: 'hsl(0,0%,100%)',
primary: 'hsl(0,0%,0%)',
secondary: 'hsl(0,0%,100%)',
info: 'hsl(0,0%,0%)',
success: 'hsl(60,100%,50%)',
notice: 'hsl(60,100%,50%)',
warning: 'hsl(0,0%,0%)',
danger: 'hsl(0,100%,50%)',
},
editor: {
primary: 'hsl(0,0%,100%)',
secondary: 'hsl(0,0%,100%)',
info: 'hsl(0,0%,100%)',
success: 'hsl(0,0%,100%)',
notice: 'hsl(60,100%,50%)',
warning: 'hsl(0,0%,100%)',
danger: 'hsl(0,0%,100%)',
},
},
},
{
id: 'monokai-pro',
label: 'Monokai Pro',
dark: true,
base: {
surface: 'hsl(285,5%,17%)',
text: 'hsl(60,25%,98%)',
textSubtle: 'hsl(0,1%,75%)',
textSubtlest: 'hsl(300,0%,57%)',
primary: 'hsl(250,77%,78%)',
secondary: 'hsl(0,1%,75%)',
info: 'hsl(186,71%,69%)',
success: 'hsl(90,59%,66%)',
notice: 'hsl(45,100%,70%)',
warning: 'hsl(20,96%,70%)',
danger: 'hsl(345,100%,69%)',
},
components: {
appHeader: {
surface: 'hsl(300,5%,13%)',
text: 'hsl(0,1%,75%)',
textSubtle: 'hsl(300,0%,57%)',
textSubtlest: 'hsl(300,1%,44%)',
},
button: {
primary: 'hsl(250,77%,70%)',
secondary: 'hsl(0,1%,68%)',
info: 'hsl(186,71%,62%)',
success: 'hsl(90,59%,59%)',
notice: 'hsl(45,100%,63%)',
warning: 'hsl(20,96%,63%)',
danger: 'hsl(345,100%,62%)',
},
},
},
{
id: 'monokai-pro-classic',
label: 'Monokai Pro Classic',
dark: true,
base: {
surface: 'hsl(70,8%,15%)',
text: 'hsl(69,100%,97%)',
textSubtle: 'hsl(65,9%,73%)',
textSubtlest: 'hsl(66,4%,55%)',
primary: 'hsl(261,100%,75%)',
secondary: 'hsl(202,8%,72%)',
info: 'hsl(190,81%,67%)',
success: 'hsl(80,76%,53%)',
notice: 'hsl(54,70%,68%)',
warning: 'hsl(32,98%,56%)',
danger: 'hsl(338,95%,56%)',
},
components: {
appHeader: {
surface: 'hsl(72,9%,11%)',
text: 'hsl(202,8%,72%)',
textSubtle: 'hsl(213,4%,48%)',
textSubtlest: 'hsl(223,6%,44%)',
},
button: {
primary: 'hsl(261,100%,68%)',
secondary: 'hsl(202,8%,65%)',
info: 'hsl(190,81%,60%)',
success: 'hsl(80,76%,48%)',
notice: 'hsl(54,71%,61%)',
warning: 'hsl(32,98%,50%)',
danger: 'hsl(338,95%,50%)',
},
},
},
{
id: 'monokai-pro-machine',
label: 'Monokai Pro Machine',
dark: true,
base: {
surface: 'hsl(200,16%,18%)',
text: 'hsl(173,24%,93%)',
textSubtle: 'hsl(185,6%,57%)',
textSubtlest: 'hsl(189,6%,45%)',
primary: 'hsl(258,86%,80%)',
secondary: 'hsl(175,9%,75%)',
info: 'hsl(194,81%,72%)',
success: 'hsl(98,67%,69%)',
notice: 'hsl(52,100%,72%)',
warning: 'hsl(28,100%,72%)',
danger: 'hsl(353,100%,71%)',
},
components: {
appHeader: {
surface: 'hsl(196,16%,14%)',
text: 'hsl(202,8%,72%)',
textSubtle: 'hsl(213,4%,48%)',
textSubtlest: 'hsl(223,6%,44%)',
},
button: {
primary: 'hsl(258,86%,72%)',
secondary: 'hsl(175,9%,68%)',
info: 'hsl(194,80%,65%)',
success: 'hsl(98,67%,62%)',
notice: 'hsl(52,100%,65%)',
warning: 'hsl(28,100%,65%)',
danger: 'hsl(353,100%,64%)',
},
},
},
{
id: 'monokai-pro-octagon',
label: 'Monokai Pro Octagon',
dark: true,
base: {
surface: 'hsl(233,18%,19%)',
text: 'hsl(173,24%,93%)',
textSubtle: 'hsl(202,8%,72%)',
textSubtlest: 'hsl(213,4%,48%)',
primary: 'hsl(292,30%,70%)',
secondary: 'hsl(202,8%,72%)',
info: 'hsl(155,37%,72%)',
success: 'hsl(75,60%,61%)',
notice: 'hsl(44,100%,71%)',
warning: 'hsl(23,100%,68%)',
danger: 'hsl(352,100%,70%)',
},
components: {
appHeader: {
surface: 'hsl(235,18%,14%)',
text: 'hsl(202,8%,72%)',
textSubtle: 'hsl(213,4%,48%)',
textSubtlest: 'hsl(223,6%,44%)',
},
button: {
primary: 'hsl(292,26%,63%)',
secondary: 'hsl(201,7%,65%)',
info: 'hsl(155,33%,65%)',
success: 'hsl(75,54%,55%)',
notice: 'hsl(44,90%,64%)',
warning: 'hsl(23,90%,61%)',
danger: 'hsl(352,90%,63%)',
},
},
},
{
id: 'monokai-pro-ristretto',
label: 'Monokai Pro Ristretto',
dark: true,
base: {
surface: 'hsl(0,9%,16%)',
text: 'hsl(351,100%,97%)',
textSubtle: 'hsl(355,9%,74%)',
textSubtlest: 'hsl(354,4%,56%)',
primary: 'hsl(239,63%,79%)',
secondary: 'hsl(355,9%,74%)',
info: 'hsl(170,53%,69%)',
success: 'hsl(88,57%,66%)',
notice: 'hsl(41,92%,70%)',
warning: 'hsl(13,85%,70%)',
danger: 'hsl(349,97%,70%)',
},
components: {
appHeader: {
surface: 'hsl(0,8%,12%)',
text: 'hsl(355,9%,74%)',
textSubtle: 'hsl(354,4%,56%)',
textSubtlest: 'hsl(353,4%,43%)',
},
button: {
primary: 'hsl(239,63%,71%)',
secondary: 'hsl(355,9%,67%)',
info: 'hsl(170,53%,62%)',
success: 'hsl(88,57%,59%)',
notice: 'hsl(41,92%,63%)',
warning: 'hsl(13,86%,63%)',
danger: 'hsl(349,97%,63%)',
},
},
},
{
id: 'monokai-pro-spectrum',
label: 'Monokai Pro Spectrum',
dark: true,
base: {
surface: 'hsl(0,0%,13%)',
text: 'hsl(266,100%,97%)',
textSubtle: 'hsl(264,7%,73%)',
textSubtlest: 'hsl(266,3%,55%)',
primary: 'hsl(247,61%,72%)',
secondary: 'hsl(264,7%,73%)',
info: 'hsl(188,74%,63%)',
success: 'hsl(133,54%,66%)',
notice: 'hsl(51,96%,69%)',
warning: 'hsl(23,98%,66%)',
danger: 'hsl(343,96%,68%)',
},
components: {
appHeader: {
surface: 'hsl(0,0%,10%)',
text: 'hsl(264,7%,73%)',
textSubtle: 'hsl(266,3%,55%)',
textSubtlest: 'hsl(264,2%,41%)',
},
button: {
primary: 'hsl(247,61%,65%)',
secondary: 'hsl(264,7%,66%)',
info: 'hsl(188,74%,57%)',
success: 'hsl(133,54%,59%)',
notice: 'hsl(51,96%,62%)',
warning: 'hsl(23,98%,59%)',
danger: 'hsl(343,96%,61%)',
},
},
},
{
id: 'moonlight',
label: 'Moonlight',
dark: true,
base: {
surface: 'hsl(234,23%,17%)',
text: 'hsl(225,71%,90%)',
textSubtle: 'hsl(230,28%,62%)',
textSubtlest: 'hsl(232,26%,43%)',
primary: 'hsl(262,100%,82%)',
secondary: 'hsl(232,18%,65%)',
info: 'hsl(217,100%,74%)',
success: 'hsl(174,66%,54%)',
notice: 'hsl(35,100%,73%)',
warning: 'hsl(17,100%,71%)',
danger: 'hsl(356,100%,73%)',
},
components: {
appHeader: {
surface: 'hsl(233,23%,15%)',
},
sidebar: {
surface: 'hsl(233,23%,15%)',
},
},
},
{
id: 'nord',
label: 'Nord',
dark: true,
base: {
surface: 'hsl(220,16%,22%)',
surfaceHighlight: 'hsl(220,14%,28%)',
text: 'hsl(220,28%,93%)',
textSubtle: 'hsl(220,26%,90%)',
textSubtlest: 'hsl(220,24%,86%)',
primary: 'hsl(193,38%,68%)',
secondary: 'hsl(210,34%,63%)',
info: 'hsl(174,25%,69%)',
success: 'hsl(89,26%,66%)',
notice: 'hsl(40,66%,73%)',
warning: 'hsl(17,48%,64%)',
danger: 'hsl(353,43%,56%)',
},
components: {
sidebar: {
backdrop: 'hsl(220,16%,22%)',
},
appHeader: {
backdrop: 'hsl(220,14%,28%)',
},
},
},
{
id: 'relaxing',
label: 'Relaxing',
dark: true,
base: {
surface: 'hsl(267,33%,17%)',
text: 'hsl(275,49%,92%)',
primary: 'hsl(267,84%,81%)',
secondary: 'hsl(227,35%,80%)',
info: 'hsl(217,92%,76%)',
success: 'hsl(115,54%,76%)',
notice: 'hsl(41,86%,83%)',
warning: 'hsl(23,92%,75%)',
danger: 'hsl(343,81%,75%)',
},
},
],
};

View File

@@ -1,11 +0,0 @@
syntax = "proto3";
package yaak.plugins.runtime;
service PluginRuntime {
rpc EventStream (stream EventStreamEvent) returns (stream EventStreamEvent);
}
message EventStreamEvent {
string event = 1;
}

366
src-tauri/Cargo.lock generated
View File

@@ -207,7 +207,7 @@ version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07"
dependencies = [
"brotli 8.0.1",
"brotli",
"flate2",
"futures-core",
"memchr",
@@ -394,7 +394,7 @@ dependencies = [
"http",
"http-body",
"http-body-util",
"itoa 1.0.15",
"itoa",
"matchit",
"memchr",
"mime",
@@ -566,17 +566,6 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "brotli"
version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
"brotli-decompressor 4.0.3",
]
[[package]]
name = "brotli"
version = "8.0.1"
@@ -585,17 +574,7 @@ checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
"brotli-decompressor 5.0.0",
]
[[package]]
name = "brotli-decompressor"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
"brotli-decompressor",
]
[[package]]
@@ -1143,16 +1122,25 @@ dependencies = [
]
[[package]]
name = "cssparser"
version = "0.27.2"
name = "csscolorparser"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a"
checksum = "5fda6aace1fbef3aa217b27f4c8d7d071ef2a70a5ca51050b1f17d40299d3f16"
dependencies = [
"phf 0.11.3",
]
[[package]]
name = "cssparser"
version = "0.29.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa"
dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa 0.4.8",
"itoa",
"matches",
"phf 0.8.0",
"phf 0.10.1",
"proc-macro2",
"quote",
"smallvec",
@@ -1318,7 +1306,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -2275,15 +2263,6 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hex_color"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d37f101bf4c633f7ca2e4b5e136050314503dd198e78e325ea602c327c484ef0"
dependencies = [
"rand 0.8.5",
]
[[package]]
name = "hkdf"
version = "0.12.4"
@@ -2304,16 +2283,14 @@ dependencies = [
[[package]]
name = "html5ever"
version = "0.26.0"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c"
dependencies = [
"log",
"mac",
"markup5ever",
"proc-macro2",
"quote",
"syn 1.0.109",
"match_token",
]
[[package]]
@@ -2324,7 +2301,7 @@ checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
dependencies = [
"bytes",
"fnv",
"itoa 1.0.15",
"itoa",
]
[[package]]
@@ -2382,7 +2359,7 @@ dependencies = [
"http-body",
"httparse",
"httpdate",
"itoa 1.0.15",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
@@ -2756,12 +2733,6 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.15"
@@ -2907,14 +2878,13 @@ dependencies = [
[[package]]
name = "kuchikiki"
version = "0.8.2"
version = "0.8.8-speedreader"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8"
checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2"
dependencies = [
"cssparser",
"html5ever",
"indexmap 1.9.3",
"matches",
"indexmap 2.9.0",
"selectors",
]
@@ -3130,18 +3100,29 @@ dependencies = [
[[package]]
name = "markup5ever"
version = "0.11.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
dependencies = [
"log",
"phf 0.10.1",
"phf_codegen 0.10.0",
"phf 0.11.3",
"phf_codegen 0.11.3",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "match_token"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
name = "matches"
version = "0.1.10"
@@ -3160,6 +3141,12 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "md5"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
[[package]]
name = "memchr"
version = "2.7.4"
@@ -3227,9 +3214,9 @@ dependencies = [
[[package]]
name = "muda"
version = "0.16.1"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4de14a9b5d569ca68d7c891d613b390cf5ab4f851c77aaa2f9e435555d3d9492"
checksum = "58b89bf91c19bf036347f1ab85a81c560f08c0667c8601bece664d860a600988"
dependencies = [
"crossbeam-channel",
"dpi",
@@ -3961,9 +3948,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
"phf_macros 0.8.0",
"phf_shared 0.8.0",
"proc-macro-hack",
]
[[package]]
@@ -3972,7 +3957,9 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
"phf_macros 0.10.0",
"phf_shared 0.10.0",
"proc-macro-hack",
]
[[package]]
@@ -3997,12 +3984,12 @@ dependencies = [
[[package]]
name = "phf_codegen"
version = "0.10.0"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator 0.10.0",
"phf_shared 0.10.0",
"phf_generator 0.11.3",
"phf_shared 0.11.3",
]
[[package]]
@@ -4037,12 +4024,12 @@ dependencies = [
[[package]]
name = "phf_macros"
version = "0.8.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
dependencies = [
"phf_generator 0.8.0",
"phf_shared 0.8.0",
"phf_generator 0.10.0",
"phf_shared 0.10.0",
"proc-macro-hack",
"proc-macro2",
"quote",
@@ -5116,22 +5103,20 @@ dependencies = [
[[package]]
name = "selectors"
version = "0.22.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe"
checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416"
dependencies = [
"bitflags 1.3.2",
"cssparser",
"derive_more",
"fxhash",
"log",
"matches",
"phf 0.8.0",
"phf_codegen 0.8.0",
"precomputed-hash",
"servo_arc",
"smallvec",
"thin-slice",
]
[[package]]
@@ -5212,7 +5197,7 @@ version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa 1.0.15",
"itoa",
"memchr",
"ryu",
"serde",
@@ -5245,7 +5230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa 1.0.15",
"itoa",
"ryu",
"serde",
]
@@ -5287,7 +5272,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap 2.9.0",
"itoa 1.0.15",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
@@ -5338,9 +5323,9 @@ dependencies = [
[[package]]
name = "servo_arc"
version = "0.1.1"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432"
checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741"
dependencies = [
"nodrop",
"stable_deref_trait",
@@ -5637,9 +5622,9 @@ dependencies = [
[[package]]
name = "tao"
version = "0.33.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e59c1f38e657351a2e822eadf40d6a2ad4627b9c25557bc1180ec1b3295ef82"
checksum = "49c380ca75a231b87b6c9dd86948f035012e7171d1a7c40a9c2890489a7ffd8a"
dependencies = [
"bitflags 2.9.1",
"core-foundation 0.10.1",
@@ -5710,17 +5695,16 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tauri"
version = "2.5.1"
version = "2.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7b0bc1aec81bda6bc455ea98fcaed26b3c98c1648c627ad6ff1c704e8bf8cbc"
checksum = "124e129c9c0faa6bec792c5948c89e86c90094133b0b9044df0ce5f0a8efaa0d"
dependencies = [
"anyhow",
"bytes",
"dirs",
"dunce",
"embed_plist",
"futures-util",
"getrandom 0.2.16",
"getrandom 0.3.3",
"glob",
"gtk",
"heck 0.5.0",
@@ -5762,9 +5746,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a0350f0df1db385ca5c02888a83e0e66655c245b7443db8b78a70da7d7f8fc"
checksum = "12f025c389d3adb83114bec704da973142e82fc6ec799c7c750c5e21cefaec83"
dependencies = [
"anyhow",
"cargo_toml",
@@ -5784,12 +5768,12 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93f035551bf7b11b3f51ad9bc231ebbe5e085565527991c16cf326aa38cdf47"
checksum = "f5df493a1075a241065bc865ed5ef8d0fbc1e76c7afdc0bf0eccfaa7d4f0e406"
dependencies = [
"base64 0.22.1",
"brotli 7.0.0",
"brotli",
"ico",
"json-patch",
"plist",
@@ -5811,9 +5795,9 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "2.2.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8db4df25e2d9d45de0c4c910da61cd5500190da14ae4830749fee3466dddd112"
checksum = "f237fbea5866fa5f2a60a21bea807a2d6e0379db070d89c3a10ac0f2d4649bbc"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -5825,9 +5809,9 @@ dependencies = [
[[package]]
name = "tauri-plugin"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37a5ebe6a610d1b78a94650896e6f7c9796323f408800cef436e0fa0539de601"
checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3"
dependencies = [
"anyhow",
"glob",
@@ -5842,9 +5826,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-clipboard-manager"
version = "2.2.2"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab4cb42fdf745229b768802e9180920a4be63122cf87ed1c879103f7609d98e"
checksum = "adddd9e9275b20e77af3061d100a25a884cced3c4c9ef680bd94dd0f7e26c1ca"
dependencies = [
"arboard",
"log",
@@ -5857,9 +5841,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-deep-link"
version = "2.3.0"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4976ac728ebc0487515aa956cfdf200abcc52b784e441493fc544bc6ce369c8"
checksum = "ab261eb006db10ab478e3fbb5a4e2692df3f7eb3e28300ee2b64428979167ed0"
dependencies = [
"dunce",
"rust-ini",
@@ -5877,9 +5861,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
version = "2.2.2"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33318fe222fc2a612961de8b0419e2982767f213f54a4d3a21b0d7b85c41df8"
checksum = "1aefb14219b492afb30b12647b5b1247cadd2c0603467310c36e0f7ae1698c28"
dependencies = [
"log",
"raw-window-handle",
@@ -5895,9 +5879,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs"
version = "2.3.0"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ead0daec5d305adcefe05af9d970fc437bcc7996052d564e7393eb291252da"
checksum = "c341290d31991dbca38b31d412c73dfbdb070bb11536784f19dd2211d13b778f"
dependencies = [
"anyhow",
"dunce",
@@ -5917,9 +5901,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-log"
version = "2.4.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d2b582d860eb214f28323f4ce4f2797ae3b78f197e27b11677f976f9f52aedb"
checksum = "a59139183e0907cec1499dddee4e085f5a801dc659efa0848ee224f461371426"
dependencies = [
"android_logger",
"byte-unit",
@@ -5939,9 +5923,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-opener"
version = "2.2.7"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66644b71a31ec1a8a52c4a16575edd28cf763c87cf4a7da24c884122b5c77097"
checksum = "ecee219f11cdac713ab32959db5d0cceec4810ba4f4458da992292ecf9660321"
dependencies = [
"dunce",
"glob",
@@ -5961,9 +5945,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-os"
version = "2.2.1"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "424f19432397850c2ddd42aa58078630c15287bbce3866eb1d90e7dbee680637"
checksum = "05bccb4c6de4299beec5a9b070878a01bce9e2c945aa7a75bcea38bcba4c675d"
dependencies = [
"gethostname 1.0.2",
"log",
@@ -5979,9 +5963,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-shell"
version = "2.2.1"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69d5eb3368b959937ad2aeaf6ef9a8f5d11e01ffe03629d3530707bbcb27ff5d"
checksum = "2b9ffadec5c3523f11e8273465cacb3d86ea7652a28e6e2a2e9b5c182f791d25"
dependencies = [
"encoding_rs",
"log",
@@ -6000,9 +5984,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-single-instance"
version = "2.2.4"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d0e07b40fb2eb13778e30778f5979347a2bf30e1b9d47f78ff7fe92d2e4b3d"
checksum = "b441b6d5d1a194e9fee0b358fe0d602ded845d0f580e1f8c8ef78ebc3c8b225d"
dependencies = [
"serde",
"serde_json",
@@ -6010,15 +5994,15 @@ dependencies = [
"tauri-plugin-deep-link",
"thiserror 2.0.12",
"tracing",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
"zbus",
]
[[package]]
name = "tauri-plugin-updater"
version = "2.7.1"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f05c38afd77a4b8fd98e8fb6f1cdbb5fbb8a46ba181eb2758b05321e3c6209"
checksum = "27cbc31740f4d507712550694749572ec0e43bdd66992db7599b89fbfd6b167b"
dependencies = [
"base64 0.22.1",
"dirs",
@@ -6042,15 +6026,15 @@ dependencies = [
"time",
"tokio",
"url",
"windows-sys 0.59.0",
"zip 2.4.2",
"windows-sys 0.60.2",
"zip",
]
[[package]]
name = "tauri-plugin-window-state"
version = "2.2.2"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a27a3fe49de72adbe0d84aee33c89a0b059722cd0b42aaeab29eaaee7f7535cd"
checksum = "5a3d22b21b9cec73601b512a868f7c74f93c044d44fd6ca1c84e9d6afb6b1559"
dependencies = [
"bitflags 2.9.1",
"log",
@@ -6063,9 +6047,9 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00f004905d549854069e6774533d742b03cacfd6f03deb08940a8677586cbe39"
checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4"
dependencies = [
"cookie",
"dpi",
@@ -6085,9 +6069,9 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "2.6.0"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f85d056f4d4b014fe874814034f3416d57114b617a493a4fe552580851a3f3a2"
checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad"
dependencies = [
"gtk",
"http",
@@ -6112,12 +6096,12 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2900399c239a471bcff7f15c4399eb1a8c4fe511ba2853e07c996d771a5e0a4"
checksum = "41743bbbeb96c3a100d234e5a0b60a46d5aa068f266160862c7afdbf828ca02e"
dependencies = [
"anyhow",
"brotli 7.0.0",
"brotli",
"cargo_metadata",
"ctor",
"dunce",
@@ -6192,12 +6176,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "thin-slice"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -6256,7 +6234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
dependencies = [
"deranged",
"itoa 1.0.15",
"itoa",
"libc",
"num-conv",
"num_threads",
@@ -6609,9 +6587,9 @@ dependencies = [
[[package]]
name = "tray-icon"
version = "0.20.1"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7eee98ec5c90daf179d55c20a49d8c0d043054ce7c26336c09a24d31f14fa0"
checksum = "2da75ec677957aa21f6e0b361df0daab972f13a5bee3606de0638fd4ee1c666a"
dependencies = [
"crossbeam-channel",
"dirs",
@@ -7186,9 +7164,9 @@ dependencies = [
[[package]]
name = "webview2-com"
version = "0.37.0"
version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b542b5cfbd9618c46c2784e4d41ba218c336ac70d44c55e47b251033e7d85601"
checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4"
dependencies = [
"webview2-com-macros",
"webview2-com-sys",
@@ -7211,9 +7189,9 @@ dependencies = [
[[package]]
name = "webview2-com-sys"
version = "0.37.0"
version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae2d11c4a686e4409659d7891791254cf9286d3cfe0eef54df1523533d22295"
checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c"
dependencies = [
"thiserror 2.0.12",
"windows",
@@ -7412,6 +7390,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.2",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
@@ -7451,13 +7438,29 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows-threading"
version = "0.1.0"
@@ -7494,6 +7497,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@@ -7512,6 +7521,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@@ -7530,12 +7545,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@@ -7554,6 +7581,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@@ -7572,6 +7605,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@@ -7590,6 +7629,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@@ -7608,6 +7653,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
version = "0.5.40"
@@ -7672,9 +7723,9 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
[[package]]
name = "wry"
version = "0.51.2"
version = "0.52.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c886a0a9d2a94fd90cfa1d929629b79cfefb1546e2c7430c63a47f0664c0e4e2"
checksum = "12a714d9ba7075aae04a6e50229d6109e3d584774b99a6a8c60de1698ca111b9"
dependencies = [
"base64 0.22.1",
"block2 0.6.1",
@@ -7781,7 +7832,7 @@ dependencies = [
"eventsource-client",
"http",
"log",
"md5",
"md5 0.8.0",
"mime_guess",
"openssl-sys",
"rand 0.9.1",
@@ -7889,7 +7940,7 @@ dependencies = [
"hyper-rustls",
"hyper-util",
"log",
"md5",
"md5 0.7.0",
"prost",
"prost-reflect",
"prost-types",
@@ -7938,7 +7989,7 @@ name = "yaak-mac-window"
version = "0.1.0"
dependencies = [
"cocoa",
"hex_color",
"csscolorparser",
"log",
"objc",
"rand 0.9.1",
@@ -7981,7 +8032,7 @@ dependencies = [
"futures-util",
"hex",
"log",
"md5",
"md5 0.7.0",
"path-slash",
"rand 0.9.1",
"regex",
@@ -8051,7 +8102,7 @@ version = "0.1.0"
dependencies = [
"futures-util",
"log",
"md5",
"md5 0.7.0",
"serde",
"serde_json",
"tauri",
@@ -8244,21 +8295,6 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "zip"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50"
dependencies = [
"arbitrary",
"crc32fast",
"crossbeam-utils",
"displaydoc",
"indexmap 2.9.0",
"memchr",
"thiserror 2.0.12",
]
[[package]]
name = "zip"
version = "4.0.0"
@@ -8293,7 +8329,7 @@ checksum = "aed5f10c571472911e37d8f7601a8dfba52b4f7f73a344015291b82ab292faf6"
dependencies = [
"log",
"thiserror 2.0.12",
"zip 4.0.0",
"zip",
]
[[package]]

View File

@@ -46,7 +46,7 @@ encoding_rs = "0.8.35"
eventsource-client = { git = "https://github.com/yaakapp/rust-eventsource-client", version = "0.14.0" }
http = { version = "1.2.0", default-features = false }
log = "0.4.27"
md5 = "0.7.0"
md5 = "0.8.0"
mime_guess = "2.0.5"
rand = "0.9.0"
reqwest = { workspace = true, features = ["multipart", "cookies", "gzip", "brotli", "deflate", "json", "rustls-tls-manual-roots-no-provider", "socks"] }
@@ -54,17 +54,17 @@ reqwest_cookie_store = "0.8.0"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["raw_value"] }
tauri = { workspace = true, features = ["devtools", "protocol-asset"] }
tauri-plugin-clipboard-manager = "2.2.2"
tauri-plugin-clipboard-manager = "2.3.0"
tauri-plugin-dialog = { workspace = true }
tauri-plugin-fs = "2.3.0"
tauri-plugin-log = { version = "2.4.0", features = ["colored"] }
tauri-plugin-opener = "2.2.6"
tauri-plugin-os = "2.2.1"
tauri-plugin-fs = "2.4.0"
tauri-plugin-log = { version = "2.6.0", features = ["colored"] }
tauri-plugin-opener = "2.4.0"
tauri-plugin-os = "2.3.0"
tauri-plugin-shell = { workspace = true }
tauri-plugin-deep-link = "2.3.0"
tauri-plugin-single-instance = { version = "2.2.4", features = ["deep-link"] }
tauri-plugin-updater = "2.7.1"
tauri-plugin-window-state = "2.2.2"
tauri-plugin-deep-link = "2.4.0"
tauri-plugin-single-instance = { version = "2.3.0", features = ["deep-link"] }
tauri-plugin-updater = "2.9.0"
tauri-plugin-window-state = "2.3.0"
thiserror = { workspace = true }
tokio = { workspace = true, features = ["sync"] }
tokio-stream = "0.1.17"
@@ -90,10 +90,10 @@ hex = "0.4.3"
reqwest = "0.12.20"
serde = "1.0.219"
serde_json = "1.0.140"
tauri = "2.5.1"
tauri-plugin = "2.2.0"
tauri-plugin-dialog = "2.2.2"
tauri-plugin-shell = "2.2.1"
tauri = "2.6.2"
tauri-plugin = "2.3.0"
tauri-plugin-dialog = "2.3.0"
tauri-plugin-shell = "2.3.0"
tokio = "1.45.1"
thiserror = "2.0.12"
ts-rs = "11.0.1"

View File

@@ -1,9 +1,12 @@
use crate::error::Result;
use tauri::{command, AppHandle, Manager, Runtime, WebviewWindow};
use tauri::{command, AppHandle, Manager, Runtime, State, WebviewWindow};
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
use yaak_crypto::manager::EncryptionManagerExt;
use yaak_plugins::events::PluginWindowContext;
use yaak_plugins::native_template_functions::{decrypt_secure_template_function, encrypt_secure_template_function};
use yaak_plugins::events::{GetThemesResponse, PluginWindowContext};
use yaak_plugins::manager::PluginManager;
use yaak_plugins::native_template_functions::{
decrypt_secure_template_function, encrypt_secure_template_function,
};
#[command]
pub(crate) async fn cmd_show_workspace_key<R: Runtime>(
@@ -38,3 +41,11 @@ pub(crate) async fn cmd_secure_template<R: Runtime>(
let window_context = &PluginWindowContext::new(&window);
Ok(encrypt_secure_template_function(&app_handle, window_context, template)?)
}
#[command]
pub(crate) async fn cmd_get_themes<R: Runtime>(
window: WebviewWindow<R>,
plugin_manager: State<'_, PluginManager>,
) -> Result<Vec<GetThemesResponse>> {
Ok(plugin_manager.get_themes(&window).await?)
}

View File

@@ -36,7 +36,8 @@ use yaak_models::models::{
use yaak_models::query_manager::QueryManagerExt;
use yaak_models::util::{BatchUpsertResult, UpdateSource, get_workspace_export_resources};
use yaak_plugins::events::{
CallHttpRequestActionRequest, FilterResponse, GetHttpAuthenticationConfigResponse,
CallGrpcRequestActionRequest, CallHttpRequestActionRequest, FilterResponse,
GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse,
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
GetTemplateFunctionsResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
PluginWindowContext, RenderPurpose,
@@ -791,6 +792,14 @@ async fn cmd_http_request_actions<R: Runtime>(
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]
async fn cmd_template_functions<R: Runtime>(
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?)
}
#[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]
async fn cmd_call_http_authentication_action<R: Runtime>(
window: WebviewWindow<R>,
@@ -1220,6 +1238,7 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![
cmd_call_http_authentication_action,
cmd_call_http_request_action,
cmd_call_grpc_request_action,
cmd_check_for_updates,
cmd_create_grpc_request,
cmd_curl_to_request,
@@ -1236,6 +1255,7 @@ pub fn run() {
cmd_get_workspace_meta,
cmd_grpc_go,
cmd_grpc_reflect,
cmd_grpc_request_actions,
cmd_http_request_actions,
cmd_import_data,
cmd_install_plugin,
@@ -1255,6 +1275,7 @@ pub fn run() {
//
// Migrated commands
crate::commands::cmd_decrypt_template,
crate::commands::cmd_get_themes,
crate::commands::cmd_secure_template,
crate::commands::cmd_show_workspace_key,
])

View File

@@ -1,6 +1,6 @@
use crate::http_request::send_http_request;
use crate::render::{render_http_request, render_json_value};
use crate::window::{CreateWindowConfig, create_window};
use crate::render::{render_grpc_request, render_http_request, render_json_value};
use crate::window::{create_window, CreateWindowConfig};
use crate::{
call_frontend, cookie_jar_from_window, environment_from_window, get_window_from_window_context,
workspace_from_window,
@@ -13,13 +13,7 @@ use tauri_plugin_clipboard_manager::ClipboardExt;
use yaak_models::models::{HttpResponse, Plugin};
use yaak_models::query_manager::QueryManagerExt;
use yaak_models::util::UpdateSource;
use yaak_plugins::events::{
Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse,
GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload,
ListCookieNamesResponse, PluginWindowContext, RenderHttpRequestResponse,
SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest, TemplateRenderResponse,
WindowNavigateEvent,
};
use yaak_plugins::events::{Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload, ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse, RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest, TemplateRenderResponse, WindowNavigateEvent};
use yaak_plugins::manager::PluginManager;
use yaak_plugins::plugin_handle::PluginHandle;
use yaak_plugins::template_callback::PluginTemplateCallback;
@@ -68,6 +62,30 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
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) => {
let window = get_window_from_window_context(app_handle, &window_context)
.expect("Failed to find window for render http request");

View File

@@ -265,7 +265,7 @@ pub fn git_status(dir: &Path) -> Result<GitStatusSummary> {
None => None,
Some(t) => match t.get_path(&Path::new(&rela_path)) {
Ok(entry) => {
let obj = entry.to_object(&repo).unwrap();
let obj = entry.to_object(&repo)?;
let content = obj.as_blob().unwrap().content();
let name = Path::new(entry.name().unwrap_or_default());
SyncModel::from_bytes(content.into(), name)?.map(|m| m.0)

View File

@@ -1,13 +1,13 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashSet};
use std::env::temp_dir;
use std::ops::Deref;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use crate::client::AutoReflectionClient;
use anyhow::anyhow;
use async_recursion::async_recursion;
use log::{debug, warn};
use log::{debug, info, warn};
use prost::Message;
use prost_reflect::{DescriptorPool, MethodDescriptor};
use prost_types::{FileDescriptorProto, FileDescriptorSet};
@@ -46,24 +46,51 @@ pub async fn fill_pool_from_files(
desc_path.to_string_lossy().to_string(),
];
let mut include_dirs = HashSet::new();
let mut include_protos = HashSet::new();
for p in paths {
if p.as_path().exists() {
args.push(p.to_string_lossy().to_string());
} else {
if !p.exists() {
continue;
}
// Dirs are added as includes
if p.is_dir() {
include_dirs.insert(p.to_string_lossy().to_string());
continue;
}
let parent = p.as_path().parent();
if let Some(parent_path) = parent {
args.push("-I".to_string());
args.push(parent_path.to_string_lossy().to_string());
args.push("-I".to_string());
args.push(parent_path.parent().unwrap().to_string_lossy().to_string());
match find_parent_proto_dir(parent_path) {
None => {
// Add parent/grandparent as fallback
include_dirs.insert(parent_path.to_string_lossy().to_string());
if let Some(grandparent_path) = parent_path.parent() {
include_dirs.insert(grandparent_path.to_string_lossy().to_string());
}
}
Some(p) => {
include_dirs.insert(p.to_string_lossy().to_string());
}
};
} else {
debug!("ignoring {:?} since it does not exist.", parent)
}
include_protos.insert(p.to_string_lossy().to_string());
}
for d in include_dirs.clone() {
args.push("-I".to_string());
args.push(d);
}
for p in include_protos.clone() {
args.push(p);
}
info!("Invoking protoc with {}", args.join(" "));
let out = app_handle
.shell()
.sidecar("yaakprotoc")
@@ -365,3 +392,22 @@ mod topology {
}
}
}
fn find_parent_proto_dir(start_path: impl AsRef<Path>) -> Option<PathBuf> {
let mut dir = start_path.as_ref().canonicalize().ok()?;
loop {
if let Some(name) = dir.file_name().and_then(|n| n.to_str()) {
if name == "proto" {
return Some(dir);
}
}
let parent = dir.parent()?;
if parent == dir {
return None; // Reached root
}
dir = parent.to_path_buf();
}
}

View File

@@ -10,10 +10,10 @@ tauri-plugin = { workspace = true, features = ["build"] }
[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.26.0"
hex_color = "3.0.0"
log = "0.4.27"
objc = "0.2.7"
rand = "0.9.0"
csscolorparser = "0.7.2"
[dependencies]
tauri = { workspace = true }

View File

@@ -1,4 +1,4 @@
use tauri::{Runtime, Window, command};
use tauri::{command, Runtime, Window};
#[command]
pub(crate) fn set_title<R: Runtime>(window: Window<R>, title: &str) {
@@ -18,12 +18,13 @@ pub(crate) fn set_title<R: Runtime>(window: Window<R>, title: &str) {
pub(crate) fn set_theme<R: Runtime>(window: Window<R>, bg_color: &str) {
#[cfg(target_os = "macos")]
{
match hex_color::HexColor::parse_rgb(bg_color.trim()) {
use log::warn;
match csscolorparser::parse(bg_color.trim()) {
Ok(color) => {
crate::mac::update_window_theme(window, color);
}
Err(err) => {
log::warn!("Failed to parse background color '{}': {}", bg_color, err)
warn!("Failed to parse background color '{}': {}", bg_color, err)
}
}
}

View File

@@ -1,5 +1,5 @@
#![allow(deprecated)]
use hex_color::HexColor;
use csscolorparser::Color;
use objc::{msg_send, sel, sel_impl};
use tauri::{Emitter, Runtime, Window};
@@ -35,12 +35,12 @@ pub(crate) fn update_window_title<R: Runtime>(window: Window<R>, title: String)
}
}
pub(crate) fn update_window_theme<R: Runtime>(window: Window<R>, color: HexColor) {
pub(crate) fn update_window_theme<R: Runtime>(window: Window<R>, color: Color) {
use cocoa::appkit::{
NSAppearance, NSAppearanceNameVibrantDark, NSAppearanceNameVibrantLight, NSWindow,
};
let brightness = (color.r as u64 + color.g as u64 + color.b as u64) / 3;
let brightness = (color.r as f64 + color.g as f64 + color.b as f64) / 3.0;
let label = window.label().to_string();
unsafe {
@@ -49,7 +49,7 @@ pub(crate) fn update_window_theme<R: Runtime>(window: Window<R>, color: HexColor
let _ = window.run_on_main_thread(move || {
let handle = window_handle;
let selected_appearance = if brightness >= 128 {
let selected_appearance = if brightness >= 0.5 {
NSAppearance(NSAppearanceNameVibrantLight)
} else {
NSAppearance(NSAppearanceNameVibrantDark)

View File

@@ -1,5 +1,6 @@
use crate::connection_or_tx::ConnectionOrTx;
use crate::error::Error::DBRowNotFound;
use crate::error::Error::ModelNotFound;
use crate::error::Result;
use crate::models::{AnyModel, UpsertModelInfo};
use crate::util::{ModelChangeEvent, ModelPayload, UpdateSource};
use log::error;
@@ -9,6 +10,7 @@ use sea_query::{
SqliteQueryBuilder,
};
use sea_query_rusqlite::RusqliteBinder;
use std::fmt::Debug;
use std::sync::mpsc;
pub struct DbContext<'a> {
@@ -19,15 +21,32 @@ pub struct DbContext<'a> {
impl<'a> DbContext<'a> {
pub(crate) fn find_one<'s, M>(
&self,
col: impl IntoColumnRef,
value: impl Into<SimpleExpr>,
) -> crate::error::Result<M>
col: impl IntoColumnRef + IntoIden + Clone,
value: impl Into<SimpleExpr> + Debug,
) -> Result<M>
where
M: Into<AnyModel> + Clone + UpsertModelInfo,
{
match self.find_optional::<M>(col, value) {
Some(v) => Ok(v),
None => Err(DBRowNotFound(format!("{:?}", M::table_name()))),
let value_debug = format!("{:?}", value);
let value_expr = value.into();
let (sql, params) = Query::select()
.from(M::table_name())
.column(Asterisk)
.cond_where(Expr::col(col.clone()).eq(value_expr))
.build_rusqlite(SqliteQueryBuilder);
let mut stmt = self.conn.prepare(sql.as_str()).expect("Failed to prepare query");
match stmt.query_row(&*params.as_params(), M::from_row) {
Ok(result) => Ok(result),
Err(rusqlite::Error::QueryReturnedNoRows) => {
Err(ModelNotFound(format!(
r#"table "{}" {} == {}"#,
M::table_name().into_iden().to_string(),
col.into_iden().to_string(),
value_debug
)))
}
Err(e) => Err(crate::error::Error::SqlError(e)),
}
}

View File

@@ -20,7 +20,7 @@ pub enum Error {
#[error("Model error: {0}")]
GenericError(String),
#[error("DB Migration Failed: {0}")]
MigrationError(String),
@@ -30,9 +30,6 @@ pub enum Error {
#[error("Multiple base environments for {0}. Delete duplicates before continuing.")]
MultipleBaseEnvironments(String),
#[error("Database row not found: {0}")]
DBRowNotFound(String),
#[error("unknown error")]
Unknown,
}

View File

@@ -123,7 +123,7 @@ pub struct Settings {
}
impl UpsertModelInfo for Settings {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
SettingsIden::Table
}
@@ -252,7 +252,7 @@ pub struct Workspace {
}
impl UpsertModelInfo for Workspace {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
WorkspaceIden::Table
}
@@ -355,7 +355,7 @@ pub struct WorkspaceMeta {
}
impl UpsertModelInfo for WorkspaceMeta {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
WorkspaceMetaIden::Table
}
@@ -456,7 +456,7 @@ pub struct CookieJar {
}
impl UpsertModelInfo for CookieJar {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
CookieJarIden::Table
}
@@ -535,7 +535,7 @@ pub struct Environment {
}
impl UpsertModelInfo for Environment {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
EnvironmentIden::Table
}
@@ -655,7 +655,7 @@ pub struct Folder {
}
impl UpsertModelInfo for Folder {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
FolderIden::Table
}
@@ -786,7 +786,7 @@ pub struct HttpRequest {
}
impl UpsertModelInfo for HttpRequest {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
HttpRequestIden::Table
}
@@ -913,7 +913,7 @@ pub struct WebsocketConnection {
}
impl UpsertModelInfo for WebsocketConnection {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
WebsocketConnectionIden::Table
}
@@ -1027,7 +1027,7 @@ pub struct WebsocketRequest {
}
impl UpsertModelInfo for WebsocketRequest {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
WebsocketRequestIden::Table
}
@@ -1152,7 +1152,7 @@ pub struct WebsocketEvent {
}
impl UpsertModelInfo for WebsocketEvent {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
WebsocketEventIden::Table
}
@@ -1269,7 +1269,7 @@ pub struct HttpResponse {
}
impl UpsertModelInfo for HttpResponse {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
HttpResponseIden::Table
}
@@ -1377,7 +1377,7 @@ pub struct GraphQlIntrospection {
}
impl UpsertModelInfo for GraphQlIntrospection {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
GraphQlIntrospectionIden::Table
}
@@ -1461,7 +1461,7 @@ pub struct GrpcRequest {
}
impl UpsertModelInfo for GrpcRequest {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
GrpcRequestIden::Table
}
@@ -1588,7 +1588,7 @@ pub struct GrpcConnection {
}
impl UpsertModelInfo for GrpcConnection {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
GrpcConnectionIden::Table
}
@@ -1708,7 +1708,7 @@ pub struct GrpcEvent {
}
impl UpsertModelInfo for GrpcEvent {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
GrpcEventIden::Table
}
@@ -1799,7 +1799,7 @@ pub struct Plugin {
}
impl UpsertModelInfo for Plugin {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
PluginIden::Table
}
@@ -1881,7 +1881,7 @@ pub struct SyncState {
}
impl UpsertModelInfo for SyncState {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
SyncStateIden::Table
}
@@ -1964,7 +1964,7 @@ pub struct KeyValue {
}
impl UpsertModelInfo for KeyValue {
fn table_name() -> impl IntoTableRef + Debug {
fn table_name() -> impl IntoTableRef + IntoIden {
KeyValueIden::Table
}
@@ -2181,7 +2181,7 @@ impl AnyModel {
}
pub trait UpsertModelInfo {
fn table_name() -> impl IntoTableRef + Debug;
fn table_name() -> impl IntoTableRef + IntoIden;
fn id_column() -> impl IntoIden + Eq + Clone;
fn generate_id() -> String;
fn order_by() -> (impl IntoColumnRef, Order);

View File

@@ -6,6 +6,10 @@ export type BootRequest = { dir: string, watch: boolean, };
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 CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
@@ -336,14 +340,14 @@ export type GetCookieValueRequest = { name: string, };
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 GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
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 GetHttpRequestByIdRequest = { id: string, };
@@ -356,6 +360,12 @@ export type GetKeyValueResponse = { value?: string, };
export type GetTemplateFunctionsResponse = { functions: Array<TemplateFunction>, pluginRefId: string, };
export type GetThemesRequest = Record<string, never>;
export type GetThemesResponse = { themes: Array<Theme>, };
export type GrpcRequestAction = { label: string, icon?: Icon, };
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
export type HttpHeader = { name: string, value: string, };
@@ -372,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 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": "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;
@@ -404,6 +414,10 @@ required?: boolean, };
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 RenderHttpRequestResponse = { httpRequest: HttpRequest, };
@@ -436,6 +450,32 @@ export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, }
export type TemplateRenderResponse = { data: JsonValue, };
export type Theme = {
/**
* How the theme is identified. This should never be changed
*/
id: string,
/**
* The friendly name of the theme to be displayed to the user
*/
label: string,
/**
* Whether the theme will be used for dark or light appearance
*/
dark: boolean,
/**
* The default top-level colors for the theme
*/
base: ThemeComponentColors,
/**
* Optionally override theme for individual UI components for more control
*/
components?: ThemeComponents, };
export type ThemeComponentColors = { surface?: string, surfaceHighlight?: string, surfaceActive?: string, text?: string, textSubtle?: string, textSubtlest?: string, border?: string, borderSubtle?: string, borderFocus?: string, shadow?: string, backdrop?: string, selection?: string, primary?: string, secondary?: string, info?: string, success?: string, notice?: string, warning?: string, danger?: string, };
export type ThemeComponents = { dialog?: ThemeComponentColors, menu?: ThemeComponentColors, toast?: ThemeComponentColors, sidebar?: ThemeComponentColors, responsePane?: ThemeComponentColors, appHeader?: ThemeComponentColors, button?: ThemeComponentColors, banner?: ThemeComponentColors, templateTag?: ThemeComponentColors, urlBar?: ThemeComponentColors, editor?: ThemeComponentColors, input?: ThemeComponentColors, };
export type WindowNavigateEvent = { url: string, };
export type WindowSize = { width: number, height: number, };

View File

@@ -89,11 +89,16 @@ pub enum InternalEventPayload {
GetCookieValueRequest(GetCookieValueRequest),
GetCookieValueResponse(GetCookieValueResponse),
// Request Actions
// HTTP Request Actions
GetHttpRequestActionsRequest(EmptyPayload),
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
// Grpc Request Actions
GetGrpcRequestActionsRequest(EmptyPayload),
GetGrpcRequestActionsResponse(GetGrpcRequestActionsResponse),
CallGrpcRequestActionRequest(CallGrpcRequestActionRequest),
// Template Functions
GetTemplateFunctionsRequest,
GetTemplateFunctionsResponse(GetTemplateFunctionsResponse),
@@ -116,6 +121,9 @@ pub enum InternalEventPayload {
RenderHttpRequestRequest(RenderHttpRequestRequest),
RenderHttpRequestResponse(RenderHttpRequestResponse),
RenderGrpcRequestRequest(RenderGrpcRequestRequest),
RenderGrpcRequestResponse(RenderGrpcRequestResponse),
GetKeyValueRequest(GetKeyValueRequest),
GetKeyValueResponse(GetKeyValueResponse),
SetKeyValueRequest(SetKeyValueRequest),
@@ -143,6 +151,9 @@ pub enum InternalEventPayload {
FindHttpResponsesRequest(FindHttpResponsesRequest),
FindHttpResponsesResponse(FindHttpResponsesResponse),
GetThemesRequest(GetThemesRequest),
GetThemesResponse(GetThemesResponse),
/// Returned when a plugin doesn't get run, just so the server
/// has something to listen for
EmptyResponse(EmptyPayload),
@@ -284,6 +295,128 @@ pub struct RenderHttpRequestResponse {
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)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct GetThemesRequest {}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct ThemeComponents {
#[ts(optional)]
pub dialog: Option<ThemeComponentColors>,
#[ts(optional)]
pub menu: Option<ThemeComponentColors>,
#[ts(optional)]
pub toast: Option<ThemeComponentColors>,
#[ts(optional)]
pub sidebar: Option<ThemeComponentColors>,
#[ts(optional)]
pub response_pane: Option<ThemeComponentColors>,
#[ts(optional)]
pub app_header: Option<ThemeComponentColors>,
#[ts(optional)]
pub button: Option<ThemeComponentColors>,
#[ts(optional)]
pub banner: Option<ThemeComponentColors>,
#[ts(optional)]
pub template_tag: Option<ThemeComponentColors>,
#[ts(optional)]
pub url_bar: Option<ThemeComponentColors>,
#[ts(optional)]
pub editor: Option<ThemeComponentColors>,
#[ts(optional)]
pub input: Option<ThemeComponentColors>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct ThemeComponentColors {
#[ts(optional)]
pub surface: Option<String>,
#[ts(optional)]
pub surface_highlight: Option<String>,
#[ts(optional)]
pub surface_active: Option<String>,
#[ts(optional)]
pub text: Option<String>,
#[ts(optional)]
pub text_subtle: Option<String>,
#[ts(optional)]
pub text_subtlest: Option<String>,
#[ts(optional)]
pub border: Option<String>,
#[ts(optional)]
pub border_subtle: Option<String>,
#[ts(optional)]
pub border_focus: Option<String>,
#[ts(optional)]
pub shadow: Option<String>,
#[ts(optional)]
pub backdrop: Option<String>,
#[ts(optional)]
pub selection: Option<String>,
#[ts(optional)]
pub primary: Option<String>,
#[ts(optional)]
pub secondary: Option<String>,
#[ts(optional)]
pub info: Option<String>,
#[ts(optional)]
pub success: Option<String>,
#[ts(optional)]
pub notice: Option<String>,
#[ts(optional)]
pub warning: Option<String>,
#[ts(optional)]
pub danger: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct Theme {
/// How the theme is identified. This should never be changed
pub id: String,
/// The friendly name of the theme to be displayed to the user
pub label: String,
/// Whether the theme will be used for dark or light appearance
pub dark: bool,
/// The default top-level colors for the theme
pub base: ThemeComponentColors,
/// Optionally override theme for individual UI components for more control
#[ts(optional)]
pub components: Option<ThemeComponents>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct GetThemesResponse {
pub themes: Vec<Theme>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
@@ -857,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)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
@@ -895,6 +1023,40 @@ pub struct CallHttpRequestActionArgs {
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)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]

View File

@@ -3,13 +3,15 @@ use crate::error::Error::{
};
use crate::error::Result;
use crate::events::{
BootRequest, CallHttpAuthenticationActionArgs, CallHttpAuthenticationActionRequest,
CallHttpAuthenticationRequest, CallHttpAuthenticationResponse, CallHttpRequestActionRequest,
CallTemplateFunctionArgs, CallTemplateFunctionRequest, CallTemplateFunctionResponse,
EmptyPayload, FilterRequest, FilterResponse, GetHttpAuthenticationConfigRequest,
BootRequest, CallGrpcRequestActionRequest, CallHttpAuthenticationActionArgs,
CallHttpAuthenticationActionRequest, CallHttpAuthenticationRequest,
CallHttpAuthenticationResponse, CallHttpRequestActionRequest, CallTemplateFunctionArgs,
CallTemplateFunctionRequest, CallTemplateFunctionResponse, EmptyPayload, FilterRequest,
FilterResponse, GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigRequest,
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
GetHttpRequestActionsResponse, GetTemplateFunctionsResponse, ImportRequest, ImportResponse,
InternalEvent, InternalEventPayload, JsonPrimitive, PluginWindowContext, RenderPurpose,
GetHttpRequestActionsResponse, GetTemplateFunctionsResponse, GetThemesRequest,
GetThemesResponse, ImportRequest, ImportResponse, InternalEvent, InternalEventPayload,
JsonPrimitive, PluginWindowContext, RenderPurpose,
};
use crate::native_template_functions::template_function_secure;
use crate::nodejs::start_nodejs_plugin_runtime;
@@ -404,6 +406,48 @@ impl PluginManager {
Ok(events)
}
pub async fn get_themes<R: Runtime>(
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<GetThemesResponse>> {
let reply_events = self
.send_and_wait(
&PluginWindowContext::new(window),
&InternalEventPayload::GetThemesRequest(GetThemesRequest {}),
)
.await?;
let mut themes = Vec::new();
for event in reply_events {
if let InternalEventPayload::GetThemesResponse(resp) = event.payload {
themes.push(resp.clone());
}
}
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>(
&self,
window: &WebviewWindow<R>,
@@ -473,6 +517,23 @@ impl PluginManager {
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>(
&self,
window: &WebviewWindow<R>,
@@ -670,9 +731,9 @@ impl PluginManager {
content_type: &str,
) -> Result<FilterResponse> {
let plugin_name = if content_type.to_lowercase().contains("json") {
"@yaakapp/filter-jsonpath"
"@yaak/filter-jsonpath"
} else {
"@yaakapp/filter-xpath"
"@yaak/filter-xpath"
};
let plugin = self

View File

@@ -0,0 +1,76 @@
import type { HttpRequest } from '@yaakapp-internal/models';
import { patchModel } from '@yaakapp-internal/models';
import { type ReactNode } from 'react';
import { useToggle } from '../hooks/useToggle';
import { showConfirm } from '../lib/confirm';
import { Banner } from './core/Banner';
import { Button } from './core/Button';
import { InlineCode } from './core/InlineCode';
import { Link } from './core/Link';
import { SizeTag } from './core/SizeTag';
import { HStack } from './core/Stacks';
interface Props {
children: ReactNode;
request: HttpRequest;
}
const LARGE_TEXT_BYTES = 2 * 1000 * 1000;
export function ConfirmLargeRequestBody({ children, request }: Props) {
const [showLargeResponse, toggleShowLargeResponse] = useToggle();
if (request.body?.text == null) {
return children;
}
const contentLength = request.body.text.length ?? 0;
const tooLargeBytes = LARGE_TEXT_BYTES;
const isLarge = contentLength > tooLargeBytes;
if (!showLargeResponse && isLarge) {
return (
<Banner color="primary" className="flex flex-col gap-3">
<p>
Rendering content over{' '}
<InlineCode>
<SizeTag contentLength={tooLargeBytes} />
</InlineCode>{' '}
may impact performance.
</p>
<p>
See{' '}
<Link href="https://feedback.yaak.app/en/help/articles/1198684-working-with-large-values">
Working With Large Values
</Link>{' '}
for tips.
</p>
<HStack wrap space={2}>
<Button color="primary" size="xs" onClick={toggleShowLargeResponse}>
Reveal Body
</Button>
<Button
color="danger"
size="xs"
variant="border"
onClick={async () => {
const confirm = await showConfirm({
id: 'delete-body-' + request.id,
confirmText: 'Delete Body',
title: 'Delete Body Text',
description: 'Are you sure you want to delete the request body text?',
color: 'danger',
});
if (confirm) {
await patchModel(request, { body: { ...request.body, text: '' } });
}
}}
>
Delete Body
</Button>
</HStack>
</Banner>
);
}
return <>{children}</>;
}

View File

@@ -3,7 +3,6 @@ import type { InternalEvent } from '@yaakapp-internal/plugins';
import type { ShowToastRequest } from '@yaakapp/api';
import { useSubscribeActiveWorkspaceId } from '../hooks/useActiveWorkspace';
import { useActiveWorkspaceChangedToast } from '../hooks/useActiveWorkspaceChangedToast';
import { useGenerateThemeCss } from '../hooks/useGenerateThemeCss';
import { useSubscribeHttpAuthentication } from '../hooks/useHttpAuthentication';
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
import { useNotificationToast } from '../hooks/useNotificationToast';
@@ -18,7 +17,6 @@ import { showToast } from '../lib/toast';
export function GlobalHooks() {
useSyncZoomSetting();
useSyncFontSizeSetting();
useGenerateThemeCss();
useSubscribeActiveWorkspaceId();

View File

@@ -10,6 +10,7 @@ import { IconButton } from './core/IconButton';
import { InlineCode } from './core/InlineCode';
import { Link } from './core/Link';
import { HStack, VStack } from './core/Stacks';
import { Icon } from './core/Icon';
interface Props {
onDone: () => void;
@@ -45,6 +46,7 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
<HStack space={2} justifyContent="start" className="flex-row-reverse">
<Button
color="primary"
variant="border"
onClick={async () => {
const selected = await open({
title: 'Select Proto Files',
@@ -58,11 +60,28 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
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
isLoading={grpc.reflect.isFetching}
disabled={grpc.reflect.isFetching}
variant="border"
color="secondary"
onClick={() => grpc.reflect.refetch()}
>
@@ -70,6 +89,14 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
</Button>
</HStack>
<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 && (
<Banner className="flex flex-col gap-2">
<p>
@@ -108,39 +135,41 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
<table className="w-full divide-y divide-surface-highlight">
<thead>
<tr>
<th className="text-text-subtlest">
Added Files
</th>
<th/>
<th />
<th className="text-text-subtlest">Added File Paths</th>
<th />
</tr>
</thead>
<tbody className="divide-y divide-surface-highlight">
{protoFiles.map((f, i) => (
<tr key={f + i} className="group">
<td className="pl-1 font-mono text-sm" title={f}>{f.split('/').pop()}</td>
<td className="w-0 py-0.5">
<IconButton
title="Remove file"
icon="trash"
className="ml-auto opacity-50 transition-opacity group-hover:opacity-100"
onClick={async () => {
await protoFilesKv.set(protoFiles.filter((p) => p !== f));
}}
/>
</td>
</tr>
))}
{protoFiles.map((f, i) => {
const parts = f.split('/');
return (
<tr key={f + i} className="group">
<td>
<Icon icon={f.endsWith('.proto') ? 'file_code' : 'folder_code'} />
</td>
<td className="pl-1 font-mono text-sm" title={f}>
{parts.length > 3 && '.../'}
{parts.slice(-3).join('/')}
</td>
<td className="w-0 py-0.5">
<IconButton
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>
</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 && (
<Banner>
<InlineCode>{request.url}</InlineCode> doesn&apos;t implement{' '}

View File

@@ -35,6 +35,7 @@ import { prepareImportQuerystring } from '../lib/prepareImportQuerystring';
import { resolvedModelName } from '../lib/resolvedModelName';
import { showToast } from '../lib/toast';
import { BinaryFileEditor } from './BinaryFileEditor';
import { ConfirmLargeRequestBody } from './ConfirmLargeRequestBody';
import { CountBadge } from './core/CountBadge';
import { Editor } from './core/Editor/Editor';
import type { GenericCompletionConfig } from './core/Editor/genericCompletion';
@@ -373,72 +374,74 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
/>
</TabContent>
<TabContent value={TAB_BODY}>
{activeRequest.bodyType === BODY_TYPE_JSON ? (
<Editor
forceUpdateKey={forceUpdateKey}
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={`${activeRequest.body?.text ?? ''}`}
language="json"
onChange={handleBodyTextChange}
stateKey={`json.${activeRequest.id}`}
/>
) : activeRequest.bodyType === BODY_TYPE_XML ? (
<Editor
forceUpdateKey={forceUpdateKey}
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={`${activeRequest.body?.text ?? ''}`}
language="xml"
onChange={handleBodyTextChange}
stateKey={`xml.${activeRequest.id}`}
/>
) : activeRequest.bodyType === BODY_TYPE_GRAPHQL ? (
<GraphQLEditor
forceUpdateKey={forceUpdateKey}
baseRequest={activeRequest}
request={activeRequest}
onChange={handleBodyChange}
/>
) : activeRequest.bodyType === BODY_TYPE_FORM_URLENCODED ? (
<FormUrlencodedEditor
forceUpdateKey={forceUpdateKey}
request={activeRequest}
onChange={handleBodyChange}
/>
) : activeRequest.bodyType === BODY_TYPE_FORM_MULTIPART ? (
<FormMultipartEditor
forceUpdateKey={forceUpdateKey}
request={activeRequest}
onChange={handleBodyChange}
/>
) : activeRequest.bodyType === BODY_TYPE_BINARY ? (
<BinaryFileEditor
requestId={activeRequest.id}
contentType={contentType}
body={activeRequest.body}
onChange={(body) => patchModel(activeRequest, { body })}
onChangeContentType={handleContentTypeChange}
/>
) : typeof activeRequest.bodyType === 'string' ? (
<Editor
forceUpdateKey={forceUpdateKey}
autocompleteFunctions
autocompleteVariables
language={languageFromContentType(contentType)}
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={`${activeRequest.body?.text ?? ''}`}
onChange={handleBodyTextChange}
stateKey={`other.${activeRequest.id}`}
/>
) : (
<EmptyStateText>No Body</EmptyStateText>
)}
<ConfirmLargeRequestBody request={activeRequest}>
{activeRequest.bodyType === BODY_TYPE_JSON ? (
<Editor
forceUpdateKey={forceUpdateKey}
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={`${activeRequest.body?.text ?? ''}`}
language="json"
onChange={handleBodyTextChange}
stateKey={`json.${activeRequest.id}`}
/>
) : activeRequest.bodyType === BODY_TYPE_XML ? (
<Editor
forceUpdateKey={forceUpdateKey}
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={`${activeRequest.body?.text ?? ''}`}
language="xml"
onChange={handleBodyTextChange}
stateKey={`xml.${activeRequest.id}`}
/>
) : activeRequest.bodyType === BODY_TYPE_GRAPHQL ? (
<GraphQLEditor
forceUpdateKey={forceUpdateKey}
baseRequest={activeRequest}
request={activeRequest}
onChange={handleBodyChange}
/>
) : activeRequest.bodyType === BODY_TYPE_FORM_URLENCODED ? (
<FormUrlencodedEditor
forceUpdateKey={forceUpdateKey}
request={activeRequest}
onChange={handleBodyChange}
/>
) : activeRequest.bodyType === BODY_TYPE_FORM_MULTIPART ? (
<FormMultipartEditor
forceUpdateKey={forceUpdateKey}
request={activeRequest}
onChange={handleBodyChange}
/>
) : activeRequest.bodyType === BODY_TYPE_BINARY ? (
<BinaryFileEditor
requestId={activeRequest.id}
contentType={contentType}
body={activeRequest.body}
onChange={(body) => patchModel(activeRequest, { body })}
onChangeContentType={handleContentTypeChange}
/>
) : typeof activeRequest.bodyType === 'string' ? (
<Editor
forceUpdateKey={forceUpdateKey}
autocompleteFunctions
autocompleteVariables
language={languageFromContentType(contentType)}
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={`${activeRequest.body?.text ?? ''}`}
onChange={handleBodyTextChange}
stateKey={`other.${activeRequest.id}`}
/>
) : (
<EmptyStateText>No Body</EmptyStateText>
)}
</ConfirmLargeRequestBody>
</TabContent>
<TabContent value={TAB_DESCRIPTION}>
<div className="grid grid-rows-[auto_minmax(0,1fr)] h-full">

View File

@@ -4,15 +4,13 @@ import React from 'react';
import { activeWorkspaceAtom } from '../../hooks/useActiveWorkspace';
import { useResolvedAppearance } from '../../hooks/useResolvedAppearance';
import { useResolvedTheme } from '../../hooks/useResolvedTheme';
import { getThemes } from '../../lib/theme/themes';
import { isThemeDark } from '../../lib/theme/window';
import type { ButtonProps } from '../core/Button';
import { Editor } from '../core/Editor/Editor';
import type { IconProps } from '../core/Icon';
import { Icon } from '../core/Icon';
import { IconButton } from '../core/IconButton';
import { Select } from '../core/Select';
import type { SelectProps } from '../core/Select';
import { Select } from '../core/Select';
import { HStack, VStack } from '../core/Stacks';
const buttonColors: ButtonProps['color'][] = [
@@ -44,29 +42,27 @@ const icons: IconProps['icon'][] = [
'send_horizontal',
];
const { themes } = getThemes();
export function SettingsTheme() {
const workspace = useAtomValue(activeWorkspaceAtom);
const settings = useAtomValue(settingsAtom);
const appearance = useResolvedAppearance();
const activeTheme = useResolvedTheme();
if (settings == null || workspace == null) {
if (settings == null || workspace == null || activeTheme.data == null) {
return null;
}
const lightThemes: SelectProps<string>['options'] = themes
.filter((theme) => !isThemeDark(theme))
const lightThemes: SelectProps<string>['options'] = activeTheme.data.themes
.filter((theme) => !theme.dark)
.map((theme) => ({
label: theme.name,
label: theme.label,
value: theme.id,
}));
const darkThemes: SelectProps<string>['options'] = themes
.filter((theme) => isThemeDark(theme))
const darkThemes: SelectProps<string>['options'] = activeTheme.data.themes
.filter((theme) => theme.dark)
.map((theme) => ({
label: theme.name,
label: theme.label,
value: theme.id,
}));
@@ -94,7 +90,7 @@ export function SettingsTheme() {
label="Light Theme"
size="sm"
className="flex-1"
value={activeTheme.light.id}
value={activeTheme.data.light.id}
options={lightThemes}
onChange={(themeLight) => patchModel(settings, { themeLight })}
/>
@@ -107,7 +103,7 @@ export function SettingsTheme() {
label="Dark Theme"
leftSlot={<Icon icon="moon" color="secondary" />}
size="sm"
value={activeTheme.dark.id}
value={activeTheme.data.dark.id}
options={darkThemes}
onChange={(themeDark) => patchModel(settings, { themeDark })}
/>
@@ -120,7 +116,7 @@ export function SettingsTheme() {
>
<HStack className="text" space={1.5}>
<Icon icon={appearance === 'dark' ? 'moon' : 'sun'} />
<strong>{activeTheme.active.name}</strong>
<strong>{activeTheme.data.active.label}</strong>
<em>(preview)</em>
</HStack>
<HStack space={1.5} className="w-full">

View File

@@ -14,7 +14,6 @@ export function Banner({ children, className, color }: BannerProps) {
className={classNames(
className,
`x-theme-banner--${color}`,
'whitespace-pre-wrap',
'border border-border bg-surface',
'px-4 py-3 rounded-lg select-auto',
'overflow-auto text-text',

View File

@@ -47,7 +47,7 @@ export function Dialog({
<div
role="dialog"
className={classNames(
'x-theme-dialog absolute inset-0 pointer-events-none',
'py-4 x-theme-dialog absolute inset-0 pointer-events-none',
'h-full flex flex-col items-center justify-center',
vAlign === 'top' && 'justify-start',
vAlign === 'center' && 'justify-center',

View File

@@ -45,6 +45,7 @@ const icons = {
eye: lucide.EyeIcon,
eye_closed: lucide.EyeOffIcon,
file_code: lucide.FileCodeIcon,
folder_code: lucide.FolderCodeIcon,
filter: lucide.FilterIcon,
flame: lucide.FlameIcon,
flask: lucide.FlaskConicalIcon,
@@ -134,6 +135,8 @@ export const Icon = memo(function Icon({
title={title}
className={classNames(
className,
!spin && 'transform-cpu',
spin && 'animate-spin',
'flex-shrink-0',
size === 'xl' && 'h-6 w-6',
size === 'lg' && 'h-5 w-5',
@@ -149,7 +152,6 @@ export const Icon = memo(function Icon({
color === 'success' && 'text-success',
color === 'primary' && 'text-primary',
color === 'secondary' && 'text-secondary',
spin && 'animate-spin',
)}
/>
);

View File

@@ -9,6 +9,7 @@ import { getAnyModel, patchModelById } from '@yaakapp-internal/models';
import classNames from 'classnames';
import { useAtom, useAtomValue } from 'jotai';
import React, { useCallback, useRef, useState } from 'react';
import { useDrop } from 'react-dnd';
import { useKey, useKeyPressEvent } from 'react-use';
import { activeRequestIdAtom } from '../../hooks/useActiveRequestId';
import { activeWorkspaceAtom } from '../../hooks/useActiveWorkspace';
@@ -22,6 +23,8 @@ import { router } from '../../lib/router';
import { setWorkspaceSearchParams } from '../../lib/setWorkspaceSearchParams';
import { ContextMenu } from '../core/Dropdown';
import { GitDropdown } from '../GitDropdown';
import type { DragItem } from './dnd';
import { ItemTypes } from './dnd';
import { sidebarSelectedIdAtom, sidebarTreeAtom } from './SidebarAtoms';
import type { SidebarItemProps } from './SidebarItem';
import { SidebarItems } from './SidebarItems';
@@ -204,15 +207,22 @@ export function Sidebar({ className }: Props) {
[hasFocus, selectableRequests, selectedId, setSelectedId, setSelectedTree],
);
const handleMoveToSidebarEnd = useCallback(() => {
setHoveredTree(tree);
// Put at the end of the top tree
setHoveredIndex(tree?.children?.length ?? 0);
}, [tree]);
const handleMove = useCallback<SidebarItemProps['onMove']>(
async (id, side) => {
(id, side) => {
let hoveredTree = treeParentMap[id] ?? null;
const dragIndex = hoveredTree?.children.findIndex((n) => n.id === id) ?? -99;
const hoveredItem = hoveredTree?.children[dragIndex] ?? null;
let hoveredIndex = dragIndex + (side === 'above' ? 0 : 1);
const isHoveredItemCollapsed =
hoveredItem != null ? getSidebarCollapsedMap()[hoveredItem.id] : false;
const collapsedMap = getSidebarCollapsedMap();
const isHoveredItemCollapsed = hoveredItem != null ? collapsedMap[hoveredItem.id] : false;
if (hoveredItem?.model === 'folder' && side === 'below' && !isHoveredItemCollapsed) {
// Move into the folder if it's open and we're moving below it
hoveredTree = hoveredTree?.children.find((n) => n.id === id) ?? null;
@@ -232,6 +242,7 @@ export function Sidebar({ className }: Props) {
const handleEnd = useCallback<SidebarItemProps['onEnd']>(
async (itemId) => {
setHoveredTree(null);
setDraggingId(null);
handleClearSelected();
if (hoveredTree == null || hoveredIndex == null) {
@@ -278,9 +289,8 @@ export function Sidebar({ className }: Props) {
);
} else {
const sortPriority = afterPriority - (afterPriority - beforePriority) / 2;
return patchModelById(child.model, child.id, { sortPriority, folderId });
await patchModelById(child.model, child.id, { sortPriority, folderId });
}
setDraggingId(null);
},
[handleClearSelected, hoveredTree, hoveredIndex, treeParentMap],
);
@@ -298,6 +308,20 @@ export function Sidebar({ className }: Props) {
const mainContextMenuItems = useCreateDropdownItems({ folderId: null });
const [, connectDrop] = useDrop<DragItem, void>(
{
accept: ItemTypes.REQUEST,
hover: (_, monitor) => {
if (sidebarRef.current == null) return;
if (!monitor.isOver({ shallow: true })) return;
handleMoveToSidebarEnd();
},
},
[handleMoveToSidebarEnd],
);
connectDrop(sidebarRef);
// Not ready to render yet
if (tree == null) {
return null;

View File

@@ -6,7 +6,7 @@ import {
type WebsocketRequest,
} from '@yaakapp-internal/models';
// This is an atom so we can use it in the child items to avoid re-rendering the entire list
// This is an atom, so we can use it in the child items to avoid re-rendering the entire list
import { atom } from 'jotai';
import { activeWorkspaceAtom } from '../../hooks/useActiveWorkspace';
import { allRequestsAtom } from '../../hooks/useAllRequests';

View File

@@ -20,15 +20,13 @@ import { HttpMethodTag } from '../core/HttpMethodTag';
import { HttpStatusTag } from '../core/HttpStatusTag';
import { Icon } from '../core/Icon';
import { LoadingIcon } from '../core/LoadingIcon';
import type { DragItem} from './dnd';
import { ItemTypes } from './dnd';
import type { SidebarTreeNode } from './Sidebar';
import { sidebarSelectedIdAtom } from './SidebarAtoms';
import { SidebarItemContextMenu } from './SidebarItemContextMenu';
import type { SidebarItemsProps } from './SidebarItems';
enum ItemTypes {
REQUEST = 'request',
}
export type SidebarItemProps = {
className?: string;
itemId: string;
@@ -44,11 +42,6 @@ export type SidebarItemProps = {
latestWebsocketConnection: WebsocketConnection | null;
} & Pick<SidebarItemsProps, 'onSelect'>;
type DragItem = {
id: string;
itemName: string;
};
export const SidebarItem = memo(function SidebarItem({
itemName,
itemId,
@@ -69,9 +62,10 @@ export const SidebarItem = memo(function SidebarItem({
const [, connectDrop] = useDrop<DragItem, void>(
{
accept: ItemTypes.REQUEST,
accept: [ItemTypes.REQUEST, ItemTypes.SIDEBAR],
hover: (_, monitor) => {
if (!ref.current) return;
if (!monitor.isOver()) return;
const hoverBoundingRect = ref.current?.getBoundingClientRect();
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
const clientOffset = monitor.getClientOffset();
@@ -226,7 +220,7 @@ export const SidebarItem = memo(function SidebarItem({
return (
<li ref={ref} draggable>
<div className={classNames(className, 'block relative group/item px-1.5 pb-0.5')}>
<div className={classNames(className, 'block relative group/item pl-2 pb-0.5')}>
{showContextMenu && (
<SidebarItemContextMenu
child={child}

View File

@@ -3,6 +3,7 @@ import { useAtomValue } from 'jotai';
import React, { useMemo } from 'react';
import { openFolderSettings } from '../../commands/openFolderSettings';
import { useCreateDropdownItems } from '../../hooks/useCreateDropdownItems';
import { useGrpcRequestActions } from '../../hooks/useGrpcRequestActions';
import { useHttpRequestActions } from '../../hooks/useHttpRequestActions';
import { useMoveToWorkspace } from '../../hooks/useMoveToWorkspace';
import { useSendAnyHttpRequest } from '../../hooks/useSendAnyHttpRequest';
@@ -25,6 +26,7 @@ interface Props {
export function SidebarItemContextMenu({ child, show, close }: Props) {
const sendManyRequests = useSendManyRequests();
const httpRequestActions = useHttpRequestActions();
const grpcRequestActions = useGrpcRequestActions();
const sendRequest = useSendAnyHttpRequest();
const workspaces = useAtomValue(workspacesAtom);
const moveToWorkspace = useMoveToWorkspace(child.id);
@@ -65,25 +67,35 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
const requestItems: DropdownItem[] =
child.model === 'http_request'
? [
{
label: 'Send',
hotKeyAction: 'http_request.send',
hotKeyLabelOnly: true, // Already bound in URL bar
leftSlot: <Icon icon="send_horizontal" />,
onSelect: () => sendRequest.mutate(child.id),
{
label: 'Send',
hotKeyAction: 'http_request.send',
hotKeyLabelOnly: true, // Already bound in URL bar
leftSlot: <Icon icon="send_horizontal" />,
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,
// 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);
},
})),
{ type: 'separator' },
]
: [];
})),
{ type: 'separator' },
]
: child.model === 'grpc_request'
? grpcRequestActions.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('grpc_request', child.id);
if (request != null) await a.call(request);
},
}))
: [];
return [
...requestItems,
{
@@ -134,6 +146,7 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
child.model,
createDropdownItems,
httpRequestActions,
grpcRequestActions,
moveToWorkspace.mutate,
sendManyRequests,
sendRequest,

View File

@@ -0,0 +1,9 @@
export enum ItemTypes {
REQUEST = 'request',
SIDEBAR = 'sidebar',
}
export type DragItem = {
id: string;
itemName: string;
};

View File

@@ -1,27 +1,12 @@
import { copyToClipboard } from '../lib/copy';
import { catppuccinMacchiato } from '../lib/theme/themes/catppuccin';
import { githubLight } from '../lib/theme/themes/github';
import { gruvboxDefault } from '../lib/theme/themes/gruvbox';
import { hotdogStandDefault } from '../lib/theme/themes/hotdog-stand';
import { monokaiProDefault } from '../lib/theme/themes/monokai-pro';
import { rosePineDefault } from '../lib/theme/themes/rose-pine';
import { yaakDark } from '../lib/theme/themes/yaak';
import { getThemes } from '../lib/theme/themes';
import { getThemeCSS } from '../lib/theme/window';
import { useListenToTauriEvent } from './useListenToTauriEvent';
export function useGenerateThemeCss() {
useListenToTauriEvent('generate_theme_css', () => {
const themesCss = [
yaakDark,
monokaiProDefault,
rosePineDefault,
catppuccinMacchiato,
githubLight,
gruvboxDefault,
hotdogStandDefault,
]
.map(getThemeCSS)
.join('\n\n');
useListenToTauriEvent('generate_theme_css', async () => {
const themes = await getThemes();
const themesCss = themes.themes.map(getThemeCSS).join('\n\n');
copyToClipboard(themesCss);
});
}

View File

@@ -1,3 +1,4 @@
import { getKeyValue } from '../lib/keyValueStore';
import { useKeyValue } from './useKeyValue';
export function protoFilesArgs(requestId: string | null) {
@@ -10,3 +11,7 @@ export function protoFilesArgs(requestId: string | null) {
export function useGrpcProtoFiles(activeRequestId: string | null) {
return useKeyValue<string[]>({ ...protoFilesArgs(activeRequestId), fallback: [] });
}
export async function getGrpcProtoFiles(activeRequestId: string | null) {
return getKeyValue<string[]>({ ...protoFilesArgs(activeRequestId), fallback: [] });
}

View 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;
}

View File

@@ -1,15 +1,25 @@
import { useQuery } from '@tanstack/react-query';
import { settingsAtom } from '@yaakapp-internal/models';
import { useAtomValue } from 'jotai';
import { getResolvedTheme } from '../lib/theme/themes';
import { getResolvedTheme, getThemes } from '../lib/theme/themes';
import { usePluginsKey } from './usePlugins';
import { usePreferredAppearance } from './usePreferredAppearance';
export function useResolvedTheme() {
const preferredAppearance = usePreferredAppearance();
const settings = useAtomValue(settingsAtom);
return getResolvedTheme(
preferredAppearance,
settings.appearance,
settings.themeLight,
settings.themeDark,
);
const pluginKey = usePluginsKey();
return useQuery({
placeholderData: (prev) => prev,
queryKey: ['resolved_theme', preferredAppearance, settings.updatedAt, pluginKey],
queryFn: async () => {
const data = await getResolvedTheme(
preferredAppearance,
settings.appearance,
settings.themeLight,
settings.themeDark,
);
return { ...data, ...await getThemes() };
},
});
}

View File

@@ -8,7 +8,7 @@ export function useToggleCommandPalette() {
id: 'command_palette',
size: 'dynamic',
hideX: true,
className: '!max-h-[min(30rem,calc(100vh-4rem))]',
className: 'mb-auto mt-[4rem] !max-h-[min(30rem,calc(100vh-4rem))]',
vAlign: 'top',
noPadding: true,
noScroll: true,

View File

@@ -2,7 +2,9 @@ import type { InvokeArgs } from '@tauri-apps/api/core';
import { invoke } from '@tauri-apps/api/core';
type TauriCmd =
| 'cmd_get_themes'
| 'cmd_call_http_authentication_action'
| 'cmd_call_grpc_request_action'
| 'cmd_call_http_request_action'
| 'cmd_check_for_updates'
| 'cmd_create_grpc_request'
@@ -22,6 +24,7 @@ type TauriCmd =
| 'cmd_get_workspace_meta'
| 'cmd_grpc_go'
| 'cmd_grpc_reflect'
| 'cmd_grpc_request_actions'
| 'cmd_http_request_actions'
| 'cmd_import_data'
| 'cmd_install_plugin'

View File

@@ -1,63 +1,108 @@
import type { GetThemesResponse } from '@yaakapp-internal/plugins';
import { invokeCmd } from '../tauri';
import type { Appearance } from './appearance';
import { resolveAppearance } from './appearance';
import { catppuccin } from './themes/catppuccin';
import { dracula } from './themes/dracula';
import { github } from './themes/github';
import { gruvbox } from './themes/gruvbox';
import { hotdogStand } from './themes/hotdog-stand';
import { monokaiPro } from './themes/monokai-pro';
import { nord } from './themes/nord';
import { moonlight } from './themes/moonlight';
import { relaxing } from './themes/relaxing';
import { rosePine } from './themes/rose-pine';
import { yaak, yaakDark, yaakLight } from './themes/yaak';
import { isThemeDark } from './window';
export const defaultDarkTheme = yaakDark;
export const defaultLightTheme = yaakLight;
const allThemes = [
...yaak,
...catppuccin,
...dracula,
...relaxing,
...rosePine,
...github,
...gruvbox,
...monokaiPro,
...nord,
...moonlight,
...hotdogStand,
];
export function getThemes() {
const dark = defaultDarkTheme;
const light = defaultLightTheme;
const otherThemes = allThemes
.filter((t) => t.id !== dark.id && t.id !== light.id)
.sort((a, b) => a.name.localeCompare(b.name));
const themes = [dark, light, ...otherThemes];
return { themes, fallback: { dark, light } };
export async function getThemes() {
const themes = (await invokeCmd<GetThemesResponse[]>('cmd_get_themes')).flatMap((t) => t.themes);
themes.sort((a, b) => a.label.localeCompare(b.label));
return { themes: [yaakDark, yaakLight, ...themes] };
}
export function getResolvedTheme(
export async function getResolvedTheme(
preferredAppearance: Appearance,
appearanceSetting: string,
themeLight: string,
themeDark: string,
) {
const appearance = resolveAppearance(preferredAppearance, appearanceSetting);
const { themes, fallback } = getThemes();
const { themes } = await getThemes();
const darkThemes = themes.filter((t) => isThemeDark(t));
const lightThemes = themes.filter((t) => !isThemeDark(t));
const darkThemes = themes.filter((t) => t.dark);
const lightThemes = themes.filter((t) => !t.dark);
const dark = darkThemes.find((t) => t.id === themeDark) ?? fallback.dark;
const light = lightThemes.find((t) => t.id === themeLight) ?? fallback.light;
const dark = darkThemes.find((t) => t.id === themeDark) ?? darkThemes[0] ?? yaakDark;
const light = lightThemes.find((t) => t.id === themeLight) ?? lightThemes[0] ?? yaakLight;
const active = appearance === 'dark' ? dark : light;
return { dark, light, active };
}
const yaakDark = {
id: 'yaak-dark',
label: 'Yaak',
dark: true,
base: {
surface: 'hsl(244,23%,14%)',
surfaceHighlight: 'hsl(244,23%,20%)',
text: 'hsl(245,23%,84%)',
textSubtle: 'hsl(245,18%,58%)',
textSubtlest: 'hsl(245,18%,45%)',
border: 'hsl(244,23%,25%)',
primary: 'hsl(266,100%,79%)',
secondary: 'hsl(245,23%,60%)',
info: 'hsl(206,100%,63%)',
success: 'hsl(150,99%,44%)',
notice: 'hsl(48,80%,63%)',
warning: 'hsl(28,100%,61%)',
danger: 'hsl(342,90%,68%)',
},
components: {
button: {
primary: 'hsl(266,100%,71.1%)',
secondary: 'hsl(244,23%,54%)',
info: 'hsl(206,100%,56.7%)',
success: 'hsl(150,99%,37.4%)',
notice: 'hsl(48,80%,50.4%)',
warning: 'hsl(28,100%,54.9%)',
danger: 'hsl(342,90%,61.2%)',
},
dialog: {
border: 'hsl(244,23%,24%)',
},
sidebar: {
surface: 'hsl(243,23%,16%)',
border: 'hsl(244,23%,22%)',
},
responsePane: {
surface: 'hsl(243,23%,16%)',
border: 'hsl(246,23%,22.72%)',
},
appHeader: {
surface: 'hsl(244,23%,12%)',
border: 'hsl(244,23%,20.8%)',
},
},
};
const yaakLight = {
id: 'yaak-light',
label: 'Yaak',
dark: false,
base: {
surface: 'hsl(0,0%,100%)',
surfaceHighlight: 'hsl(218,24%,87%)',
text: 'hsl(217,24%,15%)',
textSubtle: 'hsl(217,24%,40%)',
textSubtlest: 'hsl(217,24%,58%)',
border: 'hsl(217,22%,93%)',
primary: 'hsl(266,100%,70%)',
secondary: 'hsl(220,24%,59%)',
info: 'hsl(206,100%,48%)',
success: 'hsl(155,95%,33%)',
notice: 'hsl(45,100%,41%)',
warning: 'hsl(30,100%,43%)',
danger: 'hsl(335,75%,57%)',
},
components: {
sidebar: {
surface: 'hsl(220,20%,97%)',
border: 'hsl(217,22%,93%)',
surfaceHighlight: 'hsl(217,25%,90%)',
},
},
};
export const defaultDarkTheme = yaakDark;
export const defaultLightTheme = yaakLight;

View File

@@ -1,156 +0,0 @@
import { YaakColor } from '../yaakColor';
import type { YaakTheme } from '../window';
export const catppuccinLatte: YaakTheme = {
name: 'Catppuccin Latte',
id: 'catppuccin-latte',
surface: new YaakColor('#eff1f5', 'light'),
text: new YaakColor('#4c4f69', 'dark'),
textSubtle: new YaakColor('#6c6f85', 'light'),
textSubtlest: new YaakColor('#8c8fa1', 'light'),
primary: new YaakColor('#8839ef', 'light'),
secondary: new YaakColor('#6c6f85', 'light'),
info: new YaakColor('#7287fd', 'light'),
success: new YaakColor('#179299', 'light'),
notice: new YaakColor('#df8e1d', 'light'),
warning: new YaakColor('#fe640b', 'light'),
danger: new YaakColor('#e64553', 'light'),
components: {
sidebar: {
surface: new YaakColor('#e6e9ef', 'light'),
border: new YaakColor('#e6e9ef', 'light').lift(0.05),
},
appHeader: {
surface: new YaakColor('#dce0e8', 'light'),
border: new YaakColor('#e6e9ef', 'light').lift(0.05),
},
},
};
export const catppuccinMacchiato: YaakTheme = {
name: 'Catppuccin Macchiato',
id: 'catppuccin-macchiato',
surface: new YaakColor('#1e2030', 'dark'),
text: new YaakColor('#cad3f5', 'dark'),
textSubtle: new YaakColor('#a5adcb', 'dark'),
textSubtlest: new YaakColor('#8087a2', 'dark'),
primary: new YaakColor('#c6a0f6', 'dark'),
secondary: new YaakColor('#b8c0e0', 'dark'),
info: new YaakColor('#8aadf4', 'dark'),
success: new YaakColor('#a6da95', 'dark'),
notice: new YaakColor('#eed49f', 'dark'),
warning: new YaakColor('#f5a97f', 'dark'),
danger: new YaakColor('#ed8796', 'dark'),
components: {
dialog: {
surface: new YaakColor('#181825', 'dark'),
},
sidebar: {
surface: new YaakColor('#24273a', 'dark'),
border: new YaakColor('#24273a', 'dark').lift(0.05),
},
appHeader: {
surface: new YaakColor('#181926', 'dark'),
border: new YaakColor('#181926', 'dark').lift(0.1),
},
responsePane: {
surface: new YaakColor('#24273a', 'dark'),
border: new YaakColor('#24273a', 'dark').lift(0.05),
},
button: {
primary: new YaakColor('#c6a0f6', 'dark').lower(0.1),
secondary: new YaakColor('#b8c0e0', 'dark').lower(0.1),
info: new YaakColor('#8aadf4', 'dark').lower(0.1),
success: new YaakColor('#a6da95', 'dark').lower(0.1),
notice: new YaakColor('#eed49f', 'dark').lower(0.1),
warning: new YaakColor('#f5a97f', 'dark').lower(0.1),
danger: new YaakColor('#ed8796', 'dark').lower(0.1),
},
},
};
export const catppuccinFrappe: YaakTheme = {
name: 'Catppuccin Frappé',
id: 'catppuccin-frappe',
surface: new YaakColor('#292c3c', 'dark'),
text: new YaakColor('#c6d0f5', 'dark'),
textSubtle: new YaakColor('#a5adce', 'dark'),
textSubtlest: new YaakColor('#838ba7', 'dark'),
primary: new YaakColor('#ca9ee6', 'dark'),
secondary: new YaakColor('#b8c0e0', 'dark'),
info: new YaakColor('#8caaee', 'dark'),
success: new YaakColor('#a6d189', 'dark'),
notice: new YaakColor('#e5c890', 'dark'),
warning: new YaakColor('#ef9f76', 'dark'),
danger: new YaakColor('#e78284', 'dark'),
components: {
dialog: {
surface: new YaakColor('#181825', 'dark'),
},
sidebar: {
surface: new YaakColor('#303446', 'dark'),
border: new YaakColor('#303446', 'dark').lift(0.05),
},
appHeader: {
surface: new YaakColor('#232634', 'dark'),
border: new YaakColor('#232634', 'dark').lift(0.1),
},
responsePane: {
surface: new YaakColor('#303446', 'dark'),
border: new YaakColor('#303446', 'dark').lift(0.05),
},
button: {
primary: new YaakColor('#ca9ee6', 'dark').lower(0.1),
secondary: new YaakColor('#b8c0e0', 'dark').lower(0.1),
info: new YaakColor('#8caaee', 'dark').lower(0.1),
success: new YaakColor('#a6d189', 'dark').lower(0.1),
notice: new YaakColor('#e5c890', 'dark').lower(0.1),
warning: new YaakColor('#ef9f76', 'dark').lower(0.1),
danger: new YaakColor('#e78284', 'dark').lower(0.1),
},
},
};
const catppuccinMocha: YaakTheme = {
name: 'Catppuccin Mocha',
id: 'catppuccin-mocha',
surface: new YaakColor('#181825', 'dark'),
text: new YaakColor('#cdd6f4', 'dark'),
textSubtle: new YaakColor('#a6adc8', 'dark'),
textSubtlest: new YaakColor('#7f849c', 'dark'),
primary: new YaakColor('#c6a0f6', 'dark'),
secondary: new YaakColor('#bac2de', 'dark'),
info: new YaakColor('#89b4fa', 'dark'),
success: new YaakColor('#a6e3a1', 'dark'),
notice: new YaakColor('#f9e2af', 'dark'),
warning: new YaakColor('#fab387', 'dark'),
danger: new YaakColor('#f38ba8', 'dark'),
components: {
dialog: {
surface: new YaakColor('#181825', 'dark'),
},
sidebar: {
surface: new YaakColor('#1e1e2e', 'dark'),
border: new YaakColor('#1e1e2e', 'dark').lift(0.05),
},
appHeader: {
surface: new YaakColor('#11111b', 'dark'),
border: new YaakColor('#11111b', 'dark').lift(0.1),
},
responsePane: {
surface: new YaakColor('#1e1e2e', 'dark'),
border: new YaakColor('#1e1e2e', 'dark').lift(0.05),
},
button: {
primary: new YaakColor('#cba6f7', 'dark').lower(0.2).desaturate(0.2),
secondary: new YaakColor('#bac2de', 'dark').lower(0.2).desaturate(0.2),
info: new YaakColor('#89b4fa', 'dark').lower(0.2).desaturate(0.2),
success: new YaakColor('#a6e3a1', 'dark').lower(0.2).desaturate(0.2),
notice: new YaakColor('#f9e2af', 'dark').lower(0.2).desaturate(0.2),
warning: new YaakColor('#fab387', 'dark').lower(0.2).desaturate(0.2),
danger: new YaakColor('#f38ba8', 'dark').lower(0.2).desaturate(0.2),
},
},
};
export const catppuccin = [catppuccinFrappe, catppuccinMacchiato, catppuccinMocha, catppuccinLatte];

View File

@@ -1,29 +0,0 @@
import type { YaakTheme } from '../window';
import { YaakColor } from '../yaakColor';
const draculaDefault: YaakTheme = {
id: 'dracula',
name: 'Dracula',
surface: new YaakColor('#282A36', 'dark'),
surfaceHighlight: new YaakColor('#343746', 'dark'),
text: new YaakColor('#F8F8F2', 'dark'),
textSubtle: new YaakColor('hsl(232,14%,65%)', 'dark'),
textSubtlest: new YaakColor('hsl(232,14%,50%)', 'dark'),
primary: new YaakColor('#BD93F9', 'dark'),
secondary: new YaakColor('#6272A4', 'dark'),
info: new YaakColor('#8BE9FD', 'dark'),
success: new YaakColor('#50FA7B', 'dark'),
notice: new YaakColor('#F1FA8C', 'dark'),
warning: new YaakColor('#FFB86C', 'dark'),
danger: new YaakColor('#FF5555', 'dark'),
components: {
sidebar: {
backdrop: new YaakColor('hsl(230,15%,24%)', 'dark'),
},
appHeader: {
backdrop: new YaakColor('#21222C', 'dark'),
},
},
};
export const dracula = [draculaDefault];

View File

@@ -1,52 +0,0 @@
import { YaakColor } from '../yaakColor';
import type { YaakTheme } from '../window';
const githubDark: YaakTheme = {
id: 'github-dark',
name: 'GitHub',
surface: new YaakColor('#0d1218', 'dark'),
border: new YaakColor('#171c23', 'dark'),
surfaceHighlight: new YaakColor('#1c2127', 'dark'),
text: new YaakColor('#dce3eb', 'dark'),
textSubtle: new YaakColor('#88919b', 'dark'),
textSubtlest: new YaakColor('#6b727d', 'dark'),
primary: new YaakColor('#a579ef', 'dark').lift(0.1),
secondary: new YaakColor('#6b727d', 'dark').lift(0.1),
info: new YaakColor('#458def', 'dark').lift(0.1),
success: new YaakColor('#3eb24f', 'dark').lift(0.1),
notice: new YaakColor('#dca132', 'dark').lift(0.1),
warning: new YaakColor('#ec7934', 'dark').lift(0.1),
danger: new YaakColor('#ee5049', 'dark').lift(0.1),
components: {
button: {
primary: new YaakColor('#a579ef', 'dark'),
secondary: new YaakColor('#6b727d', 'dark'),
info: new YaakColor('#458def', 'dark'),
success: new YaakColor('#3eb24f', 'dark'),
notice: new YaakColor('#dca132', 'dark'),
warning: new YaakColor('#ec7934', 'dark'),
danger: new YaakColor('#ee5049', 'dark'),
},
},
};
export const githubLight: YaakTheme = {
id: 'github-light',
name: 'GitHub',
surface: new YaakColor('#ffffff', 'light'),
surfaceHighlight: new YaakColor('hsl(210,29%,94%)', 'light'),
border: new YaakColor('hsl(210,15%,92%)', 'light'),
borderSubtle: new YaakColor('hsl(210,15%,92%)', 'light'),
text: new YaakColor('#1f2328', 'light'),
textSubtle: new YaakColor('#636c76', 'light'),
textSubtlest: new YaakColor('#828d94', 'light'),
primary: new YaakColor('#8250df', 'light'),
secondary: new YaakColor('#6e7781', 'light'),
info: new YaakColor('hsl(212,92%,48%)', 'light'),
success: new YaakColor('hsl(137,66%,32%)', 'light'),
notice: new YaakColor('hsl(40,100%,40%)', 'light'),
warning: new YaakColor('hsl(24,100%,44%)', 'light'),
danger: new YaakColor('#d1242f', 'light'),
};
export const github = [githubDark, githubLight];

View File

@@ -1,21 +0,0 @@
import type { YaakTheme } from '../window';
import { YaakColor } from '../yaakColor';
export const gruvboxDefault: YaakTheme = {
id: 'gruvbox',
name: 'Gruvbox',
surface: new YaakColor('#282828', 'dark'),
surfaceHighlight: new YaakColor('#32302f', 'dark'),
text: new YaakColor('#f9f5d7', 'dark'),
textSubtle: new YaakColor('#bdae93', 'dark'),
textSubtlest: new YaakColor('#928374', 'dark'),
primary: new YaakColor('#d3869b', 'dark'),
secondary: new YaakColor('#83a598', 'dark'),
info: new YaakColor('#8ec07c', 'dark'),
success: new YaakColor('#b8bb26', 'dark'),
notice: new YaakColor('#fabd2f', 'dark'),
warning: new YaakColor('#fe8019', 'dark'),
danger: new YaakColor('#fb4934', 'dark'),
};
export const gruvbox = [gruvboxDefault];

View File

@@ -1,58 +0,0 @@
import { YaakColor } from '../yaakColor';
import type { YaakTheme } from '../window';
export const hotdogStandDefault: YaakTheme = {
id: 'hotdog-stand',
name: 'Hotdog Stand',
surface: new YaakColor('#ff0000', 'dark'),
border: new YaakColor('#000000', 'dark'),
surfaceHighlight: new YaakColor('#000000', 'dark'),
text: new YaakColor('#ffffff', 'dark'),
textSubtle: new YaakColor('#ffffff', 'dark'),
textSubtlest: new YaakColor('#ffff00', 'dark'),
primary: new YaakColor('#ffff00', 'dark'),
secondary: new YaakColor('#ffff00', 'dark'),
info: new YaakColor('#ffff00', 'dark'),
success: new YaakColor('#ffff00', 'dark'),
notice: new YaakColor('#ffff00', 'dark'),
warning: new YaakColor('#ffff00', 'dark'),
danger: new YaakColor('#ffff00', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#000000', 'dark'),
text: new YaakColor('#ffffff', 'dark'),
textSubtle: new YaakColor('#ffff00', 'dark'),
textSubtlest: new YaakColor('#ff0000', 'dark'),
},
menu: {
surface: new YaakColor('#000000', 'dark'),
border: new YaakColor('#ff0000', 'dark'),
surfaceHighlight: new YaakColor('#ff0000', 'dark'),
text: new YaakColor('#ffffff', 'dark'),
textSubtle: new YaakColor('#ffff00', 'dark'),
textSubtlest: new YaakColor('#ffff00', 'dark'),
},
button: {
surface: new YaakColor('#000000', 'dark'),
text: new YaakColor('#ffffff', 'dark'),
primary: new YaakColor('#000000', 'dark'),
secondary: new YaakColor('#ffffff', 'dark'),
info: new YaakColor('#000000', 'dark'),
success: new YaakColor('#ffff00', 'dark'),
notice: new YaakColor('#ffff00', 'dark'),
warning: new YaakColor('#000000', 'dark'),
danger: new YaakColor('#ff0000', 'dark'),
},
editor: {
primary: new YaakColor('#ffffff', 'dark'),
secondary: new YaakColor('#ffffff', 'dark'),
info: new YaakColor('#ffffff', 'dark'),
success: new YaakColor('#ffffff', 'dark'),
notice: new YaakColor('#ffff00', 'dark'),
warning: new YaakColor('#ffffff', 'dark'),
danger: new YaakColor('#ffffff', 'dark'),
},
},
};
export const hotdogStand = [hotdogStandDefault];

View File

@@ -1,221 +0,0 @@
import { YaakColor } from '../yaakColor';
import type { YaakTheme } from '../window';
export const monokaiProDefault: YaakTheme = {
id: 'monokai-pro',
name: 'Monokai Pro',
surface: new YaakColor('#2d2a2e', 'dark'),
text: new YaakColor('#fcfcfa', 'dark'),
textSubtle: new YaakColor('#c1c0c0', 'dark'),
textSubtlest: new YaakColor('#939293', 'dark'),
primary: new YaakColor('#ab9df2', 'dark'),
secondary: new YaakColor('#c1c0c0', 'dark'),
info: new YaakColor('#78dce8', 'dark'),
success: new YaakColor('#a9dc76', 'dark'),
notice: new YaakColor('#ffd866', 'dark'),
warning: new YaakColor('#fc9867', 'dark'),
danger: new YaakColor('#ff6188', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#221f22', 'dark'),
text: new YaakColor('#c1c0c0', 'dark'),
textSubtle: new YaakColor('#939293', 'dark'),
textSubtlest: new YaakColor('#727072', 'dark'),
},
button: {
primary: new YaakColor('#ab9df2', 'dark').lower(0.1),
secondary: new YaakColor('#c1c0c0', 'dark').lower(0.1),
info: new YaakColor('#78dce8', 'dark').lower(0.1),
success: new YaakColor('#a9dc76', 'dark').lower(0.1),
notice: new YaakColor('#ffd866', 'dark').lower(0.1),
warning: new YaakColor('#fc9867', 'dark').lower(0.1),
danger: new YaakColor('#ff6188', 'dark').lower(0.1),
},
},
};
const monokaiProClassic: YaakTheme = {
id: 'monokai-pro-classic',
name: 'Monokai Pro Classic',
surface: new YaakColor('#272822', 'dark'),
text: new YaakColor('#fdfff1', 'dark'),
textSubtle: new YaakColor('#c0c1b5', 'dark'),
textSubtlest: new YaakColor('#919288', 'dark'),
primary: new YaakColor('#ae81ff', 'dark'),
secondary: new YaakColor('#b2b9bd', 'dark'),
info: new YaakColor('#66d9ef', 'dark'),
success: new YaakColor('#a6e22e', 'dark'),
notice: new YaakColor('#e6db74', 'dark'),
warning: new YaakColor('#fd971f', 'dark'),
danger: new YaakColor('#f92672', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#1d1e19', 'dark'),
text: new YaakColor('#b2b9bd', 'dark'),
textSubtle: new YaakColor('#767b81', 'dark'),
textSubtlest: new YaakColor('#696d77', 'dark'),
},
button: {
primary: new YaakColor('#ae81ff', 'dark').lower(0.1),
secondary: new YaakColor('#b2b9bd', 'dark').lower(0.1),
info: new YaakColor('#66d9ef', 'dark').lower(0.1),
success: new YaakColor('#a6e22e', 'dark').lower(0.1),
notice: new YaakColor('#e6db74', 'dark').lower(0.1),
warning: new YaakColor('#fd971f', 'dark').lower(0.1),
danger: new YaakColor('#f92672', 'dark').lower(0.1),
},
},
};
const monokaiProMachine: YaakTheme = {
id: 'monokai-pro-machine',
name: 'Monokai Pro Machine',
surface: new YaakColor('#273136', 'dark'),
text: new YaakColor('#eaf2f1', 'dark'),
textSubtle: new YaakColor('#8b9798', 'dark'),
textSubtlest: new YaakColor('#6b7678', 'dark'),
primary: new YaakColor('#baa0f8', 'dark'),
secondary: new YaakColor('#b8c4c3', 'dark'),
info: new YaakColor('#7cd5f1', 'dark'),
success: new YaakColor('#a2e57b', 'dark'),
notice: new YaakColor('#ffed72', 'dark'),
warning: new YaakColor('#ffb270', 'dark'),
danger: new YaakColor('#ff6d7e', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#1d2528', 'dark'),
text: new YaakColor('#b2b9bd', 'dark'),
textSubtle: new YaakColor('#767b81', 'dark'),
textSubtlest: new YaakColor('#696d77', 'dark'),
},
button: {
primary: new YaakColor('#baa0f8', 'dark').lower(0.1),
secondary: new YaakColor('#b8c4c3', 'dark').lower(0.1),
info: new YaakColor('#7cd5f1', 'dark').lower(0.1),
success: new YaakColor('#a2e57b', 'dark').lower(0.1),
notice: new YaakColor('#ffed72', 'dark').lower(0.1),
warning: new YaakColor('#ffb270', 'dark').lower(0.1),
danger: new YaakColor('#ff6d7e', 'dark').lower(0.1),
},
},
};
const monokaiProOctagon: YaakTheme = {
id: 'monokai-pro-octagon',
name: 'Monokai Pro Octagon',
surface: new YaakColor('#282a3a', 'dark'),
text: new YaakColor('#eaf2f1', 'dark'),
textSubtle: new YaakColor('#b2b9bd', 'dark'),
textSubtlest: new YaakColor('#767b81', 'dark'),
primary: new YaakColor('#c39ac9', 'dark'),
secondary: new YaakColor('#b2b9bd', 'dark'),
info: new YaakColor('#9cd1bb', 'dark'),
success: new YaakColor('#bad761', 'dark'),
notice: new YaakColor('#ffd76d', 'dark'),
warning: new YaakColor('#ff9b5e', 'dark'),
danger: new YaakColor('#ff657a', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#1e1f2b', 'dark'),
text: new YaakColor('#b2b9bd', 'dark'),
textSubtle: new YaakColor('#767b81', 'dark'),
textSubtlest: new YaakColor('#696d77', 'dark'),
},
button: {
primary: new YaakColor('#c39ac9', 'dark').lower(0.1).desaturate(0.1),
secondary: new YaakColor('#b2b9bd', 'dark').lower(0.1).desaturate(0.1),
info: new YaakColor('#9cd1bb', 'dark').lower(0.1).desaturate(0.1),
success: new YaakColor('#bad761', 'dark').lower(0.1).desaturate(0.1),
notice: new YaakColor('#ffd76d', 'dark').lower(0.1).desaturate(0.1),
warning: new YaakColor('#ff9b5e', 'dark').lower(0.1).desaturate(0.1),
danger: new YaakColor('#ff657a', 'dark').lower(0.1).desaturate(0.1),
},
},
};
const monokaiProRistretto: YaakTheme = {
id: 'monokai-pro-ristretto',
name: 'Monokai Pro Ristretto',
surface: new YaakColor('#2c2525', 'dark'),
text: new YaakColor('#fff1f3', 'dark'),
textSubtle: new YaakColor('#c3b7b8', 'dark'),
textSubtlest: new YaakColor('#948a8b', 'dark'),
primary: new YaakColor('#a8a9eb', 'dark'),
secondary: new YaakColor('#c3b7b8', 'dark'),
info: new YaakColor('#85dacc', 'dark'),
success: new YaakColor('#adda78', 'dark'),
notice: new YaakColor('#f9cc6c', 'dark'),
warning: new YaakColor('#f38d70', 'dark'),
danger: new YaakColor('#fd6883', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#211c1c', 'dark'),
text: new YaakColor('#c3b7b8', 'dark'),
textSubtle: new YaakColor('#948a8b', 'dark'),
textSubtlest: new YaakColor('#72696a', 'dark'),
},
button: {
primary: new YaakColor('#a8a9eb', 'dark').lower(0.1),
secondary: new YaakColor('#c3b7b8', 'dark').lower(0.1),
info: new YaakColor('#85dacc', 'dark').lower(0.1),
success: new YaakColor('#adda78', 'dark').lower(0.1),
notice: new YaakColor('#f9cc6c', 'dark').lower(0.1),
warning: new YaakColor('#f38d70', 'dark').lower(0.1),
danger: new YaakColor('#fd6883', 'dark').lower(0.1),
},
},
};
const monokaiProSpectrum: YaakTheme = {
id: 'monokai-pro-spectrum',
name: 'Monokai Pro Spectrum',
surface: new YaakColor('#222222', 'dark'),
text: new YaakColor('#f7f1ff', 'dark'),
textSubtle: new YaakColor('#bab6c0', 'dark'),
textSubtlest: new YaakColor('#8b888f', 'dark'),
primary: new YaakColor('#948ae3', 'dark'),
secondary: new YaakColor('#bab6c0', 'dark'),
info: new YaakColor('#5ad4e6', 'dark'),
success: new YaakColor('#7bd88f', 'dark'),
notice: new YaakColor('#fce566', 'dark'),
warning: new YaakColor('#fd9353', 'dark'),
danger: new YaakColor('#fc618d', 'dark'),
components: {
appHeader: {
surface: new YaakColor('#191919', 'dark'),
text: new YaakColor('#bab6c0', 'dark'),
textSubtle: new YaakColor('#8b888f', 'dark'),
textSubtlest: new YaakColor('#69676c', 'dark'),
},
button: {
primary: new YaakColor('#948ae3', 'dark').lower(0.1),
secondary: new YaakColor('#bab6c0', 'dark').lower(0.1),
info: new YaakColor('#5ad4e6', 'dark').lower(0.1),
success: new YaakColor('#7bd88f', 'dark').lower(0.1),
notice: new YaakColor('#fce566', 'dark').lower(0.1),
warning: new YaakColor('#fd9353', 'dark').lower(0.1),
danger: new YaakColor('#fc618d', 'dark').lower(0.1),
},
},
};
export const monokaiPro = [
monokaiProDefault,
monokaiProClassic,
monokaiProMachine,
monokaiProOctagon,
monokaiProRistretto,
monokaiProSpectrum,
];

View File

@@ -1,64 +0,0 @@
import type { YaakTheme } from '../window';
import { YaakColor } from '../yaakColor';
export const colors = {
lightRed: '#ff98a4',
red: '#ff757f',
darkRed: '#ff5370',
lightOrange: '#f8b576',
orange: '#ff966c',
darkOrange: '#fc7b7b',
yellow: '#ffc777',
green: '#c3e88d',
lightTeal: '#7af8ca',
teal: '#3ad7c7',
lightCyan: '#b4f9f8',
cyan: '#78dbff',
sky: '#60bdff',
blue: '#7cafff',
darkBlue: '#3d6fe0',
darkestBlue: '#3b63cf',
indigo: '#af9fff',
purple: '#c4a2ff',
pink: '#fca7ea',
darkPink: '#fd8aca',
saturatedGray: '#7a88cf',
desaturatedGray: '#979bb6',
gray11: '#d5def8',
gray10: '#c8d3f5',
gray9: '#b4c2f0',
gray8: '#a9b8e8',
gray7: '#828bb8',
gray6: '#444a73',
gray5: '#2f334d',
gray4: '#222436',
gray3: '#1e2030',
gray2: '#191a2a',
gray1: '#131421',
} as const;
const moonlightDefault: YaakTheme = {
id: 'moonlight',
name: 'Moonlight',
surface: new YaakColor('#222436', 'dark'),
text: new YaakColor('#d5def8', 'dark'),
textSubtle: new YaakColor('#828bb8', 'dark'),
textSubtlest: new YaakColor('hsl(232,26%,43%)', 'dark'),
primary: new YaakColor(colors.purple, 'dark'),
secondary: new YaakColor(colors.desaturatedGray, 'dark'),
info: new YaakColor(colors.blue, 'dark'),
success: new YaakColor(colors.teal, 'dark'),
notice: new YaakColor(colors.yellow, 'dark'),
warning: new YaakColor(colors.orange, 'dark'),
danger: new YaakColor(colors.red, 'dark'),
components: {
appHeader: {
surface: new YaakColor(colors.gray3, 'dark'),
},
sidebar: {
surface: new YaakColor(colors.gray3, 'dark'),
},
},
};
export const moonlight = [moonlightDefault];

View File

@@ -1,30 +0,0 @@
import type { YaakTheme } from '../window';
import { YaakColor } from '../yaakColor';
const nordDefault: YaakTheme = {
id: 'nord',
name: 'Nord',
surface: new YaakColor('hsl(220, 16%, 22%)', 'dark'), // Nord0 (#2e3440)
surfaceHighlight: new YaakColor('hsl(220, 14%, 28%)', 'dark'), // Nord1 (#3b4252)
text: new YaakColor('hsl(220, 28%, 93%)', 'dark'), // Nord6 (#ECEFF4)
textSubtle: new YaakColor('hsl(220, 26%, 90%)', 'dark'), // Nord5 (#E5E9F0)
textSubtlest: new YaakColor('hsl(220, 24%, 86%)', 'dark'), // Nord4 (#D8DEE9)
primary: new YaakColor('hsl(193, 38%, 68%)', 'dark'), // Nord8 (#88C0D0)
secondary: new YaakColor('hsl(210, 34%, 63%)', 'dark'), // Nord9 (#81A1C1)
info: new YaakColor('hsl(174, 25%, 69%)', 'dark'), // Nord7 (#8FBCBB)
success: new YaakColor('hsl(89, 26%, 66%)', 'dark'), // Nord14 (#A3BE8C)
notice: new YaakColor('hsl(40, 66%, 73%)', 'dark'), // Nord13 (#EBCB8B)
warning: new YaakColor('hsl(17, 48%, 64%)', 'dark'), // Nord12 (#D08770)
danger: new YaakColor('hsl(353, 43%, 56%)', 'dark'), // Nord11 (#BF616A)
components: {
sidebar: {
backdrop: new YaakColor('hsl(220, 16%, 22%)', 'dark'), // Nord0 (#2e3440)
},
appHeader: {
backdrop: new YaakColor('hsl(220, 14%, 28%)', 'dark'), // Nord1 (#3b4252)
},
},
};
export const nord = [nordDefault];

View File

@@ -1,18 +0,0 @@
import { YaakColor } from '../yaakColor';
import type { YaakTheme } from '../window';
const relaxingDefault: YaakTheme = {
name: 'Relaxing',
id: 'relaxing',
surface: new YaakColor('#2b1e3b', 'dark'),
text: new YaakColor('#ede2f5', 'dark'),
primary: new YaakColor('#cba6f7', 'dark'),
secondary: new YaakColor('#bac2de', 'dark'),
info: new YaakColor('#89b4fa', 'dark'),
success: new YaakColor('#a6e3a1', 'dark'),
notice: new YaakColor('#f9e2af', 'dark'),
warning: new YaakColor('#fab387', 'dark'),
danger: new YaakColor('#f38ba8', 'dark'),
};
export const relaxing = [relaxingDefault];

Some files were not shown because too many files have changed in this diff Show More