Skip to content

Commit

Permalink
Merge pull request #124 from kareemmahlees/docs/missing-docs
Browse files Browse the repository at this point in the history
doc: add missing docs & fix some errors in doc testing 📝
  • Loading branch information
oscartbeaumont authored Aug 13, 2024
2 parents 0931335 + 8f2c97f commit fe2e052
Show file tree
Hide file tree
Showing 14 changed files with 387 additions and 96 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ dist-ssr
*.sw?
target

dist
dist
/_out
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ tauri-specta-macros = { version = "=2.0.0-rc.6", optional = true, path = "./macr
serde = "1"
serde_json = "1"
thiserror = "1"
tauri = { workspace = true, default-features = false, features = ["specta"] }
tauri = { workspace = true, features = ["specta"] }

# Private
heck = "0.5.0"
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ cd examples/app/
pnpm tauri dev
```

### Running tests

```bash
mkdir _out
OUT_DIR="$(pwd)/_out" cargo test --all --all-features
```

## Credit

Created by [oscartbeaumont](https://github.com/oscartbeaumont) and [Brendonovich](https://github.com/brendonovich).
4 changes: 2 additions & 2 deletions examples/app/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub struct Testing {
}

fn main() {
let mut builder = Builder::<tauri::Wry>::new()
let builder = Builder::<tauri::Wry>::new()
.commands(tauri_specta::collect_commands![
hello_world,
goodbye_world,
Expand All @@ -128,7 +128,7 @@ fn main() {
typesafe_errors_using_thiserror_with_value,
])
.events(tauri_specta::collect_events![crate::DemoEvent, EmptyEvent])
.ty::<Custom>()
.typ::<Custom>()
.constant("universalConstant", 42);

#[cfg(debug_assertions)]
Expand Down
107 changes: 55 additions & 52 deletions examples/custom-plugin/plugin/bindings.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,91 @@

// 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.

/** user-defined commands **/
/** user-defined commands **/

export const commands = {

export const commands = {
/**
* Adds two numbers, returning the result.
*/
async addNumbers(a: number, b: number) : Promise<number> {
return await TAURI_INVOKE("plugin:specta-example|add_numbers", { a, b });
return await TAURI_INVOKE("plugin:specta-example|add_numbers", { a, b });
}
}

/** user-defined events **/
/** user-defined events **/


export const events = __makeEvents__<{
randomNumber: RandomNumber
}>({
randomNumber: "plugin:specta-example:random-number"
})

/** user-defined statics **/
/** user-defined constants **/




/** user-defined types **/

export type RandomNumber = number

/** tauri-specta globals **/

import { invoke as TAURI_INVOKE } from "@tauri-apps/api/core";
import {
invoke as TAURI_INVOKE,
Channel as TAURI_CHANNEL,
} from "@tauri-apps/api/core";
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";

type __EventObj__<T> = {
listen: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
listen: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
};

export type Result<T, E> =
| { status: "ok"; data: T }
| { status: "error"; error: E };
| { status: "ok"; data: T }
| { status: "error"; error: E };

function __makeEvents__<T extends Record<string, any>>(
mappings: Record<keyof T, string>
mappings: Record<keyof T, string>,
) {
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>;
};
},
{
get: (_, event) => {
const name = mappings[event as keyof T];

return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
}
);
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>;
};
},
{
get: (_, event) => {
const name = mappings[event as keyof T];

return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
},
);
}


79 changes: 76 additions & 3 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,94 @@
)]

use heck::ToKebabCase;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
use syn::{
parse_macro_input, parse_quote, ConstParam, DeriveInput, GenericParam, Generics, LifetimeParam,
TypeParam, WhereClause,
};

#[proc_macro_derive(Event, attributes(tauri_specta))]
pub fn derive_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let crate_ref = quote!(tauri_specta);

let DeriveInput { ident, .. } = parse_macro_input!(input);
let DeriveInput {
ident, generics, ..
} = parse_macro_input!(input);

let name = ident.to_string().to_kebab_case();
let bounds = generics_with_ident_and_bounds_only(&generics);
let type_args = generics_with_ident_only(&generics);
let where_bound = add_type_to_where_clause(&generics);

quote! {
impl #crate_ref::Event for #ident {
#[automatically_derived]
impl #bounds #crate_ref::Event for #ident #type_args #where_bound {
const NAME: &'static str = #name;
}
}
.into()
}

fn generics_with_ident_and_bounds_only(generics: &Generics) -> Option<TokenStream> {
(!generics.params.is_empty())
.then(|| {
use GenericParam::*;
generics.params.iter().map(|param| match param {
Type(TypeParam {
ident,
colon_token,
bounds,
..
}) => quote!(#ident #colon_token #bounds),
Lifetime(LifetimeParam {
lifetime,
colon_token,
bounds,
..
}) => quote!(#lifetime #colon_token #bounds),
Const(ConstParam {
const_token,
ident,
colon_token,
ty,
..
}) => quote!(#const_token #ident #colon_token #ty),
})
})
.map(|gs| quote!(<#(#gs),*>))
}

fn generics_with_ident_only(generics: &Generics) -> Option<TokenStream> {
(!generics.params.is_empty())
.then(|| {
use GenericParam::*;

generics.params.iter().map(|param| match param {
Type(TypeParam { ident, .. }) | Const(ConstParam { ident, .. }) => quote!(#ident),
Lifetime(LifetimeParam { lifetime, .. }) => quote!(#lifetime),
})
})
.map(|gs| quote!(<#(#gs),*>))
}

fn add_type_to_where_clause(generics: &Generics) -> Option<WhereClause> {
let generic_types = generics
.params
.iter()
.filter_map(|gp| match gp {
GenericParam::Type(ty) => Some(ty.ident.clone()),
_ => None,
})
.collect::<Vec<_>>();
if generic_types.is_empty() {
return generics.where_clause.clone();
}
match generics.where_clause {
None => None,
Some(ref w) => {
let bounds = w.predicates.iter();
Some(parse_quote! { where #(#bounds),* })
}
}
}
Loading

0 comments on commit fe2e052

Please sign in to comment.