Skip to content

Commit

Permalink
feat: allow config's version to be a path to package.json, closes #2967
Browse files Browse the repository at this point in the history
… (#2971)
  • Loading branch information
lucasfernog committed Jan 7, 2022
1 parent 0600099 commit 46f2eae
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .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.
61 changes: 58 additions & 3 deletions core/tauri-utils/src/config.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -479,16 +482,68 @@ impl Default for BuildConfig {
}
}

#[derive(Debug, PartialEq)]
struct PackageVersion(String);

impl<'d> serde::Deserialize<'d> for PackageVersion {
fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<PackageVersion, D::Error> {
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<E: DeError>(self, value: &str) -> Result<PackageVersion, E> {
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<String>,
/// 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<String>,
}

fn version_deserializer<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
Option::<PackageVersion>::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")]
Expand Down
4 changes: 2 additions & 2 deletions examples/api/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/api/src-tauri/tauri.conf.json
Expand Up @@ -7,7 +7,7 @@
},
"package": {
"productName": "Tauri API",
"version": "0.1.0"
"version": "../package.json"
},
"tauri": {
"cli": {
Expand Down
3 changes: 2 additions & 1 deletion tooling/cli.rs/src/build.rs
Expand Up @@ -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();
Expand Down

0 comments on commit 46f2eae

Please sign in to comment.