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

143 lines
4.5 KiB
Rust
Raw Normal View History

use crate::connection::EmptyFields;
2020-09-06 06:16:36 +00:00
use crate::parser::types::Field;
2020-09-12 09:29:52 +00:00
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::type_mark::TypeMarkObject;
use crate::types::connection::CursorType;
2020-09-12 09:29:52 +00:00
use crate::{registry, Context, ContextSelectionSet, OutputValueType, Positioned, Result, Type};
use indexmap::map::IndexMap;
2020-03-19 09:20:12 +00:00
use std::borrow::Cow;
/// The edge type output by the data source
pub struct Edge<C, T, E> {
pub(crate) cursor: C,
pub(crate) node: T,
pub(crate) additional_fields: E,
2020-03-19 09:20:12 +00:00
}
impl<C, T, E> Edge<C, T, E> {
/// Create a new edge, it can have some additional fields.
pub fn with_additional_fields(cursor: C, node: T, additional_fields: E) -> Self {
Self {
cursor,
additional_fields,
node,
}
2020-04-26 04:34:08 +00:00
}
}
2020-04-26 04:34:08 +00:00
impl<C: CursorType, T> Edge<C, T, EmptyFields> {
/// Create a new edge.
pub fn new(cursor: C, node: T) -> Self {
Self {
cursor,
node,
additional_fields: EmptyFields,
}
2020-04-26 04:34:08 +00:00
}
}
impl<C, T, E> Type for Edge<C, T, E>
2020-03-19 09:20:12 +00:00
where
C: CursorType,
T: OutputValueType + Send + Sync,
E: ObjectType + Sync + Send,
2020-03-19 09:20:12 +00:00
{
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 additional_fields = if let Some(registry::MetaType::Object { fields, .. }) =
registry.types.remove(E::type_name().as_ref())
2020-03-19 09:20:12 +00:00
{
fields
2020-03-19 09:20:12 +00:00
} else {
unreachable!()
};
registry::MetaType::Object {
2020-03-19 09:20:12 +00:00
name: Self::type_name().to_string(),
description: Some("An edge in a connection."),
fields: {
let mut fields = IndexMap::new();
2020-03-19 09:20:12 +00:00
fields.insert(
"node".to_string(),
registry::MetaField {
2020-03-19 09:20:12 +00:00
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::MetaField {
2020-03-19 09:20:12 +00:00
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(additional_fields);
2020-03-19 09:20:12 +00:00
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<C, T, E> ObjectType for Edge<C, T, E>
2020-03-19 09:20:12 +00:00
where
C: CursorType + Send + Sync,
T: OutputValueType + Send + Sync,
E: ObjectType + Sync + Send,
2020-03-19 09:20:12 +00:00
{
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
2020-09-12 16:42:15 +00:00
if ctx.item.node.name.node == "node" {
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
return OutputValueType::resolve(&self.node, &ctx_obj, ctx.item).await;
2020-09-12 16:42:15 +00:00
} else if ctx.item.node.name.node == "cursor" {
return Ok(self.cursor.encode_cursor().into());
2020-03-19 09:20:12 +00:00
}
self.additional_fields.resolve_field(ctx).await
2020-03-19 09:20:12 +00:00
}
}
#[async_trait::async_trait]
impl<C, T, E> OutputValueType for Edge<C, T, E>
2020-03-19 09:20:12 +00:00
where
C: CursorType + Send + Sync,
T: OutputValueType + Send + Sync,
E: ObjectType + Sync + Send,
2020-03-19 09:20:12 +00:00
{
2020-05-20 00:18:28 +00:00
async fn resolve(
&self,
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> Result<serde_json::Value> {
2020-09-12 09:29:52 +00:00
resolve_object(ctx, self).await
2020-03-19 09:20:12 +00:00
}
}
impl<C, T, E> TypeMarkObject for Edge<C, T, E> {}