async-graphql/src/types/connection/edge.rs

115 lines
3.8 KiB
Rust
Raw Normal View History

2020-03-19 09:20:12 +00:00
use crate::{
do_resolve, registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Result, Type,
2020-03-19 09:20:12 +00:00
};
use graphql_parser::query::Field;
use graphql_parser::Pos;
2020-03-19 09:20:12 +00:00
use std::borrow::Cow;
use std::collections::HashMap;
pub struct Edge<'a, T, E> {
pub cursor: &'a str,
pub node: &'a T,
pub extra_type: &'a E,
}
impl<'a, T, E> Type for Edge<'a, T, E>
where
T: OutputValueType + Send + Sync + 'a,
E: ObjectType + Sync + Send + 'a,
{
fn type_name() -> Cow<'static, str> {
Cow::Owned(format!("{}Edge", T::type_name()))
}
fn create_type_info(registry: &mut registry::Registry) -> String {
registry.create_type::<Self, _>(|registry| {
E::create_type_info(registry);
let extra_fields = if let Some(registry::Type::Object { fields, .. }) =
registry.types.get_mut(E::type_name().as_ref())
{
fields.clone()
} else {
unreachable!()
};
registry.types.remove(E::type_name().as_ref());
registry::Type::Object {
name: Self::type_name().to_string(),
description: Some("An edge in a connection."),
fields: {
let mut fields = HashMap::new();
fields.insert(
"node".to_string(),
registry::Field {
name: "node".to_string(),
description: Some("The item at the end of the edge"),
args: Default::default(),
ty: T::create_type_info(registry),
deprecation: None,
2020-03-22 08:45:59 +00:00
cache_control: Default::default(),
2020-04-09 14:03:09 +00:00
external: false,
requires: None,
provides: None,
2020-03-19 09:20:12 +00:00
},
);
fields.insert(
"cursor".to_string(),
registry::Field {
name: "cursor".to_string(),
description: Some("A cursor for use in pagination"),
args: Default::default(),
ty: String::create_type_info(registry),
deprecation: None,
2020-03-22 08:45:59 +00:00
cache_control: Default::default(),
2020-04-09 14:03:09 +00:00
external: false,
requires: None,
provides: None,
2020-03-19 09:20:12 +00:00
},
);
fields.extend(extra_fields);
fields
},
2020-03-22 08:45:59 +00:00
cache_control: Default::default(),
2020-04-09 14:03:09 +00:00
extends: false,
keys: None,
2020-03-19 09:20:12 +00:00
}
})
}
}
#[async_trait::async_trait]
impl<'a, T, E> ObjectType for Edge<'a, T, E>
where
T: OutputValueType + Send + Sync + 'a,
E: ObjectType + Sync + Send + 'a,
{
2020-03-25 03:39:28 +00:00
async fn resolve_field(&self, ctx: &Context<'_>, field: &Field) -> Result<serde_json::Value> {
2020-03-19 09:20:12 +00:00
if field.name.as_str() == "node" {
2020-03-26 03:34:28 +00:00
let ctx_obj = ctx.with_selection_set(&field.selection_set);
return OutputValueType::resolve(self.node, &ctx_obj, field.position).await;
2020-03-19 09:20:12 +00:00
} else if field.name.as_str() == "cursor" {
2020-03-25 03:39:28 +00:00
return Ok(self.cursor.into());
2020-03-19 09:20:12 +00:00
}
2020-03-25 03:39:28 +00:00
self.extra_type.resolve_field(ctx, field).await
2020-03-19 09:20:12 +00:00
}
}
#[async_trait::async_trait]
impl<'a, T, E> OutputValueType for Edge<'a, T, E>
where
T: OutputValueType + Send + Sync + 'a,
E: ObjectType + Sync + Send + 'a,
{
async fn resolve(
value: &Self,
ctx: &ContextSelectionSet<'_>,
_pos: Pos,
) -> Result<serde_json::Value> {
2020-03-25 03:39:28 +00:00
do_resolve(ctx, value).await
2020-03-19 09:20:12 +00:00
}
}