Skip to content

Commit

Permalink
🎉 Release 2.0.0-rc.1
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Oct 4, 2023
1 parent cfad166 commit 66f123a
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 84 deletions.
14 changes: 8 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "tauri-specta"
description = "Completely typesafe Tauri commands"
version = "1.0.2"
version = "2.0.0-rc.1"
authors = ["Oscar Beaumont <[email protected]>"]
edition = "2021"
license = "MIT"
Expand All @@ -23,7 +23,7 @@ typescript = ["specta/typescript"]

[dependencies]
specta = { workspace = true, features = ["functions", "tauri"] }
tauri-specta-macros = { path = "./macros" }
tauri-specta-macros = { version = "=2.0.0-rc.1", path = "./macros" }
serde = { workspace = true }
serde_json = "1.0.106"
tauri = { workspace = true }
Expand All @@ -43,9 +43,6 @@ members = [
]

[workspace.dependencies]
specta = { version = "=2.0.0-rc.3" }
specta = { version = "=2.0.0-rc.4" }
serde = "1.0.188"
tauri = "1.4.1"

[patch.crates-io]
specta = { git = "https://github.com/oscartbeaumont/specta", rev = "928b7ffc3cd5abf8c597da2dd846d7bfe16dfe62" }
96 changes: 81 additions & 15 deletions README.md
Expand Up @@ -12,13 +12,28 @@

<br>

> This branch contains the code for tauri-specta v2. You can check the [v1.0.2 git tag](https://github.com/oscartbeaumont/tauri-specta/tree/v1.0.2) for the v1 code.
## Install

## Specta v1

```bash
cargo add specta
cargo add tauri-specta --features javascript,typescript
```

## Specta v2

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.

```bash
cargo add specta@=2.0.0-rc.4
cargo add tauri-specta@=2.0.0-rc.1 --features javascript,typescript
```

## Adding Specta to custom types

```rust
Expand Down Expand Up @@ -64,21 +79,25 @@ fn greet(name: String) -> String {
use specta::collect_types;
use tauri_specta::{ts, js};

// this example exports your types on startup when in debug mode or in a unit test. You can do whatever.
// this example exports your types on startup when in debug mode. You can do whatever.

fn main() {
#[cfg(debug_assertions)]
ts::export(collect_types![greet, greet2, greet3], "../src/bindings.ts").unwrap();

// or export to JS with JSDoc
#[cfg(debug_assertions)]
js::export(collect_types![greet, greet2, greet3], "../src/bindings.js").unwrap();
}

#[test]
fn export_bindings() {
ts::export(collect_types![greet, greet2, greet3], "../src/bindings.ts").unwrap();
js::export(collect_types![greet, greet2, greet3], "../src/bindings.js").unwrap();
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");
}
```

Expand All @@ -90,6 +109,53 @@ import * as commands from "./bindings"; // This should point to the file we expo
await commands.greet("Brendan");
```

## Events

> To use Events you must be using [Specta v2 and Tauri Specta v2](#specta-v2).
Firstly you have to define your event types. You can add as many of these as you want.

```rust
#[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:

```rust
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:

```rust
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:

```ts
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));
```


## Known limitations

- 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.
Expand All @@ -101,8 +167,8 @@ Run the example:

```bash
pnpm i
cd example/
pnpm tauri dev
cd examples/app/
pnpm dev
```

## Credit
Expand Down
73 changes: 36 additions & 37 deletions examples/app/src/bindings.ts
@@ -1,50 +1,47 @@
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.

export const commands = {
/**
* HELLO
* WORLD
* !!!!
*/
async helloWorld(myName: string): Promise<string> {
return await TAURI_INVOKE("plugin:tauri-specta|hello_world", { myName });
},
async goodbyeWorld(): Promise<string> {
return await TAURI_INVOKE("plugin:tauri-specta|goodbye_world");
},
async hasError(): Promise<__Result__<string, number>> {
try {
return {
status: "ok",
data: await TAURI_INVOKE("plugin:tauri-specta|has_error"),
};
} catch (e) {
if (e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
async someStruct(): Promise<MyStruct> {
return await TAURI_INVOKE("plugin:tauri-specta|some_struct");
},
};
export const commands = {
/**
* HELLO
* WORLD
* !!!!
*/
async helloWorld(myName: string) : Promise<string> {
return await TAURI_INVOKE("plugin:tauri-specta|hello_world", { myName });
},
async goodbyeWorld() : Promise<string> {
return await TAURI_INVOKE("plugin:tauri-specta|goodbye_world");
},
async hasError() : Promise<__Result__<string, number>> {
try {
return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|has_error") };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
async someStruct() : Promise<MyStruct> {
return await TAURI_INVOKE("plugin:tauri-specta|some_struct");
}
}

export const events = __makeEvents__<{
demoEvent: DemoEvent;
emptyEvent: EmptyEvent;
demoEvent: DemoEvent,
emptyEvent: EmptyEvent
}>({
demoEvent: "plugin:tauri-specta:demo-event",
emptyEvent: "plugin:tauri-specta:empty-event",
});
demoEvent: "plugin:tauri-specta:demo-event",
emptyEvent: "plugin:tauri-specta:empty-event"
})

/** user-defined types **/

export type DemoEvent = string;
export type EmptyEvent = null;
export type MyStruct = { some_field: string };
export type DemoEvent = string
export type EmptyEvent = null
export type MyStruct = { some_field: string }

/** tauri-specta globals **/

import { invoke as TAURI_INVOKE } from "@tauri-apps/api";
import { invoke as TAURI_INVOKE } from "@tauri-apps/api";
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
import { type WebviewWindowHandle as __WebviewWindowHandle__ } from "@tauri-apps/api/window";

Expand Down Expand Up @@ -98,3 +95,5 @@ function __makeEvents__<T extends Record<string, any>>(
}
);
}


11 changes: 8 additions & 3 deletions macros/Cargo.toml
@@ -1,9 +1,14 @@
[package]
name = "tauri-specta-macros"
version = "0.1.0"
description = "Completely typesafe Tauri commands"
version = "2.0.0-rc.1"
authors = ["Oscar Beaumont <[email protected]>"]
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
license = "MIT"
repository = "https://github.com/oscartbeaumont/tauri-specta"
documentation = "https://docs.rs/tauri-specta/latest/tauri-specta"
keywords = ["async", "specta", "rspc", "typescript", "typesafe"]
categories = ["web-programming", "asynchronous"]

[lib]
proc-macro = true
Expand Down
4 changes: 1 addition & 3 deletions package.json
@@ -1,9 +1,7 @@
{
"private": true,
"version": "0.0.0",
"scripts": {
"example": "pnpm --filter example -- "
},
"scripts": {},
"dependencies": {
"@tauri-apps/api": "^1.4.0"
}
Expand Down
4 changes: 2 additions & 2 deletions src/event.rs
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use serde::{de::DeserializeOwned, Serialize};
use specta::{DataType, NamedType, SpectaID, Type};
use specta::{DataType, NamedType, SpectaID};
use tauri::{EventHandler, Manager, Runtime, Window};

use crate::PluginName;
Expand Down Expand Up @@ -104,7 +104,7 @@ macro_rules! get_meta {
};
}

pub trait Event: Type + NamedType {
pub trait Event: NamedType {
const NAME: &'static str;

// Manager functions
Expand Down
1 change: 1 addition & 0 deletions src/js.rs
Expand Up @@ -19,6 +19,7 @@ pub type ExportConfig = crate::ExportConfig<Config>;

impl ExportLanguage for Language {
type Config = Config;
type Error = ts::ExportError;

fn run_format(path: PathBuf, cfg: &ExportConfig) {
cfg.inner.run_format(path).ok();
Expand Down
4 changes: 2 additions & 2 deletions src/js_ts.rs
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;

use heck::ToLowerCamelCase;
use indoc::formatdoc;
use specta::{functions::FunctionDataType, ts::ExportError, ts, DataType, TypeMap};
use specta::{functions::FunctionDataType, ts, ts::ExportError, DataType, TypeMap};

use crate::{EventDataType, ExportLanguage, ItemType};

Expand All @@ -19,7 +19,7 @@ pub fn render_all_parts<T: ExportLanguage<Config = specta::ts::ExportConfig>>(
cfg: &ExportConfig,
dependant_types: &str,
globals: &str,
) -> Result<String, ExportError> {
) -> Result<String, T::Error> {
let commands = T::render_commands(commands, type_map, cfg)?;
let events = T::render_events(events, type_map, cfg)?;

Expand Down

0 comments on commit 66f123a

Please sign in to comment.