Merge remote-tracking branch 'origin/master'

This commit is contained in:
Gregory Schier
2025-01-18 17:56:39 -08:00
36 changed files with 482 additions and 226 deletions

88
package-lock.json generated
View File

@@ -20,7 +20,7 @@
"src-web"
],
"devDependencies": {
"@tauri-apps/cli": "^2.2.2",
"@tauri-apps/cli": "^2.2.4",
"@typescript-eslint/eslint-plugin": "^8.18.1",
"@typescript-eslint/parser": "^8.18.1",
"eslint": "^8",
@@ -2888,9 +2888,9 @@
}
},
"node_modules/@tauri-apps/cli": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.2.2.tgz",
"integrity": "sha512-5fVEdP4t4BT0ymvXZAM78kB0S/TaiRDLDoSRWGxVy1e7XCwuKyST5m6ybeyw/h/soK/91tbf+W3xXXy7XzkT4A==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.2.4.tgz",
"integrity": "sha512-pihbuHEWJa9SEcN7JdEbMa0oq28MTTbk0nNNnRG8/irNQTKcjwM+KzxG2wuYZYbsXQVqwSu7PstdIEAnXqYHkw==",
"dev": true,
"license": "Apache-2.0 OR MIT",
"bin": {
@@ -2904,22 +2904,22 @@
"url": "https://opencollective.com/tauri"
},
"optionalDependencies": {
"@tauri-apps/cli-darwin-arm64": "2.2.2",
"@tauri-apps/cli-darwin-x64": "2.2.2",
"@tauri-apps/cli-linux-arm-gnueabihf": "2.2.2",
"@tauri-apps/cli-linux-arm64-gnu": "2.2.2",
"@tauri-apps/cli-linux-arm64-musl": "2.2.2",
"@tauri-apps/cli-linux-x64-gnu": "2.2.2",
"@tauri-apps/cli-linux-x64-musl": "2.2.2",
"@tauri-apps/cli-win32-arm64-msvc": "2.2.2",
"@tauri-apps/cli-win32-ia32-msvc": "2.2.2",
"@tauri-apps/cli-win32-x64-msvc": "2.2.2"
"@tauri-apps/cli-darwin-arm64": "2.2.4",
"@tauri-apps/cli-darwin-x64": "2.2.4",
"@tauri-apps/cli-linux-arm-gnueabihf": "2.2.4",
"@tauri-apps/cli-linux-arm64-gnu": "2.2.4",
"@tauri-apps/cli-linux-arm64-musl": "2.2.4",
"@tauri-apps/cli-linux-x64-gnu": "2.2.4",
"@tauri-apps/cli-linux-x64-musl": "2.2.4",
"@tauri-apps/cli-win32-arm64-msvc": "2.2.4",
"@tauri-apps/cli-win32-ia32-msvc": "2.2.4",
"@tauri-apps/cli-win32-x64-msvc": "2.2.4"
}
},
"node_modules/@tauri-apps/cli-darwin-arm64": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.2.2.tgz",
"integrity": "sha512-JMXbX5hGrLOzJbjisd7gBe25PmHouXA1+f4yVWg5PRlgxW7pla7krOzhu2mchFlMVDr8aLwhMLgohvvx+raXag==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.2.4.tgz",
"integrity": "sha512-+sMLkQBFebn/UENyaXpyQqRkdFQie8RdEvYVz0AGthm2p0lMVlWiBmc4ImBJmfo8569zVeDX8B+5OWt4/AuZzA==",
"cpu": [
"arm64"
],
@@ -2934,9 +2934,9 @@
}
},
"node_modules/@tauri-apps/cli-darwin-x64": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.2.2.tgz",
"integrity": "sha512-i2gxKXev+Ed0UWeq0xSiyRjSkzzBbu9MCOhs/QVv1YuV+097K/fF89f+a4v5JJftCq2IOHhSKH23KyTJBLnNKQ==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.2.4.tgz",
"integrity": "sha512-6fJvXVtQJh7H8q9sll2XC2wO5bpn7bzeh+MQxpcLq6F8SE02sFuNDLN+AqX0DQnuYV0V6jdzM2+bTYOlc1FBsw==",
"cpu": [
"x64"
],
@@ -2951,9 +2951,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.2.2.tgz",
"integrity": "sha512-iC2HndsN5smmbvEDUQFyTHyYHSgx7OwJ6puyXLLpkAHnQDo4TGSPxIlPeZFSZmEoaJEmHLdG3j1LcFWOKrxWQg==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.2.4.tgz",
"integrity": "sha512-QU6Ac6tx79iqkxsDUQesCBNq8RrVSkP9HhVzS2reKthK3xbdTCwNUXoRlfhudKMVrIxV4K7uTwUV99eAnwbm5Q==",
"cpu": [
"arm"
],
@@ -2968,9 +2968,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.2.2.tgz",
"integrity": "sha512-YzK30tleUzWxfIp1davc5RhvmNZxiZQkUnQ4zajGJZ99zxNk8kwvv8nYSC3/J2R8sYpnuv+7CzNyIwA2s6yH+w==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.2.4.tgz",
"integrity": "sha512-uZhp312s6VgJJDgUg+HuHZnhjGg93OT+q/aZMoccdZVQ6dvwH8kJzIkKt9zL1U126AXXoesb1EyYmsAruxaUKA==",
"cpu": [
"arm64"
],
@@ -2985,9 +2985,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.2.tgz",
"integrity": "sha512-nOw2apBzOCTiH1fLOjL42ajHNhMzdp640CX5RrWkDYdyVO7YbGmWzrN26PPXohScScXVjSjtDDxdeQV1gHCxhg==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.4.tgz",
"integrity": "sha512-k6JCXd9E+XU0J48nVcFr3QO//bzKg/gp8ZKagBfI2wBpHOk14CnHNBQKNs11nMQUwko4bnPeqj4llcdkbmwIbw==",
"cpu": [
"arm64"
],
@@ -3002,9 +3002,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.2.2.tgz",
"integrity": "sha512-Tmm4qVY8yxSugi8sCko1dyZxyPGK8m3tWm+b1J0DXwzxqaoMqNXuYGxkwtUdkznPXEfQSD8OGBfwjXNmVGE91Q==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.2.4.tgz",
"integrity": "sha512-bUBPU46OF1pNfM6SsGbUlkCBh/pTzvFlEdUpDISsS40v9NVt+kqCy3tHzLGB412E3lSlA6FnshB6HxkdRRdTtg==",
"cpu": [
"x64"
],
@@ -3019,9 +3019,9 @@
}
},
"node_modules/@tauri-apps/cli-linux-x64-musl": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.2.tgz",
"integrity": "sha512-AwAcaCUhmwzOFPvje80g2BAhnkoEpXdl1E0Uk+lvr9makHM0+aV++M5jibD97yxKnK5NrQ9YXPH5Sn6CdncgUg==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.4.tgz",
"integrity": "sha512-vOrpsQDiMtP8q/ZeXfXqgNi3G4Yv5LVX2vI5XkB2yvVuVF1Dvky/hcCJfi9tZQD+IpeiYxjuj7+SxHp82eQ/kA==",
"cpu": [
"x64"
],
@@ -3036,9 +3036,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.2.2.tgz",
"integrity": "sha512-u7TnwuUAN+eX6R2kDfSM8fsUFiBzNqq9PnAOsQ2qbwbHGbu7mHfGO1OFgnIzBt1C9FolFbENk2pzjiL4R9baXQ==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.2.4.tgz",
"integrity": "sha512-iEP/Cq0ts4Ln4Zh2NSC01lkYEAhr+LotbG4U2z+gxHfCdMrtYYtYdG05C2mpeIxShzL7uEIQb/lhVRBMd7robg==",
"cpu": [
"arm64"
],
@@ -3053,9 +3053,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.2.2.tgz",
"integrity": "sha512-9KScbGKU6GfHThEYWdlO0+COW/8SDfIXbYgEvEcfZztE4VedHBbI0XfU+l+aS8nJN+fvYX+DtvY0tpDwyo0G4A==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.2.4.tgz",
"integrity": "sha512-YBbqF0wyHUT00zAGZTTbEbz/C5JDGPnT1Nodor96+tzEU6qAPRYfe5eFe/rpRARbalkpw1UkcVP0Ay8gnksAiA==",
"cpu": [
"ia32"
],
@@ -3070,9 +3070,9 @@
}
},
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.2.2.tgz",
"integrity": "sha512-ko8OWCLwFaHfdBaKbRX/C5btNt61v17qKOSQPksuc5PVvY0tAoci09612nEMlYiogZKEtn7VAqSdRAG6h0tz+g==",
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.2.4.tgz",
"integrity": "sha512-MMago/SfWZbUFrwFmPCXmmbb42h7u8Y5jvLvnK2mOpOfCAsei2tLO4hx+Inoai0l2DByuYO4Ef1xDyP6shCsZQ==",
"cpu": [
"x64"
],

View File

@@ -34,7 +34,7 @@
"tauri-before-dev": "npm run --workspaces --if-present dev"
},
"devDependencies": {
"@tauri-apps/cli": "^2.2.2",
"@tauri-apps/cli": "^2.2.4",
"@typescript-eslint/eslint-plugin": "^8.18.1",
"@typescript-eslint/parser": "^8.18.1",
"eslint": "^8",

View File

@@ -1,6 +1,6 @@
{
"name": "@yaakapp/api",
"version": "0.2.27",
"version": "0.3.2",
"main": "lib/index.js",
"typings": "./lib/index.d.ts",
"files": [

View File

@@ -13,7 +13,12 @@ export type BootResponse = { name: string, version: string, capabilities: Array<
export type CallHttpAuthenticationRequest = { config: { [key in string]?: JsonValue }, method: string, url: string, headers: Array<HttpHeader>, };
export type CallHttpAuthenticationResponse = { url: string, headers: Array<HttpHeader>, };
export type CallHttpAuthenticationResponse = {
/**
* HTTP headers to add to the request. Existing headers will be replaced, while
* new headers will be added.
*/
setHeaders: Array<HttpHeader>, };
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
@@ -62,6 +67,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -76,6 +85,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -85,7 +98,15 @@ export type FormInputEditor = {
/**
* Placeholder for the text input
*/
placeholder?: string | null, language: EditorLanguage, name: string,
placeholder?: string | null,
/**
* Don't show the editor gutter (line numbers, folds, etc.)
*/
hideGutter?: boolean,
/**
* Language for syntax highlighting
*/
language?: EditorLanguage, name: string,
/**
* Whether the user must fill in the argument
*/
@@ -94,6 +115,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -116,6 +141,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -130,6 +159,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -148,6 +181,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -172,6 +209,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -217,7 +258,7 @@ cancelText?: string,
/**
* Require the user to enter a non-empty value
*/
require?: boolean, };
required?: boolean, };
export type PromptTextResponse = { value: string | null, };

View File

@@ -2,7 +2,7 @@
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
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, name: string, description: string, sortPriority: number, };

View File

@@ -1,4 +1,8 @@
import {CallHttpAuthenticationRequest, CallHttpAuthenticationResponse, GetHttpAuthenticationResponse} from '..';
import {
CallHttpAuthenticationRequest,
CallHttpAuthenticationResponse,
GetHttpAuthenticationResponse,
} from '..';
import type { Context } from './Context';
export type AuthenticationPlugin = Omit<GetHttpAuthenticationResponse, 'pluginName'> & {

175
src-tauri/Cargo.lock generated
View File

@@ -165,7 +165,7 @@ dependencies = [
"wayland-backend",
"wayland-client",
"wayland-protocols",
"zbus",
"zbus 4.0.1",
]
[[package]]
@@ -717,9 +717,9 @@ dependencies = [
[[package]]
name = "cargo_toml"
version = "0.17.2"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719"
checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472"
dependencies = [
"serde",
"toml 0.8.19",
@@ -3013,6 +3013,19 @@ dependencies = [
"memoffset",
]
[[package]]
name = "nix"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"cfg_aliases 0.2.1",
"libc",
"memoffset",
]
[[package]]
name = "nodrop"
version = "0.1.14"
@@ -3905,6 +3918,15 @@ dependencies = [
"toml_edit 0.20.2",
]
[[package]]
name = "proc-macro-crate"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit 0.22.22",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -5638,9 +5660,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.0.4"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b274ec7239ada504deb615f1c8abd7ba99631e879709e6f10e5d17217058d976"
checksum = "8e950124f6779c6cf98e3260c7a6c8488a74aa6350dd54c6950fdaa349bca2df"
dependencies = [
"anyhow",
"cargo_toml",
@@ -5796,9 +5818,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-opener"
version = "2.2.2"
version = "2.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63ac39033ef1bb4d52da4878c3d8ab6d80b0a569d69208c884e6d4d54eb427b9"
checksum = "1270bd2f3aabffc2becc05b6aafab3d24fe5679db91bec369fb44865afd7de13"
dependencies = [
"dunce",
"glob",
@@ -5813,7 +5835,7 @@ dependencies = [
"thiserror 2.0.7",
"url",
"windows",
"zbus",
"zbus 5.3.0",
]
[[package]]
@@ -5857,9 +5879,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-single-instance"
version = "2.2.0"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f36019ee9832dc99e4450bb55a21cfad8633b19c2c18bd17c7741939b070ede"
checksum = "47c387d4d96690131dc46d1d2827df5c222b896a2bfeb15a16267229a55c50b5"
dependencies = [
"serde",
"serde_json",
@@ -5867,14 +5889,14 @@ dependencies = [
"thiserror 2.0.7",
"tracing",
"windows-sys 0.59.0",
"zbus",
"zbus 5.3.0",
]
[[package]]
name = "tauri-plugin-updater"
version = "2.3.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7351014c140906bcfff59d96e04b1170c8f602557f40eb37f7de356d4e7067b"
checksum = "ce2d39224390c41ba544f02b4f1721f42256320b3fb8c371e9425cbddeb4a68c"
dependencies = [
"base64 0.22.1",
"dirs",
@@ -7676,15 +7698,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030"
dependencies = [
"async-broadcast",
"async-executor",
"async-fs",
"async-io",
"async-lock",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"derivative",
"enumflags2",
"event-listener",
@@ -7692,7 +7708,7 @@ dependencies = [
"futures-sink",
"futures-util",
"hex",
"nix",
"nix 0.27.1",
"ordered-stream",
"rand 0.8.5",
"serde",
@@ -7704,9 +7720,45 @@ dependencies = [
"uds_windows",
"windows-sys 0.52.0",
"xdg-home",
"zbus_macros",
"zbus_names",
"zvariant",
"zbus_macros 4.0.1",
"zbus_names 3.0.0",
"zvariant 4.0.0",
]
[[package]]
name = "zbus"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "192a0d989036cd60a1e91a54c9851fb9ad5bd96125d41803eed79d2e2ef74bd7"
dependencies = [
"async-broadcast",
"async-executor",
"async-fs",
"async-io",
"async-lock",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2",
"event-listener",
"futures-core",
"futures-util",
"hex",
"nix 0.29.0",
"ordered-stream",
"serde",
"serde_repr",
"static_assertions",
"tracing",
"uds_windows",
"windows-sys 0.59.0",
"winnow 0.6.20",
"xdg-home",
"zbus_macros 5.3.0",
"zbus_names 4.1.1",
"zvariant 5.2.0",
]
[[package]]
@@ -7720,7 +7772,22 @@ dependencies = [
"quote",
"regex",
"syn 1.0.109",
"zvariant_utils",
"zvariant_utils 1.1.0",
]
[[package]]
name = "zbus_macros"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3685b5c81fce630efc3e143a4ded235b107f1b1cdf186c3f115529e5e5ae4265"
dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"zbus_names 4.1.1",
"zvariant 5.2.0",
"zvariant_utils 3.1.0",
]
[[package]]
@@ -7731,7 +7798,19 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c"
dependencies = [
"serde",
"static_assertions",
"zvariant",
"zvariant 4.0.0",
]
[[package]]
name = "zbus_names"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "519629a3f80976d89c575895b05677cbc45eaf9f70d62a364d819ba646409cc8"
dependencies = [
"serde",
"static_assertions",
"winnow 0.6.20",
"zvariant 5.2.0",
]
[[package]]
@@ -7787,7 +7866,22 @@ dependencies = [
"serde",
"static_assertions",
"url",
"zvariant_derive",
"zvariant_derive 4.0.0",
]
[[package]]
name = "zvariant"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55e6b9b5f1361de2d5e7d9fd1ee5f6f7fcb6060618a1f82f3472f58f2b8d4be9"
dependencies = [
"endi",
"enumflags2",
"serde",
"static_assertions",
"winnow 0.6.20",
"zvariant_derive 5.2.0",
"zvariant_utils 3.1.0",
]
[[package]]
@@ -7800,7 +7894,20 @@ dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"zvariant_utils",
"zvariant_utils 1.1.0",
]
[[package]]
name = "zvariant_derive"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "573a8dd76961957108b10f7a45bac6ab1ea3e9b7fe01aff88325dc57bb8f5c8b"
dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"zvariant_utils 3.1.0",
]
[[package]]
@@ -7813,3 +7920,17 @@ dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "zvariant_utils"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd46446ea2a1f353bfda53e35f17633afa79f4fe290a611c94645c69fe96a50"
dependencies = [
"proc-macro2",
"quote",
"serde",
"static_assertions",
"syn 2.0.87",
"winnow 0.6.20",
]

View File

@@ -28,7 +28,7 @@ strip = true # Automatically strip symbols from the binary.
cargo-clippy = []
[build-dependencies]
tauri-build = { version = "2.0.4", features = [] }
tauri-build = { version = "2.0.5", features = [] }
[target.'cfg(target_os = "macos")'.dependencies]
objc = "0.2.7"
@@ -57,11 +57,11 @@ tauri-plugin-clipboard-manager = "2.2.0"
tauri-plugin-dialog = "2.2.0"
tauri-plugin-fs = "2.2.0"
tauri-plugin-log = { version = "2.2.0", features = ["colored"] }
tauri-plugin-opener = "2.2.2"
tauri-plugin-opener = "2.2.4"
tauri-plugin-os = "2.2.0"
tauri-plugin-shell = { workspace = true }
tauri-plugin-single-instance = "2.2.0"
tauri-plugin-updater = "2.3.0"
tauri-plugin-single-instance = "2.2.1"
tauri-plugin-updater = "2.3.1"
tauri-plugin-window-state = "2.2.0"
tokio = { version = "1.36.0", features = ["sync"] }
tokio-stream = "0.1.15"

View File

@@ -30,21 +30,24 @@ use yaak_models::queries::{
get_base_environment, get_http_response, get_or_create_settings, get_workspace,
update_response_if_id, upsert_cookie_jar, UpdateSource,
};
use yaak_plugins::events::{CallHttpAuthenticationRequest, HttpHeader, RenderPurpose, WindowContext};
use yaak_plugins::events::{
CallHttpAuthenticationRequest, HttpHeader, RenderPurpose, WindowContext,
};
use yaak_plugins::manager::PluginManager;
pub async fn send_http_request<R: Runtime>(
window: &WebviewWindow<R>,
request: &HttpRequest,
unrendered_request: &HttpRequest,
og_response: &HttpResponse,
environment: Option<Environment>,
cookie_jar: Option<CookieJar>,
cancelled_rx: &mut Receiver<bool>,
) -> Result<HttpResponse, String> {
let plugin_manager = window.state::<PluginManager>();
let workspace =
get_workspace(window, &request.workspace_id).await.expect("Failed to get Workspace");
let base_environment = get_base_environment(window, &request.workspace_id)
let workspace = get_workspace(window, &unrendered_request.workspace_id)
.await
.expect("Failed to get Workspace");
let base_environment = get_base_environment(window, &unrendered_request.workspace_id)
.await
.expect("Failed to get base environment");
let settings = get_or_create_settings(window).await;
@@ -57,10 +60,11 @@ pub async fn send_http_request<R: Runtime>(
let response_id = og_response.id.clone();
let response = Arc::new(Mutex::new(og_response.clone()));
let rendered_request =
render_http_request(&request, &base_environment, environment.as_ref(), &cb).await;
let request =
render_http_request(&unrendered_request, &base_environment, environment.as_ref(), &cb)
.await;
let mut url_string = rendered_request.url;
let mut url_string = request.url;
url_string = ensure_proto(&url_string);
if !url_string.starts_with("http://") && !url_string.starts_with("https://") {
@@ -153,7 +157,7 @@ pub async fn send_http_request<R: Runtime>(
// Render query parameters
let mut query_params = Vec::new();
for p in rendered_request.url_parameters {
for p in request.url_parameters.clone() {
if !p.enabled || p.name.is_empty() {
continue;
}
@@ -184,7 +188,7 @@ pub async fn send_http_request<R: Runtime>(
}
};
let m = Method::from_bytes(rendered_request.method.to_uppercase().as_bytes())
let m = Method::from_bytes(request.method.to_uppercase().as_bytes())
.expect("Failed to create method");
let mut request_builder = client.request(m, url).query(&query_params);
@@ -207,7 +211,7 @@ pub async fn send_http_request<R: Runtime>(
// );
// }
for h in rendered_request.headers {
for h in request.headers.clone() {
if h.name.is_empty() && h.value.is_empty() {
continue;
}
@@ -234,8 +238,8 @@ pub async fn send_http_request<R: Runtime>(
headers.insert(header_name, header_value);
}
let request_body = rendered_request.body;
if let Some(body_type) = &rendered_request.body_type {
let request_body = request.body.clone();
if let Some(body_type) = &request.body_type {
if body_type == "graphql" {
let query = get_str_h(&request_body, "query");
let variables = get_str_h(&request_body, "variables");
@@ -388,28 +392,21 @@ pub async fn send_http_request<R: Runtime>(
})
.collect(),
};
let plugin_result =
match plugin_manager.call_http_authentication(window, &auth_name, req).await {
Ok(r) => r,
Err(e) => {
return Ok(response_err(&*response.lock().await, e.to_string(), window).await);
}
};
{
let url = sendable_req.url_mut();
*url = Url::parse(&plugin_result.url).unwrap();
}
{
let headers = sendable_req.headers_mut();
for header in plugin_result.headers {
headers.insert(
HeaderName::from_str(&header.name).unwrap(),
HeaderValue::from_str(&header.value).unwrap(),
);
let auth_result = plugin_manager.call_http_authentication(window, &auth_name, req).await;
let plugin_result = match auth_result {
Ok(r) => r,
Err(e) => {
return Ok(response_err(&*response.lock().await, e.to_string(), window).await);
}
};
let headers = sendable_req.headers_mut();
for header in plugin_result.set_headers {
headers.insert(
HeaderName::from_str(&header.name).unwrap(),
HeaderValue::from_str(&header.value).unwrap(),
);
}
}
let (resp_tx, resp_rx) = oneshot::channel::<Result<Response, reqwest::Error>>();

View File

@@ -203,14 +203,15 @@ async fn cmd_grpc_go<R: Runtime>(
Some(id) => Some(get_environment(&window, id).await.map_err(|e| e.to_string())?),
None => None,
};
let req = get_grpc_request(&window, request_id)
let unrendered_request = get_grpc_request(&window, request_id)
.await
.map_err(|e| e.to_string())?
.ok_or("Failed to find GRPC request")?;
let base_environment =
get_base_environment(&window, &req.workspace_id).await.map_err(|e| e.to_string())?;
let mut req = render_grpc_request(
&req,
let base_environment = get_base_environment(&window, &unrendered_request.workspace_id)
.await
.map_err(|e| e.to_string())?;
let request = render_grpc_request(
&unrendered_request,
&base_environment,
environment.as_ref(),
&PluginTemplateCallback::new(
@@ -223,7 +224,7 @@ async fn cmd_grpc_go<R: Runtime>(
let mut metadata = BTreeMap::new();
// Add the rest of metadata
for h in req.clone().metadata {
for h in request.clone().metadata {
if h.name.is_empty() && h.value.is_empty() {
continue;
}
@@ -235,12 +236,12 @@ async fn cmd_grpc_go<R: Runtime>(
metadata.insert(h.name, h.value);
}
if let Some(auth_name) = req.authentication_type.clone() {
let auth = req.authentication.clone();
if let Some(auth_name) = request.authentication_type.clone() {
let auth = request.authentication.clone();
let plugin_req = CallHttpAuthenticationRequest {
config: serde_json::to_value(&auth).unwrap().as_object().unwrap().to_owned(),
method: "POST".to_string(),
url: req.url.clone(),
url: request.url.clone(),
headers: metadata
.iter()
.map(|(name, value)| HttpHeader {
@@ -253,15 +254,13 @@ async fn cmd_grpc_go<R: Runtime>(
.call_http_authentication(&window, &auth_name, plugin_req)
.await
.map_err(|e| e.to_string())?;
req.url = plugin_result.url;
for header in plugin_result.headers {
for header in plugin_result.set_headers {
metadata.insert(header.name, header.value);
}
}
let conn = {
let req = req.clone();
let req = request.clone();
upsert_grpc_connection(
&window,
&GrpcConnection {
@@ -282,8 +281,8 @@ async fn cmd_grpc_go<R: Runtime>(
let conn_id = conn.id.clone();
let base_msg = GrpcEvent {
workspace_id: req.clone().workspace_id,
request_id: req.clone().id,
workspace_id: request.clone().workspace_id,
request_id: request.clone().id,
connection_id: conn.clone().id,
..Default::default()
};
@@ -292,12 +291,12 @@ async fn cmd_grpc_go<R: Runtime>(
let maybe_in_msg_tx = std::sync::Mutex::new(Some(in_msg_tx.clone()));
let (cancelled_tx, mut cancelled_rx) = tokio::sync::watch::channel(false);
let uri = safe_uri(&req.url);
let uri = safe_uri(&request.url);
let in_msg_stream = tokio_stream::wrappers::ReceiverStream::new(in_msg_rx);
let (service, method) = {
let req = req.clone();
let req = request.clone();
match (req.service, req.method) {
(Some(service), Some(method)) => (service, method),
_ => return Err("Service and method are required".to_string()),
@@ -309,7 +308,7 @@ async fn cmd_grpc_go<R: Runtime>(
.lock()
.await
.connect(
&req.clone().id,
&request.clone().id,
uri.as_str(),
&proto_files.iter().map(|p| PathBuf::from_str(p).unwrap()).collect(),
)
@@ -440,7 +439,7 @@ async fn cmd_grpc_go<R: Runtime>(
let grpc_listen = {
let window = window.clone();
let base_event = base_msg.clone();
let req = req.clone();
let req = request.clone();
let msg = if req.message.is_empty() { "{}".to_string() } else { req.message };
let msg = render_template(
msg.as_str(),

View File

@@ -42,13 +42,8 @@ var plugin = {
}],
async onApply(_ctx, args) {
const { username, password } = args.config;
return {
url: args.url,
headers: [{
name: "Authorization",
value: "Basic " + Buffer.from(`${username}:${password}`).toString("base64")
}]
};
const value = "Basic " + Buffer.from(`${username}:${password}`).toString("base64");
return { setHeaders: [{ name: "Authorization", value }] };
}
}
};

View File

@@ -37,13 +37,8 @@ var plugin = {
}],
async onApply(_ctx, args) {
const { token } = args.config;
return {
url: args.url,
headers: [{
name: "Authorization",
value: `Bearer ${token}`.trim()
}]
};
const value = `Bearer ${token}`.trim();
return { setHeaders: [{ name: "Authorization", value }] };
}
}
};

View File

@@ -3844,10 +3844,8 @@ var plugin = {
const { algorithm, secret: _secret, secretBase64, payload } = args.config;
const secret = secretBase64 ? Buffer.from(`${_secret}`, "base64") : `${_secret}`;
const token = import_jsonwebtoken.default.sign(`${payload}`, secret, { algorithm });
return {
url: args.url,
headers: [{ name: "Authorization", value: `Bearer ${token}` }]
};
const value = `Bearer ${token}`;
return { setHeaders: [{ name: "Authorization", value }] };
}
}
};

View File

@@ -8824,8 +8824,8 @@ var behaviorArg = {
label: "Sending Behavior",
defaultValue: "smart",
options: [
{ label: "When no responses", value: "smart" },
{ label: "Always", value: "always" }
{ name: "When no responses", value: "smart" },
{ name: "Always", value: "always" }
]
};
var requestArg = {

View File

@@ -14,7 +14,7 @@ export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
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, name: string, description: string, sortPriority: number, };

View File

@@ -383,7 +383,8 @@ pub struct EnvironmentVariable {
pub enabled: bool,
pub name: String,
pub value: String,
pub id: String,
#[ts(optional, as = "Option<String>")]
pub id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]

View File

@@ -13,7 +13,12 @@ export type BootResponse = { name: string, version: string, capabilities: Array<
export type CallHttpAuthenticationRequest = { config: { [key in string]?: JsonValue }, method: string, url: string, headers: Array<HttpHeader>, };
export type CallHttpAuthenticationResponse = { url: string, headers: Array<HttpHeader>, };
export type CallHttpAuthenticationResponse = {
/**
* HTTP headers to add to the request. Existing headers will be replaced, while
* new headers will be added.
*/
setHeaders: Array<HttpHeader>, };
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
@@ -62,6 +67,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -76,6 +85,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -85,7 +98,15 @@ export type FormInputEditor = {
/**
* Placeholder for the text input
*/
placeholder?: string | null, language: EditorLanguage, name: string,
placeholder?: string | null,
/**
* Don't show the editor gutter (line numbers, folds, etc.)
*/
hideGutter?: boolean,
/**
* Language for syntax highlighting
*/
language?: EditorLanguage, name: string,
/**
* Whether the user must fill in the argument
*/
@@ -94,6 +115,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -116,6 +141,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -130,6 +159,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -148,6 +181,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -172,6 +209,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -217,7 +258,7 @@ cancelText?: string,
/**
* Require the user to enter a non-empty value
*/
require?: boolean, };
required?: boolean, };
export type PromptTextResponse = { value: string | null, };

View File

@@ -2,7 +2,7 @@
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
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, name: string, description: string, sortPriority: number, };

View File

@@ -248,7 +248,7 @@ pub struct PromptTextRequest {
pub cancel_text: Option<String>,
/// Require the user to enter a non-empty value
#[ts(optional)]
pub require: Option<bool>,
pub required: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
@@ -303,6 +303,14 @@ pub struct GetHttpAuthenticationResponse {
pub config: Vec<FormInput>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct HttpHeader {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
@@ -313,20 +321,13 @@ pub struct CallHttpAuthenticationRequest {
pub headers: Vec<HttpHeader>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct HttpHeader {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "events.ts")]
pub struct CallHttpAuthenticationResponse {
pub url: String,
pub headers: Vec<HttpHeader>,
/// HTTP headers to add to the request. Existing headers will be replaced, while
/// new headers will be added.
pub set_headers: Vec<HttpHeader>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
@@ -378,6 +379,10 @@ pub struct FormInputBase {
#[ts(optional)]
pub label: Option<String>,
/// Visually hide the label of the input
#[ts(optional)]
pub hide_label: Option<bool>,
/// The default value
#[ts(optional)]
pub default_value: Option<String>,
@@ -429,7 +434,13 @@ pub struct FormInputEditor {
#[ts(optional = nullable)]
pub placeholder: Option<String>,
pub language: EditorLanguage,
/// Don't show the editor gutter (line numbers, folds, etc.)
#[ts(optional)]
pub hide_gutter: Option<bool>,
/// Language for syntax highlighting
#[ts(optional)]
pub language: Option<EditorLanguage>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]

View File

@@ -2,7 +2,7 @@
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
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, name: string, description: string, sortPriority: number, };

View File

@@ -30,6 +30,7 @@ export const createFolder = createFastMutation<
label: 'Name',
defaultValue: 'Folder',
title: 'New Folder',
required: true,
confirmText: 'Create',
placeholder: 'Name',
});

View File

@@ -41,7 +41,7 @@ export function CreateWorkspaceDialog({ hide }: Props) {
hide();
}}
>
<PlainInput require label="Name" defaultValue={name} onChange={setName} />
<PlainInput required label="Name" defaultValue={name} onChange={setName} />
<SyncToFilesystemSetting
onChange={setSettingSyncDir}

View File

@@ -13,6 +13,7 @@ import { useCallback } from 'react';
import { useActiveRequest } from '../hooks/useActiveRequest';
import { useFolders } from '../hooks/useFolders';
import { useHttpRequests } from '../hooks/useHttpRequests';
import { capitalize } from '../lib/capitalize';
import { fallbackRequestName } from '../lib/fallbackRequestName';
import { Checkbox } from './core/Checkbox';
import { Editor } from './core/Editor/Editor';
@@ -30,23 +31,25 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
data,
onChange,
useTemplating,
autocompleteVariables,
stateKey,
}: {
config: FormInput[];
onChange: (value: T) => void;
data: T;
useTemplating?: boolean;
autocompleteVariables?: boolean;
stateKey: string;
}) {
const setDataAttr = useCallback(
(name: string, value: string | boolean | null) => {
onChange({ ...data, [name]: value == null ? '__NULL__' : value });
onChange({ ...data, [name]: value == DYNAMIC_FORM_NULL_ARG ? undefined : value });
},
[data, onChange],
);
return (
<VStack space={3}>
<VStack space={3} className="h-full overflow-auto">
{config.map((a, i) => {
switch (a.type) {
case 'select':
@@ -55,7 +58,9 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
key={i + stateKey}
arg={a}
onChange={(v) => setDataAttr(a.name, v)}
value={data[a.name] ? String(data[a.name]) : DYNAMIC_FORM_NULL_ARG}
value={
data[a.name] ? String(data[a.name]) : (a.defaultValue ?? DYNAMIC_FORM_NULL_ARG)
}
/>
);
case 'text':
@@ -65,8 +70,9 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
stateKey={stateKey}
arg={a}
useTemplating={useTemplating || false}
autocompleteVariables={autocompleteVariables || false}
onChange={(v) => setDataAttr(a.name, v)}
value={data[a.name] ? String(data[a.name]) : ''}
value={data[a.name] ? String(data[a.name]) : (a.defaultValue ?? '')}
/>
);
case 'editor':
@@ -76,8 +82,9 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
stateKey={stateKey}
arg={a}
useTemplating={useTemplating || false}
autocompleteVariables={autocompleteVariables || false}
onChange={(v) => setDataAttr(a.name, v)}
value={data[a.name] ? String(data[a.name]) : ''}
value={data[a.name] ? String(data[a.name]) : (a.defaultValue ?? '')}
/>
);
case 'checkbox':
@@ -95,7 +102,7 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
key={i + stateKey}
arg={a}
onChange={(v) => setDataAttr(a.name, v)}
value={data[a.name] ? String(data[a.name]) : '__ERROR__'}
value={data[a.name] ? String(data[a.name]) : DYNAMIC_FORM_NULL_ARG}
/>
);
case 'file':
@@ -104,7 +111,7 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
key={i + stateKey}
arg={a}
onChange={(v) => setDataAttr(a.name, v)}
filePath={data[a.name] ? String(data[a.name]) : '__ERROR__'}
filePath={data[a.name] ? String(data[a.name]) : DYNAMIC_FORM_NULL_ARG}
/>
);
}
@@ -118,12 +125,14 @@ function TextArg({
onChange,
value,
useTemplating,
autocompleteVariables,
stateKey,
}: {
arg: FormInputText;
value: string;
onChange: (v: string) => void;
useTemplating: boolean;
autocompleteVariables: boolean;
stateKey: string;
}) {
const handleChange = useCallback(
@@ -137,18 +146,14 @@ function TextArg({
<Input
name={arg.name}
onChange={handleChange}
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? '' : value}
require={!arg.optional}
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? arg.defaultValue : value}
required={!arg.optional}
type={arg.password ? 'password' : 'text'}
label={
<>
{arg.label ?? arg.name}
{arg.optional && <span className="text-xs text-text-subtlest"> (optional)</span>}
</>
}
label={arg.label ?? arg.name}
hideLabel={arg.label == null}
placeholder={arg.placeholder ?? arg.defaultValue ?? ''}
useTemplating={useTemplating}
autocompleteVariables={autocompleteVariables}
stateKey={stateKey}
forceUpdateKey={stateKey}
/>
@@ -160,12 +165,14 @@ function EditorArg({
onChange,
value,
useTemplating,
autocompleteVariables,
stateKey,
}: {
arg: FormInputEditor;
value: string;
onChange: (v: string) => void;
useTemplating: boolean;
autocompleteVariables: boolean;
stateKey: string;
}) {
const handleChange = useCallback(
@@ -178,22 +185,32 @@ function EditorArg({
const id = `input-${arg.name}`;
return (
<div className="w-full grid grid-rows-[auto_minmax(0,1fr)]">
<Label htmlFor={id}>{arg.label}</Label>
<div className=" w-full grid grid-cols-1 grid-rows-[auto_minmax(0,1fr)]">
<Label
htmlFor={id}
optional={arg.optional}
visuallyHidden={arg.hideLabel}
otherTags={arg.language ? [capitalize(arg.language)] : undefined}
>
{arg.label}
</Label>
<Editor
id={id}
className={classNames(
'border border-border rounded-md overflow-hidden px-2 py-1.5',
'focus-within:border-border-focus',
'max-h-[15rem]', // So it doesn't take up too much space
)}
language={arg.language}
onChange={handleChange}
heightMode="auto"
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? '' : value}
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? arg.defaultValue : value}
placeholder={arg.placeholder ?? arg.defaultValue ?? ''}
useTemplating={useTemplating}
autocompleteVariables={autocompleteVariables}
stateKey={stateKey}
forceUpdateKey={stateKey}
hideGutter
/>
</div>
);
@@ -213,11 +230,12 @@ function SelectArg({
label={arg.label ?? arg.name}
name={arg.name}
onChange={onChange}
hideLabel={arg.hideLabel}
value={value}
options={[
...arg.options.map((a) => ({
label: a.name,
value: a.value === arg.defaultValue ? DYNAMIC_FORM_NULL_ARG : a.value,
value: a.value,
})),
]}
/>

View File

@@ -39,6 +39,8 @@ export function HttpAuthenticationEditor({ request }: Props) {
return (
<DynamicForm
autocompleteVariables
useTemplating
stateKey={`auth.${request.id}.${request.authenticationType}`}
config={auth.config}
data={request.authentication}

View File

@@ -97,6 +97,7 @@ export function SettingsGeneral() {
</Heading>
<VStack className="mt-1 w-full" space={3}>
<PlainInput
required
size="sm"
name="requestTimeout"
label="Request Timeout (ms)"

View File

@@ -68,7 +68,7 @@ export function SettingsProxy() {
}}
/>
</HStack>
<Separator className="my-6"/>
<Separator className="my-6" />
<Checkbox
checked={settings.proxy.auth != null}
title="Enable authentication"
@@ -83,6 +83,7 @@ export function SettingsProxy() {
{settings.proxy.auth != null && (
<HStack space={1.5}>
<PlainInput
required
size="sm"
label="User"
placeholder="myUser"

View File

@@ -30,8 +30,8 @@ export function TemplateFunctionDialog({ templateFunction, hide, initialTokens,
initialArg?.value.type === 'str'
? initialArg?.value.text
: // TODO: Implement variable-based args
'__NULL__';
initial[arg.name] = initialArgValue ?? DYNAMIC_FORM_NULL_ARG;
undefined;
initial[arg.name] = initialArgValue ?? arg.defaultValue ?? DYNAMIC_FORM_NULL_ARG;
}
return initial;

View File

@@ -41,6 +41,7 @@ export function WorkspaceSettingsDialog({ workspaceId, hide }: Props) {
return (
<VStack space={3} alignItems="start" className="pb-3 h-full">
<Input
required
label="Name"
defaultValue={workspace.name}
onChange={(name) => upsertWorkspace.mutate({ ...workspace, name })}

View File

@@ -51,7 +51,7 @@ export interface EditorProps {
type?: 'text' | 'password';
className?: string;
heightMode?: 'auto' | 'full';
language?: EditorLanguage | 'pairs';
language?: EditorLanguage | 'pairs' | 'url';
forceUpdateKey?: string | number;
autoFocus?: boolean;
autoSelect?: boolean;

View File

@@ -6,7 +6,7 @@ export function InlineCode({ className, ...props }: HTMLAttributes<HTMLSpanEleme
<code
className={classNames(
className,
'font-mono text-shrink bg-surface-highlight border border-border-subtle',
'font-mono text-shrink bg-surface-highlight border border-border-subtle flex-grow-0',
'px-1.5 py-0.5 rounded text shadow-inner break-words',
)}
{...props}

View File

@@ -42,8 +42,9 @@ export type InputProps = Pick<
className?: string;
placeholder?: string;
validate?: boolean | ((v: string) => boolean);
require?: boolean;
required?: boolean;
wrapLines?: boolean;
multiLine?: boolean;
stateKey: EditorProps['stateKey'];
};
@@ -65,7 +66,7 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
onPaste,
onPasteOverwrite,
placeholder,
require,
required,
rightSlot,
wrapLines,
size = 'md',
@@ -73,6 +74,7 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
validate,
readOnly,
stateKey,
multiLine,
...props
}: InputProps,
ref,
@@ -102,11 +104,11 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
);
const isValid = useMemo(() => {
if (require && !validateRequire(currentValue)) return false;
if (required && !validateRequire(currentValue)) return false;
if (typeof validate === 'boolean') return validate;
if (typeof validate === 'function' && !validate(currentValue)) return false;
return true;
}, [require, currentValue, validate]);
}, [required, currentValue, validate]);
const handleChange = useCallback(
(value: string) => {
@@ -141,7 +143,12 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
labelPosition === 'top' && 'flex-row gap-0.5',
)}
>
<Label htmlFor={id.current} className={classNames(labelClassName, hideLabel && 'sr-only')}>
<Label
htmlFor={id.current}
optional={!required}
visuallyHidden={hideLabel}
className={classNames(labelClassName)}
>
{label}
</Label>
<HStack
@@ -170,9 +177,11 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
<Editor
ref={editorRef}
id={id.current}
singleLine
hideGutter
singleLine={!multiLine}
stateKey={stateKey}
wrapLines={wrapLines}
heightMode="auto"
onKeyDown={handleKeyDown}
type={type === 'password' && !obscured ? 'text' : type}
defaultValue={defaultValue}
@@ -181,7 +190,7 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
onChange={handleChange}
onPaste={onPaste}
onPasteOverwrite={onPasteOverwrite}
className={editorClassName}
className={classNames(editorClassName, multiLine && 'py-1.5')}
onFocus={handleFocus}
onBlur={handleBlur}
readOnly={readOnly}

View File

@@ -4,13 +4,35 @@ import type { HTMLAttributes } from 'react';
export function Label({
htmlFor,
className,
optional,
children,
visuallyHidden,
otherTags = [],
...props
}: HTMLAttributes<HTMLLabelElement> & { htmlFor: string }) {
}: HTMLAttributes<HTMLLabelElement> & {
htmlFor: string;
optional?: boolean;
otherTags?: string[];
visuallyHidden?: boolean;
}) {
const tags = optional ? ['optional', ...otherTags] : otherTags;
return (
<label
className={classNames(className, 'text-text-subtle whitespace-nowrap')}
className={classNames(
className,
visuallyHidden && 'sr-only',
'flex-shrink-0',
'text-text-subtle whitespace-nowrap flex items-center gap-1',
)}
htmlFor={htmlFor}
{...props}
/>
>
{children}
{tags.map((tag, i) => (
<span key={i} className="text-xs text-text-subtlest">
({tag})
</span>
))}
</label>
);
}

View File

@@ -466,7 +466,7 @@ function PairEditorRow({
wrapLines={false}
readOnly={pair.readOnlyName}
size="sm"
require={!isLast && !!pair.enabled && !!pair.value}
required={!isLast && !!pair.enabled && !!pair.value}
validate={nameValidate}
forceUpdateKey={forceUpdateKey}
containerClassName={classNames(isLast && 'border-dashed')}
@@ -577,7 +577,6 @@ function FileActionsDropdown({
onSelect: async () => {
const contentType = await showPrompt({
id: 'content-type',
require: false,
title: 'Override Content-Type',
label: 'Content-Type',
placeholder: 'text/plain',

View File

@@ -29,7 +29,7 @@ export function PlainInput({
onChange,
onFocus,
onPaste,
require,
required,
rightSlot,
size = 'md',
type = 'text',
@@ -72,11 +72,11 @@ export function PlainInput({
);
const isValid = useMemo(() => {
if (require && !validateRequire(currentValue)) return false;
if (required && !validateRequire(currentValue)) return false;
if (typeof validate === 'boolean') return validate;
if (typeof validate === 'function' && !validate(currentValue)) return false;
return true;
}, [require, currentValue, validate]);
}, [required, currentValue, validate]);
const handleChange = useCallback(
(value: string) => {
@@ -98,7 +98,12 @@ export function PlainInput({
labelPosition === 'top' && 'flex-row gap-0.5',
)}
>
<Label htmlFor={id} className={classNames(labelClassName, 'flex-shrink-0', hideLabel && 'sr-only')}>
<Label
htmlFor={id}
className={labelClassName}
visuallyHidden={hideLabel}
optional={!required}
>
{label}
</Label>
<HStack
@@ -137,7 +142,7 @@ export function PlainInput({
className={classNames(commonClassName, 'h-auto')}
onFocus={handleFocus}
onBlur={handleBlur}
required={require}
required={required}
autoFocus={autoFocus}
placeholder={placeholder}
onKeyDownCapture={onKeyDownCapture}

View File

@@ -17,7 +17,7 @@ export function Prompt({
defaultValue,
placeholder,
onResult,
require,
required,
confirmText,
cancelText,
}: PromptProps) {
@@ -38,7 +38,7 @@ export function Prompt({
<Input
hideLabel
autoSelect
require={require}
required={required}
placeholder={placeholder ?? 'Enter text'}
label={label}
defaultValue={defaultValue}

View File

@@ -5,6 +5,7 @@ import { useOsInfo } from '../../hooks/useOsInfo';
import { trackEvent } from '../../lib/analytics';
import type { ButtonProps } from './Button';
import { Button } from './Button';
import { Label } from './Label';
import type { RadioDropdownItem } from './RadioDropdown';
import { RadioDropdown } from './RadioDropdown';
import { HStack } from './Stacks';
@@ -61,16 +62,9 @@ export function Select<T extends string>({
labelPosition === 'top' && 'flex-row gap-0.5',
)}
>
<label
htmlFor={id}
className={classNames(
labelClassName,
'text-text-subtle whitespace-nowrap',
hideLabel && 'sr-only',
)}
>
<Label htmlFor={id} visuallyHidden={hideLabel} className={labelClassName}>
{label}
</label>
</Label>
{osInfo?.osType === 'macos' ? (
<HStack
space={2}