1#![expect(missing_docs)]
4
5mod debug;
6mod directive_definitions;
7mod directives;
8mod entity;
9mod enum_definitions;
10mod enum_values;
11mod extensions;
12mod from_sdl;
13mod ids;
14mod input_value_definitions;
15mod objects;
16mod render_sdl;
17mod roots;
18mod scalar_definitions;
19mod r#type;
20mod view;
21
22pub use self::{
23 from_sdl::DomainError,
24 render_sdl::{render_api_sdl, render_federated_sdl},
25};
26
27pub(crate) use self::{
28 directive_definitions::*,
29 directives::*,
30 entity::*,
31 enum_definitions::EnumDefinitionRecord,
32 enum_values::EnumValueRecord,
33 extensions::*,
34 ids::*,
35 render_sdl::display_graphql_string_literal,
36 roots::*,
37 scalar_definitions::ScalarDefinitionRecord,
38 r#type::{Definition, Type},
39 view::{View, ViewNested},
40};
41
42use enum_definitions::EnumDefinition;
43use scalar_definitions::ScalarDefinition;
44use std::{fmt, ops::Range};
45
46#[derive(Default)]
47pub struct FederatedGraph {
48 pub(crate) subgraphs: Vec<Subgraph>,
49 pub extensions: Vec<Extension>,
50 pub(crate) objects: Vec<Object>,
51 pub(crate) interfaces: Vec<Interface>,
52 pub(crate) fields: Vec<Field>,
53 pub(crate) roots: SchemaRoots,
54
55 pub(crate) directive_definitions: Vec<DirectiveDefinitionRecord>,
56 pub(crate) directive_definition_arguments: Vec<DirectiveDefinitionArgument>,
57 pub(crate) scalar_definitions: Vec<ScalarDefinitionRecord>,
58 pub(crate) enum_definitions: Vec<EnumDefinitionRecord>,
59 pub(crate) unions: Vec<Union>,
60 pub(crate) input_objects: Vec<InputObject>,
61 pub(crate) enum_values: Vec<EnumValueRecord>,
62 pub(crate) linked_schemas: Vec<LinkDirective>,
63 pub(crate) composed_directives_on_schema_definition: Vec<directives::OtherDirective>,
64
65 pub(crate) input_value_definitions: Vec<InputValueDefinition>,
67
68 pub strings: Vec<String>,
70}
71
72impl FederatedGraph {
73 pub fn from_sdl(sdl: &str) -> Result<Self, crate::DomainError> {
74 if sdl.trim().is_empty() {
75 return Ok(Default::default());
76 }
77 from_sdl::from_sdl(sdl)
78 }
79
80 pub(crate) fn definition_name(&self, definition: Definition) -> &str {
81 let name_id = match definition {
82 Definition::Scalar(scalar_id) => self[scalar_id].name,
83 Definition::Object(object_id) => self.at(object_id).name,
84 Definition::Interface(interface_id) => self.at(interface_id).name,
85 Definition::Union(union_id) => self[union_id].name,
86 Definition::Enum(enum_id) => self[enum_id].name,
87 Definition::InputObject(input_object_id) => self[input_object_id].name,
88 };
89
90 &self[name_id]
91 }
92
93 pub fn iter_interfaces(&self) -> impl ExactSizeIterator<Item = View<InterfaceId, &Interface>> {
94 (0..self.interfaces.len()).map(|idx| self.view(InterfaceId::from(idx)))
95 }
96
97 pub fn iter_objects(&self) -> impl ExactSizeIterator<Item = View<ObjectId, &Object>> {
98 (0..self.objects.len()).map(|idx| self.view(ObjectId::from(idx)))
99 }
100
101 pub fn iter_scalar_definitions(&self) -> impl Iterator<Item = ScalarDefinition<'_>> {
102 self.scalar_definitions
103 .iter()
104 .enumerate()
105 .map(|(idx, _)| self.at(ScalarDefinitionId::from(idx)))
106 }
107
108 pub fn iter_enum_definitions(&self) -> impl Iterator<Item = EnumDefinition<'_>> {
109 self.enum_definitions
110 .iter()
111 .enumerate()
112 .map(|(idx, _)| self.at(EnumDefinitionId::from(idx)))
113 }
114}
115
116#[derive(Clone, Debug)]
117pub struct Subgraph {
118 pub name: StringId,
119 pub join_graph_enum_value: EnumValueId,
120 pub url: Option<StringId>,
121}
122
123#[derive(Clone, Debug)]
124pub struct Union {
125 pub(crate) name: StringId,
126 pub(crate) description: Option<StringId>,
127 pub(crate) members: Vec<ObjectId>,
128 pub(crate) directives: Vec<Directive>,
129}
130
131#[derive(Clone, Debug)]
132pub struct InputObject {
133 pub(crate) name: StringId,
134 pub(crate) description: Option<StringId>,
135 pub(crate) fields: InputValueDefinitions,
136 pub(crate) directives: Vec<Directive>,
137}
138
139#[derive(Default, Clone, PartialEq, PartialOrd, Debug)]
140#[allow(clippy::enum_variant_names)]
141pub(crate) enum Value {
142 #[default]
143 Null,
144 String(StringId),
145 Int(i64),
146 Float(f64),
147 Boolean(bool),
148 UnboundEnumValue(StringId),
154 EnumValue(EnumValueId),
155 Object(Box<[(StringId, Value)]>),
156 List(Box<[Value]>),
157}
158
159#[derive(Clone, Debug)]
160pub struct Object {
161 pub(crate) name: StringId,
162 pub(crate) directives: Vec<Directive>,
163 pub(crate) description: Option<StringId>,
164 pub(crate) implements_interfaces: Vec<InterfaceId>,
165 pub(crate) fields: Fields,
166}
167
168#[derive(Clone, Debug)]
169pub struct Interface {
170 pub(crate) name: StringId,
171 pub(crate) directives: Vec<Directive>,
172 pub(crate) description: Option<StringId>,
173 pub(crate) implements_interfaces: Vec<InterfaceId>,
174 pub(crate) fields: Fields,
175}
176
177#[derive(Clone, Debug)]
178pub struct Field {
179 pub(crate) parent_entity_id: EntityDefinitionId,
180 pub(crate) name: StringId,
181 pub(crate) description: Option<StringId>,
182 pub(crate) r#type: Type,
183 pub(crate) arguments: InputValueDefinitions,
184 pub(crate) directives: Vec<Directive>,
185}
186
187#[derive(Clone, PartialEq, Debug)]
188pub struct InputValueDefinition {
189 pub(crate) name: StringId,
190 pub(crate) r#type: Type,
191 pub(crate) directives: Vec<Directive>,
192 pub(crate) description: Option<StringId>,
193 pub(crate) default: Option<Value>,
194}
195
196#[derive(Clone, Debug, PartialEq, PartialOrd)]
197pub(crate) struct SelectionSet(pub(crate) Vec<Selection>);
198
199impl From<Vec<Selection>> for SelectionSet {
200 fn from(selections: Vec<Selection>) -> Self {
201 SelectionSet(selections)
202 }
203}
204
205impl FromIterator<Selection> for SelectionSet {
206 fn from_iter<I: IntoIterator<Item = Selection>>(iter: I) -> Self {
207 SelectionSet(iter.into_iter().collect())
208 }
209}
210
211impl std::ops::Deref for SelectionSet {
212 type Target = Vec<Selection>;
213 fn deref(&self) -> &Self::Target {
214 &self.0
215 }
216}
217
218impl std::ops::DerefMut for SelectionSet {
219 fn deref_mut(&mut self) -> &mut Self::Target {
220 &mut self.0
221 }
222}
223
224#[derive(Clone, Debug, PartialEq, PartialOrd)]
225pub(crate) enum Selection {
226 Typename,
227 Field(FieldSelection),
228 InlineFragment { on: Definition, subselection: SelectionSet },
229}
230
231#[derive(Clone, Debug, PartialEq, PartialOrd)]
232pub struct FieldSelection {
233 pub field_id: FieldId,
234 pub arguments: Vec<(InputValueDefinitionId, Value)>,
235 pub subselection: SelectionSet,
236}
237
238impl std::ops::Index<InputValueDefinitions> for FederatedGraph {
239 type Output = [InputValueDefinition];
240
241 fn index(&self, index: InputValueDefinitions) -> &Self::Output {
242 let (start, len) = index;
243 &self.input_value_definitions[usize::from(start)..(usize::from(start) + len)]
244 }
245}
246
247impl std::ops::Index<Fields> for FederatedGraph {
248 type Output = [Field];
249
250 fn index(&self, index: Fields) -> &Self::Output {
251 &self.fields[usize::from(index.start)..usize::from(index.end)]
252 }
253}
254
255pub type InputValueDefinitionSet = Vec<InputValueDefinitionSetItem>;
256
257#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, PartialOrd)]
258pub struct InputValueDefinitionSetItem {
259 pub input_value_definition: InputValueDefinitionId,
260 pub subselection: InputValueDefinitionSet,
261}
262
263pub type Fields = Range<FieldId>;
265pub type InputValueDefinitions = (InputValueDefinitionId, usize);
267
268pub const NO_INPUT_VALUE_DEFINITION: InputValueDefinitions = (InputValueDefinitionId::const_from_usize(0), 0);
269pub const NO_FIELDS: Fields = Range {
270 start: FieldId::const_from_usize(0),
271 end: FieldId::const_from_usize(0),
272};