Remove all datasource-related code and update the documentation.
This commit is contained in:
parent
c7eeec4ae8
commit
cda4498979
|
@ -832,27 +832,6 @@ impl Interface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DataSource {
|
|
||||||
pub internal: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DataSource {
|
|
||||||
pub fn parse(args: AttributeArgs) -> Result<Self> {
|
|
||||||
let mut internal = false;
|
|
||||||
|
|
||||||
for arg in args {
|
|
||||||
match arg {
|
|
||||||
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("internal") => {
|
|
||||||
internal = true;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { internal })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Scalar {
|
pub struct Scalar {
|
||||||
pub internal: bool,
|
pub internal: bool,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
|
|
@ -15,7 +15,7 @@ mod subscription;
|
||||||
mod union;
|
mod union;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use crate::utils::{add_container_attrs, get_crate_name, parse_derive};
|
use crate::utils::{add_container_attrs, parse_derive};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::parse_macro_input;
|
use syn::parse_macro_input;
|
||||||
|
@ -189,23 +189,6 @@ pub fn Subscription(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn DataSource(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
let datasource_args = match args::DataSource::parse(parse_macro_input!(args as AttributeArgs)) {
|
|
||||||
Ok(datasource_args) => datasource_args,
|
|
||||||
Err(err) => return err.to_compile_error().into(),
|
|
||||||
};
|
|
||||||
let input2: proc_macro2::TokenStream = input.clone().into();
|
|
||||||
let _item_impl = parse_macro_input!(input as ItemImpl);
|
|
||||||
let crate_name = get_crate_name(datasource_args.internal);
|
|
||||||
let expanded = quote! {
|
|
||||||
#[#crate_name::async_trait::async_trait]
|
|
||||||
#input2
|
|
||||||
};
|
|
||||||
expanded.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Scalar(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn Scalar(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
|
|
@ -2,62 +2,12 @@
|
||||||
|
|
||||||
Relay's cursor connection specification is defined to provide a consistent method for query paging. For more details on the specification see the [GraphQL Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)。
|
Relay's cursor connection specification is defined to provide a consistent method for query paging. For more details on the specification see the [GraphQL Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)。
|
||||||
|
|
||||||
It is simple to define a cursor connection in `Async-GraphQL`
|
Define a cursor connection in `async-graphql` is very simple, you just call the `connection::query` function and query data in closure.
|
||||||
|
|
||||||
1. Implement `async_graphql::DataSource` and write the `execute_query` function.
|
|
||||||
2. Call `DataSource::query` in the field's resolver function and return the result.
|
|
||||||
|
|
||||||
Here is a simple data source that returns continuous integers:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use async_graphql::*;
|
use async_graphql::*;
|
||||||
use async_graphql::connection::*;
|
use async_graphql::connection::*;
|
||||||
|
|
||||||
struct Integers;
|
|
||||||
|
|
||||||
#[DataSource]
|
|
||||||
impl DataSource for Integers {
|
|
||||||
// Type for cursor
|
|
||||||
type CursorType = usize;
|
|
||||||
|
|
||||||
// Type for response
|
|
||||||
type NodeType = i32;
|
|
||||||
|
|
||||||
// We don't need to extend the connection fields, so this can be empty
|
|
||||||
type ConnectionFieldsType = EmptyFields;
|
|
||||||
|
|
||||||
// We don't need to extend the edge fields, so this can be empty
|
|
||||||
type EdgeFieldsType = EmptyFields;
|
|
||||||
|
|
||||||
async fn execute_query(
|
|
||||||
&mut self,
|
|
||||||
_ctx: &Context<'_>,
|
|
||||||
after: Option<usize>,
|
|
||||||
before: Option<usize>,
|
|
||||||
first: Option<usize>,
|
|
||||||
last: Option<usize>,
|
|
||||||
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
|
|
||||||
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.append(
|
|
||||||
(start..end).into_iter().map(|n|
|
|
||||||
Ok(Edge::new_with_additional_fields(n, n as i32, EmptyFields)),
|
|
||||||
)?;
|
|
||||||
Ok(connection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Query;
|
struct Query;
|
||||||
|
|
||||||
#[Object]
|
#[Object]
|
||||||
|
@ -69,7 +19,26 @@ impl Query {
|
||||||
first: Option<i32>,
|
first: Option<i32>,
|
||||||
last: Option<i32>,
|
last: Option<i32>,
|
||||||
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
|
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
|
||||||
Integers.query(after, before, first, last).await
|
query(after, before, first, last, |after, before, first, last| {
|
||||||
|
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.append(
|
||||||
|
(start..end).into_iter().map(|n|
|
||||||
|
Ok(Edge::new_with_additional_fields(n, n as i32, EmptyFields)),
|
||||||
|
))?;
|
||||||
|
Ok(connection)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
|
|
||||||
Relay定义了一套游标连接规范,以提供一致性的分页查询方式,具体的规范文档请参考[GraphQL Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)。
|
Relay定义了一套游标连接规范,以提供一致性的分页查询方式,具体的规范文档请参考[GraphQL Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)。
|
||||||
|
|
||||||
在`Async-graphql`中定义一个连接非常简单,只需要两步:
|
在`Async-graphql`中定义一个游标连接非常简单,你只需要调用connection::query函数,并在闭包中查询数据。
|
||||||
|
|
||||||
1. 实现`async_graphql::DataSource`,重写`execute_query`函数。
|
|
||||||
2. 在字段的Resolver函数中调用`DataSource::query`函数并传递响应参数。
|
|
||||||
|
|
||||||
下面是一个简单的获取连续整数的数据源:
|
下面是一个简单的获取连续整数的数据源:
|
||||||
|
|
||||||
|
@ -13,51 +10,6 @@ Relay定义了一套游标连接规范,以提供一致性的分页查询方式
|
||||||
use async_graphql::*;
|
use async_graphql::*;
|
||||||
use async_graphql::connection::*;
|
use async_graphql::connection::*;
|
||||||
|
|
||||||
struct Integers;
|
|
||||||
|
|
||||||
#[DataSource]
|
|
||||||
impl DataSource for Integers {
|
|
||||||
// 游标类型
|
|
||||||
type CursorType = usize;
|
|
||||||
|
|
||||||
// 元素类型
|
|
||||||
type NodeType = i32;
|
|
||||||
|
|
||||||
// 我们不需要扩展连接的字段,所以传EmptyFields
|
|
||||||
type ConnectionFieldsType = EmptyFields;
|
|
||||||
|
|
||||||
// 我们不需要扩展边的字段,所以传EmptyFields
|
|
||||||
type EdgeFieldsType = EmptyFields;
|
|
||||||
|
|
||||||
async fn execute_query(
|
|
||||||
&mut self,
|
|
||||||
_ctx: &Context<'_>,
|
|
||||||
after: Option<usize>,
|
|
||||||
before: Option<usize>,
|
|
||||||
first: Option<usize>,
|
|
||||||
last: Option<usize>,
|
|
||||||
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
|
|
||||||
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.append(
|
|
||||||
(start..end).into_iter().map(|n|
|
|
||||||
Ok(Edge::new_with_additional_fields(n, n as i32, EmptyFields)),
|
|
||||||
)?;
|
|
||||||
Ok(connection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Query;
|
struct Query;
|
||||||
|
|
||||||
#[Object]
|
#[Object]
|
||||||
|
@ -69,8 +21,26 @@ impl Query {
|
||||||
first: Option<i32>,
|
first: Option<i32>,
|
||||||
last: Option<i32>,
|
last: Option<i32>,
|
||||||
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
|
) -> FieldResult<Connection<usize, i32, EmptyFields, EmptyFields>> {
|
||||||
Integers.query(after, before, first, last).await
|
query(after, before, first, last, |after, before, first, last| {
|
||||||
|
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.append(
|
||||||
|
(start..end).into_iter().map(|n|
|
||||||
|
Ok(Edge::new_with_additional_fields(n, n as i32, EmptyFields)),
|
||||||
|
))?;
|
||||||
|
Ok(connection)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
|
@ -742,9 +742,6 @@ pub use async_graphql_derive::GQLUnion;
|
||||||
/// ```
|
/// ```
|
||||||
pub use async_graphql_derive::Subscription;
|
pub use async_graphql_derive::Subscription;
|
||||||
|
|
||||||
/// Define a DataSource
|
|
||||||
pub use async_graphql_derive::DataSource;
|
|
||||||
|
|
||||||
/// Define a Scalar
|
/// Define a Scalar
|
||||||
///
|
///
|
||||||
/// # Macro parameters
|
/// # Macro parameters
|
||||||
|
|
|
@ -12,7 +12,7 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
/// Connection type
|
/// Connection type
|
||||||
///
|
///
|
||||||
/// Connection is the result of a query for `DataSource`.
|
/// Connection is the result of a query for `connection::query`.
|
||||||
pub struct Connection<C, T, EC = EmptyFields, EE = EmptyFields> {
|
pub struct Connection<C, T, EC = EmptyFields, EE = EmptyFields> {
|
||||||
/// All edges of the current page.
|
/// All edges of the current page.
|
||||||
edges: Vec<Edge<C, T, EE>>,
|
edges: Vec<Edge<C, T, EE>>,
|
||||||
|
|
|
@ -19,8 +19,6 @@ pub struct EmptyFields;
|
||||||
|
|
||||||
/// Parses the parameters and executes the query.
|
/// Parses the parameters and executes the query.
|
||||||
///
|
///
|
||||||
/// If you don't want to implement `DataSource`, you can also use this function to query data directly.
|
|
||||||
///
|
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
|
|
@ -2,7 +2,7 @@ use async_graphql::connection::*;
|
||||||
use async_graphql::*;
|
use async_graphql::*;
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
pub async fn test_datasource_additional_fields() {
|
pub async fn test_connection_additional_fields() {
|
||||||
struct QueryRoot;
|
struct QueryRoot;
|
||||||
|
|
||||||
#[SimpleObject]
|
#[SimpleObject]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user