pub async fn query<Name, EdgeName, Cursor, Node, ConnectionFields, EdgeFields, F, R, E>(
    after: Option<String>,
    before: Option<String>,
    first: Option<i32>,
    last: Option<i32>,
    f: F
) -> Result<Connection<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName>> where
    Name: ConnectionNameType,
    EdgeName: EdgeNameType,
    Cursor: CursorType + Send + Sync,
    <Cursor as CursorType>::Error: Display + Send + Sync + 'static,
    Node: OutputType,
    ConnectionFields: ObjectType,
    EdgeFields: ObjectType,
    F: FnOnce(Option<Cursor>, Option<Cursor>, Option<usize>, Option<usize>) -> R,
    R: Future<Output = Result<Connection<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName>, E>>,
    E: Into<Error>, 
Expand description

Parses the parameters and executes the query.

Examples

use std::borrow::Cow;

use async_graphql::*;
use async_graphql::types::connection::*;

struct Query;

struct Numbers;

#[derive(SimpleObject)]
struct Diff {
    diff: i32,
}

#[Object]
impl Query {
    async fn numbers(&self,
        after: Option<String>,
        before: Option<String>,
        first: Option<i32>,
        last: Option<i32>
    ) -> Result<Connection<usize, i32, EmptyFields, Diff>> {
        query(after, before, first, last, |after, before, first, last| async move {
            let mut start = after.map(|after| after + 1).unwrap_or(0);
            let mut end = before.unwrap_or(10000);
            if let Some(first) = first {
                end = (start + first).min(end);
            }
            if let Some(last) = last {
                start = if last > end - start {
                    end
                } else {
                    end - last
                };
            }
            let mut connection = Connection::new(start > 0, end < 10000);
            connection.edges.extend(
                (start..end).into_iter().map(|n|
                    Edge::with_additional_fields(n, n as i32, Diff{ diff: (10000 - n) as i32 })),
            );
            Ok::<_, Error>(connection)
        }).await
    }
}

let schema = Schema::new(Query, EmptyMutation, EmptySubscription);

assert_eq!(schema.execute("{ numbers(first: 2) { edges { node diff } } }").await.into_result().unwrap().data, value!({
    "numbers": {
        "edges": [
            {"node": 0, "diff": 10000},
            {"node": 1, "diff": 9999},
        ]
    },
}));

assert_eq!(schema.execute("{ numbers(last: 2) { edges { node diff } } }").await.into_result().unwrap().data, value!({
    "numbers": {
        "edges": [
            {"node": 9998, "diff": 2},
            {"node": 9999, "diff": 1},
        ]
    },
}));

Custom connection and edge type names

use async_graphql::{connection::*, *};

#[derive(SimpleObject)]
struct MyObj {
    a: i32,
    b: String,
}

// Use to custom connection name
struct MyConnectionName;

impl ConnectionNameType for MyConnectionName {
    fn type_name<T: OutputType>() -> String {
        "MyConnection".to_string()
    }
}

// Use to custom edge name
struct MyEdgeName;

impl EdgeNameType for MyEdgeName {
    fn type_name<T: OutputType>() -> String {
        "MyEdge".to_string()
    }
}

struct Query;

#[Object]
impl Query {
    async fn numbers(
        &self,
        after: Option<String>,
        before: Option<String>,
        first: Option<i32>,
        last: Option<i32>,
    ) -> Connection<usize, MyObj, EmptyFields, EmptyFields, MyConnectionName, MyEdgeName> {
        let mut connection = Connection::new(false, false);
        connection.edges.push(Edge::new(1, MyObj { a: 100, b: "abc".to_string() }));
        connection
    }
}

let schema = Schema::new(Query, EmptyMutation, EmptySubscription);

let query = r#"{
    numbers(first: 2) {
        __typename
        edges { __typename node { a b } }
    }
}"#;
let data = schema.execute(query).await.into_result().unwrap().data;
assert_eq!(data, value!({
    "numbers": {
        "__typename": "MyConnection",
        "edges": [
            {"__typename": "MyEdge", "node": { "a": 100, "b": "abc" }},
        ]
    },
}));