pub mod cache;
pub mod columns;
pub mod discovery;
pub mod jinja;
pub mod manifest;
pub mod project;
pub mod sql;
#[allow(dead_code)]
pub mod yaml_schema;
use anyhow::Result;
use serde::de::DeserializeOwned;
pub fn yaml_from_str<T: DeserializeOwned>(content: &str, location: &str) -> Result<T> {
let value: serde_json::Value = match serde_saphyr::from_str(content) {
Ok(v) => v,
Err(e) => {
if is_duplicate_key_error(&e) {
let key = extract_duplicate_key(&e).unwrap_or("unknown");
crate::warn!(
"duplicate YAML key '{}' in {} (using last value)",
key,
location,
);
let options = serde_saphyr::options! {
duplicate_keys: serde_saphyr::options::DuplicateKeyPolicy::LastWins
};
serde_saphyr::from_str_with_options(content, options)?
} else {
return Err(e.into());
}
}
};
if value.is_null() {
return Ok(serde_json::from_value(serde_json::Value::Object(
Default::default(),
))?);
}
Ok(serde_json::from_value(value)?)
}
fn is_duplicate_key_error(e: &serde_saphyr::Error) -> bool {
match e {
serde_saphyr::Error::DuplicateMappingKey { .. } => true,
serde_saphyr::Error::WithSnippet { error, .. } => is_duplicate_key_error(error),
_ => false,
}
}
fn extract_duplicate_key(e: &serde_saphyr::Error) -> Option<&str> {
match e {
serde_saphyr::Error::DuplicateMappingKey { key, .. } => key.as_deref(),
serde_saphyr::Error::WithSnippet { error, .. } => extract_duplicate_key(error),
_ => None,
}
}