diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ed1c22a..777fc872 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changes - Wrap long error messages in response pane +- Include data path in config/collection deserialization errors + - This should make errors much less cryptic and frustrating ## [2.3.0] - 2024-11-11 diff --git a/Cargo.lock b/Cargo.lock index 9328a3e0..8ecb71e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2230,6 +2230,16 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_test" version = "1.0.177" @@ -2412,6 +2422,7 @@ dependencies = [ "serde", "serde_json", "serde_json_path", + "serde_path_to_error", "serde_test", "serde_yaml", "strum", diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 588663be..70c908ac 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -30,6 +30,7 @@ rusqlite_migration = "1.2.0" serde = {workspace = true, features = ["derive"]} serde_json = {workspace = true} serde_json_path = {workspace = true} +serde_path_to_error = "0.1.16" serde_yaml = {workspace = true} strum = {workspace = true, features = ["derive"]} thiserror = {workspace = true} diff --git a/crates/core/src/collection/models.rs b/crates/core/src/collection/models.rs index 48851b38..ad78476d 100644 --- a/crates/core/src/collection/models.rs +++ b/crates/core/src/collection/models.rs @@ -113,6 +113,7 @@ impl crate::test_util::Factory for Profile { Serialize, Deserialize, )] +#[serde(transparent)] pub struct ProfileId(String); #[cfg(any(test, feature = "test"))] @@ -235,6 +236,7 @@ pub struct Recipe { Serialize, Deserialize, )] +#[serde(transparent)] pub struct RecipeId(String); #[cfg(any(test, feature = "test"))] @@ -412,6 +414,7 @@ pub struct Chain { Serialize, Deserialize, )] +#[serde(transparent)] #[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub struct ChainId(#[deref(forward)] Identifier); diff --git a/crates/core/src/template.rs b/crates/core/src/template.rs index 8c96171d..ce189285 100644 --- a/crates/core/src/template.rs +++ b/crates/core/src/template.rs @@ -139,6 +139,7 @@ impl From for Template { Serialize, Deserialize, )] +#[serde(transparent)] #[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub struct Identifier( #[cfg_attr(test, proptest(regex = "[a-zA-Z0-9-_]+"))] String, diff --git a/crates/core/src/util.rs b/crates/core/src/util.rs index 7ebc0977..1e785c77 100644 --- a/crates/core/src/util.rs +++ b/crates/core/src/util.rs @@ -40,13 +40,14 @@ pub fn doc_link(path: &str) -> String { } /// Parse bytes from a reader into YAML. This will merge any anchors/aliases. -pub fn parse_yaml( - reader: impl Read, -) -> serde_yaml::Result { +pub fn parse_yaml(reader: impl Read) -> anyhow::Result { // Two-step parsing is required for anchor/alias merging - let mut yaml_value: serde_yaml::Value = serde_yaml::from_reader(reader)?; + let deserializer = serde_yaml::Deserializer::from_reader(reader); + let mut yaml_value: serde_yaml::Value = + serde_path_to_error::deserialize(deserializer)?; yaml_value.apply_merge()?; - serde_yaml::from_value(yaml_value) + let output = serde_path_to_error::deserialize(yaml_value)?; + Ok(output) } /// Format a datetime for the user