Strip redundant Send/Sync bounds (#688)
Additionally: - strip redundant type parameters for juniper::Context in some core definitions and reuse associated type
This commit is contained in:
parent
7578175baf
commit
4d77a1a9b9
31 changed files with 556 additions and 554 deletions
|
@ -1,11 +1,14 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
use futures::{Stream, StreamExt};
|
||||
use juniper::http::GraphQLRequest;
|
||||
use juniper::{DefaultScalarValue, EmptyMutation, FieldError, RootNode, SubscriptionCoordinator};
|
||||
use juniper_subscriptions::Coordinator;
|
||||
use std::pin::Pin;
|
||||
|
||||
use futures::{Stream, StreamExt};
|
||||
use juniper::{
|
||||
http::GraphQLRequest, DefaultScalarValue, EmptyMutation, FieldError, RootNode,
|
||||
SubscriptionCoordinator,
|
||||
};
|
||||
use juniper_subscriptions::Coordinator;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Database;
|
||||
|
||||
|
@ -50,13 +53,11 @@ async fn main() {
|
|||
let schema = schema();
|
||||
let coordinator = Coordinator::new(schema);
|
||||
let req: GraphQLRequest<DefaultScalarValue> = serde_json::from_str(
|
||||
r#"
|
||||
{
|
||||
r#"{
|
||||
"query": "subscription { helloWorld }"
|
||||
}
|
||||
"#,
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
let ctx = Database::new();
|
||||
let mut conn = coordinator.subscribe(&req, &ctx).await.unwrap();
|
||||
while let Some(result) = conn.next().await {
|
||||
|
|
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
env_logger = "0.6.2"
|
||||
futures = { version = "=0.3.1" }
|
||||
futures = "0.3.1"
|
||||
log = "0.4.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! This example demonstrates asynchronous subscriptions with warp and tokio 0.2
|
||||
|
||||
use std::{pin::Pin, sync::Arc, time::Duration};
|
||||
use std::{env, pin::Pin, sync::Arc, time::Duration};
|
||||
|
||||
use futures::{Future, FutureExt as _, Stream};
|
||||
use juniper::{DefaultScalarValue, EmptyMutation, FieldError, RootNode};
|
||||
|
@ -136,10 +136,10 @@ fn schema() -> Schema {
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
::std::env::set_var("RUST_LOG", "warp_subscriptions");
|
||||
env::set_var("RUST_LOG", "warp_subscriptions");
|
||||
env_logger::init();
|
||||
|
||||
let log = warp::log("warp_server");
|
||||
let log = warp::log("warp_subscriptions");
|
||||
|
||||
let homepage = warp::path::end().map(|| {
|
||||
Response::builder()
|
||||
|
|
|
@ -43,6 +43,7 @@ bson = { version = "1.0.0", optional = true }
|
|||
chrono = { version = "0.4.0", optional = true }
|
||||
fnv = "1.0.3"
|
||||
futures = "0.3.1"
|
||||
futures-enum = "0.1.12"
|
||||
indexmap = { version = "1.0.0", features = ["serde-1"] }
|
||||
serde = { version = "1.0.8", features = ["derive"] }
|
||||
serde_json = { version="1.0.2", optional = true }
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
};
|
||||
|
||||
use fnv::FnvHashMap;
|
||||
use futures::Stream;
|
||||
|
||||
use crate::{
|
||||
ast::{
|
||||
|
@ -224,9 +225,9 @@ pub type FieldResult<T, S = DefaultScalarValue> = Result<T, FieldError<S>>;
|
|||
/// The result of resolving an unspecified field
|
||||
pub type ExecutionResult<S = DefaultScalarValue> = Result<Value<S>, FieldError<S>>;
|
||||
|
||||
/// Boxed `futures::Stream` yielding `Result<Value<S>, ExecutionError<S>>`
|
||||
/// Boxed `Stream` yielding `Result<Value<S>, ExecutionError<S>>`
|
||||
pub type ValuesStream<'a, S = DefaultScalarValue> =
|
||||
std::pin::Pin<Box<dyn futures::Stream<Item = Result<Value<S>, ExecutionError<S>>> + Send + 'a>>;
|
||||
std::pin::Pin<Box<dyn Stream<Item = Result<Value<S>, ExecutionError<S>>> + Send + 'a>>;
|
||||
|
||||
/// The map of variables used for substitution during query execution
|
||||
pub type Variables<S = DefaultScalarValue> = HashMap<String, InputValue<S>>;
|
||||
|
@ -374,18 +375,15 @@ where
|
|||
'i: 'res,
|
||||
'v: 'res,
|
||||
'a: 'res,
|
||||
T: GraphQLSubscriptionValue<S, Context = CtxT> + Send + Sync,
|
||||
T::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
T: GraphQLSubscriptionValue<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
match self.subscribe(info, value).await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
self.push_error(e);
|
||||
Value::Null
|
||||
}
|
||||
}
|
||||
self.subscribe(info, value).await.unwrap_or_else(|e| {
|
||||
self.push_error(e);
|
||||
Value::Null
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve a single arbitrary value into a stream of [`Value`]s.
|
||||
|
@ -398,9 +396,9 @@ where
|
|||
where
|
||||
't: 'res,
|
||||
'a: 'res,
|
||||
T: GraphQLSubscriptionValue<S, Context = CtxT>,
|
||||
T::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
T: GraphQLSubscriptionValue<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
value.resolve_into_stream(info, self).await
|
||||
|
@ -427,9 +425,9 @@ where
|
|||
/// Resolve a single arbitrary value into an `ExecutionResult`
|
||||
pub async fn resolve_async<T>(&self, info: &T::TypeInfo, value: &T) -> ExecutionResult<S>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + Send + Sync + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
value
|
||||
|
@ -444,10 +442,10 @@ where
|
|||
value: &T,
|
||||
) -> ExecutionResult<S>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = NewCtxT> + Send + Sync,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S, Context = NewCtxT> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
NewCtxT: FromContext<CtxT> + Sync,
|
||||
S: Send + Sync,
|
||||
NewCtxT: FromContext<CtxT> + Send + Sync,
|
||||
{
|
||||
let e = self.replaced_context(<NewCtxT as FromContext<CtxT>>::from(self.context));
|
||||
e.resolve_async(info, value).await
|
||||
|
@ -471,9 +469,9 @@ where
|
|||
/// If the field fails to resolve, `null` will be returned.
|
||||
pub async fn resolve_into_value_async<T>(&self, info: &T::TypeInfo, value: &T) -> Value<S>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + Send + Sync + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
self.resolve_async(info, value).await.unwrap_or_else(|e| {
|
||||
|
@ -750,18 +748,18 @@ impl<S> ExecutionError<S> {
|
|||
|
||||
/// Create new `Executor` and start query/mutation execution.
|
||||
/// Returns `IsSubscription` error if subscription is passed.
|
||||
pub fn execute_validated_query<'a, 'b, QueryT, MutationT, SubscriptionT, CtxT, S>(
|
||||
pub fn execute_validated_query<'a, 'b, QueryT, MutationT, SubscriptionT, S>(
|
||||
document: &'b Document<S>,
|
||||
operation: &'b Spanning<Operation<S>>,
|
||||
root_node: &RootNode<QueryT, MutationT, SubscriptionT, S>,
|
||||
variables: &Variables<S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
S: ScalarValue,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
if operation.item.operation_type == OperationType::Subscription {
|
||||
return Err(GraphQLError::IsSubscription);
|
||||
|
@ -844,22 +842,22 @@ where
|
|||
|
||||
/// Create new `Executor` and start asynchronous query execution.
|
||||
/// Returns `IsSubscription` error if subscription is passed.
|
||||
pub async fn execute_validated_query_async<'a, 'b, QueryT, MutationT, SubscriptionT, CtxT, S>(
|
||||
pub async fn execute_validated_query_async<'a, 'b, QueryT, MutationT, SubscriptionT, S>(
|
||||
document: &'b Document<'a, S>,
|
||||
operation: &'b Spanning<Operation<'_, S>>,
|
||||
root_node: &RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
variables: &Variables<S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context> + Sync,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
if operation.item.operation_type == OperationType::Subscription {
|
||||
return Err(GraphQLError::IsSubscription);
|
||||
|
@ -986,27 +984,26 @@ pub async fn resolve_validated_subscription<
|
|||
QueryT,
|
||||
MutationT,
|
||||
SubscriptionT,
|
||||
CtxT,
|
||||
S,
|
||||
>(
|
||||
document: &Document<'d, S>,
|
||||
operation: &Spanning<Operation<'op, S>>,
|
||||
root_node: &'r RootNode<'r, QueryT, MutationT, SubscriptionT, S>,
|
||||
variables: &Variables<S>,
|
||||
context: &'r CtxT,
|
||||
context: &'r QueryT::Context,
|
||||
) -> Result<(Value<ValuesStream<'r, S>>, Vec<ExecutionError<S>>), GraphQLError<'r>>
|
||||
where
|
||||
'r: 'exec_ref,
|
||||
'd: 'r,
|
||||
'op: 'd,
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync + 'r,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = QueryT::Context>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync + 'r,
|
||||
{
|
||||
if operation.item.operation_type != OperationType::Subscription {
|
||||
return Err(GraphQLError::NotSubscription);
|
||||
|
|
|
@ -75,16 +75,16 @@ where
|
|||
///
|
||||
/// This is a simple wrapper around the `execute_sync` function exposed at the
|
||||
/// top level of this crate.
|
||||
pub fn execute_sync<'a, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub fn execute_sync<'a, QueryT, MutationT, SubscriptionT>(
|
||||
&'a self,
|
||||
root_node: &'a RootNode<QueryT, MutationT, SubscriptionT, S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
) -> GraphQLResponse<'a, S>
|
||||
where
|
||||
S: ScalarValue,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
GraphQLResponse(crate::execute_sync(
|
||||
&self.query,
|
||||
|
@ -99,20 +99,20 @@ where
|
|||
///
|
||||
/// This is a simple wrapper around the `execute` function exposed at the
|
||||
/// top level of this crate.
|
||||
pub async fn execute<'a, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub async fn execute<'a, QueryT, MutationT, SubscriptionT>(
|
||||
&'a self,
|
||||
root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
context: &'a CtxT,
|
||||
context: &'a QueryT::Context,
|
||||
) -> GraphQLResponse<'a, S>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context> + Sync,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
let op = self.operation_name();
|
||||
let vars = &self.variables();
|
||||
|
@ -125,23 +125,23 @@ where
|
|||
/// specified schema and context.
|
||||
/// This is a wrapper around the `resolve_into_stream` function exposed at the top
|
||||
/// level of this crate.
|
||||
pub async fn resolve_into_stream<'req, 'rn, 'ctx, 'a, CtxT, QueryT, MutationT, SubscriptionT, S>(
|
||||
pub async fn resolve_into_stream<'req, 'rn, 'ctx, 'a, QueryT, MutationT, SubscriptionT, S>(
|
||||
req: &'req GraphQLRequest<S>,
|
||||
root_node: &'rn RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
context: &'ctx CtxT,
|
||||
context: &'ctx QueryT::Context,
|
||||
) -> Result<(Value<ValuesStream<'a, S>>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
'req: 'a,
|
||||
'rn: 'a,
|
||||
'ctx: 'a,
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = QueryT::Context>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
let op = req.operation_name();
|
||||
let vars = req.variables();
|
||||
|
@ -257,15 +257,15 @@ where
|
|||
/// Execute a GraphQL batch request synchronously using the specified schema and context
|
||||
///
|
||||
/// This is a simple wrapper around the `execute_sync` function exposed in GraphQLRequest.
|
||||
pub fn execute_sync<'a, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub fn execute_sync<'a, QueryT, MutationT, SubscriptionT>(
|
||||
&'a self,
|
||||
root_node: &'a RootNode<QueryT, MutationT, SubscriptionT, S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
) -> GraphQLBatchResponse<'a, S>
|
||||
where
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
match *self {
|
||||
Self::Single(ref req) => {
|
||||
|
@ -283,27 +283,27 @@ where
|
|||
///
|
||||
/// This is a simple wrapper around the `execute` function exposed in
|
||||
/// GraphQLRequest
|
||||
pub async fn execute<'a, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub async fn execute<'a, QueryT, MutationT, SubscriptionT>(
|
||||
&'a self,
|
||||
root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
context: &'a CtxT,
|
||||
context: &'a QueryT::Context,
|
||||
) -> GraphQLBatchResponse<'a, S>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = QueryT::Context>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
match *self {
|
||||
Self::Single(ref req) => {
|
||||
match self {
|
||||
Self::Single(req) => {
|
||||
let resp = req.execute(root_node, context).await;
|
||||
GraphQLBatchResponse::Single(resp)
|
||||
}
|
||||
Self::Batch(ref reqs) => {
|
||||
Self::Batch(reqs) => {
|
||||
let resps = futures::future::join_all(
|
||||
reqs.iter().map(|req| req.execute(root_node, context)),
|
||||
)
|
||||
|
|
|
@ -229,18 +229,18 @@ impl<'a> fmt::Display for GraphQLError<'a> {
|
|||
impl<'a> std::error::Error for GraphQLError<'a> {}
|
||||
|
||||
/// Execute a query synchronously in a provided schema
|
||||
pub fn execute_sync<'a, S, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub fn execute_sync<'a, S, QueryT, MutationT, SubscriptionT>(
|
||||
document_source: &'a str,
|
||||
operation_name: Option<&str>,
|
||||
root_node: &'a RootNode<QueryT, MutationT, SubscriptionT, S>,
|
||||
variables: &Variables<S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
S: ScalarValue,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
let document = parse_document_source(document_source, &root_node.schema)?;
|
||||
|
||||
|
@ -268,22 +268,22 @@ where
|
|||
}
|
||||
|
||||
/// Execute a query in a provided schema
|
||||
pub async fn execute<'a, S, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub async fn execute<'a, S, QueryT, MutationT, SubscriptionT>(
|
||||
document_source: &'a str,
|
||||
operation_name: Option<&str>,
|
||||
root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
variables: &Variables<S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context> + Sync,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
let document = parse_document_source(document_source, &root_node.schema)?;
|
||||
|
||||
|
@ -312,22 +312,22 @@ where
|
|||
}
|
||||
|
||||
/// Resolve subscription into `ValuesStream`
|
||||
pub async fn resolve_into_stream<'a, S, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub async fn resolve_into_stream<'a, S, QueryT, MutationT, SubscriptionT>(
|
||||
document_source: &'a str,
|
||||
operation_name: Option<&str>,
|
||||
root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
variables: &Variables<S>,
|
||||
context: &'a CtxT,
|
||||
context: &'a QueryT::Context,
|
||||
) -> Result<(Value<ValuesStream<'a, S>>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = QueryT::Context>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
let document: crate::ast::Document<'a, S> =
|
||||
parse_document_source(document_source, &root_node.schema)?;
|
||||
|
@ -357,16 +357,16 @@ where
|
|||
}
|
||||
|
||||
/// Execute the reference introspection query in the provided schema
|
||||
pub fn introspect<'a, S, CtxT, QueryT, MutationT, SubscriptionT>(
|
||||
pub fn introspect<'a, S, QueryT, MutationT, SubscriptionT>(
|
||||
root_node: &'a RootNode<QueryT, MutationT, SubscriptionT, S>,
|
||||
context: &CtxT,
|
||||
context: &QueryT::Context,
|
||||
format: IntrospectionFormat,
|
||||
) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError<'a>>
|
||||
where
|
||||
S: ScalarValue,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
execute_sync(
|
||||
match format {
|
||||
|
|
|
@ -134,7 +134,7 @@ impl Subscription {
|
|||
|
||||
#[tokio::test]
|
||||
async fn object_introspect() {
|
||||
let res = util::run_info_query::<Query, Mutation, Subscription, Context>("Query").await;
|
||||
let res = util::run_info_query::<Query, Mutation, Subscription>("Query").await;
|
||||
assert_eq!(
|
||||
res,
|
||||
crate::graphql_value!({
|
||||
|
|
|
@ -149,7 +149,7 @@ impl Subscription {
|
|||
|
||||
#[tokio::test]
|
||||
async fn object_introspect() {
|
||||
let res = util::run_info_query::<Query, Mutation, Subscription, Context>("Subscription").await;
|
||||
let res = util::run_info_query::<Query, Mutation, Subscription>("Subscription").await;
|
||||
assert_eq!(
|
||||
res,
|
||||
crate::graphql_value!({
|
||||
|
|
|
@ -1,34 +1,41 @@
|
|||
use crate::{DefaultScalarValue, GraphQLType, GraphQLTypeAsync, RootNode, Value, Variables};
|
||||
|
||||
pub async fn run_query<Query, Mutation, Subscription, Context>(query: &str) -> Value
|
||||
pub async fn run_query<Query, Mutation, Subscription>(query: &str) -> Value
|
||||
where
|
||||
Query: GraphQLTypeAsync<DefaultScalarValue, TypeInfo = (), Context = Context> + Default,
|
||||
Mutation: GraphQLTypeAsync<DefaultScalarValue, TypeInfo = (), Context = Context> + Default,
|
||||
Query: GraphQLTypeAsync<DefaultScalarValue, TypeInfo = ()> + Default,
|
||||
Query::Context: Default + Sync,
|
||||
Mutation:
|
||||
GraphQLTypeAsync<DefaultScalarValue, TypeInfo = (), Context = Query::Context> + Default,
|
||||
Subscription:
|
||||
GraphQLType<DefaultScalarValue, TypeInfo = (), Context = Context> + Default + Sync + Send,
|
||||
Context: Default + Send + Sync,
|
||||
GraphQLType<DefaultScalarValue, TypeInfo = (), Context = Query::Context> + Default + Sync,
|
||||
{
|
||||
let schema = RootNode::new(
|
||||
Query::default(),
|
||||
Mutation::default(),
|
||||
Subscription::default(),
|
||||
);
|
||||
let (result, errs) =
|
||||
crate::execute(query, None, &schema, &Variables::new(), &Context::default())
|
||||
.await
|
||||
.expect("Execution failed");
|
||||
let (result, errs) = crate::execute(
|
||||
query,
|
||||
None,
|
||||
&schema,
|
||||
&Variables::new(),
|
||||
&Query::Context::default(),
|
||||
)
|
||||
.await
|
||||
.expect("Execution failed");
|
||||
|
||||
assert_eq!(errs, []);
|
||||
result
|
||||
}
|
||||
|
||||
pub async fn run_info_query<Query, Mutation, Subscription, Context>(type_name: &str) -> Value
|
||||
pub async fn run_info_query<Query, Mutation, Subscription>(type_name: &str) -> Value
|
||||
where
|
||||
Query: GraphQLTypeAsync<DefaultScalarValue, TypeInfo = (), Context = Context> + Default,
|
||||
Mutation: GraphQLTypeAsync<DefaultScalarValue, TypeInfo = (), Context = Context> + Default,
|
||||
Query: GraphQLTypeAsync<DefaultScalarValue, TypeInfo = ()> + Default,
|
||||
Query::Context: Default + Sync,
|
||||
Mutation:
|
||||
GraphQLTypeAsync<DefaultScalarValue, TypeInfo = (), Context = Query::Context> + Default,
|
||||
Subscription:
|
||||
GraphQLType<DefaultScalarValue, TypeInfo = (), Context = Context> + Default + Sync + Send,
|
||||
Context: Default + Send + Sync,
|
||||
GraphQLType<DefaultScalarValue, TypeInfo = (), Context = Query::Context> + Default + Sync,
|
||||
{
|
||||
let query = format!(
|
||||
r#"
|
||||
|
@ -52,7 +59,7 @@ where
|
|||
"#,
|
||||
type_name
|
||||
);
|
||||
let result = run_query::<Query, Mutation, Subscription, Context>(&query).await;
|
||||
let result = run_query::<Query, Mutation, Subscription>(&query).await;
|
||||
result
|
||||
.as_object_value()
|
||||
.expect("Result is not an object")
|
||||
|
|
|
@ -16,19 +16,19 @@ use crate::schema::{
|
|||
model::{DirectiveLocation, DirectiveType, RootNode, SchemaType, TypeType},
|
||||
};
|
||||
|
||||
impl<'a, CtxT, S, QueryT, MutationT, SubscriptionT> GraphQLType<S>
|
||||
impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLType<S>
|
||||
for RootNode<'a, QueryT, MutationT, SubscriptionT, S>
|
||||
where
|
||||
S: ScalarValue,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
fn name(info: &QueryT::TypeInfo) -> Option<&str> {
|
||||
fn name(info: &Self::TypeInfo) -> Option<&str> {
|
||||
QueryT::name(info)
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &QueryT::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -36,27 +36,27 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, CtxT, S, QueryT, MutationT, SubscriptionT> GraphQLValue<S>
|
||||
impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLValue<S>
|
||||
for RootNode<'a, QueryT, MutationT, SubscriptionT, S>
|
||||
where
|
||||
S: ScalarValue,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT: GraphQLType<S>,
|
||||
MutationT: GraphQLType<S, Context = QueryT::Context>,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
|
||||
{
|
||||
type Context = CtxT;
|
||||
type Context = QueryT::Context;
|
||||
type TypeInfo = QueryT::TypeInfo;
|
||||
|
||||
fn type_name<'i>(&self, info: &'i QueryT::TypeInfo) -> Option<&'i str> {
|
||||
fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> {
|
||||
QueryT::name(info)
|
||||
}
|
||||
|
||||
fn resolve_field(
|
||||
&self,
|
||||
info: &QueryT::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
field: &str,
|
||||
args: &Arguments<S>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
match field {
|
||||
"__schema" => executor
|
||||
|
@ -93,17 +93,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, CtxT, S, QueryT, MutationT, SubscriptionT> GraphQLValueAsync<S>
|
||||
impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLValueAsync<S>
|
||||
for RootNode<'a, QueryT, MutationT, SubscriptionT, S>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
QueryT::Context: Sync + 'a,
|
||||
MutationT: GraphQLTypeAsync<S, Context = QueryT::Context>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = QueryT::Context> + Sync,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync + 'a,
|
||||
{
|
||||
fn resolve_field_async<'b>(
|
||||
&'b self,
|
||||
|
|
|
@ -13,10 +13,10 @@ use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType, GraphQLVa
|
|||
///
|
||||
/// Convenience macros related to asynchronous queries/mutations expand into an implementation of
|
||||
/// this trait and [`GraphQLValue`] for the given type.
|
||||
pub trait GraphQLValueAsync<S = DefaultScalarValue>: GraphQLValue<S> + Send + Sync
|
||||
pub trait GraphQLValueAsync<S = DefaultScalarValue>: GraphQLValue<S> + Sync
|
||||
where
|
||||
Self::Context: Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
Self::TypeInfo: Sync,
|
||||
Self::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
/// Resolves the value of a single field on this [`GraphQLValueAsync`].
|
||||
|
@ -119,34 +119,34 @@ crate::sa::assert_obj_safe!(GraphQLValueAsync<Context = (), TypeInfo = ()>);
|
|||
/// doesn't require manual or code-generated implementation.
|
||||
pub trait GraphQLTypeAsync<S = DefaultScalarValue>: GraphQLValueAsync<S> + GraphQLType<S>
|
||||
where
|
||||
Self::Context: Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
Self::Context: Sync,
|
||||
Self::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
impl<S, T> GraphQLTypeAsync<S> for T
|
||||
where
|
||||
T: GraphQLValueAsync<S> + GraphQLType<S>,
|
||||
T::Context: Send + Sync,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S> + GraphQLType<S> + ?Sized,
|
||||
T::Context: Sync,
|
||||
T::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
// Wrapper function around resolve_selection_set_into_async_recursive.
|
||||
// This wrapper is necessary because async fns can not be recursive.
|
||||
fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
|
||||
fn resolve_selection_set_into_async<'a, 'e, T, S>(
|
||||
instance: &'a T,
|
||||
info: &'a T::TypeInfo,
|
||||
selection_set: &'e [Selection<'e, S>],
|
||||
executor: &'e Executor<'e, 'e, CtxT, S>,
|
||||
executor: &'e Executor<'e, 'e, T::Context, S>,
|
||||
) -> BoxFuture<'a, Value<S>>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
'e: 'a,
|
||||
{
|
||||
Box::pin(resolve_selection_set_into_async_recursive(
|
||||
|
@ -167,23 +167,31 @@ enum AsyncValue<S> {
|
|||
Nested(Value<S>),
|
||||
}
|
||||
|
||||
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
|
||||
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, S>(
|
||||
instance: &'a T,
|
||||
info: &'a T::TypeInfo,
|
||||
selection_set: &'a [Selection<'a, S>],
|
||||
executor: &'a Executor<'a, 'a, CtxT, S>,
|
||||
executor: &'a Executor<'a, 'a, T::Context, S>,
|
||||
) -> Value<S>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + Send + Sync + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
use futures::stream::{FuturesOrdered, StreamExt as _};
|
||||
|
||||
#[derive(futures_enum::Future)]
|
||||
enum AsyncValueFuture<A, B, C, D> {
|
||||
Field(A),
|
||||
FragmentSpread(B),
|
||||
InlineFragment1(C),
|
||||
InlineFragment2(D),
|
||||
}
|
||||
|
||||
let mut object = Object::with_capacity(selection_set.len());
|
||||
|
||||
let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();
|
||||
let mut async_values = FuturesOrdered::<AsyncValueFuture<_, _, _, _>>::new();
|
||||
|
||||
let meta_type = executor
|
||||
.schema()
|
||||
|
@ -246,7 +254,7 @@ where
|
|||
let is_non_null = meta_field.field_type.is_non_null();
|
||||
|
||||
let response_name = response_name.to_string();
|
||||
let field_future = async move {
|
||||
async_values.push(AsyncValueFuture::Field(async move {
|
||||
// TODO: implement custom future type instead of
|
||||
// two-level boxing.
|
||||
let res = instance
|
||||
|
@ -270,18 +278,16 @@ where
|
|||
name: response_name,
|
||||
value,
|
||||
})
|
||||
};
|
||||
async_values.push(Box::pin(field_future));
|
||||
}));
|
||||
}
|
||||
|
||||
Selection::FragmentSpread(Spanning {
|
||||
item: ref spread, ..
|
||||
}) => {
|
||||
if is_excluded(&spread.directives, executor.variables()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: prevent duplicate boxing.
|
||||
let f = async move {
|
||||
async_values.push(AsyncValueFuture::FragmentSpread(async move {
|
||||
let fragment = &executor
|
||||
.fragment_by_name(spread.name.item)
|
||||
.expect("Fragment could not be found");
|
||||
|
@ -293,9 +299,9 @@ where
|
|||
)
|
||||
.await;
|
||||
AsyncValue::Nested(value)
|
||||
};
|
||||
async_values.push(Box::pin(f));
|
||||
}));
|
||||
}
|
||||
|
||||
Selection::InlineFragment(Spanning {
|
||||
item: ref fragment,
|
||||
start: ref start_pos,
|
||||
|
@ -322,20 +328,18 @@ where
|
|||
|
||||
if let Ok(Value::Object(obj)) = sub_result {
|
||||
for (k, v) in obj {
|
||||
// TODO: prevent duplicate boxing.
|
||||
let f = async move {
|
||||
async_values.push(AsyncValueFuture::InlineFragment1(async move {
|
||||
AsyncValue::Field(AsyncField {
|
||||
name: k,
|
||||
value: Some(v),
|
||||
})
|
||||
};
|
||||
async_values.push(Box::pin(f));
|
||||
}));
|
||||
}
|
||||
} else if let Err(e) = sub_result {
|
||||
sub_exec.push_error_at(e, start_pos.clone());
|
||||
}
|
||||
} else {
|
||||
let f = async move {
|
||||
async_values.push(AsyncValueFuture::InlineFragment2(async move {
|
||||
let value = resolve_selection_set_into_async(
|
||||
instance,
|
||||
info,
|
||||
|
@ -344,8 +348,7 @@ where
|
|||
)
|
||||
.await;
|
||||
AsyncValue::Nested(value)
|
||||
};
|
||||
async_values.push(Box::pin(f));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -401,16 +401,16 @@ where
|
|||
/// and then merges returned values into `result` or pushes errors to
|
||||
/// field's/fragment's sub executor.
|
||||
///
|
||||
/// Returns false if any errors occured and true otherwise.
|
||||
pub(crate) fn resolve_selection_set_into<T, CtxT, S>(
|
||||
/// Returns false if any errors occurred and true otherwise.
|
||||
pub(crate) fn resolve_selection_set_into<T, S>(
|
||||
instance: &T,
|
||||
info: &T::TypeInfo,
|
||||
selection_set: &[Selection<S>],
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<T::Context, S>,
|
||||
result: &mut Object<S>,
|
||||
) -> bool
|
||||
where
|
||||
T: GraphQLValue<S, Context = CtxT> + ?Sized,
|
||||
T: GraphQLValue<S> + ?Sized,
|
||||
S: ScalarValue,
|
||||
{
|
||||
let meta_type = executor
|
||||
|
|
|
@ -9,16 +9,16 @@ use crate::{
|
|||
value::{ScalarValue, Value},
|
||||
};
|
||||
|
||||
impl<S, T, CtxT> GraphQLType<S> for Option<T>
|
||||
impl<S, T> GraphQLType<S> for Option<T>
|
||||
where
|
||||
T: GraphQLType<S>,
|
||||
S: ScalarValue,
|
||||
T: GraphQLType<S, Context = CtxT>,
|
||||
{
|
||||
fn name(_: &T::TypeInfo) -> Option<&'static str> {
|
||||
fn name(_: &Self::TypeInfo) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -26,23 +26,23 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValue<S> for Option<T>
|
||||
impl<S, T> GraphQLValue<S> for Option<T>
|
||||
where
|
||||
S: ScalarValue,
|
||||
T: GraphQLValue<S, Context = CtxT>,
|
||||
T: GraphQLValue<S>,
|
||||
{
|
||||
type Context = CtxT;
|
||||
type Context = T::Context;
|
||||
type TypeInfo = T::TypeInfo;
|
||||
|
||||
fn type_name(&self, _: &T::TypeInfo) -> Option<&'static str> {
|
||||
fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
_: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
match *self {
|
||||
Some(ref obj) => executor.resolve(info, obj),
|
||||
|
@ -51,12 +51,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValueAsync<S> for Option<T>
|
||||
impl<S, T> GraphQLValueAsync<S> for Option<T>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT>,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S>,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
@ -65,8 +65,8 @@ where
|
|||
executor: &'a Executor<Self::Context, S>,
|
||||
) -> crate::BoxFuture<'a, ExecutionResult<S>> {
|
||||
let f = async move {
|
||||
let value = match *self {
|
||||
Some(ref obj) => executor.resolve_into_value_async(info, obj).await,
|
||||
let value = match self {
|
||||
Some(obj) => executor.resolve_into_value_async(info, obj).await,
|
||||
None => Value::null(),
|
||||
};
|
||||
Ok(value)
|
||||
|
@ -101,16 +101,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLType<S> for Vec<T>
|
||||
impl<S, T> GraphQLType<S> for Vec<T>
|
||||
where
|
||||
T: GraphQLType<S, Context = CtxT>,
|
||||
T: GraphQLType<S>,
|
||||
S: ScalarValue,
|
||||
{
|
||||
fn name(_: &T::TypeInfo) -> Option<&'static str> {
|
||||
fn name(_: &Self::TypeInfo) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -118,34 +118,34 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValue<S> for Vec<T>
|
||||
impl<S, T> GraphQLValue<S> for Vec<T>
|
||||
where
|
||||
T: GraphQLValue<S, Context = CtxT>,
|
||||
T: GraphQLValue<S>,
|
||||
S: ScalarValue,
|
||||
{
|
||||
type Context = CtxT;
|
||||
type Context = T::Context;
|
||||
type TypeInfo = T::TypeInfo;
|
||||
|
||||
fn type_name(&self, _: &T::TypeInfo) -> Option<&'static str> {
|
||||
fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
_: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
resolve_into_list(executor, info, self.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValueAsync<S> for Vec<T>
|
||||
impl<S, T> GraphQLValueAsync<S> for Vec<T>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT>,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S>,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
@ -190,16 +190,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLType<S> for [T]
|
||||
impl<S, T> GraphQLType<S> for [T]
|
||||
where
|
||||
S: ScalarValue,
|
||||
T: GraphQLType<S, Context = CtxT>,
|
||||
T: GraphQLType<S>,
|
||||
{
|
||||
fn name(_: &T::TypeInfo) -> Option<&'static str> {
|
||||
fn name(_: &Self::TypeInfo) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -207,34 +207,34 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValue<S> for [T]
|
||||
impl<S, T> GraphQLValue<S> for [T]
|
||||
where
|
||||
S: ScalarValue,
|
||||
T: GraphQLValue<S, Context = CtxT>,
|
||||
T: GraphQLValue<S>,
|
||||
{
|
||||
type Context = CtxT;
|
||||
type Context = T::Context;
|
||||
type TypeInfo = T::TypeInfo;
|
||||
|
||||
fn type_name(&self, _: &T::TypeInfo) -> Option<&'static str> {
|
||||
fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
_: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
resolve_into_list(executor, info, self.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValueAsync<S> for [T]
|
||||
impl<S, T> GraphQLValueAsync<S> for [T]
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT>,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S>,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
@ -292,11 +292,11 @@ async fn resolve_into_list_async<'a, 't, S, T, I>(
|
|||
items: I,
|
||||
) -> ExecutionResult<S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
I: Iterator<Item = &'t T> + ExactSizeIterator,
|
||||
T: GraphQLValueAsync<S> + ?Sized + 't,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T::Context: Send + Sync,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
use futures::stream::{FuturesOrdered, StreamExt as _};
|
||||
use std::iter::FromIterator;
|
||||
|
@ -307,7 +307,7 @@ where
|
|||
.expect("Current type is not a list type")
|
||||
.is_non_null();
|
||||
|
||||
let iter = items.map(|item| async move { executor.resolve_into_value_async(info, item).await });
|
||||
let iter = items.map(|it| async move { executor.resolve_into_value_async(info, it).await });
|
||||
let mut futures = FuturesOrdered::from_iter(iter);
|
||||
|
||||
let mut values = Vec::with_capacity(futures.len());
|
||||
|
|
|
@ -12,16 +12,16 @@ use crate::{
|
|||
BoxFuture,
|
||||
};
|
||||
|
||||
impl<S, T, CtxT> GraphQLType<S> for Box<T>
|
||||
impl<S, T> GraphQLType<S> for Box<T>
|
||||
where
|
||||
T: GraphQLType<S> + ?Sized,
|
||||
S: ScalarValue,
|
||||
T: GraphQLType<S, Context = CtxT> + ?Sized,
|
||||
{
|
||||
fn name(info: &T::TypeInfo) -> Option<&str> {
|
||||
fn name(info: &Self::TypeInfo) -> Option<&str> {
|
||||
T::name(info)
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -29,54 +29,54 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValue<S> for Box<T>
|
||||
impl<S, T> GraphQLValue<S> for Box<T>
|
||||
where
|
||||
T: GraphQLValue<S> + ?Sized,
|
||||
S: ScalarValue,
|
||||
T: GraphQLValue<S, Context = CtxT> + ?Sized,
|
||||
{
|
||||
type Context = CtxT;
|
||||
type Context = T::Context;
|
||||
type TypeInfo = T::TypeInfo;
|
||||
|
||||
fn type_name<'i>(&self, info: &'i T::TypeInfo) -> Option<&'i str> {
|
||||
fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> {
|
||||
(**self).type_name(info)
|
||||
}
|
||||
|
||||
fn resolve_into_type(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
name: &str,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve_into_type(info, name, selection_set, executor)
|
||||
}
|
||||
|
||||
fn resolve_field(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
field: &str,
|
||||
args: &Arguments<S>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve_field(info, field, args, executor)
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve(info, selection_set, executor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T, CtxT> GraphQLValueAsync<S> for Box<T>
|
||||
impl<S, T> GraphQLValueAsync<S> for Box<T>
|
||||
where
|
||||
T: GraphQLValueAsync<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLValueAsync<S> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
@ -111,16 +111,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'e, S, T, CtxT> GraphQLType<S> for &'e T
|
||||
impl<'e, S, T> GraphQLType<S> for &'e T
|
||||
where
|
||||
T: GraphQLType<S> + ?Sized,
|
||||
S: ScalarValue,
|
||||
T: GraphQLType<S, Context = CtxT> + ?Sized,
|
||||
{
|
||||
fn name(info: &T::TypeInfo) -> Option<&str> {
|
||||
fn name(info: &Self::TypeInfo) -> Option<&str> {
|
||||
T::name(info)
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -128,43 +128,43 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'e, S, T, CtxT> GraphQLValue<S> for &'e T
|
||||
impl<'e, S, T> GraphQLValue<S> for &'e T
|
||||
where
|
||||
S: ScalarValue,
|
||||
T: GraphQLValue<S, Context = CtxT> + ?Sized,
|
||||
T: GraphQLValue<S> + ?Sized,
|
||||
{
|
||||
type Context = CtxT;
|
||||
type Context = T::Context;
|
||||
type TypeInfo = T::TypeInfo;
|
||||
|
||||
fn type_name<'i>(&self, info: &'i T::TypeInfo) -> Option<&'i str> {
|
||||
fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> {
|
||||
(**self).type_name(info)
|
||||
}
|
||||
|
||||
fn resolve_into_type(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
name: &str,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve_into_type(info, name, selection_set, executor)
|
||||
}
|
||||
|
||||
fn resolve_field(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
field: &str,
|
||||
args: &Arguments<S>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve_field(info, field, args, executor)
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve(info, selection_set, executor)
|
||||
}
|
||||
|
@ -172,10 +172,10 @@ where
|
|||
|
||||
impl<'e, S, T> GraphQLValueAsync<S> for &'e T
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
T: GraphQLValueAsync<S> + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T::Context: Send + Sync,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
fn resolve_field_async<'b>(
|
||||
&'b self,
|
||||
|
@ -212,11 +212,11 @@ where
|
|||
S: ScalarValue,
|
||||
T: GraphQLType<S> + ?Sized,
|
||||
{
|
||||
fn name(info: &T::TypeInfo) -> Option<&str> {
|
||||
fn name(info: &Self::TypeInfo) -> Option<&str> {
|
||||
T::name(info)
|
||||
}
|
||||
|
||||
fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
|
||||
where
|
||||
S: 'r,
|
||||
{
|
||||
|
@ -232,35 +232,35 @@ where
|
|||
type Context = T::Context;
|
||||
type TypeInfo = T::TypeInfo;
|
||||
|
||||
fn type_name<'i>(&self, info: &'i T::TypeInfo) -> Option<&'i str> {
|
||||
fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> {
|
||||
(**self).type_name(info)
|
||||
}
|
||||
|
||||
fn resolve_into_type(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
name: &str,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<T::Context, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve_into_type(info, name, selection_set, executor)
|
||||
}
|
||||
|
||||
fn resolve_field(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
field: &str,
|
||||
args: &Arguments<S>,
|
||||
executor: &Executor<T::Context, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve_field(info, field, args, executor)
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &T::TypeInfo,
|
||||
info: &Self::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<T::Context, S>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve(info, selection_set, executor)
|
||||
}
|
||||
|
@ -268,10 +268,10 @@ where
|
|||
|
||||
impl<'e, S, T> GraphQLValueAsync<S> for Arc<T>
|
||||
where
|
||||
T: GraphQLValueAsync<S> + Send + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
T: GraphQLValueAsync<S> + ?Sized,
|
||||
<T as GraphQLValue<S>>::TypeInfo: Send + Sync,
|
||||
<T as GraphQLValue<S>>::Context: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
|
|
@ -382,9 +382,9 @@ where
|
|||
|
||||
impl<S, T> GraphQLValueAsync<S> for EmptyMutation<T>
|
||||
where
|
||||
Self::TypeInfo: Sync,
|
||||
Self::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
Self::Context: Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -442,9 +442,9 @@ where
|
|||
|
||||
impl<T, S> GraphQLSubscriptionValue<S> for EmptySubscription<T>
|
||||
where
|
||||
Self::TypeInfo: Sync,
|
||||
Self::Context: Sync,
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
Self::Context: Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use futures::{future, stream};
|
||||
|
||||
use crate::{
|
||||
http::{GraphQLRequest, GraphQLResponse},
|
||||
parser::Spanning,
|
||||
|
@ -69,10 +71,10 @@ pub trait SubscriptionConnection<'a, S>: futures::Stream<Item = GraphQLResponse<
|
|||
///
|
||||
/// [1]: https://spec.graphql.org/June2018/#sec-Subscription
|
||||
/// [2]: https://spec.graphql.org/June2018/#sec-Objects
|
||||
pub trait GraphQLSubscriptionValue<S = DefaultScalarValue>: GraphQLValue<S> + Send + Sync
|
||||
pub trait GraphQLSubscriptionValue<S = DefaultScalarValue>: GraphQLValue<S> + Sync
|
||||
where
|
||||
Self::Context: Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
Self::TypeInfo: Sync,
|
||||
Self::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
/// Resolves into `Value<ValuesStream>`.
|
||||
|
@ -181,17 +183,17 @@ crate::sa::assert_obj_safe!(GraphQLSubscriptionValue<Context = (), TypeInfo = ()
|
|||
pub trait GraphQLSubscriptionType<S = DefaultScalarValue>:
|
||||
GraphQLSubscriptionValue<S> + GraphQLType<S>
|
||||
where
|
||||
Self::Context: Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
Self::Context: Sync,
|
||||
Self::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
impl<S, T> GraphQLSubscriptionType<S> for T
|
||||
where
|
||||
T: GraphQLSubscriptionValue<S> + GraphQLType<S>,
|
||||
T::Context: Send + Sync,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLSubscriptionValue<S> + GraphQLType<S> + ?Sized,
|
||||
T::Context: Sync,
|
||||
T::TypeInfo: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
}
|
||||
|
@ -199,10 +201,10 @@ where
|
|||
/// Wrapper function around `resolve_selection_set_into_stream_recursive`.
|
||||
/// This wrapper is necessary because async fns can not be recursive.
|
||||
/// Panics if executor's current selection set is None.
|
||||
pub(crate) fn resolve_selection_set_into_stream<'i, 'inf, 'ref_e, 'e, 'res, 'fut, T, CtxT, S>(
|
||||
pub(crate) fn resolve_selection_set_into_stream<'i, 'inf, 'ref_e, 'e, 'res, 'fut, T, S>(
|
||||
instance: &'i T,
|
||||
info: &'inf T::TypeInfo,
|
||||
executor: &'ref_e Executor<'ref_e, 'e, CtxT, S>,
|
||||
executor: &'ref_e Executor<'ref_e, 'e, T::Context, S>,
|
||||
) -> BoxFuture<'fut, Value<ValuesStream<'res, S>>>
|
||||
where
|
||||
'inf: 'res,
|
||||
|
@ -211,10 +213,10 @@ where
|
|||
'e: 'fut,
|
||||
'ref_e: 'fut,
|
||||
'res: 'fut,
|
||||
T: GraphQLSubscriptionValue<S, Context = CtxT> + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLSubscriptionValue<S> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
{
|
||||
Box::pin(resolve_selection_set_into_stream_recursive(
|
||||
instance, info, executor,
|
||||
|
@ -224,16 +226,16 @@ where
|
|||
/// Selection set default resolver logic.
|
||||
/// Returns `Value::Null` if cannot keep resolving. Otherwise pushes errors to
|
||||
/// `Executor`.
|
||||
async fn resolve_selection_set_into_stream_recursive<'i, 'inf, 'ref_e, 'e, 'res, T, CtxT, S>(
|
||||
async fn resolve_selection_set_into_stream_recursive<'i, 'inf, 'ref_e, 'e, 'res, T, S>(
|
||||
instance: &'i T,
|
||||
info: &'inf T::TypeInfo,
|
||||
executor: &'ref_e Executor<'ref_e, 'e, CtxT, S>,
|
||||
executor: &'ref_e Executor<'ref_e, 'e, T::Context, S>,
|
||||
) -> Value<ValuesStream<'res, S>>
|
||||
where
|
||||
T: GraphQLSubscriptionValue<S, Context = CtxT> + Send + Sync + ?Sized,
|
||||
T::TypeInfo: Send + Sync,
|
||||
T: GraphQLSubscriptionValue<S> + ?Sized,
|
||||
T::TypeInfo: Sync,
|
||||
T::Context: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
'inf: 'res,
|
||||
'e: 'res,
|
||||
{
|
||||
|
@ -270,7 +272,7 @@ where
|
|||
Value::scalar(instance.concrete_type_name(executor.context(), info));
|
||||
object.add_field(
|
||||
response_name,
|
||||
Value::Scalar(Box::pin(futures::stream::once(async { Ok(typename) }))),
|
||||
Value::Scalar(Box::pin(stream::once(future::ok(typename)))),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
@ -278,11 +280,11 @@ where
|
|||
let meta_field = meta_type
|
||||
.field_by_name(f.name.item)
|
||||
.unwrap_or_else(|| {
|
||||
panic!(format!(
|
||||
panic!(
|
||||
"Field {} not found on type {:?}",
|
||||
f.name.item,
|
||||
meta_type.name()
|
||||
))
|
||||
meta_type.name(),
|
||||
)
|
||||
})
|
||||
.clone();
|
||||
|
||||
|
@ -366,6 +368,7 @@ where
|
|||
Err(e) => sub_exec.push_error_at(e, start_pos.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
Selection::InlineFragment(Spanning {
|
||||
item: ref fragment,
|
||||
start: ref start_pos,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
extern crate log;
|
||||
use std::env;
|
||||
|
||||
use actix_cors::Cors;
|
||||
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
|
||||
use juniper::{
|
||||
|
@ -38,8 +39,9 @@ async fn graphql(
|
|||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
::std::env::set_var("RUST_LOG", "actix_web=info");
|
||||
env::set_var("RUST_LOG", "info");
|
||||
env_logger::init();
|
||||
|
||||
let server = HttpServer::new(move || {
|
||||
App::new()
|
||||
.data(schema())
|
||||
|
|
|
@ -83,21 +83,21 @@ where
|
|||
}
|
||||
|
||||
/// Actix Web GraphQL Handler for GET and POST requests
|
||||
pub async fn graphql_handler<Query, Mutation, Subscription, Context, S>(
|
||||
pub async fn graphql_handler<Query, Mutation, Subscription, CtxT, S>(
|
||||
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||
context: &Context,
|
||||
context: &CtxT,
|
||||
req: HttpRequest,
|
||||
payload: actix_web::web::Payload,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Context: Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Query::TypeInfo: Send + Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Mutation::TypeInfo: Send + Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = Context> + Send + Sync + 'static,
|
||||
Subscription::TypeInfo: Send + Sync,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||
Query::TypeInfo: Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||
Mutation::TypeInfo: Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT>,
|
||||
Subscription::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
match *req.method() {
|
||||
Method::POST => post_graphql_handler(schema, context, req, payload).await,
|
||||
|
@ -108,20 +108,20 @@ where
|
|||
}
|
||||
}
|
||||
/// Actix GraphQL Handler for GET requests
|
||||
pub async fn get_graphql_handler<Query, Mutation, Subscription, Context, S>(
|
||||
pub async fn get_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
|
||||
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||
context: &Context,
|
||||
context: &CtxT,
|
||||
req: HttpRequest,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Context: Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Query::TypeInfo: Send + Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Mutation::TypeInfo: Send + Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = Context> + Send + Sync + 'static,
|
||||
Subscription::TypeInfo: Send + Sync,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||
Query::TypeInfo: Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||
Mutation::TypeInfo: Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT>,
|
||||
Subscription::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
let get_req = web::Query::<GetGraphQLRequest>::from_query(req.query_string())?;
|
||||
let req = GraphQLRequest::from(get_req.into_inner());
|
||||
|
@ -137,21 +137,21 @@ where
|
|||
}
|
||||
|
||||
/// Actix GraphQL Handler for POST requests
|
||||
pub async fn post_graphql_handler<Query, Mutation, Subscription, Context, S>(
|
||||
pub async fn post_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
|
||||
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||
context: &Context,
|
||||
context: &CtxT,
|
||||
req: HttpRequest,
|
||||
payload: actix_web::web::Payload,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Context: Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Query::TypeInfo: Send + Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Mutation::TypeInfo: Send + Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = Context> + Send + Sync + 'static,
|
||||
Subscription::TypeInfo: Send + Sync,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||
Query::TypeInfo: Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||
Mutation::TypeInfo: Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT>,
|
||||
Subscription::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
let content_type_header = req
|
||||
.headers()
|
||||
|
|
|
@ -101,12 +101,12 @@ fn impl_scalar_struct(
|
|||
};
|
||||
|
||||
let _async = quote!(
|
||||
impl <__S> ::juniper::GraphQLValueAsync<__S> for #ident
|
||||
impl<__S> ::juniper::GraphQLValueAsync<__S> for #ident
|
||||
where
|
||||
Self: Sync,
|
||||
Self::TypeInfo: Sync,
|
||||
Self::Context: Sync,
|
||||
__S: ::juniper::ScalarValue + Send + Sync,
|
||||
Self: Send + Sync,
|
||||
Self::Context: Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
|
|
@ -504,9 +504,7 @@ impl ToTokens for UnionDefinition {
|
|||
let mut where_async = where_clause
|
||||
.cloned()
|
||||
.unwrap_or_else(|| parse_quote! { where });
|
||||
where_async
|
||||
.predicates
|
||||
.push(parse_quote! { Self: Send + Sync });
|
||||
where_async.predicates.push(parse_quote! { Self: Sync });
|
||||
if self.scalar.is_none() {
|
||||
where_async
|
||||
.predicates
|
||||
|
|
|
@ -247,10 +247,10 @@ pub fn build_scalar(
|
|||
let _async = quote!(
|
||||
impl#async_generic_type_decl ::juniper::GraphQLValueAsync<#async_generic_type> for #impl_for_type
|
||||
where
|
||||
Self: Sync,
|
||||
Self::TypeInfo: Sync,
|
||||
Self::Context: Sync,
|
||||
#async_generic_type: ::juniper::ScalarValue + Send + Sync,
|
||||
Self: Send + Sync,
|
||||
Self::Context: Send + Sync,
|
||||
Self::TypeInfo: Send + Sync,
|
||||
{
|
||||
fn resolve_async<'a>(
|
||||
&'a self,
|
||||
|
|
|
@ -930,7 +930,7 @@ impl GraphQLTypeDefiniton {
|
|||
where_async
|
||||
.predicates
|
||||
.push(parse_quote!( #scalar: Send + Sync ));
|
||||
where_async.predicates.push(parse_quote!(Self: Send + Sync));
|
||||
where_async.predicates.push(parse_quote!(Self: Sync));
|
||||
|
||||
// FIXME: add where clause for interfaces.
|
||||
|
||||
|
@ -1431,7 +1431,7 @@ impl GraphQLTypeDefiniton {
|
|||
where_async
|
||||
.predicates
|
||||
.push(parse_quote!( #scalar: Send + Sync ));
|
||||
where_async.predicates.push(parse_quote!(Self: Send + Sync));
|
||||
where_async.predicates.push(parse_quote!(Self: Sync));
|
||||
|
||||
let _async = quote!(
|
||||
impl#impl_generics ::juniper::GraphQLValueAsync<#scalar> for #ty
|
||||
|
@ -1683,7 +1683,7 @@ impl GraphQLTypeDefiniton {
|
|||
where_async
|
||||
.predicates
|
||||
.push(parse_quote!( #scalar: Send + Sync ));
|
||||
where_async.predicates.push(parse_quote!(Self: Send + Sync));
|
||||
where_async.predicates.push(parse_quote!(Self: Sync));
|
||||
|
||||
let async_type = quote!(
|
||||
impl#impl_generics ::juniper::GraphQLValueAsync<#scalar> for #ty #type_generics_tokens
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use hyper::{
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Method, Response, Server, StatusCode,
|
||||
|
@ -6,7 +8,6 @@ use juniper::{
|
|||
tests::{model::Database, schema::Query},
|
||||
EmptyMutation, EmptySubscription, RootNode,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
|
|
@ -21,14 +21,14 @@ pub async fn graphql_sync<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
req: Request<Body>,
|
||||
) -> Result<Response<Body>, hyper::Error>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
CtxT: Send + Sync + 'static,
|
||||
QueryT: GraphQLType<S, Context = CtxT> + Send + Sync + 'static,
|
||||
MutationT: GraphQLType<S, Context = CtxT> + Send + Sync + 'static,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT> + Send + Sync + 'static,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
Ok(match parse_req(req).await {
|
||||
Ok(req) => execute_request_sync(root_node, context, req).await,
|
||||
|
@ -42,14 +42,14 @@ pub async fn graphql<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
req: Request<Body>,
|
||||
) -> Result<Response<Body>, hyper::Error>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
CtxT: Send + Sync + 'static,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
Ok(match parse_req(req).await {
|
||||
Ok(req) => execute_request(root_node, context, req).await,
|
||||
|
@ -158,14 +158,14 @@ async fn execute_request_sync<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
request: GraphQLBatchRequest<S>,
|
||||
) -> Response<Body>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
CtxT: Send + Sync + 'static,
|
||||
QueryT: GraphQLType<S, Context = CtxT> + Send + Sync + 'static,
|
||||
MutationT: GraphQLType<S, Context = CtxT> + Send + Sync + 'static,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT> + Send + Sync + 'static,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
MutationT: GraphQLType<S, Context = CtxT>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLType<S, Context = CtxT>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
let res = request.execute_sync(&*root_node, &context);
|
||||
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
||||
|
@ -189,14 +189,14 @@ async fn execute_request<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
request: GraphQLBatchRequest<S>,
|
||||
) -> Response<Body>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
CtxT: Send + Sync + 'static,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
let res = request.execute(&*root_node, &context).await;
|
||||
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
||||
|
|
|
@ -41,6 +41,10 @@ Check the LICENSE file for details.
|
|||
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use juniper::{
|
||||
http::{self, GraphQLBatchRequest},
|
||||
DefaultScalarValue, FieldError, GraphQLType, InputValue, RootNode, ScalarValue,
|
||||
};
|
||||
use rocket::{
|
||||
data::{FromDataSimple, Outcome as FromDataOutcome},
|
||||
http::{ContentType, RawStr, Status},
|
||||
|
@ -51,12 +55,6 @@ use rocket::{
|
|||
Request,
|
||||
};
|
||||
|
||||
use juniper::{http, InputValue};
|
||||
|
||||
use juniper::{
|
||||
http::GraphQLBatchRequest, DefaultScalarValue, FieldError, GraphQLType, RootNode, ScalarValue,
|
||||
};
|
||||
|
||||
/// Simple wrapper around an incoming GraphQL request
|
||||
///
|
||||
/// See the `http` module for more information. This type can be constructed
|
||||
|
@ -422,7 +420,11 @@ mod fromform_tests {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use juniper::{
|
||||
http::tests as http_tests,
|
||||
tests::{model::Database, schema::Query},
|
||||
EmptyMutation, EmptySubscription, RootNode,
|
||||
};
|
||||
use rocket::{
|
||||
self, get,
|
||||
http::ContentType,
|
||||
|
@ -432,12 +434,6 @@ mod tests {
|
|||
routes, Rocket, State,
|
||||
};
|
||||
|
||||
use juniper::{
|
||||
http::tests as http_tests,
|
||||
tests::{model::Database, schema::Query},
|
||||
EmptyMutation, EmptySubscription, RootNode,
|
||||
};
|
||||
|
||||
type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
|
||||
|
||||
#[get("/?<request..>")]
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#![feature(decl_macro, proc_macro_hygiene)]
|
||||
|
||||
use rocket::{response::content, State};
|
||||
|
||||
use juniper::{
|
||||
tests::{model::Database, schema::Query},
|
||||
EmptyMutation, EmptySubscription, RootNode,
|
||||
};
|
||||
use rocket::{response::content, State};
|
||||
|
||||
type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
|
||||
|
||||
|
|
|
@ -119,13 +119,13 @@ where
|
|||
context: &CtxT,
|
||||
) -> GraphQLResponse
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
MutationT::TypeInfo: Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT>,
|
||||
SubscriptionT::TypeInfo: Sync,
|
||||
CtxT: Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
let response = self.0.execute(root_node, context).await;
|
||||
|
@ -204,7 +204,7 @@ impl GraphQLResponse {
|
|||
|
||||
impl<'f, S> FromForm<'f> for GraphQLRequest<S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
S: ScalarValue,
|
||||
{
|
||||
type Error = String;
|
||||
|
||||
|
@ -275,7 +275,7 @@ where
|
|||
|
||||
impl<'v, S> FromFormValue<'v> for GraphQLRequest<S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
S: ScalarValue,
|
||||
{
|
||||
type Error = String;
|
||||
|
||||
|
@ -290,7 +290,7 @@ const BODY_LIMIT: u64 = 1024 * 100;
|
|||
|
||||
impl<S> FromDataSimple for GraphQLRequest<S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
S: ScalarValue,
|
||||
{
|
||||
type Error = String;
|
||||
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
#![deny(warnings)]
|
||||
#![doc(html_root_url = "https://docs.rs/juniper_subscriptions/0.14.2")]
|
||||
|
||||
use std::{iter::FromIterator, pin::Pin};
|
||||
use std::{
|
||||
iter::FromIterator,
|
||||
pin::Pin,
|
||||
task::{self, Poll},
|
||||
};
|
||||
|
||||
use futures::{task::Poll, Stream};
|
||||
use futures::{future, stream, FutureExt as _, Stream, StreamExt as _, TryFutureExt as _};
|
||||
use juniper::{
|
||||
http::{GraphQLRequest, GraphQLResponse},
|
||||
BoxFuture, ExecutionError, GraphQLError, GraphQLSubscriptionType, GraphQLTypeAsync, Object,
|
||||
|
@ -25,14 +29,14 @@ use juniper::{
|
|||
/// - handles subscription start
|
||||
pub struct Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
root_node: juniper::RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
|
||||
}
|
||||
|
@ -40,14 +44,14 @@ where
|
|||
impl<'a, QueryT, MutationT, SubscriptionT, CtxT, S>
|
||||
Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
/// Builds new [`Coordinator`] with specified `root_node`
|
||||
pub fn new(root_node: juniper::RootNode<'a, QueryT, MutationT, SubscriptionT, S>) -> Self {
|
||||
|
@ -58,14 +62,14 @@ where
|
|||
impl<'a, QueryT, MutationT, SubscriptionT, CtxT, S> SubscriptionCoordinator<'a, CtxT, S>
|
||||
for Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'a,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send,
|
||||
QueryT::TypeInfo: Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send,
|
||||
MutationT::TypeInfo: Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send,
|
||||
SubscriptionT::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync,
|
||||
CtxT: Sync,
|
||||
S: ScalarValue + Send + Sync + 'a,
|
||||
{
|
||||
type Connection = Connection<'a, S>;
|
||||
|
||||
|
@ -76,13 +80,9 @@ where
|
|||
req: &'a GraphQLRequest<S>,
|
||||
context: &'a CtxT,
|
||||
) -> BoxFuture<'a, Result<Self::Connection, Self::Error>> {
|
||||
let rn = &self.root_node;
|
||||
|
||||
Box::pin(async move {
|
||||
let (stream, errors) = juniper::http::resolve_into_stream(req, rn, context).await?;
|
||||
|
||||
Ok(Connection::from_stream(stream, errors))
|
||||
})
|
||||
juniper::http::resolve_into_stream(req, &self.root_node, context)
|
||||
.map_ok(|(stream, errors)| Connection::from_stream(stream, errors))
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ where
|
|||
/// [`Value::Object`] - waits while each field of the [`Object`] is returned, then yields the whole object
|
||||
/// `Value::Object<Value::Object<_>>` - returns [`Value::Null`] if [`Value::Object`] consists of sub-objects
|
||||
pub struct Connection<'a, S> {
|
||||
stream: Pin<Box<dyn futures::Stream<Item = GraphQLResponse<'a, S>> + Send + 'a>>,
|
||||
stream: Pin<Box<dyn Stream<Item = GraphQLResponse<'a, S>> + Send + 'a>>,
|
||||
}
|
||||
|
||||
impl<'a, S> Connection<'a, S>
|
||||
|
@ -118,16 +118,13 @@ impl<'a, S> SubscriptionConnection<'a, S> for Connection<'a, S> where
|
|||
{
|
||||
}
|
||||
|
||||
impl<'a, S> futures::Stream for Connection<'a, S>
|
||||
impl<'a, S> Stream for Connection<'a, S>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'a,
|
||||
{
|
||||
type Item = GraphQLResponse<'a, S>;
|
||||
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut futures::task::Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
// this is safe as stream is only mutated here and is not moved anywhere
|
||||
let Connection { stream } = unsafe { self.get_unchecked_mut() };
|
||||
let stream = unsafe { Pin::new_unchecked(stream) };
|
||||
|
@ -146,22 +143,20 @@ where
|
|||
fn whole_responses_stream<'a, S>(
|
||||
stream: Value<ValuesStream<'a, S>>,
|
||||
errors: Vec<ExecutionError<S>>,
|
||||
) -> Pin<Box<dyn futures::Stream<Item = GraphQLResponse<'a, S>> + Send + 'a>>
|
||||
) -> Pin<Box<dyn Stream<Item = GraphQLResponse<'a, S>> + Send + 'a>>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'a,
|
||||
{
|
||||
use futures::stream::{self, StreamExt as _};
|
||||
|
||||
if !errors.is_empty() {
|
||||
return Box::pin(stream::once(async move {
|
||||
GraphQLResponse::from_result(Ok((Value::Null, errors)))
|
||||
}));
|
||||
return Box::pin(stream::once(future::ready(GraphQLResponse::from_result(
|
||||
Ok((Value::Null, errors)),
|
||||
))));
|
||||
}
|
||||
|
||||
match stream {
|
||||
Value::Null => Box::pin(stream::once(async move {
|
||||
GraphQLResponse::from_result(Ok((Value::Null, vec![])))
|
||||
})),
|
||||
Value::Null => Box::pin(stream::once(future::ready(GraphQLResponse::from_result(
|
||||
Ok((Value::Null, vec![])),
|
||||
)))),
|
||||
Value::Scalar(s) => Box::pin(s.map(|res| match res {
|
||||
Ok(val) => GraphQLResponse::from_result(Ok((val, vec![]))),
|
||||
Err(err) => GraphQLResponse::from_result(Ok((Value::Null, vec![err]))),
|
||||
|
@ -176,9 +171,9 @@ where
|
|||
Value::Object(mut object) => {
|
||||
let obj_len = object.field_count();
|
||||
if obj_len == 0 {
|
||||
return Box::pin(stream::once(async move {
|
||||
GraphQLResponse::from_result(Ok((Value::Null, vec![])))
|
||||
}));
|
||||
return Box::pin(stream::once(future::ready(GraphQLResponse::from_result(
|
||||
Ok((Value::Null, vec![])),
|
||||
))));
|
||||
}
|
||||
|
||||
let mut filled_count = 0;
|
||||
|
@ -187,66 +182,65 @@ where
|
|||
ready_vec.push(None);
|
||||
}
|
||||
|
||||
let stream =
|
||||
futures::stream::poll_fn(move |mut ctx| -> Poll<Option<GraphQLResponse<'a, S>>> {
|
||||
let mut obj_iterator = object.iter_mut();
|
||||
let stream = stream::poll_fn(move |mut ctx| -> Poll<Option<GraphQLResponse<'a, S>>> {
|
||||
let mut obj_iterator = object.iter_mut();
|
||||
|
||||
// Due to having to modify `ready_vec` contents (by-move pattern)
|
||||
// and only being able to iterate over `object`'s mutable references (by-ref pattern)
|
||||
// `ready_vec` and `object` cannot be iterated simultaneously.
|
||||
// TODO: iterate over i and (ref field_name, ref val) once
|
||||
// [this RFC](https://github.com/rust-lang/rust/issues/68354)
|
||||
// is implemented
|
||||
for ready in ready_vec.iter_mut().take(obj_len) {
|
||||
let (field_name, val) = match obj_iterator.next() {
|
||||
Some(v) => v,
|
||||
None => break,
|
||||
};
|
||||
// Due to having to modify `ready_vec` contents (by-move pattern)
|
||||
// and only being able to iterate over `object`'s mutable references (by-ref pattern)
|
||||
// `ready_vec` and `object` cannot be iterated simultaneously.
|
||||
// TODO: iterate over i and (ref field_name, ref val) once
|
||||
// [this RFC](https://github.com/rust-lang/rust/issues/68354)
|
||||
// is implemented
|
||||
for ready in ready_vec.iter_mut().take(obj_len) {
|
||||
let (field_name, val) = match obj_iterator.next() {
|
||||
Some(v) => v,
|
||||
None => break,
|
||||
};
|
||||
|
||||
if ready.is_some() {
|
||||
continue;
|
||||
}
|
||||
if ready.is_some() {
|
||||
continue;
|
||||
}
|
||||
|
||||
match val {
|
||||
Value::Scalar(stream) => {
|
||||
match Pin::new(stream).poll_next(&mut ctx) {
|
||||
Poll::Ready(None) => return Poll::Ready(None),
|
||||
Poll::Ready(Some(value)) => {
|
||||
*ready = Some((field_name.clone(), value));
|
||||
filled_count += 1;
|
||||
}
|
||||
Poll::Pending => { /* check back later */ }
|
||||
match val {
|
||||
Value::Scalar(stream) => {
|
||||
match Pin::new(stream).poll_next(&mut ctx) {
|
||||
Poll::Ready(None) => return Poll::Ready(None),
|
||||
Poll::Ready(Some(value)) => {
|
||||
*ready = Some((field_name.clone(), value));
|
||||
filled_count += 1;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// For now only `Object<Value::Scalar>` is supported
|
||||
*ready = Some((field_name.clone(), Ok(Value::Null)));
|
||||
filled_count += 1;
|
||||
Poll::Pending => { /* check back later */ }
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// For now only `Object<Value::Scalar>` is supported
|
||||
*ready = Some((field_name.clone(), Ok(Value::Null)));
|
||||
filled_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if filled_count == obj_len {
|
||||
filled_count = 0;
|
||||
let new_vec = (0..obj_len).map(|_| None).collect::<Vec<_>>();
|
||||
let ready_vec = std::mem::replace(&mut ready_vec, new_vec);
|
||||
let ready_vec_iterator = ready_vec.into_iter().map(|el| {
|
||||
let (name, val) = el.unwrap();
|
||||
if let Ok(value) = val {
|
||||
(name, value)
|
||||
} else {
|
||||
(name, Value::Null)
|
||||
}
|
||||
});
|
||||
let obj = Object::from_iter(ready_vec_iterator);
|
||||
Poll::Ready(Some(GraphQLResponse::from_result(Ok((
|
||||
Value::Object(obj),
|
||||
vec![],
|
||||
)))))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
});
|
||||
if filled_count == obj_len {
|
||||
filled_count = 0;
|
||||
let new_vec = (0..obj_len).map(|_| None).collect::<Vec<_>>();
|
||||
let ready_vec = std::mem::replace(&mut ready_vec, new_vec);
|
||||
let ready_vec_iterator = ready_vec.into_iter().map(|el| {
|
||||
let (name, val) = el.unwrap();
|
||||
if let Ok(value) = val {
|
||||
(name, value)
|
||||
} else {
|
||||
(name, Value::Null)
|
||||
}
|
||||
});
|
||||
let obj = Object::from_iter(ready_vec_iterator);
|
||||
Poll::Ready(Some(GraphQLResponse::from_result(Ok((
|
||||
Value::Object(obj),
|
||||
vec![],
|
||||
)))))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
});
|
||||
|
||||
Box::pin(stream)
|
||||
}
|
||||
|
@ -255,10 +249,11 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod whole_responses_stream {
|
||||
use super::*;
|
||||
use futures::{stream, StreamExt as _};
|
||||
use juniper::{DefaultScalarValue, ExecutionError, FieldError};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn with_error() {
|
||||
let expected = vec![GraphQLResponse::<DefaultScalarValue>::error(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
extern crate log;
|
||||
use std::env;
|
||||
|
||||
use juniper::{
|
||||
tests::{model::Database, schema::Query},
|
||||
|
@ -20,7 +20,7 @@ fn schema() -> Schema {
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
::std::env::set_var("RUST_LOG", "warp_server");
|
||||
env::set_var("RUST_LOG", "warp_server");
|
||||
env_logger::init();
|
||||
|
||||
let log = warp::log("warp_server");
|
||||
|
|
|
@ -111,25 +111,25 @@ use warp::{body, filters::BoxedFilter, header, http, query, Filter};
|
|||
/// .and(warp::post())
|
||||
/// .and(graphql_filter);
|
||||
/// ```
|
||||
pub fn make_graphql_filter<Query, Mutation, Subscription, Context, S>(
|
||||
pub fn make_graphql_filter<Query, Mutation, Subscription, CtxT, S>(
|
||||
schema: juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||
context_extractor: BoxedFilter<(Context,)>,
|
||||
context_extractor: BoxedFilter<(CtxT,)>,
|
||||
) -> BoxedFilter<(http::Response<Vec<u8>>,)>
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Context: Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
|
||||
Query::TypeInfo: Send + Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
|
||||
Mutation::TypeInfo: Send + Sync,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = Context> + Send + Sync + 'static,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
|
||||
Subscription::TypeInfo: Send + Sync,
|
||||
CtxT: Send + Sync + 'static,
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
{
|
||||
let schema = Arc::new(schema);
|
||||
let post_json_schema = schema.clone();
|
||||
let post_graphql_schema = schema.clone();
|
||||
|
||||
let handle_post_json_request = move |context: Context, req: GraphQLBatchRequest<S>| {
|
||||
let handle_post_json_request = move |context: CtxT, req: GraphQLBatchRequest<S>| {
|
||||
let schema = post_json_schema.clone();
|
||||
async move {
|
||||
let resp = req.execute(&schema, &context).await;
|
||||
|
@ -150,7 +150,7 @@ where
|
|||
.and(body::json())
|
||||
.and_then(handle_post_json_request);
|
||||
|
||||
let handle_post_graphql_request = move |context: Context, body: Bytes| {
|
||||
let handle_post_graphql_request = move |context: CtxT, body: Bytes| {
|
||||
let schema = post_graphql_schema.clone();
|
||||
async move {
|
||||
let query = str::from_utf8(body.as_ref()).map_err(|e| {
|
||||
|
@ -173,7 +173,7 @@ where
|
|||
.and(body::bytes())
|
||||
.and_then(handle_post_graphql_request);
|
||||
|
||||
let handle_get_request = move |context: Context, mut qry: HashMap<String, String>| {
|
||||
let handle_get_request = move |context: CtxT, mut qry: HashMap<String, String>| {
|
||||
let schema = schema.clone();
|
||||
async move {
|
||||
let req = GraphQLRequest::new(
|
||||
|
@ -206,22 +206,22 @@ where
|
|||
}
|
||||
|
||||
/// Make a synchronous filter for graphql endpoint.
|
||||
pub fn make_graphql_filter_sync<Query, Mutation, Subscription, Context, S>(
|
||||
pub fn make_graphql_filter_sync<Query, Mutation, Subscription, CtxT, S>(
|
||||
schema: juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||
context_extractor: BoxedFilter<(Context,)>,
|
||||
context_extractor: BoxedFilter<(CtxT,)>,
|
||||
) -> BoxedFilter<(http::Response<Vec<u8>>,)>
|
||||
where
|
||||
Query: juniper::GraphQLType<S, Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
|
||||
Mutation: juniper::GraphQLType<S, Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
|
||||
Subscription: juniper::GraphQLType<S, Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
|
||||
CtxT: Send + Sync + 'static,
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Context: Send + Sync + 'static,
|
||||
Query: juniper::GraphQLType<S, Context = Context, TypeInfo = ()> + Send + Sync + 'static,
|
||||
Mutation: juniper::GraphQLType<S, Context = Context, TypeInfo = ()> + Send + Sync + 'static,
|
||||
Subscription: juniper::GraphQLType<S, Context = Context, TypeInfo = ()> + Send + Sync + 'static,
|
||||
{
|
||||
let schema = Arc::new(schema);
|
||||
let post_json_schema = schema.clone();
|
||||
let post_graphql_schema = schema.clone();
|
||||
|
||||
let handle_post_json_request = move |context: Context, req: GraphQLBatchRequest<S>| {
|
||||
let handle_post_json_request = move |context: CtxT, req: GraphQLBatchRequest<S>| {
|
||||
let schema = post_json_schema.clone();
|
||||
async move {
|
||||
let res = task::spawn_blocking(move || {
|
||||
|
@ -243,7 +243,7 @@ where
|
|||
.and(body::json())
|
||||
.and_then(handle_post_json_request);
|
||||
|
||||
let handle_post_graphql_request = move |context: Context, body: Bytes| {
|
||||
let handle_post_graphql_request = move |context: CtxT, body: Bytes| {
|
||||
let schema = post_graphql_schema.clone();
|
||||
async move {
|
||||
let res = task::spawn_blocking(move || {
|
||||
|
@ -270,7 +270,7 @@ where
|
|||
.and(body::bytes())
|
||||
.and_then(handle_post_graphql_request);
|
||||
|
||||
let handle_get_request = move |context: Context, mut qry: HashMap<String, String>| {
|
||||
let handle_get_request = move |context: CtxT, mut qry: HashMap<String, String>| {
|
||||
let schema = schema.clone();
|
||||
async move {
|
||||
let res = task::spawn_blocking(move || {
|
||||
|
@ -430,21 +430,20 @@ pub mod subscriptions {
|
|||
/// - execute subscription and return values from stream
|
||||
/// - stop stream and close ws connection
|
||||
#[allow(dead_code)]
|
||||
pub fn graphql_subscriptions<Query, Mutation, Subscription, Context, S>(
|
||||
pub fn graphql_subscriptions<Query, Mutation, Subscription, CtxT, S>(
|
||||
websocket: warp::ws::WebSocket,
|
||||
coordinator: Arc<Coordinator<'static, Query, Mutation, Subscription, Context, S>>,
|
||||
context: Context,
|
||||
coordinator: Arc<Coordinator<'static, Query, Mutation, Subscription, CtxT, S>>,
|
||||
context: CtxT,
|
||||
) -> impl Future<Output = Result<(), failure::Error>> + Send
|
||||
where
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
Context: Clone + Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Query: juniper::GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
|
||||
Query::TypeInfo: Send + Sync,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = Context> + Send + Sync + 'static,
|
||||
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
|
||||
Mutation::TypeInfo: Send + Sync,
|
||||
Subscription:
|
||||
juniper::GraphQLSubscriptionType<S, Context = Context> + Send + Sync + 'static,
|
||||
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
|
||||
Subscription::TypeInfo: Send + Sync,
|
||||
CtxT: Clone + Send + Sync + 'static,
|
||||
S: ScalarValue + Send + Sync + 'static,
|
||||
{
|
||||
let (sink_tx, sink_rx) = websocket.split();
|
||||
let (ws_tx, ws_rx) = mpsc::unbounded();
|
||||
|
|
Loading…
Reference in a new issue