mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-11-28 12:27:16 +03:00
perf(core): improve binary size with api enum serde refactor (#3952)
This commit is contained in:
parent
f68af45a11
commit
c23f139ba8
5
.changes/binary-size-perf.md
Normal file
5
.changes/binary-size-perf.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
Reduce the amount of generated code for the API endpoints.
|
@ -24,6 +24,7 @@ exclude = [
|
||||
|
||||
# default to small, optimized workspace release binaries
|
||||
[profile.release]
|
||||
strip = true
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
|
@ -2,35 +2,115 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use heck::ToSnakeCase;
|
||||
use heck::{ToLowerCamelCase, ToSnakeCase};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2, TokenTree};
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
|
||||
use quote::{format_ident, quote, quote_spanned};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
parse_quote,
|
||||
spanned::Spanned,
|
||||
Data, DeriveInput, Error, Fields, FnArg, Ident, ItemFn, LitStr, Pat, Token,
|
||||
Data, DeriveInput, Error, Fields, Ident, ItemFn, LitStr, Token,
|
||||
};
|
||||
|
||||
pub fn generate_run_fn(input: DeriveInput) -> TokenStream {
|
||||
pub(crate) fn generate_command_enum(mut input: DeriveInput) -> TokenStream {
|
||||
let mut deserialize_functions = TokenStream2::new();
|
||||
let mut errors = TokenStream2::new();
|
||||
|
||||
input.attrs.push(parse_quote!(#[allow(dead_code)]));
|
||||
|
||||
match &mut input.data {
|
||||
Data::Enum(data_enum) => {
|
||||
for variant in &mut data_enum.variants {
|
||||
let mut feature: Option<Ident> = None;
|
||||
let mut error_message: Option<String> = None;
|
||||
|
||||
for attr in &variant.attrs {
|
||||
if attr.path.is_ident("cmd") {
|
||||
let r = attr
|
||||
.parse_args_with(|input: ParseStream| {
|
||||
if let Ok(f) = input.parse::<Ident>() {
|
||||
feature.replace(f);
|
||||
input.parse::<Token![,]>()?;
|
||||
let error_message_raw: LitStr = input.parse()?;
|
||||
error_message.replace(error_message_raw.value());
|
||||
}
|
||||
Ok(quote!())
|
||||
})
|
||||
.unwrap_or_else(syn::Error::into_compile_error);
|
||||
errors.extend(r);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(f) = feature {
|
||||
let error_message = if let Some(e) = error_message {
|
||||
let e = e.to_string();
|
||||
quote!(#e)
|
||||
} else {
|
||||
quote!("This API is not enabled in the allowlist.")
|
||||
};
|
||||
|
||||
let deserialize_function_name = quote::format_ident!("__{}_deserializer", variant.ident);
|
||||
deserialize_functions.extend(quote! {
|
||||
#[cfg(not(#f))]
|
||||
#[allow(non_snake_case)]
|
||||
fn #deserialize_function_name<'de, D, T>(deserializer: D) -> ::std::result::Result<T, D::Error>
|
||||
where
|
||||
D: ::serde::de::Deserializer<'de>,
|
||||
{
|
||||
::std::result::Result::Err(::serde::de::Error::custom(crate::Error::ApiNotAllowlisted(#error_message.into()).to_string()))
|
||||
}
|
||||
});
|
||||
|
||||
let deserialize_function_name = deserialize_function_name.to_string();
|
||||
|
||||
variant
|
||||
.attrs
|
||||
.push(parse_quote!(#[cfg_attr(not(#f), serde(deserialize_with = #deserialize_function_name))]));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Error::new(
|
||||
Span::call_site(),
|
||||
"`command_enum` is only implemented for enums",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into()
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(quote! {
|
||||
#errors
|
||||
#input
|
||||
#deserialize_functions
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn generate_run_fn(input: DeriveInput) -> TokenStream {
|
||||
let name = &input.ident;
|
||||
let data = &input.data;
|
||||
|
||||
let mut errors = TokenStream2::new();
|
||||
|
||||
let mut is_async = false;
|
||||
|
||||
let attrs = input.attrs;
|
||||
for attr in attrs {
|
||||
if attr.path.is_ident("cmd") {
|
||||
let _ = attr.parse_args_with(|input: ParseStream| {
|
||||
while let Some(token) = input.parse()? {
|
||||
if let TokenTree::Ident(ident) = token {
|
||||
is_async |= ident == "async";
|
||||
let r = attr
|
||||
.parse_args_with(|input: ParseStream| {
|
||||
if let Ok(token) = input.parse::<Ident>() {
|
||||
is_async = token == "async";
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
Ok(quote!())
|
||||
})
|
||||
.unwrap_or_else(syn::Error::into_compile_error);
|
||||
errors.extend(r);
|
||||
}
|
||||
}
|
||||
|
||||
let maybe_await = if is_async { quote!(.await) } else { quote!() };
|
||||
let maybe_async = if is_async { quote!(async) } else { quote!() };
|
||||
|
||||
@ -43,6 +123,30 @@ pub fn generate_run_fn(input: DeriveInput) -> TokenStream {
|
||||
for variant in &data_enum.variants {
|
||||
let variant_name = &variant.ident;
|
||||
|
||||
let mut feature = None;
|
||||
|
||||
for attr in &variant.attrs {
|
||||
if attr.path.is_ident("cmd") {
|
||||
let r = attr
|
||||
.parse_args_with(|input: ParseStream| {
|
||||
if let Ok(f) = input.parse::<Ident>() {
|
||||
feature.replace(f);
|
||||
input.parse::<Token![,]>()?;
|
||||
let _: LitStr = input.parse()?;
|
||||
}
|
||||
Ok(quote!())
|
||||
})
|
||||
.unwrap_or_else(syn::Error::into_compile_error);
|
||||
errors.extend(r);
|
||||
}
|
||||
}
|
||||
|
||||
let maybe_feature_check = if let Some(f) = feature {
|
||||
quote!(#[cfg(#f)])
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
let (fields_in_variant, variables) = match &variant.fields {
|
||||
Fields::Unit => (quote_spanned! { variant.span() => }, quote!()),
|
||||
Fields::Unnamed(fields) => {
|
||||
@ -73,9 +177,13 @@ pub fn generate_run_fn(input: DeriveInput) -> TokenStream {
|
||||
variant_execute_function_name.set_span(variant_name.span());
|
||||
|
||||
matcher.extend(quote_spanned! {
|
||||
variant.span() => #name::#variant_name #fields_in_variant => #name::#variant_execute_function_name(context, #variables)#maybe_await.map(Into::into),
|
||||
variant.span() => #maybe_feature_check #name::#variant_name #fields_in_variant => #name::#variant_execute_function_name(context, #variables)#maybe_await.map(Into::into),
|
||||
});
|
||||
}
|
||||
|
||||
matcher.extend(quote! {
|
||||
_ => Err(crate::error::into_anyhow("API not in the allowlist (https://tauri.studio/docs/api/config#tauri.allowlist)")),
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
return Error::new(
|
||||
@ -90,7 +198,8 @@ pub fn generate_run_fn(input: DeriveInput) -> TokenStream {
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics #name #ty_generics #where_clause {
|
||||
#errors
|
||||
impl #impl_generics #name #ty_generics #where_clause {
|
||||
pub #maybe_async fn run<R: crate::Runtime>(self, context: crate::endpoints::InvokeContext<R>) -> super::Result<crate::endpoints::InvokeResponse> {
|
||||
match self {
|
||||
#matcher
|
||||
@ -105,26 +214,25 @@ pub fn generate_run_fn(input: DeriveInput) -> TokenStream {
|
||||
/// Attributes for the module enum variant handler.
|
||||
pub struct HandlerAttributes {
|
||||
allowlist: Ident,
|
||||
error_message: String,
|
||||
}
|
||||
|
||||
impl Parse for HandlerAttributes {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let allowlist = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let raw: LitStr = input.parse()?;
|
||||
let error_message = raw.value();
|
||||
Ok(Self {
|
||||
allowlist,
|
||||
error_message,
|
||||
allowlist: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AllowlistCheckKind {
|
||||
Runtime,
|
||||
Serde,
|
||||
}
|
||||
|
||||
pub struct HandlerTestAttributes {
|
||||
allowlist: Ident,
|
||||
error_message: String,
|
||||
is_async: bool,
|
||||
allowlist_check_kind: AllowlistCheckKind,
|
||||
}
|
||||
|
||||
impl Parse for HandlerTestAttributes {
|
||||
@ -133,60 +241,48 @@ impl Parse for HandlerTestAttributes {
|
||||
input.parse::<Token![,]>()?;
|
||||
let error_message_raw: LitStr = input.parse()?;
|
||||
let error_message = error_message_raw.value();
|
||||
let _ = input.parse::<Token![,]>();
|
||||
let is_async = input
|
||||
.parse::<Ident>()
|
||||
.map(|i| i == "async")
|
||||
.unwrap_or_default();
|
||||
let allowlist_check_kind =
|
||||
if let (Ok(_), Ok(i)) = (input.parse::<Token![,]>(), input.parse::<Ident>()) {
|
||||
if i == "runtime" {
|
||||
AllowlistCheckKind::Runtime
|
||||
} else {
|
||||
AllowlistCheckKind::Serde
|
||||
}
|
||||
} else {
|
||||
AllowlistCheckKind::Serde
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
allowlist,
|
||||
error_message,
|
||||
is_async,
|
||||
allowlist_check_kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn command_handler(attributes: HandlerAttributes, function: ItemFn) -> TokenStream2 {
|
||||
let allowlist = attributes.allowlist;
|
||||
let error_message = attributes.error_message.as_str();
|
||||
let signature = function.sig.clone();
|
||||
|
||||
quote!(
|
||||
#[cfg(#allowlist)]
|
||||
#function
|
||||
|
||||
#[cfg(not(#allowlist))]
|
||||
#[allow(unused_variables)]
|
||||
#[allow(unused_mut)]
|
||||
#signature {
|
||||
Err(anyhow::anyhow!(crate::Error::ApiNotAllowlisted(#error_message.to_string()).to_string()))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn command_test(attributes: HandlerTestAttributes, function: ItemFn) -> TokenStream2 {
|
||||
let allowlist = attributes.allowlist;
|
||||
let is_async = attributes.is_async;
|
||||
let error_message = attributes.error_message.as_str();
|
||||
let signature = function.sig.clone();
|
||||
let test_name = function.sig.ident.clone();
|
||||
let mut args = quote!();
|
||||
for arg in &function.sig.inputs {
|
||||
if let FnArg::Typed(t) = arg {
|
||||
if let Pat::Ident(i) = &*t.pat {
|
||||
let ident = &i.ident;
|
||||
args.extend(quote!(#ident,))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let response = if is_async {
|
||||
quote!(crate::async_runtime::block_on(
|
||||
super::Cmd::#test_name(crate::test::mock_invoke_context(), #args)
|
||||
))
|
||||
} else {
|
||||
quote!(super::Cmd::#test_name(crate::test::mock_invoke_context(), #args))
|
||||
let enum_variant_name = function.sig.ident.to_string().to_lower_camel_case();
|
||||
let response = match attributes.allowlist_check_kind {
|
||||
AllowlistCheckKind::Runtime => {
|
||||
let test_name = function.sig.ident.clone();
|
||||
quote!(super::Cmd::#test_name(crate::test::mock_invoke_context()))
|
||||
}
|
||||
AllowlistCheckKind::Serde => quote! {
|
||||
serde_json::from_str::<super::Cmd>(&format!(r#"{{ "cmd": "{}", "data": null }}"#, #enum_variant_name))
|
||||
},
|
||||
};
|
||||
|
||||
quote!(
|
||||
@ -194,6 +290,7 @@ pub fn command_test(attributes: HandlerTestAttributes, function: ItemFn) -> Toke
|
||||
#function
|
||||
|
||||
#[cfg(not(#allowlist))]
|
||||
#[allow(unused_variables)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
#signature {
|
||||
if let Err(e) = #response {
|
||||
|
@ -76,6 +76,14 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre
|
||||
runtime::default_runtime(attributes, input).into()
|
||||
}
|
||||
|
||||
/// Prepares the command module enum.
|
||||
#[doc(hidden)]
|
||||
#[proc_macro_derive(CommandModule, attributes(cmd))]
|
||||
pub fn derive_command_module(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
command_module::generate_run_fn(input)
|
||||
}
|
||||
|
||||
/// Adds a `run` method to an enum (one of the tauri endpoint modules).
|
||||
/// The `run` method takes a `tauri::endpoints::InvokeContext`
|
||||
/// and returns a `tauri::Result<tauri::endpoints::InvokeResponse>`.
|
||||
@ -83,10 +91,10 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre
|
||||
/// passing the the context and the variant's fields as arguments.
|
||||
/// That function must also return the same `Result<InvokeResponse>`.
|
||||
#[doc(hidden)]
|
||||
#[proc_macro_derive(CommandModule, attributes(cmd))]
|
||||
pub fn derive_command_module(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_attribute]
|
||||
pub fn command_enum(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
command_module::generate_run_fn(input)
|
||||
command_module::generate_command_enum(input)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -60,6 +60,8 @@ fn main() {
|
||||
shell_execute: { any(shell_all, feature = "shell-execute") },
|
||||
shell_sidecar: { any(shell_all, feature = "shell-sidecar") },
|
||||
shell_open: { any(shell_all, feature = "shell-open") },
|
||||
// helper for the command module macro
|
||||
shell_script: { any(shell_execute, shell_sidecar) },
|
||||
// helper for the shell scope functionality
|
||||
shell_scope: { any(shell_execute, shell_sidecar, feature = "shell-open-api") },
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -17,7 +17,6 @@ mod cli;
|
||||
mod clipboard;
|
||||
mod dialog;
|
||||
mod event;
|
||||
#[allow(unused_imports)]
|
||||
mod file_system;
|
||||
mod global_shortcut;
|
||||
mod http;
|
||||
|
@ -5,9 +5,10 @@
|
||||
use super::InvokeContext;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::CommandModule;
|
||||
use tauri_macros::{command_enum, CommandModule};
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
|
@ -2,13 +2,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::{InvokeContext, InvokeResponse};
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
/// The API descriptor.
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[command_enum]
|
||||
#[derive(CommandModule, Deserialize)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// The get CLI matches API.
|
||||
@ -16,21 +19,26 @@ pub enum Cmd {
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(cli, "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)")]
|
||||
#[module_command_handler(cli)]
|
||||
fn cli_matches<R: Runtime>(context: InvokeContext<R>) -> super::Result<InvokeResponse> {
|
||||
if let Some(cli) = &context.config.tauri.cli {
|
||||
crate::api::cli::get_matches(cli, &context.package_info)
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
} else {
|
||||
Err(crate::Error::ApiNotAllowlisted("CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)".into()).into_anyhow())
|
||||
Err(crate::error::into_anyhow("CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)"))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(cli))]
|
||||
fn cli_matches<R: Runtime>(_: InvokeContext<R>) -> super::Result<InvokeResponse> {
|
||||
Err(crate::error::into_anyhow("CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)"))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[tauri_macros::module_command_test(cli, "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)")]
|
||||
#[tauri_macros::module_command_test(cli, "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn cli_matches() {
|
||||
let res = super::Cmd::cli_matches(crate::test::mock_invoke_context());
|
||||
|
@ -2,25 +2,29 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
#[cfg(any(clipboard_write_text, clipboard_read_text))]
|
||||
use crate::runtime::ClipboardManager;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", content = "data", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// Write a text string to the clipboard.
|
||||
#[cmd(clipboard_write_text, "clipboard > writeText")]
|
||||
WriteText(String),
|
||||
/// Read clipboard content as text.
|
||||
ReadText,
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(clipboard_write_text, "clipboard > writeText")]
|
||||
#[module_command_handler(clipboard_write_text)]
|
||||
fn write_text<R: Runtime>(context: InvokeContext<R>, text: String) -> super::Result<()> {
|
||||
context
|
||||
.window
|
||||
@ -30,7 +34,7 @@ impl Cmd {
|
||||
.map_err(crate::error::into_anyhow)
|
||||
}
|
||||
|
||||
#[module_command_handler(clipboard_read_text, "clipboard > readText")]
|
||||
#[module_command_handler(clipboard_read_text)]
|
||||
fn read_text<R: Runtime>(context: InvokeContext<R>) -> super::Result<Option<String>> {
|
||||
context
|
||||
.window
|
||||
@ -39,6 +43,11 @@ impl Cmd {
|
||||
.read_text()
|
||||
.map_err(crate::error::into_anyhow)
|
||||
}
|
||||
|
||||
#[cfg(not(clipboard_read_text))]
|
||||
fn read_text<R: Runtime>(_: InvokeContext<R>) -> super::Result<()> {
|
||||
Err(crate::Error::ApiNotAllowlisted("clipboard > readText".into()).into_anyhow())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -48,16 +57,20 @@ mod tests {
|
||||
fn write_text(text: String) {
|
||||
let ctx = crate::test::mock_invoke_context();
|
||||
super::Cmd::write_text(ctx.clone(), text.clone()).unwrap();
|
||||
#[cfg(clipboard_read_text)]
|
||||
assert_eq!(super::Cmd::read_text(ctx).unwrap(), Some(text));
|
||||
}
|
||||
|
||||
#[tauri_macros::module_command_test(clipboard_read_text, "clipboard > readText")]
|
||||
#[tauri_macros::module_command_test(clipboard_read_text, "clipboard > readText", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn read_text() {
|
||||
let ctx = crate::test::mock_invoke_context();
|
||||
assert_eq!(super::Cmd::read_text(ctx.clone()).unwrap(), None);
|
||||
let text = "Tauri!".to_string();
|
||||
super::Cmd::write_text(ctx.clone(), text.clone()).unwrap();
|
||||
assert_eq!(super::Cmd::read_text(ctx).unwrap(), Some(text));
|
||||
#[cfg(clipboard_write_text)]
|
||||
{
|
||||
let text = "Tauri!".to_string();
|
||||
super::Cmd::write_text(ctx.clone(), text.clone()).unwrap();
|
||||
assert_eq!(super::Cmd::read_text(ctx).unwrap(), Some(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::{InvokeContext, InvokeResponse};
|
||||
use crate::Runtime;
|
||||
#[cfg(any(dialog_open, dialog_save))]
|
||||
use crate::{api::dialog::blocking::FileDialogBuilder, Manager, Scopes};
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -56,25 +58,25 @@ pub struct SaveDialogOptions {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum Cmd {
|
||||
/// The open dialog API.
|
||||
OpenDialog {
|
||||
options: OpenDialogOptions,
|
||||
},
|
||||
#[cmd(dialog_open, "dialog > open")]
|
||||
OpenDialog { options: OpenDialogOptions },
|
||||
/// The save dialog API.
|
||||
SaveDialog {
|
||||
options: SaveDialogOptions,
|
||||
},
|
||||
MessageDialog {
|
||||
message: String,
|
||||
},
|
||||
#[cmd(dialog_save, "dialog > save")]
|
||||
SaveDialog { options: SaveDialogOptions },
|
||||
#[cmd(dialog_message, "dialog > message")]
|
||||
MessageDialog { message: String },
|
||||
#[cmd(dialog_ask, "dialog > ask")]
|
||||
AskDialog {
|
||||
title: Option<String>,
|
||||
message: String,
|
||||
},
|
||||
#[cmd(dialog_confirm, "dialog > confirm")]
|
||||
ConfirmDialog {
|
||||
title: Option<String>,
|
||||
message: String,
|
||||
@ -82,7 +84,7 @@ pub enum Cmd {
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(dialog_open, "dialog > open")]
|
||||
#[module_command_handler(dialog_open)]
|
||||
#[allow(unused_variables)]
|
||||
fn open_dialog<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
@ -130,7 +132,7 @@ impl Cmd {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[module_command_handler(dialog_save, "dialog > save")]
|
||||
#[module_command_handler(dialog_save)]
|
||||
#[allow(unused_variables)]
|
||||
fn save_dialog<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
@ -159,7 +161,7 @@ impl Cmd {
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[module_command_handler(dialog_message, "dialog > message")]
|
||||
#[module_command_handler(dialog_message)]
|
||||
fn message_dialog<R: Runtime>(context: InvokeContext<R>, message: String) -> super::Result<()> {
|
||||
crate::api::dialog::blocking::message(
|
||||
Some(&context.window),
|
||||
@ -169,7 +171,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(dialog_ask, "dialog > ask")]
|
||||
#[module_command_handler(dialog_ask)]
|
||||
fn ask_dialog<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
title: Option<String>,
|
||||
@ -182,7 +184,7 @@ impl Cmd {
|
||||
))
|
||||
}
|
||||
|
||||
#[module_command_handler(dialog_confirm, "dialog > confirm")]
|
||||
#[module_command_handler(dialog_confirm)]
|
||||
fn confirm_dialog<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
title: Option<String>,
|
||||
|
@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::{
|
||||
api::ipc::CallbackFn,
|
||||
@ -12,7 +14,7 @@ use crate::{
|
||||
Manager, Runtime,
|
||||
};
|
||||
use serde::{de::Deserializer, Deserialize};
|
||||
use tauri_macros::CommandModule;
|
||||
use tauri_macros::{command_enum, CommandModule};
|
||||
|
||||
pub struct EventId(String);
|
||||
|
||||
@ -51,6 +53,7 @@ impl<'de> Deserialize<'de> for WindowLabel {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
|
@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use crate::{
|
||||
api::{
|
||||
dir,
|
||||
@ -19,7 +21,7 @@ use serde::{
|
||||
de::{Deserializer, Error as DeError},
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::{
|
||||
@ -50,52 +52,62 @@ pub struct FileOperationOptions {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub(crate) enum Cmd {
|
||||
/// The read binary file API.
|
||||
#[cmd(fs_read_file, "fs > readFile")]
|
||||
ReadFile {
|
||||
path: SafePathBuf,
|
||||
options: Option<FileOperationOptions>,
|
||||
},
|
||||
/// The read binary file API.
|
||||
#[cmd(fs_read_file, "fs > readFile")]
|
||||
ReadTextFile {
|
||||
path: SafePathBuf,
|
||||
options: Option<FileOperationOptions>,
|
||||
},
|
||||
/// The write file API.
|
||||
#[cmd(fs_write_file, "fs > writeFile")]
|
||||
WriteFile {
|
||||
path: SafePathBuf,
|
||||
contents: Vec<u8>,
|
||||
options: Option<FileOperationOptions>,
|
||||
},
|
||||
/// The read dir API.
|
||||
#[cmd(fs_read_dir, "fs > readDir")]
|
||||
ReadDir {
|
||||
path: SafePathBuf,
|
||||
options: Option<DirOperationOptions>,
|
||||
},
|
||||
/// The copy file API.
|
||||
#[cmd(fs_copy_file, "fs > copyFile")]
|
||||
CopyFile {
|
||||
source: SafePathBuf,
|
||||
destination: SafePathBuf,
|
||||
options: Option<FileOperationOptions>,
|
||||
},
|
||||
/// The create dir API.
|
||||
#[cmd(fs_create_dir, "fs > createDir")]
|
||||
CreateDir {
|
||||
path: SafePathBuf,
|
||||
options: Option<DirOperationOptions>,
|
||||
},
|
||||
/// The remove dir API.
|
||||
#[cmd(fs_remove_dir, "fs > removeDir")]
|
||||
RemoveDir {
|
||||
path: SafePathBuf,
|
||||
options: Option<DirOperationOptions>,
|
||||
},
|
||||
/// The remove file API.
|
||||
#[cmd(fs_remove_file, "fs > removeFile")]
|
||||
RemoveFile {
|
||||
path: SafePathBuf,
|
||||
options: Option<FileOperationOptions>,
|
||||
},
|
||||
/// The rename file API.
|
||||
#[cmd(fs_rename_file, "fs > renameFile")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
RenameFile {
|
||||
old_path: SafePathBuf,
|
||||
@ -105,7 +117,7 @@ pub(crate) enum Cmd {
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(fs_read_file, "fs > readFile")]
|
||||
#[module_command_handler(fs_read_file)]
|
||||
fn read_file<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -123,7 +135,7 @@ impl Cmd {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_read_file, "fs > readFile")]
|
||||
#[module_command_handler(fs_read_file)]
|
||||
fn read_text_file<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -141,7 +153,7 @@ impl Cmd {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_write_file, "fs > writeFile")]
|
||||
#[module_command_handler(fs_write_file)]
|
||||
fn write_file<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -161,7 +173,7 @@ impl Cmd {
|
||||
.and_then(|mut f| f.write_all(&contents).map_err(|err| err.into()))
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_read_dir, "fs > readDir")]
|
||||
#[module_command_handler(fs_read_dir)]
|
||||
fn read_dir<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -184,7 +196,7 @@ impl Cmd {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_copy_file, "fs > copyFile")]
|
||||
#[module_command_handler(fs_copy_file)]
|
||||
fn copy_file<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
source: SafePathBuf,
|
||||
@ -215,7 +227,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_create_dir, "fs > createDir")]
|
||||
#[module_command_handler(fs_create_dir)]
|
||||
fn create_dir<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -244,7 +256,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_remove_dir, "fs > removeDir")]
|
||||
#[module_command_handler(fs_remove_dir)]
|
||||
fn remove_dir<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -273,7 +285,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_remove_file, "fs > removeFile")]
|
||||
#[module_command_handler(fs_remove_file)]
|
||||
fn remove_file<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: SafePathBuf,
|
||||
@ -291,7 +303,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(fs_rename_file, "fs > renameFile")]
|
||||
#[module_command_handler(fs_rename_file)]
|
||||
fn rename_file<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
old_path: SafePathBuf,
|
||||
|
@ -2,38 +2,45 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::{api::ipc::CallbackFn, Runtime};
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
#[cfg(global_shortcut_all)]
|
||||
use crate::runtime::GlobalShortcutManager;
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// Register a global shortcut.
|
||||
#[cmd(global_shortcut_all, "globalShortcut > all")]
|
||||
Register {
|
||||
shortcut: String,
|
||||
handler: CallbackFn,
|
||||
},
|
||||
/// Register a list of global shortcuts.
|
||||
#[cmd(global_shortcut_all, "globalShortcut > all")]
|
||||
RegisterAll {
|
||||
shortcuts: Vec<String>,
|
||||
handler: CallbackFn,
|
||||
},
|
||||
/// Unregister a global shortcut.
|
||||
#[cmd(global_shortcut_all, "globalShortcut > all")]
|
||||
Unregister { shortcut: String },
|
||||
/// Unregisters all registered shortcuts.
|
||||
UnregisterAll,
|
||||
/// Determines whether the given hotkey is registered or not.
|
||||
#[cmd(global_shortcut_all, "globalShortcut > all")]
|
||||
IsRegistered { shortcut: String },
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(global_shortcut_all, "globalShortcut > all")]
|
||||
#[module_command_handler(global_shortcut_all)]
|
||||
fn register<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
shortcut: String,
|
||||
@ -44,7 +51,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(global_shortcut_all, "globalShortcut > all")]
|
||||
#[module_command_handler(global_shortcut_all)]
|
||||
fn register_all<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
shortcuts: Vec<String>,
|
||||
@ -57,7 +64,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(global_shortcut_all, "globalShortcut > all")]
|
||||
#[module_command_handler(global_shortcut_all)]
|
||||
fn unregister<R: Runtime>(context: InvokeContext<R>, shortcut: String) -> super::Result<()> {
|
||||
context
|
||||
.window
|
||||
@ -68,7 +75,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(global_shortcut_all, "globalShortcut > all")]
|
||||
#[module_command_handler(global_shortcut_all)]
|
||||
fn unregister_all<R: Runtime>(context: InvokeContext<R>) -> super::Result<()> {
|
||||
context
|
||||
.window
|
||||
@ -79,7 +86,12 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(global_shortcut_all, "globalShortcut > all")]
|
||||
#[cfg(not(global_shortcut_all))]
|
||||
fn unregister_all<R: Runtime>(_: InvokeContext<R>) -> super::Result<()> {
|
||||
Err(crate::Error::ApiNotAllowlisted("globalShortcut > all".into()).into_anyhow())
|
||||
}
|
||||
|
||||
#[module_command_handler(global_shortcut_all)]
|
||||
fn is_registered<R: Runtime>(context: InvokeContext<R>, shortcut: String) -> super::Result<bool> {
|
||||
context
|
||||
.window
|
||||
@ -139,7 +151,7 @@ mod tests {
|
||||
assert!(!super::Cmd::is_registered(ctx, shortcut).unwrap());
|
||||
}
|
||||
|
||||
#[tauri_macros::module_command_test(global_shortcut_all, "globalShortcut > all")]
|
||||
#[tauri_macros::module_command_test(global_shortcut_all, "globalShortcut > all", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn unregister_all() {
|
||||
let shortcuts = vec!["CTRL+X".to_string(), "SUPER+C".to_string(), "D".to_string()];
|
||||
|
@ -2,10 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
#[cfg(http_request)]
|
||||
use std::{
|
||||
@ -20,6 +22,7 @@ type ClientBuilder = ();
|
||||
#[cfg(not(http_request))]
|
||||
type HttpRequestBuilder = ();
|
||||
#[cfg(not(http_request))]
|
||||
#[allow(dead_code)]
|
||||
type ResponseData = ();
|
||||
|
||||
type ClientId = u32;
|
||||
@ -34,15 +37,19 @@ fn clients() -> &'static ClientStore {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[cmd(async)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// Create a new HTTP client.
|
||||
#[cmd(http_request, "http > request")]
|
||||
CreateClient { options: Option<ClientBuilder> },
|
||||
/// Drop a HTTP client.
|
||||
#[cmd(http_request, "http > request")]
|
||||
DropClient { client: ClientId },
|
||||
/// The HTTP request API.
|
||||
#[cmd(http_request, "http > request")]
|
||||
HttpRequest {
|
||||
client: ClientId,
|
||||
options: Box<HttpRequestBuilder>,
|
||||
@ -50,7 +57,7 @@ pub enum Cmd {
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(http_request, "http > request")]
|
||||
#[module_command_handler(http_request)]
|
||||
async fn create_client<R: Runtime>(
|
||||
_context: InvokeContext<R>,
|
||||
options: Option<ClientBuilder>,
|
||||
@ -62,7 +69,7 @@ impl Cmd {
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
#[module_command_handler(http_request, "http > request")]
|
||||
#[module_command_handler(http_request)]
|
||||
async fn drop_client<R: Runtime>(
|
||||
_context: InvokeContext<R>,
|
||||
client: ClientId,
|
||||
@ -72,7 +79,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(http_request, "http > request")]
|
||||
#[module_command_handler(http_request)]
|
||||
async fn http_request<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
client_id: ClientId,
|
||||
@ -115,7 +122,7 @@ impl Cmd {
|
||||
mod tests {
|
||||
use super::{ClientBuilder, ClientId};
|
||||
|
||||
#[tauri_macros::module_command_test(http_request, "http > request", async)]
|
||||
#[tauri_macros::module_command_test(http_request, "http > request")]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn create_client(options: Option<ClientBuilder>) {
|
||||
assert!(crate::async_runtime::block_on(super::Cmd::create_client(
|
||||
@ -125,7 +132,7 @@ mod tests {
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
#[tauri_macros::module_command_test(http_request, "http > request", async)]
|
||||
#[tauri_macros::module_command_test(http_request, "http > request")]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn drop_client(client_id: ClientId) {
|
||||
crate::async_runtime::block_on(async move {
|
||||
|
@ -2,10 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
#[cfg(notification_all)]
|
||||
use crate::{api::notification::Notification, Env, Manager};
|
||||
@ -28,10 +30,12 @@ pub struct NotificationOptions {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// The show notification API.
|
||||
#[cmd(notification_all, "notification > all")]
|
||||
Notification { options: NotificationOptions },
|
||||
/// The request notification permission API.
|
||||
RequestNotificationPermission,
|
||||
@ -40,7 +44,7 @@ pub enum Cmd {
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(notification_all, "notification > all")]
|
||||
#[module_command_handler(notification_all)]
|
||||
fn notification<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
options: NotificationOptions,
|
||||
|
@ -2,13 +2,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use std::path::PathBuf;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
@ -19,33 +22,52 @@ pub enum Cmd {
|
||||
Tempdir,
|
||||
}
|
||||
|
||||
#[cfg(os_all)]
|
||||
impl Cmd {
|
||||
#[module_command_handler(os_all, "os > all")]
|
||||
fn platform<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
|
||||
Ok(os_platform())
|
||||
}
|
||||
|
||||
#[module_command_handler(os_all, "os > all")]
|
||||
fn version<R: Runtime>(_context: InvokeContext<R>) -> super::Result<String> {
|
||||
Ok(os_info::get().version().to_string())
|
||||
}
|
||||
|
||||
#[module_command_handler(os_all, "os > all")]
|
||||
fn os_type<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
|
||||
Ok(os_type())
|
||||
}
|
||||
|
||||
#[module_command_handler(os_all, "os > all")]
|
||||
fn arch<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
|
||||
Ok(std::env::consts::ARCH)
|
||||
}
|
||||
|
||||
#[module_command_handler(os_all, "os > all")]
|
||||
fn tempdir<R: Runtime>(_context: InvokeContext<R>) -> super::Result<PathBuf> {
|
||||
Ok(std::env::temp_dir())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(os_all))]
|
||||
impl Cmd {
|
||||
fn platform<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
|
||||
Err(crate::Error::ApiNotAllowlisted("os > all".into()).into_anyhow())
|
||||
}
|
||||
|
||||
fn version<R: Runtime>(_context: InvokeContext<R>) -> super::Result<String> {
|
||||
Err(crate::Error::ApiNotAllowlisted("os > all".into()).into_anyhow())
|
||||
}
|
||||
|
||||
fn os_type<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
|
||||
Err(crate::Error::ApiNotAllowlisted("os > all".into()).into_anyhow())
|
||||
}
|
||||
|
||||
fn arch<R: Runtime>(_context: InvokeContext<R>) -> super::Result<&'static str> {
|
||||
Err(crate::Error::ApiNotAllowlisted("os > all".into()).into_anyhow())
|
||||
}
|
||||
|
||||
fn tempdir<R: Runtime>(_context: InvokeContext<R>) -> super::Result<PathBuf> {
|
||||
Err(crate::Error::ApiNotAllowlisted("os > all".into()).into_anyhow())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(os_all)]
|
||||
fn os_type() -> &'static str {
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -55,6 +77,7 @@ fn os_type() -> &'static str {
|
||||
#[cfg(target_os = "macos")]
|
||||
return "Darwin";
|
||||
}
|
||||
|
||||
#[cfg(os_all)]
|
||||
fn os_platform() -> &'static str {
|
||||
match std::env::consts::OS {
|
||||
@ -66,23 +89,23 @@ fn os_platform() -> &'static str {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[tauri_macros::module_command_test(os_all, "os > all")]
|
||||
#[tauri_macros::module_command_test(os_all, "os > all", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn platform() {}
|
||||
|
||||
#[tauri_macros::module_command_test(os_all, "os > all")]
|
||||
#[tauri_macros::module_command_test(os_all, "os > all", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn version() {}
|
||||
|
||||
#[tauri_macros::module_command_test(os_all, "os > all")]
|
||||
#[tauri_macros::module_command_test(os_all, "os > all", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn os_type() {}
|
||||
|
||||
#[tauri_macros::module_command_test(os_all, "os > all")]
|
||||
#[tauri_macros::module_command_test(os_all, "os > all", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn arch() {}
|
||||
|
||||
#[tauri_macros::module_command_test(os_all, "os > all")]
|
||||
#[tauri_macros::module_command_test(os_all, "os > all", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn tempdir() {}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use crate::{api::path::BaseDirectory, Runtime};
|
||||
#[cfg(path_all)]
|
||||
use crate::{Env, Manager};
|
||||
@ -11,42 +13,36 @@ use std::path::{Component, Path, MAIN_SEPARATOR};
|
||||
|
||||
use super::InvokeContext;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
#[cmd(path_all, "path > all")]
|
||||
ResolvePath {
|
||||
path: String,
|
||||
directory: Option<BaseDirectory>,
|
||||
},
|
||||
Resolve {
|
||||
paths: Vec<String>,
|
||||
},
|
||||
Normalize {
|
||||
path: String,
|
||||
},
|
||||
Join {
|
||||
paths: Vec<String>,
|
||||
},
|
||||
Dirname {
|
||||
path: String,
|
||||
},
|
||||
Extname {
|
||||
path: String,
|
||||
},
|
||||
Basename {
|
||||
path: String,
|
||||
ext: Option<String>,
|
||||
},
|
||||
IsAbsolute {
|
||||
path: String,
|
||||
},
|
||||
#[cmd(path_all, "path > all")]
|
||||
Resolve { paths: Vec<String> },
|
||||
#[cmd(path_all, "path > all")]
|
||||
Normalize { path: String },
|
||||
#[cmd(path_all, "path > all")]
|
||||
Join { paths: Vec<String> },
|
||||
#[cmd(path_all, "path > all")]
|
||||
Dirname { path: String },
|
||||
#[cmd(path_all, "path > all")]
|
||||
Extname { path: String },
|
||||
#[cmd(path_all, "path > all")]
|
||||
Basename { path: String, ext: Option<String> },
|
||||
#[cmd(path_all, "path > all")]
|
||||
IsAbsolute { path: String },
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn resolve_path<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: String,
|
||||
@ -62,7 +58,7 @@ impl Cmd {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn resolve<R: Runtime>(_context: InvokeContext<R>, paths: Vec<String>) -> super::Result<PathBuf> {
|
||||
// Start with current directory then start adding paths from the vector one by one using `PathBuf.push()` which
|
||||
// will ensure that if an absolute path is encountered in the iteration, it will be used as the current full path.
|
||||
@ -77,7 +73,7 @@ impl Cmd {
|
||||
Ok(normalize_path(&path))
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn normalize<R: Runtime>(_context: InvokeContext<R>, path: String) -> super::Result<String> {
|
||||
let mut p = normalize_path_no_absolute(Path::new(&path))
|
||||
.to_string_lossy()
|
||||
@ -101,7 +97,7 @@ impl Cmd {
|
||||
)
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn join<R: Runtime>(_context: InvokeContext<R>, mut paths: Vec<String>) -> super::Result<String> {
|
||||
let path = PathBuf::from(
|
||||
paths
|
||||
@ -125,7 +121,7 @@ impl Cmd {
|
||||
Ok(if p.is_empty() { ".".into() } else { p })
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn dirname<R: Runtime>(_context: InvokeContext<R>, path: String) -> super::Result<PathBuf> {
|
||||
match Path::new(&path).parent() {
|
||||
Some(p) => Ok(p.to_path_buf()),
|
||||
@ -135,7 +131,7 @@ impl Cmd {
|
||||
}
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn extname<R: Runtime>(_context: InvokeContext<R>, path: String) -> super::Result<String> {
|
||||
match Path::new(&path)
|
||||
.extension()
|
||||
@ -148,7 +144,7 @@ impl Cmd {
|
||||
}
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn basename<R: Runtime>(
|
||||
_context: InvokeContext<R>,
|
||||
path: String,
|
||||
@ -169,7 +165,7 @@ impl Cmd {
|
||||
}
|
||||
}
|
||||
|
||||
#[module_command_handler(path_all, "path > all")]
|
||||
#[module_command_handler(path_all)]
|
||||
fn is_absolute<R: Runtime>(_context: InvokeContext<R>, path: String) -> super::Result<bool> {
|
||||
Ok(Path::new(&path).is_absolute())
|
||||
}
|
||||
|
@ -2,32 +2,41 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
#[cfg(process_relaunch)]
|
||||
use crate::Manager;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// Relaunch application
|
||||
Relaunch,
|
||||
/// Close application with provided exit_code
|
||||
#[cmd(process_exit, "process > exit")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Exit { exit_code: i32 },
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(process_relaunch, "process > relaunch")]
|
||||
#[module_command_handler(process_relaunch)]
|
||||
fn relaunch<R: Runtime>(context: InvokeContext<R>) -> super::Result<()> {
|
||||
context.window.app_handle().restart();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[module_command_handler(process_exit, "process > exit")]
|
||||
#[cfg(not(process_relaunch))]
|
||||
fn relaunch<R: Runtime>(_: InvokeContext<R>) -> super::Result<()> {
|
||||
Err(crate::Error::ApiNotAllowlisted("process > relaunch".into()).into_anyhow())
|
||||
}
|
||||
|
||||
#[module_command_handler(process_exit)]
|
||||
fn exit<R: Runtime>(_context: InvokeContext<R>, exit_code: i32) -> super::Result<()> {
|
||||
// would be great if we can have a handler inside tauri
|
||||
// who close all window and emit an event that user can catch
|
||||
@ -38,7 +47,7 @@ impl Cmd {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[tauri_macros::module_command_test(process_relaunch, "process > relaunch")]
|
||||
#[tauri_macros::module_command_test(process_relaunch, "process > relaunch", runtime)]
|
||||
#[quickcheck_macros::quickcheck]
|
||||
fn relaunch() {}
|
||||
|
||||
|
@ -2,12 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::{api::ipc::CallbackFn, Runtime};
|
||||
#[cfg(shell_scope)]
|
||||
use crate::{Manager, Scopes};
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
#[cfg(shell_scope)]
|
||||
use crate::ExecuteArgs;
|
||||
@ -55,10 +57,12 @@ pub struct CommandOptions {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// The execute script API.
|
||||
#[cmd(shell_script, "shell > execute or shell > sidecar")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Execute {
|
||||
program: String,
|
||||
@ -67,20 +71,16 @@ pub enum Cmd {
|
||||
#[serde(default)]
|
||||
options: CommandOptions,
|
||||
},
|
||||
StdinWrite {
|
||||
pid: ChildId,
|
||||
buffer: Buffer,
|
||||
},
|
||||
KillChild {
|
||||
pid: ChildId,
|
||||
},
|
||||
Open {
|
||||
path: String,
|
||||
with: Option<String>,
|
||||
},
|
||||
#[cmd(shell_script, "shell > execute or shell > sidecar")]
|
||||
StdinWrite { pid: ChildId, buffer: Buffer },
|
||||
#[cmd(shell_script, "shell > execute or shell > sidecar")]
|
||||
KillChild { pid: ChildId },
|
||||
#[cmd(shell_open, "shell > open")]
|
||||
Open { path: String, with: Option<String> },
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(shell_script)]
|
||||
#[allow(unused_variables)]
|
||||
fn execute<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
@ -169,7 +169,7 @@ impl Cmd {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(shell_execute, shell_sidecar))]
|
||||
#[module_command_handler(shell_script)]
|
||||
fn stdin_write<R: Runtime>(
|
||||
_context: InvokeContext<R>,
|
||||
pid: ChildId,
|
||||
@ -184,16 +184,7 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(any(shell_execute, shell_sidecar)))]
|
||||
fn stdin_write<R: Runtime>(
|
||||
_context: InvokeContext<R>,
|
||||
_pid: ChildId,
|
||||
_buffer: Buffer,
|
||||
) -> super::Result<()> {
|
||||
Err(crate::Error::ApiNotAllowlisted("shell > execute or shell > sidecar".into()).into_anyhow())
|
||||
}
|
||||
|
||||
#[cfg(any(shell_execute, shell_sidecar))]
|
||||
#[module_command_handler(shell_script)]
|
||||
fn kill_child<R: Runtime>(_context: InvokeContext<R>, pid: ChildId) -> super::Result<()> {
|
||||
if let Some(child) = command_childs().lock().unwrap().remove(&pid) {
|
||||
child.kill()?;
|
||||
@ -201,15 +192,10 @@ impl Cmd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(any(shell_execute, shell_sidecar)))]
|
||||
fn kill_child<R: Runtime>(_context: InvokeContext<R>, _pid: ChildId) -> super::Result<()> {
|
||||
Err(crate::Error::ApiNotAllowlisted("shell > execute or shell > sidecar".into()).into_anyhow())
|
||||
}
|
||||
|
||||
/// Open a (url) path with a default or specific browser opening program.
|
||||
///
|
||||
/// See [`crate::api::shell::open`] for how it handles security-related measures.
|
||||
#[module_command_handler(shell_open, "shell > open")]
|
||||
#[module_command_handler(shell_open)]
|
||||
fn open<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
path: String,
|
||||
|
@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use super::{InvokeContext, InvokeResponse};
|
||||
#[cfg(window_create)]
|
||||
use crate::runtime::{webview::WindowBuilder, Dispatch};
|
||||
@ -14,7 +16,7 @@ use crate::{
|
||||
CursorIcon, Icon, Manager, Runtime,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use tauri_macros::{module_command_handler, CommandModule};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
@ -168,13 +170,13 @@ impl WindowManagerCmd {
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
#[command_enum]
|
||||
#[derive(Deserialize, CommandModule)]
|
||||
#[cmd(async)]
|
||||
#[serde(tag = "cmd", content = "data", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
CreateWebview {
|
||||
options: Box<WindowConfig>,
|
||||
},
|
||||
#[cmd(window_create, "window > create")]
|
||||
CreateWebview { options: Box<WindowConfig> },
|
||||
Manage {
|
||||
label: Option<String>,
|
||||
cmd: WindowManagerCmd,
|
||||
@ -182,7 +184,7 @@ pub enum Cmd {
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
#[module_command_handler(window_create, "window > create")]
|
||||
#[module_command_handler(window_create)]
|
||||
async fn create_webview<R: Runtime>(
|
||||
context: InvokeContext<R>,
|
||||
options: Box<WindowConfig>,
|
||||
|
@ -71,11 +71,8 @@ pub enum Error {
|
||||
/// Client with specified ID not found.
|
||||
#[error("http client dropped or not initialized")]
|
||||
HttpClientNotInitialized,
|
||||
/// API not enabled by Tauri.
|
||||
#[error("{0}")]
|
||||
ApiNotEnabled(String),
|
||||
/// API not whitelisted on tauri.conf.json
|
||||
#[error("'{0}' not on the allowlist (https://tauri.studio/docs/api/config#tauri.allowlist)")]
|
||||
#[error("'{0}' not in the allowlist (https://tauri.studio/docs/api/config#tauri.allowlist)")]
|
||||
ApiNotAllowlisted(String),
|
||||
/// Invalid args when running a command.
|
||||
#[error("invalid args `{1}` for command `{0}`: {2}")]
|
||||
@ -138,6 +135,7 @@ pub(crate) fn into_anyhow<T: std::fmt::Display>(err: T) -> anyhow::Error {
|
||||
}
|
||||
|
||||
impl Error {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn into_anyhow(self) -> anyhow::Error {
|
||||
anyhow::anyhow!(self.to_string())
|
||||
}
|
||||
|
@ -35,7 +35,10 @@ async function readText(): Promise<string | null> {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: 'Clipboard',
|
||||
message: {
|
||||
cmd: 'readText'
|
||||
cmd: 'readText',
|
||||
// if data is not set, `serde` will ignore the custom deserializer
|
||||
// that is set when the API is not allowlisted
|
||||
data: null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user