Skip to main content

wundergraph/
graphql_type.rs

1use crate::query_builder::selection::offset::ApplyOffset;
2use crate::query_builder::selection::LoadingHandler;
3use crate::scalar::WundergraphScalarValue;
4use diesel::backend::Backend;
5use diesel::query_builder::QueryFragment;
6use diesel::QuerySource;
7use juniper::{meta, GraphQLType, Registry};
8use std::marker::PhantomData;
9
10/// A helper type to automatically provide `juniper::GraphQLObject` implementation
11/// for types that also implement `LoadingHandler`
12#[derive(Debug)]
13pub struct GraphqlWrapper<T, DB, Ctx>(T, PhantomData<(DB, Ctx)>);
14
15impl<T, DB, Ctx> GraphQLType<WundergraphScalarValue> for GraphqlWrapper<T, DB, Ctx>
16where
17    DB: Backend + ApplyOffset + 'static,
18    T::Table: 'static,
19    <T::Table as QuerySource>::FromClause: QueryFragment<DB>,
20    T: LoadingHandler<DB, Ctx>,
21    T::FieldList: WundergraphGraphqlHelper<T, DB, Ctx>,
22    DB::QueryBuilder: Default,
23{
24    type Context = ();
25    type TypeInfo = ();
26
27    fn name(_info: &Self::TypeInfo) -> Option<&str> {
28        Some(T::TYPE_NAME)
29    }
30
31    fn meta<'r>(
32        _info: &Self::TypeInfo,
33        registry: &mut Registry<'r, WundergraphScalarValue>,
34    ) -> meta::MetaType<'r, WundergraphScalarValue>
35    where
36        WundergraphScalarValue: 'r,
37    {
38        <T::FieldList as WundergraphGraphqlHelper<T, DB, Ctx>>::object_meta::<Self>(
39            T::FIELD_NAMES,
40            registry,
41        )
42    }
43}
44
45#[doc(hidden)]
46pub trait WundergraphGraphqlMapper<DB, Ctx> {
47    type GraphQLType: GraphQLType<WundergraphScalarValue, TypeInfo = ()>;
48
49    fn register_arguments<'r>(
50        _registry: &mut Registry<'r, WundergraphScalarValue>,
51        field: meta::Field<'r, WundergraphScalarValue>,
52    ) -> meta::Field<'r, WundergraphScalarValue> {
53        field
54    }
55}
56
57impl<T, DB, Ctx> WundergraphGraphqlMapper<DB, Ctx> for T
58where
59    T: GraphQLType<WundergraphScalarValue, TypeInfo = ()>,
60{
61    type GraphQLType = Self;
62}
63
64#[doc(hidden)]
65pub trait WundergraphGraphqlHelper<L, DB, Ctx> {
66    fn object_meta<'r, T>(
67        names: &[&str],
68        registry: &mut Registry<'r, WundergraphScalarValue>,
69    ) -> meta::MetaType<'r, WundergraphScalarValue>
70    where
71        T: GraphQLType<WundergraphScalarValue, TypeInfo = ()>;
72}
73
74macro_rules! wundergraph_graphql_helper_impl {
75    ($(
76        $Tuple:tt {
77            $(($idx:tt) -> $T:ident, $ST: ident, $TT: ident,) +
78        }
79    )+) => {
80        $(
81            impl<$($T,)* Loading, Back, Ctx> WundergraphGraphqlHelper<Loading, Back, Ctx> for ($($T,)*)
82            where $($T: WundergraphGraphqlMapper<Back, Ctx>,)*
83                  Back: Backend + ApplyOffset + 'static,
84                  Loading::Table: 'static,
85                  <Loading::Table as QuerySource>::FromClause: QueryFragment<Back>,
86                  Loading: LoadingHandler<Back, Ctx>,
87                  Back::QueryBuilder: Default,
88            {
89                fn object_meta<'r, Type>(
90                    names: &[&str],
91                    registry: &mut Registry<'r, WundergraphScalarValue>,
92                ) -> meta::MetaType<'r, WundergraphScalarValue>
93                    where Type: GraphQLType<WundergraphScalarValue, TypeInfo = ()>
94                {
95                    let fields  = [
96                        $({
97                            let mut field = registry.field::<<$T as WundergraphGraphqlMapper<Back, Ctx>>::GraphQLType>(names[$idx], &());
98                            field = <$T as WundergraphGraphqlMapper<Back, Ctx>>::register_arguments(registry, field);
99                            if let Some(doc) = Loading::field_description($idx) {
100                                field = field.description(doc);
101                            }
102                            if let Some(deprecated) = Loading::field_deprecation($idx) {
103                                field = field.deprecated(deprecated);
104                            }
105                            field
106                        },)*
107                    ];
108                    let mut ty = registry.build_object_type::<Type>(
109                        &(),
110                        &fields,
111                    );
112                    if let Some(doc) = Loading::TYPE_DESCRIPTION {
113                        ty = ty.description(doc);
114                    }
115                    meta::MetaType::Object(ty)
116                }
117            }
118        )*
119    };
120}
121
122__diesel_for_each_tuple!(wundergraph_graphql_helper_impl);