graphgate_planner/
plan.rs1use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
2use std::ops::{Deref, DerefMut};
3
4use indexmap::IndexMap;
5use serde::{Serialize, Serializer};
6use value::{ConstValue, Name, Variables};
7
8use crate::types::{FetchQuery, VariablesRef};
9use crate::Request;
10
11#[derive(Debug, Serialize)]
12#[serde(tag = "type", rename_all = "lowercase")]
13pub enum PlanNode<'a> {
14 Sequence(SequenceNode<'a>),
15 Parallel(ParallelNode<'a>),
16 Introspection(IntrospectionNode),
17 Fetch(FetchNode<'a>),
18 Flatten(FlattenNode<'a>),
19}
20
21impl<'a> PlanNode<'a> {
22 pub(crate) fn flatten(self) -> Self {
23 match self {
24 PlanNode::Sequence(mut node) if node.nodes.len() == 1 => node.nodes.remove(0),
25 PlanNode::Parallel(mut node) if node.nodes.len() == 1 => node.nodes.remove(0),
26 _ => self,
27 }
28 }
29}
30
31#[derive(Debug, Clone, Hash, Eq, PartialEq)]
32pub struct PathSegment<'a> {
33 pub name: &'a str,
34 pub is_list: bool,
35 pub possible_type: Option<&'a str>,
36}
37
38#[derive(Clone, Default, Hash, Eq, PartialEq)]
39pub struct ResponsePath<'a>(Vec<PathSegment<'a>>);
40
41impl<'a> Debug for ResponsePath<'a> {
42 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
43 for (idx, segment) in self.0.iter().enumerate() {
44 if idx > 0 {
45 write!(f, ".")?;
46 }
47 if segment.is_list {
48 write!(f, "[{}]", segment.name)?;
49 } else {
50 write!(f, "{}", segment.name)?;
51 }
52 if let Some(possible_type) = segment.possible_type {
53 write!(f, "({})", possible_type)?;
54 }
55 }
56 Ok(())
57 }
58}
59
60impl<'a> Display for ResponsePath<'a> {
61 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
62 Debug::fmt(self, f)
63 }
64}
65
66impl<'a> Serialize for ResponsePath<'a> {
67 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68 where
69 S: Serializer,
70 {
71 serializer.serialize_str(&self.to_string())
72 }
73}
74
75impl<'a> Deref for ResponsePath<'a> {
76 type Target = Vec<PathSegment<'a>>;
77
78 fn deref(&self) -> &Self::Target {
79 &self.0
80 }
81}
82
83impl<'a> DerefMut for ResponsePath<'a> {
84 fn deref_mut(&mut self) -> &mut Self::Target {
85 &mut self.0
86 }
87}
88
89#[derive(Default, Debug, Serialize)]
90pub struct SequenceNode<'a> {
91 pub nodes: Vec<PlanNode<'a>>,
92}
93
94#[derive(Default, Debug, Serialize)]
95pub struct ParallelNode<'a> {
96 pub nodes: Vec<PlanNode<'a>>,
97}
98
99#[derive(Debug, Serialize)]
100pub struct IntrospectionDirective {
101 pub name: Name,
102
103 #[serde(skip_serializing_if = "IndexMap::is_empty")]
104 pub arguments: IndexMap<Name, ConstValue>,
105}
106
107#[derive(Debug, Serialize)]
108pub struct IntrospectionField {
109 pub name: Name,
110
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub alias: Option<Name>,
113
114 #[serde(skip_serializing_if = "IndexMap::is_empty")]
115 pub arguments: IndexMap<Name, ConstValue>,
116
117 #[serde(skip_serializing_if = "Vec::is_empty")]
118 pub directives: Vec<IntrospectionDirective>,
119
120 pub selection_set: IntrospectionSelectionSet,
121}
122
123#[derive(Debug, Default, Serialize)]
124#[serde(transparent)]
125pub struct IntrospectionSelectionSet(pub Vec<IntrospectionField>);
126
127#[derive(Debug, Serialize)]
128#[serde(transparent)]
129pub struct IntrospectionNode {
130 pub selection_set: IntrospectionSelectionSet,
131}
132
133#[derive(Debug, Serialize)]
134#[serde(rename_all = "camelCase")]
135pub struct FetchNode<'a> {
136 pub service: &'a str,
137 #[serde(skip_serializing_if = "VariablesRef::is_empty")]
138 pub variables: VariablesRef<'a>,
139 pub query: FetchQuery<'a>,
140}
141
142impl<'a> FetchNode<'a> {
143 pub fn to_request(&self) -> Request {
144 Request::new(self.query.to_string()).variables(self.variables.to_variables())
145 }
146}
147
148#[derive(Debug, Serialize)]
149#[serde(rename_all = "camelCase")]
150pub struct FlattenNode<'a> {
151 pub path: ResponsePath<'a>,
152 pub prefix: usize,
153 pub service: &'a str,
154 #[serde(skip_serializing_if = "VariablesRef::is_empty")]
155 pub variables: VariablesRef<'a>,
156 pub query: FetchQuery<'a>,
157}
158
159impl<'a> FlattenNode<'a> {
160 pub fn to_request(&self, representations: Variables) -> Request {
161 Request::new(self.query.to_string())
162 .variables(representations)
163 .extend_variables(self.variables.to_variables())
164 }
165}
166
167#[derive(Debug, Serialize)]
168#[serde(rename_all = "camelCase")]
169pub struct SubscribeNode<'a> {
170 pub subscribe_nodes: Vec<FetchNode<'a>>,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub flatten_node: Option<PlanNode<'a>>,
173}
174
175#[derive(Debug, Serialize)]
176#[serde(tag = "type", rename_all = "lowercase")]
177pub enum RootNode<'a> {
178 Subscribe(SubscribeNode<'a>),
179 Query(PlanNode<'a>),
180}