[−][src]Trait async_graphql::DataSource
Data source of GraphQL Cursor Connections type
Edge
is an extension object type that extends the edge fields, If you don't need it, you can use EmptyEdgeFields
.
References
(GraphQL Cursor Connections Specification)[https://facebook.github.io/relay/graphql/connections.htm]
Examples
use async_graphql::*; use byteorder::{ReadBytesExt, BE}; struct QueryRoot; #[SimpleObject] struct DiffFields { diff: i32, } struct Numbers; #[DataSource] impl DataSource for Numbers { type Element = i32; type EdgeFieldsObj = DiffFields; async fn query_operation(&mut self, ctx: &Context<'_>, operation: &QueryOperation) -> FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>> { let (start, end) = match operation { QueryOperation::First {limit} => { let start = 0; let end = start + *limit as i32; (start, end) } QueryOperation::Last {limit} => { let end = 0; let start = end - *limit as i32; (start, end) } QueryOperation::FirstAfter {after, limit} => { let start = base64::decode(after.to_string()) .ok() .and_then(|data| data.as_slice().read_i32::<BE>().ok()) .map(|idx| idx + 1) .unwrap_or(0); let end = start + *limit as i32; (start, end) } QueryOperation::LastBefore {before, limit} => { let end = base64::decode(before.to_string()) .ok() .and_then(|data| data.as_slice().read_i32::<BE>().ok()) .unwrap_or(0); let start = end - *limit as i32; (start, end) } // You should handle all cases instead of using a default like this _ => (0, 10) }; 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)) } } #[Object] impl QueryRoot { async fn numbers(&self, ctx: &Context<'_>, after: Option<Cursor>, before: Option<Cursor>, first: Option<i32>, last: Option<i32> ) -> FieldResult<Connection<i32, DiffFields>> { Numbers.query(ctx, after, before, first, last).await } } #[async_std::main] async fn main() { let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); assert_eq!(schema.execute("{ numbers(first: 2) { edges { node } } }").await.unwrap().data, serde_json::json!({ "numbers": { "edges": [ {"node": 0}, {"node": 1} ] }, })); assert_eq!(schema.execute("{ numbers(last: 2) { edges { node diff } } }").await.unwrap().data, serde_json::json!({ "numbers": { "edges": [ {"node": -2, "diff": -1002}, {"node": -1, "diff": -1001} ] }, })); }
Associated Types
type Element
Record type
type EdgeFieldsObj: ObjectType + Send
Fields for Edge
Is a type that implements ObjectType
and can be defined by the procedure macro #[Object]
.
Required methods
#[must_use]fn query_operation<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 mut self,
ctx: &'life1 Context<'life2>,
operation: &'life3 QueryOperation
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
&'life0 mut self,
ctx: &'life1 Context<'life2>,
operation: &'life3 QueryOperation
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
Parses the parameters and executes the query,Usually you just need to implement this method.
Provided methods
#[must_use]fn query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 mut self,
ctx: &'life1 Context<'life2>,
after: Option<Cursor>,
before: Option<Cursor>,
first: Option<i32>,
last: Option<i32>
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
&'life0 mut self,
ctx: &'life1 Context<'life2>,
after: Option<Cursor>,
before: Option<Cursor>,
first: Option<i32>,
last: Option<i32>
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Execute the query.
Implementations on Foreign Types
impl<'a, T: Sync> DataSource for &'a [T]
[src]
type Element = &'a T
type EdgeFieldsObj = EmptyEdgeFields
fn query_operation<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 Context<'life2>,
operation: &'life3 QueryOperation
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
[src]
&'life0 mut self,
_ctx: &'life1 Context<'life2>,
operation: &'life3 QueryOperation
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
impl<'a, T, E> DataSource for BoxStream<'a, (Cursor, E, T)> where
T: Send + 'a,
E: ObjectType + Send + 'a,
[src]
T: Send + 'a,
E: ObjectType + Send + 'a,
You can use a Pin<Box<Stream<Item = (Cursor, E, T)>>> as a datasource
Examples
use async_graphql::*; use byteorder::{ReadBytesExt, BE}; use futures::StreamExt; struct QueryRoot; #[Object] impl QueryRoot { async fn stream_connection(&self, ctx: &Context<'_>, after: Option<Cursor>, before: Option<Cursor>, first: Option<i32>, last: Option<i32> ) -> FieldResult<Connection<&str>> { let mut edges_stream = futures::stream::iter(vec!["a", "b", "c", "d", "e", "f"]) .map(|node| { let cursor: Cursor = node.to_owned().into(); (cursor, EmptyEdgeFields, node) }) .boxed(); edges_stream.query(ctx, after, before, first, last).await } } #[async_std::main] async fn main() { let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); assert_eq!( schema .execute("{ streamConnection(first: 2) { edges { node } } }") .await .unwrap() .data, serde_json::json!({ "streamConnection": { "edges": [ { "node": "a" }, { "node": "b" } ] }, }) ); assert_eq!( schema .execute("{ streamConnection(last: 2) { edges { node } } }") .await .unwrap() .data, serde_json::json!({ "streamConnection": { "edges": [ { "node": "e" }, { "node": "f" } ] }, }) ); }
type Element = T
type EdgeFieldsObj = E
fn query_operation<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 Context<'life2>,
operation: &'life3 QueryOperation
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
[src]
&'life0 mut self,
_ctx: &'life1 Context<'life2>,
operation: &'life3 QueryOperation
) -> Pin<Box<dyn Future<Output = FieldResult<Connection<Self::Element, Self::EdgeFieldsObj>>> + Send + 'async_trait>> where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,