diff --git a/.changes/asset-resolver-dev-fallback.md b/.changes/asset-resolver-dev-fallback.md new file mode 100644 index 000000000..fc9b5069d --- /dev/null +++ b/.changes/asset-resolver-dev-fallback.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:enhance +"tauri-codegen": patch:enhance +--- + +Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets. diff --git a/.changes/fix-usage-without-compression.md b/.changes/fix-usage-without-compression.md new file mode 100644 index 000000000..0e6bf6154 --- /dev/null +++ b/.changes/fix-usage-without-compression.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:bug +"tauri-codegen": patch:bug +--- + +Fixes asset resolving when not using the `compression` feature. diff --git a/core/tauri-build/src/allowlist.rs b/core/tauri-build/src/allowlist.rs index 34654f689..a1ab7a521 100644 --- a/core/tauri-build/src/allowlist.rs +++ b/core/tauri-build/src/allowlist.rs @@ -59,7 +59,7 @@ pub fn check(config: &Config, manifest: &mut Manifest) -> Result<()> { if deps.is_empty() { if let Some(alias) = &metadata.alias { deps = find_dependency(manifest, alias, metadata.kind); - name = alias.clone(); + name.clone_from(alias); } } diff --git a/core/tauri-codegen/Cargo.toml b/core/tauri-codegen/Cargo.toml index b95714557..2ffed639a 100644 --- a/core/tauri-codegen/Cargo.toml +++ b/core/tauri-codegen/Cargo.toml @@ -35,7 +35,6 @@ plist = "1" time = { version = "0.3", features = [ "parsing", "formatting" ] } [features] -default = [ "compression" ] compression = [ "brotli", "tauri-utils/compression" ] isolation = [ "tauri-utils/isolation" ] shell-scope = [ "regex" ] diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index 2e95b0f25..c1283f907 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -437,17 +437,33 @@ pub fn context_codegen(data: ContextData) -> Result>( diff --git a/core/tauri-config-schema/schema.json b/core/tauri-config-schema/schema.json index d607b032d..717cbdd63 100644 --- a/core/tauri-config-schema/schema.json +++ b/core/tauri-config-schema/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Config", - "description": "The Tauri configuration object. It is read from a file where you can define your frontend assets, configure the bundler, enable the app updater, define a system tray, enable APIs via the allowlist and more.\n\nThe configuration file is generated by the [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in your Tauri application source directory (src-tauri).\n\nOnce generated, you may modify it at will to customize your Tauri application.\n\n## File Formats\n\nBy default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\nTauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively. The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`. The TOML file name is `Tauri.toml`.\n\n## Platform-Specific Configuration\n\nIn addition to the default configuration file, Tauri can read a platform-specific configuration from `tauri.linux.conf.json`, `tauri.windows.conf.json`, and `tauri.macos.conf.json` (or `Tauri.linux.toml`, `Tauri.windows.toml` and `Tauri.macos.toml` if the `Tauri.toml` format is used), which gets merged with the main configuration object.\n\n## Configuration Structure\n\nThe configuration is composed of the following objects:\n\n- [`package`](#packageconfig): Package settings - [`tauri`](#tauriconfig): The Tauri config - [`build`](#buildconfig): The build configuration - [`plugins`](#pluginconfig): The plugins config\n\n```json title=\"Example tauri.config.json file\" { \"build\": { \"beforeBuildCommand\": \"\", \"beforeDevCommand\": \"\", \"devPath\": \"../dist\", \"distDir\": \"../dist\" }, \"package\": { \"productName\": \"tauri-app\", \"version\": \"0.1.0\" }, \"tauri\": { \"allowlist\": { \"all\": true }, \"bundle\": {}, \"security\": { \"csp\": null }, \"updater\": { \"active\": false }, \"windows\": [ { \"fullscreen\": false, \"height\": 600, \"resizable\": true, \"title\": \"Tauri App\", \"width\": 800 } ] } } ```", + "description": "The Tauri configuration object. It is read from a file where you can define your frontend assets, configure the bundler, enable the app updater, define a system tray, enable APIs via the allowlist and more.\n\nThe configuration file is generated by the [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in your Tauri application source directory (src-tauri).\n\nOnce generated, you may modify it at will to customize your Tauri application.\n\n## File Formats\n\nBy default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\nTauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively. The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`. The TOML file name is `Tauri.toml`.\n\n## Platform-Specific Configuration\n\nIn addition to the default configuration file, Tauri can read a platform-specific configuration from `tauri.linux.conf.json`, `tauri.windows.conf.json`, and `tauri.macos.conf.json` (or `Tauri.linux.toml`, `Tauri.windows.toml` and `Tauri.macos.toml` if the `Tauri.toml` format is used), which gets merged with the main configuration object.\n\n## Configuration Structure\n\nThe configuration is composed of the following objects:\n\n- [`package`](#packageconfig): Package settings - [`tauri`](#tauriconfig): The Tauri config - [`build`](#buildconfig): The build configuration - [`plugins`](#pluginconfig): The plugins config\n\nExample tauri.config.json file:\n\n```json { \"build\": { \"beforeBuildCommand\": \"\", \"beforeDevCommand\": \"\", \"devPath\": \"../dist\", \"distDir\": \"../dist\" }, \"package\": { \"productName\": \"tauri-app\", \"version\": \"0.1.0\" }, \"tauri\": { \"allowlist\": { \"all\": true }, \"bundle\": {}, \"security\": { \"csp\": null }, \"updater\": { \"active\": false }, \"windows\": [ { \"fullscreen\": false, \"height\": 600, \"resizable\": true, \"title\": \"Tauri App\", \"width\": 800 } ] } } ```", "type": "object", "properties": { "$schema": { diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index 3611790ee..a36e809c8 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -3196,7 +3196,9 @@ impl PackageConfig { /// - [`build`](#buildconfig): The build configuration /// - [`plugins`](#pluginconfig): The plugins config /// -/// ```json title="Example tauri.config.json file" +/// Example tauri.config.json file: +/// +/// ```json /// { /// "build": { /// "beforeBuildCommand": "", diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index 088f0256e..e1a750204 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -354,7 +354,48 @@ pub struct AssetResolver { impl AssetResolver { /// Gets the app asset associated with the given path. + /// + /// Resolves to the embedded asset that is part of the app + /// in dev when [`devPath`](https://tauri.app/v1/api/config/#buildconfig.devpath) points to a folder in your filesystem + /// or in production when [`distDir`](https://tauri.app/v1/api/config/#buildconfig.distdir) + /// points to your frontend assets. + /// + /// Fallbacks to reading the asset from the [distDir] folder so the behavior is consistent in development. + /// Note that the dist directory must exist so you might need to build your frontend assets first. pub fn get(&self, path: String) -> Option { + #[cfg(dev)] + { + // on dev if the devPath is a path to a directory we have the embedded assets + // so we can use get_asset() directly + // we only fallback to reading from distDir directly if we're using an external URL (which is likely) + if let ( + crate::utils::config::AppUrl::Url(crate::utils::config::WindowUrl::External(_)), + crate::utils::config::AppUrl::Url(crate::utils::config::WindowUrl::App(dist_path)), + ) = ( + &self.manager.config().build.dev_path, + &self.manager.config().build.dist_dir, + ) { + let asset_path = PathBuf::from(&path) + .components() + .filter(|c| !matches!(c, std::path::Component::RootDir)) + .collect::(); + + let asset_path = self + .manager + .config_parent() + .map(|p| p.join(dist_path).join(&asset_path)) + .unwrap_or_else(|| dist_path.join(&asset_path)); + return std::fs::read(asset_path).ok().map(|bytes| { + let mime_type = crate::utils::mime_type::MimeType::parse(&bytes, &path); + Asset { + bytes, + mime_type, + csp_header: None, + } + }); + } + } + self.manager.get_asset(path).ok() } diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index e62da03bf..53f5f35a8 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -471,6 +471,8 @@ impl TryFrom for runtime::Icon { /// Unless you know what you are doing and are prepared for this type to have breaking changes, do not create it yourself. pub struct Context { pub(crate) config: Config, + #[cfg(dev)] + pub(crate) config_parent: Option, pub(crate) assets: Arc, pub(crate) default_window_icon: Option, pub(crate) app_icon: Option>, @@ -587,6 +589,8 @@ impl Context { ) -> Self { Self { config, + #[cfg(dev)] + config_parent: None, assets, default_window_icon, app_icon, @@ -598,6 +602,14 @@ impl Context { shell_scope, } } + + #[cfg(dev)] + #[doc(hidden)] + pub fn with_config_parent(&mut self, config_parent: impl AsRef) { + self + .config_parent + .replace(config_parent.as_ref().to_owned()); + } } // TODO: expand these docs diff --git a/core/tauri/src/manager.rs b/core/tauri/src/manager.rs index ec309cf60..b67018890 100644 --- a/core/tauri/src/manager.rs +++ b/core/tauri/src/manager.rs @@ -218,6 +218,8 @@ pub struct InnerWindowManager { on_page_load: Box>, config: Arc, + #[cfg(dev)] + config_parent: Option, assets: Arc, pub(crate) default_window_icon: Option, pub(crate) app_icon: Option>, @@ -325,6 +327,8 @@ impl WindowManager { invoke_handler, on_page_load, config: Arc::new(context.config), + #[cfg(dev)] + config_parent: context.config_parent, assets: context.assets, default_window_icon: context.default_window_icon, app_icon: context.app_icon, @@ -1195,6 +1199,11 @@ impl WindowManager { self.inner.config.clone() } + #[cfg(dev)] + pub fn config_parent(&self) -> Option<&std::path::PathBuf> { + self.inner.config_parent.as_ref() + } + pub fn package_info(&self) -> &PackageInfo { &self.inner.package_info } diff --git a/core/tauri/src/test/mod.rs b/core/tauri/src/test/mod.rs index 206442238..6910f1c5e 100644 --- a/core/tauri/src/test/mod.rs +++ b/core/tauri/src/test/mod.rs @@ -163,6 +163,8 @@ pub fn mock_context(assets: A) -> crate::Context { build: Default::default(), plugins: Default::default(), }, + #[cfg(dev)] + config_parent: None, assets: Arc::new(assets), default_window_icon: None, app_icon: None, diff --git a/core/tests/restart/tests/restart.rs b/core/tests/restart/tests/restart.rs index 6f5d75ab5..c881f0d9d 100644 --- a/core/tests/restart/tests/restart.rs +++ b/core/tests/restart/tests/restart.rs @@ -59,10 +59,7 @@ fn symlink_runner(create_symlinks: impl Fn(&Path) -> io::Result) -> Res // we expect the output to be the bin path, twice assert_eq!(stdout, format!("{bin}\n{bin}\n", bin = bin.display())); - } else if cfg!(all( - target_os = "macos", - not(feature = "process-relaunch-dangerous-allow-symlink-macos") - )) { + } else if cfg!(target_os = "macos") { // we expect this to fail on macOS without the dangerous symlink flag set let stderr = String::from_utf8(output.stderr)?; diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index e649a2d76..61eff36b2 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -4024,7 +4024,7 @@ checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" [[package]] name = "tauri" -version = "1.6.6" +version = "1.7.1" dependencies = [ "anyhow", "base64 0.21.7", @@ -4090,7 +4090,7 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.2" +version = "1.5.3" dependencies = [ "anyhow", "cargo_toml", @@ -4109,7 +4109,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.3" +version = "1.4.4" dependencies = [ "base64 0.21.7", "brotli", @@ -4133,7 +4133,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.4" +version = "1.4.5" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4145,7 +4145,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.3" +version = "0.14.4" dependencies = [ "gtk", "http", @@ -4164,7 +4164,7 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.7" +version = "0.14.9" dependencies = [ "arboard", "cocoa 0.24.1", @@ -4183,7 +4183,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.4" +version = "1.6.0" dependencies = [ "aes-gcm", "brotli", diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index b891fb3a7..88bc04e24 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -2395,6 +2395,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.4.2" @@ -4295,12 +4301,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa 1.0.9", + "num-conv", "powerfmt", "serde", "time-core", @@ -4315,10 +4322,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] diff --git a/tooling/cli/schema.json b/tooling/cli/schema.json index d607b032d..717cbdd63 100644 --- a/tooling/cli/schema.json +++ b/tooling/cli/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Config", - "description": "The Tauri configuration object. It is read from a file where you can define your frontend assets, configure the bundler, enable the app updater, define a system tray, enable APIs via the allowlist and more.\n\nThe configuration file is generated by the [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in your Tauri application source directory (src-tauri).\n\nOnce generated, you may modify it at will to customize your Tauri application.\n\n## File Formats\n\nBy default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\nTauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively. The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`. The TOML file name is `Tauri.toml`.\n\n## Platform-Specific Configuration\n\nIn addition to the default configuration file, Tauri can read a platform-specific configuration from `tauri.linux.conf.json`, `tauri.windows.conf.json`, and `tauri.macos.conf.json` (or `Tauri.linux.toml`, `Tauri.windows.toml` and `Tauri.macos.toml` if the `Tauri.toml` format is used), which gets merged with the main configuration object.\n\n## Configuration Structure\n\nThe configuration is composed of the following objects:\n\n- [`package`](#packageconfig): Package settings - [`tauri`](#tauriconfig): The Tauri config - [`build`](#buildconfig): The build configuration - [`plugins`](#pluginconfig): The plugins config\n\n```json title=\"Example tauri.config.json file\" { \"build\": { \"beforeBuildCommand\": \"\", \"beforeDevCommand\": \"\", \"devPath\": \"../dist\", \"distDir\": \"../dist\" }, \"package\": { \"productName\": \"tauri-app\", \"version\": \"0.1.0\" }, \"tauri\": { \"allowlist\": { \"all\": true }, \"bundle\": {}, \"security\": { \"csp\": null }, \"updater\": { \"active\": false }, \"windows\": [ { \"fullscreen\": false, \"height\": 600, \"resizable\": true, \"title\": \"Tauri App\", \"width\": 800 } ] } } ```", + "description": "The Tauri configuration object. It is read from a file where you can define your frontend assets, configure the bundler, enable the app updater, define a system tray, enable APIs via the allowlist and more.\n\nThe configuration file is generated by the [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in your Tauri application source directory (src-tauri).\n\nOnce generated, you may modify it at will to customize your Tauri application.\n\n## File Formats\n\nBy default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\nTauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively. The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`. The TOML file name is `Tauri.toml`.\n\n## Platform-Specific Configuration\n\nIn addition to the default configuration file, Tauri can read a platform-specific configuration from `tauri.linux.conf.json`, `tauri.windows.conf.json`, and `tauri.macos.conf.json` (or `Tauri.linux.toml`, `Tauri.windows.toml` and `Tauri.macos.toml` if the `Tauri.toml` format is used), which gets merged with the main configuration object.\n\n## Configuration Structure\n\nThe configuration is composed of the following objects:\n\n- [`package`](#packageconfig): Package settings - [`tauri`](#tauriconfig): The Tauri config - [`build`](#buildconfig): The build configuration - [`plugins`](#pluginconfig): The plugins config\n\nExample tauri.config.json file:\n\n```json { \"build\": { \"beforeBuildCommand\": \"\", \"beforeDevCommand\": \"\", \"devPath\": \"../dist\", \"distDir\": \"../dist\" }, \"package\": { \"productName\": \"tauri-app\", \"version\": \"0.1.0\" }, \"tauri\": { \"allowlist\": { \"all\": true }, \"bundle\": {}, \"security\": { \"csp\": null }, \"updater\": { \"active\": false }, \"windows\": [ { \"fullscreen\": false, \"height\": 600, \"resizable\": true, \"title\": \"Tauri App\", \"width\": 800 } ] } } ```", "type": "object", "properties": { "$schema": {