2020-05-28 00:02:00 +00:00
|
|
|
use crate::connection::EmptyFields;
|
|
|
|
use crate::types::connection::CursorType;
|
2020-03-19 09:20:12 +00:00
|
|
|
use crate::{
|
2020-05-20 00:18:28 +00:00
|
|
|
do_resolve, registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned,
|
2020-05-28 00:02:00 +00:00
|
|
|
QueryError, Result, Type,
|
2020-03-19 09:20:12 +00:00
|
|
|
};
|
2020-05-20 00:18:28 +00:00
|
|
|
use async_graphql_parser::query::Field;
|
2020-05-16 02:05:48 +00:00
|
|
|
use indexmap::map::IndexMap;
|
2020-03-19 09:20:12 +00:00
|
|
|
use std::borrow::Cow;
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
/// 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
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
impl<C, T, E> Edge<C, T, E> {
|
|
|
|
/// Create a new edge, it can have some additional fields.
|
2020-05-29 02:28:18 +00:00
|
|
|
pub fn with_additional_fields(cursor: C, node: T, additional_fields: E) -> Self {
|
2020-05-28 00:02:00 +00:00
|
|
|
Self {
|
|
|
|
cursor,
|
|
|
|
additional_fields,
|
|
|
|
node,
|
|
|
|
}
|
2020-04-26 04:34:08 +00:00
|
|
|
}
|
2020-05-28 00:02:00 +00:00
|
|
|
}
|
2020-04-26 04:34:08 +00:00
|
|
|
|
2020-05-28 00:02:00 +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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
impl<C, T, E> Type for Edge<C, T, E>
|
2020-03-19 09:20:12 +00:00
|
|
|
where
|
2020-05-28 00:02:00 +00:00
|
|
|
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);
|
2020-05-28 00:02:00 +00:00
|
|
|
let additional_fields = if let Some(registry::MetaType::Object { fields, .. }) =
|
2020-05-05 05:46:56 +00:00
|
|
|
registry.types.remove(E::type_name().as_ref())
|
2020-03-19 09:20:12 +00:00
|
|
|
{
|
2020-05-05 05:46:56 +00:00
|
|
|
fields
|
2020-03-19 09:20:12 +00:00
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
};
|
|
|
|
|
2020-05-15 02:08:37 +00:00
|
|
|
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: {
|
2020-05-16 02:05:48 +00:00
|
|
|
let mut fields = IndexMap::new();
|
2020-03-19 09:20:12 +00:00
|
|
|
|
|
|
|
fields.insert(
|
|
|
|
"node".to_string(),
|
2020-05-15 02:08:37 +00:00
|
|
|
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(),
|
2020-05-15 02:08:37 +00:00
|
|
|
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
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2020-05-28 00:02:00 +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]
|
2020-05-28 00:02:00 +00:00
|
|
|
impl<C, T, E> ObjectType for Edge<C, T, E>
|
2020-03-19 09:20:12 +00:00
|
|
|
where
|
2020-05-28 00:02:00 +00:00
|
|
|
C: CursorType + Send + Sync,
|
|
|
|
T: OutputValueType + Send + Sync,
|
|
|
|
E: ObjectType + Sync + Send,
|
2020-03-19 09:20:12 +00:00
|
|
|
{
|
2020-04-26 07:12:18 +00:00
|
|
|
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
|
2020-05-12 08:27:06 +00:00
|
|
|
if ctx.name.node == "node" {
|
2020-04-26 07:12:18 +00:00
|
|
|
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
2020-05-28 00:02:00 +00:00
|
|
|
return OutputValueType::resolve(&self.node, &ctx_obj, ctx.item).await;
|
2020-05-12 08:27:06 +00:00
|
|
|
} else if ctx.name.node == "cursor" {
|
2020-05-28 00:02:00 +00:00
|
|
|
return Ok(self
|
|
|
|
.cursor
|
|
|
|
.encode_cursor()
|
|
|
|
.map_err(|err| {
|
|
|
|
QueryError::FieldError {
|
|
|
|
err: err.to_string(),
|
|
|
|
extended_error: None,
|
|
|
|
}
|
|
|
|
.into_error(ctx.position())
|
|
|
|
})?
|
|
|
|
.into());
|
2020-03-19 09:20:12 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
self.additional_fields.resolve_field(ctx).await
|
2020-03-19 09:20:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
2020-05-28 00:02:00 +00:00
|
|
|
impl<C, T, E> OutputValueType for Edge<C, T, E>
|
2020-03-19 09:20:12 +00:00
|
|
|
where
|
2020-05-28 00:02:00 +00:00
|
|
|
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-05-05 13:06:48 +00:00
|
|
|
do_resolve(ctx, self).await
|
2020-03-19 09:20:12 +00:00
|
|
|
}
|
|
|
|
}
|