diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json
new file mode 100644
index 000000000..05a4d8b7a
--- /dev/null
+++ b/.agents/plugins/marketplace.json
@@ -0,0 +1,20 @@
+{
+ "name": "yaak",
+ "interface": {
+ "displayName": "Yaak"
+ },
+ "plugins": [
+ {
+ "name": "yaak",
+ "source": {
+ "source": "local",
+ "path": "./crates-cli/yaak-cli"
+ },
+ "policy": {
+ "installation": "AVAILABLE",
+ "authentication": "ON_INSTALL"
+ },
+ "category": "Developer Tools"
+ }
+ ]
+}
diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
new file mode 100644
index 000000000..bb30151f3
--- /dev/null
+++ b/.claude-plugin/marketplace.json
@@ -0,0 +1,18 @@
+{
+ "$schema": "https://json.schemastore.org/claude-code-marketplace.json",
+ "name": "yaak",
+ "description": "Plugins for Yaak, the desktop API client",
+ "owner": {
+ "name": "Yaak",
+ "url": "https://yaak.app"
+ },
+ "plugins": [
+ {
+ "name": "yaak",
+ "source": "./crates-cli/yaak-cli",
+ "description": "Build, save, and send API requests with the yaak CLI, with its MCP server for agents",
+ "category": "development",
+ "tags": ["api", "http", "rest", "graphql", "grpc", "openapi", "api-client"]
+ }
+ ]
+}
diff --git a/.gitattributes b/.gitattributes
index 67ab542ce..fdb3c5687 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5,3 +5,4 @@ crates/yaak-templates/pkg/* linguist-generated=true
# Ensure consistent line endings for test files that check exact content
crates/yaak-http/tests/test.txt text eol=lf
+crates-proxy/yaak-proxy-lib/tests/fixtures/export.har text eol=lf
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..0a86c6a74
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,55 @@
+version: 2
+
+updates:
+ - package-ecosystem: npm
+ directory: /
+ schedule:
+ interval: weekly
+ day: monday
+ open-pull-requests-limit: 5
+ ignore:
+ # Build tooling majors are opted into, not queued. These never reach a
+ # user, so the cost of being a release behind is low and the cost of a
+ # surprise is a broken build. Note this also suppresses security PRs for
+ # these, so Dependabot alerts are the backstop.
+ - dependency-name: typescript
+ update-types: ["version-update:semver-major"]
+ - dependency-name: vitest
+ update-types: ["version-update:semver-major"]
+ - dependency-name: "@types/*"
+ update-types: ["version-update:semver-major"]
+ - dependency-name: "vite-plugin-*"
+ update-types: ["version-update:semver-major"]
+ # 0.8 dropped stateExtensions and updateSchema from the package root and
+ # exposes no subpath to reach them, which GrpcEditor needs. Unpin once
+ # that editor moves to the jsonSchema helper.
+ - dependency-name: codemirror-json-schema
+ groups:
+ npm-production:
+ dependency-type: production
+ update-types:
+ - minor
+ - patch
+ npm-development:
+ dependency-type: development
+ update-types:
+ - minor
+ - patch
+
+ - package-ecosystem: cargo
+ directory: /
+ schedule:
+ interval: weekly
+ day: monday
+ open-pull-requests-limit: 5
+ ignore:
+ # Held at 11.10.0 to pin what rolldown_resolver ("^11") resolves to; it
+ # does not build against 11.11. See crates-cli/yaak-cli/Cargo.toml.
+ - dependency-name: oxc_resolver
+ groups:
+ cargo:
+ patterns:
+ - "*"
+ update-types:
+ - minor
+ - patch
diff --git a/.github/scripts/preserve-release-artifacts.mjs b/.github/scripts/preserve-release-artifacts.mjs
new file mode 100644
index 000000000..e64cfe911
--- /dev/null
+++ b/.github/scripts/preserve-release-artifacts.mjs
@@ -0,0 +1,79 @@
+// Retain only distributable bundle files, never the target tree or signing material.
+import { createHash } from "node:crypto";
+import {
+ copyFileSync,
+ createReadStream,
+ existsSync,
+ mkdirSync,
+ readdirSync,
+ writeFileSync,
+} from "node:fs";
+import { join, relative } from "node:path";
+
+const env = process.env;
+const bundle = join("target", env.RELEASE_TARGET || "", "release", "bundle");
+const destination = join(env.RUNNER_TEMP, "yaak-release-artifacts");
+const extensions =
+ /\.(dmg|deb|rpm|AppImage|exe|msi|app\.tar\.gz|AppImage\.tar\.gz|nsis\.zip|msi\.zip)(\.sig)?$/;
+const files = [];
+
+function snapshot(directory) {
+ if (!existsSync(directory)) return;
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
+ const source = join(directory, entry.name);
+ // Only descend through the bundler's immediate output folders. This excludes
+ // .app trees and the extracted CEF deb contents (which contain executables).
+ if (entry.isDirectory() && directory === bundle) {
+ snapshot(source);
+ } else if (
+ entry.isFile() &&
+ (extensions.test(entry.name) || /^yaak-cef_.*_linux_.*\.tar\.gz$/.test(entry.name))
+ ) {
+ // Match tauri-action's default macOS updater asset naming exactly.
+ const arch = env.RELEASE_ARCH === "arm64" ? "aarch64" : "x64";
+ const assetName = entry.name.replace(/\.app\.tar\.gz(\.sig)?$/, `_${arch}.app.tar.gz$1`);
+ mkdirSync(destination, { recursive: true });
+ const retained = join(destination, assetName);
+ // The second snapshot must not overwrite the original user installer/signature.
+ if (!existsSync(retained)) copyFileSync(source, retained);
+ files.push({ source: relative(".", source), assetName });
+ }
+ }
+}
+
+snapshot(bundle);
+if (existsSync(destination)) {
+ const assets = readdirSync(destination)
+ .filter((name) => name !== "provenance.json")
+ .sort();
+ const checksums = [];
+ for (const assetName of assets) {
+ const hash = createHash("sha256");
+ for await (const chunk of createReadStream(join(destination, assetName))) hash.update(chunk);
+ checksums.push({ assetName, sha256: hash.digest("hex") });
+ }
+ writeFileSync(
+ join(destination, "provenance.json"),
+ JSON.stringify(
+ {
+ repository: env.GITHUB_REPOSITORY,
+ tag: env.GITHUB_REF_NAME,
+ sha: env.GITHUB_SHA,
+ runId: env.GITHUB_RUN_ID,
+ runAttempt: env.GITHUB_RUN_ATTEMPT,
+ workflowRef: env.GITHUB_WORKFLOW_REF,
+ workflowSha: env.GITHUB_WORKFLOW_SHA,
+ tauriAction: "tauri-apps/tauri-action@v0",
+ platform: env.RELEASE_PLATFORM,
+ runtime: env.RELEASE_RUNTIME,
+ arch: env.RELEASE_ARCH,
+ target: env.RELEASE_TARGET,
+ args: env.RELEASE_ARGS,
+ assets: checksums,
+ },
+ null,
+ 2,
+ ) + "\n",
+ );
+}
+console.log(`Found ${files.length} distributable bundle files in ${bundle}`);
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dd4f90825..3a0684b13 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,3 +35,29 @@ jobs:
run: |
cargo build -p yaak-cli
node plugins/importer-openapi/tests/roundtrip.mjs
+
+ test-windows:
+ name: Rust Tests (Windows)
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: voidzero-dev/setup-vp@v1
+ with:
+ node-version: "24"
+ cache: true
+ - uses: dtolnay/rust-toolchain@stable
+ - uses: Swatinem/rust-cache@v2
+ with:
+ shared-key: ci
+ cache-on-failure: true
+ - name: Install Protoc for plugin-runtime
+ uses: arduino/setup-protoc@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - run: vp install
+ - run: npm run bootstrap
+ env:
+ YAAK_TARGET_ARCH: x64
+ - name: Run Rust Tests
+ run: cargo test --all --exclude yaak-cli --features yaak-app-client/wry
diff --git a/.github/workflows/release-app.yml b/.github/workflows/release-app.yml
index 6c5195947..a9bb6c42d 100644
--- a/.github/workflows/release-app.yml
+++ b/.github/workflows/release-app.yml
@@ -70,7 +70,7 @@ jobs:
runtime: "wry"
targets: "aarch64-pc-windows-msvc"
runs-on: ${{ matrix.platform }}
- timeout-minutes: 60
+ timeout-minutes: 360
steps:
- name: Checkout yaakapp/app
uses: actions/checkout@v4
@@ -172,7 +172,8 @@ jobs:
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/protoc/yaakprotoc || true
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/node/yaaknode || true
- - uses: tauri-apps/tauri-action@v0
+ - name: Build and upload Tauri bundles
+ uses: tauri-apps/tauri-action@v0
env:
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
@@ -194,6 +195,8 @@ jobs:
AZURE_CLIENT_SECRET: ${{ matrix.os == 'windows' && secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ matrix.os == 'windows' && secrets.AZURE_TENANT_ID }}
with:
+ # Also retries builds; upload retries alone cannot clean up starter assets.
+ retryAttempts: 3
tauriScript: "node ../../node_modules/@tauri-apps/cli/tauri.js"
tagName: "v__VERSION__"
releaseName: "Release __VERSION__"
@@ -203,6 +206,17 @@ jobs:
projectPath: ./crates-tauri/yaak-app-client
args: "${{ matrix.args }}"
+ # Snapshot before the per-machine build overwrites the regular NSIS bundle/signature.
+ - name: Snapshot Tauri bundles
+ if: ${{ !cancelled() }}
+ run: node .github/scripts/preserve-release-artifacts.mjs
+ env:
+ RELEASE_TARGET: ${{ matrix.targets }}
+ RELEASE_PLATFORM: ${{ matrix.platform }}
+ RELEASE_RUNTIME: ${{ matrix.runtime }}
+ RELEASE_ARCH: ${{ matrix.yaak_arch }}
+ RELEASE_ARGS: ${{ matrix.args }}
+
- name: Build and upload CEF tarball from deb (Linux only)
if: matrix.os == 'ubuntu' && matrix.runtime == 'cef'
env:
@@ -217,7 +231,13 @@ jobs:
mkdir -p "$extract_dir"
dpkg-deb -x "$deb" "$extract_dir"
tar -C "$extract_dir" -czf "$tarball" .
- gh release upload "${{ github.ref_name }}" "$tarball" --clobber
+ for attempt in 1 2 3 4; do
+ if gh release upload "$GITHUB_REF_NAME" "$tarball" --clobber; then
+ break
+ fi
+ if [ "$attempt" -eq 4 ]; then exit 1; fi
+ sleep 10
+ done
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
- name: Build and upload machine-wide installer (Windows only)
@@ -235,6 +255,7 @@ jobs:
Get-ChildItem -Recurse -Path target -File -Filter "*.exe.sig" | Remove-Item -Force
Push-Location crates-tauri/yaak-app-client
npx tauri bundle ${{ matrix.args }} --bundles nsis --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}'
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Pop-Location
$setup = Get-ChildItem -Recurse -Path target -Filter "*setup*.exe" | Select-Object -First 1
$setupSig = "$($setup.FullName).sig"
@@ -242,5 +263,30 @@ jobs:
$destSig = "$dest.sig"
Copy-Item $setup.FullName $dest
Copy-Item $setupSig $destSig
- gh release upload "${{ github.ref_name }}" "$dest" --clobber
- gh release upload "${{ github.ref_name }}" "$destSig" --clobber
+ foreach ($asset in @($dest, $destSig)) {
+ for ($attempt = 1; $attempt -le 4; $attempt++) {
+ gh release upload "$env:GITHUB_REF_NAME" "$asset" --clobber
+ if ($LASTEXITCODE -eq 0) { break }
+ if ($attempt -eq 4) { exit $LASTEXITCODE }
+ Start-Sleep -Seconds 10
+ }
+ }
+
+ - name: Snapshot additional release bundles
+ if: ${{ !cancelled() }}
+ run: node .github/scripts/preserve-release-artifacts.mjs
+ env:
+ RELEASE_TARGET: ${{ matrix.targets }}
+ RELEASE_PLATFORM: ${{ matrix.platform }}
+ RELEASE_RUNTIME: ${{ matrix.runtime }}
+ RELEASE_ARCH: ${{ matrix.yaak_arch }}
+ RELEASE_ARGS: ${{ matrix.args }}
+
+ - name: Retain release bundles for recovery
+ if: ${{ !cancelled() }}
+ uses: actions/upload-artifact@v4
+ with:
+ name: release-${{ github.ref_name }}-${{ matrix.platform }}-${{ matrix.runtime }}-${{ matrix.yaak_arch }}-${{ github.run_id }}-attempt-${{ github.run_attempt }}
+ path: ${{ runner.temp }}/yaak-release-artifacts/
+ retention-days: 7
+ if-no-files-found: warn
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
index 682f3b97c..b06ff6f53 100644
--- a/.oxfmtrc.json
+++ b/.oxfmtrc.json
@@ -3,6 +3,7 @@
"ignorePatterns": [
"**/bindings/**",
"crates/yaak-templates/pkg/**",
- "apps/yaak-client/routeTree.gen.ts"
+ "apps/yaak-client/routeTree.gen.ts",
+ "plugins/importer-bruno/tests/fixtures/upstream/**"
]
}
diff --git a/Cargo.lock b/Cargo.lock
index 4adf00f72..9ff5f085a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -22,34 +22,23 @@ checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "aead"
-version = "0.5.2"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99"
dependencies = [
- "crypto-common",
- "generic-array",
+ "crypto-common 0.2.2",
+ "inout 0.2.2",
]
[[package]]
name = "aes"
-version = "0.8.4"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32"
dependencies = [
- "cfg-if",
- "cipher",
- "cpufeatures",
-]
-
-[[package]]
-name = "ahash"
-version = "0.7.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
-dependencies = [
- "getrandom 0.2.16",
- "once_cell",
- "version_check",
+ "cipher 0.5.2",
+ "cpubits",
+ "cpufeatures 0.3.1",
]
[[package]]
@@ -76,13 +65,28 @@ version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
+[[package]]
+name = "alloc-no-stdlib"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2fb6cfd47bf496ff64095c20eaba0c201404ee38714d4142fcfa1dc334fcc7a"
+
[[package]]
name = "alloc-stdlib"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
dependencies = [
- "alloc-no-stdlib",
+ "alloc-no-stdlib 2.0.4",
+]
+
+[[package]]
+name = "alloc-stdlib"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b5c1865780388bfa186411ab5f247819487fc4864c6e9c3106611fa347586e1"
+dependencies = [
+ "alloc-no-stdlib 3.0.0",
]
[[package]]
@@ -104,8 +108,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f39be698127218cca460cb624878c9aa4e2b47dba3b277963d2bf00bad263b"
dependencies = [
"android_log-sys",
- "env_filter",
- "log 0.4.29",
+ "env_filter 0.1.3",
+ "log 0.4.34",
]
[[package]]
@@ -119,9 +123,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.21"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
+checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -140,9 +144,9 @@ checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
-version = "0.2.7"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [
"utf8parse",
]
@@ -169,9 +173,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.98"
+version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
[[package]]
name = "apollo-parser"
@@ -181,7 +185,7 @@ checksum = "947e21ff51879f8a40d7519dfe619268de2afba4042a8a43878276de3cb910f0"
dependencies = [
"memchr",
"rowan",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -201,21 +205,21 @@ dependencies = [
[[package]]
name = "arboard"
-version = "3.5.0"
+version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1df21f715862ede32a0c525ce2ca4d52626bb0007f8c18b87a384503ac33e70"
+checksum = "aeb9553e62312c8756a5979254fc6d7da8bbeb5986a1e17037fab932f7037917"
dependencies = [
"clipboard-win",
"image",
- "log 0.4.29",
- "objc2 0.6.4",
+ "log 0.4.34",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"parking_lot",
"percent-encoding",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
"wl-clipboard-rs",
"x11rb",
]
@@ -238,24 +242,6 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
-[[package]]
-name = "ashpd"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3d60bee1a1d38c2077030f4788e1b4e31058d2e79a8cfc8f2b440bd44db290"
-dependencies = [
- "async-fs",
- "async-net",
- "enumflags2",
- "futures-channel",
- "futures-util",
- "rand 0.8.7",
- "serde",
- "serde_repr",
- "url",
- "zbus",
-]
-
[[package]]
name = "ashpd"
version = "0.11.1"
@@ -279,9 +265,9 @@ dependencies = [
[[package]]
name = "assert_cmd"
-version = "2.1.2"
+version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c5bcfa8749ac45dd12cb11055aeeb6b27a3895560d60d71e3c23bf979e60514"
+checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6"
dependencies = [
"anstyle",
"bstr",
@@ -298,23 +284,12 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
dependencies = [
- "event-listener 5.4.0",
+ "event-listener",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
]
-[[package]]
-name = "async-channel"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
-dependencies = [
- "concurrent-queue",
- "event-listener 2.5.3",
- "futures-core",
-]
-
[[package]]
name = "async-channel"
version = "2.3.1"
@@ -329,18 +304,14 @@ dependencies = [
[[package]]
name = "async-compression"
-version = "0.4.23"
+version = "0.4.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07"
+checksum = "9d5755640120b24961f8231e05892e4a4f7e0d04e8aeca161508c9c397946970"
dependencies = [
- "brotli 8.0.1",
- "flate2",
- "futures-core",
- "memchr",
+ "compression-codecs",
+ "compression-core",
"pin-project-lite",
"tokio",
- "zstd",
- "zstd-safe",
]
[[package]]
@@ -357,32 +328,6 @@ dependencies = [
"slab",
]
-[[package]]
-name = "async-fs"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5"
-dependencies = [
- "async-lock",
- "blocking",
- "futures-lite",
-]
-
-[[package]]
-name = "async-global-executor"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
-dependencies = [
- "async-channel 2.3.1",
- "async-executor",
- "async-io",
- "async-lock",
- "blocking",
- "futures-lite",
- "once_cell",
-]
-
[[package]]
name = "async-io"
version = "2.4.1"
@@ -396,7 +341,7 @@ dependencies = [
"futures-lite",
"parking",
"polling",
- "rustix 1.0.7",
+ "rustix 1.1.5",
"slab",
"tracing",
"windows-sys 0.59.0",
@@ -408,50 +353,39 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
dependencies = [
- "event-listener 5.4.0",
+ "event-listener",
"event-listener-strategy",
"pin-project-lite",
]
-[[package]]
-name = "async-net"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
-dependencies = [
- "async-io",
- "blocking",
- "futures-lite",
-]
-
[[package]]
name = "async-process"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
dependencies = [
- "async-channel 2.3.1",
+ "async-channel",
"async-io",
"async-lock",
"async-signal",
"async-task",
"blocking",
"cfg-if",
- "event-listener 5.4.0",
+ "event-listener",
"futures-lite",
- "rustix 1.0.7",
+ "rustix 1.1.5",
"tracing",
]
[[package]]
name = "async-recursion"
-version = "1.1.1"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
+checksum = "4f8abc12baad266b1c8cec146854c195b5864b4221d4b2ca7296a7ae82d9e451"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
]
[[package]]
@@ -477,60 +411,12 @@ dependencies = [
"cfg-if",
"futures-core",
"futures-io",
- "rustix 1.0.7",
+ "rustix 1.1.5",
"signal-hook-registry",
"slab",
"windows-sys 0.59.0",
]
-[[package]]
-name = "async-std"
-version = "1.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b"
-dependencies = [
- "async-channel 1.9.0",
- "async-global-executor",
- "async-io",
- "async-lock",
- "crossbeam-utils",
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-lite",
- "gloo-timers",
- "kv-log-macro",
- "log 0.4.29",
- "memchr",
- "once_cell",
- "pin-project-lite",
- "pin-utils",
- "slab",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "async-stream"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
-dependencies = [
- "async-stream-impl",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-stream-impl"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.101",
-]
-
[[package]]
name = "async-task"
version = "4.7.1"
@@ -539,13 +425,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
-version = "0.1.88"
+version = "0.1.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
]
[[package]]
@@ -634,7 +520,7 @@ dependencies = [
"serde_urlencoded",
"sync_wrapper",
"tokio",
- "tower 0.5.2",
+ "tower",
"tower-layer",
"tower-service",
"tracing",
@@ -685,6 +571,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "base64"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
+
[[package]]
name = "base64-simd"
version = "0.8.0"
@@ -725,18 +617,6 @@ dependencies = [
"serde_core",
]
-[[package]]
-name = "bitvec"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
-dependencies = [
- "funty",
- "radium",
- "tap",
- "wyz",
-]
-
[[package]]
name = "blake3"
version = "1.8.3"
@@ -748,7 +628,7 @@ dependencies = [
"cc",
"cfg-if",
"constant_time_eq 0.4.2",
- "cpufeatures",
+ "cpufeatures 0.2.17",
]
[[package]]
@@ -766,6 +646,16 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "block-buffer"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
+dependencies = [
+ "hybrid-array",
+ "zeroize",
+]
+
[[package]]
name = "block-padding"
version = "0.3.3"
@@ -790,7 +680,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2"
dependencies = [
- "objc2 0.6.4",
+ "objc2 0.6.5",
]
[[package]]
@@ -799,66 +689,33 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
dependencies = [
- "async-channel 2.3.1",
+ "async-channel",
"async-task",
"futures-io",
"futures-lite",
"piper",
]
-[[package]]
-name = "borsh"
-version = "1.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
-dependencies = [
- "borsh-derive",
- "cfg_aliases",
-]
-
-[[package]]
-name = "borsh-derive"
-version = "1.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3"
-dependencies = [
- "once_cell",
- "proc-macro-crate 3.3.0",
- "proc-macro2",
- "quote",
- "syn 2.0.101",
-]
-
-[[package]]
-name = "brotli"
-version = "7.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd"
-dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
- "brotli-decompressor 4.0.3",
-]
-
[[package]]
name = "brotli"
version = "8.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d"
dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
+ "alloc-no-stdlib 2.0.4",
+ "alloc-stdlib 0.2.2",
"brotli-decompressor 5.0.0",
]
[[package]]
-name = "brotli-decompressor"
-version = "4.0.3"
+name = "brotli"
+version = "9.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd"
+checksum = "627b7cfb0578f0eafce087a90fcd40add1231900b69e4d4de2d456260a4f5d81"
dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
+ "alloc-no-stdlib 3.0.0",
+ "alloc-stdlib 0.3.0",
+ "brotli-decompressor 6.2.0",
]
[[package]]
@@ -867,8 +724,18 @@ version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
+ "alloc-no-stdlib 2.0.4",
+ "alloc-stdlib 0.2.2",
+]
+
+[[package]]
+name = "brotli-decompressor"
+version = "6.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34c6783f42c21c952ad7112b354f0ba2f10760e9decea5b1b60523d6e270faaf"
+dependencies = [
+ "alloc-no-stdlib 3.0.0",
+ "alloc-stdlib 0.3.0",
]
[[package]]
@@ -900,39 +767,6 @@ dependencies = [
"allocator-api2",
]
-[[package]]
-name = "byte-unit"
-version = "5.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174"
-dependencies = [
- "rust_decimal",
- "serde",
- "utf8-width",
-]
-
-[[package]]
-name = "bytecheck"
-version = "0.6.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
-dependencies = [
- "bytecheck_derive",
- "ptr_meta",
- "simdutf8",
-]
-
-[[package]]
-name = "bytecheck_derive"
-version = "0.6.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
[[package]]
name = "bytemuck"
version = "1.23.0"
@@ -953,22 +787,13 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
-version = "1.11.1"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
dependencies = [
"serde",
]
-[[package]]
-name = "bzip2"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47"
-dependencies = [
- "bzip2-sys",
-]
-
[[package]]
name = "bzip2"
version = "0.6.1"
@@ -978,16 +803,6 @@ dependencies = [
"libbz2-rs-sys",
]
-[[package]]
-name = "bzip2-sys"
-version = "0.1.13+1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
-dependencies = [
- "cc",
- "pkg-config",
-]
-
[[package]]
name = "cairo-rs"
version = "0.18.5"
@@ -1042,7 +857,7 @@ dependencies = [
"semver",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -1070,7 +885,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
]
[[package]]
@@ -1093,7 +908,7 @@ checksum = "2445d2f1e820efc064c511faa3a07c3ee79e565fdae026ca62ed3c80d0459223"
dependencies = [
"cef-dll-sys",
"libloading 0.9.0",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"windows-sys 0.61.2",
]
@@ -1150,26 +965,26 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chacha20"
-version = "0.9.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
+checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
dependencies = [
"cfg-if",
- "cipher",
- "cpufeatures",
+ "cipher 0.5.2",
+ "cpufeatures 0.3.1",
+ "rand_core 0.10.1",
]
[[package]]
name = "chacha20poly1305"
-version = "0.10.1"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
+checksum = "9b89e1c441e926b9c82a8d023f6e1b7ae0adcfaa7d621814e4d60789bac751cb"
dependencies = [
"aead",
"chacha20",
- "cipher",
+ "cipher 0.5.2",
"poly1305",
- "zeroize",
]
[[package]]
@@ -1184,9 +999,9 @@ dependencies = [
[[package]]
name = "chrono"
-version = "0.4.42"
+version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [
"iana-time-zone",
"js-sys",
@@ -1202,16 +1017,26 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
- "crypto-common",
- "inout",
- "zeroize",
+ "crypto-common 0.1.6",
+ "inout 0.1.4",
+]
+
+[[package]]
+name = "cipher"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
+dependencies = [
+ "block-buffer 0.12.1",
+ "crypto-common 0.2.2",
+ "inout 0.2.2",
]
[[package]]
name = "clap"
-version = "4.5.54"
+version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
+checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1219,9 +1044,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.54"
+version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
+checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [
"anstream",
"anstyle",
@@ -1231,21 +1056,21 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.49"
+version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
+checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "clap_lex"
-version = "0.7.6"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
+checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486"
[[package]]
name = "clipboard-win"
@@ -1265,26 +1090,32 @@ dependencies = [
"cc",
]
+[[package]]
+name = "cmov"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
+
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
name = "cocoa"
-version = "0.26.1"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c"
+checksum = "1e0d7076fd2bf3e3864683161b46e8b72277cdd0d304d6291faceea6e7db9a14"
dependencies = [
"bitflags 2.11.0",
"block",
"cocoa-foundation",
"core-foundation 0.10.1",
- "core-graphics 0.24.0",
+ "core-graphics 0.25.0",
"foreign-types 0.5.0",
"libc",
"objc",
@@ -1353,6 +1184,26 @@ dependencies = [
"static_assertions",
]
+[[package]]
+name = "compression-codecs"
+version = "0.4.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cae36683101b2899f48bd31f8db9839437356188e3b1ff23096e73dab09ba8fe"
+dependencies = [
+ "brotli 9.1.1",
+ "compression-core",
+ "flate2",
+ "memchr",
+ "zstd",
+ "zstd-safe",
+]
+
+[[package]]
+name = "compression-core"
+version = "0.4.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ebdda89edc534bf8d5dd2857562633b6495557e5846552ade994b99ed13c36a"
+
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@@ -1406,6 +1257,12 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "const-oid"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
+
[[package]]
name = "const-random"
version = "0.1.18"
@@ -1426,18 +1283,21 @@ dependencies = [
"tiny-keccak",
]
-[[package]]
-name = "constant_time_eq"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
-
[[package]]
name = "constant_time_eq"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
+[[package]]
+name = "constant_time_eq"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9eb6feb175df65d0a3ccd3e73484e940d0ac664e8034f0519fd49a93db3071d9"
+dependencies = [
+ "rustversion",
+]
+
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -1455,9 +1315,9 @@ dependencies = [
[[package]]
name = "cookie"
-version = "0.18.1"
+version = "0.18.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
+checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87"
dependencies = [
"percent-encoding",
"time",
@@ -1473,8 +1333,8 @@ dependencies = [
"cookie",
"document-features",
"idna",
- "indexmap 2.14.0",
- "log 0.4.29",
+ "indexmap 2.14.2",
+ "log 0.4.34",
"serde",
"serde_derive",
"serde_json",
@@ -1593,6 +1453,12 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79"
+[[package]]
+name = "cpubits"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
+
[[package]]
name = "cpufeatures"
version = "0.2.17"
@@ -1603,10 +1469,19 @@ dependencies = [
]
[[package]]
-name = "crc32fast"
-version = "1.4.2"
+name = "cpufeatures"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f97d3416d5337d15c4b0d78c8c91df922ca143f57ec20e2d1c188333047ef04"
dependencies = [
"cfg-if",
]
@@ -1683,10 +1558,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
- "rand_core 0.6.4",
"typenum",
]
+[[package]]
+name = "crypto-common"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
+dependencies = [
+ "getrandom 0.4.3",
+ "hybrid-array",
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "css-module-lexer"
version = "0.0.15"
@@ -1698,11 +1583,14 @@ dependencies = [
[[package]]
name = "csscolorparser"
-version = "0.7.2"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fda6aace1fbef3aa217b27f4c8d7d071ef2a70a5ca51050b1f17d40299d3f16"
+checksum = "75c9db70df93ea049adaa5ef1a727079ada6ccb33d4b358f262923aef4fcac8c"
dependencies = [
- "phf 0.11.3",
+ "num-traits",
+ "phf 0.14.0",
+ "serde",
+ "uncased",
]
[[package]]
@@ -1742,7 +1630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -1762,17 +1650,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1"
[[package]]
-name = "dark-light"
-version = "2.0.0"
+name = "ctutils"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18e1a09f280e29a8b00bc7e81eca5ac87dca0575639c9422a5fa25a07bb884b8"
+checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
dependencies = [
- "ashpd 0.10.3",
- "async-std",
- "objc2 0.5.2",
- "objc2-foundation 0.2.2",
+ "cmov",
+]
+
+[[package]]
+name = "dark-light"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f66b71ac6b73812b0bf51cda8dd646a268fbb38623f45b2b7907593c323f745"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
+ "wasm-bindgen",
"web-sys",
- "winreg 0.52.0",
+ "windows-sys 0.61.2",
+ "winreg 0.56.0",
+ "zbus",
]
[[package]]
@@ -1795,6 +1695,16 @@ dependencies = [
"darling_macro 0.23.0",
]
+[[package]]
+name = "darling"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec"
+dependencies = [
+ "darling_core 0.24.1",
+ "darling_macro 0.24.1",
+]
+
[[package]]
name = "darling_core"
version = "0.20.11"
@@ -1805,7 +1715,7 @@ dependencies = [
"ident_case",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -1818,7 +1728,20 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.101",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff"
+dependencies = [
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 3.0.3",
]
[[package]]
@@ -1829,7 +1752,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core 0.20.11",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -1840,7 +1763,18 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
dependencies = [
"darling_core 0.23.0",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785"
+dependencies = [
+ "darling_core 0.24.1",
+ "quote",
+ "syn 3.0.3",
]
[[package]]
@@ -1886,9 +1820,40 @@ dependencies = [
[[package]]
name = "deflate64"
-version = "0.1.9"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
+checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2"
+
+[[package]]
+name = "defmt"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1"
+dependencies = [
+ "bitflags 1.3.2",
+ "defmt-macros",
+]
+
+[[package]]
+name = "defmt-macros"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8"
+dependencies = [
+ "defmt-parser",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "defmt-parser"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
+dependencies = [
+ "thiserror 2.0.21",
+]
[[package]]
name = "delegate-display"
@@ -1906,11 +1871,10 @@ dependencies = [
[[package]]
name = "deranged"
-version = "0.5.5"
+version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
+checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e"
dependencies = [
- "powerfmt",
"serde_core",
]
@@ -1922,7 +1886,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -1935,7 +1899,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -1957,7 +1921,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
- "syn 2.0.101",
+ "syn 2.0.119",
"unicode-xid",
]
@@ -1967,7 +1931,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
]
[[package]]
@@ -1982,11 +1946,24 @@ version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
- "block-buffer",
- "crypto-common",
+ "block-buffer 0.10.4",
+ "crypto-common 0.1.6",
"subtle",
]
+[[package]]
+name = "digest"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
+dependencies = [
+ "block-buffer 0.12.1",
+ "const-oid",
+ "crypto-common 0.2.2",
+ "ctutils",
+ "zeroize",
+]
+
[[package]]
name = "dioxus-debug-cell"
version = "0.1.1"
@@ -2002,6 +1979,15 @@ dependencies = [
"dirs-sys",
]
+[[package]]
+name = "dirs"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d57d423b3c82e89b9a24ca3091fee61f456a26edbd28d26c65906f4bc1dcd8f"
+dependencies = [
+ "dirs-sys",
+]
+
[[package]]
name = "dirs-sys"
version = "0.5.0"
@@ -2016,14 +2002,14 @@ dependencies = [
[[package]]
name = "dispatch2"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
+checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
dependencies = [
"bitflags 2.11.0",
"block2 0.6.1",
"libc",
- "objc2 0.6.4",
+ "objc2 0.6.5",
]
[[package]]
@@ -2034,7 +2020,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -2066,7 +2052,7 @@ checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -2114,17 +2100,17 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c169adf067a787e1f1c58ed62906a557de85388bee4b54fb878b722ff606b113"
dependencies = [
- "bzip2 0.6.1",
+ "bzip2",
"clap",
"fs-err",
"indicatif",
- "regex 1.11.1",
+ "regex 1.13.1",
"semver",
"serde",
"serde_json",
"sha1_smol",
"tar",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"ureq",
]
@@ -2268,7 +2254,7 @@ checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -2277,21 +2263,31 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
- "log 0.4.29",
- "regex 1.11.1",
+ "log 0.4.34",
+ "regex 1.13.1",
+]
+
+[[package]]
+name = "env_filter"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217"
+dependencies = [
+ "log 0.4.34",
+ "regex 1.13.1",
]
[[package]]
name = "env_logger"
-version = "0.11.8"
+version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
+checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6"
dependencies = [
"anstream",
"anstyle",
- "env_filter",
+ "env_filter 2.0.0",
"jiff",
- "log 0.4.29",
+ "log 0.4.34",
]
[[package]]
@@ -2326,12 +2322,6 @@ version = "3.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
-[[package]]
-name = "event-listener"
-version = "2.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
-
[[package]]
name = "event-listener"
version = "5.4.0"
@@ -2349,7 +2339,7 @@ version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
- "event-listener 5.4.0",
+ "event-listener",
"pin-project-lite",
]
@@ -2358,7 +2348,7 @@ name = "eventsource-client"
version = "0.14.0"
source = "git+https://github.com/yaakapp/rust-eventsource-client#60e0e3ac5038149c4778dc4979b09b152214f9a8"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"pin-project",
]
@@ -2392,7 +2382,18 @@ checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
dependencies = [
"bit-set",
"regex-automata",
- "regex-syntax 0.8.5",
+ "regex-syntax 0.8.11",
+]
+
+[[package]]
+name = "fancy-regex"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d301f5bf187b3c295fce6468d3875037a0bccc5f6b151c63cac2f85babf21912"
+dependencies = [
+ "bit-set",
+ "regex-automata",
+ "regex-syntax 0.8.11",
]
[[package]]
@@ -2438,7 +2439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
dependencies = [
"colored",
- "log 0.4.29",
+ "log 0.4.34",
]
[[package]]
@@ -2483,13 +2484,13 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "flate2"
-version = "1.1.1"
+version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
+checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb"
dependencies = [
"crc32fast",
- "libz-rs-sys",
- "miniz_oxide",
+ "miniz_oxide 0.9.1",
+ "zlib-rs",
]
[[package]]
@@ -2559,7 +2560,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -2618,12 +2619,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "funty"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
-
[[package]]
name = "futf"
version = "0.1.5"
@@ -2636,9 +2631,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
+checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3"
dependencies = [
"futures-channel",
"futures-core",
@@ -2651,9 +2646,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
+checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
dependencies = [
"futures-core",
"futures-sink",
@@ -2661,15 +2656,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
[[package]]
name = "futures-executor"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
+checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432"
dependencies = [
"futures-core",
"futures-task",
@@ -2678,9 +2673,9 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
[[package]]
name = "futures-lite"
@@ -2697,32 +2692,32 @@ dependencies = [
[[package]]
name = "futures-macro"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
+checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
]
[[package]]
name = "futures-sink"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d"
[[package]]
name = "futures-task"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
[[package]]
name = "futures-util"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
dependencies = [
"futures-channel",
"futures-core",
@@ -2732,7 +2727,6 @@ dependencies = [
"futures-task",
"memchr",
"pin-project-lite",
- "pin-utils",
"slab",
]
@@ -2879,7 +2873,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55"
dependencies = [
- "rustix 1.0.7",
+ "rustix 1.1.5",
"windows-targets 0.52.6",
]
@@ -2901,23 +2895,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
- "js-sys",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "r-efi 5.2.0",
+ "wasip2",
"wasm-bindgen",
]
[[package]]
name = "getrandom"
-version = "0.3.3"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"js-sys",
"libc",
- "r-efi",
- "wasi 0.14.2+wasi-0.2.4",
+ "r-efi 6.0.0",
+ "rand_core 0.10.1",
"wasm-bindgen",
]
@@ -2955,17 +2961,15 @@ dependencies = [
[[package]]
name = "git2"
-version = "0.20.4"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b"
+checksum = "ddddbf932745a6be37109b6112d3ee09696106f848449069d3a57bba937ab82e"
dependencies = [
"bitflags 2.11.0",
"libc",
"libgit2-sys",
- "log 0.4.29",
- "openssl-probe",
+ "log 0.4.34",
"openssl-sys",
- "url",
]
[[package]]
@@ -3002,7 +3006,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -3021,18 +3025,6 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
-[[package]]
-name = "gloo-timers"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
-dependencies = [
- "futures-channel",
- "futures-core",
- "js-sys",
- "wasm-bindgen",
-]
-
[[package]]
name = "gobject-sys"
version = "0.18.0"
@@ -3093,14 +3085,14 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "h2"
-version = "0.4.10"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5"
+checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
dependencies = [
"atomic-waker",
"bytes",
@@ -3108,7 +3100,7 @@ dependencies = [
"futures-core",
"futures-sink",
"http",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"slab",
"tokio",
"tokio-util",
@@ -3144,9 +3136,6 @@ name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-dependencies = [
- "ahash",
-]
[[package]]
name = "hashbrown"
@@ -3219,7 +3208,16 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
- "digest",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "hmac"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
+dependencies = [
+ "digest 0.11.3",
]
[[package]]
@@ -3228,7 +3226,7 @@ version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"mac",
"markup5ever 0.14.1",
"match_token",
@@ -3240,26 +3238,25 @@ version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"markup5ever 0.38.0",
]
[[package]]
name = "http"
-version = "1.3.1"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
+checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0"
dependencies = [
"bytes",
- "fnv",
"itoa",
]
[[package]]
name = "http-body"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c"
dependencies = [
"bytes",
"http",
@@ -3267,9 +3264,9 @@ dependencies = [
[[package]]
name = "http-body-util"
-version = "0.1.3"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
+checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c"
dependencies = [
"bytes",
"futures-core",
@@ -3303,14 +3300,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
-name = "hyper"
-version = "1.6.0"
+name = "hybrid-array"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
+checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214"
dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "hyper"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c3e324da4c95177d6291d4c8730197c0d1822f8a9766814a4a44fa5ab797c9c"
+dependencies = [
+ "atomic-waker",
"bytes",
"futures-channel",
- "futures-util",
+ "futures-core",
"h2",
"http",
"http-body",
@@ -3325,15 +3332,14 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.27.7"
+version = "0.27.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
+checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53"
dependencies = [
"http",
"hyper",
"hyper-util",
"rustls",
- "rustls-pki-types",
"tokio",
"tokio-rustls",
"tower-service",
@@ -3370,23 +3376,23 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.17"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
+checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff"
dependencies = [
- "base64 0.22.1",
+ "base64 0.23.1",
"bytes",
"futures-channel",
- "futures-core",
"futures-util",
"http",
"http-body",
+ "httparse",
"hyper",
"ipnet",
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2 0.6.1",
+ "socket2",
"system-configuration",
"tokio",
"tower-service",
@@ -3404,7 +3410,7 @@ dependencies = [
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
- "log 0.4.29",
+ "log 0.4.34",
"wasm-bindgen",
"windows-core 0.61.2",
]
@@ -3599,7 +3605,7 @@ dependencies = [
"js-sys",
"sealed 0.6.0",
"smallvec",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
@@ -3615,7 +3621,7 @@ dependencies = [
"macroific 2.0.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -3631,9 +3637,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.14.0"
+version = "2.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
dependencies = [
"equivalent",
"hashbrown 0.17.1",
@@ -3693,6 +3699,15 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "inout"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
+dependencies = [
+ "hybrid-array",
+]
+
[[package]]
name = "inquire"
version = "0.7.5"
@@ -3798,26 +3813,39 @@ dependencies = [
[[package]]
name = "jiff"
-version = "0.2.18"
+version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e67e8da4c49d6d9909fe03361f9b620f58898859f5c7aded68351e85e71ecf50"
+checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb"
dependencies = [
+ "defmt",
+ "jiff-core",
"jiff-static",
- "log 0.4.29",
+ "log 0.4.34",
"portable-atomic",
"portable-atomic-util",
"serde_core",
]
[[package]]
-name = "jiff-static"
-version = "0.2.18"
+name = "jiff-core"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78"
+checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c"
dependencies = [
+ "defmt",
+ "log 0.4.34",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212"
+dependencies = [
+ "jiff-core",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -3829,26 +3857,75 @@ dependencies = [
"cesu8",
"cfg-if",
"combine",
- "jni-sys",
- "log 0.4.29",
+ "jni-sys 0.3.0",
+ "log 0.4.34",
"thiserror 1.0.69",
"walkdir",
"windows-sys 0.45.0",
]
+[[package]]
+name = "jni"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
+dependencies = [
+ "cfg-if",
+ "combine",
+ "jni-macros",
+ "jni-sys 0.4.1",
+ "log 0.4.34",
+ "simd_cesu8",
+ "thiserror 2.0.21",
+ "walkdir",
+ "windows-link 0.2.1",
+]
+
+[[package]]
+name = "jni-macros"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "simd_cesu8",
+ "syn 2.0.119",
+]
+
[[package]]
name = "jni-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+[[package]]
+name = "jni-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
+dependencies = [
+ "jni-sys-macros",
+]
+
+[[package]]
+name = "jni-sys-macros"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
+dependencies = [
+ "quote",
+ "syn 2.0.119",
+]
+
[[package]]
name = "jobserver"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
dependencies = [
- "getrandom 0.3.3",
+ "getrandom 0.3.4",
"libc",
]
@@ -3926,9 +4003,9 @@ checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c"
dependencies = [
"byteorder",
"dbus-secret-service",
- "log 0.4.29",
+ "log 0.4.34",
"security-framework 2.11.1",
- "security-framework 3.5.1",
+ "security-framework 3.7.0",
"windows-sys 0.60.2",
"zeroize",
]
@@ -3961,19 +4038,10 @@ checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2"
dependencies = [
"cssparser 0.29.6",
"html5ever 0.29.1",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"selectors 0.24.0",
]
-[[package]]
-name = "kv-log-macro"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
-dependencies = [
- "log 0.4.29",
-]
-
[[package]]
name = "lazy_static"
version = "0.2.11"
@@ -3996,7 +4064,7 @@ dependencies = [
"gtk",
"gtk-sys",
"libappindicator-sys",
- "log 0.4.29",
+ "log 0.4.34",
]
[[package]]
@@ -4018,9 +4086,9 @@ checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c"
[[package]]
name = "libc"
-version = "0.2.186"
+version = "0.2.191"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
+checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
[[package]]
name = "libdbus-sys"
@@ -4033,13 +4101,12 @@ dependencies = [
[[package]]
name = "libgit2-sys"
-version = "0.18.3+1.9.2"
+version = "0.18.8+1.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487"
+checksum = "7f7c568b25d7489bc3fb2988ed69ab111d2944d2f5fec3d5c987fe545ea97b50"
dependencies = [
"cc",
"libc",
- "libssh2-sys",
"libz-sys",
"openssl-sys",
"pkg-config",
@@ -4066,24 +4133,10 @@ dependencies = [
]
[[package]]
-name = "liblzma"
-version = "0.4.1"
+name = "libm"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66352d7a8ac12d4877b6e6ea5a9b7650ee094257dc40889955bea5bc5b08c1d0"
-dependencies = [
- "liblzma-sys",
-]
-
-[[package]]
-name = "liblzma-sys"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01b9596486f6d60c3bbe644c0e1be1aa6ccc472ad630fe8927b456973d7cb736"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
-]
+checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
name = "libredox"
@@ -4107,29 +4160,6 @@ dependencies = [
"vcpkg",
]
-[[package]]
-name = "libssh2-sys"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9"
-dependencies = [
- "cc",
- "libc",
- "libz-sys",
- "openssl-sys",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "libz-rs-sys"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221"
-dependencies = [
- "zlib-rs",
-]
-
[[package]]
name = "libz-sys"
version = "1.1.22"
@@ -4150,9 +4180,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "linux-raw-sys"
-version = "0.9.4"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "litemap"
@@ -4182,16 +4212,22 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
]
[[package]]
name = "log"
-version = "0.4.29"
+version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
+
+[[package]]
+name = "lzma-rust2"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7277c9742229dc25243236d578b6471a798c554512c6f6a04365ec2e87c2a3bb"
dependencies = [
- "value-bag",
+ "sha2 0.11.1",
]
[[package]]
@@ -4231,7 +4267,7 @@ dependencies = [
"proc-macro2",
"quote",
"sealed 0.6.0",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -4255,7 +4291,7 @@ dependencies = [
"proc-macro2",
"quote",
"sealed 0.6.0",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -4280,7 +4316,7 @@ dependencies = [
"macroific_core 2.0.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -4311,7 +4347,7 @@ version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"phf 0.11.3",
"phf_codegen 0.11.3",
"string_cache 0.8.9",
@@ -4325,7 +4361,7 @@ version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"tendril 0.5.0",
"web_atoms",
]
@@ -4338,7 +4374,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -4353,12 +4389,6 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
-[[package]]
-name = "md5"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
-
[[package]]
name = "md5"
version = "0.8.0"
@@ -4427,6 +4457,16 @@ dependencies = [
"simd-adler32",
]
+[[package]]
+name = "miniz_oxide"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c"
+dependencies = [
+ "adler2",
+ "simd-adler32",
+]
+
[[package]]
name = "mio"
version = "0.8.11"
@@ -4434,21 +4474,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
- "log 0.4.29",
+ "log 0.4.34",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
[[package]]
name = "mio"
-version = "1.0.4"
+version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
+checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee"
dependencies = [
"libc",
- "log 0.4.29",
+ "log 0.4.34",
"wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -4461,39 +4501,39 @@ dependencies = [
"dpi",
"gtk",
"keyboard-types",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"once_cell",
"png 0.18.1",
"serde",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"windows-sys 0.61.2",
]
[[package]]
name = "nanoid"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8"
+checksum = "8628de41fe064cc3f0cf07f3d299ee3e73521adaff72278731d5c8cae3797873"
dependencies = [
- "rand 0.8.7",
+ "rand 0.9.5",
]
[[package]]
name = "native-tls"
-version = "0.2.14"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
+checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
dependencies = [
"libc",
- "log 0.4.29",
+ "log 0.4.34",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
- "security-framework 2.11.1",
+ "security-framework 3.7.0",
"security-framework-sys",
"tempfile",
]
@@ -4505,8 +4545,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [
"bitflags 2.11.0",
- "jni-sys",
- "log 0.4.29",
+ "jni-sys 0.3.0",
+ "log 0.4.34",
"ndk-sys",
"num_enum",
"raw-window-handle",
@@ -4525,7 +4565,7 @@ version = "0.6.0+11769913"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
dependencies = [
- "jni-sys",
+ "jni-sys 0.3.0",
]
[[package]]
@@ -4567,15 +4607,14 @@ dependencies = [
[[package]]
name = "nix"
-version = "0.30.1"
+version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
+checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
dependencies = [
"bitflags 2.11.0",
"cfg-if",
"cfg_aliases",
"libc",
- "memoffset 0.9.1",
]
[[package]]
@@ -4623,21 +4662,21 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "notify"
-version = "8.0.0"
+version = "8.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943"
+checksum = "82f812702fbc75d35416d3f884e04925be7e9498f4eceea2e24ba34559284674"
dependencies = [
"bitflags 2.11.0",
- "filetime",
- "fsevent-sys",
"inotify",
"kqueue",
"libc",
- "log 0.4.29",
- "mio 1.0.4",
+ "log 0.4.34",
+ "mio 1.2.4",
"notify-types",
+ "objc2-core-foundation",
+ "objc2-core-services",
"walkdir",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -4667,9 +4706,9 @@ dependencies = [
[[package]]
name = "num-conv"
-version = "0.2.0"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
+checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]]
name = "num-integer"
@@ -4687,6 +4726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
+ "libm",
]
[[package]]
@@ -4707,7 +4747,7 @@ dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -4746,9 +4786,9 @@ dependencies = [
[[package]]
name = "objc2"
-version = "0.6.4"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
+checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8"
dependencies = [
"objc2-encode",
"objc2-exception-helper",
@@ -4756,77 +4796,79 @@ dependencies = [
[[package]]
name = "objc2-app-kit"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
+checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags 2.11.0",
"block2 0.6.1",
"libc",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-cloud-kit",
"objc2-core-data",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-image",
- "objc2-foundation 0.3.1",
- "objc2-quartz-core 0.3.1",
+ "objc2-core-text",
+ "objc2-core-video",
+ "objc2-foundation 0.3.2",
+ "objc2-quartz-core 0.3.2",
]
[[package]]
name = "objc2-cloud-kit"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d"
+checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
dependencies = [
"bitflags 2.11.0",
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-core-data"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d"
+checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
dependencies = [
"bitflags 2.11.0",
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-core-foundation"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
+checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.11.0",
"dispatch2",
- "objc2 0.6.4",
+ "objc2 0.6.5",
]
[[package]]
name = "objc2-core-graphics"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
+checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.11.0",
"dispatch2",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]]
name = "objc2-core-image"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e"
+checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
dependencies = [
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
]
[[package]]
@@ -4835,8 +4877,43 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac0f75792558aa9d618443bbb5db7426a7a0b6fddf96903f86ef9ad02e135740"
dependencies = [
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
+]
+
+[[package]]
+name = "objc2-core-services"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "583300ad934cba24ff5292aee751ecc070f7ca6b39a574cc21b7b5e588e06a0b"
+dependencies = [
+ "libc",
+ "objc2-core-foundation",
+]
+
+[[package]]
+name = "objc2-core-text"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
+dependencies = [
+ "bitflags 2.11.0",
+ "objc2 0.6.5",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+]
+
+[[package]]
+name = "objc2-core-video"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
+dependencies = [
+ "bitflags 2.11.0",
+ "objc2 0.6.5",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-io-surface",
]
[[package]]
@@ -4868,25 +4945,25 @@ dependencies = [
[[package]]
name = "objc2-foundation"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
+checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.11.0",
"block2 0.6.1",
"libc",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-core-foundation",
]
[[package]]
name = "objc2-io-surface"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
+checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
dependencies = [
"bitflags 2.11.0",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-core-foundation",
]
@@ -4896,7 +4973,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9052cb1bb50a4c161d934befcf879526fb87ae9a68858f241e693ca46225cf5a"
dependencies = [
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-core-foundation",
]
@@ -4919,9 +4996,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26bb88504b5a050dbba515d2414607bf5e57dd56b107bc5f0351197a3e7bdc5d"
dependencies = [
"bitflags 2.11.0",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
]
[[package]]
@@ -4939,27 +5016,39 @@ dependencies = [
[[package]]
name = "objc2-quartz-core"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5"
+checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
dependencies = [
"bitflags 2.11.0",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-core-foundation",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-security"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1f8e0ef3ab66b08c42644dcb34dba6ec0a574bbd8adbb8bdbdc7a2779731a44"
+checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a"
dependencies = [
"bitflags 2.11.0",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-core-foundation",
]
+[[package]]
+name = "objc2-service-management"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b213642d6959cc6023ceb1217aa595eaaf09b8094ce95127c103cab611fe65e8"
+dependencies = [
+ "objc2 0.6.5",
+ "objc2-core-foundation",
+ "objc2-foundation 0.3.2",
+ "objc2-security",
+]
+
[[package]]
name = "objc2-ui-kit"
version = "0.3.1"
@@ -4968,15 +5057,15 @@ checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed"
dependencies = [
"bitflags 2.11.0",
"block2 0.6.1",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-cloud-kit",
"objc2-core-data",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-image",
"objc2-core-location",
- "objc2-foundation 0.3.1",
- "objc2-quartz-core 0.3.1",
+ "objc2-foundation 0.3.2",
+ "objc2-quartz-core 0.3.2",
"objc2-user-notifications",
]
@@ -4986,8 +5075,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a3f5ec77a81d9e0c5a0b32159b0cb143d7086165e79708351e02bf37dfc65cd"
dependencies = [
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
]
[[package]]
@@ -4998,10 +5087,10 @@ checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad"
dependencies = [
"bitflags 2.11.0",
"block2 0.6.1",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"objc2-javascript-core",
"objc2-security",
]
@@ -5018,12 +5107,6 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
-[[package]]
-name = "opaque-debug"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
-
[[package]]
name = "open"
version = "5.3.2"
@@ -5058,14 +5141,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "openssl-probe"
-version = "0.1.6"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "openssl-src"
@@ -5130,7 +5213,7 @@ version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fc863e2ca13dc2d5c34fb22ea4a588248ac14db929616ba65c45f21744b1e9"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"serde",
"windows-sys 0.52.0",
]
@@ -5151,12 +5234,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b"
dependencies = [
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
"objc2-osa-kit",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -5206,7 +5289,7 @@ dependencies = [
"rustc-hash 2.1.1",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -5219,7 +5302,7 @@ dependencies = [
"owo-colors",
"oxc-miette-derive",
"textwrap",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"unicode-segmentation",
"unicode-width 0.2.2",
]
@@ -5232,7 +5315,7 @@ checksum = "d4faecb54d0971f948fbc1918df69b26007e6f279a204793669542e1e8b75eb3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -5276,7 +5359,7 @@ dependencies = [
"phf 0.13.1",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -5501,7 +5584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec96245d28afd809ea0d830d0cdedb372907d5f6d9c8fac2683888f14dfd62c"
dependencies = [
"cfg-if",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"json-strip-comments",
"libc",
"once_cell",
@@ -5513,7 +5596,7 @@ dependencies = [
"serde_json",
"simd-json",
"simdutf8",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tracing",
"url",
"windows 0.62.0",
@@ -5597,7 +5680,7 @@ checksum = "7d55a4cd5291f307ae9138e30de09b6b3004b07001df7b70b9d9d72b87593d07"
dependencies = [
"base64 0.22.1",
"compact_str",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"itoa",
"memchr",
"oxc_allocator",
@@ -5616,7 +5699,7 @@ dependencies = [
"rustc-hash 2.1.1",
"serde",
"serde_json",
- "sha1",
+ "sha1 0.10.7",
]
[[package]]
@@ -5666,14 +5749,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4873306de53fe82e7e484df31e1e947d61514b6ea2ed6cd7b45d63006fd9224"
dependencies = [
"cbc",
- "cipher",
+ "cipher 0.4.4",
"des",
"getrandom 0.2.16",
- "hmac",
+ "hmac 0.12.1",
"lazy_static 1.5.0",
"rc2",
- "sha1",
- "yasna",
+ "sha1 0.10.7",
+ "yasna 0.5.2",
]
[[package]]
@@ -5740,6 +5823,12 @@ dependencies = [
"windows-targets 0.52.6",
]
+[[package]]
+name = "pastey"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
+
[[package]]
name = "path-slash"
version = "0.2.1"
@@ -5754,12 +5843,12 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "pbkdf2"
-version = "0.12.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
+checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629"
dependencies = [
- "digest",
- "hmac",
+ "digest 0.11.3",
+ "hmac 0.13.0",
]
[[package]]
@@ -5778,6 +5867,12 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+[[package]]
+name = "peresil"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57"
+
[[package]]
name = "pest"
version = "0.3.3"
@@ -5791,7 +5886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [
"fixedbitset 0.4.2",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
]
[[package]]
@@ -5802,7 +5897,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
dependencies = [
"fixedbitset 0.5.7",
"hashbrown 0.15.3",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"serde",
]
@@ -5832,7 +5927,6 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
- "phf_macros 0.11.3",
"phf_shared 0.11.3",
]
@@ -5847,6 +5941,17 @@ dependencies = [
"serde",
]
+[[package]]
+name = "phf"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "010378780309880b08997fae13be7834dba947d36393bd372f2b1556deb2a2f6"
+dependencies = [
+ "phf_macros 0.14.0",
+ "phf_shared 0.14.0",
+ "serde",
+]
+
[[package]]
name = "phf_codegen"
version = "0.8.0"
@@ -5894,7 +5999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
dependencies = [
"phf_shared 0.10.0",
- "rand 0.8.7",
+ "rand 0.8.8",
]
[[package]]
@@ -5904,7 +6009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared 0.11.3",
- "rand 0.8.7",
+ "rand 0.8.8",
]
[[package]]
@@ -5917,6 +6022,16 @@ dependencies = [
"phf_shared 0.13.1",
]
+[[package]]
+name = "phf_generator"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aeb62e0959d5a1bebc965f4d15d9e2b7cea002b6b0f5ba8cde6cc26738467100"
+dependencies = [
+ "fastrand",
+ "phf_shared 0.14.0",
+]
+
[[package]]
name = "phf_macros"
version = "0.10.0"
@@ -5931,19 +6046,6 @@ dependencies = [
"syn 1.0.109",
]
-[[package]]
-name = "phf_macros"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
-dependencies = [
- "phf_generator 0.11.3",
- "phf_shared 0.11.3",
- "proc-macro2",
- "quote",
- "syn 2.0.101",
-]
-
[[package]]
name = "phf_macros"
version = "0.13.1"
@@ -5954,7 +6056,21 @@ dependencies = [
"phf_shared 0.13.1",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fa8d0ca26d424d27630da600c6624696e7dec8bf7b3b492b383c5dc49e5e085"
+dependencies = [
+ "phf_generator 0.14.0",
+ "phf_shared 0.14.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+ "uncased",
]
[[package]]
@@ -5993,6 +6109,16 @@ dependencies = [
"siphasher 1.0.1",
]
+[[package]]
+name = "phf_shared"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6fd9027e2d9319be6349febd1db4e8d02aa544921200c9b777720ac34a3aa89"
+dependencies = [
+ "siphasher 1.0.1",
+ "uncased",
+]
+
[[package]]
name = "pin-project"
version = "1.1.10"
@@ -6010,7 +6136,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -6019,12 +6145,6 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
[[package]]
name = "piper"
version = "0.2.4"
@@ -6044,13 +6164,13 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "plist"
-version = "1.7.1"
+version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d"
+checksum = "327a4cb2ad49dc48adfdc9da89e22c64d488b508c67a044d71ba729e4521a285"
dependencies = [
- "base64 0.22.1",
- "indexmap 2.14.0",
- "quick-xml 0.32.0",
+ "base64 0.23.1",
+ "indexmap 2.14.2",
+ "quick-xml 0.42.0",
"serde",
"time",
]
@@ -6065,7 +6185,7 @@ dependencies = [
"crc32fast",
"fdeflate",
"flate2",
- "miniz_oxide",
+ "miniz_oxide 0.8.8",
]
[[package]]
@@ -6078,7 +6198,7 @@ dependencies = [
"crc32fast",
"fdeflate",
"flate2",
- "miniz_oxide",
+ "miniz_oxide 0.8.8",
]
[[package]]
@@ -6089,7 +6209,7 @@ checksum = "a6e38320d5a8e386647f622067588bdb338c9e6e43eb32cf6f8991dd0e8f0046"
dependencies = [
"byteorder",
"concurrent_lru",
- "fancy-regex",
+ "fancy-regex 0.17.0",
"flate2",
"nodejs-built-in-modules",
"pathdiff",
@@ -6097,7 +6217,7 @@ dependencies = [
"rustc-hash 2.1.1",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -6110,7 +6230,7 @@ dependencies = [
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
- "rustix 1.0.7",
+ "rustix 1.1.5",
"tracing",
"windows-sys 0.59.0",
]
@@ -6123,12 +6243,11 @@ checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
[[package]]
name = "poly1305"
-version = "0.8.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
+checksum = "6e2d0073b297041425c7c3df6eb4792d598a15323fe63346852b092eca02904c"
dependencies = [
- "cpufeatures",
- "opaque-debug",
+ "cpufeatures 0.3.1",
"universal-hash",
]
@@ -6174,6 +6293,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+[[package]]
+name = "ppmd-rust"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd4acc8d264ea385db64ccfdcdfd5909ee9eda0975666723d59f3bfec80b3611"
+
[[package]]
name = "ppv-lite86"
version = "0.2.21"
@@ -6200,7 +6325,7 @@ dependencies = [
"float-cmp",
"normalize-line-endings",
"predicates-core",
- "regex 1.11.1",
+ "regex 1.13.1",
]
[[package]]
@@ -6291,18 +6416,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "prost"
-version = "0.13.5"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
+checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1"
dependencies = [
"bytes",
"prost-derive",
@@ -6310,25 +6435,24 @@ dependencies = [
[[package]]
name = "prost-derive"
-version = "0.13.5"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
+checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "prost-reflect"
-version = "0.14.7"
+version = "0.16.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5edd582b62f5cde844716e66d92565d7faf7ab1445c8cebce6e00fba83ddb2"
+checksum = "01b80ea363c31af2de2b92e3c07ed1156628f7838c4afb4df75ee78a37fedbd1"
dependencies = [
"base64 0.22.1",
- "once_cell",
"prost",
"prost-reflect-derive",
"prost-types",
@@ -6338,44 +6462,24 @@ dependencies = [
[[package]]
name = "prost-reflect-derive"
-version = "0.14.0"
+version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4fce6b22f15cc8d8d400a2b98ad29202b33bd56c7d9ddd815bc803a807ecb65"
+checksum = "30320eb03b43b7dfcaf9b361f808a4f1adad1e718ad219df1d7e4283e34e73f5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "prost-types"
-version = "0.13.5"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
+checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a"
dependencies = [
"prost",
]
-[[package]]
-name = "ptr_meta"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
-dependencies = [
- "ptr_meta_derive",
-]
-
-[[package]]
-name = "ptr_meta_derive"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
[[package]]
name = "quick-error"
version = "1.2.3"
@@ -6384,27 +6488,27 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quick-xml"
-version = "0.32.0"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
+checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
-version = "0.37.5"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
+checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
-version = "1.0.40"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@@ -6415,13 +6519,19 @@ version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+[[package]]
+name = "r-efi"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
+
[[package]]
name = "r2d2"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"parking_lot",
"scheduled-thread-pool",
]
@@ -6437,12 +6547,6 @@ dependencies = [
"uuid",
]
-[[package]]
-name = "radium"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
-
[[package]]
name = "radix_trie"
version = "0.3.0"
@@ -6469,9 +6573,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
+checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -6488,6 +6592,17 @@ dependencies = [
"rand_core 0.9.3",
]
+[[package]]
+name = "rand"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
+dependencies = [
+ "chacha20",
+ "getrandom 0.4.3",
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "rand_chacha"
version = "0.2.2"
@@ -6542,9 +6657,15 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
- "getrandom 0.3.3",
+ "getrandom 0.3.4",
]
+[[package]]
+name = "rand_core"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
+
[[package]]
name = "rand_hc"
version = "0.2.0"
@@ -6595,7 +6716,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62c64daa8e9438b84aaae55010a93f396f8e60e3911590fcba770d04643fc1dd"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
]
[[package]]
@@ -6608,7 +6729,7 @@ dependencies = [
"ring",
"rustls-pki-types",
"time",
- "yasna",
+ "yasna 0.5.2",
]
[[package]]
@@ -6628,7 +6749,7 @@ checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
dependencies = [
"getrandom 0.2.16",
"libredox",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -6648,7 +6769,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -6666,25 +6787,25 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.11.1"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
dependencies = [
"aho-corasick 1.1.3",
"memchr",
"regex-automata",
- "regex-syntax 0.8.5",
+ "regex-syntax 0.8.11",
]
[[package]]
name = "regex-automata"
-version = "0.4.9"
+version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
dependencies = [
"aho-corasick 1.1.3",
"memchr",
- "regex-syntax 0.8.5",
+ "regex-syntax 0.8.11",
]
[[package]]
@@ -6698,9 +6819,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.5"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "regress"
@@ -6712,23 +6833,13 @@ dependencies = [
"memchr",
]
-[[package]]
-name = "rend"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
-dependencies = [
- "bytecheck",
-]
-
[[package]]
name = "reqwest"
-version = "0.12.20"
+version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813"
+checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029"
dependencies = [
- "async-compression",
- "base64 0.22.1",
+ "base64 0.23.1",
"bytes",
"encoding_rs",
"futures-core",
@@ -6742,7 +6853,7 @@ dependencies = [
"hyper-tls",
"hyper-util",
"js-sys",
- "log 0.4.29",
+ "log 0.4.34",
"mime",
"mime_guess",
"native-tls",
@@ -6750,6 +6861,7 @@ dependencies = [
"pin-project-lite",
"rustls",
"rustls-pki-types",
+ "rustls-platform-verifier",
"serde",
"serde_json",
"serde_urlencoded",
@@ -6758,52 +6870,13 @@ dependencies = [
"tokio-native-tls",
"tokio-rustls",
"tokio-util",
- "tower 0.5.2",
- "tower-http",
+ "tower",
+ "tower-http 0.6.11",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
- "wasm-streams 0.4.2",
- "web-sys",
-]
-
-[[package]]
-name = "reqwest"
-version = "0.13.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
-dependencies = [
- "base64 0.22.1",
- "bytes",
- "futures-core",
- "futures-util",
- "http",
- "http-body",
- "http-body-util",
- "hyper",
- "hyper-rustls",
- "hyper-util",
- "js-sys",
- "log 0.4.29",
- "percent-encoding",
- "pin-project-lite",
- "rustls",
- "rustls-pki-types",
- "rustls-platform-verifier",
- "serde",
- "serde_json",
- "sync_wrapper",
- "tokio",
- "tokio-rustls",
- "tokio-util",
- "tower 0.5.2",
- "tower-http",
- "tower-service",
- "url",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "wasm-streams 0.5.0",
+ "wasm-streams",
"web-sys",
]
@@ -6813,18 +6886,18 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672"
dependencies = [
- "ashpd 0.11.1",
+ "ashpd",
"block2 0.6.1",
"dispatch2",
"glib-sys",
"gobject-sys",
"gtk-sys",
"js-sys",
- "log 0.4.29",
- "objc2 0.6.4",
+ "log 0.4.34",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"pollster",
"raw-window-handle",
"urlencoding",
@@ -6848,35 +6921,6 @@ dependencies = [
"windows-sys 0.52.0",
]
-[[package]]
-name = "rkyv"
-version = "0.7.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
-dependencies = [
- "bitvec",
- "bytecheck",
- "bytes",
- "hashbrown 0.12.3",
- "ptr_meta",
- "rend",
- "rkyv_derive",
- "seahash",
- "tinyvec",
- "uuid",
-]
-
-[[package]]
-name = "rkyv_derive"
-version = "0.7.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
[[package]]
name = "rlimit"
version = "0.11.0"
@@ -6886,6 +6930,52 @@ dependencies = [
"libc",
]
+[[package]]
+name = "rmcp"
+version = "3.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8be15815186873ea063bf005011d16c356804973489e40c39116ae3a2878d1f"
+dependencies = [
+ "async-trait",
+ "base64 0.23.1",
+ "bytes",
+ "chrono",
+ "futures",
+ "http",
+ "http-body",
+ "http-body-util",
+ "indexmap 2.14.2",
+ "libc",
+ "pastey",
+ "pin-project-lite",
+ "rand 0.10.3",
+ "rmcp-macros",
+ "schemars 1.2.1",
+ "serde",
+ "serde_json",
+ "sse-stream",
+ "thiserror 2.0.21",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower-service",
+ "tracing",
+ "uuid",
+]
+
+[[package]]
+name = "rmcp-macros"
+version = "3.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b0748e054a5f5598b3213cf72099ae6b2745ba4d996c59ccf455150a7dbb839"
+dependencies = [
+ "darling 0.24.1",
+ "proc-macro2",
+ "quote",
+ "serde_json",
+ "syn 3.0.3",
+]
+
[[package]]
name = "rolldown"
version = "0.1.0"
@@ -6901,7 +6991,7 @@ dependencies = [
"derive_more 2.1.1",
"dunce",
"futures",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"itertools",
"itoa",
"json-escape-simd",
@@ -6972,8 +7062,8 @@ dependencies = [
"inotify",
"kqueue",
"libc",
- "log 0.4.29",
- "mio 1.0.4",
+ "log 0.4.34",
+ "mio 1.2.4",
"rolldown-notify-types",
"walkdir",
"windows-sys 0.61.2",
@@ -6985,7 +7075,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69128ae9ebf6d65638157e79dc9430e9341179aed9d85dde315ce6a702dba7e1"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"rolldown-file-id",
"rolldown-notify",
"rolldown-notify-types",
@@ -7230,7 +7320,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfe1535df7c67d246e3394196a6b89050ef63cb0a6c0d1c70bb32d747be94d6"
dependencies = [
- "regex 1.11.1",
+ "regex 1.13.1",
]
[[package]]
@@ -7260,7 +7350,7 @@ dependencies = [
"fast-glob",
"form_urlencoded",
"futures",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"infer",
"itoa",
"memchr",
@@ -7270,7 +7360,7 @@ dependencies = [
"oxc_index",
"phf 0.13.1",
"rayon",
- "regex 1.11.1",
+ "regex 1.13.1",
"regress",
"rolldown_std_utils",
"rustc-hash 2.1.1",
@@ -7322,7 +7412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c"
dependencies = [
"hashbrown 0.16.1",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -7352,22 +7442,6 @@ dependencies = [
"trim-in-place",
]
-[[package]]
-name = "rust_decimal"
-version = "1.37.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50"
-dependencies = [
- "arrayvec",
- "borsh",
- "bytes",
- "num-traits",
- "rand 0.8.7",
- "rkyv",
- "serde",
- "serde_json",
-]
-
[[package]]
name = "rustc-hash"
version = "1.1.0"
@@ -7404,25 +7478,25 @@ dependencies = [
[[package]]
name = "rustix"
-version = "1.0.7"
+version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d"
dependencies = [
"bitflags 2.11.0",
"errno",
"libc",
- "linux-raw-sys 0.9.4",
- "windows-sys 0.59.0",
+ "linux-raw-sys 0.12.1",
+ "windows-sys 0.61.2",
]
[[package]]
name = "rustls"
-version = "0.23.34"
+version = "0.23.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7"
+checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
dependencies = [
"aws-lc-rs",
- "log 0.4.29",
+ "log 0.4.34",
"once_cell",
"ring",
"rustls-pki-types",
@@ -7433,14 +7507,14 @@ dependencies = [
[[package]]
name = "rustls-native-certs"
-version = "0.8.1"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
+checksum = "4a073f5dc7469f984c52ad2752b63b0807745133b6de880b7b64c1ac4c48aec4"
dependencies = [
"openssl-probe",
"rustls-pki-types",
"schannel",
- "security-framework 3.5.1",
+ "security-framework 3.7.0",
]
[[package]]
@@ -7463,20 +7537,20 @@ dependencies = [
[[package]]
name = "rustls-platform-verifier"
-version = "0.6.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
+checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
- "jni",
- "log 0.4.29",
+ "jni 0.22.4",
+ "log 0.4.34",
"once_cell",
"rustls",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
- "security-framework 3.5.1",
+ "security-framework 3.7.0",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
@@ -7484,15 +7558,15 @@ dependencies = [
[[package]]
name = "rustls-platform-verifier-android"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
+checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
[[package]]
name = "rustls-webpki"
-version = "0.103.13"
+version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
+checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"aws-lc-rs",
"ring",
@@ -7523,11 +7597,11 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.27"
+version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
+checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -7573,6 +7647,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
dependencies = [
+ "chrono",
"dyn-clone",
"ref-cast",
"schemars_derive 1.2.1",
@@ -7591,7 +7666,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -7603,7 +7678,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -7639,8 +7714,8 @@ dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
- "syn 2.0.101",
- "thiserror 2.0.17",
+ "syn 2.0.119",
+ "thiserror 2.0.21",
]
[[package]]
@@ -7653,12 +7728,6 @@ dependencies = [
"sea-query",
]
-[[package]]
-name = "seahash"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
-
[[package]]
name = "sealed"
version = "0.6.0"
@@ -7667,7 +7736,7 @@ checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -7696,9 +7765,9 @@ dependencies = [
[[package]]
name = "security-framework"
-version = "3.5.1"
+version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags 2.11.0",
"core-foundation 0.10.1",
@@ -7709,9 +7778,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.15.0"
+version = "2.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
+checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
dependencies = [
"core-foundation-sys",
"libc",
@@ -7737,7 +7806,7 @@ dependencies = [
"cssparser 0.29.6",
"derive_more 0.99.20",
"fxhash",
- "log 0.4.29",
+ "log 0.4.34",
"phf 0.8.0",
"phf_codegen 0.8.0",
"precomputed-hash",
@@ -7754,7 +7823,7 @@ dependencies = [
"bitflags 2.11.0",
"cssparser 0.36.0",
"derive_more 2.1.1",
- "log 0.4.29",
+ "log 0.4.34",
"new_debug_unreachable",
"phf 0.13.1",
"phf_codegen 0.13.1",
@@ -7787,9 +7856,9 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
[[package]]
name = "serde"
-version = "1.0.228"
+version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@@ -7829,22 +7898,22 @@ dependencies = [
[[package]]
name = "serde_core"
-version = "1.0.228"
+version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.228"
+version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
]
[[package]]
@@ -7855,21 +7924,22 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "serde_json"
-version = "1.0.145"
+version = "1.0.154"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
+checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
dependencies = [
- "indexmap 2.14.0",
+ "foldhash 0.2.0",
+ "indexmap 2.14.2",
"itoa",
"memchr",
- "ryu",
"serde",
"serde_core",
+ "zmij",
]
[[package]]
@@ -7891,7 +7961,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -7935,7 +8005,7 @@ dependencies = [
"chrono",
"hex",
"indexmap 1.9.3",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"schemars 0.9.0",
"schemars 1.2.1",
"serde_core",
@@ -7953,7 +8023,7 @@ dependencies = [
"darling 0.23.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -7962,7 +8032,7 @@ version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"itoa",
"ryu",
"serde",
@@ -7988,7 +8058,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -8033,13 +8103,24 @@ dependencies = [
[[package]]
name = "sha1"
-version = "0.10.6"
+version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
dependencies = [
"cfg-if",
- "cpufeatures",
- "digest",
+ "cpufeatures 0.2.17",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha1"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.1",
+ "digest 0.11.3",
]
[[package]]
@@ -8055,8 +8136,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
- "cpufeatures",
- "digest",
+ "cpufeatures 0.2.17",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha2"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.1",
+ "digest 0.11.3",
]
[[package]]
@@ -8116,9 +8208,9 @@ dependencies = [
[[package]]
name = "simd-adler32"
-version = "0.3.7"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
+checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
[[package]]
name = "simd-json"
@@ -8132,6 +8224,16 @@ dependencies = [
"value-trait",
]
+[[package]]
+name = "simd_cesu8"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
+dependencies = [
+ "rustc_version",
+ "simdutf8",
+]
+
[[package]]
name = "simdutf8"
version = "0.1.5"
@@ -8173,22 +8275,12 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]]
name = "socket2"
-version = "0.5.10"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
dependencies = [
"libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "socket2"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
-dependencies = [
- "libc",
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -8213,7 +8305,7 @@ dependencies = [
"core-graphics 0.24.0",
"foreign-types 0.5.0",
"js-sys",
- "log 0.4.29",
+ "log 0.4.34",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2-quartz-core 0.2.2",
@@ -8271,13 +8363,26 @@ dependencies = [
"indexed_db_futures",
"js-sys",
"rsqlite-vfs",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
+[[package]]
+name = "sse-stream"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c25ac7aff0abd1dbc474536e40416e1102c7dd9bfba0b9861c6d357f835dcfb4"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http-body",
+ "http-body-util",
+ "pin-project-lite",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
@@ -8390,6 +8495,27 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "sxd-document"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94d82f37be9faf1b10a82c4bd492b74f698e40082f0f40de38ab275f31d42078"
+dependencies = [
+ "peresil",
+ "typed-arena",
+]
+
+[[package]]
+name = "sxd-xpath"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36e39da5d30887b5690e29de4c5ebb8ddff64ebd9933f98a01daaa4fd11b36ea"
+dependencies = [
+ "peresil",
+ "quick-error",
+ "sxd-document",
+]
+
[[package]]
name = "syn"
version = "1.0.109"
@@ -8403,9 +8529,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.101"
+version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
+checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
@@ -8440,7 +8566,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -8466,9 +8592,9 @@ dependencies = [
[[package]]
name = "system-configuration"
-version = "0.6.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
+checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags 2.11.0",
"core-foundation 0.9.4",
@@ -8516,14 +8642,14 @@ dependencies = [
"gdkwayland-sys",
"gdkx11-sys",
"gtk",
- "jni",
+ "jni 0.21.1",
"libc",
- "log 0.4.29",
+ "log 0.4.34",
"ndk",
"ndk-sys",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"objc2-ui-kit",
"once_cell",
"parking_lot",
@@ -8546,15 +8672,9 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
-[[package]]
-name = "tap"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
-
[[package]]
name = "tar"
version = "0.4.46"
@@ -8580,29 +8700,29 @@ dependencies = [
"anyhow",
"bytes",
"cookie",
- "dirs",
+ "dirs 6.0.0",
"dunce",
"embed_plist",
- "getrandom 0.3.3",
+ "getrandom 0.3.4",
"glob",
"gtk",
"heck 0.5.0",
"http",
"http-range",
- "jni",
+ "jni 0.21.1",
"libc",
- "log 0.4.29",
+ "log 0.4.34",
"mime",
"muda",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"objc2-ui-kit",
"objc2-web-kit",
"percent-encoding",
"plist",
"raw-window-handle",
- "reqwest 0.13.3",
+ "reqwest",
"serde",
"serde_json",
"serde_repr",
@@ -8613,8 +8733,8 @@ dependencies = [
"tauri-runtime",
"tauri-runtime-cef",
"tauri-runtime-wry",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
- "thiserror 2.0.17",
+ "tauri-utils 2.9.1",
+ "thiserror 2.0.21",
"tokio",
"tray-icon",
"url",
@@ -8631,7 +8751,7 @@ source = "git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f
dependencies = [
"anyhow",
"cargo_toml",
- "dirs",
+ "dirs 6.0.0",
"glob",
"heck 0.5.0",
"json-patch",
@@ -8639,7 +8759,7 @@ dependencies = [
"semver",
"serde",
"serde_json",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
+ "tauri-utils 2.9.1",
"tauri-winres",
"walkdir",
]
@@ -8660,10 +8780,10 @@ dependencies = [
"semver",
"serde",
"serde_json",
- "sha2",
- "syn 2.0.101",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
- "thiserror 2.0.17",
+ "sha2 0.10.9",
+ "syn 2.0.119",
+ "tauri-utils 2.9.1",
+ "thiserror 2.0.21",
"time",
"url",
"uuid",
@@ -8678,16 +8798,16 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
"tauri-codegen",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
+ "tauri-utils 2.9.1",
]
[[package]]
name = "tauri-plugin"
-version = "2.6.1"
+version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eefb2c18e8a605c23edb48fc56bb77381199e1a1e7f6ff0c9b970afe7b3cb8ee"
+checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020"
dependencies = [
"anyhow",
"glob",
@@ -8695,30 +8815,30 @@ dependencies = [
"schemars 0.8.22",
"serde",
"serde_json",
- "tauri-utils 2.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tauri-utils 2.9.3",
"walkdir",
]
[[package]]
name = "tauri-plugin-clipboard-manager"
-version = "2.3.2"
+version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "206dc20af4ed210748ba945c2774e60fd0acd52b9a73a028402caf809e9b6ecf"
+checksum = "4136fb69d967753d000423d7e5f863f89bf949efbdfbecb43a580426a01a0194"
dependencies = [
"arboard",
- "log 0.4.29",
+ "log 0.4.34",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
name = "tauri-plugin-deep-link"
-version = "2.4.9"
+version = "2.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ee75bc5627f77bfdf40c913255ebc258117b10ebe2b2239a1a1cf40b0b58aa"
+checksum = "92d489b8ecceae1cd09f6e1f7606f2095ac721cc8d54cf2f0e6bb377cc52cff6"
dependencies = [
"dunce",
"plist",
@@ -8727,8 +8847,8 @@ dependencies = [
"serde_json",
"tauri",
"tauri-plugin",
- "tauri-utils 2.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thiserror 2.0.17",
+ "tauri-utils 2.9.3",
+ "thiserror 2.0.21",
"tracing",
"url",
"windows-registry",
@@ -8737,11 +8857,11 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
-version = "2.7.1"
+version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65981abb771e74e571a38196c3baa11c459379164791eba0e67abc1a5fac9884"
+checksum = "61854a36651aa48381e5e209f69a01273b77f3f9f91f0c430b1b98d33bd47229"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"raw-window-handle",
"rfd",
"serde",
@@ -8749,21 +8869,21 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-plugin-fs",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"url",
]
[[package]]
name = "tauri-plugin-fs"
-version = "2.5.1"
+version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371"
+checksum = "de22eef34fd78c0da050e748710edd50bf127e651d02ea1b2bfada1523cc5c51"
dependencies = [
"anyhow",
"dunce",
"glob",
- "log 0.4.29",
- "objc2-foundation 0.3.1",
+ "log 0.4.34",
+ "objc2-foundation 0.3.2",
"percent-encoding",
"schemars 0.8.22",
"serde",
@@ -8771,51 +8891,50 @@ dependencies = [
"serde_repr",
"tauri",
"tauri-plugin",
- "tauri-utils 2.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thiserror 2.0.17",
+ "tauri-utils 2.9.3",
+ "thiserror 2.0.21",
"toml 1.1.2+spec-1.1.0",
"url",
]
[[package]]
name = "tauri-plugin-log"
-version = "2.8.0"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7545bd67f070a4500432c826e2e0682146a1d6712aee22a2786490156b574d93"
+checksum = "86f2e3c40b77fd1eb7f8e1b6900fb036aee2da1ea2d3783c91255a82c636649d"
dependencies = [
"android_logger",
- "byte-unit",
"fern",
- "log 0.4.29",
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "log 0.4.34",
+ "objc2 0.6.5",
+ "objc2-foundation 0.3.2",
"serde",
"serde_json",
"serde_repr",
"swift-rs",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"time",
]
[[package]]
name = "tauri-plugin-opener"
-version = "2.5.4"
+version = "2.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17e1bea14edce6b793a04e2417e3fd924b9bc4faae83cdee7d714156cceeed29"
+checksum = "60d60366174b745b4ef5824b8bbc1c457fd08f0ce101ff643c0a49181a9f4e91"
dependencies = [
"dunce",
"glob",
"objc2-app-kit",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"open",
"schemars 0.8.22",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"url",
"windows 0.61.1",
"zbus",
@@ -8828,7 +8947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997"
dependencies = [
"gethostname 1.0.2",
- "log 0.4.29",
+ "log 0.4.34",
"os_info",
"serde",
"serde_json",
@@ -8836,41 +8955,42 @@ dependencies = [
"sys-locale",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
name = "tauri-plugin-shell"
-version = "2.3.5"
+version = "2.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8457dbf9e2bab1edd8df22bb2c20857a59a9868e79cb3eac5ed639eec4d0c73b"
+checksum = "8548af174c5516e4f71f142acea4d02e00316296ea9aafa58798851481003e3c"
dependencies = [
"encoding_rs",
- "log 0.4.29",
+ "log 0.4.34",
"open",
"os_pipe",
- "regex 1.11.1",
+ "regex 1.13.1",
"schemars 0.8.22",
"serde",
"serde_json",
"shared_child",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
]
[[package]]
name = "tauri-plugin-single-instance"
-version = "2.4.2"
+version = "2.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c8f29386f5e9fdc699182388a33ee80a56de436d91b67459e86afef426282af"
+checksum = "db817fe9295e19b7d8357e900af31edb93703dd9fb6de524b007b47b6afc63b0"
dependencies = [
"serde",
"serde_json",
"tauri",
"tauri-plugin-deep-link",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
+ "tokio",
"tracing",
"windows-sys 0.60.2",
"zbus",
@@ -8878,21 +8998,21 @@ dependencies = [
[[package]]
name = "tauri-plugin-updater"
-version = "2.10.1"
+version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "806d9dac662c2e4594ff03c647a552f2c9bd544e7d0f683ec58f872f952ce4af"
+checksum = "7a5cad8ed5948d988e1018ecd31e27cacedbf72ce3fb972940c3e4bf51639e4b"
dependencies = [
"base64 0.22.1",
- "dirs",
+ "dirs 6.0.0",
"flate2",
"futures-util",
"http",
"infer",
- "log 0.4.29",
+ "log 0.4.34",
"minisign-verify",
"osakit",
"percent-encoding",
- "reqwest 0.13.3",
+ "reqwest",
"rustls",
"semver",
"serde",
@@ -8901,12 +9021,12 @@ dependencies = [
"tauri",
"tauri-plugin",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"time",
"tokio",
"url",
"windows-sys 0.60.2",
- "zip",
+ "zip 4.6.1",
]
[[package]]
@@ -8918,14 +9038,14 @@ dependencies = [
"dpi",
"gtk",
"http",
- "jni",
- "objc2 0.6.4",
+ "jni 0.21.1",
+ "objc2 0.6.5",
"objc2-ui-kit",
"raw-window-handle",
"serde",
"serde_json",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
- "thiserror 2.0.17",
+ "tauri-utils 2.9.1",
+ "thiserror 2.0.21",
"url",
"windows 0.61.1",
]
@@ -8939,21 +9059,21 @@ dependencies = [
"cef",
"cef-dll-sys",
"dioxus-debug-cell",
- "dirs",
+ "dirs 6.0.0",
"gtk",
"html5ever 0.29.1",
"http",
"kuchikiki",
- "log 0.4.29",
- "objc2 0.6.4",
+ "log 0.4.34",
+ "objc2 0.6.5",
"objc2-app-kit",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"raw-window-handle",
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
"tauri-runtime",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
+ "tauri-utils 2.9.1",
"url",
"windows 0.61.1",
"x11-dl",
@@ -8966,9 +9086,9 @@ source = "git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f
dependencies = [
"gtk",
"http",
- "jni",
- "log 0.4.29",
- "objc2 0.6.4",
+ "jni 0.21.1",
+ "log 0.4.34",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-web-kit",
"once_cell",
@@ -8977,7 +9097,7 @@ dependencies = [
"softbuffer",
"tao",
"tauri-runtime",
- "tauri-utils 2.9.1 (git+https://github.com/tauri-apps/tauri?rev=d9bc695c18d9a25baec21d8a5f36d72e3a14ee53)",
+ "tauri-utils 2.9.1",
"url",
"webkit2gtk",
"webview2-com",
@@ -8985,42 +9105,6 @@ dependencies = [
"wry",
]
-[[package]]
-name = "tauri-utils"
-version = "2.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d57200389a2f82b4b0a40ae29ca19b6978116e8f4d4e974c3234ce40c0ffbdec"
-dependencies = [
- "anyhow",
- "cargo_metadata",
- "ctor",
- "dom_query",
- "dunce",
- "glob",
- "http",
- "infer",
- "json-patch",
- "log 0.4.29",
- "memchr",
- "phf 0.13.1",
- "plist",
- "proc-macro2",
- "quote",
- "regex 1.11.1",
- "schemars 0.8.22",
- "semver",
- "serde",
- "serde-untagged",
- "serde_json",
- "serde_with",
- "swift-rs",
- "thiserror 2.0.17",
- "toml 1.1.2+spec-1.1.0",
- "url",
- "urlpattern",
- "uuid",
-]
-
[[package]]
name = "tauri-utils"
version = "2.9.1"
@@ -9038,13 +9122,13 @@ dependencies = [
"infer",
"json-patch",
"kuchikiki",
- "log 0.4.29",
+ "log 0.4.34",
"memchr",
"phf 0.13.1",
"plist",
"proc-macro2",
"quote",
- "regex 1.11.1",
+ "regex 1.13.1",
"schemars 1.2.1",
"semver",
"serde",
@@ -9052,7 +9136,7 @@ dependencies = [
"serde_json",
"serde_with",
"swift-rs",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"toml 1.1.2+spec-1.1.0",
"url",
"urlpattern",
@@ -9060,6 +9144,42 @@ dependencies = [
"walkdir",
]
+[[package]]
+name = "tauri-utils"
+version = "2.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887"
+dependencies = [
+ "anyhow",
+ "cargo_metadata",
+ "ctor",
+ "dom_query",
+ "dunce",
+ "glob",
+ "http",
+ "infer",
+ "json-patch",
+ "log 0.4.34",
+ "memchr",
+ "phf 0.13.1",
+ "plist",
+ "proc-macro2",
+ "quote",
+ "regex 1.13.1",
+ "schemars 0.8.22",
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde_json",
+ "serde_with",
+ "swift-rs",
+ "thiserror 2.0.21",
+ "toml 1.1.2+spec-1.1.0",
+ "url",
+ "urlpattern",
+ "uuid",
+]
+
[[package]]
name = "tauri-winres"
version = "0.3.1"
@@ -9067,21 +9187,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4"
dependencies = [
"embed-resource",
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"toml 0.8.23",
]
[[package]]
name = "tempfile"
-version = "3.20.0"
+version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
+checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
- "getrandom 0.3.3",
+ "getrandom 0.4.3",
"once_cell",
- "rustix 1.0.7",
- "windows-sys 0.59.0",
+ "rustix 1.1.5",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -9148,11 +9268,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.17"
+version = "2.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
+checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
dependencies = [
- "thiserror-impl 2.0.17",
+ "thiserror-impl 2.0.21",
]
[[package]]
@@ -9163,18 +9283,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.17"
+version = "2.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
+checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
]
[[package]]
@@ -9208,12 +9328,12 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.47"
+version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
+checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134"
dependencies = [
"deranged",
- "itoa",
+ "js-sys",
"libc",
"num-conv",
"num_threads",
@@ -9225,15 +9345,15 @@ dependencies = [
[[package]]
name = "time-core"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
+checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "time-macros"
-version = "0.2.27"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
+checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85"
dependencies = [
"num-conv",
"time-core",
@@ -9281,16 +9401,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.48.0"
+version = "1.54.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
+checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3"
dependencies = [
"bytes",
"libc",
- "mio 1.0.4",
+ "mio 1.2.4",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.1",
+ "socket2",
"tokio-macros",
"tracing",
"windows-sys 0.61.2",
@@ -9298,13 +9418,13 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "2.6.0"
+version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
]
[[package]]
@@ -9319,9 +9439,9 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.26.2"
+version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
+checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db"
dependencies = [
"rustls",
"tokio",
@@ -9329,9 +9449,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
-version = "0.1.17"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
+checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -9340,12 +9460,12 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
-version = "0.26.2"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
+checksum = "17a073bfed563fa236697a068031408a93cd9522e08abf9933ead3e73411bd71"
dependencies = [
"futures-util",
- "log 0.4.29",
+ "log 0.4.34",
"rustls",
"rustls-native-certs",
"rustls-pki-types",
@@ -9356,13 +9476,14 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.15"
+version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
+checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
+ "libc",
"pin-project-lite",
"tokio",
]
@@ -9385,7 +9506,7 @@ version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"serde_core",
"serde_spanned 1.1.1",
"toml_datetime 1.1.1+spec-1.1.0",
@@ -9418,7 +9539,7 @@ version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"toml_datetime 0.6.11",
"winnow 0.5.40",
]
@@ -9429,7 +9550,7 @@ version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"toml_datetime 0.6.11",
"winnow 0.5.40",
]
@@ -9440,7 +9561,7 @@ version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap 2.14.2",
"serde",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
@@ -9471,13 +9592,11 @@ checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
[[package]]
name = "tonic"
-version = "0.12.3"
+version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
+checksum = "e2cdfc673aabd30fe8fee92e65837b644c37c5d47f0f97ae6d5e0f1237d15e1b"
dependencies = [
- "async-stream",
"async-trait",
- "axum",
"base64 0.22.1",
"bytes",
"h2",
@@ -9489,42 +9608,54 @@ dependencies = [
"hyper-util",
"percent-encoding",
"pin-project",
- "prost",
- "socket2 0.5.10",
+ "socket2",
+ "sync_wrapper",
"tokio",
"tokio-stream",
- "tower 0.4.13",
+ "tokio-util",
+ "tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
-name = "tonic-reflection"
-version = "0.12.3"
+name = "tonic-prost"
+version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "878d81f52e7fcfd80026b7fdb6a9b578b3c3653ba987f87f0dce4b64043cba27"
+checksum = "eba464054e2226f182a34489b8b079bf4c6e3e7ab5fd7fc30e024f24aa92a484"
+dependencies = [
+ "bytes",
+ "prost",
+ "tonic",
+]
+
+[[package]]
+name = "tonic-reflection"
+version = "0.14.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7eb4700e220803efd45baf3babaa1958c79adc9e0fe6fbd4422f9188d1e57d26"
dependencies = [
"prost",
"prost-types",
"tokio",
"tokio-stream",
"tonic",
+ "tonic-prost",
]
[[package]]
name = "tower"
-version = "0.4.13"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
dependencies = [
"futures-core",
"futures-util",
- "indexmap 1.9.3",
- "pin-project",
+ "indexmap 2.14.2",
"pin-project-lite",
- "rand 0.8.7",
"slab",
+ "sync_wrapper",
"tokio",
"tokio-util",
"tower-layer",
@@ -9533,26 +9664,33 @@ dependencies = [
]
[[package]]
-name = "tower"
-version = "0.5.2"
+name = "tower-http"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
dependencies = [
+ "async-compression",
+ "bitflags 2.11.0",
+ "bytes",
"futures-core",
"futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
"pin-project-lite",
- "sync_wrapper",
"tokio",
+ "tokio-util",
+ "tower",
"tower-layer",
"tower-service",
- "tracing",
+ "url",
]
[[package]]
name = "tower-http"
-version = "0.6.10"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
+checksum = "08a05a66a4fdd61cbbe0a1d755ffe0ca6aba159dd4820936a0ff8a8278245b9c"
dependencies = [
"async-compression",
"bitflags 2.11.0",
@@ -9570,10 +9708,8 @@ dependencies = [
"pin-project-lite",
"tokio",
"tokio-util",
- "tower 0.5.2",
"tower-layer",
"tower-service",
- "url",
]
[[package]]
@@ -9594,7 +9730,7 @@ version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -9608,7 +9744,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -9638,7 +9774,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"once_cell",
"tracing-core",
]
@@ -9677,18 +9813,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773"
dependencies = [
"crossbeam-channel",
- "dirs",
+ "dirs 6.0.0",
"libappindicator",
"muda",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"once_cell",
"png 0.18.1",
"serde",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"windows-sys 0.61.2",
]
@@ -9725,7 +9861,7 @@ checksum = "4994acea2522cd2b3b85c1d9529a55991e3ad5e25cdcd3de9d505972c4379424"
dependencies = [
"chrono",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"ts-rs-macros",
]
@@ -9737,29 +9873,40 @@ checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
"termcolor",
]
[[package]]
name = "tungstenite"
-version = "0.26.2"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
+checksum = "e48ac77174b19c110a50ab2128b24215ac9cb40e0e12e093fb602d175c569d22"
dependencies = [
"bytes",
"data-encoding",
"http",
"httparse",
- "log 0.4.29",
- "rand 0.9.5",
+ "log 0.4.34",
+ "rand 0.10.3",
"rustls",
"rustls-pki-types",
- "sha1",
- "thiserror 2.0.17",
- "utf-8",
+ "sha1 0.11.0",
+ "thiserror 2.0.21",
]
+[[package]]
+name = "typed-arena"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
+
+[[package]]
+name = "typed-path"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54ec2755506471f54baf5e4bb5499d8e510cc1caf271270e778a736bd2d7336c"
+
[[package]]
name = "typedmap"
version = "0.6.0"
@@ -9798,6 +9945,15 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "uncased"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697"
+dependencies = [
+ "version_check",
+]
+
[[package]]
name = "unic-char-property"
version = "0.9.0"
@@ -9895,12 +10051,12 @@ checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3"
[[package]]
name = "universal-hash"
-version = "0.5.1"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96"
dependencies = [
- "crypto-common",
- "subtle",
+ "crypto-common 0.2.2",
+ "ctutils",
]
[[package]]
@@ -9924,7 +10080,7 @@ dependencies = [
"base64 0.22.1",
"cookie_store",
"flate2",
- "log 0.4.29",
+ "log 0.4.34",
"percent-encoding",
"rustls",
"rustls-pki-types",
@@ -9945,7 +10101,7 @@ dependencies = [
"base64 0.22.1",
"http",
"httparse",
- "log 0.4.29",
+ "log 0.4.34",
]
[[package]]
@@ -9972,7 +10128,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d"
dependencies = [
- "regex 1.11.1",
+ "regex 1.13.1",
"serde",
"unic-ucd-ident",
"url",
@@ -9990,12 +10146,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba"
-[[package]]
-name = "utf8-width"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
-
[[package]]
name = "utf8-zero"
version = "0.8.1"
@@ -10016,14 +10166,14 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
-version = "1.17.0"
+version = "1.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
+checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514"
dependencies = [
- "getrandom 0.3.3",
+ "getrandom 0.4.3",
"js-sys",
- "rand 0.9.5",
- "serde",
+ "rand 0.10.3",
+ "serde_core",
"wasm-bindgen",
]
@@ -10033,12 +10183,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
-[[package]]
-name = "value-bag"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0"
-
[[package]]
name = "value-trait"
version = "0.12.1"
@@ -10125,9 +10269,9 @@ dependencies = [
[[package]]
name = "want"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b"
dependencies = [
"try-lock",
]
@@ -10145,12 +10289,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
-name = "wasi"
-version = "0.14.2+wasi-0.2.4"
+name = "wasip2"
+version = "1.0.4+wasi-0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
dependencies = [
- "wit-bindgen-rt",
+ "wit-bindgen",
]
[[package]]
@@ -10197,7 +10341,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
"wasm-bindgen-shared",
]
@@ -10210,19 +10354,6 @@ dependencies = [
"unicode-ident",
]
-[[package]]
-name = "wasm-streams"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
-dependencies = [
- "futures-util",
- "js-sys",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
-]
-
[[package]]
name = "wasm-streams"
version = "0.5.0"
@@ -10238,13 +10369,13 @@ dependencies = [
[[package]]
name = "wayland-backend"
-version = "0.3.10"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
+checksum = "38a91b4eaddff87b1cd1074985e3713da4af2c49742d1b356b2c01670a67a078"
dependencies = [
"cc",
"downcast-rs",
- "rustix 0.38.44",
+ "rustix 1.1.5",
"scoped-tls",
"smallvec",
"wayland-sys",
@@ -10252,21 +10383,21 @@ dependencies = [
[[package]]
name = "wayland-client"
-version = "0.31.10"
+version = "0.31.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
+checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073"
dependencies = [
"bitflags 2.11.0",
- "rustix 0.38.44",
+ "rustix 1.1.5",
"wayland-backend",
"wayland-scanner",
]
[[package]]
name = "wayland-protocols"
-version = "0.32.8"
+version = "0.32.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a"
+checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6"
dependencies = [
"bitflags 2.11.0",
"wayland-backend",
@@ -10276,9 +10407,9 @@ dependencies = [
[[package]]
name = "wayland-protocols-wlr"
-version = "0.3.8"
+version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf"
+checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234"
dependencies = [
"bitflags 2.11.0",
"wayland-backend",
@@ -10289,23 +10420,23 @@ dependencies = [
[[package]]
name = "wayland-scanner"
-version = "0.31.6"
+version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
+checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0"
dependencies = [
"proc-macro2",
- "quick-xml 0.37.5",
+ "quick-xml 0.41.0",
"quote",
]
[[package]]
name = "wayland-sys"
-version = "0.31.6"
+version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
+checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be"
dependencies = [
"dlib",
- "log 0.4.29",
+ "log 0.4.34",
"pkg-config",
]
@@ -10343,16 +10474,16 @@ dependencies = [
[[package]]
name = "webbrowser"
-version = "1.1.0"
+version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2"
+checksum = "d2c8ddfbbf66e501434657400268cefe51b95140a0266236415cda7627732df7"
dependencies = [
- "core-foundation 0.10.1",
- "jni",
- "log 0.4.29",
+ "jni 0.22.4",
+ "log 0.4.34",
"ndk-context",
- "objc2 0.6.4",
- "objc2-foundation 0.3.1",
+ "objc2 0.6.5",
+ "objc2-app-kit",
+ "objc2-foundation 0.3.2",
"url",
"web-sys",
]
@@ -10441,7 +10572,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -10450,7 +10581,7 @@ version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c"
dependencies = [
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"windows 0.61.1",
"windows-core 0.61.2",
]
@@ -10498,10 +10629,10 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c"
dependencies = [
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"raw-window-handle",
"windows-sys 0.59.0",
"windows-version",
@@ -10607,7 +10738,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -10618,7 +10749,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -11046,6 +11177,9 @@ name = "winnow"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
+dependencies = [
+ "memchr",
+]
[[package]]
name = "winreg"
@@ -11056,16 +11190,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "winreg"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
-dependencies = [
- "cfg-if",
- "windows-sys 0.48.0",
-]
-
[[package]]
name = "winreg"
version = "0.55.0"
@@ -11077,26 +11201,32 @@ dependencies = [
]
[[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
+name = "winreg"
+version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
dependencies = [
- "bitflags 2.11.0",
+ "cfg-if",
+ "windows-sys 0.61.2",
]
[[package]]
-name = "wl-clipboard-rs"
-version = "0.9.2"
+name = "wit-bindgen"
+version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5ff8d0e60065f549fafd9d6cb626203ea64a798186c80d8e7df4f8af56baeb"
+checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
+
+[[package]]
+name = "wl-clipboard-rs"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "959c7ac3b8afde864f7a7448ac16f29b2b83350b7eccbf77fb781c3999aa6848"
dependencies = [
"libc",
- "log 0.4.29",
+ "log 0.4.34",
"os_pipe",
- "rustix 0.38.44",
- "tempfile",
- "thiserror 2.0.17",
+ "rustix 1.1.5",
+ "thiserror 2.0.21",
"tree_magic_mini",
"wayland-backend",
"wayland-client",
@@ -11120,7 +11250,7 @@ dependencies = [
"block2 0.6.1",
"cookie",
"crossbeam-channel",
- "dirs",
+ "dirs 6.0.0",
"dom_query",
"dpi",
"dunce",
@@ -11128,22 +11258,22 @@ dependencies = [
"gtk",
"http",
"javascriptcore-rs",
- "jni",
+ "jni 0.21.1",
"libc",
"ndk",
- "objc2 0.6.4",
+ "objc2 0.6.5",
"objc2-app-kit",
"objc2-core-foundation",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"objc2-ui-kit",
"objc2-web-kit",
"once_cell",
"percent-encoding",
"raw-window-handle",
- "sha2",
+ "sha2 0.10.9",
"soup3",
"tao-macros",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"url",
"webkit2gtk",
"webkit2gtk-sys",
@@ -11154,15 +11284,6 @@ dependencies = [
"x11-dl",
]
-[[package]]
-name = "wyz"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
-dependencies = [
- "tap",
-]
-
[[package]]
name = "x11"
version = "2.21.0"
@@ -11208,31 +11329,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e"
dependencies = [
"libc",
- "rustix 1.0.7",
+ "rustix 1.1.5",
]
[[package]]
name = "xxhash-rust"
-version = "0.8.15"
+version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
+checksum = "550a2b930b62486a393c52d5c3b84bff264b28aa437ed64694d31e93b1757af7"
[[package]]
name = "yaak"
version = "0.1.0"
dependencies = [
"async-trait",
- "base64 0.22.1",
+ "base64 0.23.1",
"chrono",
- "log 0.4.29",
- "md5 0.8.0",
+ "log 0.4.34",
+ "md5",
"rusqlite",
"serde_json",
+ "sha2 0.10.9",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"yaak-core",
"yaak-crypto",
+ "yaak-filter",
"yaak-http",
"yaak-models",
"yaak-plugins",
@@ -11244,10 +11367,10 @@ dependencies = [
name = "yaak-api"
version = "0.1.0"
dependencies = [
- "log 0.4.29",
- "reqwest 0.12.20",
+ "log 0.4.34",
+ "reqwest",
"sysproxy",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"yaak-common",
]
@@ -11255,22 +11378,22 @@ dependencies = [
name = "yaak-app-client"
version = "0.0.0"
dependencies = [
- "base64 0.22.1",
+ "base64 0.23.1",
"charset",
"chrono",
"cookie",
"eventsource-client",
"http",
- "log 0.4.29",
- "md5 0.8.0",
+ "log 0.4.34",
+ "md5",
"mime_guess",
"notify",
"openssl-sys",
"pretty_graphql",
"r2d2",
"r2d2_sqlite",
- "rand 0.9.5",
- "reqwest 0.12.20",
+ "rand 0.10.3",
+ "reqwest",
"rlimit",
"serde",
"serde_json",
@@ -11286,7 +11409,7 @@ dependencies = [
"tauri-plugin-shell",
"tauri-plugin-single-instance",
"tauri-plugin-updater",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"tokio-stream",
"tokio-tungstenite",
@@ -11300,6 +11423,7 @@ dependencies = [
"yaak-common",
"yaak-core",
"yaak-crypto",
+ "yaak-filter",
"yaak-fonts",
"yaak-git",
"yaak-grpc",
@@ -11307,6 +11431,7 @@ dependencies = [
"yaak-license",
"yaak-lifecycle",
"yaak-mac-window",
+ "yaak-mcp",
"yaak-models",
"yaak-plugins",
"yaak-rpc",
@@ -11325,10 +11450,12 @@ dependencies = [
name = "yaak-app-proxy"
version = "0.0.0"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"serde_json",
"tauri",
"tauri-build",
+ "tauri-plugin-dialog",
+ "tauri-plugin-opener",
"tauri-plugin-os",
"yaak-mac-window",
"yaak-proxy-lib",
@@ -11342,40 +11469,43 @@ version = "0.1.0"
dependencies = [
"arboard",
"assert_cmd",
- "base64 0.22.1",
+ "base64 0.23.1",
"clap",
"console 0.15.11",
- "dirs",
+ "dirs 7.0.0",
"env_logger",
"futures",
"hex",
"include_dir",
"inquire",
"keyring",
- "log 0.4.29",
+ "log 0.4.34",
"oxc_resolver",
"predicates",
- "rand 0.8.7",
- "reqwest 0.12.20",
+ "rand 0.10.3",
+ "reqwest",
+ "rmcp",
"rolldown",
"schemars 0.8.22",
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
"tempfile",
"tokio",
"walkdir",
"webbrowser",
"yaak",
"yaak-api",
+ "yaak-common",
"yaak-core",
"yaak-crypto",
"yaak-http",
"yaak-lifecycle",
+ "yaak-mcp",
"yaak-models",
"yaak-plugins",
"yaak-templates",
- "zip",
+ "zip 9.0.5",
]
[[package]]
@@ -11384,7 +11514,7 @@ version = "0.0.0"
dependencies = [
"serde_json",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"yaak",
"yaak-core",
@@ -11399,6 +11529,7 @@ dependencies = [
name = "yaak-common"
version = "0.1.0"
dependencies = [
+ "dirs 7.0.0",
"serde_json",
"tokio",
]
@@ -11407,7 +11538,7 @@ dependencies = [
name = "yaak-core"
version = "0.0.0"
dependencies = [
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
]
[[package]]
@@ -11415,12 +11546,12 @@ name = "yaak-crypto"
version = "0.1.0"
dependencies = [
"base32",
- "base64 0.22.1",
+ "base64 0.23.1",
"chacha20poly1305",
"keyring",
- "log 0.4.29",
+ "log 0.4.34",
"serde",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"yaak-models",
]
@@ -11429,9 +11560,9 @@ name = "yaak-database"
version = "0.1.0"
dependencies = [
"chrono",
- "getrandom 0.2.16",
+ "getrandom 0.3.4",
"include_dir",
- "log 0.4.29",
+ "log 0.4.34",
"nanoid",
"r2d2",
"r2d2_sqlite",
@@ -11440,11 +11571,22 @@ dependencies = [
"sea-query-rusqlite",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"ts-rs",
"uuid",
]
+[[package]]
+name = "yaak-filter"
+version = "0.1.0"
+dependencies = [
+ "fancy-regex 0.19.2",
+ "indexmap 2.14.2",
+ "serde_json",
+ "sxd-document",
+ "sxd-xpath",
+]
+
[[package]]
name = "yaak-fonts"
version = "0.1.0"
@@ -11453,7 +11595,7 @@ dependencies = [
"serde",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"ts-rs",
]
@@ -11463,12 +11605,12 @@ version = "0.1.0"
dependencies = [
"chrono",
"git2",
- "log 0.4.29",
+ "log 0.4.34",
"serde",
"serde_json",
"serde_yaml",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"ts-rs",
"url",
@@ -11486,14 +11628,14 @@ dependencies = [
"dunce",
"hyper-rustls",
"hyper-util",
- "log 0.4.29",
- "md5 0.7.0",
+ "log 0.4.34",
+ "md5",
"prost",
"prost-reflect",
"prost-types",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"tokio-stream",
"tonic",
@@ -11510,21 +11652,21 @@ version = "0.1.0"
dependencies = [
"async-compression",
"async-trait",
- "brotli 7.0.0",
+ "brotli 9.1.1",
"bytes",
"cookie",
"flate2",
"futures-util",
"http-body",
"hyper-util",
- "log 0.4.29",
+ "log 0.4.34",
"mime_guess",
"native-tls",
- "reqwest 0.12.20",
+ "reqwest",
"serde",
"serde_json",
"tempfile",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"tokio-util",
"tower-service",
@@ -11542,13 +11684,13 @@ name = "yaak-license"
version = "0.1.0"
dependencies = [
"chrono",
- "log 0.4.29",
- "reqwest 0.12.20",
+ "log 0.4.34",
+ "reqwest",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"ts-rs",
"yaak-api",
"yaak-common",
@@ -11559,7 +11701,7 @@ dependencies = [
name = "yaak-lifecycle"
version = "0.0.0"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"yaak-models",
]
@@ -11569,13 +11711,32 @@ version = "0.1.0"
dependencies = [
"cocoa",
"csscolorparser",
- "log 0.4.29",
+ "log 0.4.34",
"objc",
- "rand 0.9.5",
+ "rand 0.10.3",
"tauri",
"tauri-plugin",
]
+[[package]]
+name = "yaak-mcp"
+version = "0.1.0"
+dependencies = [
+ "bytes",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "log 0.4.34",
+ "reqwest",
+ "rmcp",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tokio-util",
+ "yaak-models",
+ "yaak-plugins",
+]
+
[[package]]
name = "yaak-models"
version = "0.1.0"
@@ -11583,7 +11744,7 @@ dependencies = [
"chrono",
"hex",
"include_dir",
- "log 0.4.29",
+ "log 0.4.34",
"nanoid",
"r2d2",
"r2d2_sqlite",
@@ -11593,8 +11754,8 @@ dependencies = [
"sea-query-rusqlite",
"serde",
"serde_json",
- "sha2",
- "thiserror 2.0.17",
+ "sha2 0.10.9",
+ "thiserror 2.0.21",
"ts-rs",
"urlencoding",
"yaak-core",
@@ -11602,25 +11763,42 @@ dependencies = [
"yaak-templates",
]
+[[package]]
+name = "yaak-playground"
+version = "0.1.0"
+dependencies = [
+ "axum",
+ "bytes",
+ "clap",
+ "env_logger",
+ "log 0.4.34",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tower",
+ "tower-http 0.7.1",
+ "uuid",
+]
+
[[package]]
name = "yaak-plugins"
version = "0.1.0"
dependencies = [
- "base64 0.22.1",
+ "base64 0.23.1",
"chrono",
"dunce",
"futures-util",
"hex",
"keyring",
- "log 0.4.29",
- "md5 0.7.0",
+ "log 0.4.34",
+ "md5",
"path-slash",
- "rand 0.9.5",
- "reqwest 0.12.20",
+ "rand 0.10.3",
+ "reqwest",
"serde",
"serde_json",
- "sha2",
- "thiserror 2.0.17",
+ "sha2 0.10.9",
+ "thiserror 2.0.21",
"tokio",
"tokio-tungstenite",
"ts-rs",
@@ -11628,7 +11806,7 @@ dependencies = [
"yaak-crypto",
"yaak-models",
"yaak-templates",
- "zip-extract",
+ "zip 9.0.5",
]
[[package]]
@@ -11636,42 +11814,85 @@ name = "yaak-proxy"
version = "0.1.0"
dependencies = [
"bytes",
+ "futures-util",
"http",
"http-body-util",
"hyper",
"hyper-util",
+ "log 0.4.34",
"pem",
"rcgen",
+ "reqwest",
"rustls",
"rustls-native-certs",
+ "tempfile",
+ "time",
"tokio",
"tokio-rustls",
+ "tokio-tungstenite",
+]
+
+[[package]]
+name = "yaak-proxy-helper"
+version = "0.0.0"
+dependencies = [
+ "core-foundation 0.10.1",
+ "libc",
+ "security-framework 3.7.0",
+ "serde",
+ "serde_json",
+ "tempfile",
+ "ts-rs",
]
[[package]]
name = "yaak-proxy-lib"
version = "0.0.0"
dependencies = [
+ "base64 0.23.1",
+ "bytes",
"chrono",
+ "encoding_rs",
+ "flate2",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
"include_dir",
- "log 0.4.29",
+ "libc",
+ "log 0.4.34",
+ "objc2 0.6.5",
+ "objc2-app-kit",
+ "objc2-foundation 0.3.2",
+ "objc2-service-management",
+ "plist",
"r2d2",
"r2d2_sqlite",
+ "reqwest",
"rusqlite",
"sea-query",
"serde",
"serde_json",
+ "tempfile",
+ "tokio",
"ts-rs",
+ "url",
+ "yaak-common",
"yaak-database",
+ "yaak-filter",
+ "yaak-http",
+ "yaak-lifecycle",
+ "yaak-models",
"yaak-proxy",
+ "yaak-proxy-helper",
"yaak-rpc",
+ "yaak-templates",
]
[[package]]
name = "yaak-rpc"
version = "0.0.0"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"serde",
"serde_json",
"ts-rs",
@@ -11707,14 +11928,15 @@ version = "0.1.0"
dependencies = [
"chrono",
"hex",
- "log 0.4.29",
+ "log 0.4.34",
"notify",
"serde",
"serde_json",
"serde_path_to_error",
"serde_yaml",
- "sha1",
- "thiserror 2.0.17",
+ "sha1 0.11.0",
+ "tempfile",
+ "thiserror 2.0.21",
"tokio",
"ts-rs",
"yaak-models",
@@ -11726,9 +11948,9 @@ version = "0.1.0"
dependencies = [
"dark-light",
"dispatch2",
- "log 0.4.29",
+ "log 0.4.34",
"objc2-app-kit",
- "objc2-foundation 0.3.1",
+ "objc2-foundation 0.3.2",
"tauri",
]
@@ -11736,7 +11958,7 @@ dependencies = [
name = "yaak-tauri-utils"
version = "0.1.0"
dependencies = [
- "regex 1.11.1",
+ "regex 1.13.1",
"tauri",
"yaak-core",
]
@@ -11745,12 +11967,12 @@ dependencies = [
name = "yaak-templates"
version = "0.1.0"
dependencies = [
- "base64 0.22.1",
- "log 0.4.29",
+ "base64 0.23.1",
+ "log 0.4.34",
"serde",
"serde-wasm-bindgen",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"ts-rs",
"wasm-bindgen",
@@ -11760,17 +11982,17 @@ dependencies = [
name = "yaak-tls"
version = "0.1.0"
dependencies = [
- "log 0.4.29",
+ "log 0.4.34",
"p12",
"pem",
"rustls",
"rustls-pemfile",
"rustls-platform-verifier",
"serde",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"url",
"yaak-models",
- "yasna",
+ "yasna 0.6.0",
]
[[package]]
@@ -11779,7 +12001,7 @@ version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"js-sys",
- "log 0.4.29",
+ "log 0.4.34",
"serde",
"serde-wasm-bindgen",
"serde_json",
@@ -11799,16 +12021,18 @@ version = "0.1.0"
dependencies = [
"async-trait",
"axum",
- "base64 0.22.1",
+ "base64 0.23.1",
"bytes",
"clap",
"env_logger",
"futures-util",
- "log 0.4.29",
+ "log 0.4.34",
"serde",
"serde_json",
+ "tempfile",
"tokio",
- "tower-http",
+ "tower",
+ "tower-http 0.7.1",
"ts-rs",
"url",
"uuid",
@@ -11820,9 +12044,9 @@ dependencies = [
name = "yaak-window"
version = "0.1.0"
dependencies = [
- "log 0.4.29",
- "md5 0.8.0",
- "rand 0.9.5",
+ "log 0.4.34",
+ "md5",
+ "rand 0.10.3",
"serde",
"serde_json",
"tauri",
@@ -11835,11 +12059,11 @@ version = "0.1.0"
dependencies = [
"futures-util",
"http",
- "log 0.4.29",
- "md5 0.8.0",
+ "log 0.4.34",
+ "md5",
"serde",
"serde_json",
- "thiserror 2.0.17",
+ "thiserror 2.0.21",
"tokio",
"tokio-tungstenite",
"url",
@@ -11864,6 +12088,12 @@ dependencies = [
"time",
]
+[[package]]
+name = "yasna"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282"
+
[[package]]
name = "yoke"
version = "0.8.0"
@@ -11884,15 +12114,15 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
"synstructure",
]
[[package]]
name = "zbus"
-version = "5.11.0"
+version = "5.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d07e46d035fb8e375b2ce63ba4e4ff90a7f73cf2ffb0138b29e1158d2eaadf7"
+checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907"
dependencies = [
"async-broadcast",
"async-executor",
@@ -11904,19 +12134,21 @@ dependencies = [
"async-trait",
"blocking",
"enumflags2",
- "event-listener 5.4.0",
+ "event-listener",
"futures-core",
"futures-lite",
"hex",
- "nix 0.30.1",
+ "libc",
"ordered-stream",
+ "rustix 1.1.5",
"serde",
"serde_repr",
"tokio",
"tracing",
"uds_windows",
- "windows-sys 0.60.2",
- "winnow 0.7.10",
+ "uuid",
+ "windows-sys 0.61.2",
+ "winnow 1.0.2",
"zbus_macros",
"zbus_names",
"zvariant",
@@ -11924,14 +12156,14 @@ dependencies = [
[[package]]
name = "zbus_macros"
-version = "5.11.0"
+version = "5.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57e797a9c847ed3ccc5b6254e8bcce056494b375b511b3d6edcec0aeb4defaca"
+checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40"
dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
"zbus_names",
"zvariant",
"zvariant_utils",
@@ -11939,16 +12171,24 @@ dependencies = [
[[package]]
name = "zbus_names"
-version = "4.2.0"
+version = "4.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
+checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e"
dependencies = [
"serde",
- "static_assertions",
- "winnow 0.7.10",
+ "winnow 1.0.2",
"zvariant",
]
+[[package]]
+name = "zcheapstr"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "zerocopy"
version = "0.8.25"
@@ -11966,7 +12206,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -11986,7 +12226,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
"synstructure",
]
@@ -12007,7 +12247,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
@@ -12040,87 +12280,96 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 2.0.119",
]
[[package]]
name = "zip"
-version = "4.0.0"
+version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "153a6fff49d264c4babdcfa6b4d534747f520e56e8f0f384f3b808c4b64cc1fd"
+checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1"
+dependencies = [
+ "arbitrary",
+ "crc32fast",
+ "indexmap 2.14.2",
+ "memchr",
+]
+
+[[package]]
+name = "zip"
+version = "9.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e04976da629d3b04204ba8105b396a193af8ad2583b2c79bfb3ab8af580a11e"
dependencies = [
"aes",
- "arbitrary",
- "bzip2 0.5.2",
- "constant_time_eq 0.3.1",
+ "bzip2",
+ "constant_time_eq 0.6.1",
"crc32fast",
"deflate64",
"flate2",
- "getrandom 0.3.3",
- "hmac",
- "indexmap 2.14.0",
- "liblzma",
+ "getrandom 0.4.3",
+ "hmac 0.13.0",
+ "indexmap 2.14.2",
+ "lzma-rust2",
"memchr",
+ "nix 0.31.3",
"pbkdf2",
- "sha1",
+ "ppmd-rust",
+ "sha1 0.11.0",
"time",
+ "typed-path",
"zeroize",
"zopfli",
"zstd",
]
[[package]]
-name = "zip-extract"
-version = "0.4.0"
+name = "zlib-rs"
+version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aed5f10c571472911e37d8f7601a8dfba52b4f7f73a344015291b82ab292faf6"
-dependencies = [
- "log 0.4.29",
- "thiserror 2.0.17",
- "zip",
-]
+checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12"
[[package]]
-name = "zlib-rs"
-version = "0.5.1"
+name = "zmij"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
[[package]]
name = "zopfli"
-version = "0.8.2"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7"
+checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249"
dependencies = [
"bumpalo",
"crc32fast",
- "log 0.4.29",
+ "log 0.4.34",
"simd-adler32",
]
[[package]]
name = "zstd"
-version = "0.13.3"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
+checksum = "bf06bd8162af0734b344780deb55b42a2429ae430870d13fcc12f238e880fe6e"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
-version = "7.2.4"
+version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
+checksum = "ae42c0555055784c70058d19ba8e275528e8a99a706684868ace5da4e716a4ab"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
-version = "2.0.15+zstd.1.5.7"
+version = "2.1.0+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
+checksum = "0ef0a8027ec3ee71300ab3bcbcd0393f434aa72b91ca6d635a39941deae8eea0"
dependencies = [
"cc",
"pkg-config",
@@ -12128,42 +12377,42 @@ dependencies = [
[[package]]
name = "zvariant"
-version = "5.5.3"
+version = "5.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d30786f75e393ee63a21de4f9074d4c038d52c5b1bb4471f955db249f9dffb1"
+checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147"
dependencies = [
"endi",
"enumflags2",
"serde",
"url",
- "winnow 0.7.10",
+ "winnow 1.0.2",
+ "zcheapstr",
"zvariant_derive",
"zvariant_utils",
]
[[package]]
name = "zvariant_derive"
-version = "5.5.3"
+version = "5.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75fda702cd42d735ccd48117b1630432219c0e9616bf6cb0f8350844ee4d9580"
+checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497"
dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.101",
+ "syn 3.0.3",
"zvariant_utils",
]
[[package]]
name = "zvariant_utils"
-version = "3.2.0"
+version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34"
+checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3"
dependencies = [
"proc-macro2",
"quote",
"serde",
- "static_assertions",
- "syn 2.0.101",
- "winnow 0.7.10",
+ "syn 3.0.3",
+ "winnow 1.0.2",
]
diff --git a/Cargo.toml b/Cargo.toml
index 772e679de..40557a8ea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,10 +11,12 @@ members = [
"crates/yaak-core",
"crates/yaak-common",
"crates/yaak-crypto",
+ "crates/yaak-filter",
"crates/yaak-git",
"crates/yaak-grpc",
"crates/yaak-http",
"crates/yaak-lifecycle",
+ "crates/yaak-mcp",
"crates/yaak-models",
"crates/yaak-plugins",
"crates/yaak-sse",
@@ -29,6 +31,7 @@ members = [
"crates-proxy/yaak-proxy-lib",
# Server crates (the browser tier's hosted send executor)
"crates-server/yaak-web",
+ "crates-server/yaak-playground",
# CLI crates
"crates-cli/yaak-cli",
# Tauri-specific crates
@@ -37,6 +40,7 @@ members = [
"crates-tauri/yaak-fonts",
"crates-tauri/yaak-license",
"crates-tauri/yaak-mac-window",
+ "crates-tauri/yaak-proxy-helper",
"crates-tauri/yaak-system-appearance",
"crates-tauri/yaak-tauri-utils",
"crates-tauri/yaak-window",
@@ -47,9 +51,16 @@ chrono = "0.4.42"
hex = "0.4.3"
keyring = "3.6.3"
log = "0.4.29"
-reqwest = "0.12.20"
+reqwest = { version = "0.13.5", default-features = false, features = [
+ # reqwest 0.13 switched `default-tls` from native-tls to rustls; keep the
+ # rest of the old default set and stay on native-tls.
+ "charset",
+ "http2",
+ "system-proxy",
+ "native-tls",
+] }
rustls = { version = "0.23.34", default-features = false }
-rustls-platform-verifier = "0.6.2"
+rustls-platform-verifier = "0.7.1"
schemars = { version = "0.8.22", features = ["chrono"] }
serde = "1.0.228"
serde_json = "1.0.145"
@@ -77,10 +88,12 @@ yaak = { path = "crates/yaak" }
yaak-commands = { path = "crates/yaak-commands" }
yaak-common = { path = "crates/yaak-common" }
yaak-crypto = { path = "crates/yaak-crypto" }
+yaak-filter = { path = "crates/yaak-filter" }
yaak-git = { path = "crates/yaak-git" }
yaak-grpc = { path = "crates/yaak-grpc" }
yaak-http = { path = "crates/yaak-http" }
yaak-lifecycle = { path = "crates/yaak-lifecycle" }
+yaak-mcp = { path = "crates/yaak-mcp" }
yaak-models = { path = "crates/yaak-models" }
yaak-plugins = { path = "crates/yaak-plugins" }
yaak-sse = { path = "crates/yaak-sse" }
@@ -98,6 +111,7 @@ yaak-proxy-lib = { path = "crates-proxy/yaak-proxy-lib" }
yaak-fonts = { path = "crates-tauri/yaak-fonts" }
yaak-license = { path = "crates-tauri/yaak-license" }
yaak-mac-window = { path = "crates-tauri/yaak-mac-window" }
+yaak-proxy-helper = { path = "crates-tauri/yaak-proxy-helper" }
yaak-system-appearance = { path = "crates-tauri/yaak-system-appearance" }
yaak-tauri-utils = { path = "crates-tauri/yaak-tauri-utils" }
yaak-window = { path = "crates-tauri/yaak-window" }
diff --git a/Dockerfile.playground b/Dockerfile.playground
new file mode 100644
index 000000000..e631eb190
--- /dev/null
+++ b/Dockerfile.playground
@@ -0,0 +1,15 @@
+# syntax=docker/dockerfile:1
+# The playground API behind yaak.run. See crates-server/yaak-playground/README.md.
+
+FROM rust:1-bookworm AS build
+WORKDIR /app
+COPY . .
+RUN cargo build --release -p yaak-playground
+
+FROM debian:bookworm-slim
+COPY --from=build /app/target/release/yaak-playground /usr/local/bin/yaak-playground
+ENV HOST=0.0.0.0
+ENV PORT=8080
+EXPOSE 8080
+USER nobody
+CMD ["yaak-playground"]
diff --git a/Dockerfile.web b/Dockerfile.web
index dba755ccc..460b5a1e8 100644
--- a/Dockerfile.web
+++ b/Dockerfile.web
@@ -38,7 +38,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates libssl3 && rm -rf /var/lib/apt/lists/*
COPY --from=server /app/target/release/yaak-web /usr/local/bin/yaak-web
COPY --from=web /app/dist/apps/yaak-client /srv
-ENV YAAK_WEB_BIND=0.0.0.0:8080
+# 0.0.0.0 so the port is reachable from outside the container. PORT is the variable a
+# platform-as-a-service assigns, so a deploy that sets it needs nothing else changed.
+ENV HOST=0.0.0.0
+ENV PORT=8080
EXPOSE 8080
USER nobody
# Overriding the command (dropping --serve) leaves the stateless send executor:
diff --git a/README.md b/README.md
index df97f9612..7778b212c 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
-
+
@@ -25,6 +25,10 @@

+## Install
+
+Download Yaak for macOS, Windows, or Linux from [yaak.app/download](https://yaak.app/download). Package managers and other install methods are in the [installation docs](https://yaak.app/docs/getting-started/installation).
+
## Features
Yaak is an offline-first API client designed to stay out of your way while giving you everything you need when you need it.
@@ -68,3 +72,9 @@ Built with [Tauri](https://tauri.app), Rust, and React, it’s fast, lightweight
- [Yaak vs Postman](https://yaak.app/alternatives/postman)
- [Yaak vs Bruno](https://yaak.app/alternatives/bruno)
- [Yaak vs Insomnia](https://yaak.app/alternatives/insomnia)
+
+## License
+
+The source is [MIT licensed](LICENSE) and can be built and run for free, for both personal and commercial use.
+
+The prebuilt binaries follow Yaak's [pricing terms](https://yaak.app/pricing): free for personal use, license required for commercial use.
diff --git a/apps/yaak-client/commands/commands.test.tsx b/apps/yaak-client/commands/commands.test.tsx
new file mode 100644
index 000000000..eef1f85ca
--- /dev/null
+++ b/apps/yaak-client/commands/commands.test.tsx
@@ -0,0 +1,148 @@
+import type { FunctionComponent, ReactElement } from "react";
+import { beforeEach, expect, test, vi } from "vite-plus/test";
+import type { SyncOp } from "@yaakapp-internal/sync/bindings/gen_sync";
+import type { DialogInstance } from "../components/Dialogs";
+import { syncWorkspace } from "./commands";
+
+const mocks = vi.hoisted(() => ({
+ calculateSync: vi.fn(),
+ applySync: vi.fn(),
+ showDialog: vi.fn<(dialog: DialogInstance) => void>(),
+ hideDialog: vi.fn(),
+ showToast: vi.fn(),
+}));
+
+vi.mock("@yaakapp-internal/sync", () => mocks);
+vi.mock("@yaakapp-internal/models", () => ({
+ createWorkspaceModel: vi.fn(),
+ modelTypeLabel: () => "Request",
+}));
+vi.mock("@yaakapp-internal/ui", () => ({
+ Banner: "div",
+ InlineCode: "code",
+ Table: "table",
+ TableBody: "tbody",
+ TableCell: "td",
+ TableHead: "thead",
+ TableHeaderCell: "th",
+ TableRow: "tr",
+ TruncatedWideTableCell: "td",
+}));
+vi.mock("../components/core/Button", () => ({ Button: "button" }));
+vi.mock("../hooks/useActiveWorkspace", () => ({ activeWorkspaceIdAtom: null }));
+vi.mock("../lib/dialog", () => mocks);
+vi.mock("../lib/jotai", () => ({ jotaiStore: { get: vi.fn() } }));
+vi.mock("../lib/prompt", () => ({ showPrompt: vi.fn() }));
+vi.mock("../lib/resolvedModelName", () => ({ resolvedModelNameWithFolders: () => "Request" }));
+vi.mock("../lib/toast", () => mocks);
+
+const staleToast = expect.objectContaining({
+ message: "Files changed while syncing. Review the changes again.",
+});
+
+const params = { workspaceId: "wk_test", syncDir: "/sync" };
+const deletion = {
+ type: "dbDelete",
+ model: { id: "rq_test", model: "http_request" },
+ state: {},
+} as Extract;
+const update = {
+ type: "dbUpdate",
+ model: { id: "rq_test", model: "http_request" },
+ fs: { model: { id: "rq_test", model: "http_request", name: "Updated" } },
+ state: {},
+} as Extract;
+
+async function submit(dialog: DialogInstance) {
+ const render = dialog.render as FunctionComponent<{ hide: () => void }>;
+ const form = render({ hide: () => mocks.hideDialog(dialog.id) }) as ReactElement<{
+ onSubmit: (event: { preventDefault: () => void }) => Promise;
+ }>;
+ await form.props.onSubmit({ preventDefault: vi.fn() });
+}
+
+function latestDialog() {
+ const dialog = mocks.showDialog.mock.calls.at(-1)?.[0];
+ if (dialog == null) throw new Error("Expected a sync dialog");
+ return dialog;
+}
+
+beforeEach(() => {
+ vi.resetAllMocks();
+ mocks.applySync.mockResolvedValue(true);
+});
+
+test("closes an obsolete dialog when the restored file leaves no changes", async () => {
+ mocks.calculateSync.mockResolvedValueOnce([deletion]).mockResolvedValueOnce([]);
+ await syncWorkspace.mutateAsync(params);
+ mocks.applySync.mockResolvedValueOnce(false);
+
+ await submit(latestDialog());
+
+ expect(mocks.applySync).toHaveBeenCalledTimes(1);
+ expect(mocks.applySync).toHaveBeenCalledWith(params.workspaceId, params.syncDir, [deletion]);
+ expect(mocks.hideDialog).toHaveBeenCalledWith("commit-sync");
+ expect(mocks.showDialog).toHaveBeenCalledTimes(1);
+});
+
+test("requires another confirmation for a changed plan", async () => {
+ mocks.calculateSync.mockResolvedValueOnce([deletion]).mockResolvedValueOnce([update]);
+ await syncWorkspace.mutateAsync(params);
+ const original = latestDialog();
+ mocks.applySync.mockResolvedValueOnce(false);
+
+ await submit(original);
+
+ expect(mocks.applySync).toHaveBeenCalledTimes(1);
+ expect(mocks.showDialog).toHaveBeenCalledTimes(2);
+ expect(mocks.showToast).toHaveBeenCalledWith(staleToast);
+ expect(mocks.hideDialog).not.toHaveBeenCalled();
+ await submit(latestDialog());
+ expect(mocks.applySync).toHaveBeenLastCalledWith(params.workspaceId, params.syncDir, [update]);
+ expect(mocks.hideDialog).toHaveBeenCalledWith("commit-sync");
+});
+
+test("applies an unchanged reviewed plan and closes the dialog", async () => {
+ mocks.calculateSync.mockResolvedValue([update]);
+ await syncWorkspace.mutateAsync(params);
+ await submit(latestDialog());
+
+ expect(mocks.calculateSync).toHaveBeenCalledTimes(1);
+ expect(mocks.applySync).toHaveBeenCalledTimes(1);
+ expect(mocks.hideDialog).toHaveBeenCalledWith("commit-sync");
+});
+
+test("forced sync retries the current plan without requesting another confirmation", async () => {
+ mocks.calculateSync.mockResolvedValueOnce([deletion]).mockResolvedValueOnce([update]);
+ mocks.applySync.mockResolvedValueOnce(false);
+
+ await syncWorkspace.mutateAsync({ ...params, force: true });
+
+ expect(mocks.applySync).toHaveBeenCalledTimes(2);
+ expect(mocks.applySync).toHaveBeenLastCalledWith(params.workspaceId, params.syncDir, [update]);
+ expect(mocks.showDialog).not.toHaveBeenCalled();
+});
+
+test("outbound-only changes clear the old dialog and sync automatically", async () => {
+ const outbound = { type: "fsUpdate", model: update.model, state: {} } as SyncOp;
+ mocks.calculateSync.mockResolvedValueOnce([deletion]).mockResolvedValueOnce([outbound]);
+ await syncWorkspace.mutateAsync(params);
+ await syncWorkspace.mutateAsync(params);
+
+ expect(mocks.applySync).toHaveBeenCalledWith(params.workspaceId, params.syncDir, [outbound]);
+ expect(mocks.hideDialog).toHaveBeenCalledWith("commit-sync");
+ expect(mocks.showDialog).toHaveBeenCalledTimes(1);
+});
+
+test("stops retrying a plan that keeps going stale", async () => {
+ mocks.calculateSync.mockResolvedValue([update]);
+ mocks.applySync.mockResolvedValue(false);
+
+ await syncWorkspace.mutateAsync({ ...params, force: true });
+
+ expect(mocks.calculateSync).toHaveBeenCalledTimes(3);
+ expect(mocks.applySync).toHaveBeenCalledTimes(3);
+ expect(mocks.showToast).toHaveBeenCalledTimes(1);
+ expect(mocks.showToast).toHaveBeenCalledWith(staleToast);
+ expect(mocks.showDialog).not.toHaveBeenCalled();
+});
diff --git a/apps/yaak-client/commands/commands.tsx b/apps/yaak-client/commands/commands.tsx
index 40618a77a..dc9a7adbc 100644
--- a/apps/yaak-client/commands/commands.tsx
+++ b/apps/yaak-client/commands/commands.tsx
@@ -14,11 +14,12 @@ import {
} from "@yaakapp-internal/ui";
import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
import { createFastMutation } from "../hooks/useFastMutation";
-import { showDialog } from "../lib/dialog";
+import { hideDialog, showDialog } from "../lib/dialog";
import { jotaiStore } from "../lib/jotai";
-import { pluralizeCount } from "../lib/pluralize";
import { showPrompt } from "../lib/prompt";
import { resolvedModelNameWithFolders } from "../lib/resolvedModelName";
+import { showToast } from "../lib/toast";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
export const createFolder = createFastMutation<
string | null,
@@ -52,24 +53,48 @@ export const createFolder = createFastMutation<
},
});
+// Files can keep changing under a plan, so stop recalculating after a few stale applies.
+const MAX_SYNC_ATTEMPTS = 3;
+
+function showStaleSyncToast() {
+ showToast({
+ id: "sync-stale",
+ color: "warning",
+ message: "Files changed while syncing. Review the changes again.",
+ });
+}
+
export const syncWorkspace = createFastMutation<
void,
void,
- { workspaceId: string; syncDir: string; force?: boolean }
+ { workspaceId: string; syncDir: string; force?: boolean; attempt?: number }
>({
mutationKey: [],
- mutationFn: async ({ workspaceId, syncDir, force }) => {
+ mutationFn: async ({ workspaceId, syncDir, force, attempt = 1 }) => {
const ops = (await calculateSync(workspaceId, syncDir)) ?? [];
if (ops.length === 0) {
console.log("Nothing to sync", workspaceId, syncDir);
+ hideDialog("commit-sync");
return;
}
console.log("Syncing workspace", workspaceId, syncDir, ops);
const dbOps = ops.filter((o) => o.type.startsWith("db"));
- if (dbOps.length === 0) {
- await applySync(workspaceId, syncDir, ops);
+ const apply = async () => {
+ if (await applySync(workspaceId, syncDir, ops)) {
+ hideDialog("commit-sync");
+ } else if (attempt < MAX_SYNC_ATTEMPTS) {
+ await syncWorkspace.mutateAsync({ workspaceId, syncDir, force, attempt: attempt + 1 });
+ } else {
+ hideDialog("commit-sync");
+ showStaleSyncToast();
+ }
+ };
+
+ if (dbOps.length === 0 || force) {
+ hideDialog("commit-sync");
+ await apply();
return;
}
@@ -79,9 +104,8 @@ export const syncWorkspace = createFastMutation<
console.log("Directory changes detected", { dbOps, ops });
- if (force) {
- await applySync(workspaceId, syncDir, ops);
- return;
+ if (attempt > 1) {
+ showStaleSyncToast();
}
showDialog({
@@ -93,8 +117,7 @@ export const syncWorkspace = createFastMutation<
className="h-full grid grid-rows-[auto_auto_minmax(0,1fr)_auto] gap-3"
onSubmit={async (e) => {
e.preventDefault();
- await applySync(workspaceId, syncDir, ops);
- hide();
+ await apply();
}}
>
{isDeletingWorkspace ? (
diff --git a/apps/yaak-client/commands/createEnvironment.tsx b/apps/yaak-client/commands/createEnvironment.tsx
index 80f68e10f..acd81efa7 100644
--- a/apps/yaak-client/commands/createEnvironment.tsx
+++ b/apps/yaak-client/commands/createEnvironment.tsx
@@ -6,11 +6,12 @@ import { showDialog } from "../lib/dialog";
import { jotaiStore } from "../lib/jotai";
import { setWorkspaceSearchParams } from "../lib/setWorkspaceSearchParams";
-export const createSubEnvironmentAndActivate = createFastMutation<
- string | null,
- unknown,
- Environment | null
->({
+/**
+ * Prompt for and create a sub-environment of the given base environment, resolving with the new
+ * environment's ID (or null if the dialog was dismissed). This does not change the workspace's
+ * active environment.
+ */
+export const createSubEnvironment = createFastMutation({
mutationKey: ["create_environment"],
mutationFn: async (baseEnvironment) => {
if (baseEnvironment == null) {
@@ -41,6 +42,17 @@ export const createSubEnvironmentAndActivate = createFastMutation<
});
});
},
+});
+
+/** Same as {@link createSubEnvironment}, but also makes the new environment the active one. */
+export const createSubEnvironmentAndActivate = createFastMutation<
+ string | null,
+ unknown,
+ Environment | null
+>({
+ mutationKey: ["create_environment_and_activate"],
+ mutationFn: (baseEnvironment) => createSubEnvironment.mutateAsync(baseEnvironment),
+ disableToastError: true, // Already shown by createSubEnvironment
onSuccess: async (environmentId) => {
if (environmentId == null) {
return; // Was not created
diff --git a/apps/yaak-client/commands/moveToWorkspace.tsx b/apps/yaak-client/commands/moveToWorkspace.tsx
index 3428a5805..c88432937 100644
--- a/apps/yaak-client/commands/moveToWorkspace.tsx
+++ b/apps/yaak-client/commands/moveToWorkspace.tsx
@@ -3,9 +3,9 @@ import type { GrpcRequest, HttpRequest, WebsocketRequest } from "@yaakapp-intern
import { MoveToWorkspaceDialog } from "../components/MoveToWorkspaceDialog";
import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
import { createFastMutation } from "../hooks/useFastMutation";
-import { pluralizeCount } from "../lib/pluralize";
import { showDialog } from "../lib/dialog";
import { jotaiStore } from "../lib/jotai";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
export const moveToWorkspace = createFastMutation({
mutationKey: ["move_workspace"],
diff --git a/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx b/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx
index 9c5b6d2f0..b12d90d84 100644
--- a/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx
+++ b/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx
@@ -17,7 +17,7 @@ export const openWorkspaceFromSyncDir = createFastMutation({
return;
}
- await applySync(workspace.id, dir, ops);
+ await applySync(workspace.id, dir, ops, { fsOnly: true });
await router.navigate({
to: "/workspaces/$workspaceId",
diff --git a/apps/yaak-client/components/ClientEditorHost.tsx b/apps/yaak-client/components/ClientEditorHost.tsx
new file mode 100644
index 000000000..48151927e
--- /dev/null
+++ b/apps/yaak-client/components/ClientEditorHost.tsx
@@ -0,0 +1,99 @@
+import { platform } from "@yaakapp-internal/platform";
+import {
+ Banner,
+ type EditorHost,
+ EditorHostProvider,
+ EmptyStateText,
+ type HostBodyViewerArgs,
+ type HttpBodyLoader,
+ LoadingIcon,
+ type StoredValue,
+ type StoredValueNamespace,
+} from "@yaakapp-internal/ui";
+import { lazy, type ReactNode, Suspense } from "react";
+import { useKeyValue } from "../hooks/useKeyValue";
+import { copyToClipboard } from "../lib/copy";
+import { showDialog } from "../lib/dialog";
+import { showPrompt } from "../lib/prompt";
+import { useDetailsBannerStoredValue } from "./core/DetailsBanner";
+import { Editor } from "./core/Editor/LazyEditor";
+import { Input } from "./core/Input";
+import { ErrorBoundary } from "./ErrorBoundary";
+import { MultipartViewer } from "./responseViewers/MultipartViewer";
+import { TextViewer } from "./responseViewers/TextViewer";
+import { SelectFile } from "./SelectFile";
+
+const PdfViewer = lazy(() =>
+ import("./responseViewers/PdfViewer").then((m) => ({ default: m.PdfViewer })),
+);
+
+function useClientStoredValue(
+ key: string | string[] | null,
+ fallback: T,
+ namespace: StoredValueNamespace = "global",
+) {
+ // A null key is never written by the shared components, so any stable key will do
+ const { value, set } = useKeyValue({ namespace, key: key ?? ["tabs", "default"], fallback });
+ return [value ?? fallback, set] as const;
+}
+
+function renderBodyViewer({ source, mimeType, body, complete }: HostBodyViewerArgs) {
+ if (!mimeType?.match(/pdf/i)) return null;
+ return source === "response" ? (
+
+ ) : (
+
+ );
+}
+
+/** Waits for the whole response, then loads the PDF from its file */
+function PdfResponseBody({ body, complete }: { body: HttpBodyLoader; complete: boolean }) {
+ const bodyUrl = body.useUrl(complete);
+
+ if (!complete || bodyUrl.isLoading) {
+ return (
+
+
+
+ );
+ }
+ if (bodyUrl.error) {
+ return {String(bodyUrl.error)};
+ }
+ if (bodyUrl.data == null) {
+ return Empty response body
;
+ }
+ return ;
+}
+
+function PdfRequestBody({ body }: { body: HttpBodyLoader }) {
+ const bytes = body.useBytes();
+ if (bytes.data == null) return null;
+ return (
+ }>
+
+
+ );
+}
+
+const clientEditorHost: EditorHost = {
+ Editor,
+ Input,
+ SelectFile,
+ showDialog,
+ showPrompt,
+ basename: (path) => platform.files.basename(path),
+ useStoredValue: useClientStoredValue,
+ useDetailsBannerStoredValue,
+ ErrorBoundary,
+ TextViewer,
+ MultipartViewer,
+ renderBodyViewer,
+ openUrl: (url) => platform.openUrl(url),
+ copy: (text) => copyToClipboard(text, { disableToast: true }),
+};
+
+/** Gives the shared editing components the client's templated editor, dialogs and storage */
+export function ClientEditorHost({ children }: { children: ReactNode }) {
+ return {children};
+}
diff --git a/apps/yaak-client/components/CloneGitRepositoryDialog.tsx b/apps/yaak-client/components/CloneGitRepositoryDialog.tsx
index 160211018..dcba92539 100644
--- a/apps/yaak-client/components/CloneGitRepositoryDialog.tsx
+++ b/apps/yaak-client/components/CloneGitRepositoryDialog.tsx
@@ -1,12 +1,12 @@
import { gitClone } from "@yaakapp-internal/git";
import { Banner, VStack } from "@yaakapp-internal/ui";
-import { useState } from "react";
+import { useId, useState } from "react";
import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir";
import { appInfo } from "../lib/appInfo";
import { CommercialUseBanner } from "./CommercialUseBanner";
import { showErrorToast } from "../lib/toast";
-import { Button } from "./core/Button";
import { Checkbox } from "./core/Checkbox";
+import { DialogFooter } from "./core/Dialog";
import { IconButton } from "./core/IconButton";
import { PlainInput } from "./core/PlainInput";
import { promptCredentials } from "./git/credentials";
@@ -29,6 +29,7 @@ export function CloneGitRepositoryDialog({ hide }: Props) {
const [subdirectory, setSubdirectory] = useState("");
const [isCloning, setIsCloning] = useState(false);
const [error, setError] = useState(null);
+ const formId = useId();
const repoName = extractRepoName(url);
const sep = getPathSeparator(baseDirectory);
@@ -83,7 +84,7 @@ export function CloneGitRepositoryDialog({ hide }: Props) {
};
return (
-
+
{error && (
{error}
@@ -132,15 +133,17 @@ export function CloneGitRepositoryDialog({ hide }: Props) {
/>
)}
-
+
);
}
diff --git a/apps/yaak-client/components/ConfirmLargeRequestBody.tsx b/apps/yaak-client/components/ConfirmLargeRequestBody.tsx
index f8acf535e..31956044b 100644
--- a/apps/yaak-client/components/ConfirmLargeRequestBody.tsx
+++ b/apps/yaak-client/components/ConfirmLargeRequestBody.tsx
@@ -1,12 +1,11 @@
import type { HttpRequest } from "@yaakapp-internal/models";
import { patchModel } from "@yaakapp-internal/models";
-import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui";
+import { Banner, HStack, InlineCode, SizeTag } from "@yaakapp-internal/ui";
import type { ReactNode } from "react";
import { useToggle } from "../hooks/useToggle";
import { showConfirm } from "../lib/confirm";
import { Button } from "./core/Button";
import { Link } from "./core/Link";
-import { SizeTag } from "./core/SizeTag";
interface Props {
children: ReactNode;
diff --git a/apps/yaak-client/components/ConfirmLargeResponse.tsx b/apps/yaak-client/components/ConfirmLargeResponse.tsx
deleted file mode 100644
index 90bb2c850..000000000
--- a/apps/yaak-client/components/ConfirmLargeResponse.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import type { HttpResponse } from "@yaakapp-internal/models";
-import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui";
-import { type ReactNode, useMemo } from "react";
-import { useSaveResponse } from "../hooks/useSaveResponse";
-import { useToggle } from "../hooks/useToggle";
-import { isProbablyTextContentType } from "../lib/contentType";
-import { getContentTypeFromHeaders } from "../lib/model_util";
-import { getResponseBodyText } from "../lib/responseBody";
-import { CopyButton } from "./CopyButton";
-import { Button } from "./core/Button";
-import { SizeTag } from "./core/SizeTag";
-
-interface Props {
- children: ReactNode;
- response: HttpResponse;
-}
-
-const LARGE_BYTES = 2 * 1000 * 1000;
-
-export function ConfirmLargeResponse({ children, response }: Props) {
- const { mutate: saveResponse } = useSaveResponse(response);
- const [showLargeResponse, toggleShowLargeResponse] = useToggle();
- const isProbablyText = useMemo(() => {
- const contentType = getContentTypeFromHeaders(response.headers);
- return isProbablyTextContentType(contentType);
- }, [response.headers]);
-
- const contentLength = response.contentLength ?? 0;
- const isLarge = contentLength > LARGE_BYTES;
- if (!showLargeResponse && isLarge) {
- return (
-
-
- Showing responses over{" "}
-
-
- {" "}
- may impact performance
-
-
-
-
- {isProbablyText && (
- getResponseBodyText({ response, filter: null })}
- />
- )}
-
-
- );
- }
-
- return <>{children}>;
-}
diff --git a/apps/yaak-client/components/ConfirmLargeResponseRequest.tsx b/apps/yaak-client/components/ConfirmLargeResponseRequest.tsx
deleted file mode 100644
index 92525f705..000000000
--- a/apps/yaak-client/components/ConfirmLargeResponseRequest.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import type { HttpResponse } from "@yaakapp-internal/models";
-import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui";
-import { type ReactNode, useMemo } from "react";
-import { getRequestBodyText as getHttpResponseRequestBodyText } from "../hooks/useHttpRequestBody";
-import { useToggle } from "../hooks/useToggle";
-import { isProbablyTextContentType } from "../lib/contentType";
-import { getContentTypeFromHeaders } from "../lib/model_util";
-import { CopyButton } from "./CopyButton";
-import { Button } from "./core/Button";
-import { SizeTag } from "./core/SizeTag";
-
-interface Props {
- children: ReactNode;
- response: HttpResponse;
-}
-
-const LARGE_BYTES = 2 * 1000 * 1000;
-
-export function ConfirmLargeResponseRequest({ children, response }: Props) {
- const [showLargeResponse, toggleShowLargeResponse] = useToggle();
- const isProbablyText = useMemo(() => {
- const contentType = getContentTypeFromHeaders(response.headers);
- return isProbablyTextContentType(contentType);
- }, [response.headers]);
-
- const contentLength = response.requestContentLength ?? 0;
- const isLarge = contentLength > LARGE_BYTES;
- if (!showLargeResponse && isLarge) {
- return (
-
-
- Showing content over{" "}
-
-
- {" "}
- may impact performance
-
-
-
- {isProbablyText && (
- getHttpResponseRequestBodyText(response).then((d) => d?.bodyText ?? "")}
- />
- )}
-
-
- );
- }
-
- return <>{children}>;
-}
diff --git a/apps/yaak-client/components/CookieDialog.tsx b/apps/yaak-client/components/CookieDialog.tsx
index 31c90913d..0c7a831f4 100644
--- a/apps/yaak-client/components/CookieDialog.tsx
+++ b/apps/yaak-client/components/CookieDialog.tsx
@@ -25,12 +25,13 @@ import {
TableHeaderCell,
TableRow,
TruncatedWideTableCell,
+ KeyValueRows,
} from "@yaakapp-internal/ui";
import { IconButton } from "./core/IconButton";
import { Checkbox } from "./core/Checkbox";
import classNames from "classnames";
import { EventDetailHeader } from "./core/EventViewer";
-import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
+import { KeyValueRow } from "./core/KeyValueRow";
import { EmptyStateText } from "./EmptyStateText";
import { PlainInput } from "./core/PlainInput";
import { Select } from "./core/Select";
diff --git a/apps/yaak-client/components/CopyIconButton.tsx b/apps/yaak-client/components/CopyIconButton.tsx
index a97a032cf..d55a4ec36 100644
--- a/apps/yaak-client/components/CopyIconButton.tsx
+++ b/apps/yaak-client/components/CopyIconButton.tsx
@@ -1,31 +1,22 @@
-import { IconButton, type IconButtonProps, useTimedBoolean } from "@yaakapp-internal/ui";
+import {
+ CopyIconButton as BaseCopyIconButton,
+ type CopyIconButtonProps,
+} from "@yaakapp-internal/ui";
import { copyToClipboard } from "../lib/copy";
import { showToast } from "../lib/toast";
-interface Props extends Omit {
- text: string | (() => Promise);
+export function CopyIconButton(props: Omit) {
+ return ;
}
-export function CopyIconButton({ text, ...props }: Props) {
- const [copied, setCopied] = useTimedBoolean();
- return (
- {
- const content = typeof text === "function" ? await text() : text;
- if (content == null) {
- showToast({
- id: "failed-to-copy",
- color: "danger",
- message: "Failed to copy",
- });
- } else {
- copyToClipboard(content, { disableToast: true });
- setCopied();
- }
- }}
- />
- );
+function copy(text: string) {
+ copyToClipboard(text, { disableToast: true });
+}
+
+function showCopyFailed() {
+ showToast({
+ id: "failed-to-copy",
+ color: "danger",
+ message: "Failed to copy",
+ });
}
diff --git a/apps/yaak-client/components/CreateEnvironmentDialog.tsx b/apps/yaak-client/components/CreateEnvironmentDialog.tsx
index 1436617a1..e5058133b 100644
--- a/apps/yaak-client/components/CreateEnvironmentDialog.tsx
+++ b/apps/yaak-client/components/CreateEnvironmentDialog.tsx
@@ -1,12 +1,12 @@
import { createWorkspaceModel } from "@yaakapp-internal/models";
-import { useState } from "react";
+import { useId, useState } from "react";
import { useToggle } from "../hooks/useToggle";
import { ColorIndicator } from "./ColorIndicator";
-import { Button } from "./core/Button";
import { Checkbox } from "./core/Checkbox";
import { ColorPickerWithThemeColors } from "./core/ColorPicker";
-import { Label } from "./core/Label";
+import { DialogFooter } from "./core/Dialog";
import { PlainInput } from "./core/PlainInput";
+import { Label } from "@yaakapp-internal/ui";
interface Props {
onCreate: (id: string) => void;
@@ -18,9 +18,11 @@ export function CreateEnvironmentDialog({ workspaceId, hide, onCreate }: Props)
const [name, setName] = useState("");
const [color, setColor] = useState(null);
const [sharable, toggleSharable] = useToggle(false);
+ const formId = useId();
return (
);
}
diff --git a/apps/yaak-client/components/CreateWorkspaceDialog.tsx b/apps/yaak-client/components/CreateWorkspaceDialog.tsx
index 25e736127..557d089c1 100644
--- a/apps/yaak-client/components/CreateWorkspaceDialog.tsx
+++ b/apps/yaak-client/components/CreateWorkspaceDialog.tsx
@@ -1,15 +1,14 @@
import { gitMutations } from "@yaakapp-internal/git";
import type { WorkspaceMeta } from "@yaakapp-internal/models";
import { createGlobalModel, updateModel } from "@yaakapp-internal/models";
-import { VStack } from "@yaakapp-internal/ui";
-import { useState } from "react";
+import { VStack, Label } from "@yaakapp-internal/ui";
+import { useId, useState } from "react";
import { router } from "../lib/router";
import { setupOrConfigureEncryption } from "../lib/setupOrConfigureEncryption";
import { rpc } from "../lib/rpc";
import { showErrorToast } from "../lib/toast";
-import { Button } from "./core/Button";
import { Checkbox } from "./core/Checkbox";
-import { Label } from "./core/Label";
+import { DialogFooter } from "./core/Dialog";
import { PlainInput } from "./core/PlainInput";
import { EncryptionHelp } from "./EncryptionHelp";
import { gitCallbacks } from "./git/callbacks";
@@ -26,12 +25,13 @@ export function CreateWorkspaceDialog({ hide }: Props) {
initGit?: boolean;
}>({ filePath: null, initGit: false });
const [setupEncryption, setSetupEncryption] = useState(false);
+ const formId = useId();
return (
{
e.preventDefault();
const workspaceId = await createGlobalModel({ model: "workspace", name });
@@ -89,9 +89,7 @@ export function CreateWorkspaceDialog({ hide }: Props) {
title="Enable Encryption"
/>
-
+
);
}
diff --git a/apps/yaak-client/components/DynamicForm.tsx b/apps/yaak-client/components/DynamicForm.tsx
index adb314148..3f55cc754 100644
--- a/apps/yaak-client/components/DynamicForm.tsx
+++ b/apps/yaak-client/components/DynamicForm.tsx
@@ -11,7 +11,7 @@ import type {
FormInputText,
JsonPrimitive,
} from "@yaakapp-internal/plugins";
-import { Banner, VStack } from "@yaakapp-internal/ui";
+import { Banner, VStack, Label } from "@yaakapp-internal/ui";
import classNames from "classnames";
import { useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo } from "react";
@@ -26,7 +26,6 @@ import { Editor } from "./core/Editor/LazyEditor";
import { IconButton } from "./core/IconButton";
import type { InputProps } from "./core/Input";
import { Input } from "./core/Input";
-import { Label } from "./core/Label";
import type { Pair } from "./core/PairEditor";
import { PairEditor } from "./core/PairEditor";
import { PlainInput } from "./core/PlainInput";
diff --git a/apps/yaak-client/components/EmptyStateText.tsx b/apps/yaak-client/components/EmptyStateText.tsx
index 30f75bb40..4a557c4d2 100644
--- a/apps/yaak-client/components/EmptyStateText.tsx
+++ b/apps/yaak-client/components/EmptyStateText.tsx
@@ -1,24 +1 @@
-import classNames from "classnames";
-import type { ReactNode } from "react";
-
-interface Props {
- children: ReactNode;
- className?: string;
- wrapperClassName?: string;
-}
-
-export function EmptyStateText({ children, className, wrapperClassName }: Props) {
- return (
-
- );
-}
+export { EmptyStateText } from "@yaakapp-internal/ui";
diff --git a/apps/yaak-client/components/EnvironmentEditDialog.tsx b/apps/yaak-client/components/EnvironmentEditDialog.tsx
index aecf1d877..8e53126ff 100644
--- a/apps/yaak-client/components/EnvironmentEditDialog.tsx
+++ b/apps/yaak-client/components/EnvironmentEditDialog.tsx
@@ -1,11 +1,19 @@
import type { Environment, Workspace } from "@yaakapp-internal/models";
import { duplicateModel, patchModel } from "@yaakapp-internal/models";
import type { TreeHandle, TreeNode, TreeProps } from "@yaakapp-internal/ui";
-import { Banner, Icon, InlineCode, SplitLayout, Tree } from "@yaakapp-internal/ui";
+import { Banner, Icon, InlineCode, SplitLayout, Tree, IconTooltip } from "@yaakapp-internal/ui";
import { atom, useAtomValue } from "jotai";
import { atomFamily } from "jotai-family";
-import { useCallback, useLayoutEffect, useRef, useState } from "react";
-import { createSubEnvironmentAndActivate } from "../commands/createEnvironment";
+import {
+ createContext,
+ useCallback,
+ useContext,
+ useEffect,
+ useLayoutEffect,
+ useRef,
+ useState,
+} from "react";
+import { createSubEnvironment } from "../commands/createEnvironment";
import { activeWorkspaceAtom, activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
import {
environmentsBreakdownAtom,
@@ -22,7 +30,6 @@ import { showColorPicker } from "../lib/showColorPicker";
import type { ContextMenuProps, DropdownItem } from "./core/Dropdown";
import { ContextMenu } from "./core/Dropdown";
import { IconButton } from "./core/IconButton";
-import { IconTooltip } from "./core/IconTooltip";
import type { PairEditorHandle } from "./core/PairEditor";
import { EnvironmentColorIndicator } from "./EnvironmentColorIndicator";
import { EnvironmentEditor } from "./EnvironmentEditor";
@@ -40,6 +47,9 @@ interface Props {
type TreeModel = Environment | Workspace;
+/** Lets tree row slots create a sub-environment and select it in the editor. */
+const CreateSubEnvironmentContext = createContext<() => Promise>(async () => {});
+
export function EnvironmentEditDialog({ initialEnvironmentId, setRef }: Props) {
const { allEnvironments, baseEnvironment, baseEnvironments } = useEnvironmentsBreakdown();
const [selectedEnvironmentId, setSelectedEnvironmentId] = useState(
@@ -115,7 +125,7 @@ function EnvironmentEditDialogSidebar({
const activeWorkspaceId = useAtomValue(activeWorkspaceIdAtom) ?? "";
const treeId = `environment.${activeWorkspaceId}.sidebar`;
const treeRef = useRef(null);
- const { baseEnvironment, baseEnvironments } = useEnvironmentsBreakdown();
+ const { allEnvironments, baseEnvironment, baseEnvironments } = useEnvironmentsBreakdown();
// oxlint-disable-next-line react-hooks/exhaustive-deps -- none
useLayoutEffect(() => {
@@ -124,6 +134,31 @@ function EnvironmentEditDialogSidebar({
treeRef.current?.focus();
}, []);
+ // A just-created environment to select once it reaches the model store. Selecting it before
+ // then would show a "failed to find" error in the editor, and the tree would drop the
+ // selection of an item it doesn't have yet.
+ const [pendingSelectionId, setPendingSelectionId] = useState(null);
+ const tree = useAtomValue(treeAtom);
+ useEffect(() => {
+ if (pendingSelectionId == null) return;
+ if (!allEnvironments.some((e) => e.id === pendingSelectionId)) return;
+
+ setPendingSelectionId(null);
+ setSelectedEnvironmentId(pendingSelectionId);
+
+ // The tree leaves out sub-environments while there are multiple base environments
+ const node = tree == null ? null : findTreeNode(tree, pendingSelectionId);
+ if (node == null) return;
+ if (node.parent != null) {
+ // Expand the parent so the new item is visible to be selected
+ const parentId = node.parent.item.id;
+ jotaiStore.set(collapsedFamily(treeId), (prev) => ({ ...prev, [parentId]: false }));
+ }
+ // Wait a frame so the tree's own pending selection fixups, which may have been scheduled
+ // before the new item arrived, don't reset this selection
+ requestAnimationFrame(() => treeRef.current?.selectItem(pendingSelectionId));
+ }, [allEnvironments, pendingSelectionId, setSelectedEnvironmentId, tree, treeId]);
+
const handleDeleteEnvironment = useCallback(
async (environment: Environment) => {
await deleteModelWithConfirm(environment);
@@ -134,6 +169,14 @@ function EnvironmentEditDialogSidebar({
[baseEnvironment?.id, selectedEnvironmentId, setSelectedEnvironmentId],
);
+ const handleCreateSubEnvironment = useCallback(async () => {
+ const { baseEnvironment } = jotaiStore.get(environmentsBreakdownAtom);
+ if (baseEnvironment == null) return;
+ const id = await createSubEnvironment.mutateAsync(baseEnvironment);
+ // Show the new environment in the editor without changing the workspace's active environment
+ if (id != null) setPendingSelectionId(id);
+ }, []);
+
const treeHasFocus = useCallback(() => treeRef.current?.hasFocus() ?? false, []);
const getSelectedTreeModels = useCallback(
@@ -195,13 +238,14 @@ function EnvironmentEditDialogSidebar({
const addEnvironmentItem: DropdownItem = {
label: "Create Sub Environment",
leftSlot: ,
- onSelect: async () => {
- await createSubEnvironment();
- },
+ onSelect: handleCreateSubEnvironment,
};
+ // Sub-environments aren't shown while there are multiple base environments, same as the
+ // plus button on the base environment row
+ const canCreateSubEnvironment = baseEnvironments.length <= 1;
if (environment == null || environment.model !== "environment") {
- return [addEnvironmentItem];
+ return canCreateSubEnvironment ? [addEnvironmentItem] : [];
}
const singleEnvironment = items.length === 1;
@@ -257,7 +301,7 @@ function EnvironmentEditDialogSidebar({
];
// Add sub environment to base environment
- if (isBaseEnvironment(environment) && singleEnvironment) {
+ if (isBaseEnvironment(environment) && singleEnvironment && canCreateSubEnvironment) {
menuItems.push({ type: "separator" });
menuItems.push(addEnvironmentItem);
}
@@ -266,6 +310,7 @@ function EnvironmentEditDialogSidebar({
},
[
baseEnvironments.length,
+ handleCreateSubEnvironment,
handleDeleteEnvironment,
handleDuplicateSelected,
handleRenameSelected,
@@ -317,34 +362,37 @@ function EnvironmentEditDialogSidebar({
);
const renderContextMenuFn = useCallback["renderContextMenu"]>>(
- ({ items, position, onClose }) => (
-
- ),
+ ({ items, position, onClose }) =>
+ // Right-clicking empty space has nothing to offer while there are multiple base environments
+ items.length === 0 ? null : (
+
+ ),
[],
);
- const tree = useAtomValue(treeAtom);
return (
);
@@ -384,6 +432,15 @@ const treeAtom = atom | null>((get) => {
return root;
});
+function findTreeNode(node: TreeNode, id: string): TreeNode | null {
+ if (node.item.id === id) return node;
+ for (const child of node.children ?? []) {
+ const found = findTreeNode(child, id);
+ if (found != null) return found;
+ }
+ return null;
+}
+
function ItemLeftSlotInner({ item }: { item: TreeModel }) {
const { baseEnvironments } = useEnvironmentsBreakdown();
return baseEnvironments.length > 1 ? (
@@ -395,6 +452,7 @@ function ItemLeftSlotInner({ item }: { item: TreeModel }) {
function ItemRightSlot({ item }: { item: TreeModel }) {
const { baseEnvironments } = useEnvironmentsBreakdown();
+ const handleCreateSubEnvironment = useContext(CreateSubEnvironmentContext);
return (
<>
{item.model === "environment" && baseEnvironments.length <= 1 && isBaseEnvironment(item) && (
@@ -405,7 +463,7 @@ function ItemRightSlot({ item }: { item: TreeModel }) {
icon="plus_circle"
className="opacity-50 hover:opacity-100"
title="Add Sub-Environment"
- onClick={createSubEnvironment}
+ onClick={handleCreateSubEnvironment}
/>
)}
>
@@ -425,13 +483,6 @@ function ItemInner({ item }: { item: TreeModel }) {
);
}
-async function createSubEnvironment() {
- const { baseEnvironment } = jotaiStore.get(environmentsBreakdownAtom);
- if (baseEnvironment == null) return;
- const id = await createSubEnvironmentAndActivate.mutateAsync(baseEnvironment);
- return id;
-}
-
function getEditOptions(item: TreeModel) {
const options: ReturnType["getEditOptions"]>> = {
defaultValue: item.name,
diff --git a/apps/yaak-client/components/EnvironmentSharableTooltip.tsx b/apps/yaak-client/components/EnvironmentSharableTooltip.tsx
index 642d76eb2..aa8ef57c9 100644
--- a/apps/yaak-client/components/EnvironmentSharableTooltip.tsx
+++ b/apps/yaak-client/components/EnvironmentSharableTooltip.tsx
@@ -1,4 +1,4 @@
-import { IconTooltip } from "./core/IconTooltip";
+import { IconTooltip } from "@yaakapp-internal/ui";
export function EnvironmentSharableTooltip() {
return (
diff --git a/apps/yaak-client/components/ErrorBoundary.tsx b/apps/yaak-client/components/ErrorBoundary.tsx
index a764bfe77..dfc4f85d3 100644
--- a/apps/yaak-client/components/ErrorBoundary.tsx
+++ b/apps/yaak-client/components/ErrorBoundary.tsx
@@ -1,60 +1,19 @@
-import { Banner, Button, InlineCode } from "@yaakapp-internal/ui";
-import type { ErrorInfo, ReactNode } from "react";
-import { Component, useEffect } from "react";
+import { ErrorBoundary as BaseErrorBoundary } from "@yaakapp-internal/ui";
+import type { ReactNode } from "react";
+import { useEffect } from "react";
import { showDialog } from "../lib/dialog";
import RouteError from "./RouteError";
-interface ErrorBoundaryProps {
- name: string;
- children: ReactNode;
+export function ErrorBoundary({ name, children }: { name: string; children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
}
-interface ErrorBoundaryState {
- hasError: boolean;
- error: Error | null;
-}
-
-export class ErrorBoundary extends Component {
- constructor(props: ErrorBoundaryProps) {
- super(props);
- this.state = { hasError: false, error: null };
- }
-
- static getDerivedStateFromError(error: Error): ErrorBoundaryState {
- return { hasError: true, error };
- }
-
- componentDidCatch(error: Error, info: ErrorInfo) {
- console.warn("Error caught by ErrorBoundary:", error, info);
- }
-
- render() {
- if (this.state.hasError) {
- return (
-
-
- Error rendering {this.props.name} component
-
-
-
- );
- }
-
- return this.props.children;
- }
+export function showErrorDialog(error: unknown) {
+ showDialog({ id: "error-boundary", render: () => });
}
export function ErrorBoundaryTestThrow() {
diff --git a/apps/yaak-client/components/ExportDataDialog.tsx b/apps/yaak-client/components/ExportDataDialog.tsx
index a43e340f1..1f27c7124 100644
--- a/apps/yaak-client/components/ExportDataDialog.tsx
+++ b/apps/yaak-client/components/ExportDataDialog.tsx
@@ -1,18 +1,18 @@
import type { Workspace } from "@yaakapp-internal/models";
import { workspacesAtom } from "@yaakapp-internal/models";
-import { HStack, VStack } from "@yaakapp-internal/ui";
+import { VStack } from "@yaakapp-internal/ui";
import { useAtomValue } from "jotai";
import { useCallback, useMemo, useState } from "react";
import slugify from "slugify";
import { activeWorkspaceAtom } from "../hooks/useActiveWorkspace";
-import { pluralizeCount } from "../lib/pluralize";
import { rpc } from "../lib/rpc";
import { CommercialUseBanner } from "./CommercialUseBanner";
-import { Button } from "./core/Button";
import { Checkbox } from "./core/Checkbox";
import { DetailsBanner } from "./core/DetailsBanner";
+import { DialogFooter } from "./core/Dialog";
import { Link } from "./core/Link";
import { platform } from "@yaakapp-internal/platform";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
interface Props {
onHide: () => void;
@@ -65,29 +65,30 @@ function ExportDataDialogContent({
const ids = Object.keys(selectedWorkspaces).filter((k) => selectedWorkspaces[k]);
const workspace = ids.length === 1 ? workspaces.find((w) => w.id === ids[0]) : undefined;
const slug = workspace ? slugify(workspace.name, { lower: true }) : "workspaces";
- const exportPath = await platform.dialog.save({
- title: "Export Data",
- defaultPath: `yaak.${slug}.json`,
- });
- if (exportPath == null) {
- return;
- }
-
- await rpc("cmd_export_data", {
+ const document = await rpc("cmd_export_data", {
workspaceIds: ids,
- exportPath,
includePrivateEnvironments: includePrivateEnvironments,
});
+
+ const savedTo = await platform.files.save(
+ `yaak.${slug}.json`,
+ new TextEncoder().encode(document),
+ [{ name: "JSON", extensions: ["json"] }],
+ );
+ if (savedTo == null) {
+ return; // Cancelled
+ }
+
onHide();
- onSuccess(exportPath);
+ onSuccess(savedTo);
}, [includePrivateEnvironments, onHide, onSuccess, selectedWorkspaces, workspaces]);
const allSelected = workspaces.every((w) => selectedWorkspaces[w.id]);
const numSelected = Object.values(selectedWorkspaces).filter(Boolean).length;
const noneSelected = numSelected === 0;
return (
-
-
+ <>
+
@@ -140,29 +141,22 @@ function ExportDataDialogContent({
/>
-
-
+ }
+ actions={[
+ { label: "Cancel", onClick: onHide },
+ {
+ label: `Export ${pluralizeCount("Workspace", numSelected, { omitSingle: true, noneWord: "Nothing" })}`,
+ color: "primary",
+ disabled: noneSelected,
+ onClick: () => handleExport(),
+ },
+ ]}
+ />
+ >
);
}
diff --git a/apps/yaak-client/components/FolderLayout.tsx b/apps/yaak-client/components/FolderLayout.tsx
index a693080a5..14c3085db 100644
--- a/apps/yaak-client/components/FolderLayout.tsx
+++ b/apps/yaak-client/components/FolderLayout.tsx
@@ -1,6 +1,14 @@
import type { Folder, GrpcRequest, HttpRequest, WebsocketRequest } from "@yaakapp-internal/models";
import { foldersAtom } from "@yaakapp-internal/models";
-import { Heading, HStack, Icon, LoadingIcon } from "@yaakapp-internal/ui";
+import {
+ Heading,
+ HStack,
+ Icon,
+ LoadingIcon,
+ HttpResponseDurationTag,
+ HttpStatusTag,
+ SizeTag,
+} from "@yaakapp-internal/ui";
import classNames from "classnames";
import { useAtomValue } from "jotai";
import type { CSSProperties, ReactNode } from "react";
@@ -13,11 +21,8 @@ import { showDialog } from "../lib/dialog";
import { resolvedModelName } from "../lib/resolvedModelName";
import { router } from "../lib/router";
import { Button } from "./core/Button";
-import { HttpResponseDurationTag } from "./core/HttpResponseDurationTag";
-import { HttpStatusTag } from "./core/HttpStatusTag";
import { IconButton } from "./core/IconButton";
import { Separator } from "./core/Separator";
-import { SizeTag } from "./core/SizeTag";
import { HttpResponsePane } from "./HttpResponsePane";
interface Props {
diff --git a/apps/yaak-client/components/FolderSettingsDialog.tsx b/apps/yaak-client/components/FolderSettingsDialog.tsx
index 7b0a3e4e9..66758a153 100644
--- a/apps/yaak-client/components/FolderSettingsDialog.tsx
+++ b/apps/yaak-client/components/FolderSettingsDialog.tsx
@@ -1,5 +1,5 @@
import { createWorkspaceModel, foldersAtom, patchModel } from "@yaakapp-internal/models";
-import { HStack, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
+import { HStack, Icon, InlineCode, VStack, CountBadge } from "@yaakapp-internal/ui";
import { useAtomValue } from "jotai";
import { Fragment, useMemo } from "react";
import { useAuthTab } from "../hooks/useAuthTab";
@@ -11,7 +11,6 @@ import { deleteModelWithConfirm } from "../lib/deleteModelWithConfirm";
import { hideDialog } from "../lib/dialog";
import { CopyIconButton } from "./CopyIconButton";
import { Button } from "./core/Button";
-import { CountBadge } from "./core/CountBadge";
import { Input } from "./core/Input";
import { Link } from "./core/Link";
import type { TabItem } from "./core/Tabs/Tabs";
diff --git a/apps/yaak-client/components/FormUrlencodedEditor.tsx b/apps/yaak-client/components/FormUrlencodedEditor.tsx
deleted file mode 100644
index 94a0aa03b..000000000
--- a/apps/yaak-client/components/FormUrlencodedEditor.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import type { HttpRequest } from "@yaakapp-internal/models";
-import { useCallback, useMemo } from "react";
-import type { Pair, PairEditorProps } from "./core/PairEditor";
-import { PairOrBulkEditor } from "./core/PairOrBulkEditor";
-
-type Props = {
- forceUpdateKey: string;
- request: HttpRequest;
- onChange: (headers: HttpRequest["body"]) => void;
-};
-
-export function FormUrlencodedEditor({ request, forceUpdateKey, onChange }: Props) {
- const pairs = useMemo(
- () =>
- (Array.isArray(request.body.form) ? request.body.form : []).map((p) => ({
- enabled: !!p.enabled,
- name: p.name || "",
- value: p.value || "",
- id: p.id,
- })),
- [request.body.form],
- );
-
- const handleChange = useCallback(
- (pairs) =>
- onChange({ form: pairs.map((p) => ({ enabled: p.enabled, name: p.name, value: p.value })) }),
- [onChange],
- );
-
- return (
-
- );
-}
diff --git a/apps/yaak-client/components/GlobalHooks.tsx b/apps/yaak-client/components/GlobalHooks.tsx
index 67499e94a..240ab9848 100644
--- a/apps/yaak-client/components/GlobalHooks.tsx
+++ b/apps/yaak-client/components/GlobalHooks.tsx
@@ -1,3 +1,4 @@
+import type { NavigateWorkspace } from "@yaakapp-internal/tauri-client";
import { activeRequestAtom } from "../hooks/useActiveRequest";
import { useSubscribeActiveWorkspaceId } from "../hooks/useActiveWorkspace";
import { useActiveWorkspaceChangedToast } from "../hooks/useActiveWorkspaceChangedToast";
@@ -5,10 +6,13 @@ import { useHotKey, useSubscribeHotKeys } from "../hooks/useHotKey";
import { useSubscribeHttpAuthentication } from "../hooks/useHttpAuthentication";
import { useSyncFontSizeSetting } from "../hooks/useSyncFontSizeSetting";
import { useSyncWorkspaceChildModels } from "../hooks/useSyncWorkspaceChildModels";
+import { usePlatformEvent } from "../hooks/usePlatformEvent";
import { useSyncZoomSetting } from "../hooks/useSyncZoomSetting";
import { useSubscribeTemplateFunctions } from "../hooks/useTemplateFunctions";
+import { fireAndForget } from "../lib/fireAndForget";
import { jotaiStore } from "../lib/jotai";
import { renameModelWithPrompt } from "../lib/renameModelWithPrompt";
+import { router } from "../lib/router";
export function GlobalHooks() {
useSyncZoomSetting();
@@ -24,6 +28,20 @@ export function GlobalHooks() {
useActiveWorkspaceChangedToast();
useSubscribeHotKeys();
+ usePlatformEvent("show_home", () => {
+ fireAndForget(router.navigate({ to: "/", search: { home: true } }));
+ });
+
+ usePlatformEvent("navigate_workspace", ({ workspaceId, environmentId }) => {
+ fireAndForget(
+ router.navigate({
+ to: "/workspaces/$workspaceId",
+ params: { workspaceId },
+ search: { environment_id: environmentId },
+ }),
+ );
+ });
+
useHotKey(
"request.rename",
async () => {
diff --git a/apps/yaak-client/components/GrpcEditor.tsx b/apps/yaak-client/components/GrpcEditor.tsx
index e44fc1f22..c626f46e0 100644
--- a/apps/yaak-client/components/GrpcEditor.tsx
+++ b/apps/yaak-client/components/GrpcEditor.tsx
@@ -20,13 +20,13 @@ import { showConfirm } from "../lib/confirm";
import { showDialog } from "../lib/dialog";
import type { JsonSchema } from "../lib/jsonSchemaExample";
import { buildExampleFromSchema } from "../lib/jsonSchemaExample";
-import { pluralizeCount } from "../lib/pluralize";
import { queryClient } from "../lib/queryClient";
import { Button } from "./core/Button";
import { Dropdown } from "./core/Dropdown";
import type { EditorProps } from "./core/Editor/Editor";
import { Editor } from "./core/Editor/LazyEditor";
import { GrpcProtoSelectionDialog } from "./GrpcProtoSelectionDialog";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
type Props = Pick & {
services: ReflectResponseService[] | null;
@@ -239,6 +239,7 @@ export function GrpcEditor({
showDialog({
title: "Configure Schema",
size: "md",
+ className: "h-[30rem]",
id: "grpc-configure-schema",
render: ({ hide }) => ,
});
diff --git a/apps/yaak-client/components/GrpcProtoSelectionDialog.tsx b/apps/yaak-client/components/GrpcProtoSelectionDialog.tsx
index cafa422ed..e010deb87 100644
--- a/apps/yaak-client/components/GrpcProtoSelectionDialog.tsx
+++ b/apps/yaak-client/components/GrpcProtoSelectionDialog.tsx
@@ -1,13 +1,13 @@
import type { GrpcRequest } from "@yaakapp-internal/models";
-import { Banner, HStack, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
+import { Banner, InlineCode, VStack } from "@yaakapp-internal/ui";
import { useActiveRequest } from "../hooks/useActiveRequest";
import { useGrpc } from "../hooks/useGrpc";
import { useGrpcProtoFiles } from "../hooks/useGrpcProtoFiles";
-import { pluralizeCount } from "../lib/pluralize";
-import { Button } from "./core/Button";
-import { IconButton } from "./core/IconButton";
+import { DialogFooter } from "./core/Dialog";
+import { PathList } from "./core/PathList";
import { Link } from "./core/Link";
import { platform } from "@yaakapp-internal/platform";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
interface Props {
onDone: () => void;
@@ -20,7 +20,10 @@ export function GrpcProtoSelectionDialog(props: Props) {
return ;
}
-function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: GrpcRequest }) {
+function GrpcProtoSelectionDialogWithRequest({
+ request,
+ onDone,
+}: Props & { request: GrpcRequest }) {
const protoFilesKv = useGrpcProtoFiles(request.id);
const protoFiles = protoFilesKv.value ?? [];
const grpc = useGrpc(request, null, protoFiles);
@@ -38,54 +41,8 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
}
return (
-
- {/* Buttons on top so they get focus first */}
-
-
-
-
-
-
+ <>
+
{reflectError && (
@@ -128,46 +85,47 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
)}
- {protoFiles.length > 0 && (
-
-
-
- |
- Added File Paths
- |
-
-
-
- {protoFiles.map((f, i) => {
- const parts = f.split("/");
- // oxlint-disable-next-line no-array-index-key -- none
- return (
-
- |
-
- |
-
- {parts.length > 3 && ".../"}
- {parts.slice(-3).join("/")}
- |
-
- {
- await protoFilesKv.set(protoFiles.filter((p) => p !== f));
- }}
- />
- |
-
- );
- })}
-
-
- )}
+ ({
+ path,
+ icon: path.endsWith(".proto") ? "file_code" : "folder_code",
+ }))}
+ onRemove={async (path) => {
+ await protoFilesKv.set(protoFiles.filter((p) => p !== path));
+ await grpc.reflect.refetch();
+ }}
+ addLabel="Add proto files or an import folder"
+ addItems={[
+ {
+ label: "Proto files",
+ icon: "file_code",
+ onSelect: async () => {
+ const selected = await platform.dialog.open({
+ title: "Select Proto Files",
+ multiple: true,
+ filters: [{ name: "Proto Files", extensions: ["proto"] }],
+ });
+ if (selected == null) return;
+ const newFiles = selected.filter((p) => !protoFiles.includes(p));
+ await protoFilesKv.set([...protoFiles, ...newFiles]);
+ await grpc.reflect.refetch();
+ },
+ },
+ {
+ label: "Import folder",
+ icon: "folder_code",
+ onSelect: async () => {
+ const selected = await platform.dialog.open({
+ title: "Select Proto Directory",
+ directory: true,
+ });
+ if (selected == null) return;
+ await protoFilesKv.set([...protoFiles.filter((f) => f !== selected), selected]);
+ await grpc.reflect.refetch();
+ },
+ },
+ ]}
+ />
{reflectionUnimplemented && protoFiles.length === 0 && (
{request.url} doesn't implement{" "}
@@ -178,6 +136,17 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
)}
-
+ grpc.reflect.refetch(),
+ },
+ { label: "Done", color: "primary", onClick: onDone },
+ ]}
+ />
+ >
);
}
diff --git a/apps/yaak-client/components/GrpcRequestPane.tsx b/apps/yaak-client/components/GrpcRequestPane.tsx
index bec53ee4a..43754b864 100644
--- a/apps/yaak-client/components/GrpcRequestPane.tsx
+++ b/apps/yaak-client/components/GrpcRequestPane.tsx
@@ -4,7 +4,7 @@ import {
patchModel,
patchModelDebounced,
} from "@yaakapp-internal/models";
-import { HStack, Icon, useContainerSize, VStack } from "@yaakapp-internal/ui";
+import { HStack, Icon, useContainerSize, VStack, CountBadge } from "@yaakapp-internal/ui";
import classNames from "classnames";
import type { CSSProperties } from "react";
import { useCallback, useMemo, useRef } from "react";
@@ -15,7 +15,6 @@ import { useInheritedHeaders } from "../hooks/useInheritedHeaders";
import { useRequestUpdateKey } from "../hooks/useRequestUpdateKey";
import { resolvedModelName } from "../lib/resolvedModelName";
import { Button } from "./core/Button";
-import { CountBadge } from "./core/CountBadge";
import { IconButton } from "./core/IconButton";
import { PlainInput } from "./core/PlainInput";
import { RadioDropdown } from "./core/RadioDropdown";
@@ -133,6 +132,8 @@ export function GrpcRequestPane({
onSend({ message: activeRequest.message });
}, [activeRequest, onSend]);
+ const hasDescription = activeRequest.description.trim().length > 0;
+
const tabs: TabItem[] = useMemo(
() => [
{ value: TAB_MESSAGE, label: "Message" },
@@ -146,10 +147,10 @@ export function GrpcRequestPane({
{
value: TAB_DESCRIPTION,
label: "Info",
- rightSlot: activeRequest.description && ,
+ rightSlot: hasDescription && ,
},
],
- [activeRequest.description, authTab, metadataTab, numSettingsOverrides],
+ [authTab, hasDescription, metadataTab, numSettingsOverrides],
);
const handleMetadataChange = useCallback(
diff --git a/apps/yaak-client/components/GrpcResponsePane.tsx b/apps/yaak-client/components/GrpcResponsePane.tsx
index 601b3e12b..7228011f0 100644
--- a/apps/yaak-client/components/GrpcResponsePane.tsx
+++ b/apps/yaak-client/components/GrpcResponsePane.tsx
@@ -1,5 +1,13 @@
import type { GrpcEvent, GrpcRequest } from "@yaakapp-internal/models";
-import { HStack, Icon, type IconProps, LoadingIcon, VStack } from "@yaakapp-internal/ui";
+import {
+ HStack,
+ Icon,
+ type IconProps,
+ LoadingIcon,
+ VStack,
+ useStateWithDeps,
+ KeyValueRows,
+} from "@yaakapp-internal/ui";
import { useAtomValue, useSetAtom } from "jotai";
import type { CSSProperties } from "react";
import { useEffect, useMemo, useState } from "react";
@@ -9,13 +17,12 @@ import {
pinnedGrpcConnectionIdAtom,
useGrpcEvents,
} from "../hooks/usePinnedGrpcConnection";
-import { useStateWithDeps } from "../hooks/useStateWithDeps";
import { Button } from "./core/Button";
import { Editor } from "./core/Editor/LazyEditor";
import { EventDetailHeader, EventViewer } from "./core/EventViewer";
import { EventViewerRow } from "./core/EventViewerRow";
import { HotkeyList } from "./core/HotkeyList";
-import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
+import { KeyValueRow } from "./core/KeyValueRow";
import { EmptyStateText } from "./EmptyStateText";
import { ErrorBoundary } from "./ErrorBoundary";
import { RecentGrpcConnectionsDropdown } from "./RecentGrpcConnectionsDropdown";
diff --git a/apps/yaak-client/components/HeadersEditor.tsx b/apps/yaak-client/components/HeadersEditor.tsx
index fa1d80105..77c9cf9d3 100644
--- a/apps/yaak-client/components/HeadersEditor.tsx
+++ b/apps/yaak-client/components/HeadersEditor.tsx
@@ -1,190 +1 @@
-import type { HttpRequestHeader } from "@yaakapp-internal/models";
-import { HStack } from "@yaakapp-internal/ui";
-import { acceptLanguages } from "../lib/data/acceptLanguages";
-import { cacheControlDirectives } from "../lib/data/cacheControl";
-import { charsets } from "../lib/data/charsets";
-import { connections } from "../lib/data/connections";
-import { encodings } from "../lib/data/encodings";
-import type { HeaderValuePreset } from "../lib/data/headerValuePresets";
-import { headerNames } from "../lib/data/headerNames";
-import { mimeTypes } from "../lib/data/mimetypes";
-import { userAgents } from "../lib/data/userAgents";
-import { CountBadge } from "./core/CountBadge";
-import { DetailsBanner } from "./core/DetailsBanner";
-import type { GenericCompletion, GenericCompletionConfig } from "./core/Editor/genericCompletion";
-import type { InputProps } from "./core/Input";
-import type { Pair, PairEditorProps } from "./core/PairEditor";
-import { PairEditorRow } from "./core/PairEditor";
-import { ensurePairId } from "./core/PairEditor.util";
-import { PairOrBulkEditor } from "./core/PairOrBulkEditor";
-
-type Props = {
- forceUpdateKey: string;
- headers: HttpRequestHeader[];
- inheritedHeaders?: HttpRequestHeader[];
- inheritedHeadersLabel?: string;
- stateKey: string;
- onChange: (headers: HttpRequestHeader[]) => void;
- label?: string;
-};
-
-export function HeadersEditor({
- stateKey,
- headers,
- inheritedHeaders,
- inheritedHeadersLabel = "Inherited",
- onChange,
- forceUpdateKey,
-}: Props) {
- // Get header names defined at current level (case-insensitive)
- const currentHeaderNames = new Set(
- headers.filter((h) => h.name).map((h) => h.name.toLowerCase()),
- );
- // Filter inherited headers: must be enabled, have content, and not be overridden by current level
- const validInheritedHeaders =
- inheritedHeaders?.filter(
- (pair) =>
- pair.enabled &&
- (pair.name || pair.value) &&
- !currentHeaderNames.has(pair.name.toLowerCase()),
- ) ?? [];
- const hasInheritedHeaders = validInheritedHeaders.length > 0;
- return (
-
- {hasInheritedHeaders && (
-
- {inheritedHeadersLabel}
-
- }
- >
-
- {validInheritedHeaders?.map((pair, i) => (
-
- ))}
-
-
- )}
-
-
- );
-}
-
-const MIN_MATCH = 3;
-
-const headerOptionsMap: Record = {
- "content-type": mimeTypes,
- accept: ["*/*", ...mimeTypes],
- "accept-encoding": encodings,
- "content-encoding": encodings,
- connection: connections,
- "accept-charset": charsets,
- "accept-language": acceptLanguages,
- "cache-control": cacheControlDirectives,
- "user-agent": userAgents,
- pragma: ["no-cache"],
- te: ["trailers", "compress", "deflate", "gzip"],
- dnt: ["1", "0"],
- "upgrade-insecure-requests": ["1"],
- "x-requested-with": ["XMLHttpRequest"],
-};
-
-const valueType = (pair: Pair): InputProps["type"] => {
- const name = pair.name.toLowerCase().trim();
- if (
- name.includes("authorization") ||
- name.includes("api-key") ||
- name.includes("access-token") ||
- name.includes("auth") ||
- name.includes("secret") ||
- name.includes("token") ||
- name === "cookie" ||
- name === "set-cookie"
- ) {
- return "password";
- }
- return "text";
-};
-
-const valueAutocomplete = (headerName: string): GenericCompletionConfig | undefined => {
- const name = headerName.toLowerCase().trim();
- const options: GenericCompletion[] =
- headerOptionsMap[name]?.map((o) =>
- typeof o === "string"
- ? {
- label: o,
- type: "constant",
- boost: 1, // Put above other completions
- }
- : {
- // Show the short label but insert the full value (e.g. User-Agent)
- label: o.label,
- apply: o.value,
- type: "constant",
- boost: 1,
- },
- ) ?? [];
- return { minMatch: MIN_MATCH, options };
-};
-
-const nameAutocomplete: PairEditorProps["nameAutocomplete"] = {
- minMatch: MIN_MATCH,
- options: headerNames.map((t) =>
- typeof t === "string"
- ? {
- label: t,
- type: "constant",
- boost: 1, // Put above other completions
- }
- : {
- ...t,
- boost: 1, // Put above other completions
- },
- ),
-};
-
-const validateHttpHeader = (v: string) => {
- if (v === "") {
- return true;
- }
-
- // Template strings are not allowed so we replace them with a valid example string
- const withoutTemplateStrings = v.replace(/\$\{\[\s*[^\]\s]+\s*]}/gi, "123");
- return withoutTemplateStrings.match(/^[a-zA-Z0-9-_]+$/) !== null;
-};
+export { HeadersEditor } from "@yaakapp-internal/ui";
diff --git a/apps/yaak-client/components/HttpRequestPane.tsx b/apps/yaak-client/components/HttpRequestPane.tsx
index c6d25c3f4..579c26622 100644
--- a/apps/yaak-client/components/HttpRequestPane.tsx
+++ b/apps/yaak-client/components/HttpRequestPane.tsx
@@ -1,9 +1,16 @@
import type { HttpRequest } from "@yaakapp-internal/models";
import { getModel, patchModel, patchModelDebounced } from "@yaakapp-internal/models";
import type { GenericCompletionOption } from "@yaakapp-internal/plugins";
-import classNames from "classnames";
+import {
+ CountBadge,
+ type EditablePair,
+ type ExtraPaneTab,
+ HttpRequestPaneView,
+ InlineCode,
+ languageFromContentType,
+} from "@yaakapp-internal/ui";
import { atom, useAtomValue } from "jotai";
-import type { CSSProperties } from "react";
+import type { CSSProperties, ReactNode } from "react";
import { lazy, Suspense, useCallback, useMemo, useRef, useState } from "react";
import { importCurl, looksLikeCurl } from "../commands/importCurl";
import { allRequestUrlsAtom } from "../hooks/useAllRequests";
@@ -15,10 +22,8 @@ import { usePinnedHttpResponse } from "../hooks/usePinnedHttpResponse";
import { useRequestEditor, useRequestEditorEvent } from "../hooks/useRequestEditor";
import { useRequestUpdateKey } from "../hooks/useRequestUpdateKey";
import { useSendAnyHttpRequest } from "../hooks/useSendAnyHttpRequest";
-import { languageFromContentType } from "../lib/contentType";
-import { generateId } from "../lib/generateId";
-import { derivePathPlaceholderPairs, renamePathPlaceholder } from "../lib/pathPlaceholders";
-import { convertRequestBody } from "../lib/requestBodyConversion";
+import { fireAndForget } from "../lib/fireAndForget";
+import { httpRequestToView } from "../lib/httpViews";
import {
BODY_TYPE_BINARY,
BODY_TYPE_FORM_MULTIPART,
@@ -30,30 +35,24 @@ import {
BODY_TYPE_XML,
getContentTypeFromHeaders,
} from "../lib/model_util";
+import { derivePathPlaceholderPairs, renamePathPlaceholder } from "../lib/pathPlaceholders";
import { prepareImportQuerystring } from "../lib/prepareImportQuerystring";
+import { convertRequestBody } from "../lib/requestBodyConversion";
import { resolvedModelName } from "../lib/resolvedModelName";
import { showToast } from "../lib/toast";
import { BinaryFileEditor } from "./BinaryFileEditor";
import { ConfirmLargeRequestBody } from "./ConfirmLargeRequestBody";
-import { CountBadge } from "./core/CountBadge";
import type { GenericCompletionConfig } from "./core/Editor/genericCompletion";
import { getUrlCompletionConfig } from "./core/Editor/url/completion";
-import { Editor } from "./core/Editor/LazyEditor";
-import { InlineCode } from "@yaakapp-internal/ui";
import { PlainInput } from "./core/PlainInput";
import type { TabItem, TabsRef } from "./core/Tabs/Tabs";
-import { setActiveTab, TabContent, Tabs } from "./core/Tabs/Tabs";
-import { EmptyStateText } from "./EmptyStateText";
-import { FormMultipartEditor } from "./FormMultipartEditor";
-import { FormUrlencodedEditor } from "./FormUrlencodedEditor";
-import { HeadersEditor } from "./HeadersEditor";
+import { setActiveTab } from "./core/Tabs/Tabs";
import { HttpAuthenticationEditor } from "./HttpAuthenticationEditor";
-import { JsonBodyEditor } from "./JsonBodyEditor";
import { MarkdownEditor } from "./MarkdownEditor";
-import { RequestMethodDropdown } from "./RequestMethodDropdown";
import { countOverriddenSettings, ModelSettingsEditor } from "./ModelSettingsEditor";
-import { UrlBar } from "./UrlBar";
+import { RequestMethodDropdown } from "./RequestMethodDropdown";
import { UrlParametersEditor } from "./UrlParameterEditor";
+import { generateId } from "@yaakapp-internal/lib/generateId";
const GraphQLEditor = lazy(() =>
import("./graphql/GraphQLEditor").then((m) => ({ default: m.GraphQLEditor })),
@@ -165,9 +164,11 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
: 0;
}
- const tabs = useMemo(
- () => [
- {
+ const hasDescription = activeRequest.description.trim().length > 0;
+
+ const bodyTab = useMemo(
+ () =>
+ ({
value: TAB_BODY,
rightSlot: numParams > 0 ? : null,
options: {
@@ -244,34 +245,8 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
}
},
},
- },
- {
- value: TAB_PARAMS,
- rightSlot: ,
- label: "Params",
- },
- ...headersTab,
- ...authTab,
- {
- value: TAB_SETTINGS,
- label: "Settings",
- rightSlot: ,
- },
- {
- value: TAB_DESCRIPTION,
- label: "Info",
- },
- ],
- [
- activeRequest,
- authTab,
- contentType,
- handleContentTypeChange,
- headersTab,
- numParams,
- numSettingsOverrides,
- urlParameterPairs.length,
- ],
+ }) satisfies TabItem,
+ [activeRequest, contentType, handleContentTypeChange, numParams],
);
const { mutate: sendRequest } = useSendAnyHttpRequest();
@@ -333,154 +308,152 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
[activeRequest],
);
- return (
-
- {activeRequest && (
- <>
-
-
-
- }
- forceUpdateKey={updateKey}
- isLoading={activeResponse != null && activeResponse.state !== "closed"}
+ const handleJsonOrBodyTextChange = useCallback(
+ (text: string, bodyType: string | null) => {
+ // JSON writes at once, as its editor always has; other text debounces
+ if (bodyType === BODY_TYPE_JSON) {
+ return patchModel(activeRequest, { body: { ...activeRequest.body, text } });
+ }
+ return handleBodyTextChange(text);
+ },
+ [activeRequest, handleBodyTextChange],
+ );
+
+ const handleSendJsonCommentsChange = useCallback(
+ (sendJsonComments: boolean) => {
+ const newBody = { ...activeRequest.body };
+ if (sendJsonComments) {
+ newBody.sendJsonComments = true;
+ } else {
+ delete newBody.sendJsonComments;
+ }
+ fireAndForget(patchModel(activeRequest, { body: newBody }));
+ },
+ [activeRequest],
+ );
+
+ const requestView = useMemo(() => httpRequestToView(activeRequest), [activeRequest]);
+
+ const extraTabs = useMemo(
+ () => [
+ {
+ tab: {
+ value: TAB_SETTINGS,
+ label: "Settings",
+ rightSlot: ,
+ },
+ content: ,
+ },
+ {
+ tab: {
+ value: TAB_DESCRIPTION,
+ label: "Info",
+ rightSlot: hasDescription && ,
+ },
+ content: (
+
+
patchModel(activeRequest, { name })}
+ />
+ patchModel(activeRequest, { description })}
+ />
+
+ ),
+ },
+ ],
+ [activeRequest, hasDescription, numSettingsOverrides, updateKey],
+ );
+
+ const renderBody = useCallback(
+ (sharedEditor: ReactNode) => (
+
+ {activeRequest.bodyType === BODY_TYPE_GRAPHQL ? (
+
+
+
+ ) : activeRequest.bodyType === BODY_TYPE_BINARY ? (
+ patchModelDebounced(activeRequest, { body })}
+ onChangeContentType={handleContentTypeChange}
/>
-
-
-
-
-
- patchModelDebounced(activeRequest, { headers })}
- />
-
-
- patchModelDebounced(activeRequest, { urlParameters })}
- />
-
-
-
-
-
-
- {activeRequest.bodyType === BODY_TYPE_JSON ? (
-
- ) : activeRequest.bodyType === BODY_TYPE_XML ? (
-
- ) : activeRequest.bodyType === BODY_TYPE_GRAPHQL ? (
-
-
-
- ) : activeRequest.bodyType === BODY_TYPE_FORM_URLENCODED ? (
-
- ) : activeRequest.bodyType === BODY_TYPE_FORM_MULTIPART ? (
-
- ) : activeRequest.bodyType === BODY_TYPE_BINARY ? (
- patchModelDebounced(activeRequest, { body })}
- onChangeContentType={handleContentTypeChange}
- />
- ) : typeof activeRequest.bodyType === "string" ? (
-
- ) : (
- No Body
- )}
-
-
-
-
-
patchModel(activeRequest, { name })}
- />
- patchModel(activeRequest, { description })}
- />
-
-
-
- >
- )}
-
+ ) : (
+ sharedEditor
+ )}
+
+ ),
+ [activeRequest, contentType, forceUpdateKey, handleBodyChange, handleContentTypeChange],
+ );
+
+ const renderUrlParameters = useCallback(
+ (pairs: EditablePair[]) => (
+ patchModelDebounced(activeRequest, { urlParameters })}
+ />
+ ),
+ [activeRequest, forceUpdateKey, urlParametersKey],
+ );
+
+ return (
+ }
+ bodyTab={bodyTab}
+ renderBody={renderBody}
+ onBodyChange={handleBodyChange}
+ onBodyTextChange={handleJsonOrBodyTextChange}
+ onSendJsonCommentsChange={handleSendJsonCommentsChange}
+ jsonNoticeStorageKey={activeRequest.workspaceId}
+ urlParameterPairs={urlParameterPairs}
+ renderUrlParameters={renderUrlParameters}
+ headersTabs={headersTab}
+ inheritedHeaders={inheritedHeaders}
+ headersForceUpdateKey={`${forceUpdateHeaderEditorKey}::${forceUpdateKey}`}
+ onHeadersChange={(headers) => patchModelDebounced(activeRequest, { headers })}
+ authTabs={authTab}
+ authContent={}
+ extraTabs={extraTabs}
+ />
);
}
diff --git a/apps/yaak-client/components/HttpResponsePane.tsx b/apps/yaak-client/components/HttpResponsePane.tsx
index e133ed78f..2016f334e 100644
--- a/apps/yaak-client/components/HttpResponsePane.tsx
+++ b/apps/yaak-client/components/HttpResponsePane.tsx
@@ -1,51 +1,38 @@
import type { HttpResponse, HttpResponseEvent } from "@yaakapp-internal/models";
-import { Banner, HStack, Icon, LoadingIcon, VStack } from "@yaakapp-internal/ui";
-import classNames from "classnames";
-import type { ComponentType, CSSProperties } from "react";
-import { lazy, Suspense, useMemo } from "react";
+import {
+ CountBadge,
+ type ExtraPaneTab,
+ type HostBodyViewerArgs,
+ HStack,
+ HttpResponsePaneView,
+ Icon,
+ type ResponseTextViewerExtras,
+ type TextFilterApi,
+ Tooltip,
+ VStack,
+} from "@yaakapp-internal/ui";
+import type { CSSProperties } from "react";
+import { useCallback, useMemo } from "react";
import { useCancelHttpResponse } from "../hooks/useCancelHttpResponse";
import { useCopyHttpResponse } from "../hooks/useCopyHttpResponse";
+import { useRequestBodyLoader, useResponseBodyLoader } from "../hooks/useHttpBodyLoaders";
import { useHttpResponseEvents } from "../hooks/useHttpResponseEvents";
import { usePinnedHttpResponse } from "../hooks/usePinnedHttpResponse";
-import { useResponseBodyBytes, useResponseBodyText } from "../hooks/useResponseBodyText";
-import { useResponseBodyUrl } from "../hooks/useResponseBodyUrl";
+import { useRecentFilters } from "../hooks/useRecentFilters";
import { useResponseViewMode } from "../hooks/useResponseViewMode";
import { useSaveResponse } from "../hooks/useSaveResponse";
import { useTimelineViewMode } from "../hooks/useTimelineViewMode";
-import { getMimeTypeFromContentType } from "../lib/contentType";
-import { getContentTypeFromHeaders, getCookieCounts } from "../lib/model_util";
-import { ConfirmLargeResponse } from "./ConfirmLargeResponse";
-import { ConfirmLargeResponseRequest } from "./ConfirmLargeResponseRequest";
-import { Button } from "./core/Button";
-import { CountBadge } from "./core/CountBadge";
+import { httpResponseToView } from "../lib/httpViews";
+import { getCookieCounts } from "../lib/model_util";
+import { CopyButton } from "./CopyButton";
import { HotkeyList } from "./core/HotkeyList";
-import { HttpResponseDurationTag } from "./core/HttpResponseDurationTag";
-import { HttpStatusTag } from "./core/HttpStatusTag";
+import { IconButton } from "./core/IconButton";
import { PillButton } from "./core/PillButton";
-import { SizeTag } from "./core/SizeTag";
-import type { TabItem } from "./core/Tabs/Tabs";
-import { TabContent, Tabs } from "./core/Tabs/Tabs";
-import { Tooltip } from "./core/Tooltip";
-import { EmptyStateText } from "./EmptyStateText";
-import { ErrorBoundary } from "./ErrorBoundary";
import { HttpResponseTimeline } from "./HttpResponseTimeline";
import { RecentHttpResponsesDropdown } from "./RecentHttpResponsesDropdown";
import { RequestVersionDropdown } from "./RequestVersionDropdown";
-import { RequestBodyViewer } from "./RequestBodyViewer";
-import { ResponseCookies } from "./ResponseCookies";
-import { ResponseHeaders } from "./ResponseHeaders";
-import { AudioViewer } from "./responseViewers/AudioViewer";
-import { CsvViewer } from "./responseViewers/CsvViewer";
import { EventStreamViewer } from "./responseViewers/EventStreamViewer";
-import { HTMLOrTextViewer } from "./responseViewers/HTMLOrTextViewer";
-import { ImageViewer } from "./responseViewers/ImageViewer";
-import { MultipartViewer } from "./responseViewers/MultipartViewer";
-import { SvgViewer } from "./responseViewers/SvgViewer";
-import { VideoViewer } from "./responseViewers/VideoViewer";
-
-const PdfViewer = lazy(() =>
- import("./responseViewers/PdfViewer").then((m) => ({ default: m.PdfViewer })),
-);
+import { RecentFiltersDropdown } from "./responseViewers/RecentFiltersDropdown";
interface Props {
style?: CSSProperties;
@@ -53,10 +40,6 @@ interface Props {
activeRequestId: string;
}
-const TAB_BODY = "body";
-const TAB_REQUEST = "request";
-const TAB_HEADERS = "headers";
-const TAB_COOKIES = "cookies";
const TAB_TIMELINE = "timeline";
export type TimelineViewMode = "timeline" | "text";
@@ -66,12 +49,11 @@ interface RedirectDropWarning {
droppedHeaders: string[];
}
+/** The shared response pane, bound to the pinned response of the active request */
export function HttpResponsePane({ style, className, activeRequestId }: Props) {
const { activeResponse, setPinnedResponseId, responses } = usePinnedHttpResponse(activeRequestId);
const [viewMode, setViewMode] = useResponseViewMode(activeResponse?.requestId);
const [timelineViewMode, setTimelineViewMode] = useTimelineViewMode();
- const contentType = getContentTypeFromHeaders(activeResponse?.headers ?? null);
- const mimeType = contentType == null ? null : getMimeTypeFromContentType(contentType).essence;
const responseEvents = useHttpResponseEvents(activeResponse);
const redirectDropWarning = useMemo(
@@ -84,281 +66,184 @@ export function HttpResponsePane({ style, className, activeRequestId }: Props) {
const cookieCounts = useMemo(() => getCookieCounts(responseEvents.data), [responseEvents.data]);
const saveResponse = useSaveResponse(activeResponse ?? null);
const copyResponse = useCopyHttpResponse(activeResponse ?? null);
+ const cancel = useCancelHttpResponse(activeResponse?.id ?? null);
+ const body = useResponseBodyLoader(activeResponse ?? null);
+ const requestBody = useRequestBodyLoader(activeResponse ?? null);
+ const textViewer = useResponseTextViewerExtras(activeResponse ?? null);
- const tabs = useMemo(
- () => [
- {
- value: TAB_BODY,
- label: "Response",
- options: {
- value: viewMode,
- onChange: setViewMode,
- items: [
- { label: "Response", value: "pretty" },
- ...(mimeType?.startsWith("image")
- ? []
- : [{ label: "Response (Raw)", shortLabel: "Raw", value: "raw" }]),
- ],
- itemsAfter: [
- {
- label: "Save to File",
- onSelect: saveResponse.mutate,
- leftSlot: ,
- hidden: activeResponse == null || !!activeResponse.error,
- disabled: activeResponse?.state !== "closed" && (activeResponse?.status ?? 0) >= 100,
- },
- {
- label: "Copy Body",
- onSelect: copyResponse.mutate,
- leftSlot: ,
- hidden: activeResponse == null || !!activeResponse.error,
- disabled: activeResponse?.state !== "closed" && (activeResponse?.status ?? 0) >= 100,
- },
- ],
- },
- },
- {
- value: TAB_REQUEST,
- label: "Request",
- rightSlot:
- (activeResponse?.requestContentLength ?? 0) > 0 ? : null,
- },
- {
- value: TAB_HEADERS,
- label: "Headers",
- rightSlot: (
-
- ),
- },
- {
- value: TAB_COOKIES,
- label: "Cookies",
- rightSlot:
- cookieCounts.sent > 0 || cookieCounts.received > 0 ? (
-
- ) : null,
- },
- {
- value: TAB_TIMELINE,
- rightSlot: ,
- options: {
- value: timelineViewMode,
- onChange: (v) => setTimelineViewMode((v as TimelineViewMode) ?? "timeline"),
- items: [
- { label: "Timeline", value: "timeline" },
- { label: "Timeline (Text)", shortLabel: "Timeline", value: "text" },
- ],
- },
- },
- ],
- [
- activeResponse?.headers,
- activeResponse,
- activeResponse?.error,
- activeResponse?.requestContentLength,
- activeResponse?.requestHeaders.length,
- activeResponse?.state,
- activeResponse?.status,
- cookieCounts.sent,
- cookieCounts.received,
- copyResponse.mutate,
- mimeType,
- responseEvents.data?.length,
- saveResponse.mutate,
- setViewMode,
- viewMode,
- timelineViewMode,
- setTimelineViewMode,
- ],
+ const responseView = useMemo(
+ () => (activeResponse == null ? null : httpResponseToView(activeResponse, responseEvents.data)),
+ [activeResponse, responseEvents.data],
);
- const cancel = useCancelHttpResponse(activeResponse?.id ?? null);
+ const extraTabs = useMemo(
+ () =>
+ activeResponse == null
+ ? []
+ : [
+ {
+ tab: {
+ value: TAB_TIMELINE,
+ rightSlot: ,
+ options: {
+ value: timelineViewMode,
+ onChange: (v) => setTimelineViewMode((v as TimelineViewMode) ?? "timeline"),
+ items: [
+ { label: "Timeline", value: "timeline" },
+ { label: "Timeline (Text)", shortLabel: "Timeline", value: "text" },
+ ],
+ },
+ },
+ content: (
+
+ ),
+ },
+ ],
+ [activeResponse, responseEvents.data?.length, setTimelineViewMode, timelineViewMode],
+ );
+
+ const renderBodyViewer = useCallback(
+ ({ mimeType, viewMode }: HostBodyViewerArgs) =>
+ activeResponse != null && mimeType?.match(/^text\/event-stream/i) && viewMode === "pretty" ? (
+
+ ) : null,
+ [activeResponse],
+ );
return (
-
- {activeResponse == null ? (
+ className={className}
+ response={responseView}
+ body={body}
+ requestBody={requestBody}
+ emptyState={
- ) : (
-
-
- {activeResponse && (
-
+
Redirect changed this request
+ {redirectDropWarning.droppedBodyCount > 0 && (
+
+ Body dropped on {redirectDropWarning.droppedBodyCount}{" "}
+ {redirectDropWarning.droppedBodyCount === 1 ? "redirect hop" : "redirect hops"}
+
)}
- >
-
- {activeResponse.state !== "closed" && }
-
- •
-
- •
-
-
- {shouldShowRedirectDropWarning ? (
-
-
- Redirect changed this request
-
- {redirectDropWarning.droppedBodyCount > 0 && (
-
- Body dropped on {redirectDropWarning.droppedBodyCount}{" "}
- {redirectDropWarning.droppedBodyCount === 1
- ? "redirect hop"
- : "redirect hops"}
-
- )}
- {redirectDropWarning.droppedHeaders.length > 0 && (
-
- Headers dropped:{" "}
-
- {redirectDropWarning.droppedHeaders.join(", ")}
-
-
- )}
- See Timeline for details.
-
- }
- >
-
- }
- >
-
- {getRedirectWarningLabel(redirectDropWarning)}
-
-
+ {redirectDropWarning.droppedHeaders.length > 0 && (
+
+ Headers dropped:{" "}
+
+ {redirectDropWarning.droppedHeaders.join(", ")}
-
- ) : (
-
+
)}
-
-
-
-
-
- )}
+ See Timeline for details.
+
+ }
+ >
+
+ }
+ >
+ {getRedirectWarningLabel(redirectDropWarning)}
+
+
+
+ ) : null
+ }
+ statusLineRight={
+ activeResponse != null && (
+
+
+
-
-
- {activeResponse?.error && (
-
- {activeResponse.error}
-
- )}
- {/* Show tabs if we have any data (headers, body, etc.) even if there's an error */}
-
-
-
-
-
- {activeResponse.state === "initialized" ? (
-
-
-
-
- Sending Request
-
-
-
-
- ) : activeResponse.state === "closed" &&
- (activeResponse.contentLength ?? 0) === 0 ? (
- Empty
- ) : mimeType?.match(/^text\/event-stream/i) && viewMode === "pretty" ? (
-
- ) : mimeType?.match(/^image\/svg/) ? (
-
- ) : mimeType?.match(/^image/i) ? (
-
- ) : mimeType?.match(/^audio/i) ? (
-
- ) : mimeType?.match(/^video/i) ? (
-
- ) : mimeType?.match(/^multipart/i) && viewMode === "pretty" ? (
-
- ) : mimeType?.match(/pdf/i) ? (
-
- ) : mimeType?.match(/csv|tab-separated/i) && viewMode === "pretty" ? (
-
- ) : (
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
+ )
+ }
+ />
);
}
+/** The client's additions to the response text viewer: filter history, save and copy */
+function useResponseTextViewerExtras(
+ response: HttpResponse | null,
+): ResponseTextViewerExtras | undefined {
+ const filterStateKey = `response.body.${response?.requestId ?? ""}`;
+ const { recentFilters, addFilter, removeFilter, togglePin, clearFilters } =
+ useRecentFilters(filterStateKey);
+ const saveResponse = useSaveResponse(response);
+ const copyResponse = useCopyHttpResponse(response);
+ const filterLeftSlot = useCallback(
+ (filter: TextFilterApi) => (
+
+
+
+ ),
+ [recentFilters, removeFilter, togglePin, clearFilters],
+ );
+
+ if (response == null) return undefined;
+ const actionsDisabled = response.state !== "closed" && response.status >= 100;
+ return {
+ filterStateKey,
+ onFilterApplied: addFilter,
+ filterLeftSlot,
+ footerActions: [
+ saveResponse.mutate()}
+ className="border !border-border-subtle"
+ />,
+ copyResponse.mutate()}
+ className="border !border-border-subtle"
+ />,
+ ],
+ };
+}
+
+function renderCopyButton(getText: () => Promise) {
+ return ;
+}
+
function getRedirectDropWarning(
events: HttpResponseEvent[] | undefined,
): RedirectDropWarning | null {
@@ -406,58 +291,3 @@ function getRedirectWarningLabel(warning: RedirectDropWarning): string {
}
return "Dropped headers";
}
-
-function EnsureCompleteResponse({
- response,
- Component,
-}: {
- response: HttpResponse;
- Component: ComponentType<{ bodyUrl: string }>;
-}) {
- // Wait until the response has been fully-downloaded before asking for it
- const complete = response.state === "closed";
- const bodyUrl = useResponseBodyUrl(complete ? response : null);
-
- if (!complete || bodyUrl.isPending) {
- return (
-
-
-
- );
- }
-
- if (bodyUrl.error) {
- return {String(bodyUrl.error)};
- }
-
- if (bodyUrl.data == null) {
- return Empty response body
;
- }
-
- return ;
-}
-
-function HttpSvgViewer({ response }: { response: HttpResponse }) {
- const body = useResponseBodyText({ response, filter: null });
-
- if (!body.data) return null;
-
- return ;
-}
-
-function HttpCsvViewer({ response, className }: { response: HttpResponse; className?: string }) {
- const body = useResponseBodyText({ response, filter: null });
-
- return ;
-}
-
-function HttpMultipartViewer({ response }: { response: HttpResponse }) {
- const body = useResponseBodyBytes({ response });
-
- if (body.data == null) return null;
-
- const contentTypeHeader = getContentTypeFromHeaders(response.headers);
- const boundary = contentTypeHeader?.split("boundary=")[1] ?? "unknown";
-
- return ;
-}
diff --git a/apps/yaak-client/components/HttpResponseTimeline.tsx b/apps/yaak-client/components/HttpResponseTimeline.tsx
index 4475b4a0c..72b05a382 100644
--- a/apps/yaak-client/components/HttpResponseTimeline.tsx
+++ b/apps/yaak-client/components/HttpResponseTimeline.tsx
@@ -13,9 +13,8 @@ import { resolvedModelName } from "../lib/resolvedModelName";
import { Editor } from "./core/Editor/LazyEditor";
import { type EventDetailAction, EventDetailHeader, EventViewer } from "./core/EventViewer";
import { EventViewerRow } from "./core/EventViewerRow";
-import { HttpStatusTagRaw } from "./core/HttpStatusTag";
-import { Icon, type IconProps } from "@yaakapp-internal/ui";
-import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
+import { Icon, type IconProps, HttpStatusTagRaw, KeyValueRows } from "@yaakapp-internal/ui";
+import { KeyValueRow } from "./core/KeyValueRow";
import type { TimelineViewMode } from "./HttpResponsePane";
interface Props {
diff --git a/apps/yaak-client/components/ImportDataDialog.tsx b/apps/yaak-client/components/ImportDataDialog.tsx
index 951613017..43e698e06 100644
--- a/apps/yaak-client/components/ImportDataDialog.tsx
+++ b/apps/yaak-client/components/ImportDataDialog.tsx
@@ -1,33 +1,35 @@
import {
- type Folder,
type ImportDestination,
type ImportPlan,
type ImportPlanItem,
type ImportSource,
type Workspace,
} from "@yaakapp-internal/models";
-import { HStack, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
-import { platform } from "@yaakapp-internal/platform";
+import { Banner, FormattedError, HStack, Icon, VStack, IconTooltip } from "@yaakapp-internal/ui";
import classNames from "classnames";
-import { formatDistanceToNowStrict } from "date-fns";
-import { useEffect, useMemo, useRef, useState } from "react";
-import { pluralize } from "../lib/pluralize";
+import { type ComponentProps, useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { errorMessage } from "../lib/errorMessage";
import { CommercialUseBanner } from "./CommercialUseBanner";
-import { Button } from "./core/Button";
-import { Checkbox } from "./core/Checkbox";
+import {
+ ImportSourceList,
+ type ImportSourceDetection,
+ type ImportSourcePath,
+ InlineButton,
+ toSourcePath,
+} from "./ImportSourceList";
import type { CheckboxTreeNode } from "./core/CheckboxTree";
import { CheckboxTree } from "./core/CheckboxTree";
-import { IconTooltip } from "./core/IconTooltip";
-import { PlainInput } from "./core/PlainInput";
+import { Chip } from "./core/Chip";
+import { DialogFooter } from "./core/Dialog";
import { Select } from "./core/Select";
import { SegmentedControl } from "./core/SegmentedControl";
+import { pluralize } from "@yaakapp-internal/lib/pluralize";
interface Props {
currentWorkspace: Workspace | null;
workspaces: Workspace[];
- selectedFolder: Folder | null;
- planFile: (filePath: string, destination: ImportDestination) => Promise;
- planUrl: (url: string, destination: ImportDestination) => Promise;
+ planSources: (sources: ImportSourcePath[], destination: ImportDestination) => Promise;
+ detectSource: (source: ImportSourcePath) => Promise;
listSources: (workspaceId: string) => Promise;
findSourcesForOrigin: (args: { filePath?: string; url?: string }) => Promise;
commit: (plan: ImportPlan) => Promise;
@@ -35,25 +37,6 @@ interface Props {
onError: (err: unknown) => void;
}
-/**
- * An absolute or relative path is unambiguously a file. Everything else is treated as a URL, so a
- * bare host like `example.com/openapi.json` still works (the backend defaults it to https).
- */
-function isFilePath(value: string): boolean {
- return (
- value.startsWith("/") ||
- value.startsWith("./") ||
- value.startsWith("../") ||
- value.startsWith("~/") ||
- value.startsWith("\\\\") ||
- /^[a-zA-Z]:[\\/]/.test(value)
- );
-}
-
-function fileName(path: string): string {
- return path.split(/[/\\]/).at(-1) || path;
-}
-
/**
* Loads the current workspace's linked sources before rendering the dialog, so the inner
* component can construct its initial state (prefilled path, destination) in one pass instead of
@@ -82,30 +65,19 @@ export function ImportDataDialog(props: Props) {
return ;
}
-function latestSource(sources: ImportSource[]): ImportSource | null {
- return sources.reduce(
- (latest, s) => (latest == null || s.lastImportedAt > latest.lastImportedAt ? s : latest),
- null,
- );
-}
-
function LoadedImportDataDialog({
currentWorkspace,
workspaces,
- selectedFolder,
- planFile,
- planUrl,
- listSources,
+ planSources,
+ detectSource,
findSourcesForOrigin,
commit,
cancel,
onError,
initialSources,
}: Props & { initialSources: ImportSource[] }) {
- // A workspace with a linked source is probably being re-imported, so start from that source
- const prefill = latestSource(initialSources);
-
const [isLoading, setIsLoading] = useState(false);
+ const [sourceError, setSourceError] = useState(null);
const [plan, setPlan] = useState(null);
const [items, setItems] = useState([]);
// null means no explicit choice yet, so the default below applies
@@ -113,65 +85,82 @@ function LoadedImportDataDialog({
null,
);
const [otherWorkspaceId, setOtherWorkspaceId] = useState(null);
- const [targetSelectedFolder, setTargetSelectedFolder] = useState(selectedFolder != null);
- const [linkedSources, setLinkedSources] = useState(
- prefill != null ? initialSources : [],
+ const [originSources, setOriginSources] = useState(initialSources);
+ const initialPaths = useMemo(
+ () => [...new Set(initialSources.map((source) => source.origin))].map(toSourcePath),
+ [initialSources],
);
- const [originSources, setOriginSources] = useState(
- prefill != null ? [prefill] : [],
+ const [sources, setSources] = useState(initialPaths);
+ const knownPaths = useRef(new Set(initialPaths.map((source) => source.path)));
+ const [detections, setDetections] = useState>({});
+ const detect = useCallback(
+ (added: ImportSourcePath[]) => {
+ setDetections((prev) => ({
+ ...prev,
+ ...Object.fromEntries(added.map((s) => [s.path, { status: "loading" as const }])),
+ }));
+ for (const source of added) {
+ const settle = (detection: ImportSourceDetection) =>
+ setDetections((prev) =>
+ source.path in prev ? { ...prev, [source.path]: detection } : prev,
+ );
+ detectSource(source).then(
+ (importer) => settle({ status: "ok", importer }),
+ (err) => settle({ status: "error", message: errorMessage(err) }),
+ );
+ }
+ },
+ [detectSource],
);
- // A file path or a URL. Both inputs write here, so there is only ever one thing to import
- const [source, setSource] = useState(prefill?.origin ?? null);
- const [forceUpdateKey, setForceUpdateKey] = useState(0);
- const [isHovering, setIsHovering] = useState(false);
- const ref = useRef(null);
- const trimmedSource = source?.trim() ?? "";
- const filePath = isFilePath(trimmedSource) ? trimmedSource : null;
+ const allDetected = sources.every((source) => detections[source.path]?.status === "ok");
+ useEffect(() => {
+ detect(initialPaths);
+ }, [detect, initialPaths]);
- const selectSource = (value: string) => {
- setSource(value);
- // Remount the input so it shows the path of the newly-picked file
- setForceUpdateKey((k) => k + 1);
+ const addSources = useCallback(
+ (added: ImportSourcePath[]) => {
+ setSourceError(null);
+ const fresh = added.filter(({ path }) => {
+ if (knownPaths.current.has(path)) return false;
+ knownPaths.current.add(path);
+ return true;
+ });
+ if (fresh.length === 0) return;
+ setSources((existing) => [...existing, ...fresh]);
+ detect(fresh);
+ },
+ [detect],
+ );
+ const removeSource = (path: string) => {
+ setSourceError(null);
+ knownPaths.current.delete(path);
+ setSources((current) => current.filter((source) => source.path !== path));
+ setDetections(({ [path]: _removed, ...rest }) => rest);
};
- // Accept a file dropped anywhere on the dialog, the way SelectFile does for its button
useEffect(() => {
- return platform.window.onDragDrop((event) => {
- if (event.type === "over") {
- const p = event.position;
- const r = ref.current?.getBoundingClientRect();
- if (r == null) return;
- setIsHovering(p.x >= r.left && p.x <= r.right && p.y >= r.top && p.y <= r.bottom);
- } else if (event.type === "drop" && isHovering) {
- const p = event.paths[0];
- if (p) selectSource(p);
- setIsHovering(false);
- } else {
- setIsHovering(false);
- }
- });
- }, [isHovering, setSource]);
-
- useEffect(() => {
- if (trimmedSource === "") {
+ let cancelled = false;
+ if (sources.length === 0) {
setOriginSources([]);
return;
}
- let cancelled = false;
- const timeout = setTimeout(() => {
- findSourcesForOrigin(filePath != null ? { filePath } : { url: trimmedSource })
- .then((sources) => {
- if (!cancelled) setOriginSources(sources);
- })
- .catch(() => setOriginSources([]));
- }, 300);
+ Promise.all(
+ sources.map(({ path, kind }) =>
+ findSourcesForOrigin(kind === "url" ? { url: path } : { filePath: path }),
+ ),
+ )
+ .then((found) => {
+ if (!cancelled) setOriginSources(found.flat());
+ })
+ .catch(() => {
+ if (!cancelled) setOriginSources([]);
+ });
return () => {
cancelled = true;
- clearTimeout(timeout);
};
- }, [trimmedSource, filePath, findSourcesForOrigin]);
+ }, [sources, findSourcesForOrigin]);
- // The one workspace this file is linked to, if there is exactly one.
+ // The one workspace these sources are linked to, if there is exactly one.
const linkedWorkspace = useMemo(() => {
const ids = [...new Set(originSources.map((s) => s.workspaceId))];
if (ids.length !== 1) return null;
@@ -193,32 +182,6 @@ function LoadedImportDataDialog({
? otherWorkspaceId
: null;
- useEffect(() => {
- if (destinationWorkspaceId == null) {
- setLinkedSources([]);
- return;
- }
- let cancelled = false;
- listSources(destinationWorkspaceId)
- .then((sources) => {
- if (!cancelled) setLinkedSources(sources);
- })
- .catch(() => setLinkedSources([]));
- return () => {
- cancelled = true;
- };
- }, [destinationWorkspaceId, listSources]);
-
- const handleSelectFile = async () => {
- const selected = await platform.dialog.open({ title: "Select File", multiple: false });
- if (selected == null) return;
- selectSource(selected);
- };
-
- // The selected folder belongs to the workspace being viewed, so it is only offerable when that
- // is also the destination.
- const canTargetSelectedFolder = selectedFolder != null && destinationKind === "current";
-
const destination = (): ImportDestination => {
if (destinationWorkspaceId == null) {
return { type: "new_workspace" };
@@ -226,21 +189,18 @@ function LoadedImportDataDialog({
return {
type: "existing_workspace",
workspaceId: destinationWorkspaceId,
- folderId: canTargetSelectedFolder && targetSelectedFolder ? selectedFolder.id : undefined,
};
};
const handlePreview = async () => {
setIsLoading(true);
+ setSourceError(null);
try {
- const nextPlan =
- filePath != null
- ? await planFile(filePath, destination())
- : await planUrl(trimmedSource, destination());
+ const nextPlan = await planSources(sources, destination());
setPlan(nextPlan);
setItems(nextPlan.items);
} catch (err) {
- onError(err);
+ setSourceError(err);
} finally {
setIsLoading(false);
}
@@ -258,16 +218,17 @@ function LoadedImportDataDialog({
}
};
- const itemTree = useMemo(() => buildItemTree(items), [items]);
-
- // A folder row's checkbox aggregates its subtree the way the git commit tree does: creates and
- // updates toggle together, while removals only ever cascade beneath a removed folder.
- const toggleNode = (node: CheckboxTreeNode, checked: boolean) => {
- const targets = new Set(
- collectItems(node)
- .filter((i) => togglesWith(node.data, i))
- .map((i) => i.modelId),
- );
+ // A folder row's checkbox carries everything beneath it, deletions included — the row labels
+ // say which of those are destructive. Checking anything also brings back the folders it needs
+ // to live in.
+ const toggleNode = (node: CheckboxTreeNode, checked: boolean) => {
+ const targets = new Set(togglableItems(node).map((i) => i.modelId));
+ if (checked && node.data.kind === "item") {
+ const byId = new Map(items.map((i) => [i.modelId, i]));
+ for (const ancestor of ancestorsOf(node.data.item, byId)) {
+ if (isMissingFolder(ancestor)) targets.add(ancestor.modelId);
+ }
+ }
setItems((prev) => prev.map((i) => (targets.has(i.modelId) ? { ...i, selected: checked } : i)));
};
@@ -277,25 +238,16 @@ function LoadedImportDataDialog({
);
};
- // A row the user can't meaningfully toggle on its own: a planned resource inside a deselected
- // new folder can't exist, and a removed folder takes its contents with it.
+ // Deleting a folder takes its contents with it, so those rows have nothing left to decide.
const disabledIds = useMemo(() => {
const disabled = new Set();
const byId = new Map(items.map((i) => [i.modelId, i]));
for (const item of items) {
- const seen = new Set();
- let parentId = item.parentId;
- while (parentId != null && !seen.has(parentId)) {
- seen.add(parentId);
- const parent = byId.get(parentId);
- if (parent == null || parent.model !== "folder") break;
- if (parent.action === "create" && !parent.selected && item.action !== "delete") {
+ if (item.action !== "delete") continue;
+ for (const parent of ancestorsOf(item, byId)) {
+ if (parent.action === "delete" && parent.selected) {
disabled.add(item.modelId);
}
- if (parent.action === "delete" && parent.selected && item.action === "delete") {
- disabled.add(item.modelId);
- }
- parentId = parent.parentId;
}
}
return disabled;
@@ -314,193 +266,220 @@ function LoadedImportDataDialog({
return item.selected;
}).length;
- const destinationLabel = (() => {
- if (plan.destination.type === "new_workspace") return "New workspace";
- const { workspaceId, folderId } = plan.destination;
+ // The row's label carries what kind of destination it is, so the value can just be its name
+ const [destinationLabel, destinationValue] = ((): [string, string] => {
+ if (plan.destination.type === "new_workspace") {
+ const names = plan.resources.workspaces.map((w) => w.name).filter((n) => n !== "");
+ if (names.length === 0) return ["New workspace", "Untitled"];
+ return [
+ names.length === 1 ? "New workspace" : `${names.length} new workspaces`,
+ names.join(", "),
+ ];
+ }
+ const { workspaceId } = plan.destination;
const name = workspaces.find((w) => w.id === workspaceId)?.name ?? "Unknown workspace";
- return folderId != null && folderId === selectedFolder?.id
- ? `${name} / ${selectedFolder.name}`
- : name;
+ return ["Destination", name];
})();
// The destination workspace roots the tree. It is not a plan item — commit always applies
// it — so its checkbox only aggregates the subtree.
- const workspaceRoot: CheckboxTreeNode = (() => {
- const planned = plan.resources.workspaces[0];
+ const workspaceRoots: CheckboxTreeNode[] = (() => {
const planDestination = plan.destination;
const existing =
planDestination.type === "existing_workspace"
? workspaces.find((w) => w.id === planDestination.workspaceId)
: null;
- return {
- key: existing?.id ?? planned?.id ?? "workspace",
+ const destinations = existing ? [existing] : plan.resources.workspaces;
+ if (destinations.length === 1) {
+ const workspace = destinations[0]!;
+ return [
+ {
+ key: workspace.id,
+ data: {
+ kind: "destination",
+ label: workspace.name,
+ isNew: planDestination.type === "new_workspace",
+ },
+ children: buildItemTree(items),
+ },
+ ];
+ }
+ const workspaceById = new Map(
+ [
+ ...plan.resources.environments,
+ ...plan.resources.folders,
+ ...plan.resources.httpRequests,
+ ...plan.resources.grpcRequests,
+ ...plan.resources.websocketRequests,
+ ].map((resource) => [resource.id, resource.workspaceId]),
+ );
+ return destinations.map((workspace) => ({
+ key: workspace.id,
data: {
- action: plan.destination.type === "new_workspace" ? "create" : "unchanged",
- model: "workspace",
- modelId: existing?.id ?? planned?.id ?? "workspace",
- name: existing?.name ?? planned?.name ?? "New workspace",
- selected: true,
+ kind: "destination",
+ label: workspace.name,
+ isNew: planDestination.type === "new_workspace",
},
- children: itemTree,
- };
+ children: buildItemTree(
+ items.filter((item) => workspaceById.get(item.modelId) === workspace.id),
+ ),
+ }));
})();
return (
-
-
-
-
- disabledIds.has(n.key)}
- isRelevant={(n) => n.data.model === "workspace" || n.data.action !== "unchanged"}
- renderRow={(n) => }
- />
-
-
- {plan.warnings.length > 0 && (
-
-
Import details
-
- {plan.warnings.map((warning) => (
-
-
-
-
{warning.title}
-
{warning.detail}
-
-
- ))}
-
+ <>
+
+
- )}
-
- {footerNote !== "" && {footerNote}
}
-
-
-
-
+ {plan.warnings
+ .filter(
+ (warning, index, warnings) =>
+ warnings.findIndex(
+ (other) =>
+ other.title === warning.title &&
+ other.detail === warning.detail &&
+ other.level === warning.level,
+ ) === index,
+ )
+ .map((warning) => (
+
+
+
+
{warning.title}
+
{warning.detail}
+
+
+ ))}
+
+ {workspaceRoots.map((root) => (
+
+ disabledIds.has(n.key)}
+ isCollapsedByDefault={(n) =>
+ (n.data.kind === "destination" && workspaceRoots.length > 1) ||
+ (n.data.kind === "item" && n.data.item.action === "ignored")
+ }
+ isRelevant={(n) =>
+ n.data.kind === "destination" ||
+ (n.data.kind === "item" && n.data.item.action !== "unchanged")
+ }
+ renderRow={(n) => (
+
+ )}
+ />
+
+ ))}
+
+
{footerNote}
+ ) : undefined
+ }
+ actions={[
+ {
+ label: "Back",
+ disabled: isLoading,
+ onClick: () => {
+ setPlan(null);
+ setItems([]);
+ },
+ },
+ {
+ label: isLoading
+ ? "Importing"
+ : changeCount > 0
+ ? `Apply ${changeCount} ${changeCount === 1 ? "Change" : "Changes"}`
+ : "Done",
+ color: "primary",
+ isLoading,
+ onClick: handleCommit,
+ },
+ ]}
+ />
+ >
);
}
- const lastImported =
- originSources.find((s) => s.workspaceId === destinationWorkspaceId) ??
- linkedSources.reduce(
- (latest, s) => (latest == null || s.lastImportedAt > latest.lastImportedAt ? s : latest),
- null,
- );
-
- return (
-
-
-
-
-
-
+
-
-
+ {destinationKind === "other" && (
+
+ >
);
}
function ImportTreeRow({
- item,
+ row,
onResolveConflict,
}: {
- item: ImportPlanItem;
+ row: TreeRow;
onResolveConflict: (modelId: string, resolution: "keep_mine" | "take_source") => void;
}) {
+ if (row.kind !== "item") {
+ return (
+ <>
+ {row.kind === "destination" && (
+
+ )}
+ {row.label}
+ {row.kind === "destination" && row.isNew && (
+
+ )}
+ >
+ );
+ }
+
+ const { item } = row;
+ const label = actionLabel(item);
return (
<>
- {item.model === "workspace" || item.model === "folder" || item.model === "environment" ? (
-
- ) : (
-
- )}
{item.name}
{item.action === "conflict" ? (
-
+
onResolveConflict(item.modelId, v)}
options={[
@@ -577,29 +556,50 @@ function ImportTreeRow({
{ value: "take_source", label: "Take source" },
]}
/>
-
) : (
- actionLabel(item) && (
-
- {actionLabel(item)}
-
-
+ label != null && (
+
)
)}
>
);
}
+function ActionChip({
+ label,
+ help,
+ color,
+}: {
+ label: string;
+ help: string | null;
+ color: ComponentProps
["color"];
+}) {
+ return (
+
+ {label}
+ {help != null && }
+
+ );
+}
+
+function actionColor(item: ImportPlanItem): ComponentProps["color"] {
+ switch (item.action) {
+ case "create":
+ return "success";
+ case "update":
+ return "info";
+ case "delete":
+ return "danger";
+ case "keep_local":
+ return item.selected ? "warning" : "default";
+ case "unchanged":
+ case "conflict":
+ case "ignored":
+ return "default";
+ }
+}
+
function actionLabel(item: ImportPlanItem): string | null {
switch (item.action) {
case "create":
@@ -610,29 +610,68 @@ function actionLabel(item: ImportPlanItem): string | null {
return "removed";
case "keep_local":
return "edited";
+ case "ignored":
+ return "ignored";
default:
return null;
}
}
function actionHelp(item: ImportPlanItem): string | null {
+ const help = (text: string) =>
+ item.changedFields.length > 0
+ ? `${text} · ${item.changedFields.map(fieldLabel).join(", ")}`
+ : text;
switch (item.action) {
case "create":
- return "Added since the last import";
+ return "Not in this workspace yet";
case "update":
- return "Changed since the last import";
+ return item.reason === "moved_into_ignored_folder"
+ ? "Moved into a folder that isn't imported. Importing that folder brings it along"
+ : help("Changed in the source since the last import");
case "delete":
- return "Deleted since the last import";
+ return "Gone from the source since the last import. Checking it deletes it here";
case "keep_local":
- return "Local edits made since the last import. Importing will revert them if checked";
+ return help("Changed here since the last import. Checking it reverts to the source");
case "conflict":
- return "Changed both here and in the file since the last import";
+ return help("Changed here and in the source since the last import");
+ case "ignored":
+ return "Not in this workspace. Imports leave it alone until you check it";
default:
return null;
}
}
-function buildItemTree(items: ImportPlanItem[]): CheckboxTreeNode[] {
+function fieldLabel(field: string): string {
+ return field.replace(/([A-Z])/g, " $1").toLowerCase();
+}
+
+/** Every plan item above `item`, nearest first. */
+function ancestorsOf(item: ImportPlanItem, byId: Map): ImportPlanItem[] {
+ const ancestors: ImportPlanItem[] = [];
+ const seen = new Set();
+ let parentId = item.parentId;
+ while (parentId != null && !seen.has(parentId)) {
+ seen.add(parentId);
+ const parent = byId.get(parentId);
+ if (parent == null) break;
+ ancestors.push(parent);
+ parentId = parent.parentId;
+ }
+ return ancestors;
+}
+
+/**
+ * A row of the preview tree. Most are plan items, but the destination workspace and the group the
+ * workspace's environments sit in are headings: they aggregate their children and decide nothing
+ * themselves.
+ */
+type TreeRow =
+ | { kind: "destination"; label: string; isNew: boolean }
+ | { kind: "group"; label: string }
+ | { kind: "item"; item: ImportPlanItem };
+
+function buildItemTree(items: ImportPlanItem[]): CheckboxTreeNode[] {
const byId = new Map(items.map((i) => [i.modelId, i]));
const childrenOf = new Map();
const roots: ImportPlanItem[] = [];
@@ -646,45 +685,66 @@ function buildItemTree(items: ImportPlanItem[]): CheckboxTreeNode [
+ const byKind = (list: ImportPlanItem[]) => [
+ ...list.filter((i) => i.model === "environment"),
...list.filter((i) => i.model === "folder"),
- ...list.filter((i) => i.model !== "folder"),
+ ...list.filter((i) => i.model !== "environment" && i.model !== "folder"),
];
- const toNode = (item: ImportPlanItem, seen: Set): CheckboxTreeNode => ({
+ const toNode = (item: ImportPlanItem, seen: Set): CheckboxTreeNode => ({
key: item.modelId,
- data: item,
+ data: { kind: "item", item },
children: seen.has(item.modelId)
? []
- : foldersFirst(childrenOf.get(item.modelId) ?? []).map((c) =>
+ : byKind(childrenOf.get(item.modelId) ?? []).map((c) =>
toNode(c, new Set([...seen, item.modelId])),
),
});
- return foldersFirst(roots).map((r) => toNode(r, new Set()));
+ // The workspace's environments have nothing to sit under — a sub-environment is a sibling of
+ // the base one, not its child — so a heading groups them into one thing to turn on and off.
+ const environments = roots.filter((i) => i.model === "environment");
+ const others = byKind(roots.filter((i) => i.model !== "environment"));
+ const nodes = others.map((r) => toNode(r, new Set()));
+ if (environments.length === 0) return nodes;
+ return [
+ {
+ key: "group:environments",
+ data: { kind: "group", label: "Variables" },
+ children: environments.map((e) => toNode(e, new Set())),
+ },
+ ...nodes,
+ ];
}
-function collectItems(node: CheckboxTreeNode): ImportPlanItem[] {
- return [node.data, ...node.children.flatMap(collectItems)];
+function collectRows(node: CheckboxTreeNode): TreeRow[] {
+ return [node.data, ...node.children.flatMap(collectRows)];
+}
+
+/** A folder that isn't there yet, so anything inside it needs it brought in first. */
+function isMissingFolder(item: ImportPlanItem): boolean {
+ return item.model === "folder" && (item.action === "create" || item.action === "ignored");
}
/**
- * Whether toggling `root`'s checkbox also toggles `item` in its subtree. Destructive decisions
- * (deletions, reverting local edits) never ride along with a parent toggle.
+ * The plan item a row's checkbox decides, if it decides one. An unchanged resource has nothing to
+ * decide and a conflict is decided by its own control, so neither takes a checkbox — nor rides
+ * along with a parent's.
*/
-function togglesWith(root: ImportPlanItem, item: ImportPlanItem): boolean {
- if (item.model === "workspace") return false;
- if (root.action === "delete") return item.action === "delete";
- if (item.action === "keep_local") {
- return root.modelId === item.modelId && item.model !== "folder";
- }
- return item.action === "create" || item.action === "update";
+function togglableItem(row: TreeRow): ImportPlanItem | null {
+ if (row.kind !== "item") return null;
+ const { item } = row;
+ return item.action === "unchanged" || item.action === "conflict" ? null : item;
}
-function nodeCheckedStatus(
- node: CheckboxTreeNode,
-): boolean | "indeterminate" | "hidden" {
- const covered = collectItems(node).filter((i) => togglesWith(node.data, i));
+function togglableItems(node: CheckboxTreeNode): ImportPlanItem[] {
+ return collectRows(node)
+ .map(togglableItem)
+ .filter((i) => i != null);
+}
+
+function nodeCheckedStatus(node: CheckboxTreeNode): boolean | "indeterminate" | "hidden" {
+ const covered = togglableItems(node);
if (covered.length === 0) return "hidden";
const selected = covered.filter((i) => i.selected).length;
if (selected === covered.length) return true;
diff --git a/apps/yaak-client/components/ImportSourceList.tsx b/apps/yaak-client/components/ImportSourceList.tsx
new file mode 100644
index 000000000..82db4745b
--- /dev/null
+++ b/apps/yaak-client/components/ImportSourceList.tsx
@@ -0,0 +1,271 @@
+import { platform } from "@yaakapp-internal/platform";
+import { Icon, LoadingIcon } from "@yaakapp-internal/ui";
+import classNames from "classnames";
+import { type KeyboardEvent, type ReactNode, useEffect, useRef, useState } from "react";
+import { Button } from "./core/Button";
+import { IconButton } from "./core/IconButton";
+import { PathList, splitPath } from "./core/PathList";
+import { PlainInput } from "./core/PlainInput";
+
+export interface ImportSourcePath {
+ path: string;
+ kind?: "file" | "folder" | "url";
+}
+
+export type ImportSourceDetection =
+ | { status: "loading" }
+ | { status: "ok"; importer: string }
+ | { status: "error"; message: string };
+
+interface Props {
+ sources: ImportSourcePath[];
+ detections: Record;
+ disabled?: boolean;
+ onAdd: (sources: ImportSourcePath[]) => void;
+ onRemove: (path: string) => void;
+ onError: (err: unknown) => void;
+}
+
+/** A bare hostname is a URL; local paths need an absolute or explicit relative prefix. */
+export function isImportFilePath(value: string): boolean {
+ return (
+ value.startsWith("/") ||
+ value.startsWith("./") ||
+ value.startsWith("../") ||
+ value.startsWith("~/") ||
+ value.startsWith("\\\\") ||
+ /^[a-zA-Z]:[\\/]/.test(value)
+ );
+}
+
+/** A typed or prefilled path is a URL unless it looks like a local path; kind is left for the host */
+export function toSourcePath(path: string): ImportSourcePath {
+ return { path, kind: isImportFilePath(path) ? undefined : "url" };
+}
+
+export function ImportSourceList({
+ sources,
+ detections,
+ disabled,
+ onAdd,
+ onRemove,
+ onError,
+}: Props) {
+ const ref = useRef(null);
+ const [isHovering, setIsHovering] = useState(false);
+ const [pathInput, setPathInput] = useState("");
+ const [showPathInput, setShowPathInput] = useState(false);
+ const pathInputRef = useRef<{ focus: () => void }>(null);
+ const trimmedPath = pathInput.trim();
+
+ const openPathInput = () => {
+ setShowPathInput(true);
+ // The add-row menu hands focus back to its trigger as it closes, on a timer, so focus after it
+ setTimeout(() => pathInputRef.current?.focus(), 50);
+ };
+
+ const closePathInput = () => {
+ setPathInput("");
+ setShowPathInput(false);
+ };
+
+ const addPath = () => {
+ if (!trimmedPath || disabled) return;
+ onAdd([toSourcePath(trimmedPath)]);
+ closePathInput();
+ };
+
+ useEffect(() => {
+ if (disabled) return;
+ return platform.window.onDragDrop((event) => {
+ if (event.type === "leave") {
+ setIsHovering(false);
+ return;
+ }
+ const rect = ref.current?.getBoundingClientRect();
+ const { x, y } = event.position;
+ const isOver =
+ rect != null && x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
+ if (event.type === "drop") {
+ if (isOver) onAdd(event.paths.map((path) => ({ path })));
+ setIsHovering(false);
+ } else {
+ setIsHovering(isOver);
+ }
+ });
+ }, [disabled, onAdd]);
+
+ const pick = async (directory: boolean) => {
+ try {
+ const selected = await platform.dialog.open({
+ title: directory ? "Select Import Folder" : "Select Import Files",
+ multiple: true,
+ directory,
+ });
+ if (selected == null) return;
+ onAdd(selected.map((path) => ({ path, kind: directory ? "folder" : "file" })));
+ } catch (err) {
+ onError(err);
+ }
+ };
+
+ const handlePathKeyDown = (event: KeyboardEvent) => {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ addPath();
+ } else if (event.key === "Escape") {
+ event.stopPropagation();
+ closePathInput();
+ }
+ };
+
+ const pathInputEl = (
+
+ {trimmedPath !== "" && (
+
+ )}
+
+
+ }
+ />
+ );
+
+ if (sources.length === 0) {
+ return (
+
+
+
+ {isHovering ? (
+ Drop to add
+ ) : (
+
+ Choose{" "}
+ pick(false)}>
+ files
+
+ , a{" "}
+ pick(true)}>
+ folder
+
+ , or a{" "}
+
+ URL
+
+ , or drag them here
+
+ )}
+
+ Supports OpenAPI, Swagger, Postman, Insomnia, Bruno, curl, and Yaak exports
+
+
+ {showPathInput && pathInputEl}
+
+ );
+ }
+
+ return (
+ pick(false) },
+ { label: "Folder", icon: "folder", onSelect: () => pick(true) },
+ { label: "URL or file path", icon: "globe", onSelect: openPathInput },
+ ]}
+ items={sources.map((source) => {
+ const detection = detections[source.path];
+ return {
+ path: source.path,
+ icon: sourceIcon(source),
+ failed: detection?.status === "error",
+ subtitle: ,
+ };
+ })}
+ >
+ {showPathInput && pathInputEl}
+
+ );
+}
+
+function DetectionSubtitle({
+ path,
+ detection,
+}: {
+ path: string;
+ detection: ImportSourceDetection | undefined;
+}) {
+ const { parent } = splitPath(path);
+ if (detection?.status === "loading") {
+ return (
+ <>
+
+ Detecting format
+ >
+ );
+ }
+ if (detection?.status === "error") return detection.message;
+ return (
+ <>
+ {detection?.status === "ok" && {detection.importer}}
+ {detection?.status === "ok" && parent !== "" && ·}
+ {parent !== "" && {parent}}
+ >
+ );
+}
+
+function sourceIcon({ kind }: ImportSourcePath) {
+ switch (kind) {
+ case "url":
+ return "globe";
+ case "folder":
+ return "folder";
+ case "file":
+ return "file";
+ case undefined:
+ return "import";
+ }
+}
+
+export function InlineButton({
+ children,
+ disabled,
+ onClick,
+}: {
+ children: ReactNode;
+ disabled?: boolean;
+ onClick: () => void;
+}) {
+ return (
+
+ );
+}
diff --git a/apps/yaak-client/components/JsonBodyEditor.tsx b/apps/yaak-client/components/JsonBodyEditor.tsx
deleted file mode 100644
index 209fbac50..000000000
--- a/apps/yaak-client/components/JsonBodyEditor.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import { linter } from "@codemirror/lint";
-import type { HttpRequest } from "@yaakapp-internal/models";
-import { patchModel } from "@yaakapp-internal/models";
-import { Banner, Icon } from "@yaakapp-internal/ui";
-import { useCallback, useMemo } from "react";
-import { useKeyValue } from "../hooks/useKeyValue";
-import { fireAndForget } from "../lib/fireAndForget";
-import { textLikelyContainsJsonComments } from "../lib/jsonComments";
-import type { DropdownItem } from "./core/Dropdown";
-import { Dropdown } from "./core/Dropdown";
-import type { EditorProps } from "./core/Editor/Editor";
-import { jsonParseLinter } from "./core/Editor/json-lint";
-import { Editor } from "./core/Editor/LazyEditor";
-import { IconButton } from "./core/IconButton";
-import { IconTooltip } from "./core/IconTooltip";
-
-interface Props {
- forceUpdateKey: string;
- heightMode: EditorProps["heightMode"];
- request: HttpRequest;
-}
-
-export function JsonBodyEditor({ forceUpdateKey, heightMode, request }: Props) {
- const handleChange = useCallback(
- (text: string) => patchModel(request, { body: { ...request.body, text } }),
- [request],
- );
-
- const autoFix = request.body?.sendJsonComments !== true;
-
- const lintExtension = useMemo(
- () =>
- linter(
- jsonParseLinter(
- autoFix
- ? { allowComments: true, allowTrailingCommas: true }
- : { allowComments: false, allowTrailingCommas: false },
- ),
- ),
- [autoFix],
- );
-
- const hasComments = useMemo(
- () => textLikelyContainsJsonComments(request.body?.text ?? ""),
- [request.body?.text],
- );
-
- const { value: bannerDismissed, set: setBannerDismissed } = useKeyValue({
- namespace: "no_sync",
- key: ["json-fix-3", request.workspaceId],
- fallback: false,
- });
-
- const handleToggleAutoFix = useCallback(() => {
- const newBody = { ...request.body };
- if (autoFix) {
- newBody.sendJsonComments = true;
- } else {
- delete newBody.sendJsonComments;
- }
- fireAndForget(patchModel(request, { body: newBody }));
- }, [request, autoFix]);
-
- const handleDropdownOpen = useCallback(() => {
- if (!bannerDismissed) {
- fireAndForget(setBannerDismissed(true));
- }
- }, [bannerDismissed, setBannerDismissed]);
-
- const showBanner = hasComments && autoFix && !bannerDismissed;
-
- const stripMessage = "Automatically strip comments and trailing commas before sending";
- const actions = useMemo(
- () => [
- showBanner && (
-
-
- Auto-fix enabled
-
-
-
- ),
-
- ,
- leftSlot: (
-
- ),
- },
- ] satisfies DropdownItem[]
- }
- >
-
-
-
,
- ],
- [handleDropdownOpen, handleToggleAutoFix, autoFix, showBanner],
- );
-
- return (
-
- );
-}
diff --git a/apps/yaak-client/components/LargeValueDialog.tsx b/apps/yaak-client/components/LargeValueDialog.tsx
index ecafea00d..34f6ccf1f 100644
--- a/apps/yaak-client/components/LargeValueDialog.tsx
+++ b/apps/yaak-client/components/LargeValueDialog.tsx
@@ -1,15 +1,20 @@
import { formatSize } from "@yaakapp-internal/lib/formatSize";
-import { Banner, Button, HStack, LoadingIcon } from "@yaakapp-internal/ui";
+import {
+ Banner,
+ Button,
+ HStack,
+ LoadingIcon,
+ AudioViewer,
+ ImageViewer,
+ SvgViewer,
+ VideoViewer,
+} from "@yaakapp-internal/ui";
import type { ReactNode } from "react";
import { lazy, Suspense, useEffect, useMemo, useState } from "react";
import type { SniffedValue } from "./core/Editor/sniffValue";
import { showDialog } from "../lib/dialog";
import { decodeValue, largeValueActions } from "../lib/largeValue";
import { Dropdown } from "./core/Dropdown";
-import { AudioViewer } from "./responseViewers/AudioViewer";
-import { ImageViewer } from "./responseViewers/ImageViewer";
-import { SvgViewer } from "./responseViewers/SvgViewer";
-import { VideoViewer } from "./responseViewers/VideoViewer";
const PdfViewer = lazy(() =>
import("./responseViewers/PdfViewer").then((m) => ({ default: m.PdfViewer })),
diff --git a/apps/yaak-client/components/MoveToWorkspaceDialog.tsx b/apps/yaak-client/components/MoveToWorkspaceDialog.tsx
index 564e64132..6f1bb4ca7 100644
--- a/apps/yaak-client/components/MoveToWorkspaceDialog.tsx
+++ b/apps/yaak-client/components/MoveToWorkspaceDialog.tsx
@@ -3,12 +3,12 @@ import { patchModel, workspacesAtom } from "@yaakapp-internal/models";
import { InlineCode, VStack } from "@yaakapp-internal/ui";
import { useAtomValue } from "jotai";
import { useState } from "react";
-import { pluralizeCount } from "../lib/pluralize";
import { resolvedModelName } from "../lib/resolvedModelName";
import { router } from "../lib/router";
import { showToast } from "../lib/toast";
import { Button } from "./core/Button";
import { Select } from "./core/Select";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
interface Props {
activeWorkspaceId: string;
diff --git a/apps/yaak-client/components/Onboarding.tsx b/apps/yaak-client/components/Onboarding.tsx
new file mode 100644
index 000000000..63e753af6
--- /dev/null
+++ b/apps/yaak-client/components/Onboarding.tsx
@@ -0,0 +1,212 @@
+import type { Color } from "@yaakapp-internal/plugins";
+import { platform } from "@yaakapp-internal/platform";
+import { settingsAtom } from "@yaakapp-internal/models";
+import { HeaderSize, Heading, Icon, type IconProps, LoadingIcon } from "@yaakapp-internal/ui";
+import classNames from "classnames";
+import { useAtomValue } from "jotai";
+import { useState } from "react";
+import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir";
+import { showDialog } from "../lib/dialog";
+import { importData } from "../lib/importData";
+import {
+ createExampleWorkspace,
+ createFreshWorkspace,
+ type OnboardingChoice,
+ recordOnboardingChoice,
+} from "../lib/onboarding";
+import { showErrorToast } from "../lib/toast";
+import { CloneGitRepositoryDialog } from "./CloneGitRepositoryDialog";
+import { Button } from "./core/Button";
+
+/** Shown instead of a workspace when there are none. */
+export function Onboarding() {
+ const settings = useAtomValue(settingsAtom);
+ const { capabilities } = platform;
+ const canImport = capabilities.plugins;
+ const showAlreadyUsing = capabilities.localFiles || capabilities.git || canImport;
+ const [busy, setBusy] = useState(null);
+
+ const choose = (choice: OnboardingChoice, run: () => Promise | void) => async () => {
+ recordOnboardingChoice(choice);
+ setBusy(choice);
+ try {
+ await run();
+ } catch (err) {
+ showErrorToast({
+ id: "onboarding-failed",
+ title: "Something went wrong",
+ message: String(err),
+ });
+ } finally {
+ setBusy(null);
+ }
+ };
+
+ return (
+
+
+
+
+
+
How would you like to get started?
+
+ {canImport
+ ? "Bring over existing work, try a real API, or start fresh."
+ : "Try a real API, or start fresh."}
+
+
+
+
+ {canImport && (
+ importData.mutateAsync())}
+ />
+ )}
+
+
+
+
+ {showAlreadyUsing && (
+
+
Already using Yaak?
+
+ {capabilities.localFiles && (
+ }
+ disabled={busy != null}
+ onClick={choose("open_folder", async () => {
+ const dir = await platform.dialog.open({
+ title: "Select Workspace Directory",
+ directory: true,
+ multiple: false,
+ });
+ if (dir == null) return;
+ await openWorkspaceFromSyncDir.mutateAsync(dir);
+ })}
+ >
+ Open folder
+
+ )}
+ {capabilities.git && (
+ }
+ disabled={busy != null}
+ onClick={choose("clone_git", () => {
+ showDialog({
+ id: "clone-git-repository",
+ size: "md",
+ title: "Clone Git Repository",
+ render: ({ hide }) => ,
+ });
+ })}
+ >
+ Clone repository
+
+ )}
+ {canImport && (
+ }
+ disabled={busy != null}
+ onClick={choose("import_yaak", () => importData.mutateAsync())}
+ >
+ Import
+
+ )}
+
+
+ )}
+
+
+
+ );
+}
+
+function StartOption({
+ color,
+ icon,
+ title,
+ description,
+ onClick,
+ busy,
+ disabled,
+}: {
+ color: Color;
+ icon: IconProps["icon"];
+ title: string;
+ description: string;
+ onClick: () => void;
+ busy: boolean;
+ disabled: boolean;
+}) {
+ return (
+
+ );
+}
diff --git a/apps/yaak-client/components/RecentGrpcConnectionsDropdown.tsx b/apps/yaak-client/components/RecentGrpcConnectionsDropdown.tsx
index 224731fb5..26f034edc 100644
--- a/apps/yaak-client/components/RecentGrpcConnectionsDropdown.tsx
+++ b/apps/yaak-client/components/RecentGrpcConnectionsDropdown.tsx
@@ -1,6 +1,6 @@
import type { GrpcConnection } from "@yaakapp-internal/models";
import { deleteModel } from "@yaakapp-internal/models";
-import { HStack, Icon } from "@yaakapp-internal/ui";
+import { HStack, Icon, formatMillis } from "@yaakapp-internal/ui";
import {
differenceInHours,
differenceInMinutes,
@@ -9,10 +9,9 @@ import {
isYesterday,
} from "date-fns";
import { useDeleteGrpcConnections } from "../hooks/useDeleteGrpcConnections";
-import { pluralizeCount } from "../lib/pluralize";
import { Dropdown, type DropdownItem } from "./core/Dropdown";
-import { formatMillis } from "./core/HttpResponseDurationTag";
import { IconButton } from "./core/IconButton";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
interface Props {
connections: GrpcConnection[];
diff --git a/apps/yaak-client/components/RecentHttpResponsesDropdown.tsx b/apps/yaak-client/components/RecentHttpResponsesDropdown.tsx
index 4db7a0f5a..94428b9a7 100644
--- a/apps/yaak-client/components/RecentHttpResponsesDropdown.tsx
+++ b/apps/yaak-client/components/RecentHttpResponsesDropdown.tsx
@@ -1,6 +1,6 @@
import type { HttpResponse } from "@yaakapp-internal/models";
import { deleteModel } from "@yaakapp-internal/models";
-import { HStack, Icon } from "@yaakapp-internal/ui";
+import { HStack, Icon, formatMillis, HttpStatusTag, SizeTag } from "@yaakapp-internal/ui";
import {
differenceInHours,
differenceInMinutes,
@@ -12,10 +12,7 @@ import { useDeleteHttpResponses } from "../hooks/useDeleteHttpResponses";
import { useKeyValue } from "../hooks/useKeyValue";
import { DismissibleBanner } from "./core/DismissibleBanner";
import { Dropdown, type DropdownItem } from "./core/Dropdown";
-import { formatMillis } from "./core/HttpResponseDurationTag";
-import { HttpStatusTag } from "./core/HttpStatusTag";
import { IconButton } from "./core/IconButton";
-import { SizeTag } from "./core/SizeTag";
interface Props {
responses: HttpResponse[];
diff --git a/apps/yaak-client/components/RecentWebsocketConnectionsDropdown.tsx b/apps/yaak-client/components/RecentWebsocketConnectionsDropdown.tsx
index 5b6aa1452..0d55a9e31 100644
--- a/apps/yaak-client/components/RecentWebsocketConnectionsDropdown.tsx
+++ b/apps/yaak-client/components/RecentWebsocketConnectionsDropdown.tsx
@@ -1,6 +1,6 @@
import type { WebsocketConnection } from "@yaakapp-internal/models";
import { deleteModel, getModel } from "@yaakapp-internal/models";
-import { HStack, Icon } from "@yaakapp-internal/ui";
+import { HStack, Icon, formatMillis } from "@yaakapp-internal/ui";
import {
differenceInHours,
differenceInMinutes,
@@ -9,10 +9,9 @@ import {
isYesterday,
} from "date-fns";
import { deleteWebsocketConnections } from "../commands/deleteWebsocketConnections";
-import { pluralizeCount } from "../lib/pluralize";
import { Dropdown, type DropdownItem } from "./core/Dropdown";
-import { formatMillis } from "./core/HttpResponseDurationTag";
import { IconButton } from "./core/IconButton";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
interface Props {
connections: WebsocketConnection[];
diff --git a/apps/yaak-client/components/RedirectToLatestWorkspace.tsx b/apps/yaak-client/components/RedirectToLatestWorkspace.tsx
index 49616ac5c..0d21fe5ea 100644
--- a/apps/yaak-client/components/RedirectToLatestWorkspace.tsx
+++ b/apps/yaak-client/components/RedirectToLatestWorkspace.tsx
@@ -7,6 +7,7 @@ import { getRecentRequests } from "../hooks/useRecentRequests";
import { useRecentWorkspaces } from "../hooks/useRecentWorkspaces";
import { fireAndForget } from "../lib/fireAndForget";
import { router } from "../lib/router";
+import { Onboarding } from "./Onboarding";
export function RedirectToLatestWorkspace() {
const workspaces = useAtomValue(workspacesAtom);
@@ -14,10 +15,6 @@ export function RedirectToLatestWorkspace() {
useEffect(() => {
if (workspaces.length === 0 || recentWorkspaces == null) {
- console.log("No workspaces found to redirect to. Skipping.", {
- workspaces,
- recentWorkspaces,
- });
return;
}
@@ -34,11 +31,21 @@ export function RedirectToLatestWorkspace() {
request_id: requestId,
};
+ // Whatever created the first workspace may have already navigated into it
+ const currentId = router.history.location.pathname.match(/^\/workspaces\/([^/]+)/)?.[1];
+ if (workspaces.some((w) => w.id === currentId)) return;
+
console.log("Redirecting to workspace", params, search);
await router.navigate({ to: "/workspaces/$workspaceId", params, search });
})(),
);
}, [recentWorkspaces, workspaces, workspaces.length]);
+ // The global models are loaded before the router mounts, so an empty list is a real
+ // first launch (or the last workspace was just deleted), not a store still loading
+ if (workspaces.length === 0) {
+ return ;
+ }
+
return null;
}
diff --git a/apps/yaak-client/components/RequestBodyViewer.tsx b/apps/yaak-client/components/RequestBodyViewer.tsx
deleted file mode 100644
index a5a77825f..000000000
--- a/apps/yaak-client/components/RequestBodyViewer.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-import type { HttpResponse } from "@yaakapp-internal/models";
-import { lazy, Suspense } from "react";
-import { useHttpRequestBody } from "../hooks/useHttpRequestBody";
-import { getMimeTypeFromContentType, languageFromContentType } from "../lib/contentType";
-import { LoadingIcon } from "@yaakapp-internal/ui";
-import { EmptyStateText } from "./EmptyStateText";
-import { AudioViewer } from "./responseViewers/AudioViewer";
-import { CsvViewer } from "./responseViewers/CsvViewer";
-import { ImageViewer } from "./responseViewers/ImageViewer";
-import { MultipartViewer } from "./responseViewers/MultipartViewer";
-import { SvgViewer } from "./responseViewers/SvgViewer";
-import { TextViewer } from "./responseViewers/TextViewer";
-import { VideoViewer } from "./responseViewers/VideoViewer";
-import { WebPageViewer } from "./responseViewers/WebPageViewer";
-
-const PdfViewer = lazy(() =>
- import("./responseViewers/PdfViewer").then((m) => ({ default: m.PdfViewer })),
-);
-
-interface Props {
- response: HttpResponse;
-}
-
-export function RequestBodyViewer({ response }: Props) {
- return ;
-}
-
-function RequestBodyViewerInner({ response }: Props) {
- const { data, isLoading, error } = useHttpRequestBody(response);
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- if (error) {
- return Error loading request body: {error.message};
- }
-
- if (data?.bodyText == null || data.bodyText.length === 0) {
- return No request body;
- }
-
- const { bodyText, body } = data;
-
- // Try to detect language from content-type header that was sent
- const contentTypeHeader = response.requestHeaders.find(
- (h) => h.name.toLowerCase() === "content-type",
- );
- const contentType = contentTypeHeader?.value ?? null;
- const mimeType = contentType ? getMimeTypeFromContentType(contentType).essence : null;
- const language = languageFromContentType(contentType, bodyText);
-
- // Route to appropriate viewer based on content type
- if (mimeType?.match(/^multipart/i)) {
- const boundary = contentType?.split("boundary=")[1] ?? "unknown";
- // Create a copy because parseMultipart may detach the buffer
- const bodyCopy = new Uint8Array(body);
- return (
-
- );
- }
-
- if (mimeType?.match(/^image\/svg/i)) {
- return ;
- }
-
- if (mimeType?.match(/^image/i)) {
- return ;
- }
-
- if (mimeType?.match(/^audio/i)) {
- return ;
- }
-
- if (mimeType?.match(/^video/i)) {
- return ;
- }
-
- if (mimeType?.match(/csv|tab-separated/i)) {
- return ;
- }
-
- if (mimeType?.match(/^text\/html/i)) {
- return ;
- }
-
- if (mimeType?.match(/pdf/i)) {
- return (
- }>
-
-
- );
- }
-
- return (
-
- );
-}
diff --git a/apps/yaak-client/components/RequestMethodDropdown.tsx b/apps/yaak-client/components/RequestMethodDropdown.tsx
index 8754750e0..746117ad2 100644
--- a/apps/yaak-client/components/RequestMethodDropdown.tsx
+++ b/apps/yaak-client/components/RequestMethodDropdown.tsx
@@ -1,38 +1,20 @@
import type { HttpRequest } from "@yaakapp-internal/models";
-import { patchModel } from "@yaakapp-internal/models";
-import classNames from "classnames";
-import { memo, useCallback, useMemo } from "react";
-import { showPrompt } from "../lib/prompt";
-import { Button } from "./core/Button";
-import type { DropdownItem } from "./core/Dropdown";
-import { HttpMethodTag, HttpMethodTagRaw } from "./core/HttpMethodTag";
-import { Icon } from "@yaakapp-internal/ui";
-import type { RadioDropdownItem } from "./core/RadioDropdown";
-import { RadioDropdown } from "./core/RadioDropdown";
+import { patchModel, settingsAtom } from "@yaakapp-internal/models";
+import { RequestMethodDropdown as BaseRequestMethodDropdown } from "@yaakapp-internal/ui";
+import { useAtomValue } from "jotai";
+import { memo, useCallback } from "react";
type Props = {
request: HttpRequest;
className?: string;
};
-const radioItems: RadioDropdownItem[] = [
- "GET",
- "PUT",
- "POST",
- "PATCH",
- "DELETE",
- "OPTIONS",
- "QUERY",
- "HEAD",
-].map((m) => ({
- value: m,
- label: ,
-}));
-
+/** The shared method menu, writing to the request and coloured by the user's setting */
export const RequestMethodDropdown = memo(function RequestMethodDropdown({
request,
className,
}: Props) {
+ const settings = useAtomValue(settingsAtom);
const handleChange = useCallback(
async (method: string) => {
await patchModel(request, { method });
@@ -40,39 +22,12 @@ export const RequestMethodDropdown = memo(function RequestMethodDropdown({
[request],
);
- const itemsAfter = useMemo(
- () => [
- {
- key: "custom",
- label: "CUSTOM",
- leftSlot: ,
- onSelect: async () => {
- const newMethod = await showPrompt({
- id: "custom-method",
- label: "Http Method",
- title: "Custom Method",
- confirmText: "Save",
- description: "Enter a custom method name",
- placeholder: "CUSTOM",
- });
- if (newMethod == null) return;
- await handleChange(newMethod);
- },
- },
- ],
- [handleChange],
- );
-
return (
-
-
-
+ className={className}
+ />
);
});
diff --git a/apps/yaak-client/components/ResponseHeaders.tsx b/apps/yaak-client/components/ResponseHeaders.tsx
deleted file mode 100644
index ea1182ffc..000000000
--- a/apps/yaak-client/components/ResponseHeaders.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import type { HttpResponse } from "@yaakapp-internal/models";
-import { format, formatDistanceToNowStrict } from "date-fns";
-import { useMemo } from "react";
-import { CountBadge } from "./core/CountBadge";
-import { DetailsBanner } from "./core/DetailsBanner";
-import { IconButton } from "./core/IconButton";
-import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
-import { platform } from "@yaakapp-internal/platform";
-
-interface Props {
- response: HttpResponse;
-}
-
-export function ResponseHeaders({ response }: Props) {
- const responseHeaders = useMemo(
- () =>
- [...response.headers].sort((a, b) =>
- a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()),
- ),
- [response.headers],
- );
- const requestHeaders = useMemo(
- () =>
- [...response.requestHeaders].sort((a, b) =>
- a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()),
- ),
- [response.requestHeaders],
- );
- return (
-
-
Info}>
-
-
-
-
-
-
- {response.url}
- platform.openUrl(response.url)}
- title="Open in browser"
- />
-
-
-
- {response.remoteAddr ?? --}
-
-
- {response.version ?? --}
-
-
-
-
- Request Headers
-
- }
- >
- {requestHeaders.length === 0 ? (
-
- ) : (
-
- {requestHeaders.map((h, i) => (
- // oxlint-disable-next-line react/no-array-index-key
-
- {h.value}
-
- ))}
-
- )}
-
-
- Response Headers
-
- }
- >
- {responseHeaders.length === 0 ? (
-
- ) : (
-
- {responseHeaders.map((h, i) => (
- // oxlint-disable-next-line react/no-array-index-key
-
- {h.value}
-
- ))}
-
- )}
-
-
- );
-}
-
-function NoHeaders() {
- return No Headers;
-}
diff --git a/apps/yaak-client/components/ResponseInfo.tsx b/apps/yaak-client/components/ResponseInfo.tsx
index 378895fc3..7bdfe6115 100644
--- a/apps/yaak-client/components/ResponseInfo.tsx
+++ b/apps/yaak-client/components/ResponseInfo.tsx
@@ -1,7 +1,8 @@
import type { HttpResponse } from "@yaakapp-internal/models";
import { IconButton } from "./core/IconButton";
-import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
+import { KeyValueRow } from "./core/KeyValueRow";
import { platform } from "@yaakapp-internal/platform";
+import { KeyValueRows } from "@yaakapp-internal/ui";
interface Props {
response: HttpResponse;
diff --git a/apps/yaak-client/components/SelectFile.tsx b/apps/yaak-client/components/SelectFile.tsx
index bc1487238..800a05d21 100644
--- a/apps/yaak-client/components/SelectFile.tsx
+++ b/apps/yaak-client/components/SelectFile.tsx
@@ -1,5 +1,5 @@
import { platform } from "@yaakapp-internal/platform";
-import { HStack } from "@yaakapp-internal/ui";
+import { HStack, IconTooltip, Label } from "@yaakapp-internal/ui";
import classNames from "classnames";
import mime from "mime";
import type { ReactNode } from "react";
@@ -7,8 +7,6 @@ import { useEffect, useRef, useState } from "react";
import type { ButtonProps } from "./core/Button";
import { Button } from "./core/Button";
import { IconButton } from "./core/IconButton";
-import { IconTooltip } from "./core/IconTooltip";
-import { Label } from "./core/Label";
type Props = Omit & {
onChange: (value: { filePath: string | null; contentType: string | null }) => void;
diff --git a/apps/yaak-client/components/Settings/Settings.tsx b/apps/yaak-client/components/Settings/Settings.tsx
index 5588734df..1039ce74f 100644
--- a/apps/yaak-client/components/Settings/Settings.tsx
+++ b/apps/yaak-client/components/Settings/Settings.tsx
@@ -1,14 +1,14 @@
import { platform } from "@yaakapp-internal/platform";
import { useLicense } from "@yaakapp-internal/license";
import { pluginsAtom, settingsAtom } from "@yaakapp-internal/models";
-import { HeaderSize, HStack, Icon } from "@yaakapp-internal/ui";
+import { HeaderSize, HStack, Icon, CountBadge } from "@yaakapp-internal/ui";
import classNames from "classnames";
import { useAtomValue } from "jotai";
import { useKeyPressEvent } from "react-use";
import { appInfo } from "../../lib/appInfo";
import { capitalize } from "../../lib/capitalize";
-import { CountBadge } from "../core/CountBadge";
import { TabContent, type TabItem, Tabs } from "../core/Tabs/Tabs";
+import { SettingsAgents } from "./SettingsAgents";
import { SettingsCertificates } from "./SettingsCertificates";
import { SettingsGeneral } from "./SettingsGeneral";
import { SettingsHotkeys } from "./SettingsHotkeys";
@@ -31,6 +31,7 @@ const TAB_SHORTCUTS = "shortcuts";
const TAB_PROXY = "proxy";
const TAB_CERTIFICATES = "certificates";
const TAB_PLUGINS = "plugins";
+const TAB_AGENTS = "agents";
const TAB_LICENSE = "license";
const tabs = [
TAB_GENERAL,
@@ -38,6 +39,7 @@ const tabs = [
TAB_INTERFACE,
TAB_SHORTCUTS,
TAB_PLUGINS,
+ TAB_AGENTS,
TAB_CERTIFICATES,
TAB_PROXY,
TAB_LICENSE,
@@ -93,7 +95,9 @@ export default function Settings({ tab, hide }: Props) {
(value): TabItem => ({
value,
label: capitalize(value),
- hidden: !appInfo.featureLicense && value === TAB_LICENSE,
+ hidden:
+ (!appInfo.featureLicense && value === TAB_LICENSE) ||
+ (!platform.capabilities.agents && value === TAB_AGENTS),
leftSlot:
value === TAB_GENERAL ? (
@@ -109,6 +113,8 @@ export default function Settings({ tab, hide }: Props) {
) : value === TAB_PLUGINS ? (
+ ) : value === TAB_AGENTS ? (
+
) : value === TAB_LICENSE ? (
) : null,
@@ -140,6 +146,9 @@ export default function Settings({ tab, hide }: Props) {
+
+
+
diff --git a/apps/yaak-client/components/Settings/SettingsAgents.tsx b/apps/yaak-client/components/Settings/SettingsAgents.tsx
new file mode 100644
index 000000000..4ba04091c
--- /dev/null
+++ b/apps/yaak-client/components/Settings/SettingsAgents.tsx
@@ -0,0 +1,140 @@
+import { useQuery, useQueryClient } from "@tanstack/react-query";
+import { platform } from "@yaakapp-internal/platform";
+import type { AgentSetupStatus, AppMetaData } from "@yaakapp-internal/rpc-schema";
+import { Banner, Heading, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
+import { useEffect } from "react";
+import { useKeyValue } from "../../hooks/useKeyValue";
+import { usePluginInfos } from "../../hooks/usePluginInfo";
+import {
+ AGENT_CLIENTS,
+ type AgentClient,
+ cliSetup,
+ skillInstallCommand,
+} from "../../lib/agentSetup";
+import { appInfo } from "../../lib/appInfo";
+import { rpc } from "../../lib/rpc";
+import { Link } from "../core/Link";
+import { SegmentedControl } from "../core/SegmentedControl";
+import {
+ SettingCommand,
+ SettingSnippet,
+ SettingsList,
+ SettingsSection,
+} from "../core/SettingRow";
+import { DeprecatedPluginBanner } from "./SettingsPlugins";
+
+const CLI_INSTALL_COMMAND = "npm install -g @yaakapp/cli";
+const MCP_SERVER_PLUGIN = "@yaak/mcp-server";
+
+export function SettingsAgents() {
+ const queryClient = useQueryClient();
+ const { value: storedClient, set: setClient } = useKeyValue({
+ key: "agents_setup_client",
+ fallback: "claude_code",
+ });
+ const client = AGENT_CLIENTS.find((c) => c.value === storedClient)?.value ?? "claude_code";
+ const clientLabel = AGENT_CLIENTS.find((c) => c.value === client)?.label ?? "your agent";
+ const cliVersion = useQuery({
+ queryKey: ["cli_version"],
+ queryFn: async () => (await rpc("cmd_metadata")).cliVersion,
+ initialData: appInfo.cliVersion,
+ });
+ const setupStatus = useQuery({
+ queryKey: ["agent_setup_status", client],
+ queryFn: () => rpc("cmd_agent_setup_status", { agent: client }),
+ });
+ const mcpServerPlugin = usePluginInfos().find(({ info }) => info.name === MCP_SERVER_PLUGIN);
+
+ useEffect(() => {
+ return platform.window.onFocusChanged((focused) => {
+ if (!focused) return;
+ void queryClient.invalidateQueries({ queryKey: ["cli_version"] });
+ void queryClient.invalidateQueries({ queryKey: ["agent_setup_status"] });
+ });
+ }, [queryClient]);
+
+ const cliInstalled = cliVersion.data != null;
+ const cli = cliSetup(client);
+
+ return (
+
+
+
Agents
+
+ Connect AI coding agents like Claude Code and Cursor to Yaak.
+
+
+
+
+
+
+
+ {cliInstalled ? (
+
+
+
+ Yaak CLI {cliVersion.data} is installed.
+
+
+ ) : (
+
+
+
+
+ Install the Yaak CLI first
+
+
+ Agents launch it to reach Yaak, even with the app closed.
+
+
+
+ Docs
+
+ Checks again when you come back to Yaak.
+
+
+
+
+ )}
+ {mcpServerPlugin != null && (
+
+
+ The two steps below replace it. Uninstall it once your agent is connected.
+
+
+ )}
+
+
+ Lets {clientLabel} run the yaak command directly.
+ >
+ }
+ snippet={skillInstallCommand(client)}
+ language="shell"
+ disabled={!cliInstalled}
+ done={setupStatus.data?.skill ? "Installed" : null}
+ />
+
+
+
+ );
+}
diff --git a/apps/yaak-client/components/Settings/SettingsLicense.tsx b/apps/yaak-client/components/Settings/SettingsLicense.tsx
index f2ac0016d..9e72d481c 100644
--- a/apps/yaak-client/components/Settings/SettingsLicense.tsx
+++ b/apps/yaak-client/components/Settings/SettingsLicense.tsx
@@ -4,7 +4,6 @@ import { differenceInDays } from "date-fns";
import { formatDate } from "date-fns/format";
import { useState } from "react";
import { useToggle } from "../../hooks/useToggle";
-import { pluralizeCount } from "../../lib/pluralize";
import { pricingUrl } from "../../lib/pricingUrl";
import { CargoFeature } from "../CargoFeature";
import { Button } from "../core/Button";
@@ -12,6 +11,7 @@ import { Link } from "../core/Link";
import { PlainInput } from "../core/PlainInput";
import { Separator } from "../core/Separator";
import { platform } from "@yaakapp-internal/platform";
+import { pluralizeCount } from "@yaakapp-internal/lib/pluralize";
export function SettingsLicense() {
return (
diff --git a/apps/yaak-client/components/Settings/SettingsPlugins.tsx b/apps/yaak-client/components/Settings/SettingsPlugins.tsx
index e83cdc382..d9bdcaa6c 100644
--- a/apps/yaak-client/components/Settings/SettingsPlugins.tsx
+++ b/apps/yaak-client/components/Settings/SettingsPlugins.tsx
@@ -2,13 +2,9 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import type { Plugin } from "@yaakapp-internal/models";
import { patchModel, pluginsAtom } from "@yaakapp-internal/models";
import type { PluginVersion } from "@yaakapp-internal/plugins";
+import { checkPluginUpdates, installPlugin, searchPlugins } from "@yaakapp-internal/plugins";
import {
- checkPluginUpdates,
- installPlugin,
- searchPlugins,
- uninstallPlugin,
-} from "@yaakapp-internal/plugins";
-import {
+ Banner,
HStack,
Icon,
InlineCode,
@@ -20,18 +16,17 @@ import {
TableHeaderCell,
TableRow,
useDebouncedValue,
+ CountBadge,
} from "@yaakapp-internal/ui";
import classNames from "classnames";
import { useAtomValue } from "jotai";
-import { useState } from "react";
+import { type ReactNode, useState } from "react";
import { useInstallPlugin } from "../../hooks/useInstallPlugin";
-import { usePluginInfo } from "../../hooks/usePluginInfo";
+import { usePluginInfo, usePluginInfos } from "../../hooks/usePluginInfo";
import { usePluginsKey, useRefreshPlugins } from "../../hooks/usePlugins";
-import { showConfirmDelete } from "../../lib/confirm";
-import { minPromiseMillis } from "../../lib/minPromiseMillis";
+import { usePromptUninstallPlugin } from "../../hooks/useUninstallPlugin";
import { Button } from "../core/Button";
import { Checkbox } from "../core/Checkbox";
-import { CountBadge } from "../core/CountBadge";
import { IconButton } from "../core/IconButton";
import { Link } from "../core/Link";
import { PlainInput } from "../core/PlainInput";
@@ -205,7 +200,7 @@ function PluginTableRow({
mutationKey: ["install_plugin", name],
mutationFn: (name: string) => installPlugin(name, null),
});
- const uninstall = usePromptUninstall(plugin?.id ?? null, displayName);
+ const uninstall = usePromptUninstallPlugin(plugin?.id ?? null, displayName);
const refreshPlugins = useRefreshPlugins();
return (
@@ -296,7 +291,10 @@ function PluginSearch() {
const debouncedQuery = useDebouncedValue(query);
const results = useQuery({
queryKey: ["plugins", debouncedQuery],
- queryFn: () => searchPlugins(query),
+ queryFn: async () => {
+ const { plugins } = await searchPlugins(query);
+ return { plugins: plugins.filter((p) => p.deprecated == null) };
+ },
});
return (
@@ -349,22 +347,77 @@ function InstalledPlugins({ plugins, className }: { plugins: Plugin[]; className
) : (
-
-
-
-
- Display Name
- Name
- Version
-
-
-
-
- {plugins.map((p) => (
-
- ))}
-
-
+
+
+
+
+
+
+ Display Name
+ Name
+ Version
+
+
+
+
+ {plugins.map((p) => (
+
+ ))}
+
+
+
+ );
+}
+
+function DeprecatedPluginBanners() {
+ const deprecated = usePluginInfos().filter(
+ ({ plugin, info }) => plugin.source !== "bundled" && info.deprecated != null,
+ );
+ return (
+ 0 && "pb-3")}>
+ {deprecated.map(({ plugin, info }) => (
+
+ {withInlineCode(info.deprecated ?? "")}
+
+ ))}
+
+ );
+}
+
+/** Backtick spans in a package.json string, set as code. */
+function withInlineCode(text: string): ReactNode {
+ return text
+ .split("`")
+ .map((part, i) => (i % 2 === 1 ? {part} : part));
+}
+
+export function DeprecatedPluginBanner({
+ children,
+ name,
+ plugin,
+}: {
+ children: ReactNode;
+ name: string;
+ plugin: Plugin;
+}) {
+ const uninstall = usePromptUninstallPlugin(plugin.id, name);
+ return (
+
+
+
The {name} plugin is deprecated.
+
{children}
+
+
+
);
}
@@ -393,31 +446,6 @@ function BundledPlugins({ plugins }: { plugins: Plugin[] }) {
);
}
-function usePromptUninstall(pluginId: string | null, name: string) {
- const mut = useMutation({
- mutationKey: ["uninstall_plugin", pluginId],
- mutationFn: async () => {
- if (pluginId == null) return;
-
- const confirmed = await showConfirmDelete({
- id: `uninstall-plugin-${pluginId}`,
- title: "Uninstall Plugin",
- confirmText: "Uninstall",
- description: (
- <>
- Permanently uninstall {name}?
- >
- ),
- });
- if (confirmed) {
- await minPromiseMillis(uninstallPlugin(pluginId), 700);
- }
- },
- });
-
- return pluginId == null ? null : mut;
-}
-
function usePluginUpdates() {
return useQuery({
queryKey: ["plugin_updates", usePluginsKey()],
diff --git a/apps/yaak-client/components/SettingsDropdown.tsx b/apps/yaak-client/components/SettingsDropdown.tsx
index 2c9336bec..48a677f29 100644
--- a/apps/yaak-client/components/SettingsDropdown.tsx
+++ b/apps/yaak-client/components/SettingsDropdown.tsx
@@ -82,10 +82,9 @@ export function SettingsDropdown() {
},
{
label: "Install CLI",
- hidden: appInfo.cliVersion != null,
+ hidden: appInfo.cliVersion != null || !platform.capabilities.agents,
leftSlot: ,
- rightSlot: ,
- onSelect: () => platform.openUrl("https://yaak.app/docs/cli"),
+ onSelect: () => openSettings.mutate("agents"),
},
{
label: "Feedback",
diff --git a/apps/yaak-client/components/Sidebar.tsx b/apps/yaak-client/components/Sidebar.tsx
index 3e600a27d..b072b148a 100644
--- a/apps/yaak-client/components/Sidebar.tsx
+++ b/apps/yaak-client/components/Sidebar.tsx
@@ -69,7 +69,6 @@ import type { Ast } from "./core/Editor/filter/query";
import { evaluate, parseQuery } from "./core/Editor/filter/query";
import { formatFieldFilter } from "./core/Editor/filter/format";
import { HttpMethodTag } from "./core/HttpMethodTag";
-import { HttpStatusTag } from "./core/HttpStatusTag";
import {
Icon,
LoadingIcon,
@@ -77,6 +76,7 @@ import {
isSelectedFamily,
selectedIdsFamily,
InlineCode,
+ HttpStatusTag,
} from "@yaakapp-internal/ui";
import type { TreeNode, TreeHandle, TreeProps, TreeItemProps } from "@yaakapp-internal/ui";
import { IconButton } from "./core/IconButton";
@@ -941,10 +941,14 @@ const sidebarTreeAtom = atom<
if (node.children != null) {
childItems.sort((a, b) => {
- if (a.sortPriority === b.sortPriority) {
- return a.updatedAt > b.updatedAt ? 1 : -1;
+ if (a.sortPriority !== b.sortPriority) {
+ return a.sortPriority - b.sortPriority;
}
- return a.sortPriority - b.sortPriority;
+ // Keep equal-priority items in a stable order when they are edited.
+ if (a.createdAt !== b.createdAt) {
+ return a.createdAt > b.createdAt ? 1 : -1;
+ }
+ return a.id === b.id ? 0 : a.id > b.id ? 1 : -1;
});
for (const item of childItems) {
diff --git a/apps/yaak-client/components/SwitchWorkspaceDialog.tsx b/apps/yaak-client/components/SwitchWorkspaceDialog.tsx
index 2852b8e15..45e9f4946 100644
--- a/apps/yaak-client/components/SwitchWorkspaceDialog.tsx
+++ b/apps/yaak-client/components/SwitchWorkspaceDialog.tsx
@@ -1,11 +1,11 @@
import type { Workspace } from "@yaakapp-internal/models";
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
-import { HStack, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
+import { Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
import { useAtomValue } from "jotai";
import { useState } from "react";
import { switchWorkspace } from "../commands/switchWorkspace";
-import { Button } from "./core/Button";
import { Checkbox } from "./core/Checkbox";
+import { DialogFooter } from "./core/Dialog";
interface Props {
hide: () => void;
@@ -16,45 +16,33 @@ export function SwitchWorkspaceDialog({ hide, workspace }: Props) {
const settings = useAtomValue(settingsAtom);
const [remember, setRemember] = useState(false);
+ const open = async (inNewWindow: boolean) => {
+ hide();
+ switchWorkspace.mutate({ workspaceId: workspace.id, inNewWindow });
+ if (remember) {
+ await patchModel(settings, { openWorkspaceNewWindow: inNewWindow });
+ }
+ };
+
return (
Where would you like to open {workspace.name}?
-
-
- }
- onClick={async () => {
- hide();
- switchWorkspace.mutate({ workspaceId: workspace.id, inNewWindow: true });
- if (remember) {
- await patchModel(settings, { openWorkspaceNewWindow: true });
- }
- }}
- >
- New Window
-
-
{settings && (
-
-
-
+
)}
+ ,
+ onClick: () => open(true),
+ },
+ { label: "This Window", color: "primary", autoFocus: true, onClick: () => open(false) },
+ ]}
+ />
);
}
diff --git a/apps/yaak-client/components/TemplateFunctionDialog.test.tsx b/apps/yaak-client/components/TemplateFunctionDialog.test.tsx
new file mode 100644
index 000000000..5cdbe277c
--- /dev/null
+++ b/apps/yaak-client/components/TemplateFunctionDialog.test.tsx
@@ -0,0 +1,152 @@
+// @vitest-environment happy-dom
+import { readFile } from "node:fs/promises";
+import { resolve } from "node:path";
+import { pathToFileURL } from "node:url";
+import type { Workspace } from "@yaakapp-internal/models";
+import type { TemplateFunction } from "@yaakapp-internal/plugins";
+import type { Tokens } from "@yaakapp-internal/templates";
+import { act, type ReactNode } from "react";
+import { createRoot, type Root } from "react-dom/client";
+import { afterEach, beforeAll, beforeEach, expect, test, vi } from "vite-plus/test";
+import { TemplateFunctionDialog } from "./TemplateFunctionDialog";
+
+interface FormProps {
+ data: Record;
+ onChange: (values: Record) => void;
+}
+
+const mocks = vi.hoisted(() => ({
+ parse: vi.fn<(text: string) => Tokens>(),
+ print: vi.fn<(tokens: Tokens) => Promise>(),
+ serialize: vi.fn<(tokens: Tokens) => { data: string }>(),
+ preview: vi.fn<({ template }: { template: string }) => { data: string }>(),
+ form: null as FormProps | null,
+ config: {
+ name: "timestamp.format",
+ args: [
+ { type: "text", name: "date" },
+ { type: "text", name: "format" },
+ ],
+ } as TemplateFunction,
+}));
+
+vi.mock("@yaakapp-internal/templates", () => ({ parseTemplate: mocks.parse }));
+vi.mock("@yaakapp-internal/ui", () => ({
+ HStack: ({ children }: { children: ReactNode }) => {children}
,
+ InlineCode: "code",
+ LoadingIcon: () => null,
+ useDebouncedValue: (value: string) => value,
+}));
+vi.mock("../hooks/useActiveWorkspace", () => ({ activeWorkspaceAtom: null }));
+vi.mock("../hooks/useRenderTemplate", () => ({ useRenderTemplate: mocks.preview }));
+vi.mock("../hooks/useTemplateFunctionConfig", () => ({
+ useTemplateFunctionConfig: () => ({ data: mocks.config }),
+}));
+vi.mock("../hooks/useTemplateTokensToString", () => ({
+ templateTokensToString: mocks.print,
+ useTemplateTokensToString: mocks.serialize,
+}));
+vi.mock("../lib/dialog", () => ({ showDialog: vi.fn() }));
+vi.mock("../lib/encryption", () => ({ convertTemplateToInsecure: vi.fn() }));
+vi.mock("../lib/jotai", () => ({ jotaiStore: { get: vi.fn() } }));
+vi.mock("../lib/setupOrConfigureEncryption", () => ({ setupOrConfigureEncryption: vi.fn() }));
+vi.mock("./core/Dialog", () => ({ DialogFooter: () => }));
+vi.mock("./core/IconButton", () => ({ IconButton: () => }));
+vi.mock("./core/PlainInput", () => ({ PlainInput: () => null }));
+vi.mock("./DynamicForm", () => ({
+ DYNAMIC_FORM_NULL_ARG: "__NULL__",
+ DynamicForm: (props: FormProps) => {
+ mocks.form = props;
+ return ;
+ },
+}));
+
+beforeAll(async () => {
+ const base = pathToFileURL(
+ resolve(import.meta.dirname, "../../../crates/yaak-templates/pkg") + "/",
+ );
+ const bindings = await import(new URL("yaak_templates_bg.js", base).href);
+ const { instance } = await WebAssembly.instantiate(
+ await readFile(new URL("yaak_templates_bg.wasm", base)),
+ { "./yaak_templates_bg.js": bindings },
+ );
+ bindings.__wbg_set_wasm(instance.exports);
+ (instance.exports.__wbindgen_start as () => void)();
+ mocks.parse.mockImplementation(bindings.parse_template);
+});
+
+let root: Root;
+let host: HTMLDivElement;
+beforeEach(() => {
+ vi.clearAllMocks();
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
+ mocks.form = null;
+ // The transport returns an opaque string. Carry the AST as JSON so the assertions can
+ // inspect what Preview and Save receive, without duplicating the backend's printer.
+ mocks.serialize.mockImplementation((tokens) => ({ data: JSON.stringify(tokens) }));
+ mocks.preview.mockImplementation(({ template }) => ({ data: template }));
+ host = document.createElement("div");
+ document.body.append(host);
+ root = createRoot(host);
+});
+
+afterEach(async () => {
+ await act(async () => root.unmount());
+ host.remove();
+ vi.unstubAllGlobals();
+});
+
+function functionValue(tokens: Tokens) {
+ const first = tokens.tokens[0];
+ if (first?.type !== "tag" || first.val.type !== "fn") throw new Error("Expected function");
+ return first.val;
+}
+
+test.each([
+ ["timestamp.offset(expression='-1h')", "${[ timestamp.offset(expression='-1h') ]}"],
+ ["date_var", "${[ date_var ]}"],
+ ["dates.previous", "${[ dates.previous ]}"],
+ ["'${[ date_var ]}'", "${[ date_var ]}"],
+])("Preview and Save preserve %s until that input changes", async (expression, display) => {
+ const initialTokens = mocks.parse(`\${[ timestamp.format(date=${expression}, format='HH:mm') ]}`);
+ const originalDate = functionValue(initialTokens).args[0];
+ const saved = vi.fn<(value: string) => void>();
+ mocks.print.mockResolvedValue(display);
+
+ await act(async () =>
+ root.render(
+ {}}
+ />,
+ ),
+ );
+ expect(host.querySelector("input")?.value).toBe(display);
+
+ async function submit() {
+ const form = host.querySelector("form");
+ if (form == null) throw new Error("Dialog did not initialize");
+ await act(async () => {
+ form.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
+ });
+ const value = saved.mock.calls.at(-1)?.[0];
+ expect(value).toBe(mocks.preview.mock.calls.at(-1)?.[0].template);
+ return functionValue(JSON.parse(value ?? "null") as Tokens).args;
+ }
+
+ expect((await submit())[0]).toEqual(originalDate);
+ await act(async () => mocks.form?.onChange({ ...mocks.form.data, format: "yyyy" }));
+ expect(await submit()).toEqual([
+ originalDate,
+ { name: "format", value: { type: "str", text: "yyyy" } },
+ ]);
+
+ const edited = "${[ timestamp.offset(expression='-2h') ]}";
+ await act(async () => mocks.form?.onChange({ ...mocks.form.data, date: edited }));
+ expect((await submit())[0]).toEqual({ name: "date", value: { type: "str", text: edited } });
+ await act(async () => mocks.form?.onChange({ ...mocks.form.data, date: "" }));
+ expect((await submit())[0]).toEqual({ name: "date", value: { type: "str", text: "" } });
+});
diff --git a/apps/yaak-client/components/TemplateFunctionDialog.tsx b/apps/yaak-client/components/TemplateFunctionDialog.tsx
index 92e217720..fecbe099d 100644
--- a/apps/yaak-client/components/TemplateFunctionDialog.tsx
+++ b/apps/yaak-client/components/TemplateFunctionDialog.tsx
@@ -11,7 +11,7 @@ import type { FnArg, Tokens } from "@yaakapp-internal/templates";
import { parseTemplate } from "@yaakapp-internal/templates";
import { HStack, InlineCode, LoadingIcon, useDebouncedValue } from "@yaakapp-internal/ui";
import classNames from "classnames";
-import { useEffect, useMemo, useState } from "react";
+import { useEffect, useId, useMemo, useState } from "react";
import { activeWorkspaceAtom } from "../hooks/useActiveWorkspace";
import { useRenderTemplate } from "../hooks/useRenderTemplate";
import { useTemplateFunctionConfig } from "../hooks/useTemplateFunctionConfig";
@@ -24,8 +24,11 @@ import { showDialog } from "../lib/dialog";
import { convertTemplateToInsecure } from "../lib/encryption";
import { jotaiStore } from "../lib/jotai";
import { setupOrConfigureEncryption } from "../lib/setupOrConfigureEncryption";
-import { Button } from "./core/Button";
-import { collectArgumentValues } from "./core/Editor/twig/util";
+import {
+ collectEditableArgumentValues,
+ preserveUnchangedArgumentExpressions,
+} from "../lib/templateFunctionArguments";
+import { DialogFooter } from "./core/Dialog";
import { IconButton } from "./core/IconButton";
import { PlainInput } from "./core/PlainInput";
import { DYNAMIC_FORM_NULL_ARG, DynamicForm } from "./DynamicForm";
@@ -48,7 +51,11 @@ export function TemplateFunctionDialog({ initialTokens, templateFunction, ...pro
}
(async () => {
- const initial = collectArgumentValues(initialTokens, templateFunction);
+ const initial = await collectEditableArgumentValues(
+ initialTokens,
+ templateFunction,
+ templateTokensToString,
+ );
// HACK: Replace the secure() function's encrypted `value` arg with the decrypted version so
// we can display it in the editor input.
@@ -74,6 +81,7 @@ export function TemplateFunctionDialog({ initialTokens, templateFunction, ...pro
);
@@ -82,15 +90,17 @@ export function TemplateFunctionDialog({ initialTokens, templateFunction, ...pro
function InitializedTemplateFunctionDialog({
templateFunction: { name, previewType: ogPreviewType },
initialArgValues,
+ initialTokens,
hide,
onChange,
model,
-}: Omit & {
+}: Props & {
initialArgValues: Record;
}) {
const previewType = ogPreviewType == null ? "live" : ogPreviewType;
const [showSecretsInPreview, toggleShowSecretsInPreview] = useToggle(false);
const [argValues, setArgValues] = useState>(initialArgValues);
+ const formId = useId();
const tokens: Tokens = useMemo(() => {
const argTokens: FnArg[] = Object.keys(argValues).map((name) => ({
@@ -110,12 +120,17 @@ function InitializedTemplateFunctionDialog({
val: {
type: "fn",
name,
- args: argTokens,
+ args: preserveUnchangedArgumentExpressions(
+ argTokens,
+ initialTokens,
+ initialArgValues,
+ argValues,
+ ),
},
},
],
};
- }, [argValues, name]);
+ }, [argValues, initialArgValues, initialTokens, name]);
const tagText = useTemplateTokensToString(tokens);
const templateFunction = useTemplateFunctionConfig(name, argValues, model);
@@ -160,13 +175,14 @@ function InitializedTemplateFunctionDialog({
return (