Преглед изворни кода

chore(desktop): integrate tauri-specta (#11740)

Brendan Allan пре 3 недеља
родитељ
комит
04aef44fc3

+ 207 - 40
packages/desktop/src-tauri/Cargo.lock

@@ -2,6 +2,12 @@
 # It is not intended for manual editing.
 version = 4
 
+[[package]]
+name = "Inflector"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
+
 [[package]]
 name = "adler2"
 version = "2.0.1"
@@ -1994,9 +2000,9 @@ dependencies = [
 
 [[package]]
 name = "ico"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98"
+checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371"
 dependencies = [
  "byteorder",
  "png 0.17.16",
@@ -3065,12 +3071,14 @@ dependencies = [
  "listeners",
  "objc2 0.6.3",
  "objc2-web-kit",
- "reqwest",
+ "reqwest 0.12.24",
  "semver",
  "serde",
  "serde_json",
+ "specta",
+ "specta-typescript",
  "tauri",
- "tauri-build",
+ "tauri-build 2.5.2",
  "tauri-plugin-clipboard-manager",
  "tauri-plugin-decorum",
  "tauri-plugin-deep-link",
@@ -3085,6 +3093,7 @@ dependencies = [
  "tauri-plugin-store",
  "tauri-plugin-updater",
  "tauri-plugin-window-state",
+ "tauri-specta",
  "tokio",
  "uuid",
  "webkit2gtk",
@@ -3221,6 +3230,12 @@ dependencies = [
  "windows-link 0.2.1",
 ]
 
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
 [[package]]
 name = "pathdiff"
 version = "0.2.3"
@@ -3947,6 +3962,40 @@ dependencies = [
  "webpki-roots",
 ]
 
+[[package]]
+name = "reqwest"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62"
+dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "js-sys",
+ "log",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "serde_json",
+ "sync_wrapper",
+ "tokio",
+ "tokio-util",
+ "tower",
+ "tower-http",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-streams",
+ "web-sys",
+]
+
 [[package]]
 name = "rfd"
 version = "0.15.4"
@@ -4497,6 +4546,44 @@ dependencies = [
  "system-deps",
 ]
 
+[[package]]
+name = "specta"
+version = "2.0.0-rc.22"
+source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
+dependencies = [
+ "paste",
+ "rustc_version",
+ "specta-macros",
+]
+
+[[package]]
+name = "specta-macros"
+version = "2.0.0-rc.18"
+source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
+dependencies = [
+ "Inflector",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.110",
+]
+
+[[package]]
+name = "specta-serde"
+version = "0.0.9"
+source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
+dependencies = [
+ "specta",
+]
+
+[[package]]
+name = "specta-typescript"
+version = "0.0.9"
+source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
+dependencies = [
+ "specta",
+ "specta-serde",
+]
+
 [[package]]
 name = "stable_deref_trait"
 version = "1.2.1"
@@ -4712,9 +4799,8 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
 
 [[package]]
 name = "tauri"
-version = "2.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e492485dd390b35f7497401f67694f46161a2a00ffd800938d5dd3c898fb9d8"
+version = "2.9.5"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
 dependencies = [
  "anyhow",
  "bytes",
@@ -4740,17 +4826,18 @@ dependencies = [
  "percent-encoding",
  "plist",
  "raw-window-handle",
- "reqwest",
+ "reqwest 0.13.1",
  "serde",
  "serde_json",
  "serde_repr",
  "serialize-to-javascript",
+ "specta",
  "swift-rs",
- "tauri-build",
+ "tauri-build 2.5.3",
  "tauri-macros",
  "tauri-runtime",
  "tauri-runtime-wry",
- "tauri-utils",
+ "tauri-utils 2.8.1",
  "thiserror 2.0.17",
  "tokio",
  "tray-icon",
@@ -4777,7 +4864,28 @@ dependencies = [
  "semver",
  "serde",
  "serde_json",
- "tauri-utils",
+ "tauri-utils 2.8.0",
+ "tauri-winres",
+ "toml 0.9.8",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-build"
+version = "2.5.3"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
+dependencies = [
+ "anyhow",
+ "cargo_toml",
+ "dirs",
+ "glob",
+ "heck 0.5.0",
+ "json-patch",
+ "schemars 0.8.22",
+ "semver",
+ "serde",
+ "serde_json",
+ "tauri-utils 2.8.1",
  "tauri-winres",
  "toml 0.9.8",
  "walkdir",
@@ -4785,9 +4893,8 @@ dependencies = [
 
 [[package]]
 name = "tauri-codegen"
-version = "2.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7ef707148f0755110ca54377560ab891d722de4d53297595380a748026f139f"
+version = "2.5.2"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
 dependencies = [
  "base64 0.22.1",
  "brotli",
@@ -4802,7 +4909,7 @@ dependencies = [
  "serde_json",
  "sha2",
  "syn 2.0.110",
- "tauri-utils",
+ "tauri-utils 2.8.1",
  "thiserror 2.0.17",
  "time",
  "url",
@@ -4812,16 +4919,15 @@ dependencies = [
 
 [[package]]
 name = "tauri-macros"
-version = "2.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71664fd715ee6e382c05345ad258d6d1d50f90cf1b58c0aa726638b33c2a075d"
+version = "2.5.2"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
  "syn 2.0.110",
  "tauri-codegen",
- "tauri-utils",
+ "tauri-utils 2.8.1",
 ]
 
 [[package]]
@@ -4836,7 +4942,7 @@ dependencies = [
  "schemars 0.8.22",
  "serde",
  "serde_json",
- "tauri-utils",
+ "tauri-utils 2.8.0",
  "toml 0.9.8",
  "walkdir",
 ]
@@ -4886,7 +4992,7 @@ dependencies = [
  "serde_json",
  "tauri",
  "tauri-plugin",
- "tauri-utils",
+ "tauri-utils 2.8.0",
  "thiserror 2.0.17",
  "tracing",
  "url",
@@ -4928,7 +5034,7 @@ dependencies = [
  "serde_repr",
  "tauri",
  "tauri-plugin",
- "tauri-utils",
+ "tauri-utils 2.8.0",
  "thiserror 2.0.17",
  "toml 0.9.8",
  "url",
@@ -4945,7 +5051,7 @@ dependencies = [
  "data-url",
  "http",
  "regex",
- "reqwest",
+ "reqwest 0.12.24",
  "schemars 0.8.22",
  "serde",
  "serde_json",
@@ -5096,7 +5202,7 @@ dependencies = [
  "minisign-verify",
  "osakit",
  "percent-encoding",
- "reqwest",
+ "reqwest 0.12.24",
  "semver",
  "serde",
  "serde_json",
@@ -5129,9 +5235,8 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime"
-version = "2.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9368f09358496f2229313fccb37682ad116b7f46fa76981efe116994a0628926"
+version = "2.9.2"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
 dependencies = [
  "cookie",
  "dpi",
@@ -5144,7 +5249,7 @@ dependencies = [
  "raw-window-handle",
  "serde",
  "serde_json",
- "tauri-utils",
+ "tauri-utils 2.8.1",
  "thiserror 2.0.17",
  "url",
  "webkit2gtk",
@@ -5154,9 +5259,8 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime-wry"
-version = "2.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "929f5df216f5c02a9e894554401bcdab6eec3e39ec6a4a7731c7067fc8688a93"
+version = "2.9.3"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
 dependencies = [
  "gtk",
  "http",
@@ -5171,7 +5275,7 @@ dependencies = [
  "softbuffer",
  "tao",
  "tauri-runtime",
- "tauri-utils",
+ "tauri-utils 2.8.1",
  "url",
  "webkit2gtk",
  "webview2-com",
@@ -5179,11 +5283,74 @@ dependencies = [
  "wry",
 ]
 
+[[package]]
+name = "tauri-specta"
+version = "2.0.0-rc.21"
+source = "git+https://github.com/specta-rs/tauri-specta?rev=6720b2848eff9a3e40af54c48d65f6d56b640c0b#6720b2848eff9a3e40af54c48d65f6d56b640c0b"
+dependencies = [
+ "heck 0.5.0",
+ "serde",
+ "serde_json",
+ "specta",
+ "specta-typescript",
+ "tauri",
+ "tauri-specta-macros",
+ "thiserror 2.0.17",
+]
+
+[[package]]
+name = "tauri-specta-macros"
+version = "2.0.0-rc.16"
+source = "git+https://github.com/specta-rs/tauri-specta?rev=6720b2848eff9a3e40af54c48d65f6d56b640c0b#6720b2848eff9a3e40af54c48d65f6d56b640c0b"
+dependencies = [
+ "darling",
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.110",
+]
+
 [[package]]
 name = "tauri-utils"
 version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6b8bbe426abdbf52d050e52ed693130dbd68375b9ad82a3fb17efb4c8d85673"
+dependencies = [
+ "anyhow",
+ "cargo_metadata",
+ "ctor",
+ "dunce",
+ "glob",
+ "html5ever",
+ "http",
+ "infer",
+ "json-patch",
+ "kuchikiki",
+ "log",
+ "memchr",
+ "phf 0.11.3",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "schemars 0.8.22",
+ "semver",
+ "serde",
+ "serde-untagged",
+ "serde_json",
+ "serde_with",
+ "swift-rs",
+ "thiserror 2.0.17",
+ "toml 0.9.8",
+ "url",
+ "urlpattern",
+ "uuid",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-utils"
+version = "2.8.1"
+source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
 dependencies = [
  "anyhow",
  "brotli",
@@ -5547,9 +5714,9 @@ dependencies = [
 
 [[package]]
 name = "tower-http"
-version = "0.6.6"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
+checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
 dependencies = [
  "bitflags 2.10.0",
  "bytes",
@@ -6034,9 +6201,9 @@ dependencies = [
 
 [[package]]
 name = "webkit2gtk"
-version = "2.0.1"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a"
+checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793"
 dependencies = [
  "bitflags 1.3.2",
  "cairo-rs",
@@ -6058,9 +6225,9 @@ dependencies = [
 
 [[package]]
 name = "webkit2gtk-sys"
-version = "2.0.1"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c"
+checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5"
 dependencies = [
  "bitflags 1.3.2",
  "cairo-sys-rs",
@@ -6719,9 +6886,9 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
 
 [[package]]
 name = "wry"
-version = "0.53.5"
+version = "0.54.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2"
+checksum = "5ed1a195b0375491dd15a7066a10251be217ce743cf4bbbbdcf5391d6473bee0"
 dependencies = [
  "base64 0.22.1",
  "block2 0.6.2",

+ 12 - 2
packages/desktop/src-tauri/Cargo.toml

@@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
 tauri-build = { version = "2", features = [] }
 
 [dependencies]
-tauri = { version = "2", features = ["macos-private-api", "devtools"] }
+tauri = { version = "2.9.5", features = ["macos-private-api", "devtools"] }
 tauri-plugin-opener = "2"
 tauri-plugin-deep-link = "2.4.6"
 tauri-plugin-shell = "2"
@@ -43,10 +43,13 @@ reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"
 uuid = { version = "1.19.0", features = ["v4"] }
 tauri-plugin-decorum = "1.1.1"
 comrak = { version = "0.50", default-features = false }
+specta = "=2.0.0-rc.22"
+specta-typescript = "0.0.9"
+tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] }
 
 [target.'cfg(target_os = "linux")'.dependencies]
 gtk = "0.18.2"
-webkit2gtk = "=2.0.1"
+webkit2gtk = "=2.0.2"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 objc2 = "0.6"
@@ -59,3 +62,10 @@ windows = { version = "0.61", features = [
     "Win32_System_Threading",
     "Win32_Security"
 ] }
+
+[patch.crates-io]
+specta = { git = "https://github.com/specta-rs/specta", rev = "106425eac4964d8ff34d3a02f1612e33117b08bb" }
+specta-typescript = { git = "https://github.com/specta-rs/specta", rev = "106425eac4964d8ff34d3a02f1612e33117b08bb" }
+tauri-specta = { git = "https://github.com/specta-rs/tauri-specta", rev = "6720b2848eff9a3e40af54c48d65f6d56b640c0b" }
+# TODO: https://github.com/tauri-apps/tauri/pull/14812
+tauri  = { git = "https://github.com/tauri-apps/tauri", rev = "4d5d78daf636feaac20c5bc48a6071491c4291ee" }

+ 1 - 0
packages/desktop/src-tauri/src/cli.rs

@@ -51,6 +51,7 @@ fn is_cli_installed() -> bool {
 const INSTALL_SCRIPT: &str = include_str!("../../../../install");
 
 #[tauri::command]
+#[specta::specta]
 pub fn install_cli(app: tauri::AppHandle) -> Result<String, String> {
     if cfg!(not(unix)) {
         return Err("CLI installation is only supported on macOS & Linux".to_string());

+ 30 - 11
packages/desktop/src-tauri/src/lib.rs

@@ -16,10 +16,10 @@ use std::{
     time::{Duration, Instant},
 };
 use tauri::{AppHandle, LogicalSize, Manager, RunEvent, State, WebviewWindowBuilder};
-#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
-use tauri_plugin_deep_link::DeepLinkExt;
 #[cfg(windows)]
 use tauri_plugin_decorum::WebviewWindowExt;
+#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
+use tauri_plugin_deep_link::DeepLinkExt;
 use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult};
 use tauri_plugin_shell::process::{CommandChild, CommandEvent};
 use tauri_plugin_store::StoreExt;
@@ -30,7 +30,7 @@ use crate::window_customizer::PinchZoomDisablePlugin;
 const SETTINGS_STORE: &str = "opencode.settings.dat";
 const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl";
 
-#[derive(Clone, serde::Serialize)]
+#[derive(Clone, serde::Serialize, specta::Type)]
 struct ServerReadyData {
     url: String,
     password: Option<String>,
@@ -64,6 +64,7 @@ struct LogState(Arc<Mutex<VecDeque<String>>>);
 const MAX_LOG_ENTRIES: usize = 200;
 
 #[tauri::command]
+#[specta::specta]
 fn kill_sidecar(app: AppHandle) {
     let Some(server_state) = app.try_state::<ServerState>() else {
         println!("Server not running");
@@ -97,6 +98,7 @@ async fn get_logs(app: AppHandle) -> Result<String, String> {
 }
 
 #[tauri::command]
+#[specta::specta]
 async fn ensure_server_ready(state: State<'_, ServerState>) -> Result<ServerReadyData, String> {
     state
         .status
@@ -106,6 +108,7 @@ async fn ensure_server_ready(state: State<'_, ServerState>) -> Result<ServerRead
 }
 
 #[tauri::command]
+#[specta::specta]
 fn get_default_server_url(app: AppHandle) -> Result<Option<String>, String> {
     let store = app
         .store(SETTINGS_STORE)
@@ -119,6 +122,7 @@ fn get_default_server_url(app: AppHandle) -> Result<Option<String>, String> {
 }
 
 #[tauri::command]
+#[specta::specta]
 async fn set_default_server_url(app: AppHandle, url: Option<String>) -> Result<(), String> {
     let store = app
         .store(SETTINGS_STORE)
@@ -252,6 +256,26 @@ async fn check_server_health(url: &str, password: Option<&str>) -> bool {
 pub fn run() {
     let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some();
 
+    let builder = tauri_specta::Builder::<tauri::Wry>::new()
+        // Then register them (separated by a comma)
+        .commands(tauri_specta::collect_commands![
+            kill_sidecar,
+            install_cli,
+            ensure_server_ready,
+            get_default_server_url,
+            set_default_server_url,
+            markdown::parse_markdown_command
+        ])
+        .error_handling(tauri_specta::ErrorHandlingMode::Throw);
+
+    #[cfg(debug_assertions)] // <- Only export on non-release builds
+    builder
+        .export(
+            specta_typescript::Typescript::default(),
+            "../src/bindings.ts",
+        )
+        .expect("Failed to export typescript bindings");
+
     #[cfg(all(target_os = "macos", not(debug_assertions)))]
     let _ = std::process::Command::new("killall")
         .arg("opencode-cli")
@@ -285,15 +309,10 @@ pub fn run() {
         .plugin(tauri_plugin_notification::init())
         .plugin(PinchZoomDisablePlugin)
         .plugin(tauri_plugin_decorum::init())
-        .invoke_handler(tauri::generate_handler![
-            kill_sidecar,
-            install_cli,
-            ensure_server_ready,
-            get_default_server_url,
-            set_default_server_url,
-            markdown::parse_markdown_command
-        ])
+        .invoke_handler(builder.invoke_handler())
         .setup(move |app| {
+            builder.mount_events(app);
+
             #[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
             app.deep_link().register_all().ok();
 

+ 4 - 1
packages/desktop/src-tauri/src/markdown.rs

@@ -1,4 +1,6 @@
-use comrak::{create_formatter, parse_document, Arena, Options, html::ChildRendering, nodes::NodeValue};
+use comrak::{
+    Arena, Options, create_formatter, html::ChildRendering, nodes::NodeValue, parse_document,
+};
 use std::fmt::Write;
 
 create_formatter!(ExternalLinkFormatter, {
@@ -55,6 +57,7 @@ pub fn parse_markdown(input: &str) -> String {
 }
 
 #[tauri::command]
+#[specta::specta]
 pub async fn parse_markdown_command(markdown: String) -> Result<String, String> {
     Ok(parse_markdown(&markdown))
 }

+ 20 - 0
packages/desktop/src/bindings.ts

@@ -0,0 +1,20 @@
+// This file has been generated by Tauri Specta. Do not edit this file manually.
+
+import { invoke as __TAURI_INVOKE, Channel } from '@tauri-apps/api/core';
+
+/** Commands */
+export const commands = {
+	killSidecar: () => __TAURI_INVOKE<void>("kill_sidecar"),
+	installCli: () => __TAURI_INVOKE<string>("install_cli"),
+	ensureServerReady: () => __TAURI_INVOKE<ServerReadyData>("ensure_server_ready"),
+	getDefaultServerUrl: () => __TAURI_INVOKE<string | null>("get_default_server_url"),
+	setDefaultServerUrl: (url: string | null) => __TAURI_INVOKE<null>("set_default_server_url", { url }),
+	parseMarkdownCommand: (markdown: string) => __TAURI_INVOKE<string>("parse_markdown_command", { markdown }),
+};
+
+/* Types */
+export type ServerReadyData = {
+		url: string,
+		password: string | null,
+	};
+

+ 2 - 2
packages/desktop/src/cli.ts

@@ -1,13 +1,13 @@
-import { invoke } from "@tauri-apps/api/core"
 import { message } from "@tauri-apps/plugin-dialog"
 
 import { initI18n, t } from "./i18n"
+import { commands } from "./bindings"
 
 export async function installCli(): Promise<void> {
   await initI18n()
 
   try {
-    const path = await invoke<string>("install_cli")
+    const path = await commands.installCli()
     await message(t("desktop.cli.installed.message", { path }), { title: t("desktop.cli.installed.title") })
   } catch (e) {
     await message(t("desktop.cli.failed.message", { error: String(e) }), { title: t("desktop.cli.failed.title") })

+ 8 - 12
packages/desktop/src/index.tsx

@@ -7,7 +7,6 @@ import { getCurrent, onOpenUrl } from "@tauri-apps/plugin-deep-link"
 import { open as shellOpen } from "@tauri-apps/plugin-shell"
 import { type as ostype } from "@tauri-apps/plugin-os"
 import { check, Update } from "@tauri-apps/plugin-updater"
-import { invoke } from "@tauri-apps/api/core"
 import { getCurrentWindow } from "@tauri-apps/api/window"
 import { isPermissionGranted, requestPermission } from "@tauri-apps/plugin-notification"
 import { relaunch } from "@tauri-apps/plugin-process"
@@ -22,6 +21,7 @@ import { createMenu } from "./menu"
 import { initI18n, t } from "./i18n"
 import pkg from "../package.json"
 import "./styles.css"
+import { commands } from "./bindings"
 
 const root = document.getElementById("root")
 if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
@@ -274,12 +274,12 @@ const createPlatform = (password: Accessor<string | null>): Platform => ({
 
   update: async () => {
     if (!UPDATER_ENABLED || !update) return
-    if (ostype() === "windows") await invoke("kill_sidecar").catch(() => undefined)
+    if (ostype() === "windows") await commands.killSidecar().catch(() => undefined)
     await update.install().catch(() => undefined)
   },
 
   restart: async () => {
-    await invoke("kill_sidecar").catch(() => undefined)
+    await commands.killSidecar().catch(() => undefined)
     await relaunch()
   },
 
@@ -335,17 +335,13 @@ const createPlatform = (password: Accessor<string | null>): Platform => ({
   },
 
   getDefaultServerUrl: async () => {
-    const result = await invoke<string | null>("get_default_server_url").catch(() => null)
+    const result = await commands.getDefaultServerUrl().catch(() => null)
     return result
   },
 
-  setDefaultServerUrl: async (url: string | null) => {
-    await invoke("set_default_server_url", { url })
-  },
+  setDefaultServerUrl: async (url: string | null) => { await commands.setDefaultServerUrl(url) },
 
-  parseMarkdown: async (markdown: string) => {
-    return invoke<string>("parse_markdown_command", { markdown })
-  },
+  parseMarkdown: (markdown: string) => commands.parseMarkdownCommand(markdown),
 
   webviewZoom,
 })
@@ -394,7 +390,7 @@ type ServerReadyData = { url: string; password: string | null }
 // Gate component that waits for the server to be ready
 function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.Element }) {
   const [serverData] = createResource<ServerReadyData>(() =>
-    invoke("ensure_server_ready").then((v) => {
+    commands.ensureServerReady().then((v) => {
       return new Promise((res) => setTimeout(() => res(v as ServerReadyData), 2000))
     }),
   )
@@ -408,7 +404,7 @@ function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.
   }
 
   const restartApp = async () => {
-    await invoke("kill_sidecar").catch(() => undefined)
+    await commands.killSidecar().catch(() => undefined)
     await relaunch().catch(() => undefined)
   }
 

+ 2 - 2
packages/desktop/src/menu.ts

@@ -1,11 +1,11 @@
 import { Menu, MenuItem, PredefinedMenuItem, Submenu } from "@tauri-apps/api/menu"
 import { type as ostype } from "@tauri-apps/plugin-os"
-import { invoke } from "@tauri-apps/api/core"
 import { relaunch } from "@tauri-apps/plugin-process"
 
 import { runUpdater, UPDATER_ENABLED } from "./updater"
 import { installCli } from "./cli"
 import { initI18n, t } from "./i18n"
+import { commands } from "./bindings"
 
 export async function createMenu() {
   if (ostype() !== "macos") return
@@ -35,7 +35,7 @@ export async function createMenu() {
           }),
           await MenuItem.new({
             action: async () => {
-              await invoke("kill_sidecar").catch(() => undefined)
+              await commands.killSidecar().catch(() => undefined)
               await relaunch().catch(() => undefined)
             },
             text: t("desktop.menu.restart"),

+ 3 - 3
packages/desktop/src/updater.ts

@@ -1,10 +1,10 @@
 import { check } from "@tauri-apps/plugin-updater"
 import { relaunch } from "@tauri-apps/plugin-process"
 import { ask, message } from "@tauri-apps/plugin-dialog"
-import { invoke } from "@tauri-apps/api/core"
 import { type as ostype } from "@tauri-apps/plugin-os"
 
 import { initI18n, t } from "./i18n"
+import { commands } from "./bindings"
 
 export const UPDATER_ENABLED = window.__OPENCODE__?.updaterEnabled ?? false
 
@@ -39,13 +39,13 @@ export async function runUpdater({ alertOnFail }: { alertOnFail: boolean }) {
   if (!shouldUpdate) return
 
   try {
-    if (ostype() === "windows") await invoke("kill_sidecar")
+    if (ostype() === "windows") await commands.killSidecar()
     await update.install()
   } catch {
     await message(t("desktop.updater.installFailed.message"), { title: t("desktop.updater.installFailed.title") })
     return
   }
 
-  await invoke("kill_sidecar")
+  await commands.killSidecar()
   await relaunch()
 }