diff --git a/package-lock.json b/package-lock.json index e4e624fb..32aea8ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "src-web" ], "devDependencies": { - "@tauri-apps/cli": "^2.0.3", + "@tauri-apps/cli": "^2.0.4", "@typescript-eslint/eslint-plugin": "^8.5.0", "@typescript-eslint/parser": "^8.5.0", "eslint": "^8", @@ -2689,9 +2689,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.3.tgz", - "integrity": "sha512-JwEyhc5BAVpn4E8kxzY/h7+bVOiXQdudR1r3ODMfyyumZBfgIWqpD/WuTcPq6Yjchju1BSS+80jAE/oYwI/RKg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.4.tgz", + "integrity": "sha512-Hl9eFXz+O366+6su9PfaSzu2EJdFe1p8K8ghkWmi40dz8VmSE7vsMTaOStD0I71ckSOkh2ICDX7FQTBgjlpjWw==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -2705,22 +2705,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.0.3", - "@tauri-apps/cli-darwin-x64": "2.0.3", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.0.3", - "@tauri-apps/cli-linux-arm64-gnu": "2.0.3", - "@tauri-apps/cli-linux-arm64-musl": "2.0.3", - "@tauri-apps/cli-linux-x64-gnu": "2.0.3", - "@tauri-apps/cli-linux-x64-musl": "2.0.3", - "@tauri-apps/cli-win32-arm64-msvc": "2.0.3", - "@tauri-apps/cli-win32-ia32-msvc": "2.0.3", - "@tauri-apps/cli-win32-x64-msvc": "2.0.3" + "@tauri-apps/cli-darwin-arm64": "2.0.4", + "@tauri-apps/cli-darwin-x64": "2.0.4", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.0.4", + "@tauri-apps/cli-linux-arm64-gnu": "2.0.4", + "@tauri-apps/cli-linux-arm64-musl": "2.0.4", + "@tauri-apps/cli-linux-x64-gnu": "2.0.4", + "@tauri-apps/cli-linux-x64-musl": "2.0.4", + "@tauri-apps/cli-win32-arm64-msvc": "2.0.4", + "@tauri-apps/cli-win32-ia32-msvc": "2.0.4", + "@tauri-apps/cli-win32-x64-msvc": "2.0.4" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.3.tgz", - "integrity": "sha512-jIsbxGWS+As1ZN7umo90nkql/ZAbrDK0GBT6UsgHSz5zSwwArICsZFFwE1pLZip5yoiV5mn3TGG2c1+v+0puzQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.4.tgz", + "integrity": "sha512-siH7rOHobb16rPbc11k64p1mxIpiRCkWmzs2qmL5IX21Gx9K5onI3Tk67Oqpf2uNupbYzItrOttaDT4NHFC7tw==", "cpu": [ "arm64" ], @@ -2735,9 +2735,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.3.tgz", - "integrity": "sha512-ROITHtLTA1muyrwgyuwyasmaLCGtT4as/Kd1kerXaSDtFcYrnxiM984ZD0+FDUEDl5BgXtYa/sKKkKQFjgmM0A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.4.tgz", + "integrity": "sha512-zIccfbCoZMfmUpnk6PFCV0keFyfVj1A9XV3Oiiitj/dkTZ9CQvzjhX3XC0XcK4rsTWegfr2PjSrK06aiPAROAw==", "cpu": [ "x64" ], @@ -2752,9 +2752,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.3.tgz", - "integrity": "sha512-bQ3EZwCFfrLg/ZQ2I8sLuifSxESz4TP56SleTkKsPtTIZgNnKpM88PRDz4neiRroHVOq8NK0X276qi9LjGcXPw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.4.tgz", + "integrity": "sha512-fgQqJzefOGWCBNg4yrVA82Rg4s1XQr5K0dc2rCxBhJfa696e8dQ1LDrnWq/AiO5r+uHfVaoQTIUvxxpFicYRSA==", "cpu": [ "arm" ], @@ -2769,9 +2769,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.3.tgz", - "integrity": "sha512-aLfAA8P9OTErVUk3sATxtXqpAtlfDPMPp4fGjDysEELG/MyekGhmh2k/kG/i32OdPeCfO+Nr37wJksARJKubGw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.4.tgz", + "integrity": "sha512-u8wbt5tPA9pI6j+d7jGrfOz9UVCiTp+IYzKNiIqlrDsAjqAUFaNXYHKqOUboeFWEmI4zoCWj6LgpS2OJTQ5FKg==", "cpu": [ "arm64" ], @@ -2786,9 +2786,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.3.tgz", - "integrity": "sha512-I4MVD7nf6lLLRmNQPpe5beEIFM6q7Zkmh77ROA5BNu/+vHNL5kiTMD+bmd10ZL2r753A6pO7AvqkIxcBuIl0tg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.4.tgz", + "integrity": "sha512-hntF1V8e3V1hlrESm93PsghDhf3lA5pbvFrRfYxU1c+fVD/jRXGVw8BH3O1lW8MWwhEg1YdhKk01oAgsuHLuig==", "cpu": [ "arm64" ], @@ -2803,9 +2803,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.3.tgz", - "integrity": "sha512-C6Jkx2zZGKkoi+sg5FK9GoH/0EvAaOgrZfF5azV5EALGba46g7VpWcZgp9zFUd7K2IzTi+0OOY8TQ2OVfKZgew==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.4.tgz", + "integrity": "sha512-Iq1GGJb+oT1T0ZV8izrgf0cBtlzPCJaWcNueRbf1ZXquMf+FSTyQv+/Lo8rq5T6buOIJOH7cAOTuEWWqiCZteg==", "cpu": [ "x64" ], @@ -2820,9 +2820,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.3.tgz", - "integrity": "sha512-qi4ghmTfSAl+EEUDwmwI9AJUiOLNSmU1RgiGgcPRE+7A/W+Am9UnxYySAiRbB/gJgTl9sj/pqH5Y9duP1/sqHg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.4.tgz", + "integrity": "sha512-9NTk6Pf0bSwXqCBdAA+PDYts9HeHebZzIo8mbRzRyUbER6QngG5HZb9Ka36Z1QWtJjdRy6uxSb4zb/9NuTeHfA==", "cpu": [ "x64" ], @@ -2837,9 +2837,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.3.tgz", - "integrity": "sha512-UXxHkYmFesC97qVmZre4vY7oDxRDtC2OeKNv0bH+iSnuUp/ROxzJYGyaelnv9Ybvgl4YVqDCnxgB28qMM938TA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.4.tgz", + "integrity": "sha512-OF2e9oxiBFR8A8wVMOhUx9QGN/I1ZkquWC7gVQBnA56nx9PabJlDT08QBy5UD8USqZFVznnfNr2ehlheQahb3g==", "cpu": [ "arm64" ], @@ -2854,9 +2854,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.3.tgz", - "integrity": "sha512-D+xoaa35RGlkXDpnL5uDTpj29untuC5Wp6bN9snfgFDagD0wnFfC8+2ZQGu16bD0IteWqDI0OSoIXhNvy+F+wg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.4.tgz", + "integrity": "sha512-T+hCKB3rFP6q0saHHtR02hm6wr1ZPJ0Mkii3oRTxjPG6BBXoVzHNCYzvdgEGJPTA2sFuAQtJH764NRtNlDMifw==", "cpu": [ "ia32" ], @@ -2871,9 +2871,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.3.tgz", - "integrity": "sha512-eWV9XWb4dSYHXl13OtYWLjX1JHphUEkHkkGwJrhr8qFBm7RbxXxQvrsUEprSi51ug/dwJenjJgM4zR8By4htfw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.4.tgz", + "integrity": "sha512-GVaiI3KWRFLomjJmApHqihhYlkJ+7FqhumhVfBO6Z2tWzZjQyVQgTdNp0kYEuW2WoAYEj0dKY6qd4YM33xYcUA==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index 892b125a..d947eb27 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "tauri-before-dev": "npm run --workspaces --if-present dev" }, "devDependencies": { - "@tauri-apps/cli": "^2.0.3", + "@tauri-apps/cli": "^2.0.4", "@typescript-eslint/eslint-plugin": "^8.5.0", "@typescript-eslint/parser": "^8.5.0", "eslint": "^8", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 82966d6e..0e9caf64 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -209,7 +209,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ - "brotli", + "brotli 6.0.0", "flate2", "futures-core", "memchr", @@ -638,6 +638,17 @@ dependencies = [ "brotli-decompressor", ] +[[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", +] + [[package]] name = "brotli-decompressor" version = "4.0.1" @@ -2938,7 +2949,19 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" dependencies = [ - "jsonptr", + "jsonptr 0.4.7", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "json-patch" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" +dependencies = [ + "jsonptr 0.6.3", "serde", "serde_json", "thiserror", @@ -2955,6 +2978,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "jsonptr" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "keyboard-types" version = "0.7.0" @@ -4767,9 +4800,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -4779,9 +4812,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -4790,9 +4823,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rend" @@ -6095,9 +6128,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.0.4" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44438500b50708bfc1e6083844e135d1b516325aae58710dcd8fb67e050ae87c" +checksum = "d3889b392db6d32a105d3757230ea0220090b8f94c90d3e60b6c5eb91178ab1b" dependencies = [ "anyhow", "bytes", @@ -6146,16 +6179,16 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "935f9b3c49b22b3e2e485a57f46d61cd1ae07b1cbb2ba87387a387caf2d8c4e7" +checksum = "9f96827ccfb1aa40d55d0ded79562d18ba18566657a553f992a982d755148376" dependencies = [ "anyhow", "cargo_toml", "dirs", "glob", "heck 0.5.0", - "json-patch", + "json-patch 3.0.1", "schemars", "semver", "serde", @@ -6168,14 +6201,14 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d7443dd4f0b597704b6a14b964ee2ed16e99928d8e6292ae9825f09fbcd30e" +checksum = "8947f16f47becd9e9cd39b74ee337fd1981574d78819be18e4384d85e5a0b82f" dependencies = [ "base64 0.22.1", - "brotli", + "brotli 7.0.0", "ico", - "json-patch", + "json-patch 2.0.0", "plist", "png", "proc-macro2", @@ -6195,9 +6228,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d2c0963ccfc3f5194415f2cce7acc975942a8797fbabfb0aa1ed6f59326ae7f" +checksum = "8bd1c8d4a66799d3438747c3a79705cd665a95d6f24cb5f315413ff7a981fe2a" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -6242,9 +6275,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.0.1" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddb2fe88b602461c118722c574e2775ab26a4e68886680583874b2f6520608b7" +checksum = "4307310e1d2c09ab110235834722e7c2b85099b683e1eb7342ab351b0be5ada3" dependencies = [ "log", "raw-window-handle", @@ -6260,9 +6293,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.0.1" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab300488ebec3487ca5f56289692e7e45feb07eea8d5e1dba497f7dc9dd9c407" +checksum = "96ba7d46e86db8c830d143ef90ab5a453328365b0cc834c24edea4267b16aba0" dependencies = [ "anyhow", "dunce", @@ -6321,9 +6354,9 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "371fb9aca2823990a2d0db7970573be5fdf07881fcaa2b835b29631feb84aec1" +checksum = "0ad7880c5586b6b2104be451e3d7fc0f3800c84bda69e9ba81c828f87cb34267" dependencies = [ "encoding_rs", "log", @@ -6387,9 +6420,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8f437293d6f5e5dce829250f4dbdce4e0b52905e297a6689cc2963eb53ac728" +checksum = "a1ef7363e7229ac8d04e8a5d405670dbd43dde8fc4bc3bc56105c35452d03784" dependencies = [ "dpi", "gtk", @@ -6406,9 +6439,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1431602bcc71f2f840ad623915c9842ecc32999b867c4a787d975a17a9625cc6" +checksum = "62fa2068e8498ad007b54d5773d03d57c3ff6dd96f8c8ce58beff44d0d5e0d30" dependencies = [ "gtk", "http 1.1.0", @@ -6432,18 +6465,18 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38b0230d6880cf6dd07b6d7dd7789a0869f98ac12146e0d18d1c1049215a045" +checksum = "1fc65d6f5c54e56b66258948a6d9e47a82ea41f4b5a7612bfbdd1634c2913ed0" dependencies = [ - "brotli", + "brotli 7.0.0", "cargo_metadata", "ctor", "dunce", "glob", "html5ever", "infer", - "json-patch", + "json-patch 2.0.0", "kuchikiki", "log", "memchr", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2d3ecae4..9d52503c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ crate-type = ["staticlib", "cdylib", "lib"] strip = true # Automatically strip symbols from the binary. [build-dependencies] -tauri-build = { version = "2.0.1", features = [] } +tauri-build = { version = "2.0.2", features = [] } [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2.7" @@ -48,8 +48,8 @@ serde_yaml = "0.9.34" tauri = { workspace = true } tauri-plugin-shell = { workspace = true } tauri-plugin-clipboard-manager = "2.0.1" -tauri-plugin-dialog = "2.0.1" -tauri-plugin-fs = "2.0.1" +tauri-plugin-dialog = "2.0.3" +tauri-plugin-fs = "2.0.3" tauri-plugin-log = { version = "2.0.1", features = ["colored"] } tauri-plugin-os = "2.0.1" tauri-plugin-updater = "2.0.2" @@ -65,5 +65,5 @@ eventsource-client = { git = "https://github.com/yaakapp/rust-eventsource-client [workspace.dependencies] yaak_models = { path = "yaak_models" } yaak_plugin_runtime = { path = "yaak_plugin_runtime" } -tauri-plugin-shell = "2.0.1" -tauri = { version = "2.0.4", features = ["devtools", "protocol-asset"] } +tauri-plugin-shell = "2.0.2" +tauri = { version = "2.0.6", features = ["devtools", "protocol-asset"] } diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 07a78793..24c6e547 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -37,7 +37,7 @@ ], "definitions": { "Capability": { - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, \"platforms\": [\"macOS\",\"windows\"] } ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", "type": "object", "required": [ "identifier", diff --git a/src-tauri/gen/schemas/macOS-schema.json b/src-tauri/gen/schemas/macOS-schema.json index 07a78793..24c6e547 100644 --- a/src-tauri/gen/schemas/macOS-schema.json +++ b/src-tauri/gen/schemas/macOS-schema.json @@ -37,7 +37,7 @@ ], "definitions": { "Capability": { - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, \"platforms\": [\"macOS\",\"windows\"] } ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", "type": "object", "required": [ "identifier", diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d8e326cd..26474a15 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -75,6 +75,7 @@ use yaak_plugin_runtime::events::{ use yaak_plugin_runtime::plugin_handle::PluginHandle; use yaak_sse::sse::ServerSentEvent; use yaak_templates::{Parser, Tokens}; +use yaak_templates::format::format_json; mod analytics; mod export_resources; @@ -737,6 +738,11 @@ async fn cmd_send_ephemeral_request( send_http_request(&window, &request, &response, environment, cookie_jar, &mut cancel_rx).await } +#[tauri::command] +async fn cmd_format_json(text: &str) -> Result { + Ok(format_json(text, " ")) +} + #[tauri::command] async fn cmd_filter_response( window: WebviewWindow, @@ -1711,12 +1717,10 @@ pub fn run() { cmd_create_folder, cmd_create_grpc_request, cmd_create_http_request, - cmd_install_plugin, cmd_create_workspace, cmd_curl_to_request, cmd_delete_all_grpc_connections, cmd_delete_all_http_responses, - cmd_delete_send_history, cmd_delete_cookie_jar, cmd_delete_environment, cmd_delete_folder, @@ -1724,26 +1728,28 @@ pub fn run() { cmd_delete_grpc_request, cmd_delete_http_request, cmd_delete_http_response, - cmd_uninstall_plugin, + cmd_delete_send_history, cmd_delete_workspace, cmd_dismiss_notification, cmd_duplicate_grpc_request, cmd_duplicate_http_request, cmd_export_data, cmd_filter_response, + cmd_format_json, cmd_get_cookie_jar, cmd_get_environment, cmd_get_folder, cmd_get_grpc_request, cmd_get_http_request, - cmd_get_sse_events, cmd_get_key_value, cmd_get_settings, + cmd_get_sse_events, cmd_get_workspace, cmd_grpc_go, cmd_grpc_reflect, cmd_http_request_actions, cmd_import_data, + cmd_install_plugin, cmd_list_cookie_jars, cmd_list_environments, cmd_list_folders, @@ -1769,6 +1775,7 @@ pub fn run() { cmd_template_functions, cmd_template_tokens_to_string, cmd_track_event, + cmd_uninstall_plugin, cmd_update_cookie_jar, cmd_update_environment, cmd_update_folder, diff --git a/src-tauri/yaak_templates/src/format.rs b/src-tauri/yaak_templates/src/format.rs new file mode 100644 index 00000000..7e027446 --- /dev/null +++ b/src-tauri/yaak_templates/src/format.rs @@ -0,0 +1,230 @@ +enum FormatState { + TemplateTag, + String, + None, +} + +/// Formats JSON that might contain template tags (skipped entirely) +pub fn format_json(text: &str, tab: &str) -> String { + let mut chars = text.chars().peekable(); + + let mut new_json = "".to_string(); + let mut depth = 0; + let mut state = FormatState::None; + + loop { + let rest_of_chars = chars.clone(); + let current_char = match chars.next() { + None => break, + Some(c) => c, + }; + + // Handle JSON string states + if let FormatState::String = state { + match current_char { + '"' => { + state = FormatState::None; + new_json.push(current_char); + continue; + } + '\\' => { + new_json.push(current_char); + if let Some(c) = chars.next() { + new_json.push(c); + } + continue; + } + _ => { + new_json.push(current_char); + continue; + } + } + } + // Close Template tag states + if let FormatState::TemplateTag = state { + if rest_of_chars.take(2).collect::() == "]}" { + state = FormatState::None; + new_json.push_str("]}"); + chars.next(); // Skip the second closing bracket + continue; + } else { + new_json.push(current_char); + continue; + } + } + + if rest_of_chars.take(3).collect::() == "${[" { + state = FormatState::TemplateTag; + new_json.push_str("${["); + chars.next(); // Skip { + chars.next(); // Skip [ + continue; + } + + match current_char { + ',' => { + new_json.push(current_char); + new_json.push('\n'); + new_json.push_str(tab.to_string().repeat(depth).as_str()); + } + '{' => match chars.peek() { + Some('}') => { + new_json.push(current_char); + new_json.push('}'); + } + _ => { + depth += 1; + new_json.push(current_char); + new_json.push('\n'); + new_json.push_str(tab.to_string().repeat(depth).as_str()); + } + }, + '[' => match chars.peek() { + Some(']') => { + new_json.push(current_char); + new_json.push(']'); + } + _ => { + depth += 1; + new_json.push(current_char); + new_json.push('\n'); + new_json.push_str(tab.to_string().repeat(depth).as_str()); + } + }, + '}' => { + depth -= 1; + new_json.push('\n'); + new_json.push_str(tab.to_string().repeat(depth).as_str()); + new_json.push(current_char); + // Pad with space if the next char is not a comma + if let Some(',') = chars.peek() { + new_json.push(' '); + } + } + ']' => { + depth -= 1; + new_json.push('\n'); + new_json.push_str(tab.to_string().repeat(depth).as_str()); + new_json.push(current_char); + // Pad with space if the next char is not a comma + if let Some(',') = chars.peek() { + new_json.push(' '); + } + } + ':' => { + new_json.push(current_char); + new_json.push(' '); // Pad with space + } + '"' => { + state = FormatState::String; + new_json.push(current_char); + } + _ => { + if current_char == ' ' + || current_char == '\n' + || current_char == '\t' + || current_char == '\r' + { + // Don't add these + } else { + new_json.push(current_char); + } + } + } + } + + // Replace only lines containing whitespace with nothing + new_json + .lines() + .filter(|line| !line.trim().is_empty()) // Filter out whitespace-only lines + .collect::>() // Collect the non-empty lines into a vector + .join("\n") // Join the lines back into a single string +} + +#[cfg(test)] +mod test { + use crate::format::format_json; + + #[test] + fn test_simple_object() { + assert_eq!( + format_json(r#"{"foo":"bar","baz":"qux"}"#, " "), + r#" +{ + "foo": "bar", + "baz": "qux" +} +"# + .trim() + ); + } + + #[test] + fn test_simple_array() { + assert_eq!( + format_json(r#"["foo","bar","baz","qux"]"#, " "), + r#" +[ + "foo", + "bar", + "baz", + "qux" +] +"# + .trim() + ); + } + + #[test] + fn test_extra_whitespace() { + assert_eq!( + format_json( + r#"["foo", "bar", "baz","qux" + + ]"#, + " " + ), + r#" +[ + "foo", + "bar", + "baz", + "qux" +] +"# + .trim() + ); + } + + #[test] + fn test_invalid_json() { + assert_eq!( + format_json(r#"["foo", {"bar", }"baz",["qux" ]]"#, " "), + r#" +[ + "foo", + { + "bar", + }"baz", + [ + "qux" + ] +] +"# + .trim() + ); + } + + #[test] + fn test_skip_template_tags() { + assert_eq!( + format_json(r#"{"foo":${[ fn("hello", "world") ]} }"#, " "), + r#" +{ + "foo": ${[ fn("hello", "world") ]} +} +"# + .trim() + ); + } +} diff --git a/src-tauri/yaak_templates/src/lib.rs b/src-tauri/yaak_templates/src/lib.rs index 43b4e37f..55c9da3d 100644 --- a/src-tauri/yaak_templates/src/lib.rs +++ b/src-tauri/yaak_templates/src/lib.rs @@ -1,5 +1,6 @@ pub mod parser; pub mod renderer; +pub mod format; pub use parser::*; pub use renderer::*; \ No newline at end of file diff --git a/src-web/components/core/Editor/Editor.tsx b/src-web/components/core/Editor/Editor.tsx index d7acd28c..454ac686 100644 --- a/src-web/components/core/Editor/Editor.tsx +++ b/src-web/components/core/Editor/Editor.tsx @@ -61,7 +61,7 @@ export interface EditorProps { onKeyDown?: (e: KeyboardEvent) => void; singleLine?: boolean; wrapLines?: boolean; - format?: (v: string) => string; + format?: (v: string) => Promise; autocomplete?: GenericCompletionConfig; autocompleteVariables?: boolean; extraExtensions?: Extension[]; @@ -387,10 +387,10 @@ export const Editor = forwardRef(function E icon="magic_wand" variant="border" className={classNames(actionClassName)} - onClick={() => { + onClick={async () => { if (cm.current === null) return; const { doc } = cm.current.view.state; - const formatted = format(doc.toString()); + const formatted = await format(doc.toString()); // Update editor and blur because the cursor will reset anyway cm.current.view.dispatch({ changes: { from: 0, to: doc.length, insert: formatted }, diff --git a/src-web/components/responseViewers/EventStreamViewer.tsx b/src-web/components/responseViewers/EventStreamViewer.tsx index 8e7d8e0d..14c4ebb2 100644 --- a/src-web/components/responseViewers/EventStreamViewer.tsx +++ b/src-web/components/responseViewers/EventStreamViewer.tsx @@ -4,10 +4,11 @@ import type { ServerSentEvent } from '@yaakapp-internal/sse'; import classNames from 'classnames'; import { motion } from 'framer-motion'; import React, { Fragment, useMemo, useRef, useState } from 'react'; +import { useFormatText } from '../../hooks/useFormatText'; import { useResponseBodyEventSource } from '../../hooks/useResponseBodyEventSource'; import { isJSON } from '../../lib/contentType'; -import { tryFormatJson } from '../../lib/formatters'; import { Button } from '../core/Button'; +import type { EditorProps } from '../core/Editor'; import { Editor } from '../core/Editor'; import { Icon } from '../core/Icon'; import { InlineCode } from '../core/InlineCode'; @@ -95,11 +96,7 @@ function ActualEventStreamViewer({ response }: Props) { ) : ( - + )} @@ -110,6 +107,12 @@ function ActualEventStreamViewer({ response }: Props) { ); } +function FormattedEditor({ text, language }: { text: string; language: EditorProps['language'] }) { + const formatted = useFormatText({ text, language, pretty: true }); + if (formatted.data == null) return null; + return ; +} + function EventStreamEventsVirtual({ events, activeEventIndex, diff --git a/src-web/components/responseViewers/HTMLOrTextViewer.tsx b/src-web/components/responseViewers/HTMLOrTextViewer.tsx index fe32ba47..a08658c1 100644 --- a/src-web/components/responseViewers/HTMLOrTextViewer.tsx +++ b/src-web/components/responseViewers/HTMLOrTextViewer.tsx @@ -31,7 +31,7 @@ export function HTMLOrTextViewer({ response, pretty, textViewerClassName }: Prop } if (language === 'html' && pretty) { - return ; + return ; } else { return ( LARGE_RESPONSE_BYTES) { return ( @@ -140,12 +142,9 @@ export function TextViewer({ ); } - const formattedBody = - pretty && language === 'json' - ? tryFormatJson(text) - : pretty && (language === 'xml' || language === 'html') - ? tryFormatXml(text) - : text; + if (formattedBody.isFetching) { + return null; + } let body; if (isSearching && filterText?.length > 0) { @@ -155,7 +154,7 @@ export function TextViewer({ body = filteredResponse.data != null ? filteredResponse.data : ''; } } else { - body = formattedBody; + body = formattedBody.data; } return ( diff --git a/src-web/hooks/useFormatText.ts b/src-web/hooks/useFormatText.ts new file mode 100644 index 00000000..5d7ce40e --- /dev/null +++ b/src-web/hooks/useFormatText.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; +import type { EditorProps } from '../components/core/Editor'; +import { tryFormatJson, tryFormatXml } from '../lib/formatters'; + +export function useFormatText({ + text, + language, + pretty, +}: { + text: string; + language: EditorProps['language']; + pretty: boolean; +}) { + return useQuery({ + queryKey: [text], + queryFn: async () => { + if (text === '' || !pretty) { + return text; + } else if (language === 'json') { + return tryFormatJson(text); + } else if (language === 'xml' || language === 'html') { + return tryFormatXml(text); + } else { + return text; + } + }, + }); +} diff --git a/src-web/hooks/useSyncWorkspaceChildModels.ts b/src-web/hooks/useSyncWorkspaceChildModels.ts index ef87cf07..625615de 100644 --- a/src-web/hooks/useSyncWorkspaceChildModels.ts +++ b/src-web/hooks/useSyncWorkspaceChildModels.ts @@ -23,6 +23,7 @@ export function useSyncWorkspaceChildModels() { const workspaceId = workspace?.id ?? 'n/a'; useEffect(() => { (async function () { + console.log('Syncing model stores', { workspaceId }); // Set the things we need first, first setHttpRequests(await invokeCmd('cmd_list_http_requests', { workspaceId })); setGrpcRequests(await invokeCmd('cmd_list_grpc_requests', { workspaceId })); diff --git a/src-web/lib/formatters.ts b/src-web/lib/formatters.ts index 3b0537bd..26ac00e3 100644 --- a/src-web/lib/formatters.ts +++ b/src-web/lib/formatters.ts @@ -1,20 +1,14 @@ import xmlFormat from 'xml-formatter'; +import { invokeCmd } from './tauri'; const INDENT = ' '; -export function tryFormatJson(text: string, pretty = true): string { +export async function tryFormatJson(text: string): Promise { if (text === '') return text; - - try { - if (pretty) return JSON.stringify(JSON.parse(text), null, INDENT); - else return JSON.stringify(JSON.parse(text)); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - } catch (err) { - return text; - } + return invokeCmd('cmd_format_json', { text }); } -export function tryFormatXml(text: string): string { +export async function tryFormatXml(text: string): Promise { if (text === '') return text; try { diff --git a/src-web/lib/tauri.ts b/src-web/lib/tauri.ts index abaeac33..466d12c8 100644 --- a/src-web/lib/tauri.ts +++ b/src-web/lib/tauri.ts @@ -28,6 +28,7 @@ type TauriCmd = | 'cmd_duplicate_http_request' | 'cmd_export_data' | 'cmd_filter_response' + | 'cmd_format_json' | 'cmd_get_cookie_jar' | 'cmd_get_environment' | 'cmd_get_folder'