use crate::tui::model::EditModel;
use serde_json::Value;
fn seed_value(overlay: Option<&str>) -> Result<Value, String> {
let mut base: Value = serde_json::from_str(crate::template::DEFAULT)
.map_err(|err| format!("builtin template invalid: {err}"))?;
strip_to_seed_defaults(&mut base);
if let Some(overlay) = overlay {
let over: Value = serde_json::from_str(overlay)
.map_err(|err| format!(".apic/template.json is not valid JSON: {err}"))?;
overlay_values(&mut base, &over);
}
Ok(base)
}
fn strip_to_seed_defaults(v: &mut Value) {
match v {
Value::Array(items) => items.clear(),
Value::Object(map) => {
for (k, val) in map.iter_mut() {
if k == "example" {
*val = Value::Null;
} else {
strip_to_seed_defaults(val);
}
}
}
_ => {}
}
}
fn overlay_values(base: &mut Value, overlay: &Value) {
match (base, overlay) {
(Value::Object(base_map), Value::Object(over_map)) => {
for (k, ov) in over_map {
overlay_values(base_map.entry(k.clone()).or_insert(Value::Null), ov);
}
}
(slot, ov) => *slot = ov.clone(),
}
}
pub(crate) fn seed_model(overlay: Option<&str>) -> Result<EditModel, String> {
let value = seed_value(overlay)?;
let text = serde_json::to_string(&value).map_err(|err| format!("seed render failed: {err}"))?;
let contract = crate::json::json_get(&text, None)
.map_err(|err| format!("seed is not a valid contract: {err}"))?;
Ok(EditModel::from_contract(contract))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_overlay_keeps_scalars_empties_arrays() {
let m = seed_model(None).unwrap();
assert_eq!(m.name, "endpoint-name");
assert_eq!(m.url.protocol, "https");
assert_eq!(m.url.host, "api.example.com");
assert!(m.url.path.is_empty());
assert!(m.url.query.is_empty());
assert!(m.url.variable.is_empty());
assert!(m.headers.is_empty());
assert!(m.responses.is_empty());
assert!(m.request.as_ref().unwrap().schema.is_empty());
}
#[test]
fn overlay_values_are_kept() {
let overlay = r#"{ "name": "real-endpoint",
"url": { "host": "api.real.com" } }"#;
let m = seed_model(Some(overlay)).unwrap();
assert_eq!(m.name, "real-endpoint");
assert_eq!(m.url.host, "api.real.com");
assert_eq!(m.url.protocol, "https");
assert!(m.url.path.is_empty());
}
#[test]
fn seed_is_a_valid_contract() {
let m = seed_model(None).unwrap();
assert!(m.to_json().is_ok());
}
}