This branch contains the code for tauri-specta v2. You can check the v1.0.2 git tag for the v1 code.
cargo add specta
cargo add tauri-specta --features javascript,typescript
Specta v2 hasn't officially launched yet but it can be used through the release candidate (rc
) versions.
You must ensure you lock your Specta version to avoid breaking changes.
cargo add specta@=2.0.0-rc.7
cargo add tauri-specta@=2.0.0-rc.4 --features javascript,typescript
use specta::Type;
use serde::{Deserialize, Serialize};
// The `specta::Type` macro allows us to understand your types
// We implement `specta::Type` on primitive types for you.
// If you want to use a type from an external crate you may need to enable the feature on Specta.
#[derive(Serialize, Type)]
pub struct MyCustomReturnType {
pub some_field: String,
}
#[derive(Deserialize, Type)]
pub struct MyCustomArgumentType {
pub foo: String,
pub bar: i32,
}
#[tauri::command]
#[specta::specta] // <-- This bit here
fn greet3() -> MyCustomReturnType {
MyCustomReturnType {
some_field: "Hello World".into(),
}
}
#[tauri::command]
#[specta::specta] // <-- This bit here
fn greet(name: String) -> String {
format!("Hello {name}!")
}
use specta::collect_types;
use tauri_specta::{ts, js};
// this example exports your types on startup when in debug mode. You can do whatever.
fn main() {
let specta_builder = {
// You can use `tauri_specta::js::builder` for exporting JS Doc instead of Typescript!`
let specta_builder = tauri_specta::ts::builder()
.commands(tauri_specta::collect_commands![greet, greet2, greet3 ]); // <- Each of your comments
#[cfg(debug_assertions)] // <- Only export on non-release builds
let specta_builder = specta_builder.path("../src/bindings.ts");
specta_builder.into_plugin()
};
tauri::Builder::default()
.plugin(specta_builder)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
import * as commands from "./bindings"; // This should point to the file we export from Rust
await commands.greet("Brendan");
To use Events you must be using Specta v2 and Tauri Specta v2.
Firstly you have to define your event types. You can add as many of these as you want.
#[derive(Debug, Clone, Serialize, Deserialize, specta::Type, tauri_specta::Event)]
pub struct DemoEvent(String);
Next you must add it to the builder like the following:
let specta_builder = ts::builder()
.events(tauri_specta::collect_events![DemoEvent]); // This should contain all your events.
Then it can be used in Rust like the following:
tauri::Builder::default()
.setup(|app| {
let handle = app.handle();
DemoEvent::listen_global(&handle, |event| {
dbg!(event.payload);
});
DemoEvent("Test".to_string()).emit_all(&handle).unwrap();
});
and it can be used in TS like the following:
import { commands, events } from "./bindings";
import { appWindow } from "@tauri-apps/api/window";
// For all windows
events.demoEvent.listen((e) => console.log(e));
// For a single window
events.demoEvent(appWindow).listen((e) => console.log(e));
// Emit to the backend and all windows
await events.demoEvent.emit("Test")
// Emit to a window
await events.demoEvent(appWindow).emit("Test")
- Your command can only take up to 10 arguments. Any more and you'll get a compile error. If you need more just use a struct.
- Exporting your schema within a directory tracked by Tauri's hot reload will cause an infinite reload loop.
Run the example:
pnpm i
cd examples/app/
pnpm dev
Created by oscartbeaumont and Brendonovich.