2020-03-01 13:56:14 +00:00
|
|
|
//! # The GraphQL server library implemented by rust
|
|
|
|
//!
|
|
|
|
//! <div align="center">
|
|
|
|
//! <!-- CI -->
|
|
|
|
//! <img src="https://github.com/sunli829/potatonet/workflows/CI/badge.svg" />
|
|
|
|
//! <!-- Crates version -->
|
|
|
|
//! <a href="https://crates.io/crates/async-graphql">
|
|
|
|
//! <img src="https://img.shields.io/crates/v/async-graphql.svg?style=flat-square"
|
|
|
|
//! alt="Crates.io version" />
|
|
|
|
//! </a>
|
|
|
|
//! <!-- Downloads -->
|
|
|
|
//! <a href="https://crates.io/crates/async-graphql">
|
|
|
|
//! <img src="https://img.shields.io/crates/d/async-graphql.svg?style=flat-square"
|
|
|
|
//! alt="Download" />
|
|
|
|
//! </a>
|
|
|
|
//! <!-- docs.rs docs -->
|
|
|
|
//! <a href="https://docs.rs/async-graphql">
|
|
|
|
//! <img src="https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square"
|
|
|
|
//! alt="docs.rs docs" />
|
|
|
|
//! </a>
|
|
|
|
//! </div>
|
|
|
|
//!
|
|
|
|
//! ## Documentation
|
|
|
|
//!
|
|
|
|
//! * [GitHub repository](https://github.com/sunli829/async-graphql)
|
|
|
|
//! * [Cargo package](https://crates.io/crates/async-graphql)
|
2020-03-10 07:39:50 +00:00
|
|
|
//! * Minimum supported Rust version: 1.40 or later
|
2020-03-01 13:56:14 +00:00
|
|
|
//!
|
2020-03-04 06:27:00 +00:00
|
|
|
//! ## Features
|
|
|
|
//!
|
2020-03-17 11:11:14 +00:00
|
|
|
//! * Fully support async/await
|
|
|
|
//! * Type safety
|
|
|
|
//! * Rustfmt friendly (Procedural Macro)
|
|
|
|
//! * Custom scalar
|
|
|
|
//! * Minimal overhead
|
|
|
|
//! * Easy integration (hyper, actix_web, tide ...)
|
|
|
|
//! * Upload files (Multipart request)
|
|
|
|
//! * Subscription (WebSocket transport)
|
2020-03-26 03:34:28 +00:00
|
|
|
//! * Custom extension
|
|
|
|
//! * Apollo Tracing extension
|
|
|
|
//! * Limit query complexity/depth
|
2020-03-31 03:19:18 +00:00
|
|
|
//! * Error Extensions
|
2020-03-04 06:27:00 +00:00
|
|
|
//!
|
2020-03-18 03:15:02 +00:00
|
|
|
//! ## Integrations
|
|
|
|
//!
|
|
|
|
//! * Actix-web [async-graphql-actix-web](https://crates.io/crates/async-graphql-actix-web)
|
|
|
|
//!
|
2020-03-04 06:27:00 +00:00
|
|
|
//! ## License
|
|
|
|
//!
|
|
|
|
//! Licensed under either of
|
|
|
|
//!
|
|
|
|
//! * Apache License, Version 2.0,
|
|
|
|
//! (./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
//! * MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT)
|
|
|
|
//! at your option.
|
|
|
|
//!
|
2020-03-01 13:56:14 +00:00
|
|
|
//! ## References
|
|
|
|
//!
|
|
|
|
//! * [GraphQL](https://graphql.org)
|
2020-03-20 03:56:08 +00:00
|
|
|
//! * [GraphQL Multipart Request](https://github.com/jaydenseric/graphql-multipart-request-spec)
|
|
|
|
//! * [GraphQL Cursor Connections Specification](https://facebook.github.io/relay/graphql/connections.htm)
|
|
|
|
//! * [GraphQL over WebSocket Protocol](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md)
|
2020-03-26 07:27:35 +00:00
|
|
|
//! * [Apollo Tracing](https://github.com/apollographql/apollo-tracing)
|
2020-03-20 03:56:08 +00:00
|
|
|
|
|
|
|
#![warn(missing_docs)]
|
2020-03-21 01:32:13 +00:00
|
|
|
#![allow(clippy::needless_doctest_main)]
|
|
|
|
#![allow(clippy::needless_lifetimes)]
|
2020-03-01 13:56:14 +00:00
|
|
|
|
2020-03-01 10:54:34 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate thiserror;
|
2020-03-05 00:39:56 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate serde_derive;
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-03-03 03:48:00 +00:00
|
|
|
mod base;
|
2020-03-01 10:54:34 +00:00
|
|
|
mod context;
|
|
|
|
mod error;
|
2020-03-26 03:34:28 +00:00
|
|
|
pub mod extensions;
|
2020-03-03 11:15:18 +00:00
|
|
|
mod model;
|
2020-03-17 09:26:59 +00:00
|
|
|
mod query;
|
2020-03-06 15:58:43 +00:00
|
|
|
mod resolver;
|
2020-03-02 00:24:49 +00:00
|
|
|
mod scalars;
|
2020-03-03 11:15:18 +00:00
|
|
|
mod schema;
|
2020-03-17 09:26:59 +00:00
|
|
|
mod subscription;
|
2020-03-02 00:24:49 +00:00
|
|
|
mod types;
|
2020-03-08 12:35:36 +00:00
|
|
|
mod validation;
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-03-21 01:32:13 +00:00
|
|
|
/// Input value validators
|
|
|
|
pub mod validators;
|
|
|
|
|
2020-03-01 17:15:05 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-01 10:54:34 +00:00
|
|
|
pub use anyhow;
|
2020-03-01 17:15:05 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-01 10:54:34 +00:00
|
|
|
pub use async_trait;
|
2020-03-01 17:15:05 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-01 10:54:34 +00:00
|
|
|
pub use graphql_parser;
|
2020-03-01 17:15:05 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-01 10:54:34 +00:00
|
|
|
pub use serde_json;
|
|
|
|
|
2020-03-05 00:39:56 +00:00
|
|
|
pub mod http;
|
|
|
|
|
2020-03-20 03:56:08 +00:00
|
|
|
pub use base::{Scalar, Type};
|
2020-03-26 10:30:29 +00:00
|
|
|
pub use context::{Context, QueryPathSegment, Variables};
|
2020-04-02 04:57:53 +00:00
|
|
|
pub use error::{Error, ErrorExtensions, FieldError, FieldResult, QueryError, ResultExt};
|
2020-03-01 10:54:34 +00:00
|
|
|
pub use graphql_parser::query::Value;
|
2020-04-02 02:21:04 +00:00
|
|
|
pub use graphql_parser::Pos;
|
|
|
|
pub use query::{QueryBuilder, QueryResponse};
|
2020-03-22 08:45:59 +00:00
|
|
|
pub use registry::CacheControl;
|
2020-03-02 00:24:49 +00:00
|
|
|
pub use scalars::ID;
|
2020-03-29 12:02:52 +00:00
|
|
|
pub use schema::{publish, Schema};
|
|
|
|
pub use subscription::{
|
2020-03-31 03:19:18 +00:00
|
|
|
SubscriptionConnectionBuilder, SubscriptionStream, SubscriptionStub, SubscriptionStubs,
|
|
|
|
SubscriptionTransport, WebSocketTransport,
|
2020-03-29 12:02:52 +00:00
|
|
|
};
|
2020-03-19 09:20:12 +00:00
|
|
|
pub use types::{
|
|
|
|
Connection, DataSource, EmptyEdgeFields, EmptyMutation, EmptySubscription, QueryOperation,
|
|
|
|
Upload,
|
|
|
|
};
|
2020-03-02 00:24:49 +00:00
|
|
|
|
2020-03-20 03:56:08 +00:00
|
|
|
/// Result type, are actually `anyhow::Result<T>`
|
2020-04-02 02:21:04 +00:00
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
2020-03-01 13:35:39 +00:00
|
|
|
|
|
|
|
// internal types
|
2020-03-01 17:15:05 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
pub use context::ContextSelectionSet;
|
|
|
|
#[doc(hidden)]
|
2020-03-03 11:15:18 +00:00
|
|
|
pub mod registry;
|
2020-03-07 02:39:55 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-25 03:39:28 +00:00
|
|
|
pub use base::{BoxFieldFuture, InputObjectType, InputValueType, ObjectType, OutputValueType};
|
2020-03-09 10:05:52 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-07 03:27:44 +00:00
|
|
|
pub use context::ContextBase;
|
|
|
|
#[doc(hidden)]
|
2020-03-25 03:39:28 +00:00
|
|
|
pub use resolver::{collect_fields, do_resolve};
|
2020-03-09 10:05:52 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-29 12:02:52 +00:00
|
|
|
pub use subscription::SubscriptionType;
|
2020-03-17 09:26:59 +00:00
|
|
|
#[doc(hidden)]
|
2020-03-19 09:20:12 +00:00
|
|
|
pub use types::{EnumItem, EnumType};
|
2020-03-09 10:05:52 +00:00
|
|
|
|
|
|
|
/// Define a GraphQL object
|
|
|
|
///
|
|
|
|
/// # Macro parameters
|
|
|
|
///
|
2020-03-22 08:45:59 +00:00
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |---------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Object name | string | Y |
|
|
|
|
/// | desc | Object description | string | Y |
|
|
|
|
/// | cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// # Field parameters
|
|
|
|
///
|
2020-03-22 08:45:59 +00:00
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |---------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Field name | string | Y |
|
|
|
|
/// | desc | Field description | string | Y |
|
|
|
|
/// | deprecation | Field deprecation reason | string | Y |
|
|
|
|
/// | cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// # Field argument parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Argument name | string | Y |
|
|
|
|
/// | desc | Argument description | string | Y |
|
|
|
|
/// | default | Argument default value | string | Y |
|
2020-03-22 01:34:32 +00:00
|
|
|
/// | validator | Input value validator | [`InputValueValidator`](validators/trait.InputValueValidator.html) | Y |
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// # The field returns the value type
|
|
|
|
///
|
|
|
|
/// - A scalar value, such as `i32`, `bool`
|
|
|
|
/// - Borrowing of scalar values, such as `&i32`, `&bool`
|
|
|
|
/// - Vec<T>, such as `Vec<i32>`
|
|
|
|
/// - Slice<T>, such as `&[i32]`
|
|
|
|
/// - Option<T>, such as `Option<i32>`
|
2020-03-19 09:20:12 +00:00
|
|
|
/// - Object and &Object
|
|
|
|
/// - Enum
|
2020-04-02 02:21:04 +00:00
|
|
|
/// - FieldResult<T, E>, such as `FieldResult<i32, E>`
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// # Context
|
|
|
|
///
|
|
|
|
/// You can define a context as an argument to a method, and the context should be the first argument to the method.
|
|
|
|
///
|
|
|
|
/// ```ignore
|
|
|
|
/// #[Object]
|
2020-03-27 02:20:20 +00:00
|
|
|
/// impl QueryRoot {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// async fn value(&self, ctx: &Context<'_>) -> { ... }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use async_graphql::*;
|
|
|
|
///
|
2020-03-27 02:20:20 +00:00
|
|
|
/// struct QueryRoot {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// value: i32,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[Object]
|
2020-03-27 02:20:20 +00:00
|
|
|
/// impl QueryRoot {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// #[field(desc = "value")]
|
|
|
|
/// async fn value(&self) -> i32 {
|
|
|
|
/// self.value
|
|
|
|
/// }
|
|
|
|
///
|
2020-03-10 06:14:09 +00:00
|
|
|
/// #[field(desc = "reference value")]
|
2020-03-09 10:05:52 +00:00
|
|
|
/// async fn value_ref(&self) -> &i32 {
|
|
|
|
/// &self.value
|
|
|
|
/// }
|
|
|
|
///
|
2020-03-10 06:14:09 +00:00
|
|
|
/// #[field(desc = "value with error")]
|
2020-04-02 02:21:04 +00:00
|
|
|
/// async fn value_with_error(&self) -> FieldResult<i32> {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// Ok(self.value)
|
|
|
|
/// }
|
|
|
|
///
|
2020-03-10 06:14:09 +00:00
|
|
|
/// #[field]
|
2020-03-09 10:05:52 +00:00
|
|
|
/// async fn value_with_arg(&self, #[arg(default = "1")] a: i32) -> i32 {
|
|
|
|
/// a
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[async_std::main]
|
|
|
|
/// async fn main() {
|
2020-03-27 02:20:20 +00:00
|
|
|
/// let schema = Schema::new(QueryRoot{ value: 10 }, EmptyMutation, EmptySubscription);
|
2020-04-02 04:53:53 +00:00
|
|
|
/// let res = schema.execute(r#"{
|
2020-03-09 10:05:52 +00:00
|
|
|
/// value
|
|
|
|
/// valueRef
|
|
|
|
/// valueWithError
|
|
|
|
/// valueWithArg1: valueWithArg
|
|
|
|
/// valueWithArg2: valueWithArg(a: 99)
|
2020-04-02 04:53:53 +00:00
|
|
|
/// }"#).await.unwrap().data;
|
2020-03-09 10:05:52 +00:00
|
|
|
/// assert_eq!(res, serde_json::json!({
|
|
|
|
/// "value": 10,
|
|
|
|
/// "valueRef": 10,
|
|
|
|
/// "valueWithError": 10,
|
|
|
|
/// "valueWithArg1": 1,
|
|
|
|
/// "valueWithArg2": 99
|
|
|
|
/// }));
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
pub use async_graphql_derive::Object;
|
|
|
|
|
2020-03-27 02:20:20 +00:00
|
|
|
/// Define a GraphQL object
|
|
|
|
///
|
|
|
|
/// Similar to `Object`, but defined on a structure that automatically generates getters for all fields.
|
|
|
|
///
|
|
|
|
/// # Macro parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |---------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Object name | string | Y |
|
|
|
|
/// | desc | Object description | string | Y |
|
|
|
|
/// | cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
|
|
|
|
///
|
|
|
|
/// # Field parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |---------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Field name | string | Y |
|
|
|
|
/// | desc | Field description | string | Y |
|
|
|
|
/// | deprecation | Field deprecation reason | string | Y |
|
|
|
|
/// | cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use async_graphql::*;
|
|
|
|
///
|
|
|
|
/// #[SimpleObject]
|
|
|
|
/// struct QueryRoot {
|
|
|
|
/// #[field]
|
|
|
|
/// value: i32,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[async_std::main]
|
|
|
|
/// async fn main() {
|
|
|
|
/// let schema = Schema::new(QueryRoot{ value: 10 }, EmptyMutation, EmptySubscription);
|
2020-04-02 04:53:53 +00:00
|
|
|
/// let res = schema.execute("{ value }").await.unwrap().data;
|
2020-03-27 02:20:20 +00:00
|
|
|
/// assert_eq!(res, serde_json::json!({
|
|
|
|
/// "value": 10,
|
|
|
|
/// }));
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
pub use async_graphql_derive::SimpleObject;
|
|
|
|
|
2020-03-09 10:05:52 +00:00
|
|
|
/// Define a GraphQL enum
|
|
|
|
///
|
|
|
|
/// # Macro parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Enum name | string | Y |
|
|
|
|
/// | desc | Enum description | string | Y |
|
|
|
|
///
|
|
|
|
/// # Item parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Item name | string | Y |
|
|
|
|
/// | desc | Item description | string | Y |
|
|
|
|
/// | deprecation | Item deprecation reason | string | Y |
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use async_graphql::*;
|
|
|
|
///
|
|
|
|
/// #[Enum]
|
|
|
|
/// enum MyEnum {
|
|
|
|
/// A,
|
|
|
|
/// #[item(name = "b")] B,
|
|
|
|
/// }
|
|
|
|
///
|
2020-03-27 02:20:20 +00:00
|
|
|
/// struct QueryRoot {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// value1: MyEnum,
|
|
|
|
/// value2: MyEnum,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[Object]
|
2020-03-27 02:20:20 +00:00
|
|
|
/// impl QueryRoot {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// #[field(desc = "value")]
|
|
|
|
/// async fn value1(&self) -> MyEnum {
|
|
|
|
/// self.value1
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[field(desc = "value")]
|
|
|
|
/// async fn value2(&self) -> MyEnum {
|
|
|
|
/// self.value2
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[async_std::main]
|
|
|
|
/// async fn main() {
|
2020-03-27 02:20:20 +00:00
|
|
|
/// let schema = Schema::new(QueryRoot{ value1: MyEnum::A, value2: MyEnum::B }, EmptyMutation, EmptySubscription);
|
2020-04-02 04:53:53 +00:00
|
|
|
/// let res = schema.execute("{ value1 value2 }").await.unwrap().data;
|
2020-03-09 10:05:52 +00:00
|
|
|
/// assert_eq!(res, serde_json::json!({ "value1": "A", "value2": "b" }));
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
pub use async_graphql_derive::Enum;
|
|
|
|
|
|
|
|
/// Define a GraphQL input object
|
|
|
|
///
|
|
|
|
/// # Macro parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Object name | string | Y |
|
|
|
|
/// | desc | Object description | string | Y |
|
|
|
|
///
|
|
|
|
/// # Field parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Field name | string | Y |
|
|
|
|
/// | desc | Field description | string | Y |
|
|
|
|
/// | default | Field default value | string | Y |
|
2020-03-22 01:34:32 +00:00
|
|
|
/// | validator | Input value validator | [`InputValueValidator`](validators/trait.InputValueValidator.html) | Y |
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use async_graphql::*;
|
|
|
|
///
|
|
|
|
/// #[InputObject]
|
|
|
|
/// struct MyInputObject {
|
|
|
|
/// a: i32,
|
|
|
|
/// #[field(default = "10")]
|
|
|
|
/// b: i32,
|
|
|
|
/// }
|
|
|
|
///
|
2020-03-27 02:20:20 +00:00
|
|
|
/// struct QueryRoot;
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// #[Object]
|
2020-03-27 02:20:20 +00:00
|
|
|
/// impl QueryRoot {
|
2020-03-09 10:05:52 +00:00
|
|
|
/// #[field(desc = "value")]
|
|
|
|
/// async fn value(&self, input: MyInputObject) -> i32 {
|
|
|
|
/// input.a * input.b
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[async_std::main]
|
|
|
|
/// async fn main() {
|
2020-03-27 02:20:20 +00:00
|
|
|
/// let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
|
2020-04-02 04:53:53 +00:00
|
|
|
/// let res = schema.execute(r#"
|
2020-03-09 10:05:52 +00:00
|
|
|
/// {
|
|
|
|
/// value1: value(input:{a:9, b:3})
|
|
|
|
/// value2: value(input:{a:9})
|
2020-04-02 04:53:53 +00:00
|
|
|
/// }"#).await.unwrap().data;
|
2020-03-09 10:05:52 +00:00
|
|
|
/// assert_eq!(res, serde_json::json!({ "value1": 27, "value2": 90 }));
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
pub use async_graphql_derive::InputObject;
|
|
|
|
|
|
|
|
/// Define a GraphQL interface
|
|
|
|
///
|
|
|
|
/// # Macro parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Object name | string | Y |
|
|
|
|
/// | desc | Object description | string | Y |
|
|
|
|
///
|
|
|
|
/// # Field parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Field name | string | N |
|
|
|
|
/// | type | Field type | string | N |
|
|
|
|
/// | desc | Field description | string | Y |
|
|
|
|
/// | context | Method with the context | string | Y |
|
|
|
|
/// | deprecation | Field deprecation reason | string | Y |
|
2020-03-22 01:34:32 +00:00
|
|
|
/// | args | Field arguments | | Y |
|
2020-03-09 10:05:52 +00:00
|
|
|
///
|
|
|
|
/// # Field argument parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Argument name | string | N |
|
|
|
|
/// | type | Argument type | string | N |
|
|
|
|
/// | desc | Argument description | string | Y |
|
|
|
|
/// | default | Argument default value | string | Y |
|
|
|
|
///
|
|
|
|
/// # Define an interface
|
|
|
|
///
|
|
|
|
/// Define TypeA, TypeB, TypeC... Implement the MyInterface
|
|
|
|
///
|
|
|
|
/// ```ignore
|
|
|
|
/// #[Interface]
|
|
|
|
/// struct MyInterface(TypeA, TypeB, TypeC, ...);
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// # Fields
|
|
|
|
///
|
|
|
|
/// The type, name, and parameters of the interface field must exactly match the type that implements the interface,
|
|
|
|
/// The internal implementation is a forward of the function call.
|
|
|
|
/// You can specify the field function name that implements the interface type through the 'method' property,
|
|
|
|
/// or you can specify that the field function has a context parameter through the 'context' attribute.
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use async_graphql::*;
|
|
|
|
///
|
|
|
|
/// struct TypeA {
|
|
|
|
/// value: i32,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[Object]
|
|
|
|
/// impl TypeA {
|
|
|
|
/// /// Returns data borrowed from the context
|
|
|
|
/// #[field]
|
|
|
|
/// async fn value_a<'a>(&self, ctx: &'a Context<'_>) -> &'a str {
|
|
|
|
/// ctx.data::<String>().as_str()
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// /// Returns data borrowed self
|
|
|
|
/// #[field]
|
|
|
|
/// async fn value_b(&self) -> &i32 {
|
|
|
|
/// &self.value
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// /// With parameters
|
|
|
|
/// #[field]
|
|
|
|
/// async fn value_c(&self, a: i32, b: i32) -> i32 {
|
|
|
|
/// a + b
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[Interface(
|
|
|
|
/// field(name = "value_a", type = "&'ctx str", context),
|
|
|
|
/// field(name = "value_b", type = "&i32"),
|
|
|
|
/// field(name = "value_c", type = "i32",
|
|
|
|
/// arg(name = "a", type = "i32"),
|
|
|
|
/// arg(name = "b", type = "i32")),
|
|
|
|
/// )]
|
|
|
|
/// struct MyInterface(TypeA);
|
|
|
|
///
|
|
|
|
/// struct QueryRoot;
|
|
|
|
///
|
|
|
|
/// #[Object]
|
|
|
|
/// impl QueryRoot {
|
|
|
|
/// #[field]
|
|
|
|
/// async fn type_a(&self) -> MyInterface {
|
|
|
|
/// TypeA { value: 10 }.into()
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// #[async_std::main]
|
|
|
|
/// async fn main() {
|
2020-03-29 12:02:52 +00:00
|
|
|
/// let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).data("hello".to_string()).finish();
|
2020-04-02 04:53:53 +00:00
|
|
|
/// let res = schema.execute(r#"
|
2020-03-09 10:05:52 +00:00
|
|
|
/// {
|
2020-03-09 12:00:57 +00:00
|
|
|
/// typeA {
|
|
|
|
/// valueA
|
|
|
|
/// valueB
|
|
|
|
/// valueC(a: 3, b: 2)
|
2020-03-09 10:05:52 +00:00
|
|
|
/// }
|
2020-04-02 04:53:53 +00:00
|
|
|
/// }"#).await.unwrap().data;
|
2020-03-09 10:05:52 +00:00
|
|
|
/// assert_eq!(res, serde_json::json!({
|
2020-03-09 12:00:57 +00:00
|
|
|
/// "typeA": {
|
|
|
|
/// "valueA": "hello",
|
|
|
|
/// "valueB": 10,
|
|
|
|
/// "valueC": 5
|
2020-03-09 10:05:52 +00:00
|
|
|
/// }
|
|
|
|
/// }));
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
pub use async_graphql_derive::Interface;
|
2020-03-09 12:59:25 +00:00
|
|
|
|
2020-03-09 12:59:31 +00:00
|
|
|
/// Define a GraphQL union
|
2020-03-09 12:59:25 +00:00
|
|
|
///
|
|
|
|
/// It's similar to Interface, but it doesn't have fields.
|
|
|
|
pub use async_graphql_derive::Union;
|
2020-03-17 09:26:59 +00:00
|
|
|
|
2020-03-17 11:11:14 +00:00
|
|
|
/// Define a GraphQL subscription
|
|
|
|
///
|
|
|
|
/// The field function is a synchronization function that performs filtering. When true is returned, the message is pushed to the client.
|
|
|
|
/// The second parameter is the type of the field.
|
|
|
|
/// Starting with the third parameter is one or more filtering conditions, The filter condition is the parameter of the field.
|
|
|
|
/// The filter function should be synchronous.
|
|
|
|
///
|
|
|
|
/// # Macro parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Object name | string | Y |
|
|
|
|
/// | desc | Object description | string | Y |
|
|
|
|
///
|
|
|
|
/// # Field parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Field name | string | Y |
|
|
|
|
/// | desc | Field description | string | Y |
|
|
|
|
/// | deprecation | Field deprecation reason | string | Y |
|
|
|
|
///
|
|
|
|
/// # Field argument parameters
|
|
|
|
///
|
|
|
|
/// | Attribute | description | Type | Optional |
|
|
|
|
/// |-------------|---------------------------|----------|----------|
|
|
|
|
/// | name | Argument name | string | Y |
|
|
|
|
/// | desc | Argument description | string | Y |
|
|
|
|
/// | default | Argument default value | string | Y |
|
2020-03-22 01:34:32 +00:00
|
|
|
/// | validator | Input value validator | [`InputValueValidator`](validators/trait.InputValueValidator.html) | Y |
|
2020-03-17 11:11:14 +00:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```ignore
|
|
|
|
/// use async_graphql::*;
|
|
|
|
///
|
|
|
|
/// #[Object]
|
|
|
|
/// struct Event {
|
|
|
|
/// value: i32,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// struct SubscriptionRoot;
|
|
|
|
///
|
|
|
|
/// #[Subscription]
|
|
|
|
/// impl SubscriptionRoot {
|
|
|
|
/// #[field]
|
|
|
|
/// async fn value(&self, event: &Event, condition: i32) -> bool {
|
|
|
|
/// // Push when value is greater than condition
|
|
|
|
/// event.value > condition
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2020-03-17 09:26:59 +00:00
|
|
|
pub use async_graphql_derive::Subscription;
|