Compare commits

..

24 Commits

Author SHA1 Message Date
Gregory Schier
41fe01adb9 Update generated route tree formatting 2026-05-06 07:51:35 -07:00
Gregory Schier
a200410697 Fix gRPC Any response reflection (#451) 2026-05-06 07:42:35 -07:00
pandeb
4c15a49f8f fix: align HTTP method tags to the left (#450) 2026-05-06 07:13:22 -07:00
Gregory Schier
c901ad4cbd Some cleanup 2026-04-30 09:00:12 -07:00
Gregory Schier
d73d38f418 Surface error when failing importing a binary file 2026-04-29 07:33:21 -07:00
Gregory Schier
b0740770df Increase HTTP/2 response header limit
Set Yaak's reqwest request clients to accept HTTP/2 response header lists up to 1 MiB and wrap configured clients so the sender path cannot accidentally bypass the shared builder.

Feedback: https://yaak.app/feedback/posts/when-response-headers-exceed-a-certain-size-hyper-throws-error
2026-04-28 07:49:47 -07:00
dependabot[bot]
75d94da578 Bump quinn-proto from 0.11.12 to 0.11.14 (#421)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:43:06 -07:00
dependabot[bot]
79c49d8398 Bump vite-plus from 0.1.11 to 0.1.19 (#447)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:42:48 -07:00
dependabot[bot]
7c51510616 Bump rustls-webpki from 0.103.10 to 0.103.13 (#446)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:40:01 -07:00
dependabot[bot]
0b36ee56d2 Bump hono from 4.12.4 to 4.12.14 (#442)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:38:31 -07:00
dependabot[bot]
2c345fc2ca Bump picomatch from 4.0.3 to 4.0.4 (#436)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:38:13 -07:00
dependabot[bot]
909580c4a4 Bump rustls-webpki from 0.103.7 to 0.103.10 (#434)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:38:06 -07:00
dependabot[bot]
e805b225f7 Bump yaml from 2.8.2 to 2.8.3 (#435)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:38:00 -07:00
dependabot[bot]
0def693b63 Bump follow-redirects from 1.15.11 to 1.16.0 (#441)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:37:52 -07:00
dependabot[bot]
7109db911a Bump @xmldom/xmldom from 0.9.8 to 0.9.10 (#444)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:37:45 -07:00
dependabot[bot]
980f26f2f0 Bump uuid from 11.1.0 to 14.0.0 (#445)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:37:40 -07:00
dependabot[bot]
6b56ec569f Bump @hono/node-server from 1.19.10 to 1.19.13 (#439)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:37:00 -07:00
dependabot[bot]
36fa7a52fe Bump tar from 0.4.44 to 0.4.45 (#433)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-23 06:36:49 -07:00
Gregory Schier
c95099588f Fix duplicate request snapshotting URL as name (#429) 2026-04-23 06:36:33 -07:00
Nguyễn Huy Hoàng
929f6202a4 fix: bug where selection layer leaves a ghost residual line below wrapped lines after deselecting (#432)
Co-authored-by: hoangnh290 <hoangnh290@viettel.com.vn>
2026-04-23 06:30:18 -07:00
Julien Bourdeau
915af7e3de chore: Delete old .nvmrc (#443) 2026-04-23 06:28:49 -07:00
Gregory Schier
eb9b5b6bb6 Don't override user-defined Content-Type for GraphQL and form-urlencoded requests
The frontend already sets the appropriate Content-Type header when
selecting a body type, so the backend no longer needs to force it.
This allows users to override Content-Type for servers with
non-standard requirements.

Fixes https://yaak.app/feedback/posts/graphql-mode-ignores-manual-content-type-header-override

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 09:43:04 -07:00
Gregory Schier
b4a1c418bb Run oxfmt across repo, add format script and docs
Add .oxfmtignore to skip generated bindings and wasm-pack output.
Add npm format script, update DEVELOPMENT.md for Vite+ toolchain,
and format all non-generated files with oxfmt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:15:49 -07:00
Gregory Schier
45262edfbd Migrate to Vite+ unified toolchain (#428) 2026-03-13 09:27:56 -07:00
31 changed files with 810 additions and 453 deletions

1
.nvmrc
View File

@@ -1 +0,0 @@
20

View File

@@ -1,2 +0,0 @@
**/bindings/**
crates/yaak-templates/pkg/**

4
.oxfmtrc.json Normal file
View File

@@ -0,0 +1,4 @@
{
"printWidth": 100,
"ignorePatterns": ["**/bindings/**", "crates/yaak-templates/pkg/**", "src-web/routeTree.gen.ts"]
}

16
Cargo.lock generated
View File

@@ -1147,7 +1147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
dependencies = [ dependencies = [
"lazy_static 1.5.0", "lazy_static 1.5.0",
"windows-sys 0.59.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@@ -5753,9 +5753,9 @@ dependencies = [
[[package]] [[package]]
name = "quinn-proto" name = "quinn-proto"
version = "0.11.12" version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
dependencies = [ dependencies = [
"bytes", "bytes",
"getrandom 0.3.3", "getrandom 0.3.3",
@@ -6803,9 +6803,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.103.7" version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
@@ -7692,9 +7692,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]] [[package]]
name = "tar" name = "tar"
version = "0.4.44" version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
dependencies = [ dependencies = [
"filetime", "filetime",
"libc", "libc",
@@ -9495,7 +9495,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]

View File

@@ -1,9 +1,10 @@
use crate::PluginContextExt; use crate::PluginContextExt;
use crate::error::Result; use crate::error::{Error, Result};
use crate::models_ext::QueryManagerExt; use crate::models_ext::QueryManagerExt;
use log::info; use log::info;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::io::ErrorKind;
use tauri::{Manager, Runtime, WebviewWindow}; use tauri::{Manager, Runtime, WebviewWindow};
use yaak_core::WorkspaceContext; use yaak_core::WorkspaceContext;
use yaak_models::models::{ use yaak_models::models::{
@@ -18,8 +19,7 @@ pub(crate) async fn import_data<R: Runtime>(
file_path: &str, file_path: &str,
) -> Result<BatchUpsertResult> { ) -> Result<BatchUpsertResult> {
let plugin_manager = window.state::<PluginManager>(); let plugin_manager = window.state::<PluginManager>();
let file = let file = read_import_file(file_path)?;
read_to_string(file_path).unwrap_or_else(|_| panic!("Unable to read file {}", file_path));
let file_contents = file.as_str(); let file_contents = file.as_str();
let import_result = plugin_manager.import_data(&window.plugin_context(), file_contents).await?; let import_result = plugin_manager.import_data(&window.plugin_context(), file_contents).await?;
@@ -127,3 +127,41 @@ pub(crate) async fn import_data<R: Runtime>(
Ok(upserted) Ok(upserted)
} }
fn read_import_file(file_path: &str) -> Result<String> {
read_to_string(file_path).map_err(|err| {
if err.kind() == ErrorKind::InvalidData {
Error::GenericError(format!(
"Import file must be UTF-8 text; binary files are not supported: {file_path}"
))
} else {
Error::GenericError(format!("Unable to read import file {file_path}: {err}"))
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::{remove_file, write};
use std::time::{SystemTime, UNIX_EPOCH};
#[test]
fn read_import_file_returns_error_for_binary_file() {
let path = std::env::temp_dir().join(format!(
"yaak-import-binary-{}.pftrace",
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system time before unix epoch")
.as_nanos()
));
write(&path, [0xff, 0xfe, 0xfd]).expect("write binary fixture");
let err = read_import_file(path.to_str().expect("temp path is utf-8"))
.expect_err("binary import should return an error");
assert!(err.to_string().contains("binary files are not supported"));
remove_file(path).expect("remove binary fixture");
}
}

View File

@@ -34,8 +34,7 @@ use tokio::time;
use yaak_common::command::new_checked_command; use yaak_common::command::new_checked_command;
use yaak_crypto::manager::EncryptionManager; use yaak_crypto::manager::EncryptionManager;
use yaak_grpc::manager::{GrpcConfig, GrpcHandle}; use yaak_grpc::manager::{GrpcConfig, GrpcHandle};
use yaak_templates::strip_json_comments::strip_json_comments; use yaak_grpc::{Code, ServiceDefinition};
use yaak_grpc::{Code, ServiceDefinition, serialize_message};
use yaak_mac_window::AppHandleMacWindowExt; use yaak_mac_window::AppHandleMacWindowExt;
use yaak_models::models::{ use yaak_models::models::{
AnyModel, CookieJar, Environment, GrpcConnection, GrpcConnectionState, GrpcEvent, AnyModel, CookieJar, Environment, GrpcConnection, GrpcConnectionState, GrpcEvent,
@@ -60,6 +59,7 @@ use yaak_plugins::template_callback::PluginTemplateCallback;
use yaak_sse::sse::ServerSentEvent; use yaak_sse::sse::ServerSentEvent;
use yaak_tauri_utils::window::WorkspaceWindowTrait; use yaak_tauri_utils::window::WorkspaceWindowTrait;
use yaak_templates::format_json::format_json; use yaak_templates::format_json::format_json;
use yaak_templates::strip_json_comments::strip_json_comments;
use yaak_templates::{RenderErrorBehavior, RenderOptions, Tokens, transform_args}; use yaak_templates::{RenderErrorBehavior, RenderOptions, Tokens, transform_args};
use yaak_tls::find_client_certificate; use yaak_tls::find_client_certificate;
@@ -522,7 +522,7 @@ async fn cmd_grpc_go<R: Runtime>(
&method, &method,
in_msg_stream, in_msg_stream,
&metadata, &metadata,
client_cert, client_cert.clone(),
on_message.clone(), on_message.clone(),
) )
.await, .await,
@@ -538,7 +538,7 @@ async fn cmd_grpc_go<R: Runtime>(
&method, &method,
in_msg_stream, in_msg_stream,
&metadata, &metadata,
client_cert, client_cert.clone(),
on_message.clone(), on_message.clone(),
) )
.await, .await,
@@ -551,7 +551,9 @@ async fn cmd_grpc_go<R: Runtime>(
(false, false) => ( (false, false) => (
None, None,
Some( Some(
connection.unary(&service, &method, &msg, &metadata, client_cert).await, connection
.unary(&service, &method, &msg, &metadata, client_cert.clone())
.await,
), ),
), ),
}; };
@@ -589,11 +591,34 @@ async fn cmd_grpc_go<R: Runtime>(
&UpdateSource::from_window_label(window.label()), &UpdateSource::from_window_label(window.label()),
) )
.unwrap(); .unwrap();
let response_message = msg.into_inner();
let content = match connection
.serialize_message(&response_message, &metadata, client_cert.clone())
.await
{
Ok(content) => content,
Err(err) => {
app_handle
.db()
.upsert_grpc_event(
&GrpcEvent {
content: "Failed to read response".to_string(),
error: Some(err.to_string()),
status: Some(Code::Internal as i32),
event_type: GrpcEventType::ConnectionEnd,
..base_event.clone()
},
&UpdateSource::from_window_label(window.label()),
)
.unwrap();
return;
}
};
app_handle app_handle
.db() .db()
.upsert_grpc_event( .upsert_grpc_event(
&GrpcEvent { &GrpcEvent {
content: serialize_message(&msg.into_inner()).unwrap(), content,
event_type: GrpcEventType::ServerMessage, event_type: GrpcEventType::ServerMessage,
..base_event.clone() ..base_event.clone()
}, },
@@ -728,7 +753,28 @@ async fn cmd_grpc_go<R: Runtime>(
loop { loop {
match stream.message().await { match stream.message().await {
Ok(Some(msg)) => { Ok(Some(msg)) => {
let message = serialize_message(&msg).unwrap(); let message = match connection
.serialize_message(&msg, &metadata, client_cert.clone())
.await
{
Ok(message) => message,
Err(err) => {
app_handle
.db()
.upsert_grpc_event(
&GrpcEvent {
content: "Failed to read response".to_string(),
error: Some(err.to_string()),
status: Some(Code::Internal as i32),
event_type: GrpcEventType::ConnectionEnd,
..base_event.clone()
},
&UpdateSource::from_window_label(window.label()),
)
.unwrap();
break;
}
};
app_handle app_handle
.db() .db()
.upsert_grpc_event( .upsert_grpc_event(

View File

@@ -25,6 +25,7 @@ pub(crate) struct PluginState {
} }
pub fn init<R: Runtime>() -> TauriPlugin<R> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
#[cfg_attr(not(target_os = "macos"), allow(unused_mut))]
let mut builder = plugin::Builder::new("yaak-mac-window") let mut builder = plugin::Builder::new("yaak-mac-window")
.setup(move |app, _| { .setup(move |app, _| {
app.manage(PluginState { native_titlebar: AtomicBool::new(false) }); app.manage(PluginState { native_titlebar: AtomicBool::new(false) });

View File

@@ -37,7 +37,7 @@ pub struct MethodDefinition {
static SERIALIZE_OPTIONS: &'static SerializeOptions = static SERIALIZE_OPTIONS: &'static SerializeOptions =
&SerializeOptions::new().skip_default_fields(false).stringify_64_bit_integers(false); &SerializeOptions::new().skip_default_fields(false).stringify_64_bit_integers(false);
pub fn serialize_message(msg: &DynamicMessage) -> Result<String, String> { pub(crate) fn serialize_dynamic_message_json(msg: &DynamicMessage) -> Result<String, String> {
let mut buf = Vec::new(); let mut buf = Vec::new();
let mut se = serde_json::Serializer::pretty(&mut buf); let mut se = serde_json::Serializer::pretty(&mut buf);
msg.serialize_with_options(&mut se, SERIALIZE_OPTIONS).map_err(|e| e.to_string())?; msg.serialize_with_options(&mut se, SERIALIZE_OPTIONS).map_err(|e| e.to_string())?;

View File

@@ -2,7 +2,8 @@ use crate::codec::DynamicCodec;
use crate::error::Error::GenericError; use crate::error::Error::GenericError;
use crate::error::Result; use crate::error::Result;
use crate::reflection::{ use crate::reflection::{
fill_pool_from_files, fill_pool_from_reflection, method_desc_to_path, reflect_types_for_message, fill_pool_from_files, fill_pool_from_reflection, method_desc_to_path,
reflect_types_for_dynamic_message, reflect_types_for_message,
}; };
use crate::transport::get_transport; use crate::transport::get_transport;
use crate::{MethodDefinition, ServiceDefinition, json_schema}; use crate::{MethodDefinition, ServiceDefinition, json_schema};
@@ -11,8 +12,11 @@ use hyper_util::client::legacy::Client;
use hyper_util::client::legacy::connect::HttpConnector; use hyper_util::client::legacy::connect::HttpConnector;
use log::{info, warn}; use log::{info, warn};
pub use prost_reflect::DynamicMessage; pub use prost_reflect::DynamicMessage;
use prost_reflect::ReflectMessage;
use prost_reflect::prost::Message;
use prost_reflect::{DescriptorPool, MethodDescriptor, ServiceDescriptor}; use prost_reflect::{DescriptorPool, MethodDescriptor, ServiceDescriptor};
use serde_json::Deserializer; use serde_json::Deserializer;
use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
@@ -115,6 +119,38 @@ impl GrpcConnection {
Ok(client.unary(req, path, codec).await?) Ok(client.unary(req, path, codec).await?)
} }
pub async fn serialize_message(
&self,
message: &DynamicMessage,
metadata: &BTreeMap<String, String>,
client_cert: Option<ClientCertificateConfig>,
) -> Result<String> {
let message = if self.use_reflection {
reflect_types_for_dynamic_message(
self.pool.clone(),
&self.uri,
message,
metadata,
client_cert,
)
.await?;
let message_name = message.descriptor().full_name().to_string();
let message_desc = {
let pool = self.pool.read().await;
pool.get_message_by_name(&message_name)
.ok_or(GenericError(format!("Failed to find message {message_name}")))?
};
let mut message_with_updated_pool = DynamicMessage::new(message_desc);
message_with_updated_pool.merge(message.encode_to_vec().as_slice())?;
Cow::Owned(message_with_updated_pool)
} else {
Cow::Borrowed(message)
};
crate::serialize_dynamic_message_json(message.as_ref()).map_err(GenericError)
}
pub async fn streaming<F>( pub async fn streaming<F>(
&self, &self,
service: &str, service: &str,

View File

@@ -7,7 +7,7 @@ use anyhow::anyhow;
use async_recursion::async_recursion; use async_recursion::async_recursion;
use log::{debug, info, warn}; use log::{debug, info, warn};
use prost::Message; use prost::Message;
use prost_reflect::{DescriptorPool, MethodDescriptor}; use prost_reflect::{DescriptorPool, DynamicMessage, MethodDescriptor, ReflectMessage, Value};
use prost_types::{FileDescriptorProto, FileDescriptorSet}; use prost_types::{FileDescriptorProto, FileDescriptorSet};
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use std::env::temp_dir; use std::env::temp_dir;
@@ -233,6 +233,83 @@ pub(crate) async fn reflect_types_for_message(
Ok(()) Ok(())
} }
pub(crate) async fn reflect_types_for_dynamic_message(
pool: Arc<RwLock<DescriptorPool>>,
uri: &Uri,
message: &DynamicMessage,
metadata: &BTreeMap<String, String>,
client_cert: Option<ClientCertificateConfig>,
) -> Result<()> {
let mut extra_types = HashSet::new();
collect_any_types_from_dynamic_message(message, &mut extra_types);
if extra_types.is_empty() {
return Ok(());
}
let mut client = AutoReflectionClient::new(uri, false, client_cert)?;
for extra_type in extra_types {
{
let guard = pool.read().await;
if guard.get_message_by_name(&extra_type).is_some() {
continue;
}
}
info!("Adding response file descriptor for {:?} from reflection", extra_type);
let req = MessageRequest::FileContainingSymbol(extra_type.clone().into());
let resp = match client.send_reflection_request(req, metadata).await {
Ok(r) => r,
Err(e) => {
return Err(GenericError(format!(
"Error sending reflection request for response @type \"{extra_type}\": {e:?}",
)));
}
};
let files = match resp {
MessageResponse::FileDescriptorResponse(resp) => resp.file_descriptor_proto,
_ => panic!("Expected a FileDescriptorResponse variant"),
};
{
let mut guard = pool.write().await;
add_file_descriptors_to_pool(files, &mut *guard, &mut client, metadata).await;
}
}
Ok(())
}
fn collect_any_types_from_dynamic_message(message: &DynamicMessage, out: &mut HashSet<String>) {
if message.descriptor().full_name() == "google.protobuf.Any" {
if let Some(Value::String(type_url)) = message.get_field_by_name("type_url").as_deref() {
if let Some(full_name) = type_url.rsplit_once('/').map(|(_, name)| name) {
out.insert(full_name.to_string());
}
}
}
for (_, value) in message.fields() {
collect_any_types_from_value(value, out);
}
}
fn collect_any_types_from_value(value: &Value, out: &mut HashSet<String>) {
match value {
Value::Message(message) => collect_any_types_from_dynamic_message(message, out),
Value::List(values) => {
for value in values {
collect_any_types_from_value(value, out);
}
}
Value::Map(values) => {
for value in values.values() {
collect_any_types_from_value(value, out);
}
}
_ => {}
}
}
#[async_recursion] #[async_recursion]
pub(crate) async fn add_file_descriptors_to_pool( pub(crate) async fn add_file_descriptors_to_pool(
fds: Vec<Vec<u8>>, fds: Vec<Vec<u8>>,

View File

@@ -1,11 +1,36 @@
use crate::dns::LocalhostResolver; use crate::dns::LocalhostResolver;
use crate::error::Result; use crate::error::Result;
use log::{debug, info, warn}; use log::{debug, info, warn};
use reqwest::{Client, Proxy, redirect}; use reqwest::{Client, ClientBuilder, Proxy, redirect};
use std::sync::Arc; use std::sync::Arc;
use yaak_models::models::DnsOverride; use yaak_models::models::DnsOverride;
use yaak_tls::{ClientCertificateConfig, get_tls_config}; use yaak_tls::{ClientCertificateConfig, get_tls_config};
pub const HTTP2_MAX_RESPONSE_HEADER_LIST_SIZE: u32 = 1024 * 1024;
fn client_builder() -> ClientBuilder {
Client::builder().http2_max_header_list_size(HTTP2_MAX_RESPONSE_HEADER_LIST_SIZE)
}
#[derive(Clone)]
pub struct ConfiguredClient {
inner: Client,
}
impl ConfiguredClient {
pub(crate) fn build_default() -> Result<Self> {
Ok(Self { inner: client_builder().build()? })
}
pub(crate) fn from_inner(inner: Client) -> Self {
Self { inner }
}
pub(crate) fn inner(&self) -> &Client {
&self.inner
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct HttpConnectionProxySettingAuth { pub struct HttpConnectionProxySettingAuth {
pub user: String, pub user: String,
@@ -37,8 +62,8 @@ impl HttpConnectionOptions {
/// Build a reqwest Client and return it along with the DNS resolver. /// Build a reqwest Client and return it along with the DNS resolver.
/// The resolver is returned separately so it can be configured per-request /// The resolver is returned separately so it can be configured per-request
/// to emit DNS timing events to the appropriate channel. /// to emit DNS timing events to the appropriate channel.
pub(crate) fn build_client(&self) -> Result<(Client, Arc<LocalhostResolver>)> { pub(crate) fn build_client(&self) -> Result<(ConfiguredClient, Arc<LocalhostResolver>)> {
let mut client = Client::builder() let mut client = client_builder()
.connection_verbose(true) .connection_verbose(true)
.redirect(redirect::Policy::none()) .redirect(redirect::Policy::none())
// Decompression is handled by HttpTransaction, not reqwest // Decompression is handled by HttpTransaction, not reqwest
@@ -79,7 +104,7 @@ impl HttpConnectionOptions {
self.client_certificate.is_some() self.client_certificate.is_some()
); );
Ok((client.build()?, resolver)) Ok((ConfiguredClient::from_inner(client.build()?), resolver))
} }
} }

View File

@@ -1,7 +1,6 @@
use crate::client::HttpConnectionOptions; use crate::client::{ConfiguredClient, HttpConnectionOptions};
use crate::dns::LocalhostResolver; use crate::dns::LocalhostResolver;
use crate::error::Result; use crate::error::Result;
use reqwest::Client;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@@ -10,7 +9,7 @@ use tokio::sync::RwLock;
/// A cached HTTP client along with its DNS resolver. /// A cached HTTP client along with its DNS resolver.
/// The resolver is needed to set the event sender per-request. /// The resolver is needed to set the event sender per-request.
pub struct CachedClient { pub struct CachedClient {
pub client: Client, pub client: ConfiguredClient,
pub resolver: Arc<LocalhostResolver>, pub resolver: Arc<LocalhostResolver>,
} }

View File

@@ -5,7 +5,7 @@ use async_trait::async_trait;
use bytes::Bytes; use bytes::Bytes;
use futures_util::StreamExt; use futures_util::StreamExt;
use http_body::{Body as HttpBody, Frame, SizeHint}; use http_body::{Body as HttpBody, Frame, SizeHint};
use reqwest::{Client, Method, Version}; use reqwest::{Method, Version};
use std::fmt::Display; use std::fmt::Display;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@@ -411,18 +411,18 @@ pub trait HttpSender: Send + Sync {
/// Reqwest-based implementation of HttpSender /// Reqwest-based implementation of HttpSender
pub struct ReqwestSender { pub struct ReqwestSender {
client: Client, client: crate::client::ConfiguredClient,
} }
impl ReqwestSender { impl ReqwestSender {
/// Create a new ReqwestSender with a default client /// Create a new ReqwestSender with a default client
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let client = Client::builder().build().map_err(Error::Client)?; let client = crate::client::ConfiguredClient::build_default()?;
Ok(Self { client }) Ok(Self { client })
} }
/// Create a new ReqwestSender with a custom client /// Create a new ReqwestSender with a configured client
pub fn with_client(client: Client) -> Self { pub fn with_client(client: crate::client::ConfiguredClient) -> Self {
Self { client } Self { client }
} }
} }
@@ -444,7 +444,7 @@ impl HttpSender for ReqwestSender {
.map_err(|e| Error::RequestError(format!("Invalid HTTP method: {}", e)))?; .map_err(|e| Error::RequestError(format!("Invalid HTTP method: {}", e)))?;
// Build the request // Build the request
let mut req_builder = self.client.request(method, &request.url); let mut req_builder = self.client.inner().request(method, &request.url);
// Add headers // Add headers
for header in request.headers { for header in request.headers {
@@ -513,7 +513,7 @@ impl HttpSender for ReqwestSender {
send_event(HttpResponseEvent::Info("Sending request to server".to_string())); send_event(HttpResponseEvent::Info("Sending request to server".to_string()));
// Map some errors to our own, so they look nicer // Map some errors to our own, so they look nicer
let response = self.client.execute(sendable_req).await.map_err(|e| { let response = self.client.inner().execute(sendable_req).await.map_err(|e| {
if reqwest::Error::is_timeout(&e) { if reqwest::Error::is_timeout(&e) {
Error::RequestTimeout( Error::RequestTimeout(
request.options.timeout.unwrap_or(Duration::from_secs(0)).clone(), request.options.timeout.unwrap_or(Duration::from_secs(0)).clone(),

View File

@@ -226,10 +226,8 @@ async fn build_body(
let (body, content_type) = match body_type.as_str() { let (body, content_type) = match body_type.as_str() {
"binary" => (build_binary_body(&body).await?, None), "binary" => (build_binary_body(&body).await?, None),
"graphql" => (build_graphql_body(&method, &body), Some("application/json".to_string())), "graphql" => (build_graphql_body(&method, &body), None),
"application/x-www-form-urlencoded" => { "application/x-www-form-urlencoded" => (build_form_body(&body), None),
(build_form_body(&body), Some("application/x-www-form-urlencoded".to_string()))
}
"multipart/form-data" => build_multipart_body(&body, &headers).await?, "multipart/form-data" => build_multipart_body(&body, &headers).await?,
_ if body.contains_key("text") => (build_text_body(&body, body_type), None), _ if body.contains_key("text") => (build_text_body(&body, body_type), None),
t => { t => {

View File

@@ -144,9 +144,10 @@ export function duplicateModel<M extends AnyModel["model"], T extends ExtractMod
throw new Error("Failed to duplicate null model"); throw new Error("Failed to duplicate null model");
} }
// If the model has a name, try to duplicate it with a name that doesn't conflict // If the model has an explicit (non-empty) name, try to duplicate it with a name that doesn't conflict.
let name = "name" in model ? resolvedModelName(model) : undefined; // When the name is empty, keep it empty so the display falls back to the URL.
if (name != null) { let name = "name" in model ? model.name : undefined;
if (name) {
const existingModels = listModels(model.model); const existingModels = listModels(model.model);
for (let i = 0; i < 100; i++) { for (let i = 0; i < 100; i++) {
const hasConflict = existingModels.some((m) => { const hasConflict = existingModels.some((m) => {

703
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -82,7 +82,7 @@
"vendor:vendor-plugins": "node scripts/vendor-plugins.cjs", "vendor:vendor-plugins": "node scripts/vendor-plugins.cjs",
"vendor:vendor-protoc": "node scripts/vendor-protoc.cjs", "vendor:vendor-protoc": "node scripts/vendor-protoc.cjs",
"vendor:vendor-node": "node scripts/vendor-node.cjs", "vendor:vendor-node": "node scripts/vendor-node.cjs",
"format": "vp fmt --ignore-path .oxfmtignore", "format": "vp fmt",
"lint": "run-p lint:*", "lint": "run-p lint:*",
"lint:vp": "vp lint", "lint:vp": "vp lint",
"lint:workspaces": "npm run --workspaces --if-present lint", "lint:workspaces": "npm run --workspaces --if-present lint",

View File

@@ -5,6 +5,7 @@
"lib": ["es2021", "dom"], "lib": ["es2021", "dom"],
"declaration": true, "declaration": true,
"declarationDir": "./lib", "declarationDir": "./lib",
"rootDir": "./src",
"outDir": "./lib", "outDir": "./lib",
"strict": true, "strict": true,
"types": ["node"] "types": ["node"]

View File

@@ -10,6 +10,7 @@
"moduleResolution": "node16", "moduleResolution": "node16",
"resolveJsonModule": true, "resolveJsonModule": true,
"sourceMap": true, "sourceMap": true,
"rootDir": "src",
"outDir": "build" "outDir": "build"
}, },
"include": ["src"] "include": ["src"]

View File

@@ -15,9 +15,9 @@
}, },
"dependencies": { "dependencies": {
"@hono/mcp": "^0.2.3", "@hono/mcp": "^0.2.3",
"@hono/node-server": "^1.19.10", "@hono/node-server": "^1.19.13",
"@modelcontextprotocol/sdk": "^1.26.0", "@modelcontextprotocol/sdk": "^1.26.0",
"hono": "^4.12.4", "hono": "^4.12.14",
"zod": "^3.25.76" "zod": "^3.25.76"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -9,7 +9,7 @@
"dev": "yaakcli dev" "dev": "yaakcli dev"
}, },
"dependencies": { "dependencies": {
"@xmldom/xmldom": "^0.9.8", "@xmldom/xmldom": "^0.9.10",
"xpath": "^0.0.34" "xpath": "^0.0.34"
} }
} }

View File

@@ -10,6 +10,6 @@
"test": "vp test --run tests" "test": "vp test --run tests"
}, },
"dependencies": { "dependencies": {
"yaml": "^2.4.2" "yaml": "^2.8.3"
} }
} }

View File

@@ -11,7 +11,7 @@
}, },
"dependencies": { "dependencies": {
"openapi-to-postmanv2": "^5.8.0", "openapi-to-postmanv2": "^5.8.0",
"yaml": "^2.4.2" "yaml": "^2.8.3"
}, },
"devDependencies": { "devDependencies": {
"@types/openapi-to-postmanv2": "^5.0.0" "@types/openapi-to-postmanv2": "^5.0.0"

View File

@@ -9,6 +9,6 @@
"dev": "yaakcli dev" "dev": "yaakcli dev"
}, },
"dependencies": { "dependencies": {
"uuid": "^11.1.0" "uuid": "^14.0.0"
} }
} }

2
plugins/template-function-xml/package.json Executable file → Normal file
View File

@@ -11,7 +11,7 @@
"dev": "yaakcli dev" "dev": "yaakcli dev"
}, },
"dependencies": { "dependencies": {
"@xmldom/xmldom": "^0.9.8", "@xmldom/xmldom": "^0.9.10",
"xpath": "^0.0.34" "xpath": "^0.0.34"
} }
} }

View File

@@ -67,6 +67,13 @@
@apply bg-selection !important; @apply bg-selection !important;
} }
/* Fix WebKit/WKWebView rendering bug where selection layer leaves a ghost
residual line below wrapped lines after deselecting (CodeMirror issue #1600, #1627).
The layer div must be hidden when empty to force a repaint. */
.cm-selectionLayer:empty {
display: none;
}
/* Style gutters */ /* Style gutters */
.cm-gutters { .cm-gutters {

View File

@@ -57,7 +57,7 @@ export function HttpMethodTagRaw({
let label = method.toUpperCase(); let label = method.toUpperCase();
if (short) { if (short) {
label = methodNames[method.toLowerCase()] ?? method.slice(0, 4); label = methodNames[method.toLowerCase()] ?? method.slice(0, 4);
label = label.padStart(4, " "); label = label.padEnd(4, " ");
} }
const m = method.toUpperCase(); const m = method.toUpperCase();

View File

@@ -70,10 +70,10 @@
"remark-frontmatter": "^5.0.0", "remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"uuid": "^11.1.0", "uuid": "^14.0.0",
"vkbeautify": "^0.99.3", "vkbeautify": "^0.99.3",
"whatwg-mimetype": "^4.0.0", "whatwg-mimetype": "^4.0.0",
"yaml": "^2.6.1" "yaml": "^2.8.3"
}, },
"devDependencies": { "devDependencies": {
"@lezer/generator": "^1.8.0", "@lezer/generator": "^1.8.0",

View File

@@ -8,131 +8,133 @@
// You should NOT make any changes in this file as it will be overwritten. // You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from "./routes/__root"; import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from "./routes/index"; import { Route as IndexRouteImport } from './routes/index'
import { Route as WorkspacesIndexRouteImport } from "./routes/workspaces/index"; import { Route as WorkspacesIndexRouteImport } from './routes/workspaces/index'
import { Route as WorkspacesWorkspaceIdIndexRouteImport } from "./routes/workspaces/$workspaceId/index"; import { Route as WorkspacesWorkspaceIdIndexRouteImport } from './routes/workspaces/$workspaceId/index'
import { Route as WorkspacesWorkspaceIdSettingsRouteImport } from "./routes/workspaces/$workspaceId/settings"; import { Route as WorkspacesWorkspaceIdSettingsRouteImport } from './routes/workspaces/$workspaceId/settings'
import { Route as WorkspacesWorkspaceIdRequestsRequestIdRouteImport } from "./routes/workspaces/$workspaceId/requests/$requestId"; import { Route as WorkspacesWorkspaceIdRequestsRequestIdRouteImport } from './routes/workspaces/$workspaceId/requests/$requestId'
const IndexRoute = IndexRouteImport.update({ const IndexRoute = IndexRouteImport.update({
id: "/", id: '/',
path: "/", path: '/',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any); } as any)
const WorkspacesIndexRoute = WorkspacesIndexRouteImport.update({ const WorkspacesIndexRoute = WorkspacesIndexRouteImport.update({
id: "/workspaces/", id: '/workspaces/',
path: "/workspaces/", path: '/workspaces/',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any); } as any)
const WorkspacesWorkspaceIdIndexRoute = WorkspacesWorkspaceIdIndexRouteImport.update({ const WorkspacesWorkspaceIdIndexRoute =
id: "/workspaces/$workspaceId/", WorkspacesWorkspaceIdIndexRouteImport.update({
path: "/workspaces/$workspaceId/", id: '/workspaces/$workspaceId/',
getParentRoute: () => rootRouteImport, path: '/workspaces/$workspaceId/',
} as any); getParentRoute: () => rootRouteImport,
const WorkspacesWorkspaceIdSettingsRoute = WorkspacesWorkspaceIdSettingsRouteImport.update({ } as any)
id: "/workspaces/$workspaceId/settings", const WorkspacesWorkspaceIdSettingsRoute =
path: "/workspaces/$workspaceId/settings", WorkspacesWorkspaceIdSettingsRouteImport.update({
getParentRoute: () => rootRouteImport, id: '/workspaces/$workspaceId/settings',
} as any); path: '/workspaces/$workspaceId/settings',
getParentRoute: () => rootRouteImport,
} as any)
const WorkspacesWorkspaceIdRequestsRequestIdRoute = const WorkspacesWorkspaceIdRequestsRequestIdRoute =
WorkspacesWorkspaceIdRequestsRequestIdRouteImport.update({ WorkspacesWorkspaceIdRequestsRequestIdRouteImport.update({
id: "/workspaces/$workspaceId/requests/$requestId", id: '/workspaces/$workspaceId/requests/$requestId',
path: "/workspaces/$workspaceId/requests/$requestId", path: '/workspaces/$workspaceId/requests/$requestId',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any); } as any)
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
"/": typeof IndexRoute; '/': typeof IndexRoute
"/workspaces": typeof WorkspacesIndexRoute; '/workspaces': typeof WorkspacesIndexRoute
"/workspaces/$workspaceId/settings": typeof WorkspacesWorkspaceIdSettingsRoute; '/workspaces/$workspaceId/settings': typeof WorkspacesWorkspaceIdSettingsRoute
"/workspaces/$workspaceId": typeof WorkspacesWorkspaceIdIndexRoute; '/workspaces/$workspaceId': typeof WorkspacesWorkspaceIdIndexRoute
"/workspaces/$workspaceId/requests/$requestId": typeof WorkspacesWorkspaceIdRequestsRequestIdRoute; '/workspaces/$workspaceId/requests/$requestId': typeof WorkspacesWorkspaceIdRequestsRequestIdRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
"/": typeof IndexRoute; '/': typeof IndexRoute
"/workspaces": typeof WorkspacesIndexRoute; '/workspaces': typeof WorkspacesIndexRoute
"/workspaces/$workspaceId/settings": typeof WorkspacesWorkspaceIdSettingsRoute; '/workspaces/$workspaceId/settings': typeof WorkspacesWorkspaceIdSettingsRoute
"/workspaces/$workspaceId": typeof WorkspacesWorkspaceIdIndexRoute; '/workspaces/$workspaceId': typeof WorkspacesWorkspaceIdIndexRoute
"/workspaces/$workspaceId/requests/$requestId": typeof WorkspacesWorkspaceIdRequestsRequestIdRoute; '/workspaces/$workspaceId/requests/$requestId': typeof WorkspacesWorkspaceIdRequestsRequestIdRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRouteImport; __root__: typeof rootRouteImport
"/": typeof IndexRoute; '/': typeof IndexRoute
"/workspaces/": typeof WorkspacesIndexRoute; '/workspaces/': typeof WorkspacesIndexRoute
"/workspaces/$workspaceId/settings": typeof WorkspacesWorkspaceIdSettingsRoute; '/workspaces/$workspaceId/settings': typeof WorkspacesWorkspaceIdSettingsRoute
"/workspaces/$workspaceId/": typeof WorkspacesWorkspaceIdIndexRoute; '/workspaces/$workspaceId/': typeof WorkspacesWorkspaceIdIndexRoute
"/workspaces/$workspaceId/requests/$requestId": typeof WorkspacesWorkspaceIdRequestsRequestIdRoute; '/workspaces/$workspaceId/requests/$requestId': typeof WorkspacesWorkspaceIdRequestsRequestIdRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath; fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: fullPaths:
| "/" | '/'
| "/workspaces" | '/workspaces'
| "/workspaces/$workspaceId/settings" | '/workspaces/$workspaceId/settings'
| "/workspaces/$workspaceId" | '/workspaces/$workspaceId'
| "/workspaces/$workspaceId/requests/$requestId"; | '/workspaces/$workspaceId/requests/$requestId'
fileRoutesByTo: FileRoutesByTo; fileRoutesByTo: FileRoutesByTo
to: to:
| "/" | '/'
| "/workspaces" | '/workspaces'
| "/workspaces/$workspaceId/settings" | '/workspaces/$workspaceId/settings'
| "/workspaces/$workspaceId" | '/workspaces/$workspaceId'
| "/workspaces/$workspaceId/requests/$requestId"; | '/workspaces/$workspaceId/requests/$requestId'
id: id:
| "__root__" | '__root__'
| "/" | '/'
| "/workspaces/" | '/workspaces/'
| "/workspaces/$workspaceId/settings" | '/workspaces/$workspaceId/settings'
| "/workspaces/$workspaceId/" | '/workspaces/$workspaceId/'
| "/workspaces/$workspaceId/requests/$requestId"; | '/workspaces/$workspaceId/requests/$requestId'
fileRoutesById: FileRoutesById; fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute; IndexRoute: typeof IndexRoute
WorkspacesIndexRoute: typeof WorkspacesIndexRoute; WorkspacesIndexRoute: typeof WorkspacesIndexRoute
WorkspacesWorkspaceIdSettingsRoute: typeof WorkspacesWorkspaceIdSettingsRoute; WorkspacesWorkspaceIdSettingsRoute: typeof WorkspacesWorkspaceIdSettingsRoute
WorkspacesWorkspaceIdIndexRoute: typeof WorkspacesWorkspaceIdIndexRoute; WorkspacesWorkspaceIdIndexRoute: typeof WorkspacesWorkspaceIdIndexRoute
WorkspacesWorkspaceIdRequestsRequestIdRoute: typeof WorkspacesWorkspaceIdRequestsRequestIdRoute; WorkspacesWorkspaceIdRequestsRequestIdRoute: typeof WorkspacesWorkspaceIdRequestsRequestIdRoute
} }
declare module "@tanstack/react-router" { declare module '@tanstack/react-router' {
interface FileRoutesByPath { interface FileRoutesByPath {
"/": { '/': {
id: "/"; id: '/'
path: "/"; path: '/'
fullPath: "/"; fullPath: '/'
preLoaderRoute: typeof IndexRouteImport; preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport; parentRoute: typeof rootRouteImport
}; }
"/workspaces/": { '/workspaces/': {
id: "/workspaces/"; id: '/workspaces/'
path: "/workspaces"; path: '/workspaces'
fullPath: "/workspaces"; fullPath: '/workspaces'
preLoaderRoute: typeof WorkspacesIndexRouteImport; preLoaderRoute: typeof WorkspacesIndexRouteImport
parentRoute: typeof rootRouteImport; parentRoute: typeof rootRouteImport
}; }
"/workspaces/$workspaceId/": { '/workspaces/$workspaceId/': {
id: "/workspaces/$workspaceId/"; id: '/workspaces/$workspaceId/'
path: "/workspaces/$workspaceId"; path: '/workspaces/$workspaceId'
fullPath: "/workspaces/$workspaceId"; fullPath: '/workspaces/$workspaceId'
preLoaderRoute: typeof WorkspacesWorkspaceIdIndexRouteImport; preLoaderRoute: typeof WorkspacesWorkspaceIdIndexRouteImport
parentRoute: typeof rootRouteImport; parentRoute: typeof rootRouteImport
}; }
"/workspaces/$workspaceId/settings": { '/workspaces/$workspaceId/settings': {
id: "/workspaces/$workspaceId/settings"; id: '/workspaces/$workspaceId/settings'
path: "/workspaces/$workspaceId/settings"; path: '/workspaces/$workspaceId/settings'
fullPath: "/workspaces/$workspaceId/settings"; fullPath: '/workspaces/$workspaceId/settings'
preLoaderRoute: typeof WorkspacesWorkspaceIdSettingsRouteImport; preLoaderRoute: typeof WorkspacesWorkspaceIdSettingsRouteImport
parentRoute: typeof rootRouteImport; parentRoute: typeof rootRouteImport
}; }
"/workspaces/$workspaceId/requests/$requestId": { '/workspaces/$workspaceId/requests/$requestId': {
id: "/workspaces/$workspaceId/requests/$requestId"; id: '/workspaces/$workspaceId/requests/$requestId'
path: "/workspaces/$workspaceId/requests/$requestId"; path: '/workspaces/$workspaceId/requests/$requestId'
fullPath: "/workspaces/$workspaceId/requests/$requestId"; fullPath: '/workspaces/$workspaceId/requests/$requestId'
preLoaderRoute: typeof WorkspacesWorkspaceIdRequestsRequestIdRouteImport; preLoaderRoute: typeof WorkspacesWorkspaceIdRequestsRequestIdRouteImport
parentRoute: typeof rootRouteImport; parentRoute: typeof rootRouteImport
}; }
} }
} }
@@ -141,8 +143,9 @@ const rootRouteChildren: RootRouteChildren = {
WorkspacesIndexRoute: WorkspacesIndexRoute, WorkspacesIndexRoute: WorkspacesIndexRoute,
WorkspacesWorkspaceIdSettingsRoute: WorkspacesWorkspaceIdSettingsRoute, WorkspacesWorkspaceIdSettingsRoute: WorkspacesWorkspaceIdSettingsRoute,
WorkspacesWorkspaceIdIndexRoute: WorkspacesWorkspaceIdIndexRoute, WorkspacesWorkspaceIdIndexRoute: WorkspacesWorkspaceIdIndexRoute,
WorkspacesWorkspaceIdRequestsRequestIdRoute: WorkspacesWorkspaceIdRequestsRequestIdRoute, WorkspacesWorkspaceIdRequestsRequestIdRoute:
}; WorkspacesWorkspaceIdRequestsRequestIdRoute,
}
export const routeTree = rootRouteImport export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren) ._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>(); ._addFileTypes<FileRouteTypes>()

View File

@@ -5,7 +5,6 @@
"useDefineForClassFields": true, "useDefineForClassFields": true,
"allowJs": false, "allowJs": false,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": true, "strict": true,
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,
@@ -15,9 +14,9 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx",
}, },
"include": ["."], "include": ["."],
"exclude": ["vite.config.ts"], "exclude": ["vite.config.ts"],
"references": [{ "path": "./tsconfig.node.json" }] "references": [{ "path": "./tsconfig.node.json" }],
} }

View File

@@ -5,7 +5,6 @@
"useDefineForClassFields": true, "useDefineForClassFields": true,
"allowJs": false, "allowJs": false,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": true, "strict": true,
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,