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