use std::collections::BTreeSet;
use serde::Serialize;
use crate::bus::BUS_ABI;
use crate::participant::spec::{ContractUse, ParticipantBehavior};
pub const EMIT_SCHEMA: &str = "phoxal.emit-apis/v0";
#[derive(Debug, Serialize)]
pub struct ParticipantMetadata {
pub schema: &'static str,
pub artifact: Artifact,
pub framework: Framework,
pub api_version: String,
pub participant_class: &'static str,
pub bus_abi: String,
pub required_contracts: Vec<ContractView>,
pub config_schema: serde_json::Value,
}
#[derive(Debug, Serialize)]
pub struct Artifact {
pub kind: &'static str,
pub id: String,
}
#[derive(Debug, Serialize)]
pub struct Framework {
pub version: String,
}
#[derive(Debug, Serialize)]
pub struct ContractView {
pub api_version: String,
pub schema_id: String,
pub family: String,
}
impl From<&ContractUse> for ContractView {
fn from(c: &ContractUse) -> Self {
ContractView {
api_version: c.api_version.to_string(),
schema_id: c.schema_id.to_string(),
family: c.family.to_string(),
}
}
}
pub fn participant_metadata<R: ParticipantBehavior>() -> ParticipantMetadata {
let mut seen = BTreeSet::new();
let required_contracts = R::FIELD_CONTRACTS
.iter()
.chain(R::SERVER_CONTRACTS.iter())
.filter(|contract| {
seen.insert((
contract.api_version.to_string(),
contract.schema_id.to_string(),
contract.family.to_string(),
))
})
.map(ContractView::from)
.collect();
ParticipantMetadata {
schema: EMIT_SCHEMA,
artifact: Artifact {
kind: R::KIND,
id: R::ID.to_string(),
},
framework: Framework {
version: env!("CARGO_PKG_VERSION").to_string(),
},
api_version: R::API_VERSION.to_string(),
participant_class: R::PARTICIPANT_CLASS,
bus_abi: BUS_ABI.id().to_string(),
required_contracts,
config_schema: serde_json::to_value(schemars::schema_for!(R::Config))
.expect("config JSON schema is always serializable"),
}
}
pub fn emit_apis_json<R: ParticipantBehavior>() -> String {
serde_json::to_string_pretty(&participant_metadata::<R>())
.expect("ParticipantMetadata is always serializable")
}
pub fn print_emit_apis<R: ParticipantBehavior>() {
println!("{}", emit_apis_json::<R>());
}