From 3251e03883cbfc47a9a767320365797fc645ac4c Mon Sep 17 00:00:00 2001 From: vasfvitor Date: Wed, 1 May 2024 12:58:07 -0300 Subject: [PATCH] expeirment: move files --- src/content/docs/develop/index.mdx | 26 + .../docs/{guides => }/develop/sidecar.mdx | 0 src/content/docs/guides/develop/index.mdx | 6 +- .../guides/upgrade-migrate/from-tauri-1.mdx | 12 +- .../start/Upgrade & Migrate/from-tauri-1.mdx | 1178 +++++++++++++++++ 5 files changed, 1206 insertions(+), 16 deletions(-) create mode 100644 src/content/docs/develop/index.mdx rename src/content/docs/{guides => }/develop/sidecar.mdx (100%) create mode 100644 src/content/docs/start/Upgrade & Migrate/from-tauri-1.mdx diff --git a/src/content/docs/develop/index.mdx b/src/content/docs/develop/index.mdx new file mode 100644 index 00000000000..3349c8bfddb --- /dev/null +++ b/src/content/docs/develop/index.mdx @@ -0,0 +1,26 @@ +--- +title: Develop +description: Core concepts for developing with Tauri. +sidebar: + order: 0 + label: Overview + badge: + text: WIP + variant: caution +--- + +import Stub from '@components/Stub.astro'; + + + + +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + + + + + + diff --git a/src/content/docs/guides/develop/sidecar.mdx b/src/content/docs/develop/sidecar.mdx similarity index 100% rename from src/content/docs/guides/develop/sidecar.mdx rename to src/content/docs/develop/sidecar.mdx diff --git a/src/content/docs/guides/develop/index.mdx b/src/content/docs/guides/develop/index.mdx index 2369b439ed5..24f3c1a598c 100644 --- a/src/content/docs/guides/develop/index.mdx +++ b/src/content/docs/guides/develop/index.mdx @@ -14,8 +14,4 @@ import { LinkCard, CardGrid } from '@astrojs/starlight/components'; title="Updating Dependencies" href="/guides/develop/updating-dependencies" /> - - + \ No newline at end of file diff --git a/src/content/docs/guides/upgrade-migrate/from-tauri-1.mdx b/src/content/docs/guides/upgrade-migrate/from-tauri-1.mdx index c54d09dfab5..fa79fbac9a1 100644 --- a/src/content/docs/guides/upgrade-migrate/from-tauri-1.mdx +++ b/src/content/docs/guides/upgrade-migrate/from-tauri-1.mdx @@ -74,7 +74,7 @@ Below is a summary of the changes from Tauri 1.0 to Tauri 2.0: - `package > productName` and `package > version` moved to top-level field. - `package` removed. - `tauri` key renamed to `app`. -- `tauri > allowlist` removed. Refer to [Migrate Permissions](migrate-permissions). +- `tauri > allowlist` removed. - `tauri > allowlist > protocol > assetScope` moved to `app > security > assetProtocol > scope`. - `tauri > cli` moved to `plugins > cli`. - `tauri > updater > active` removed. @@ -1156,16 +1156,6 @@ On the JavaScript side, the `WebviewWindow` class is now exported in the `@tauri The `onMenuClicked` function was removed, you can intercept menu events when creating a menu in JavaScript instead. -### Migrate Embedded External Binaries (Sidecar) - -In Tauri v1, the external binaries and their arguments were defined in the allowlist. In v2, use the new permissions system. Read [Migrate Permissions](#migrate-permissions) for more information. - -On the JavaScript side, make sure you [Migrate to Shell Plugin](#migrate-to-shell-plugin). - -On the Rust side, `tauri::api::process` API has been removed. Use `tauri_plugin_shell::ShellExt` and `tauri_plugin_shell::process::CommandEvent` APIs instead. Read the [Embedding External Binaries](/guides/develop/sidecar/#running-it-from-rust) guide to see how. - -The "process-command-api" features flag has been removed in v2. So running the external binaries does not require this feature to be defined in the Tauri config anymore. - ### Migrate Permissions The v1 allowlist have been rewritten to a completely new system for permissions that works for individual plugins and is much more configurable for multiwindow and remote URL support. diff --git a/src/content/docs/start/Upgrade & Migrate/from-tauri-1.mdx b/src/content/docs/start/Upgrade & Migrate/from-tauri-1.mdx new file mode 100644 index 00000000000..c54d09dfab5 --- /dev/null +++ b/src/content/docs/start/Upgrade & Migrate/from-tauri-1.mdx @@ -0,0 +1,1178 @@ +--- +title: Upgrade from Tauri 1.0 +i18nReady: true +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +This guide walks you through upgrading your Tauri 1.0 application to Tauri 2.0. + +## Preparing for Mobile + +The mobile interface of Tauri requires your project to output a shared library. If you are targetting mobile for your existing application, you must change your crate to produce that kind of artifact along with the desktop executable. + +1. Change the Cargo manifest to produce the library. Append the following block: + +```toml +// src-tauri/Cargo.toml +[lib] +name = "app_lib" +crate-type = ["staticlib", "cdylib", "rlib"] +``` + +2. Rename `src-tauri/src/main.rs` to `src-tauri/src/lib.rs`. This file will be shared by both desktop and mobile targets. + +3. Rename the `main` function header in `lib.rs` to the following: + +```rust +// src-tauri/src/lib.rs +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + // your code here +} +``` + +The `tauri::mobile_entry_point` macro prepares your function to be executed on mobile. + +4. Recreate the `main.rs` file calling the shared run function: + +```rust +// src-tauri/src/main.rs +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + app_lib::run(); +} +``` + +## Automated Migration + +The Tauri v2 CLI includes a `migrate` command that automates most of the process and helps you finish the migration: + + + +{/* TODO: 2.0 */} + +Learn more about the `migrate` command in the [Command Line Interface reference](/references/v2/cli#migrate) + +## Summary of Changes + +Below is a summary of the changes from Tauri 1.0 to Tauri 2.0: + +### Tauri Configuration + +- `package > productName` and `package > version` moved to top-level field. +- `package` removed. +- `tauri` key renamed to `app`. +- `tauri > allowlist` removed. Refer to [Migrate Permissions](migrate-permissions). +- `tauri > allowlist > protocol > assetScope` moved to `app > security > assetProtocol > scope`. +- `tauri > cli` moved to `plugins > cli`. +- `tauri > updater > active` removed. +- `tauri > updater > dialog` removed. +- `tauri > updater` moved to `plugins > updater`. +- `tauri > systemTray` renamed to `app > trayIcon`. +- `tauri > pattern` moved to `app > security > pattern`. +- `tauri > bundle` moved top-level. +- `tauri > bundle > dmg` moved to `bundle > macOS > dmg` +- `tauri > bundle > deb` moved to `bundle > linux > deb` +- `tauri > bundle > appimage` moved to `bundle > linux > appimage` +- `tauri > bundle > macOS > license` removed, use `bundle > licenseFile` instead. +- `tauri > bundle > windows > wix > license` removed, use `bundle > licenseFile` instead. +- `tauri > bundle > windows > nsis > license` removed, use `bundle > licenseFile` instead. +- `build > withGlobalTauri` moved to `app > withGlobalTauri`. +- `build > distDir` renamed to `frontendDist`. +- `build > devPath` renamed to `devUrl`. + +[Tauri 2.0 Configuration API reference](/references/v2/config) + +### New Cargo Features + +- linux-protocol-body: Enables custom protocol request body parsing, allowing the IPC to use it. Requires webkit2gtk 2.40. + +### Removed Cargo Features + +- reqwest-client: reqwest is now the only supported client. +- reqwest-native-tls-vendored: use `native-tls-vendored` instead. +- process-command-api: use the `shell` plugin instead (see instructions in the following section). +- shell-open-api: use the `shell` plugin instead (see instructions in the following section). +- windows7-compat: moved to the `notification` plugin. +- updater: Updater is now a plugin. +- linux-protocol-headers: Now enabled by default since we upgraded our minimum webkit2gtk version. +- system-tray: renamed to `tray-icon`. + +### Rust Crate Changes + +- `api` module removed. Each API module can be found in a Tauri plugin. +- `api::dialog` module removed. Use `tauri-plugin-dialog` instead. [Migration](#migrate-to-dialog-plugin) +- `api::file` module removed. Use Rust's [`std::fs`](https://doc.rust-lang.org/std/fs/) instead. +- `api::http` module removed. Use `tauri-plugin-http` instead. [Migration](#migrate-to-http-plugin) +- `api::ip` module rewritten and moved to `tauri::ipc`. Check out the new APIs, specially `tauri::ipc::Channel`. +- `api::path` module functions and `tauri::PathResolved` moved to `tauri::Manager::path`. [Migration](#migrate-path-to-tauri-manager) +- `api::process::Command`, `tauri::api::shell` and `tauri::Manager::shell_scope` APIs removed. Use `tauri-plugin-shell` instead. [Migration](#migrate-to-shell-plugin) +- `api::process::current_binary` and `tauri::api::process::restart` moved to `tauri::process`. +- `api::version` module has been removed. Use the [semver crate](https://docs.rs/semver/latest/semver/) instead. +- `App::clipboard_manager` and `AppHandle::clipboard_manager` removed. Use `tauri-plugin-clipboard` instead. [Migration](#migrate-to-clipboard-plugin) +- `App::get_cli_matches` removed. Use `tauri-plugin-cli` instead. [Migration](#migrate-to-cli-plugin) +- `App::global_shortcut_manager` and `AppHandle::global_shortcut_manager` removed. Use `tauri-plugin-global-shortcut` instead. [Migration](#migrate-to-global-shortcut-plugin) +- `Manager::fs_scope` removed. The file system scope can be accessed via `tauri_plugin_fs::FsExt`. +- `Plugin::PluginApi` now receives a plugin configuration as a second argument. +- `Plugin::setup_with_config` removed. Use the updated `tauri::Plugin::PluginApi` instead. +- `scope::ipc::RemoteDomainAccessScope::enable_tauri_api` and `scope::ipc::RemoteDomainAccessScope::enables_tauri_api` removed. Enable each core plugin individually via `scope::ipc::RemoteDomainAccessScope::add_plugin` instead. +- `scope::IpcScope` removed, use `scope::ipc::Scope` instead. +- `scope::IpcScope` removed, use `scope::ipc::Scope` instead. +- `scope::FsScope`, `scope::GlobPattern` and `scope::FsScopeEvent` removed, use `scope::fs::Scope`, `scope::fs::Pattern` and `scope::fs::Event` respectively. +- `updater` module removed. Use `tauri-plugin-updater` instead. [Migration](#migrate-to-updater-plugin) +- `Env.args` field has been removed, use `Env.args_os` field instead. +- `Menu`, `MenuEvent`, `CustomMenuItem`, `Submenu`, `WindowMenuEvent`, `MenuItem` and `Builder::on_menu_event` APIs removed. [Migration](#migrate-to-menu) +- `SystemTray`, `SystemTrayHandle`, `SystemTrayMenu`, `SystemTrayMenuItemHandle`, `SystemTraySubmenu`, `MenuEntry` and `SystemTrayMenuItem` APIs removed. [Migration](#migrate-to-tray-icon-module) + +### JavaScript API Changes + +The `@tauri-apps/api` package no longer provides non-core modules. Only the previous `tauri` (now `core`), `path`, `event` and `window` modules are exported. All others have been moved to plugins. + +- `@tauri-apps/api/tauri` module renamed to `@tauri-apps/api/core`. [Migration](#migrate-to-core-module) +- `@tauri-apps/api/cli` module removed. Use `@tauri-apps/plugin-cli` instead. [Migration](#migrate-to-cli-plugin) +- `@tauri-apps/api/clipboard` module removed. Use `@tauri-apps/plugin-clipboard` instead. [Migration](#migrate-to-clipboard-plugin) +- `@tauri-apps/api/dialog` module removed. Use `@tauri-apps/plugin-dialog` instead. [Migration](#migrate-to-dialog-plugin) +- `@tauri-apps/api/fs` module removed. Use `@tauri-apps/plugin-fs` instead. [Migration](#migrate-to-file-system-plugin) +- `@tauri-apps/api/global-shortcut` module removed. Use `@tauri-apps/plugin-global-shortcut` instead. [Migration](#migrate-to-global-shortcut-plugin) +- `@tauri-apps/api/http` module removed. Use `@tauri-apps/plugin-http` instead. [Migration](#migrate-to-http-plugin) +- `@tauri-apps/api/os` module removed. Use `@tauri-apps/plugin-os` instead. [Migration](#migrate-to-os-plugin) +- `@tauri-apps/api/notification` module removed. Use `@tauri-apps/plugin-notification` instead. [Migration](#migrate-to-notification-plugin) +- `@tauri-apps/api/process` module removed. Use `@tauri-apps/plugin-process` instead. [Migration](#migrate-to-process-plugin) +- `@tauri-apps/api/shell` module removed. Use `@tauri-apps/plugin-shell` instead. [Migration](#migrate-to-shell-plugin) +- `@tauri-apps/api/updater` module removed. Use `@tauri-apps/plugin-updater` instead [Migration](#migrate-to-updater-plugin) +- `@tauri-apps/api/window` module renamed to `@tauri-apps/api/webviewWindow`. [Migration](#migrate-to-new-window-api) + +### Environment Variables Changes + +Most of the environment variables read and written by the Tauri CLI were renamed for consistency and prevention of mistakes: + +- `TAURI_PRIVATE_KEY` -> `TAURI_SIGNING_PRIVATE_KEY` +- `TAURI_KEY_PASSWORD` -> `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` +- `TAURI_SKIP_DEVSERVER_CHECK` -> `TAURI_CLI_NO_DEV_SERVER_WAIT` +- `TAURI_DEV_SERVER_PORT` -> `TAURI_CLI_PORT` +- `TAURI_PATH_DEPTH` -> `TAURI_CLI_CONFIG_DEPTH` +- `TAURI_FIPS_COMPLIANT` -> `TAURI_BUNDLER_WIX_FIPS_COMPLIANT` +- `TAURI_DEV_WATCHER_IGNORE_FILE` -> `TAURI_CLI_WATCHER_IGNORE_FILENAME` +- `TAURI_TRAY` -> `TAURI_LINUX_AYATANA_APPINDICATOR` +- `TAURI_APPLE_DEVELOPMENT_TEAM` -> `APPLE_DEVELOPMENT_TEAM` +- `TAURI_PLATFORM` -> `TAURI_ENV_PLATFORM` +- `TAURI_ARCH` -> `TAURI_ENV_ARCH` +- `TAURI_FAMILY` -> `TAURI_ENV_FAMILY` +- `TAURI_PLATFORM_VERSION` -> `TAURI_ENV_PLATFORM_VERSION` +- `TAURI_PLATFORM_TYPE` -> `TAURI_ENV_PLATFORM_TYPE` +- `TAURI_DEBUG` -> `TAURI_ENV_DEBUG` + +### Event System + +The event system was redesigned to be easier to use. Instead of relying on the source of the event, it now has a simpler implementation that relies on event targets. + +- The `emit` function now emits the event to all event listeners +- Added a new `emit_to` function to trigger an event to a specific target +- `emit_filter` now filters based on [`EventTarget`](https://docs.rs/tauri/2.0.0-beta/tauri/event/enum.EventTarget.html) instead of a window. +- Renamed `listen_global` to `listen_any`. It now listens to all events regardless of their filters and targets. + +### Multiwebview support + +Tauri v2 introduces multiwebview support currently behind an `unstable` feature flag. +In order to support it, we renamed the Rust `Window` type to `WebviewWindow` and the Manager `get_window` function to `get_webview_window`. + +The `WebviewWindow` JS API type is now re-exported from `@tauri-apps/api/webviewWindow` instead of `@tauri-apps/api/window`. + +## Detailed Migration Steps + +Common scenarios you may encounter when migrating your Tauri 1.0 app to Tauri 2.0. + +### Migrate to Core Module + +The `@tauri-apps/api/tauri` module was renamed to `@tauri-apps/api/core`. +Simply rename the module import: + +```diff +- import { invoke } from "@tauri-apps/api/tauri" ++ import { invoke } from "@tauri-apps/api/core" +``` + +### Migrate to CLI Plugin + +The Rust `App::get_cli_matches` JavaScript `@tauri-apps/api/cli` APIs have been removed. Use the `@tauri-apps/plugin-cli` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-cli = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_cli::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-cli": "^2.0.0" + } +} +``` + +```js +import { getMatches } from '@tauri-apps/plugin-cli'; +const matches = await getMatches(); +``` + + + + +```rust +fn main() { + use tauri_plugin_cli::CliExt; + tauri::Builder::default() + .plugin(tauri_plugin_cli::init()) + .setup(|app| { + let cli_matches = app.cli().matches()?; + Ok(()) + }) +} +``` + + + + +### Migrate to Clipboard Plugin + +The Rust `App::clipboard_manager` and `AppHandle::clipboard_manager` and JavaScript `@tauri-apps/api/clipboard` APIs have been removed. Use the `@tauri-apps/plugin-clipboard-manager` plugin instead: + +```toml +[dependencies] +tauri-plugin-clipboard-manager = "2" +``` + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_clipboard_manager::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-clipboard-manager": "^2.0.0" + } +} +``` + +```js +import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager'; +await writeText('Tauri is awesome!'); +assert(await readText(), 'Tauri is awesome!'); +``` + + + + +```rust +use tauri_plugin_clipboard::{ClipboardExt, ClipKind}; +tauri::Builder::default() + .plugin(tauri_plugin_clipboard::init()) + .setup(|app| { + app.clipboard().write(ClipKind::PlainText { + label: None, + text: "Tauri is awesome!".into(), + })?; + Ok(()) + }) +``` + + + + +### Migrate to Dialog Plugin + +The Rust `tauri::api::dialog` JavaScript `@tauri-apps/api/dialog` APIs have been removed. Use the `@tauri-apps/plugin-dialog` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-dialog = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-dialog": "^2.0.0" + } +} +``` + +```js +import { save } from '@tauri-apps/plugin-dialog'; +const filePath = await save({ + filters: [ + { + name: 'Image', + extensions: ['png', 'jpeg'], + }, + ], +}); +``` + + + + +```rust +use tauri_plugin_dialog::DialogExt; +tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .setup(|app| { + app.dialog().file().pick_file(|file_path| { + // do something with the optional file path here + // the file path is `None` if the user closed the dialog + }); + + app.dialog().message("Tauri is Awesome!").show(); + Ok(()) + }) +``` + + + + +### Migrate to File System Plugin + +The Rust `App::get_cli_matches` JavaScript `@tauri-apps/api/fs` APIs have been removed. Use the [`std::fs`](https://doc.rust-lang.org/std/fs/) for Rust and `@tauri-apps/plugin-fs` plugin for JavaScript instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-fs = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_fs::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-fs": "^2.0.0" + } +} +``` + +```js +import { mkdir, BaseDirectory } from '@tauri-apps/plugin-fs'; +await mkdir('db', { baseDir: BaseDirectory.AppLocalData }); +``` + +Some functions and types have been renamed or removed: + +- `Dir` enum alias removed, use `BaseDirectory`. +- `FileEntry`, `FsBinaryFileOption`, `FsDirOptions`, `FsOptions`, `FsTextFileOption` and `BinaryFileContents` interfaces and type aliases have been removed and replaced with new interfaces suited for each function. +- `createDir` renamed to `mkdir`. +- `readBinaryFile` renamed to `readFile`. +- `removeDir` removed and replaced with `remove`. +- `removeFile` removed and replaced with `remove`. +- `renameFile` removed and replaced with `rename`. +- `writeBinaryFile` renamed to `writeFile`. + + + + +Use the Rust [`std::fs`](https://doc.rust-lang.org/std/fs/) functions. + + + + +### Migrate to Global Shortcut Plugin + +The Rust `App::global_shortcut_manager` and `AppHandle::global_shortcut_manager` and JavaScript `@tauri-apps/api/global-shortcut` APIs have been removed. Use the `@tauri-apps/plugin-global-shortcut` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] +tauri-plugin-global-shortcut = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_global_shortcut::Builder::default().build()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-global-shortcut": "^2.0.0" + } +} +``` + +```js +import { register } from '@tauri-apps/plugin-global-shortcut'; +await register('CommandOrControl+Shift+C', () => { + console.log('Shortcut triggered'); +}); +``` + + + + +```rust +use tauri_plugin_global_shortcut::GlobalShortcutExt; + +tauri::Builder::default() + .plugin( + tauri_plugin_global_shortcut::Builder::with_handler(|app, shortcut| { + println!("Shortcut triggered: {:?}", shortcut); + }) + .build(), + ) + .setup(|app| { + // register a global shortcut + // on macOS, the Cmd key is used + // on Windows and Linux, the Ctrl key is used + app.global_shortcut().register("CmdOrCtrl+Y")?; + Ok(()) + }) +``` + + + + +### Migrate to HTTP Plugin + +The Rust `tauri::api::http` JavaScript `@tauri-apps/api/http` APIs have been removed. Use the `@tauri-apps/plugin-http` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-http = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_http::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-http": "^2.0.0" + } +} +``` + +```js +import { fetch } from '@tauri-apps/plugin-http'; +const response = await fetch( + 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json' +); +``` + + + + +```rust +use tauri_plugin_dialog::reqwest; + +tauri::Builder::default() + .plugin(tauri_plugin_http::init()) + .setup(|app| { + let response_data = tauri::async_runtime::block_on(async { + let response = reqwest::get( + "https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json", + ) + .await + .unwrap(); + response.text().await + })?; + Ok(()) + }) +``` + +The HTTP plugin re-exports [reqwest](https://docs.rs/reqwest/latest/reqwest/) so you can check out their documentation for more information. + + + + +### Migrate to Notification Plugin + +The Rust `tauri::api::notification` JavaScript `@tauri-apps/api/notification` APIs have been removed. Use the `@tauri-apps/plugin-notification` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-notification = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_notification::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-notification": "^2.0.0" + } +} +``` + +```js +import { sendNotification } from '@tauri-apps/plugin-notification'; +sendNotification('Tauri is awesome!'); +``` + + + + +```rust +use tauri_plugin_notification::{NotificationExt, PermissionState}; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_notification::init()) + .setup(|app| { + if app.notification().permission_state()? == PermissionState::Unknown { + app.notification().request_permission()?; + } + if app.notification().permission_state()? == PermissionState::Granted { + app.notification() + .builder() + .body("Tauri is awesome!") + .show()?; + } + Ok(()) + }) +} +``` + + + + +### Migrate to Menu Module + +The Rust `Menu` APIs were moved to the `tauri::menu` module and refactored to use the [muda crate](https://github.com/tauri-apps/muda). + +#### Use `tauri::menu::MenuBuilder` + +Use `tauri::menu::MenuBuilder` instead of `tauri::Menu`. Note that its constructor takes a Manager instance (one of `App`, `AppHandle` or `WebviewWindow`) as an argument: + +```rust +use tauri::menu::MenuBuilder; + +tauri::Builder::default() + .setup(|app| { + let menu = MenuBuilder::new(app) + .copy() + .paste() + .separator() + .undo() + .redo() + .text("open-url", "Open URL") + .check("toggle", "Toggle") + .icon("show-app", "Show App", app.default_window_icon().cloned().unwrap()) + .build()?; + Ok(()) + }) +``` + +#### Use `tauri::menu::PredefinedMenuItem` + +Use `tauri::menu::PredefinedMenuItem` instead of `tauri::MenuItem`: + +```rust +use tauri::menu::{MenuBuilder, PredefinedMenuItem}; + +tauri::Builder::default() + .setup(|app| { + let menu = MenuBuilder::new(app).item(&PredefinedMenuItem::copy(app)?).build()?; + Ok(()) + }) +``` + +:::tip +The menu builder has dedicated methods to add each predefined menu item so you can call `.copy()` instead of `.item(&PredefinedMenuItem::copy(app, None)?)`. +::: + +#### Use `tauri::menu::MenuItemBuilder` + +Use `tauri::menu::MenuItemBuilder` instead of `tauri::CustomMenuItem`: + +```rust +use tauri::menu::MenuItemBuilder; + +tauri::Builder::default() + .setup(|app| { + let toggle = MenuItemBuilder::new("Toggle").accelerator("Ctrl+Shift+T").build(app)?; + Ok(()) + }) +``` + +#### Use `tauri::menu::SubmenuBuilder` + +Use `tauri::menu::SubmenuBuilder` instead of `tauri::Submenu`: + +```rust +use tauri::menu::{MenuBuilder, SubmenuBuilder}; + +tauri::Builder::default() + .setup(|app| { + let submenu = SubmenuBuilder::new(app, "Sub") + .text("Tauri") + .separator() + .check("Is Awesome") + .build()?; + let menu = MenuBuilder::new(app).item(&submenu).build()?; + Ok(()) + }) +``` + +`tauri::Builder::menu` now takes a closure because the menu needs a Manager instance to be built. See [the documentation](https://docs.rs/tauri/2.0.0-beta/tauri/struct.Builder.html#method.menu) for more information. + +#### Menu Events + +The Rust `tauri::Builder::on_menu_event` API was removed. Use `tauri::App::on_menu_event` or `tauri::AppHandle::on_menu_event` instead: + +```rust +use tauri::menu::{CheckMenuItemBuilder, MenuBuilder, MenuItemBuilder}; + +tauri::Builder::default() + .setup(|app| { + let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?; + let check = CheckMenuItemBuilder::new("Mark").build(app)?; + let menu = MenuBuilder::new(app).items(&[&toggle, &check]).build()?; + + app.set_menu(menu)?; + + app.on_menu_event(move |app, event| { + if event.id() == check.id() { + println!("`check` triggered, do something! is checked? {}", check.is_checked().unwrap()); + } else if event.id() == "toggle" { + println!("toggle triggered!"); + } + }); + Ok(()) + }) +``` + +Note that there are two ways to check which menu item was selected: move the item to the event handler closure and compare IDs, or define a custom ID for the item through the `with_id` constructor and use that ID string to compare. + +:::tip +Menu items can be shared across menus, and the menu event is bound to a menu item instead of a menu or window. +If you don't want all listeners to be triggered when a menu item is selected, do not share menu items and use dedicated instances instead, that you could move into `tauri::WebviewWindow/WebviewWindowBuilder::on_menu_event` closure. +::: + +### Migrate to OS Plugin + +The Rust `tauri::api::os` JavaScript `@tauri-apps/api/os` APIs have been removed. Use the `@tauri-apps/plugin-os` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-os = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_os::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-os": "^2.0.0" + } +} +``` + +```js +import { arch } from '@tauri-apps/plugin-os'; +const architecture = await arch(); +``` + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_os::init()) + .setup(|app| { + let os_arch = tauri_plugin_os::arch(); + Ok(()) + }) +} +``` + + + + +### Migrate to Process Plugin + +The Rust `tauri::api::process` JavaScript `@tauri-apps/api/process` APIs have been removed. Use the `@tauri-apps/plugin-process` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-process = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_process::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-process": "^2.0.0" + } +} +``` + +```js +import { exit, relaunch } from '@tauri-apps/plugin-process'; +await exit(0); +await relaunch(); +``` + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_process::init()) + .setup(|app| { + // exit the app with a status code + app.handle().exit(1); + // restart the app + app.handle().restart(); + Ok(()) + }) +} +``` + + + + +### Migrate to Shell Plugin + +The Rust `tauri::api::shell` JavaScript `@tauri-apps/api/shell` APIs have been removed. Use the `@tauri-apps/plugin-shell` plugin instead: + +1. Add to cargo dependencies: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-shell = "2" +``` + +2. Use in JavaScript or Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-shell": "^2.0.0" + } +} +``` + +```js +import { Command, open } from '@tauri-apps/plugin-shell'; +const output = await Command.create('echo', 'message').execute(); + +await open('https://github.com/tauri-apps/tauri'); +``` + + + + +- Open an URL + +```rust +use tauri_plugin_shell::ShellExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + app.shell().open("https://github.com/tauri-apps/tauri", None)?; + Ok(()) + }) +} +``` + +- Spawn a child process and retrieve the status code + +```rust +use tauri_plugin_shell::ShellExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + let status = tauri::async_runtime::block_on(async move { app.shell().command("which").args(["ls"]).status().await.unwrap() }); + println!("`which` finished with status: {:?}", status.code()); + Ok(()) + }) +} +``` + +- Spawn a child process and capture its output + +```rust +use tauri_plugin_shell::ShellExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + let output = tauri::async_runtime::block_on(async move { app.shell().command("echo").args(["TAURI"]).output().await.unwrap() }); + assert!(output.status.success()); + assert_eq!(String::from_utf8(output.stdout).unwrap(), "TAURI"); + Ok(()) + }) +} +``` + +- Spawn a child process and read its events asynchronously: + +```rust +use tauri_plugin_shell::{ShellExt, process::CommandEvent}; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + let handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + let (mut rx, mut child) = handle.shell().command("cargo") + .args(["tauri", "dev"]) + .spawn() + .expect("Failed to spawn cargo"); + + let mut i = 0; + while let Some(event) = rx.recv().await { + if let CommandEvent::Stdout(line) = event { + println!("got: {}", String::from_utf8(line).unwrap()); + i += 1; + if i == 4 { + child.write("message from Rust\n".as_bytes()).unwrap(); + i = 0; + } + } + } + }); + Ok(()) + }) +} +``` + + + + +### Migrate to Tray Icon Module + +The Rust `SystemTray` APIs were renamed to `TrayIcon` for consistency. The new APIs can be found in the Rust `tray` module. + +#### Use `tauri::tray::TrayIconBuilder` + +Use `tauri::tray::TrayIconBuilder` instead of `tauri::SystemTray`: + +```rust +let tray = tauri::tray::TrayIconBuilder::with_id("my-tray").build(app)?; +``` + +See [TrayIconBuilder](https://docs.rs/tauri/2.0.0-beta/tauri/tray/struct.TrayIconBuilder.html) for more information. + +#### Migrate to Menu + +Use `tauri::menu::Menu` instead of `tauri::SystemTrayMenu`, `tauri::menu::Submenu` instead of `tauri::SystemTraySubmenu` and `tauri::menu::PredefinedMenuItem` instead of `tauri::SystemTrayMenuItem`. [Migration](#migrate-to-menu) + +#### Tray Events + +`tauri::SystemTray::on_event` have been split into `tauri::tray::TrayIconBuilder::on_menu_event` and `tauri::tray::TrayIconBuilder::on_tray_icon_event`: + +```rust +use tauri::{ + menu::{MenuBuilder, MenuItemBuilder}, + tray::{ClickType, TrayIconBuilder}, +}; + +tauri::Builder::default() + .setup(|app| { + let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?; + let menu = MenuBuilder::new(app).items(&[&toggle]).build()?; + let tray = TrayIconBuilder::new() + .menu(&menu) + .on_menu_event(move |app, event| match event.id().as_ref() { + "toggle" => { + println!("toggle clicked"); + } + _ => (), + }) + .on_tray_icon_event(|tray, event| { + if event.click_type == ClickType::Left { + let app = tray.app_handle(); + if let Some(webview_window) = app.get_webview_window("main") { + let _ = webview_window.show(); + let _ = webview_window.set_focus(); + } + } + }) + .build(app)?; + + Ok(()) + }) +``` + +### Migrate to Updater Plugin + +The built-in dialog with an automatic update check was removed, use the Rust and JS APIs to check for and install updates instead. + +The Rust `tauri::updater` and JavaScript `@tauri-apps/api-updater` APIs have been removed. To set a custom updater target with the `@tauri-apps/plugin-updater`: + +1. Add to cargo dependencies: + +```toml +[dependencies] +tauri-plugin-updater = "2" +``` + +2. Use in JavaScript of Rust project: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_updater::Builder::new().build()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-updater": "^2.0.0" + } +} +``` + +```js +import { check } from '@tauri-apps/plugin-updater'; +import { relaunch } from '@tauri-apps/plugin-process'; + +const update = await check(); +if (update?.available) { + console.log(`Update to ${update.version} available! Date: ${update.date}`); + console.log(`Release notes: ${update.body}`); + await update.downloadAndInstall(); + // requires the `process` plugin + await relaunch(); +} +``` + + + + +To check for updates: + +```rust +use tauri_plugin_updater::UpdaterExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_updater::Builder::new().build()) + .setup(|app| { + let handle = app.handle(); + tauri::async_runtime::spawn(async move { + let response = handle.updater().check().await; + }); + Ok(()) + }) +} +``` + +To set a custom updater target: + +```rust +fn main() { + let mut updater = tauri_plugin_updater::Builder::new(); + #[cfg(target_os = "macos")] + { + updater = updater.target("darwin-universal"); + } + tauri::Builder::default() + .plugin(updater.build()) +} +``` + + + + +### Migrate Path to Tauri Manager + +The Rust `tauri::api::path` module functions and `tauri::PathResolver` have been moved to `tauri::Manager::path`: + +```rust +use tauri::{path::BaseDirectory, Manager}; + +tauri::Builder::default() + .setup(|app| { + let home_dir_path = app.path().home_dir().expect("failed to get home dir"); + + let path = app.path().resolve("path/to/something", BaseDirectory::Config)?; + + Ok(()) + }) +``` + +### Migrate to new Window API + +On the Rust side, `Window` was renamed to `WebviewWindow` and its builder `WindowBuilder` is now named `WebviewWindowBuilder`. + +Additionally, the `Manager::get_window` function was renamed to `get_webview_window` and +the window's `parent_window` API was renamed to `parent_raw` to support a high level window parent API. + +On the JavaScript side, the `WebviewWindow` class is now exported in the `@tauri-apps/api/webviewWindow` path. + +The `onMenuClicked` function was removed, you can intercept menu events when creating a menu in JavaScript instead. + +### Migrate Embedded External Binaries (Sidecar) + +In Tauri v1, the external binaries and their arguments were defined in the allowlist. In v2, use the new permissions system. Read [Migrate Permissions](#migrate-permissions) for more information. + +On the JavaScript side, make sure you [Migrate to Shell Plugin](#migrate-to-shell-plugin). + +On the Rust side, `tauri::api::process` API has been removed. Use `tauri_plugin_shell::ShellExt` and `tauri_plugin_shell::process::CommandEvent` APIs instead. Read the [Embedding External Binaries](/guides/develop/sidecar/#running-it-from-rust) guide to see how. + +The "process-command-api" features flag has been removed in v2. So running the external binaries does not require this feature to be defined in the Tauri config anymore. + +### Migrate Permissions + +The v1 allowlist have been rewritten to a completely new system for permissions that works for individual plugins and is much more configurable for multiwindow and remote URL support. +This new system works like an access control list (ACL) where you can allow or deny commands, allocate permissions to a specific set of windows and domains, and define access scopes. + +To enable permissions for your app, you must create capability files inside the `src-tauri/capabilities` folder, and Tauri will automatically configure everything else for you. + +The `migrate` CLI command automatically parses your v1 allowlist and generates the associated capability file. + +To learn more about permissions and capabilities, see [the documentation](/references/v2/acl).