libgraphql_core/schema/schema.rs
1use crate::ReadOnlyMap;
2use crate::schema::SchemaBuilder;
3use crate::types::Directive;
4use crate::types::GraphQLType;
5use crate::types::NamedGraphQLTypeRef;
6use std::collections::HashMap;
7
8/// Represents a fully typechecked and immutable GraphQL schema.
9#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
10pub struct Schema {
11 pub(crate) directive_defs: HashMap<String, Directive>,
12 pub(crate) query_type: NamedGraphQLTypeRef,
13 pub(crate) mutation_type: Option<NamedGraphQLTypeRef>,
14 pub(crate) subscription_type: Option<NamedGraphQLTypeRef>,
15 pub(crate) types: HashMap<String, GraphQLType>,
16}
17impl Schema {
18 /// Returns a map from DirectiveName ([`String`]) -> [`Directive`] for *all*
19 /// directives (including built-in GraphQL directives) provided by this
20 /// [`Schema`].
21 ///
22 /// > **⚠️ NOTE:** In addition to directives defined directly in this
23 /// > [`Schema`] this map also includes implicitly-defined, built-in
24 /// > directives like [`Directive::Deprecated`], [`Directive::Include`],
25 /// > [`Directive::Skip`], etc.
26 pub fn all_directives(&self) -> ReadOnlyMap<'_, String, Directive> {
27 ReadOnlyMap::new(&self.directive_defs, None)
28 }
29
30 /// Returns a map from TypeName ([`String`]) -> [`GraphQLType`] for *all*
31 /// types (including built-in GraphQL types) provided by this [`Schema`].
32 ///
33 /// > **⚠️ NOTE:** In addition to types defined directly in this [`Schema`]
34 /// > this map also includes implicitly-defined, built-in types like
35 /// > [`GraphQLType::Bool`], [`GraphQLType::Float`], [`GraphQLType::ID`],
36 /// > etc.
37 pub fn all_types(&self) -> ReadOnlyMap<'_, String, GraphQLType> {
38 ReadOnlyMap::new(&self.types, None)
39 }
40
41 /// Helper function that just delegates to [`SchemaBuilder::new()`].
42 pub fn builder() -> SchemaBuilder {
43 SchemaBuilder::new()
44 }
45
46 /// Returns a map from DirectiveName ([`String`]) -> [`Directive`] for all
47 /// ***non-builtin*** directives defined by this [`Schema`].
48 ///
49 /// > **⚠️ NOTE:** This map does not include any of the built-in directives
50 /// > like [`Directive::Deprecated`], [`Directive::Include`],
51 /// > [`Directive::Skip`], etc. It only includes directives that were
52 /// > defined directly in this [`Schema`].
53 pub fn defined_directives(&self) -> ReadOnlyMap<'_, String, Directive> {
54 ReadOnlyMap::new(
55 &self.directive_defs,
56 Some(|(_, directive)| !directive.is_builtin()),
57 )
58 }
59
60 /// Returns a map from TypeName ([`String`]) -> [`GraphQLType`] for all
61 /// ***non-builtin*** types defined by this [`Schema`].
62 ///
63 /// > **⚠️ NOTE:** This map does not include any of the built-in types like
64 /// > [`GraphQLType::Bool`], [`GraphQLType::Float`], [`GraphQLType::ID`],
65 /// > etc. It only includes types that were defined directly in this
66 /// > [`Schema`].
67 pub fn defined_types(&self) -> ReadOnlyMap<'_, String, GraphQLType> {
68 ReadOnlyMap::new(
69 &self.types,
70 Some(|(_, graphql_type)| !graphql_type.is_builtin()),
71 )
72 }
73
74 /// Returns this [`Schema`]'s Mutation root operation type (if one was
75 /// defined).
76 ///
77 /// > **⚠️ NOTE:** It is ***strongly*** recommended that you use
78 /// > [`Schema::mutation_type()`] in favor of looking for an
79 /// > [`ObjectType`](crate::types::ObjectType) whose name is `"Mutation"`.
80 /// > GraphQL [defines an object type named "Mutation" as the _default_
81 /// > Mutation type ](https://spec.graphql.org/October2021/#sec-Root-Operation-Types.Default-Root-Operation-Type-Names),
82 /// > but it is aslo [possible to override this default
83 /// > ](https://spec.graphql.org/October2021/#RootOperationTypeDefinition) and
84 /// > use a differently-named [`ObjectType`](crate::types::ObjectType)
85 /// > instead. [`Schema::mutation_type()`] factors in any such override and
86 /// > will return the _correct_ [`ObjectType`](crate::types::ObjectType) for
87 /// > this schema.
88 pub fn mutation_type(&self) -> Option<&GraphQLType> {
89 self.mutation_type.as_ref().map(|named_ref| {
90 named_ref.deref(self)
91 .expect("type is present in schema")
92 })
93 }
94
95 /// Returns this [`Schema`]'s Query root operation type.
96 //
97 /// > **⚠️ NOTE**: It is ***strongly*** recommended that you use
98 /// > [`Schema::query_type()`] in favor of looking for an
99 /// > [`ObjectType`](crate::types::ObjectType) whose name is `"Query"`.
100 /// > GraphQL [defines an object type named "Query" as the _default_ Query
101 /// > type](https://spec.graphql.org/October2021/#sec-Root-Operation-Types.Default-Root-Operation-Type-Names),
102 /// > but it is aslo [possible to override this default
103 /// > ](https://spec.graphql.org/October2021/#RootOperationTypeDefinition) and
104 /// > use a differently-named [`ObjectType`](crate::types::ObjectType)
105 /// > instead. [`Schema::query_type()`] factors in any such override and will
106 /// > return the _correct_ [`ObjectType`](crate::types::ObjectType) for this
107 /// > schema.
108 pub fn query_type(&self) -> &GraphQLType {
109 self.query_type.deref(self)
110 .expect("type is present in schema")
111 }
112
113 /// Returns this [`Schema`]'s Subscription root operation type.
114 //
115 /// > **⚠️ NOTE**: It is ***strongly*** recommended that you use
116 /// > [`Schema::subscription_type()`] in favor of looking for an
117 /// > [`ObjectType`](crate::types::ObjectType) whose name is `"Subscription"`.
118 /// > GraphQL [defines an object type named "Subscription" as the _default_
119 /// > Subscription type](https://spec.graphql.org/October2021/#sec-Root-Operation-Types.Default-Root-Operation-Type-Names),
120 /// > but it is aslo [possible to override this default
121 /// > ](https://spec.graphql.org/October2021/#RootOperationTypeDefinition) and
122 /// > use a differently-named [`ObjectType`](crate::types::ObjectType)
123 /// > instead. [`Schema::subscription_type()`] factors in any such override
124 /// > and will return the _correct_ [`ObjectType`](crate::types::ObjectType)
125 /// > for this schema.
126 pub fn subscription_type(&self) -> Option<&GraphQLType> {
127 self.subscription_type.as_ref().map(|named_ref| {
128 named_ref.deref(self)
129 .expect("type is present in schema")
130 })
131 }
132}