1
1
use std:: { borrow:: Cow , fmt} ;
2
2
3
3
use fnv:: FnvHashMap ;
4
+
4
5
#[ cfg( feature = "schema-language" ) ]
5
6
use graphql_parser:: schema:: Document ;
6
7
@@ -53,7 +54,7 @@ pub struct SchemaType<'a, S> {
53
54
pub ( crate ) query_type_name : String ,
54
55
pub ( crate ) mutation_type_name : Option < String > ,
55
56
pub ( crate ) subscription_type_name : Option < String > ,
56
- directives : FnvHashMap < String , DirectiveType < ' a , S > > ,
57
+ pub ( crate ) directives : FnvHashMap < String , DirectiveType < ' a , S > > ,
57
58
}
58
59
59
60
impl < S > Context for SchemaType < ' _ , S > { }
@@ -66,33 +67,51 @@ pub enum TypeType<'a, S: 'a> {
66
67
}
67
68
68
69
#[ derive( Debug ) ]
70
+ /// Represents a graphql directive
69
71
pub struct DirectiveType < ' a , S > {
72
+ /// required a unique name per schema
70
73
pub name : String ,
74
+ /// optional a description
71
75
pub description : Option < String > ,
76
+ /// required atleast a location
72
77
pub locations : Vec < DirectiveLocation > ,
78
+ /// Optional arguments
73
79
pub arguments : Vec < Argument < ' a , S > > ,
80
+ /// Allow repeating a directive
74
81
pub is_repeatable : bool ,
75
82
}
76
83
77
84
#[ derive( Clone , PartialEq , Eq , Debug , GraphQLEnum ) ]
78
85
#[ graphql( name = "__DirectiveLocation" , internal) ]
86
+ /// Describes the different allowed locations of a directive
79
87
pub enum DirectiveLocation {
88
+ /// directive for query
80
89
Query ,
90
+ /// directive for Mutation
81
91
Mutation ,
92
+ /// directive for Subscription
82
93
Subscription ,
94
+ /// directive for Field
83
95
Field ,
96
+ /// directive for Scalar
84
97
Scalar ,
85
98
#[ graphql( name = "FRAGMENT_DEFINITION" ) ]
99
+ /// directive for FragmentDefinition
86
100
FragmentDefinition ,
87
101
#[ graphql( name = "FIELD_DEFINITION" ) ]
102
+ /// directive for FieldDefinition
88
103
FieldDefinition ,
89
104
#[ graphql( name = "VARIABLE_DEFINITION" ) ]
105
+ /// directive for VariableDefinition
90
106
VariableDefinition ,
91
107
#[ graphql( name = "FRAGMENT_SPREAD" ) ]
108
+ /// directive for FragmentSpread
92
109
FragmentSpread ,
93
110
#[ graphql( name = "INLINE_FRAGMENT" ) ]
111
+ /// directive for InlineFragment
94
112
InlineFragment ,
95
113
#[ graphql( name = "ENUM_VALUE" ) ]
114
+ /// directive for Enum
96
115
EnumValue ,
97
116
}
98
117
@@ -104,7 +123,7 @@ where
104
123
SubscriptionT : GraphQLType < DefaultScalarValue , TypeInfo = ( ) > ,
105
124
{
106
125
/// Constructs a new [`RootNode`] from `query`, `mutation` and `subscription` nodes,
107
- /// parametrizing it with a [`DefaultScalarValue`].
126
+ /// parametrizing it with a [`DefaultScalarValue`] .
108
127
pub fn new ( query : QueryT , mutation : MutationT , subscription : SubscriptionT ) -> Self {
109
128
Self :: new_with_info ( query, mutation, subscription, ( ) , ( ) , ( ) )
110
129
}
@@ -118,14 +137,67 @@ where
118
137
SubscriptionT : GraphQLType < S , TypeInfo = ( ) > ,
119
138
{
120
139
/// Constructs a new [`RootNode`] from `query`, `mutation` and `subscription` nodes,
121
- /// parametrizing it with the provided [`ScalarValue`].
140
+ /// parametrized it with the provided [`ScalarValue`].
122
141
pub fn new_with_scalar_value (
123
142
query : QueryT ,
124
143
mutation : MutationT ,
125
144
subscription : SubscriptionT ,
126
145
) -> Self {
127
146
RootNode :: new_with_info ( query, mutation, subscription, ( ) , ( ) , ( ) )
128
147
}
148
+
149
+ /// Constructs a new [`RootNode`] from `query`, `mutation` and `subscription` nodes,
150
+ /// parametrized it with a [`ScalarValue`] and directives
151
+ /// ```rust
152
+ /// use juniper::{
153
+ /// graphql_object, graphql_vars, EmptyMutation, EmptySubscription, GraphQLError,
154
+ /// RootNode, DirectiveLocation , DirectiveType
155
+ /// };
156
+ ///
157
+ /// struct Query{}
158
+ ///
159
+ /// #[graphql_object]
160
+ /// impl Query {
161
+ /// pub fn hello() -> String {
162
+ /// "Hello".to_string()
163
+ /// }
164
+ /// }
165
+ ///
166
+ /// type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>;
167
+ ///
168
+ /// let schema = Schema::new_with_directives(Query {}, EmptyMutation::new(), EmptySubscription::new()
169
+ /// ,vec![ DirectiveType::new("my_directive", &[DirectiveLocation::Query] , &[] , false )]);
170
+ ///
171
+ /// let query = "query @my_directive { hello }";
172
+ ///
173
+ /// match juniper::execute_sync(query, None, &schema, &graphql_vars! {}, &()) {
174
+ /// Err(GraphQLError::ValidationError(errs)) => { panic!("should not give an error"); }
175
+ /// res => {}
176
+ /// }
177
+ ///
178
+ /// let query = "query @non_existing_directive { hello }";
179
+ ///
180
+ /// match juniper::execute_sync(query, None, &schema, &graphql_vars! {}, &()) {
181
+ /// Err(GraphQLError::ValidationError(errs)) => { }
182
+ /// res => { panic!("should give an error"); }
183
+ /// }
184
+ /// ```
185
+ pub fn new_with_directives (
186
+ query : QueryT ,
187
+ mutation : MutationT ,
188
+ subscription : SubscriptionT ,
189
+ custom_directives : Vec < DirectiveType < ' a , S > > ,
190
+ ) -> Self {
191
+ Self :: new_with_directives_and_info (
192
+ query,
193
+ mutation,
194
+ subscription,
195
+ custom_directives,
196
+ ( ) ,
197
+ ( ) ,
198
+ ( ) ,
199
+ )
200
+ }
129
201
}
130
202
131
203
impl < ' a , S , QueryT , MutationT , SubscriptionT > RootNode < ' a , QueryT , MutationT , SubscriptionT , S >
@@ -162,6 +234,34 @@ where
162
234
}
163
235
}
164
236
237
+ /// Construct a new root node with default meta types
238
+ /// and with custom directives
239
+ pub fn new_with_directives_and_info (
240
+ query_obj : QueryT ,
241
+ mutation_obj : MutationT ,
242
+ subscription_obj : SubscriptionT ,
243
+ custom_directives : Vec < DirectiveType < ' a , S > > ,
244
+ query_info : QueryT :: TypeInfo ,
245
+ mutation_info : MutationT :: TypeInfo ,
246
+ subscription_info : SubscriptionT :: TypeInfo ,
247
+ ) -> Self {
248
+ Self {
249
+ query_type : query_obj,
250
+ mutation_type : mutation_obj,
251
+ subscription_type : subscription_obj,
252
+ schema : SchemaType :: new_with_directives :: < QueryT , MutationT , SubscriptionT > (
253
+ & query_info,
254
+ & mutation_info,
255
+ & subscription_info,
256
+ custom_directives. into ( ) ,
257
+ ) ,
258
+ query_info,
259
+ mutation_info,
260
+ subscription_info,
261
+ introspection_disabled : false ,
262
+ }
263
+ }
264
+
165
265
/// Disables introspection for this [`RootNode`], making it to return a [`FieldError`] whenever
166
266
/// its `__schema` or `__type` field is resolved.
167
267
///
@@ -257,12 +357,29 @@ where
257
357
}
258
358
259
359
impl < ' a , S > SchemaType < ' a , S > {
360
+
260
361
/// Create a new schema.
261
362
pub fn new < QueryT , MutationT , SubscriptionT > (
262
363
query_info : & QueryT :: TypeInfo ,
263
364
mutation_info : & MutationT :: TypeInfo ,
264
365
subscription_info : & SubscriptionT :: TypeInfo ,
265
366
) -> Self
367
+ where
368
+ S : ScalarValue + ' a ,
369
+ QueryT : GraphQLType < S > ,
370
+ MutationT : GraphQLType < S > ,
371
+ SubscriptionT : GraphQLType < S > ,
372
+ {
373
+ Self :: new_with_directives :: < QueryT , MutationT , SubscriptionT > ( query_info, mutation_info, subscription_info, None )
374
+ }
375
+
376
+ /// Create a new schema with custom directives
377
+ pub fn new_with_directives < QueryT , MutationT , SubscriptionT > (
378
+ query_info : & QueryT :: TypeInfo ,
379
+ mutation_info : & MutationT :: TypeInfo ,
380
+ subscription_info : & SubscriptionT :: TypeInfo ,
381
+ custom_directives : Option < Vec < DirectiveType < ' a , S > > > ,
382
+ ) -> Self
266
383
where
267
384
S : ScalarValue + ' a ,
268
385
QueryT : GraphQLType < S > ,
@@ -298,6 +415,12 @@ impl<'a, S> SchemaType<'a, S> {
298
415
DirectiveType :: new_specified_by ( & mut registry) ,
299
416
) ;
300
417
418
+ if let Some ( custom_directives) = custom_directives {
419
+ for custom_directive in custom_directives. into_iter ( ) {
420
+ directives. insert ( custom_directive. name . clone ( ) , custom_directive) ;
421
+ }
422
+ }
423
+
301
424
let mut meta_fields = vec ! [
302
425
registry. field:: <SchemaType <S >>( "__schema" , & ( ) ) ,
303
426
registry
@@ -585,6 +708,7 @@ impl<'a, S> DirectiveType<'a, S>
585
708
where
586
709
S : ScalarValue + ' a ,
587
710
{
711
+ /// Create a new default directive
588
712
pub fn new (
589
713
name : & str ,
590
714
locations : & [ DirectiveLocation ] ,
@@ -600,6 +724,15 @@ where
600
724
}
601
725
}
602
726
727
+ /// skip,include,deprecated,specifiedBy are standard graphQL directive
728
+ /// wiil not show up in generated scheme
729
+ pub fn is_builtin ( & self ) -> bool {
730
+ match self . name . as_str ( ) {
731
+ "skip" | "include" | "deprecated" | "specifiedBy" => true ,
732
+ _ => false ,
733
+ }
734
+ }
735
+
603
736
fn new_skip ( registry : & mut Registry < ' a , S > ) -> DirectiveType < ' a , S >
604
737
where
605
738
S : ScalarValue ,
@@ -659,6 +792,7 @@ where
659
792
)
660
793
}
661
794
795
+ /// Set description of directive
662
796
pub fn description ( mut self , description : & str ) -> DirectiveType < ' a , S > {
663
797
self . description = Some ( description. into ( ) ) ;
664
798
self
0 commit comments