diff --git a/apps/yaak-client/components/HttpResponseTimeline.tsx b/apps/yaak-client/components/HttpResponseTimeline.tsx
index 8ad5e3aa..c668694b 100644
--- a/apps/yaak-client/components/HttpResponseTimeline.tsx
+++ b/apps/yaak-client/components/HttpResponseTimeline.tsx
@@ -1,10 +1,15 @@
import type {
+ AnyModel,
HttpResponse,
HttpResponseEvent,
HttpResponseEventData,
} from "@yaakapp-internal/models";
+import { foldersAtom, workspacesAtom } from "@yaakapp-internal/models";
+import { useAtomValue } from "jotai";
import { type ReactNode, useMemo, useState } from "react";
import { useHttpResponseEvents } from "../hooks/useHttpResponseEvents";
+import { useAllRequests } from "../hooks/useAllRequests";
+import { resolvedModelName } from "../lib/resolvedModelName";
import { Editor } from "./core/Editor/LazyEditor";
import { type EventDetailAction, EventDetailHeader, EventViewer } from "./core/EventViewer";
import { EventViewerRow } from "./core/EventViewerRow";
@@ -95,6 +100,7 @@ function EventDetails({
}) {
const { label } = getEventDisplay(event.event);
const e = event.event;
+ const settingSourceModels = useSettingSourceModels();
const actions: EventDetailAction[] = [
{
@@ -211,6 +217,9 @@ function EventDetails({
{e.name}
{e.value}
+ {e.source_model != null ? (
+ {formatSettingSource(e, settingSourceModels)}
+ ) : null}
);
}
@@ -315,6 +324,35 @@ function formatEventText(event: HttpResponseEventData, includePrefix: boolean):
return includePrefix ? `${prefix} ${text}` : text;
}
+function useSettingSourceModels() {
+ const requests = useAllRequests();
+ const folders = useAtomValue(foldersAtom);
+ const workspaces = useAtomValue(workspacesAtom);
+
+ return useMemo(
+ () => [...requests, ...folders, ...workspaces],
+ [requests, folders, workspaces],
+ );
+}
+
+function formatSettingSource(
+ event: Extract,
+ models: AnyModel[],
+): string {
+ const sourceModel = event.source_model;
+ if (sourceModel == null || sourceModel === "default") {
+ return "Default";
+ }
+
+ const model =
+ event.source_id == null
+ ? null
+ : (models.find((m) => m.model === sourceModel && m.id === event.source_id) ?? null);
+ const name = model == null ? event.source_name : resolvedModelName(model);
+ const label = sourceModel.replaceAll("_", " ");
+ return name == null || name.length === 0 ? label : `${name} (${label})`;
+}
+
type EventDisplay = {
icon: IconProps["icon"];
color: IconProps["color"];
diff --git a/crates-tauri/yaak-app-client/src/ws_ext.rs b/crates-tauri/yaak-app-client/src/ws_ext.rs
index 936756cc..e627f867 100644
--- a/crates-tauri/yaak-app-client/src/ws_ext.rs
+++ b/crates-tauri/yaak-app-client/src/ws_ext.rs
@@ -248,16 +248,18 @@ pub async fn cmd_ws_connect(
}
}
- let mut cookie_jar =
- match (resolved_settings.send_cookies || resolved_settings.store_cookies, cookie_jar_id) {
- (true, Some(id)) => Some(app_handle.db().get_cookie_jar(id)?),
- _ => None,
- };
+ let mut cookie_jar = match (
+ resolved_settings.send_cookies.value || resolved_settings.store_cookies.value,
+ cookie_jar_id,
+ ) {
+ (true, Some(id)) => Some(app_handle.db().get_cookie_jar(id)?),
+ _ => None,
+ };
let cookie_store =
cookie_jar.as_ref().map(|jar| CookieStore::from_cookies(jar.cookies.clone()));
// Add cookies to WS HTTP Upgrade
- if let (true, Some(store)) = (resolved_settings.send_cookies, cookie_store.as_ref()) {
+ if let (true, Some(store)) = (resolved_settings.send_cookies.value, cookie_store.as_ref()) {
// Convert WS URL -> HTTP URL because our cookie store matches based on
// Path/HttpOnly/Secure attributes even though WS upgrades are HTTP requests
let http_url = convert_ws_url_to_http(&url);
@@ -295,7 +297,7 @@ pub async fn cmd_ws_connect(
url.as_str(),
headers,
receive_tx,
- resolved_settings.validate_certificates,
+ resolved_settings.validate_certificates.value,
client_cert,
)
.await
@@ -335,7 +337,7 @@ pub async fn cmd_ws_connect(
.collect::>();
if let (true, Some(cookie_jar), Some(store)) =
- (resolved_settings.store_cookies, cookie_jar.as_mut(), cookie_store.as_ref())
+ (resolved_settings.store_cookies.value, cookie_jar.as_mut(), cookie_store.as_ref())
{
let set_cookie_headers = response
.headers()
diff --git a/crates/yaak-http/src/sender.rs b/crates/yaak-http/src/sender.rs
index 063f0a47..2ffdcde8 100644
--- a/crates/yaak-http/src/sender.rs
+++ b/crates/yaak-http/src/sender.rs
@@ -24,7 +24,13 @@ pub enum RedirectBehavior {
#[derive(Debug, Clone)]
pub enum HttpResponseEvent {
- Setting(String, String),
+ Setting {
+ name: String,
+ value: String,
+ source_model: Option,
+ source_id: Option,
+ source_name: Option,
+ },
Info(String),
Redirect {
url: String,
@@ -67,7 +73,9 @@ pub enum HttpResponseEvent {
impl Display for HttpResponseEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
- HttpResponseEvent::Setting(name, value) => write!(f, "* Setting {}={}", name, value),
+ HttpResponseEvent::Setting { name, value, .. } => {
+ write!(f, "* Setting {}={}", name, value)
+ }
HttpResponseEvent::Info(s) => write!(f, "* {}", s),
HttpResponseEvent::Redirect {
url,
@@ -146,7 +154,9 @@ impl From for yaak_models::models::HttpResponseEventData {
fn from(event: HttpResponseEvent) -> Self {
use yaak_models::models::HttpResponseEventData as D;
match event {
- HttpResponseEvent::Setting(name, value) => D::Setting { name, value },
+ HttpResponseEvent::Setting { name, value, source_model, source_id, source_name } => {
+ D::Setting { name, value, source_model, source_id, source_name }
+ }
HttpResponseEvent::Info(message) => D::Info { message },
HttpResponseEvent::Redirect {
url,
@@ -483,15 +493,6 @@ impl HttpSender for ReqwestSender {
// Send the request
let sendable_req = req_builder.build()?;
- send_event(HttpResponseEvent::Setting(
- "timeout".to_string(),
- if request.options.timeout.unwrap_or_default().is_zero() {
- "Infinity".to_string()
- } else {
- format!("{:?}", request.options.timeout)
- },
- ));
-
send_event(HttpResponseEvent::SendUrl {
method: sendable_req.method().to_string(),
scheme: sendable_req.url().scheme().to_string(),
diff --git a/crates/yaak-http/src/transaction.rs b/crates/yaak-http/src/transaction.rs
index 67019693..be7ce972 100644
--- a/crates/yaak-http/src/transaction.rs
+++ b/crates/yaak-http/src/transaction.rs
@@ -144,12 +144,6 @@ impl HttpTransaction {
options: request.options.clone(),
};
- // Send the request
- send_event(HttpResponseEvent::Setting(
- "redirects".to_string(),
- request.options.follow_redirects.to_string(),
- ));
-
// Execute with cancellation support
let response = tokio::select! {
result = self.sender.send(req, event_tx.clone()) => result?,
diff --git a/crates/yaak-models/bindings/gen_models.ts b/crates/yaak-models/bindings/gen_models.ts
index 359f4895..616dc43f 100644
--- a/crates/yaak-models/bindings/gen_models.ts
+++ b/crates/yaak-models/bindings/gen_models.ts
@@ -258,7 +258,14 @@ export type HttpResponseEvent = {
* The `From` impl is in yaak-http to avoid circular dependencies.
*/
export type HttpResponseEventData =
- | { type: "setting"; name: string; value: string }
+ | {
+ type: "setting";
+ name: string;
+ value: string;
+ source_model?: string;
+ source_id?: string;
+ source_name?: string;
+ }
| { type: "info"; message: string }
| {
type: "redirect";
diff --git a/crates/yaak-models/src/models.rs b/crates/yaak-models/src/models.rs
index 3050c725..59b17901 100644
--- a/crates/yaak-models/src/models.rs
+++ b/crates/yaak-models/src/models.rs
@@ -92,23 +92,46 @@ pub struct DnsOverride {
pub enabled: bool,
}
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct ResolvedSetting {
+ pub value: T,
+ pub source_model: String,
+ pub source_id: Option,
+ pub source_name: Option,
+}
+
+impl ResolvedSetting {
+ pub fn from_model(value: T, model: AnyModel) -> Self {
+ Self {
+ value,
+ source_model: model.model().to_string(),
+ source_id: Some(model.id().to_string()),
+ source_name: Some(model.resolved_name()),
+ }
+ }
+
+ pub fn default_source(value: T) -> Self {
+ Self { value, source_model: "default".to_string(), source_id: None, source_name: None }
+ }
+}
+
#[derive(Debug, Clone, PartialEq)]
pub struct ResolvedHttpRequestSettings {
- pub validate_certificates: bool,
- pub follow_redirects: bool,
- pub request_timeout: i32,
- pub send_cookies: bool,
- pub store_cookies: bool,
+ pub validate_certificates: ResolvedSetting,
+ pub follow_redirects: ResolvedSetting,
+ pub request_timeout: ResolvedSetting,
+ pub send_cookies: ResolvedSetting,
+ pub store_cookies: ResolvedSetting,
}
impl Default for ResolvedHttpRequestSettings {
fn default() -> Self {
Self {
- validate_certificates: true,
- follow_redirects: true,
- request_timeout: 0,
- send_cookies: true,
- store_cookies: true,
+ validate_certificates: ResolvedSetting::default_source(true),
+ follow_redirects: ResolvedSetting::default_source(true),
+ request_timeout: ResolvedSetting::default_source(0),
+ send_cookies: ResolvedSetting::default_source(true),
+ store_cookies: ResolvedSetting::default_source(true),
}
}
}
@@ -1748,6 +1771,15 @@ pub enum HttpResponseEventData {
Setting {
name: String,
value: String,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ #[ts(optional, as = "Option")]
+ source_model: Option,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ #[ts(optional, as = "Option")]
+ source_id: Option,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ #[ts(optional, as = "Option")]
+ source_name: Option,
},
Info {
message: String,
diff --git a/crates/yaak-models/src/queries/folders.rs b/crates/yaak-models/src/queries/folders.rs
index 75ece683..c2be0823 100644
--- a/crates/yaak-models/src/queries/folders.rs
+++ b/crates/yaak-models/src/queries/folders.rs
@@ -2,9 +2,9 @@ use crate::client_db::ClientDb;
use crate::connection_or_tx::ConnectionOrTx;
use crate::error::Result;
use crate::models::{
- Environment, EnvironmentIden, Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequest,
- HttpRequestHeader, HttpRequestIden, ResolvedHttpRequestSettings, WebsocketRequest,
- WebsocketRequestIden,
+ AnyModel, Environment, EnvironmentIden, Folder, FolderIden, GrpcRequest, GrpcRequestIden,
+ HttpRequest, HttpRequestHeader, HttpRequestIden, ResolvedHttpRequestSettings, ResolvedSetting,
+ WebsocketRequest, WebsocketRequestIden,
};
use crate::util::UpdateSource;
use serde_json::Value;
@@ -157,27 +157,42 @@ impl<'a> ClientDb<'a> {
Ok(ResolvedHttpRequestSettings {
validate_certificates: if folder.setting_validate_certificates.enabled {
- folder.setting_validate_certificates.value
+ ResolvedSetting::from_model(
+ folder.setting_validate_certificates.value,
+ AnyModel::Folder(folder.clone()),
+ )
} else {
parent.validate_certificates
},
follow_redirects: if folder.setting_follow_redirects.enabled {
- folder.setting_follow_redirects.value
+ ResolvedSetting::from_model(
+ folder.setting_follow_redirects.value,
+ AnyModel::Folder(folder.clone()),
+ )
} else {
parent.follow_redirects
},
request_timeout: if folder.setting_request_timeout.enabled {
- folder.setting_request_timeout.value
+ ResolvedSetting::from_model(
+ folder.setting_request_timeout.value,
+ AnyModel::Folder(folder.clone()),
+ )
} else {
parent.request_timeout
},
send_cookies: if folder.setting_send_cookies.enabled {
- folder.setting_send_cookies.value
+ ResolvedSetting::from_model(
+ folder.setting_send_cookies.value,
+ AnyModel::Folder(folder.clone()),
+ )
} else {
parent.send_cookies
},
store_cookies: if folder.setting_store_cookies.enabled {
- folder.setting_store_cookies.value
+ ResolvedSetting::from_model(
+ folder.setting_store_cookies.value,
+ AnyModel::Folder(folder.clone()),
+ )
} else {
parent.store_cookies
},
diff --git a/crates/yaak-models/src/queries/http_requests.rs b/crates/yaak-models/src/queries/http_requests.rs
index 22e337eb..b05d9afe 100644
--- a/crates/yaak-models/src/queries/http_requests.rs
+++ b/crates/yaak-models/src/queries/http_requests.rs
@@ -2,8 +2,8 @@ use super::dedupe_headers;
use crate::client_db::ClientDb;
use crate::error::Result;
use crate::models::{
- Folder, FolderIden, HttpRequest, HttpRequestHeader, HttpRequestIden,
- ResolvedHttpRequestSettings,
+ AnyModel, Folder, FolderIden, HttpRequest, HttpRequestHeader, HttpRequestIden,
+ ResolvedHttpRequestSettings, ResolvedSetting,
};
use crate::util::UpdateSource;
use serde_json::Value;
@@ -108,27 +108,42 @@ impl<'a> ClientDb<'a> {
Ok(ResolvedHttpRequestSettings {
validate_certificates: if http_request.setting_validate_certificates.enabled {
- http_request.setting_validate_certificates.value
+ ResolvedSetting::from_model(
+ http_request.setting_validate_certificates.value,
+ AnyModel::HttpRequest(http_request.clone()),
+ )
} else {
parent.validate_certificates
},
follow_redirects: if http_request.setting_follow_redirects.enabled {
- http_request.setting_follow_redirects.value
+ ResolvedSetting::from_model(
+ http_request.setting_follow_redirects.value,
+ AnyModel::HttpRequest(http_request.clone()),
+ )
} else {
parent.follow_redirects
},
request_timeout: if http_request.setting_request_timeout.enabled {
- http_request.setting_request_timeout.value
+ ResolvedSetting::from_model(
+ http_request.setting_request_timeout.value,
+ AnyModel::HttpRequest(http_request.clone()),
+ )
} else {
parent.request_timeout
},
send_cookies: if http_request.setting_send_cookies.enabled {
- http_request.setting_send_cookies.value
+ ResolvedSetting::from_model(
+ http_request.setting_send_cookies.value,
+ AnyModel::HttpRequest(http_request.clone()),
+ )
} else {
parent.send_cookies
},
store_cookies: if http_request.setting_store_cookies.enabled {
- http_request.setting_store_cookies.value
+ ResolvedSetting::from_model(
+ http_request.setting_store_cookies.value,
+ AnyModel::HttpRequest(http_request.clone()),
+ )
} else {
parent.store_cookies
},
diff --git a/crates/yaak-models/src/queries/websocket_requests.rs b/crates/yaak-models/src/queries/websocket_requests.rs
index 598100a3..78617747 100644
--- a/crates/yaak-models/src/queries/websocket_requests.rs
+++ b/crates/yaak-models/src/queries/websocket_requests.rs
@@ -2,8 +2,8 @@ use super::dedupe_headers;
use crate::client_db::ClientDb;
use crate::error::Result;
use crate::models::{
- Folder, FolderIden, HttpRequestHeader, ResolvedHttpRequestSettings, WebsocketRequest,
- WebsocketRequestIden,
+ AnyModel, Folder, FolderIden, HttpRequestHeader, ResolvedHttpRequestSettings, ResolvedSetting,
+ WebsocketRequest, WebsocketRequestIden,
};
use crate::util::UpdateSource;
use serde_json::Value;
@@ -132,12 +132,18 @@ impl<'a> ClientDb<'a> {
Ok(ResolvedHttpRequestSettings {
send_cookies: if websocket_request.setting_send_cookies.enabled {
- websocket_request.setting_send_cookies.value
+ ResolvedSetting::from_model(
+ websocket_request.setting_send_cookies.value,
+ AnyModel::WebsocketRequest(websocket_request.clone()),
+ )
} else {
parent.send_cookies
},
store_cookies: if websocket_request.setting_store_cookies.enabled {
- websocket_request.setting_store_cookies.value
+ ResolvedSetting::from_model(
+ websocket_request.setting_store_cookies.value,
+ AnyModel::WebsocketRequest(websocket_request.clone()),
+ )
} else {
parent.store_cookies
},
diff --git a/crates/yaak-models/src/queries/workspaces.rs b/crates/yaak-models/src/queries/workspaces.rs
index 118483bb..fd97cc47 100644
--- a/crates/yaak-models/src/queries/workspaces.rs
+++ b/crates/yaak-models/src/queries/workspaces.rs
@@ -1,8 +1,8 @@
use crate::client_db::ClientDb;
use crate::error::Result;
use crate::models::{
- EnvironmentIden, FolderIden, GrpcRequestIden, HttpRequestHeader, HttpRequestIden,
- ResolvedHttpRequestSettings, WebsocketRequestIden, Workspace, WorkspaceIden,
+ AnyModel, EnvironmentIden, FolderIden, GrpcRequestIden, HttpRequestHeader, HttpRequestIden,
+ ResolvedHttpRequestSettings, ResolvedSetting, WebsocketRequestIden, Workspace, WorkspaceIden,
};
use crate::util::UpdateSource;
use serde_json::Value;
@@ -90,11 +90,26 @@ impl<'a> ClientDb<'a> {
workspace: &Workspace,
) -> ResolvedHttpRequestSettings {
ResolvedHttpRequestSettings {
- validate_certificates: workspace.setting_validate_certificates,
- follow_redirects: workspace.setting_follow_redirects,
- request_timeout: workspace.setting_request_timeout,
- send_cookies: workspace.setting_send_cookies,
- store_cookies: workspace.setting_store_cookies,
+ validate_certificates: ResolvedSetting::from_model(
+ workspace.setting_validate_certificates,
+ AnyModel::Workspace(workspace.clone()),
+ ),
+ follow_redirects: ResolvedSetting::from_model(
+ workspace.setting_follow_redirects,
+ AnyModel::Workspace(workspace.clone()),
+ ),
+ request_timeout: ResolvedSetting::from_model(
+ workspace.setting_request_timeout,
+ AnyModel::Workspace(workspace.clone()),
+ ),
+ send_cookies: ResolvedSetting::from_model(
+ workspace.setting_send_cookies,
+ AnyModel::Workspace(workspace.clone()),
+ ),
+ store_cookies: ResolvedSetting::from_model(
+ workspace.setting_store_cookies,
+ AnyModel::Workspace(workspace.clone()),
+ ),
}
}
}
diff --git a/crates/yaak-plugins/bindings/gen_models.ts b/crates/yaak-plugins/bindings/gen_models.ts
index 5d02b60b..c9b7bfc3 100644
--- a/crates/yaak-plugins/bindings/gen_models.ts
+++ b/crates/yaak-plugins/bindings/gen_models.ts
@@ -1,108 +1,482 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
-export type AnyModel = CookieJar | Environment | Folder | GraphQlIntrospection | GrpcConnection | GrpcEvent | GrpcRequest | HttpRequest | HttpResponse | HttpResponseEvent | KeyValue | Plugin | Settings | SyncState | WebsocketConnection | WebsocketEvent | WebsocketRequest | Workspace | WorkspaceMeta;
+export type AnyModel =
+ | CookieJar
+ | Environment
+ | Folder
+ | GraphQlIntrospection
+ | GrpcConnection
+ | GrpcEvent
+ | GrpcRequest
+ | HttpRequest
+ | HttpResponse
+ | HttpResponseEvent
+ | KeyValue
+ | Plugin
+ | Settings
+ | SyncState
+ | WebsocketConnection
+ | WebsocketEvent
+ | WebsocketRequest
+ | Workspace
+ | WorkspaceMeta;
-export type ClientCertificate = { host: string, port: number | null, crtFile: string | null, keyFile: string | null, pfxFile: string | null, passphrase: string | null, enabled?: boolean, };
+export type ClientCertificate = {
+ host: string;
+ port: number | null;
+ crtFile: string | null;
+ keyFile: string | null;
+ pfxFile: string | null;
+ passphrase: string | null;
+ enabled?: boolean;
+};
-export type Cookie = { raw_cookie: string, domain: CookieDomain, expires: CookieExpires, path: [string, boolean], };
+export type Cookie = {
+ name: string;
+ value: string;
+ domain: CookieDomain;
+ expires: CookieExpires;
+ path: string;
+ secure: boolean;
+ httpOnly: boolean;
+ sameSite: CookieSameSite | null;
+};
-export type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "NotPresent" | "Empty";
+export type CookieDomain = { HostOnly: string } | { Suffix: string } | "NotPresent" | "Empty";
-export type CookieExpires = { "AtUtc": string } | "SessionEnd";
+export type CookieExpires = { AtUtc: string } | "SessionEnd";
-export type CookieJar = { model: "cookie_jar", id: string, createdAt: string, updatedAt: string, workspaceId: string, cookies: Array, name: string, };
+export type CookieJar = {
+ model: "cookie_jar";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ cookies: Array;
+ name: string;
+};
-export type DnsOverride = { hostname: string, ipv4: Array, ipv6: Array, enabled?: boolean, };
+export type CookieSameSite = "Strict" | "Lax" | "None";
+
+export type DnsOverride = {
+ hostname: string;
+ ipv4: Array;
+ ipv6: Array;
+ enabled?: boolean;
+};
export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
-export type EncryptedKey = { encryptedKey: string, };
+export type EncryptedKey = { encryptedKey: string };
-export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null,
-/**
- * Variables defined in this environment scope.
- * Child environments override parent variables by name.
- */
-variables: Array, color: string | null, sortPriority: number, };
+export type Environment = {
+ model: "environment";
+ id: string;
+ workspaceId: string;
+ createdAt: string;
+ updatedAt: string;
+ name: string;
+ public: boolean;
+ parentModel: string;
+ parentId: string | null;
+ /**
+ * Variables defined in this environment scope.
+ * Child environments override parent variables by name.
+ */
+ variables: Array;
+ color: string | null;
+ sortPriority: number;
+};
-export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
+export type EnvironmentVariable = { enabled?: boolean; name: string; value: string; id?: string };
-export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, description: string, headers: Array, name: string, sortPriority: number, };
+export type Folder = {
+ model: "folder";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authentication: Record;
+ authenticationType: string | null;
+ description: string;
+ headers: Array;
+ name: string;
+ sortPriority: number;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+ settingValidateCertificates: InheritedBoolSetting;
+ settingFollowRedirects: InheritedBoolSetting;
+ settingRequestTimeout: InheritedIntSetting;
+};
-export type GraphQlIntrospection = { model: "graphql_introspection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, content: string | null, };
+export type GraphQlIntrospection = {
+ model: "graphql_introspection";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ content: string | null;
+};
-export type GrpcConnection = { model: "grpc_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, method: string, service: string, status: number, state: GrpcConnectionState, trailers: { [key in string]?: string }, url: string, };
+export type GrpcConnection = {
+ model: "grpc_connection";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ elapsed: number;
+ error: string | null;
+ method: string;
+ service: string;
+ status: number;
+ state: GrpcConnectionState;
+ trailers: { [key in string]?: string };
+ url: string;
+};
export type GrpcConnectionState = "initialized" | "connected" | "closed";
-export type GrpcEvent = { model: "grpc_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, content: string, error: string | null, eventType: GrpcEventType, metadata: { [key in string]?: string }, status: number | null, };
+export type GrpcEvent = {
+ model: "grpc_event";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ connectionId: string;
+ content: string;
+ error: string | null;
+ eventType: GrpcEventType;
+ metadata: { [key in string]?: string };
+ status: number | null;
+};
-export type GrpcEventType = "info" | "error" | "client_message" | "server_message" | "connection_start" | "connection_end";
+export type GrpcEventType =
+ | "info"
+ | "error"
+ | "client_message"
+ | "server_message"
+ | "connection_start"
+ | "connection_end";
-export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record, description: string, message: string, metadata: Array, method: string | null, name: string, service: string | null, sortPriority: number,
-/**
- * Server URL (http for plaintext or https for secure)
- */
-url: string, };
+export type GrpcRequest = {
+ model: "grpc_request";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authenticationType: string | null;
+ authentication: Record;
+ description: string;
+ message: string;
+ metadata: Array;
+ method: string | null;
+ name: string;
+ service: string | null;
+ sortPriority: number;
+ /**
+ * Server URL (http for plaintext or https for secure)
+ */
+ url: string;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+};
-export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, body: Record, bodyType: string | null, description: string, headers: Array, method: string, name: string, sortPriority: number, url: string,
-/**
- * URL parameters used for both path placeholders (`:id`) and query string entries.
- */
-urlParameters: Array, };
+export type HttpRequest = {
+ model: "http_request";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authentication: Record;
+ authenticationType: string | null;
+ body: Record;
+ bodyType: string | null;
+ description: string;
+ headers: Array;
+ method: string;
+ name: string;
+ sortPriority: number;
+ url: string;
+ /**
+ * URL parameters used for both path placeholders (`:id`) and query string entries.
+ */
+ urlParameters: Array;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+ settingValidateCertificates: InheritedBoolSetting;
+ settingFollowRedirects: InheritedBoolSetting;
+ settingRequestTimeout: InheritedIntSetting;
+};
-export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
+export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
-export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, contentLengthCompressed: number | null, elapsed: number, elapsedHeaders: number, elapsedDns: number, error: string | null, headers: Array, remoteAddr: string | null, requestContentLength: number | null, requestHeaders: Array, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
+export type HttpResponse = {
+ model: "http_response";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ bodyPath: string | null;
+ contentLength: number | null;
+ contentLengthCompressed: number | null;
+ elapsed: number;
+ elapsedHeaders: number;
+ elapsedDns: number;
+ error: string | null;
+ headers: Array;
+ remoteAddr: string | null;
+ requestContentLength: number | null;
+ requestHeaders: Array;
+ status: number;
+ statusReason: string | null;
+ state: HttpResponseState;
+ url: string;
+ version: string | null;
+};
-export type HttpResponseEvent = { model: "http_response_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, responseId: string, event: HttpResponseEventData, };
+export type HttpResponseEvent = {
+ model: "http_response_event";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ responseId: string;
+ event: HttpResponseEventData;
+};
/**
* Serializable representation of HTTP response events for DB storage.
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
* The `From` impl is in yaak-http to avoid circular dependencies.
*/
-export type HttpResponseEventData = { "type": "setting", name: string, value: string, } | { "type": "info", message: string, } | { "type": "redirect", url: string, status: number, behavior: string, dropped_body: boolean, dropped_headers: Array, } | { "type": "send_url", method: string, scheme: string, username: string, password: string, host: string, port: number, path: string, query: string, fragment: string, } | { "type": "receive_url", version: string, status: string, } | { "type": "header_up", name: string, value: string, } | { "type": "header_down", name: string, value: string, } | { "type": "chunk_sent", bytes: number, } | { "type": "chunk_received", bytes: number, } | { "type": "dns_resolved", hostname: string, addresses: Array, duration: bigint, overridden: boolean, };
+export type HttpResponseEventData =
+ | {
+ type: "setting";
+ name: string;
+ value: string;
+ source_model?: string;
+ source_id?: string;
+ source_name?: string;
+ }
+ | { type: "info"; message: string }
+ | {
+ type: "redirect";
+ url: string;
+ status: number;
+ behavior: string;
+ dropped_body: boolean;
+ dropped_headers: Array;
+ }
+ | {
+ type: "send_url";
+ method: string;
+ scheme: string;
+ username: string;
+ password: string;
+ host: string;
+ port: number;
+ path: string;
+ query: string;
+ fragment: string;
+ }
+ | { type: "receive_url"; version: string; status: string }
+ | { type: "header_up"; name: string; value: string }
+ | { type: "header_down"; name: string; value: string }
+ | { type: "chunk_sent"; bytes: number }
+ | { type: "chunk_received"; bytes: number }
+ | {
+ type: "dns_resolved";
+ hostname: string;
+ addresses: Array;
+ duration: bigint;
+ overridden: boolean;
+ };
-export type HttpResponseHeader = { name: string, value: string, };
+export type HttpResponseHeader = { name: string; value: string };
export type HttpResponseState = "initialized" | "connected" | "closed";
-export type HttpUrlParameter = { enabled?: boolean,
-/**
- * Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
- * Other entries are appended as query parameters
- */
-name: string, value: string, id?: string, };
+export type HttpUrlParameter = {
+ enabled?: boolean;
+ /**
+ * Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
+ * Other entries are appended as query parameters
+ */
+ name: string;
+ value: string;
+ id?: string;
+};
-export type KeyValue = { model: "key_value", id: string, createdAt: string, updatedAt: string, key: string, namespace: string, value: string, };
+export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
-export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt: string, checkedAt: string | null, directory: string, enabled: boolean, url: string | null, source: PluginSource, };
+export type InheritedIntSetting = { enabled?: boolean; value: number };
+
+export type KeyValue = {
+ model: "key_value";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ key: string;
+ namespace: string;
+ value: string;
+};
+
+export type Plugin = {
+ model: "plugin";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ checkedAt: string | null;
+ directory: string;
+ enabled: boolean;
+ url: string | null;
+ source: PluginSource;
+};
export type PluginSource = "bundled" | "filesystem" | "registry";
-export type ProxySetting = { "type": "enabled", http: string, https: string, auth: ProxySettingAuth | null, bypass: string, disabled: boolean, } | { "type": "disabled" };
+export type ProxySetting =
+ | {
+ type: "enabled";
+ http: string;
+ https: string;
+ auth: ProxySettingAuth | null;
+ bypass: string;
+ disabled: boolean;
+ }
+ | { type: "disabled" };
-export type ProxySettingAuth = { user: string, password: string, };
+export type ProxySettingAuth = { user: string; password: string };
-export type Settings = { model: "settings", id: string, createdAt: string, updatedAt: string, appearance: string, clientCertificates: Array, coloredMethods: boolean, editorFont: string | null, editorFontSize: number, editorKeymap: EditorKeymap, editorSoftWrap: boolean, hideWindowControls: boolean, useNativeTitlebar: boolean, interfaceFont: string | null, interfaceFontSize: number, interfaceScale: number, openWorkspaceNewWindow: boolean | null, proxy: ProxySetting | null, themeDark: string, themeLight: string, updateChannel: string, hideLicenseBadge: boolean, autoupdate: boolean, autoDownloadUpdates: boolean, checkNotifications: boolean, hotkeys: { [key in string]?: Array }, };
+export type Settings = {
+ model: "settings";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ appearance: string;
+ clientCertificates: Array;
+ coloredMethods: boolean;
+ editorFont: string | null;
+ editorFontSize: number;
+ editorKeymap: EditorKeymap;
+ editorSoftWrap: boolean;
+ hideWindowControls: boolean;
+ useNativeTitlebar: boolean;
+ interfaceFont: string | null;
+ interfaceFontSize: number;
+ interfaceScale: number;
+ openWorkspaceNewWindow: boolean | null;
+ proxy: ProxySetting | null;
+ themeDark: string;
+ themeLight: string;
+ updateChannel: string;
+ hideLicenseBadge: boolean;
+ autoupdate: boolean;
+ autoDownloadUpdates: boolean;
+ checkNotifications: boolean;
+ hotkeys: { [key in string]?: Array };
+};
-export type SyncState = { model: "sync_state", id: string, workspaceId: string, createdAt: string, updatedAt: string, flushedAt: string, modelId: string, checksum: string, relPath: string, syncDir: string, };
+export type SyncState = {
+ model: "sync_state";
+ id: string;
+ workspaceId: string;
+ createdAt: string;
+ updatedAt: string;
+ flushedAt: string;
+ modelId: string;
+ checksum: string;
+ relPath: string;
+ syncDir: string;
+};
-export type WebsocketConnection = { model: "websocket_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, headers: Array, state: WebsocketConnectionState, status: number, url: string, };
+export type WebsocketConnection = {
+ model: "websocket_connection";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ elapsed: number;
+ error: string | null;
+ headers: Array;
+ state: WebsocketConnectionState;
+ status: number;
+ url: string;
+};
export type WebsocketConnectionState = "initialized" | "connected" | "closing" | "closed";
-export type WebsocketEvent = { model: "websocket_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, isServer: boolean, message: Array, messageType: WebsocketEventType, };
+export type WebsocketEvent = {
+ model: "websocket_event";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ connectionId: string;
+ isServer: boolean;
+ message: Array;
+ messageType: WebsocketEventType;
+};
export type WebsocketEventType = "binary" | "close" | "frame" | "open" | "ping" | "pong" | "text";
-export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, description: string, headers: Array, message: string, name: string, sortPriority: number, url: string,
-/**
- * URL parameters used for both path placeholders (`:id`) and query string entries.
- */
-urlParameters: Array, };
+export type WebsocketRequest = {
+ model: "websocket_request";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authentication: Record;
+ authenticationType: string | null;
+ description: string;
+ headers: Array;
+ message: string;
+ name: string;
+ sortPriority: number;
+ url: string;
+ /**
+ * URL parameters used for both path placeholders (`:id`) and query string entries.
+ */
+ urlParameters: Array;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+};
-export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, authentication: Record, authenticationType: string | null, description: string, headers: Array, name: string, encryptionKeyChallenge: string | null, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, settingDnsOverrides: Array, };
+export type Workspace = {
+ model: "workspace";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ authentication: Record;
+ authenticationType: string | null;
+ description: string;
+ headers: Array;
+ name: string;
+ encryptionKeyChallenge: string | null;
+ settingValidateCertificates: boolean;
+ settingFollowRedirects: boolean;
+ settingRequestTimeout: number;
+ settingDnsOverrides: Array;
+ settingSendCookies: boolean;
+ settingStoreCookies: boolean;
+};
-export type WorkspaceMeta = { model: "workspace_meta", id: string, workspaceId: string, createdAt: string, updatedAt: string, encryptionKey: EncryptedKey | null, settingSyncDir: string | null, };
+export type WorkspaceMeta = {
+ model: "workspace_meta";
+ id: string;
+ workspaceId: string;
+ createdAt: string;
+ updatedAt: string;
+ encryptionKey: EncryptedKey | null;
+ settingSyncDir: string | null;
+};
diff --git a/crates/yaak/src/send.rs b/crates/yaak/src/send.rs
index f1f2a6e1..fc342571 100644
--- a/crates/yaak/src/send.rs
+++ b/crates/yaak/src/send.rs
@@ -4,7 +4,7 @@ use log::warn;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::atomic::{AtomicI32, Ordering};
-use std::time::Instant;
+use std::time::{Duration, Instant};
use thiserror::Error;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
@@ -26,6 +26,7 @@ use yaak_models::blob_manager::{BlobManager, BodyChunk};
use yaak_models::models::{
ClientCertificate, CookieJar, DnsOverride, Environment, HttpRequest, HttpResponse,
HttpResponseEvent, HttpResponseHeader, HttpResponseState, ProxySetting, ProxySettingAuth,
+ ResolvedSetting,
};
use yaak_models::query_manager::QueryManager;
use yaak_models::util::{UpdateSource, generate_prefixed_id};
@@ -343,16 +344,16 @@ pub fn resolve_http_send_runtime_config(
Ok(HttpSendRuntimeConfig {
send_options: SendableHttpRequestOptions {
- follow_redirects: resolved_settings.follow_redirects,
- timeout: if resolved_settings.request_timeout > 0 {
+ follow_redirects: resolved_settings.follow_redirects.value,
+ timeout: if resolved_settings.request_timeout.value > 0 {
Some(std::time::Duration::from_millis(
- resolved_settings.request_timeout.unsigned_abs() as u64,
+ resolved_settings.request_timeout.value.unsigned_abs() as u64,
))
} else {
None
},
},
- validate_certificates: resolved_settings.validate_certificates,
+ validate_certificates: resolved_settings.validate_certificates.value,
proxy: proxy_setting_from_settings(settings.proxy),
dns_overrides: workspace.setting_dns_overrides,
client_certificates: settings.client_certificates,
@@ -486,8 +487,8 @@ pub async fn send_http_request(
cookie_jar.as_ref().map(|jar| CookieStore::from_cookies(jar.cookies.clone()));
let cookie_behavior = CookieBehavior {
store: cookie_store,
- send_cookies: resolved_settings.send_cookies,
- store_cookies: resolved_settings.store_cookies,
+ send_cookies: resolved_settings.send_cookies.value,
+ store_cookies: resolved_settings.store_cookies.value,
};
let rendered_request = render_http_request(
@@ -614,6 +615,37 @@ pub async fn send_http_request(
let started_at = Instant::now();
let request_started_url = sendable_request.url.clone();
+ send_setting_event(
+ &event_tx,
+ "validate_certificates",
+ runtime_config.validate_certificates.to_string(),
+ &resolved_settings.validate_certificates,
+ );
+ send_setting_event(
+ &event_tx,
+ "redirects",
+ sendable_request.options.follow_redirects.to_string(),
+ &resolved_settings.follow_redirects,
+ );
+ send_setting_event(
+ &event_tx,
+ "timeout",
+ timeout_setting_value(sendable_request.options.timeout),
+ &resolved_settings.request_timeout,
+ );
+ send_setting_event(
+ &event_tx,
+ "send_cookies",
+ cookie_behavior.send_cookies.to_string(),
+ &resolved_settings.send_cookies,
+ );
+ send_setting_event(
+ &event_tx,
+ "store_cookies",
+ cookie_behavior.store_cookies.to_string(),
+ &resolved_settings.store_cookies,
+ );
+
let mut http_response =
match executor.send(sendable_request, event_tx, cookie_behavior.clone()).await {
Ok(response) => response,
@@ -958,6 +990,28 @@ fn persist_cookie_jar(
}
}
+fn send_setting_event(
+ event_tx: &mpsc::Sender,
+ name: impl Into,
+ value: impl Into,
+ setting: &ResolvedSetting,
+) {
+ let _ = event_tx.try_send(SenderHttpResponseEvent::Setting {
+ name: name.into(),
+ value: value.into(),
+ source_model: Some(setting.source_model.clone()),
+ source_id: setting.source_id.clone(),
+ source_name: setting.source_name.clone(),
+ });
+}
+
+fn timeout_setting_value(timeout: Option) -> String {
+ match timeout {
+ Some(timeout) if !timeout.is_zero() => format!("{timeout:?}"),
+ _ => "Infinity".to_string(),
+ }
+}
+
fn proxy_setting_from_settings(proxy: Option) -> HttpConnectionProxySetting {
match proxy {
None => HttpConnectionProxySetting::System,
diff --git a/packages/plugin-runtime-types/src/bindings/gen_models.ts b/packages/plugin-runtime-types/src/bindings/gen_models.ts
index 5d02b60b..c9b7bfc3 100644
--- a/packages/plugin-runtime-types/src/bindings/gen_models.ts
+++ b/packages/plugin-runtime-types/src/bindings/gen_models.ts
@@ -1,108 +1,482 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
-export type AnyModel = CookieJar | Environment | Folder | GraphQlIntrospection | GrpcConnection | GrpcEvent | GrpcRequest | HttpRequest | HttpResponse | HttpResponseEvent | KeyValue | Plugin | Settings | SyncState | WebsocketConnection | WebsocketEvent | WebsocketRequest | Workspace | WorkspaceMeta;
+export type AnyModel =
+ | CookieJar
+ | Environment
+ | Folder
+ | GraphQlIntrospection
+ | GrpcConnection
+ | GrpcEvent
+ | GrpcRequest
+ | HttpRequest
+ | HttpResponse
+ | HttpResponseEvent
+ | KeyValue
+ | Plugin
+ | Settings
+ | SyncState
+ | WebsocketConnection
+ | WebsocketEvent
+ | WebsocketRequest
+ | Workspace
+ | WorkspaceMeta;
-export type ClientCertificate = { host: string, port: number | null, crtFile: string | null, keyFile: string | null, pfxFile: string | null, passphrase: string | null, enabled?: boolean, };
+export type ClientCertificate = {
+ host: string;
+ port: number | null;
+ crtFile: string | null;
+ keyFile: string | null;
+ pfxFile: string | null;
+ passphrase: string | null;
+ enabled?: boolean;
+};
-export type Cookie = { raw_cookie: string, domain: CookieDomain, expires: CookieExpires, path: [string, boolean], };
+export type Cookie = {
+ name: string;
+ value: string;
+ domain: CookieDomain;
+ expires: CookieExpires;
+ path: string;
+ secure: boolean;
+ httpOnly: boolean;
+ sameSite: CookieSameSite | null;
+};
-export type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "NotPresent" | "Empty";
+export type CookieDomain = { HostOnly: string } | { Suffix: string } | "NotPresent" | "Empty";
-export type CookieExpires = { "AtUtc": string } | "SessionEnd";
+export type CookieExpires = { AtUtc: string } | "SessionEnd";
-export type CookieJar = { model: "cookie_jar", id: string, createdAt: string, updatedAt: string, workspaceId: string, cookies: Array, name: string, };
+export type CookieJar = {
+ model: "cookie_jar";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ cookies: Array;
+ name: string;
+};
-export type DnsOverride = { hostname: string, ipv4: Array, ipv6: Array, enabled?: boolean, };
+export type CookieSameSite = "Strict" | "Lax" | "None";
+
+export type DnsOverride = {
+ hostname: string;
+ ipv4: Array;
+ ipv6: Array;
+ enabled?: boolean;
+};
export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
-export type EncryptedKey = { encryptedKey: string, };
+export type EncryptedKey = { encryptedKey: string };
-export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null,
-/**
- * Variables defined in this environment scope.
- * Child environments override parent variables by name.
- */
-variables: Array, color: string | null, sortPriority: number, };
+export type Environment = {
+ model: "environment";
+ id: string;
+ workspaceId: string;
+ createdAt: string;
+ updatedAt: string;
+ name: string;
+ public: boolean;
+ parentModel: string;
+ parentId: string | null;
+ /**
+ * Variables defined in this environment scope.
+ * Child environments override parent variables by name.
+ */
+ variables: Array;
+ color: string | null;
+ sortPriority: number;
+};
-export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
+export type EnvironmentVariable = { enabled?: boolean; name: string; value: string; id?: string };
-export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, description: string, headers: Array, name: string, sortPriority: number, };
+export type Folder = {
+ model: "folder";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authentication: Record;
+ authenticationType: string | null;
+ description: string;
+ headers: Array;
+ name: string;
+ sortPriority: number;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+ settingValidateCertificates: InheritedBoolSetting;
+ settingFollowRedirects: InheritedBoolSetting;
+ settingRequestTimeout: InheritedIntSetting;
+};
-export type GraphQlIntrospection = { model: "graphql_introspection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, content: string | null, };
+export type GraphQlIntrospection = {
+ model: "graphql_introspection";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ content: string | null;
+};
-export type GrpcConnection = { model: "grpc_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, method: string, service: string, status: number, state: GrpcConnectionState, trailers: { [key in string]?: string }, url: string, };
+export type GrpcConnection = {
+ model: "grpc_connection";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ elapsed: number;
+ error: string | null;
+ method: string;
+ service: string;
+ status: number;
+ state: GrpcConnectionState;
+ trailers: { [key in string]?: string };
+ url: string;
+};
export type GrpcConnectionState = "initialized" | "connected" | "closed";
-export type GrpcEvent = { model: "grpc_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, content: string, error: string | null, eventType: GrpcEventType, metadata: { [key in string]?: string }, status: number | null, };
+export type GrpcEvent = {
+ model: "grpc_event";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ connectionId: string;
+ content: string;
+ error: string | null;
+ eventType: GrpcEventType;
+ metadata: { [key in string]?: string };
+ status: number | null;
+};
-export type GrpcEventType = "info" | "error" | "client_message" | "server_message" | "connection_start" | "connection_end";
+export type GrpcEventType =
+ | "info"
+ | "error"
+ | "client_message"
+ | "server_message"
+ | "connection_start"
+ | "connection_end";
-export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record, description: string, message: string, metadata: Array, method: string | null, name: string, service: string | null, sortPriority: number,
-/**
- * Server URL (http for plaintext or https for secure)
- */
-url: string, };
+export type GrpcRequest = {
+ model: "grpc_request";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authenticationType: string | null;
+ authentication: Record;
+ description: string;
+ message: string;
+ metadata: Array;
+ method: string | null;
+ name: string;
+ service: string | null;
+ sortPriority: number;
+ /**
+ * Server URL (http for plaintext or https for secure)
+ */
+ url: string;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+};
-export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, body: Record, bodyType: string | null, description: string, headers: Array, method: string, name: string, sortPriority: number, url: string,
-/**
- * URL parameters used for both path placeholders (`:id`) and query string entries.
- */
-urlParameters: Array, };
+export type HttpRequest = {
+ model: "http_request";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authentication: Record;
+ authenticationType: string | null;
+ body: Record;
+ bodyType: string | null;
+ description: string;
+ headers: Array;
+ method: string;
+ name: string;
+ sortPriority: number;
+ url: string;
+ /**
+ * URL parameters used for both path placeholders (`:id`) and query string entries.
+ */
+ urlParameters: Array;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+ settingValidateCertificates: InheritedBoolSetting;
+ settingFollowRedirects: InheritedBoolSetting;
+ settingRequestTimeout: InheritedIntSetting;
+};
-export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
+export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
-export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, contentLengthCompressed: number | null, elapsed: number, elapsedHeaders: number, elapsedDns: number, error: string | null, headers: Array, remoteAddr: string | null, requestContentLength: number | null, requestHeaders: Array, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
+export type HttpResponse = {
+ model: "http_response";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ bodyPath: string | null;
+ contentLength: number | null;
+ contentLengthCompressed: number | null;
+ elapsed: number;
+ elapsedHeaders: number;
+ elapsedDns: number;
+ error: string | null;
+ headers: Array;
+ remoteAddr: string | null;
+ requestContentLength: number | null;
+ requestHeaders: Array;
+ status: number;
+ statusReason: string | null;
+ state: HttpResponseState;
+ url: string;
+ version: string | null;
+};
-export type HttpResponseEvent = { model: "http_response_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, responseId: string, event: HttpResponseEventData, };
+export type HttpResponseEvent = {
+ model: "http_response_event";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ responseId: string;
+ event: HttpResponseEventData;
+};
/**
* Serializable representation of HTTP response events for DB storage.
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
* The `From` impl is in yaak-http to avoid circular dependencies.
*/
-export type HttpResponseEventData = { "type": "setting", name: string, value: string, } | { "type": "info", message: string, } | { "type": "redirect", url: string, status: number, behavior: string, dropped_body: boolean, dropped_headers: Array, } | { "type": "send_url", method: string, scheme: string, username: string, password: string, host: string, port: number, path: string, query: string, fragment: string, } | { "type": "receive_url", version: string, status: string, } | { "type": "header_up", name: string, value: string, } | { "type": "header_down", name: string, value: string, } | { "type": "chunk_sent", bytes: number, } | { "type": "chunk_received", bytes: number, } | { "type": "dns_resolved", hostname: string, addresses: Array, duration: bigint, overridden: boolean, };
+export type HttpResponseEventData =
+ | {
+ type: "setting";
+ name: string;
+ value: string;
+ source_model?: string;
+ source_id?: string;
+ source_name?: string;
+ }
+ | { type: "info"; message: string }
+ | {
+ type: "redirect";
+ url: string;
+ status: number;
+ behavior: string;
+ dropped_body: boolean;
+ dropped_headers: Array;
+ }
+ | {
+ type: "send_url";
+ method: string;
+ scheme: string;
+ username: string;
+ password: string;
+ host: string;
+ port: number;
+ path: string;
+ query: string;
+ fragment: string;
+ }
+ | { type: "receive_url"; version: string; status: string }
+ | { type: "header_up"; name: string; value: string }
+ | { type: "header_down"; name: string; value: string }
+ | { type: "chunk_sent"; bytes: number }
+ | { type: "chunk_received"; bytes: number }
+ | {
+ type: "dns_resolved";
+ hostname: string;
+ addresses: Array;
+ duration: bigint;
+ overridden: boolean;
+ };
-export type HttpResponseHeader = { name: string, value: string, };
+export type HttpResponseHeader = { name: string; value: string };
export type HttpResponseState = "initialized" | "connected" | "closed";
-export type HttpUrlParameter = { enabled?: boolean,
-/**
- * Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
- * Other entries are appended as query parameters
- */
-name: string, value: string, id?: string, };
+export type HttpUrlParameter = {
+ enabled?: boolean;
+ /**
+ * Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
+ * Other entries are appended as query parameters
+ */
+ name: string;
+ value: string;
+ id?: string;
+};
-export type KeyValue = { model: "key_value", id: string, createdAt: string, updatedAt: string, key: string, namespace: string, value: string, };
+export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
-export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt: string, checkedAt: string | null, directory: string, enabled: boolean, url: string | null, source: PluginSource, };
+export type InheritedIntSetting = { enabled?: boolean; value: number };
+
+export type KeyValue = {
+ model: "key_value";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ key: string;
+ namespace: string;
+ value: string;
+};
+
+export type Plugin = {
+ model: "plugin";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ checkedAt: string | null;
+ directory: string;
+ enabled: boolean;
+ url: string | null;
+ source: PluginSource;
+};
export type PluginSource = "bundled" | "filesystem" | "registry";
-export type ProxySetting = { "type": "enabled", http: string, https: string, auth: ProxySettingAuth | null, bypass: string, disabled: boolean, } | { "type": "disabled" };
+export type ProxySetting =
+ | {
+ type: "enabled";
+ http: string;
+ https: string;
+ auth: ProxySettingAuth | null;
+ bypass: string;
+ disabled: boolean;
+ }
+ | { type: "disabled" };
-export type ProxySettingAuth = { user: string, password: string, };
+export type ProxySettingAuth = { user: string; password: string };
-export type Settings = { model: "settings", id: string, createdAt: string, updatedAt: string, appearance: string, clientCertificates: Array, coloredMethods: boolean, editorFont: string | null, editorFontSize: number, editorKeymap: EditorKeymap, editorSoftWrap: boolean, hideWindowControls: boolean, useNativeTitlebar: boolean, interfaceFont: string | null, interfaceFontSize: number, interfaceScale: number, openWorkspaceNewWindow: boolean | null, proxy: ProxySetting | null, themeDark: string, themeLight: string, updateChannel: string, hideLicenseBadge: boolean, autoupdate: boolean, autoDownloadUpdates: boolean, checkNotifications: boolean, hotkeys: { [key in string]?: Array }, };
+export type Settings = {
+ model: "settings";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ appearance: string;
+ clientCertificates: Array;
+ coloredMethods: boolean;
+ editorFont: string | null;
+ editorFontSize: number;
+ editorKeymap: EditorKeymap;
+ editorSoftWrap: boolean;
+ hideWindowControls: boolean;
+ useNativeTitlebar: boolean;
+ interfaceFont: string | null;
+ interfaceFontSize: number;
+ interfaceScale: number;
+ openWorkspaceNewWindow: boolean | null;
+ proxy: ProxySetting | null;
+ themeDark: string;
+ themeLight: string;
+ updateChannel: string;
+ hideLicenseBadge: boolean;
+ autoupdate: boolean;
+ autoDownloadUpdates: boolean;
+ checkNotifications: boolean;
+ hotkeys: { [key in string]?: Array };
+};
-export type SyncState = { model: "sync_state", id: string, workspaceId: string, createdAt: string, updatedAt: string, flushedAt: string, modelId: string, checksum: string, relPath: string, syncDir: string, };
+export type SyncState = {
+ model: "sync_state";
+ id: string;
+ workspaceId: string;
+ createdAt: string;
+ updatedAt: string;
+ flushedAt: string;
+ modelId: string;
+ checksum: string;
+ relPath: string;
+ syncDir: string;
+};
-export type WebsocketConnection = { model: "websocket_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, headers: Array, state: WebsocketConnectionState, status: number, url: string, };
+export type WebsocketConnection = {
+ model: "websocket_connection";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ elapsed: number;
+ error: string | null;
+ headers: Array;
+ state: WebsocketConnectionState;
+ status: number;
+ url: string;
+};
export type WebsocketConnectionState = "initialized" | "connected" | "closing" | "closed";
-export type WebsocketEvent = { model: "websocket_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, isServer: boolean, message: Array, messageType: WebsocketEventType, };
+export type WebsocketEvent = {
+ model: "websocket_event";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ requestId: string;
+ connectionId: string;
+ isServer: boolean;
+ message: Array;
+ messageType: WebsocketEventType;
+};
export type WebsocketEventType = "binary" | "close" | "frame" | "open" | "ping" | "pong" | "text";
-export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, description: string, headers: Array, message: string, name: string, sortPriority: number, url: string,
-/**
- * URL parameters used for both path placeholders (`:id`) and query string entries.
- */
-urlParameters: Array, };
+export type WebsocketRequest = {
+ model: "websocket_request";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ workspaceId: string;
+ folderId: string | null;
+ authentication: Record;
+ authenticationType: string | null;
+ description: string;
+ headers: Array;
+ message: string;
+ name: string;
+ sortPriority: number;
+ url: string;
+ /**
+ * URL parameters used for both path placeholders (`:id`) and query string entries.
+ */
+ urlParameters: Array;
+ settingSendCookies: InheritedBoolSetting;
+ settingStoreCookies: InheritedBoolSetting;
+};
-export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, authentication: Record, authenticationType: string | null, description: string, headers: Array, name: string, encryptionKeyChallenge: string | null, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, settingDnsOverrides: Array, };
+export type Workspace = {
+ model: "workspace";
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ authentication: Record;
+ authenticationType: string | null;
+ description: string;
+ headers: Array;
+ name: string;
+ encryptionKeyChallenge: string | null;
+ settingValidateCertificates: boolean;
+ settingFollowRedirects: boolean;
+ settingRequestTimeout: number;
+ settingDnsOverrides: Array;
+ settingSendCookies: boolean;
+ settingStoreCookies: boolean;
+};
-export type WorkspaceMeta = { model: "workspace_meta", id: string, workspaceId: string, createdAt: string, updatedAt: string, encryptionKey: EncryptedKey | null, settingSyncDir: string | null, };
+export type WorkspaceMeta = {
+ model: "workspace_meta";
+ id: string;
+ workspaceId: string;
+ createdAt: string;
+ updatedAt: string;
+ encryptionKey: EncryptedKey | null;
+ settingSyncDir: string | null;
+};