graphql_federated_graph/directives/
mod.rs

1mod authorized;
2mod complexity_control;
3mod deprecated;
4mod extension;
5mod federation;
6mod require;
7
8use crate::{ListSize, StringId, SubgraphId, Value};
9
10pub use self::{
11    complexity_control::{CostDirective, ListSizeDirective},
12    deprecated::DeprecatedDirective,
13    require::RequireDirective,
14};
15pub use authorized::*;
16pub use extension::*;
17pub use federation::*;
18
19#[derive(PartialEq, PartialOrd, Clone, Debug)]
20pub enum Directive {
21    Authenticated,
22    CompositeLookup {
23        graph: SubgraphId,
24    },
25    CompositeRequire {
26        graph: SubgraphId,
27        field: StringId,
28    },
29    Deprecated {
30        reason: Option<StringId>,
31    },
32    OneOf,
33    Inaccessible,
34    Policy(Vec<Vec<StringId>>),
35    RequiresScopes(Vec<Vec<StringId>>),
36    Cost {
37        weight: i32,
38    },
39    JoinGraph(JoinGraphDirective),
40    JoinField(JoinFieldDirective),
41    JoinType(JoinTypeDirective),
42    JoinUnionMember(JoinUnionMemberDirective),
43    JoinImplements(JoinImplementsDirective),
44    Authorized(AuthorizedDirective),
45    Other {
46        name: StringId,
47        arguments: Vec<(StringId, Value)>,
48    },
49    ListSize(ListSize),
50
51    ExtensionDirective(ExtensionDirective),
52}
53
54impl From<JoinFieldDirective> for Directive {
55    fn from(d: JoinFieldDirective) -> Self {
56        Self::JoinField(d)
57    }
58}
59
60impl From<JoinTypeDirective> for Directive {
61    fn from(d: JoinTypeDirective) -> Self {
62        Self::JoinType(d)
63    }
64}
65
66impl Directive {
67    pub fn as_join_field(&self) -> Option<&JoinFieldDirective> {
68        match self {
69            Directive::JoinField(d) => Some(d),
70            _ => None,
71        }
72    }
73
74    pub fn as_join_field_mut(&mut self) -> Option<&mut JoinFieldDirective> {
75        match self {
76            Directive::JoinField(d) => Some(d),
77            _ => None,
78        }
79    }
80
81    pub fn as_join_type(&self) -> Option<&JoinTypeDirective> {
82        match self {
83            Directive::JoinType(d) => Some(d),
84            _ => None,
85        }
86    }
87
88    pub fn as_join_union_member(&self) -> Option<&JoinUnionMemberDirective> {
89        match self {
90            Directive::JoinUnionMember(d) => Some(d),
91            _ => None,
92        }
93    }
94
95    pub fn as_extension_directive(&self) -> Option<&ExtensionDirective> {
96        match self {
97            Directive::ExtensionDirective(d) => Some(d),
98            _ => None,
99        }
100    }
101
102    pub fn as_join_implements(&self) -> Option<&JoinImplementsDirective> {
103        match self {
104            Directive::JoinImplements(d) => Some(d),
105            _ => None,
106        }
107    }
108}
109
110#[cfg(test)]
111/// Helper for tests
112fn parse_directive<T>(input: &str) -> Result<T, cynic_parser_deser::Error>
113where
114    T: cynic_parser_deser::ValueDeserializeOwned,
115{
116    let doc = directive_test_document(input);
117    parse_from_test_document(&doc)
118}
119
120#[cfg(test)]
121/// Helper for tests where the directive has a lifetime
122///
123/// Should be used with parse_from_test_document
124fn directive_test_document(directive: &str) -> cynic_parser::TypeSystemDocument {
125    cynic_parser::parse_type_system_document(&format!("type Object {directive} {{name: String}}")).unwrap()
126}
127
128#[cfg(test)]
129/// Helper for tests where the directive has a lifetime
130///
131/// Should be used with the document from directive_test_document
132fn parse_from_test_document<'a, T>(doc: &'a cynic_parser::TypeSystemDocument) -> Result<T, cynic_parser_deser::Error>
133where
134    T: cynic_parser_deser::ValueDeserialize<'a>,
135{
136    use cynic_parser::type_system::Definition;
137    use cynic_parser_deser::ConstDeserializer;
138    let Definition::Type(definition) = doc.definitions().next().unwrap() else {
139        unreachable!()
140    };
141    definition.directives().next().unwrap().deserialize::<T>()
142}