1
1
use std:: { borrow:: Cow , fmt} ;
2
2
3
3
use fnv:: FnvHashMap ;
4
- #[ cfg( feature = "graphql-parser " ) ]
4
+ #[ cfg( feature = "schema-language " ) ]
5
5
use graphql_parser:: schema:: Document ;
6
6
7
7
use crate :: {
@@ -13,9 +13,6 @@ use crate::{
13
13
GraphQLEnum ,
14
14
} ;
15
15
16
- #[ cfg( feature = "graphql-parser" ) ]
17
- use crate :: schema:: translate:: { graphql_parser:: GraphQLParserTranslator , SchemaTranslator } ;
18
-
19
16
/// Root query node of a schema
20
17
///
21
18
/// This brings the mutation, subscription and query types together,
@@ -221,17 +218,40 @@ where
221
218
}
222
219
223
220
#[ cfg( feature = "schema-language" ) ]
224
- /// The schema definition as a `String` in the
225
- /// [GraphQL Schema Language](https://graphql.org/learn/schema/#type-language)
226
- /// format.
227
- pub fn as_schema_language ( & self ) -> String {
228
- self . as_parser_document ( ) . to_string ( )
221
+ /// Returns this [`RootNode`] as a [`String`] containing the schema in [SDL (schema definition language)].
222
+ ///
223
+ /// # Sorted
224
+ ///
225
+ /// The order of the generated definitions is stable and is sorted in the "type-then-name" manner.
226
+ ///
227
+ /// If another sorting order is required, then the [`as_document()`] method should be used, which allows to sort the
228
+ /// returned [`Document`] in the desired manner and then to convert it [`to_string()`].
229
+ ///
230
+ /// [`as_document()`]: RootNode::as_document
231
+ /// [`to_string()`]: ToString::to_string
232
+ /// [0]: https://graphql.org/learn/schema#type-language
233
+ #[ must_use]
234
+ pub fn as_sdl ( & self ) -> String {
235
+ use crate :: schema:: translate:: graphql_parser:: sort_schema_document;
236
+
237
+ let mut doc = self . as_document ( ) ;
238
+ sort_schema_document ( & mut doc) ;
239
+ doc. to_string ( )
229
240
}
230
241
231
- #[ cfg( feature = "graphql-parser" ) ]
232
- /// The schema definition as a [`graphql_parser`](https://crates.io/crates/graphql-parser)
233
- /// [`Document`](https://docs.rs/graphql-parser/latest/graphql_parser/schema/struct.Document.html).
234
- pub fn as_parser_document ( & ' a self ) -> Document < ' a , & ' a str > {
242
+ #[ cfg( feature = "schema-language" ) ]
243
+ /// Returns this [`RootNode`] as a [`graphql_parser`]'s [`Document`].
244
+ ///
245
+ /// # Unsorted
246
+ ///
247
+ /// The order of the generated definitions in the returned [`Document`] is NOT stable and may change without any
248
+ /// real schema changes.
249
+ #[ must_use]
250
+ pub fn as_document ( & ' a self ) -> Document < ' a , & ' a str > {
251
+ use crate :: schema:: translate:: {
252
+ graphql_parser:: GraphQLParserTranslator , SchemaTranslator as _,
253
+ } ;
254
+
235
255
GraphQLParserTranslator :: translate_schema ( & self . schema )
236
256
}
237
257
}
@@ -666,119 +686,141 @@ impl<'a, S> fmt::Display for TypeType<'a, S> {
666
686
}
667
687
668
688
#[ cfg( test) ]
669
- mod test {
670
-
671
- #[ cfg( feature = "graphql-parser" ) ]
672
- mod graphql_parser_integration {
689
+ mod root_node_test {
690
+ #[ cfg( feature = "schema-language" ) ]
691
+ mod as_document {
673
692
use crate :: { graphql_object, EmptyMutation , EmptySubscription , RootNode } ;
674
693
675
- #[ test]
676
- fn graphql_parser_doc ( ) {
677
- struct Query ;
678
- #[ graphql_object]
679
- impl Query {
680
- fn blah ( ) -> bool {
681
- true
682
- }
694
+ struct Query ;
695
+
696
+ #[ graphql_object]
697
+ impl Query {
698
+ fn blah ( ) -> bool {
699
+ true
683
700
}
701
+ }
702
+
703
+ #[ test]
704
+ fn generates_correct_document ( ) {
684
705
let schema = RootNode :: new (
685
706
Query ,
686
707
EmptyMutation :: < ( ) > :: new ( ) ,
687
708
EmptySubscription :: < ( ) > :: new ( ) ,
688
709
) ;
689
710
let ast = graphql_parser:: parse_schema :: < & str > (
711
+ //language=GraphQL
690
712
r#"
691
713
type Query {
692
- blah: Boolean!
714
+ blah: Boolean!
693
715
}
694
716
695
717
schema {
696
718
query: Query
697
719
}
698
- "# ,
720
+ "# ,
699
721
)
700
722
. unwrap ( ) ;
701
- assert_eq ! ( ast. to_string( ) , schema. as_parser_document( ) . to_string( ) ) ;
723
+
724
+ assert_eq ! ( ast. to_string( ) , schema. as_document( ) . to_string( ) ) ;
702
725
}
703
726
}
704
727
705
728
#[ cfg( feature = "schema-language" ) ]
706
- mod schema_language {
729
+ mod as_sdl {
707
730
use crate :: {
708
731
graphql_object, EmptyMutation , EmptySubscription , GraphQLEnum , GraphQLInputObject ,
709
732
GraphQLObject , GraphQLUnion , RootNode ,
710
733
} ;
711
734
712
- #[ test]
713
- fn schema_language ( ) {
714
- #[ derive( GraphQLObject , Default ) ]
715
- struct Cake {
716
- fresh : bool ,
717
- }
718
- #[ derive( GraphQLObject , Default ) ]
719
- struct IceCream {
720
- cold : bool ,
735
+ #[ derive( GraphQLObject , Default ) ]
736
+ struct Cake {
737
+ fresh : bool ,
738
+ }
739
+
740
+ #[ derive( GraphQLObject , Default ) ]
741
+ struct IceCream {
742
+ cold : bool ,
743
+ }
744
+
745
+ #[ derive( GraphQLUnion ) ]
746
+ enum GlutenFree {
747
+ Cake ( Cake ) ,
748
+ IceCream ( IceCream ) ,
749
+ }
750
+
751
+ #[ derive( GraphQLEnum ) ]
752
+ enum Fruit {
753
+ Apple ,
754
+ Orange ,
755
+ }
756
+
757
+ #[ derive( GraphQLInputObject ) ]
758
+ struct Coordinate {
759
+ latitude : f64 ,
760
+ longitude : f64 ,
761
+ }
762
+
763
+ struct Query ;
764
+
765
+ #[ graphql_object]
766
+ impl Query {
767
+ fn blah ( ) -> bool {
768
+ true
721
769
}
722
- # [ derive ( GraphQLUnion ) ]
723
- enum GlutenFree {
724
- Cake ( Cake ) ,
725
- IceCream ( IceCream ) ,
770
+
771
+ /// This is whatever's description.
772
+ fn whatever ( ) -> String {
773
+ "foo" . into ( )
726
774
}
727
- #[ derive( GraphQLEnum ) ]
728
- enum Fruit {
729
- Apple ,
730
- Orange ,
775
+
776
+ fn arr ( stuff : Vec < Coordinate > ) -> Option < & ' static str > {
777
+ ( !stuff. is_empty ( ) ) . then_some ( "stuff" )
731
778
}
732
- #[ derive( GraphQLInputObject ) ]
733
- struct Coordinate {
734
- latitude : f64 ,
735
- longitude : f64 ,
779
+
780
+ fn fruit ( ) -> Fruit {
781
+ Fruit :: Apple
736
782
}
737
- struct Query ;
738
- #[ graphql_object]
739
- impl Query {
740
- fn blah ( ) -> bool {
741
- true
742
- }
743
- /// This is whatever's description.
744
- fn whatever ( ) -> String {
745
- "foo" . into ( )
746
- }
747
- fn arr ( stuff : Vec < Coordinate > ) -> Option < & ' static str > {
748
- ( !stuff. is_empty ( ) ) . then_some ( "stuff" )
749
- }
750
- fn fruit ( ) -> Fruit {
751
- Fruit :: Apple
752
- }
753
- fn gluten_free ( flavor : String ) -> GlutenFree {
754
- if flavor == "savory" {
755
- GlutenFree :: Cake ( Cake :: default ( ) )
756
- } else {
757
- GlutenFree :: IceCream ( IceCream :: default ( ) )
758
- }
759
- }
760
- #[ deprecated]
761
- fn old ( ) -> i32 {
762
- 42
763
- }
764
- #[ deprecated( note = "This field is deprecated, use another." ) ]
765
- fn really_old ( ) -> f64 {
766
- 42.0
783
+
784
+ fn gluten_free ( flavor : String ) -> GlutenFree {
785
+ if flavor == "savory" {
786
+ GlutenFree :: Cake ( Cake :: default ( ) )
787
+ } else {
788
+ GlutenFree :: IceCream ( IceCream :: default ( ) )
767
789
}
768
790
}
769
791
770
- let schema = RootNode :: new (
792
+ #[ deprecated]
793
+ fn old ( ) -> i32 {
794
+ 42
795
+ }
796
+
797
+ #[ deprecated( note = "This field is deprecated, use another." ) ]
798
+ fn really_old ( ) -> f64 {
799
+ 42.0
800
+ }
801
+ }
802
+
803
+ #[ test]
804
+ fn generates_correct_sdl ( ) {
805
+ let actual = RootNode :: new (
771
806
Query ,
772
807
EmptyMutation :: < ( ) > :: new ( ) ,
773
808
EmptySubscription :: < ( ) > :: new ( ) ,
774
809
) ;
775
- let ast = graphql_parser:: parse_schema :: < & str > (
810
+ let expected = graphql_parser:: parse_schema :: < & str > (
811
+ //language=GraphQL
776
812
r#"
777
- union GlutenFree = Cake | IceCream
813
+ schema {
814
+ query: Query
815
+ }
778
816
enum Fruit {
779
817
APPLE
780
818
ORANGE
781
819
}
820
+ input Coordinate {
821
+ latitude: Float!
822
+ longitude: Float!
823
+ }
782
824
type Cake {
783
825
fresh: Boolean!
784
826
}
@@ -795,17 +837,12 @@ mod test {
795
837
old: Int! @deprecated
796
838
reallyOld: Float! @deprecated(reason: "This field is deprecated, use another.")
797
839
}
798
- input Coordinate {
799
- latitude: Float!
800
- longitude: Float!
801
- }
802
- schema {
803
- query: Query
804
- }
805
- "# ,
840
+ union GlutenFree = Cake | IceCream
841
+ "# ,
806
842
)
807
843
. unwrap ( ) ;
808
- assert_eq ! ( ast. to_string( ) , schema. as_schema_language( ) ) ;
844
+
845
+ assert_eq ! ( actual. as_sdl( ) , expected. to_string( ) ) ;
809
846
}
810
847
}
811
848
}
0 commit comments