Initial switch to compatibility with Tauri v2. Only event API is implemented, all other APIs have been removed. Irrelevant or deprecated documentation was removed.

This commit is contained in:
Brian Carlsen 2024-06-27 11:08:31 +02:00
parent dca9e751c5
commit 22267c5862
No known key found for this signature in database
GPG key ID: B14D281A79B2DDB7
36 changed files with 363 additions and 10251 deletions

148
Cargo.lock generated
View file

@ -163,7 +163,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -609,7 +609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e"
dependencies = [
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -639,7 +639,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -650,7 +650,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -801,7 +801,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -925,9 +925,9 @@ dependencies = [
[[package]]
name = "futures"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
@ -940,9 +940,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
@ -950,15 +950,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
@ -967,9 +967,9 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-lite"
@ -988,32 +988,32 @@ dependencies = [
[[package]]
name = "futures-macro"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
name = "futures-sink"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
@ -1714,9 +1714,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
version = "0.3.68"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
@ -1797,9 +1797,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.20"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
dependencies = [
"serde",
"value-bag",
@ -2436,7 +2436,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -2581,9 +2581,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.70"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
@ -2599,9 +2599,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
@ -2986,18 +2986,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.193"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.6.3"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9b713f70513ae1f8d92665bbbbda5c295c2cf1da5542881ae5eefe20c9af132"
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
dependencies = [
"js-sys",
"serde",
@ -3006,13 +3006,13 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.193"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -3028,13 +3028,13 @@ dependencies = [
[[package]]
name = "serde_repr"
version = "0.1.17"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -3084,7 +3084,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -3397,9 +3397,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.41"
version = "2.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
dependencies = [
"proc-macro2",
"quote",
@ -3711,18 +3711,16 @@ dependencies = [
[[package]]
name = "tauri-sys"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"futures",
"js-sys",
"log",
"semver 1.0.20",
"serde",
"serde-wasm-bindgen",
"serde_repr",
"tauri-sys",
"thiserror",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test",
@ -3838,22 +3836,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
[[package]]
name = "thiserror"
version = "1.0.50"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]
@ -4191,9 +4189,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "value-bag"
version = "1.4.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe"
checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101"
[[package]]
name = "vcpkg"
@ -4279,9 +4277,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -4289,24 +4287,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.41"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97"
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
dependencies = [
"cfg-if",
"js-sys",
@ -4316,9 +4314,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -4326,28 +4324,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.41"
version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "143ddeb4f833e2ed0d252e618986e18bfc7b0e52f2d28d77d05b2f045dd8eb61"
checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b"
dependencies = [
"console_error_panic_hook",
"js-sys",
@ -4359,13 +4357,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.41"
version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89"
checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.41",
"syn 2.0.68",
]
[[package]]

View file

@ -1,46 +1,31 @@
[package]
edition = "2021"
name = "tauri-sys"
version = "0.1.0"
version = "0.2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
futures = { version = "0.3.29", optional = true }
js-sys = "0.3.66"
log = "0.4.20"
semver = {version = "1.0.20", optional = true, features = ["serde"]}
serde = {version = "1.0.193", features = ["derive"]}
serde-wasm-bindgen = "0.6.3"
serde_repr = "0.1.17"
thiserror = "1.0.50"
url = {version = "2.5.0", optional = true, features = ["serde"]}
wasm-bindgen = "0.2.89"
wasm-bindgen-futures = "0.4.39"
futures = { version = "0.3.30", optional = true }
js-sys = "0.3.69"
log = "0.4.21"
serde = {version = "1.0.203", features = ["derive"]}
serde-wasm-bindgen = "0.6.5"
serde_repr = "0.1.19"
thiserror = "1.0.61"
wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "0.4.42"
[dev-dependencies]
tauri-sys = {path = ".", features = ["all"]}
wasm-bindgen-test = "0.3.41"
wasm-bindgen-test = "0.3.42"
[package.metadata.docs.rs]
all-features = true
[features]
all = ["app", "clipboard", "event", "fs", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path", "updater", "global_shortcut"]
app = ["dep:semver"]
clipboard = []
dialog = []
all = ["event"]
event = ["dep:futures"]
fs = []
global_shortcut = []
mocks = []
notification = []
os = []
path = []
process = []
tauri = ["dep:url"]
updater = ["dep:futures", "event"]
window = ["dep:futures", "event"]
[workspace]
members = ["examples/test", "examples/test/src-tauri"]

View file

@ -21,7 +21,8 @@
This crate is not yet published to crates.io, so you need to use it from git. You also need a global installation of [`esbuild`].
```toml
tauri-sys = { git = "https://github.com/JonasKruckenberg/tauri-sys" }
tauri-sys = { git = "https://github.com/JonasKruckenberg/tauri-sys" } // v1, main repo
tauri-sys = { git = "https://github.com/bicarlsen/tauri-sys" } // v2 branch
```
## Usage
@ -49,35 +50,24 @@ fn main() {
All modules are gated by accordingly named Cargo features. It is recommended you keep this synced with the features enabled in your [Tauri Allowlist] but no automated tool for this exists (yet).
- **all**: Enables all modules.
- **app**: Enables the `app` module.
- **clipboard**: Enables the `clipboard` module.
- **dialog**: Enables the `dialog` module.
- **event**: Enables the `event` module.
- **fs**: Enables the `fs` module.
- **mocks**: Enables the `mocks` module.
- **tauri**: Enables the `tauri` module.
## Are we Tauri yet?
These API bindings are not completely on-par with `@tauri-apps/api` yet, but here is the current status-quo:
- [x] `app`
- [ ] `cli`
- [x] `clipboard`
- [x] `dialog`
- [ ] `app`
- [ ] `core`
- [ ] `dpi`
- [x] `event`
- [x] `fs`
- [x] `global_shortcut`
- [ ] `http`
- [x] `mocks`
- [x] `notification`
- [x] `os`
- [x] `path`
- [x] `process`
- [ ] `shell`
- [x] `tauri`
- [ ] `updater`
- [x] `window`
- [ ] `image`
- [ ] `menu`
- [ ] `mocks`
- [ ] `path`
- [ ] `tray`
- [ ] `webview`
- [ ] `webviewWindow`
- [ ] `window`
The current API also very closely mirrors the JS API even though that might not be the most ergonomic choice, ideas for improving the API with quality-of-life features beyond the regular JS API interface are very welcome.

View file

@ -1,91 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/app.ts
async function getVersion() {
return invokeTauriCommand({
__tauriModule: "App",
message: {
cmd: "getAppVersion"
}
});
}
async function getName() {
return invokeTauriCommand({
__tauriModule: "App",
message: {
cmd: "getAppName"
}
});
}
async function getTauriVersion() {
return invokeTauriCommand({
__tauriModule: "App",
message: {
cmd: "getTauriVersion"
}
});
}
async function show() {
return invokeTauriCommand({
__tauriModule: "App",
message: {
cmd: "show"
}
});
}
async function hide() {
return invokeTauriCommand({
__tauriModule: "App",
message: {
cmd: "hide"
}
});
}
export {
getName,
getTauriVersion,
getVersion,
hide,
show
};

View file

@ -1,116 +0,0 @@
//! Get application metadata.
//!
//! he APIs must be added to tauri.allowlist.app in tauri.conf.json:
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "app": {
//! "all": true, // enable all app APIs
//! "show": true,
//! "hide": true
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use semver::Version;
/// Gets the application name.
///
/// # Example
///
/// ```typescript
/// import { getName } from '@tauri-apps/api/app';
/// const appName = await getName();
/// ```
#[inline(always)]
pub async fn get_name() -> crate::Result<String> {
let js_val = inner::getName().await?;
Ok(serde_wasm_bindgen::from_value(js_val)?)
}
/// Gets the application version.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::app::get_version;
///
/// let version = get_version().await;
/// ```
#[inline(always)]
pub async fn get_version() -> crate::Result<Version> {
let js_val = inner::getVersion().await?;
Ok(serde_wasm_bindgen::from_value(js_val)?)
}
/// Gets the Tauri version.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_app::app:get_tauri_version;
///
/// let version = get_tauri_version().await;
/// ```
#[inline(always)]
pub async fn get_tauri_version() -> crate::Result<Version> {
let js_val = inner::getTauriVersion().await?;
Ok(serde_wasm_bindgen::from_value(js_val)?)
}
/// Shows the application on macOS. This function does not automatically focus the apps windows.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::app::show;
///
/// show().await;
/// ```
///
/// Requires [`allowlist > app > show`](https://tauri.app/v1/api/config#appallowlistconfig.show) to be enabled.
#[inline(always)]
pub async fn show() -> crate::Result<()> {
Ok(inner::show().await?)
}
/// Hides the application on macOS.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::app::hide;
///
/// hide().await;
/// ```
///
/// Requires [`allowlist > app > hide`](https://tauri.app/v1/api/config#appallowlistconfig.hide) to be enabled.
#[inline(always)]
pub async fn hide() -> crate::Result<()> {
Ok(inner::hide().await?)
}
mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/app.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn getName() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn getTauriVersion() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn getVersion() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn hide() -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn show() -> Result<(), JsValue>;
}
}

View file

@ -1,55 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/cli.ts
async function getMatches() {
return invokeTauriCommand({
__tauriModule: "Cli",
message: {
cmd: "cliMatches"
}
});
}
export {
getMatches
};

View file

@ -1,66 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/clipboard.ts
async function writeText(text) {
return invokeTauriCommand({
__tauriModule: "Clipboard",
message: {
cmd: "writeText",
data: text
}
});
}
async function readText() {
return invokeTauriCommand({
__tauriModule: "Clipboard",
message: {
cmd: "readText",
data: null
}
});
}
export {
readText,
writeText
};

View file

@ -1,64 +0,0 @@
//! Read and write to the system clipboard.
//!
//! The APIs must be added to tauri.allowlist.clipboard in tauri.conf.json:
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "clipboard": {
//! "all": true, // enable all Clipboard APIs
//! "writeText": true,
//! "readText": true
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
/// Gets the clipboard content as plain text.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::clipboard::read_text;
///
/// let clipboard_text = read_text().await;
/// ```
///
/// Requires [`allowlist > clipboard > readText`](https://tauri.app/v1/api/config#clipboardallowlistconfig.readtext) to be enabled.
#[inline(always)]
pub async fn read_text() -> crate::Result<String> {
let js_val = inner::readText().await?;
Ok(serde_wasm_bindgen::from_value(js_val)?)
}
/// Writes plain text to the clipboard.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::clipboard::{write_text, read_text};
///
/// write_text("Tauri is awesome!").await;
/// assert_eq!(read_text().await, "Tauri is awesome!");
/// ```
///
/// Requires [`allowlist > clipboard > writeText`](https://tauri.app/v1/api/config#clipboardallowlistconfig.writetext) to be enabled.
#[inline(always)]
pub async fn write_text(text: &str) -> crate::Result<()> {
Ok(inner::writeText(text).await?)
}
mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/clipboard.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn readText() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn writeText(text: &str) -> Result<(), JsValue>;
}
}

View file

@ -1,120 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/dialog.ts
async function open(options = {}) {
if (typeof options === "object") {
Object.freeze(options);
}
return invokeTauriCommand({
__tauriModule: "Dialog",
message: {
cmd: "openDialog",
options
}
});
}
async function save(options = {}) {
if (typeof options === "object") {
Object.freeze(options);
}
return invokeTauriCommand({
__tauriModule: "Dialog",
message: {
cmd: "saveDialog",
options
}
});
}
async function message(message2, options) {
const opts = typeof options === "string" ? { title: options } : options;
return invokeTauriCommand({
__tauriModule: "Dialog",
message: {
cmd: "messageDialog",
message: message2.toString(),
title: opts?.title?.toString(),
type: opts?.type,
buttonLabel: opts?.okLabel?.toString()
}
});
}
async function ask(message2, options) {
const opts = typeof options === "string" ? { title: options } : options;
return invokeTauriCommand({
__tauriModule: "Dialog",
message: {
cmd: "askDialog",
message: message2.toString(),
title: opts?.title?.toString(),
type: opts?.type,
buttonLabels: [
opts?.okLabel?.toString() ?? "Yes",
opts?.cancelLabel?.toString() ?? "No"
]
}
});
}
async function confirm(message2, options) {
const opts = typeof options === "string" ? { title: options } : options;
return invokeTauriCommand({
__tauriModule: "Dialog",
message: {
cmd: "confirmDialog",
message: message2.toString(),
title: opts?.title?.toString(),
type: opts?.type,
buttonLabels: [
opts?.okLabel?.toString() ?? "Ok",
opts?.cancelLabel?.toString() ?? "Cancel"
]
}
});
}
export {
ask,
confirm,
message,
open,
save
};

View file

@ -1,398 +0,0 @@
//! Native system dialogs for opening and saving files.
//!
//! The APIs must be added to `tauri.allowlist.dialog` in `tauri.conf.json`:
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "dialog": {
//! "all": true, // enable all dialog APIs
//! "open": true, // enable file open API
//! "save": true // enable file save API
//! "message": true,
//! "ask": true,
//! "confirm": true
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use js_sys::Array;
use serde::Serialize;
use std::path::{Path, PathBuf};
use crate::utils::ArrayIterator;
#[derive(Debug, Clone, Copy, Hash, Serialize)]
struct DialogFilter<'a> {
extensions: &'a [&'a str],
name: &'a str,
}
/// The file dialog builder.
///
/// Constructs file picker dialogs that can select single/multiple files or directories.
#[derive(Debug, Default, Clone, Hash, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FileDialogBuilder<'a> {
default_path: Option<&'a Path>,
filters: Vec<DialogFilter<'a>>,
title: Option<&'a str>,
directory: bool,
multiple: bool,
recursive: bool,
}
impl<'a> FileDialogBuilder<'a> {
/// Gets the default file dialog builder.
pub fn new() -> Self {
Self::default()
}
/// Set starting file name or directory of the dialog.
pub fn set_default_path(&mut self, default_path: &'a Path) -> &mut Self {
self.default_path = Some(default_path);
self
}
/// If directory is true, indicates that it will be read recursively later.
/// Defines whether subdirectories will be allowed on the scope or not.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().set_recursive(true);
/// # Ok(())
/// # }
/// ```
pub fn set_recursive(&mut self, recursive: bool) -> &mut Self {
self.recursive = recursive;
self
}
/// Set the title of the dialog.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().set_title("Test Title");
/// # Ok(())
/// # }
/// ```
pub fn set_title(&mut self, title: &'a str) -> &mut Self {
self.title = Some(title);
self
}
/// Add file extension filter. Takes in the name of the filter, and list of extensions
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().add_filter("Image", &["png", "jpeg"]);
/// # Ok(())
/// # }
/// ```
pub fn add_filter(&mut self, name: &'a str, extensions: &'a [&'a str]) -> &mut Self {
self.filters.push(DialogFilter { name, extensions });
self
}
/// Add many file extension filters.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().add_filters(&[("Image", &["png", "jpeg"]),("Video", &["mp4"])]);
/// # Ok(())
/// # }
/// ```
pub fn add_filters(
&mut self,
filters: impl IntoIterator<Item = (&'a str, &'a [&'a str])>,
) -> &mut Self {
for (name, extensions) in filters.into_iter() {
self.filters.push(DialogFilter {
name: name.as_ref(),
extensions,
});
}
self
}
/// Shows the dialog to select a single file.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = FileDialogBuilder::new().pick_file().await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_file(&self) -> crate::Result<Option<PathBuf>> {
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows the dialog to select multiple files.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let files = FileDialogBuilder::new().pick_files().await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_files(&mut self) -> crate::Result<Option<impl Iterator<Item = PathBuf>>> {
self.multiple = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
if let Ok(files) = Array::try_from(raw) {
let files =
ArrayIterator::new(files).map(|raw| serde_wasm_bindgen::from_value(raw).unwrap());
Ok(Some(files))
} else {
Ok(None)
}
}
/// Shows the dialog to select a single folder.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let files = FileDialogBuilder::new().pick_folder().await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_folder(&mut self) -> crate::Result<Option<PathBuf>> {
self.directory = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows the dialog to select multiple folders.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let files = FileDialogBuilder::new().pick_folders().await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_folders(&mut self) -> crate::Result<Option<impl Iterator<Item = PathBuf>>> {
self.directory = true;
self.multiple = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
if let Ok(files) = Array::try_from(raw) {
let files =
ArrayIterator::new(files).map(|raw| serde_wasm_bindgen::from_value(raw).unwrap());
Ok(Some(files))
} else {
Ok(None)
}
}
/// Open a file/directory save dialog.
///
/// The selected path is added to the filesystem and asset protocol allowlist scopes.
/// When security is more important than the easy of use of this API, prefer writing a dedicated command instead.
///
/// Note that the allowlist scope change is not persisted, so the values are cleared when the application is restarted.
/// You can save it to the filesystem using tauri-plugin-persisted-scope.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = FileDialogBuilder::new().save().await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > save`](https://tauri.app/v1/api/config#dialogallowlistconfig.save) to be enabled.
pub async fn save(&self) -> crate::Result<Option<PathBuf>> {
let raw = inner::save(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
}
/// Types of message, ask and confirm dialogs.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
pub enum MessageDialogKind {
#[default]
#[serde(rename = "info")]
Info,
#[serde(rename = "warning")]
Warning,
#[serde(rename = "error")]
Error,
}
/// A builder for message dialogs.
#[derive(Debug, Default, Clone, Copy, Hash, Serialize)]
pub struct MessageDialogBuilder<'a> {
title: Option<&'a str>,
#[serde(rename = "type")]
kind: MessageDialogKind,
}
impl<'a> MessageDialogBuilder<'a> {
pub fn new() -> Self {
Self::default()
}
/// Set the title of the dialog.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = MessageDialogBuilder::new().set_title("Test Title");
/// # Ok(())
/// # }
/// ```
pub fn set_title(&mut self, title: &'a str) -> &mut Self {
self.title = Some(title);
self
}
/// Set the type of the dialog.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::{MessageDialogBuilder,MessageDialogKind};
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = MessageDialogBuilder::new().set_kind(MessageDialogKind::Error);
/// # Ok(())
/// # }
/// ```
pub fn set_kind(&mut self, kind: MessageDialogKind) -> &mut Self {
self.kind = kind;
self
}
/// Shows a message dialog with an `Ok` button.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = MessageDialogBuilder::new().message("Tauri is awesome").await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > message`](https://tauri.app/v1/api/config#dialogallowlistconfig.message) to be enabled.
pub async fn message(&self, message: &str) -> crate::Result<()> {
Ok(inner::message(message, serde_wasm_bindgen::to_value(&self)?).await?)
}
/// Shows a question dialog with `Yes` and `No` buttons.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let confirmation = MessageDialogBuilder::new().ask("Are you sure?").await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > ask`](https://tauri.app/v1/api/config#dialogallowlistconfig.ask) to be enabled.
pub async fn ask(&self, message: &str) -> crate::Result<bool> {
let raw = inner::ask(message, serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows a question dialog with `Ok` and `Cancel` buttons.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let confirmation = MessageDialogBuilder::new().confirm("Are you sure?").await?;
/// # Ok(())
/// # }
/// ```
///
/// Requires [`allowlist > dialog > confirm`](https://tauri.app/v1/api/config#dialogallowlistconfig.confirm) to be enabled.
pub async fn confirm(&self, message: &str) -> crate::Result<bool> {
let raw = inner::confirm(message, serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
}
mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/dialog.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn ask(message: &str, options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn confirm(message: &str, options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn open(options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn message(message: &str, option: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn save(options: JsValue) -> Result<JsValue, JsValue>;
}
}

View file

@ -1,123 +1,82 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once3 = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once3) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
// tauri/tooling/api/src/core.ts
function transformCallback(callback, once = false) {
return window.__TAURI_INTERNALS__.transformCallback(callback, once)
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
// NB: `options` ignored as not used here.
return window.__TAURI_INTERNALS__.invoke(cmd, args)
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/helpers/event.ts
// tauri/tooling/api/src/event.ts
async function _unlisten(event, eventId) {
return invokeTauriCommand({
__tauriModule: "Event",
message: {
cmd: "unlisten",
event,
eventId
}
});
await invoke('plugin:event|unlisten', {
event,
eventId
})
}
async function emit(event, windowLabel, payload) {
await invokeTauriCommand({
__tauriModule: "Event",
message: {
cmd: "emit",
event,
windowLabel,
payload
}
});
async function emit(event, payload) {
await invoke('plugin:event|emit', {
event,
payload
})
}
async function listen(event, windowLabel, handler) {
return invokeTauriCommand({
__tauriModule: "Event",
message: {
cmd: "listen",
event,
windowLabel,
handler: transformCallback(handler)
}
}).then((eventId) => {
return async () => _unlisten(event, eventId);
});
async function emitTo(
target,
event,
payload
) {
await invoke('plugin:event|emit_to', {
target,
event,
payload
})
}
async function once(event, windowLabel, handler) {
return listen(event, windowLabel, (eventData) => {
handler(eventData);
_unlisten(event, eventData.id).catch(() => {
});
});
async function listen(event, handler, options) {
const target =
typeof options?.target === 'string'
? { kind: 'AnyLabel', label: options.target }
: options?.target ?? { kind: 'Any' }
return invoke('plugin:event|listen', {
event,
target,
handler: transformCallback(handler)
}).then((eventId) => {
return async () => _unlisten(event, eventId)
})
}
async function once(event, handler, options) {
return listen(
event,
(eventData) => {
handler(eventData)
_unlisten(event, eventData.id).catch(() => { })
},
options
)
}
// tauri/tooling/api/src/event.ts
var TauriEvent = /* @__PURE__ */ ((TauriEvent2) => {
TauriEvent2["WINDOW_RESIZED"] = "tauri://resize";
TauriEvent2["WINDOW_MOVED"] = "tauri://move";
TauriEvent2["WINDOW_CLOSE_REQUESTED"] = "tauri://close-requested";
TauriEvent2["WINDOW_CREATED"] = "tauri://window-created";
TauriEvent2["WINDOW_DESTROYED"] = "tauri://destroyed";
TauriEvent2["WINDOW_FOCUS"] = "tauri://focus";
TauriEvent2["WINDOW_BLUR"] = "tauri://blur";
TauriEvent2["WINDOW_SCALE_FACTOR_CHANGED"] = "tauri://scale-change";
TauriEvent2["WINDOW_THEME_CHANGED"] = "tauri://theme-changed";
TauriEvent2["WINDOW_FILE_DROP"] = "tauri://file-drop";
TauriEvent2["WINDOW_FILE_DROP_HOVER"] = "tauri://file-drop-hover";
TauriEvent2["WINDOW_FILE_DROP_CANCELLED"] = "tauri://file-drop-cancelled";
TauriEvent2["MENU"] = "tauri://menu";
TauriEvent2["CHECK_UPDATE"] = "tauri://update";
TauriEvent2["UPDATE_AVAILABLE"] = "tauri://update-available";
TauriEvent2["INSTALL_UPDATE"] = "tauri://update-install";
TauriEvent2["STATUS_UPDATE"] = "tauri://update-status";
TauriEvent2["DOWNLOAD_PROGRESS"] = "tauri://update-download-progress";
return TauriEvent2;
TauriEvent2["WINDOW_RESIZED"] = 'tauri://resize';
TauriEvent2["WINDOW_MOVED"] = 'tauri://move';
TauriEvent2["WINDOW_CLOSE_REQUESTED"] = 'tauri://close-requested';
TauriEvent2["WINDOW_DESTROYED"] = 'tauri://destroyed';
TauriEvent2["WINDOW_FOCUS"] = 'tauri://focus';
TauriEvent2["WINDOW_BLUR"] = 'tauri://blur';
TauriEvent2["WINDOW_SCALE_FACTOR_CHANGED"] = 'tauri://scale-change';
TauriEvent2["WINDOW_THEME_CHANGED"] = 'tauri://theme-changed';
TauriEvent2["WINDOW_CREATED"] = 'tauri://window-created';
TauriEvent2["WEBVIEW_CREATED"] = 'tauri://webview-created';
TauriEvent2["DRAG"] = 'tauri://drag';
TauriEvent2["DROP"] = 'tauri://drop';
TauriEvent2["DROP_OVER"] = 'tauri://drop-over';
TauriEvent2["DROP_CANCELLED"] = 'tauri://drag-cancelled';
return TauriEvent2;
})(TauriEvent || {});
async function listen2(event, handler) {
return listen(event, null, handler);
}
async function once2(event, handler) {
return once(event, null, handler);
}
async function emit2(event, payload) {
return emit(event, void 0, payload);
}
export {
TauriEvent,
emit2 as emit,
listen2 as listen,
once2 as once
TauriEvent,
emit,
emitTo,
listen,
once
};

View file

@ -17,8 +17,22 @@ pub struct Event<T> {
pub id: f32,
/// Event payload
pub payload: T,
/// The label of the window that emitted this event
pub window_label: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(tag = "kind", content = "label")]
pub enum EventTarget {
Any,
AnyLabel(String),
App,
Window(String),
Webview(String),
WebviewWindow(String),
}
#[derive(Debug, Clone, PartialEq, Serialize)]
struct Options {
target: EventTarget,
}
/// Emits an event to the backend.
@ -46,8 +60,42 @@ pub async fn emit<T: Serialize>(event: &str, payload: &T) -> crate::Result<()> {
Ok(())
}
/// Emits an event to the backend.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::event::{EventTarget, emit_to};
/// use serde::Serialize;
///
/// #[derive(Serialize)]
/// struct Payload {
/// logged_in: bool,
/// token: String
/// }
///
/// emit_to(EventTarget::Any, "frontend-loaded", &Payload { logged_in: true, token: "authToken" }).await;
/// ```
///
/// @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
#[inline(always)]
pub async fn emit_to<T: Serialize>(
target: &EventTarget,
event: &str,
payload: &T,
) -> crate::Result<()> {
inner::emitTo(
serde_wasm_bindgen::to_value(target)?,
event,
serde_wasm_bindgen::to_value(payload)?,
)
.await?;
Ok(())
}
/// Listen to an event from the backend.
///
///
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
///
@ -56,8 +104,9 @@ pub async fn emit<T: Serialize>(event: &str, payload: &T) -> crate::Result<()> {
/// ```rust,no_run
/// use tauri_api::event::listen;
/// use web_sys::console;
/// use futures::StreamExt;
///
/// let events = listen::<String>("error");
/// let events = listen::<String>("error", EventTarget::Any);
///
/// while let Some(event) = events.next().await {
/// console::log_1(&format!("Got error in window {}, payload: {}", event.window_label, event.payload).into());
@ -73,7 +122,59 @@ where
let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let _ = tx.unbounded_send(serde_wasm_bindgen::from_value(raw).unwrap());
});
let unlisten = inner::listen(event, &closure).await?;
let unlisten = inner::listen(
event,
&closure,
serde_wasm_bindgen::to_value(&Options {
target: EventTarget::Any,
})?,
)
.await?;
closure.forget();
Ok(Listen {
rx,
unlisten: js_sys::Function::from(unlisten),
})
}
/// Listen to an event from the backend.
///
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::event::{EventTarget, listen_to};
/// use web_sys::console;
/// use futures::StreamExt;
///
/// let events = listen_to::<String>("error", EventTarget::Any);
///
/// while let Some(event) = events.next().await {
/// console::log_1(&format!("Got error in window {}, payload: {}", event.window_label, event.payload).into());
/// }
/// ```
#[inline(always)]
pub async fn listen_to<T>(
event: &str,
target: EventTarget,
) -> crate::Result<impl Stream<Item = Event<T>>>
where
T: DeserializeOwned + 'static,
{
let (tx, rx) = mpsc::unbounded::<Event<T>>();
let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let _ = tx.unbounded_send(serde_wasm_bindgen::from_value(raw).unwrap());
});
let unlisten = inner::listen(
event,
&closure,
serde_wasm_bindgen::to_value(&Options { target })?,
)
.await?;
closure.forget();
Ok(Listen {
@ -109,7 +210,7 @@ impl<T> Stream for Listen<T> {
///
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
///
///
/// # Example
///
/// ```rust,no_run
@ -122,10 +223,10 @@ impl<T> Stream for Listen<T> {
/// logged_in: bool,
/// token: String
/// }
///
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// const event = once::<LoadedPayload>("loaded").await?;
///
///
/// console::log_1!(&format!("App is loaded, loggedIn: {}, token: {}", event.payload.logged_in, event.payload.token).into());
/// # Ok(())
/// # }
@ -140,7 +241,65 @@ where
let closure: Closure<dyn FnMut(JsValue)> = Closure::once(move |raw| {
let _ = tx.send(serde_wasm_bindgen::from_value(raw).unwrap());
});
let unlisten = inner::once(event, &closure).await?;
let unlisten = inner::once(
event,
&closure,
serde_wasm_bindgen::to_value(&Options {
target: EventTarget::Any,
})?,
)
.await?;
closure.forget();
let fut = Once {
rx,
unlisten: js_sys::Function::from(unlisten),
};
fut.await
}
/// Listen to an one-off event from the backend.
///
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::event::{EventTarget, once_to};
/// use serde::Deserialize;
/// use web_sys::console;
///
/// #[derive(Deserialize)]
/// interface LoadedPayload {
/// logged_in: bool,
/// token: String
/// }
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// const event = once_to::<LoadedPayload>("loaded", EventTarget::Any).await?;
///
/// console::log_1!(&format!("App is loaded, loggedIn: {}, token: {}", event.payload.logged_in, event.payload.token).into());
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn once_to<T>(event: &str, target: EventTarget) -> crate::Result<Event<T>>
where
T: DeserializeOwned + 'static,
{
let (tx, rx) = oneshot::channel::<Event<T>>();
let closure: Closure<dyn FnMut(JsValue)> = Closure::once(move |raw| {
let _ = tx.send(serde_wasm_bindgen::from_value(raw).unwrap());
});
let unlisten = inner::once(
event,
&closure,
serde_wasm_bindgen::to_value(&Options { target })?,
)
.await?;
closure.forget();
let fut = Once {
@ -186,14 +345,18 @@ mod inner {
#[wasm_bindgen(catch)]
pub async fn emit(event: &str, payload: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn emitTo(target: JsValue, event: &str, payload: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn listen(
event: &str,
handler: &Closure<dyn FnMut(JsValue)>,
options: JsValue,
) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn once(
event: &str,
handler: &Closure<dyn FnMut(JsValue)>,
options: JsValue,
) -> Result<JsValue, JsValue>;
}
}

243
src/fs.js
View file

@ -1,243 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/fs.ts
var BaseDirectory = /* @__PURE__ */ ((BaseDirectory2) => {
BaseDirectory2[BaseDirectory2["Audio"] = 1] = "Audio";
BaseDirectory2[BaseDirectory2["Cache"] = 2] = "Cache";
BaseDirectory2[BaseDirectory2["Config"] = 3] = "Config";
BaseDirectory2[BaseDirectory2["Data"] = 4] = "Data";
BaseDirectory2[BaseDirectory2["LocalData"] = 5] = "LocalData";
BaseDirectory2[BaseDirectory2["Desktop"] = 6] = "Desktop";
BaseDirectory2[BaseDirectory2["Document"] = 7] = "Document";
BaseDirectory2[BaseDirectory2["Download"] = 8] = "Download";
BaseDirectory2[BaseDirectory2["Executable"] = 9] = "Executable";
BaseDirectory2[BaseDirectory2["Font"] = 10] = "Font";
BaseDirectory2[BaseDirectory2["Home"] = 11] = "Home";
BaseDirectory2[BaseDirectory2["Picture"] = 12] = "Picture";
BaseDirectory2[BaseDirectory2["Public"] = 13] = "Public";
BaseDirectory2[BaseDirectory2["Runtime"] = 14] = "Runtime";
BaseDirectory2[BaseDirectory2["Template"] = 15] = "Template";
BaseDirectory2[BaseDirectory2["Video"] = 16] = "Video";
BaseDirectory2[BaseDirectory2["Resource"] = 17] = "Resource";
BaseDirectory2[BaseDirectory2["App"] = 18] = "App";
BaseDirectory2[BaseDirectory2["Log"] = 19] = "Log";
BaseDirectory2[BaseDirectory2["Temp"] = 20] = "Temp";
BaseDirectory2[BaseDirectory2["AppConfig"] = 21] = "AppConfig";
BaseDirectory2[BaseDirectory2["AppData"] = 22] = "AppData";
BaseDirectory2[BaseDirectory2["AppLocalData"] = 23] = "AppLocalData";
BaseDirectory2[BaseDirectory2["AppCache"] = 24] = "AppCache";
BaseDirectory2[BaseDirectory2["AppLog"] = 25] = "AppLog";
return BaseDirectory2;
})(BaseDirectory || {});
async function readTextFile(filePath, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "readTextFile",
path: filePath,
options
}
});
}
async function readBinaryFile(filePath, options = {}) {
const arr = await invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "readFile",
path: filePath,
options
}
});
return Uint8Array.from(arr);
}
async function writeTextFile(path, contents, options) {
if (typeof options === "object") {
Object.freeze(options);
}
if (typeof path === "object") {
Object.freeze(path);
}
const file = { path: "", contents: "" };
let fileOptions = options;
if (typeof path === "string") {
file.path = path;
} else {
file.path = path.path;
file.contents = path.contents;
}
if (typeof contents === "string") {
file.contents = contents ?? "";
} else {
fileOptions = contents;
}
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "writeFile",
path: file.path,
contents: Array.from(new TextEncoder().encode(file.contents)),
options: fileOptions
}
});
}
async function writeBinaryFile(path, contents, options) {
if (typeof options === "object") {
Object.freeze(options);
}
if (typeof path === "object") {
Object.freeze(path);
}
const file = { path: "", contents: [] };
let fileOptions = options;
if (typeof path === "string") {
file.path = path;
} else {
file.path = path.path;
file.contents = path.contents;
}
if (contents && "dir" in contents) {
fileOptions = contents;
} else if (typeof path === "string") {
file.contents = contents ?? [];
}
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "writeFile",
path: file.path,
contents: Array.from(
file.contents instanceof ArrayBuffer ? new Uint8Array(file.contents) : file.contents
),
options: fileOptions
}
});
}
async function readDir(dir, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "readDir",
path: dir,
options
}
});
}
async function createDir(dir, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "createDir",
path: dir,
options
}
});
}
async function removeDir(dir, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "removeDir",
path: dir,
options
}
});
}
async function copyFile(source, destination, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "copyFile",
source,
destination,
options
}
});
}
async function removeFile(file, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "removeFile",
path: file,
options
}
});
}
async function renameFile(oldPath, newPath, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "renameFile",
oldPath,
newPath,
options
}
});
}
async function exists(path, options = {}) {
return invokeTauriCommand({
__tauriModule: "Fs",
message: {
cmd: "exists",
path,
options
}
});
}
export {
BaseDirectory,
BaseDirectory as Dir,
copyFile,
createDir,
exists,
readBinaryFile,
readDir,
readTextFile,
removeDir,
removeFile,
renameFile,
writeBinaryFile,
writeTextFile as writeFile,
writeTextFile
};

513
src/fs.rs
View file

@ -1,513 +0,0 @@
//! Access the file system.
//!
//! The APIs must be added to `tauri.allowlist.fs` in `tauri.conf.json`:
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "fs": {
//! "all": true, // enable all FS APIs
//! "readFile": true,
//! "writeFile": true,
//! "readDir": true,
//! "copyFile": true,
//! "createDir": true,
//! "removeDir": true,
//! "removeFile": true,
//! "renameFile": true,
//! "exists": true
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use crate::Error;
use js_sys::ArrayBuffer;
use serde::{Deserialize, Serialize};
use serde_repr::*;
use std::path::{Path, PathBuf};
use std::str;
#[derive(Serialize_repr, Clone, PartialEq, Eq, Debug)]
#[repr(u16)]
pub enum BaseDirectory {
Audio = 1,
Cache = 2,
Config = 3,
Data = 4,
LocalData = 5,
Desktop = 6,
Document = 7,
Download = 8,
Executable = 9,
Font = 10,
Home = 11,
Picture = 12,
Public = 13,
Runtime = 14,
Template = 15,
Video = 16,
Resource = 17,
App = 18,
Log = 19,
Temp = 20,
AppConfig = 21,
AppData = 22,
AppLocalData = 23,
AppCache = 24,
AppLog = 25,
}
#[derive(Deserialize, Clone, PartialEq, Debug)]
pub struct FileEntry {
pub path: PathBuf,
pub name: Option<String>,
pub children: Option<Vec<FileEntry>>,
}
#[derive(Serialize, Clone, PartialEq, Debug)]
struct FsDirOptions {
pub dir: Option<BaseDirectory>,
pub recursive: Option<bool>,
}
#[derive(Serialize, Clone, PartialEq, Debug)]
struct FsOptions {
pub dir: Option<BaseDirectory>,
}
#[derive(Serialize, Clone, PartialEq, Debug)]
struct FsTextFileOption {
pub contents: String,
path: PathBuf,
}
/// Copies a file to a destination.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::copy_file(source, destination, BaseDirectory::Download).expect("could not copy file");
/// ```
///
/// Requires [`allowlist > fs > copyFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn copy_file(source: &Path, destination: &Path, dir: BaseDirectory) -> crate::Result<()> {
let Some(source) = source.to_str() else {
return Err(Error::Utf8(source.to_path_buf()));
};
let Some(destination) = destination.to_str() else {
return Err(Error::Utf8(destination.to_path_buf()));
};
let raw = inner::copyFile(
source,
destination,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Creates a directory.
/// If one of the path's parent components doesn't exist the promise will be rejected.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::create_dir(dir, BaseDirectory::Download).expect("could not create directory");
/// ```
///
/// Requires [`allowlist > fs > createDir`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn create_dir(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
let recursive = Some(false);
let Some(dir) = dir.to_str() else {
return Err(Error::Utf8(dir.to_path_buf()));
};
Ok(inner::createDir(
dir,
serde_wasm_bindgen::to_value(&FsDirOptions {
dir: Some(base_dir),
recursive,
})?,
)
.await?)
}
/// Creates a directory recursively.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::create_dir_all(dir, BaseDirectory::Download).expect("could not create directory");
/// ```
///
/// Requires [`allowlist > fs > createDir`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn create_dir_all(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
let recursive = Some(true);
let Some(dir) = dir.to_str() else {
return Err(Error::Utf8(dir.to_path_buf()));
};
Ok(inner::createDir(
dir,
serde_wasm_bindgen::to_value(&FsDirOptions {
dir: Some(base_dir),
recursive,
})?,
)
.await?)
}
/// Checks if a path exists.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// let file_exists = fs::exists(path, BaseDirectory::Download).expect("could not check if path exists");
/// ```
///
/// Requires [`allowlist > fs > exists`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn exists(path: &Path, dir: BaseDirectory) -> crate::Result<bool> {
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
let raw = inner::exists(
path,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Reads a file as a byte array.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// let contents = fs::read_binary_file(filePath, BaseDirectory::Download).expect("could not read file contents");
/// ```
///
/// Requires [`allowlist > fs > readBinaryFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn read_binary_file(path: &Path, dir: BaseDirectory) -> crate::Result<Vec<u8>> {
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
let raw = inner::readBinaryFile(
path,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// List directory files.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// let files = fs::read_dir(path, BaseDirectory::Download).expect("could not read directory");
/// ```
///
/// Requires [`allowlist > fs > readDir`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn read_dir(path: &Path, dir: BaseDirectory) -> crate::Result<Vec<FileEntry>> {
let recursive = Some(false);
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
let raw = inner::readDir(
path,
serde_wasm_bindgen::to_value(&FsDirOptions {
dir: Some(dir),
recursive,
})?,
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// List directory files recursively.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// let files = fs::read_dir_all(path, BaseDirectory::Download).expect("could not read directory");
/// ```
///
/// Requires [`allowlist > fs > readDir`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn read_dir_all(path: &Path, dir: BaseDirectory) -> crate::Result<Vec<FileEntry>> {
let recursive = Some(true);
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
let raw = inner::readDir(
path,
serde_wasm_bindgen::to_value(&FsDirOptions {
dir: Some(dir),
recursive,
})?,
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Read a file as an UTF-8 encoded string.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// let contents = fs::readTextFile(path, BaseDirectory::Download).expect("could not read file as text");
/// ```
///
/// Requires [`allowlist > fs > readTextFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn read_text_file(path: &Path, dir: BaseDirectory) -> crate::Result<String> {
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
let raw = inner::readTextFile(
path,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Removes a directory.
/// If the directory is not empty the promise will be rejected.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::remove_dir(path, BaseDirectory::Download).expect("could not remove directory");
/// ```
///
/// Requires [`allowlist > fs > removeDir`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn remove_dir(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
let recursive = Some(false);
let Some(dir) = dir.to_str() else {
return Err(Error::Utf8(dir.to_path_buf()));
};
Ok(inner::removeDir(
dir,
serde_wasm_bindgen::to_value(&FsDirOptions {
dir: Some(base_dir),
recursive,
})?,
)
.await?)
}
/// Removes a directory and its contents.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::remove_dir_all(path, BaseDirectory::Download).expect("could not remove directory");
/// ```
///
/// Requires [`allowlist > fs > removeDir`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn remove_dir_all(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
let recursive = Some(true);
let Some(dir) = dir.to_str() else {
return Err(Error::Utf8(dir.to_path_buf()));
};
Ok(inner::removeDir(
dir,
serde_wasm_bindgen::to_value(&FsDirOptions {
dir: Some(base_dir),
recursive,
})?,
)
.await?)
}
/// Removes a file.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::remove_file(path, BaseDirectory::Download).expect("could not remove file");
/// ```
///
/// Requires [`allowlist > fs > removeFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn remove_file(file: &Path, dir: BaseDirectory) -> crate::Result<()> {
let Some(file) = file.to_str() else {
return Err(Error::Utf8(file.to_path_buf()));
};
Ok(inner::removeFile(
file,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?)
}
/// Renames a file.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::rename_file(old_path, new_path, BaseDirectory::Download).expect("could not rename file");
/// ```
///
/// Requires [`allowlist > fs > renameFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn rename_file(
old_path: &Path,
new_path: &Path,
dir: BaseDirectory,
) -> crate::Result<()> {
let Some(old_path) = old_path.to_str() else {
return Err(Error::Utf8(old_path.to_path_buf()));
};
let Some(new_path) = new_path.to_str() else {
return Err(Error::Utf8(new_path.to_path_buf()));
};
Ok(inner::renameFile(
old_path,
new_path,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?)
}
/// Writes a byte array content to a file.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::write_binary_file(path, contents, BaseDirectory::Download).expect("could not writes binary file");
/// ```
///
/// Requires [`allowlist > fs > writeBinaryFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn write_binary_file(
path: &Path,
contents: ArrayBuffer,
dir: BaseDirectory,
) -> crate::Result<()> {
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
Ok(inner::writeBinaryFile(
path,
contents,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?)
}
/// Writes a UTF-8 text file.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::fs;
///
/// fs::write_text_file(path, contents, BaseDirectory::Download).expect("could not writes binary file");
/// ```
///
/// Requires [`allowlist > fs > writeTextFile`](https://tauri.app/v1/api/js/fs) to be enabled.
pub async fn write_text_file(path: &Path, contents: &str, dir: BaseDirectory) -> crate::Result<()> {
let Some(path) = path.to_str() else {
return Err(Error::Utf8(path.to_path_buf()));
};
Ok(inner::writeTextFile(
path,
&contents,
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
)
.await?)
}
mod inner {
use super::ArrayBuffer;
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/fs.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn copyFile(
source: &str,
destination: &str,
options: JsValue,
) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn createDir(dir: &str, options: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn exists(path: &str, options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn readBinaryFile(filePath: &str, options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn readTextFile(filePath: &str, options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn readDir(dir: &str, options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn removeDir(dir: &str, options: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn removeFile(source: &str, options: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn renameFile(
oldPath: &str,
newPath: &str,
options: JsValue,
) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn writeBinaryFile(
filePath: &str,
contents: ArrayBuffer,
options: JsValue,
) -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
pub async fn writeTextFile(
filePath: &str,
contents: &str,
options: JsValue,
) -> Result<(), JsValue>;
}
}

View file

@ -1,97 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/globalShortcut.ts
async function register(shortcut, handler) {
return invokeTauriCommand({
__tauriModule: "GlobalShortcut",
message: {
cmd: "register",
shortcut,
handler: transformCallback(handler)
}
});
}
async function registerAll(shortcuts, handler) {
return invokeTauriCommand({
__tauriModule: "GlobalShortcut",
message: {
cmd: "registerAll",
shortcuts,
handler: transformCallback(handler)
}
});
}
async function isRegistered(shortcut) {
return invokeTauriCommand({
__tauriModule: "GlobalShortcut",
message: {
cmd: "isRegistered",
shortcut
}
});
}
async function unregister(shortcut) {
return invokeTauriCommand({
__tauriModule: "GlobalShortcut",
message: {
cmd: "unregister",
shortcut
}
});
}
async function unregisterAll() {
return invokeTauriCommand({
__tauriModule: "GlobalShortcut",
message: {
cmd: "unregisterAll"
}
});
}
export {
isRegistered,
register,
registerAll,
unregister,
unregisterAll
};

View file

@ -1,199 +0,0 @@
//! Register global shortcuts.
//!
//! ## Differences to the JavaScript API
//!
//! ## `registerAll`
//!
//! ```rust,no_run
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let shortcuts = ["CommandOrControl+Shift+C", "Ctrl+Alt+F12"];
//!
//! let streams = futures::future::try_join_all(shortcuts.map(|s| async move {
//! let stream = global_shortcut::register(s).await?;
//!
//! anyhow::Ok(stream.map(move |_| s))
//! }))
//! .await?;
//!
//! let mut events = futures::stream::select_all(streams);
//!
//! while let Some(shortcut) = events.next().await {
//! log::debug!("Shortcut {} triggered", shortcut)
//! }
//! # Ok(())
//! # }
//! ```
//!
//! The APIs must be added to tauri.allowlist.globalShortcut in tauri.conf.json:
//!
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "globalShortcut": {
//! "all": true // enable all global shortcut APIs
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use futures::{channel::mpsc, Stream, StreamExt};
use wasm_bindgen::{prelude::Closure, JsValue};
/// Determines whether the given shortcut is registered by this application or not.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::global_shortcut::is_registered;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let registered = is_registered("CommandOrControl+P").await?;
/// # Ok(())
/// # }
/// ```
pub async fn is_registered(shortcut: &str) -> crate::Result<bool> {
let raw = inner::isRegistered(shortcut).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Register a global shortcut.
///
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri_sys::global_shortcut::register;
/// use web_sys::console;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let events = register("CommandOrControl+Shift+C").await?;
///
/// while let Some(_) in events.next().await {
/// console::log_1(&"Shortcut triggered".into());
/// }
/// # Ok(())
/// # }
/// ```
pub async fn register(shortcut: &str) -> crate::Result<impl Stream<Item = ()>> {
let (tx, rx) = mpsc::unbounded();
let closure = Closure::<dyn FnMut(JsValue)>::new(move |_| {
let _ = tx.unbounded_send(());
});
inner::register(shortcut, &closure).await?;
closure.forget();
Ok(Listen {
shortcut: JsValue::from_str(shortcut),
rx,
})
}
struct Listen<T> {
pub shortcut: JsValue,
pub rx: mpsc::UnboundedReceiver<T>,
}
impl<T> Drop for Listen<T> {
fn drop(&mut self) {
log::debug!("Unregistering shortcut {:?}", self.shortcut);
inner::unregister(self.shortcut.clone());
}
}
impl<T> Stream for Listen<T> {
type Item = T;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
self.rx.poll_next_unpin(cx)
}
}
/// Register a collection of global shortcuts.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::global_shortcut::register;
/// use web_sys::console;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let events = register_all(["CommandOrControl+Shift+C", "Ctrl+Alt+F12"]).await?;
///
/// while let Some(shortcut) in events.next().await {
/// console::log_1(&format!("Shortcut {} triggered", shortcut).into());
/// }
/// # Ok(())
/// # }
/// ```
// pub async fn register_all<I>(shortcuts: impl IntoIterator<Item = &str>) -> crate::Result<impl Stream<Item = String>>
// {
// let shortcuts: Array = shortcuts.into_iter().map(JsValue::from_str).collect();
// let (tx, rx) = mpsc::unbounded::<String>();
// let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
// let _ = tx.unbounded_send(serde_wasm_bindgen::from_value(raw).unwrap());
// });
// inner::registerAll(shortcuts.clone(), &closure).await?;
// closure.forget();
// Ok(ListenAll { shortcuts, rx })
// }
// struct ListenAll<T> {
// pub shortcuts: js_sys::Array,
// pub rx: mpsc::UnboundedReceiver<T>,
// }
// impl<T> Drop for ListenAll<T> {
// fn drop(&mut self) {
// for shortcut in self.shortcuts.iter() {
// inner::unregister(shortcut);
// }
// }
// }
// impl<T> Stream for ListenAll<T> {
// type Item = T;
// fn poll_next(
// mut self: std::pin::Pin<&mut Self>,
// cx: &mut std::task::Context<'_>,
// ) -> std::task::Poll<Option<Self::Item>> {
// self.rx.poll_next_unpin(cx)
// }
// }
mod inner {
// use js_sys::Array;
use wasm_bindgen::{
prelude::{wasm_bindgen, Closure},
JsValue,
};
#[wasm_bindgen(module = "/src/globalShortcut.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn isRegistered(shortcut: &str) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn register(
shortcut: &str,
handler: &Closure<dyn FnMut(JsValue)>,
) -> Result<(), JsValue>;
// #[wasm_bindgen(catch)]
// pub async fn registerAll(
// shortcuts: Array,
// handler: &Closure<dyn FnMut(JsValue)>,
// ) -> Result<(), JsValue>;
pub fn unregister(shortcut: JsValue);
}
}

View file

@ -1,229 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/http.ts
var ResponseType = /* @__PURE__ */ ((ResponseType2) => {
ResponseType2[ResponseType2["JSON"] = 1] = "JSON";
ResponseType2[ResponseType2["Text"] = 2] = "Text";
ResponseType2[ResponseType2["Binary"] = 3] = "Binary";
return ResponseType2;
})(ResponseType || {});
async function formBody(data) {
const form = {};
const append = async (key, v) => {
if (v !== null) {
let r;
if (typeof v === "string") {
r = v;
} else if (v instanceof Uint8Array || Array.isArray(v)) {
r = Array.from(v);
} else if (v instanceof File) {
r = {
file: Array.from(new Uint8Array(await v.arrayBuffer())),
mime: v.type,
fileName: v.name
};
} else if (typeof v.file === "string") {
r = { file: v.file, mime: v.mime, fileName: v.fileName };
} else {
r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName };
}
form[String(key)] = r;
}
};
if (data instanceof FormData) {
for (const [key, value] of data) {
await append(key, value);
}
} else {
for (const [key, value] of Object.entries(data)) {
await append(key, value);
}
}
return form;
}
var Body = class {
constructor(type, payload) {
this.type = type;
this.payload = payload;
}
static form(data) {
return new Body("Form", data);
}
static json(data) {
return new Body("Json", data);
}
static text(value) {
return new Body("Text", value);
}
static bytes(bytes) {
return new Body(
"Bytes",
Array.from(bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes)
);
}
};
var Response = class {
constructor(response) {
this.url = response.url;
this.status = response.status;
this.ok = this.status >= 200 && this.status < 300;
this.headers = response.headers;
this.rawHeaders = response.rawHeaders;
this.data = response.data;
}
};
var Client = class {
constructor(id) {
this.id = id;
}
async drop() {
return invokeTauriCommand({
__tauriModule: "Http",
message: {
cmd: "dropClient",
client: this.id
}
});
}
async request(options) {
const jsonResponse = !options.responseType || options.responseType === 1 /* JSON */;
if (jsonResponse) {
options.responseType = 2 /* Text */;
}
if (options.body?.type === "Form") {
options.body.payload = await formBody(options.body.payload);
}
return invokeTauriCommand({
__tauriModule: "Http",
message: {
cmd: "httpRequest",
client: this.id,
options
}
}).then((res) => {
const response = new Response(res);
if (jsonResponse) {
try {
response.data = JSON.parse(response.data);
} catch (e) {
if (response.ok && response.data === "") {
response.data = {};
} else if (response.ok) {
throw Error(
`Failed to parse response \`${response.data}\` as JSON: ${e};
try setting the \`responseType\` option to \`ResponseType.Text\` or \`ResponseType.Binary\` if the API does not return a JSON response.`
);
}
}
return response;
}
return response;
});
}
async get(url, options) {
return this.request({
method: "GET",
url,
...options
});
}
async post(url, body, options) {
return this.request({
method: "POST",
url,
body,
...options
});
}
async put(url, body, options) {
return this.request({
method: "PUT",
url,
body,
...options
});
}
async patch(url, options) {
return this.request({
method: "PATCH",
url,
...options
});
}
async delete(url, options) {
return this.request({
method: "DELETE",
url,
...options
});
}
};
async function getClient(options) {
return invokeTauriCommand({
__tauriModule: "Http",
message: {
cmd: "createClient",
options
}
}).then((id) => new Client(id));
}
var defaultClient = null;
async function fetch(url, options) {
if (defaultClient === null) {
defaultClient = await getClient();
}
return defaultClient.request({
url,
method: options?.method ?? "GET",
...options
});
}
export {
Body,
Client,
Response,
ResponseType,
fetch,
getClient
};

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
//! Bindings to the [`Tauri API`](https://tauri.app/v1/api/js/) for projects using [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen)
//! Bindings to the [`Tauri API`](https://v2.tauri.app) for projects using [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen)
//!
//! Tauri is a framework for building tiny, blazing fast, and secure cross-platform applications.
//! Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.
@ -13,7 +13,7 @@
//!
//! ## Event Listeners
//!
//! Event Listeners, such as [`event::listen`] module or [`window::WebviewWindow::listen`],
//! Event Listeners, such as [`event::listen`] module,
//! are modeled as async streams of data using the [`futures::Stream`] trait instead of using callbacks.
//! Streams have multiple advantages over callbacks:
//!
@ -22,39 +22,6 @@
//! Streams are essentially the async equivalent of the standard [`Iterator`] and therefore expose a very similar set of combinator functions.
//! This means streams are much more versatile and ergonomic than simple callbacks.
//!
//! For example, we can use Stream combinators and various utility functions
//! to replicate the `registerAll` function that unregisters the shortcuts after 20 seconds:
//!
//! ```rust
//! use futures::{future, stream, Stream, StreamExt};
//! use std::time::Duration;
//! use tauri_sys::global_shortcut;
//!
//! async fn register_with_shortcut<'a>(
//! shortcut: &'a str,
//! ) -> anyhow::Result<impl Stream<Item = &'a str>> {
//! let stream = global_shortcut::register(shortcut).await?;
//!
//! Ok(stream.map(move |_| shortcut))
//! }
//!
//! async fn register_all() {
//! let shortcuts = ["CommandOrControl+Shift+C", "Ctrl+Alt+F12"];
//!
//! let timeout = gloo_timers::future::sleep(Duration::from_secs(20));
//!
//! // await the futures that creates the streams, exiting early if any future resolves with an error
//! let streams = future::try_join_all(shortcuts.map(register_with_shortcut)).await?;
//!
//! // combine all streams into one
//! let mut events = stream::select_all(streams).take_until(timeout);
//!
//! while let Some(shortcut) = events.next().await {
//! log::debug!("Shortcut {} triggered", shortcut);
//! }
//! }
//! ```
//!
//! #### Automatic cleanup
//!
//! Streams follow Rust's RAII idiom as they automatically clean up after themselves when being dropped.
@ -118,65 +85,39 @@
//! abort_handle.abort();
//! ```
#[cfg(feature = "app")]
pub mod app;
#[cfg(feature = "clipboard")]
pub mod clipboard;
#[cfg(feature = "dialog")]
pub mod dialog;
mod error;
#[cfg(feature = "event")]
pub mod event;
#[cfg(feature = "fs")]
pub mod fs;
#[cfg(feature = "global_shortcut")]
pub mod global_shortcut;
#[cfg(feature = "mocks")]
pub mod mocks;
#[cfg(feature = "notification")]
pub mod notification;
#[cfg(feature = "os")]
pub mod os;
#[cfg(feature = "path")]
pub mod path;
#[cfg(feature = "process")]
pub mod process;
#[cfg(feature = "tauri")]
pub mod tauri;
#[cfg(feature = "updater")]
pub mod updater;
#[cfg(feature = "window")]
pub mod window;
pub use error::Error;
pub(crate) type Result<T> = core::result::Result<T, Error>;
#[cfg(any(feature = "dialog", feature = "window"))]
pub(crate) mod utils {
pub struct ArrayIterator {
pos: u32,
arr: js_sys::Array,
}
// #[cfg(any(feature = "window"))]
// pub(crate) mod utils {
// pub struct ArrayIterator {
// pos: u32,
// arr: js_sys::Array,
// }
impl ArrayIterator {
pub fn new(arr: js_sys::Array) -> Self {
Self { pos: 0, arr }
}
}
// impl ArrayIterator {
// pub fn new(arr: js_sys::Array) -> Self {
// Self { pos: 0, arr }
// }
// }
impl Iterator for ArrayIterator {
type Item = wasm_bindgen::JsValue;
// impl Iterator for ArrayIterator {
// type Item = wasm_bindgen::JsValue;
fn next(&mut self) -> Option<Self::Item> {
let raw = self.arr.get(self.pos);
// fn next(&mut self) -> Option<Self::Item> {
// let raw = self.arr.get(self.pos);
if raw.is_undefined() {
None
} else {
self.pos += 1;
// if raw.is_undefined() {
// None
// } else {
// self.pos += 1;
Some(raw)
}
}
}
}
// Some(raw)
// }
// }
// }
// }

View file

@ -1,42 +0,0 @@
// tauri/tooling/api/src/mocks.ts
function mockIPC(cb) {
window.__TAURI_IPC__ = async ({
cmd,
callback,
error,
...args
}) => {
try {
window[`_${callback}`](await cb(cmd, args));
} catch (err) {
window[`_${error}`](err);
}
};
}
function mockWindows(current, ...additionalWindows) {
window.__TAURI_METADATA__ = {
__windows: [current, ...additionalWindows].map((label) => ({ label })),
__currentWindow: { label: current }
};
}
function mockConvertFileSrc(osName, windowsProtocolScheme = "https") {
window.__TAURI__ = window.__TAURI__ ?? {};
window.__TAURI__.convertFileSrc = function(filePath, protocol = "asset") {
const path = encodeURIComponent(filePath);
return osName === "windows" ? `${windowsProtocolScheme}://${protocol}.localhost/${path}` : `${protocol}://localhost/${path}`;
};
}
function clearMocks() {
if (window.__TAURI__?.convertFileSrc)
delete window.__TAURI__.convertFileSrc;
if (window.__TAURI_IPC__)
delete window.__TAURI_IPC__;
if (window.__TAURI_METADATA__)
delete window.__TAURI_METADATA__;
}
export {
clearMocks,
mockConvertFileSrc,
mockIPC,
mockWindows
};

View file

@ -1,67 +0,0 @@
//!
use js_sys::Array;
use wasm_bindgen::{prelude::Closure, JsValue};
/// Mocks the current window label
/// In non-tauri context it is required to call this function///before* using the `@tauri-apps/api/window` module.
///
/// This function only mocks the *presence* of a window,
/// window properties (e.g. width and height) can be mocked like regular IPC calls using the `mockIPC` function.
pub fn mock_window(current: &str) {
inner::mockWindows(current, JsValue::UNDEFINED)
}
/// Mocks many window labels.
/// In non-tauri context it is required to call this function///before* using the `@tauri-apps/api/window` module.
///
/// This function only mocks the *presence* of windows,
/// window properties (e.g. width and height) can be mocked like regular IPC calls using the `mockIPC` function.
///
/// @param current Label of window this JavaScript context is running in.
/// @param additionalWindows Label of additional windows the app has.
pub fn mock_windows(current: &str, additional_windows: &[&str]) {
inner::mockWindows(
current,
Array::from_iter(additional_windows.iter().map(|str| JsValue::from_str(str))).into(),
)
}
/// Intercepts all IPC requests with the given mock handler.
///
/// This function can be used when testing tauri frontend applications or when running the frontend in a Node.js context during static site generation.
pub fn mock_ipc<H, R, E>(mut handler: H)
where
H: FnMut(String, JsValue) -> Result<R, E> + 'static,
R: Into<JsValue>,
E: Into<JsValue>,
{
let closure = Closure::<dyn FnMut(String, JsValue) -> Result<JsValue, JsValue>>::new(
move |cmd, payload| (handler)(cmd, payload).map(Into::into).map_err(Into::into),
);
inner::mockIPC(&closure);
closure.forget();
}
/// Clears mocked functions/data injected by the other functions in this module.
/// When using a test runner that doesn't provide a fresh window object for each test, calling this function will reset tauri specific properties.
pub fn clear_mocks() {
inner::clearMocks()
}
mod inner {
use wasm_bindgen::{
prelude::{wasm_bindgen, Closure},
JsValue,
};
#[wasm_bindgen(module = "/src/mocks.js")]
extern "C" {
#[wasm_bindgen(variadic)]
pub fn mockWindows(current: &str, rest: JsValue);
pub fn mockIPC(handler: &Closure<dyn FnMut(String, JsValue) -> Result<JsValue, JsValue>>);
pub fn clearMocks();
}
}

View file

@ -1,70 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/notification.ts
async function isPermissionGranted() {
if (window.Notification.permission !== "default") {
return Promise.resolve(window.Notification.permission === "granted");
}
return invokeTauriCommand({
__tauriModule: "Notification",
message: {
cmd: "isNotificationPermissionGranted"
}
});
}
async function requestPermission() {
return window.Notification.requestPermission();
}
function sendNotification(options) {
if (typeof options === "string") {
new window.Notification(options);
} else {
new window.Notification(options.title, options);
}
}
export {
isPermissionGranted,
requestPermission,
sendNotification
};

View file

@ -1,135 +0,0 @@
//! Send toast notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.
//!
//! The APIs must be added to tauri.allowlist.notification in tauri.conf.json:
//!
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "notification": {
//! "all": true // enable all notification APIs
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use serde::{Deserialize, Serialize};
/// Checks if the permission to send notifications is granted.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::notification;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let is_granted = notification::is_permission_granted().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn is_permission_granted() -> crate::Result<bool> {
let raw = inner::isPermissionGranted().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Requests the permission to send notifications.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::notification;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let perm = notification::request_permission().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn request_permission() -> crate::Result<Permission> {
let raw = inner::requestPermission().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Possible permission values.
#[derive(Debug, Deserialize, Default, Clone, Copy, PartialEq, Eq)]
pub enum Permission {
#[default]
#[serde(rename = "default")]
Default,
#[serde(rename = "granted")]
Granted,
#[serde(rename = "denied")]
Denied,
}
/// The desktop notification definition.
///
/// Allows you to construct a Notification data and send it.
#[derive(Debug, Default, Serialize)]
pub struct Notification<'a> {
body: Option<&'a str>,
title: Option<&'a str>,
icon: Option<&'a str>,
}
impl<'a> Notification<'a> {
pub fn new() -> Self {
Self::default()
}
/// Sets the notification title.
pub fn set_title(&mut self, title: &'a str) {
self.title = Some(title);
}
/// Sets the notification body.
pub fn set_body(&mut self, body: &'a str) {
self.body = Some(body);
}
/// Sets the notification icon.
pub fn set_icon(&mut self, icon: &'a str) {
self.icon = Some(icon);
}
/// Shows the notification.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::notification::Notification;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// Notification::new()
/// .set_title("Tauri")
/// .set_body("Tauri is awesome!")
/// .show()?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub fn show(&self) -> crate::Result<()> {
inner::sendNotification(serde_wasm_bindgen::to_value(&self)?)?;
Ok(())
}
}
mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/notification.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn isPermissionGranted() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn requestPermission() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub fn sendNotification(notification: JsValue) -> Result<(), JsValue>;
}
}

107
src/os.js
View file

@ -1,107 +0,0 @@
// tauri/tooling/api/src/helpers/os-check.ts
function isWindows() {
return navigator.appVersion.includes("Win");
}
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/os.ts
var EOL = isWindows() ? "\r\n" : "\n";
async function platform() {
return invokeTauriCommand({
__tauriModule: "Os",
message: {
cmd: "platform"
}
});
}
async function version() {
return invokeTauriCommand({
__tauriModule: "Os",
message: {
cmd: "version"
}
});
}
async function type() {
return invokeTauriCommand({
__tauriModule: "Os",
message: {
cmd: "osType"
}
});
}
async function arch() {
return invokeTauriCommand({
__tauriModule: "Os",
message: {
cmd: "arch"
}
});
}
async function tempdir() {
return invokeTauriCommand({
__tauriModule: "Os",
message: {
cmd: "tempdir"
}
});
}
async function locale() {
return invokeTauriCommand({
__tauriModule: "Os",
message: {
cmd: "locale"
}
});
}
export {
EOL,
arch,
locale,
platform,
tempdir,
type,
version
};

136
src/os.rs
View file

@ -1,136 +0,0 @@
//! Provides operating system-related utility methods and properties.
//!
//! The APIs must be added to tauri.allowlist.os in tauri.conf.json:
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "os": {
//! "all": true, // enable all Os APIs
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum Arch {
#[serde(rename = "x86")]
X86,
#[serde(rename = "x86_64")]
X86_64,
#[serde(rename = "arm")]
Arm,
#[serde(rename = "aarch64")]
Aarch64,
#[serde(rename = "mips")]
Mips,
#[serde(rename = "mips64")]
Mips64,
#[serde(rename = "powerpc")]
Powerpc,
#[serde(rename = "powerpc64")]
Powerpc64,
#[serde(rename = "riscv64")]
Riscv64,
#[serde(rename = "s390x")]
S390x,
#[serde(rename = "sparc64")]
Sparc64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum Platform {
#[serde(rename = "linux")]
Linux,
#[serde(rename = "darwin")]
Darwin,
#[serde(rename = "ios")]
Ios,
#[serde(rename = "freebsd")]
Freebsd,
#[serde(rename = "dragonfly")]
Dragonfly,
#[serde(rename = "netbsd")]
Netbsd,
#[serde(rename = "openbsd")]
Openbsd,
#[serde(rename = "solaris")]
Solaris,
#[serde(rename = "android")]
Android,
#[serde(rename = "win32")]
Win32,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum OsKind {
#[serde(rename = "Linux")]
Linux,
#[serde(rename = "Darwin")]
Darwin,
#[serde(rename = "Windows_NT")]
WindowsNT,
}
/// Returns the operating system CPU architecture for which the tauri app was compiled.
#[inline(always)]
pub async fn arch() -> crate::Result<Arch> {
let raw = inner::arch().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns a string identifying the operating system platform. The value is set at compile time.
#[inline(always)]
pub async fn platform() -> crate::Result<Platform> {
let raw = inner::platform().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the operating system's default directory for temporary files.
#[inline(always)]
pub async fn tempdir() -> crate::Result<PathBuf> {
let raw = inner::tempdir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns [`OsKind::Linux`] on Linux, [`OsKind::Darwin`] on macOS, and [`OsKind::WindowsNT`] on Windows.
#[inline(always)]
pub async fn kind() -> crate::Result<OsKind> {
let raw = inner::kind().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns a string identifying the kernel version.
#[inline(always)]
pub async fn version() -> crate::Result<String> {
let raw = inner::version().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
mod inner {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "/src/os.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn arch() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn platform() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn tempdir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch, js_name = "type")]
pub async fn kind() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn version() -> Result<JsValue, JsValue>;
}
}

View file

@ -1,418 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve2, reject) => {
const callback = transformCallback((e) => {
resolve2(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/fs.ts
var BaseDirectory = /* @__PURE__ */ ((BaseDirectory2) => {
BaseDirectory2[BaseDirectory2["Audio"] = 1] = "Audio";
BaseDirectory2[BaseDirectory2["Cache"] = 2] = "Cache";
BaseDirectory2[BaseDirectory2["Config"] = 3] = "Config";
BaseDirectory2[BaseDirectory2["Data"] = 4] = "Data";
BaseDirectory2[BaseDirectory2["LocalData"] = 5] = "LocalData";
BaseDirectory2[BaseDirectory2["Desktop"] = 6] = "Desktop";
BaseDirectory2[BaseDirectory2["Document"] = 7] = "Document";
BaseDirectory2[BaseDirectory2["Download"] = 8] = "Download";
BaseDirectory2[BaseDirectory2["Executable"] = 9] = "Executable";
BaseDirectory2[BaseDirectory2["Font"] = 10] = "Font";
BaseDirectory2[BaseDirectory2["Home"] = 11] = "Home";
BaseDirectory2[BaseDirectory2["Picture"] = 12] = "Picture";
BaseDirectory2[BaseDirectory2["Public"] = 13] = "Public";
BaseDirectory2[BaseDirectory2["Runtime"] = 14] = "Runtime";
BaseDirectory2[BaseDirectory2["Template"] = 15] = "Template";
BaseDirectory2[BaseDirectory2["Video"] = 16] = "Video";
BaseDirectory2[BaseDirectory2["Resource"] = 17] = "Resource";
BaseDirectory2[BaseDirectory2["App"] = 18] = "App";
BaseDirectory2[BaseDirectory2["Log"] = 19] = "Log";
BaseDirectory2[BaseDirectory2["Temp"] = 20] = "Temp";
BaseDirectory2[BaseDirectory2["AppConfig"] = 21] = "AppConfig";
BaseDirectory2[BaseDirectory2["AppData"] = 22] = "AppData";
BaseDirectory2[BaseDirectory2["AppLocalData"] = 23] = "AppLocalData";
BaseDirectory2[BaseDirectory2["AppCache"] = 24] = "AppCache";
BaseDirectory2[BaseDirectory2["AppLog"] = 25] = "AppLog";
return BaseDirectory2;
})(BaseDirectory || {});
// tauri/tooling/api/src/helpers/os-check.ts
function isWindows() {
return navigator.appVersion.includes("Win");
}
// tauri/tooling/api/src/path.ts
async function appDir() {
return appConfigDir();
}
async function appConfigDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 21 /* AppConfig */
}
});
}
async function appDataDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 22 /* AppData */
}
});
}
async function appLocalDataDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 23 /* AppLocalData */
}
});
}
async function appCacheDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 24 /* AppCache */
}
});
}
async function audioDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 1 /* Audio */
}
});
}
async function cacheDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 2 /* Cache */
}
});
}
async function configDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 3 /* Config */
}
});
}
async function dataDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 4 /* Data */
}
});
}
async function desktopDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 6 /* Desktop */
}
});
}
async function documentDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 7 /* Document */
}
});
}
async function downloadDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 8 /* Download */
}
});
}
async function executableDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 9 /* Executable */
}
});
}
async function fontDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 10 /* Font */
}
});
}
async function homeDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 11 /* Home */
}
});
}
async function localDataDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 5 /* LocalData */
}
});
}
async function pictureDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 12 /* Picture */
}
});
}
async function publicDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 13 /* Public */
}
});
}
async function resourceDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 17 /* Resource */
}
});
}
async function resolveResource(resourcePath) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: resourcePath,
directory: 17 /* Resource */
}
});
}
async function runtimeDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 14 /* Runtime */
}
});
}
async function templateDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 15 /* Template */
}
});
}
async function videoDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 16 /* Video */
}
});
}
async function logDir() {
return appLogDir();
}
async function appLogDir() {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolvePath",
path: "",
directory: 25 /* AppLog */
}
});
}
var sep = isWindows() ? "\\" : "/";
var delimiter = isWindows() ? ";" : ":";
async function resolve(...paths) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "resolve",
paths
}
});
}
async function normalize(path) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "normalize",
path
}
});
}
async function join(...paths) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "join",
paths
}
});
}
async function dirname(path) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "dirname",
path
}
});
}
async function extname(path) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "extname",
path
}
});
}
async function basename(path, ext) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "basename",
path,
ext
}
});
}
async function isAbsolute(path) {
return invokeTauriCommand({
__tauriModule: "Path",
message: {
cmd: "isAbsolute",
path
}
});
}
export {
BaseDirectory,
appCacheDir,
appConfigDir,
appDataDir,
appDir,
appLocalDataDir,
appLogDir,
audioDir,
basename,
cacheDir,
configDir,
dataDir,
delimiter,
desktopDir,
dirname,
documentDir,
downloadDir,
executableDir,
extname,
fontDir,
homeDir,
isAbsolute,
join,
localDataDir,
logDir,
normalize,
pictureDir,
publicDir,
resolve,
resolveResource,
resourceDir,
runtimeDir,
sep,
templateDir,
videoDir
};

View file

@ -1,790 +0,0 @@
//! The path module provides utilities for working with file and directory paths.
//!
//! The APIs must be added to tauri.allowlist.path in tauri.conf.json:
//! ```json
//! {
//! "tauri": {
//! "allowlist": {
//! "path": {
//! "all": true, // enable all Path APIs
//! }
//! }
//! }
//! }
//! ```
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
use std::path::PathBuf;
use wasm_bindgen::JsValue;
/// Returns the path to the suggested directory for your app's config files.
///
/// Resolves to `${configDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::app_config_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_config_dir_path = app_config_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn app_config_dir() -> crate::Result<PathBuf> {
let raw = inner::appConfigDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the suggested directory for your app's data files.
///
/// Resolves to `${dataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::app_data_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_data_dir_path = app_data_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn app_data_dir() -> crate::Result<PathBuf> {
let raw = inner::appDataDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the suggested directory for your app's local data files.
///
/// Resolves to `${localDataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::app_local_data_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_local_data_dir_path = app_local_data_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn app_local_data_dir() -> crate::Result<PathBuf> {
let raw = inner::appLocalDataDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the suggested directory for your app's cache files.
///
/// Resolves to `${cacheDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::app_cache_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_cache_dir_path = app_cache_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn app_cache_dir() -> crate::Result<PathBuf> {
let raw = inner::appCacheDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's audio directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_MUSIC_DIR`.
/// - **macOS:** Resolves to `$HOME/Music`.
/// - **Windows:** Resolves to `{FOLDERID_Music}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::audio_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let audio_dir_path = audio_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn audio_dir() -> crate::Result<PathBuf> {
let raw = inner::audioDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's cache directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_CACHE_HOME` or `$HOME/.cache`.
/// - **macOS:** Resolves to `$HOME/Library/Caches`.
/// - **Windows:** Resolves to `{FOLDERID_LocalAppData}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::cache_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let cache_dir_path = cache_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn cache_dir() -> crate::Result<PathBuf> {
let raw = inner::cacheDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's config directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_CONFIG_HOME` or `$HOME/.config`.
/// - **macOS:** Resolves to `$HOME/Library/Application Support`.
/// - **Windows:** Resolves to `{FOLDERID_RoamingAppData}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::config_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let config_dir_path = config_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn config_dir() -> crate::Result<PathBuf> {
let raw = inner::configDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's data directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`.
/// - **macOS:** Resolves to `$HOME/Library/Application Support`.
/// - **Windows:** Resolves to `{FOLDERID_RoamingAppData}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::data_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let data_dir_path = data_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn data_dir() -> crate::Result<PathBuf> {
let raw = inner::dataDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's desktop directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DESKTOP_DIR`.
/// - **macOS:** Resolves to `$HOME/Desktop`.
/// - **Windows:** Resolves to `{FOLDERID_Desktop}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::desktop_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let desktop_dir_path = desktop_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn desktop_dir() -> crate::Result<PathBuf> {
let raw = inner::desktopDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's document directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOCUMENTS_DIR`.
/// - **macOS:** Resolves to `$HOME/Documents`.
/// - **Windows:** Resolves to `{FOLDERID_Documents}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::document_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let document_dir_path = document_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn document_dir() -> crate::Result<PathBuf> {
let raw = inner::documentDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's download directory.
///
/// #### Platform-specific
///
/// - **Linux**: Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOWNLOAD_DIR`.
/// - **macOS**: Resolves to `$HOME/Downloads`.
/// - **Windows**: Resolves to `{FOLDERID_Downloads}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::download_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let download_dir_path = download_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn download_dir() -> crate::Result<PathBuf> {
let raw = inner::downloadDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's executable directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_BIN_HOME/../bin` or `$XDG_DATA_HOME/../bin` or `$HOME/.local/bin`.
/// - **macOS:** Not supported.
/// - **Windows:** Not supported.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::executable_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let executable_dir_path = executable_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn executable_dir() -> crate::Result<PathBuf> {
let raw = inner::executableDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's font directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_DATA_HOME/fonts` or `$HOME/.local/share/fonts`.
/// - **macOS:** Resolves to `$HOME/Library/Fonts`.
/// - **Windows:** Not supported.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::font_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let font_dir_path = font_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn font_dir() -> crate::Result<PathBuf> {
let raw = inner::fontDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's home directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$HOME`.
/// - **macOS:** Resolves to `$HOME`.
/// - **Windows:** Resolves to `{FOLDERID_Profile}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::home_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let home_dir_path = home_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn home_dir() -> crate::Result<PathBuf> {
let raw = inner::homeDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's local data directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`.
/// - **macOS:** Resolves to `$HOME/Library/Application Support`.
/// - **Windows:** Resolves to `{FOLDERID_LocalAppData}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::local_data_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let local_data_dir_path = local_data_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn local_data_dir() -> crate::Result<PathBuf> {
let raw = inner::localDataDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's picture directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PICTURES_DIR`.
/// - **macOS:** Resolves to `$HOME/Pictures`.
/// - **Windows:** Resolves to `{FOLDERID_Pictures}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::picture_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let picture_dir_path = picture_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn picture_dir() -> crate::Result<PathBuf> {
let raw = inner::pictureDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's public directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PUBLICSHARE_DIR`.
/// - **macOS:** Resolves to `$HOME/Public`.
/// - **Windows:** Resolves to `{FOLDERID_Public}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::public_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let public_dir_path = public_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn public_dir() -> crate::Result<PathBuf> {
let raw = inner::publicDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the application's resource directory.
///
/// To resolve a resource path, see the [`resolve_resource`] function.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::resource_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let resource_dir_path = resource_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn resource_dir() -> crate::Result<PathBuf> {
let raw = inner::resourceDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Resolve the path to a resource file.
///
/// @param resourcePath The path to the resource.
/// Must follow the same syntax as defined in `tauri.conf.json > tauri > bundle > resources`, i.e. keeping subfolders and parent dir components (`../`).
/// @returns The full path to the resource.
///
/// ```rust,no_run
/// use tauri_sys::path::resolve_resource;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let resource_path = resolve_resource("script.sh").await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn resolve_resource(resource_path: &str) -> crate::Result<PathBuf> {
let raw = inner::resolveResource(JsValue::from_str(resource_path)).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's runtime directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `$XDG_RUNTIME_DIR`.
/// - **macOS:** Not supported.
/// - **Windows:** Not supported.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::runtime_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let runtime_dir_path = runtime_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn runtime_dir() -> crate::Result<PathBuf> {
let raw = inner::runtimeDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's template directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_TEMPLATES_DIR`.
/// - **macOS:** Not supported.
/// - **Windows:** Resolves to `{FOLDERID_Templates}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::template_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let template_dir_path = template_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn template_dir() -> crate::Result<PathBuf> {
let raw = inner::templateDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the user's video directory.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_VIDEOS_DIR`.
/// - **macOS:** Resolves to `$HOME/Movies`.
/// - **Windows:** Resolves to `{FOLDERID_Videos}`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::video_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let video_dir_path = video_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn video_dir() -> crate::Result<PathBuf> {
let raw = inner::videoDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the path to the suggested directory for your app's log files.
///
/// #### Platform-specific
///
/// - **Linux:** Resolves to `${configDir}/${bundleIdentifier}/logs`.
/// - **macOS:** Resolves to `${homeDir}/Library/Logs/{bundleIdentifier}`
/// - **Windows:** Resolves to `${configDir}/${bundleIdentifier}/logs`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::app_log_dir;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_log_dir_path = app_log_dir().await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn app_log_dir() -> crate::Result<PathBuf> {
let raw = inner::appLogDir().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Resolves a sequence of `paths` or `path` segments into an absolute path.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::{resolve, app_data_dir};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_data_dir_path = app_data_dir().await?;
///
/// let path = resolve([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn resolve(paths: impl IntoIterator<Item = &str>) -> crate::Result<PathBuf> {
let paths = paths.into_iter();
let raw = inner::resolve(serde_wasm_bindgen::to_value(&paths.collect::<Vec<_>>())?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Normalizes the given `path`, resolving `'..'` and `'.'` segments and resolve symbolic links.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::{normalize, app_data_dir};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_data_dir_path = app_data_dir().await?;
///
/// let path = normalize([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn normalize(path: &str) -> crate::Result<PathBuf> {
let raw = inner::normalize(JsValue::from_str(path)).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Joins all given `path` segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::{join, app_data_dir};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_data_dir_path = app_data_dir().await?;
///
/// let path = join([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn join(paths: impl IntoIterator<Item = &str>) -> crate::Result<PathBuf> {
let paths = paths.into_iter();
let raw = inner::join(serde_wasm_bindgen::to_value(&paths.collect::<Vec<_>>())?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the directory name of a `path`. Trailing directory separators are ignored.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::{dirname, app_data_dir};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let app_data_dir_path = app_data_dir().await?;
///
/// let dir = dirname(app_data_dir_path).await?;
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn dirname(path: &str) -> crate::Result<PathBuf> {
let raw = inner::dirname(JsValue::from_str(path)).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the extension of the `path`.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::{extname, resolve_resource};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let resource_path = await resolve_resource("app.conf").await?;
/// let ext = extname(resource_path).await?;
/// assert_eq!(ext, "conf");
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn extname(path: &str) -> crate::Result<PathBuf> {
let raw = inner::extname(JsValue::from_str(path)).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns the last portion of a `path`. Trailing directory separators are ignored.
///
/// @param ext An optional file extension to be removed from the returned path.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::{basename, resolve_resource};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let resource_path = await resolve_resource("app.conf").await?;
/// let ext = basename(resource_path).await?;
/// assert_eq!(ext, "app");
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn basename(path: &str, ext: Option<&str>) -> crate::Result<PathBuf> {
let raw = inner::basename(
JsValue::from_str(path),
ext.map(JsValue::from_str).unwrap_or(JsValue::null()),
)
.await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Returns whether the path is absolute or not.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::path::is_absolute;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// assert!(is_absolute("/home/tauri").await?);
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn is_absolute(path: &str) -> crate::Result<bool> {
let raw = inner::isAbsolute(JsValue::from_str(path)).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
mod inner {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "/src/path.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn appCacheDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn appConfigDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn appDataDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn appLocalDataDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn appLogDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn audioDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn basename(path: JsValue, ext: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn cacheDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn configDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn dataDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn desktopDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn dirname(path: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn documentDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn downloadDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn executableDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn extname(path: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn fontDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn homeDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn isAbsolute(path: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn join(paths: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn localDataDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn normalize(path: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn pictureDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn publicDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn resolve(paths: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn resolveResource(path: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn resourceDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn runtimeDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn templateDir() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn videoDir() -> Result<JsValue, JsValue>;
}
}

View file

@ -1,65 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/process.ts
async function exit(exitCode = 0) {
return invokeTauriCommand({
__tauriModule: "Process",
message: {
cmd: "exit",
exitCode
}
});
}
async function relaunch() {
return invokeTauriCommand({
__tauriModule: "Process",
message: {
cmd: "relaunch"
}
});
}
export {
exit,
relaunch
};

View file

@ -1,24 +0,0 @@
//! Perform operations on the current process.
/// Exits immediately with the given `exit_code`.
#[inline(always)]
pub async fn exit(exit_code: i32) -> ! {
inner::exit(exit_code).await;
unreachable!()
}
/// Exits the current instance of the app then relaunches it.
#[inline(always)]
pub fn relaunch() {
inner::relaunch();
}
mod inner {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "/src/process.js")]
extern "C" {
pub async fn exit(exitCode: i32);
pub fn relaunch();
}
}

View file

@ -1,230 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/shell.ts
async function execute(onEvent, program, args = [], options) {
if (typeof args === "object") {
Object.freeze(args);
}
return invokeTauriCommand({
__tauriModule: "Shell",
message: {
cmd: "execute",
program,
args,
options,
onEventFn: transformCallback(onEvent)
}
});
}
var EventEmitter = class {
constructor() {
this.eventListeners = /* @__PURE__ */ Object.create(null);
}
addListener(eventName, listener) {
return this.on(eventName, listener);
}
removeListener(eventName, listener) {
return this.off(eventName, listener);
}
on(eventName, listener) {
if (eventName in this.eventListeners) {
this.eventListeners[eventName].push(listener);
} else {
this.eventListeners[eventName] = [listener];
}
return this;
}
once(eventName, listener) {
const wrapper = (...args) => {
this.removeListener(eventName, wrapper);
listener(...args);
};
return this.addListener(eventName, wrapper);
}
off(eventName, listener) {
if (eventName in this.eventListeners) {
this.eventListeners[eventName] = this.eventListeners[eventName].filter(
(l) => l !== listener
);
}
return this;
}
removeAllListeners(event) {
if (event) {
delete this.eventListeners[event];
} else {
this.eventListeners = /* @__PURE__ */ Object.create(null);
}
return this;
}
emit(eventName, ...args) {
if (eventName in this.eventListeners) {
const listeners = this.eventListeners[eventName];
for (const listener of listeners)
listener(...args);
return true;
}
return false;
}
listenerCount(eventName) {
if (eventName in this.eventListeners)
return this.eventListeners[eventName].length;
return 0;
}
prependListener(eventName, listener) {
if (eventName in this.eventListeners) {
this.eventListeners[eventName].unshift(listener);
} else {
this.eventListeners[eventName] = [listener];
}
return this;
}
prependOnceListener(eventName, listener) {
const wrapper = (...args) => {
this.removeListener(eventName, wrapper);
listener(...args);
};
return this.prependListener(eventName, wrapper);
}
};
var Child = class {
constructor(pid) {
this.pid = pid;
}
async write(data) {
return invokeTauriCommand({
__tauriModule: "Shell",
message: {
cmd: "stdinWrite",
pid: this.pid,
buffer: typeof data === "string" ? data : Array.from(data)
}
});
}
async kill() {
return invokeTauriCommand({
__tauriModule: "Shell",
message: {
cmd: "killChild",
pid: this.pid
}
});
}
};
var Command = class extends EventEmitter {
constructor(program, args = [], options) {
super();
this.stdout = new EventEmitter();
this.stderr = new EventEmitter();
this.program = program;
this.args = typeof args === "string" ? [args] : args;
this.options = options ?? {};
}
static sidecar(program, args = [], options) {
const instance = new Command(program, args, options);
instance.options.sidecar = true;
return instance;
}
async spawn() {
return execute(
(event) => {
switch (event.event) {
case "Error":
this.emit("error", event.payload);
break;
case "Terminated":
this.emit("close", event.payload);
break;
case "Stdout":
this.stdout.emit("data", event.payload);
break;
case "Stderr":
this.stderr.emit("data", event.payload);
break;
}
},
this.program,
this.args,
this.options
).then((pid) => new Child(pid));
}
async execute() {
return new Promise((resolve, reject) => {
this.on("error", reject);
const stdout = [];
const stderr = [];
this.stdout.on("data", (line) => {
stdout.push(line);
});
this.stderr.on("data", (line) => {
stderr.push(line);
});
this.on("close", (payload) => {
resolve({
code: payload.code,
signal: payload.signal,
stdout: stdout.join("\n"),
stderr: stderr.join("\n")
});
});
this.spawn().catch(reject);
});
}
};
async function open(path, openWith) {
return invokeTauriCommand({
__tauriModule: "Shell",
message: {
cmd: "open",
path,
with: openWith
}
});
}
export {
Child,
Command,
EventEmitter,
open
};

View file

@ -1,45 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
function convertFileSrc(filePath, protocol = "asset") {
return window.__TAURI__.convertFileSrc(filePath, protocol);
}
export {
convertFileSrc,
invoke,
transformCallback
};

View file

@ -1,110 +0,0 @@
//! Invoke your custom commands.
use serde::{de::DeserializeOwned, Serialize};
use url::Url;
/// Convert a device file path to an URL that can be loaded by the webview.
///
/// Note that `asset:` and `https://asset.localhost` must be added to [`tauri.security.csp`](https://tauri.app/v1/api/config/#securityconfig.csp) in `tauri.conf.json`.
/// Example CSP value: `"csp": "default-src 'self'; img-src 'self' asset: https://asset.localhost"` to use the asset protocol on image sources.
///
/// Additionally, `asset` must be added to [`tauri.allowlist.protocol`](https://tauri.app/v1/api/config/#allowlistconfig.protocol)
/// in `tauri.conf.json` and its access scope must be defined on the `assetScope` array on the same `protocol` object.
///
/// @param filePath The file path.
/// @param protocol The protocol to use. Defaults to `asset`. You only need to set this when using a custom protocol.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::path::{app_data_dir, join};
/// use tauri_api::tauri::convert_file_src;
///
/// const app_data_dir_path = app_data_dir().await;
/// const file_path = join(app_data_dir_path, "assets/video.mp4").await;
/// const asset_url = convert_file_src(file_path);
///
/// let window = web_sys::window().expect("no global `window` exists");
/// let document = window.document().expect("should have a document on window");
///
/// // Manufacture the element we're gonna append
/// let video = document.get_element_by_id("my-video")?;
/// let source = document.create_element("source")?;
///
/// source.set_attribute("type", "video/mp4")?;
/// source.set_attribute("src", asset_url.as_str())?;
///
/// video.append_child(&val)?;
/// ```
///
/// @return the URL that can be used as source on the webview.
#[inline(always)]
pub async fn convert_file_src(file_path: &str, protocol: Option<&str>) -> crate::Result<Url> {
let js_val = inner::convertFileSrc(file_path, protocol).await?;
Ok(serde_wasm_bindgen::from_value(js_val)?)
}
/// Sends a message to the backend.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::tauri::invoke;
///
/// struct User<'a> {
/// user: &'a str,
/// password: &'a str
/// }
///
/// invoke("login", &User { user: "tauri", password: "poiwe3h4r5ip3yrhtew9ty" }).await;
/// ```
///
/// @param cmd The command name.
/// @param args The optional arguments to pass to the command.
/// @return A promise resolving or rejecting to the backend response.
#[inline(always)]
pub async fn invoke<A: Serialize, R: DeserializeOwned>(cmd: &str, args: &A) -> crate::Result<R> {
let raw = inner::invoke(cmd, serde_wasm_bindgen::to_value(args)?).await?;
serde_wasm_bindgen::from_value(raw).map_err(Into::into)
}
/// Transforms a callback function to a string identifier that can be passed to the backend.
///
/// The backend uses the identifier to `eval()` the callback.
///
/// @return A unique identifier associated with the callback function.
#[inline(always)]
pub async fn transform_callback<T: DeserializeOwned>(
callback: &dyn Fn(T),
once: bool,
) -> crate::Result<f64> {
let js_val = inner::transformCallback(
&|raw| callback(serde_wasm_bindgen::from_value(raw).unwrap()),
once,
)
.await?;
Ok(serde_wasm_bindgen::from_value(js_val)?)
}
mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/tauri.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn convertFileSrc(
filePath: &str,
protocol: Option<&str>,
) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn invoke(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn transformCallback(
callback: &dyn Fn(JsValue),
once: bool,
) -> Result<JsValue, JsValue>;
}
}

View file

@ -1,187 +0,0 @@
// tauri/tooling/api/src/tauri.ts
function uid() {
return window.crypto.getRandomValues(new Uint32Array(1))[0];
}
function transformCallback(callback, once3 = false) {
const identifier = uid();
const prop = `_${identifier}`;
Object.defineProperty(window, prop, {
value: (result) => {
if (once3) {
Reflect.deleteProperty(window, prop);
}
return callback?.(result);
},
writable: false,
configurable: true
});
return identifier;
}
async function invoke(cmd, args = {}) {
return new Promise((resolve, reject) => {
const callback = transformCallback((e) => {
resolve(e);
Reflect.deleteProperty(window, `_${error}`);
}, true);
const error = transformCallback((e) => {
reject(e);
Reflect.deleteProperty(window, `_${callback}`);
}, true);
window.__TAURI_IPC__({
cmd,
callback,
error,
...args
});
});
}
// tauri/tooling/api/src/helpers/tauri.ts
async function invokeTauriCommand(command) {
return invoke("tauri", command);
}
// tauri/tooling/api/src/helpers/event.ts
async function _unlisten(event, eventId) {
return invokeTauriCommand({
__tauriModule: "Event",
message: {
cmd: "unlisten",
event,
eventId
}
});
}
async function emit(event, windowLabel, payload) {
await invokeTauriCommand({
__tauriModule: "Event",
message: {
cmd: "emit",
event,
windowLabel,
payload
}
});
}
async function listen(event, windowLabel, handler) {
return invokeTauriCommand({
__tauriModule: "Event",
message: {
cmd: "listen",
event,
windowLabel,
handler: transformCallback(handler)
}
}).then((eventId) => {
return async () => _unlisten(event, eventId);
});
}
async function once(event, windowLabel, handler) {
return listen(event, windowLabel, (eventData) => {
handler(eventData);
_unlisten(event, eventData.id).catch(() => {
});
});
}
// tauri/tooling/api/src/event.ts
async function listen2(event, handler) {
return listen(event, null, handler);
}
async function once2(event, handler) {
return once(event, null, handler);
}
async function emit2(event, payload) {
return emit(event, void 0, payload);
}
// tauri/tooling/api/src/updater.ts
async function onUpdaterEvent(handler) {
return listen2("tauri://update-status" /* STATUS_UPDATE */, (data) => {
handler(data?.payload);
});
}
async function installUpdate() {
let unlistenerFn;
function cleanListener() {
if (unlistenerFn) {
unlistenerFn();
}
unlistenerFn = void 0;
}
return new Promise((resolve, reject) => {
function onStatusChange(statusResult) {
if (statusResult.error) {
cleanListener();
reject(statusResult.error);
return;
}
if (statusResult.status === "DONE") {
cleanListener();
resolve();
}
}
onUpdaterEvent(onStatusChange).then((fn) => {
unlistenerFn = fn;
}).catch((e) => {
cleanListener();
throw e;
});
emit2("tauri://update-install" /* INSTALL_UPDATE */).catch((e) => {
cleanListener();
throw e;
});
});
}
async function checkUpdate() {
let unlistenerFn;
function cleanListener() {
if (unlistenerFn) {
unlistenerFn();
}
unlistenerFn = void 0;
}
return new Promise((resolve, reject) => {
function onUpdateAvailable(manifest) {
cleanListener();
resolve({
manifest,
shouldUpdate: true
});
}
function onStatusChange(statusResult) {
if (statusResult.error) {
cleanListener();
reject(statusResult.error);
return;
}
if (statusResult.status === "UPTODATE") {
cleanListener();
resolve({
shouldUpdate: false
});
}
}
once2("tauri://update-available" /* UPDATE_AVAILABLE */, (data) => {
onUpdateAvailable(data?.payload);
}).catch((e) => {
cleanListener();
throw e;
});
onUpdaterEvent(onStatusChange).then((fn) => {
unlistenerFn = fn;
}).catch((e) => {
cleanListener();
throw e;
});
emit2("tauri://update" /* CHECK_UPDATE */).catch((e) => {
cleanListener();
throw e;
});
});
}
export {
checkUpdate,
installUpdate,
onUpdaterEvent
};

View file

@ -1,139 +0,0 @@
//! Customize the auto updater flow.
use futures::{Stream, channel::mpsc};
use serde::Deserialize;
use wasm_bindgen::{prelude::Closure, JsValue};
use crate::event::Listen;
#[derive(Deserialize, Debug, Clone)]
pub struct UpdateManifest {
pub body: String,
pub date: String,
pub version: String,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateResult {
pub manifest: Option<UpdateManifest>,
pub should_update: bool,
}
#[derive(Deserialize)]
struct UpdateStatusResult {
error: Option<String>,
status: UpdateStatus,
}
#[derive(Deserialize)]
pub enum UpdateStatus {
#[serde(rename = "PENDING")]
Pending,
#[serde(rename = "DONE")]
Done,
#[serde(rename = "UPTODATE")]
UpToDate,
}
/// Checks if an update is available.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::updater::check_update;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let update = check_update().await?;
/// // now run installUpdate() if needed
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn check_update() -> crate::Result<UpdateResult> {
let raw = inner::checkUpdate().await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Install the update if there's one available.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::updater::{check_update, install_update};
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let update = check_update().await?;
///
/// if update.should_update {
/// log::info("Installing update {:?}", update.manifest);
/// install_update().await?;
/// }
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn install_update() -> crate::Result<()> {
inner::installUpdate().await?;
Ok(())
}
/// Listen to an updater event.
///
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::updater::updater_events;
/// use web_sys::console;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let events = updater_events();
///
/// while let Some(event) = events.next().await {
/// console::log_1(&format!("Updater event {:?}", event).into());
/// }
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub async fn updater_events() -> crate::Result<impl Stream<Item = Result<UpdateStatus, String>>> {
let (tx, rx) = mpsc::unbounded::<Result<UpdateStatus, String>>();
let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let raw: UpdateStatusResult = serde_wasm_bindgen::from_value(raw).unwrap();
let msg = if let Some(error) = raw.error {
Err(error)
} else {
Ok(raw.status)
};
let _ = tx.unbounded_send(msg);
});
let unlisten = inner::onUpdaterEvent(&closure).await?;
closure.forget();
Ok(Listen {
rx,
unlisten: js_sys::Function::from(unlisten),
})
}
mod inner {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "/src/updater.js")]
extern "C" {
#[wasm_bindgen(catch)]
pub async fn checkUpdate() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn installUpdate() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn onUpdaterEvent(
handler: &Closure<dyn FnMut(JsValue)>,
) -> Result<JsValue, JsValue>;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff