use schemars::{JsonSchema, generate::SchemaSettings};
use serde_json::Value;
use super::{FlowGraphView, HumanInboxEntry, RunOverview, StepDossierView, TimelinePage};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProjectionSchemaFamily {
FlowGraph,
RunTimeline,
StepDossier,
HumanInbox,
RunOverview,
}
pub const PROJECTION_SCHEMA_FAMILIES: [ProjectionSchemaFamily; 5] = [
ProjectionSchemaFamily::FlowGraph,
ProjectionSchemaFamily::RunTimeline,
ProjectionSchemaFamily::StepDossier,
ProjectionSchemaFamily::HumanInbox,
ProjectionSchemaFamily::RunOverview,
];
impl ProjectionSchemaFamily {
pub fn stem(self) -> &'static str {
match self {
ProjectionSchemaFamily::FlowGraph => "flow-graph-view",
ProjectionSchemaFamily::RunTimeline => "run-timeline",
ProjectionSchemaFamily::StepDossier => "step-dossier-view",
ProjectionSchemaFamily::HumanInbox => "human-inbox-entry",
ProjectionSchemaFamily::RunOverview => "run-overview",
}
}
pub fn title(self) -> &'static str {
match self {
ProjectionSchemaFamily::FlowGraph => "FlowGraphView",
ProjectionSchemaFamily::RunTimeline => "TimelinePage",
ProjectionSchemaFamily::StepDossier => "StepDossierView",
ProjectionSchemaFamily::HumanInbox => "HumanInboxEntry",
ProjectionSchemaFamily::RunOverview => "RunOverview",
}
}
pub fn schema_id(self) -> String {
format!("urn:pointlock:schema:projection:v1:{}", self.stem())
}
}
fn root_schema<T: JsonSchema>(family: ProjectionSchemaFamily) -> Value {
let settings = SchemaSettings::draft2020_12();
let mut generator = settings.into_generator();
let schema = generator.root_schema_for::<T>();
let mut doc = serde_json::to_value(&schema).expect("schema serializes to JSON");
if let Value::Object(root) = &mut doc {
root.insert("$id".to_owned(), Value::String(family.schema_id()));
root.insert("title".to_owned(), Value::String(family.title().to_owned()));
}
doc
}
pub fn projection_schema(family: ProjectionSchemaFamily) -> Value {
match family {
ProjectionSchemaFamily::FlowGraph => root_schema::<FlowGraphView>(family),
ProjectionSchemaFamily::RunTimeline => root_schema::<TimelinePage>(family),
ProjectionSchemaFamily::StepDossier => root_schema::<StepDossierView>(family),
ProjectionSchemaFamily::HumanInbox => root_schema::<HumanInboxEntry>(family),
ProjectionSchemaFamily::RunOverview => root_schema::<RunOverview>(family),
}
}
pub fn projection_schemas() -> Vec<(ProjectionSchemaFamily, Value)> {
PROJECTION_SCHEMA_FAMILIES
.iter()
.map(|&family| (family, projection_schema(family)))
.collect()
}