1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use juniper::{GraphQLSubscriptionType, GraphQLTypeAsync, RootNode, ScalarValue};
use std::sync::Arc;

/// Schema defines the requirements for schemas that can be used for operations. Typically this is
/// just an `Arc<RootNode<...>>` and you should not have to implement it yourself.
pub trait Schema: Unpin + Clone + Send + Sync + 'static {
    /// The context type.
    type Context: Unpin + Send + Sync;

    /// The scalar value type.
    type ScalarValue: ScalarValue + Send + Sync;

    /// The query type info.
    type QueryTypeInfo: Send + Sync;

    /// The query type.
    type Query: GraphQLTypeAsync<Self::ScalarValue, Context = Self::Context, TypeInfo = Self::QueryTypeInfo>
        + Send;

    /// The mutation type info.
    type MutationTypeInfo: Send + Sync;

    /// The mutation type.
    type Mutation: GraphQLTypeAsync<
            Self::ScalarValue,
            Context = Self::Context,
            TypeInfo = Self::MutationTypeInfo,
        > + Send;

    /// The subscription type info.
    type SubscriptionTypeInfo: Send + Sync;

    /// The subscription type.
    type Subscription: GraphQLSubscriptionType<
            Self::ScalarValue,
            Context = Self::Context,
            TypeInfo = Self::SubscriptionTypeInfo,
        > + Send;

    /// Returns the root node for the schema.
    fn root_node(
        &self,
    ) -> &RootNode<'static, Self::Query, Self::Mutation, Self::Subscription, Self::ScalarValue>;
}

/// This exists as a work-around for this issue: https://github.com/rust-lang/rust/issues/64552
///
/// It can be used in generators where using Arc directly would result in an error.
// TODO: Remove this once that issue is resolved.
#[doc(hidden)]
pub struct ArcSchema<QueryT, MutationT, SubscriptionT, CtxT, S>(
    pub Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
)
where
    QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    QueryT::TypeInfo: Send + Sync,
    MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    MutationT::TypeInfo: Send + Sync,
    SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
    SubscriptionT::TypeInfo: Send + Sync,
    CtxT: Unpin + Send + Sync,
    S: ScalarValue + Send + Sync + 'static;

impl<QueryT, MutationT, SubscriptionT, CtxT, S> Clone
    for ArcSchema<QueryT, MutationT, SubscriptionT, CtxT, S>
where
    QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    QueryT::TypeInfo: Send + Sync,
    MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    MutationT::TypeInfo: Send + Sync,
    SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
    SubscriptionT::TypeInfo: Send + Sync,
    CtxT: Unpin + Send + Sync,
    S: ScalarValue + Send + Sync + 'static,
{
    fn clone(&self) -> Self {
        Self(self.0.clone())
    }
}

impl<QueryT, MutationT, SubscriptionT, CtxT, S> Schema
    for ArcSchema<QueryT, MutationT, SubscriptionT, CtxT, S>
where
    QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    QueryT::TypeInfo: Send + Sync,
    MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    MutationT::TypeInfo: Send + Sync,
    SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
    SubscriptionT::TypeInfo: Send + Sync,
    CtxT: Unpin + Send + Sync + 'static,
    S: ScalarValue + Send + Sync + 'static,
{
    type Context = CtxT;
    type ScalarValue = S;
    type QueryTypeInfo = QueryT::TypeInfo;
    type Query = QueryT;
    type MutationTypeInfo = MutationT::TypeInfo;
    type Mutation = MutationT;
    type SubscriptionTypeInfo = SubscriptionT::TypeInfo;
    type Subscription = SubscriptionT;

    fn root_node(&self) -> &RootNode<'static, QueryT, MutationT, SubscriptionT, S> {
        &self.0
    }
}

impl<QueryT, MutationT, SubscriptionT, CtxT, S> Schema
    for Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>
where
    QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    QueryT::TypeInfo: Send + Sync,
    MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + 'static,
    MutationT::TypeInfo: Send + Sync,
    SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
    SubscriptionT::TypeInfo: Send + Sync,
    CtxT: Unpin + Send + Sync,
    S: ScalarValue + Send + Sync + 'static,
{
    type Context = CtxT;
    type ScalarValue = S;
    type QueryTypeInfo = QueryT::TypeInfo;
    type Query = QueryT;
    type MutationTypeInfo = MutationT::TypeInfo;
    type Mutation = MutationT;
    type SubscriptionTypeInfo = SubscriptionT::TypeInfo;
    type Subscription = SubscriptionT;

    fn root_node(&self) -> &RootNode<'static, QueryT, MutationT, SubscriptionT, S> {
        self
    }
}