aqlgen_renderer/base/
context.rs

1use super::Config;
2use async_graphql_parser::types::{
3    ServiceDocument, TypeDefinition, TypeKind, TypeSystemDefinition,
4};
5use std::collections::HashMap;
6
7use crate::document_wrapper::{
8    EnumTypeWrapper, FileRender, InputObjectTypeWrapper, InterfaceTypeWrapper,
9    MutationsTypeWrapper, ObjectPath, ObjectTypeWrapper, RenderType, ScalarTypeWrapper,
10    SubscriptionRootTypeWrapper, UnionTypeWrapper,
11};
12
13#[derive(Debug, Clone)]
14pub struct Context<'a> {
15    pub config: &'a Config,
16    doc: &'a ServiceDocument,
17}
18
19fn get_paths<T>(obj: &[T]) -> Vec<ObjectPath>
20where
21    T: FileRender,
22{
23    obj.iter().map(|f| f.path()).collect()
24}
25
26impl<'a> Context<'a> {
27    #[must_use]
28    pub const fn new(config: &'a Config, doc: &'a ServiceDocument) -> Self {
29        Self { config, doc }
30    }
31
32    #[must_use]
33    pub fn scalar_names(&self) -> Vec<String> {
34        self.scalar_types()
35            .iter()
36            .map(ScalarTypeWrapper::name)
37            .collect()
38    }
39
40    #[must_use]
41    pub fn union_names(&self) -> Vec<String> {
42        self.union_types()
43            .iter()
44            .map(UnionTypeWrapper::name)
45            .collect()
46    }
47
48    #[must_use]
49    pub fn enum_names(&self) -> Vec<String> {
50        self.enum_types()
51            .iter()
52            .map(EnumTypeWrapper::name)
53            .collect()
54    }
55
56    pub fn input_object_type_names(&self) -> Vec<String> {
57        self.input_object_types()
58            .iter()
59            .map(InputObjectTypeWrapper::name)
60            .collect()
61    }
62
63    pub fn file_paths(&self) -> Vec<ObjectPath> {
64        vec![
65            self.enum_file_paths(),
66            self.scalar_file_paths(),
67            self.object_type_file_paths(),
68            self.interface_type_file_paths(),
69            self.mutation_type_file_paths(),
70            self.input_object_type_file_paths(),
71            self.union_type_file_paths(),
72            self.subscription_type_file_paths(),
73        ]
74        .into_iter()
75        .flatten()
76        .collect()
77    }
78
79    pub fn structured_file_paths(&self) -> HashMap<String, Vec<ObjectPath>> {
80        let mut map = HashMap::new();
81
82        self.file_paths().iter().for_each(|f| {
83            let r = vec![];
84            map.entry(f.super_module_name.clone())
85                .or_insert_with(|| r)
86                .push(f.clone());
87        });
88        map
89    }
90
91    fn enum_file_paths(&self) -> Vec<ObjectPath> {
92        get_paths(&self.enum_types())
93    }
94
95    fn scalar_file_paths(&self) -> Vec<ObjectPath> {
96        get_paths(&self.scalar_types())
97    }
98
99    fn object_type_file_paths(&self) -> Vec<ObjectPath> {
100        get_paths(&self.object_types())
101    }
102
103    fn interface_type_file_paths(&self) -> Vec<ObjectPath> {
104        get_paths(&self.interface_types())
105    }
106
107    fn mutation_type_file_paths(&self) -> Vec<ObjectPath> {
108        get_paths(&self.mutation_types())
109    }
110
111    fn subscription_type_file_paths(&self) -> Vec<ObjectPath> {
112        get_paths(&self.subscription_types())
113    }
114
115    fn input_object_type_file_paths(&self) -> Vec<ObjectPath> {
116        get_paths(&self.input_object_types())
117    }
118
119    fn union_type_file_paths(&self) -> Vec<ObjectPath> {
120        get_paths(&self.union_types())
121    }
122
123    fn type_definition(&self) -> Vec<&TypeDefinition> {
124        self.doc
125            .definitions
126            .iter()
127            .filter_map(|f| match &f {
128                TypeSystemDefinition::Type(n) => Some(&n.node),
129                TypeSystemDefinition::Schema(_) => None,
130                _ => panic!("Not implemented:{:?}", f),
131            })
132            .collect()
133    }
134
135    #[must_use]
136    pub fn mutation_types(&self) -> Vec<MutationsTypeWrapper> {
137        self.type_definition()
138            .iter()
139            .filter_map(|f| match &f.kind {
140                TypeKind::Object(kind) => {
141                    if f.name.node.as_str() == "Mutation" {
142                        return Some(MutationsTypeWrapper {
143                            doc: *f,
144                            object: kind,
145                            context: self,
146                        });
147                    }
148                    None
149                }
150                _ => None,
151            })
152            .collect()
153    }
154
155    #[must_use]
156    pub fn subscription_types(&self) -> Vec<SubscriptionRootTypeWrapper> {
157        self.type_definition()
158            .iter()
159            .filter_map(|f| match &f.kind {
160                TypeKind::Object(kind) => {
161                    if f.name.node.as_str() == "Subscription" {
162                        return Some(SubscriptionRootTypeWrapper {
163                            doc: *f,
164                            object: kind,
165                            context: self,
166                        });
167                    }
168                    None
169                }
170                _ => None,
171            })
172            .collect()
173    }
174
175    #[must_use]
176    pub fn object_types(&self) -> Vec<ObjectTypeWrapper> {
177        self.type_definition()
178            .iter()
179            .filter_map(|f| match &f.kind {
180                TypeKind::Object(kind) => {
181                    if f.name.node.as_str() == "Mutation" {
182                        return None;
183                    }
184                    if f.name.node.as_str() == "Subscription" {
185                        return None;
186                    }
187                    Some(ObjectTypeWrapper {
188                        doc: *f,
189                        kind,
190                        context: self,
191                    })
192                }
193                _ => None,
194            })
195            .collect()
196    }
197
198    #[must_use]
199    pub fn scalar_types(&self) -> Vec<ScalarTypeWrapper> {
200        self.type_definition()
201            .iter()
202            .filter_map(|f| match &f.kind {
203                TypeKind::Scalar => Some(ScalarTypeWrapper {
204                    doc: *f,
205                    kind: &(),
206                    context: self,
207                }),
208                _ => None,
209            })
210            .collect()
211    }
212
213    #[must_use]
214    pub fn union_types(&self) -> Vec<UnionTypeWrapper> {
215        self.type_definition()
216            .iter()
217            .filter_map(|f| match &f.kind {
218                TypeKind::Union(kind) => Some(UnionTypeWrapper {
219                    doc: *f,
220                    kind,
221                    context: self,
222                }),
223                _ => None,
224            })
225            .collect()
226    }
227
228    #[must_use]
229    pub fn enum_types(&self) -> Vec<EnumTypeWrapper> {
230        self.type_definition()
231            .iter()
232            .filter_map(|f| match &f.kind {
233                TypeKind::Enum(kind) => Some(EnumTypeWrapper {
234                    doc: *f,
235                    kind,
236                    context: self,
237                }),
238                _ => None,
239            })
240            .collect()
241    }
242
243    #[must_use]
244    pub fn interface_types(&self) -> Vec<InterfaceTypeWrapper> {
245        self.type_definition()
246            .iter()
247            .filter_map(|f| match &f.kind {
248                TypeKind::Interface(kind) => Some(InterfaceTypeWrapper {
249                    doc: *f,
250                    kind,
251                    context: self,
252                }),
253                _ => None,
254            })
255            .collect()
256    }
257
258    #[must_use]
259    pub fn input_object_types(&self) -> Vec<InputObjectTypeWrapper> {
260        self.type_definition()
261            .iter()
262            .filter_map(|f| match &f.kind {
263                TypeKind::InputObject(kind) => Some(InputObjectTypeWrapper {
264                    doc: *f,
265                    input: kind,
266                    context: self,
267                }),
268                _ => None,
269            })
270            .collect()
271    }
272}