From 46f2eae8aad7c6a228eaf48480d5603dae6454b4 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Fri, 7 Jan 2022 16:55:30 -0300 Subject: [PATCH] feat: allow config's version to be a path to package.json, closes #2967 (#2971) --- .changes/version-package-json.md | 5 +++ core/tauri-utils/src/config.rs | 61 ++++++++++++++++++++++++-- examples/api/src-tauri/Cargo.lock | 4 +- examples/api/src-tauri/tauri.conf.json | 2 +- tooling/cli.rs/src/build.rs | 3 +- 5 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 .changes/version-package-json.md diff --git a/.changes/version-package-json.md b/.changes/version-package-json.md new file mode 100644 index 000000000..f22887f99 --- /dev/null +++ b/.changes/version-package-json.md @@ -0,0 +1,5 @@ +--- +"tauri": patch +--- + +Allow `tauri.conf.json > package > version` to specify a path to a `package.json` file and pull the version from it. diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index b4a1849af..79641e818 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -10,9 +10,12 @@ //! This is a core functionality that is not considered part of the stable API. //! If you use it, note that it may include breaking changes in the future. -use std::{collections::HashMap, path::PathBuf}; +use std::{collections::HashMap, fmt, fs::read_to_string, path::PathBuf}; -use serde::Deserialize; +use serde::{ + de::{Deserializer, Error as DeError, Visitor}, + Deserialize, +}; use serde_json::Value as JsonValue; use url::Url; @@ -479,16 +482,68 @@ impl Default for BuildConfig { } } +#[derive(Debug, PartialEq)] +struct PackageVersion(String); + +impl<'d> serde::Deserialize<'d> for PackageVersion { + fn deserialize>(deserializer: D) -> Result { + struct PackageVersionVisitor; + + impl<'d> Visitor<'d> for PackageVersionVisitor { + type Value = PackageVersion; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + formatter, + "a semver string or a path to a package.json file" + ) + } + + fn visit_str(self, value: &str) -> Result { + let path = PathBuf::from(value); + if path.exists() { + let json_str = read_to_string(&path) + .map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?; + let package_json: serde_json::Value = serde_json::from_str(&json_str) + .map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?; + if let Some(obj) = package_json.as_object() { + let version = obj + .get("version") + .ok_or_else(|| DeError::custom("JSON must contain a `version` field"))? + .as_str() + .ok_or_else(|| DeError::custom("`version` must be a string"))?; + Ok(PackageVersion(version.into())) + } else { + Err(DeError::custom("value is not a path to a JSON object")) + } + } else { + Ok(PackageVersion(value.into())) + } + } + } + + deserializer.deserialize_string(PackageVersionVisitor {}) + } +} + /// The package configuration. #[derive(Debug, Default, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PackageConfig { /// App name. pub product_name: Option, - /// App version. + /// App version. It is a semver version number or a path to a `package.json` file contaning the `version` field. + #[serde(deserialize_with = "version_deserializer", default)] pub version: Option, } +fn version_deserializer<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + Option::::deserialize(deserializer).map(|v| v.map(|v| v.0)) +} + /// The config type mapped to `tauri.conf.json`. #[derive(Debug, Default, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index dc518167d..58ac2ad38 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -345,9 +345,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.0-rc.9" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7843ae7a539bef687e018bf9edf7e87728024b29d02b0f8409726be8880ae1a" +checksum = "d01c9347757e131122b19cd19a05c85805b68c2352a97b623efdc3c295290299" dependencies = [ "atty", "bitflags", diff --git a/examples/api/src-tauri/tauri.conf.json b/examples/api/src-tauri/tauri.conf.json index 398fc7a97..2051855eb 100644 --- a/examples/api/src-tauri/tauri.conf.json +++ b/examples/api/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ }, "package": { "productName": "Tauri API", - "version": "0.1.0" + "version": "../package.json" }, "tauri": { "cli": { diff --git a/tooling/cli.rs/src/build.rs b/tooling/cli.rs/src/build.rs index afa25bfdb..9a47d3bbe 100644 --- a/tooling/cli.rs/src/build.rs +++ b/tooling/cli.rs/src/build.rs @@ -56,11 +56,12 @@ pub fn command(options: Options) -> Result<()> { } else { None }; - let config = get_config(merge_config.as_deref())?; let tauri_path = tauri_dir(); set_current_dir(&tauri_path).with_context(|| "failed to change current working directory")?; + let config = get_config(merge_config.as_deref())?; + let manifest = rewrite_manifest(config.clone())?; let config_guard = config.lock().unwrap();