use async_graphql::indexmap::IndexMap;
use async_graphql::{
Name, OutputType, ScalarType, SelectionField, ServerError, ServerResult, Value,
};
use p2panda_rs::document::{DocumentId, DocumentViewId};
use crate::graphql::client::dynamic_types::utils::{metafield, metaobject};
use crate::graphql::scalars::{DocumentIdScalar, DocumentViewIdScalar};
pub const DOCUMENT_ID_FIELD: &str = "documentId";
pub const VIEW_ID_FIELD: &str = "viewId";
pub struct DocumentMeta;
impl DocumentMeta {
pub fn type_name() -> &'static str {
"DocumentMeta"
}
pub fn register_type(registry: &mut async_graphql::registry::Registry) {
DocumentIdScalar::create_type_info(registry);
let mut fields = IndexMap::new();
fields.insert(
DOCUMENT_ID_FIELD.to_string(),
metafield(
DOCUMENT_ID_FIELD,
Some("The document id of this response object."),
&*DocumentIdScalar::type_name(),
),
);
fields.insert(
VIEW_ID_FIELD.to_string(),
metafield(
VIEW_ID_FIELD,
Some("The specific document view id contained in this response object."),
&*DocumentViewIdScalar::type_name(),
),
);
registry.types.insert(
Self::type_name().to_string(),
metaobject(
Self::type_name(),
Some("Metadata for documents of this schema."),
fields,
),
);
}
#[allow(clippy::unnecessary_unwrap)]
pub fn resolve(
root_field: SelectionField,
document_id: Option<&DocumentId>,
view_id: Option<&DocumentViewId>,
) -> ServerResult<Value> {
let mut meta_fields = IndexMap::<Name, Value>::new();
for meta_field in root_field.selection_set() {
let response_key = Name::new(meta_field.alias().unwrap_or_else(|| meta_field.name()));
match meta_field.name() {
"__typename" => {
meta_fields.insert(
response_key,
Value::String(DocumentMeta::type_name().to_string()),
);
}
DOCUMENT_ID_FIELD => {
if let Some(document_id) = document_id {
meta_fields
.insert(response_key, DocumentIdScalar::from(document_id).to_value());
}
}
VIEW_ID_FIELD => {
if let Some(view_id) = view_id {
meta_fields.insert(response_key, Value::String(view_id.to_string()));
}
}
_ => Err(ServerError::new(
format!(
"Field '{}' does not exist on {}",
meta_field.name(),
Self::type_name(),
),
None,
))?,
}
}
Ok(Value::Object(meta_fields))
}
}