use std::path::Path;
pub const META_SCHEMA_MANIFEST: &str = include_str!("../generated/schema-manifest.schema.json");
pub const META_SCHEMA_TYPE_DEFINITION: &str =
include_str!("../generated/type-definition.schema.json");
pub const META_SCHEMA_DIR: &str = "meta-schemas";
pub const META_SCHEMA_MANIFEST_FILE: &str = "schema-manifest.schema.json";
pub const META_SCHEMA_TYPE_DEFINITION_FILE: &str = "type-definition.schema.json";
pub fn publish_meta_schemas(workspace_root: &Path) -> std::io::Result<()> {
let dir = workspace_root.join(".memstead").join(META_SCHEMA_DIR);
write_if_changed(&dir.join(META_SCHEMA_MANIFEST_FILE), META_SCHEMA_MANIFEST)?;
write_if_changed(
&dir.join(META_SCHEMA_TYPE_DEFINITION_FILE),
META_SCHEMA_TYPE_DEFINITION,
)?;
Ok(())
}
fn write_if_changed(path: &Path, contents: &str) -> std::io::Result<()> {
if let Ok(existing) = std::fs::read_to_string(path)
&& existing == contents
{
return Ok(());
}
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(path, contents)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn embedded_meta_schemas_are_valid_json_objects() {
let manifest: serde_json::Value = serde_json::from_str(META_SCHEMA_MANIFEST).unwrap();
assert!(
manifest.get("properties").is_some(),
"manifest meta-schema has properties"
);
let type_def: serde_json::Value =
serde_json::from_str(META_SCHEMA_TYPE_DEFINITION).unwrap();
assert!(
type_def.get("properties").is_some(),
"type meta-schema has properties"
);
}
#[test]
fn publish_writes_both_and_is_idempotent() {
let tmp = tempfile::tempdir().unwrap();
publish_meta_schemas(tmp.path()).unwrap();
let mdir = tmp.path().join(".memstead").join("meta-schemas");
assert_eq!(
std::fs::read_to_string(mdir.join(META_SCHEMA_MANIFEST_FILE)).unwrap(),
META_SCHEMA_MANIFEST,
);
assert!(mdir.join(META_SCHEMA_TYPE_DEFINITION_FILE).is_file());
publish_meta_schemas(tmp.path()).unwrap();
assert_eq!(
std::fs::read_to_string(mdir.join(META_SCHEMA_MANIFEST_FILE)).unwrap(),
META_SCHEMA_MANIFEST,
);
}
}