mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-02-19 00:57:48 +01:00
Compare commits
3 Commits
v2024.3.0-
...
v2024.3.0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50ad4efad7 | ||
|
|
79a3d9c8df | ||
|
|
b8e20d885f |
3
.github/workflows/artifacts.yml
vendored
3
.github/workflows/artifacts.yml
vendored
@@ -7,6 +7,7 @@ permissions: write-all
|
||||
|
||||
jobs:
|
||||
build-artifacts:
|
||||
name: Build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -37,7 +38,7 @@ jobs:
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('src-tauri/Cargo.lock') }}
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
33
src-tauri/Cargo.lock
generated
33
src-tauri/Cargo.lock
generated
@@ -1699,6 +1699,7 @@ dependencies = [
|
||||
"protoc-bin-vendored",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tonic",
|
||||
@@ -1763,9 +1764,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.21"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
|
||||
checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -1773,7 +1774,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.1.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@@ -2974,6 +2975,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
@@ -4164,6 +4175,16 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.1.0"
|
||||
@@ -4197,9 +4218,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.2"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
@@ -4776,6 +4797,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"open",
|
||||
"os_info",
|
||||
"os_pipe",
|
||||
"percent-encoding",
|
||||
"rand 0.8.5",
|
||||
"raw-window-handle",
|
||||
@@ -4787,6 +4809,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"serialize-to-javascript",
|
||||
"shared_child",
|
||||
"state",
|
||||
"sys-locale",
|
||||
"tar",
|
||||
|
||||
@@ -44,6 +44,7 @@ tauri = { version = "1.5.4", features = [
|
||||
"os-all",
|
||||
"protocol-asset",
|
||||
"shell-open",
|
||||
"shell-sidecar",
|
||||
"updater",
|
||||
"window-close",
|
||||
"window-maximize",
|
||||
|
||||
@@ -20,3 +20,4 @@ hyper = { version = "0.14" }
|
||||
hyper-rustls = { version = "0.24.0", features = ["http2"] }
|
||||
protoc-bin-vendored = "3.0.0"
|
||||
uuid = { version = "1.7.0", features = ["v4"] }
|
||||
tauri = { version = "1.5.4", features = ["process-command-api"]}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
use std::env::temp_dir;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use hyper::client::HttpConnector;
|
||||
use hyper::Client;
|
||||
use hyper::client::HttpConnector;
|
||||
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
|
||||
use log::{debug, warn};
|
||||
use log::{debug, info, warn};
|
||||
use prost::Message;
|
||||
use prost_reflect::{DescriptorPool, MethodDescriptor};
|
||||
use prost_types::{FileDescriptorProto, FileDescriptorSet};
|
||||
use tauri::api::process::{Command, CommandEvent};
|
||||
use tokio::fs;
|
||||
use tokio_stream::StreamExt;
|
||||
use tonic::body::BoxBody;
|
||||
use tonic::codegen::http::uri::PathAndQuery;
|
||||
use tonic::transport::Uri;
|
||||
use tonic::Request;
|
||||
use tonic::transport::Uri;
|
||||
use tonic_reflection::pb::server_reflection_client::ServerReflectionClient;
|
||||
use tonic_reflection::pb::server_reflection_request::MessageRequest;
|
||||
use tonic_reflection::pb::server_reflection_response::MessageResponse;
|
||||
@@ -27,36 +27,67 @@ pub async fn fill_pool_from_files(paths: Vec<PathBuf>) -> Result<DescriptorPool,
|
||||
let mut pool = DescriptorPool::new();
|
||||
let random_file_name = format!("{}.desc", uuid::Uuid::new_v4());
|
||||
let desc_path = temp_dir().join(random_file_name);
|
||||
let bin = protoc_bin_vendored::protoc_bin_path().unwrap();
|
||||
|
||||
let mut cmd = Command::new(bin.clone());
|
||||
cmd.arg("--include_imports")
|
||||
.arg("--include_source_info")
|
||||
.arg("-o")
|
||||
.arg(&desc_path);
|
||||
let mut args = vec![
|
||||
"--include_imports".to_string(),
|
||||
"--include_source_info".to_string(),
|
||||
"-o".to_string(),
|
||||
desc_path.to_string_lossy().to_string(),
|
||||
];
|
||||
|
||||
for p in paths {
|
||||
if p.as_path().exists() {
|
||||
cmd.arg(p.as_path().to_string_lossy().as_ref());
|
||||
args.push(p.to_string_lossy().to_string());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
let parent = p.as_path().parent();
|
||||
if let Some(parent_path) = parent {
|
||||
cmd.arg("-I").arg(parent_path);
|
||||
cmd.arg("-I").arg(parent_path.parent().unwrap());
|
||||
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());
|
||||
} else {
|
||||
debug!("ignoring {:?} since it does not exist.", parent)
|
||||
}
|
||||
}
|
||||
|
||||
let output = cmd.output().map_err(|e| e.to_string())?;
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"protoc failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
let (mut rx, _child) = Command::new_sidecar("protoc")
|
||||
.expect("protoc not found")
|
||||
.args(args)
|
||||
.spawn()
|
||||
.expect("protoc failed to start");
|
||||
|
||||
while let Some(event) = rx.recv().await {
|
||||
match event {
|
||||
CommandEvent::Stdout(line) => {
|
||||
info!("protoc stdout: {}", line);
|
||||
}
|
||||
CommandEvent::Stderr(line) => {
|
||||
info!("protoc stderr: {}", line);
|
||||
}
|
||||
CommandEvent::Error(e) => {
|
||||
return Err(e.to_string());
|
||||
}
|
||||
CommandEvent::Terminated(c) => {
|
||||
match c.code {
|
||||
Some(0) => {
|
||||
// success
|
||||
}
|
||||
Some(code) => {
|
||||
return Err(format!(
|
||||
"protoc failed with exit code: {}",
|
||||
code,
|
||||
));
|
||||
}
|
||||
None => {
|
||||
return Err("protoc failed with no exit code".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
let bytes = fs::read(desc_path.as_path())
|
||||
|
||||
BIN
src-tauri/protoc-vendored/protoc-aarch64-apple-darwin
Executable file
BIN
src-tauri/protoc-vendored/protoc-aarch64-apple-darwin
Executable file
Binary file not shown.
BIN
src-tauri/protoc-vendored/protoc-x86_64-apple-darwin
Executable file
BIN
src-tauri/protoc-vendored/protoc-x86_64-apple-darwin
Executable file
Binary file not shown.
BIN
src-tauri/protoc-vendored/protoc-x86_64-pc-windows-msvc.exe
Executable file
BIN
src-tauri/protoc-vendored/protoc-x86_64-pc-windows-msvc.exe
Executable file
Binary file not shown.
BIN
src-tauri/protoc-vendored/protoc-x86_64-unknown-linux-gnu
Executable file
BIN
src-tauri/protoc-vendored/protoc-x86_64-unknown-linux-gnu
Executable file
Binary file not shown.
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "Yaak",
|
||||
"version": "2024.3.0-beta.1"
|
||||
"version": "2024.3.0-beta.2"
|
||||
},
|
||||
"tauri": {
|
||||
"windows": [],
|
||||
@@ -32,7 +32,13 @@
|
||||
},
|
||||
"shell": {
|
||||
"all": false,
|
||||
"open": true
|
||||
"open": true,
|
||||
"sidecar": true,
|
||||
"scope": [
|
||||
{ "name": "protoc", "sidecar": true,
|
||||
"args": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"window": {
|
||||
"close": true,
|
||||
@@ -56,7 +62,9 @@
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"externalBin": [],
|
||||
"externalBin": [
|
||||
"protoc-vendored/protoc"
|
||||
],
|
||||
"icon": [
|
||||
"icons/release/32x32.png",
|
||||
"icons/release/128x128.png",
|
||||
|
||||
@@ -8,16 +8,17 @@ import { Dropdown } from './core/Dropdown';
|
||||
interface Props {
|
||||
hideFolder?: boolean;
|
||||
children: DropdownProps['children'];
|
||||
openOnHotKeyAction?: DropdownProps['openOnHotKeyAction'];
|
||||
}
|
||||
|
||||
export function CreateDropdown({ hideFolder, children }: Props) {
|
||||
export function CreateDropdown({ hideFolder, children, openOnHotKeyAction }: Props) {
|
||||
const createHttpRequest = useCreateHttpRequest();
|
||||
const createGrpcRequest = useCreateGrpcRequest();
|
||||
const createFolder = useCreateFolder();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
openOnHotKeyAction="http_request.create"
|
||||
openOnHotKeyAction={openOnHotKeyAction}
|
||||
items={[
|
||||
{
|
||||
key: 'create-http-request',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import type { ForwardedRef, ReactNode } from 'react';
|
||||
import React, { Fragment, forwardRef, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import React, { forwardRef, Fragment, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import type { XYCoord } from 'react-dnd';
|
||||
import { useDrag, useDrop } from 'react-dnd';
|
||||
import { useKey, useKeyPressEvent } from 'react-use';
|
||||
@@ -11,8 +11,6 @@ import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||
import { useAppRoutes } from '../hooks/useAppRoutes';
|
||||
import { useCreateFolder } from '../hooks/useCreateFolder';
|
||||
import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest';
|
||||
import { useDeleteAnyGrpcRequest } from '../hooks/useDeleteAnyGrpcRequest';
|
||||
import { useDeleteAnyHttpRequest } from '../hooks/useDeleteAnyHttpRequest';
|
||||
import { useDeleteFolder } from '../hooks/useDeleteFolder';
|
||||
import { useDeleteRequest } from '../hooks/useDeleteRequest';
|
||||
import { useDuplicateGrpcRequest } from '../hooks/useDuplicateGrpcRequest';
|
||||
@@ -68,8 +66,6 @@ export function Sidebar({ className }: Props) {
|
||||
const httpRequests = useHttpRequests();
|
||||
const grpcRequests = useGrpcRequests();
|
||||
const folders = useFolders();
|
||||
const deleteAnyHttpRequest = useDeleteAnyHttpRequest();
|
||||
const deleteAnyGrpcRequest = useDeleteAnyGrpcRequest();
|
||||
const activeWorkspace = useActiveWorkspace();
|
||||
const duplicateHttpRequest = useDuplicateHttpRequest({
|
||||
id: activeRequest?.id ?? null,
|
||||
@@ -108,9 +104,10 @@ export function Sidebar({ className }: Props) {
|
||||
[collapsed.value],
|
||||
);
|
||||
|
||||
const { tree, treeParentMap, selectableRequests } = useMemo<{
|
||||
const { tree, treeParentMap, selectableRequests, selectedRequest } = useMemo<{
|
||||
tree: TreeNode | null;
|
||||
treeParentMap: Record<string, TreeNode>;
|
||||
selectedRequest: HttpRequest | GrpcRequest | null;
|
||||
selectableRequests: {
|
||||
id: string;
|
||||
index: number;
|
||||
@@ -123,14 +120,23 @@ export function Sidebar({ className }: Props) {
|
||||
index: number;
|
||||
tree: TreeNode;
|
||||
}[] = [];
|
||||
|
||||
if (activeWorkspace == null) {
|
||||
return { tree: null, treeParentMap, selectableRequests };
|
||||
return { tree: null, treeParentMap, selectableRequests, selectedRequest: null };
|
||||
}
|
||||
|
||||
let selectedRequest: HttpRequest | GrpcRequest | null = null;
|
||||
let selectableRequestIndex = 0;
|
||||
|
||||
// Put requests and folders into a tree structure
|
||||
const next = (node: TreeNode): TreeNode => {
|
||||
if (
|
||||
node.item.id === selectedId &&
|
||||
(node.item.model === 'http_request' || node.item.model === 'grpc_request')
|
||||
) {
|
||||
selectedRequest = node.item;
|
||||
}
|
||||
|
||||
const childItems = [...httpRequests, ...grpcRequests, ...folders].filter((f) =>
|
||||
node.item.model === 'workspace' ? f.folderId == null : f.folderId === node.item.id,
|
||||
);
|
||||
@@ -149,8 +155,10 @@ export function Sidebar({ className }: Props) {
|
||||
|
||||
const tree = next({ item: activeWorkspace, children: [], depth: 0 });
|
||||
|
||||
return { tree, treeParentMap, selectableRequests };
|
||||
}, [activeWorkspace, httpRequests, grpcRequests, folders]);
|
||||
return { tree, treeParentMap, selectableRequests, selectedRequest };
|
||||
}, [activeWorkspace, selectedId, httpRequests, grpcRequests, folders]);
|
||||
|
||||
const deleteSelectedRequest = useDeleteRequest(selectedRequest);
|
||||
|
||||
const focusActiveRequest = useCallback(
|
||||
(
|
||||
@@ -221,16 +229,15 @@ export function Sidebar({ className }: Props) {
|
||||
const handleBlur = useCallback(() => setHasFocus(false), []);
|
||||
|
||||
const handleDeleteKey = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
async (e: KeyboardEvent) => {
|
||||
if (!hasFocus) return;
|
||||
e.preventDefault();
|
||||
|
||||
const selected = selectableRequests.find((r) => r.id === selectedId);
|
||||
if (selected == null) return;
|
||||
deleteAnyHttpRequest.mutate(selected.id);
|
||||
deleteAnyGrpcRequest.mutate(selected.id);
|
||||
await deleteSelectedRequest.mutateAsync();
|
||||
},
|
||||
[deleteAnyHttpRequest, deleteAnyGrpcRequest, hasFocus, selectableRequests, selectedId],
|
||||
[hasFocus, selectableRequests, deleteSelectedRequest, selectedId],
|
||||
);
|
||||
|
||||
useKeyPressEvent('Backspace', handleDeleteKey);
|
||||
@@ -577,7 +584,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
const createRequest = useCreateHttpRequest();
|
||||
const createFolder = useCreateFolder();
|
||||
const deleteFolder = useDeleteFolder(itemId);
|
||||
const deleteRequest = useDeleteRequest(itemId);
|
||||
const deleteRequest = useDeleteRequest(activeRequest ?? null);
|
||||
const duplicateHttpRequest = useDuplicateHttpRequest({ id: itemId, navigateAfter: true });
|
||||
const duplicateGrpcRequest = useDuplicateGrpcRequest({ id: itemId, navigateAfter: true });
|
||||
const sendRequest = useSendRequest(itemId);
|
||||
|
||||
@@ -25,7 +25,7 @@ export const SidebarActions = memo(function SidebarActions() {
|
||||
hotkeyAction="sidebar.toggle"
|
||||
icon={hidden ? 'leftPanelHidden' : 'leftPanelVisible'}
|
||||
/>
|
||||
<CreateDropdown>
|
||||
<CreateDropdown openOnHotKeyAction="http_request.create">
|
||||
<IconButton size="sm" icon="plusCircle" title="Add Resource" />
|
||||
</CreateDropdown>
|
||||
</HStack>
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import type { GrpcRequest, HttpRequest } from '../lib/models';
|
||||
import { useDeleteAnyGrpcRequest } from './useDeleteAnyGrpcRequest';
|
||||
import { useDeleteAnyHttpRequest } from './useDeleteAnyHttpRequest';
|
||||
|
||||
export function useDeleteRequest(id: string | null) {
|
||||
const deleteAnyRequest = useDeleteAnyHttpRequest();
|
||||
export function useDeleteRequest(request: HttpRequest | GrpcRequest | null) {
|
||||
const deleteAnyHttpRequest = useDeleteAnyHttpRequest();
|
||||
const deleteAnyGrpcRequest = useDeleteAnyGrpcRequest();
|
||||
|
||||
return useMutation<HttpRequest | null, string>({
|
||||
mutationFn: () => deleteAnyRequest.mutateAsync(id ?? 'n/a'),
|
||||
return useMutation<void, string>({
|
||||
mutationFn: async () => {
|
||||
if (request?.model === 'http_request') {
|
||||
await deleteAnyHttpRequest.mutateAsync(request.id);
|
||||
} else if (request?.model === 'grpc_request') {
|
||||
await deleteAnyGrpcRequest.mutateAsync(request.id);
|
||||
} else {
|
||||
// Request is null
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user