parent
a5b2272b59
commit
eaa50a52e0
|
@ -1,3 +1,4 @@
|
|||
use crate::types::connection::cursor::Cursor;
|
||||
use crate::types::connection::edge::Edge;
|
||||
use crate::types::connection::page_info::PageInfo;
|
||||
use crate::{
|
||||
|
@ -18,7 +19,7 @@ use std::collections::HashMap;
|
|||
pub struct Connection<T, E: ObjectType + Sync + Send = EmptyEdgeFields> {
|
||||
total_count: Option<usize>,
|
||||
page_info: PageInfo,
|
||||
nodes: Vec<(String, E, T)>,
|
||||
nodes: Vec<(Cursor, E, T)>,
|
||||
}
|
||||
|
||||
impl<T, E: ObjectType + Sync + Send> Connection<T, E> {
|
||||
|
@ -27,7 +28,7 @@ impl<T, E: ObjectType + Sync + Send> Connection<T, E> {
|
|||
total_count: Option<usize>,
|
||||
has_previous_page: bool,
|
||||
has_next_page: bool,
|
||||
nodes: Vec<(String, E, T)>,
|
||||
nodes: Vec<(Cursor, E, T)>,
|
||||
) -> Self {
|
||||
Connection {
|
||||
total_count,
|
||||
|
|
66
src/types/connection/cursor.rs
Normal file
66
src/types/connection/cursor.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use crate::{Result, ScalarType, Value};
|
||||
use async_graphql_derive::Scalar;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// Cursor scalar
|
||||
///
|
||||
/// A custom scalar that serializes as a string.
|
||||
/// https://relay.dev/graphql/connections.htm#sec-Cursor
|
||||
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct Cursor(String);
|
||||
|
||||
impl std::fmt::Display for Cursor {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Cursor {
|
||||
type Target = String;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Cursor {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Cursor {
|
||||
fn from(value: String) -> Self {
|
||||
Cursor(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Cursor {
|
||||
fn from(value: &'a str) -> Self {
|
||||
Cursor(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Cursor {
|
||||
fn from(value: usize) -> Self {
|
||||
Cursor(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[Scalar(internal)]
|
||||
impl ScalarType for Cursor {
|
||||
fn type_name() -> &'static str {
|
||||
"Cursor"
|
||||
}
|
||||
|
||||
fn parse(value: &Value) -> Option<Self> {
|
||||
match value {
|
||||
Value::String(s) => Some(Cursor(s.into())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_json(&self) -> Result<serde_json::Value> {
|
||||
Ok(self.0.to_string().into())
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
mod connection_type;
|
||||
mod cursor;
|
||||
mod edge;
|
||||
mod page_info;
|
||||
mod slice;
|
||||
|
@ -6,6 +7,7 @@ mod slice;
|
|||
use crate::{Context, FieldResult, ObjectType};
|
||||
|
||||
pub use connection_type::Connection;
|
||||
pub use cursor::Cursor;
|
||||
|
||||
/// Connection query operation
|
||||
pub enum QueryOperation<'a> {
|
||||
|
@ -77,7 +79,7 @@ pub struct EmptyEdgeFields;
|
|||
/// }
|
||||
/// };
|
||||
///
|
||||
/// let nodes = (start..end).into_iter().map(|n| (base64::encode(n.to_be_bytes()), DiffFields {diff: n - 1000}, n)).collect();
|
||||
/// let nodes = (start..end).into_iter().map(|n| (base64::encode(n.to_be_bytes()).into(), DiffFields {diff: n - 1000}, n)).collect();
|
||||
/// Ok(Connection::new(None, true, true, nodes))
|
||||
/// }
|
||||
/// }
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::types::connection::cursor::Cursor;
|
||||
use async_graphql_derive::Object;
|
||||
|
||||
pub struct PageInfo {
|
||||
pub has_previous_page: bool,
|
||||
pub has_next_page: bool,
|
||||
pub start_cursor: Option<String>,
|
||||
pub end_cursor: Option<String>,
|
||||
pub start_cursor: Option<Cursor>,
|
||||
pub end_cursor: Option<Cursor>,
|
||||
}
|
||||
|
||||
#[Object(internal)]
|
||||
|
@ -20,12 +21,12 @@ impl PageInfo {
|
|||
}
|
||||
|
||||
#[field(desc = "When paginating backwards, the cursor to continue.")]
|
||||
async fn start_cursor(&self) -> &Option<String> {
|
||||
async fn start_cursor(&self) -> &Option<Cursor> {
|
||||
&self.start_cursor
|
||||
}
|
||||
|
||||
#[field(desc = "When paginating forwards, the cursor to continue.")]
|
||||
async fn end_cursor(&self) -> &Option<String> {
|
||||
async fn end_cursor(&self) -> &Option<Cursor> {
|
||||
&self.end_cursor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ impl<'a, T: Sync> DataSource for &'a [T] {
|
|||
let mut nodes = Vec::with_capacity(end - start);
|
||||
for (idx, item) in self[start..end].iter().enumerate() {
|
||||
nodes.push((
|
||||
base64::encode((idx as u32).to_be_bytes()),
|
||||
base64::encode((idx as u32).to_be_bytes()).into(),
|
||||
EmptyEdgeFields,
|
||||
item,
|
||||
));
|
||||
|
|
|
@ -7,7 +7,7 @@ mod optional;
|
|||
mod query_root;
|
||||
mod upload;
|
||||
|
||||
pub use connection::{Connection, DataSource, EmptyEdgeFields, QueryOperation};
|
||||
pub use connection::{Connection, Cursor, DataSource, EmptyEdgeFields, QueryOperation};
|
||||
pub use empty_mutation::EmptyMutation;
|
||||
pub use empty_subscription::EmptySubscription;
|
||||
pub use query_root::QueryRoot;
|
||||
|
|
Loading…
Reference in New Issue
Block a user