use anyhow::{Context, Result, bail};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use crate::schema::intermediate::IntermediateInjectDefaults;
#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct InjectDefaultsToml {
#[serde(default, skip_serializing_if = "IndexMap::is_empty")]
pub queries: IndexMap<String, String>,
#[serde(default, skip_serializing_if = "IndexMap::is_empty")]
pub mutations: IndexMap<String, String>,
#[serde(flatten)]
pub base: IndexMap<String, String>,
}
impl InjectDefaultsToml {
pub fn to_intermediate(&self) -> Result<IntermediateInjectDefaults> {
serde_json::from_value(serde_json::json!({
"base": self.base,
"queries": self.queries,
"mutations": self.mutations,
}))
.context("Invalid [inject_defaults] in fraiseql.toml")
}
pub fn reconcile(
config: Option<&Self>,
document: Option<IntermediateInjectDefaults>,
) -> Result<Option<IntermediateInjectDefaults>> {
let Some(config) = config else {
return Ok(document);
};
let from_config = config.to_intermediate()?;
match document {
Some(from_document) if from_document != from_config => bail!(
"[inject_defaults] in fraiseql.toml differs from `inject_defaults` in the \
schema document.\n fraiseql.toml: {}\n schema: {}\nRegenerate the \
schema from this fraiseql.toml, or remove the block from one of them.",
serde_json::to_string(&from_config).unwrap_or_default(),
serde_json::to_string(&from_document).unwrap_or_default(),
),
_ => Ok(Some(from_config)),
}
}
}
#[cfg(test)]
mod tests;