mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-21 00:49:17 +01:00
Show gRPC requests in sidebar
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use log::{debug, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use sqlx::{Pool, Sqlite};
|
||||
use sqlx::types::JsonValue;
|
||||
use sqlx::{Pool, Sqlite};
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
use crate::{is_dev, models};
|
||||
@@ -15,6 +15,7 @@ pub enum AnalyticsResource {
|
||||
Dialog,
|
||||
Environment,
|
||||
Folder,
|
||||
GrpcRequest,
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
KeyValue,
|
||||
@@ -30,6 +31,7 @@ impl AnalyticsResource {
|
||||
"CookieJar" => Some(AnalyticsResource::CookieJar),
|
||||
"Environment" => Some(AnalyticsResource::Environment),
|
||||
"Folder" => Some(AnalyticsResource::Folder),
|
||||
"GrpcRequest" => Some(AnalyticsResource::GrpcRequest),
|
||||
"HttpRequest" => Some(AnalyticsResource::HttpRequest),
|
||||
"HttpResponse" => Some(AnalyticsResource::HttpResponse),
|
||||
"KeyValue" => Some(AnalyticsResource::KeyValue),
|
||||
@@ -89,6 +91,7 @@ fn resource_name(resource: AnalyticsResource) -> &'static str {
|
||||
AnalyticsResource::Dialog => "dialog",
|
||||
AnalyticsResource::Environment => "environment",
|
||||
AnalyticsResource::Folder => "folder",
|
||||
AnalyticsResource::GrpcRequest => "grpc_request",
|
||||
AnalyticsResource::HttpRequest => "http_request",
|
||||
AnalyticsResource::HttpResponse => "http_response",
|
||||
AnalyticsResource::KeyValue => "key_value",
|
||||
|
||||
@@ -44,13 +44,14 @@ use crate::http::send_http_request;
|
||||
use crate::models::{
|
||||
cancel_pending_responses, create_response, delete_all_responses, delete_cookie_jar,
|
||||
delete_environment, delete_folder, delete_request, delete_response, delete_workspace,
|
||||
duplicate_request, find_cookie_jars, find_environments, find_folders, find_requests,
|
||||
find_responses, find_workspaces, generate_id, get_cookie_jar, get_environment, get_folder,
|
||||
get_http_request, get_key_value_raw, get_or_create_settings, get_response, get_workspace,
|
||||
get_workspace_export_resources, set_key_value_raw, update_response_if_id, update_settings,
|
||||
upsert_cookie_jar, upsert_environment, upsert_folder, upsert_request, upsert_workspace,
|
||||
CookieJar, Environment, EnvironmentVariable, Folder, HttpRequest, HttpResponse, KeyValue,
|
||||
Settings, Workspace,
|
||||
duplicate_grpc_request, duplicate_http_request, list_cookie_jars, list_folders, list_requests,
|
||||
list_responses, list_workspaces, generate_id, get_cookie_jar, get_environment, get_folder,
|
||||
get_grpc_request, get_http_request, get_key_value_raw, get_or_create_settings, get_response,
|
||||
get_workspace, get_workspace_export_resources, list_environments, list_grpc_requests,
|
||||
set_key_value_raw, update_response_if_id, update_settings, upsert_cookie_jar,
|
||||
upsert_environment, upsert_folder, upsert_grpc_request, upsert_http_request, upsert_workspace,
|
||||
CookieJar, Environment, EnvironmentVariable, Folder, GrpcRequest, HttpRequest, HttpResponse,
|
||||
KeyValue, Settings, Workspace,
|
||||
};
|
||||
use crate::plugin::{ImportResources, ImportResult};
|
||||
use crate::updates::{update_mode_from_str, UpdateMode, YaakUpdater};
|
||||
@@ -467,7 +468,7 @@ async fn cmd_import_data(
|
||||
}
|
||||
|
||||
for r in r.resources.requests {
|
||||
let x = upsert_request(db, r)
|
||||
let x = upsert_http_request(db, r)
|
||||
.await
|
||||
.expect("Failed to create request");
|
||||
imported_resources.requests.push(x.clone());
|
||||
@@ -747,7 +748,46 @@ async fn cmd_create_environment(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_create_request(
|
||||
async fn cmd_create_grpc_request(
|
||||
workspace_id: &str,
|
||||
name: &str,
|
||||
sort_priority: f64,
|
||||
folder_id: Option<&str>,
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<GrpcRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let created = upsert_grpc_request(
|
||||
db,
|
||||
&GrpcRequest {
|
||||
workspace_id: workspace_id.to_string(),
|
||||
name: name.to_string(),
|
||||
folder_id: folder_id.map(|s| s.to_string()),
|
||||
sort_priority,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create grpc request");
|
||||
|
||||
emit_and_return(&window, "created_model", created)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_duplicate_grpc_request(
|
||||
id: &str,
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<GrpcRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let request = duplicate_grpc_request(db, id)
|
||||
.await
|
||||
.expect("Failed to duplicate grpc request");
|
||||
emit_and_return(&window, "updated_model", request)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_create_http_request(
|
||||
workspace_id: &str,
|
||||
name: &str,
|
||||
sort_priority: f64,
|
||||
@@ -756,7 +796,7 @@ async fn cmd_create_request(
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<HttpRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let created_request = upsert_request(
|
||||
let created_request = upsert_http_request(
|
||||
db,
|
||||
HttpRequest {
|
||||
workspace_id: workspace_id.to_string(),
|
||||
@@ -768,21 +808,21 @@ async fn cmd_create_request(
|
||||
},
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create request");
|
||||
.expect("Failed to create http request");
|
||||
|
||||
emit_and_return(&window, "created_model", created_request)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_duplicate_request(
|
||||
async fn cmd_duplicate_http_request(
|
||||
id: &str,
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<HttpRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let request = duplicate_request(db, id)
|
||||
let request = duplicate_http_request(db, id)
|
||||
.await
|
||||
.expect("Failed to duplicate request");
|
||||
.expect("Failed to duplicate http request");
|
||||
emit_and_return(&window, "updated_model", request)
|
||||
}
|
||||
|
||||
@@ -815,20 +855,46 @@ async fn cmd_update_environment(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_update_request(
|
||||
async fn cmd_update_grpc_request(
|
||||
request: GrpcRequest,
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<GrpcRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let updated_request = upsert_grpc_request(db, &request)
|
||||
.await
|
||||
.expect("Failed to update grpc request");
|
||||
emit_and_return(&window, "updated_model", updated_request)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_update_http_request(
|
||||
request: HttpRequest,
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<HttpRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let updated_request = upsert_request(db, request)
|
||||
let updated_request = upsert_http_request(db, request)
|
||||
.await
|
||||
.expect("Failed to update request");
|
||||
emit_and_return(&window, "updated_model", updated_request)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_delete_request(
|
||||
async fn cmd_delete_grpc_request(
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
request_id: &str,
|
||||
) -> Result<HttpRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let req = delete_request(db, request_id)
|
||||
.await
|
||||
.expect("Failed to delete request");
|
||||
emit_and_return(&window, "deleted_model", req)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_delete_http_request(
|
||||
window: Window<Wry>,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
request_id: &str,
|
||||
@@ -846,7 +912,7 @@ async fn cmd_list_folders(
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<Folder>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
find_folders(db, workspace_id)
|
||||
list_folders(db, workspace_id)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -917,12 +983,25 @@ async fn cmd_delete_environment(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_list_requests(
|
||||
async fn cmd_list_grpc_requests(
|
||||
workspace_id: &str,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<GrpcRequest>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let requests = list_grpc_requests(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to find grpc requests");
|
||||
// .map_err(|e| e.to_string())
|
||||
Ok(requests)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_list_http_requests(
|
||||
workspace_id: &str,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<HttpRequest>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let requests = find_requests(db, workspace_id)
|
||||
let requests = list_requests(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to find requests");
|
||||
// .map_err(|e| e.to_string())
|
||||
@@ -935,7 +1014,7 @@ async fn cmd_list_environments(
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<Environment>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let environments = find_environments(db, workspace_id)
|
||||
let environments = list_environments(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to find environments");
|
||||
|
||||
@@ -972,7 +1051,16 @@ async fn cmd_get_folder(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_get_request(
|
||||
async fn cmd_get_grpc_request(
|
||||
id: &str,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<GrpcRequest, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
get_grpc_request(db, id).await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_get_http_request(
|
||||
id: &str,
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<HttpRequest, String> {
|
||||
@@ -995,7 +1083,7 @@ async fn cmd_list_cookie_jars(
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<CookieJar>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let cookie_jars = find_cookie_jars(db, workspace_id)
|
||||
let cookie_jars = list_cookie_jars(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to find cookie jars");
|
||||
|
||||
@@ -1041,7 +1129,7 @@ async fn cmd_list_responses(
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<HttpResponse>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
find_responses(db, request_id, limit)
|
||||
list_responses(db, request_id, limit)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -1075,7 +1163,7 @@ async fn cmd_list_workspaces(
|
||||
db_state: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<Workspace>, String> {
|
||||
let db = &*db_state.lock().await;
|
||||
let workspaces = find_workspaces(db)
|
||||
let workspaces = list_workspaces(db)
|
||||
.await
|
||||
.expect("Failed to find workspaces");
|
||||
if workspaces.is_empty() {
|
||||
@@ -1203,23 +1291,26 @@ fn main() {
|
||||
cmd_create_cookie_jar,
|
||||
cmd_create_environment,
|
||||
cmd_create_folder,
|
||||
cmd_create_request,
|
||||
cmd_create_grpc_request,
|
||||
cmd_create_http_request,
|
||||
cmd_create_workspace,
|
||||
cmd_delete_all_responses,
|
||||
cmd_delete_cookie_jar,
|
||||
cmd_delete_environment,
|
||||
cmd_delete_folder,
|
||||
cmd_delete_request,
|
||||
cmd_delete_grpc_request,
|
||||
cmd_delete_http_request,
|
||||
cmd_delete_response,
|
||||
cmd_delete_workspace,
|
||||
cmd_duplicate_request,
|
||||
cmd_duplicate_http_request,
|
||||
cmd_export_data,
|
||||
cmd_filter_response,
|
||||
cmd_get_cookie_jar,
|
||||
cmd_get_environment,
|
||||
cmd_get_folder,
|
||||
cmd_get_key_value,
|
||||
cmd_get_request,
|
||||
cmd_get_http_request,
|
||||
cmd_get_grpc_request,
|
||||
cmd_get_settings,
|
||||
cmd_get_workspace,
|
||||
cmd_grpc_call_unary,
|
||||
@@ -1231,7 +1322,8 @@ fn main() {
|
||||
cmd_list_cookie_jars,
|
||||
cmd_list_environments,
|
||||
cmd_list_folders,
|
||||
cmd_list_requests,
|
||||
cmd_list_http_requests,
|
||||
cmd_list_grpc_requests,
|
||||
cmd_list_responses,
|
||||
cmd_list_workspaces,
|
||||
cmd_new_window,
|
||||
@@ -1243,7 +1335,8 @@ fn main() {
|
||||
cmd_update_cookie_jar,
|
||||
cmd_update_environment,
|
||||
cmd_update_folder,
|
||||
cmd_update_request,
|
||||
cmd_update_grpc_request,
|
||||
cmd_update_http_request,
|
||||
cmd_update_settings,
|
||||
cmd_update_workspace,
|
||||
])
|
||||
|
||||
@@ -355,7 +355,7 @@ pub async fn get_key_value_raw(db: &Pool<Sqlite>, namespace: &str, key: &str) ->
|
||||
.ok()
|
||||
}
|
||||
|
||||
pub async fn find_workspaces(db: &Pool<Sqlite>) -> Result<Vec<Workspace>, sqlx::Error> {
|
||||
pub async fn list_workspaces(db: &Pool<Sqlite>) -> Result<Vec<Workspace>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Workspace,
|
||||
r#"
|
||||
@@ -398,7 +398,7 @@ pub async fn delete_workspace(db: &Pool<Sqlite>, id: &str) -> Result<Workspace,
|
||||
.execute(db)
|
||||
.await;
|
||||
|
||||
for r in find_responses_by_workspace_id(db, id).await? {
|
||||
for r in list_responses_by_workspace_id(db, id).await? {
|
||||
delete_response(db, &r.id).await?;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ pub async fn get_cookie_jar(db: &Pool<Sqlite>, id: &str) -> Result<CookieJar, sq
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_cookie_jars(
|
||||
pub async fn list_cookie_jars(
|
||||
db: &Pool<Sqlite>,
|
||||
workspace_id: &str,
|
||||
) -> Result<Vec<CookieJar>, sqlx::Error> {
|
||||
@@ -454,6 +454,15 @@ pub async fn delete_cookie_jar(db: &Pool<Sqlite>, id: &str) -> Result<CookieJar,
|
||||
Ok(cookie_jar)
|
||||
}
|
||||
|
||||
pub async fn duplicate_grpc_request(
|
||||
db: &Pool<Sqlite>,
|
||||
id: &str,
|
||||
) -> Result<GrpcRequest, sqlx::Error> {
|
||||
let mut request = get_grpc_request(db, id).await?.clone();
|
||||
request.id = "".to_string();
|
||||
upsert_grpc_request(db, &request).await
|
||||
}
|
||||
|
||||
pub async fn upsert_grpc_request(
|
||||
db: &Pool<Sqlite>,
|
||||
request: &GrpcRequest,
|
||||
@@ -687,7 +696,7 @@ pub async fn upsert_cookie_jar(
|
||||
get_cookie_jar(db, &id).await
|
||||
}
|
||||
|
||||
pub async fn find_environments(
|
||||
pub async fn list_environments(
|
||||
db: &Pool<Sqlite>,
|
||||
workspace_id: &str,
|
||||
) -> Result<Vec<Environment>, sqlx::Error> {
|
||||
@@ -832,7 +841,7 @@ pub async fn get_folder(db: &Pool<Sqlite>, id: &str) -> Result<Folder, sqlx::Err
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_folders(
|
||||
pub async fn list_folders(
|
||||
db: &Pool<Sqlite>,
|
||||
workspace_id: &str,
|
||||
) -> Result<Vec<Folder>, sqlx::Error> {
|
||||
@@ -896,13 +905,19 @@ pub async fn upsert_folder(db: &Pool<Sqlite>, r: Folder) -> Result<Folder, sqlx:
|
||||
get_folder(db, &id).await
|
||||
}
|
||||
|
||||
pub async fn duplicate_request(db: &Pool<Sqlite>, id: &str) -> Result<HttpRequest, sqlx::Error> {
|
||||
pub async fn duplicate_http_request(
|
||||
db: &Pool<Sqlite>,
|
||||
id: &str,
|
||||
) -> Result<HttpRequest, sqlx::Error> {
|
||||
let mut request = get_http_request(db, id).await?.clone();
|
||||
request.id = "".to_string();
|
||||
upsert_request(db, request).await
|
||||
upsert_http_request(db, request).await
|
||||
}
|
||||
|
||||
pub async fn upsert_request(db: &Pool<Sqlite>, r: HttpRequest) -> Result<HttpRequest, sqlx::Error> {
|
||||
pub async fn upsert_http_request(
|
||||
db: &Pool<Sqlite>,
|
||||
r: HttpRequest,
|
||||
) -> Result<HttpRequest, sqlx::Error> {
|
||||
let id = match r.id.as_str() {
|
||||
"" => generate_id(Some("rq")),
|
||||
_ => r.id.to_string(),
|
||||
@@ -952,7 +967,7 @@ pub async fn upsert_request(db: &Pool<Sqlite>, r: HttpRequest) -> Result<HttpReq
|
||||
get_http_request(db, &id).await
|
||||
}
|
||||
|
||||
pub async fn find_requests(
|
||||
pub async fn list_requests(
|
||||
db: &Pool<Sqlite>,
|
||||
workspace_id: &str,
|
||||
) -> Result<Vec<HttpRequest>, sqlx::Error> {
|
||||
@@ -1171,7 +1186,7 @@ pub async fn get_response(db: &Pool<Sqlite>, id: &str) -> Result<HttpResponse, s
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_responses(
|
||||
pub async fn list_responses(
|
||||
db: &Pool<Sqlite>,
|
||||
request_id: &str,
|
||||
limit: Option<i64>,
|
||||
@@ -1197,7 +1212,7 @@ pub async fn find_responses(
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_responses_by_workspace_id(
|
||||
pub async fn list_responses_by_workspace_id(
|
||||
db: &Pool<Sqlite>,
|
||||
workspace_id: &str,
|
||||
) -> Result<Vec<HttpResponse>, sqlx::Error> {
|
||||
@@ -1243,7 +1258,7 @@ pub async fn delete_response(db: &Pool<Sqlite>, id: &str) -> Result<HttpResponse
|
||||
}
|
||||
|
||||
pub async fn delete_all_responses(db: &Pool<Sqlite>, request_id: &str) -> Result<(), sqlx::Error> {
|
||||
for r in find_responses(db, request_id, None).await? {
|
||||
for r in list_responses(db, request_id, None).await? {
|
||||
delete_response(db, &r.id).await?;
|
||||
}
|
||||
Ok(())
|
||||
@@ -1289,13 +1304,13 @@ pub async fn get_workspace_export_resources(
|
||||
timestamp: chrono::Utc::now().naive_utc(),
|
||||
resources: WorkspaceExportResources {
|
||||
workspaces: vec![workspace],
|
||||
environments: find_environments(db, workspace_id)
|
||||
environments: list_environments(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get environments"),
|
||||
folders: find_folders(db, workspace_id)
|
||||
folders: list_folders(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get folders"),
|
||||
requests: find_requests(db, workspace_id)
|
||||
requests: list_requests(db, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get requests"),
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createBrowserRouter, Navigate, Outlet, RouterProvider } from 'react-router-dom';
|
||||
import { routePaths, useAppRoutes } from '../hooks/useAppRoutes';
|
||||
import { useRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useRequests } from '../hooks/useRequests';
|
||||
import { useHttpRequests } from '../hooks/useHttpRequests';
|
||||
import { GlobalHooks } from './GlobalHooks';
|
||||
import Workspace from './Workspace';
|
||||
import Workspaces from './Workspaces';
|
||||
@@ -49,7 +49,7 @@ export function AppRouter() {
|
||||
function WorkspaceOrRedirect() {
|
||||
const recentRequests = useRecentRequests();
|
||||
const activeEnvironmentId = useActiveEnvironmentId();
|
||||
const requests = useRequests();
|
||||
const requests = useHttpRequests();
|
||||
const request = requests.find((r) => r.id === recentRequests[0]);
|
||||
const routes = useAppRoutes();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||
import { useUpdateHttpRequest } from '../hooks/useUpdateHttpRequest';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { Input } from './core/Input';
|
||||
import { VStack } from './core/Stacks';
|
||||
@@ -9,7 +9,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export function BasicAuth({ requestId, authentication }: Props) {
|
||||
const updateRequest = useUpdateRequest(requestId);
|
||||
const updateRequest = useUpdateHttpRequest(requestId);
|
||||
|
||||
return (
|
||||
<VStack className="my-2" space={2}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||
import { useUpdateHttpRequest } from '../hooks/useUpdateHttpRequest';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { Input } from './core/Input';
|
||||
import { VStack } from './core/Stacks';
|
||||
@@ -9,7 +9,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export function BearerAuth({ requestId, authentication }: Props) {
|
||||
const updateRequest = useUpdateRequest(requestId);
|
||||
const updateRequest = useUpdateHttpRequest(requestId);
|
||||
|
||||
return (
|
||||
<VStack className="my-2" space={2}>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
||||
import { useRecentEnvironments } from '../hooks/useRecentEnvironments';
|
||||
import { useRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces';
|
||||
import { requestsQueryKey } from '../hooks/useRequests';
|
||||
import { httpRequestsQueryKey } from '../hooks/useHttpRequests';
|
||||
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
||||
import { responsesQueryKey } from '../hooks/useResponses';
|
||||
import { settingsQueryKey } from '../hooks/useSettings';
|
||||
@@ -47,7 +47,7 @@ export function GlobalHooks() {
|
||||
|
||||
const queryKey =
|
||||
payload.model === 'http_request'
|
||||
? requestsQueryKey(payload)
|
||||
? httpRequestsQueryKey(payload)
|
||||
: payload.model === 'http_response'
|
||||
? responsesQueryKey(payload)
|
||||
: payload.model === 'workspace'
|
||||
@@ -76,7 +76,7 @@ export function GlobalHooks() {
|
||||
|
||||
const queryKey =
|
||||
payload.model === 'http_request'
|
||||
? requestsQueryKey(payload)
|
||||
? httpRequestsQueryKey(payload)
|
||||
: payload.model === 'http_response'
|
||||
? responsesQueryKey(payload)
|
||||
: payload.model === 'workspace'
|
||||
@@ -115,7 +115,7 @@ export function GlobalHooks() {
|
||||
if (payload.model === 'workspace') {
|
||||
queryClient.setQueryData<Workspace[]>(workspacesQueryKey(), removeById(payload));
|
||||
} else if (payload.model === 'http_request') {
|
||||
queryClient.setQueryData<HttpRequest[]>(requestsQueryKey(payload), removeById(payload));
|
||||
queryClient.setQueryData<HttpRequest[]>(httpRequestsQueryKey(payload), removeById(payload));
|
||||
} else if (payload.model === 'http_response') {
|
||||
queryClient.setQueryData<HttpResponse[]>(responsesQueryKey(payload), removeById(payload));
|
||||
} else if (payload.model === 'key_value') {
|
||||
|
||||
@@ -208,7 +208,7 @@ export function GrpcConnectionLayout({ style }: Props) {
|
||||
className="border border-highlight"
|
||||
size="sm"
|
||||
title="to-do"
|
||||
hotkeyAction={grpc.isStreaming ? undefined : 'request.send'}
|
||||
hotkeyAction={grpc.isStreaming ? undefined : 'http_request.send'}
|
||||
onClick={grpc.isStreaming ? handleCancel : handleConnect}
|
||||
icon={
|
||||
grpc.isStreaming
|
||||
@@ -227,7 +227,7 @@ export function GrpcConnectionLayout({ style }: Props) {
|
||||
className="border border-highlight"
|
||||
size="sm"
|
||||
title="to-do"
|
||||
hotkeyAction="request.send"
|
||||
hotkeyAction="grpc_request.send"
|
||||
onClick={() => grpc.send.mutateAsync({ message: message.value ?? '' })}
|
||||
icon="sendHorizontal"
|
||||
/>
|
||||
@@ -331,7 +331,7 @@ export function GrpcConnectionLayout({ style }: Props) {
|
||||
forceUpdateKey={resp}
|
||||
/>
|
||||
) : (
|
||||
<HotKeyList hotkeys={['grpc.send', 'sidebar.toggle', 'urlBar.focus']} />
|
||||
<HotKeyList hotkeys={['grpc_request.send', 'sidebar.toggle', 'urlBar.focus']} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
|
||||
import { useAppRoutes } from '../hooks/useAppRoutes';
|
||||
import { useHotKey } from '../hooks/useHotKey';
|
||||
import { useRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useRequests } from '../hooks/useRequests';
|
||||
import { useHttpRequests } from '../hooks/useHttpRequests';
|
||||
import { fallbackRequestName } from '../lib/fallbackRequestName';
|
||||
import type { ButtonProps } from './core/Button';
|
||||
import { Button } from './core/Button';
|
||||
@@ -19,7 +19,7 @@ export function RecentRequestsDropdown({ className }: Pick<ButtonProps, 'classNa
|
||||
const activeRequest = useActiveRequest();
|
||||
const activeWorkspaceId = useActiveWorkspaceId();
|
||||
const activeEnvironmentId = useActiveEnvironmentId();
|
||||
const requests = useRequests();
|
||||
const requests = useHttpRequests();
|
||||
const routes = useAppRoutes();
|
||||
const allRecentRequestIds = useRecentRequests();
|
||||
const recentRequestIds = useMemo(() => allRecentRequestIds.slice(1), [allRecentRequestIds]);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
|
||||
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
||||
import { useSendRequest } from '../hooks/useSendRequest';
|
||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||
import { useUpdateHttpRequest } from '../hooks/useUpdateHttpRequest';
|
||||
import { tryFormatJson } from '../lib/formatters';
|
||||
import type { HttpHeader, HttpRequest, HttpUrlParameter } from '../lib/models';
|
||||
import {
|
||||
@@ -43,9 +43,9 @@ interface Props {
|
||||
const useActiveTab = createGlobalState<string>('body');
|
||||
|
||||
export const RequestPane = memo(function RequestPane({ style, fullHeight, className }: Props) {
|
||||
const activeRequest = useActiveRequest();
|
||||
const activeRequest = useActiveRequest('http_request');
|
||||
const activeRequestId = activeRequest?.id ?? null;
|
||||
const updateRequest = useUpdateRequest(activeRequestId);
|
||||
const updateRequest = useUpdateHttpRequest(activeRequestId);
|
||||
const [activeTab, setActiveTab] = useActiveTab();
|
||||
const [forceUpdateHeaderEditorKey, setForceUpdateHeaderEditorKey] = useState<number>(0);
|
||||
const { updateKey: forceUpdateKey } = useRequestUpdateKey(activeRequest?.id ?? null);
|
||||
|
||||
@@ -110,7 +110,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
||||
<>
|
||||
<span />
|
||||
<HotKeyList
|
||||
hotkeys={['request.send', 'request.create', 'sidebar.toggle', 'urlBar.focus']}
|
||||
hotkeys={['http_request.send', 'http_request.create', 'sidebar.toggle', 'urlBar.focus']}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -11,26 +11,27 @@ import { useActiveRequestId } from '../hooks/useActiveRequestId';
|
||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||
import { useAppRoutes } from '../hooks/useAppRoutes';
|
||||
import { useCreateFolder } from '../hooks/useCreateFolder';
|
||||
import { useCreateRequest } from '../hooks/useCreateRequest';
|
||||
import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest';
|
||||
import { useDeleteAnyRequest } from '../hooks/useDeleteAnyRequest';
|
||||
import { useDeleteFolder } from '../hooks/useDeleteFolder';
|
||||
import { useDeleteRequest } from '../hooks/useDeleteRequest';
|
||||
import { useDuplicateRequest } from '../hooks/useDuplicateRequest';
|
||||
import { useFolders } from '../hooks/useFolders';
|
||||
import { useGrpcRequests } from '../hooks/useGrpcRequests';
|
||||
import { useHotKey } from '../hooks/useHotKey';
|
||||
import { useKeyValue } from '../hooks/useKeyValue';
|
||||
import { useLatestResponse } from '../hooks/useLatestResponse';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { useRequests } from '../hooks/useRequests';
|
||||
import { useHttpRequests } from '../hooks/useHttpRequests';
|
||||
import { useSendManyRequests } from '../hooks/useSendFolder';
|
||||
import { useSendRequest } from '../hooks/useSendRequest';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { useUpdateAnyFolder } from '../hooks/useUpdateAnyFolder';
|
||||
import { useUpdateAnyRequest } from '../hooks/useUpdateAnyRequest';
|
||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
|
||||
import { useUpdateHttpRequest } from '../hooks/useUpdateHttpRequest';
|
||||
import { fallbackRequestName } from '../lib/fallbackRequestName';
|
||||
import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
|
||||
import type { Folder, HttpRequest, Workspace } from '../lib/models';
|
||||
import type { Folder, GrpcRequest, HttpRequest, Workspace } from '../lib/models';
|
||||
import { isResponseLoading } from '../lib/models';
|
||||
import { ContextMenu } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
@@ -48,7 +49,7 @@ enum ItemTypes {
|
||||
}
|
||||
|
||||
interface TreeNode {
|
||||
item: Workspace | Folder | HttpRequest;
|
||||
item: Workspace | Folder | HttpRequest | GrpcRequest;
|
||||
children: TreeNode[];
|
||||
depth: number;
|
||||
}
|
||||
@@ -58,7 +59,8 @@ export function Sidebar({ className }: Props) {
|
||||
const sidebarRef = useRef<HTMLLIElement>(null);
|
||||
const activeRequestId = useActiveRequestId();
|
||||
const activeEnvironmentId = useActiveEnvironmentId();
|
||||
const requests = useRequests();
|
||||
const httpRequests = useHttpRequests();
|
||||
const grpcRequests = useGrpcRequests();
|
||||
const folders = useFolders();
|
||||
const deleteAnyRequest = useDeleteAnyRequest();
|
||||
const activeWorkspace = useActiveWorkspace();
|
||||
@@ -67,7 +69,7 @@ export function Sidebar({ className }: Props) {
|
||||
const [hasFocus, setHasFocus] = useState<boolean>(false);
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [selectedTree, setSelectedTree] = useState<TreeNode | null>(null);
|
||||
const updateAnyRequest = useUpdateAnyRequest();
|
||||
const updateAnyRequest = useUpdateAnyHttpRequest();
|
||||
const updateAnyFolder = useUpdateAnyFolder();
|
||||
const [draggingId, setDraggingId] = useState<string | null>(null);
|
||||
const [hoveredTree, setHoveredTree] = useState<TreeNode | null>(null);
|
||||
@@ -78,7 +80,7 @@ export function Sidebar({ className }: Props) {
|
||||
namespace: NAMESPACE_NO_SYNC,
|
||||
});
|
||||
|
||||
useHotKey('request.duplicate', () => {
|
||||
useHotKey('http_request.duplicate', () => {
|
||||
duplicateRequest.mutate();
|
||||
});
|
||||
|
||||
@@ -110,7 +112,7 @@ export function Sidebar({ className }: Props) {
|
||||
|
||||
// Put requests and folders into a tree structure
|
||||
const next = (node: TreeNode): TreeNode => {
|
||||
const childItems = [...requests, ...folders].filter((f) =>
|
||||
const childItems = [...httpRequests, ...grpcRequests, ...folders].filter((f) =>
|
||||
node.item.model === 'workspace' ? f.folderId == null : f.folderId === node.item.id,
|
||||
);
|
||||
|
||||
@@ -119,7 +121,7 @@ export function Sidebar({ className }: Props) {
|
||||
for (const item of childItems) {
|
||||
treeParentMap[item.id] = node;
|
||||
node.children.push(next({ item, children: [], depth }));
|
||||
if (item.model === 'http_request') {
|
||||
if (item.model !== 'folder') {
|
||||
selectableRequests.push({ id: item.id, index: selectableRequestIndex++, tree: node });
|
||||
}
|
||||
}
|
||||
@@ -129,7 +131,7 @@ export function Sidebar({ className }: Props) {
|
||||
const tree = next({ item: activeWorkspace, children: [], depth: 0 });
|
||||
|
||||
return { tree, treeParentMap, selectableRequests };
|
||||
}, [activeWorkspace, requests, folders]);
|
||||
}, [activeWorkspace, httpRequests, grpcRequests, folders]);
|
||||
|
||||
const focusActiveRequest = useCallback(
|
||||
(
|
||||
@@ -160,7 +162,7 @@ export function Sidebar({ className }: Props) {
|
||||
);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(id: string) => {
|
||||
async (id: string) => {
|
||||
const tree = treeParentMap[id ?? 'n/a'] ?? null;
|
||||
const children = tree?.children ?? [];
|
||||
const node = children.find((m) => m.item.id === id) ?? null;
|
||||
@@ -171,7 +173,7 @@ export function Sidebar({ className }: Props) {
|
||||
const { item } = node;
|
||||
|
||||
if (item.model === 'folder') {
|
||||
collapsed.set((c) => ({ ...c, [item.id]: !c[item.id] }));
|
||||
await collapsed.set((c) => ({ ...c, [item.id]: !c[item.id] }));
|
||||
} else {
|
||||
routes.navigate('request', {
|
||||
requestId: id,
|
||||
@@ -339,6 +341,10 @@ export function Sidebar({ className }: Props) {
|
||||
if (child.item.model === 'folder') {
|
||||
const updateFolder = (f: Folder) => ({ ...f, sortPriority, folderId });
|
||||
return updateAnyFolder.mutateAsync({ id: child.item.id, update: updateFolder });
|
||||
} else if (child.item.model === 'grpc_request') {
|
||||
// TODO
|
||||
// const updateRequest = (r: HttpRequest) => ({ ...r, sortPriority, folderId });
|
||||
// return updateAnyRequest.mutateAsync({ id: child.item.id, update: updateRequest });
|
||||
} else if (child.item.model === 'http_request') {
|
||||
const updateRequest = (r: HttpRequest) => ({ ...r, sortPriority, folderId });
|
||||
return updateAnyRequest.mutateAsync({ id: child.item.id, update: updateRequest });
|
||||
@@ -350,6 +356,10 @@ export function Sidebar({ className }: Props) {
|
||||
if (child.item.model === 'folder') {
|
||||
const updateFolder = (f: Folder) => ({ ...f, sortPriority, folderId });
|
||||
await updateAnyFolder.mutateAsync({ id: child.item.id, update: updateFolder });
|
||||
} else if (child.item.model === 'grpc_request') {
|
||||
// TODO
|
||||
// const updateRequest = (r: HttpRequest) => ({ ...r, sortPriority, folderId });
|
||||
// await updateAnyRequest.mutateAsync({ id: child.item.id, update: updateRequest });
|
||||
} else if (child.item.model === 'http_request') {
|
||||
const updateRequest = (r: HttpRequest) => ({ ...r, sortPriority, folderId });
|
||||
await updateAnyRequest.mutateAsync({ id: child.item.id, update: updateRequest });
|
||||
@@ -454,7 +464,9 @@ function SidebarItems({
|
||||
itemId={child.item.id}
|
||||
itemName={child.item.name}
|
||||
itemFallbackName={
|
||||
child.item.model === 'http_request' ? fallbackRequestName(child.item) : 'New Folder'
|
||||
child.item.model === 'http_request' || child.item.model === 'grpc_request'
|
||||
? fallbackRequestName(child.item)
|
||||
: 'New Folder'
|
||||
}
|
||||
itemModel={child.item.model}
|
||||
onMove={handleMove}
|
||||
@@ -524,16 +536,15 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
ref: ForwardedRef<HTMLLIElement>,
|
||||
) {
|
||||
const activeRequest = useActiveRequest();
|
||||
const createRequest = useCreateRequest();
|
||||
const createRequest = useCreateHttpRequest();
|
||||
const createFolder = useCreateFolder();
|
||||
const deleteFolder = useDeleteFolder(itemId);
|
||||
const deleteRequest = useDeleteRequest(itemId);
|
||||
const duplicateRequest = useDuplicateRequest({ id: itemId, navigateAfter: true });
|
||||
const sendRequest = useSendRequest(itemId);
|
||||
const sendAndDownloadRequest = useSendRequest(itemId, { download: true });
|
||||
const sendManyRequests = useSendManyRequests();
|
||||
const latestResponse = useLatestResponse(itemId);
|
||||
const updateRequest = useUpdateRequest(itemId);
|
||||
const updateRequest = useUpdateHttpRequest(itemId);
|
||||
const updateAnyFolder = useUpdateAnyFolder();
|
||||
const prompt = usePrompt();
|
||||
const [editing, setEditing] = useState<boolean>(false);
|
||||
@@ -570,7 +581,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
);
|
||||
|
||||
const handleStartEditing = useCallback(() => {
|
||||
if (itemModel !== 'http_request') return;
|
||||
if (itemModel !== 'http_request' && itemModel !== 'grpc_request') return;
|
||||
setEditing(true);
|
||||
}, [setEditing, itemModel]);
|
||||
|
||||
@@ -652,7 +663,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
{
|
||||
key: 'sendRequest',
|
||||
label: 'Send',
|
||||
hotKeyAction: 'request.send',
|
||||
hotKeyAction: 'http_request.send',
|
||||
hotKeyLabelOnly: true, // Already bound in URL bar
|
||||
leftSlot: <Icon icon="sendHorizontal" />,
|
||||
onSelect: () => sendRequest.mutate(),
|
||||
@@ -661,7 +672,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
||||
{
|
||||
key: 'duplicateRequest',
|
||||
label: 'Duplicate',
|
||||
hotKeyAction: 'request.duplicate',
|
||||
hotKeyAction: 'http_request.duplicate',
|
||||
hotKeyLabelOnly: true, // Would trigger for every request (bad)
|
||||
leftSlot: <Icon icon="copy" />,
|
||||
onSelect: () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { memo } from 'react';
|
||||
import { useCreateFolder } from '../hooks/useCreateFolder';
|
||||
import { useCreateRequest } from '../hooks/useCreateRequest';
|
||||
import { useCreateGrpcRequest } from '../hooks/useCreateGrpcRequest';
|
||||
import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest';
|
||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||
import { trackEvent } from '../lib/analytics';
|
||||
import { Dropdown } from './core/Dropdown';
|
||||
@@ -8,16 +9,17 @@ import { IconButton } from './core/IconButton';
|
||||
import { HStack } from './core/Stacks';
|
||||
|
||||
export const SidebarActions = memo(function SidebarActions() {
|
||||
const createRequest = useCreateRequest();
|
||||
const createHttpRequest = useCreateHttpRequest();
|
||||
const createGrpcRequest = useCreateGrpcRequest();
|
||||
const createFolder = useCreateFolder();
|
||||
const { hidden, toggle } = useSidebarHidden();
|
||||
|
||||
return (
|
||||
<HStack>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
onClick={async () => {
|
||||
trackEvent('Sidebar', 'Toggle');
|
||||
toggle();
|
||||
await toggle();
|
||||
}}
|
||||
className="pointer-events-auto"
|
||||
size="sm"
|
||||
@@ -28,14 +30,19 @@ export const SidebarActions = memo(function SidebarActions() {
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
key: 'create-request',
|
||||
label: 'New Request',
|
||||
hotKeyAction: 'request.create',
|
||||
onSelect: () => createRequest.mutate({}),
|
||||
key: 'create-http-request',
|
||||
label: 'HTTP Request',
|
||||
hotKeyAction: 'http_request.create',
|
||||
onSelect: () => createHttpRequest.mutate({}),
|
||||
},
|
||||
{
|
||||
key: 'create-grpc-request',
|
||||
label: 'GRPC Request',
|
||||
onSelect: () => createGrpcRequest.mutate({}),
|
||||
},
|
||||
{
|
||||
key: 'create-folder',
|
||||
label: 'New Folder',
|
||||
label: 'Folder',
|
||||
onSelect: () => createFolder.mutate({}),
|
||||
},
|
||||
]}
|
||||
|
||||
@@ -83,7 +83,7 @@ export const UrlBar = memo(function UrlBar({
|
||||
className="w-8 mr-0.5 my-0.5"
|
||||
icon={isLoading ? 'update' : submitIcon}
|
||||
spin={isLoading}
|
||||
hotkeyAction="request.send"
|
||||
hotkeyAction="http_request.send"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export default function Workspace() {
|
||||
const { setWidth, width, resetWidth } = useSidebarWidth();
|
||||
const { hide, show, hidden } = useSidebarHidden();
|
||||
const activeRequest = useActiveRequest();
|
||||
console.log('ACTIVE REQUEST', activeRequest);
|
||||
|
||||
const windowSize = useWindowSize();
|
||||
const [floating, setFloating] = useState<boolean>(false);
|
||||
@@ -166,7 +167,7 @@ export default function Workspace() {
|
||||
>
|
||||
<WorkspaceHeader className="pointer-events-none" />
|
||||
</HeaderSize>
|
||||
{activeRequest?.name.includes('gRPC') ? (
|
||||
{activeRequest?.model === 'grpc_request' ? (
|
||||
<GrpcConnectionLayout style={body} />
|
||||
) : (
|
||||
<HttpRequestLayout style={body} />
|
||||
|
||||
@@ -140,7 +140,7 @@ export function SplitLayout({
|
||||
|
||||
const activeRequestId = useActiveRequestId();
|
||||
if (activeRequestId === null) {
|
||||
return <HotKeyList hotkeys={['request.create', 'sidebar.toggle']} />;
|
||||
return <HotKeyList hotkeys={['http_request.create', 'sidebar.toggle']} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { r } from 'vitest/dist/types-94cfe4b4';
|
||||
import type { GrpcRequest, HttpRequest } from '../lib/models';
|
||||
import { useActiveRequestId } from './useActiveRequestId';
|
||||
import { useRequests } from './useRequests';
|
||||
import { useGrpcRequests } from './useGrpcRequests';
|
||||
import { useHttpRequests } from './useHttpRequests';
|
||||
|
||||
export function useActiveRequest(): HttpRequest | null {
|
||||
const requestId = useActiveRequestId();
|
||||
const requests = useRequests();
|
||||
return requests.find((r) => r.id === requestId) ?? null;
|
||||
interface TypeMap {
|
||||
http_request: HttpRequest;
|
||||
grpc_request: GrpcRequest;
|
||||
}
|
||||
|
||||
export function useActiveRequest<T extends keyof TypeMap>(
|
||||
model?: T | undefined,
|
||||
): TypeMap[T] | null {
|
||||
const requestId = useActiveRequestId();
|
||||
const httpRequests = useHttpRequests();
|
||||
const grpcRequests = useGrpcRequests();
|
||||
|
||||
if (model === 'http_request') {
|
||||
return (httpRequests.find((r) => r.id === requestId) ?? null) as TypeMap[T] | null;
|
||||
} else if (model === 'grpc_request') {
|
||||
return (grpcRequests.find((r) => r.id === requestId) ?? null) as TypeMap[T] | null;
|
||||
} else {
|
||||
return (grpcRequests.find((r) => r.id === requestId) ??
|
||||
httpRequests.find((r) => r.id === requestId) ??
|
||||
null) as TypeMap[T] | null;
|
||||
}
|
||||
}
|
||||
|
||||
55
src-web/hooks/useCreateGrpcRequest.ts
Normal file
55
src-web/hooks/useCreateGrpcRequest.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { trackEvent } from '../lib/analytics';
|
||||
import type { GrpcRequest, HttpRequest } from '../lib/models';
|
||||
import { useActiveEnvironmentId } from './useActiveEnvironmentId';
|
||||
import { useActiveRequest } from './useActiveRequest';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
import { useAppRoutes } from './useAppRoutes';
|
||||
import { grpcRequestsQueryKey } from './useGrpcRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
|
||||
export function useCreateGrpcRequest() {
|
||||
const workspaceId = useActiveWorkspaceId();
|
||||
const activeEnvironmentId = useActiveEnvironmentId();
|
||||
// const activeRequest = useActiveRequest();
|
||||
const activeRequest = null;
|
||||
const routes = useAppRoutes();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<
|
||||
GrpcRequest,
|
||||
unknown,
|
||||
Partial<Pick<GrpcRequest, 'name' | 'sortPriority' | 'folderId'>>
|
||||
>({
|
||||
mutationFn: (patch) => {
|
||||
if (workspaceId === null) {
|
||||
throw new Error("Cannot create grpc request when there's no active workspace");
|
||||
}
|
||||
if (patch.sortPriority === undefined) {
|
||||
if (activeRequest != null) {
|
||||
// Place above currently-active request
|
||||
// patch.sortPriority = activeRequest.sortPriority + 0.0001;
|
||||
} else {
|
||||
// Place at the very top
|
||||
patch.sortPriority = -Date.now();
|
||||
}
|
||||
}
|
||||
// patch.folderId = patch.folderId; // TODO: || activeRequest?.folderId;
|
||||
return invoke('cmd_create_grpc_request', { workspaceId, name: '', ...patch });
|
||||
},
|
||||
onSettled: () => trackEvent('GrpcRequest', 'Create'),
|
||||
onSuccess: async (request) => {
|
||||
queryClient.setQueryData<GrpcRequest[]>(
|
||||
grpcRequestsQueryKey({ workspaceId: request.workspaceId }),
|
||||
(requests) => [...(requests ?? []), request],
|
||||
);
|
||||
// TODO: This should navigate to the new request
|
||||
routes.navigate('request', {
|
||||
workspaceId: request.workspaceId,
|
||||
requestId: request.id,
|
||||
environmentId: activeEnvironmentId ?? undefined,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import { useActiveEnvironmentId } from './useActiveEnvironmentId';
|
||||
import { useActiveRequest } from './useActiveRequest';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
import { useAppRoutes } from './useAppRoutes';
|
||||
import { requestsQueryKey } from './useRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
|
||||
export function useCreateRequest() {
|
||||
export function useCreateHttpRequest() {
|
||||
const workspaceId = useActiveWorkspaceId();
|
||||
const activeEnvironmentId = useActiveEnvironmentId();
|
||||
const activeRequest = useActiveRequest();
|
||||
@@ -34,12 +34,12 @@ export function useCreateRequest() {
|
||||
}
|
||||
}
|
||||
patch.folderId = patch.folderId || activeRequest?.folderId;
|
||||
return invoke('cmd_create_request', { workspaceId, name: '', ...patch });
|
||||
return invoke('cmd_create_http_request', { workspaceId, name: '', ...patch });
|
||||
},
|
||||
onSettled: () => trackEvent('HttpRequest', 'Create'),
|
||||
onSuccess: async (request) => {
|
||||
queryClient.setQueryData<HttpRequest[]>(
|
||||
requestsQueryKey({ workspaceId: request.workspaceId }),
|
||||
httpRequestsQueryKey({ workspaceId: request.workspaceId }),
|
||||
(requests) => [...(requests ?? []), request],
|
||||
);
|
||||
routes.navigate('request', {
|
||||
@@ -6,7 +6,7 @@ import { fallbackRequestName } from '../lib/fallbackRequestName';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { getRequest } from '../lib/store';
|
||||
import { useConfirm } from './useConfirm';
|
||||
import { requestsQueryKey } from './useRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
import { responsesQueryKey } from './useResponses';
|
||||
|
||||
export function useDeleteAnyRequest() {
|
||||
@@ -27,7 +27,7 @@ export function useDeleteAnyRequest() {
|
||||
),
|
||||
});
|
||||
if (!confirmed) return null;
|
||||
return invoke('cmd_delete_request', { requestId: id });
|
||||
return invoke('cmd_delete_http_request', { requestId: id });
|
||||
},
|
||||
onSettled: () => trackEvent('HttpRequest', 'Delete'),
|
||||
onSuccess: async (request) => {
|
||||
@@ -36,7 +36,7 @@ export function useDeleteAnyRequest() {
|
||||
|
||||
const { workspaceId, id: requestId } = request;
|
||||
queryClient.setQueryData(responsesQueryKey({ requestId }), []); // Responses were deleted
|
||||
queryClient.setQueryData<HttpRequest[]>(requestsQueryKey({ workspaceId }), (requests) =>
|
||||
queryClient.setQueryData<HttpRequest[]>(httpRequestsQueryKey({ workspaceId }), (requests) =>
|
||||
(requests ?? []).filter((r) => r.id !== requestId),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { Folder } from '../lib/models';
|
||||
import { getFolder } from '../lib/store';
|
||||
import { useConfirm } from './useConfirm';
|
||||
import { foldersQueryKey } from './useFolders';
|
||||
import { requestsQueryKey } from './useRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
|
||||
export function useDeleteFolder(id: string | null) {
|
||||
const queryClient = useQueryClient();
|
||||
@@ -36,7 +36,7 @@ export function useDeleteFolder(id: string | null) {
|
||||
const { workspaceId } = folder;
|
||||
|
||||
// Nesting makes it hard to clean things up, so just clear everything that could have been deleted
|
||||
await queryClient.invalidateQueries(requestsQueryKey({ workspaceId }));
|
||||
await queryClient.invalidateQueries(httpRequestsQueryKey({ workspaceId }));
|
||||
await queryClient.invalidateQueries(foldersQueryKey({ workspaceId }));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { Workspace } from '../lib/models';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
import { useAppRoutes } from './useAppRoutes';
|
||||
import { useConfirm } from './useConfirm';
|
||||
import { requestsQueryKey } from './useRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
import { workspacesQueryKey } from './useWorkspaces';
|
||||
|
||||
export function useDeleteWorkspace(workspace: Workspace | null) {
|
||||
@@ -43,8 +43,8 @@ export function useDeleteWorkspace(workspace: Workspace | null) {
|
||||
}
|
||||
|
||||
// Also clean up other things that may have been deleted
|
||||
queryClient.setQueryData(requestsQueryKey({ workspaceId }), []);
|
||||
await queryClient.invalidateQueries(requestsQueryKey({ workspaceId }));
|
||||
queryClient.setQueryData(httpRequestsQueryKey({ workspaceId }), []);
|
||||
await queryClient.invalidateQueries(httpRequestsQueryKey({ workspaceId }));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { HttpRequest } from '../lib/models';
|
||||
import { useActiveEnvironmentId } from './useActiveEnvironmentId';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
import { useAppRoutes } from './useAppRoutes';
|
||||
import { requestsQueryKey } from './useRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
|
||||
export function useDuplicateRequest({
|
||||
id,
|
||||
@@ -21,12 +21,12 @@ export function useDuplicateRequest({
|
||||
return useMutation<HttpRequest, string>({
|
||||
mutationFn: async () => {
|
||||
if (id === null) throw new Error("Can't duplicate a null request");
|
||||
return invoke('cmd_duplicate_request', { id });
|
||||
return invoke('cmd_duplicate_http_request', { id });
|
||||
},
|
||||
onSettled: () => trackEvent('HttpRequest', 'Duplicate'),
|
||||
onSuccess: async (request) => {
|
||||
queryClient.setQueryData<HttpRequest[]>(
|
||||
requestsQueryKey({ workspaceId: request.workspaceId }),
|
||||
httpRequestsQueryKey({ workspaceId: request.workspaceId }),
|
||||
(requests) => [...(requests ?? []), request],
|
||||
);
|
||||
if (navigateAfter && activeWorkspaceId !== null) {
|
||||
|
||||
22
src-web/hooks/useGrpcRequests.ts
Normal file
22
src-web/hooks/useGrpcRequests.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import type { GrpcRequest } from '../lib/models';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
|
||||
export function grpcRequestsQueryKey({ workspaceId }: { workspaceId: string }) {
|
||||
return ['grpc_requests', { workspaceId }];
|
||||
}
|
||||
|
||||
export function useGrpcRequests() {
|
||||
const workspaceId = useActiveWorkspaceId();
|
||||
return (
|
||||
useQuery({
|
||||
enabled: workspaceId != null,
|
||||
queryKey: grpcRequestsQueryKey({ workspaceId: workspaceId ?? 'n/a' }),
|
||||
queryFn: async () => {
|
||||
if (workspaceId == null) return [];
|
||||
return (await invoke('cmd_list_grpc_requests', { workspaceId })) as GrpcRequest[];
|
||||
},
|
||||
}).data ?? []
|
||||
);
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import { useOsInfo } from './useOsInfo';
|
||||
|
||||
export type HotkeyAction =
|
||||
| 'environmentEditor.toggle'
|
||||
| 'grpc.send'
|
||||
| 'hotkeys.showHelp'
|
||||
| 'request.create'
|
||||
| 'request.duplicate'
|
||||
| 'request.send'
|
||||
| 'grpc_request.send'
|
||||
| 'http_request.create'
|
||||
| 'http_request.duplicate'
|
||||
| 'http_request.send'
|
||||
| 'requestSwitcher.next'
|
||||
| 'requestSwitcher.prev'
|
||||
| 'settings.show'
|
||||
@@ -20,11 +20,11 @@ export type HotkeyAction =
|
||||
|
||||
const hotkeys: Record<HotkeyAction, string[]> = {
|
||||
'environmentEditor.toggle': ['CmdCtrl+Shift+e'],
|
||||
'grpc.send': ['CmdCtrl+Enter', 'CmdCtrl+r'],
|
||||
'grpc_request.send': ['CmdCtrl+Enter', 'CmdCtrl+r'],
|
||||
'hotkeys.showHelp': ['CmdCtrl+Shift+/'],
|
||||
'request.create': ['CmdCtrl+n'],
|
||||
'request.duplicate': ['CmdCtrl+d'],
|
||||
'request.send': ['CmdCtrl+Enter', 'CmdCtrl+r'],
|
||||
'http_request.create': ['CmdCtrl+n'],
|
||||
'http_request.duplicate': ['CmdCtrl+d'],
|
||||
'http_request.send': ['CmdCtrl+Enter', 'CmdCtrl+r'],
|
||||
'requestSwitcher.next': ['Control+Shift+Tab'],
|
||||
'requestSwitcher.prev': ['Control+Tab'],
|
||||
'settings.show': ['CmdCtrl+,'],
|
||||
@@ -35,11 +35,11 @@ const hotkeys: Record<HotkeyAction, string[]> = {
|
||||
|
||||
const hotkeyLabels: Record<HotkeyAction, string> = {
|
||||
'environmentEditor.toggle': 'Edit Environments',
|
||||
'grpc.send': 'Send Message',
|
||||
'grpc_request.send': 'Send Message',
|
||||
'hotkeys.showHelp': 'Show Keyboard Shortcuts',
|
||||
'request.create': 'New Request',
|
||||
'request.duplicate': 'Duplicate Request',
|
||||
'request.send': 'Send Request',
|
||||
'http_request.create': 'New Request',
|
||||
'http_request.duplicate': 'Duplicate Request',
|
||||
'http_request.send': 'Send Request',
|
||||
'requestSwitcher.next': 'Go To Previous Request',
|
||||
'requestSwitcher.prev': 'Go To Next Request',
|
||||
'settings.show': 'Open Settings',
|
||||
|
||||
@@ -3,19 +3,19 @@ import { invoke } from '@tauri-apps/api';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
|
||||
export function requestsQueryKey({ workspaceId }: { workspaceId: string }) {
|
||||
export function httpRequestsQueryKey({ workspaceId }: { workspaceId: string }) {
|
||||
return ['http_requests', { workspaceId }];
|
||||
}
|
||||
|
||||
export function useRequests() {
|
||||
export function useHttpRequests() {
|
||||
const workspaceId = useActiveWorkspaceId();
|
||||
return (
|
||||
useQuery({
|
||||
enabled: workspaceId != null,
|
||||
queryKey: requestsQueryKey({ workspaceId: workspaceId ?? 'n/a' }),
|
||||
queryKey: httpRequestsQueryKey({ workspaceId: workspaceId ?? 'n/a' }),
|
||||
queryFn: async () => {
|
||||
if (workspaceId == null) return [];
|
||||
return (await invoke('cmd_list_requests', { workspaceId })) as HttpRequest[];
|
||||
return (await invoke('cmd_list_http_requests', { workspaceId })) as HttpRequest[];
|
||||
},
|
||||
}).data ?? []
|
||||
);
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { useRequests } from './useRequests';
|
||||
import { useHttpRequests } from './useHttpRequests';
|
||||
|
||||
export function useRequest(id: string | null): HttpRequest | null {
|
||||
const requests = useRequests();
|
||||
const requests = useHttpRequests();
|
||||
return requests.find((r) => r.id === id) ?? null;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { getRequest } from '../lib/store';
|
||||
import { requestsQueryKey } from './useRequests';
|
||||
import { httpRequestsQueryKey } from './useHttpRequests';
|
||||
|
||||
export function useUpdateAnyRequest() {
|
||||
export function useUpdateAnyHttpRequest() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<
|
||||
@@ -20,14 +20,14 @@ export function useUpdateAnyRequest() {
|
||||
|
||||
const patchedRequest =
|
||||
typeof update === 'function' ? update(request) : { ...request, ...update };
|
||||
await invoke('cmd_update_request', { request: patchedRequest });
|
||||
await invoke('cmd_update_http_request', { request: patchedRequest });
|
||||
},
|
||||
onMutate: async ({ id, update }) => {
|
||||
const request = await getRequest(id);
|
||||
if (request === null) return;
|
||||
const patchedRequest =
|
||||
typeof update === 'function' ? update(request) : { ...request, ...update };
|
||||
queryClient.setQueryData<HttpRequest[]>(requestsQueryKey(request), (requests) =>
|
||||
queryClient.setQueryData<HttpRequest[]>(httpRequestsQueryKey(request), (requests) =>
|
||||
(requests ?? []).map((r) => (r.id === patchedRequest.id ? patchedRequest : r)),
|
||||
);
|
||||
},
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { useUpdateAnyRequest } from './useUpdateAnyRequest';
|
||||
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
|
||||
|
||||
export function useUpdateRequest(id: string | null) {
|
||||
const updateAnyRequest = useUpdateAnyRequest();
|
||||
export function useUpdateHttpRequest(id: string | null) {
|
||||
const updateAnyRequest = useUpdateAnyHttpRequest();
|
||||
return useMutation<void, unknown, Partial<HttpRequest> | ((r: HttpRequest) => HttpRequest)>({
|
||||
mutationFn: async (update) => updateAnyRequest.mutateAsync({ id: id ?? 'n/a', update }),
|
||||
});
|
||||
@@ -9,6 +9,7 @@ export function trackEvent(
|
||||
| 'Workspace'
|
||||
| 'Environment'
|
||||
| 'Folder'
|
||||
| 'GrpcRequest'
|
||||
| 'HttpRequest'
|
||||
| 'HttpResponse'
|
||||
| 'KeyValue',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { HttpRequest } from './models';
|
||||
import type { GrpcRequest, HttpRequest } from './models';
|
||||
|
||||
export function fallbackRequestName(r: HttpRequest | null): string {
|
||||
export function fallbackRequestName(r: HttpRequest | GrpcRequest | null): string {
|
||||
if (r == null) return '';
|
||||
|
||||
if (r.name) {
|
||||
@@ -9,7 +9,7 @@ export function fallbackRequestName(r: HttpRequest | null): string {
|
||||
|
||||
const withoutVariables = r.url.replace(/\$\{\[[^\]]+]}/g, '');
|
||||
if (withoutVariables.trim() === '') {
|
||||
return 'New Request';
|
||||
return r.model === 'http_request' ? 'New HTTP Request' : 'new gRPC Request';
|
||||
}
|
||||
|
||||
const fixedUrl = r.url.match(/^https?:\/\//) ? r.url : 'http://' + r.url;
|
||||
|
||||
@@ -12,6 +12,7 @@ export const AUTH_TYPE_BEARER = 'bearer';
|
||||
export type Model =
|
||||
| Settings
|
||||
| Workspace
|
||||
| GrpcRequest
|
||||
| HttpRequest
|
||||
| HttpResponse
|
||||
| KeyValue
|
||||
@@ -101,6 +102,18 @@ export interface HttpUrlParameter {
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface GrpcRequest extends BaseModel {
|
||||
readonly workspaceId: string;
|
||||
readonly model: 'grpc_request';
|
||||
folderId: string | null;
|
||||
sortPriority: number;
|
||||
name: string;
|
||||
url: string;
|
||||
service: string | null;
|
||||
method: string | null;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface HttpRequest extends BaseModel {
|
||||
readonly workspaceId: string;
|
||||
readonly model: 'http_request';
|
||||
|
||||
@@ -7,7 +7,7 @@ export async function getSettings(): Promise<Settings> {
|
||||
|
||||
export async function getRequest(id: string | null): Promise<HttpRequest | null> {
|
||||
if (id === null) return null;
|
||||
const request: HttpRequest = (await invoke('cmd_get_request', { id })) ?? null;
|
||||
const request: HttpRequest = (await invoke('cmd_get_http_request', { id })) ?? null;
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user