summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrendan Allan <[email protected]>2026-02-02 15:58:08 +0800
committerGitHub <[email protected]>2026-02-02 07:58:08 +0000
commit04aef44fc30d599f11ea2ada60ed63c4856a18ff (patch)
tree391c103e232d085f9322dec41d0321752d27f154
parentc02dd067b2ae62553c63b087b7b48a0f46628747 (diff)
downloadopencode-04aef44fc30d599f11ea2ada60ed63c4856a18ff.tar.gz
opencode-04aef44fc30d599f11ea2ada60ed63c4856a18ff.zip
chore(desktop): integrate tauri-specta (#11740)
-rw-r--r--packages/desktop/src-tauri/Cargo.lock247
-rw-r--r--packages/desktop/src-tauri/Cargo.toml14
-rw-r--r--packages/desktop/src-tauri/src/cli.rs1
-rw-r--r--packages/desktop/src-tauri/src/lib.rs41
-rw-r--r--packages/desktop/src-tauri/src/markdown.rs5
-rw-r--r--packages/desktop/src/bindings.ts20
-rw-r--r--packages/desktop/src/cli.ts4
-rw-r--r--packages/desktop/src/index.tsx20
-rw-r--r--packages/desktop/src/menu.ts4
-rw-r--r--packages/desktop/src/updater.ts6
10 files changed, 289 insertions, 73 deletions
diff --git a/packages/desktop/src-tauri/Cargo.lock b/packages/desktop/src-tauri/Cargo.lock
index 51e5e0049..14030218e 100644
--- a/packages/desktop/src-tauri/Cargo.lock
+++ b/packages/desktop/src-tauri/Cargo.lock
@@ -3,6 +3,12 @@
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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -3222,6 +3231,12 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3948,6 +3963,40 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4498,6 +4547,44 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -5180,12 +5284,75 @@ dependencies = [
]
[[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",
"cargo_metadata",
"ctor",
@@ -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",
diff --git a/packages/desktop/src-tauri/Cargo.toml b/packages/desktop/src-tauri/Cargo.toml
index e87bf77c2..2efa484e8 100644
--- a/packages/desktop/src-tauri/Cargo.toml
+++ b/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" }
diff --git a/packages/desktop/src-tauri/src/cli.rs b/packages/desktop/src-tauri/src/cli.rs
index f64beed6a..16e4bfec9 100644
--- a/packages/desktop/src-tauri/src/cli.rs
+++ b/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());
diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs
index 0958481ad..2fe7c4aa1 100644
--- a/packages/desktop/src-tauri/src/lib.rs
+++ b/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();
diff --git a/packages/desktop/src-tauri/src/markdown.rs b/packages/desktop/src-tauri/src/markdown.rs
index c3ca73857..39a64a431 100644
--- a/packages/desktop/src-tauri/src/markdown.rs
+++ b/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))
}
diff --git a/packages/desktop/src/bindings.ts b/packages/desktop/src/bindings.ts
new file mode 100644
index 000000000..eb5498fa6
--- /dev/null
+++ b/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,
+ };
+
diff --git a/packages/desktop/src/cli.ts b/packages/desktop/src/cli.ts
index 5a8875cf8..28623bdf7 100644
--- a/packages/desktop/src/cli.ts
+++ b/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") })
diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx
index 505a00b16..2b4406162 100644
--- a/packages/desktop/src/index.tsx
+++ b/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)
}
diff --git a/packages/desktop/src/menu.ts b/packages/desktop/src/menu.ts
index 2edeff42b..d41084404 100644
--- a/packages/desktop/src/menu.ts
+++ b/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"),
diff --git a/packages/desktop/src/updater.ts b/packages/desktop/src/updater.ts
index b48bb6be0..732669633 100644
--- a/packages/desktop/src/updater.ts
+++ b/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()
}