Compare commits

..

47 Commits

Author SHA1 Message Date
github-actions[bot] 4bb51b3cc8 publish new versions (#2603)
Co-authored-by: lucasfernog <20051258+lucasfernog@users.noreply.github.com>
2025-04-18 09:04:15 -03:00
Tony c5b0f51cfd fix(updater): don't override user provided headers (#2621) 2025-04-16 23:09:49 -03:00
Patrick F. 10f9e66e32 fix(biometric) prompt for fallback credentials when enabled and biometry unavailable on iOS (fix #2632) (#2633) 2025-04-16 17:56:43 -03:00
renovate[bot] c97e9c511d chore(deps): update tauri monorepo to v2.5.0 (v2) (#2634)
* chore(deps): update tauri monorepo to v2.5.0

* Update rust dependency and re-build iifes

* Downgrade for msrv

don't know why MSRV-aware resolver didn't work

* Downgrade cargo_metadata

* Downgrade home

* Downgrade native-tls

* trigger ci?

* Downgrade colored and base64ct

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-04-16 10:27:20 +08:00
renovate[bot] 60075f0fb6 chore(deps): update dependency typescript-eslint to v8.30.1 (#2630)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 09:24:39 +08:00
Merlin Gough f81e8003c0 chore(notifications): regen lockfile bumping notify-rust to 4.11.7 (#2623) 2025-04-14 14:47:02 +02:00
Lucas Fernandes Nogueira 686a839c96 fix(log): iOS simulator freezes when calling os_log too early (#2626)
let's delay logs on simulator to prevent deadlocks - looks like the logging system isn't available when the Rust process starts, and it's freezing the app (simulator only)

closes https://github.com/tauri-apps/tauri/issues/12172
2025-04-12 12:50:18 -03:00
renovate[bot] db7baff3fc chore(deps): update dependency rollup to v4.40.0 (#2627)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 17:46:15 +08:00
Lucas Fernandes Nogueira c9b21f6f43 fix(log): export the LogLevel type (#2625)
* fix(log): export the LogLevel type

`LogLevel` is an argument of the log functions but it's incorrectly not exported

* rebuild
2025-04-11 20:35:05 -03:00
dependabot[bot] c698e72594 chore(deps): bump crossbeam-channel (#2616)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 16:53:39 +02:00
renovate[bot] 4ec8716155 chore(deps): update dependency eslint-config-prettier to v10.1.2 (v2) (#2611)
* chore(deps): update dependency eslint-config-prettier to v10.1.2

* Bump vite

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-04-10 19:22:11 +08:00
Tony 2445e103f2 refactor(log): use time macro (#2604) 2025-04-08 20:01:11 +08:00
Tony 4cd625049d docs: fix log targets docs (#2602)
* docs: fix log targets docs

* replace(s)
2025-04-08 20:00:59 +08:00
renovate[bot] d88387ace6 chore(deps): update dependency typescript-eslint to v8.29.1 (#2606)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 11:25:39 +08:00
renovate[bot] ba611e4341 chore(deps): update rust crate tokio to v1.43.1 [security] (#2607)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 09:35:39 +08:00
Jim 60fc35d35c Support emitting traces behind feature flag (#2576)
* Let logging be skippable so user can handle logger()

* Add changes file

* changes meta info

* Update documentation

* Support emitting to tracing behind feature flag

* typo

* rename key_values => kv

* changes file

* Remove rebase skip-logger

* fix format
2025-04-07 10:33:52 +08:00
TATSUNO “Taz” Yasuhiro 9629c2f4f9 [v2][log]: Add generic fern::Dispatch TargetKind to log (#2600)
* [v2][log]: Add generic fern::Dispatch TargetKind to log

Original: https://github.com/tauri-apps/plugins-workspace/pull/1130/commits/b691382d1ea54733ca837995cfac9f82ea05f168

* Add change file

* clippy

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
Co-authored-by: venkr <venkateshrameshkumar+1@gmail.com>
2025-04-07 10:13:17 +08:00
East Monster 🍉 d1609913be docs: acces -> access typo (#2599) 2025-04-05 10:39:58 +08:00
renovate[bot] c2fd60ab3f chore(deps): update eslint monorepo to v9.24.0 (#2596)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 10:25:56 +08:00
dependabot[bot] 996975ce52 chore(deps): bump openssl (#2595)
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.70 to 0.10.72.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.70...openssl-v0.10.72)

---
updated-dependencies:
- dependency-name: openssl
  dependency-version: 0.10.72
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-05 10:06:48 +08:00
renovate[bot] 20770a96ae chore(deps): update dependency typescript to v5.8.3 (#2597)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 10:05:19 +08:00
renovate[bot] efe3f88acd chore(deps): update dependency rollup to v4.39.0 (#2590)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 17:18:15 +08:00
github-actions[bot] 8b39aefb1b publish new versions (#2545)
Co-authored-by: lucasfernog <20051258+lucasfernog@users.noreply.github.com>
2025-04-02 00:31:52 -03:00
Lucas Nogueira beab018b21 fix: remove packageManager field from package.json 2025-04-02 00:27:37 -03:00
Tillmann 9cf0390a52 Merge commit from fork
* fix(shell): properly validate open scope

* change empty regex to an impossible match

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Co-authored-by: Chip Reed <chip@chip.sh>
2025-04-02 00:24:25 -03:00
renovate[bot] 4dd5c51436 chore(deps): update tauri monorepo to v2.4.1 (v2) (#2589)
* chore(deps): update tauri monorepo to v2.4.1

* Update tauri and regenerate command ref and schema

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-04-02 09:37:19 +08:00
Tony d2aef2fddb chore(process): use request_restart (#2581) 2025-04-01 22:17:23 +08:00
renovate[bot] 02e886b21a chore(deps): update dependency vite to v6.2.4 [security] (#2585)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 08:58:54 +08:00
renovate[bot] d78930cdd4 chore(deps): update dependency typescript-eslint to v8.29.0 (#2586)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 08:58:34 +08:00
Tony a35fea5015 fix(window-state): window size jump on multi monitor setup (#2583)
* fix: window size jump on multi monitor setup

* Add change file
2025-03-31 22:34:57 +08:00
Tony a77b1353e9 refactor(window-state): simply some code (#2578) 2025-03-30 00:31:54 +08:00
renovate[bot] 6fa388d0b2 chore(deps): update dependency rollup to v4.38.0 (#2577)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-29 15:16:09 +08:00
Tony 2d731f8022 fix(updater): format Update.date to RFC 3339 (#2573)
* fix(updater): format `Update.date` to RFC 3339

* Messed up on argument in #2572

* Format

* Update example

* Avoid extra to_string

* Deprecate `Update.available`
2025-03-29 08:36:50 +08:00
Tony 0bc5d58874 fix(updater): download reuses check's timeout (#2572)
* fix(updater): download inherit timeout from check

* Add change file
2025-03-28 18:53:49 +08:00
renovate[bot] 517a29a1a1 chore(deps): update dependency vite to v6.2.3 [security] (#2570)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 23:19:24 +08:00
Tony 8ecb418a1a feat(auto-start): introduce a builder (#2569)
* feat(auto-start): introduce a builder

* Update examples

* Fix missing end --- in change file

* Fix missing self.

* Update .changes/autostart-builder.md

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>

---------

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
2025-03-25 22:57:40 +08:00
renovate[bot] 286e3c6252 chore(deps): update dependency typescript-eslint to v8.28.0 (#2567)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 10:04:19 +08:00
renovate[bot] 174b31b8b1 chore(deps): update dependency rollup to v4.37.0 (#2565)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 09:44:35 +08:00
renovate[bot] 35c1cd9aa5 chore(deps): update eslint monorepo to v9.23.0 (#2559)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 10:34:32 +08:00
Teddy Byron 37c0477afe feat(http): add zstd support (#2561) 2025-03-22 03:26:57 +02:00
Tim Ramage 831c35ff39 fix(fs): convert async iterator syntax to manual read (#2550) 2025-03-21 09:19:50 +02:00
renovate[bot] a9cbefc910 chore(deps): update tauri monorepo to v2.4.0 (v2) (#2555)
* chore(deps): update tauri monorepo to v2.4.0

* Bump tauri rust crates in lock file

* Re-generate window-state api-iife.js

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-03-21 11:16:29 +08:00
renovate[bot] 43f0f95da6 chore(deps): update dependency typescript-eslint to v8.27.0 (#2551)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 14:18:34 +08:00
Tony 38deef43dc fix(deep-link): local machine registry handling (#2483)
* fix(deep-link): local machine registry handling

* typo

* Wrong version bump

* return false if registry open fails

---------

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
2025-03-18 09:18:43 -03:00
renovate[bot] c245f123ea chore(deps): update rust crate zip to v2.3.0 [security] (#2547)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 11:36:35 +08:00
renovate[bot] 8c540d54a1 chore(deps): update dependency rollup to v4.36.0 (#2543)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 19:35:52 +08:00
Amr Bashir 9ebbfb2e3c feat(http): persist cookies on disk (#1978)
* enhance(http): persist cookies on disk

closes tauri-apps/tauri#11518

* clippy

* inline reqwest_cookie_store to fix clippy

* clippy

* Update .changes/persist-cookies.md

* Update plugins/http/src/reqwest_cookie_store.rs

* update example

* fallback to empty store if failed to load

* fix example

* persist cookies immediately

* clone

* lint

* .cookies filename

* prevent race condition

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-17 07:26:42 -03:00
141 changed files with 3820 additions and 2598 deletions
Generated
+1104 -1037
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -1,5 +1,24 @@
# Changelog
## \[2.0.21]
### Dependencies
- Upgraded to `log-js@2.4.0`
- Upgraded to `biometric-js@2.2.1`
- Upgraded to `updater-js@2.7.1`
## \[2.0.20]
### Dependencies
- Upgraded to `http-js@2.4.3`
- Upgraded to `shell-js@2.2.1`
- Upgraded to `fs-js@2.2.1`
- Upgraded to `process-js@2.2.1`
- Upgraded to `updater-js@2.7.0`
- Upgraded to `dialog-js@2.2.1`
## \[2.0.19]
### Dependencies
+11 -11
View File
@@ -1,7 +1,7 @@
{
"name": "api",
"private": true,
"version": "2.0.19",
"version": "2.0.21",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -10,35 +10,35 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.3.0",
"@tauri-apps/api": "2.5.0",
"@tauri-apps/plugin-barcode-scanner": "^2.2.0",
"@tauri-apps/plugin-biometric": "^2.2.0",
"@tauri-apps/plugin-biometric": "^2.2.1",
"@tauri-apps/plugin-cli": "^2.2.0",
"@tauri-apps/plugin-clipboard-manager": "^2.2.2",
"@tauri-apps/plugin-dialog": "^2.2.0",
"@tauri-apps/plugin-fs": "^2.2.0",
"@tauri-apps/plugin-dialog": "^2.2.1",
"@tauri-apps/plugin-fs": "^2.2.1",
"@tauri-apps/plugin-geolocation": "^2.2.0",
"@tauri-apps/plugin-global-shortcut": "^2.2.0",
"@tauri-apps/plugin-haptics": "^2.2.0",
"@tauri-apps/plugin-http": "^2.4.2",
"@tauri-apps/plugin-http": "^2.4.3",
"@tauri-apps/plugin-nfc": "^2.2.0",
"@tauri-apps/plugin-notification": "^2.2.2",
"@tauri-apps/plugin-opener": "^2.2.6",
"@tauri-apps/plugin-os": "^2.2.1",
"@tauri-apps/plugin-process": "^2.2.0",
"@tauri-apps/plugin-shell": "^2.2.0",
"@tauri-apps/plugin-process": "^2.2.1",
"@tauri-apps/plugin-shell": "^2.2.1",
"@tauri-apps/plugin-store": "^2.2.0",
"@tauri-apps/plugin-updater": "^2.6.1",
"@tauri-apps/plugin-updater": "^2.7.1",
"@zerodevx/svelte-json-view": "1.0.11"
},
"devDependencies": {
"@iconify-json/codicon": "^1.2.12",
"@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tauri-apps/cli": "2.3.1",
"@tauri-apps/cli": "2.5.0",
"@unocss/extractor-svelte": "^66.0.0",
"svelte": "^5.20.4",
"unocss": "^66.0.0",
"vite": "^6.2.0"
"vite": "^6.2.6"
}
}
+19
View File
@@ -1,5 +1,24 @@
# Changelog
## \[2.0.25]
### Dependencies
- Upgraded to `log@2.4.0`
- Upgraded to `biometric@2.2.1`
- Upgraded to `updater@2.7.1`
## \[2.0.24]
### Dependencies
- Upgraded to `http@2.4.3`
- Upgraded to `shell@2.2.1`
- Upgraded to `fs@2.2.1`
- Upgraded to `process@2.2.1`
- Upgraded to `updater@2.7.0`
- Upgraded to `dialog@2.2.1`
## \[2.0.23]
### Dependencies
+11 -9
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.23"
version = "2.0.25"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -18,23 +18,25 @@ tauri-build = { workspace = true, features = ["codegen", "isolation"] }
serde_json = { workspace = true }
serde = { workspace = true }
tiny_http = "0.12"
time = "0.3"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.3.1" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.0", features = [
tauri-plugin-log = { path = "../../../plugins/log", version = "2.4.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.1", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.2.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.2.0" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.2.1" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
], version = "2.4.2" }
"cookies",
], version = "2.4.3" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.2.2", features = [
"windows7-compat",
] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.2.1" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.2.0" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.2.1" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.2.6" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.0" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.1" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.2.0" }
[dependencies.tauri]
@@ -53,13 +55,13 @@ features = [
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.2.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.2.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.6.1" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.7.1" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.2.0" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.2.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.2.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.2.1" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.2.4" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.2.4" }
@@ -53,7 +53,7 @@
}
]
},
"shell:allow-open",
"shell:default",
"shell:allow-kill",
"shell:allow-stdin-write",
"process:allow-exit",
+20 -1
View File
@@ -102,9 +102,28 @@ pub fn run() {
if let Ok(mut request) = server.recv() {
let mut body = Vec::new();
let _ = request.as_reader().read_to_end(&mut body);
let mut headers = request.headers().to_vec();
if !headers.iter().any(|header| header.field == tiny_http::HeaderField::from_bytes(b"Cookie").unwrap()) {
let expires = time::OffsetDateTime::now_utc() + time::Duration::days(1);
// RFC 1123 format
let format = time::macros::format_description!(
"[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second] GMT"
);
let expires_str = expires.format(format).unwrap();
headers.push(
tiny_http::Header::from_bytes(
&b"Set-Cookie"[..],
format!("session-token=test-value; Secure; Path=/; Expires={expires_str}")
.as_bytes(),
)
.unwrap(),
);
}
let response = tiny_http::Response::new(
tiny_http::StatusCode(200),
request.headers().to_vec(),
headers,
std::io::Cursor::new(body),
request.body_length(),
None,
+7 -3
View File
@@ -12,10 +12,14 @@
isChecking = true
try {
const update = await check()
onMessage(`Should update: ${update.available}`)
onMessage(update)
if (update) {
onMessage(`Should update: ${update.available}`)
onMessage(update)
newUpdate = update
newUpdate = update
} else {
onMessage('No update available')
}
} catch (e) {
onMessage(e)
} finally {
+6 -6
View File
@@ -11,19 +11,19 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev"
},
"devDependencies": {
"@eslint/js": "9.22.0",
"@eslint/js": "9.24.0",
"@rollup/plugin-node-resolve": "16.0.1",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "12.1.2",
"covector": "^0.12.4",
"eslint": "9.22.0",
"eslint-config-prettier": "10.1.1",
"eslint": "9.24.0",
"eslint-config-prettier": "10.1.2",
"eslint-plugin-security": "3.0.1",
"prettier": "3.5.3",
"rollup": "4.35.0",
"rollup": "4.40.0",
"tslib": "2.8.1",
"typescript": "5.8.2",
"typescript-eslint": "8.26.1"
"typescript": "5.8.3",
"typescript-eslint": "8.30.1"
},
"pnpm": {
"overrides": {
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.3.0]
- [`8ecb418a`](https://github.com/tauri-apps/plugins-workspace/commit/8ecb418a1a35d7f234dc5d833746ac2d8e062aec) ([#2569](https://github.com/tauri-apps/plugins-workspace/pull/2569)) Add a `Builder` for more flexible settings
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-autostart"
version = "2.2.0"
version = "2.3.0"
description = "Automatically launch your application at startup."
authors = { workspace = true }
license = { workspace = true }
+1 -3
View File
@@ -57,11 +57,9 @@ First you need to register the core plugin with Tauri:
`src-tauri/src/lib.rs`
```rust
use tauri_plugin_autostart::MacosLauncher;
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec!["--flag1", "--flag2"]) /* arbitrary number of args to pass to your app */))
.plugin(tauri_plugin_autostart::Builder::new().args((["--flag1", "--flag2"])).build()))
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-autostart",
"version": "2.2.0",
"version": "2.3.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -11,6 +11,8 @@ disable the automatic start on boot.
#### This default permission set includes the following:
- `allow-enable`
- `allow-disable`
- `allow-is-enabled`
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,37 +297,44 @@
{
"description": "Enables the disable command without any pre-configured scope.",
"type": "string",
"const": "allow-disable"
"const": "allow-disable",
"markdownDescription": "Enables the disable command without any pre-configured scope."
},
{
"description": "Denies the disable command without any pre-configured scope.",
"type": "string",
"const": "deny-disable"
"const": "deny-disable",
"markdownDescription": "Denies the disable command without any pre-configured scope."
},
{
"description": "Enables the enable command without any pre-configured scope.",
"type": "string",
"const": "allow-enable"
"const": "allow-enable",
"markdownDescription": "Enables the enable command without any pre-configured scope."
},
{
"description": "Denies the enable command without any pre-configured scope.",
"type": "string",
"const": "deny-enable"
"const": "deny-enable",
"markdownDescription": "Denies the enable command without any pre-configured scope."
},
{
"description": "Enables the is_enabled command without any pre-configured scope.",
"type": "string",
"const": "allow-is-enabled"
"const": "allow-is-enabled",
"markdownDescription": "Enables the is_enabled command without any pre-configured scope."
},
{
"description": "Denies the is_enabled command without any pre-configured scope.",
"type": "string",
"const": "deny-is-enabled"
"const": "deny-is-enabled",
"markdownDescription": "Denies the is_enabled command without any pre-configured scope."
},
{
"description": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
"description": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`"
}
]
}
+125 -49
View File
@@ -14,7 +14,7 @@ use auto_launch::{AutoLaunch, AutoLaunchBuilder};
use serde::{ser::Serializer, Serialize};
use tauri::{
command,
plugin::{Builder, TauriPlugin},
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State,
};
@@ -22,8 +22,9 @@ use std::env::current_exe;
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Default, Copy, Clone)]
pub enum MacosLauncher {
#[default]
LaunchAgent,
AppleScript,
}
@@ -71,10 +72,12 @@ impl AutoLaunchManager {
}
pub trait ManagerExt<R: Runtime> {
/// TODO: Rename these to `autostart` or `auto_start` in v3
fn autolaunch(&self) -> State<'_, AutoLaunchManager>;
}
impl<R: Runtime, T: Manager<R>> ManagerExt<R> for T {
/// TODO: Rename these to `autostart` or `auto_start` in v3
fn autolaunch(&self) -> State<'_, AutoLaunchManager> {
self.state::<AutoLaunchManager>()
}
@@ -95,59 +98,132 @@ async fn is_enabled(manager: State<'_, AutoLaunchManager>) -> Result<bool> {
manager.is_enabled()
}
/// Initializes the plugin.
///
/// `args` - are passed to your app on startup.
pub fn init<R: Runtime>(
#[derive(Default)]
pub struct Builder {
#[cfg(target_os = "macos")]
macos_launcher: MacosLauncher,
args: Option<Vec<&'static str>>,
) -> TauriPlugin<R> {
Builder::new("autostart")
.invoke_handler(tauri::generate_handler![enable, disable, is_enabled])
.setup(move |app, _api| {
let mut builder = AutoLaunchBuilder::new();
builder.set_app_name(&app.package_info().name);
if let Some(args) = args {
builder.set_args(&args);
}
builder.set_use_launch_agent(matches!(macos_launcher, MacosLauncher::LaunchAgent));
args: Vec<String>,
}
let current_exe = current_exe()?;
impl Builder {
/// Create a new auto start builder with default settings
pub fn new() -> Self {
Self::default()
}
#[cfg(windows)]
builder.set_app_path(&current_exe.display().to_string());
#[cfg(target_os = "macos")]
{
// on macOS, current_exe gives path to /Applications/Example.app/MacOS/Example
// but this results in seeing a Unix Executable in macOS login items
// It must be: /Applications/Example.app
// If it didn't find exactly a single occurance of .app, it will default to
// exe path to not break it.
let exe_path = current_exe.canonicalize()?.display().to_string();
let parts: Vec<&str> = exe_path.split(".app/").collect();
let app_path =
if parts.len() == 2 && matches!(macos_launcher, MacosLauncher::AppleScript) {
/// Adds an argument to pass to your app on startup.
///
/// ## Examples
///
/// ```no_run
/// Builder::new()
/// .arg("--from-autostart")
/// .arg("--hey")
/// .build();
/// ```
pub fn arg<S: Into<String>>(mut self, arg: S) -> Self {
self.args.push(arg.into());
self
}
/// Adds multiple arguments to pass to your app on startup.
///
/// ## Examples
///
/// ```no_run
/// Builder::new()
/// .args(["--from-autostart", "--hey"])
/// .build();
/// ```
pub fn args<I, S>(mut self, args: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
for arg in args {
self = self.arg(arg);
}
self
}
/// Sets whether to use launch agent or apple script to be used to enable auto start,
/// the builder's default is [`MacosLauncher::LaunchAgent`]
#[cfg(target_os = "macos")]
pub fn macos_launcher(mut self, macos_launcher: MacosLauncher) -> Self {
self.macos_launcher = macos_launcher;
self
}
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
PluginBuilder::new("autostart")
.invoke_handler(tauri::generate_handler![enable, disable, is_enabled])
.setup(move |app, _api| {
let mut builder = AutoLaunchBuilder::new();
builder.set_app_name(&app.package_info().name);
builder.set_args(&self.args);
let current_exe = current_exe()?;
#[cfg(windows)]
builder.set_app_path(&current_exe.display().to_string());
#[cfg(target_os = "macos")]
{
builder.set_use_launch_agent(matches!(
self.macos_launcher,
MacosLauncher::LaunchAgent
));
// on macOS, current_exe gives path to /Applications/Example.app/MacOS/Example
// but this results in seeing a Unix Executable in macOS login items
// It must be: /Applications/Example.app
// If it didn't find exactly a single occurance of .app, it will default to
// exe path to not break it.
let exe_path = current_exe.canonicalize()?.display().to_string();
let parts: Vec<&str> = exe_path.split(".app/").collect();
let app_path = if parts.len() == 2
&& matches!(self.macos_launcher, MacosLauncher::AppleScript)
{
format!("{}.app", parts.first().unwrap())
} else {
exe_path
};
builder.set_app_path(&app_path);
}
#[cfg(target_os = "linux")]
if let Some(appimage) = app
.env()
.appimage
.and_then(|p| p.to_str().map(|s| s.to_string()))
{
builder.set_app_path(&appimage);
} else {
builder.set_app_path(&current_exe.display().to_string());
}
builder.set_app_path(&app_path);
}
app.manage(AutoLaunchManager(
builder.build().map_err(|e| e.to_string())?,
));
Ok(())
})
.build()
#[cfg(target_os = "linux")]
if let Some(appimage) = app
.env()
.appimage
.and_then(|p| p.to_str().map(|s| s.to_string()))
{
builder.set_app_path(&appimage);
} else {
builder.set_app_path(&current_exe.display().to_string());
}
app.manage(AutoLaunchManager(
builder.build().map_err(|e| e.to_string())?,
));
Ok(())
})
.build()
}
}
/// Initializes the plugin.
///
/// `args` - are passed to your app on startup.
pub fn init<R: Runtime>(
#[allow(unused)] macos_launcher: MacosLauncher,
args: Option<Vec<&'static str>>,
) -> TauriPlugin<R> {
let mut builder = Builder::new();
if let Some(args) = args {
builder = builder.args(args)
}
#[cfg(target_os = "macos")]
{
builder = builder.macos_launcher(macos_launcher);
}
builder.build()
}
@@ -9,6 +9,8 @@ It allows all barcode related features.
#### This default permission set includes the following:
- `allow-cancel`
- `allow-check-permissions`
- `allow-open-app-settings`
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,67 +297,80 @@
{
"description": "Enables the cancel command without any pre-configured scope.",
"type": "string",
"const": "allow-cancel"
"const": "allow-cancel",
"markdownDescription": "Enables the cancel command without any pre-configured scope."
},
{
"description": "Denies the cancel command without any pre-configured scope.",
"type": "string",
"const": "deny-cancel"
"const": "deny-cancel",
"markdownDescription": "Denies the cancel command without any pre-configured scope."
},
{
"description": "Enables the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-check-permissions"
"const": "allow-check-permissions",
"markdownDescription": "Enables the check_permissions command without any pre-configured scope."
},
{
"description": "Denies the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-check-permissions"
"const": "deny-check-permissions",
"markdownDescription": "Denies the check_permissions command without any pre-configured scope."
},
{
"description": "Enables the open_app_settings command without any pre-configured scope.",
"type": "string",
"const": "allow-open-app-settings"
"const": "allow-open-app-settings",
"markdownDescription": "Enables the open_app_settings command without any pre-configured scope."
},
{
"description": "Denies the open_app_settings command without any pre-configured scope.",
"type": "string",
"const": "deny-open-app-settings"
"const": "deny-open-app-settings",
"markdownDescription": "Denies the open_app_settings command without any pre-configured scope."
},
{
"description": "Enables the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-request-permissions"
"const": "allow-request-permissions",
"markdownDescription": "Enables the request_permissions command without any pre-configured scope."
},
{
"description": "Denies the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-request-permissions"
"const": "deny-request-permissions",
"markdownDescription": "Denies the request_permissions command without any pre-configured scope."
},
{
"description": "Enables the scan command without any pre-configured scope.",
"type": "string",
"const": "allow-scan"
"const": "allow-scan",
"markdownDescription": "Enables the scan command without any pre-configured scope."
},
{
"description": "Denies the scan command without any pre-configured scope.",
"type": "string",
"const": "deny-scan"
"const": "deny-scan",
"markdownDescription": "Denies the scan command without any pre-configured scope."
},
{
"description": "Enables the vibrate command without any pre-configured scope.",
"type": "string",
"const": "allow-vibrate"
"const": "allow-vibrate",
"markdownDescription": "Enables the vibrate command without any pre-configured scope."
},
{
"description": "Denies the vibrate command without any pre-configured scope.",
"type": "string",
"const": "deny-vibrate"
"const": "deny-vibrate",
"markdownDescription": "Denies the vibrate command without any pre-configured scope."
},
{
"description": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n",
"description": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n\n#### This default permission set includes:\n\n- `allow-cancel`\n- `allow-check-permissions`\n- `allow-open-app-settings`\n- `allow-request-permissions`\n- `allow-scan`\n- `allow-vibrate`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n\n#### This default permission set includes:\n\n- `allow-cancel`\n- `allow-check-permissions`\n- `allow-open-app-settings`\n- `allow-request-permissions`\n- `allow-scan`\n- `allow-vibrate`"
}
]
}
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.1]
### bug
- [`10f9e66e`](https://github.com/tauri-apps/plugins-workspace/commit/10f9e66e32141dd35f4bf884fbf9102691187e92) ([#2633](https://github.com/tauri-apps/plugins-workspace/pull/2633) by [@pjf-dev](https://github.com/tauri-apps/plugins-workspace/../../pjf-dev)) Fix biometric plugin ignoring fallback logic when biometry status is unavailable or not enrolled on iOS.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-biometric"
version = "2.2.0"
version = "2.2.1"
description = "Prompt the user for biometric authentication on Android and iOS."
edition = { workspace = true }
authors = { workspace = true }
@@ -98,7 +98,12 @@ class BiometricPlugin: Plugin {
}
@objc func authenticate(_ invoke: Invoke) throws {
guard self.status.available else {
let args = try invoke.parseArgs(AuthOptions.self)
let allowDeviceCredential = args.allowDeviceCredential ?? false
guard self.status.available || allowDeviceCredential else {
// Biometry unavailable, fallback disabled
invoke.reject(
self.status.errorReason ?? "",
code: self.status.errorCode ?? ""
@@ -106,15 +111,11 @@ class BiometricPlugin: Plugin {
return
}
let args = try invoke.parseArgs(AuthOptions.self)
let context = LAContext()
context.localizedFallbackTitle = args.fallbackTitle
context.localizedCancelTitle = args.cancelTitle
context.touchIDAuthenticationAllowableReuseDuration = 0
let allowDeviceCredential = args.allowDeviceCredential ?? false
// force system default fallback title if an empty string is provided (the OS hides the fallback button in this case)
if allowDeviceCredential,
let fallbackTitle = context.localizedFallbackTitle,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-biometric",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -9,6 +9,8 @@ It allows acccess to all biometric commands.
#### This default permission set includes the following:
- `allow-authenticate`
- `allow-status`
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,27 +297,32 @@
{
"description": "Enables the authenticate command without any pre-configured scope.",
"type": "string",
"const": "allow-authenticate"
"const": "allow-authenticate",
"markdownDescription": "Enables the authenticate command without any pre-configured scope."
},
{
"description": "Denies the authenticate command without any pre-configured scope.",
"type": "string",
"const": "deny-authenticate"
"const": "deny-authenticate",
"markdownDescription": "Denies the authenticate command without any pre-configured scope."
},
{
"description": "Enables the status command without any pre-configured scope.",
"type": "string",
"const": "allow-status"
"const": "allow-status",
"markdownDescription": "Enables the status command without any pre-configured scope."
},
{
"description": "Denies the status command without any pre-configured scope.",
"type": "string",
"const": "deny-status"
"const": "deny-status",
"markdownDescription": "Denies the status command without any pre-configured scope."
},
{
"description": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n",
"description": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`"
}
]
}
@@ -2,6 +2,8 @@
Allows reading the CLI matches
#### This default permission set includes the following:
- `allow-cli-matches`
## Permission Table
+9 -6
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,17 +297,20 @@
{
"description": "Enables the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "allow-cli-matches"
"const": "allow-cli-matches",
"markdownDescription": "Enables the cli_matches command without any pre-configured scope."
},
{
"description": "Denies the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "deny-cli-matches"
"const": "deny-cli-matches",
"markdownDescription": "Denies the cli_matches command without any pre-configured scope."
},
{
"description": "Allows reading the CLI matches",
"description": "Allows reading the CLI matches\n#### This default permission set includes:\n\n- `allow-cli-matches`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "Allows reading the CLI matches\n#### This default permission set includes:\n\n- `allow-cli-matches`"
}
]
}
@@ -7,6 +7,8 @@ application specific if read and/or write access is needed.
Clipboard interaction needs to be explicitly enabled.
#### This default permission set includes the following:
## Permission Table
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,67 +297,80 @@
{
"description": "Enables the clear command without any pre-configured scope.",
"type": "string",
"const": "allow-clear"
"const": "allow-clear",
"markdownDescription": "Enables the clear command without any pre-configured scope."
},
{
"description": "Denies the clear command without any pre-configured scope.",
"type": "string",
"const": "deny-clear"
"const": "deny-clear",
"markdownDescription": "Denies the clear command without any pre-configured scope."
},
{
"description": "Enables the read_image command without any pre-configured scope.",
"type": "string",
"const": "allow-read-image"
"const": "allow-read-image",
"markdownDescription": "Enables the read_image command without any pre-configured scope."
},
{
"description": "Denies the read_image command without any pre-configured scope.",
"type": "string",
"const": "deny-read-image"
"const": "deny-read-image",
"markdownDescription": "Denies the read_image command without any pre-configured scope."
},
{
"description": "Enables the read_text command without any pre-configured scope.",
"type": "string",
"const": "allow-read-text"
"const": "allow-read-text",
"markdownDescription": "Enables the read_text command without any pre-configured scope."
},
{
"description": "Denies the read_text command without any pre-configured scope.",
"type": "string",
"const": "deny-read-text"
"const": "deny-read-text",
"markdownDescription": "Denies the read_text command without any pre-configured scope."
},
{
"description": "Enables the write_html command without any pre-configured scope.",
"type": "string",
"const": "allow-write-html"
"const": "allow-write-html",
"markdownDescription": "Enables the write_html command without any pre-configured scope."
},
{
"description": "Denies the write_html command without any pre-configured scope.",
"type": "string",
"const": "deny-write-html"
"const": "deny-write-html",
"markdownDescription": "Denies the write_html command without any pre-configured scope."
},
{
"description": "Enables the write_image command without any pre-configured scope.",
"type": "string",
"const": "allow-write-image"
"const": "allow-write-image",
"markdownDescription": "Enables the write_image command without any pre-configured scope."
},
{
"description": "Denies the write_image command without any pre-configured scope.",
"type": "string",
"const": "deny-write-image"
"const": "deny-write-image",
"markdownDescription": "Denies the write_image command without any pre-configured scope."
},
{
"description": "Enables the write_text command without any pre-configured scope.",
"type": "string",
"const": "allow-write-text"
"const": "allow-write-text",
"markdownDescription": "Enables the write_text command without any pre-configured scope."
},
{
"description": "Denies the write_text command without any pre-configured scope.",
"type": "string",
"const": "deny-write-text"
"const": "deny-write-text",
"markdownDescription": "Denies the write_text command without any pre-configured scope."
},
{
"description": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n"
}
]
}
+7
View File
@@ -1,5 +1,12 @@
# Changelog
## \[2.2.1]
### bug
- [`38deef43`](https://github.com/tauri-apps/plugins-workspace/commit/38deef43dca9d5a09a38ed2da45b0f86c6afa1c5) ([#2483](https://github.com/tauri-apps/plugins-workspace/pull/2483)) Fix `is_registered` not being able to pickup deep link registered in `HKEY_LOCAL_MACHINE` on Windows
- [`38deef43`](https://github.com/tauri-apps/plugins-workspace/commit/38deef43dca9d5a09a38ed2da45b0f86c6afa1c5) ([#2483](https://github.com/tauri-apps/plugins-workspace/pull/2483)) Fix `unregister` not being able to remove deep link registered in `HKEY_LOCAL_MACHINE` on Windows
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-deep-link"
version = "2.2.0"
version = "2.2.1"
description = "Set your Tauri application as the default handler for an URL"
authors = { workspace = true }
license = { workspace = true }
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.1]
### Dependencies
- Upgraded to `deep-link-js@2.2.1`
## \[2.2.0]
### Dependencies
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "deep-link-example",
"private": true,
"version": "2.2.0",
"version": "2.2.1",
"type": "module",
"scripts": {
"dev": "vite",
@@ -10,12 +10,12 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.3.0",
"@tauri-apps/plugin-deep-link": "2.2.0"
"@tauri-apps/api": "2.5.0",
"@tauri-apps/plugin-deep-link": "2.2.1"
},
"devDependencies": {
"@tauri-apps/cli": "2.3.1",
"@tauri-apps/cli": "2.5.0",
"typescript": "^5.7.3",
"vite": "^6.2.0"
"vite": "^6.2.6"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-deep-link",
"version": "2.2.0",
"version": "2.2.1",
"description": "Set your Tauri application as the default handler for an URL",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -2,6 +2,8 @@
Allows reading the opened deep link via the get_current command
#### This default permission set includes the following:
- `allow-get-current`
## Permission Table
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,47 +297,56 @@
{
"description": "Enables the get_current command without any pre-configured scope.",
"type": "string",
"const": "allow-get-current"
"const": "allow-get-current",
"markdownDescription": "Enables the get_current command without any pre-configured scope."
},
{
"description": "Denies the get_current command without any pre-configured scope.",
"type": "string",
"const": "deny-get-current"
"const": "deny-get-current",
"markdownDescription": "Denies the get_current command without any pre-configured scope."
},
{
"description": "Enables the is_registered command without any pre-configured scope.",
"type": "string",
"const": "allow-is-registered"
"const": "allow-is-registered",
"markdownDescription": "Enables the is_registered command without any pre-configured scope."
},
{
"description": "Denies the is_registered command without any pre-configured scope.",
"type": "string",
"const": "deny-is-registered"
"const": "deny-is-registered",
"markdownDescription": "Denies the is_registered command without any pre-configured scope."
},
{
"description": "Enables the register command without any pre-configured scope.",
"type": "string",
"const": "allow-register"
"const": "allow-register",
"markdownDescription": "Enables the register command without any pre-configured scope."
},
{
"description": "Denies the register command without any pre-configured scope.",
"type": "string",
"const": "deny-register"
"const": "deny-register",
"markdownDescription": "Denies the register command without any pre-configured scope."
},
{
"description": "Enables the unregister command without any pre-configured scope.",
"type": "string",
"const": "allow-unregister"
"const": "allow-unregister",
"markdownDescription": "Enables the unregister command without any pre-configured scope."
},
{
"description": "Denies the unregister command without any pre-configured scope.",
"type": "string",
"const": "deny-unregister"
"const": "deny-unregister",
"markdownDescription": "Denies the unregister command without any pre-configured scope."
},
{
"description": "Allows reading the opened deep link via the get_current command",
"description": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`"
}
]
}
+18 -8
View File
@@ -172,7 +172,7 @@ mod imp {
use tauri::Manager;
use tauri::{AppHandle, Runtime};
#[cfg(windows)]
use windows_registry::CURRENT_USER;
use windows_registry::{CLASSES_ROOT, CURRENT_USER, LOCAL_MACHINE};
/// Access to the deep-link APIs.
pub struct DeepLink<R: Runtime> {
@@ -258,7 +258,8 @@ mod imp {
pub fn register<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
#[cfg(windows)]
{
let key_base = format!("Software\\Classes\\{}", _protocol.as_ref());
let protocol = _protocol.as_ref();
let key_base = format!("Software\\Classes\\{protocol}");
let exe = dunce::simplified(&tauri::utils::platform::current_exe()?)
.display()
@@ -348,13 +349,21 @@ mod imp {
///
/// ## Platform-specific:
///
/// - **Windows**: Requires admin rights if the protocol is registered on local machine
/// (this can happen when registered from the NSIS installer when the install mode is set to both or per machine)
/// - **Linux**: Can only unregister the scheme if it was initially registered with [`register`](`Self::register`). May not work on older distros.
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
pub fn unregister<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
#[cfg(windows)]
{
CURRENT_USER.remove_tree(format!("Software\\Classes\\{}", _protocol.as_ref()))?;
let protocol = _protocol.as_ref();
let path = format!("Software\\Classes\\{protocol}");
if LOCAL_MACHINE.open(&path).is_ok() {
LOCAL_MACHINE.remove_tree(&path)?;
}
if CURRENT_USER.open(&path).is_ok() {
CURRENT_USER.remove_tree(&path)?;
}
Ok(())
}
@@ -398,10 +407,11 @@ mod imp {
pub fn is_registered<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<bool> {
#[cfg(windows)]
{
let cmd_reg = CURRENT_USER.open(format!(
"Software\\Classes\\{}\\shell\\open\\command",
_protocol.as_ref()
))?;
let protocol = _protocol.as_ref();
let Ok(cmd_reg) = CLASSES_ROOT.open(format!("{protocol}\\shell\\open\\command"))
else {
return Ok(false);
};
let registered_cmd = cmd_reg.get_string("")?;
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.1]
### Dependencies
- Upgraded to `fs-js@2.2.1`
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-dialog"
version = "2.2.0"
version = "2.2.1"
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
@@ -34,7 +34,7 @@ tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
tauri-plugin-fs = { path = "../fs", version = "2.2.0" }
tauri-plugin-fs = { path = "../fs", version = "2.2.1" }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-dialog",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -10,6 +10,8 @@ All dialog types are enabled.
#### This default permission set includes the following:
- `allow-ask`
- `allow-confirm`
- `allow-message`
+25 -14
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,57 +297,68 @@
{
"description": "Enables the ask command without any pre-configured scope.",
"type": "string",
"const": "allow-ask"
"const": "allow-ask",
"markdownDescription": "Enables the ask command without any pre-configured scope."
},
{
"description": "Denies the ask command without any pre-configured scope.",
"type": "string",
"const": "deny-ask"
"const": "deny-ask",
"markdownDescription": "Denies the ask command without any pre-configured scope."
},
{
"description": "Enables the confirm command without any pre-configured scope.",
"type": "string",
"const": "allow-confirm"
"const": "allow-confirm",
"markdownDescription": "Enables the confirm command without any pre-configured scope."
},
{
"description": "Denies the confirm command without any pre-configured scope.",
"type": "string",
"const": "deny-confirm"
"const": "deny-confirm",
"markdownDescription": "Denies the confirm command without any pre-configured scope."
},
{
"description": "Enables the message command without any pre-configured scope.",
"type": "string",
"const": "allow-message"
"const": "allow-message",
"markdownDescription": "Enables the message command without any pre-configured scope."
},
{
"description": "Denies the message command without any pre-configured scope.",
"type": "string",
"const": "deny-message"
"const": "deny-message",
"markdownDescription": "Denies the message command without any pre-configured scope."
},
{
"description": "Enables the open command without any pre-configured scope.",
"type": "string",
"const": "allow-open"
"const": "allow-open",
"markdownDescription": "Enables the open command without any pre-configured scope."
},
{
"description": "Denies the open command without any pre-configured scope.",
"type": "string",
"const": "deny-open"
"const": "deny-open",
"markdownDescription": "Denies the open command without any pre-configured scope."
},
{
"description": "Enables the save command without any pre-configured scope.",
"type": "string",
"const": "allow-save"
"const": "allow-save",
"markdownDescription": "Enables the save command without any pre-configured scope."
},
{
"description": "Denies the save command without any pre-configured scope.",
"type": "string",
"const": "deny-save"
"const": "deny-save",
"markdownDescription": "Denies the save command without any pre-configured scope."
},
{
"description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n",
"description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`"
}
]
}
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.1]
### bug
- [`831c35ff`](https://github.com/tauri-apps/plugins-workspace/commit/831c35ff3940e841fe4418bb4cb104038b03304b) ([#2550](https://github.com/tauri-apps/plugins-workspace/pull/2550)) Fix `writeFile` ReadableStream handling due to missing async iterator support on macOS platform
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-fs"
version = "2.2.0"
version = "2.2.1"
description = "Access the file system."
authors = { workspace = true }
license = { workspace = true }
@@ -14,7 +14,7 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write acces in `$RESOURCES` folder" }
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write access in `$RESOURCES` folder" }
linux = { level = "full", notes = "No write access to `$RESOURCES` folder" }
macos = { level = "full", notes = "No write access to `$RESOURCES` folder" }
android = { level = "partial", notes = "Access is restricted to Application folder by default" }
File diff suppressed because one or more lines are too long
+11 -3
View File
@@ -1075,10 +1075,18 @@ async function writeFile(
if (data instanceof ReadableStream) {
const file = await open(path, options)
for await (const chunk of data) {
await file.write(chunk)
const reader = data.getReader()
try {
while (true) {
const { done, value } = await reader.read()
if (done) break
await file.write(value)
}
} finally {
reader.releaseLock()
await file.close()
}
await file.close()
} else {
await invoke('plugin:fs|write_file', data, {
headers: {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-fs",
"version": "2.2.0",
"version": "2.2.1",
"description": "Access the file system.",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -24,8 +24,8 @@ This default permission set prevents access to critical components
of the Tauri application by default.
On Windows the webview data folder access is denied.
#### Included permissions within this default permission set:
#### This default permission set includes the following:
- `create-app-specific-dirs`
- `read-app-specific-dirs-recursive`
-2
View File
@@ -25,8 +25,6 @@ the `mkdir` command.
This default permission set prevents access to critical components
of the Tauri application by default.
On Windows the webview data folder access is denied.
#### Included permissions within this default permission set:
"""
permissions = [
"create-app-specific-dirs",
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,e,i){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?i:"a"===e?i.call(t):i?i.value:n.get(t)}function e(t,n,e,i,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,e),e}var i,s,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),s.set(this,0),o.set(this,[]),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((({message:t,id:r})=>{if(r==n(this,s,"f"))for(n(this,i,"f").call(this,t),e(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,i,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],e(this,s,n(this,s,"f")+1)}else n(this,o,"f")[r]=t}))}set onmessage(t){e(this,i,t)}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,s=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return t.checkPermissions=async function(){return await async function(t){return c(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await c("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await c("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await c("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const e=new a;return e.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await c("plugin:geolocation|watch_position",{options:t,channel:e}),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,e,i){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?i:"a"===e?i.call(t):i?i.value:n.get(t)}function e(t,n,e,i,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,e),e}var i,s,o,r;"function"==typeof SuppressedError&&SuppressedError;const a="__TAURI_TO_IPC_KEY__";class c{constructor(t){i.set(this,void 0),s.set(this,0),o.set(this,[]),r.set(this,void 0),e(this,i,t||(()=>{})),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((t=>{const a=t.index;if("end"in t)return void(a==n(this,s,"f")?this.cleanupCallback():e(this,r,a));const c=t.message;if(a==n(this,s,"f")){for(n(this,i,"f").call(this,c),e(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,i,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],e(this,s,n(this,s,"f")+1)}n(this,s,"f")===n(this,r,"f")&&this.cleanupCallback()}else n(this,o,"f")[a]=c}))}cleanupCallback(){Reflect.deleteProperty(window,`_${this.id}`)}set onmessage(t){e(this,i,t)}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,s=new WeakMap,o=new WeakMap,r=new WeakMap,a)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[a]()}}async function _(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return t.checkPermissions=async function(){return await async function(t){return _(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await _("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await _("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await _("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const e=new c;return e.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await _("plugin:geolocation|watch_position",{options:t,channel:e}),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,62 +297,74 @@
{
"description": "Enables the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-check-permissions"
"const": "allow-check-permissions",
"markdownDescription": "Enables the check_permissions command without any pre-configured scope."
},
{
"description": "Denies the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-check-permissions"
"const": "deny-check-permissions",
"markdownDescription": "Denies the check_permissions command without any pre-configured scope."
},
{
"description": "Enables the clear_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-clear-permissions"
"const": "allow-clear-permissions",
"markdownDescription": "Enables the clear_permissions command without any pre-configured scope."
},
{
"description": "Denies the clear_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-clear-permissions"
"const": "deny-clear-permissions",
"markdownDescription": "Denies the clear_permissions command without any pre-configured scope."
},
{
"description": "Enables the clear_watch command without any pre-configured scope.",
"type": "string",
"const": "allow-clear-watch"
"const": "allow-clear-watch",
"markdownDescription": "Enables the clear_watch command without any pre-configured scope."
},
{
"description": "Denies the clear_watch command without any pre-configured scope.",
"type": "string",
"const": "deny-clear-watch"
"const": "deny-clear-watch",
"markdownDescription": "Denies the clear_watch command without any pre-configured scope."
},
{
"description": "Enables the get_current_position command without any pre-configured scope.",
"type": "string",
"const": "allow-get-current-position"
"const": "allow-get-current-position",
"markdownDescription": "Enables the get_current_position command without any pre-configured scope."
},
{
"description": "Denies the get_current_position command without any pre-configured scope.",
"type": "string",
"const": "deny-get-current-position"
"const": "deny-get-current-position",
"markdownDescription": "Denies the get_current_position command without any pre-configured scope."
},
{
"description": "Enables the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-request-permissions"
"const": "allow-request-permissions",
"markdownDescription": "Enables the request_permissions command without any pre-configured scope."
},
{
"description": "Denies the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-request-permissions"
"const": "deny-request-permissions",
"markdownDescription": "Denies the request_permissions command without any pre-configured scope."
},
{
"description": "Enables the watch_position command without any pre-configured scope.",
"type": "string",
"const": "allow-watch-position"
"const": "allow-watch-position",
"markdownDescription": "Enables the watch_position command without any pre-configured scope."
},
{
"description": "Denies the watch_position command without any pre-configured scope.",
"type": "string",
"const": "deny-watch-position"
"const": "deny-watch-position",
"markdownDescription": "Denies the watch_position command without any pre-configured scope."
}
]
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,i,n;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),n.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o==e(this,i,"f"))for(e(this,s,"f").call(this,t),r(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,n,"f")[e(this,i,"f")],r(this,i,e(this,i,"f")+1)}else e(this,n,"f")[o]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,n=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function _(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return t.isRegistered=async function(t){return await _("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new a;return r.onmessage=e,await _("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await _("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await _("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(t):i?i.value:e.get(t)}function s(t,e,s,i,r){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,s),s}var i,r,n,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class c{constructor(t){i.set(this,void 0),r.set(this,0),n.set(this,[]),a.set(this,void 0),s(this,i,t||(()=>{})),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((t=>{const o=t.index;if("end"in t)return void(o==e(this,r,"f")?this.cleanupCallback():s(this,a,o));const c=t.message;if(o==e(this,r,"f")){for(e(this,i,"f").call(this,c),s(this,r,e(this,r,"f")+1);e(this,r,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,r,"f")];e(this,i,"f").call(this,t),delete e(this,n,"f")[e(this,r,"f")],s(this,r,e(this,r,"f")+1)}e(this,r,"f")===e(this,a,"f")&&this.cleanupCallback()}else e(this,n,"f")[o]=c}))}cleanupCallback(){Reflect.deleteProperty(window,`_${this.id}`)}set onmessage(t){s(this,i,t)}get onmessage(){return e(this,i,"f")}[(i=new WeakMap,r=new WeakMap,n=new WeakMap,a=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function u(t,e={},s){return window.__TAURI_INTERNALS__.invoke(t,e,s)}return t.isRegistered=async function(t){return await u("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const s=new c;return s.onmessage=e,await u("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:s})},t.unregister=async function(t){return await u("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await u("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
@@ -6,6 +6,8 @@ application specific if specific shortcuts should be
registered or unregistered.
#### This default permission set includes the following:
## Permission Table
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,57 +297,68 @@
{
"description": "Enables the is_registered command without any pre-configured scope.",
"type": "string",
"const": "allow-is-registered"
"const": "allow-is-registered",
"markdownDescription": "Enables the is_registered command without any pre-configured scope."
},
{
"description": "Denies the is_registered command without any pre-configured scope.",
"type": "string",
"const": "deny-is-registered"
"const": "deny-is-registered",
"markdownDescription": "Denies the is_registered command without any pre-configured scope."
},
{
"description": "Enables the register command without any pre-configured scope.",
"type": "string",
"const": "allow-register"
"const": "allow-register",
"markdownDescription": "Enables the register command without any pre-configured scope."
},
{
"description": "Denies the register command without any pre-configured scope.",
"type": "string",
"const": "deny-register"
"const": "deny-register",
"markdownDescription": "Denies the register command without any pre-configured scope."
},
{
"description": "Enables the register_all command without any pre-configured scope.",
"type": "string",
"const": "allow-register-all"
"const": "allow-register-all",
"markdownDescription": "Enables the register_all command without any pre-configured scope."
},
{
"description": "Denies the register_all command without any pre-configured scope.",
"type": "string",
"const": "deny-register-all"
"const": "deny-register-all",
"markdownDescription": "Denies the register_all command without any pre-configured scope."
},
{
"description": "Enables the unregister command without any pre-configured scope.",
"type": "string",
"const": "allow-unregister"
"const": "allow-unregister",
"markdownDescription": "Enables the unregister command without any pre-configured scope."
},
{
"description": "Denies the unregister command without any pre-configured scope.",
"type": "string",
"const": "deny-unregister"
"const": "deny-unregister",
"markdownDescription": "Denies the unregister command without any pre-configured scope."
},
{
"description": "Enables the unregister_all command without any pre-configured scope.",
"type": "string",
"const": "allow-unregister-all"
"const": "allow-unregister-all",
"markdownDescription": "Enables the unregister_all command without any pre-configured scope."
},
{
"description": "Denies the unregister_all command without any pre-configured scope.",
"type": "string",
"const": "deny-unregister-all"
"const": "deny-unregister-all",
"markdownDescription": "Denies the unregister_all command without any pre-configured scope."
},
{
"description": "No features are enabled by default, as we believe\nthe shortcuts can be inherently dangerous and it is\napplication specific if specific shortcuts should be\nregistered or unregistered.\n",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "No features are enabled by default, as we believe\nthe shortcuts can be inherently dangerous and it is\napplication specific if specific shortcuts should be\nregistered or unregistered.\n"
}
]
}
+18 -10
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,42 +297,50 @@
{
"description": "Enables the impact_feedback command without any pre-configured scope.",
"type": "string",
"const": "allow-impact-feedback"
"const": "allow-impact-feedback",
"markdownDescription": "Enables the impact_feedback command without any pre-configured scope."
},
{
"description": "Denies the impact_feedback command without any pre-configured scope.",
"type": "string",
"const": "deny-impact-feedback"
"const": "deny-impact-feedback",
"markdownDescription": "Denies the impact_feedback command without any pre-configured scope."
},
{
"description": "Enables the notification_feedback command without any pre-configured scope.",
"type": "string",
"const": "allow-notification-feedback"
"const": "allow-notification-feedback",
"markdownDescription": "Enables the notification_feedback command without any pre-configured scope."
},
{
"description": "Denies the notification_feedback command without any pre-configured scope.",
"type": "string",
"const": "deny-notification-feedback"
"const": "deny-notification-feedback",
"markdownDescription": "Denies the notification_feedback command without any pre-configured scope."
},
{
"description": "Enables the selection_feedback command without any pre-configured scope.",
"type": "string",
"const": "allow-selection-feedback"
"const": "allow-selection-feedback",
"markdownDescription": "Enables the selection_feedback command without any pre-configured scope."
},
{
"description": "Denies the selection_feedback command without any pre-configured scope.",
"type": "string",
"const": "deny-selection-feedback"
"const": "deny-selection-feedback",
"markdownDescription": "Denies the selection_feedback command without any pre-configured scope."
},
{
"description": "Enables the vibrate command without any pre-configured scope.",
"type": "string",
"const": "allow-vibrate"
"const": "allow-vibrate",
"markdownDescription": "Enables the vibrate command without any pre-configured scope."
},
{
"description": "Denies the vibrate command without any pre-configured scope.",
"type": "string",
"const": "deny-vibrate"
"const": "deny-vibrate",
"markdownDescription": "Denies the vibrate command without any pre-configured scope."
}
]
}
+9
View File
@@ -1,5 +1,14 @@
# Changelog
## \[2.4.3]
- [`37c0477a`](https://github.com/tauri-apps/plugins-workspace/commit/37c0477afe926d326573f1827045875ce8bf8187) ([#2561](https://github.com/tauri-apps/plugins-workspace/pull/2561)) Add `zstd` cargo feature flag to enable `reqwest/zstd` flag.
- [`9ebbfb2e`](https://github.com/tauri-apps/plugins-workspace/commit/9ebbfb2e3ccef8e0f277a0c02fe6b399b41feeb6) ([#1978](https://github.com/tauri-apps/plugins-workspace/pull/1978)) Persist cookies to disk and load it on next app start.
### Dependencies
- Upgraded to `fs-js@2.2.1`
## \[2.4.2]
- [`a15eedf3`](https://github.com/tauri-apps/plugins-workspace/commit/a15eedf37854344f7ffbcb0d373d848563817011) ([#2535](https://github.com/tauri-apps/plugins-workspace/pull/2535) by [@amrbashir](https://github.com/tauri-apps/plugins-workspace/../../amrbashir)) Fix `fetch` occasionally throwing an error due to trying to close the underline stream twice.
+6 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-http"
version = "2.4.2"
version = "2.4.3"
description = "Access an HTTP client written in Rust."
edition = { workspace = true }
authors = { workspace = true }
@@ -34,13 +34,15 @@ serde_json = { workspace = true }
tauri = { workspace = true }
thiserror = { workspace = true }
tokio = { version = "1", features = ["sync", "macros"] }
tauri-plugin-fs = { path = "../fs", version = "2.2.0" }
tauri-plugin-fs = { path = "../fs", version = "2.2.1" }
urlpattern = "0.3"
regex = "1"
http = "1"
reqwest = { version = "0.12", default-features = false }
url = { workspace = true }
data-url = "0.3"
cookie_store = { version = "0.21.1", optional = true, features = ["serde"] }
bytes = { version = "1.9", optional = true }
tracing = { workspace = true, optional = true }
[features]
@@ -62,10 +64,11 @@ rustls-tls-manual-roots = ["reqwest/rustls-tls-manual-roots"]
rustls-tls-webpki-roots = ["reqwest/rustls-tls-webpki-roots"]
rustls-tls-native-roots = ["reqwest/rustls-tls-native-roots"]
blocking = ["reqwest/blocking"]
cookies = ["reqwest/cookies"]
cookies = ["reqwest/cookies", "dep:cookie_store", "dep:bytes"]
gzip = ["reqwest/gzip"]
brotli = ["reqwest/brotli"]
deflate = ["reqwest/deflate"]
zstd = ["reqwest/zstd"]
trust-dns = ["reqwest/trust-dns"]
socks = ["reqwest/socks"]
http2 = ["reqwest/http2"]
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";function t(e,t,r,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}function r(e,t,r,n,s){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,r),r}var n,s,a;"function"==typeof SuppressedError&&SuppressedError;const i="__TAURI_TO_IPC_KEY__";class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),s.set(this,0),a.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:i})=>{if(i==t(this,s,"f"))for(t(this,n,"f").call(this,e),r(this,s,t(this,s,"f")+1);t(this,s,"f")in t(this,a,"f");){const e=t(this,a,"f")[t(this,s,"f")];t(this,n,"f").call(this,e),delete t(this,a,"f")[t(this,s,"f")],r(this,s,t(this,s,"f")+1)}else t(this,a,"f")[i]=e}))}set onmessage(e){r(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,s=new WeakMap,a=new WeakMap,i)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[i]()}}async function c(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}const d="Request cancelled";return e.fetch=async function(e,t){const r=t?.signal;if(r?.aborted)throw new Error(d);const n=t?.maxRedirections,s=t?.connectTimeout,a=t?.proxy,i=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const h=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,f=new Request(e,t),_=await f.arrayBuffer(),u=0!==_.byteLength?Array.from(new Uint8Array(_)):null;for(const[e,t]of f.headers)h.get(e)||h.set(e,t);const l=(h instanceof Headers?Array.from(h.entries()):Array.isArray(h)?h:Object.entries(h)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(r?.aborted)throw new Error(d);const w=await c("plugin:http|fetch",{clientConfig:{method:f.method,url:f.url,headers:l,data:u,maxRedirections:n,connectTimeout:s,proxy:a,danger:i}}),p=()=>c("plugin:http|fetch_cancel",{rid:w});if(r?.aborted)throw p(),new Error(d);r?.addEventListener("abort",(()=>{p()}));const{status:y,statusText:m,url:T,headers:g,rid:b}=await c("plugin:http|fetch_send",{rid:w}),A=new ReadableStream({start:e=>{const t=new o;t.onmessage=t=>{if(r?.aborted)return void e.error(d);const n=new Uint8Array(t),s=n[n.byteLength-1],a=n.slice(0,n.byteLength-1);1!=s?e.enqueue(a):e.close()},c("plugin:http|fetch_read_body",{rid:b,streamChannel:t}).catch((t=>{e.error(t)}))}}),R=new Response(A,{status:y,statusText:m});return Object.defineProperty(R,"url",{value:T}),Object.defineProperty(R,"headers",{value:new Headers(g)}),R},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";function t(e,t,r,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}function r(e,t,r,n,s){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,r),r}var n,s,i,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class c{constructor(e){n.set(this,void 0),s.set(this,0),i.set(this,[]),a.set(this,void 0),r(this,n,e||(()=>{})),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((e=>{const o=e.index;if("end"in e)return void(o==t(this,s,"f")?this.cleanupCallback():r(this,a,o));const c=e.message;if(o==t(this,s,"f")){for(t(this,n,"f").call(this,c),r(this,s,t(this,s,"f")+1);t(this,s,"f")in t(this,i,"f");){const e=t(this,i,"f")[t(this,s,"f")];t(this,n,"f").call(this,e),delete t(this,i,"f")[t(this,s,"f")],r(this,s,t(this,s,"f")+1)}t(this,s,"f")===t(this,a,"f")&&this.cleanupCallback()}else t(this,i,"f")[o]=c}))}cleanupCallback(){Reflect.deleteProperty(window,`_${this.id}`)}set onmessage(e){r(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,s=new WeakMap,i=new WeakMap,a=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function d(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}const h="Request cancelled";return e.fetch=async function(e,t){const r=t?.signal;if(r?.aborted)throw new Error(h);const n=t?.maxRedirections,s=t?.connectTimeout,i=t?.proxy,a=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const o=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,f=new Request(e,t),l=await f.arrayBuffer(),u=0!==l.byteLength?Array.from(new Uint8Array(l)):null;for(const[e,t]of f.headers)o.get(e)||o.set(e,t);const _=(o instanceof Headers?Array.from(o.entries()):Array.isArray(o)?o:Object.entries(o)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(r?.aborted)throw new Error(h);const w=await d("plugin:http|fetch",{clientConfig:{method:f.method,url:f.url,headers:_,data:u,maxRedirections:n,connectTimeout:s,proxy:i,danger:a}}),p=()=>d("plugin:http|fetch_cancel",{rid:w});if(r?.aborted)throw p(),new Error(h);r?.addEventListener("abort",(()=>{p()}));const{status:y,statusText:m,url:b,headers:g,rid:T}=await d("plugin:http|fetch_send",{rid:w}),R=new ReadableStream({start:e=>{const t=new c;t.onmessage=t=>{if(r?.aborted)return void e.error(h);const n=new Uint8Array(t),s=n[n.byteLength-1],i=n.slice(0,n.byteLength-1);1!=s?e.enqueue(i):e.close()},d("plugin:http|fetch_read_body",{rid:T,streamChannel:t}).catch((t=>{e.error(t)}))}}),A=new Response(R,{status:y,statusText:m});return Object.defineProperty(A,"url",{value:b}),Object.defineProperty(A,"headers",{value:new Headers(g)}),A},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-http",
"version": "2.4.2",
"version": "2.4.3",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -13,6 +13,8 @@ All fetch operations are enabled.
#### This default permission set includes the following:
- `allow-fetch`
- `allow-fetch-cancel`
- `allow-fetch-read-body`
+21 -12
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,47 +297,56 @@
{
"description": "Enables the fetch command without any pre-configured scope.",
"type": "string",
"const": "allow-fetch"
"const": "allow-fetch",
"markdownDescription": "Enables the fetch command without any pre-configured scope."
},
{
"description": "Denies the fetch command without any pre-configured scope.",
"type": "string",
"const": "deny-fetch"
"const": "deny-fetch",
"markdownDescription": "Denies the fetch command without any pre-configured scope."
},
{
"description": "Enables the fetch_cancel command without any pre-configured scope.",
"type": "string",
"const": "allow-fetch-cancel"
"const": "allow-fetch-cancel",
"markdownDescription": "Enables the fetch_cancel command without any pre-configured scope."
},
{
"description": "Denies the fetch_cancel command without any pre-configured scope.",
"type": "string",
"const": "deny-fetch-cancel"
"const": "deny-fetch-cancel",
"markdownDescription": "Denies the fetch_cancel command without any pre-configured scope."
},
{
"description": "Enables the fetch_read_body command without any pre-configured scope.",
"type": "string",
"const": "allow-fetch-read-body"
"const": "allow-fetch-read-body",
"markdownDescription": "Enables the fetch_read_body command without any pre-configured scope."
},
{
"description": "Denies the fetch_read_body command without any pre-configured scope.",
"type": "string",
"const": "deny-fetch-read-body"
"const": "deny-fetch-read-body",
"markdownDescription": "Denies the fetch_read_body command without any pre-configured scope."
},
{
"description": "Enables the fetch_send command without any pre-configured scope.",
"type": "string",
"const": "allow-fetch-send"
"const": "allow-fetch-send",
"markdownDescription": "Enables the fetch_send command without any pre-configured scope."
},
{
"description": "Denies the fetch_send command without any pre-configured scope.",
"type": "string",
"const": "deny-fetch-send"
"const": "deny-fetch-send",
"markdownDescription": "Denies the fetch_send command without any pre-configured scope."
},
{
"description": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n",
"description": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n\n#### This default permission set includes:\n\n- `allow-fetch`\n- `allow-fetch-cancel`\n- `allow-fetch-read-body`\n- `allow-fetch-send`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n\n#### This default permission set includes:\n\n- `allow-fetch`\n- `allow-fetch-cancel`\n- `allow-fetch-read-body`\n- `allow-fetch-send`"
}
]
}
+49 -2
View File
@@ -14,25 +14,72 @@ pub use error::{Error, Result};
mod commands;
mod error;
#[cfg(feature = "cookies")]
mod reqwest_cookie_store;
mod scope;
#[cfg(feature = "cookies")]
const COOKIES_FILENAME: &str = ".cookies";
pub(crate) struct Http {
#[cfg(feature = "cookies")]
cookies_jar: std::sync::Arc<reqwest::cookie::Jar>,
cookies_jar: std::sync::Arc<crate::reqwest_cookie_store::CookieStoreMutex>,
}
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::<R>::new("http")
.setup(|app, _| {
#[cfg(feature = "cookies")]
let cookies_jar = {
use crate::reqwest_cookie_store::*;
use std::fs::File;
use std::io::BufReader;
let cache_dir = app.path().app_cache_dir()?;
std::fs::create_dir_all(&cache_dir)?;
let path = cache_dir.join(COOKIES_FILENAME);
let file = File::options()
.create(true)
.append(true)
.read(true)
.open(&path)?;
let reader = BufReader::new(file);
CookieStoreMutex::load(path.clone(), reader).unwrap_or_else(|_e| {
#[cfg(feature = "tracing")]
tracing::warn!(
"failed to load cookie store: {_e}, falling back to empty store"
);
CookieStoreMutex::new(path, Default::default())
})
};
let state = Http {
#[cfg(feature = "cookies")]
cookies_jar: std::sync::Arc::new(reqwest::cookie::Jar::default()),
cookies_jar: std::sync::Arc::new(cookies_jar),
};
app.manage(state);
Ok(())
})
.on_event(|app, event| {
#[cfg(feature = "cookies")]
if let tauri::RunEvent::Exit = event {
let state = app.state::<Http>();
match state.cookies_jar.request_save() {
Ok(rx) => {
let _ = rx.recv();
}
Err(_e) => {
#[cfg(feature = "tracing")]
tracing::error!("failed to save cookie jar: {_e}");
}
}
}
})
.invoke_handler(tauri::generate_handler![
commands::fetch,
commands::fetch_cancel,
+133
View File
@@ -0,0 +1,133 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
// taken from https://github.com/pfernie/reqwest_cookie_store/blob/2ec4afabcd55e24d3afe3f0626ee6dc97bed938d/src/lib.rs
use std::{
path::PathBuf,
sync::{mpsc::Receiver, Mutex},
};
use cookie_store::{CookieStore, RawCookie, RawCookieParseError};
use reqwest::header::HeaderValue;
fn set_cookies(
cookie_store: &mut CookieStore,
cookie_headers: &mut dyn Iterator<Item = &HeaderValue>,
url: &url::Url,
) {
let cookies = cookie_headers.filter_map(|val| {
std::str::from_utf8(val.as_bytes())
.map_err(RawCookieParseError::from)
.and_then(RawCookie::parse)
.map(|c| c.into_owned())
.ok()
});
cookie_store.store_response_cookies(cookies, url);
}
fn cookies(cookie_store: &CookieStore, url: &url::Url) -> Option<HeaderValue> {
let s = cookie_store
.get_request_values(url)
.map(|(name, value)| format!("{}={}", name, value))
.collect::<Vec<_>>()
.join("; ");
if s.is_empty() {
return None;
}
HeaderValue::from_maybe_shared(bytes::Bytes::from(s)).ok()
}
/// A [`cookie_store::CookieStore`] wrapped internally by a [`std::sync::Mutex`], suitable for use in
/// async/concurrent contexts.
#[derive(Debug)]
pub struct CookieStoreMutex {
pub path: PathBuf,
store: Mutex<CookieStore>,
save_task: Mutex<Option<CancellableTask>>,
}
impl CookieStoreMutex {
/// Create a new [`CookieStoreMutex`] from an existing [`cookie_store::CookieStore`].
pub fn new(path: PathBuf, cookie_store: CookieStore) -> CookieStoreMutex {
CookieStoreMutex {
path,
store: Mutex::new(cookie_store),
save_task: Default::default(),
}
}
pub fn load<R: std::io::BufRead>(
path: PathBuf,
reader: R,
) -> cookie_store::Result<CookieStoreMutex> {
cookie_store::serde::load(reader, |c| serde_json::from_str(c))
.map(|store| CookieStoreMutex::new(path, store))
}
fn cookies_to_str(&self) -> Result<String, serde_json::Error> {
let mut cookies = Vec::new();
for cookie in self
.store
.lock()
.expect("poisoned cookie jar mutex")
.iter_unexpired()
{
if cookie.is_persistent() {
cookies.push(cookie.clone());
}
}
serde_json::to_string(&cookies)
}
pub fn request_save(&self) -> cookie_store::Result<Receiver<()>> {
let cookie_str = self.cookies_to_str()?;
let path = self.path.clone();
let (tx, rx) = std::sync::mpsc::channel();
let task = tauri::async_runtime::spawn(async move {
match tokio::fs::write(&path, &cookie_str).await {
Ok(()) => {
let _ = tx.send(());
}
Err(_e) => {
#[cfg(feature = "tracing")]
tracing::error!("failed to save cookie jar: {_e}");
}
}
});
self.save_task
.lock()
.unwrap()
.replace(CancellableTask(task));
Ok(rx)
}
}
impl reqwest::cookie::CookieStore for CookieStoreMutex {
fn set_cookies(&self, cookie_headers: &mut dyn Iterator<Item = &HeaderValue>, url: &url::Url) {
set_cookies(&mut self.store.lock().unwrap(), cookie_headers, url);
// try to persist cookies immediately asynchronously
if let Err(_e) = self.request_save() {
#[cfg(feature = "tracing")]
tracing::error!("failed to save cookie jar: {_e}");
}
}
fn cookies(&self, url: &url::Url) -> Option<HeaderValue> {
let store = self.store.lock().unwrap();
cookies(&store, url)
}
}
#[derive(Debug)]
struct CancellableTask(tauri::async_runtime::JoinHandle<()>);
impl Drop for CancellableTask {
fn drop(&mut self) {
self.0.abort();
}
}
+10
View File
@@ -1,5 +1,15 @@
# Changelog
## \[2.4.0]
- [`c9b21f6f`](https://github.com/tauri-apps/plugins-workspace/commit/c9b21f6f4345806eff5f495885f20dea0082b7d7) ([#2625](https://github.com/tauri-apps/plugins-workspace/pull/2625) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Export the `LogLevel` type.
- [`9629c2f4`](https://github.com/tauri-apps/plugins-workspace/commit/9629c2f4f90a56b5c2d265d1d13d3af40fc0c525) ([#2600](https://github.com/tauri-apps/plugins-workspace/pull/2600) by [@exoego](https://github.com/tauri-apps/plugins-workspace/../../exoego)) Adds a new varient `TargetKind::Dispatch` that allows you to construct arbitrary log targets
- [`686a839c`](https://github.com/tauri-apps/plugins-workspace/commit/686a839c96fae1b0334f2df9dc76ca5cdbe00dbe) ([#2626](https://github.com/tauri-apps/plugins-workspace/pull/2626) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fix iOS app stuck when using the iOS Simulator and the log plugin due to a deadlock when calling os_log too early.
### feat
- [`60fc35d3`](https://github.com/tauri-apps/plugins-workspace/commit/60fc35d35cccaf1654eceb4446ecf0f89dc15502) ([#2576](https://github.com/tauri-apps/plugins-workspace/pull/2576) by [@3lpsy](https://github.com/tauri-apps/plugins-workspace/../../3lpsy)) Add a `tracing` feature to the `log` plugin that emits log messages to the `tracing` system.
## \[2.3.1]
- [`1bb1ced5`](https://github.com/tauri-apps/plugins-workspace/commit/1bb1ced53820127204aa7adf57510c1cbce55e12) ([#2524](https://github.com/tauri-apps/plugins-workspace/pull/2524) by [@elwerene](https://github.com/tauri-apps/plugins-workspace/../../elwerene)) enable TargetKind::LogDir on mobile
+5 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-log"
version = "2.3.1"
version = "2.4.0"
description = "Configurable logging for your Tauri app."
authors = { workspace = true }
license = { workspace = true }
@@ -31,8 +31,10 @@ thiserror = { workspace = true }
serde_repr = "0.1"
byte-unit = "5"
log = { workspace = true, features = ["kv_unstable"] }
time = { version = "0.3", features = ["formatting", "local-offset"] }
time = { version = "0.3", features = ["formatting", "local-offset", "macros"] }
fern = "0.7"
tracing = { workspace = true, optional = true }
[target."cfg(target_os = \"android\")".dependencies]
android_logger = "0.15"
@@ -47,3 +49,4 @@ objc2-foundation = { version = "0.3", default-features = false, features = [
[features]
colored = ["fern/colored"]
tracing = ["dep:tracing"]
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_LOG__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var a,t;async function o(e,a,t){const o={kind:"Any"};return r("plugin:event|listen",{event:e,target:o,handler:n(a)}).then((n=>async()=>async function(e,n){await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}async function i(e,n,a){const t=function(e){if(e){if(!e.startsWith("Error")){const n=e.split("\n").map((e=>e.split("@"))).filter((([e,n])=>e.length>0&&"[native code]"!==n));return n[2]?.filter((e=>e.length>0)).join("@")}{const n=e.split("\n"),r=n[3]?.trim();if(!r)return;const a=/at\s+(?<functionName>.*?)\s+\((?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)\)/,t=r.match(a);if(t){const{functionName:e,fileName:n,lineNumber:r,columnNumber:a}=t.groups;return`${e}@${n}:${r}:${a}`}{const e=/at\s+(?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)/,n=r.match(e);if(n){const{fileName:e,lineNumber:r,columnNumber:a}=n.groups;return`<anonymous>@${e}:${r}:${a}`}}}}}((new Error).stack),{file:o,line:i,keyValues:u}=a??{};await r("plugin:log|log",{level:e,message:n,location:t,file:o,line:i,keyValues:u})}async function u(e){return await o("log://log",(n=>{const{level:r}=n.payload;let{message:a}=n.payload;a=a.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),e({message:a,level:r})}))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(a||(a={})),function(e){e[e.Trace=1]="Trace",e[e.Debug=2]="Debug",e[e.Info=3]="Info",e[e.Warn=4]="Warn",e[e.Error=5]="Error"}(t||(t={})),e.attachConsole=async function(){return await u((({level:e,message:n})=>{switch(e){case t.Trace:console.log(n);break;case t.Debug:console.debug(n);break;case t.Info:console.info(n);break;case t.Warn:console.warn(n);break;case t.Error:console.error(n);break;default:throw new Error(`unknown log level ${e}`)}}))},e.attachLogger=u,e.debug=async function(e,n){await i(t.Debug,e,n)},e.error=async function(e,n){await i(t.Error,e,n)},e.info=async function(e,n){await i(t.Info,e,n)},e.trace=async function(e,n){await i(t.Trace,e,n)},e.warn=async function(e,n){await i(t.Warn,e,n)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_PLUGIN_LOG__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_LOG__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var a,o;async function t(e,a,o){const t={kind:"Any"};return r("plugin:event|listen",{event:e,target:t,handler:n(a)}).then((n=>async()=>async function(e,n){await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}async function i(e,n,a){const o=function(e){if(e){if(!e.startsWith("Error")){const n=e.split("\n").map((e=>e.split("@"))).filter((([e,n])=>e.length>0&&"[native code]"!==n));return n[2]?.filter((e=>e.length>0)).join("@")}{const n=e.split("\n"),r=n[3]?.trim();if(!r)return;const a=/at\s+(?<functionName>.*?)\s+\((?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)\)/,o=r.match(a);if(o){const{functionName:e,fileName:n,lineNumber:r,columnNumber:a}=o.groups;return`${e}@${n}:${r}:${a}`}{const e=/at\s+(?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)/,n=r.match(e);if(n){const{fileName:e,lineNumber:r,columnNumber:a}=n.groups;return`<anonymous>@${e}:${r}:${a}`}}}}}((new Error).stack),{file:t,line:i,keyValues:l}=a??{};await r("plugin:log|log",{level:e,message:n,location:o,file:t,line:i,keyValues:l})}async function l(e){return await t("log://log",(n=>{const{level:r}=n.payload;let{message:a}=n.payload;a=a.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),e({message:a,level:r})}))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(a||(a={})),e.LogLevel=void 0,(o=e.LogLevel||(e.LogLevel={}))[o.Trace=1]="Trace",o[o.Debug=2]="Debug",o[o.Info=3]="Info",o[o.Warn=4]="Warn",o[o.Error=5]="Error",e.attachConsole=async function(){return await l((({level:n,message:r})=>{switch(n){case e.LogLevel.Trace:console.log(r);break;case e.LogLevel.Debug:console.debug(r);break;case e.LogLevel.Info:console.info(r);break;case e.LogLevel.Warn:console.warn(r);break;case e.LogLevel.Error:console.error(r);break;default:throw new Error(`unknown log level ${n}`)}}))},e.attachLogger=l,e.debug=async function(n,r){await i(e.LogLevel.Debug,n,r)},e.error=async function(n,r){await i(e.LogLevel.Error,n,r)},e.info=async function(n,r){await i(e.LogLevel.Info,n,r)},e.trace=async function(n,r){await i(e.LogLevel.Trace,n,r)},e.warn=async function(n,r){await i(e.LogLevel.Warn,n,r)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_PLUGIN_LOG__})}
+1 -1
View File
@@ -11,7 +11,7 @@ export interface LogOptions {
keyValues?: Record<string, string | undefined>
}
enum LogLevel {
export enum LogLevel {
/**
* The "trace" level.
*
+33 -8
View File
@@ -2,16 +2,41 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import UIKit
import Tauri
import SwiftRs
import Tauri
import UIKit
#if targetEnvironment(simulator)
var logReady = false
#else
var logReady = true
#endif
@_cdecl("tauri_log")
func log(level: Int, message: NSString) {
switch level {
case 1: Logger.debug(message as String)
case 2: Logger.info(message as String)
case 3: Logger.error(message as String)
default: break
}
if logReady {
os_log(level, message)
} else {
dispatch_log(level, message)
}
}
func dispatch_log(_ level: Int, _ message: NSString) {
// delay logging when the logger isn't immediately available
// in some cases when using the simulator the app would hang when calling os_log too soon
// better be safe here and wait a few seconds than actually freeze the app in dev mode
// in production this isn't a problem
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
os_log(level, message)
logReady = true
}
}
func os_log(_ level: Int, _ message: NSString) {
switch level {
case 1: Logger.debug(message as String)
case 2: Logger.info(message as String)
case 3: Logger.error(message as String)
default: break
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-log",
"version": "2.3.1",
"version": "2.4.0",
"description": "Configurable logging for your Tauri app.",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -2,6 +2,8 @@
Allows the log command
#### This default permission set includes the following:
- `allow-log`
## Permission Table
+9 -6
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,17 +297,20 @@
{
"description": "Enables the log command without any pre-configured scope.",
"type": "string",
"const": "allow-log"
"const": "allow-log",
"markdownDescription": "Enables the log command without any pre-configured scope."
},
{
"description": "Denies the log command without any pre-configured scope.",
"type": "string",
"const": "deny-log"
"const": "deny-log",
"markdownDescription": "Denies the log command without any pre-configured scope."
},
{
"description": "Allows the log command",
"description": "Allows the log command\n#### This default permission set includes:\n\n- `allow-log`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "Allows the log command\n#### This default permission set includes:\n\n- `allow-log`"
}
]
}
+48 -18
View File
@@ -27,9 +27,9 @@ use tauri::{
Manager, Runtime,
};
use tauri::{AppHandle, Emitter};
use time::{macros::format_description, OffsetDateTime};
pub use fern;
use time::OffsetDateTime;
pub const WEBVIEW_TARGET: &str = "webview";
@@ -170,6 +170,10 @@ pub enum TargetKind {
///
/// This requires the webview to subscribe to log events, via this plugins `attachConsole` function.
Webview,
/// Send logs to a [`fern::Dispatch`]
///
/// You can use this to construct arbitrary log targets.
Dispatch(fern::Dispatch),
}
/// A log target.
@@ -197,6 +201,38 @@ impl Target {
}
}
// Target becomes default and location is added as a parameter
#[cfg(feature = "tracing")]
fn emit_trace(
level: log::Level,
message: &String,
location: Option<&str>,
file: Option<&str>,
line: Option<u32>,
kv: &HashMap<&str, &str>,
) {
macro_rules! emit_event {
($level:expr) => {
tracing::event!(
target: WEBVIEW_TARGET,
$level,
message = %message,
location = location,
file,
line,
?kv
)
};
}
match level {
log::Level::Error => emit_event!(tracing::Level::ERROR),
log::Level::Warn => emit_event!(tracing::Level::WARN),
log::Level::Info => emit_event!(tracing::Level::INFO),
log::Level::Debug => emit_event!(tracing::Level::DEBUG),
log::Level::Trace => emit_event!(tracing::Level::TRACE),
}
}
#[tauri::command]
fn log(
level: LogLevel,
@@ -223,6 +259,8 @@ fn log(
kv.insert(k.as_str(), v.as_str());
}
builder.key_values(&kv);
#[cfg(feature = "tracing")]
emit_trace(level, &message, location, file, line, &kv);
logger().log(&builder.args(format_args!("{message}")).build());
}
@@ -239,9 +277,7 @@ pub struct Builder {
impl Default for Builder {
fn default() -> Self {
#[cfg(desktop)]
let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
.unwrap();
let format = format_description!("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]");
let dispatch = fern::Dispatch::new().format(move |out, message, record| {
out.finish(
#[cfg(mobile)]
@@ -280,9 +316,7 @@ impl Builder {
pub fn timezone_strategy(mut self, timezone_strategy: TimezoneStrategy) -> Self {
self.timezone_strategy = timezone_strategy.clone();
let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
.unwrap();
let format = format_description!("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]");
self.dispatch = self.dispatch.format(move |out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
@@ -346,7 +380,7 @@ impl Builder {
/// Skip the creation and global registration of a logger
///
/// If you wish to use your own global logger, you must call `skip_logger` so that the plugin does not attempt to set a second global logger. In this configuration, no logger will be created and the plugin's `log` command will rely on the result of `log::logger()`. You will be responsible for configuring the logger yourself and any included targets will be ignored. This can also be used with `tracing-log` or if running tests in parallel that require the plugin to be registered.
/// If you wish to use your own global logger, you must call `skip_logger` so that the plugin does not attempt to set a second global logger. In this configuration, no logger will be created and the plugin's `log` command will rely on the result of `log::logger()`. You will be responsible for configuring the logger yourself and any included targets will be ignored. If ever initializing the plugin multiple times, such as if registering the plugin while testing, call this method to avoid panicking when registering multiple loggers. For interacting with `tracing`, you can leverage the `tracing-log` logger to forward logs to `tracing` or enable the `tracing` feature for this plugin to emit events directly to the tracing system. Both scenarios require calling this method.
/// ```rust
/// static LOGGER: SimpleLogger = SimpleLogger;
///
@@ -360,12 +394,11 @@ impl Builder {
self
}
/// Adds a collection of targets to the logger.
/// Replaces the targets of the logger.
///
/// ```rust
/// use tauri_plugin_log::{Target, TargetKind, WEBVIEW_TARGET};
/// tauri_plugin_log::Builder::new()
/// .clear_targets()
/// .targets([
/// Target::new(TargetKind::Webview),
/// Target::new(TargetKind::LogDir { file_name: Some("webview".into()) }).filter(|metadata| metadata.target().starts_with(WEBVIEW_TARGET)),
@@ -379,9 +412,7 @@ impl Builder {
#[cfg(feature = "colored")]
pub fn with_colors(self, colors: fern::colors::ColoredLevelConfig) -> Self {
let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
.unwrap();
let format = format_description!("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]");
let timezone_strategy = self.timezone_strategy.clone();
self.format(move |out, message, record| {
@@ -481,6 +512,7 @@ impl Builder {
});
})
}
TargetKind::Dispatch(dispatch) => dispatch.into(),
};
target_dispatch = target_dispatch.chain(logger);
@@ -562,11 +594,9 @@ fn get_log_file_path(
let to = dir.as_ref().join(format!(
"{}_{}.log",
file_name,
timezone_strategy
.get_now()
.format(&time::format_description::parse(
"[year]-[month]-[day]_[hour]-[minute]-[second]"
)?)?,
timezone_strategy.get_now().format(&format_description!(
"[year]-[month]-[day]_[hour]-[minute]-[second]"
))?,
));
if to.is_file() {
// designated rotated log file name already exists
@@ -11,6 +11,8 @@ Writing to tags needs to be manually enabled.
#### This default permission set includes the following:
- `allow-is-available`
- `allow-scan`
+17 -10
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,37 +297,44 @@
{
"description": "Enables the is_available command without any pre-configured scope.",
"type": "string",
"const": "allow-is-available"
"const": "allow-is-available",
"markdownDescription": "Enables the is_available command without any pre-configured scope."
},
{
"description": "Denies the is_available command without any pre-configured scope.",
"type": "string",
"const": "deny-is-available"
"const": "deny-is-available",
"markdownDescription": "Denies the is_available command without any pre-configured scope."
},
{
"description": "Enables the scan command without any pre-configured scope.",
"type": "string",
"const": "allow-scan"
"const": "allow-scan",
"markdownDescription": "Enables the scan command without any pre-configured scope."
},
{
"description": "Denies the scan command without any pre-configured scope.",
"type": "string",
"const": "deny-scan"
"const": "deny-scan",
"markdownDescription": "Denies the scan command without any pre-configured scope."
},
{
"description": "Enables the write command without any pre-configured scope.",
"type": "string",
"const": "allow-write"
"const": "allow-write",
"markdownDescription": "Enables the write command without any pre-configured scope."
},
{
"description": "Denies the write command without any pre-configured scope.",
"type": "string",
"const": "deny-write"
"const": "deny-write",
"markdownDescription": "Denies the write command without any pre-configured scope."
},
{
"description": "This permission set configures what kind of\noperations are available from the nfc plugin.\n\n#### Granted Permissions\n\nChecking if the NFC functionality is available\nand scanning nearby tags is allowed.\nWriting to tags needs to be manually enabled.\n\n",
"description": "This permission set configures what kind of\noperations are available from the nfc plugin.\n\n#### Granted Permissions\n\nChecking if the NFC functionality is available\nand scanning nearby tags is allowed.\nWriting to tags needs to be manually enabled.\n\n\n#### This default permission set includes:\n\n- `allow-is-available`\n- `allow-scan`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures what kind of\noperations are available from the nfc plugin.\n\n#### Granted Permissions\n\nChecking if the NFC functionality is available\nand scanning nearby tags is allowed.\nWriting to tags needs to be manually enabled.\n\n\n#### This default permission set includes:\n\n- `allow-is-available`\n- `allow-scan`"
}
]
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function n(i,n,t,e){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?e:"a"===t?e.call(i):e?e.value:n.get(i)}function t(i,n,t,e,o){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(i,t),t}var e,o,a;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class c{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,e.set(this,(()=>{})),o.set(this,0),a.set(this,[]),this.id=function(i,n=!1){return window.__TAURI_INTERNALS__.transformCallback(i,n)}((({message:i,id:r})=>{if(r==n(this,o,"f"))for(n(this,e,"f").call(this,i),t(this,o,n(this,o,"f")+1);n(this,o,"f")in n(this,a,"f");){const i=n(this,a,"f")[n(this,o,"f")];n(this,e,"f").call(this,i),delete n(this,a,"f")[n(this,o,"f")],t(this,o,n(this,o,"f")+1)}else n(this,a,"f")[r]=i}))}set onmessage(i){t(this,e,i)}get onmessage(){return n(this,e,"f")}[(e=new WeakMap,o=new WeakMap,a=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}class s{constructor(i,n,t){this.plugin=i,this.event=n,this.channelId=t}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(i,n,t){const e=new c;return e.onmessage=t,u(`plugin:${i}|registerListener`,{event:n,handler:e}).then((()=>new s(i,n,e.id)))}async function u(i,n={},t){return window.__TAURI_INTERNALS__.invoke(i,n,t)}var f,h,d;i.ScheduleEvery=void 0,(f=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",f.Month="month",f.TwoWeeks="twoWeeks",f.Week="week",f.Day="day",f.Hour="hour",f.Minute="minute",f.Second="second";return i.Importance=void 0,(h=i.Importance||(i.Importance={}))[h.None=0]="None",h[h.Min=1]="Min",h[h.Low=2]="Low",h[h.Default=3]="Default",h[h.High=4]="High",i.Visibility=void 0,(d=i.Visibility||(i.Visibility={}))[d.Secret=-1]="Secret",d[d.Private=0]="Private",d[d.Public=1]="Public",i.Schedule=class{static at(i,n=!1,t=!1){return{at:{date:i,repeating:n,allowWhileIdle:t},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,t=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:t}}}},i.active=async function(){return await u("plugin:notification|get_active")},i.cancel=async function(i){await u("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await u("plugin:notification|cancel")},i.channels=async function(){return await u("plugin:notification|listChannels")},i.createChannel=async function(i){await u("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await u("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await l("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await l("notification","notification",i)},i.pending=async function(){return await u("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await u("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await u("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await u("plugin:notification|remove_active")},i.removeChannel=async function(i){await u("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function t(i,t,n,e){if("function"==typeof t||!t.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?e:"a"===n?e.call(i):e?e.value:t.get(i)}function n(i,t,n,e,a){if("function"==typeof t||!t.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(i,n),n}var e,a,o,r;"function"==typeof SuppressedError&&SuppressedError;const c="__TAURI_TO_IPC_KEY__";class s{constructor(i){e.set(this,void 0),a.set(this,0),o.set(this,[]),r.set(this,void 0),n(this,e,i||(()=>{})),this.id=function(i,t=!1){return window.__TAURI_INTERNALS__.transformCallback(i,t)}((i=>{const c=i.index;if("end"in i)return void(c==t(this,a,"f")?this.cleanupCallback():n(this,r,c));const s=i.message;if(c==t(this,a,"f")){for(t(this,e,"f").call(this,s),n(this,a,t(this,a,"f")+1);t(this,a,"f")in t(this,o,"f");){const i=t(this,o,"f")[t(this,a,"f")];t(this,e,"f").call(this,i),delete t(this,o,"f")[t(this,a,"f")],n(this,a,t(this,a,"f")+1)}t(this,a,"f")===t(this,r,"f")&&this.cleanupCallback()}else t(this,o,"f")[c]=s}))}cleanupCallback(){Reflect.deleteProperty(window,`_${this.id}`)}set onmessage(i){n(this,e,i)}get onmessage(){return t(this,e,"f")}[(e=new WeakMap,a=new WeakMap,o=new WeakMap,r=new WeakMap,c)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[c]()}}class l{constructor(i,t,n){this.plugin=i,this.event=t,this.channelId=n}async unregister(){return f(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function u(i,t,n){const e=new s(n);return f(`plugin:${i}|registerListener`,{event:t,handler:e}).then((()=>new l(i,t,e.id)))}async function f(i,t={},n){return window.__TAURI_INTERNALS__.invoke(i,t,n)}var h,d,w;i.ScheduleEvery=void 0,(h=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",h.Month="month",h.TwoWeeks="twoWeeks",h.Week="week",h.Day="day",h.Hour="hour",h.Minute="minute",h.Second="second";return i.Importance=void 0,(d=i.Importance||(i.Importance={}))[d.None=0]="None",d[d.Min=1]="Min",d[d.Low=2]="Low",d[d.Default=3]="Default",d[d.High=4]="High",i.Visibility=void 0,(w=i.Visibility||(i.Visibility={}))[w.Secret=-1]="Secret",w[w.Private=0]="Private",w[w.Public=1]="Public",i.Schedule=class{static at(i,t=!1,n=!1){return{at:{date:i,repeating:t,allowWhileIdle:n},interval:void 0,every:void 0}}static interval(i,t=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:t},every:void 0}}static every(i,t,n=!1){return{at:void 0,interval:void 0,every:{interval:i,count:t,allowWhileIdle:n}}}},i.active=async function(){return await f("plugin:notification|get_active")},i.cancel=async function(i){await f("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await f("plugin:notification|cancel")},i.channels=async function(){return await f("plugin:notification|listChannels")},i.createChannel=async function(i){await f("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await f("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await u("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await u("notification","notification",i)},i.pending=async function(){return await f("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await f("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await f("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await f("plugin:notification|remove_active")},i.removeChannel=async function(i){await f("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
@@ -9,6 +9,8 @@ It allows all notification related features.
#### This default permission set includes the following:
- `allow-is-permission-granted`
- `allow-request-permission`
- `allow-notify`
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,167 +297,200 @@
{
"description": "Enables the batch command without any pre-configured scope.",
"type": "string",
"const": "allow-batch"
"const": "allow-batch",
"markdownDescription": "Enables the batch command without any pre-configured scope."
},
{
"description": "Denies the batch command without any pre-configured scope.",
"type": "string",
"const": "deny-batch"
"const": "deny-batch",
"markdownDescription": "Denies the batch command without any pre-configured scope."
},
{
"description": "Enables the cancel command without any pre-configured scope.",
"type": "string",
"const": "allow-cancel"
"const": "allow-cancel",
"markdownDescription": "Enables the cancel command without any pre-configured scope."
},
{
"description": "Denies the cancel command without any pre-configured scope.",
"type": "string",
"const": "deny-cancel"
"const": "deny-cancel",
"markdownDescription": "Denies the cancel command without any pre-configured scope."
},
{
"description": "Enables the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-check-permissions"
"const": "allow-check-permissions",
"markdownDescription": "Enables the check_permissions command without any pre-configured scope."
},
{
"description": "Denies the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-check-permissions"
"const": "deny-check-permissions",
"markdownDescription": "Denies the check_permissions command without any pre-configured scope."
},
{
"description": "Enables the create_channel command without any pre-configured scope.",
"type": "string",
"const": "allow-create-channel"
"const": "allow-create-channel",
"markdownDescription": "Enables the create_channel command without any pre-configured scope."
},
{
"description": "Denies the create_channel command without any pre-configured scope.",
"type": "string",
"const": "deny-create-channel"
"const": "deny-create-channel",
"markdownDescription": "Denies the create_channel command without any pre-configured scope."
},
{
"description": "Enables the delete_channel command without any pre-configured scope.",
"type": "string",
"const": "allow-delete-channel"
"const": "allow-delete-channel",
"markdownDescription": "Enables the delete_channel command without any pre-configured scope."
},
{
"description": "Denies the delete_channel command without any pre-configured scope.",
"type": "string",
"const": "deny-delete-channel"
"const": "deny-delete-channel",
"markdownDescription": "Denies the delete_channel command without any pre-configured scope."
},
{
"description": "Enables the get_active command without any pre-configured scope.",
"type": "string",
"const": "allow-get-active"
"const": "allow-get-active",
"markdownDescription": "Enables the get_active command without any pre-configured scope."
},
{
"description": "Denies the get_active command without any pre-configured scope.",
"type": "string",
"const": "deny-get-active"
"const": "deny-get-active",
"markdownDescription": "Denies the get_active command without any pre-configured scope."
},
{
"description": "Enables the get_pending command without any pre-configured scope.",
"type": "string",
"const": "allow-get-pending"
"const": "allow-get-pending",
"markdownDescription": "Enables the get_pending command without any pre-configured scope."
},
{
"description": "Denies the get_pending command without any pre-configured scope.",
"type": "string",
"const": "deny-get-pending"
"const": "deny-get-pending",
"markdownDescription": "Denies the get_pending command without any pre-configured scope."
},
{
"description": "Enables the is_permission_granted command without any pre-configured scope.",
"type": "string",
"const": "allow-is-permission-granted"
"const": "allow-is-permission-granted",
"markdownDescription": "Enables the is_permission_granted command without any pre-configured scope."
},
{
"description": "Denies the is_permission_granted command without any pre-configured scope.",
"type": "string",
"const": "deny-is-permission-granted"
"const": "deny-is-permission-granted",
"markdownDescription": "Denies the is_permission_granted command without any pre-configured scope."
},
{
"description": "Enables the list_channels command without any pre-configured scope.",
"type": "string",
"const": "allow-list-channels"
"const": "allow-list-channels",
"markdownDescription": "Enables the list_channels command without any pre-configured scope."
},
{
"description": "Denies the list_channels command without any pre-configured scope.",
"type": "string",
"const": "deny-list-channels"
"const": "deny-list-channels",
"markdownDescription": "Denies the list_channels command without any pre-configured scope."
},
{
"description": "Enables the notify command without any pre-configured scope.",
"type": "string",
"const": "allow-notify"
"const": "allow-notify",
"markdownDescription": "Enables the notify command without any pre-configured scope."
},
{
"description": "Denies the notify command without any pre-configured scope.",
"type": "string",
"const": "deny-notify"
"const": "deny-notify",
"markdownDescription": "Denies the notify command without any pre-configured scope."
},
{
"description": "Enables the permission_state command without any pre-configured scope.",
"type": "string",
"const": "allow-permission-state"
"const": "allow-permission-state",
"markdownDescription": "Enables the permission_state command without any pre-configured scope."
},
{
"description": "Denies the permission_state command without any pre-configured scope.",
"type": "string",
"const": "deny-permission-state"
"const": "deny-permission-state",
"markdownDescription": "Denies the permission_state command without any pre-configured scope."
},
{
"description": "Enables the register_action_types command without any pre-configured scope.",
"type": "string",
"const": "allow-register-action-types"
"const": "allow-register-action-types",
"markdownDescription": "Enables the register_action_types command without any pre-configured scope."
},
{
"description": "Denies the register_action_types command without any pre-configured scope.",
"type": "string",
"const": "deny-register-action-types"
"const": "deny-register-action-types",
"markdownDescription": "Denies the register_action_types command without any pre-configured scope."
},
{
"description": "Enables the register_listener command without any pre-configured scope.",
"type": "string",
"const": "allow-register-listener"
"const": "allow-register-listener",
"markdownDescription": "Enables the register_listener command without any pre-configured scope."
},
{
"description": "Denies the register_listener command without any pre-configured scope.",
"type": "string",
"const": "deny-register-listener"
"const": "deny-register-listener",
"markdownDescription": "Denies the register_listener command without any pre-configured scope."
},
{
"description": "Enables the remove_active command without any pre-configured scope.",
"type": "string",
"const": "allow-remove-active"
"const": "allow-remove-active",
"markdownDescription": "Enables the remove_active command without any pre-configured scope."
},
{
"description": "Denies the remove_active command without any pre-configured scope.",
"type": "string",
"const": "deny-remove-active"
"const": "deny-remove-active",
"markdownDescription": "Denies the remove_active command without any pre-configured scope."
},
{
"description": "Enables the request_permission command without any pre-configured scope.",
"type": "string",
"const": "allow-request-permission"
"const": "allow-request-permission",
"markdownDescription": "Enables the request_permission command without any pre-configured scope."
},
{
"description": "Denies the request_permission command without any pre-configured scope.",
"type": "string",
"const": "deny-request-permission"
"const": "deny-request-permission",
"markdownDescription": "Denies the request_permission command without any pre-configured scope."
},
{
"description": "Enables the show command without any pre-configured scope.",
"type": "string",
"const": "allow-show"
"const": "allow-show",
"markdownDescription": "Enables the show command without any pre-configured scope."
},
{
"description": "Denies the show command without any pre-configured scope.",
"type": "string",
"const": "deny-show"
"const": "deny-show",
"markdownDescription": "Denies the show command without any pre-configured scope."
},
{
"description": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n",
"description": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`"
}
]
}
@@ -3,6 +3,8 @@
This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application
as well as reveal file in directories using default file explorer
#### This default permission set includes the following:
- `allow-open-url`
- `allow-reveal-item-in-dir`
- `allow-default-urls`
+19 -11
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,42 +297,50 @@
{
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
"type": "string",
"const": "allow-default-urls"
"const": "allow-default-urls",
"markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application."
},
{
"description": "Enables the open_path command without any pre-configured scope.",
"type": "string",
"const": "allow-open-path"
"const": "allow-open-path",
"markdownDescription": "Enables the open_path command without any pre-configured scope."
},
{
"description": "Denies the open_path command without any pre-configured scope.",
"type": "string",
"const": "deny-open-path"
"const": "deny-open-path",
"markdownDescription": "Denies the open_path command without any pre-configured scope."
},
{
"description": "Enables the open_url command without any pre-configured scope.",
"type": "string",
"const": "allow-open-url"
"const": "allow-open-url",
"markdownDescription": "Enables the open_url command without any pre-configured scope."
},
{
"description": "Denies the open_url command without any pre-configured scope.",
"type": "string",
"const": "deny-open-url"
"const": "deny-open-url",
"markdownDescription": "Denies the open_url command without any pre-configured scope."
},
{
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
"type": "string",
"const": "allow-reveal-item-in-dir"
"const": "allow-reveal-item-in-dir",
"markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope."
},
{
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
"type": "string",
"const": "deny-reveal-item-in-dir"
"const": "deny-reveal-item-in-dir",
"markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope."
},
{
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer",
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`"
}
]
}
@@ -10,6 +10,8 @@ All information except the host name are available.
#### This default permission set includes the following:
- `allow-arch`
- `allow-exe-extension`
- `allow-family`
+37 -20
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,87 +297,104 @@
{
"description": "Enables the arch command without any pre-configured scope.",
"type": "string",
"const": "allow-arch"
"const": "allow-arch",
"markdownDescription": "Enables the arch command without any pre-configured scope."
},
{
"description": "Denies the arch command without any pre-configured scope.",
"type": "string",
"const": "deny-arch"
"const": "deny-arch",
"markdownDescription": "Denies the arch command without any pre-configured scope."
},
{
"description": "Enables the exe_extension command without any pre-configured scope.",
"type": "string",
"const": "allow-exe-extension"
"const": "allow-exe-extension",
"markdownDescription": "Enables the exe_extension command without any pre-configured scope."
},
{
"description": "Denies the exe_extension command without any pre-configured scope.",
"type": "string",
"const": "deny-exe-extension"
"const": "deny-exe-extension",
"markdownDescription": "Denies the exe_extension command without any pre-configured scope."
},
{
"description": "Enables the family command without any pre-configured scope.",
"type": "string",
"const": "allow-family"
"const": "allow-family",
"markdownDescription": "Enables the family command without any pre-configured scope."
},
{
"description": "Denies the family command without any pre-configured scope.",
"type": "string",
"const": "deny-family"
"const": "deny-family",
"markdownDescription": "Denies the family command without any pre-configured scope."
},
{
"description": "Enables the hostname command without any pre-configured scope.",
"type": "string",
"const": "allow-hostname"
"const": "allow-hostname",
"markdownDescription": "Enables the hostname command without any pre-configured scope."
},
{
"description": "Denies the hostname command without any pre-configured scope.",
"type": "string",
"const": "deny-hostname"
"const": "deny-hostname",
"markdownDescription": "Denies the hostname command without any pre-configured scope."
},
{
"description": "Enables the locale command without any pre-configured scope.",
"type": "string",
"const": "allow-locale"
"const": "allow-locale",
"markdownDescription": "Enables the locale command without any pre-configured scope."
},
{
"description": "Denies the locale command without any pre-configured scope.",
"type": "string",
"const": "deny-locale"
"const": "deny-locale",
"markdownDescription": "Denies the locale command without any pre-configured scope."
},
{
"description": "Enables the os_type command without any pre-configured scope.",
"type": "string",
"const": "allow-os-type"
"const": "allow-os-type",
"markdownDescription": "Enables the os_type command without any pre-configured scope."
},
{
"description": "Denies the os_type command without any pre-configured scope.",
"type": "string",
"const": "deny-os-type"
"const": "deny-os-type",
"markdownDescription": "Denies the os_type command without any pre-configured scope."
},
{
"description": "Enables the platform command without any pre-configured scope.",
"type": "string",
"const": "allow-platform"
"const": "allow-platform",
"markdownDescription": "Enables the platform command without any pre-configured scope."
},
{
"description": "Denies the platform command without any pre-configured scope.",
"type": "string",
"const": "deny-platform"
"const": "deny-platform",
"markdownDescription": "Denies the platform command without any pre-configured scope."
},
{
"description": "Enables the version command without any pre-configured scope.",
"type": "string",
"const": "allow-version"
"const": "allow-version",
"markdownDescription": "Enables the version command without any pre-configured scope."
},
{
"description": "Denies the version command without any pre-configured scope.",
"type": "string",
"const": "deny-version"
"const": "deny-version",
"markdownDescription": "Denies the version command without any pre-configured scope."
},
{
"description": "This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n",
"description": "This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n\n#### This default permission set includes:\n\n- `allow-arch`\n- `allow-exe-extension`\n- `allow-family`\n- `allow-locale`\n- `allow-os-type`\n- `allow-platform`\n- `allow-version`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n\n#### This default permission set includes:\n\n- `allow-arch`\n- `allow-exe-extension`\n- `allow-family`\n- `allow-locale`\n- `allow-os-type`\n- `allow-platform`\n- `allow-version`"
}
]
}
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.1]
### Dependencies
- Upgraded to `fs@2.2.1`
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-persisted-scope"
version = "2.2.0"
version = "2.2.1"
description = "Save filesystem and asset scopes and restore them when the app is reopened."
authors = { workspace = true }
license = { workspace = true }
@@ -27,7 +27,7 @@ log = { workspace = true }
thiserror = { workspace = true }
aho-corasick = "1"
bincode = "1"
tauri-plugin-fs = { path = "../fs", version = "2.2.0" }
tauri-plugin-fs = { path = "../fs", version = "2.2.1" }
[features]
protocol-asset = ["tauri/protocol-asset"]
@@ -2,6 +2,8 @@
Allows the moveWindow and handleIconState APIs
#### This default permission set includes the following:
- `allow-move-window`
- `allow-move-window-constrained`
- `allow-set-tray-icon-state`
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,37 +297,44 @@
{
"description": "Enables the move_window command without any pre-configured scope.",
"type": "string",
"const": "allow-move-window"
"const": "allow-move-window",
"markdownDescription": "Enables the move_window command without any pre-configured scope."
},
{
"description": "Denies the move_window command without any pre-configured scope.",
"type": "string",
"const": "deny-move-window"
"const": "deny-move-window",
"markdownDescription": "Denies the move_window command without any pre-configured scope."
},
{
"description": "Enables the move_window_constrained command without any pre-configured scope.",
"type": "string",
"const": "allow-move-window-constrained"
"const": "allow-move-window-constrained",
"markdownDescription": "Enables the move_window_constrained command without any pre-configured scope."
},
{
"description": "Denies the move_window_constrained command without any pre-configured scope.",
"type": "string",
"const": "deny-move-window-constrained"
"const": "deny-move-window-constrained",
"markdownDescription": "Denies the move_window_constrained command without any pre-configured scope."
},
{
"description": "Enables the set_tray_icon_state command without any pre-configured scope.",
"type": "string",
"const": "allow-set-tray-icon-state"
"const": "allow-set-tray-icon-state",
"markdownDescription": "Enables the set_tray_icon_state command without any pre-configured scope."
},
{
"description": "Denies the set_tray_icon_state command without any pre-configured scope.",
"type": "string",
"const": "deny-set-tray-icon-state"
"const": "deny-set-tray-icon-state",
"markdownDescription": "Denies the set_tray_icon_state command without any pre-configured scope."
},
{
"description": "Allows the moveWindow and handleIconState APIs",
"description": "Allows the moveWindow and handleIconState APIs\n#### This default permission set includes:\n\n- `allow-move-window`\n- `allow-move-window-constrained`\n- `allow-set-tray-icon-state`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "Allows the moveWindow and handleIconState APIs\n#### This default permission set includes:\n\n- `allow-move-window`\n- `allow-move-window-constrained`\n- `allow-set-tray-icon-state`"
}
]
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`d2aef2fd`](https://github.com/tauri-apps/plugins-workspace/commit/d2aef2fddbdfad6526935c55ac10a94171a4f5f5) ([#2581](https://github.com/tauri-apps/plugins-workspace/pull/2581)) Migrate restart to use tauri's new `AppHandle::request_restart` method
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-process"
version = "2.2.0"
version = "2.2.1"
description = "Access the current process of your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-process",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -9,6 +9,8 @@ This enables to quit via `allow-exit` and restart via `allow-restart`
the application.
#### This default permission set includes the following:
- `allow-exit`
- `allow-restart`
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,27 +297,32 @@
{
"description": "Enables the exit command without any pre-configured scope.",
"type": "string",
"const": "allow-exit"
"const": "allow-exit",
"markdownDescription": "Enables the exit command without any pre-configured scope."
},
{
"description": "Denies the exit command without any pre-configured scope.",
"type": "string",
"const": "deny-exit"
"const": "deny-exit",
"markdownDescription": "Denies the exit command without any pre-configured scope."
},
{
"description": "Enables the restart command without any pre-configured scope.",
"type": "string",
"const": "allow-restart"
"const": "allow-restart",
"markdownDescription": "Enables the restart command without any pre-configured scope."
},
{
"description": "Denies the restart command without any pre-configured scope.",
"type": "string",
"const": "deny-restart"
"const": "deny-restart",
"markdownDescription": "Denies the restart command without any pre-configured scope."
},
{
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n\n#### This default permission set includes:\n\n- `allow-exit`\n- `allow-restart`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n\n#### This default permission set includes:\n\n- `allow-exit`\n- `allow-restart`"
}
]
}
+1 -1
View File
@@ -11,5 +11,5 @@ pub fn exit<R: Runtime>(app: AppHandle<R>, code: i32) {
#[tauri::command]
pub fn restart<R: Runtime>(app: AppHandle<R>) {
app.restart()
app.request_restart()
}
+7
View File
@@ -1,5 +1,12 @@
# Changelog
## \[2.2.1]
### bug
- [`9cf0390a`](https://github.com/tauri-apps/plugins-workspace/commit/9cf0390a52497e273db1a1b613a0e26827aa327c) Apply the default open validation regex `^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+` when the open configuration is not set, preventing unchecked input from being used in this scenario (previously the plugin would skip validation when it should disable all calls). This keeps backwards compatibility while still fixing this vulnerability.
The scope is no longer validated for Rust calls via `ShellExt::shell()` so if you need to block JavaScript from calling the API you can simply set `tauri.conf.json > plugins > shell > open` to `false`.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-shell"
version = "2.2.0"
version = "2.2.1"
description = "Access the system shell. Allows you to spawn child processes and manage files and URLs using their default application."
edition = { workspace = true }
authors = { workspace = true }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(e,t,s,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),n.set(this,0),r.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:o})=>{if(o==t(this,n,"f"))for(t(this,i,"f").call(this,e),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}else t(this,r,"f")[o]=e}))}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function h(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.prependListener(e,s)}}class l{constructor(e){this.pid=e}async write(e){await h("plugin:shell|stdin_write",{pid:this.pid,buffer:e})}async kill(){await h("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class u extends c{constructor(e,t=[],s){super(),this.stdout=new c,this.stderr=new c,this.program=e,this.args="string"==typeof t?[t]:t,this.options=s??{}}static create(e,t=[],s){return new u(e,t,s)}static sidecar(e,t=[],s){const i=new u(e,t,s);return i.options.sidecar=!0,i}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const i=new a;return i.onmessage=e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}},await h("plugin:shell|spawn",{program:e,args:t,options:s,onEvent:i}).then((e=>new l(e)))}async execute(){const e=this.program,t=this.args,s=this.options;return"object"==typeof t&&Object.freeze(t),await h("plugin:shell|execute",{program:e,args:t,options:s})}}return e.Child=l,e.Command=u,e.EventEmitter=c,e.open=async function(e,t){await h("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_PLUGIN_SHELL__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(e,t,s,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r,o;"function"==typeof SuppressedError&&SuppressedError;const a="__TAURI_TO_IPC_KEY__";class h{constructor(e){i.set(this,void 0),n.set(this,0),r.set(this,[]),o.set(this,void 0),s(this,i,e||(()=>{})),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((e=>{const a=e.index;if("end"in e)return void(a==t(this,n,"f")?this.cleanupCallback():s(this,o,a));const h=e.message;if(a==t(this,n,"f")){for(t(this,i,"f").call(this,h),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}t(this,n,"f")===t(this,o,"f")&&this.cleanupCallback()}else t(this,r,"f")[a]=h}))}cleanupCallback(){Reflect.deleteProperty(window,`_${this.id}`)}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o=new WeakMap,a)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[a]()}}async function c(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class l{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.prependListener(e,s)}}class u{constructor(e){this.pid=e}async write(e){await c("plugin:shell|stdin_write",{pid:this.pid,buffer:e})}async kill(){await c("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class p extends l{constructor(e,t=[],s){super(),this.stdout=new l,this.stderr=new l,this.program=e,this.args="string"==typeof t?[t]:t,this.options=s??{}}static create(e,t=[],s){return new p(e,t,s)}static sidecar(e,t=[],s){const i=new p(e,t,s);return i.options.sidecar=!0,i}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const i=new h;return i.onmessage=e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}},await c("plugin:shell|spawn",{program:e,args:t,options:s,onEvent:i}).then((e=>new u(e)))}async execute(){const e=this.program,t=this.args,s=this.options;return"object"==typeof t&&Object.freeze(t),await c("plugin:shell|execute",{program:e,args:t,options:s})}}return e.Child=u,e.Command=p,e.EventEmitter=l,e.open=async function(e,t){await c("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_PLUGIN_SHELL__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-shell",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -5,11 +5,13 @@ shell functionality is exposed by default.
#### Granted Permissions
It allows to use the `open` functionality without any specific
It allows to use the `open` functionality with a reasonable
scope pre-configured. It will allow opening `http(s)://`,
`tel:` and `mailto:` links.
#### This default permission set includes the following:
- `allow-open`
## Permission Table
+1 -1
View File
@@ -7,7 +7,7 @@ shell functionality is exposed by default.
#### Granted Permissions
It allows to use the `open` functionality without any specific
It allows to use the `open` functionality with a reasonable
scope pre-configured. It will allow opening `http(s)://`,
`tel:` and `mailto:` links.
"""
+25 -14
View File
@@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -297,57 +297,68 @@
{
"description": "Enables the execute command without any pre-configured scope.",
"type": "string",
"const": "allow-execute"
"const": "allow-execute",
"markdownDescription": "Enables the execute command without any pre-configured scope."
},
{
"description": "Denies the execute command without any pre-configured scope.",
"type": "string",
"const": "deny-execute"
"const": "deny-execute",
"markdownDescription": "Denies the execute command without any pre-configured scope."
},
{
"description": "Enables the kill command without any pre-configured scope.",
"type": "string",
"const": "allow-kill"
"const": "allow-kill",
"markdownDescription": "Enables the kill command without any pre-configured scope."
},
{
"description": "Denies the kill command without any pre-configured scope.",
"type": "string",
"const": "deny-kill"
"const": "deny-kill",
"markdownDescription": "Denies the kill command without any pre-configured scope."
},
{
"description": "Enables the open command without any pre-configured scope.",
"type": "string",
"const": "allow-open"
"const": "allow-open",
"markdownDescription": "Enables the open command without any pre-configured scope."
},
{
"description": "Denies the open command without any pre-configured scope.",
"type": "string",
"const": "deny-open"
"const": "deny-open",
"markdownDescription": "Denies the open command without any pre-configured scope."
},
{
"description": "Enables the spawn command without any pre-configured scope.",
"type": "string",
"const": "allow-spawn"
"const": "allow-spawn",
"markdownDescription": "Enables the spawn command without any pre-configured scope."
},
{
"description": "Denies the spawn command without any pre-configured scope.",
"type": "string",
"const": "deny-spawn"
"const": "deny-spawn",
"markdownDescription": "Denies the spawn command without any pre-configured scope."
},
{
"description": "Enables the stdin_write command without any pre-configured scope.",
"type": "string",
"const": "allow-stdin-write"
"const": "allow-stdin-write",
"markdownDescription": "Enables the stdin_write command without any pre-configured scope."
},
{
"description": "Denies the stdin_write command without any pre-configured scope.",
"type": "string",
"const": "deny-stdin-write"
"const": "deny-stdin-write",
"markdownDescription": "Denies the stdin_write command without any pre-configured scope."
},
{
"description": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n",
"description": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`",
"type": "string",
"const": "default"
"const": "default",
"markdownDescription": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`"
}
]
}
+1 -1
View File
@@ -311,5 +311,5 @@ pub async fn open<R: Runtime>(
path: String,
with: Option<Program>,
) -> crate::Result<()> {
shell.open(path, with)
crate::open::open(Some(&shell.open_scope), path, with)
}
+4 -1
View File
@@ -18,6 +18,9 @@ pub struct Config {
#[serde(untagged, deny_unknown_fields)]
#[non_exhaustive]
pub enum ShellAllowlistOpen {
/// Shell open API allowlist is not defined by the user.
/// In this case we add the default validation regex (same as [`Self::Flag(true)`]).
Unset,
/// If the shell open API should be enabled.
///
/// If enabled, the default validation regex (`^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+`) is used.
@@ -35,6 +38,6 @@ pub enum ShellAllowlistOpen {
impl Default for ShellAllowlistOpen {
fn default() -> Self {
Self::Flag(false)
Self::Unset
}
}

Some files were not shown because too many files have changed in this diff Show More