Skip to content

Commit 46f2eae

Browse files
authored
feat: allow config's version to be a path to package.json, closes #2967 (#2971)
1 parent 0600099 commit 46f2eae

5 files changed

Lines changed: 68 additions & 7 deletions

File tree

.changes/version-package-json.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Allow `tauri.conf.json > package > version` to specify a path to a `package.json` file and pull the version from it.

core/tauri-utils/src/config.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
//! This is a core functionality that is not considered part of the stable API.
1111
//! If you use it, note that it may include breaking changes in the future.
1212
13-
use std::{collections::HashMap, path::PathBuf};
13+
use std::{collections::HashMap, fmt, fs::read_to_string, path::PathBuf};
1414

15-
use serde::Deserialize;
15+
use serde::{
16+
de::{Deserializer, Error as DeError, Visitor},
17+
Deserialize,
18+
};
1619
use serde_json::Value as JsonValue;
1720
use url::Url;
1821

@@ -479,16 +482,68 @@ impl Default for BuildConfig {
479482
}
480483
}
481484

485+
#[derive(Debug, PartialEq)]
486+
struct PackageVersion(String);
487+
488+
impl<'d> serde::Deserialize<'d> for PackageVersion {
489+
fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<PackageVersion, D::Error> {
490+
struct PackageVersionVisitor;
491+
492+
impl<'d> Visitor<'d> for PackageVersionVisitor {
493+
type Value = PackageVersion;
494+
495+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
496+
write!(
497+
formatter,
498+
"a semver string or a path to a package.json file"
499+
)
500+
}
501+
502+
fn visit_str<E: DeError>(self, value: &str) -> Result<PackageVersion, E> {
503+
let path = PathBuf::from(value);
504+
if path.exists() {
505+
let json_str = read_to_string(&path)
506+
.map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?;
507+
let package_json: serde_json::Value = serde_json::from_str(&json_str)
508+
.map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?;
509+
if let Some(obj) = package_json.as_object() {
510+
let version = obj
511+
.get("version")
512+
.ok_or_else(|| DeError::custom("JSON must contain a `version` field"))?
513+
.as_str()
514+
.ok_or_else(|| DeError::custom("`version` must be a string"))?;
515+
Ok(PackageVersion(version.into()))
516+
} else {
517+
Err(DeError::custom("value is not a path to a JSON object"))
518+
}
519+
} else {
520+
Ok(PackageVersion(value.into()))
521+
}
522+
}
523+
}
524+
525+
deserializer.deserialize_string(PackageVersionVisitor {})
526+
}
527+
}
528+
482529
/// The package configuration.
483530
#[derive(Debug, Default, PartialEq, Deserialize)]
484531
#[serde(rename_all = "camelCase")]
485532
pub struct PackageConfig {
486533
/// App name.
487534
pub product_name: Option<String>,
488-
/// App version.
535+
/// App version. It is a semver version number or a path to a `package.json` file contaning the `version` field.
536+
#[serde(deserialize_with = "version_deserializer", default)]
489537
pub version: Option<String>,
490538
}
491539

540+
fn version_deserializer<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
541+
where
542+
D: Deserializer<'de>,
543+
{
544+
Option::<PackageVersion>::deserialize(deserializer).map(|v| v.map(|v| v.0))
545+
}
546+
492547
/// The config type mapped to `tauri.conf.json`.
493548
#[derive(Debug, Default, PartialEq, Deserialize)]
494549
#[serde(rename_all = "camelCase")]

examples/api/src-tauri/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/api/src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88
"package": {
99
"productName": "Tauri API",
10-
"version": "0.1.0"
10+
"version": "../package.json"
1111
},
1212
"tauri": {
1313
"cli": {

tooling/cli.rs/src/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ pub fn command(options: Options) -> Result<()> {
5656
} else {
5757
None
5858
};
59-
let config = get_config(merge_config.as_deref())?;
6059

6160
let tauri_path = tauri_dir();
6261
set_current_dir(&tauri_path).with_context(|| "failed to change current working directory")?;
6362

63+
let config = get_config(merge_config.as_deref())?;
64+
6465
let manifest = rewrite_manifest(config.clone())?;
6566

6667
let config_guard = config.lock().unwrap();

0 commit comments

Comments
 (0)